diff --git a/Cargo.lock b/Cargo.lock index d7577747..59310619 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3190,6 +3190,14 @@ dependencies = [ "winresource", ] +[[package]] +name = "pyrowave-sys" +version = "0.11.0" +dependencies = [ + "bindgen", + "cmake", +] + [[package]] name = "quick-error" version = "1.2.3" diff --git a/Cargo.toml b/Cargo.toml index bbea5015..7ba9018a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ members = [ "crates/pf-console-ui", "crates/pf-ffvk", "crates/pf-driver-proto", + "crates/pyrowave-sys", "clients/probe", "clients/linux", "clients/session", diff --git a/crates/pyrowave-sys/CMakeLists.txt b/crates/pyrowave-sys/CMakeLists.txt new file mode 100644 index 00000000..769f1895 --- /dev/null +++ b/crates/pyrowave-sys/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.20) +project(pyrowave-sys LANGUAGES CXX C) + +if(NOT DEFINED PYROWAVE_VENDOR_DIR) + set(PYROWAVE_VENDOR_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/pyrowave) +endif() + +# Mirror upstream pyrowave's standalone (top-level) Granite configuration +# (CMakeLists.txt lines 88-99 at the vendored pin), but produce static +# archives only — the Rust crate links the C API statically. +set(GRANITE_RENDERER OFF CACHE BOOL "" FORCE) +set(GRANITE_VULKAN_SPIRV_CROSS OFF CACHE BOOL "" FORCE) +set(GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER OFF CACHE BOOL "" FORCE) +set(GRANITE_VULKAN_SYSTEM_HANDLES OFF CACHE BOOL "" FORCE) +set(GRANITE_SHADER_COMPILER_OPTIMIZE OFF CACHE BOOL "" FORCE) +set(GRANITE_POSITION_INDEPENDENT ON CACHE BOOL "" FORCE) +set(GRANITE_VULKAN_FOSSILIZE OFF CACHE BOOL "" FORCE) +set(GRANITE_SHIPPING ON CACHE BOOL "" FORCE) +set(GRANITE_PLATFORM "null" CACHE STRING "" FORCE) + +add_subdirectory(${PYROWAVE_VENDOR_DIR}/Granite ${CMAKE_CURRENT_BINARY_DIR}/Granite EXCLUDE_FROM_ALL) +# Not top-level from here, so upstream's CMake only defines the static +# `pyrowave` codec library (shared lib / tests / install rules are skipped). +add_subdirectory(${PYROWAVE_VENDOR_DIR} ${CMAKE_CURRENT_BINARY_DIR}/pyrowave EXCLUDE_FROM_ALL) + +# The C API as a static archive. Upstream only ships it as a SHARED target; +# compiling pyrowave_c.cpp against the same deps is equivalent minus the +# dllexport attributes (PYROWAVE_EXPORT_SYMBOLS stays undefined). +add_library(pyrowave-capi STATIC ${PYROWAVE_VENDOR_DIR}/pyrowave_c.cpp) +target_link_libraries(pyrowave-capi PRIVATE pyrowave granite-vulkan) diff --git a/crates/pyrowave-sys/Cargo.toml b/crates/pyrowave-sys/Cargo.toml new file mode 100644 index 00000000..3c0723dd --- /dev/null +++ b/crates/pyrowave-sys/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "pyrowave-sys" +description = "Vendored PyroWave (Themaister's intra-only wavelet codec, Vulkan compute) built from source + bindgen over its C API — the LAN low-latency codec backend (design/pyrowave-codec-plan.md). Upstream pin recorded in vendor/pyrowave/PUNKTFUNK-VENDOR.txt; bumping it is a protocol-affecting change (§4.2)." +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +authors.workspace = true +repository.workspace = true +links = "pyrowave" + +[build-dependencies] +# Same CMake-from-vendored-source model as opus/audiopus_sys: reproducible +# offline builds (CI, MSVC, flatpak — the flatpak builder has no network). +cmake = "0.1" +# Same bindgen configuration as pf-ffvk (runtime = dlopen libclang). +bindgen = { version = "0.72", features = ["runtime"], default-features = false } diff --git a/crates/pyrowave-sys/build.rs b/crates/pyrowave-sys/build.rs new file mode 100644 index 00000000..c2454b20 --- /dev/null +++ b/crates/pyrowave-sys/build.rs @@ -0,0 +1,103 @@ +//! Build the vendored PyroWave codec (C++/Vulkan compute) as static archives via +//! CMake and generate bindings over its C API (`pyrowave.h`). +//! +//! Linux + Windows only — the platforms whose hosts/clients run the Vulkan codec +//! path (design/pyrowave-codec-plan.md §5). Other targets get an empty bindings +//! file so the workspace builds everywhere (the Apple client is a native Metal +//! port, §4.7 — it never links this crate). +//! +//! Everything compiles from the committed vendor tree: no network, no system +//! pyrowave, no pkg-config — CI, MSVC, and the offline flatpak builder all get +//! reproducible builds (§4.1). Vulkan headers come vendored too; only a libclang +//! for bindgen is required on the build machine. + +use std::env; +use std::path::PathBuf; + +fn main() { + println!("cargo:rerun-if-changed=wrapper.h"); + println!("cargo:rerun-if-changed=CMakeLists.txt"); + println!("cargo:rerun-if-changed=vendor/pyrowave"); + + let out = PathBuf::from(env::var("OUT_DIR").unwrap()); + let bindings_path = out.join("bindings.rs"); + + let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); + if target_os != "linux" && target_os != "windows" { + std::fs::write( + &bindings_path, + "// pyrowave-sys: Linux/Windows-only, empty on this target\n", + ) + .unwrap(); + return; + } + + let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + let vendor = manifest_dir.join("vendor/pyrowave"); + let vk_include = vendor.join("Granite/third_party/khronos/vulkan-headers/include"); + + // Always Release: a debug build of the wavelet kernels' host code buys no + // debuggability (the hot path is GPU shaders baked into the source) and the + // MSVC debug CRT would clash with Rust's release CRT. + let dst = cmake::Config::new(&manifest_dir) + .profile("Release") + .build_target("pyrowave-capi") + .build(); + let build = dst.join("build"); + + // Static link closure, dependents before dependencies (GNU ld is order-sensitive). + println!("cargo:rustc-link-search=native={}", build.display()); + for sub in [ + "pyrowave", + "Granite/vulkan", + "Granite/util", + "Granite/math", + "Granite/third_party", + ] { + println!( + "cargo:rustc-link-search=native={}", + build.join(sub).display() + ); + // MSVC multi-config generators put archives in a Release/ subdir. + println!( + "cargo:rustc-link-search=native={}", + build.join(sub).join("Release").display() + ); + } + println!( + "cargo:rustc-link-search=native={}", + build.join("Release").display() + ); + for lib in [ + "pyrowave-capi", + "pyrowave", + "granite-vulkan", + "granite-util", + "granite-math", + "granite-volk", + ] { + println!("cargo:rustc-link-lib=static={lib}"); + } + if target_os == "linux" { + println!("cargo:rustc-link-lib=dylib=stdc++"); + // volk loads the Vulkan loader at runtime. + println!("cargo:rustc-link-lib=dylib=dl"); + println!("cargo:rustc-link-lib=dylib=pthread"); + } + + let bindings = bindgen::Builder::default() + .header("wrapper.h") + .clang_arg(format!("-I{}", vendor.display())) + .clang_arg(format!("-I{}", vk_include.display())) + .allowlist_function("pyrowave_.*") + .allowlist_type("pyrowave_.*") + .allowlist_var("PYROWAVE_.*") + // The Vk* handles/structs the API mentions come along via the allowlist + // closure; they are ABI-identical to ash's, callers cast at the seam. + .derive_default(true) + .generate() + .expect("bindgen failed for pyrowave.h"); + bindings + .write_to_file(&bindings_path) + .expect("failed to write pyrowave bindings"); +} diff --git a/crates/pyrowave-sys/src/lib.rs b/crates/pyrowave-sys/src/lib.rs new file mode 100644 index 00000000..9b91a0e8 --- /dev/null +++ b/crates/pyrowave-sys/src/lib.rs @@ -0,0 +1,29 @@ +//! Raw FFI bindings to the vendored PyroWave C API (`pyrowave.h`). +//! +//! Empty on targets other than Linux/Windows — see build.rs. The safe wrapper +//! lives with its consumer (`punktfunk-host`'s encoder backend, and later the +//! Rust clients' decoder backend); this crate is bindings only. + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +// Bindgen output for a C API: u128 layout warnings and the like are upstream's concern. +#![allow(improper_ctypes)] + +#[cfg(any(target_os = "linux", target_os = "windows"))] +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +#[cfg(all(test, any(target_os = "linux", target_os = "windows")))] +mod tests { + use super::*; + + /// Link sanity: statically linked archives resolve and the vendored pin is + /// the API version we designed against. No GPU or Vulkan loader required — + /// the version query touches no device state. + #[test] + fn api_version_matches_vendored_pin() { + let (mut major, mut minor, mut patch) = (0u32, 0u32, 0u32); + unsafe { pyrowave_get_api_version(&mut major, &mut minor, &mut patch) }; + assert_eq!((major, minor, patch), (0, 4, 0), "vendored pyrowave API version moved — re-check the §4.2 protocol coupling before bumping"); + } +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/CMakeLists.txt new file mode 100644 index 00000000..490f62a5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/CMakeLists.txt @@ -0,0 +1,173 @@ +cmake_minimum_required(VERSION 3.20) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_C_STANDARD 99) +project(pyrowave LANGUAGES CXX C) + +if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) + set(PYROWAVE_CXX_FLAGS -Wshadow -Wall -Wextra -Wno-comment -Wno-missing-field-initializers -Wno-empty-body -fvisibility=hidden) + if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") + set(PYROWAVE_CXX_FLAGS ${PYROWAVE_CXX_FLAGS} -Wno-backslash-newline-escape) + endif() + if (NOT (${CMAKE_BUILD_TYPE} MATCHES "Release")) + message("Enabling frame pointer for profiling/debug.") + set(PYROWAVE_CXX_FLAGS ${PYROWAVE_CXX_FLAGS} -fno-omit-frame-pointer) + endif() + if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + message("Enabling SSE3 support.") + set(PYROWAVE_CXX_FLAGS ${PYROWAVE_CXX_FLAGS} -msse3) + endif() +elseif (MSVC) + set(PYROWAVE_CXX_FLAGS /D_CRT_SECURE_NO_WARNINGS /wd4267 /wd4244 /wd4309 /wd4005 /MP) +endif() + +add_library(pyrowave STATIC + pyrowave_config.hpp shaders/slangmosh.hpp + pyrowave_encoder.hpp pyrowave_encoder.cpp + pyrowave_decoder.hpp pyrowave_decoder.cpp + pyrowave_common.hpp pyrowave_common.cpp) + +target_include_directories(pyrowave PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_options(pyrowave PRIVATE ${PYROWAVE_CXX_FLAGS}) +set_target_properties(pyrowave PROPERTIES POSITION_INDEPENDENT_CODE ON) + +option(PYROWAVE_DEVEL "Build PyroWave as a standalone sandbox with development tooling." OFF) + +if (ANDROID) + # Mobile chips really like FP16 + target_compile_definitions(pyrowave PRIVATE PYROWAVE_PRECISION=0) + message("Forcing FP16 default on Android.") +else() + option(PYROWAVE_FP32_STORAGE "Configure for full FP32 and extended precision." OFF) + option(PYROWAVE_FP32_MATH "Configure for FP32 arithmetic, but reduced range storage." ON) + if (PYROWAVE_FP32_STORAGE) + target_compile_definitions(pyrowave PRIVATE PYROWAVE_PRECISION=2) + elseif(PYROWAVE_FP32_MATH) + target_compile_definitions(pyrowave PRIVATE PYROWAVE_PRECISION=1) + else() + target_compile_definitions(pyrowave PRIVATE PYROWAVE_PRECISION=0) + endif() +endif() + +if (PYROWAVE_DEVEL) + add_library(pyrowave-utils STATIC yuv4mpeg.cpp yuv4mpeg.hpp) + + # Standalone build, build the sandbox. + set(GRANITE_RENDERER ON CACHE BOOL "" FORCE) + set(GRANITE_VULKAN_FOSSILIZE OFF CACHE BOOL "" FORCE) + set(GRANITE_SHIPPING OFF CACHE BOOL "" FORCE) + set(GRANITE_PLATFORM "SDL" CACHE STRING "" FORCE) + set(GRANITE_HIDDEN ON CACHE BOOL "" FORCE) + set(GRANITE_POSITION_INDEPENDENT ON CACHE BOOL "" FORCE) + add_subdirectory(Granite EXCLUDE_FROM_ALL) + + add_granite_offline_tool(pyrowave-sandbox sandbox.cpp) + target_link_libraries(pyrowave-sandbox PRIVATE pyrowave) + target_compile_definitions(pyrowave-sandbox PRIVATE ASSET_DIRECTORY=\"${CMAKE_CURRENT_SOURCE_DIR}/shaders\") + target_link_libraries(pyrowave-sandbox PRIVATE granite-renderer pyrowave-utils) + + add_granite_offline_tool(pyrowave-bench bench.cpp) + target_link_libraries(pyrowave-bench PRIVATE pyrowave) + target_link_libraries(pyrowave-bench PRIVATE granite-vulkan pyrowave-utils) + + add_granite_offline_tool(pyrowave-encode encode.cpp) + target_link_libraries(pyrowave-encode PRIVATE pyrowave) + target_link_libraries(pyrowave-encode PRIVATE granite-vulkan pyrowave-utils) + + add_granite_offline_tool(pyrowave-decode decode.cpp) + target_link_libraries(pyrowave-decode PRIVATE pyrowave) + target_link_libraries(pyrowave-decode PRIVATE granite-vulkan pyrowave-utils) + + add_granite_offline_tool(pyrowave-psnr psnr.cpp) + target_link_libraries(pyrowave-psnr PRIVATE pyrowave-utils) + + add_granite_application(pyrowave-viewer viewer.cpp) + target_link_libraries(pyrowave-viewer PRIVATE pyrowave pyrowave-utils) + if (NOT ANDROID) + target_compile_definitions(pyrowave-viewer PRIVATE ASSET_DIRECTORY=\"${CMAKE_CURRENT_SOURCE_DIR}/shaders\") + endif() +elseif (${PROJECT_IS_TOP_LEVEL} AND (NOT TARGET granite-vulkan)) + set(GRANITE_RENDERER OFF CACHE BOOL "" FORCE) + set(GRANITE_VULKAN_SPIRV_CROSS OFF CACHE BOOL "" FORCE) + set(GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER OFF CACHE BOOL "" FORCE) + set(GRANITE_VULKAN_SYSTEM_HANDLES OFF CACHE BOOL "" FORCE) + set(GRANITE_SHADER_COMPILER_OPTIMIZE OFF CACHE BOOL "" FORCE) + set(GRANITE_POSITION_INDEPENDENT ON CACHE BOOL "" FORCE) + set(GRANITE_VULKAN_FOSSILIZE OFF CACHE BOOL "" FORCE) + set(GRANITE_SHIPPING ON CACHE BOOL "" FORCE) + set(GRANITE_PLATFORM "null" CACHE STRING "" FORCE) + add_subdirectory(Granite EXCLUDE_FROM_ALL) +endif() + +target_link_libraries(pyrowave PRIVATE granite-vulkan granite-math) + +if (${PROJECT_IS_TOP_LEVEL}) + add_library(pyrowave-shared SHARED pyrowave_c.cpp pyrowave.h) + target_link_libraries(pyrowave-shared PRIVATE pyrowave granite-vulkan) + target_compile_definitions(pyrowave-shared PRIVATE PYROWAVE_EXPORT_SYMBOLS) + target_compile_options(pyrowave-shared PRIVATE ${PYROWAVE_CXX_FLAGS}) + + add_executable(pyrowave-c-test pyrowave_c_test.cpp) + target_link_libraries(pyrowave-c-test PRIVATE pyrowave-shared granite-volk-headers) + target_compile_options(pyrowave-c-test PRIVATE ${PYROWAVE_CXX_FLAGS}) + + add_executable(pyrowave-c-interop-test pyrowave_c_interop_test.cpp com_ptr.hpp) + target_link_libraries(pyrowave-c-interop-test PRIVATE pyrowave-shared granite-vulkan) + target_compile_options(pyrowave-c-interop-test PRIVATE ${PYROWAVE_CXX_FLAGS}) + + add_executable(pyrowave-device-validation pyrowave_device_validation.cpp com_ptr.hpp) + target_link_libraries(pyrowave-device-validation PRIVATE pyrowave-shared granite-util granite-volk-headers) + target_compile_options(pyrowave-device-validation PRIVATE ${PYROWAVE_CXX_FLAGS}) + + set(PYROWAVE_API_VERSION_MAJOR 0) + set(PYROWAVE_API_VERSION_MINOR 4) + set(PYROWAVE_API_VERSION_PATCH 0) + set(PYROWAVE_API_VERSION ${PYROWAVE_API_VERSION_MAJOR}.${PYROWAVE_API_VERSION_MINOR}.${PYROWAVE_API_VERSION_PATCH}) + + # DLL_NAME_WITH_SOVERSION requires CMake 3.27+. SteamRT doesn't have CMake 3.27 yet though. + if (WIN32 AND (CMAKE_VERSION VERSION_LESS "3.27")) + message(FATAL_ERROR "CMake build on Windows expects version 3.27 at minimum.") + endif() + + set_target_properties(pyrowave-shared + PROPERTIES VERSION ${PYROWAVE_API_VERSION} + SOVERSION ${PYROWAVE_API_VERSION_MAJOR} + DLL_NAME_WITH_SOVERSION ON) + + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pyrowave.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pyrowave) + install(TARGETS pyrowave-shared EXPORT pyrowave-sharedConfig + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pyrowave) + install(EXPORT pyrowave-sharedConfig DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pyrowave-shared/cmake) + install(TARGETS pyrowave-device-validation RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + set(PYROWAVE_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) + set(PYROWAVE_INSTALL_INC_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/pyrowave) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pkg-config/pyrowave-shared.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/pyrowave-shared.pc @ONLY) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pyrowave-shared.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig) + + if (WIN32 AND CMAKE_COMPILER_IS_GNUCXX) + target_link_libraries(pyrowave-shared PRIVATE -static gcc stdc++ winpthread) + target_link_libraries(pyrowave-c-test PRIVATE -static gcc stdc++ winpthread) + target_link_libraries(pyrowave-c-interop-test PRIVATE -static gcc stdc++ winpthread) + target_link_libraries(pyrowave-device-validation PRIVATE -static gcc stdc++ winpthread) + endif() + + if (NOT WIN32) + target_link_libraries(pyrowave-shared PRIVATE -pthread) + target_link_libraries(pyrowave-c-test PRIVATE -pthread) + target_link_libraries(pyrowave-c-interop-test PRIVATE -pthread) + target_link_libraries(pyrowave-device-validation PRIVATE -pthread) + endif() + + if (WIN32) + target_sources(pyrowave-shared PRIVATE pyrowave-shared.def) + set_target_properties(pyrowave-shared PROPERTIES PREFIX "lib") + target_link_libraries(pyrowave-c-interop-test PRIVATE d3d11 d3d12 dxgi) + else() + target_link_options(pyrowave-shared PRIVATE -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/link.T) + endif() +endif() + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/.clang-format b/crates/pyrowave-sys/vendor/pyrowave/Granite/.clang-format new file mode 100755 index 00000000..443f90b7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/.clang-format @@ -0,0 +1,167 @@ +# The style used for all options not specifically set in the configuration. +BasedOnStyle: LLVM + +# The extra indent or outdent of access modifiers, e.g. public:. +AccessModifierOffset: -4 + +# If true, aligns escaped newlines as far left as possible. Otherwise puts them into the right-most column. +AlignEscapedNewlinesLeft: true + +# If true, aligns trailing comments. +AlignTrailingComments: false + +# Allow putting all parameters of a function declaration onto the next line even if BinPackParameters is false. +AllowAllParametersOfDeclarationOnNextLine: false + +# Allows contracting simple braced statements to a single line. +AllowShortBlocksOnASingleLine: false + +# If true, short case labels will be contracted to a single line. +AllowShortCaseLabelsOnASingleLine: false + +# Dependent on the value, int f() { return 0; } can be put on a single line. Possible values: None, Inline, All. +AllowShortFunctionsOnASingleLine: None + +# If true, if (a) return; can be put on a single line. +AllowShortIfStatementsOnASingleLine: false + +# If true, while (true) continue; can be put on a single line. +AllowShortLoopsOnASingleLine: false + +# If true, always break after function definition return types. +AlwaysBreakAfterDefinitionReturnType: false + +# If true, always break before multiline string literals. +AlwaysBreakBeforeMultilineStrings: false + +# If true, always break after the template<...> of a template declaration. +AlwaysBreakTemplateDeclarations: true + +# If false, a function call's arguments will either be all on the same line or will have one line each. +BinPackArguments: true + +# If false, a function declaration's or function definition's parameters will either all be on the same line +# or will have one line each. +BinPackParameters: true + +# The way to wrap binary operators. Possible values: None, NonAssignment, All. +BreakBeforeBinaryOperators: None + +# The brace breaking style to use. Possible values: Attach, Linux, Stroustrup, Allman, GNU. +BreakBeforeBraces: Allman + +# If true, ternary operators will be placed after line breaks. +BreakBeforeTernaryOperators: false + +# Always break constructor initializers before commas and align the commas with the colon. +BreakConstructorInitializersBeforeComma: true + +# The column limit. A column limit of 0 means that there is no column limit. +ColumnLimit: 120 + +# A regular expression that describes comments with special meaning, which should not be split into lines or otherwise changed. +CommentPragmas: '^ *' + +# If the constructor initializers don't fit on a line, put each initializer on its own line. +ConstructorInitializerAllOnOneLineOrOnePerLine: false + +# The number of characters to use for indentation of constructor initializer lists. +ConstructorInitializerIndentWidth: 4 + +# Indent width for line continuations. +ContinuationIndentWidth: 4 + +# If true, format braced lists as best suited for C++11 braced lists. +Cpp11BracedListStyle: false + +# Disables formatting at all. +DisableFormat: false + +# A vector of macros that should be interpreted as foreach loops instead of as function calls. +#ForEachMacros: '' + +# Indent case labels one level from the switch statement. +# When false, use the same indentation level as for the switch statement. +# Switch statement body is always indented one level more than case labels. +IndentCaseLabels: false + +# The number of columns to use for indentation. +IndentWidth: 4 + +# Indent if a function definition or declaration is wrapped after the type. +IndentWrappedFunctionNames: false + +# If true, empty lines at the start of blocks are kept. +KeepEmptyLinesAtTheStartOfBlocks: true + +# Language, this format style is targeted at. Possible values: None, Cpp, Java, JavaScript, Proto. +Language: Cpp + +# The maximum number of consecutive empty lines to keep. +MaxEmptyLinesToKeep: 1 + +# The indentation used for namespaces. Possible values: None, Inner, All. +NamespaceIndentation: None + +# The penalty for breaking a function call after "call(". +PenaltyBreakBeforeFirstCallParameter: 19 + +# The penalty for each line break introduced inside a comment. +PenaltyBreakComment: 300 + +# The penalty for breaking before the first <<. +PenaltyBreakFirstLessLess: 120 + +# The penalty for each line break introduced inside a string literal. +PenaltyBreakString: 1000 + +# The penalty for each character outside of the column limit. +PenaltyExcessCharacter: 1000000 + +# Penalty for putting the return type of a function onto its own line. +PenaltyReturnTypeOnItsOwnLine: 1000000000 + +# Pointer and reference alignment style. Possible values: Left, Right, Middle. +PointerAlignment: Right + +# If true, a space may be inserted after C style casts. +SpaceAfterCStyleCast: false + +# If false, spaces will be removed before assignment operators. +SpaceBeforeAssignmentOperators: true + +# Defines in which cases to put a space before opening parentheses. Possible values: Never, ControlStatements, Always. +SpaceBeforeParens: ControlStatements + +# If true, spaces may be inserted into '()'. +SpaceInEmptyParentheses: false + +# The number of spaces before trailing line comments (// - comments). +SpacesBeforeTrailingComments: 1 + +# If true, spaces will be inserted after '<' and before '>' in template argument lists. +SpacesInAngles: false + +# If true, spaces may be inserted into C style casts. +SpacesInCStyleCastParentheses: false + +# If true, spaces are inserted inside container literals (e.g. ObjC and Javascript array and dict literals). +SpacesInContainerLiterals: false + +# If true, spaces will be inserted after '(' and before ')'. +SpacesInParentheses: false + +# If true, spaces will be inserted after '[' and befor']'. +SpacesInSquareBrackets: false + +# Format compatible with this standard, e.g. use A > instead of A> for LS_Cpp03. Possible values: Cpp03, Cpp11, Auto. +Standard: Cpp11 + +# The number of columns used for tab stops. +TabWidth: 4 + +# The way to use tab characters in the resulting file. Possible values: Never, ForIndentation, Always. +UseTab: ForIndentation + +# Do not reflow comments +ReflowComments: false diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/.gitmodules b/crates/pyrowave-sys/vendor/pyrowave/Granite/.gitmodules new file mode 100644 index 00000000..fc829003 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/.gitmodules @@ -0,0 +1,54 @@ +[submodule "third_party/spirv-cross"] + path = third_party/spirv-cross + url = https://github.com/KhronosGroup/SPIRV-Cross +[submodule "third_party/shaderc"] + path = third_party/shaderc + url = https://github.com/google/shaderc.git +[submodule "third_party/glslang"] + path = third_party/glslang + url = https://github.com/Themaister/glslang.git +[submodule "third_party/spirv-tools"] + path = third_party/spirv-tools + url = https://github.com/Themaister/SPIRV-Tools +[submodule "third_party/spirv-headers"] + path = third_party/spirv-headers + url = https://github.com/KhronosGroup/SPIRV-Headers +[submodule "third_party/rapidjson"] + path = third_party/rapidjson + url = https://github.com/miloyip/rapidjson +[submodule "third_party/stb/stb"] + path = third_party/stb/stb + url = https://github.com/nothings/stb +[submodule "third_party/astc-encoder"] + path = third_party/astc-encoder + url = https://github.com/ARM-software/astc-encoder +[submodule "third_party/fossilize"] + path = third_party/fossilize + url = https://github.com/ValveSoftware/Fossilize +[submodule "third_party/volk"] + path = third_party/volk + url = https://github.com/zeux/volk +[submodule "third_party/meshoptimizer"] + path = third_party/meshoptimizer + url = https://github.com/zeux/meshoptimizer +[submodule "third_party/muFFT"] + path = third_party/muFFT + url = https://github.com/Themaister/muFFT +[submodule "third_party/oboe"] + path = third_party/oboe + url = https://github.com/google/oboe +[submodule "third_party/khronos/vulkan-headers"] + path = third_party/khronos/vulkan-headers + url = https://github.com/KhronosGroup/Vulkan-Headers +[submodule "third_party/fsr2"] + path = third_party/fsr2 + url = https://github.com/Themaister/FidelityFX-FSR2 +[submodule "third_party/sdl3"] + path = third_party/sdl3 + url = https://github.com/libsdl-org/SDL +[submodule "third_party/pyroenc"] + path = third_party/pyroenc + url = https://github.com/HansKristian-Work/pyroenc +[submodule "third_party/pyrowave"] + path = third_party/pyrowave + url = https://github.com/Themaister/pyrowave diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/CMakeLists.txt new file mode 100644 index 00000000..8d5adb0d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/CMakeLists.txt @@ -0,0 +1,386 @@ +cmake_minimum_required(VERSION 3.6) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_C_STANDARD 99) +project(Granite LANGUAGES CXX C) + +if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) + set(GRANITE_CXX_FLAGS -Wshadow -Wall -Wextra -Wno-comment -Wno-missing-field-initializers -Wno-empty-body) + if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} -Wno-backslash-newline-escape) + endif() + if (NOT (${CMAKE_BUILD_TYPE} MATCHES "Release")) + message("Enabling frame pointer for profiling/debug.") + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} -fno-omit-frame-pointer) + endif() + if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + message("Enabling SSE3 support.") + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} -msse3) + endif() +elseif (MSVC) + set(GRANITE_CXX_FLAGS /D_CRT_SECURE_NO_WARNINGS /wd4267 /wd4244 /wd4309 /wd4005 /MP) +endif() + +include(GNUInstallDirs) + +option(GRANITE_SHARED "Build Granite as a shared library." OFF) +option(GRANITE_ISPC_TEXTURE_COMPRESSION "Enable ISPC texture compression" OFF) +option(GRANITE_ASTC_ENCODER_COMPRESSION "Enable astc-encoder texture compression" OFF) +option(GRANITE_TOOLS "Build Granite tools." ON) +option(GRANITE_KHR_DISPLAY_ACQUIRE_XLIB "Try to acquire Xlib display when using VK_KHR_display." OFF) +option(GRANITE_ANDROID_APK_FILESYSTEM "Use APK file system for assets and builtin files." ON) +option(GRANITE_ANDROID_SWAPPY "Use swappy on Android." OFF) +option(GRANITE_SHADER_COMPILER_OPTIMIZE "Optimize SPIR-V." ON) +option(GRANITE_VULKAN_SYSTEM_HANDLES "Add system handle support to Vulkan backend." ON) +option(GRANITE_RENDERER "Add higher level rendering functionality." ON) +option(GRANITE_VULKAN_SPIRV_CROSS "Add reflection support to Vulkan backend." ON) +option(GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER "Enable Vulkan GLSL runtime compiler." ON) +option(GRANITE_VULKAN_FOSSILIZE "Enable support for Fossilize." ON) +option(GRANITE_VULKAN_PROFILES "Enable profiles support." OFF) +option(GRANITE_VULKAN_DXGI_INTEROP "Enable DXGI interop when running on Windows." ON) +option(GRANITE_VULKAN_POST_MORTEM "Add extra support for port-mortem debug." OFF) +option(GRANITE_AUDIO "Enable Audio support." OFF) +option(GRANITE_PLATFORM "Granite Platform" "SDL") +option(GRANITE_HIDDEN "Declare symbols as hidden by default. Useful if you build Granite as a static library and you link to it in your shared library." OFF) +option(GRANITE_SANITIZE_ADDRESS "Sanitize address" OFF) +option(GRANITE_SANITIZE_THREADS "Sanitize threads" OFF) +option(GRANITE_SANITIZE_MEMORY "Sanitize memory" OFF) +option(GRANITE_TARGET_NATIVE "Target native arch (-march=native)" OFF) +option(GRANITE_BULLET "Enable Bullet support." OFF) +option(GRANITE_RENDERDOC_CAPTURE "Enable support for RenderDoc capture from API." ON) +option(GRANITE_INSTALL_TARGETS "Add install targets." ON) +option(GRANITE_INSTALL_EXE_TARGETS "Add executable install targets." OFF) +option(GRANITE_FFMPEG "Enable FFmpeg." OFF) +option(GRANITE_FFMPEG_VULKAN "Enable experimental Vulkan HW decode support in FFmpeg." OFF) +option(GRANITE_FAST_MATH "Enable fast math." OFF) +option(GRANITE_SHIPPING "Disable code paths not related to development." OFF) +option(GRANITE_SYSTEM_SDL "Use system SDL3 instead of vendored submodule." OFF) + +if (GRANITE_FAST_MATH) + message("Enabling fast math.") + if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} -ffast-math) + elseif (MSVC) + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} /fp:fast) + endif() +else() + message("Enabling precise math.") + if (MSVC) + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} /fp:precise) + endif() +endif() + +if (NOT GRANITE_PLATFORM) + set(GRANITE_PLATFORM "SDL") +endif() + +if (GRANITE_HIDDEN) + if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") + endif() +elseif(${GRANITE_PLATFORM} MATCHES "libretro") + if (NOT GRANITE_SHARED) + if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") + endif() + endif() +endif() + +if (GRANITE_TARGET_NATIVE) + if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native") + endif() +endif() + +set(GRANITE_LINK_FLAGS) + +if (${CMAKE_VERSION} GREATER "3.13") + # Executable targets are not stripped in release mode on Android, do it explicitly. + add_link_options($<$,$>:-s>) +endif() + +if (GRANITE_SANITIZE_ADDRESS) + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} -fsanitize=address) + set(GRANITE_LINK_FLAGS "${GRANITE_LINK_FLAGS} -fsanitize=address") +endif() + +if (GRANITE_SANITIZE_THREADS) + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} -fsanitize=thread) + set(GRANITE_LINK_FLAGS "${GRANITE_LINK_FLAGS} -fsanitize=thread") +endif() + +if (GRANITE_SANITIZE_MEMORY) + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} -fsanitize=memory) + set(GRANITE_LINK_FLAGS "${GRANITE_LINK_FLAGS} -fsanitize=memory") +endif() + +if (ANDROID) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + +if (GRANITE_SHARED) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + +if (GRANITE_SHARED) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +else() + if (${GRANITE_PLATFORM} MATCHES "libretro") + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + elseif (GRANITE_POSITION_INDEPENDENT) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + elseif (ANDROID) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + else() + set(CMAKE_POSITION_INDEPENDENT_CODE OFF) + endif() +endif() + +set(GRANITE_VERSION_MAJOR 0) +set(GRANITE_VERSION_MINOR 0) +set(GRANITE_VERSION_PATCH 0) + +# Make sure .dlls are placed next to .exe, since there is no RPATH. +if (WIN32) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +endif() + +function(granite_install_executable NAME) + install(TARGETS ${NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + if (NOT WIN32) + set_target_properties(${NAME} PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") + endif() +endfunction() + +macro(granite_setup_default_link_libraries NAME) + if (NOT WIN32) + target_link_libraries(${NAME} PRIVATE -pthread dl m) + find_library(LIBRT_LIBRARY rt) + if (EXISTS ${LIBRT_LIBRARY}) + target_link_libraries(${NAME} PUBLIC rt) + endif() + endif() + if (WIN32 AND CMAKE_COMPILER_IS_GNUCXX) + target_link_libraries(${NAME} PRIVATE -static gcc stdc++ winpthread) + endif() +endmacro() + +function(add_granite_third_party_lib NAME) + if (GRANITE_SHARED) + add_library(${NAME} SHARED ${ARGN}) + + if (GRANITE_INSTALL_TARGETS) + if (WIN32) + install(TARGETS ${NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + else() + install(TARGETS ${NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) + set_target_properties(${NAME} PROPERTIES INSTALL_RPATH "\$ORIGIN/") + set_target_properties(${NAME} PROPERTIES + VERSION ${GRANITE_VERSION_MAJOR}.${GRANITE_VERSION_MINOR}.${GRANITE_VERSION_PATCH} + SOVERSION ${GRANITE_VERSION_MAJOR}) + endif() + endif() + + granite_setup_default_link_libraries(${NAME}) + + if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) + set_target_properties(${NAME} PROPERTIES LINK_FLAGS "-Wl,--no-undefined") + endif() + if (MSVC) + set_target_properties(${NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) + endif() + else() + add_library(${NAME} STATIC ${ARGN}) + if (MSVC) + set_target_properties(${NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS OFF) + endif() + endif() +endfunction() + +function(add_granite_internal_lib NAME) + add_granite_third_party_lib(${NAME} ${ARGN}) + target_compile_options(${NAME} PRIVATE ${GRANITE_CXX_FLAGS}) + if (GRANITE_SHARED AND MSVC) + set_target_properties(${NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) + endif() +endfunction() + +function(add_granite_internal_static_lib NAME) + add_library(${NAME} STATIC ${ARGN}) + target_compile_options(${NAME} PRIVATE ${GRANITE_CXX_FLAGS}) +endfunction() + +add_subdirectory(third_party) +add_subdirectory(util) +add_subdirectory(path) +add_subdirectory(math) +add_subdirectory(threading) +add_subdirectory(compiler) +add_subdirectory(filesystem) +add_subdirectory(vulkan) +add_subdirectory(ecs) +add_subdirectory(event) +if (GRANITE_VULKAN_SYSTEM_HANDLES AND GRANITE_RENDERER) + add_subdirectory(renderer) + add_subdirectory(ui) + add_subdirectory(scene-export) +endif() + +if (GRANITE_FFMPEG) + add_subdirectory(video) +endif() + +add_subdirectory(application) + +if (GRANITE_AUDIO) + add_subdirectory(audio) +endif() +if (GRANITE_BULLET) + add_subdirectory(physics) +endif() + +add_library(granite-base INTERFACE) +target_link_libraries(granite-base INTERFACE granite-util granite-path granite-application granite-vulkan) +if (TARGET granite-renderer) + target_link_libraries(granite-base INTERFACE granite-renderer granite-ui) +endif() + +function(add_granite_executable NAME) + if (ANDROID) + add_library(${NAME} SHARED ${ARGN}) + target_link_libraries(${NAME} PRIVATE log android) + elseif(${GRANITE_PLATFORM} MATCHES "libretro") + add_library(${NAME} SHARED ${ARGN}) + if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) + set_target_properties(${NAME} PROPERTIES LINK_FLAGS "-Wl,--no-undefined") + endif() + else() + add_executable(${NAME} ${ARGN}) + endif() + # Need this for some reason on OSX. + if (APPLE) + set_target_properties(${NAME} PROPERTIES LINK_FLAGS "-Wl,-all_load") + endif() + target_link_libraries(${NAME} PRIVATE granite-base granite-application-global-init) + target_compile_options(${NAME} PRIVATE ${GRANITE_CXX_FLAGS}) + granite_setup_default_link_libraries(${NAME}) + if (GRANITE_SANITIZE_ADDRESS OR GRANITE_SANITIZE_THREADS OR GRANITE_SANITIZE_MEMORY) + set_target_properties(${NAME} PROPERTIES LINK_FLAGS "${GRANITE_LINK_FLAGS}") + endif() +endfunction() + +function(add_granite_application TARGET_NAME) + if (WIN32 AND (NOT ${GRANITE_PLATFORM} MATCHES "libretro")) + add_granite_executable(${TARGET_NAME} WIN32 ${ARGN}) + else() + add_granite_executable(${TARGET_NAME} ${ARGN}) + endif() + if (ANDROID) + target_link_libraries(${TARGET_NAME} PRIVATE granite-base granite-platform) + elseif (${GRANITE_PLATFORM} MATCHES "libretro") + target_link_libraries(${TARGET_NAME} PRIVATE granite-base granite-platform) + else() + target_link_libraries(${TARGET_NAME} PRIVATE granite-application-entry) + endif() + granite_setup_default_link_libraries(${TARGET_NAME}) + if (GRANITE_INSTALL_EXE_TARGETS) + granite_install_executable(${TARGET_NAME}) + endif() +endfunction() + +function(add_granite_headless_application TARGET_NAME) + add_executable(${TARGET_NAME} ${ARGN}) + + target_compile_options(${TARGET_NAME} PRIVATE ${GRANITE_CXX_FLAGS}) + if (GRANITE_SANITIZE_ADDRESS OR GRANITE_SANITIZE_THREADS OR GRANITE_SANITIZE_MEMORY) + set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "${GRANITE_LINK_FLAGS}") + endif() + if (ANDROID) + target_link_libraries(${TARGET_NAME} PRIVATE log android) + endif() + target_link_libraries(${TARGET_NAME} PRIVATE granite-base granite-application-entry-headless) + granite_setup_default_link_libraries(${TARGET_NAME}) + if (GRANITE_INSTALL_EXE_TARGETS) + granite_install_executable(${TARGET_NAME}) + endif() +endfunction() + +function(add_granite_offline_tool NAME) + add_executable(${NAME} ${ARGN}) + target_compile_options(${NAME} PRIVATE ${GRANITE_CXX_FLAGS}) + + # Need this for some reason on OSX. + if (APPLE) + set_target_properties(${NAME} PROPERTIES LINK_FLAGS "-Wl,-all_load") + endif() + target_link_libraries(${NAME} PRIVATE granite-base granite-application-global-init) + target_compile_options(${NAME} PRIVATE ${GRANITE_CXX_FLAGS}) + if (GRANITE_SANITIZE_ADDRESS OR GRANITE_SANITIZE_THREADS OR GRANITE_SANITIZE_MEMORY) + set_target_properties(${NAME} PROPERTIES LINK_FLAGS "${GRANITE_LINK_FLAGS}") + endif() + granite_setup_default_link_libraries(${NAME}) + if (GRANITE_INSTALL_EXE_TARGETS) + granite_install_executable(${NAME}) + endif() +endfunction() + +if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") + set(GRANITE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +else() + set(GRANITE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE) + set(GRANITE_CXX_FLAGS ${GRANITE_CXX_FLAGS} PARENT_SCOPE) + set(GRANITE_LINK_FLAGS ${GRANITE_LINK_FLAGS} PARENT_SCOPE) +endif() + +function(add_blob_archive_target TARGET_NAME BLOB_NAME) + find_package(Python3 REQUIRED) + set_source_files_properties( + ${CMAKE_BINARY_DIR}/${BLOB_NAME}.h + ${CMAKE_BINARY_DIR}/${BLOB_NAME}.c + PROPERTIES GENERATED ON) + add_library(${TARGET_NAME} STATIC + ${CMAKE_BINARY_DIR}/${BLOB_NAME}.h + ${CMAKE_BINARY_DIR}/${BLOB_NAME}.c) + target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_BINARY_DIR}) + # ... CMake, y u gotta be like this. + set(_arg_list) + set(_arg_counter 0) + foreach(_arg IN LISTS ARGN) + math(EXPR _arg_counter_mod "${_arg_counter} % 2") + if (NOT ${_arg_counter_mod}) + list(APPEND _arg_list --input) + endif() + list(APPEND _arg_list ${_arg}) + math(EXPR _arg_counter "${_arg_counter} + 1") + endforeach() + add_custom_command(OUTPUT + ${CMAKE_BINARY_DIR}/${BLOB_NAME}.h + ${CMAKE_BINARY_DIR}/${BLOB_NAME}.c + COMMAND ${Python3_EXECUTABLE} + ${GRANITE_SOURCE_DIR}/tools/blobify.py + --output ${CMAKE_BINARY_DIR}/${BLOB_NAME}.blob + ${_arg_list} + COMMAND ${Python3_EXECUTABLE} + ${GRANITE_SOURCE_DIR}/tools/bin_to_text.py + --output ${CMAKE_BINARY_DIR}/${BLOB_NAME} + --blob-name ${BLOB_NAME} + ${CMAKE_BINARY_DIR}/${BLOB_NAME}.blob + BYPRODUCTS + ${CMAKE_BINARY_DIR}/${BLOB_NAME}.blob) +endfunction() + +if (TARGET granite-renderer) + add_subdirectory(tests) + add_subdirectory(viewer) + if (GRANITE_TOOLS) + add_subdirectory(tools) + add_subdirectory(renderer/fft/test) + endif() +endif() + +if (GRANITE_TOOLS AND GRANITE_VULKAN_SPIRV_CROSS AND GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER) + add_subdirectory(slangmosh) +endif() + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/LICENSE b/crates/pyrowave-sys/vendor/pyrowave/Granite/LICENSE new file mode 100644 index 00000000..e13a3380 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2017-2026 Hans-Kristian Arntzen + +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. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/OVERVIEW.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/OVERVIEW.md new file mode 100644 index 00000000..afd82779 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/OVERVIEW.md @@ -0,0 +1,632 @@ +# Granite code base overview + +The top level structure contains several folders which contain high level concepts. + +## Build system + +The build system is pure CMake and should be very straight forward to use. +To build Granite as a standalone project for example to run the glTF viewer, it's standard CMake: + +``` +mkdir build +cd build +cmake .. -DCMAKE_BUILD_TYPE=Release +make -j16 # Or whatever build system cmake spits out. +./viewer/gltf-viewer /path/to/my.gltf +``` + +A Python installation is probably necessary for SPIRV-Tools to build. + +### Submodules + +Granite uses submodules to pull in third party modules. Make sure that +`git submodule update --init` is called when checking out new versions of Granite. + +### Building Android apps with Granite + +There is no builtin way of building Android apps, but it's fairly straight forward to set up. +You can use the `gltf-viewer` as an example. + +#### Setting up the Gradle app folder + +You'll need an app folder. This is found under `viewer/app`, but you will need to make your own. +Here you place the Android manifest. The manifest needs to point to the GraniteActivity. +This activity is basically just NativeActivity with a few extra utility functions. +The lib_name needs to point to a particular native library which is the +CMake target you have chosen to use for your CMake `add_granite_application()`. +See `viewer/CMakeLists.txt` for how to use `add_granite_application()`. + +See `viewer/app/AndroidManifest.xml` for an example manifest file. +`viewer/app/build.gradle` connects CMake, the manifest, where to pull assets from, etc. +Make sure that the builtin resources in assets/ are pulled in as well as your own assets. +The viewer application has its own asset folder in `viewer/assets`. +For example, to try the Android version of the `gltf-viewer`, place a scene called `scene.glb` +into `viewer/assets` and build. By default, the Android app will load from `assets://scene.glb`, which will +point to the APKs asset manager. You can place `android.json`, `config.json` and `quirks.json` into the assets folder as well. +See the code for more detail. + +In `viewer/app/res`, various icons and string resources should go as normal. +The default `AndroidManifest.xml` points to a built-in Android icon, so you'll probably have to add that. + +In `viewer/app/build.gradle` replace what is needed. Likely, only the `targets` line. +Otherwise, it can mostly be copy-pasted. +`viewer/build.gradle` is weird magic that has to be there. +The gradle plugin version might depend a bit on your Android Studio installation. +`viewer/settings.gradle` pulls in your app as well as the simple, common GraniteActivity Java cruft. + +Once you've set it up, a normal gradle build should suffice. + +### Using Granite as a dependency + +Granite is designed to be used as a statically linked library, but can be built with position independent code if you need +to wrap your application in a dynamic library (e.g. libretro target). + +The normal idea is to have Granite somewhere as a folder in your tree, either a submodule, symlink or whatever. +Create a CMake project and add Granite as a subdirectory. +Use `add_granite_application()` to set up the build. +It's mostly just a convenience script to link in relevant targets. + +``` +cmake_minimum_required(VERSION 3.5) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_C_STANDARD 99) +project(AppBringup LANGUAGES CXX C) + +add_subdirectory(Granite EXCLUDE_FROM_ALL) + +add_granite_application(app-bringup app_bringup.cpp) +target_link_libraries(app-bringup renderer) +if (NOT ANDROID) + target_compile_definitions(app-bringup PRIVATE ASSET_DIRECTORY=\"${CMAKE_CURRENT_SOURCE_DIR}/assets\") +endif() +``` + +### Using Granite as a pure Vulkan backend + +Some projects would only be interested in the raw Vulkan backend. +The Vulkan backend has some dependencies on other Granite modules which might end up unwieldy. +Most of these can be stripped out, e.g.: + +``` +# If using Granite as part of your shared library. +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(GRANITE_POSITION_INDEPENDENT ON CACHE STRING "Granite position independent" FORCE) +set(GRANITE_HIDDEN ON CACHE STRING "Granite hidden" FORCE) + +# Disable dependencies on other modules. +set(GRANITE_VULKAN_FOSSILIZE OFF CACHE STRING "Vulkan Fossilize" FORCE) +set(GRANITE_VULKAN_SYSTEM_HANDLES OFF CACHE STRING "Vulkan filesystem" FORCE) +add_subdirectory(Granite EXCLUDE_FROM_ALL) +``` + +At this point, it should only depend on SPIRV-Cross and volk. + +## `application/` + +This module implements anything related to an applications lifecycle. +Platform specific application things go in here as well, like various backends for `VkSurfaceKHR`, +and input handling. + +- Android +- GLFW +- Headless (no WSI, used for benchmarking) +- VK_KHR_display +- libretro +- Custom plugin surface (used if you have some fancy, special purpose surface code). + +This module defines the "Application" interface, used by the platform code in the main loop. +The platform code implements main() or whatever equivalent the platform requires. + +The gltf-viewer application is also implemented here by `SceneViewerApplication`. +This application can load glTF scenes, and you can move around, add lights, I use it as a sandbox for testing stuff. + +See `application.cpp` for how to implement a `Granite::Application` interface. +You basically implement a `render_frame()` callback. + +Applications are expected to implement `Granite::application_create()`, which should create +an instance of the application, and the platform code will pump this through. +Applications do not own their main loop as some platforms do not support that. + +It is perfectly possible to avoid this and just use the Vulkan backend API directly. +This is useful for standalone tooling which needs to use the GPU. +See `tools/convert_cube_to_environment.cpp` as an example here. + +## `assets/` + +Here the builtin assets for Granite are found. Various shaders for the most part and a couple of look-up textures. +These are not relevant if you only use Granite for its Vulkan backend. + +## `compiler/` + +Here `third_party/shaderc` is used to implement GLSL -> SPIR-V compilation in run-time, +with or without optimizations with SPIRV-Tools-opt. +I do this for convenience sake. +A production application will probably want to pre-compile shaders and ship the SPIR-V only. + +## `event/` + +Here you find the event manager. The event manager is global, and is used to dispatch events throughout the application in a decoupled way. +There are two kinds of events, latched and immediate. Latched events are events which continue to persist until they are destroyed. +This is used for things like "device created" and "swapchain created". The device remains alive until it dies, similar with the swapchain. +For new event handler registrations, the event manager will make sure to fire events for device created events even if the device created event has already been fired. +This allows subsystems to always know when the Vulkan device is alive, or dead without having to plumb a ton of state through all the subsystems. + +Immediate events are things like "key pressed", "mouse moved" etc. These events fire once and disappear. +Event handlers must be member function which inherit from `Granite::EventHandler`. +You can easily create your own events by tagging a type. + +E.g.: + +``` +class SwapchainParameterEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(SwapchainParameterEvent) +}; + +class TestApp : public Granite::EventHandler +{ + TestApp() + { + EVENT_MANAGER_REGISTER_LATCH(TestApp, on_swapchain_created, on_swapchain_destroyed, SwapchainParameterEvent); + EVENT_MANAGER_REGISTER(TestApp, on_key_pressed, KeyboardEvent); + } + + // return true to keep responding to these events, false to detach yourself. + bool on_key_pressed(const KeyboardEvent &e); + + void on_swapchain_created(const SwapchainParameterEvent &e); + void on_swapchain_destroyed(const SwapchainParameterEvent &); +}; +``` + +This module also implements a simple Entity Component System (ECS). (Not sure why I moved it to event/, but anyways). +This is used by the scene graph for various purposes. Some pretty funky variadic template magic happens here. +You create entities, and components are added to them. You can query for component groups, e.g. "give me all renderables which should be rendered opaque", things like that. +It's a very neat system for different kind of queries. +It's likely very unoptimized compared to what it could be, +but I haven't had any issues except that removing components is quite costly. + +## `filesystem/` + +This implements a filesystem. +The design here is a bit radical. The only file operations supported are `mmap()` or `MapViewOfFile()`. No stream API exists. +On Android, the APK buffer mapping feature is used (which should basically map to mmap anyways for uncompressed files). + +The path system is based around protocols where a path is `protocol://path/inside/protocol`. The builtin protocols are: +- `builtin://`. Should always refer to `assets/` in some shape or form, where you can find the Granite builtin shaders and so on. +- `assets://`. Application specific assets. Usually set up by the application manually. +- `cache://`. Used for various caching purposes internally. Usually just points to `build_directory/cache`. + +Paths without a protocol are thought to be of the `file://` protocol, which is basically the same as just using the normal filesystem +path system directly. + +The filesystem supports notions of notifications when anything changes. There is a backend for inotify on Linux. +This is used to automatically reload textures and shaders when they are modified on disk. Very useful for hacking. + +The protocols are set up automatically on startup, but can be overridden by the application. + +## `math/` + +A simple math library cloning the parts of GLM I need. It used to be GLM, but it got bogged down in very long compile times, +so I rewrote only what I needed and sped up compilation by ~40/50% o_O. + +Matrix math conventions are like GLM: +- Matrices are column major. Indexing into a matrix picks out columns. +- Quaternions are declared in order W, X, Y, Z. +- The coordinate system is GL-style view space, a right handed coordinate system. In view space +X is right, +Y is up, camera points towards -Z. +- Clip space is Vulkan-like (duh). X is right, Y is down (top-left, not bottom-left like GL!), Z = 1 is far plane, Z = 0 is near plane. + Basically the projection matrices are like GL, except Y is flipped. I could have gone for bottom-left clip space, + but I would require VK_KHR_maintenance1 which isn't supported on some old Android phones (yay ...). + +## `network/` + +Some Linux-only networking code lying around. +It is used by the networked filesystem code, but it hasn't been worked on for a long time. + +## `renderer/` + +The biggest module. This module is responsible for implementing the high level rendering +code which deals with the problem of meshes, materials, scene graphs, lights, etc, etc. + +### `renderer/fft/` + +A Vulkan port of my GLFFT library. Used by Ocean rendering. + +### `renderer/lights/` + +Light rendering, including a clustered shading system. + +### `renderer/post/` + +Post-FX. HDR bloom and tonemapping, FXAA, SMAA and TAA. + +### `renderer/utils/` + +Some simple utility functions, like converting cubes and equirect into IBL and so on. +It can also read back and save textures (GTX format) to disk, even for arrays, cubes, etc. + +### `abstract_renderable.hpp` + +Renderable objects inherit from this. The `Renderer` will ask the `AbstractRenderable` for rendering info, which is pushed into a `RenderQueue`. +See `mesh.cpp` for the `StaticMesh` implementation. + +### `render_components.hpp` + +Some component types used in the renderer, like `OpaqueComponent`, `RenderableComponent`, etc. +Applications will pull out the components which are relevant and act on all of entities which have +certain combinations of components. + +### The flow of rendering objects + +You should study `SceneViewerApplication` for details. +The architecture for rendering glTF scenes is roughly as follows: + +#### Setup + +- Load scene with `SceneLoader`. This gives you a `Scene` which is basically an ECS paired with a node hierarchy. +- Have a `RenderContext`. This is responsible for containing global camera information, view and projection matrices, + frustum planes (for culling) and lighting setup. +- Set up a `LightingParameters` struct. Fill in relevant data, and pass it to `RenderContext::set_lighting_parameters()`. +- Make some Camera, either an `FPSCamera` or pick a camera from the `Scene`. +- Set up a `Renderer` with a constructor argument depending if it's a forward, deferred or lighting renderer. + If using forward, you need to set options using `Renderer::set_mesh_renderer_options_from_lighting()`. + This makes sure that the shaders will support all the features required from the Lighting setup. + +#### Per-frame + +You can modify `Scene::Node` transforms every frame for say, animation. +Every frame you need to call `Scene::update_cached_transforms()`. This will walk through the node hierarchy and update +world space `AABB`, world model matrix as well as normal matrices, or the transforms for all bones for skinned meshes. + +Also, we need to update the `RenderContext` based on the Camera. `RenderContext::set_camera()` will do this. + +Keep a `VisibilityList` around. +Query the `Scene` for renderables. For forward rendering, you could do something like: +- `Scene::gather_visible_opaque_renderables()` +- `Scene::gather_visible_transparent_renderables()` +- `Scene::gather_unbounded_renderables()` + +You pass in the render context and a visibility list, and out comes all the objects you need to render. + +To actually render, you would do: +- `Renderer::begin()`: Resets render queues. +- `Renderer::push_renderables()`: Calls `AbstractRenderable::get_render_info()` to push data into the render queue. +For depth-only rendering, use `push_depth_renderables` to get simpler rendering. +- `Renderer::flush()`: Sorts the queue as appropriate, batches, and submits commands to `CommandBuffer`. +You will need to be in a render pass (see Vulkan section) to call `flush()`. + +It is possible to pass in various flags to `flush()` which controls some common render state. + +### Render graph + +A powerful system for declaring the rendering you're doing up front, and have the render graph sort out dependencies and synchronization. +Used by the `SceneViewerApplication`. + +### Scene and scene loader + +Loads glTF scene, and constructs a `Scene` from it. The scene contains a node hierarchy as well as an Entity Component System to let application query relevant object types. + +### Shader suite + +The renderer uses a bank of shaders which renderable objects will pull shaders from. To get alternative shaders for glTF meshes and other renderables, this could be modified. + +## `scene_formats/` + +Deals with glTF file format import and export as well as dealing with compressed textures. + +- BC1/3/6/7 is supported through ISPC +- BC 4/5 is supported by custom code +- ASTC is supported by ISPC or astcenc + +A special purpose texture file format is defined here as well (GTX, Granite Texture Format, totally not confusing to anyone :P). +It's designed to be loaded directly as a memory mapped file and integrates nicely with the filesystem code. + +This used to use GLI to load KTX files, but there was no clean way to pipe it through with `mmap()` +and compile times soared. + +## `tests/` + +A couple ad-hoc tests and sandboxy code to test things quick and dirty. +You can find some API usage examples here. + +## `third_party/` + +Submodule heaven. All third party submodules are checked out here. See README.md for which submodules are used. + +## `threading/` + +A fairly straight forward thread pool with task scheduling and dependency tracking. Not used that extensively yet. +Used for texture loading in the texture manager and for the CPU clustering implementation. +The idea is to make the render graph automatically thread everything through this, but that's a pretty large TODO. + +## `tools/` + +Some useful tools for special purposes. Read source for more details. + +### `aa-bench` + +Benchmarks AA implementations. + +### `sweep_*.py` + +Benchmarks and analyzes a glTF scene rendered in many different ways. + +### `gltf-repacker` + +Optimizes a glTF scene. +Removes duplicate mesh data, quantizes attributes, optimizes meshes, compresses textures (into GTX format), etc. + +### `obj-to-gltf` + +A crude converter from OBJ to glTF. Needed a special purpose converter once for Sponza. + +## `ui/` + +A bare-bones retained mode UI experiment. + +## `util/` + +Various standalone utility classes. +The most widely used one is the `IntrusivePtr` and `IntrusiveList`, used by the Vulkan backend +to deal with ref-counted handles. + +The object pool is also used extensively. Pairing object pool with intrusive pointer was found +to be very nifty indeed. + +## `viewer/` + +A standalone glTF viewer. It uses `SceneViewerApplication` directly. + +## `vulkan/` + +This is the Vulkan backend and is the part of the code base which needs most +explanation and rationale behind its design. + +### `context.cpp` and `context.hpp` + +Here we have the "context". This is the module which: + +- Initializes the Vulkan loader +- Creates a VkInstance +- Creates a VkDevice +- Initializes various VkQueues. +The goal is to find 3 queues. +One for graphics or "general" workloads, +one compute queue (ideally async compute in a different queue family), +and one transfer/DMA queue (ideally a separate DMA engine). + +The queues will alias each other if no "ideal" queue can be found. +The context owns the lifetime for a VkInstance or VkDevice. + +Validation layers are also hooked up and reported here. + +### `wsi.cpp` and `wsi.hpp` + +In the layer below we have the WSI or windowing system integration. +This module is responsible for managing `VkSurfaceKHR` and `VkSwapchainKHR`. +Surfaces are created and interacted with through the `WSIPlatform` +interface which the platform code (or application code) is responsible for implementing. + +The module also has support for external swapchains, i.e. a swapchain whose images do not belong to a `VkSwapchainKHR`. +This is is useful for applications which want to use offscreen rendering only. +In this case, the implementation can simply pretend it's working with swapchain images +and provide release semaphores and take acquire semaphores directly from the application. + +The WSI owns a `Device` instance as well, so `WSI` is essentially a superset of `Device`. +Normally, an `Application` instance owns a `WSI` instance as well, +so applications normally don't need to know about this. + +The main entry points into WSI which are called on a per-frame basis is: +- `WSI::begin_frame()`: Acquires the swapchain, and calls `Device::begin_frame()` +- `WSI::end_frame()`: Flushes the frame with `Device::end_frame()`. If the swapchain was rendered into, +`vkQueuePresentKHR` will be called and the backbuffer is flipped on-screen. If the swapchain was not rendered into, +the implementation will stall with `vkDeviceWaitIdle` as it assumes the application is in some +kind of loading scenario and old resources should be flushed out. + +This is typically called by the platform code via `Application::run_frame()`. + +### `device.cpp` and `device.hpp` + +This is the main interface to Vulkan, `Vulkan::Device`. Here you: +- Create and allocate resources +- Request command buffers +- Submit command buffers and signal fences and/or semaphores +- Wait for semaphores, etc +- Various physical device queries (like format support, etc) +- Interact with texture and shader managers + +#### Per-frame resources + +To manage synchronization between CPU and GPU at a higher level, the implementation +has a concept of frames. Each frame corresponds to a swapchain frame. +Each frame owns a data structure which serves as a pool of various resources to be deleted or recycled. + +If you allocate command buffers, it comes from the pool of the current frame. +If you delete a resource like a buffer or image, it will be recycled back into +the per-frame pool, and deleted later. + +Each frame has a list of fences to wait for and/or recycle when that frame index begins. +When a particular frame has begun (usually pumped through by WSI acquire), fences are waited on, +and deferred actions happen. This will be resetting command pools, descriptor set allocator state updated, +buffers and images deleted, fences and semaphores recycled, and so on. +This scheme means we avoid having to think too hard about waiting on GPU to complete stuff +before we touch them on CPU. + +#### Command buffer requests and submissions + +To submit work to the GPU, you can request a command buffer with a specific type: +- Generic +- Async compute +- Async graphics (tries to run graphics on the compute queue if it can support it, very special purpose) +- Transfer + +This maps directly to a `VkCommandBuffer`, but has a lot of plumbing around it to make it easy. +There is a separate section for the details. + +When you request a command buffer you lock the current frame, and it cannot end until you submit +the command buffer. The reasoning for this is multi-threading complicated things +and the fact that command buffers are owned by a single `VkCommandPool`, +and thus allocators which are tied to a particular frame. +I chose not to decouple command buffer allocation from the frame, +or we would end up with a huge number of separate pools, +which on some implementations would be pretty terrible. + +Locking is only a potential problem with multi-threading if we try to record +some command buffer completely asynchronously with the swapchain and that operation takes a long time, +but recording the actual command buffer should be a quick and easy operation. +If locking ever becomes a problem, this needs to be redesigned a bit. +The main case where this "async command buffer" recording happens is threaded image uploads which are done by the texture manager. +However, just recording a simple `copy_buffer_to_image()` isn't the most expensive thing in the world. + +#### Resources + +Resources which are held by the application are managed through a "smart pointer", +but it is effectively typedef-ed away. All resource types like Buffer, Image, +etc implement `IntrusivePtrEnabled`, which embeds a shared_ptr-like control block internally. +The intent here is that we can easily make it single-threaded ref-count or multi-threaded (atomics), +by flipping a define or by changing the IntrusivePtrEnabled inheritance. + +Resource handle memory is managed through an `ObjectPool`, +which means freeing and allocating objects should minimize the required heap allocations. +When the `IntrusivePtr` is destroyed, it recycles itself properly into the respective pools. + +#### Allocating GPU memory + +Allocating GPU memory is done by a custom heap memory allocator. +This predates the de-factor memory allocator from AMD by a long while, but it's basically the same concept. +To the host side, you have some choices when you allocate buffers and images. + +Host-visible memory is always persistently mapped with `vkMapMemory()`. +Mapping and unmapping in the API is basically free, +except maybe `vkFlushMappedRanges` and similar if you're using incoherent memory. + +For buffers you can decide between: +- Device: The buffer will be kept in `DEVICE_LOCAL` memory. +It may or may not be `HOST_VISIBLE`. +- Host: The buffer will be kept in `HOST_VISIBLE | HOST_COHERENT`. +Designed for upload to the GPU, because it's likely not `CACHED`. +- CachedHost: `HOST_VISIBLE | HOST_CACHED`. May not be `COHERENT`, +but the details here are abstracted through `Device::map_host_buffer()`. +Use it for readbacks from GPU to CPU. + +For images you can pick: +- Physical: Backed by physical memory. +- Transient: Only backed by on-chip tile memory. Use for g-buffers, etc, although there is a simpler interface +for requesting transient surfaces, see `Device::get_transient_attachment()`. + +E.g.: +``` +CommandBufferHandle cmd = device->request_command_buffer(); +cmd->set_texture(set = 0, binding = 1, view = my_texture->get_view(), sampler = StockSampler::LinearClamp); +``` + +#### Shaders + +Shader objects can be requested from the Device by providing a SPIR-V blob. +Granite will manage these internally and build reflection information using SPIRV-Cross. +Programs are linked together using multiple Shader objects, this creates the final pipeline layout, +and we set up descriptor set allocators based on the associated descriptor set layouts. + +#### Texture and shader managers + +If filesystem support is built in (default), the Granite device also supports +a texture and shader manager. These allow you to pass in paths, and get handles back. +Through the magic of inotify, the backing shaders will be recompiled and textures will automatically update themselves. +The texture manager loads images in the background in the thread pool. + +#### Submitting command buffers, signalling sync objects and waiting + +You can submit command buffers using `Device::submit()`. +This will queue up submissions internally until flushed, and submit it as a batch. +You can pass in either a pointer to `Fence`, and/or `Semaphore`. +These map directly to `VkFence` and `VkSemaphore` respectively. +If you signal a fence or semaphore, +there is an implicit flush to ensure that we don't end up in a wait-before-signal scenario. + +Fences can wait on CPU, while semaphores can be waited on using `Device::add_wait_semaphore()` in a particular queue. +Note that semaphores can only be waited on once (Vulkan restriction), unlike fences. + +You can manually flush using `Device::flush_frame()`, wait idle and reclaim all pending resources with `Device::wait_idle()`, +or only signal fence or semaphores using `Device::submit_empty()`. + +### `command_buffer.hpp` and `command_buffer.cpp` + +The aim of Granite is a "mid-level" abstraction. Some convenience is allowed at the cost of CPU cycles, +but not so much that we're back to GL levels of silliness. + +#### Barriers and image layouts + +Granite does not attempt to perform any synchronization on behalf of the application, +except for a few isolated cases like `create_buffer()` and `create_image()`, +where we can just wait on `VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT`, and block all possible consumers of the resource. +Another exception is rendering to the swap chain. +The backend will wait for the acquire semaphore and deal with layout transitions automatically. +The other exception is transient images, these are synchronized with `VK_SUBPASS_EXTERNAL` dependencies, +and implicit layout transitions in a render pass. Applications do not need to synchronize this. + +It is your responsibility to synchronize with pipeline barriers, events, or semaphores. +You will also need to change image layouts manually. + +The render graph is designed to remove most of the need to do manual synchronization like this. + +Image handles can have one of two layouts "Optimal" and "General". If the image is in Optimal, the command buffer recorder +will always assume that the image is being used in its related, optimal layout. E.g., when sampling, it must be +`SHADER_READ_ONLY_OPTIMAL`. In General, the image layout is assumed to always be the catch-all `VK_IMAGE_LAYOUT_GENERAL`. + +#### Descriptor set management + +Descriptor sets are managed internally. +Granite uses a more traditional binding model where you bind resources to slots like in GL/D3D11, except, +to be more Vulkan-like, descriptor sets and bindings are separated. And there is no remapping of bindings. +On draw call time, Granite will build new descriptor sets for you, or reuse them if it has seen it before. +The application is freed from the burden of building descriptor sets by hand. +Descriptor set memory is managed internally as well, and recycled as appropriate. + +#### Pipeline management + +Granite also uses a more classic way of setting rendering state. +State can be saved and restored in a more stack-like way which removes most need to set specific rendering state +all the time in scene rendering. Pipelines are compiled on-demand. + +Since on-demand pipeline creation can cause issues, Granite supports pipeline caches, as well as Fossilize, which +allows us to prewarm the internal hashmaps with VkPipelines ready to go if we so choose. + +#### Allocating scratch data (VBO, IBO, UBO) + +Sometimes you just need to stream out data and forget about it, like vertex buffers, index buffers, and in particular, +uniform buffer data. To avoid having to manage this memory explicitly, the command buffers has convenience functions +to allocate and bind. This allocation is basically free because it's backed by a pool of linear allocators. +Always use this for streamed data which can be discarded after you're done rendering. + +#### Updating textures asynchronously + +Similar to creating staging data for VBO, IBO and UBOs, you can do similar kind of updates to textures. +It will allocate staging data for you, issue `vkCmdCopyBufferToImage` commands and give you a pointer you can write. + +#### Drawing + +Granite supports the basic draw commands you'd expect. +On draw, any dirty state or dirty descriptor sets are resolved, +just like you would expect in an older engine. + +#### Render passes + +Granite has very explicit render passes, and maps almost 1:1 to Vulkan. +You fill in a `RenderPassInfo` and call `CommandBuffer::begin_render_pass()` and `end_render_pass()`. +You can declare a full multipass setup, but you are freed from the burden of figuring out subpass dependencies, +layout transitions in the render passes, etc. + +For the simple non-multipass case, you need to set up: +- Color attachments w/ count +- Depth stencil attachment +- Which attachments should be cleared, and to what color. +- Which attachments should be loaded to tile. +- Which attachments should be stored and not discarded. +- Whether depth-stencil is read-only. + +##### Rendering to swap chain + +There is a special purpose function to render to the swap chain. +Use `Device::get_swapchain_render_pass()`. +You can pick if you want color-only, color/depth or color/depth/stencil attachments. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/README.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/README.md new file mode 100644 index 00000000..971b1a68 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/README.md @@ -0,0 +1,205 @@ +# Granite + +Granite is my personal Vulkan renderer project. + +## Why release this? + +The most interesting part of this project compared to the other open-source Vulkan renderers so far +is probably the render graph implementation. + +The project is on GitHub in the hope it might be useful as-is +for learning purposes or generating implementation ideas. + +### Disclaimer + +**Do not expect any support or help. +Pull requests will likely be ignored or dismissed.** + +## License + +The code is licensed under MIT. Feel free to use it for whatever purpose. + +## High-level documentation + +See `OVERVIEW.md`. + +## Low-level rendering backend + +The rendering backend focuses entirely on Vulkan, +so it reuses Vulkan enums and data structures where appropriate. +However, the API greatly simplifies the more painful points of writing straight Vulkan. +It's not designed to be the fastest renderer ever made, it's likely a happy middle ground between +"perfect" Vulkan and OpenGL/D3D11 w.r.t. CPU overhead. + +- Memory manager +- Deferred destruction and release of API objects and memory +- Automatic descriptor set management +- Linear allocators for vertex/index/uniform/staging data +- Automatic pipeline creation +- Command buffer tracks state similar to older APIs +- Uses TRANSFER-queue on desktop to upload linear-allocated vertex/index/uniform data in bulk +- Vulkan GLSL for shaders, shaders are compiled in runtime with shaderc +- Pipeline cache save-to-disk and reload +- Warm up internal hashmaps with Fossilize +- Easier-to-use fences and semaphores + +Missing bits: +- Multithreaded rendering +- Precompile all shaders to optimized SPIR-V + +Implementation is found in `vulkan/`. + +## High-level rendering backend + +A basic scene graph, component system and other higher-level scaffolding lives in `renderer/`. +This is probably the most unoptimized and naive part. + +## PBR renderer + +Pretty barebones, half-assed PBR renderer. Very simplified IBL support. +Fancy rendering is not the real motivation behind this project. + +## Post-AA + +Fairly straight forward FXAA, SMAA and TAA (no true velocity buffer though). + +## Automatic shader recompile and texture reload (Linux/Android only) + +Immediately when shaders are modified or textures are changed, the resources are automatically reloaded. +The implementation uses inotify to do this, +so it's exclusive to Linux unless a backend is implemented on Windows (no). + +## Network VFS + +For Linux host and Android device, +assets and shaders can be pulled over TCP (via ADB port-forwarding) with `network/netfs_server.cpp`. +Quite convenient. + +## Validation + +In debug build, LunarG validation layers are enabled. +Granite is squeaky clean. + +## Render graph + +`renderer/render_graph.hpp` and `renderer/render_graph.cpp` contains a fairly complete +render graph. It supports: + +- Automatic layout transitions +- Automatic loadOp/storeOp usage +- Automatic scaled loadOp for simple lower-res game -> high-res UI rendering scenarios +- Uses async compute queues automatically +- Optimal barrier placement, signals as early as possible, waits as late as possible + VkEvent is used for in-queue resources, VkSemaphore for cross-queue resources +- Basic render target aliasing +- Can merge two or more passes into multiple subpasses for efficient rendering on tile-based architectures +- Automatic mip-mapping if requested +- Uses transient attachments automatically to save memory on tile-based architectures +- Render target history, read previous frame's results in next frame for feedback +- Conditional render passes, can preserve render passes if necessary +- Render passes are reordered for optimal (?) overlap in execution +- Automatic, optimal multisampled resolve with pResolveAttachments + +I have written up a longer blog post about its implementation +[here](http://themaister.net/blog/2017/08/15/render-graphs-and-vulkan-a-deep-dive/). + +The default application scene renderer in `application/application.cpp` sets up +a render graph which does: +- Conditionally renders a shadow map covering entire scene +- Renders a close shadow map +- Automatically pulls in reflection/refraction render passes if present in the scene graph +- Renders scene G-Buffer with deferred +- Lighting pass (merged with G-Buffer pass into a single render pass) +- Bloom threshold pass +- Bloom pyramid downsampling +- Async compute is kicked off to get average luminance of scene, adjusts exposure +- Two upsampling steps to complete blurring in parallel with async +- Tonemap (HDR + Bloom) rendered to backbuffer (sRGB) +- (Potentially UI can be rendered on top with merged subpasses) + +## Scene format + +glTF 2.0 with PBR materials is mostly supported. +A custom JSON format is also added in order to plug multiple +glTF files together for rapid prototyping of test scenes. + +## Texture formats + +- PNG, JPG, TGA, HDR (via stb) +- GTX (Granite Texture Format, custom texture format for compressed formats) + +ASTC, ETC2 and BCn/DXTn compressed formats are supported. + +## `gltf-repacker` + +There's a tool to repack glTF models. +Textures can be compressed to ASTC or BC using ISPC Texture Compressor. +zeux's meshoptimizer library can also optimize meshes. +The glTF emitted uses some Granite specific extras to be more optimal, so it's mostly for internal use. + +## Compilers + +Tested on GCC, Clang, and MSVC 2017. + +## Platforms + +- SDL3 (Linux / Windows) +- `VK_KHR_display` (headless Linux w/ basic keyboard, mouse, gamepad support) +- libretro Vulkan HW interface +- Headless (benchmarking) +- Custom surface plugin +- Android + +## Vulkan implementations tested + +- AMD Linux (Mesa, AMDVLK) +- Intel Linux (Mesa) +- AMD Windows +- nVidia Linux +- Arm Mali (Galaxy S7/S8/S9) +- Pixel C tablet (Tegra X1) + +## Build + +Plain CMake. Remember to check out submodules with `git submodule update --init`. + +``` +mkdir build +cd build +cmake .. -DCMAKE_BUILD_TYPE=Release -G Ninja +ninja -j16 # YMMV :3 +``` + +For MSVC, it should work to use the appropriate `-G` flag. +There aren't any real samples yet, so not much to do unless you use Granite as a submodule. + +`viewer/gltf-viewer` is a basic glTF viewer used as my sandbox for more complex testing. +Try some models from glTF-Sample-Models. + +### Android + +Something ala: +``` +cd viewer +gradle build +``` +Assets used in the default `gltf-viewer` target are pulled from `viewer/assets`. + +### Third party software + +These are pulled in as submodules. + +- [SDL3](https://github.com/libsdl-org/SDL) +- [glslang](https://github.com/google/glslang.git) +- [rapidjson](https://github.com/miloyip/rapidjson) +- [shaderc](https://github.com/google/shaderc.git) +- [SPIRV-Cross](https://github.com/KhronosGroup/SPIRV-Cross) +- [SPIRV-Headers](https://github.com/KhronosGroup/SPIRV-Headers) +- [SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools) +- [stb](https://github.com/nothings/stb) +- [volk](https://github.com/zeux/volk) +- [meshoptimizer](https://github.com/zeux/meshoptimizer) +- [Fossilize](https://github.com/ValveSoftware/Fossilize) +- [muFFT](https://github.com/Themaister/muFFT) +- MikkTSpace (inlined into `third_party/mikktspace`) + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/CMakeLists.txt new file mode 100644 index 00000000..fd73f51d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/CMakeLists.txt @@ -0,0 +1,64 @@ +add_granite_internal_lib(granite-application + application.hpp + application_glue.hpp + application.cpp) + +if (GRANITE_FFMPEG) + target_link_libraries(granite-application PRIVATE granite-video) +endif() + +target_link_libraries(granite-application PUBLIC + granite-vulkan + granite-event + granite-input + granite-application-global-init + granite-application-events + granite-threading + granite-filesystem) + +if (NOT (${GRANITE_PLATFORM} MATCHES "null")) + target_sources(granite-application PRIVATE platforms/application_headless.cpp) + target_link_libraries(granite-application PRIVATE granite-stb granite-rapidjson) +endif() + +target_include_directories(granite-application PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +if (TARGET granite-renderer) + target_link_libraries(granite-application PUBLIC granite-renderer PRIVATE granite-ui) + target_compile_definitions(granite-application PRIVATE HAVE_GRANITE_RENDERER) + + add_granite_internal_lib(granite-scene-viewer scene_viewer_application.cpp scene_viewer_application.hpp) + target_include_directories(granite-scene-viewer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(granite-scene-viewer + PUBLIC granite-scene-export granite-ui granite-application + PRIVATE granite-rapidjson) +endif() + +# Can be defined by application to get a custom entry point. +# Otherwise, get a default one. +if (NOT TARGET granite-application-interface-query) + add_granite_internal_lib(granite-application-interface-query STATIC application_interface_query.cpp) + target_compile_options(granite-application-interface-query PRIVATE ${GRANITE_CXX_FLAGS}) +endif() + +if (NOT ANDROID) + add_granite_internal_lib(granite-application-entry STATIC application_entry.cpp) + target_compile_options(granite-application-entry PRIVATE ${GRANITE_CXX_FLAGS}) + target_link_libraries(granite-application-entry + PRIVATE granite-application-interface-query granite-application granite-platform granite-filesystem) +endif() + +add_library(granite-application-entry-headless STATIC application_entry.cpp) +target_compile_definitions(granite-application-entry-headless PRIVATE APPLICATION_ENTRY_HEADLESS=1) +target_link_libraries(granite-application-entry-headless + PRIVATE granite-application-interface-query granite-application granite-platform granite-filesystem) +target_compile_options(granite-application-entry-headless PRIVATE ${GRANITE_CXX_FLAGS}) + +add_subdirectory(events) +add_subdirectory(input) +add_subdirectory(platforms) +add_subdirectory(global) + +if (GRANITE_AUDIO) + target_link_libraries(granite-application PRIVATE granite-audio) +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application.cpp new file mode 100644 index 00000000..709c75e4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application.cpp @@ -0,0 +1,344 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "application.hpp" +#include "asset_manager.hpp" +#include "thread_group.hpp" +#ifdef HAVE_GRANITE_RENDERER +#include "material_manager.hpp" +#include "common_renderer_data.hpp" +#endif +#ifdef HAVE_GRANITE_AUDIO +#include "audio_mixer.hpp" +#endif + +using namespace Vulkan; + +namespace Granite +{ +Application::~Application() +{ + auto *group = GRANITE_THREAD_GROUP(); + if (group) + group->wait_idle(); + + teardown_wsi(); +} + +bool Application::init_platform(std::unique_ptr new_platform) +{ +#ifdef HAVE_GRANITE_RENDERER + if (auto *common = GRANITE_COMMON_RENDERER_DATA()) + common->initialize_static_assets(GRANITE_ASSET_MANAGER(), GRANITE_FILESYSTEM()); +#endif + platform = std::move(new_platform); + application_wsi.set_platform(platform.get()); + + if (auto *event = GRANITE_EVENT_MANAGER()) + event->enqueue_latched(*platform); + + return true; +} + +void Application::teardown_wsi() +{ + if (auto *event = GRANITE_EVENT_MANAGER()) + { + event->dequeue_all_latched(DevicePipelineReadyEvent::get_type_id()); + event->dequeue_all_latched(DeviceShaderModuleReadyEvent::get_type_id()); + event->dequeue_all_latched(ApplicationWSIPlatformEvent::get_type_id()); + } + application_wsi.teardown(); + ready_modules = false; + ready_pipelines = false; +} + +bool Application::init_wsi(Vulkan::ContextHandle context) +{ + if (context) + { + if (!application_wsi.init_from_existing_context(std::move(context))) + return false; + } + else + { + Context::SystemHandles system_handles; + system_handles.filesystem = GRANITE_FILESYSTEM(); + system_handles.thread_group = GRANITE_THREAD_GROUP(); + system_handles.asset_manager = GRANITE_ASSET_MANAGER(); + system_handles.timeline_trace_file = system_handles.thread_group->get_timeline_trace_file(); + + if (!application_wsi.init_context_from_platform( + system_handles.thread_group->get_num_threads() + 1, + system_handles)) + { + return false; + } + } + + if (!application_wsi.init_device()) + return false; + + application_wsi.get_device().begin_shader_caches(); + + { + GRANITE_SCOPED_TIMELINE_EVENT("wsi-init-swapchain"); + if (!platform->has_external_swapchain() && !application_wsi.init_surface_swapchain()) + return false; + } + + return true; +} + +void Application::poll_input_tracker_async(Granite::InputTrackerHandler *override_handler) +{ + get_platform().poll_input_async(override_handler); +} + +bool Application::poll() +{ + auto &wsi = get_wsi(); + if (!get_platform().alive(wsi)) + return false; + + if (requested_shutdown) + return false; + + auto *fs = GRANITE_FILESYSTEM(); + auto *em = GRANITE_EVENT_MANAGER(); + if (fs) + fs->poll_notifications(); + if (em) + em->dispatch(); + +#ifdef HAVE_GRANITE_AUDIO + auto *backend = GRANITE_AUDIO_BACKEND(); + if (backend) + backend->heartbeat(); + auto *am = GRANITE_AUDIO_MIXER(); + if (am) + { + // Pump through events from audio thread. + auto &queue = am->get_message_queue(); + Util::MessageQueuePayload payload; + while ((payload = queue.read_message())) + { + auto &event = payload.as(); + if (em) + em->dispatch_inline(event); + queue.recycle_payload(std::move(payload)); + } + + // Recycle dead streams. + am->dispose_dead_streams(); + } +#endif + + return true; +} + +void Application::check_initialization_progress() +{ + auto &device = get_wsi().get_device(); + + if (!ready_modules) + { + if (device.query_initialization_progress(Device::InitializationStage::CacheMaintenance) >= 100 && + device.query_initialization_progress(Device::InitializationStage::ShaderModules) >= 100) + { + if (auto *manager = GRANITE_ASSET_MANAGER()) + { + // Now is a good time to kick shader manager since it might require compute shaders for decode. + manager->iterate(GRANITE_THREAD_GROUP()); + } + + if (auto *event = GRANITE_EVENT_MANAGER()) + { + GRANITE_SCOPED_TIMELINE_EVENT("dispatch-ready-modules"); +#ifdef HAVE_GRANITE_RENDERER + auto *manager = &device.get_shader_manager(); +#else + constexpr Vulkan::ShaderManager *manager = nullptr; +#endif + event->enqueue_latched(&device, manager); + } + ready_modules = true; + } + } + + if (!ready_pipelines) + { + if (device.query_initialization_progress(Device::InitializationStage::Pipelines) >= 100) + { + if (auto *event = GRANITE_EVENT_MANAGER()) + { + GRANITE_SCOPED_TIMELINE_EVENT("dispatch-ready-pipelines"); +#ifdef HAVE_GRANITE_RENDERER + auto *manager = &device.get_shader_manager(); +#else + constexpr Vulkan::ShaderManager *manager = nullptr; +#endif + event->enqueue_latched(&device, manager); + } + ready_pipelines = true; + } + } +} + +void Application::show_message_box(const std::string &str, Vulkan::WSIPlatform::MessageType type) +{ + if (platform) + platform->show_message_box(str, type); + + switch (type) + { + case Vulkan::WSIPlatform::MessageType::Error: + LOGE("%s\n", str.c_str()); + break; + + case Vulkan::WSIPlatform::MessageType::Warning: + LOGW("%s\n", str.c_str()); + break; + + case Vulkan::WSIPlatform::MessageType::Info: + LOGI("%s\n", str.c_str()); + break; + } +} + +void Application::run_frame() +{ + check_initialization_progress(); + + { + GRANITE_SCOPED_TIMELINE_EVENT("wsi-begin-frame"); + if (!application_wsi.begin_frame()) + { + LOGE("Failed to begin frame. Fatal error. Shutting down.\n"); + request_shutdown(); + return; + } + } + + double smooth_frame_time = application_wsi.get_smooth_frame_time(); + double smooth_elapsed = application_wsi.get_smooth_elapsed_time(); + + if (!ready_modules) + { + GRANITE_SCOPED_TIMELINE_EVENT("render-early-loading"); + render_early_loading(smooth_frame_time, smooth_elapsed); + } + else if (!ready_pipelines) + { + GRANITE_SCOPED_TIMELINE_EVENT("render-loading"); + render_loading(smooth_frame_time, smooth_elapsed); + } + else + { + GRANITE_SCOPED_TIMELINE_EVENT("render-frame"); + render_frame(smooth_frame_time, smooth_elapsed); + } + + { + GRANITE_SCOPED_TIMELINE_EVENT("wsi-end-frame"); + application_wsi.end_frame(); + } + + { + GRANITE_SCOPED_TIMELINE_EVENT("post-frame"); + post_frame(); + } +} + +void Application::render_early_loading(double, double) +{ + auto &device = application_wsi.get_device(); + auto cmd = device.request_command_buffer(); + auto rp = device.get_swapchain_render_pass(SwapchainRenderPass::ColorOnly); + rp.clear_color[0].float32[0] = 0.01f; + rp.clear_color[0].float32[2] = 0.02f; + rp.clear_color[0].float32[3] = 0.03f; + cmd->begin_render_pass(rp); + auto vp = cmd->get_viewport(); + + VkClearRect rect = {}; + rect.layerCount = 1; + rect.rect.extent = { + uint32_t(vp.width * 0.01f * float(device.query_initialization_progress(Device::InitializationStage::ShaderModules))), + uint32_t(vp.height), + }; + + VkClearValue value = {}; + value.color.float32[0] = 0.08f; + value.color.float32[1] = 0.01f; + value.color.float32[2] = 0.01f; + + if (rect.rect.extent.width > 0) + cmd->clear_quad(0, rect, value); + + cmd->end_render_pass(); + device.submit(cmd); +} + +void Application::render_loading(double, double) +{ + auto &device = application_wsi.get_device(); + auto cmd = device.request_command_buffer(); + auto rp = device.get_swapchain_render_pass(SwapchainRenderPass::ColorOnly); + rp.clear_color[0].float32[0] = 0.01f; + rp.clear_color[0].float32[2] = 0.02f; + rp.clear_color[0].float32[3] = 0.03f; + cmd->begin_render_pass(rp); + auto vp = cmd->get_viewport(); + + VkClearRect rect = {}; + rect.layerCount = 1; + rect.rect.extent = { + uint32_t(vp.width * 0.01f * float(device.query_initialization_progress(Device::InitializationStage::Pipelines))), + uint32_t(vp.height), + }; + + VkClearValue value = {}; + value.color.float32[0] = 0.01f; + value.color.float32[1] = 0.08f; + value.color.float32[2] = 0.01f; + if (rect.rect.extent.width > 0) + cmd->clear_quad(0, rect, value); + + cmd->end_render_pass(); + device.submit(cmd); +} + +void Application::post_frame() +{ + // Texture manager might require shaders to be ready before we can submit work. + if (ready_modules) + { + if (auto *manager = GRANITE_ASSET_MANAGER()) + manager->iterate(GRANITE_THREAD_GROUP()); + } + + if (auto *manager = Global::material_manager()) + manager->iterate(Global::asset_manager()); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application.hpp new file mode 100644 index 00000000..cdb88fc0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application.hpp @@ -0,0 +1,106 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include "wsi.hpp" +#include "application_wsi_events.hpp" +#include "input.hpp" +#include "application_glue.hpp" + +namespace Granite +{ +class Application +{ +public: + virtual ~Application(); + virtual void render_frame(double frame_time, double elapsed_time) = 0; + bool init_platform(std::unique_ptr platform); + bool init_wsi(Vulkan::ContextHandle context = {}); + void teardown_wsi(); + + // Called after the frame is submitted for presentation. + // Can do "garbage collection" or similar batched cleanup + // that does not depend on submitting more graphics work. + virtual void post_frame(); + + // In early loading, we have not loaded SPIR-V yet. + // Rendering a background color or extremely basic shaders could work here. + // If compiling without SPIRV-Cross or compiler support in a shipping configuration, + // any SPIR-V must be provided inline through slangmosh or similar. + virtual void render_early_loading(double frame_time, double elapsed_time); + // In loading, we have access to SPIR-V, but compiling pipelines is not done yet. + // This stage is more suited for rendering splash screens or similar. + virtual void render_loading(double frame_time, double elapsed_time); + + Vulkan::WSI &get_wsi() + { + return application_wsi; + } + + Vulkan::WSIPlatform &get_platform() + { + return *platform; + } + + virtual std::string get_name() + { + return "granite"; + } + + virtual unsigned get_version() + { + return 0; + } + + virtual unsigned get_default_width() + { + return 1280; + } + + virtual unsigned get_default_height() + { + return 720; + } + + bool poll(); + void run_frame(); + void show_message_box(const std::string &str, Vulkan::WSIPlatform::MessageType type); + +protected: + void request_shutdown() + { + requested_shutdown = true; + } + + void poll_input_tracker_async(InputTrackerHandler *override_handler); + +private: + std::unique_ptr platform; + Vulkan::WSI application_wsi; + bool requested_shutdown = false; + + // Ready state for deferred device initialization. + bool ready_modules = false; + bool ready_pipelines = false; + void check_initialization_progress(); +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application_entry.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application_entry.cpp new file mode 100644 index 00000000..b953c256 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application_entry.cpp @@ -0,0 +1,100 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "application.hpp" +#include "filesystem.hpp" +#include "path_utils.hpp" + +//#define USE_FP_EXCEPTIONS +#ifdef USE_FP_EXCEPTIONS +#include +#endif + +#if defined(_WIN32) && !defined(APPLICATION_ENTRY_HEADLESS) +#define USE_WINMAIN +#endif + +#ifdef USE_WINMAIN +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#endif + +namespace Granite +{ +// Make sure this is linked in. +void application_dummy() +{ +} + +// Alternatively, make sure this is linked in. +// Implementation is here to trick a linker to always let main() in static library work. +void application_setup_default_filesystem(const char *default_asset_directory) +{ + auto *filesystem = GRANITE_FILESYSTEM(); + if (filesystem) + Filesystem::setup_default_filesystem(filesystem, default_asset_directory); +} +} + +#ifdef USE_WINMAIN +int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +#else +int main(int argc, char *argv[]) +#endif +{ +#ifdef USE_FP_EXCEPTIONS + feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); +#endif + +#ifdef USE_WINMAIN + int argc; + wchar_t **wide_argv = CommandLineToArgvW(GetCommandLineW(), &argc); + std::vector argv_buffer(argc + 1); + char **argv = nullptr; + std::vector argv_strings(argc); + + if (wide_argv) + { + argv = argv_buffer.data(); + for (int i = 0; i < argc; i++) + { + argv_strings[i] = Granite::Path::to_utf8(wide_argv[i]); + argv_buffer[i] = const_cast(argv_strings[i].c_str()); + } + } +#endif + +#ifdef APPLICATION_ENTRY_HEADLESS + int ret = Granite::application_main_headless(Granite::query_application_interface, + Granite::application_create, + argc, argv); +#else + int ret = Granite::application_main(Granite::query_application_interface, + Granite::application_create, + argc, argv); +#endif + + return ret; +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application_glue.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application_glue.hpp new file mode 100644 index 00000000..46254f44 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application_glue.hpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include +#include + +namespace Granite +{ +enum class ApplicationQuery +{ + DefaultManagerFlags +}; + +class Application; + +int application_main( + bool (*query_application_interface)(ApplicationQuery, void *data, size_t size), + Application *(*create_application)(int, char **), + int argc, char **argv); + +int application_main_headless( + bool (*query_application_interface)(ApplicationQuery, void *data, size_t size), + Application *(*create_application)(int, char **), + int argc, char **argv); + +extern Application *application_create(int argc, char *argv[]); + +struct ApplicationQueryDefaultManagerFlags +{ + uint32_t manager_feature_flags; +}; + +extern bool query_application_interface(ApplicationQuery query, void *data, size_t size); + +// Call this or setup_default_filesystem to ensure application-main is linked in correctly without having to mess around +// with -Wl,--whole-archive. +void application_dummy(); + +void application_setup_default_filesystem(const char *default_asset_directory); +} + +#ifdef ASSET_DIRECTORY +#define GRANITE_APPLICATION_SETUP_FILESYSTEM() ::Granite::application_setup_default_filesystem(ASSET_DIRECTORY) +#else +#define GRANITE_APPLICATION_SETUP_FILESYSTEM() ::Granite::application_setup_default_filesystem(nullptr) +#endif + +#define GRANITE_APPLICATION_DECL_DEFAULT_QUERY() namespace Granite { bool query_application_interface(Granite::ApplicationQuery, void *, size_t) { return false; } } diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application_interface_query.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application_interface_query.cpp new file mode 100644 index 00000000..19a85a1e --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/application_interface_query.cpp @@ -0,0 +1,2 @@ +#include "application_glue.hpp" +GRANITE_APPLICATION_DECL_DEFAULT_QUERY() \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/CMakeLists.txt new file mode 100644 index 00000000..f2b921f8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/CMakeLists.txt @@ -0,0 +1,7 @@ +add_granite_internal_lib(granite-application-events + application_wsi.hpp + application_wsi.cpp application_wsi_events.hpp + application_events.hpp) +target_include_directories(granite-application-events PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-application-events + PRIVATE granite-vulkan granite-event granite-input granite-application-global) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_events.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_events.hpp new file mode 100644 index 00000000..5d2e160a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_events.hpp @@ -0,0 +1,55 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "event.hpp" + +namespace Granite +{ +enum class ApplicationLifecycle +{ + Running, + Paused, + Stopped, + Dead +}; + +class ApplicationLifecycleEvent : public Event +{ +public: + GRANITE_EVENT_TYPE_DECL(ApplicationLifecycleEvent) + + explicit ApplicationLifecycleEvent(ApplicationLifecycle lifecycle_) + : lifecycle(lifecycle_) + { + } + + ApplicationLifecycle get_lifecycle() const + { + return lifecycle; + } + +private: + ApplicationLifecycle lifecycle; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_wsi.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_wsi.cpp new file mode 100644 index 00000000..07911446 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_wsi.cpp @@ -0,0 +1,188 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "application_wsi.hpp" +#include "application_wsi_events.hpp" +#include "application_events.hpp" +#include "global_managers.hpp" +#include "event.hpp" + +namespace Granite +{ +GraniteWSIPlatform::GraniteWSIPlatform() +{ + input_tracker.set_input_handler(this); +} + +void GraniteWSIPlatform::event_swapchain_created(Vulkan::Device *device, VkSwapchainKHR, unsigned width, unsigned height, + float aspect_ratio, size_t image_count, VkFormat format, + VkColorSpaceKHR color_space, + VkSurfaceTransformFlagBitsKHR transform) +{ + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + { + em->enqueue_latched(device, width, height, aspect_ratio, image_count, format, + color_space, transform); + } +} + +void GraniteWSIPlatform::event_swapchain_destroyed() +{ + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + em->dequeue_all_latched(Vulkan::SwapchainParameterEvent::get_type_id()); +} + +void GraniteWSIPlatform::event_device_created(Vulkan::Device *device) +{ + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + em->enqueue_latched(device); +} + +void GraniteWSIPlatform::event_device_destroyed() +{ + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + em->dequeue_all_latched(Vulkan::DeviceCreatedEvent::get_type_id()); +} + +void GraniteWSIPlatform::event_swapchain_index(Vulkan::Device *device, unsigned index) +{ + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + { + em->dequeue_all_latched(Vulkan::SwapchainIndexEvent::get_type_id()); + em->enqueue_latched(device, index); + } +} + +void GraniteWSIPlatform::event_frame_tick(double, double) +{ +} + +template +void GraniteWSIPlatform::dispatch_template(const T &t) +{ + if (auto *em = GRANITE_EVENT_MANAGER()) + em->dispatch_inline(t); +} + +template +void GraniteWSIPlatform::dispatch_template_filter(const T &t) +{ + auto *ui = Global::ui_manager(); + if (ui && !ui->filter_input_event(t)) + return; + dispatch_template(t); +} + +template +void GraniteWSIPlatform::dispatch_or_defer(Func &&func) +{ + if (in_async_input) + captured.emplace_back(std::forward(func)); + else + func(); +} + +#define WORK(work) dispatch_or_defer([this, e]() { work; }) + +void GraniteWSIPlatform::dispatch(const TouchDownEvent &e) +{ + WORK(dispatch_template_filter(e)); +} + +void GraniteWSIPlatform::dispatch(const TouchUpEvent &e) +{ + WORK(dispatch_template_filter(e)); +} + +void GraniteWSIPlatform::dispatch(const TouchGestureEvent &e) +{ + WORK(dispatch_template_filter(e)); +} + +void GraniteWSIPlatform::dispatch(const JoypadButtonEvent &e) +{ + WORK(dispatch_template_filter(e)); +} + +void GraniteWSIPlatform::dispatch(const JoypadAxisEvent &e) +{ + WORK(dispatch_template_filter(e)); +} + +void GraniteWSIPlatform::dispatch(const KeyboardEvent &e) +{ + WORK(dispatch_template_filter(e)); +} + +void GraniteWSIPlatform::dispatch(const OrientationEvent &e) +{ + WORK(dispatch_template_filter(e)); +} + +void GraniteWSIPlatform::dispatch(const MouseButtonEvent &e) +{ + WORK(dispatch_template_filter(e)); +} + +void GraniteWSIPlatform::dispatch(const MouseMoveEvent &e) +{ + WORK(dispatch_template_filter(e)); +} + +void GraniteWSIPlatform::dispatch(const JoypadStateEvent &e) +{ + WORK(dispatch_template(e)); +} + +void GraniteWSIPlatform::dispatch(const InputStateEvent &e) +{ + WORK(dispatch_template(e)); +} + +void GraniteWSIPlatform::dispatch(const JoypadConnectionEvent &e) +{ + WORK(dispatch_template(e)); +} + +void GraniteWSIPlatform::begin_async_input_handling() +{ + in_async_input = true; +} + +void GraniteWSIPlatform::end_async_input_handling() +{ + in_async_input = false; +} + +void GraniteWSIPlatform::flush_deferred_input_events() +{ + VK_ASSERT(!in_async_input); + for (auto &func : captured) + func(); + captured.clear(); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_wsi.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_wsi.hpp new file mode 100644 index 00000000..8232d4c2 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_wsi.hpp @@ -0,0 +1,81 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "wsi.hpp" +#include "input.hpp" +#include + +namespace Granite +{ +class GraniteWSIPlatform : public Vulkan::WSIPlatform, private InputTrackerHandler +{ +public: + GraniteWSIPlatform(); + + InputTracker &get_input_tracker() + { + return input_tracker; + } + +protected: + void event_device_created(Vulkan::Device *device) override; + void event_device_destroyed() override; + void event_swapchain_created(Vulkan::Device *device, VkSwapchainKHR swapchain, + unsigned width, unsigned height, + float aspect_ratio, size_t image_count, + VkFormat format, VkColorSpaceKHR color_space, + VkSurfaceTransformFlagBitsKHR pre_rotate) override; + void event_swapchain_destroyed() override; + void event_swapchain_index(Vulkan::Device *device, unsigned index) override; + void event_frame_tick(double frame, double elapsed) override; + + void begin_async_input_handling(); + void end_async_input_handling(); + void flush_deferred_input_events(); + +private: + InputTracker input_tracker; + void dispatch(const TouchDownEvent &e) override; + void dispatch(const TouchUpEvent &e) override; + void dispatch(const TouchGestureEvent &e) override; + void dispatch(const JoypadButtonEvent &e) override; + void dispatch(const JoypadAxisEvent &e) override; + void dispatch(const KeyboardEvent &e) override; + void dispatch(const OrientationEvent &e) override; + void dispatch(const MouseButtonEvent &e) override; + void dispatch(const MouseMoveEvent &e) override; + void dispatch(const JoypadStateEvent &e) override; + void dispatch(const InputStateEvent &e) override; + void dispatch(const JoypadConnectionEvent &e) override; + template + void dispatch_template_filter(const T &t); + template + void dispatch_template(const T &t); + template + void dispatch_or_defer(Func &&func); + + bool in_async_input = false; + std::vector> captured; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_wsi_events.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_wsi_events.hpp new file mode 100644 index 00000000..8028b309 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/events/application_wsi_events.hpp @@ -0,0 +1,258 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "event.hpp" +#include "vulkan_headers.hpp" + +namespace Vulkan +{ +class Device; +class ShaderManager; +class WSIPlatform; + +class DeviceCreatedEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(DeviceCreatedEvent) + + explicit DeviceCreatedEvent(Device *device_) + : device(*device_) + {} + + Device &get_device() const + { + return device; + } + +private: + Device &device; +}; + +class DeviceShaderModuleReadyEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(DeviceShaderModuleReadyEvent) + + explicit DeviceShaderModuleReadyEvent(Device *device_, ShaderManager *manager_) + : device(*device_), manager(*manager_) + {} + + Device &get_device() const + { + return device; + } + + ShaderManager &get_shader_manager() const + { + return manager; + } + +private: + Device &device; + ShaderManager &manager; +}; + +class DevicePipelineReadyEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(DevicePipelineReadyEvent) + + explicit DevicePipelineReadyEvent(Device *device_, ShaderManager *manager_) + : device(*device_), manager(*manager_) + {} + + Device &get_device() const + { + return device; + } + + ShaderManager &get_shader_manager() const + { + return manager; + } + +private: + Device &device; + ShaderManager &manager; +}; + +class SwapchainParameterEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(SwapchainParameterEvent) + + SwapchainParameterEvent(Device *device_, + unsigned width_, unsigned height_, + float aspect_ratio_, unsigned count_, + VkFormat format_, VkColorSpaceKHR color_space_, + VkSurfaceTransformFlagBitsKHR transform_) + : device(*device_), width(width_), height(height_), + aspect_ratio(aspect_ratio_), image_count(count_), format(format_), color_space(color_space_), transform(transform_) + {} + + Device &get_device() const + { + return device; + } + + unsigned get_width() const + { + return width; + } + + unsigned get_height() const + { + return height; + } + + float get_aspect_ratio() const + { + return aspect_ratio; + } + + unsigned get_image_count() const + { + return image_count; + } + + VkFormat get_format() const + { + return format; + } + + VkColorSpaceKHR get_color_space() const + { + return color_space; + } + + VkSurfaceTransformFlagBitsKHR get_prerotate() const + { + return transform; + } + +private: + Device &device; + unsigned width; + unsigned height; + float aspect_ratio; + unsigned image_count; + VkFormat format; + VkColorSpaceKHR color_space; + VkSurfaceTransformFlagBitsKHR transform; +}; + +class SwapchainIndexEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(SwapchainIndexEvent) + + SwapchainIndexEvent(Device *device_, unsigned index_) + : device(*device_), index(index_) + {} + + Device &get_device() const + { + return device; + } + + unsigned get_index() const + { + return index; + } + +private: + Device &device; + unsigned index; +}; + +class ApplicationWSIPlatformEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(ApplicationWSIPlatformEvent) + + explicit ApplicationWSIPlatformEvent(WSIPlatform &platform_) + : platform(platform_) + {} + + WSIPlatform &get_platform() const + { + return platform; + } + +private: + WSIPlatform &platform; +}; + +class ApplicationWindowFileDropEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(ApplicationWindowFileDropEvent) + explicit ApplicationWindowFileDropEvent(std::string path_) + : path(std::move(path_)) + {} + + const std::string &get_path() const + { + return path; + } + +private: + std::string path; +}; + +class ApplicationWindowTextDropEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(ApplicationWindowTextDropEvent) + explicit ApplicationWindowTextDropEvent(std::string str_) + : str(std::move(str_)) + {} + + const std::string &get_text() const + { + return str; + } + +private: + std::string str; +}; + +class ApplicationSoftKeyboardUpdateEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(ApplicationSoftKeyboardUpdateEvent) + explicit ApplicationSoftKeyboardUpdateEvent(std::string str_) + : str(std::move(str_)) + { + } + + const std::string &get_text() const + { + return str; + } + +private: + std::string str; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/CMakeLists.txt new file mode 100644 index 00000000..4cdcad93 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/CMakeLists.txt @@ -0,0 +1,27 @@ +add_granite_internal_lib(granite-application-global + global_managers.hpp global_managers.cpp) +target_include_directories(granite-application-global PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-application-global PUBLIC granite-util) + +add_granite_internal_lib(granite-application-global-init + global_managers_init.hpp global_managers_init.cpp) +target_include_directories(granite-application-global-init PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-application-global-init + PUBLIC granite-application-global + PRIVATE granite-threading granite-event granite-filesystem) + +if (TARGET granite-renderer) + target_link_libraries(granite-application-global-init PRIVATE granite-renderer granite-ui) + target_compile_definitions(granite-application-global-init PRIVATE HAVE_GRANITE_RENDERER) +endif() + +if (GRANITE_AUDIO) + target_link_libraries(granite-application-global-init PRIVATE granite-audio) +endif() + +if (GRANITE_BULLET) + target_link_libraries(granite-application-global-init PRIVATE granite-physics) +endif() + +add_library(granite-application-global-interface INTERFACE) +target_include_directories(granite-application-global-interface INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers.cpp new file mode 100644 index 00000000..36268594 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers.cpp @@ -0,0 +1,308 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "global_managers.hpp" +#include "environment.hpp" +#include "logging.hpp" +#include +#include +#include + +namespace Granite +{ +namespace Global +{ +// Could use unique_ptr here, but would be nice to avoid global ctor/dtor. +struct GlobalManagers +{ + Factory *factory; + + FilesystemInterface *filesystem; + AssetManagerInterface *asset_manager; + MaterialManagerInterface *material_manager; + EventManagerInterface *event_manager; + ThreadGroupInterface *thread_group; + UI::UIManagerInterface *ui_manager; + CommonRendererDataInterface *common_renderer_data; + Util::MessageQueueInterface *logging; + Audio::BackendInterface *audio_backend; + Audio::MixerInterface *audio_mixer; + PhysicsSystemInterface *physics; +}; + +static thread_local GlobalManagers global_managers; + +GlobalManagersHandle create_thread_context() +{ + return GlobalManagersHandle(new GlobalManagers(global_managers)); +} + +void delete_thread_context(GlobalManagers *managers) +{ + delete managers; +} + +void GlobalManagerDeleter::operator()(GlobalManagers *managers) +{ + delete_thread_context(managers); +} + +void set_thread_context(const GlobalManagers &managers) +{ + global_managers = managers; + if (managers.thread_group) + managers.thread_group->set_thread_context(); + if (managers.logging) + Util::set_thread_logging_interface(managers.logging); +} + +void clear_thread_context() +{ + global_managers = {}; +} + +Util::MessageQueueInterface *message_queue() +{ + return global_managers.logging; +} + +FilesystemInterface *filesystem() +{ + return global_managers.filesystem; +} + +AssetManagerInterface *asset_manager() +{ + return global_managers.asset_manager; +} + +MaterialManagerInterface *material_manager() +{ + return global_managers.material_manager; +} + +EventManagerInterface *event_manager() +{ + return global_managers.event_manager; +} + +ThreadGroupInterface *thread_group() +{ + return global_managers.thread_group; +} + +UI::UIManagerInterface *ui_manager() +{ + return global_managers.ui_manager; +} + +CommonRendererDataInterface *common_renderer_data() +{ + return global_managers.common_renderer_data; +} + +Audio::BackendInterface *audio_backend() { return global_managers.audio_backend; } +Audio::MixerInterface *audio_mixer() { return global_managers.audio_mixer; } + +void install_audio_system(Audio::BackendInterface *backend, Audio::MixerInterface *mixer) +{ + delete global_managers.audio_mixer; + global_managers.audio_mixer = mixer; + delete global_managers.audio_backend; + global_managers.audio_backend = backend; +} + +PhysicsSystemInterface *physics() +{ + return global_managers.physics; +} + +void init(Factory &factory, ManagerFeatureFlags flags, unsigned max_threads, float audio_sample_rate) +{ + assert(!global_managers.factory || global_managers.factory == &factory); + global_managers.factory = &factory; + + if (flags & MANAGER_FEATURE_EVENT_BIT) + { + if (!global_managers.event_manager) + global_managers.event_manager = factory.create_event_manager(); + } + + if (flags & MANAGER_FEATURE_FILESYSTEM_BIT) + { + if (!global_managers.filesystem) + global_managers.filesystem = factory.create_filesystem(); + } + + if (flags & MANAGER_FEATURE_ASSET_MANAGER_BIT) + { + if (!global_managers.asset_manager) + global_managers.asset_manager = factory.create_asset_manager(); + } + + if (flags & MANAGER_FEATURE_MATERIAL_MANAGER_BIT) + { + if (!global_managers.material_manager) + global_managers.material_manager = factory.create_material_manager(); + } + + bool kick_threads = false; + if (flags & MANAGER_FEATURE_THREAD_GROUP_BIT) + { + if (!global_managers.thread_group) + { + global_managers.thread_group = factory.create_thread_group(); + kick_threads = true; + } + } + + if (flags & MANAGER_FEATURE_UI_MANAGER_BIT) + { + if (!global_managers.ui_manager) + global_managers.ui_manager = factory.create_ui_manager(); + } + + if (flags & MANAGER_FEATURE_COMMON_RENDERER_DATA_BIT) + { + if (!global_managers.common_renderer_data) + global_managers.common_renderer_data = factory.create_common_renderer_data(); + } + + if (flags & MANAGER_FEATURE_LOGGING_BIT) + { + if (!global_managers.logging) + global_managers.logging = factory.create_message_queue(); + Util::set_thread_logging_interface(global_managers.logging); + } + + if (flags & MANAGER_FEATURE_PHYSICS_BIT) + { + if (!global_managers.physics) + global_managers.physics = factory.create_physics_system(); + } + + if (flags & MANAGER_FEATURE_AUDIO_MIXER_BIT) + { + if (!global_managers.audio_mixer) + global_managers.audio_mixer = factory.create_audio_mixer(); + } + + if (flags & MANAGER_FEATURE_AUDIO_BACKEND_BIT) + { + if (!global_managers.audio_backend) + global_managers.audio_backend = factory.create_audio_backend(global_managers.audio_mixer, audio_sample_rate, 2); + } + + // Kick threads after all global managers are set up. + if (kick_threads) + { + unsigned cpu_threads = std::thread::hardware_concurrency(); + cpu_threads = cpu_threads > 1 ? (cpu_threads - 1u) : 1u; + + if (cpu_threads > max_threads) + cpu_threads = max_threads; + cpu_threads = Util::get_environment_uint("GRANITE_NUM_WORKER_THREADS", cpu_threads); + + unsigned background_cpu_threads = (cpu_threads + 1) / 2; + + global_managers.thread_group->start(cpu_threads, background_cpu_threads, + [ctx = std::shared_ptr(create_thread_context())] { + set_thread_context(*ctx); + }); + } +} + +void deinit() +{ + if (!global_managers.factory) + return; + + if (global_managers.audio_backend) + global_managers.audio_backend->stop(); + + delete global_managers.audio_backend; + delete global_managers.audio_mixer; + delete global_managers.physics; + delete global_managers.common_renderer_data; + delete global_managers.ui_manager; + delete global_managers.thread_group; + delete global_managers.material_manager; + delete global_managers.asset_manager; + delete global_managers.filesystem; + delete global_managers.event_manager; + delete global_managers.logging; + + global_managers.audio_backend = nullptr; + global_managers.audio_mixer = nullptr; + global_managers.physics = nullptr; + global_managers.common_renderer_data = nullptr; + global_managers.filesystem = nullptr; + global_managers.material_manager = nullptr; + global_managers.asset_manager = nullptr; + global_managers.event_manager = nullptr; + global_managers.thread_group = nullptr; + global_managers.ui_manager = nullptr; + global_managers.logging = nullptr; + + global_managers.factory = nullptr; +} + +void start_audio_system() +{ + if (!global_managers.audio_backend) + return; + + if (!global_managers.audio_backend->start()) + { + LOGE("Failed to start audio subsystem!\n"); + return; + } + + if (global_managers.event_manager && global_managers.audio_mixer) + global_managers.audio_mixer->event_start(*global_managers.event_manager); +} + +void stop_audio_system() +{ + if (!global_managers.audio_backend) + return; + + if (!global_managers.audio_backend->stop()) + LOGE("Failed to stop audio subsystem!\n"); + + if (global_managers.event_manager && global_managers.audio_mixer) + global_managers.audio_mixer->event_stop(*global_managers.event_manager); +} + +FilesystemInterface *Factory::create_filesystem() { return nullptr; } +AssetManagerInterface *Factory::create_asset_manager() { return nullptr; } +MaterialManagerInterface *Factory::create_material_manager() { return nullptr; } +EventManagerInterface *Factory::create_event_manager() { return nullptr; } +ThreadGroupInterface *Factory::create_thread_group() { return nullptr; } +CommonRendererDataInterface *Factory::create_common_renderer_data() { return nullptr; } +PhysicsSystemInterface *Factory::create_physics_system() { return nullptr; } +Audio::BackendInterface *Factory::create_audio_backend(Audio::MixerInterface *, float, unsigned) { return nullptr; } +Audio::MixerInterface *Factory::create_audio_mixer() { return nullptr; } +UI::UIManagerInterface *Factory::create_ui_manager() { return nullptr; } +Util::MessageQueueInterface *Factory::create_message_queue() { return nullptr; } +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers.hpp new file mode 100644 index 00000000..967cd93c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers.hpp @@ -0,0 +1,127 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include "global_managers_interface.hpp" + +namespace Granite +{ +namespace Global +{ +enum ManagerFeatureFlagBits +{ + MANAGER_FEATURE_FILESYSTEM_BIT = 1 << 0, + MANAGER_FEATURE_EVENT_BIT = 1 << 1, + MANAGER_FEATURE_THREAD_GROUP_BIT = 1 << 2, + MANAGER_FEATURE_UI_MANAGER_BIT = 1 << 3, + MANAGER_FEATURE_AUDIO_MIXER_BIT = 1 << 4, + MANAGER_FEATURE_AUDIO_BACKEND_BIT = 1 << 5, + MANAGER_FEATURE_COMMON_RENDERER_DATA_BIT = 1 << 6, + MANAGER_FEATURE_PHYSICS_BIT = 1 << 7, + MANAGER_FEATURE_LOGGING_BIT = 1 << 8, + MANAGER_FEATURE_ASSET_MANAGER_BIT = 1 << 9, + MANAGER_FEATURE_MATERIAL_MANAGER_BIT = 1 << 10, + MANAGER_FEATURE_DEFAULT_BITS = (MANAGER_FEATURE_FILESYSTEM_BIT | + MANAGER_FEATURE_ASSET_MANAGER_BIT | + MANAGER_FEATURE_MATERIAL_MANAGER_BIT | + MANAGER_FEATURE_EVENT_BIT | + MANAGER_FEATURE_THREAD_GROUP_BIT | + MANAGER_FEATURE_COMMON_RENDERER_DATA_BIT | + MANAGER_FEATURE_UI_MANAGER_BIT | + MANAGER_FEATURE_AUDIO_MIXER_BIT | + MANAGER_FEATURE_AUDIO_BACKEND_BIT) +}; +using ManagerFeatureFlags = uint32_t; + +// Decouple creation from global TLS storage. +// This avoids some nasty cyclical dependencies. +class Factory +{ +public: + virtual ~Factory() = default; + + virtual FilesystemInterface *create_filesystem(); + virtual AssetManagerInterface *create_asset_manager(); + virtual MaterialManagerInterface *create_material_manager(); + virtual EventManagerInterface *create_event_manager(); + virtual ThreadGroupInterface *create_thread_group(); + virtual CommonRendererDataInterface *create_common_renderer_data(); + virtual PhysicsSystemInterface *create_physics_system(); + virtual Audio::BackendInterface *create_audio_backend(Audio::MixerInterface *mixer, + float sample_rate, + unsigned channels); + virtual Audio::MixerInterface *create_audio_mixer(); + virtual UI::UIManagerInterface *create_ui_manager(); + virtual Util::MessageQueueInterface *create_message_queue(); +}; + +void init(Factory &factory, ManagerFeatureFlags flags = MANAGER_FEATURE_DEFAULT_BITS, + unsigned max_threads = UINT_MAX, float audio_sample_rate = -1.0f); +void deinit(); + +// Used if the application wants to use multiple instances of Granite in the same process. +// This allows each thread to be associated to a global context. +struct GlobalManagers; +struct GlobalManagerDeleter +{ + void operator()(GlobalManagers *managers); +}; +using GlobalManagersHandle = std::unique_ptr; +GlobalManagersHandle create_thread_context(); +void delete_thread_context(GlobalManagers *managers); +void set_thread_context(const GlobalManagers &managers); +void clear_thread_context(); + +void start_audio_system(); +void stop_audio_system(); +void install_audio_system(Audio::BackendInterface *backend, Audio::MixerInterface *mixer); + +Util::MessageQueueInterface *message_queue(); +FilesystemInterface *filesystem(); +AssetManagerInterface *asset_manager(); +MaterialManagerInterface *material_manager(); +EventManagerInterface *event_manager(); +ThreadGroupInterface *thread_group(); +UI::UIManagerInterface *ui_manager(); +CommonRendererDataInterface *common_renderer_data(); +Audio::BackendInterface *audio_backend(); +Audio::MixerInterface *audio_mixer(); +PhysicsSystemInterface *physics(); +} +} + +#define GRANITE_MESSAGE_QUEUE() static_cast<::Util::MessageQueue *>(::Granite::Global::message_queue()) +#define GRANITE_FILESYSTEM() static_cast<::Granite::Filesystem *>(::Granite::Global::filesystem()) +#define GRANITE_ASSET_MANAGER() static_cast<::Granite::AssetManager *>(::Granite::Global::asset_manager()) +#define GRANITE_MATERIAL_MANAGER() static_cast<::Granite::MaterialManager *>(::Granite::Global::material_manager()) +#define GRANITE_EVENT_MANAGER() static_cast<::Granite::EventManager *>(::Granite::Global::event_manager()) +#define GRANITE_THREAD_GROUP() static_cast<::Granite::ThreadGroup *>(::Granite::Global::thread_group()) +#define GRANITE_UI_MANAGER() static_cast<::Granite::UI::UIManager *>(::Granite::Global::ui_manager()) +#define GRANITE_COMMON_RENDERER_DATA() static_cast<::Granite::CommonRendererData *>(::Granite::Global::common_renderer_data()) +#define GRANITE_AUDIO_BACKEND() static_cast<::Granite::Audio::Backend *>(::Granite::Global::audio_backend()) +#define GRANITE_AUDIO_MIXER() static_cast<::Granite::Audio::Mixer *>(::Granite::Global::audio_mixer()) +#define GRANITE_PHYSICS() static_cast<::Granite::PhysicsSystem *>(::Granite::Global::physics()) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers_init.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers_init.cpp new file mode 100644 index 00000000..a914ca7b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers_init.cpp @@ -0,0 +1,137 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "global_managers_init.hpp" +#include "global_managers.hpp" +#include "event.hpp" +#include "thread_group.hpp" +#include "filesystem.hpp" +#include "asset_manager.hpp" +#ifdef HAVE_GRANITE_RENDERER +#include "material_manager.hpp" +#include "common_renderer_data.hpp" +#include "ui_manager.hpp" +#endif +#ifdef HAVE_GRANITE_AUDIO +#include "audio_mixer.hpp" +#include "audio_interface.hpp" +#endif +#ifdef HAVE_GRANITE_PHYSICS +#include "physics_system.hpp" +#endif + +namespace Granite +{ +namespace Global +{ +struct FactoryImplementation : Factory +{ + FilesystemInterface *create_filesystem() override + { + return new Filesystem; + } + + AssetManagerInterface *create_asset_manager() override + { + return new AssetManager; + } + + EventManagerInterface *create_event_manager() override + { + return new EventManager; + } + + ThreadGroupInterface *create_thread_group() override + { + return new ThreadGroup; + } + + CommonRendererDataInterface *create_common_renderer_data() override + { +#ifdef HAVE_GRANITE_RENDERER + return new CommonRendererData; +#else + return nullptr; +#endif + } + + UI::UIManagerInterface *create_ui_manager() override + { +#ifdef HAVE_GRANITE_RENDERER + return new UI::UIManager; +#else + return nullptr; +#endif + } + + MaterialManagerInterface *create_material_manager() override + { +#ifdef HAVE_GRANITE_RENDERER + return new MaterialManager; +#else + return nullptr; +#endif + } + + Audio::MixerInterface *create_audio_mixer() override + { +#ifdef HAVE_GRANITE_AUDIO + return new Audio::Mixer; +#else + return nullptr; +#endif + } + + Audio::BackendInterface *create_audio_backend(Audio::MixerInterface *iface, float sample_rate, unsigned channels) override + { +#ifdef HAVE_GRANITE_AUDIO + if (iface) + return Audio::create_default_audio_backend(static_cast(iface), sample_rate, channels); + else + return nullptr; +#else + (void)iface; + (void)sample_rate; + (void)channels; + return nullptr; +#endif + } + + PhysicsSystemInterface *create_physics_system() override + { +#ifdef HAVE_GRANITE_PHYSICS + return new PhysicsSystem; +#else + return nullptr; +#endif + } +}; + +static FactoryImplementation factory; + +void init(ManagerFeatureFlags flags, unsigned max_threads, float audio_sample_rate) +{ + init(factory, flags, max_threads, audio_sample_rate); +} +} +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers_init.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers_init.hpp new file mode 100644 index 00000000..ee0af26c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers_init.hpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "global_managers.hpp" + +namespace Granite +{ +namespace Global +{ +void init(ManagerFeatureFlags flags = MANAGER_FEATURE_DEFAULT_BITS, + unsigned max_threads = UINT_MAX, float audio_sample_rate = -1.0f); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers_interface.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers_interface.hpp new file mode 100644 index 00000000..751c61d3 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/global/global_managers_interface.hpp @@ -0,0 +1,133 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include "logging.hpp" + +namespace Util +{ +class MessageQueueInterface : public LoggingInterface +{ +public: + virtual ~MessageQueueInterface() = default; +}; +} + +namespace Granite +{ +class FilesystemInterface +{ +public: + virtual ~FilesystemInterface() = default; + virtual bool load_text_file(const std::string &path, std::string &str) = 0; +}; + +class AssetManagerInterface +{ +public: + virtual ~AssetManagerInterface() = default; +}; + +class MaterialManagerInterface +{ +public: + virtual ~MaterialManagerInterface() = default; + virtual void iterate(AssetManagerInterface *iface) = 0; +}; + +class ThreadGroupInterface +{ +public: + virtual ~ThreadGroupInterface() = default; + virtual void start(unsigned foreground_count, unsigned background_count, + const std::function &cb) = 0; + virtual void set_thread_context() = 0; +}; + +class EventManagerInterface +{ +public: + virtual ~EventManagerInterface() = default; +}; + +class CommonRendererDataInterface +{ +public: + virtual ~CommonRendererDataInterface() = default; +}; + +class PhysicsSystemInterface +{ +public: + virtual ~PhysicsSystemInterface() = default; +}; + +class TouchDownEvent; +class TouchUpEvent; +class MouseMoveEvent; +class KeyboardEvent; +class OrientationEvent; +class TouchGestureEvent; +class MouseButtonEvent; +class JoypadButtonEvent; +class JoypadAxisEvent; + +namespace UI +{ +class UIManagerInterface +{ +public: + virtual ~UIManagerInterface() = default; + virtual bool filter_input_event(const TouchDownEvent &e) = 0; + virtual bool filter_input_event(const TouchUpEvent &e) = 0; + virtual bool filter_input_event(const MouseMoveEvent &e) = 0; + virtual bool filter_input_event(const KeyboardEvent &e) = 0; + virtual bool filter_input_event(const OrientationEvent &e) = 0; + virtual bool filter_input_event(const TouchGestureEvent &e) = 0; + virtual bool filter_input_event(const MouseButtonEvent &e) = 0; + virtual bool filter_input_event(const JoypadButtonEvent &e) = 0; + virtual bool filter_input_event(const JoypadAxisEvent &e) = 0; +}; +} + +namespace Audio +{ +class BackendInterface +{ +public: + virtual ~BackendInterface() = default; + virtual bool start() = 0; + virtual bool stop() = 0; +}; + +class MixerInterface +{ +public: + virtual ~MixerInterface() = default; + virtual void event_start(EventManagerInterface &event_manager) = 0; + virtual void event_stop(EventManagerInterface &event_manager) = 0; +}; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/CMakeLists.txt new file mode 100644 index 00000000..1f414441 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/CMakeLists.txt @@ -0,0 +1,14 @@ +add_granite_internal_lib(granite-input input.hpp input.cpp) +target_include_directories(granite-input PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-input PUBLIC granite-util granite-event granite-math) + +if (${GRANITE_PLATFORM} MATCHES "SDL") + add_granite_internal_static_lib(granite-input-sdl input_sdl.cpp input_sdl.hpp) + target_link_libraries(granite-input-sdl PUBLIC granite-input) + if (GRANITE_SYSTEM_SDL) + find_package(SDL3 REQUIRED) + target_link_libraries(granite-input-sdl PUBLIC SDL3::SDL3-shared) + else() + target_link_libraries(granite-input-sdl PUBLIC SDL3-static) + endif() +endif() \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input.cpp new file mode 100644 index 00000000..0d0acfed --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input.cpp @@ -0,0 +1,376 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "input.hpp" +#include "event.hpp" +#include "muglm/muglm_impl.hpp" +#include "logging.hpp" +#include +#include + +using namespace Util; + +namespace Granite +{ +const char *joypad_key_to_tag(JoypadKey key) +{ +#define D(k) case JoypadKey::k: return #k + switch (key) + { + D(Left); + D(Right); + D(Up); + D(Down); + D(LeftShoulder); + D(RightShoulder); + D(West); + D(East); + D(North); + D(South); + D(LeftThumb); + D(RightThumb); + D(Mode); + D(Start); + D(Select); + default: + return "Unknown"; + } +#undef D +} + +const char *joypad_axis_to_tag(JoypadAxis axis) +{ +#define D(k) case JoypadAxis::k: return #k + switch (axis) + { + D(LeftX); + D(LeftY); + D(RightX); + D(RightY); + D(LeftTrigger); + D(RightTrigger); + default: + return "Unknown"; + } +#undef D +} + +void InputTracker::orientation_event(quat rot) +{ + OrientationEvent event(rot); + if (handler) + handler->dispatch(event); +} + +void InputTracker::on_touch_down(unsigned id, float x, float y) +{ + if (touch.active_pointers >= TouchCount) + { + LOGE("Touch pointer overflow!\n"); + return; + } + + unsigned index = touch.active_pointers++; + auto &pointer = touch.pointers[index]; + pointer.id = id; + pointer.start_x = x; + pointer.start_y = y; + pointer.last_x = x; + pointer.last_y = y; + pointer.x = x; + pointer.y = y; + + TouchDownEvent event(index, id, x, y, touch.width, touch.height); + if (handler) + handler->dispatch(event); +} + +void InputTracker::dispatch_touch_gesture() +{ + TouchGestureEvent event(touch); + if (handler) + handler->dispatch(event); +} + +void InputTracker::on_touch_move(unsigned id, float x, float y) +{ + auto &pointers = touch.pointers; + auto itr = std::find_if(std::begin(pointers), std::begin(pointers) + touch.active_pointers, [id](const TouchState::Pointer &pointer) { + return pointer.id == id; + }); + + if (itr == std::end(pointers)) + { + LOGE("Could not find pointer!\n"); + return; + } + + itr->x = x; + itr->y = y; +} + +void InputTracker::on_touch_up(unsigned id, float x, float y) +{ + auto &pointers = touch.pointers; + auto itr = std::find_if(std::begin(pointers), std::begin(pointers) + touch.active_pointers, [id](const TouchState::Pointer &pointer) { + return pointer.id == id; + }); + + if (itr == std::end(pointers)) + { + LOGE("Could not find pointer!\n"); + return; + } + + auto index = itr - std::begin(pointers); + + TouchUpEvent event(itr->id, x, y, itr->start_x, itr->start_y, touch.width, touch.height); + + if (handler) + handler->dispatch(event); + + memmove(&pointers[index], &pointers[index + 1], (TouchCount - (index + 1)) * sizeof(TouchState::Pointer)); + touch.active_pointers--; +} + +void InputTracker::joypad_key_state(unsigned index, JoypadKey key, JoypadKeyState state) +{ + if (index >= Joypads) + return; + + assert(active_joypads & (1u << index)); + + auto &joy = joypads[index]; + unsigned key_index = Util::ecast(key); + unsigned key_mask = 1u << key_index; + if (state == JoypadKeyState::Pressed) + { + if ((joy.button_mask & key_mask) == 0) + { + JoypadButtonEvent event(index, key, state); + if (handler) + handler->dispatch(event); + } + joy.button_mask |= key_mask; + } + else if (state == JoypadKeyState::Released) + { + if ((joy.button_mask & key_mask) != 0) + { + JoypadButtonEvent event(index, key, state); + if (handler) + handler->dispatch(event); + } + joy.button_mask &= ~key_mask; + } +} + +void JoypadState::snap_deadzone(float deadzone) +{ + memcpy(snapped_axis, raw_axis, sizeof(raw_axis)); + + static const JoypadAxis fused_axes[2][2] = { + { JoypadAxis::LeftX, JoypadAxis::LeftY }, + { JoypadAxis::RightX, JoypadAxis::RightY }, + }; + + for (auto &fused : fused_axes) + { + if (std::abs(raw_axis[int(fused[0])]) < deadzone && std::abs(raw_axis[int(fused[1])]) < deadzone) + for (auto &axis : fused) + snapped_axis[int(axis)] = 0.0f; + } +} + +void InputTracker::joyaxis_state(unsigned index, JoypadAxis axis, float value) +{ + if (index >= Joypads) + return; + + assert(active_joypads & (1u << index)); + + auto &joy = joypads[index]; + unsigned axis_index = Util::ecast(axis); + auto &a = joy.raw_axis[axis_index]; + if (a != value) + { + JoypadAxisEvent event(index, axis, value); + if (handler) + handler->dispatch(event); + } + + a = value; +} + +void InputTracker::key_event(Key key, KeyState state) +{ + if (state == KeyState::Released) + key_state &= ~(1ull << ecast(key)); + else if (state == KeyState::Pressed) + key_state |= 1ull << ecast(key); + + KeyboardEvent event(key, state); + if (handler) + handler->dispatch(event); +} + +void InputTracker::mouse_button_event(Granite::MouseButton button, bool pressed) +{ + mouse_button_event(button, last_mouse_x, last_mouse_y, pressed); +} + +void InputTracker::mouse_button_event(MouseButton button, double x, double y, bool pressed) +{ + if (pressed) + mouse_button_state |= 1ull << ecast(button); + else + mouse_button_state &= ~(1ull << ecast(button)); + + if (mouse_active) + { + last_mouse_x = x; + last_mouse_y = y; + } + + MouseButtonEvent event(button, x, y, pressed); + if (handler) + handler->dispatch(event); +} + +void InputTracker::mouse_move_event_relative(double x, double y) +{ + x *= mouse_speed_x; + y *= mouse_speed_y; + if (mouse_active) + { + last_mouse_x += x; + last_mouse_y += y; + last_mouse_x = clamp(last_mouse_x, mouse_relative_range_x, + mouse_relative_range_x + mouse_relative_range_width); + last_mouse_y = clamp(last_mouse_y, mouse_relative_range_y, + mouse_relative_range_y + mouse_relative_range_height); + MouseMoveEvent event(x, y, last_mouse_x, last_mouse_y, key_state, mouse_button_state); + if (handler) + handler->dispatch(event); + } +} + +void InputTracker::mouse_move_event_absolute(double x, double y) +{ + if (mouse_active) + { + double delta_x = x - last_mouse_x; + double delta_y = y - last_mouse_y; + last_mouse_x = x; + last_mouse_y = y; + MouseMoveEvent event(delta_x, delta_y, x, y, key_state, mouse_button_state); + if (handler) + handler->dispatch(event); + } +} + +void InputTracker::mouse_move_event_absolute_normalized(double x, double y) +{ + mouse_move_event_absolute(x * double(touch.width), y * double(touch.height)); +} + +void InputTracker::mouse_button_event_normalized(MouseButton button, double x, double y, bool pressed) +{ + mouse_button_event(button, x * double(touch.width), y * double(touch.height), pressed); +} + +void InputTracker::mouse_enter(double x, double y) +{ + mouse_active = true; + last_mouse_x = x; + last_mouse_y = y; +} + +void InputTracker::mouse_leave() +{ + mouse_active = false; +} + +void InputTracker::dispatch_current_state(double delta_time, InputTrackerHandler *override_handler) +{ + if (!override_handler) + override_handler = handler; + + if (override_handler) + { + for (auto &pad : joypads) + pad.snap_deadzone(axis_deadzone); + + override_handler->dispatch(JoypadStateEvent{active_joypads, joypads, Joypads, delta_time}); + override_handler->dispatch(InputStateEvent{last_mouse_x, last_mouse_y, + delta_time, key_state, mouse_button_state, mouse_active}); + } +} + +int InputTracker::find_vacant_joypad_index() const +{ + for (int i = 0; i < Joypads; i++) + { + if ((active_joypads & (1 << i)) == 0) + return i; + } + + return -1; +} + +void InputTracker::enable_joypad(unsigned index, uint32_t vid, uint32_t pid) +{ + if (index >= Joypads) + return; + + if (active_joypads & (1u << index)) + return; + + active_joypads |= 1u << index; + joypads[index] = {}; + joypads[index].vid = vid; + joypads[index].pid = pid; + JoypadConnectionEvent event(index, true, vid, pid); + if (handler) + handler->dispatch(event); +} + +void InputTracker::disable_joypad(unsigned index, uint32_t vid, uint32_t pid) +{ + if (index >= Joypads) + return; + + if ((active_joypads & (1u << index)) == 0) + return; + + active_joypads &= ~(1u << index); + joypads[index] = {}; + JoypadConnectionEvent event(index, false, vid, pid); + if (handler) + handler->dispatch(event); +} + +std::mutex &InputTracker::get_lock() +{ + return dispatch_lock; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input.hpp new file mode 100644 index 00000000..fa88c53a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input.hpp @@ -0,0 +1,719 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "enum_cast.hpp" +#include "event.hpp" +#include +#include "math.hpp" +#include +#include +#include + +namespace Granite +{ +enum class JoypadKey +{ + Left, + Right, + Up, + Down, + East, + South, + West, + North, + LeftShoulder, + RightShoulder, + LeftThumb, + RightThumb, + Start, + Select, + Mode, + Count, + Unknown +}; + +const char *joypad_key_to_tag(JoypadKey key); + +enum class JoypadAxis +{ + LeftX, + LeftY, + RightX, + RightY, + LeftTrigger, + RightTrigger, + Count, + Unknown +}; + +const char *joypad_axis_to_tag(JoypadAxis axis); + +enum class JoypadKeyState +{ + Pressed, + Released, + Count +}; + +enum class Key +{ + Unknown, + 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, + Return, + LeftCtrl, + LeftAlt, + LeftShift, + Space, + Escape, + Left, Right, Up, Down, + _1, _2, _3, _4, _5, _6, _7, _8, _9, _0, + Count +}; + +enum class MouseButton +{ + Left, + Middle, + Right, + Count +}; + +enum class KeyState +{ + Pressed, + Released, + Repeat, + Count +}; +static_assert(Util::ecast(Key::Count) <= 64, "Cannot have more than 64 keys for bit-packing."); + +struct TouchState +{ + enum { PointerCount = 16 }; + struct Pointer + { + unsigned id; + float start_x; + float start_y; + float last_x; + float last_y; + float x; + float y; + }; + Pointer pointers[PointerCount] = {}; + unsigned active_pointers = 0; + + unsigned width; + unsigned height; +}; + +struct JoypadState +{ + bool is_button_pressed(JoypadKey key) const + { + return (button_mask & (1u << Util::ecast(key))) != 0; + } + + float get_axis(JoypadAxis a) const + { + return snapped_axis[Util::ecast(a)]; + } + + void snap_deadzone(float deadzone); + + float raw_axis[Util::ecast(JoypadAxis::Count)] = {}; + float snapped_axis[Util::ecast(JoypadAxis::Count)] = {}; + uint32_t button_mask = 0; + uint32_t vid = 0; + uint32_t pid = 0; +}; +static_assert(Util::ecast(JoypadKey::Count) <= 32, "Cannot have more than 32 joypad buttons."); + +class InputTrackerHandler; + +class InputTracker +{ +public: + void key_event(Key key, KeyState state); + void mouse_button_event(MouseButton button, double x, double y, bool pressed); + void mouse_button_event_normalized(MouseButton button, double x, double y, bool pressed); + void mouse_button_event(MouseButton button, bool pressed); + void mouse_move_event_absolute(double x, double y); + void mouse_move_event_absolute_normalized(double x, double y); + void mouse_move_event_relative(double x, double y); + void dispatch_current_state(double delta_time, InputTrackerHandler *override_handler = nullptr); + void orientation_event(quat rot); + void joypad_key_state(unsigned index, JoypadKey key, JoypadKeyState state); + void joyaxis_state(unsigned index, JoypadAxis axis, float value); + + void on_touch_down(unsigned id, float x, float y); + void on_touch_move(unsigned id, float x, float y); + void on_touch_up(unsigned id, float x, float y); + + void mouse_enter(double x, double y); + void mouse_leave(); + + bool key_pressed(Key key) const + { + return (key_state & (1ull << Util::ecast(key))) != 0; + } + + bool joykey_pressed(unsigned index, JoypadKey key) const + { + if (index >= Joypads) + return false; + + return (joypads[index].button_mask & (1u << Util::ecast(key))) != 0; + } + + bool mouse_button_pressed(MouseButton button) const + { + return (mouse_button_state & (1ull << Util::ecast(button))) != 0; + } + + void dispatch_touch_gesture(); + + void set_axis_deadzone(float deadzone) + { + axis_deadzone = deadzone; + } + + void set_relative_mouse_rect(double x, double y, double width, double height) + { + mouse_relative_range_x = x; + mouse_relative_range_y = y; + mouse_relative_range_width = width; + mouse_relative_range_height = height; + } + + void set_relative_mouse_speed(double speed_x, double speed_y) + { + mouse_speed_x = speed_x; + mouse_speed_y = speed_y; + } + + void enable_joypad(unsigned index, uint32_t vid, uint32_t pid); + void disable_joypad(unsigned index, uint32_t vid, uint32_t pid); + int find_vacant_joypad_index() const; + + void set_touch_resolution(unsigned width, unsigned height) + { + touch.width = width; + touch.height = height; + } + + void set_input_handler(InputTrackerHandler *handler_) + { + handler = handler_; + } + + // To support dispatching input manager (i.e. polling) state from async threads. + std::mutex &get_lock(); + + enum { TouchCount = 16 }; + enum { Joypads = 8 }; + +private: + InputTrackerHandler *handler = nullptr; + std::mutex dispatch_lock; + uint64_t key_state = 0; + uint8_t mouse_button_state = 0; + bool mouse_active = false; + + double last_mouse_x = 0.0; + double last_mouse_y = 0.0; + double mouse_relative_range_x = 0.0; + double mouse_relative_range_y = 0.0; + double mouse_relative_range_width = DBL_MAX; + double mouse_relative_range_height = DBL_MAX; + double mouse_speed_x = 1.0; + double mouse_speed_y = 1.0; + + uint8_t active_joypads = 0; + JoypadState joypads[Joypads] = {}; + TouchState touch; + + float axis_deadzone = 0.3f; +}; + +class JoypadConnectionEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(JoypadConnectionEvent) + JoypadConnectionEvent(unsigned index_, bool connected_, uint32_t vid_, uint32_t pid_) + : index(index_), connected(connected_), vid(vid_), pid(pid_) + { + } + + unsigned get_index() const + { + return index; + } + + bool is_connected() const + { + return connected; + } + + uint32_t get_vid() const + { + return vid; + } + + uint32_t get_pid() const + { + return pid; + } + +private: + unsigned index; + bool connected; + uint32_t vid, pid; +}; + +class TouchGestureEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(TouchGestureEvent) + + explicit TouchGestureEvent(const TouchState &state_) + : state(state_) + { + } + + const TouchState &get_state() const + { + return state; + } + +private: + const TouchState &state; +}; + +class TouchDownEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(TouchDownEvent) + + TouchDownEvent(unsigned index_, unsigned id_, + float x_, float y_, + unsigned screen_width_, unsigned screen_height_) + : index(index_), id(id_), + x(x_), y(y_), + width(screen_width_), height(screen_height_) + { + } + + float get_x() const + { + return x; + } + + float get_y() const + { + return y; + } + + unsigned get_index() const + { + return index; + } + + unsigned get_id() const + { + return id; + } + + unsigned get_screen_width() const + { + return width; + } + + unsigned get_screen_height() const + { + return height; + } + +private: + unsigned index, id; + float x, y; + unsigned width, height; +}; + +class TouchUpEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(TouchUpEvent) + + TouchUpEvent(unsigned id_, float x_, float y_, + float start_x_, float start_y_, + unsigned screen_width_, unsigned screen_height_) + : id(id_), x(x_), y(y_), + start_x(start_x_), start_y(start_y_), + width(screen_width_), height(screen_height_) + { + } + + float get_x() const + { + return x; + } + + float get_y() const + { + return y; + } + + float get_start_x() const + { + return start_x; + } + + float get_start_y() const + { + return start_y; + } + + unsigned get_id() const + { + return id; + } + + unsigned get_screen_width() const + { + return width; + } + + unsigned get_screen_height() const + { + return height; + } + +private: + unsigned id; + float x, y; + float start_x, start_y; + unsigned width, height; +}; + +class JoypadButtonEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(JoypadButtonEvent) + + JoypadButtonEvent(unsigned index_, JoypadKey key_, JoypadKeyState state_) + : index(index_), key(key_), state(state_) + { + } + + unsigned get_index() const + { + return index; + } + + JoypadKey get_key() const + { + return key; + } + + JoypadKeyState get_state() const + { + return state; + } + +private: + unsigned index; + JoypadKey key; + JoypadKeyState state; +}; + +class JoypadAxisEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(JoypadAxisEvent) + + JoypadAxisEvent(unsigned index_, JoypadAxis axis_, float value_) + : index(index_), axis(axis_), value(value_) + { + } + + unsigned get_index() const + { + return index; + } + + JoypadAxis get_axis() const + { + return axis; + } + + float get_value() const + { + return value; + } + +private: + unsigned index; + JoypadAxis axis; + float value; +}; + +class KeyboardEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(KeyboardEvent) + + KeyboardEvent(Key key_, KeyState state_) + : key(key_), state(state_) + { + } + + Key get_key() const + { + return key; + } + + KeyState get_key_state() const + { + return state; + } + +private: + Key key; + KeyState state; +}; + +class OrientationEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(OrientationEvent) + explicit OrientationEvent(const quat &rot_) + : rot(rot_) + { + } + + const quat &get_rotation() const + { + return rot; + } + +private: + quat rot; +}; + +class MouseButtonEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(MouseButtonEvent) + + MouseButtonEvent(MouseButton button_, double abs_x_, double abs_y_, bool pressed_) + : button(button_), abs_x(abs_x_), abs_y(abs_y_), pressed(pressed_) + { + } + + MouseButton get_button() const + { + return button; + } + + double get_abs_x() const + { + return abs_x; + } + + double get_abs_y() const + { + return abs_y; + } + + bool get_pressed() const + { + return pressed; + } + +private: + MouseButton button; + double abs_x; + double abs_y; + bool pressed; +}; + +class MouseMoveEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(MouseMoveEvent); + + MouseMoveEvent(double delta_x_, double delta_y_, double abs_x_, double abs_y_, + uint64_t key_mask_, uint8_t btn_mask_) + : delta_x(delta_x_), delta_y(delta_y_), + abs_x(abs_x_), abs_y(abs_y_), + key_mask(key_mask_), btn_mask(btn_mask_) + { + } + + bool get_mouse_button_pressed(MouseButton button) const + { + return (btn_mask & (1 << Util::ecast(button))) != 0; + } + + bool get_key_pressed(Key key) const + { + return (key_mask & (1ull << Util::ecast(key))) != 0; + } + + double get_delta_x() const + { + return delta_x; + } + + double get_delta_y() const + { + return delta_y; + } + + double get_abs_x() const + { + return abs_x; + } + + double get_abs_y() const + { + return abs_y; + } + +private: + double delta_x, delta_y, abs_x, abs_y; + uint64_t key_mask; + uint8_t btn_mask; +}; + +class JoypadStateEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(JoypadStateEvent) + + JoypadStateEvent(uint8_t active_mask_, const JoypadState *states_, + unsigned count_, double delta_time_) + : states(states_), count(count_), delta_time(delta_time_), active_mask(active_mask_) + { + } + + bool is_connected(unsigned index) const + { + if (index >= count) + return false; + return (active_mask & (1u << index)) != 0; + } + + unsigned get_num_indices() const + { + return count; + } + + const JoypadState &get_state(unsigned index) const + { + return states[index]; + } + + double get_delta_time() const + { + return delta_time; + } + +private: + const JoypadState *states; + unsigned count; + double delta_time; + uint8_t active_mask; +}; + +class InputStateEvent : public Granite::Event +{ +public: + GRANITE_EVENT_TYPE_DECL(InputStateEvent) + + InputStateEvent(double abs_x_, double abs_y_, + double delta_time_, uint64_t key_mask_, uint8_t btn_mask_, bool mouse_active_) + : abs_x(abs_x_), abs_y(abs_y_), + delta_time(delta_time_), key_mask(key_mask_), + btn_mask(btn_mask_), mouse_active(mouse_active_) + { + } + + double get_delta_time() const + { + return delta_time; + } + + bool get_mouse_active() const + { + return mouse_active; + } + + bool get_mouse_button_pressed(MouseButton button) const + { + return (btn_mask & (1 << Util::ecast(button))) != 0; + } + + bool get_key_pressed(Key key) const + { + return (key_mask & (1ull << Util::ecast(key))) != 0; + } + + double get_mouse_x() const + { + return abs_x; + } + + double get_mouse_y() const + { + return abs_y; + } + +private: + double abs_x, abs_y; + double delta_time; + uint64_t key_mask; + uint8_t btn_mask; + bool mouse_active; +}; + +class InputTrackerHandler +{ +public: + virtual ~InputTrackerHandler() = default; + virtual void dispatch(const TouchDownEvent &e) = 0; + virtual void dispatch(const TouchUpEvent &e) = 0; + virtual void dispatch(const TouchGestureEvent &e) = 0; + virtual void dispatch(const JoypadButtonEvent &e) = 0; + virtual void dispatch(const JoypadAxisEvent &e) = 0; + virtual void dispatch(const KeyboardEvent &e) = 0; + virtual void dispatch(const OrientationEvent &e) = 0; + virtual void dispatch(const MouseButtonEvent &e) = 0; + virtual void dispatch(const MouseMoveEvent &e) = 0; + virtual void dispatch(const JoypadStateEvent &e) = 0; + virtual void dispatch(const InputStateEvent &e) = 0; + virtual void dispatch(const JoypadConnectionEvent &e) = 0; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input_sdl.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input_sdl.cpp new file mode 100644 index 00000000..bc8aedf8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input_sdl.cpp @@ -0,0 +1,184 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "input_sdl.hpp" + +namespace Granite +{ +bool InputTrackerSDL::init(InputTracker &tracker, const Dispatcher &dispatcher) +{ + // Open existing gamepads. + int num_pads = 0; + SDL_JoystickID *gamepad_ids = SDL_GetGamepads(&num_pads); + for (int i = 0; i < num_pads; i++) + add_gamepad(gamepad_ids[i], tracker, dispatcher); + if (gamepad_ids) + SDL_free(gamepad_ids); + + // Poll these separately, inline in poll_input(). + SDL_SetGamepadEventsEnabled(false); + SDL_SetJoystickEventsEnabled(false); + SDL_SetEventEnabled(SDL_EVENT_GAMEPAD_ADDED, true); + SDL_SetEventEnabled(SDL_EVENT_GAMEPAD_REMOVED, true); + SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE, false); + SDL_SetEventEnabled(SDL_EVENT_GAMEPAD_UPDATE_COMPLETE, false); + + return true; +} + +void InputTrackerSDL::update(InputTracker &tracker) +{ + SDL_UpdateGamepads(); + + for (int i = 0; i < int(InputTracker::Joypads); i++) + { + auto *pad = pads[i]; + if (!pad) + continue; + + static const struct + { + JoypadKey gkey; + SDL_GamepadButton sdl; + } buttons[] = { + { JoypadKey::Left, SDL_GAMEPAD_BUTTON_DPAD_LEFT }, + { JoypadKey::Right, SDL_GAMEPAD_BUTTON_DPAD_RIGHT }, + { JoypadKey::Up, SDL_GAMEPAD_BUTTON_DPAD_UP }, + { JoypadKey::Down, SDL_GAMEPAD_BUTTON_DPAD_DOWN }, + { JoypadKey::Start, SDL_GAMEPAD_BUTTON_START }, + { JoypadKey::Select, SDL_GAMEPAD_BUTTON_BACK }, + { JoypadKey::East, SDL_GAMEPAD_BUTTON_EAST }, + { JoypadKey::West, SDL_GAMEPAD_BUTTON_WEST }, + { JoypadKey::North, SDL_GAMEPAD_BUTTON_NORTH }, + { JoypadKey::South, SDL_GAMEPAD_BUTTON_SOUTH }, + { JoypadKey::LeftShoulder, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER }, + { JoypadKey::RightShoulder, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER }, + { JoypadKey::LeftThumb, SDL_GAMEPAD_BUTTON_LEFT_STICK }, + { JoypadKey::RightThumb, SDL_GAMEPAD_BUTTON_RIGHT_STICK }, + { JoypadKey::Mode, SDL_GAMEPAD_BUTTON_GUIDE }, + }; + + for (auto &b : buttons) + { + tracker.joypad_key_state(i, b.gkey, + SDL_GetGamepadButton(pad, b.sdl) ? + JoypadKeyState::Pressed : JoypadKeyState::Released); + } + + static const struct + { + JoypadAxis gaxis; + SDL_GamepadAxis sdl; + } axes[] = { + { JoypadAxis::LeftX, SDL_GAMEPAD_AXIS_LEFTX }, + { JoypadAxis::LeftY, SDL_GAMEPAD_AXIS_LEFTY }, + { JoypadAxis::RightX, SDL_GAMEPAD_AXIS_RIGHTX }, + { JoypadAxis::RightY, SDL_GAMEPAD_AXIS_RIGHTY }, + }; + + for (auto &a : axes) + { + float value = float(SDL_GetGamepadAxis(pad, a.sdl) - SDL_JOYSTICK_AXIS_MIN) / + float(SDL_JOYSTICK_AXIS_MAX - SDL_JOYSTICK_AXIS_MIN); + value = 2.0f * value - 1.0f; + tracker.joyaxis_state(i, a.gaxis, value); + } + + tracker.joyaxis_state(i, JoypadAxis::LeftTrigger, + float(SDL_GetGamepadAxis(pad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER)) / + float(SDL_JOYSTICK_AXIS_MAX)); + + tracker.joyaxis_state(i, JoypadAxis::RightTrigger, + float(SDL_GetGamepadAxis(pad, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)) / + float(SDL_JOYSTICK_AXIS_MAX)); + } +} + +void InputTrackerSDL::close() +{ + for (auto *pad : pads) + if (pad) + SDL_CloseGamepad(pad); +} + +bool InputTrackerSDL::process_sdl_event(const SDL_Event &e, InputTracker &tracker, + const InputTrackerSDL::Dispatcher &dispatcher) +{ + switch (e.type) + { + case SDL_EVENT_GAMEPAD_ADDED: + { + add_gamepad(e.gdevice.which, tracker, dispatcher); + return true; + } + + case SDL_EVENT_GAMEPAD_REMOVED: + { + remove_gamepad(e.gdevice.which, tracker, dispatcher); + return true; + } + + default: + break; + } + + return false; +} + +void InputTrackerSDL::add_gamepad(SDL_JoystickID id, InputTracker &tracker, const Dispatcher &dispatcher) +{ + int player_index = SDL_GetJoystickPlayerIndexForID(id); + if (player_index >= 0 && player_index < int(InputTracker::Joypads) && !pads[player_index]) + { + uint32_t vid = SDL_GetGamepadVendorForID(id); + uint32_t pid = SDL_GetGamepadProductForID(id); + const char *name = SDL_GetGamepadNameForID(id); + LOGI("Plugging in controller: \"%s\" (%u/%u).\n", name, vid, pid); + const char *mapping = SDL_GetGamepadMappingForID(id); + LOGI(" Using mapping: \"%s\"\n", mapping); + pads[player_index] = SDL_OpenGamepad(id); + ids[player_index] = id; + dispatcher([player_index, vid, pid, &tracker]() { + tracker.enable_joypad(player_index, vid, pid); + }); + } +} + +void InputTrackerSDL::remove_gamepad(SDL_JoystickID id, InputTracker &tracker, const Dispatcher &dispatcher) +{ + for (int i = 0; i < int(InputTracker::Joypads); i++) + { + if (pads[i] && ids[i] == id) + { + uint32_t vid = SDL_GetGamepadVendor(pads[i]); + uint32_t pid = SDL_GetGamepadProduct(pads[i]); + SDL_CloseGamepad(pads[i]); + pads[i] = nullptr; + ids[i] = 0; + dispatcher([i, vid, pid, &tracker]() { + tracker.disable_joypad(i, vid, pid); + }); + break; + } + } +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input_sdl.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input_sdl.hpp new file mode 100644 index 00000000..cb6a6504 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/input/input_sdl.hpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include +#include "input.hpp" +#include + +namespace Granite +{ +class InputTrackerSDL +{ +public: + using Dispatcher = std::function)>; + bool init(InputTracker &tracker, const Dispatcher &dispatcher); + void close(); + bool process_sdl_event(const SDL_Event &event, InputTracker &tracker, const Dispatcher &dispatcher); + void update(InputTracker &tracker); + +private: + SDL_Gamepad *pads[InputTracker::Joypads] = {}; + SDL_JoystickID ids[InputTracker::Joypads] = {}; + void add_gamepad(SDL_JoystickID id, InputTracker &tracker, const Dispatcher &dispatcher); + void remove_gamepad(SDL_JoystickID id, InputTracker &tracker, const Dispatcher &dispatcher); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/.dummy.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/.dummy.cpp new file mode 100644 index 00000000..e69de29b diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/CMakeLists.txt new file mode 100644 index 00000000..44601339 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/CMakeLists.txt @@ -0,0 +1,53 @@ +# Must be static due to Granite::application_create() feedback. + +if (ANDROID) + add_granite_internal_static_lib(granite-platform application_android.cpp) + find_package(game-activity REQUIRED CONFIG) + find_package(games-controller REQUIRED CONFIG) + find_package(games-frame-pacing REQUIRED CONFIG) + target_link_libraries(granite-platform PRIVATE granite-rapidjson + game-activity::game-activity_static + games-controller::paddleboat games-frame-pacing::swappy) + + target_compile_definitions(granite-platform PRIVATE VK_USE_PLATFORM_ANDROID_KHR) + if (GRANITE_ANDROID_SWAPPY) + target_compile_definitions(granite-platform PRIVATE HAVE_SWAPPY) + endif() + if (GRANITE_ANDROID_APK_FILESYSTEM) + target_compile_definitions(granite-platform PRIVATE ANDROID_APK_FILESYSTEM) + endif() +elseif (${GRANITE_PLATFORM} MATCHES "libretro") + add_granite_internal_static_lib(granite-platform + application_libretro.cpp + application_libretro_utils.cpp + application_libretro_utils.hpp) + target_compile_definitions(granite-platform PUBLIC HAVE_LIBRETRO) + target_include_directories(granite-platform PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libretro) +elseif (${GRANITE_PLATFORM} MATCHES "SDL") + add_granite_internal_static_lib(granite-platform application_sdl3.cpp) + + if (GRANITE_SYSTEM_SDL) + find_package(SDL3 REQUIRED) + target_link_libraries(granite-platform PRIVATE SDL3::SDL3-shared) + else() + target_link_libraries(granite-platform PRIVATE SDL3-static) + if (NOT WIN32) + target_link_libraries(granite-platform PRIVATE dl) + endif() + endif() + target_link_libraries(granite-platform PRIVATE granite-input-sdl) +elseif (${GRANITE_PLATFORM} MATCHES "headless") + add_granite_internal_static_lib(granite-platform application_headless_wrapper.cpp) +elseif (${GRANITE_PLATFORM} MATCHES "null") + add_granite_internal_static_lib(granite-platform application_null.cpp) +else() + message(FATAL "GRANITE_PLATFORM is not set.") +endif() + +if (NOT (${GRANITE_PLATFORM} MATCHES "null")) + target_link_libraries(granite-platform PRIVATE granite-application-interface-query granite-application granite-input granite-application-global-init) +endif() + +if (GRANITE_AUDIO) + target_link_libraries(granite-platform PRIVATE granite-audio) +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/build.gradle b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/build.gradle new file mode 100644 index 00000000..8a50a47d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/build.gradle @@ -0,0 +1,20 @@ +apply plugin: 'com.android.library' + +android { + namespace = 'net.themaister.granite' + compileSdkVersion = 34 + buildFeatures.prefab = true + + defaultConfig { + minSdkVersion = 26 + targetSdkVersion = 34 + } +} + +dependencies { + implementation 'androidx.appcompat:appcompat:1.5.1' + implementation 'com.google.android.material:material:1.7.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.core:core:1.9.0' + implementation 'androidx.games:games-activity:4.0.0' +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/external_layers/README.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/external_layers/README.txt new file mode 100644 index 00000000..d67c4b85 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/external_layers/README.txt @@ -0,0 +1 @@ +Place {arm64-v8a,armeabi-v7a}/libVkLayer_*.so here to have it bundled in the APK. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/AndroidManifest.xml b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/AndroidManifest.xml new file mode 100644 index 00000000..6af90d3d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/build.gradle b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/build.gradle new file mode 100644 index 00000000..1a74f628 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/build.gradle @@ -0,0 +1,100 @@ +apply plugin: 'com.android.application' + +android { + namespace = '$$NAMESPACE$$' + compileSdkVersion = 34 + + defaultConfig { + minSdkVersion = 26 + targetSdkVersion = 34 + + ndk { + abiFilters = [$$ABIS$$] + } + } + + ndkVersion = '29.0.14206865' + + buildTypes { + debug { + externalNativeBuild { + cmake { + arguments = ["-DANDROID_TOOLCHAIN=clang", + "-DANDROID_STL=c++_shared", + "-DANDROID_ARM_MODE=arm", + "-DANDROID_CPP_FEATURES=exceptions", + "-DGRANITE_SHADER_COMPILER_OPTIMIZE=$$SHADER_OPTIMIZE$$", + "-DGRANITE_VULKAN_FOSSILIZE=$$FOSSILIZE$$", + "-DGRANITE_ANDROID_SWAPPY=$$SWAPPY$$", + "-DCMAKE_BUILD_TYPE=Debug", + "-DANDROID_PLATFORM=android-26", + "-DGRANITE_SHIPPING=ON", + "-DGRANITE_AUDIO=$$AUDIO$$", + "-DGRANITE_BULLET=$$PHYSICS$$", + "-DANDROID_ARM_NEON=ON", + "-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF", + "-DCMAKE_POLICY_VERSION_MINIMUM=3.5"] + + targets = ["$$TARGET$$"] + } + } + jniDebuggable = true + } + release { + externalNativeBuild { + cmake { + arguments = ["-DANDROID_TOOLCHAIN=clang", + "-DANDROID_STL=c++_shared", + "-DANDROID_ARM_MODE=arm", + "-DANDROID_CPP_FEATURES=exceptions", + "-DGRANITE_SHADER_COMPILER_OPTIMIZE=$$SHADER_OPTIMIZE$$", + "-DGRANITE_VULKAN_FOSSILIZE=$$FOSSILIZE$$", + "-DGRANITE_ANDROID_SWAPPY=$$SWAPPY$$", + "-DCMAKE_BUILD_TYPE=Release", + "-DANDROID_PLATFORM=android-26", + "-DGRANITE_SHIPPING=ON", + "-DGRANITE_AUDIO=$$AUDIO$$", + "-DGRANITE_BULLET=$$PHYSICS$$", + "-DANDROID_ARM_NEON=ON", + "-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF", + "-DCMAKE_POLICY_VERSION_MINIMUM=3.5"] + + targets = ["$$TARGET$$"] + } + } + debuggable = true + signingConfig = signingConfigs.debug + jniDebuggable = true + } + } + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + resources.srcDirs = ['res'] + res.srcDirs = ['res'] + assets.srcDirs = ['$$ASSETS$$', '$$GRANITE_ASSETS$$'] + jniLibs.srcDirs = ['$$EXTERNAL_JNI$$'] + $$GRANITE_AUX_ASSETS$$ + } + } + + externalNativeBuild { + cmake { + path = "$$CMAKELISTS$$" + version = "3.22.0+" + } + } + + buildFeatures { + prefab = true + } +} + +dependencies { + api project(':granite') + implementation 'androidx.games:games-activity:4.0.0' + implementation 'androidx.games:games-controller:2.0.2' + implementation 'androidx.games:games-frame-pacing:2.1.3' + $$EXTRA_DEPENDENCIES$$ +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/gradle.properties b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/gradle.properties new file mode 100644 index 00000000..5bac8ac5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX=true diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-hdpi/icon.png b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-hdpi/icon.png new file mode 100644 index 00000000..83b7a19a Binary files /dev/null and b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-hdpi/icon.png differ diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-mdpi/icon.png b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-mdpi/icon.png new file mode 100644 index 00000000..f843f898 Binary files /dev/null and b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-mdpi/icon.png differ diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-xhdpi/icon.png b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-xhdpi/icon.png new file mode 100644 index 00000000..2d813876 Binary files /dev/null and b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-xhdpi/icon.png differ diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-xxhdpi/icon.png b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-xxhdpi/icon.png new file mode 100644 index 00000000..f33b9bf8 Binary files /dev/null and b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-xxhdpi/icon.png differ diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-xxxhdpi/icon.png b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-xxxhdpi/icon.png new file mode 100644 index 00000000..27c5fea0 Binary files /dev/null and b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/res/drawable-xxxhdpi/icon.png differ diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/settings.gradle b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/settings.gradle new file mode 100644 index 00000000..fc3e2bdb --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/settings.gradle @@ -0,0 +1,3 @@ +include 'granite' +project(':granite').projectDir = file('$$GRANITE_ANDROID_ACTIVITY_PATH$$') +include '$$APP$$' diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/settings_custom.gradle b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/settings_custom.gradle new file mode 100644 index 00000000..6739171b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/settings_custom.gradle @@ -0,0 +1,5 @@ +include 'granite' +project(':granite').projectDir = file('$$GRANITE_ANDROID_ACTIVITY_PATH$$') +include 'custom' +project(':custom').projectDir = file('$$ANDROID_ACTIVITY_PATH$$') +include '$$APP$$' diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/toplevel.build.gradle b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/toplevel.build.gradle new file mode 100644 index 00000000..1cae4dd1 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/gradle/toplevel.build.gradle @@ -0,0 +1,26 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:9.0.0-rc01' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + + +allprojects { + repositories { + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/src/main/java/net/themaister/granite/GraniteActivity.java b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/src/main/java/net/themaister/granite/GraniteActivity.java new file mode 100644 index 00000000..8d207dec --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/src/main/java/net/themaister/granite/GraniteActivity.java @@ -0,0 +1,146 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +package net.themaister.granite; + +import com.google.androidgamesdk.GameActivity; +import android.content.Context; +import android.content.Intent; +import android.media.AudioManager; +import android.os.Build; +import android.os.Bundle; +import android.view.Display; +import android.view.View; +import android.view.WindowManager; + +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.core.view.WindowInsetsControllerCompat; + +public class GraniteActivity extends GameActivity +{ + private final static String TAG = "Granite"; + + private void hideSystemUI() + { + // This will put the game behind any cutouts and waterfalls on devices which have + // them, so the corresponding insets will be non-zero. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) + { + getWindow().getAttributes().layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + + // From API 30 onwards, this is the recommended way to hide the system UI, rather than + // using View.setSystemUiVisibility. + View decorView = getWindow().getDecorView(); + WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(getWindow(), + decorView); + controller.hide(WindowInsetsCompat.Type.systemBars()); + controller.hide(WindowInsetsCompat.Type.displayCutout()); + controller.setSystemBarsBehavior( + WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); + } + else + { + getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_FULLSCREEN | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + } + } + + @Override + protected void onCreate(Bundle savedState) + { + // When true, the app will fit inside any system UI windows. + // When false, we render behind any system UI windows. + WindowCompat.setDecorFitsSystemWindows(getWindow(), false); + hideSystemUI(); + setVolumeControlStream(AudioManager.STREAM_MUSIC); + super.onCreate(savedState); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) + { + super.onWindowFocusChanged(hasFocus); + if (hasFocus && Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + hideSystemUI(); + } + + @Override + public void onBackPressed() + { + // Do nothing. We catch this inside native code instead. + } + + public int getDisplayRotation() + { + Display display = getWindowManager().getDefaultDisplay(); + if (display == null) + return 0; + + return display.getRotation(); + } + + public int getAudioNativeSampleRate() + { + AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + if (am == null) + return 0; + + String sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); + if (sampleRate == null) + return 0; + + int rate = Integer.parseInt(sampleRate); + return rate; + } + + public int getAudioNativeBlockFrames() + { + AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + if (am == null) + return 0; + + String frames = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER); + if (frames == null) + return 0; + + int count = Integer.parseInt(frames); + return count; + } + + public String getCommandLineArgument(String key) + { + Intent intent = getIntent(); + if (intent == null) + return ""; + String extra = intent.getStringExtra(key); + if (extra == null) + return ""; + return extra; + } +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/src/main/res/values/strings.xml b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/src/main/res/values/strings.xml new file mode 100644 index 00000000..85420055 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/src/main/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/src/main/res/values/themes.xml b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/src/main/res/values/themes.xml new file mode 100644 index 00000000..1bf466d9 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/android/src/main/res/values/themes.xml @@ -0,0 +1,7 @@ + + + + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_android.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_android.cpp new file mode 100644 index 00000000..890f1db2 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_android.cpp @@ -0,0 +1,1363 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "global_managers_init.hpp" +#include "game-activity/GameActivity.h" +#include "game-activity/native_app_glue/android_native_app_glue.h" +#include "paddleboat/paddleboat.h" +#include "logging.hpp" +#include "application.hpp" +#include "application_events.hpp" +#include "application_wsi.hpp" +#include "context.hpp" +#include "string_helpers.hpp" +#include +#include +#include +#if defined(HAVE_SWAPPY) +#include "swappy/swappyVk.h" +#endif + +#include "android.hpp" +#include "os_filesystem.hpp" +#include "rapidjson_wrapper.hpp" +#include "muglm/muglm_impl.hpp" + +#ifdef AUDIO_HAVE_OPENSL +#include "audio_opensl.hpp" +#endif +#ifdef AUDIO_HAVE_OBOE +#include "audio_oboe.hpp" +#endif + +using namespace Vulkan; + +#define SENSOR_GAME_ROTATION_VECTOR 15 + +namespace Granite +{ +uint32_t android_api_version; +void *java_vm; + +void application_dummy() +{ +} + +// Alternatively, make sure this is linked in. +// Implementation is here to trick a linker to always let main() in static library work. +void application_setup_default_filesystem(const char *default_asset_directory) +{ + auto *filesystem = GRANITE_FILESYSTEM(); + if (filesystem) + Filesystem::setup_default_filesystem(filesystem, default_asset_directory); +} + +struct GlobalState +{ + android_app *app; + int32_t base_width; + int32_t base_height; + int display_rotation; + bool has_window; + bool active; + bool content_rect_changed; +}; + +struct Config +{ + unsigned target_width = 0; + unsigned target_height = 0; + bool support_prerotate = true; + bool support_gyro = false; +}; + +struct JNI +{ + JNIEnv *env; + jclass granite; + jmethodID getDisplayRotation; + jmethodID getAudioNativeSampleRate; + jmethodID getAudioNativeBlockFrames; + jmethodID getCommandLineArgument; + jclass classLoaderClass; + jobject classLoader; + + ASensorEventQueue *sensor_queue; + const ASensor *rotation_sensor; +}; + +static GlobalState global_state; +static Config global_config; +static JNI jni; + +static void on_window_resized(android_app *app) +{ + if (app->window) + { + auto new_width = ANativeWindow_getWidth(app->window); + auto new_height = ANativeWindow_getHeight(app->window); + if (new_width != global_state.base_width || new_height != global_state.base_height) + { + global_state.base_width = new_width; + global_state.base_height = new_height; + global_state.content_rect_changed = true; + } + } +} + +static void on_content_rect_changed(GameActivity *, const ARect *rect) +{ + global_state.base_width = rect->right - rect->left; + global_state.base_height = rect->bottom - rect->top; + global_state.content_rect_changed = true; + LOGI("Got content rect: %d x %d\n", global_state.base_width, global_state.base_height); +} + +namespace App +{ +static std::string getCommandLine() +{ + std::string result; + + jstring key = jni.env->NewStringUTF("granite"); + jstring str = static_cast(jni.env->CallObjectMethod(global_state.app->activity->javaGameActivity, + jni.getCommandLineArgument, + key)); + if (str) + { + const char *data = jni.env->GetStringUTFChars(str, nullptr); + if (data) + { + result = data; + jni.env->ReleaseStringUTFChars(str, data); + } + else + LOGE("Failed to get JNI string data.\n"); + } + else + LOGE("Failed to get JNI string from getCommandLine().\n"); + + return result; +} + +#ifdef HAVE_GRANITE_AUDIO +static int getAudioNativeSampleRate() +{ + int ret = jni.env->CallIntMethod(global_state.app->activity->javaGameActivity, jni.getAudioNativeSampleRate); + return ret; +} + +static int getAudioNativeBlockFrames() +{ + int ret = jni.env->CallIntMethod(global_state.app->activity->javaGameActivity, jni.getAudioNativeBlockFrames); + return ret; +} +#endif + +static int getDisplayRotation() +{ + int ret = jni.env->CallIntMethod(global_state.app->activity->javaGameActivity, jni.getDisplayRotation); + return ret; +} +} + +struct WSIPlatformAndroid : Granite::GraniteWSIPlatform +{ + bool init(unsigned width_, unsigned height_) + { + width = width_; + height = height_; + VK_ASSERT(global_state.base_width && global_state.base_height); + + if (width == 0 && height != 0) + { + width = unsigned(std::round(float(height) * get_aspect_ratio())); + LOGI("Adjusting width to %u pixels based on aspect ratio.\n", width); + } + + if (width != 0 && height == 0) + { + height = unsigned(std::round(float(width) / get_aspect_ratio())); + LOGI("Adjusting height to %u pixels based on aspect ratio.\n", height); + } + + if (!Vulkan::Context::init_loader(nullptr)) + { + LOGE("Failed to init Vulkan loader.\n"); + return false; + } + + get_input_tracker().set_touch_resolution(width, height); + has_window = global_state.has_window; + active = global_state.active; + + return true; + } + +#if defined(HAVE_SWAPPY) + VkDevice current_device = VK_NULL_HANDLE; +#endif + + void event_swapchain_created(Device *device_, VkSwapchainKHR swapchain, unsigned width_, unsigned height_, float aspect_, size_t count_, + VkFormat format_, VkColorSpaceKHR color_space_, VkSurfaceTransformFlagBitsKHR transform_) override + { +#if defined(HAVE_SWAPPY) + current_device = device_->get_device(); + + uint64_t refresh = 0; + if (SwappyVk_initAndGetRefreshCycleDuration(jni.env, global_state.app->activity->javaGameActivity, + device_->get_physical_device(), device_->get_device(), + swapchain, &refresh)) + { + LOGI("Swappy reported refresh duration of %.3f ms.\n", double(refresh) * 1e-6); + } + else + LOGW("Failed to initialize swappy refresh rate.\n"); + + SwappyVk_setWindow(current_device, swapchain, global_state.app->window); +#endif + + Granite::GraniteWSIPlatform::event_swapchain_created(device_, swapchain, width_, height_, + aspect_, count_, format_, + color_space_, transform_); + + if (transform_ & (VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR)) + { + std::swap(width_, height_); + } + get_input_tracker().set_touch_resolution(width_, height_); + } + + void destroy_swapchain_resources(VkSwapchainKHR swapchain) override + { + (void)swapchain; +#if defined(HAVE_SWAPPY) + if (current_device && swapchain) + { + SwappyVk_destroySwapchain(current_device, swapchain); + current_device = VK_NULL_HANDLE; + } +#endif + } + + void update_orientation(); + bool alive(Vulkan::WSI &wsi) override; + void poll_input() override; + void poll_input_async(Granite::InputTrackerHandler *override_handler) override; + + void request_teardown(); + void gamepad_update(bool async); + + std::vector get_instance_extensions() override + { + return { "VK_KHR_surface", "VK_KHR_android_surface" }; + } + + uint32_t get_surface_width() override + { + return width; + } + + uint32_t get_surface_height() override + { + return height; + } + + float get_aspect_ratio() override + { + return float(global_state.base_width) / global_state.base_height; + } + + VkSurfaceKHR create_surface(VkInstance instance, VkPhysicalDevice) override; + + unsigned width = 0, height = 0; + Application *app = nullptr; + Vulkan::WSI *app_wsi = nullptr; + uint64_t active_axes = 0; + bool active = false; + bool has_window = true; + bool wsi_idle = false; + bool requesting_teardown = false; + + bool pending_native_window_init = false; + bool pending_native_window_term = false; + bool pending_config_change = false; + bool has_mouse_input = false; + + struct + { + GameTextInputState state = {}; + char buffer[1024]; + } ime = {}; + + void begin_soft_keyboard(const std::string &initial) override + { + if (global_state.app && global_state.app->activity) + { + // Very unclear from documentation what the lifetime of this struct is. + // Just keep it alive until end of time. + ime.state.composingRegion.start = SPAN_UNDEFINED; + ime.state.composingRegion.end = SPAN_UNDEFINED; + ime.state.text_UTF8 = ime.buffer; + strncpy(ime.buffer, initial.c_str(), sizeof(ime.buffer) - 1); + ime.state.text_length = strlen(ime.state.text_UTF8); + // Might be broken w.r.t. unicode? + ime.state.selection.start = ime.state.text_length; + ime.state.selection.end = ime.state.text_length; + GameActivity_setTextInputState(global_state.app->activity, &ime.state); + GameActivity_showSoftInput(global_state.app->activity, + GAMEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT); + } + } + + void end_soft_keyboard() override + { + if (global_state.app && global_state.app->activity) + GameActivity_hideSoftInput(global_state.app->activity, GAMEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY); + } +}; + +static VkSurfaceKHR create_surface_from_native_window(VkInstance instance, ANativeWindow *window) +{ + VkSurfaceKHR surface = VK_NULL_HANDLE; + VkAndroidSurfaceCreateInfoKHR create_info = { VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR }; + create_info.window = window; + + auto gpa = Vulkan::Context::get_instance_proc_addr(); +#define SYM(x) PFN_##x p_##x; do { PFN_vkVoidFunction vf = gpa(instance, #x); memcpy(&p_##x, &vf, sizeof(vf)); } while(0) + SYM(vkCreateAndroidSurfaceKHR); + if (p_vkCreateAndroidSurfaceKHR(instance, &create_info, nullptr, &surface) != VK_SUCCESS) + return VK_NULL_HANDLE; + return surface; +} + +static void enable_sensors() +{ + if (!jni.rotation_sensor || !jni.sensor_queue) + return; + + int min_delay = ASensor_getMinDelay(jni.rotation_sensor); + ASensorEventQueue_enableSensor(jni.sensor_queue, jni.rotation_sensor); + if (ASensorEventQueue_setEventRate(jni.sensor_queue, jni.rotation_sensor, std::max(8000, min_delay)) < 0) + LOGE("Failed to set event rate.\n"); +} + +static void disable_sensors() +{ + if (!jni.rotation_sensor || !jni.sensor_queue) + return; + + ASensorEventQueue_disableSensor(jni.sensor_queue, jni.rotation_sensor); +} + +static void handle_sensors() +{ + if (!global_state.app->userData) + return; + + auto &state = *static_cast(global_state.app->userData); + + if (!ASensorEventQueue_hasEvents(jni.sensor_queue)) + return; + + ASensorEvent events[64]; + for (;;) + { + int count = ASensorEventQueue_getEvents(jni.sensor_queue, events, 64); + if (count <= 0) + return; + + for (int i = 0; i < count; i++) + { + auto &event = events[i]; + if (event.type == SENSOR_GAME_ROTATION_VECTOR) + { + quat q(event.data[3], -event.data[0], -event.data[1], -event.data[2]); + + // Compensate for different display rotation. + if (global_state.display_rotation == 1) + { + std::swap(q.x, q.y); + q.x = -q.x; + } + else if (global_state.display_rotation == 2) + { + // Doesn't seem to be possible to trigger this? + LOGE("Untested orientation %u!\n", global_state.display_rotation); + } + else if (global_state.display_rotation == 3) + { + std::swap(q.x, q.y); + q.y = -q.y; + } + + static const quat landscape(muglm::one_over_root_two(), muglm::one_over_root_two(), 0.0f, 0.0f); + q = conjugate(normalize(q * landscape)); + state.get_input_tracker().orientation_event(q); + } + } + } +} + +static void engine_handle_input(WSIPlatformAndroid &state) +{ + auto *input_buffer = android_app_swap_input_buffers(global_state.app); + + if (!input_buffer) + return; + + for (uint32_t i = 0; i < input_buffer->keyEventsCount; i++) + { + auto &event = input_buffer->keyEvents[i]; + + auto action = event.action; + auto code = event.keyCode; + + if (Paddleboat_isInitialized()) + if (Paddleboat_processGameActivityKeyInputEvent(&event, sizeof(event))) + continue; + + if (event.source == AINPUT_SOURCE_KEYBOARD) + { + if (action == AKEY_EVENT_ACTION_DOWN && code == AKEYCODE_BACK) + { + LOGI("Requesting teardown.\n"); + state.requesting_teardown = true; + } + } + } + + android_app_clear_key_events(input_buffer); + + for (uint32_t i = 0; i < input_buffer->motionEventsCount; i++) + { + auto &event = input_buffer->motionEvents[i]; + + auto action = event.action & AMOTION_EVENT_ACTION_MASK; + auto index = (event.action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + auto source = event.source; + + // Paddleboat eats mouse events, and we want to handle them raw. + if (source == AINPUT_SOURCE_MOUSE) + { + // TODO: Does Android have concept of focus? + if (!state.has_mouse_input) + { + state.get_input_tracker().mouse_enter(0.0, 0.0); + state.has_mouse_input = true; + } + + switch (action) + { + case AMOTION_EVENT_ACTION_MOVE: + case AMOTION_EVENT_ACTION_HOVER_MOVE: + { + auto x = GameActivityPointerAxes_getX(&event.pointers[index]); + auto y = GameActivityPointerAxes_getY(&event.pointers[index]); + x /= float(global_state.base_width); + y /= float(global_state.base_height); + state.get_input_tracker().mouse_move_event_absolute_normalized(x, y); + break; + } + + case AMOTION_EVENT_ACTION_DOWN: + case AMOTION_EVENT_ACTION_POINTER_DOWN: + { + auto x = GameActivityPointerAxes_getX(&event.pointers[index]); + auto y = GameActivityPointerAxes_getY(&event.pointers[index]); + x /= float(global_state.base_width); + y /= float(global_state.base_height); + if (event.buttonState & AMOTION_EVENT_BUTTON_PRIMARY) + state.get_input_tracker().mouse_button_event_normalized(MouseButton::Left, x, y, true); + if (event.buttonState & AMOTION_EVENT_BUTTON_SECONDARY) + state.get_input_tracker().mouse_button_event_normalized(MouseButton::Right, x, y, true); + break; + } + + case AMOTION_EVENT_ACTION_UP: + case AMOTION_EVENT_ACTION_POINTER_UP: + { + if (!(event.buttonState & AMOTION_EVENT_BUTTON_PRIMARY)) + state.get_input_tracker().mouse_button_event(MouseButton::Left, false); + if (!(event.buttonState & AMOTION_EVENT_BUTTON_SECONDARY)) + state.get_input_tracker().mouse_button_event(MouseButton::Right, false); + break; + } + + default: + break; + } + + continue; + } + + if (Paddleboat_isInitialized()) + if (Paddleboat_processGameActivityMotionInputEvent(&event, sizeof(event))) + continue; + + if (source == AINPUT_SOURCE_TOUCHSCREEN) + { + switch (action) + { + case AMOTION_EVENT_ACTION_DOWN: + case AMOTION_EVENT_ACTION_POINTER_DOWN: + { + auto x = GameActivityPointerAxes_getX(&event.pointers[index]); + auto y = GameActivityPointerAxes_getY(&event.pointers[index]); + x /= float(global_state.base_width); + y /= float(global_state.base_height); + int id = event.pointers[index].id; + state.get_input_tracker().on_touch_down(id, x, y); + break; + } + + case AMOTION_EVENT_ACTION_MOVE: + { + size_t count = event.pointerCount; + for (size_t p = 0; p < count; p++) + { + // Divide by base_width / base_height? + auto x = GameActivityPointerAxes_getX(&event.pointers[p]); + auto y = GameActivityPointerAxes_getY(&event.pointers[p]); + x /= float(global_state.base_width); + y /= float(global_state.base_height); + int id = event.pointers[p].id; + state.get_input_tracker().on_touch_move(id, x, y); + } + state.get_input_tracker().dispatch_touch_gesture(); + break; + } + + case AMOTION_EVENT_ACTION_UP: + case AMOTION_EVENT_ACTION_POINTER_UP: + { + auto x = GameActivityPointerAxes_getX(&event.pointers[index]); + auto y = GameActivityPointerAxes_getY(&event.pointers[index]); + x /= float(global_state.base_width); + y /= float(global_state.base_height); + int id = event.pointers[index].id; + state.get_input_tracker().on_touch_up(id, x, y); + break; + } + + default: + break; + } + } + } + + android_app_clear_motion_events(input_buffer); +} + +static void engine_handle_cmd_init(android_app *app, int32_t cmd) +{ + switch (cmd) + { + case APP_CMD_RESUME: + { + LOGI("Lifecycle resume\n"); + enable_sensors(); + + global_state.active = true; + break; + } + + case APP_CMD_PAUSE: + { + LOGI("Lifecycle pause\n"); + disable_sensors(); + global_state.active = false; + break; + } + + case APP_CMD_START: + { + LOGI("Lifecycle start\n"); + if (jni.env && Paddleboat_isInitialized()) + Paddleboat_onStart(jni.env); + break; + } + + case APP_CMD_STOP: + { + LOGI("Lifecycle stop\n"); + if (jni.env && Paddleboat_isInitialized()) + Paddleboat_onStop(jni.env); + break; + } + + case APP_CMD_INIT_WINDOW: + { + global_state.has_window = app->window != nullptr; + if (app->window) + { + LOGI("Init window\n"); + global_state.base_width = ANativeWindow_getWidth(app->window); + global_state.base_height = ANativeWindow_getHeight(app->window); + global_state.content_rect_changed = true; + } + + global_state.display_rotation = jni.env->CallIntMethod(app->activity->javaGameActivity, jni.getDisplayRotation); + break; + } + + case APP_CMD_WINDOW_RESIZED: + { + on_window_resized(app); + break; + } + + case APP_CMD_CONTENT_RECT_CHANGED: + { + on_content_rect_changed(app->activity, &app->contentRect); + break; + } + + default: + break; + } +} + +static void engine_handle_cmd(android_app *app, int32_t cmd) +{ + if (!app->userData) + return; + auto &state = *static_cast(app->userData); + + switch (cmd) + { + case APP_CMD_RESUME: + { + LOGI("Lifecycle resume\n"); + if (auto *e = GRANITE_EVENT_MANAGER()) + { + e->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + e->enqueue_latched( + ApplicationLifecycle::Running); + } + enable_sensors(); + + Granite::Global::start_audio_system(); + + state.active = true; + if (state.wsi_idle) + { + state.get_frame_timer().leave_idle(); + state.wsi_idle = false; + } + break; + } + + case APP_CMD_PAUSE: + { + LOGI("Lifecycle pause\n"); + if (auto *e = GRANITE_EVENT_MANAGER()) + { + e->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + e->enqueue_latched( + ApplicationLifecycle::Paused); + } + disable_sensors(); + Granite::Global::stop_audio_system(); + + state.active = false; + state.get_frame_timer().enter_idle(); + state.wsi_idle = true; + break; + } + + case APP_CMD_START: + { + LOGI("Lifecycle start\n"); + if (auto *e = GRANITE_EVENT_MANAGER()) + { + e->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + e->enqueue_latched( + ApplicationLifecycle::Paused); + } + if (jni.env && Paddleboat_isInitialized()) + Paddleboat_onStart(jni.env); + break; + } + + case APP_CMD_STOP: + { + LOGI("Lifecycle stop\n"); + if (auto *e = GRANITE_EVENT_MANAGER()) + { + e->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + e->enqueue_latched( + ApplicationLifecycle::Stopped); + } + if (jni.env && Paddleboat_isInitialized()) + Paddleboat_onStop(jni.env); + break; + } + + case APP_CMD_INIT_WINDOW: + if (app->window != nullptr) + { + state.has_window = true; + LOGI("New window size %d x %d\n", global_state.base_width, global_state.base_height); + global_state.base_width = ANativeWindow_getWidth(app->window); + global_state.base_height = ANativeWindow_getHeight(app->window); + global_state.content_rect_changed = false; + + if (state.app_wsi) + { + LOGI("Lifecycle init window.\n"); + auto surface = create_surface_from_native_window(state.app_wsi->get_context().get_instance(), app->window); + state.app_wsi->reinit_surface_and_swapchain(surface); + } + else + { + LOGI("Pending init window.\n"); + state.pending_native_window_init = true; + } + } + break; + + case APP_CMD_TERM_WINDOW: + state.has_window = false; + if (state.app_wsi) + { + LOGI("Lifecycle deinit window.\n"); + state.app_wsi->deinit_surface_and_swapchain(); + } + else + { + LOGI("Pending deinit window.\n"); + state.pending_native_window_term = true; + } + break; + + case APP_CMD_WINDOW_RESIZED: + { + on_window_resized(app); + break; + } + + case APP_CMD_CONTENT_RECT_CHANGED: + { + on_content_rect_changed(app->activity, &app->contentRect); + break; + } + + default: + break; + } +} + +VkSurfaceKHR WSIPlatformAndroid::create_surface(VkInstance instance, VkPhysicalDevice) +{ + return create_surface_from_native_window(instance, global_state.app->window); +} + +void WSIPlatformAndroid::update_orientation() +{ + global_state.display_rotation = App::getDisplayRotation(); + LOGI("Got new rotation: %d\n", global_state.display_rotation); + LOGI("Got new resolution: %d x %d\n", global_state.base_width, global_state.base_height); + pending_config_change = true; +} + +void WSIPlatformAndroid::request_teardown() +{ + requesting_teardown = true; +} + +void WSIPlatformAndroid::gamepad_update(bool async) +{ + // Don't deal with anything JNI related in async callbacks. + if (!async) + { + if (jni.env && Paddleboat_isInitialized()) + Paddleboat_update(jni.env); + + // Need to explicitly enables axes we care about. + const uint64_t new_active_axes = Paddleboat_getActiveAxisMask(); + uint64_t new_axes = new_active_axes ^ active_axes; + + if (new_axes != 0) + { + active_axes = new_active_axes; + int32_t axis_index = 0; + + while (new_axes != 0) + { + if ((new_axes & 1) != 0) + { + LOGI("Enable Axis: %d", axis_index); + GameActivityPointerAxes_enableAxis(axis_index); + } + axis_index++; + new_axes >>= 1; + } + } + } + + auto &tracker = get_input_tracker(); + for (int i = 0; i < PADDLEBOAT_MAX_CONTROLLERS; i++) + { + if (Paddleboat_getControllerStatus(i) != PADDLEBOAT_CONTROLLER_ACTIVE) + continue; + + Paddleboat_Controller_Info info = {}; + Paddleboat_getControllerInfo(i, &info); + bool known_layout = false; + + switch (info.controllerFlags & PADDLEBOAT_CONTROLLER_LAYOUT_MASK) + { + case PADDLEBOAT_CONTROLLER_LAYOUT_SHAPES: + case PADDLEBOAT_CONTROLLER_LAYOUT_STANDARD: + known_layout = true; + break; + + default: + break; + } + + if (!known_layout) + continue; + + Paddleboat_Controller_Data data = {}; + Paddleboat_getControllerData(i, &data); + + struct Mapping + { + JoypadKey key; + uint32_t mask; + }; + static const Mapping map[] = { + { JoypadKey::Left, PADDLEBOAT_BUTTON_DPAD_LEFT }, + { JoypadKey::Right, PADDLEBOAT_BUTTON_DPAD_RIGHT }, + { JoypadKey::Up, PADDLEBOAT_BUTTON_DPAD_UP }, + { JoypadKey::Down, PADDLEBOAT_BUTTON_DPAD_DOWN }, + { JoypadKey::West, PADDLEBOAT_BUTTON_X }, + { JoypadKey::East, PADDLEBOAT_BUTTON_B }, + { JoypadKey::North, PADDLEBOAT_BUTTON_Y }, + { JoypadKey::South, PADDLEBOAT_BUTTON_A }, + { JoypadKey::Start, PADDLEBOAT_BUTTON_START }, + { JoypadKey::Select, PADDLEBOAT_BUTTON_SELECT }, + { JoypadKey::LeftShoulder, PADDLEBOAT_BUTTON_L1 }, + { JoypadKey::RightShoulder, PADDLEBOAT_BUTTON_R1 }, + { JoypadKey::LeftThumb, PADDLEBOAT_BUTTON_L3 }, + { JoypadKey::RightThumb, PADDLEBOAT_BUTTON_R3 }, + { JoypadKey::Mode, PADDLEBOAT_BUTTON_SYSTEM }, + }; + + for (auto &m : map) + { + tracker.joypad_key_state(i, m.key, + (data.buttonsDown & m.mask) != 0 ? + JoypadKeyState::Pressed : JoypadKeyState::Released); + } + + tracker.joyaxis_state(i, JoypadAxis::LeftX, data.leftStick.stickX); + tracker.joyaxis_state(i, JoypadAxis::LeftY, data.leftStick.stickY); + tracker.joyaxis_state(i, JoypadAxis::RightX, data.rightStick.stickX); + tracker.joyaxis_state(i, JoypadAxis::RightY, data.rightStick.stickY); + tracker.joyaxis_state(i, JoypadAxis::LeftTrigger, data.triggerL2); + tracker.joyaxis_state(i, JoypadAxis::RightTrigger, data.triggerR2); + } +} + +extern "C" +{ +static void game_text_input_cb(void *userdata, const struct GameTextInputState *state) +{ + auto *app = static_cast(userdata); + if (!app || !state) + return; + + if (auto *e = GRANITE_EVENT_MANAGER()) + e->enqueue(state->text_UTF8); + + // Clear the text input flag. + app->textInputState = 0; +} +} + +void WSIPlatformAndroid::poll_input() +{ + std::lock_guard holder{get_input_tracker().get_lock()}; + int events; + int ident; + android_poll_source *source; + app_wsi = nullptr; + + while ((ident = ALooper_pollOnce(0, nullptr, &events, reinterpret_cast(&source))) > ALOOPER_POLL_TIMEOUT) + { + if (source) + source->process(global_state.app, source); + + if (ident == LOOPER_ID_USER) + handle_sensors(); + + if (global_state.app->destroyRequested) + return; + } + + if (global_state.app->textInputState) + { + GameActivity_getTextInputState(global_state.app->activity, game_text_input_cb, + global_state.app); + } + + engine_handle_input(*this); + gamepad_update(false); + get_input_tracker().dispatch_current_state(get_frame_timer().get_frame_time()); +} + +void WSIPlatformAndroid::poll_input_async(Granite::InputTrackerHandler *override_handler) +{ + std::lock_guard holder{get_input_tracker().get_lock()}; + begin_async_input_handling(); + { + // Only process input events here, not anything related to lifetimes. + engine_handle_input(*this); + gamepad_update(true); + } + end_async_input_handling(); + get_input_tracker().dispatch_current_state(0.0, override_handler); +} + +bool WSIPlatformAndroid::alive(Vulkan::WSI &wsi) +{ + auto &state = *static_cast(global_state.app->userData); + int events; + int ident; + android_poll_source *source; + state.app_wsi = &wsi; + + if (global_state.app->destroyRequested || requesting_teardown) + return false; + + bool once = false; + + if (global_state.content_rect_changed) + { + update_orientation(); + global_state.content_rect_changed = false; + } + + if (state.pending_config_change) + { + state.pending_native_window_term = true; + state.pending_native_window_init = true; + state.pending_config_change = false; + } + + const auto flush_pending = [&]() { + if (state.pending_native_window_term) + { + LOGI("Pending native window term\n"); + wsi.deinit_surface_and_swapchain(); + state.pending_native_window_term = false; + } + + if (state.pending_native_window_init) + { + LOGI("Pending native window init\n"); + auto surface = create_surface_from_native_window(wsi.get_context().get_instance(), global_state.app->window); + wsi.reinit_surface_and_swapchain(surface); + state.pending_native_window_init = false; + } + }; + + flush_pending(); + + while (!once || !state.active || !state.has_window) + { + while ((ident = ALooper_pollOnce((state.has_window && state.active) ? 0 : -1, + nullptr, &events, reinterpret_cast(&source))) > ALOOPER_POLL_TIMEOUT) + { + if (source) + source->process(global_state.app, source); + + if (ident == LOOPER_ID_USER) + handle_sensors(); + + if (global_state.app->destroyRequested) + return false; + } + + once = true; + } + + flush_pending(); + + return true; +} + +static void deinit_jni() +{ + if (jni.env && Paddleboat_isInitialized()) + Paddleboat_destroy(jni.env); + + if (jni.env && global_state.app) + { + global_state.app->activity->vm->DetachCurrentThread(); + jni.env = nullptr; + } +} + +void paddleboat_controller_status_cb( + const int32_t controllerIndex, + const Paddleboat_ControllerStatus controllerStatus, void *) +{ + if (controllerStatus == PADDLEBOAT_CONTROLLER_JUST_CONNECTED) + { + char name[1024]; + *name = '\0'; + Paddleboat_getControllerName(controllerIndex, sizeof(name), name); + LOGI("Controller #%u (%s) connected.\n", controllerIndex, name); + auto *platform = static_cast(global_state.app->userData); + if (platform) + platform->get_input_tracker().enable_joypad(controllerIndex, 0, 0 /* todo */); + + } + else if (controllerStatus == PADDLEBOAT_CONTROLLER_JUST_DISCONNECTED) + { + LOGI("Controller #%u disconnected.\n", controllerIndex); + auto *platform = static_cast(global_state.app->userData); + if (platform) + platform->get_input_tracker().disable_joypad(controllerIndex, 0, 0 /* todo */); + } +} + +static void init_jni() +{ + auto *app = global_state.app; + app->activity->vm->AttachCurrentThread(&jni.env, nullptr); + java_vm = app->activity->vm; + + if (Paddleboat_init(jni.env, app->activity->javaGameActivity) != PADDLEBOAT_NO_ERROR) + LOGE("Failed to initialize Paddleboat.\n"); + else if (!Paddleboat_isInitialized()) + LOGE("Paddleboat is not initialized.\n"); + else + Paddleboat_setControllerStatusCallback(paddleboat_controller_status_cb, nullptr); + + jclass clazz = jni.env->GetObjectClass(app->activity->javaGameActivity); + jmethodID getApplication = jni.env->GetMethodID(clazz, "getApplication", "()Landroid/app/Application;"); + jobject application = jni.env->CallObjectMethod(app->activity->javaGameActivity, getApplication); + + jclass applicationClass = jni.env->GetObjectClass(application); + jmethodID getApplicationContext = jni.env->GetMethodID(applicationClass, "getApplicationContext", "()Landroid/content/Context;"); + jobject context = jni.env->CallObjectMethod(application, getApplicationContext); + + jclass contextClass = jni.env->GetObjectClass(context); + jmethodID getClassLoader = jni.env->GetMethodID(contextClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); + jni.classLoader = jni.env->CallObjectMethod(context, getClassLoader); + + jni.classLoaderClass = jni.env->GetObjectClass(jni.classLoader); + jmethodID loadClass = jni.env->GetMethodID(jni.classLoaderClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + + jstring granite_str = jni.env->NewStringUTF("net.themaister.granite.GraniteActivity"); + jni.granite = static_cast(jni.env->CallObjectMethod(jni.classLoader, loadClass, granite_str)); + + jni.getDisplayRotation = jni.env->GetMethodID(jni.granite, "getDisplayRotation", "()I"); + jni.getAudioNativeSampleRate = jni.env->GetMethodID(jni.granite, "getAudioNativeSampleRate", "()I"); + jni.getAudioNativeBlockFrames = jni.env->GetMethodID(jni.granite, "getAudioNativeBlockFrames", "()I"); + jni.getCommandLineArgument = jni.env->GetMethodID(jni.granite, "getCommandLineArgument", "(Ljava/lang/String;)Ljava/lang/String;"); + +#ifdef HAVE_GRANITE_AUDIO + int sample_rate = App::getAudioNativeSampleRate(); + int block_frames = App::getAudioNativeBlockFrames(); +#ifdef AUDIO_HAVE_OBOE + Granite::Audio::set_oboe_low_latency_parameters(sample_rate, block_frames); +#endif +#endif + + GameActivity_setWindowFlags(app->activity, + AWINDOW_FLAG_KEEP_SCREEN_ON | AWINDOW_FLAG_TURN_SCREEN_ON | + AWINDOW_FLAG_FULLSCREEN | + AWINDOW_FLAG_SHOW_WHEN_LOCKED, + 0); +} + +static void init_sensors() +{ + auto *manager = ASensorManager_getInstanceForPackage("net.themaister.GraniteActivity"); + if (!manager) + return; + + jni.rotation_sensor = ASensorManager_getDefaultSensor(manager, SENSOR_GAME_ROTATION_VECTOR); + if (!jni.rotation_sensor) + return; + + LOGI("Game Sensor name: %s\n", ASensor_getName(jni.rotation_sensor)); + + jni.sensor_queue = ASensorManager_createEventQueue(manager, ALooper_forThread(), LOOPER_ID_USER, nullptr, nullptr); + if (!jni.sensor_queue) + return; +} +} + +using namespace Granite; + +static void wait_for_complete_teardown(android_app *app) +{ + // If we requested to be torn down with GameActivity_finish(), + // at least make sure we observe and pump through all takedown events, + // or we get a deadlock. + while (!app->destroyRequested) + { + android_poll_source *source = nullptr; + int events = 0; + + if (ALooper_pollOnce(-1, nullptr, &events, reinterpret_cast(&source)) > ALOOPER_POLL_TIMEOUT) + { + if (source) + source->process(app, source); + } + } + + assert(app->activityState == APP_CMD_STOP); +} + +static bool key_event_filter(const GameActivityKeyEvent *event) +{ + // For some inexplicable reason, this can be a bitmask of GAMEPAD and KEYBOARD ... + if (event->source & (AINPUT_SOURCE_GAMEPAD & AINPUT_SOURCE_ANY)) + return true; + + if (event->source & (AINPUT_SOURCE_KEYBOARD & AINPUT_SOURCE_ANY)) + { + // System level keycodes that we don't care about + // should be handled by system. + auto code = event->keyCode; + bool handled = code != AKEYCODE_VOLUME_DOWN && + code != AKEYCODE_VOLUME_UP; + return handled; + } + + return false; +} + +static bool motion_event_filter(const GameActivityMotionEvent *event) +{ + return (event->source & + (AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_JOYSTICK | AINPUT_SOURCE_MOUSE) & + AINPUT_SOURCE_ANY) != 0; +} + +static void parse_config() +{ + std::string android_config; + GRANITE_FILESYSTEM()->read_file_to_string("assets://android.json", android_config); + + if (!android_config.empty()) + { + rapidjson::Document doc; + doc.Parse(android_config); + + if (doc.HasMember("width")) + global_config.target_width = doc["width"].GetUint(); + if (doc.HasMember("height")) + global_config.target_height = doc["height"].GetUint(); + if (doc.HasMember("supportPrerotate")) + global_config.support_prerotate = doc["supportPrerotate"].GetBool(); + if (doc.HasMember("enableGyro")) + global_config.support_gyro = doc["enableGyro"].GetBool(); + } +} + +void android_main(android_app *app) +{ + // Statics on Android might not be cleared out. + global_state = {}; + global_config = {}; + jni = {}; + + global_state.app = app; + + init_jni(); + + ApplicationQueryDefaultManagerFlags flags{Global::MANAGER_FEATURE_DEFAULT_BITS}; + query_application_interface(ApplicationQuery::DefaultManagerFlags, &flags, sizeof(flags)); + Global::init(flags.manager_feature_flags | Global::MANAGER_FEATURE_FILESYSTEM_BIT); + + LOGI("Starting Granite!\n"); + +#ifdef ANDROID_APK_FILESYSTEM + +#ifndef ANDROID_BUILTIN_ASSET_PATH +#define ANDROID_BUILTIN_ASSET_PATH "" +#endif + +#ifndef ANDROID_ASSET_PATH +#define ANDROID_ASSET_PATH "" +#endif + +#ifndef ANDROID_FSR2_ASSET_PATH +#define ANDROID_FSR2_ASSET_PATH "" +#endif + + AssetManagerFilesystem::global_asset_manager = app->activity->assetManager; + if (auto *fs = GRANITE_FILESYSTEM()) + { + fs->register_protocol("builtin", std::make_unique( + ANDROID_BUILTIN_ASSET_PATH)); + fs->register_protocol("assets", std::make_unique( + ANDROID_ASSET_PATH)); + fs->register_protocol("fsr2", std::make_unique( + ANDROID_FSR2_ASSET_PATH)); + fs->register_protocol("cache", std::make_unique( + app->activity->internalDataPath)); + fs->register_protocol("external", std::make_unique( + app->activity->externalDataPath)); + + parse_config(); + } +#endif + + android_app_set_key_event_filter(app, key_event_filter); + android_app_set_motion_event_filter(app, motion_event_filter); + app->onAppCmd = engine_handle_cmd_init; + app->userData = nullptr; + + if (global_config.support_gyro) + init_sensors(); + + if (auto *e = GRANITE_EVENT_MANAGER()) + e->enqueue_latched(ApplicationLifecycle::Stopped); + + for (;;) + { + int events; + int ident; + android_poll_source *source; + while ((ident = ALooper_pollOnce(-1, nullptr, &events, reinterpret_cast(&source))) > ALOOPER_POLL_TIMEOUT) + { + if (source) + source->process(app, source); + + if (app->destroyRequested) + { + if (auto *e = GRANITE_EVENT_MANAGER()) + e->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + Global::deinit(); + deinit_jni(); + return; + } + + if (ident == LOOPER_ID_USER) + handle_sensors(); + + if (Granite::global_state.has_window && Granite::global_state.active && + Granite::global_state.content_rect_changed) + { + Granite::global_state.content_rect_changed = false; + app->onAppCmd = Granite::engine_handle_cmd; + + try + { + std::vector argv; + argv.push_back("granite"); + + std::string cli_arguments = App::getCommandLine(); + std::vector arguments; + LOGI("Intent arguments: %s\n", cli_arguments.c_str()); + if (!cli_arguments.empty()) + { + arguments = Util::split_no_empty(cli_arguments, " "); + for (auto &arg : arguments) + { + LOGI("Command line argument: %s\n", arg.c_str()); + argv.push_back(arg.c_str()); + } + } + argv.push_back(nullptr); + + auto app_handle = std::unique_ptr( + Granite::application_create(int(argv.size()) - 1, + const_cast(argv.data()))); + + int ret; + if (app_handle) + { + LOGI("Using resolution: %u x %u\n", global_config.target_width, global_config.target_height); + app_handle->get_wsi().set_support_prerotate(global_config.support_prerotate); + + if (auto *e = GRANITE_EVENT_MANAGER()) + { + e->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + e->enqueue_latched( + ApplicationLifecycle::Paused); + e->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + e->enqueue_latched( + ApplicationLifecycle::Running); + } + + auto platform = std::make_unique(); + if (platform->init(global_config.target_width, global_config.target_height)) + { + global_state.app->userData = platform.get(); + if (!app_handle->init_platform(std::move(platform)) || !app_handle->init_wsi()) + ret = 1; + else + { + // Defer initializing audio until the application has loaded. + Granite::Global::start_audio_system(); + + while (app_handle->poll()) + app_handle->run_frame(); + ret = 0; + } + } + else + ret = 1; + } + else + { + global_state.app->userData = nullptr; + ret = 1; + } + + LOGI("Application returned %d.\n", ret); + if (auto *e = GRANITE_EVENT_MANAGER()) + e->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + GameActivity_finish(global_state.app->activity); + + wait_for_complete_teardown(global_state.app); + + app_handle.reset(); + Global::deinit(); + deinit_jni(); + global_state.app->userData = nullptr; + return; + } + catch (const std::exception &e) + { + LOGE("Application threw exception: %s\n", e.what()); + deinit_jni(); + exit(1); + } + } + } + } +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_headless.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_headless.cpp new file mode 100644 index 00000000..5f47ff05 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_headless.cpp @@ -0,0 +1,686 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "application.hpp" +#include "application_events.hpp" +#include "application_wsi.hpp" +#include "vulkan_headers.hpp" +#include +#include +#include +#include "stb_image_write.h" +#include "cli_parser.hpp" +#include "os_filesystem.hpp" +#include "rapidjson_wrapper.hpp" +#include +#include +#include "thread_group.hpp" +#include "global_managers_init.hpp" +#include "path_utils.hpp" +#include "thread_group.hpp" +#include "asset_manager.hpp" + +#ifdef HAVE_GRANITE_FFMPEG +#include "ffmpeg_encode.hpp" +#endif + +#ifdef HAVE_GRANITE_AUDIO +#include "audio_interface.hpp" +#include "audio_mixer.hpp" +#endif + +using namespace rapidjson; +using namespace Vulkan; +using namespace Util; + +namespace Granite +{ +struct WSIPlatformHeadless : Granite::GraniteWSIPlatform +{ +public: + ~WSIPlatformHeadless() override + { + release_resources(); + } + + void release_resources() override + { + for (auto &t : swapchain_tasks) + t.reset(); + if (last_task_dependency) + last_task_dependency->wait(); + last_task_dependency.reset(); + + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + { + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Paused); + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Stopped); + } + + swapchain_images.clear(); + readback_buffers.clear(); + acquire_semaphore.clear(); +#ifdef HAVE_GRANITE_FFMPEG + ycbcr_pipelines.clear(); +#endif + } + + bool alive(Vulkan::WSI &) override + { + return frames < max_frames; + } + + void poll_input() override + { + std::lock_guard holder{get_input_tracker().get_lock()}; + get_input_tracker().dispatch_current_state(get_frame_timer().get_frame_time()); + } + + void poll_input_async(Granite::InputTrackerHandler *override_handler) override + { + std::lock_guard holder{get_input_tracker().get_lock()}; + get_input_tracker().dispatch_current_state(0.0, override_handler); + } + + void enable_png_readback(std::string base_path) + { + png_readback = std::move(base_path); + } + + std::vector get_instance_extensions() override + { + return {}; + } + + VkSurfaceKHR create_surface(VkInstance, VkPhysicalDevice) override + { + return VK_NULL_HANDLE; + } + + uint32_t get_surface_width() override + { + return width; + } + + uint32_t get_surface_height() override + { + return height; + } + + void notify_resize(unsigned width_, unsigned height_) + { + resize = true; + width = width_; + height = height_; + } + + void set_max_frames(unsigned max_frames_) + { + max_frames = max_frames_; + } + + bool has_external_swapchain() override + { + return true; + } + + bool init(unsigned width_, unsigned height_) + { + width = width_; + height = height_; + if (!Context::init_loader(nullptr)) + { + LOGE("Failed to initialize Vulkan loader.\n"); + return false; + } + + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + { + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Stopped); + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Paused); + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Running); + } + + return true; + } + + bool init_headless(Application *app_) + { + app = app_; + + auto context = Util::make_handle(); + + Context::SystemHandles system_handles; + system_handles.filesystem = GRANITE_FILESYSTEM(); + system_handles.thread_group = GRANITE_THREAD_GROUP(); + system_handles.timeline_trace_file = system_handles.thread_group->get_timeline_trace_file(); + system_handles.asset_manager = GRANITE_ASSET_MANAGER(); + context->set_system_handles(system_handles); + + context->set_num_thread_indices(GRANITE_THREAD_GROUP()->get_num_threads() + 1); + const char *khr_surface = VK_KHR_SURFACE_EXTENSION_NAME; + const char *khr_swapchain = VK_KHR_SWAPCHAIN_EXTENSION_NAME; + + auto name = app->get_name(); + if (name.empty()) + name = Path::basename(Path::get_executable_path()); + VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; + app_info.pEngineName = "Granite"; + app_info.pApplicationName = name.empty() ? "Granite" : name.c_str(); + app_info.apiVersion = VK_API_VERSION_1_1; + context->set_application_info(&app_info); + + if (!context->init_instance_and_device(&khr_surface, 1, &khr_swapchain, 1)) + return false; + if (!app->init_wsi(std::move(context))) + return false; + + auto &device = app->get_wsi().get_device(); + + auto info = ImageCreateInfo::render_target(width, height, VK_FORMAT_R8G8B8A8_SRGB); + info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + info.misc |= Vulkan::IMAGE_MISC_MUTABLE_SRGB_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + BufferCreateInfo readback = {}; + readback.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + readback.domain = BufferDomain::CachedHost; + readback.size = width * height * sizeof(uint32_t); + + for (unsigned i = 0; i < SwapchainImages; i++) + { + swapchain_images.push_back(device.create_image(info, nullptr)); + readback_buffers.push_back(device.create_buffer(readback, nullptr)); + acquire_semaphore.emplace_back(nullptr); + } + + // Target present layouts to be more accurate for timing in case PRESENT_SRC forces decompress, + // and also makes sure pipeline caches are valid w.r.t render passes. + for (auto &swap : swapchain_images) + swap->set_swapchain_layout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + + app->get_wsi().init_external_swapchain(swapchain_images); + return true; + } + +#ifdef HAVE_GRANITE_FFMPEG + void init_headless_recording(std::string path) + { +#ifndef HAVE_GRANITE_RENDERER + LOGE("Need to include system handles in build to encode.\n"); + return; +#endif + + video_encode_path = std::move(path); + VideoEncoder::Options enc_opts = {}; + enc_opts.width = width; + enc_opts.height = height; + + double frame_rate = std::round(1.0 / time_step); + enc_opts.frame_timebase.num = 1; + enc_opts.frame_timebase.den = int(frame_rate); + +#ifdef HAVE_GRANITE_AUDIO + enc_opts.walltime_to_pts = true; + record_stream.reset(Audio::create_default_audio_record_backend("headless", 44100.0f, 2)); + if (record_stream) + encoder.set_audio_record_stream(record_stream.get()); +#endif + + if (!encoder.init(&app->get_wsi().get_device(), video_encode_path.c_str(), enc_opts)) + { + LOGE("Failed to initialize encoder.\n"); + video_encode_path.clear(); + } + +#ifdef HAVE_GRANITE_RENDERER + for (unsigned i = 0; i < SwapchainImages; i++) + { + auto &device = app->get_wsi().get_device(); + FFmpegEncode::Shaders<> shaders; + + shaders.scaler = device.get_shader_manager().register_compute( + "builtin://shaders/util/scaler.comp")->register_variant({})->get_program(); + ycbcr_pipelines.push_back(encoder.create_ycbcr_pipeline(shaders)); + } +#endif + +#ifdef HAVE_GRANITE_AUDIO + record_stream->start(); +#endif + } +#endif + + void set_time_step(double t) + { + time_step = t; + } + + void begin_frame() + { + auto &wsi = app->get_wsi(); + wsi.set_external_frame(frame_index, std::move(acquire_semaphore[frame_index]), time_step); + acquire_semaphore[frame_index] = {}; + } + + void end_frame() + { + auto &wsi = app->get_wsi(); + auto &device = wsi.get_device(); + auto release_semaphore = wsi.consume_external_release_semaphore(); + + if (release_semaphore && release_semaphore->get_semaphore() != VK_NULL_HANDLE) + { + if (swapchain_tasks[frame_index]) + { + swapchain_tasks[frame_index]->wait(); + swapchain_tasks[frame_index].reset(); + } + + acquire_semaphore[frame_index] = {}; + + if (!next_readback_path.empty() || !png_readback.empty()) + { + OwnershipTransferInfo transfer_info = {}; + transfer_info.old_queue = wsi.get_current_present_queue_type(); + transfer_info.new_queue = CommandBuffer::Type::AsyncTransfer; + transfer_info.old_image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + transfer_info.new_image_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + transfer_info.dst_pipeline_stage = VK_PIPELINE_STAGE_2_COPY_BIT; + transfer_info.dst_access = VK_ACCESS_TRANSFER_READ_BIT; + auto cmd = request_command_buffer_with_ownership_transfer(device, *swapchain_images[frame_index], + transfer_info, release_semaphore); + + cmd->copy_image_to_buffer(*readback_buffers[frame_index], *swapchain_images[frame_index], + 0, {}, {width, height, 1}, + 0, 0, {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}); + + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_HOST_BIT, VK_ACCESS_HOST_READ_BIT); + + Fence readback_fence; + device.submit(cmd, &readback_fence, 1, &acquire_semaphore[frame_index]); + + if (!next_readback_path.empty()) + { + swapchain_tasks[frame_index] = GRANITE_THREAD_GROUP()->create_task( + [this, readback_fence, index = frame_index, frame = this->frames, p = std::make_unique(next_readback_path)]() mutable { + readback_fence->wait(); + dump_frame_single(*p, frame, index); + }); + next_readback_path.clear(); + } + else + { + swapchain_tasks[frame_index] = GRANITE_THREAD_GROUP()->create_task( + [this, readback_fence, index = frame_index, frame = this->frames]() mutable { + readback_fence->wait(); + dump_frame(frame, index); + }); + } + } +#ifdef HAVE_GRANITE_FFMPEG + else if (!video_encode_path.empty()) + { + auto pts = encoder.sample_realtime_pts(); + + OwnershipTransferInfo transfer_info = {}; + transfer_info.old_queue = wsi.get_current_present_queue_type(); + transfer_info.new_queue = CommandBuffer::Type::AsyncCompute; + transfer_info.old_image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + transfer_info.new_image_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + transfer_info.dst_pipeline_stage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + transfer_info.dst_access = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT; + auto cmd = request_command_buffer_with_ownership_transfer(device, *swapchain_images[frame_index], + transfer_info, release_semaphore); + + encoder.process_rgb(*cmd, ycbcr_pipelines[frame_index], swapchain_images[frame_index]->get_view()); + encoder.submit_process_rgb(cmd, ycbcr_pipelines[frame_index]); + + acquire_semaphore[frame_index] = device.request_semaphore(VK_SEMAPHORE_TYPE_BINARY); + device.submit_empty(CommandBuffer::Type::AsyncCompute, nullptr, acquire_semaphore[frame_index].get()); + + swapchain_tasks[frame_index] = GRANITE_THREAD_GROUP()->create_task( + [this, index = frame_index, pts]() mutable { + if (!encoder.encode_frame(ycbcr_pipelines[index], pts)) + LOGE("Failed to push frame to encoder.\n"); + }); + } +#endif + else + { + // Do nothing. + acquire_semaphore[frame_index] = std::move(release_semaphore); + } + + if (swapchain_tasks[frame_index]) + { + swapchain_tasks[frame_index]->set_desc("application-headless-readback"); + swapchain_tasks[frame_index]->set_task_class(TaskClass::Background); + + if (last_task_dependency) + GRANITE_THREAD_GROUP()->add_dependency(*swapchain_tasks[frame_index], *last_task_dependency); + + // Add a dummy task that only serves to chain dependencies. + last_task_dependency = GRANITE_THREAD_GROUP()->create_task(); + last_task_dependency->set_task_class(TaskClass::Background); + GRANITE_THREAD_GROUP()->add_dependency(*last_task_dependency, *swapchain_tasks[frame_index]); + swapchain_tasks[frame_index]->flush(); + } + } + + release_semaphore = {}; + frame_index = (frame_index + 1) % SwapchainImages; + frames++; + } + + void set_next_readback(std::string path) + { + next_readback_path = std::move(path); + } + + void wait_threads() + { + GRANITE_THREAD_GROUP()->wait_idle(); + } + +private: + unsigned width = 0; + unsigned height = 0; + unsigned frames = 0; + unsigned max_frames = UINT_MAX; + unsigned frame_index = 0; + double time_step = 0.01; + std::string png_readback; + std::string video_encode_path; + enum { SwapchainImages = 4 }; + +#ifdef HAVE_GRANITE_AUDIO + std::unique_ptr record_stream; +#endif + + std::vector swapchain_images; + std::vector readback_buffers; + std::vector acquire_semaphore; + std::string next_readback_path; + TaskGroupHandle swapchain_tasks[SwapchainImages]; + TaskGroupHandle last_task_dependency; + +#ifdef HAVE_GRANITE_FFMPEG + VideoEncoder encoder; + std::vector ycbcr_pipelines; +#endif + + void dump_frame_single(const std::string &path, unsigned frame, unsigned index) + { + auto &wsi = app->get_wsi(); + auto &device = wsi.get_device(); + + LOGI("Dumping frame: %u (index: %u)\n", frame, index); + + auto *ptr = static_cast(device.map_host_buffer(*readback_buffers[index], MEMORY_ACCESS_READ_WRITE_BIT)); + for (unsigned i = 0; i < width * height; i++) + ptr[i] |= 0xff000000u; + + if (!stbi_write_png(path.c_str(), width, height, 4, ptr, width * 4)) + LOGE("Failed to write PNG to disk.\n"); + device.unmap_host_buffer(*readback_buffers[index], MEMORY_ACCESS_READ_WRITE_BIT); + } + + void dump_frame(unsigned frame, unsigned index) + { + char buffer[64]; + sprintf(buffer, "_%05u.png", frame); + auto path = png_readback + buffer; + dump_frame_single(path, frame, index); + } + + Application *app = nullptr; +}; +} + +static void print_help() +{ + LOGI("[--png-path ] [--stat ]\n" + "[--fs-assets ] [--fs-cache ] [--fs-builtin ]\n" + "[--video-encode-path ]\n" + "[--png-reference-path ] [--frames ] [--width ] [--height ] [--time-step ].\n"); +} + +namespace Granite +{ +int application_main_headless( + bool (*query_application_interface)(ApplicationQuery, void *, size_t), + Application *(*create_application)(int, char **), + int argc, char *argv[]) +{ + if (argc < 1) + return 1; + + struct Args + { + std::string png_path; + std::string video_encode_path; + std::string png_reference_path; + std::string stat; + std::string assets; + std::string cache; + std::string builtin; + unsigned max_frames = UINT_MAX; + unsigned width = 1280; + unsigned height = 720; + double time_step = 0.01; + } args; + + CLICallbacks cbs; + cbs.add("--frames", [&](CLIParser &parser) { args.max_frames = parser.next_uint(); }); + cbs.add("--width", [&](CLIParser &parser) { args.width = parser.next_uint(); }); + cbs.add("--height", [&](CLIParser &parser) { args.height = parser.next_uint(); }); + cbs.add("--time-step", [&](CLIParser &parser) { args.time_step = parser.next_double(); }); + cbs.add("--png-path", [&](CLIParser &parser) { args.png_path = parser.next_string(); }); + cbs.add("--png-reference-path", [&](CLIParser &parser) { args.png_reference_path = parser.next_string(); }); + cbs.add("--video-encode-path", [&](CLIParser &parser) { args.video_encode_path = parser.next_string(); }); + cbs.add("--fs-assets", [&](CLIParser &parser) { args.assets = parser.next_string(); }); + cbs.add("--fs-builtin", [&](CLIParser &parser) { args.builtin = parser.next_string(); }); + cbs.add("--fs-cache", [&](CLIParser &parser) { args.cache = parser.next_string(); }); + cbs.add("--stat", [&](CLIParser &parser) { args.stat = parser.next_string(); }); + cbs.add("--help", [](CLIParser &parser) + { + print_help(); + parser.end(); + }); + cbs.error_handler = [&]() { print_help(); }; + int exit_code; + + if (!Util::parse_cli_filtered(std::move(cbs), argc, argv, exit_code)) + return exit_code; + + ApplicationQueryDefaultManagerFlags flags{Global::MANAGER_FEATURE_DEFAULT_BITS}; + query_application_interface(ApplicationQuery::DefaultManagerFlags, &flags, sizeof(flags)); + Granite::Global::init(flags.manager_feature_flags); + + if (flags.manager_feature_flags & Global::MANAGER_FEATURE_FILESYSTEM_BIT) + { + if (!args.assets.empty()) + GRANITE_FILESYSTEM()->register_protocol("assets", std::make_unique(args.assets)); + if (!args.builtin.empty()) + GRANITE_FILESYSTEM()->register_protocol("builtin", std::make_unique(args.builtin)); + if (!args.cache.empty()) + GRANITE_FILESYSTEM()->register_protocol("cache", std::make_unique(args.cache)); + } + + auto app = std::unique_ptr(create_application(argc, argv)); + + if (app) + { + auto platform = std::make_unique(); + if (!platform->init(args.width, args.height)) + return 1; + + auto *p = platform.get(); + + if (!app->init_platform(std::move(platform))) + return 1; + + p->set_max_frames(args.max_frames); + p->set_time_step(args.time_step); + p->init_headless(app.get()); + + // Ensure all startup work is complete. + while (app->get_wsi().get_device().query_initialization_progress(Vulkan::Device::InitializationStage::Pipelines) < 100 && + app->poll()) + { + p->begin_frame(); + app->run_frame(); + p->end_frame(); + } + + if (!args.png_path.empty()) + p->enable_png_readback(args.png_path); + + if (!args.video_encode_path.empty()) + { +#ifdef HAVE_GRANITE_FFMPEG + p->init_headless_recording(args.video_encode_path); +#else + LOGE("FFmpeg is not enabled in build.\n"); +#endif + } + +#ifdef HAVE_GRANITE_AUDIO + Global::start_audio_system(); +#endif + + // Run warm-up frame. + if (app->poll()) + { + p->begin_frame(); + app->run_frame(); + p->end_frame(); + } + + p->wait_threads(); + app->get_wsi().get_device().wait_idle(); + app->get_wsi().get_device().timestamp_log_reset(); + + LOGI("=== Begin run ===\n"); + + auto start_time = get_current_time_nsecs(); + unsigned rendered_frames = 0; + while (app->poll()) + { + p->begin_frame(); + app->run_frame(); + p->end_frame(); + if (!args.video_encode_path.empty() || !args.png_path.empty()) + { + LOGI(" Queued frame %u (Total time = %.3f ms).\n", rendered_frames, + 1e-6 * double(get_current_time_nsecs() - start_time)); + } + rendered_frames++; + } + + p->wait_threads(); + app->get_wsi().get_device().wait_idle(); + auto end_time = get_current_time_nsecs(); + + LOGI("=== End run ===\n"); + + struct Report + { + std::string tag; + TimestampIntervalReport report; + }; + std::vector reports; + app->get_wsi().get_device().timestamp_log([&](const std::string &tag, const TimestampIntervalReport &report) { + reports.push_back({ tag, report }); + }); + app->get_wsi().get_device().timestamp_log_reset(); + + if (rendered_frames) + { + double usec = 1e-3 * double(end_time - start_time) / rendered_frames; + LOGI("Average frame time: %.3f usec\n", usec); + + if (!args.stat.empty()) + { + Document doc; + doc.SetObject(); + auto &allocator = doc.GetAllocator(); + + doc.AddMember("averageFrameTimeUs", usec, allocator); + doc.AddMember("gpu", StringRef(app->get_wsi().get_context().get_gpu_props().deviceName), allocator); + doc.AddMember("driverVersion", app->get_wsi().get_context().get_gpu_props().driverVersion, allocator); + + if (!reports.empty()) + { + Value report_objs(kObjectType); + for (auto &rep : reports) + { + Value report_obj(kObjectType); + report_obj.AddMember("timePerAccumulationUs", 1e6 * rep.report.time_per_accumulation, allocator); + report_obj.AddMember("timePerFrameContextUs", 1e6 * rep.report.time_per_frame_context, allocator); + report_obj.AddMember("accumulationsPerFrameContext", rep.report.accumulations_per_frame_context, allocator); + report_objs.AddMember(StringRef(rep.tag), report_obj, allocator); + } + doc.AddMember("performance", report_objs, allocator); + } + + StringBuffer buffer; + PrettyWriter writer(buffer); + doc.Accept(writer); + + if (!GRANITE_FILESYSTEM()->write_string_to_file(args.stat, buffer.GetString())) + LOGE("Failed to write stat file to disk.\n"); + } + } + + if (!args.png_reference_path.empty()) + { + p->set_next_readback(args.png_reference_path); + p->begin_frame(); + app->run_frame(); + p->end_frame(); + } + + p->wait_threads(); + +#ifdef HAVE_GRANITE_AUDIO + Global::stop_audio_system(); +#endif + + app.reset(); + Granite::Global::deinit(); + return 0; + } + else + return 1; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_headless_wrapper.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_headless_wrapper.cpp new file mode 100644 index 00000000..530d1d64 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_headless_wrapper.cpp @@ -0,0 +1,33 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "application_glue.hpp" + +namespace Granite +{ +int application_main( + bool (*query_application_interface)(ApplicationQuery, void *, size_t), + Application *(*create_application)(int, char **), int argc, char *argv[]) +{ + return application_main_headless(query_application_interface, create_application, argc, argv); +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_libretro.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_libretro.cpp new file mode 100644 index 00000000..1ff1cc40 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_libretro.cpp @@ -0,0 +1,441 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "application_libretro_utils.hpp" +#include "global_managers_init.hpp" +#include "application.hpp" +#include "application_wsi.hpp" +#include "muglm/muglm_impl.hpp" + +using namespace Granite; + +static Application *app; +static retro_environment_t environ_cb; +static retro_video_refresh_t video_cb; +static retro_audio_sample_batch_t audio_cb; +static retro_input_poll_t input_poll_cb; +static retro_input_state_t input_state_cb; + +static retro_usec_t last_frame_time; +static std::string application_name; +static std::string application_internal_resolution; + +static unsigned current_width; +static unsigned current_height; + +struct WSIPlatformLibretro : Granite::GraniteWSIPlatform +{ + VkSurfaceKHR create_surface(VkInstance, VkPhysicalDevice) override + { + return VK_NULL_HANDLE; + } + + std::vector get_instance_extensions() override + { + return {}; + } + + unsigned get_surface_width() override + { + return current_width; + } + + unsigned get_surface_height() override + { + return current_height; + } + + bool alive(Vulkan::WSI &) override + { + return true; + } + + void poll_input() override + { + std::lock_guard holder{get_input_tracker().get_lock()}; + input_poll_cb(); + + auto &tracker = get_input_tracker(); + const auto poll_key = [&](unsigned index, JoypadKey key, unsigned retro_key) { + tracker.joypad_key_state(index, key, + input_state_cb(index, RETRO_DEVICE_JOYPAD, 0, retro_key) + ? JoypadKeyState::Pressed : JoypadKeyState::Released); + }; + + const auto poll_axis = [&](unsigned index, JoypadAxis axis, unsigned retro_index, unsigned retro_id) { + tracker.joyaxis_state(index, axis, + clamp(input_state_cb(index, RETRO_DEVICE_ANALOG, + retro_index, retro_id) * (1.0f / 0x7fff), -1.0f, 1.0f)); + }; + + const auto poll_axis_button = [&](unsigned index, JoypadAxis axis, unsigned retro_key) { + tracker.joyaxis_state(index, axis, + input_state_cb(index, RETRO_DEVICE_JOYPAD, 0, retro_key) ? 1.0f : 0.0f); + }; + + tracker.enable_joypad(0, 0, 0); + tracker.enable_joypad(1, 0, 0); + for (unsigned i = 0; i < 2; i++) + { + poll_key(i, JoypadKey::Left, RETRO_DEVICE_ID_JOYPAD_LEFT); + poll_key(i, JoypadKey::Right, RETRO_DEVICE_ID_JOYPAD_RIGHT); + poll_key(i, JoypadKey::Up, RETRO_DEVICE_ID_JOYPAD_UP); + poll_key(i, JoypadKey::Down, RETRO_DEVICE_ID_JOYPAD_DOWN); + poll_key(i, JoypadKey::Select, RETRO_DEVICE_ID_JOYPAD_SELECT); + poll_key(i, JoypadKey::Start, RETRO_DEVICE_ID_JOYPAD_START); + poll_key(i, JoypadKey::LeftShoulder, RETRO_DEVICE_ID_JOYPAD_L); + poll_key(i, JoypadKey::LeftThumb, RETRO_DEVICE_ID_JOYPAD_L3); + poll_key(i, JoypadKey::RightShoulder, RETRO_DEVICE_ID_JOYPAD_R); + poll_key(i, JoypadKey::RightThumb, RETRO_DEVICE_ID_JOYPAD_R3); + poll_key(i, JoypadKey::South, RETRO_DEVICE_ID_JOYPAD_B); + poll_key(i, JoypadKey::East, RETRO_DEVICE_ID_JOYPAD_A); + poll_key(i, JoypadKey::North, RETRO_DEVICE_ID_JOYPAD_X); + poll_key(i, JoypadKey::West, RETRO_DEVICE_ID_JOYPAD_Y); + + poll_axis(i, JoypadAxis::LeftX, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X); + poll_axis(i, JoypadAxis::LeftY, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y); + poll_axis(i, JoypadAxis::RightX, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X); + poll_axis(i, JoypadAxis::RightY, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y); + + poll_axis_button(i, JoypadAxis::LeftTrigger, RETRO_DEVICE_ID_JOYPAD_L2); + poll_axis_button(i, JoypadAxis::RightTrigger, RETRO_DEVICE_ID_JOYPAD_R2); + } + + tracker.dispatch_current_state(app->get_platform().get_frame_timer().get_frame_time()); + } + + void poll_input_async(Granite::InputTrackerHandler *override_handler) override + { + std::lock_guard holder{get_input_tracker().get_lock()}; + get_input_tracker().dispatch_current_state(0.0, override_handler); + } + + bool has_external_swapchain() override + { + return true; + } +}; + +static retro_hw_render_callback hw_render; + +RETRO_API void retro_init(void) +{ + ApplicationQueryDefaultManagerFlags flags{Global::MANAGER_FEATURE_DEFAULT_BITS}; + query_application_interface(ApplicationQuery::DefaultManagerFlags, &flags, sizeof(flags)); + Global::init(flags.manager_feature_flags); +} + +RETRO_API void retro_deinit(void) +{ + Global::deinit(); +} + +static void setup_variables() +{ + application_internal_resolution = application_name + "_internal_resolution"; + + static const retro_variable variables[] = { + { application_internal_resolution.c_str(), "Internal resolution; 1280x720|640x360|1280x1024|1920x1080" }, + { nullptr, nullptr }, + }; + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, const_cast(variables)); +} + +static void query_variables() +{ + retro_variable var = { application_internal_resolution.c_str(), nullptr }; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + unsigned new_width, new_height; + if (sscanf(var.value, "%ux%u", &new_width, &new_height) == 2) + { + current_width = new_width; + current_height = new_height; + } + } +} + +RETRO_API void retro_set_environment(retro_environment_t cb) +{ + environ_cb = cb; + + retro_log_callback log_interface; + if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log_interface)) + Granite::libretro_log = log_interface.log; +} + +RETRO_API void retro_set_video_refresh(retro_video_refresh_t cb) +{ + video_cb = cb; +} + +RETRO_API void retro_set_audio_sample(retro_audio_sample_t) +{ +} + +RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) +{ + audio_cb = cb; +} + +RETRO_API void retro_set_input_poll(retro_input_poll_t cb) +{ + input_poll_cb = cb; +} + +RETRO_API void retro_set_input_state(retro_input_state_t cb) +{ + input_state_cb = cb; +} + +RETRO_API unsigned retro_api_version(void) +{ + return RETRO_API_VERSION; +} + +RETRO_API void retro_get_system_info(struct retro_system_info *info) +{ + info->block_extract = false; + info->library_name = "Sample Scene Viewer"; + info->library_version = "0.0"; + info->need_fullpath = true; + info->valid_extensions = "gltf|glb|scene"; +} + +RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info) +{ + info->timing.fps = 60.0; + info->timing.sample_rate = 44100.0; + info->geometry.aspect_ratio = float(current_width) / current_height; + info->geometry.base_height = current_width; + info->geometry.base_width = current_height; + info->geometry.max_width = current_width; + info->geometry.max_height = current_height; +} + +RETRO_API void retro_set_controller_port_device(unsigned, unsigned) +{ +} + +RETRO_API void retro_reset(void) +{ +} + +static void check_variables() +{ + bool updated = false; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) + { + unsigned old_width = current_width; + unsigned old_height = current_height; + query_variables(); + if (old_width != current_width || old_height != current_height) + { + retro_system_av_info av_info; + retro_get_system_av_info(&av_info); + libretro_set_swapchain_size(current_width, current_height); + if (!environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &av_info)) + { + current_width = old_width; + current_height = old_height; + libretro_set_swapchain_size(current_width, current_height); + } + } + } +} + +RETRO_API void retro_run(void) +{ + if (!app) + { + // The application is dead, force a shutdown. + input_poll_cb(); + environ_cb(RETRO_ENVIRONMENT_SHUTDOWN, nullptr); + return; + } + + check_variables(); + + // Begin frame. + libretro_begin_frame(app->get_wsi(), last_frame_time); + + // Run frame. + app->poll(); + app->run_frame(); + + // Present. + libretro_end_frame(video_cb, app->get_wsi()); +} + +RETRO_API size_t retro_serialize_size(void) +{ + return 0; +} + +RETRO_API bool retro_serialize(void *, size_t) +{ + return false; +} + +RETRO_API bool retro_unserialize(const void *, size_t) +{ + return false; +} + +RETRO_API void retro_cheat_reset(void) +{ +} + +RETRO_API void retro_cheat_set(unsigned, bool, const char *) +{ +} + +static void context_destroy(void) +{ + libretro_context_destroy(app); +} + +static void context_reset(void) +{ + retro_hw_render_interface_vulkan *vulkan; + if (!environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, &vulkan)) + { + Granite::libretro_log(RETRO_LOG_ERROR, "Didn't get Vulkan HW interface."); + delete app; + app = nullptr; + return; + } + + if (!libretro_context_reset(vulkan, *app)) + { + Granite::libretro_log(RETRO_LOG_ERROR, "Failed to reset Vulkan context."); + delete app; + app = nullptr; + return; + } +} + +static void frame_time_callback(retro_usec_t usecs) +{ + last_frame_time = usecs; +} + +RETRO_API bool retro_load_game(const struct retro_game_info *info) +{ + char *argv[] = { + const_cast("libretro-granite"), + const_cast(info->path), + nullptr, + }; + + app = Granite::application_create(2, argv); + if (!app) + { + Granite::libretro_log(RETRO_LOG_ERROR, "Failed to load scene: %s\n", info->path); + return false; + } + + current_width = app->get_default_width(); + current_height = app->get_default_height(); + + if (!app->init_platform(std::make_unique())) + { + Granite::libretro_log(RETRO_LOG_ERROR, "Failed to init platform."); + delete app; + return false; + } + + application_name = app->get_name(); + libretro_set_application_info(application_name.c_str(), app->get_version()); + + setup_variables(); + query_variables(); + libretro_set_swapchain_size(current_width, current_height); + + hw_render.context_destroy = context_destroy; + hw_render.context_reset = context_reset; + hw_render.context_type = RETRO_HW_CONTEXT_VULKAN; + hw_render.version_major = 1; + hw_render.version_minor = 0; + if (!environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) + { + Granite::libretro_log(RETRO_LOG_ERROR, "SET_HW_RENDER failed, this core cannot run.\n"); + return false; + } + + if (!libretro_load_game(environ_cb)) + { + Granite::libretro_log(RETRO_LOG_ERROR, "Failed to set up Vulkan application, this core cannot run.\n"); + return false; + } + + retro_frame_time_callback frame_cb = {}; + frame_cb.callback = frame_time_callback; + frame_cb.reference = (1000000 + 30) / 60; + last_frame_time = frame_cb.reference; + environ_cb(RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK, &frame_cb); + + return true; +} + +RETRO_API bool retro_load_game_special(unsigned, const struct retro_game_info *, size_t) +{ + return false; +} + +RETRO_API void retro_unload_game(void) +{ + libretro_unload_game(); + delete app; + app = nullptr; +} + +RETRO_API unsigned retro_get_region(void) +{ + return RETRO_REGION_NTSC; +} + +RETRO_API void *retro_get_memory_data(unsigned) +{ + return nullptr; +} + +RETRO_API size_t retro_get_memory_size(unsigned) +{ + return 0; +} + +namespace Granite +{ +void application_dummy() +{ +} + +// Alternatively, make sure this is linked in. +// Implementation is here to trick a linker to always let main() in static library work. +void application_setup_default_filesystem(const char *default_asset_directory) +{ + auto *filesystem = GRANITE_FILESYSTEM(); + if (filesystem) + Filesystem::setup_default_filesystem(filesystem, default_asset_directory); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_libretro_utils.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_libretro_utils.cpp new file mode 100644 index 00000000..50d2220b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_libretro_utils.cpp @@ -0,0 +1,403 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "application_libretro_utils.hpp" +#include "application.hpp" +#include "application_events.hpp" +#include "thread_group.hpp" +#include "asset_manager.hpp" +#include "context.hpp" + +namespace Granite +{ +retro_log_printf_t libretro_log; +static retro_hw_render_interface_vulkan *vulkan_interface; +static retro_hw_render_context_negotiation_interface_vulkan vulkan_negotiation; +static Vulkan::ContextHandle vulkan_context; +static Vulkan::ImageViewHandle swapchain_unorm_view; +static Vulkan::ImageHandle swapchain_image; +static retro_vulkan_image swapchain_image_info; +static bool can_dupe = false; +static std::string application_name; +static unsigned application_version; + +static unsigned swapchain_width; +static unsigned swapchain_height; +static unsigned swapchain_frame_index; +static Vulkan::Semaphore acquire_semaphore; + +static VkApplicationInfo vulkan_app = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, + nullptr, + nullptr, 0, + "Granite", + 0, + VK_API_VERSION_1_1, +}; + +void libretro_set_swapchain_size(unsigned width, unsigned height) +{ + swapchain_width = width; + swapchain_height = height; +} + +void libretro_set_application_info(const char *name, unsigned version) +{ + application_name = name; + application_version = version; + vulkan_app.pApplicationName = application_name.c_str(); + vulkan_app.applicationVersion = application_version; +} + +bool libretro_create_device( + struct retro_vulkan_context *context, + VkInstance instance, + VkPhysicalDevice gpu, + VkSurfaceKHR surface, + PFN_vkGetInstanceProcAddr get_instance_proc_addr, + const char **required_device_extensions, + unsigned num_required_device_extensions, + const char **, unsigned, // Deprecated. + const VkPhysicalDeviceFeatures *required_features) +{ + if (!Vulkan::Context::init_loader(get_instance_proc_addr)) + return false; + + vulkan_context = Util::make_handle(); + Vulkan::Context::SystemHandles system_handles; + system_handles.filesystem = GRANITE_FILESYSTEM(); + system_handles.thread_group = GRANITE_THREAD_GROUP(); + system_handles.asset_manager = GRANITE_ASSET_MANAGER(); + system_handles.timeline_trace_file = system_handles.thread_group->get_timeline_trace_file(); + vulkan_context->set_system_handles(system_handles); + vulkan_context->set_num_thread_indices(GRANITE_THREAD_GROUP()->get_num_threads() + 1); + if (!vulkan_context->init_device_from_instance(instance, gpu, surface, required_device_extensions, num_required_device_extensions, + required_features)) + { + return false; + } + + vulkan_context->release_device(); + context->gpu = vulkan_context->get_gpu(); + context->device = vulkan_context->get_device(); + context->presentation_queue = vulkan_context->get_queue_info().queues[Vulkan::QUEUE_INDEX_GRAPHICS]; + context->presentation_queue_family_index = vulkan_context->get_queue_info().family_indices[Vulkan::QUEUE_INDEX_GRAPHICS]; + context->queue = vulkan_context->get_queue_info().queues[Vulkan::QUEUE_INDEX_GRAPHICS]; + context->queue_family_index = vulkan_context->get_queue_info().family_indices[Vulkan::QUEUE_INDEX_GRAPHICS]; + return true; +} + +static VkInstance libretro_create_instance( + PFN_vkGetInstanceProcAddr get_instance_proc_addr, + const VkApplicationInfo *app, + retro_vulkan_create_instance_wrapper_t create_instance_wrapper, + void *opaque) +{ + if (!Vulkan::Context::init_loader(get_instance_proc_addr)) + return VK_NULL_HANDLE; + + vulkan_context = Util::make_handle(); + Vulkan::Context::SystemHandles system_handles; + system_handles.filesystem = GRANITE_FILESYSTEM(); + system_handles.thread_group = GRANITE_THREAD_GROUP(); + system_handles.asset_manager = GRANITE_ASSET_MANAGER(); + system_handles.timeline_trace_file = system_handles.thread_group->get_timeline_trace_file(); + + vulkan_context->set_application_info(app); + vulkan_context->set_system_handles(system_handles); + vulkan_context->set_num_thread_indices(GRANITE_THREAD_GROUP()->get_num_threads() + 1); + + struct Factory final : Vulkan::InstanceFactory + { + VkInstance create_instance(const VkInstanceCreateInfo *info) override + { + return wrapper(opaque, info); + } + + retro_vulkan_create_instance_wrapper_t wrapper = nullptr; + void *opaque = nullptr; + } factory; + + factory.wrapper = create_instance_wrapper; + factory.opaque = opaque; + vulkan_context->set_instance_factory(&factory); + + if (!vulkan_context->init_instance(nullptr, 0)) + { + vulkan_context.reset(); + return VK_NULL_HANDLE; + } + + vulkan_context->release_instance(); + return vulkan_context->get_instance(); +} + +static bool libretro_create_device2( + struct retro_vulkan_context *context, + VkInstance instance, + VkPhysicalDevice gpu, + VkSurfaceKHR surface, + PFN_vkGetInstanceProcAddr get_instance_proc_addr, + retro_vulkan_create_device_wrapper_t create_device_wrapper, + void *opaque) +{ + // We are guaranteed that create_instance has been called here. + if (!vulkan_context) + return false; + + // Sanity check inputs. + if (vulkan_context->get_instance() != instance) + return false; + if (Vulkan::Context::get_instance_proc_addr() != get_instance_proc_addr) + return false; + + struct Factory final : Vulkan::DeviceFactory + { + VkDevice create_device(VkPhysicalDevice gpu, const VkDeviceCreateInfo *info) override + { + return wrapper(gpu, opaque, info); + } + + retro_vulkan_create_device_wrapper_t wrapper = nullptr; + void *opaque = nullptr; + } factory; + + factory.wrapper = create_device_wrapper; + factory.opaque = opaque; + vulkan_context->set_device_factory(&factory); + + if (!vulkan_context->init_device(gpu, surface, nullptr, 0)) + return false; + + vulkan_context->release_device(); + context->gpu = vulkan_context->get_gpu(); + context->device = vulkan_context->get_device(); + context->presentation_queue = vulkan_context->get_queue_info().queues[Vulkan::QUEUE_INDEX_GRAPHICS]; + context->presentation_queue_family_index = vulkan_context->get_queue_info().family_indices[Vulkan::QUEUE_INDEX_GRAPHICS]; + context->queue = vulkan_context->get_queue_info().queues[Vulkan::QUEUE_INDEX_GRAPHICS]; + context->queue_family_index = vulkan_context->get_queue_info().family_indices[Vulkan::QUEUE_INDEX_GRAPHICS]; + return true; +} + +void libretro_begin_frame(Vulkan::WSI &wsi, retro_usec_t frame_time) +{ + // Setup the external frame. + vulkan_interface->wait_sync_index(vulkan_interface->handle); + wsi.set_external_frame(swapchain_frame_index, std::move(acquire_semaphore), double(frame_time) * 1e-6); + acquire_semaphore = {}; + + swapchain_frame_index ^= 1; +} + +void libretro_end_frame(retro_video_refresh_t video_cb, Vulkan::WSI &wsi) +{ + // Present to libretro frontend. + auto signal_semaphore = wsi.get_device().request_semaphore(VK_SEMAPHORE_TYPE_BINARY); + vulkan_interface->set_signal_semaphore(vulkan_interface->handle, + signal_semaphore->get_semaphore()); + signal_semaphore->signal_external(); + + acquire_semaphore = wsi.consume_external_release_semaphore(); + if (acquire_semaphore && acquire_semaphore->get_semaphore() != VK_NULL_HANDLE) + { + vulkan_interface->set_image(vulkan_interface->handle, + &swapchain_image_info, + 1, &acquire_semaphore->get_semaphore(), + VK_QUEUE_FAMILY_IGNORED); + + // Lets us recycle the semaphore. + acquire_semaphore->wait_external(); + + video_cb(RETRO_HW_FRAME_BUFFER_VALID, swapchain_width, swapchain_height, 0); + can_dupe = true; + } + else + { + vulkan_interface->set_image(vulkan_interface->handle, + &swapchain_image_info, + 0, nullptr, + VK_QUEUE_FAMILY_IGNORED); + + if (!can_dupe) + { + // Need something to show ... Just clear the image to black and present that. + // This should only happen if we don't render to swapchain the very first frame, + // so performance doesn't really matter. + auto &device = wsi.get_device(); + auto cmd = device.request_command_buffer(); + cmd->image_barrier(*swapchain_image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, VK_PIPELINE_STAGE_2_CLEAR_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + cmd->clear_image(*swapchain_image, {}); + cmd->image_barrier(*swapchain_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_CLEAR_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + device.submit(cmd); + video_cb(RETRO_HW_FRAME_BUFFER_VALID, swapchain_width, swapchain_height, 0); + can_dupe = true; + } + else + { + video_cb(nullptr, swapchain_width, swapchain_height, 0); + } + } + + // Mark video_cb has having done work in our frame context. + wsi.get_device().submit_external(Vulkan::CommandBuffer::Type::Generic); + + acquire_semaphore = signal_semaphore; +} + +bool libretro_context_reset(retro_hw_render_interface_vulkan *vulkan, Granite::Application &app) +{ + vulkan_interface = vulkan; + if (vulkan->interface_type != RETRO_HW_RENDER_INTERFACE_VULKAN) + return false; + + if (vulkan->interface_version != RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION) + return false; + + if (!app.init_wsi(std::move(vulkan_context))) + return false; + + auto &device = app.get_wsi().get_device(); + device.set_queue_lock([vulkan]() { + vulkan->lock_queue(vulkan->handle); + }, + [vulkan]() { + vulkan->unlock_queue(vulkan->handle); + }); + + const unsigned num_swapchain_images = 2; + + Vulkan::ImageCreateInfo info = Vulkan::ImageCreateInfo::render_target(swapchain_width, swapchain_height, + VK_FORMAT_R8G8B8A8_SRGB); + info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + swapchain_image = device.create_image(info, nullptr); + swapchain_image->set_swapchain_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); + can_dupe = false; + + Vulkan::ImageViewCreateInfo view_info; + view_info.format = VK_FORMAT_R8G8B8A8_UNORM; + view_info.image = swapchain_image.get(); + swapchain_unorm_view = device.create_image_view(view_info); + + std::vector images; + for (unsigned i = 0; i < num_swapchain_images; i++) + images.push_back(swapchain_image); + + device.init_frame_contexts(2); + if (!app.get_wsi().init_external_swapchain(std::move(images))) + return false; + + // Setup the swapchain image info for the frontend. + swapchain_image_info.image_view = swapchain_unorm_view->get_view().view; + swapchain_image_info.image_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + swapchain_image_info.create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + swapchain_image_info.create_info.image = swapchain_unorm_view->get_image().get_image(); + swapchain_image_info.create_info.format = VK_FORMAT_R8G8B8A8_UNORM; + swapchain_image_info.create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + swapchain_image_info.create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + swapchain_image_info.create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + swapchain_image_info.create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + swapchain_image_info.create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + swapchain_image_info.create_info.subresourceRange.levelCount = 1; + swapchain_image_info.create_info.subresourceRange.layerCount = 1; + swapchain_image_info.create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + swapchain_frame_index = 0; + return true; +} + +void libretro_context_destroy(Granite::Application *app) +{ + swapchain_unorm_view.reset(); + swapchain_image.reset(); + acquire_semaphore.reset(); + + if (app) + app->teardown_wsi(); +} + +static const VkApplicationInfo *get_application_info(void) +{ + return &vulkan_app; +} + +bool libretro_load_game(retro_environment_t environ_cb) +{ + vulkan_negotiation.interface_type = RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN; + if (!environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT, &vulkan_negotiation)) + { + Granite::libretro_log(RETRO_LOG_WARN, "GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT failed, assuming v1 only.\n"); + vulkan_negotiation.interface_version = 1; + } + else if (vulkan_negotiation.interface_version == 0) + { + Granite::libretro_log(RETRO_LOG_ERROR, "Vulkan is not supported, this core cannot run.\n"); + } + else + { + Granite::libretro_log(RETRO_LOG_INFO, "GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT passed, exposing v2.\n"); + vulkan_negotiation.interface_version = 2; + } + + vulkan_negotiation.create_device = Granite::libretro_create_device; + vulkan_negotiation.create_device2 = Granite::libretro_create_device2; + vulkan_negotiation.create_instance = Granite::libretro_create_instance; + vulkan_negotiation.destroy_device = nullptr; + vulkan_negotiation.get_application_info = get_application_info; + + if (!environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE, &vulkan_negotiation)) + { + Granite::libretro_log(RETRO_LOG_ERROR, "SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE failed, this core cannot run.\n"); + return false; + } + + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + { + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Stopped); + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Paused); + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Running); + } + return true; +} + +void libretro_unload_game() +{ + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + { + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Paused); + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Stopped); + } +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_libretro_utils.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_libretro_utils.hpp new file mode 100644 index 00000000..92589bf4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_libretro_utils.hpp @@ -0,0 +1,71 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include "libretro.h" +#include "libretro_vulkan.h" +#include "application.hpp" + +// Various utilities to make writing a libretro Vulkan interface easier. +// The heavy lifting of WSI interfacing with the libretro frontend is implemented here. + +namespace Granite +{ +extern retro_log_printf_t libretro_log; + +bool libretro_create_device( + struct retro_vulkan_context *context, + VkInstance instance, + VkPhysicalDevice gpu, + VkSurfaceKHR surface, + PFN_vkGetInstanceProcAddr get_instance_proc_addr, + const char **required_device_extensions, + unsigned num_required_device_extensions, + const char **required_device_layers, + unsigned num_required_device_layers, + const VkPhysicalDeviceFeatures *required_features); + +// Takes effect next time the swapchain is recreated, on context_reset. +void libretro_set_swapchain_size(unsigned width, unsigned height); + +// Used in get_application_info. +void libretro_set_application_info(const char *name, unsigned version); + +// Called on context_reset HW_RENDER callback. +bool libretro_context_reset(retro_hw_render_interface_vulkan *vulkan, Granite::Application &app); + +// Called on context_destroy HW_RENDER callback. +void libretro_context_destroy(Granite::Application *app); + +// Called at the start of the frame. +void libretro_begin_frame(Vulkan::WSI &wsi, retro_usec_t frame_time); + +// Called at the end of the frame. +void libretro_end_frame(retro_video_refresh_t video_cb, Vulkan::WSI &wsi); + +// Called on retro_load_game. +bool libretro_load_game(retro_environment_t environ_cb); +// Called on retro_unload_game. +void libretro_unload_game(); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_null.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_null.cpp new file mode 100644 index 00000000..94090150 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_null.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "../application_glue.hpp" +#include + +namespace Granite +{ +int application_main( + bool (*query_application_interface)(ApplicationQuery, void *, size_t), + Application *(*create_application)(int, char **), int argc, char *argv[]) +{ + (void)query_application_interface; + (void)create_application; + return 0; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_sdl3.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_sdl3.cpp new file mode 100644 index 00000000..b3f218f4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/application_sdl3.cpp @@ -0,0 +1,856 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include +#include +#include + +#include "application.hpp" +#include "application_wsi.hpp" +#include "application_events.hpp" +#include "input.hpp" +#include "input_sdl.hpp" +#include "cli_parser.hpp" +#include "global_managers_init.hpp" +#include "timeline_trace_file.hpp" +#include "path_utils.hpp" +#include "thread_group.hpp" +#include "thread_id.hpp" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#ifdef __linux__ +#include +#endif + +namespace Granite +{ +static Key sdl_key_to_granite_key(SDL_Keycode key) +{ + if (key >= 'a' && key <= 'z') + return Key(int(Granite::Key::A) + (key - 'a')); + else if (key >= 'A' && key <= 'Z') + return Key(int(Granite::Key::A) + (key - 'A')); + +#define k(sdl, granite) case SDLK_##sdl: return Key::granite + switch (key) + { + k(LCTRL, LeftCtrl); + k(LALT, LeftAlt); + k(LSHIFT, LeftShift); + k(RETURN, Return); + k(SPACE, Space); + k(ESCAPE, Escape); + k(LEFT, Left); + k(RIGHT, Right); + k(UP, Up); + k(DOWN, Down); + k(0, _0); + k(1, _1); + k(2, _2); + k(3, _3); + k(4, _4); + k(5, _5); + k(6, _6); + k(7, _7); + k(8, _8); + k(9, _9); + default: + return Key::Unknown; + } +#undef k +} + +struct WSIPlatformSDL : GraniteWSIPlatform +{ +public: + struct Options + { + unsigned override_width = 0; + unsigned override_height = 0; + bool fullscreen = false; +#ifdef _WIN32 + bool threaded = true; +#else + bool threaded = false; +#endif + }; + + explicit WSIPlatformSDL(const Options &options_) + : options(options_) + { + } + + void run_gamepad_init() + { + Util::Timer tmp_timer; + tmp_timer.start(); + + if (!SDL_Init(SDL_INIT_GAMEPAD)) + { + LOGE("Failed to init gamepad.\n"); + return; + } + + LOGI("SDL_Init(GAMEPAD) took %.3f seconds async.\n", tmp_timer.end()); + + LOGI("Pushing task to main thread.\n"); + push_task_to_main_thread([this]() { + LOGI("Running task in main thread.\n"); + if (!pad.init(get_input_tracker(), [](std::function func) { func(); })) + LOGE("Failed to init gamepad tracker.\n"); + + gamepad_init_async.store(true, std::memory_order_release); + }); + } + + void kick_gamepad_init() + { + SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + // Adding gamepad events will make main loop spin without waiting. + SDL_SetHint(SDL_HINT_AUTO_UPDATE_JOYSTICKS, "0"); + + // Enumerating gamepads can be extremely slow in some cases. Do this async. + // Gamepad interface is very async friendly. + + gamepad_init_async = false; + + if (auto *tg = GRANITE_THREAD_GROUP()) + { + gamepad_init_task = tg->create_task([this]() { run_gamepad_init(); }); + gamepad_init_task->set_desc("SDL init gamepad"); + gamepad_init_task->set_task_class(TaskClass::Background); + gamepad_init_task->flush(); + } + else + run_gamepad_init(); + } + + bool init(const std::string &name, unsigned width_, unsigned height_) + { + request_tear_down.store(false); + width = width_; + height = height_; + + if (options.override_width) + width = options.override_width; + if (options.override_height) + height = options.override_height; + +#ifdef __linux__ + // RenderDoc doesn't support Wayland, and SDL3 uses Wayland by default. + // Opt in to X11 to avoid having to manually remember to pass down SDL_VIDEO_DRIVER=x11. + void *renderdoc_module = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD); + if (renderdoc_module) + { + LOGI("RenderDoc is loaded, disabling Wayland.\n"); + setenv("SDL_VIDEO_DRIVER", "x11", 0); + } +#endif + + Util::Timer tmp_timer; + tmp_timer.start(); + if (!SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO)) + { + LOGE("Failed to init SDL.\n"); + return false; + } + LOGI("SDL_Init took %.3f seconds.\n", tmp_timer.end()); + + kick_gamepad_init(); + + SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, false); + SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, false); + + if (!SDL_Vulkan_LoadLibrary(nullptr)) + { + LOGE("Failed to load Vulkan library.\n"); + return false; + } + + if (!Vulkan::Context::init_loader( + reinterpret_cast(SDL_Vulkan_GetVkGetInstanceProcAddr()))) + { + LOGE("Failed to initialize Vulkan loader.\n"); + return false; + } + + wake_event_type = SDL_RegisterEvents(1); + + application.name = name; + if (application.name.empty()) + application.name = Path::basename(Path::get_executable_path()); + + window = SDL_CreateWindow(application.name.empty() ? "SDL Window" : application.name.c_str(), + int(width), int(height), SDL_WINDOW_RESIZABLE | SDL_WINDOW_VULKAN); + if (!window) + { + LOGE("Failed to create SDL window.\n"); + return false; + } + + if (options.fullscreen) + toggle_fullscreen(); + + application.info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + application.info.pEngineName = "Granite"; + application.info.pApplicationName = application.name.empty() ? "Granite" : application.name.c_str(); + application.info.apiVersion = VK_API_VERSION_1_1; + + return true; + } + + const VkApplicationInfo *get_application_info() override + { + return &application.info; + } + + void begin_drop_event() override + { + push_task_to_main_thread([]() { + SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, true); + }); + } + + void show_message_box(const std::string &str, MessageType type) override + { + push_task_to_main_thread([this, str, type]() { + const char *title = nullptr; + Uint32 flags = 0; + switch (type) + { + case MessageType::Error: + flags = SDL_MESSAGEBOX_ERROR; + title = "Error"; + break; + + case MessageType::Warning: + flags = SDL_MESSAGEBOX_WARNING; + title = "Warning"; + break; + + case MessageType::Info: + flags = SDL_MESSAGEBOX_INFORMATION; + title = "Info"; + break; + } + + SDL_ShowSimpleMessageBox(flags, title, str.c_str(), window); + }); + } + + uintptr_t get_native_window() override + { +#ifdef _WIN32 + SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_LockProperties(props); + auto hwnd = static_cast(SDL_GetPointerProperty(props, "SDL.window.win32.hwnd", nullptr)); + SDL_UnlockProperties(props); + return reinterpret_cast(hwnd); +#else + return 0; +#endif + } + + void toggle_fullscreen() + { + bool is_fullscreen = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0; + + if (!is_fullscreen) + { + if (!SDL_SetWindowFullscreen(window, true)) + { + LOGE("Failed to toggle fullscreen.\n"); + } +#ifdef _WIN32 + else + { + SDL_PropertiesID props = SDL_GetWindowProperties(window); + SDL_LockProperties(props); + auto hwnd = static_cast(SDL_GetPointerProperty(props, "SDL.window.win32.hwnd", nullptr)); + SDL_UnlockProperties(props); + + push_task_to_async_thread([this, hwnd]() { + set_hmonitor(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY)); + }); + } +#endif + } + else + { +#ifdef _WIN32 + push_task_to_async_thread([this]() { + set_hmonitor(nullptr); + }); +#endif + SDL_SetWindowFullscreen(window, false); + } + } + + bool alive(Vulkan::WSI &) override + { + std::lock_guard holder{get_input_tracker().get_lock()}; + flush_deferred_input_events(); + process_events_async_thread(); + process_events_async_thread_non_pollable(); + return !request_tear_down.load(); + } + + void poll_input() override + { + if (!options.threaded && !iterate_message_loop()) + request_tear_down = true; + + std::lock_guard holder{get_input_tracker().get_lock()}; + flush_deferred_input_events(); + process_events_async_thread(); + + if (gamepad_init_async.load(std::memory_order_acquire)) + pad.update(get_input_tracker()); + get_input_tracker().dispatch_current_state(get_frame_timer().get_frame_time()); + } + + void poll_input_async(Granite::InputTrackerHandler *override_handler) override + { + std::lock_guard holder{get_input_tracker().get_lock()}; + begin_async_input_handling(); + { + process_events_async_thread(); + if (gamepad_init_async.load(std::memory_order_acquire)) + pad.update(get_input_tracker()); + } + end_async_input_handling(); + get_input_tracker().dispatch_current_state(0.0, override_handler); + } + + std::vector get_instance_extensions() override + { + uint32_t count; + const char * const *ext = SDL_Vulkan_GetInstanceExtensions(&count); + return { ext, ext + count }; + } + + VkSurfaceKHR create_surface(VkInstance instance, VkPhysicalDevice) override + { + VkSurfaceKHR surface = VK_NULL_HANDLE; + if (!SDL_Vulkan_CreateSurface(window, instance, nullptr, &surface)) + return VK_NULL_HANDLE; + + int actual_width, actual_height; + SDL_GetWindowSizeInPixels(window, &actual_width, &actual_height); + width = unsigned(actual_width); + height = unsigned(actual_height); + return surface; + } + + uint32_t get_surface_width() override + { + return width; + } + + uint32_t get_surface_height() override + { + return height; + } + + ~WSIPlatformSDL() + { + if (gamepad_init_task) + gamepad_init_task->wait(); + + if (window) + SDL_DestroyWindow(window); + + pad.close(); + SDL_Quit(); + } + + void block_until_wsi_forward_progress(Vulkan::WSI &wsi) override + { + if (options.threaded) + { + get_frame_timer().enter_idle(); + while (!resize && alive(wsi)) + process_events_async_thread_blocking(); + get_frame_timer().leave_idle(); + } + else + { + WSIPlatform::block_until_wsi_forward_progress(wsi); + } + } + + void notify_resize(unsigned width_, unsigned height_) + { + LOGI("Resize: %u x %u\n", width_, height_); + push_task_to_async_thread([=]() { + resize = true; + width = width_; + height = height_; + }); + } + + void notify_current_swapchain_dimensions(unsigned width_, unsigned height_) override + { + push_task_to_main_thread([=]() { + WSIPlatform::notify_current_swapchain_dimensions(width_, height_); + }); + } + + void set_window_title(const std::string &title) override + { + push_task_to_main_thread([=]() { + if (window) + SDL_SetWindowTitle(window, title.c_str()); + }); + } + + bool process_sdl_event(const SDL_Event &e) + { + if (e.type == wake_event_type) + { + LOGI("Processing events main thread.\n"); + process_events_main_thread(); + return true; + } + + const auto dispatcher = [this](std::function func) { + push_task_to_async_thread(std::move(func)); + }; + + if (pad.process_sdl_event(e, get_input_tracker(), dispatcher)) + return true; + + switch (e.type) + { + case SDL_EVENT_QUIT: + return false; + + case SDL_EVENT_WINDOW_RESIZED: + if (e.window.windowID == SDL_GetWindowID(window)) + notify_resize(e.window.data1, e.window.data2); + break; + + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: + if (e.button.windowID == SDL_GetWindowID(window)) + { + MouseButton btn; + if (e.button.button == SDL_BUTTON_LEFT) + btn = MouseButton::Left; + else if (e.button.button == SDL_BUTTON_MIDDLE) + btn = MouseButton::Middle; + else if (e.button.button == SDL_BUTTON_RIGHT) + btn = MouseButton::Right; + else + break; + + push_task_to_async_thread( + [this, btn, x = e.button.x, y = e.button.y, + pressed = e.type == SDL_EVENT_MOUSE_BUTTON_DOWN]() { + get_input_tracker().mouse_button_event(btn, x, y, pressed); + }); + } + break; + + case SDL_EVENT_WINDOW_MOUSE_ENTER: + if (e.window.windowID == SDL_GetWindowID(window)) + { + float x, y; + SDL_GetMouseState(&x, &y); + push_task_to_async_thread([this, x, y]() { + get_input_tracker().mouse_enter(x, y); + }); + } + break; + + case SDL_EVENT_WINDOW_MOUSE_LEAVE: + if (e.window.windowID == SDL_GetWindowID(window)) + { + push_task_to_async_thread([this]() { + get_input_tracker().mouse_leave(); + }); + } + break; + + case SDL_EVENT_MOUSE_MOTION: + if (e.motion.windowID == SDL_GetWindowID(window)) + { + push_task_to_async_thread([this, x = e.motion.x, y = e.motion.y]() { + get_input_tracker().mouse_move_event_absolute(x, y); + }); + } + break; + + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: + if (e.key.windowID == SDL_GetWindowID(window)) + { + KeyState state; + if (e.key.repeat) + state = KeyState::Repeat; + else if (e.type == SDL_EVENT_KEY_DOWN) + state = KeyState::Pressed; + else + state = KeyState::Released; + + if (state == KeyState::Pressed && e.key.key == SDLK_ESCAPE) + { + return false; + } + else if (state == KeyState::Pressed && e.key.key == SDLK_RETURN && + (e.key.mod & SDL_KMOD_ALT) != 0) + { + toggle_fullscreen(); + } + else if (state == KeyState::Pressed && tolower(e.key.key) == 'v' && + (e.key.mod & SDL_KMOD_LCTRL) != 0) + { + push_non_pollable_task_to_async_thread([c = clipboard]() mutable { + if (auto *manager = GRANITE_EVENT_MANAGER()) + manager->enqueue(std::move(c)); + }); + } + else + { + Key key = sdl_key_to_granite_key(e.key.key); + push_task_to_async_thread([=]() { + get_input_tracker().key_event(key, state); + }); + } + } + break; + + case SDL_EVENT_DROP_FILE: + if (e.drop.windowID == SDL_GetWindowID(window)) + { + std::string str = e.drop.data; + push_non_pollable_task_to_async_thread([s = std::move(str)]() mutable { + if (auto *manager = GRANITE_EVENT_MANAGER()) + manager->enqueue(std::move(s)); + }); + } + break; + + case SDL_EVENT_DROP_COMPLETE: + SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, false); + break; + + case SDL_EVENT_CLIPBOARD_UPDATE: + if (SDL_HasClipboardText()) + { + const char *text = SDL_GetClipboardText(); + if (text) + clipboard = text; + else + clipboard.clear(); + } + else + clipboard.clear(); + break; + + default: + break; + } + + return true; + } + + void run_message_loop() + { + SDL_Event e; + while (async_loop_alive && SDL_WaitEvent(&e)) + if (!process_sdl_event(e)) + break; + } + + bool iterate_message_loop() + { + SDL_Event e; + while (SDL_PollEvent(&e)) + if (!process_sdl_event(e)) + return false; + return true; + } + + void run_loop(Application *app) + { + auto ctx = Global::create_thread_context(); + + process_events_main_thread(); + + if (options.threaded) + { + async_loop_alive = true; + threaded_main_loop = std::thread(&WSIPlatformSDL::thread_main, this, app, std::move(ctx)); + + run_message_loop(); + notify_close(); + + if (threaded_main_loop.joinable()) + threaded_main_loop.join(); + } + else + thread_main(app, {}); + } + + static void dispatch_running_events() + { + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + { + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Stopped); + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Paused); + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Running); + } + } + + static void dispatch_stopped_events() + { + auto *em = GRANITE_EVENT_MANAGER(); + if (em) + { + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Paused); + em->dequeue_all_latched(ApplicationLifecycleEvent::get_type_id()); + em->enqueue_latched(ApplicationLifecycle::Stopped); + } + } + + void thread_main(Application *app, Global::GlobalManagersHandle ctx) + { + if (options.threaded) + { + // Set this up as an alternative main thread. + ThreadGroup::set_async_main_thread(); + Global::set_thread_context(*ctx); + Util::register_thread_index(0); + ctx.reset(); + } + + { + GRANITE_SCOPED_TIMELINE_EVENT("sdl-dispatch-running-events"); + dispatch_running_events(); + } + + { + { + GRANITE_SCOPED_TIMELINE_EVENT("sdl-start-audio-system"); + Granite::Global::start_audio_system(); + } + + while (app->poll()) + app->run_frame(); + Granite::Global::stop_audio_system(); + } + dispatch_stopped_events(); + push_task_to_main_thread([this]() { async_loop_alive = false; }); + } + + void notify_close() + { + request_tear_down.store(true); + } + +#ifdef _WIN32 + void set_hmonitor(HMONITOR monitor) + { + current_hmonitor = monitor; + } + + uintptr_t get_fullscreen_monitor() override + { + return reinterpret_cast(current_hmonitor); + } +#endif + + template + void push_task_to_async_thread(Op &&op) + { + push_task_to_list(task_list_async, std::forward(op)); + } + + template + void push_non_pollable_task_to_async_thread(Op &&op) + { + push_non_pollable_task_to_list(task_list_async, std::forward(op)); + } + +private: + SDL_Window *window = nullptr; + unsigned width = 0; + unsigned height = 0; + uint32_t wake_event_type = 0; + Options options; + std::string clipboard; + TaskGroupHandle gamepad_init_task; + std::atomic gamepad_init_async; + + struct + { + VkApplicationInfo info = {}; + std::string name; + } application; + + std::thread threaded_main_loop; + struct TaskList + { + std::mutex lock; + std::condition_variable cond; + std::vector> list; + std::vector> non_pollable_list; + } task_list_main, task_list_async; + + static void process_events_for_list(TaskList &list, bool blocking) + { + std::unique_lock holder{list.lock}; + + if (blocking) + while (list.list.empty()) + list.cond.wait(holder, [&list]() { return !list.list.empty(); }); + + for (auto &task : list.list) + task(); + list.list.clear(); + } + + template + void push_task_to_list(TaskList &list, Op &&op) + { + std::lock_guard holder{list.lock}; + list.list.emplace_back(std::forward(op)); + list.cond.notify_one(); + } + + template + void push_non_pollable_task_to_list(TaskList &list, Op &&op) + { + std::lock_guard holder{list.lock}; + list.non_pollable_list.emplace_back(std::forward(op)); + list.cond.notify_one(); + } + + void process_events_main_thread() + { + process_events_for_list(task_list_main, false); + } + + void process_events_main_thread_blocking() + { + process_events_for_list(task_list_main, true); + } + + void process_events_async_thread() + { + process_events_for_list(task_list_async, false); + } + + void process_events_async_thread_non_pollable() + { + std::unique_lock holder{task_list_async.lock}; + for (auto &task : task_list_async.non_pollable_list) + task(); + task_list_async.non_pollable_list.clear(); + } + + void process_events_async_thread_blocking() + { + process_events_for_list(task_list_async, true); + } + + InputTrackerSDL pad; + + template + void push_task_to_main_thread(Op &&op) + { + push_task_to_list(task_list_main, std::forward(op)); + SDL_Event wake_event = {}; + wake_event.type = wake_event_type; + SDL_PushEvent(&wake_event); + } + + std::atomic_bool request_tear_down; + bool async_loop_alive = false; + +#ifdef _WIN32 + HMONITOR current_hmonitor = nullptr; +#endif +}; +} + +namespace Granite +{ +int application_main( + bool (*query_application_interface)(ApplicationQuery, void *, size_t), + Application *(*create_application)(int, char **), int argc, char *argv[]) +{ + ApplicationQueryDefaultManagerFlags flags{Global::MANAGER_FEATURE_DEFAULT_BITS}; + query_application_interface(ApplicationQuery::DefaultManagerFlags, &flags, sizeof(flags)); + Global::init(flags.manager_feature_flags); + + WSIPlatformSDL::Options options; + int exit_code; + + Util::CLICallbacks cbs; + cbs.add("--fullscreen", [&](Util::CLIParser &) { options.fullscreen = true; }); + cbs.add("--width", [&](Util::CLIParser &parser) { options.override_width = parser.next_uint(); }); + cbs.add("--height", [&](Util::CLIParser &parser) { options.override_height = parser.next_uint(); }); + cbs.add("--thread-main-loop", [&](Util::CLIParser &) { options.threaded = true; }); + cbs.add("--no-thread-main-loop", [&](Util::CLIParser &) { options.threaded = false; }); + cbs.error_handler = [&]() { LOGE("Failed to parse CLI arguments for SDL.\n"); }; + if (!Util::parse_cli_filtered(std::move(cbs), argc, argv, exit_code)) + return exit_code; + + auto app = std::unique_ptr(create_application(argc, argv)); + int ret; + + if (app) + { + auto platform = std::make_unique(options); + auto *platform_handle = platform.get(); + + if (!platform->init(app->get_name(), app->get_default_width(), app->get_default_height())) + return 1; + + if (!app->init_platform(std::move(platform)) || !app->init_wsi()) + return 1; + + platform_handle->run_loop(app.get()); + + app.reset(); + ret = EXIT_SUCCESS; + } + else + { + ret = EXIT_FAILURE; + } + + Global::deinit(); + return ret; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/libretro/libretro.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/libretro/libretro.h new file mode 100644 index 00000000..3d6df6f9 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/libretro/libretro.h @@ -0,0 +1,3964 @@ +/* Copyright (C) 2010-2020 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro API header (libretro.h). + * --------------------------------------------------------------------------------------- + * + * 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. + */ + +#ifndef LIBRETRO_H__ +#define LIBRETRO_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __cplusplus +#if defined(_MSC_VER) && _MSC_VER < 1800 && !defined(SN_TARGET_PS3) +/* Hack applied for MSVC when compiling in C89 mode + * as it isn't C99-compliant. */ +#define bool unsigned char +#define true 1 +#define false 0 +#else +#include +#endif +#endif + +#ifndef RETRO_CALLCONV +# if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__) +# define RETRO_CALLCONV __attribute__((cdecl)) +# elif defined(_MSC_VER) && defined(_M_X86) && !defined(_M_X64) +# define RETRO_CALLCONV __cdecl +# else +# define RETRO_CALLCONV /* all other platforms only have one calling convention each */ +# endif +#endif + +#ifndef RETRO_API +# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) +# ifdef RETRO_IMPORT_SYMBOLS +# ifdef __GNUC__ +# define RETRO_API RETRO_CALLCONV __attribute__((__dllimport__)) +# else +# define RETRO_API RETRO_CALLCONV __declspec(dllimport) +# endif +# else +# ifdef __GNUC__ +# define RETRO_API RETRO_CALLCONV __attribute__((__dllexport__)) +# else +# define RETRO_API RETRO_CALLCONV __declspec(dllexport) +# endif +# endif +# else +# if defined(__GNUC__) && __GNUC__ >= 4 +# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default"))) +# else +# define RETRO_API RETRO_CALLCONV +# endif +# endif +#endif + +/* Used for checking API/ABI mismatches that can break libretro + * implementations. + * It is not incremented for compatible changes to the API. + */ +#define RETRO_API_VERSION 1 + +/* + * Libretro's fundamental device abstractions. + * + * Libretro's input system consists of some standardized device types, + * such as a joypad (with/without analog), mouse, keyboard, lightgun + * and a pointer. + * + * The functionality of these devices are fixed, and individual cores + * map their own concept of a controller to libretro's abstractions. + * This makes it possible for frontends to map the abstract types to a + * real input device, and not having to worry about binding input + * correctly to arbitrary controller layouts. + */ + +#define RETRO_DEVICE_TYPE_SHIFT 8 +#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1) +#define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base) + +/* Input disabled. */ +#define RETRO_DEVICE_NONE 0 + +/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo + * controller, but with additional L2/R2/L3/R3 buttons, similar to a + * PS1 DualShock. */ +#define RETRO_DEVICE_JOYPAD 1 + +/* The mouse is a simple mouse, similar to Super Nintendo's mouse. + * X and Y coordinates are reported relatively to last poll (poll callback). + * It is up to the libretro implementation to keep track of where the mouse + * pointer is supposed to be on the screen. + * The frontend must make sure not to interfere with its own hardware + * mouse pointer. + */ +#define RETRO_DEVICE_MOUSE 2 + +/* KEYBOARD device lets one poll for raw key pressed. + * It is poll based, so input callback will return with the current + * pressed state. + * For event/text based keyboard input, see + * RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. + */ +#define RETRO_DEVICE_KEYBOARD 3 + +/* LIGHTGUN device is similar to Guncon-2 for PlayStation 2. + * It reports X/Y coordinates in screen space (similar to the pointer) + * in the range [-0x8000, 0x7fff] in both axes, with zero being center and + * -0x8000 being out of bounds. + * As well as reporting on/off screen state. It features a trigger, + * start/select buttons, auxiliary action buttons and a + * directional pad. A forced off-screen shot can be requested for + * auto-reloading function in some games. + */ +#define RETRO_DEVICE_LIGHTGUN 4 + +/* The ANALOG device is an extension to JOYPAD (RetroPad). + * Similar to DualShock2 it adds two analog sticks and all buttons can + * be analog. This is treated as a separate device type as it returns + * axis values in the full analog range of [-0x7fff, 0x7fff], + * although some devices may return -0x8000. + * Positive X axis is right. Positive Y axis is down. + * Buttons are returned in the range [0, 0x7fff]. + * Only use ANALOG type when polling for analog values. + */ +#define RETRO_DEVICE_ANALOG 5 + +/* Abstracts the concept of a pointing mechanism, e.g. touch. + * This allows libretro to query in absolute coordinates where on the + * screen a mouse (or something similar) is being placed. + * For a touch centric device, coordinates reported are the coordinates + * of the press. + * + * Coordinates in X and Y are reported as: + * [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, + * and 0x7fff corresponds to the far right/bottom of the screen. + * The "screen" is here defined as area that is passed to the frontend and + * later displayed on the monitor. + * + * The frontend is free to scale/resize this screen as it sees fit, however, + * (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the + * game image, etc. + * + * To check if the pointer coordinates are valid (e.g. a touch display + * actually being touched), PRESSED returns 1 or 0. + * + * If using a mouse on a desktop, PRESSED will usually correspond to the + * left mouse button, but this is a frontend decision. + * PRESSED will only return 1 if the pointer is inside the game screen. + * + * For multi-touch, the index variable can be used to successively query + * more presses. + * If index = 0 returns true for _PRESSED, coordinates can be extracted + * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with + * index = 1, and so on. + * Eventually _PRESSED will return false for an index. No further presses + * are registered at this point. */ +#define RETRO_DEVICE_POINTER 6 + +/* Buttons for the RetroPad (JOYPAD). + * The placement of these is equivalent to placements on the + * Super Nintendo controller. + * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. + * Also used as id values for RETRO_DEVICE_INDEX_ANALOG_BUTTON */ +#define RETRO_DEVICE_ID_JOYPAD_B 0 +#define RETRO_DEVICE_ID_JOYPAD_Y 1 +#define RETRO_DEVICE_ID_JOYPAD_SELECT 2 +#define RETRO_DEVICE_ID_JOYPAD_START 3 +#define RETRO_DEVICE_ID_JOYPAD_UP 4 +#define RETRO_DEVICE_ID_JOYPAD_DOWN 5 +#define RETRO_DEVICE_ID_JOYPAD_LEFT 6 +#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 +#define RETRO_DEVICE_ID_JOYPAD_A 8 +#define RETRO_DEVICE_ID_JOYPAD_X 9 +#define RETRO_DEVICE_ID_JOYPAD_L 10 +#define RETRO_DEVICE_ID_JOYPAD_R 11 +#define RETRO_DEVICE_ID_JOYPAD_L2 12 +#define RETRO_DEVICE_ID_JOYPAD_R2 13 +#define RETRO_DEVICE_ID_JOYPAD_L3 14 +#define RETRO_DEVICE_ID_JOYPAD_R3 15 + +#define RETRO_DEVICE_ID_JOYPAD_MASK 256 + +/* Index / Id values for ANALOG device. */ +#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 +#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 +#define RETRO_DEVICE_INDEX_ANALOG_BUTTON 2 +#define RETRO_DEVICE_ID_ANALOG_X 0 +#define RETRO_DEVICE_ID_ANALOG_Y 1 + +/* Id values for MOUSE. */ +#define RETRO_DEVICE_ID_MOUSE_X 0 +#define RETRO_DEVICE_ID_MOUSE_Y 1 +#define RETRO_DEVICE_ID_MOUSE_LEFT 2 +#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 +#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 +#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 +#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 +#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7 +#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8 +#define RETRO_DEVICE_ID_MOUSE_BUTTON_4 9 +#define RETRO_DEVICE_ID_MOUSE_BUTTON_5 10 + +/* Id values for LIGHTGUN. */ +#define RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X 13 /*Absolute Position*/ +#define RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y 14 /*Absolute*/ +#define RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN 15 /*Status Check*/ +#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 +#define RETRO_DEVICE_ID_LIGHTGUN_RELOAD 16 /*Forced off-screen shot*/ +#define RETRO_DEVICE_ID_LIGHTGUN_AUX_A 3 +#define RETRO_DEVICE_ID_LIGHTGUN_AUX_B 4 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 +#define RETRO_DEVICE_ID_LIGHTGUN_SELECT 7 +#define RETRO_DEVICE_ID_LIGHTGUN_AUX_C 8 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP 9 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN 10 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT 11 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT 12 +/* deprecated */ +#define RETRO_DEVICE_ID_LIGHTGUN_X 0 /*Relative Position*/ +#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 /*Relative*/ +#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 /*Use Aux:A*/ +#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 /*Use Aux:B*/ +#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 /*Use Start*/ + +/* Id values for POINTER. */ +#define RETRO_DEVICE_ID_POINTER_X 0 +#define RETRO_DEVICE_ID_POINTER_Y 1 +#define RETRO_DEVICE_ID_POINTER_PRESSED 2 +#define RETRO_DEVICE_ID_POINTER_COUNT 3 + +/* Returned from retro_get_region(). */ +#define RETRO_REGION_NTSC 0 +#define RETRO_REGION_PAL 1 + +/* Id values for LANGUAGE */ +enum retro_language +{ + RETRO_LANGUAGE_ENGLISH = 0, + RETRO_LANGUAGE_JAPANESE = 1, + RETRO_LANGUAGE_FRENCH = 2, + RETRO_LANGUAGE_SPANISH = 3, + RETRO_LANGUAGE_GERMAN = 4, + RETRO_LANGUAGE_ITALIAN = 5, + RETRO_LANGUAGE_DUTCH = 6, + RETRO_LANGUAGE_PORTUGUESE_BRAZIL = 7, + RETRO_LANGUAGE_PORTUGUESE_PORTUGAL = 8, + RETRO_LANGUAGE_RUSSIAN = 9, + RETRO_LANGUAGE_KOREAN = 10, + RETRO_LANGUAGE_CHINESE_TRADITIONAL = 11, + RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 12, + RETRO_LANGUAGE_ESPERANTO = 13, + RETRO_LANGUAGE_POLISH = 14, + RETRO_LANGUAGE_VIETNAMESE = 15, + RETRO_LANGUAGE_ARABIC = 16, + RETRO_LANGUAGE_GREEK = 17, + RETRO_LANGUAGE_TURKISH = 18, + RETRO_LANGUAGE_SLOVAK = 19, + RETRO_LANGUAGE_PERSIAN = 20, + RETRO_LANGUAGE_HEBREW = 21, + RETRO_LANGUAGE_ASTURIAN = 22, + RETRO_LANGUAGE_FINNISH = 23, + RETRO_LANGUAGE_INDONESIAN = 24, + RETRO_LANGUAGE_SWEDISH = 25, + RETRO_LANGUAGE_UKRAINIAN = 26, + RETRO_LANGUAGE_CZECH = 27, + RETRO_LANGUAGE_CATALAN_VALENCIA = 28, + RETRO_LANGUAGE_CATALAN = 29, + RETRO_LANGUAGE_BRITISH_ENGLISH = 30, + RETRO_LANGUAGE_HUNGARIAN = 31, + RETRO_LANGUAGE_LAST, + + /* Ensure sizeof(enum) == sizeof(int) */ + RETRO_LANGUAGE_DUMMY = INT_MAX +}; + +/* Passed to retro_get_memory_data/size(). + * If the memory type doesn't apply to the + * implementation NULL/0 can be returned. + */ +#define RETRO_MEMORY_MASK 0xff + +/* Regular save RAM. This RAM is usually found on a game cartridge, + * backed up by a battery. + * If save game data is too complex for a single memory buffer, + * the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment + * callback can be used. */ +#define RETRO_MEMORY_SAVE_RAM 0 + +/* Some games have a built-in clock to keep track of time. + * This memory is usually just a couple of bytes to keep track of time. + */ +#define RETRO_MEMORY_RTC 1 + +/* System ram lets a frontend peek into a game systems main RAM. */ +#define RETRO_MEMORY_SYSTEM_RAM 2 + +/* Video ram lets a frontend peek into a game systems video RAM (VRAM). */ +#define RETRO_MEMORY_VIDEO_RAM 3 + +/* Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. */ +enum retro_key +{ + RETROK_UNKNOWN = 0, + RETROK_FIRST = 0, + RETROK_BACKSPACE = 8, + RETROK_TAB = 9, + RETROK_CLEAR = 12, + RETROK_RETURN = 13, + RETROK_PAUSE = 19, + RETROK_ESCAPE = 27, + RETROK_SPACE = 32, + RETROK_EXCLAIM = 33, + RETROK_QUOTEDBL = 34, + RETROK_HASH = 35, + RETROK_DOLLAR = 36, + RETROK_AMPERSAND = 38, + RETROK_QUOTE = 39, + RETROK_LEFTPAREN = 40, + RETROK_RIGHTPAREN = 41, + RETROK_ASTERISK = 42, + RETROK_PLUS = 43, + RETROK_COMMA = 44, + RETROK_MINUS = 45, + RETROK_PERIOD = 46, + RETROK_SLASH = 47, + RETROK_0 = 48, + RETROK_1 = 49, + RETROK_2 = 50, + RETROK_3 = 51, + RETROK_4 = 52, + RETROK_5 = 53, + RETROK_6 = 54, + RETROK_7 = 55, + RETROK_8 = 56, + RETROK_9 = 57, + RETROK_COLON = 58, + RETROK_SEMICOLON = 59, + RETROK_LESS = 60, + RETROK_EQUALS = 61, + RETROK_GREATER = 62, + RETROK_QUESTION = 63, + RETROK_AT = 64, + RETROK_LEFTBRACKET = 91, + RETROK_BACKSLASH = 92, + RETROK_RIGHTBRACKET = 93, + RETROK_CARET = 94, + RETROK_UNDERSCORE = 95, + RETROK_BACKQUOTE = 96, + RETROK_a = 97, + RETROK_b = 98, + RETROK_c = 99, + RETROK_d = 100, + RETROK_e = 101, + RETROK_f = 102, + RETROK_g = 103, + RETROK_h = 104, + RETROK_i = 105, + RETROK_j = 106, + RETROK_k = 107, + RETROK_l = 108, + RETROK_m = 109, + RETROK_n = 110, + RETROK_o = 111, + RETROK_p = 112, + RETROK_q = 113, + RETROK_r = 114, + RETROK_s = 115, + RETROK_t = 116, + RETROK_u = 117, + RETROK_v = 118, + RETROK_w = 119, + RETROK_x = 120, + RETROK_y = 121, + RETROK_z = 122, + RETROK_LEFTBRACE = 123, + RETROK_BAR = 124, + RETROK_RIGHTBRACE = 125, + RETROK_TILDE = 126, + RETROK_DELETE = 127, + + RETROK_KP0 = 256, + RETROK_KP1 = 257, + RETROK_KP2 = 258, + RETROK_KP3 = 259, + RETROK_KP4 = 260, + RETROK_KP5 = 261, + RETROK_KP6 = 262, + RETROK_KP7 = 263, + RETROK_KP8 = 264, + RETROK_KP9 = 265, + RETROK_KP_PERIOD = 266, + RETROK_KP_DIVIDE = 267, + RETROK_KP_MULTIPLY = 268, + RETROK_KP_MINUS = 269, + RETROK_KP_PLUS = 270, + RETROK_KP_ENTER = 271, + RETROK_KP_EQUALS = 272, + + RETROK_UP = 273, + RETROK_DOWN = 274, + RETROK_RIGHT = 275, + RETROK_LEFT = 276, + RETROK_INSERT = 277, + RETROK_HOME = 278, + RETROK_END = 279, + RETROK_PAGEUP = 280, + RETROK_PAGEDOWN = 281, + + RETROK_F1 = 282, + RETROK_F2 = 283, + RETROK_F3 = 284, + RETROK_F4 = 285, + RETROK_F5 = 286, + RETROK_F6 = 287, + RETROK_F7 = 288, + RETROK_F8 = 289, + RETROK_F9 = 290, + RETROK_F10 = 291, + RETROK_F11 = 292, + RETROK_F12 = 293, + RETROK_F13 = 294, + RETROK_F14 = 295, + RETROK_F15 = 296, + + RETROK_NUMLOCK = 300, + RETROK_CAPSLOCK = 301, + RETROK_SCROLLOCK = 302, + RETROK_RSHIFT = 303, + RETROK_LSHIFT = 304, + RETROK_RCTRL = 305, + RETROK_LCTRL = 306, + RETROK_RALT = 307, + RETROK_LALT = 308, + RETROK_RMETA = 309, + RETROK_LMETA = 310, + RETROK_LSUPER = 311, + RETROK_RSUPER = 312, + RETROK_MODE = 313, + RETROK_COMPOSE = 314, + + RETROK_HELP = 315, + RETROK_PRINT = 316, + RETROK_SYSREQ = 317, + RETROK_BREAK = 318, + RETROK_MENU = 319, + RETROK_POWER = 320, + RETROK_EURO = 321, + RETROK_UNDO = 322, + RETROK_OEM_102 = 323, + + RETROK_LAST, + + RETROK_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ +}; + +enum retro_mod +{ + RETROKMOD_NONE = 0x0000, + + RETROKMOD_SHIFT = 0x01, + RETROKMOD_CTRL = 0x02, + RETROKMOD_ALT = 0x04, + RETROKMOD_META = 0x08, + + RETROKMOD_NUMLOCK = 0x10, + RETROKMOD_CAPSLOCK = 0x20, + RETROKMOD_SCROLLOCK = 0x40, + + RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ +}; + +/* If set, this call is not part of the public libretro API yet. It can + * change or be removed at any time. */ +#define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 +/* Environment callback to be used internally in frontend. */ +#define RETRO_ENVIRONMENT_PRIVATE 0x20000 + +/* Environment commands. */ +#define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- + * Sets screen rotation of graphics. + * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, + * 270 degrees counter-clockwise respectively. + */ +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * -- + * NOTE: As of 2019 this callback is considered deprecated in favor of + * using core options to manage overscan in a more nuanced, core-specific way. + * + * Boolean value whether or not the implementation should use overscan, + * or crop away overscan. + */ +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 /* bool * -- + * Boolean value whether or not frontend supports frame duping, + * passing NULL to video frame callback. + */ + + /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), + * and reserved to avoid possible ABI clash. + */ + +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 /* const struct retro_message * -- + * Sets a message to be displayed in implementation-specific manner + * for a certain amount of 'frames'. + * Should not be used for trivial messages, which should simply be + * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a + * fallback, stderr). + */ +#define RETRO_ENVIRONMENT_SHUTDOWN 7 /* N/A (NULL) -- + * Requests the frontend to shutdown. + * Should only be used if game has a specific + * way to shutdown the game from a menu item or similar. + */ +#define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 + /* const unsigned * -- + * Gives a hint to the frontend how demanding this implementation + * is on a system. E.g. reporting a level of 2 means + * this implementation should run decently on all frontends + * of level 2 and up. + * + * It can be used by the frontend to potentially warn + * about too demanding implementations. + * + * The levels are "floating". + * + * This function can be called on a per-game basis, + * as certain games an implementation can play might be + * particularly demanding. + * If called, it should be called in retro_load_game(). + */ +#define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 + /* const char ** -- + * Returns the "system" directory of the frontend. + * This directory can be used to store system specific + * content such as BIOSes, configuration data, etc. + * The returned value can be NULL. + * If so, no such directory is defined, + * and it's up to the implementation to find a suitable directory. + * + * NOTE: Some cores used this folder also for "save" data such as + * memory cards, etc, for lack of a better place to put it. + * This is now discouraged, and if possible, cores should try to + * use the new GET_SAVE_DIRECTORY. + */ +#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 + /* const enum retro_pixel_format * -- + * Sets the internal pixel format used by the implementation. + * The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. + * This pixel format however, is deprecated (see enum retro_pixel_format). + * If the call returns false, the frontend does not support this pixel + * format. + * + * This function should be called inside retro_load_game() or + * retro_get_system_av_info(). + */ +#define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 + /* const struct retro_input_descriptor * -- + * Sets an array of retro_input_descriptors. + * It is up to the frontend to present this in a usable way. + * The array is terminated by retro_input_descriptor::description + * being set to NULL. + * This function can be called at any time, but it is recommended + * to call it as early as possible. + */ +#define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 + /* const struct retro_keyboard_callback * -- + * Sets a callback function used to notify core about keyboard events. + */ +#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 + /* const struct retro_disk_control_callback * -- + * Sets an interface which frontend can use to eject and insert + * disk images. + * This is used for games which consist of multiple images and + * must be manually swapped out by the user (e.g. PSX). + */ +#define RETRO_ENVIRONMENT_SET_HW_RENDER 14 + /* struct retro_hw_render_callback * -- + * Sets an interface to let a libretro core render with + * hardware acceleration. + * Should be called in retro_load_game(). + * If successful, libretro cores will be able to render to a + * frontend-provided framebuffer. + * The size of this framebuffer will be at least as large as + * max_width/max_height provided in get_av_info(). + * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or + * NULL to retro_video_refresh_t. + */ +#define RETRO_ENVIRONMENT_GET_VARIABLE 15 + /* struct retro_variable * -- + * Interface to acquire user-defined information from environment + * that cannot feasibly be supported in a multi-system way. + * 'key' should be set to a key which has already been set by + * SET_VARIABLES. + * 'data' will be set to a value or NULL. + */ +#define RETRO_ENVIRONMENT_SET_VARIABLES 16 + /* const struct retro_variable * -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterward it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * + * 'data' points to an array of retro_variable structs + * terminated by a { NULL, NULL } element. + * retro_variable::key should be namespaced to not collide + * with other implementations' keys. E.g. A core called + * 'foo' should use keys named as 'foo_option'. + * retro_variable::value should contain a human readable + * description of the key as well as a '|' delimited list + * of expected values. + * + * The number of possible options should be very limited, + * i.e. it should be feasible to cycle through options + * without a keyboard. + * + * First entry should be treated as a default. + * + * Example entry: + * { "foo_option", "Speed hack coprocessor X; false|true" } + * + * Text before first ';' is description. This ';' must be + * followed by a space, and followed by a list of possible + * values split up with '|'. + * + * Only strings are operated on. The possible values will + * generally be displayed and stored as-is by the frontend. + */ +#define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 + /* bool * -- + * Result is set to true if some variables are updated by + * frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. + * Variables should be queried with GET_VARIABLE. + */ +#define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 + /* const bool * -- + * If true, the libretro implementation supports calls to + * retro_load_game() with NULL as argument. + * Used by cores which can run without particular game data. + * This should be called within retro_set_environment() only. + */ +#define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 + /* const char ** -- + * Retrieves the absolute path from where this libretro + * implementation was loaded. + * NULL is returned if the libretro was loaded statically + * (i.e. linked statically to frontend), or if the path cannot be + * determined. + * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can + * be loaded without ugly hacks. + */ + + /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. + * It was not used by any known core at the time, + * and was removed from the API. */ +#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 + /* const struct retro_frame_time_callback * -- + * Lets the core know how much time has passed since last + * invocation of retro_run(). + * The frontend can tamper with the timing to fake fast-forward, + * slow-motion, frame stepping, etc. + * In this case the delta time will use the reference value + * in frame_time_callback.. + */ +#define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 + /* const struct retro_audio_callback * -- + * Sets an interface which is used to notify a libretro core about audio + * being available for writing. + * The callback can be called from any thread, so a core using this must + * have a thread safe audio implementation. + * It is intended for games where audio and video are completely + * asynchronous and audio can be generated on the fly. + * This interface is not recommended for use with emulators which have + * highly synchronous audio. + * + * The callback only notifies about writability; the libretro core still + * has to call the normal audio callbacks + * to write audio. The audio callbacks must be called from within the + * notification callback. + * The amount of audio data to write is up to the implementation. + * Generally, the audio callback will be called continously in a loop. + * + * Due to thread safety guarantees and lack of sync between audio and + * video, a frontend can selectively disallow this interface based on + * internal configuration. A core using this interface must also + * implement the "normal" audio interface. + * + * A libretro core using SET_AUDIO_CALLBACK should also make use of + * SET_FRAME_TIME_CALLBACK. + */ +#define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 + /* struct retro_rumble_interface * -- + * Gets an interface which is used by a libretro core to set + * state of rumble motors in controllers. + * A strong and weak motor is supported, and they can be + * controlled indepedently. + * Should be called from either retro_init() or retro_load_game(). + * Should not be called from retro_set_environment(). + * Returns false if rumble functionality is unavailable. + */ +#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 + /* uint64_t * -- + * Gets a bitmask telling which device type are expected to be + * handled properly in a call to retro_input_state_t. + * Devices which are not handled or recognized always return + * 0 in retro_input_state_t. + * Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). + * Should only be called in retro_run(). + */ +#define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_sensor_interface * -- + * Gets access to the sensor interface. + * The purpose of this interface is to allow + * setting state related to sensors such as polling rate, + * enabling/disable it entirely, etc. + * Reading sensor state is done via the normal + * input_state_callback API. + */ +#define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_camera_callback * -- + * Gets an interface to a video camera driver. + * A libretro core can use this interface to get access to a + * video camera. + * New video frames are delivered in a callback in same + * thread as retro_run(). + * + * GET_CAMERA_INTERFACE should be called in retro_load_game(). + * + * Depending on the camera implementation used, camera frames + * will be delivered as a raw framebuffer, + * or as an OpenGL texture directly. + * + * The core has to tell the frontend here which types of + * buffers can be handled properly. + * An OpenGL texture can only be handled when using a + * libretro GL core (SET_HW_RENDER). + * It is recommended to use a libretro GL core when + * using camera interface. + * + * The camera is not started automatically. The retrieved start/stop + * functions must be used to explicitly + * start and stop the camera driver. + */ +#define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 + /* struct retro_log_callback * -- + * Gets an interface for logging. This is useful for + * logging in a cross-platform way + * as certain platforms cannot use stderr for logging. + * It also allows the frontend to + * show logging information in a more suitable way. + * If this interface is not used, libretro cores should + * log to stderr as desired. + */ +#define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 + /* struct retro_perf_callback * -- + * Gets an interface for performance counters. This is useful + * for performance logging in a cross-platform way and for detecting + * architecture-specific features, such as SIMD support. + */ +#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 + /* struct retro_location_callback * -- + * Gets access to the location interface. + * The purpose of this interface is to be able to retrieve + * location-based information from the host device, + * such as current latitude / longitude. + */ +#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */ +#define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30 + /* const char ** -- + * Returns the "core assets" directory of the frontend. + * This directory can be used to store specific assets that the + * core relies upon, such as art assets, + * input data, etc etc. + * The returned value can be NULL. + * If so, no such directory is defined, + * and it's up to the implementation to find a suitable directory. + */ +#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 + /* const char ** -- + * Returns the "save" directory of the frontend, unless there is no + * save directory available. The save directory should be used to + * store SRAM, memory cards, high scores, etc, if the libretro core + * cannot use the regular memory interface (retro_get_memory_data()). + * + * If the frontend cannot designate a save directory, it will return + * NULL to indicate that the core should attempt to operate without a + * save directory set. + * + * NOTE: early libretro cores used the system directory for save + * files. Cores that need to be backwards-compatible can still check + * GET_SYSTEM_DIRECTORY. + */ +#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 + /* const struct retro_system_av_info * -- + * Sets a new av_info structure. This can only be called from + * within retro_run(). + * This should *only* be used if the core is completely altering the + * internal resolutions, aspect ratios, timings, sampling rate, etc. + * Calling this can require a full reinitialization of video/audio + * drivers in the frontend, + * + * so it is important to call it very sparingly, and usually only with + * the users explicit consent. + * An eventual driver reinitialize will happen so that video and + * audio callbacks + * happening after this call within the same retro_run() call will + * target the newly initialized driver. + * + * This callback makes it possible to support configurable resolutions + * in games, which can be useful to + * avoid setting the "worst case" in max_width/max_height. + * + * ***HIGHLY RECOMMENDED*** Do not call this callback every time + * resolution changes in an emulator core if it's + * expected to be a temporary change, for the reasons of possible + * driver reinitialization. + * This call is not a free pass for not trying to provide + * correct values in retro_get_system_av_info(). If you need to change + * things like aspect ratio or nominal width/height, + * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant + * of SET_SYSTEM_AV_INFO. + * + * If this returns false, the frontend does not acknowledge a + * changed av_info struct. + */ +#define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 + /* const struct retro_get_proc_address_interface * -- + * Allows a libretro core to announce support for the + * get_proc_address() interface. + * This interface allows for a standard way to extend libretro where + * use of environment calls are too indirect, + * e.g. for cases where the frontend wants to call directly into the core. + * + * If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK + * **MUST** be called from within retro_set_environment(). + */ +#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 + /* const struct retro_subsystem_info * -- + * This environment call introduces the concept of libretro "subsystems". + * A subsystem is a variant of a libretro core which supports + * different kinds of games. + * The purpose of this is to support e.g. emulators which might + * have special needs, e.g. Super Nintendo's Super GameBoy, Sufami Turbo. + * It can also be used to pick among subsystems in an explicit way + * if the libretro implementation is a multi-system emulator itself. + * + * Loading a game via a subsystem is done with retro_load_game_special(), + * and this environment call allows a libretro core to expose which + * subsystems are supported for use with retro_load_game_special(). + * A core passes an array of retro_game_special_info which is terminated + * with a zeroed out retro_game_special_info struct. + * + * If a core wants to use this functionality, SET_SUBSYSTEM_INFO + * **MUST** be called from within retro_set_environment(). + */ +#define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 + /* const struct retro_controller_info * -- + * This environment call lets a libretro core tell the frontend + * which controller subclasses are recognized in calls to + * retro_set_controller_port_device(). + * + * Some emulators such as Super Nintendo support multiple lightgun + * types which must be specifically selected from. It is therefore + * sometimes necessary for a frontend to be able to tell the core + * about a special kind of input device which is not specifcally + * provided by the Libretro API. + * + * In order for a frontend to understand the workings of those devices, + * they must be defined as a specialized subclass of the generic device + * types already defined in the libretro API. + * + * The core must pass an array of const struct retro_controller_info which + * is terminated with a blanked out struct. Each element of the + * retro_controller_info struct corresponds to the ascending port index + * that is passed to retro_set_controller_port_device() when that function + * is called to indicate to the core that the frontend has changed the + * active device subclass. SEE ALSO: retro_set_controller_port_device() + * + * The ascending input port indexes provided by the core in the struct + * are generally presented by frontends as ascending User # or Player #, + * such as Player 1, Player 2, Player 3, etc. Which device subclasses are + * supported can vary per input port. + * + * The first inner element of each entry in the retro_controller_info array + * is a retro_controller_description struct that specifies the names and + * codes of all device subclasses that are available for the corresponding + * User or Player, beginning with the generic Libretro device that the + * subclasses are derived from. The second inner element of each entry is the + * total number of subclasses that are listed in the retro_controller_description. + * + * NOTE: Even if special device types are set in the libretro core, + * libretro should only poll input based on the base input device types. + */ +#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_memory_map * -- + * This environment call lets a libretro core tell the frontend + * about the memory maps this core emulates. + * This can be used to implement, for example, cheats in a core-agnostic way. + * + * Should only be used by emulators; it doesn't make much sense for + * anything else. + * It is recommended to expose all relevant pointers through + * retro_get_memory_* as well. + * + * Can be called from retro_init and retro_load_game. + */ +#define RETRO_ENVIRONMENT_SET_GEOMETRY 37 + /* const struct retro_game_geometry * -- + * This environment call is similar to SET_SYSTEM_AV_INFO for changing + * video parameters, but provides a guarantee that drivers will not be + * reinitialized. + * This can only be called from within retro_run(). + * + * The purpose of this call is to allow a core to alter nominal + * width/heights as well as aspect ratios on-the-fly, which can be + * useful for some emulators to change in run-time. + * + * max_width/max_height arguments are ignored and cannot be changed + * with this call as this could potentially require a reinitialization or a + * non-constant time operation. + * If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required. + * + * A frontend must guarantee that this environment call completes in + * constant time. + */ +#define RETRO_ENVIRONMENT_GET_USERNAME 38 + /* const char ** + * Returns the specified username of the frontend, if specified by the user. + * This username can be used as a nickname for a core that has online facilities + * or any other mode where personalization of the user is desirable. + * The returned value can be NULL. + * If this environ callback is used by a core that requires a valid username, + * a default username should be specified by the core. + */ +#define RETRO_ENVIRONMENT_GET_LANGUAGE 39 + /* unsigned * -- + * Returns the specified language of the frontend, if specified by the user. + * It can be used by the core for localization purposes. + */ +#define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_framebuffer * -- + * Returns a preallocated framebuffer which the core can use for rendering + * the frame into when not using SET_HW_RENDER. + * The framebuffer returned from this call must not be used + * after the current call to retro_run() returns. + * + * The goal of this call is to allow zero-copy behavior where a core + * can render directly into video memory, avoiding extra bandwidth cost by copying + * memory from core to video memory. + * + * If this call succeeds and the core renders into it, + * the framebuffer pointer and pitch can be passed to retro_video_refresh_t. + * If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used, + * the core must pass the exact + * same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER; + * i.e. passing a pointer which is offset from the + * buffer is undefined. The width, height and pitch parameters + * must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER. + * + * It is possible for a frontend to return a different pixel format + * than the one used in SET_PIXEL_FORMAT. This can happen if the frontend + * needs to perform conversion. + * + * It is still valid for a core to render to a different buffer + * even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds. + * + * A frontend must make sure that the pointer obtained from this function is + * writeable (and readable). + */ +#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_hw_render_interface ** -- + * Returns an API specific rendering interface for accessing API specific data. + * Not all HW rendering APIs support or need this. + * The contents of the returned pointer is specific to the rendering API + * being used. See the various headers like libretro_vulkan.h, etc. + * + * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called. + * Similarly, after context_destroyed callback returns, + * the contents of the HW_RENDER_INTERFACE are invalidated. + */ +#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const bool * -- + * If true, the libretro implementation supports achievements + * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS + * or via retro_get_memory_data/retro_get_memory_size. + * + * This must be called before the first call to retro_run. + */ +#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_hw_render_context_negotiation_interface * -- + * Sets an interface which lets the libretro core negotiate with frontend how a context is created. + * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier. + * This interface will be used when the frontend is trying to create a HW rendering context, + * so it will be used after SET_HW_RENDER, but before the context_reset callback. + */ +#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44 + /* uint64_t * -- + * Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't + * recognize or support. Should be set in either retro_init or retro_load_game, but not both. + */ +#define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* N/A (null) * -- + * The frontend will try to use a 'shared' hardware context (mostly applicable + * to OpenGL) when a hardware context is being set up. + * + * Returns true if the frontend supports shared hardware contexts and false + * if the frontend does not support shared hardware contexts. + * + * This will do nothing on its own until SET_HW_RENDER env callbacks are + * being used. + */ +#define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_vfs_interface_info * -- + * Gets access to the VFS interface. + * VFS presence needs to be queried prior to load_game or any + * get_system/save/other_directory being called to let front end know + * core supports VFS before it starts handing out paths. + * It is recomended to do so in retro_set_environment + */ +#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_led_interface * -- + * Gets an interface which is used by a libretro core to set + * state of LEDs. + */ +#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* int * -- + * Tells the core if the frontend wants audio or video. + * If disabled, the frontend will discard the audio or video, + * so the core may decide to skip generating a frame or generating audio. + * This is mainly used for increasing performance. + * Bit 0 (value 1): Enable Video + * Bit 1 (value 2): Enable Audio + * Bit 2 (value 4): Use Fast Savestates. + * Bit 3 (value 8): Hard Disable Audio + * Other bits are reserved for future use and will default to zero. + * If video is disabled: + * * The frontend wants the core to not generate any video, + * including presenting frames via hardware acceleration. + * * The frontend's video frame callback will do nothing. + * * After running the frame, the video output of the next frame should be + * no different than if video was enabled, and saving and loading state + * should have no issues. + * If audio is disabled: + * * The frontend wants the core to not generate any audio. + * * The frontend's audio callbacks will do nothing. + * * After running the frame, the audio output of the next frame should be + * no different than if audio was enabled, and saving and loading state + * should have no issues. + * Fast Savestates: + * * Guaranteed to be created by the same binary that will load them. + * * Will not be written to or read from the disk. + * * Suggest that the core assumes loading state will succeed. + * * Suggest that the core updates its memory buffers in-place if possible. + * * Suggest that the core skips clearing memory. + * * Suggest that the core skips resetting the system. + * * Suggest that the core may skip validation steps. + * Hard Disable Audio: + * * Used for a secondary core when running ahead. + * * Indicates that the frontend will never need audio from the core. + * * Suggests that the core may stop synthesizing audio, but this should not + * compromise emulation accuracy. + * * Audio output for the next frame does not matter, and the frontend will + * never need an accurate audio state in the future. + * * State will never be saved when using Hard Disable Audio. + */ +#define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_midi_interface ** -- + * Returns a MIDI interface that can be used for raw data I/O. + */ + +#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* bool * -- + * Boolean value that indicates whether or not the frontend is in + * fastforwarding mode. + */ + +#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* float * -- + * Float value that lets us know what target refresh rate + * is curently in use by the frontend. + * + * The core can use the returned value to set an ideal + * refresh rate/framerate. + */ + +#define RETRO_ENVIRONMENT_GET_INPUT_BITMASKS (51 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* bool * -- + * Boolean value that indicates whether or not the frontend supports + * input bitmasks being returned by retro_input_state_t. The advantage + * of this is that retro_input_state_t has to be only called once to + * grab all button states instead of multiple times. + * + * If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id' + * to retro_input_state_t (make sure 'device' is set to RETRO_DEVICE_JOYPAD). + * It will return a bitmask of all the digital buttons. + */ + +#define RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION 52 + /* unsigned * -- + * Unsigned value is the API version number of the core options + * interface supported by the frontend. If callback return false, + * API version is assumed to be 0. + * + * In legacy code, core options are set by passing an array of + * retro_variable structs to RETRO_ENVIRONMENT_SET_VARIABLES. + * This may be still be done regardless of the core options + * interface version. + * + * If version is >= 1 however, core options may instead be set by + * passing an array of retro_core_option_definition structs to + * RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of + * retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL. + * This allows the core to additionally set option sublabel information + * and/or provide localisation support. + * + * If version is >= 2, core options may instead be set by passing + * a retro_core_options_v2 struct to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2, + * or an array of retro_core_options_v2 structs to + * RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL. This allows the core + * to additionally set optional core option category information + * for frontends with core option category support. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS 53 + /* const struct retro_core_option_definition ** -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION + * returns an API version of >= 1. + * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterwards it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * + * 'data' points to an array of retro_core_option_definition structs + * terminated by a { NULL, NULL, NULL, {{0}}, NULL } element. + * retro_core_option_definition::key should be namespaced to not collide + * with other implementations' keys. e.g. A core called + * 'foo' should use keys named as 'foo_option'. + * retro_core_option_definition::desc should contain a human readable + * description of the key. + * retro_core_option_definition::info should contain any additional human + * readable information text that a typical user may need to + * understand the functionality of the option. + * retro_core_option_definition::values is an array of retro_core_option_value + * structs terminated by a { NULL, NULL } element. + * > retro_core_option_definition::values[index].value is an expected option + * value. + * > retro_core_option_definition::values[index].label is a human readable + * label used when displaying the value on screen. If NULL, + * the value itself is used. + * retro_core_option_definition::default_value is the default core option + * setting. It must match one of the expected option values in the + * retro_core_option_definition::values array. If it does not, or the + * default value is NULL, the first entry in the + * retro_core_option_definition::values array is treated as the default. + * + * The number of possible option values should be very limited, + * and must be less than RETRO_NUM_CORE_OPTION_VALUES_MAX. + * i.e. it should be feasible to cycle through options + * without a keyboard. + * + * Example entry: + * { + * "foo_option", + * "Speed hack coprocessor X", + * "Provides increased performance at the expense of reduced accuracy", + * { + * { "false", NULL }, + * { "true", NULL }, + * { "unstable", "Turbo (Unstable)" }, + * { NULL, NULL }, + * }, + * "false" + * } + * + * Only strings are operated on. The possible values will + * generally be displayed and stored as-is by the frontend. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL 54 + /* const struct retro_core_options_intl * -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION + * returns an API version of >= 1. + * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. + * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS. + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterwards it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * + * This is fundamentally the same as RETRO_ENVIRONMENT_SET_CORE_OPTIONS, + * with the addition of localisation support. The description of the + * RETRO_ENVIRONMENT_SET_CORE_OPTIONS callback should be consulted + * for further details. + * + * 'data' points to a retro_core_options_intl struct. + * + * retro_core_options_intl::us is a pointer to an array of + * retro_core_option_definition structs defining the US English + * core options implementation. It must point to a valid array. + * + * retro_core_options_intl::local is a pointer to an array of + * retro_core_option_definition structs defining core options for + * the current frontend language. It may be NULL (in which case + * retro_core_options_intl::us is used by the frontend). Any items + * missing from this array will be read from retro_core_options_intl::us + * instead. + * + * NOTE: Default core option values are always taken from the + * retro_core_options_intl::us array. Any default values in + * retro_core_options_intl::local array will be ignored. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY 55 + /* struct retro_core_option_display * -- + * + * Allows an implementation to signal the environment to show + * or hide a variable when displaying core options. This is + * considered a *suggestion*. The frontend is free to ignore + * this callback, and its implementation not considered mandatory. + * + * 'data' points to a retro_core_option_display struct + * + * retro_core_option_display::key is a variable identifier + * which has already been set by SET_VARIABLES/SET_CORE_OPTIONS. + * + * retro_core_option_display::visible is a boolean, specifying + * whether variable should be displayed + * + * Note that all core option variables will be set visible by + * default when calling SET_VARIABLES/SET_CORE_OPTIONS. + */ + +#define RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER 56 + /* unsigned * -- + * + * Allows an implementation to ask frontend preferred hardware + * context to use. Core should use this information to deal + * with what specific context to request with SET_HW_RENDER. + * + * 'data' points to an unsigned variable + */ + +#define RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION 57 + /* unsigned * -- + * Unsigned value is the API version number of the disk control + * interface supported by the frontend. If callback return false, + * API version is assumed to be 0. + * + * In legacy code, the disk control interface is defined by passing + * a struct of type retro_disk_control_callback to + * RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. + * This may be still be done regardless of the disk control + * interface version. + * + * If version is >= 1 however, the disk control interface may + * instead be defined by passing a struct of type + * retro_disk_control_ext_callback to + * RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE. + * This allows the core to provide additional information about + * disk images to the frontend and/or enables extra + * disk control functionality by the frontend. + */ + +#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE 58 + /* const struct retro_disk_control_ext_callback * -- + * Sets an interface which frontend can use to eject and insert + * disk images, and also obtain information about individual + * disk image files registered by the core. + * This is used for games which consist of multiple images and + * must be manually swapped out by the user (e.g. PSX, floppy disk + * based systems). + */ + +#define RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION 59 + /* unsigned * -- + * Unsigned value is the API version number of the message + * interface supported by the frontend. If callback returns + * false, API version is assumed to be 0. + * + * In legacy code, messages may be displayed in an + * implementation-specific manner by passing a struct + * of type retro_message to RETRO_ENVIRONMENT_SET_MESSAGE. + * This may be still be done regardless of the message + * interface version. + * + * If version is >= 1 however, messages may instead be + * displayed by passing a struct of type retro_message_ext + * to RETRO_ENVIRONMENT_SET_MESSAGE_EXT. This allows the + * core to specify message logging level, priority and + * destination (OSD, logging interface or both). + */ + +#define RETRO_ENVIRONMENT_SET_MESSAGE_EXT 60 + /* const struct retro_message_ext * -- + * Sets a message to be displayed in an implementation-specific + * manner for a certain amount of 'frames'. Additionally allows + * the core to specify message logging level, priority and + * destination (OSD, logging interface or both). + * Should not be used for trivial messages, which should simply be + * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a + * fallback, stderr). + */ + +#define RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS 61 + /* unsigned * -- + * Unsigned value is the number of active input devices + * provided by the frontend. This may change between + * frames, but will remain constant for the duration + * of each frame. + * If callback returns true, a core need not poll any + * input device with an index greater than or equal to + * the number of active devices. + * If callback returns false, the number of active input + * devices is unknown. In this case, all input devices + * should be considered active. + */ + +#define RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK 62 + /* const struct retro_audio_buffer_status_callback * -- + * Lets the core know the occupancy level of the frontend + * audio buffer. Can be used by a core to attempt frame + * skipping in order to avoid buffer under-runs. + * A core may pass NULL to disable buffer status reporting + * in the frontend. + */ + +#define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63 + /* const unsigned * -- + * Sets minimum frontend audio latency in milliseconds. + * Resultant audio latency may be larger than set value, + * or smaller if a hardware limit is encountered. A frontend + * is expected to honour requests up to 512 ms. + * + * - If value is less than current frontend + * audio latency, callback has no effect + * - If value is zero, default frontend audio + * latency is set + * + * May be used by a core to increase audio latency and + * therefore decrease the probability of buffer under-runs + * (crackling) when performing 'intensive' operations. + * A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK + * to implement audio-buffer-based frame skipping may achieve + * optimal results by setting the audio latency to a 'high' + * (typically 6x or 8x) integer multiple of the expected + * frame time. + * + * WARNING: This can only be called from within retro_run(). + * Calling this can require a full reinitialization of audio + * drivers in the frontend, so it is important to call it very + * sparingly, and usually only with the users explicit consent. + * An eventual driver reinitialize will happen so that audio + * callbacks happening after this call within the same retro_run() + * call will target the newly initialized driver. + */ + +#define RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE 64 + /* const struct retro_fastforwarding_override * -- + * Used by a libretro core to override the current + * fastforwarding mode of the frontend. + * If NULL is passed to this function, the frontend + * will return true if fastforwarding override + * functionality is supported (no change in + * fastforwarding state will occur in this case). + */ + +#define RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE 65 + /* const struct retro_system_content_info_override * -- + * Allows an implementation to override 'global' content + * info parameters reported by retro_get_system_info(). + * Overrides also affect subsystem content info parameters + * set via RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO. + * This function must be called inside retro_set_environment(). + * If callback returns false, content info overrides + * are unsupported by the frontend, and will be ignored. + * If callback returns true, extended game info may be + * retrieved by calling RETRO_ENVIRONMENT_GET_GAME_INFO_EXT + * in retro_load_game() or retro_load_game_special(). + * + * 'data' points to an array of retro_system_content_info_override + * structs terminated by a { NULL, false, false } element. + * If 'data' is NULL, no changes will be made to the frontend; + * a core may therefore pass NULL in order to test whether + * the RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE and + * RETRO_ENVIRONMENT_GET_GAME_INFO_EXT callbacks are supported + * by the frontend. + * + * For struct member descriptions, see the definition of + * struct retro_system_content_info_override. + * + * Example: + * + * - struct retro_system_info: + * { + * "My Core", // library_name + * "v1.0", // library_version + * "m3u|md|cue|iso|chd|sms|gg|sg", // valid_extensions + * true, // need_fullpath + * false // block_extract + * } + * + * - Array of struct retro_system_content_info_override: + * { + * { + * "md|sms|gg", // extensions + * false, // need_fullpath + * true // persistent_data + * }, + * { + * "sg", // extensions + * false, // need_fullpath + * false // persistent_data + * }, + * { NULL, false, false } + * } + * + * Result: + * - Files of type m3u, cue, iso, chd will not be + * loaded by the frontend. Frontend will pass a + * valid path to the core, and core will handle + * loading internally + * - Files of type md, sms, gg will be loaded by + * the frontend. A valid memory buffer will be + * passed to the core. This memory buffer will + * remain valid until retro_deinit() returns + * - Files of type sg will be loaded by the frontend. + * A valid memory buffer will be passed to the core. + * This memory buffer will remain valid until + * retro_load_game() (or retro_load_game_special()) + * returns + * + * NOTE: If an extension is listed multiple times in + * an array of retro_system_content_info_override + * structs, only the first instance will be registered + */ + +#define RETRO_ENVIRONMENT_GET_GAME_INFO_EXT 66 + /* const struct retro_game_info_ext ** -- + * Allows an implementation to fetch extended game + * information, providing additional content path + * and memory buffer status details. + * This function may only be called inside + * retro_load_game() or retro_load_game_special(). + * If callback returns false, extended game information + * is unsupported by the frontend. In this case, only + * regular retro_game_info will be available. + * RETRO_ENVIRONMENT_GET_GAME_INFO_EXT is guaranteed + * to return true if RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE + * returns true. + * + * 'data' points to an array of retro_game_info_ext structs. + * + * For struct member descriptions, see the definition of + * struct retro_game_info_ext. + * + * - If function is called inside retro_load_game(), + * the retro_game_info_ext array is guaranteed to + * have a size of 1 - i.e. the returned pointer may + * be used to access directly the members of the + * first retro_game_info_ext struct, for example: + * + * struct retro_game_info_ext *game_info_ext; + * if (environ_cb(RETRO_ENVIRONMENT_GET_GAME_INFO_EXT, &game_info_ext)) + * printf("Content Directory: %s\n", game_info_ext->dir); + * + * - If the function is called inside retro_load_game_special(), + * the retro_game_info_ext array is guaranteed to have a + * size equal to the num_info argument passed to + * retro_load_game_special() + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 67 + /* const struct retro_core_options_v2 * -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION + * returns an API version of >= 2. + * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. + * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS. + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterwards it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * If RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION returns an API + * version of >= 2, this callback is guaranteed to succeed + * (i.e. callback return value does not indicate success) + * If callback returns true, frontend has core option category + * support. + * If callback returns false, frontend does not have core option + * category support. + * + * 'data' points to a retro_core_options_v2 struct, containing + * of two pointers: + * - retro_core_options_v2::categories is an array of + * retro_core_option_v2_category structs terminated by a + * { NULL, NULL, NULL } element. If retro_core_options_v2::categories + * is NULL, all core options will have no category and will be shown + * at the top level of the frontend core option interface. If frontend + * does not have core option category support, categories array will + * be ignored. + * - retro_core_options_v2::definitions is an array of + * retro_core_option_v2_definition structs terminated by a + * { NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL } + * element. + * + * >> retro_core_option_v2_category notes: + * + * - retro_core_option_v2_category::key should contain string + * that uniquely identifies the core option category. Valid + * key characters are [a-z, A-Z, 0-9, _, -] + * Namespace collisions with other implementations' category + * keys are permitted. + * - retro_core_option_v2_category::desc should contain a human + * readable description of the category key. + * - retro_core_option_v2_category::info should contain any + * additional human readable information text that a typical + * user may need to understand the nature of the core option + * category. + * + * Example entry: + * { + * "advanced_settings", + * "Advanced", + * "Options affecting low-level emulation performance and accuracy." + * } + * + * >> retro_core_option_v2_definition notes: + * + * - retro_core_option_v2_definition::key should be namespaced to not + * collide with other implementations' keys. e.g. A core called + * 'foo' should use keys named as 'foo_option'. Valid key characters + * are [a-z, A-Z, 0-9, _, -]. + * - retro_core_option_v2_definition::desc should contain a human readable + * description of the key. Will be used when the frontend does not + * have core option category support. Examples: "Aspect Ratio" or + * "Video > Aspect Ratio". + * - retro_core_option_v2_definition::desc_categorized should contain a + * human readable description of the key, which will be used when + * frontend has core option category support. Example: "Aspect Ratio", + * where associated retro_core_option_v2_category::desc is "Video". + * If empty or NULL, the string specified by + * retro_core_option_v2_definition::desc will be used instead. + * retro_core_option_v2_definition::desc_categorized will be ignored + * if retro_core_option_v2_definition::category_key is empty or NULL. + * - retro_core_option_v2_definition::info should contain any additional + * human readable information text that a typical user may need to + * understand the functionality of the option. + * - retro_core_option_v2_definition::info_categorized should contain + * any additional human readable information text that a typical user + * may need to understand the functionality of the option, and will be + * used when frontend has core option category support. This is provided + * to accommodate the case where info text references an option by + * name/desc, and the desc/desc_categorized text for that option differ. + * If empty or NULL, the string specified by + * retro_core_option_v2_definition::info will be used instead. + * retro_core_option_v2_definition::info_categorized will be ignored + * if retro_core_option_v2_definition::category_key is empty or NULL. + * - retro_core_option_v2_definition::category_key should contain a + * category identifier (e.g. "video" or "audio") that will be + * assigned to the core option if frontend has core option category + * support. A categorized option will be shown in a subsection/ + * submenu of the frontend core option interface. If key is empty + * or NULL, or if key does not match one of the + * retro_core_option_v2_category::key values in the associated + * retro_core_option_v2_category array, option will have no category + * and will be shown at the top level of the frontend core option + * interface. + * - retro_core_option_v2_definition::values is an array of + * retro_core_option_value structs terminated by a { NULL, NULL } + * element. + * --> retro_core_option_v2_definition::values[index].value is an + * expected option value. + * --> retro_core_option_v2_definition::values[index].label is a + * human readable label used when displaying the value on screen. + * If NULL, the value itself is used. + * - retro_core_option_v2_definition::default_value is the default + * core option setting. It must match one of the expected option + * values in the retro_core_option_v2_definition::values array. If + * it does not, or the default value is NULL, the first entry in the + * retro_core_option_v2_definition::values array is treated as the + * default. + * + * The number of possible option values should be very limited, + * and must be less than RETRO_NUM_CORE_OPTION_VALUES_MAX. + * i.e. it should be feasible to cycle through options + * without a keyboard. + * + * Example entries: + * + * - Uncategorized: + * + * { + * "foo_option", + * "Speed hack coprocessor X", + * NULL, + * "Provides increased performance at the expense of reduced accuracy.", + * NULL, + * NULL, + * { + * { "false", NULL }, + * { "true", NULL }, + * { "unstable", "Turbo (Unstable)" }, + * { NULL, NULL }, + * }, + * "false" + * } + * + * - Categorized: + * + * { + * "foo_option", + * "Advanced > Speed hack coprocessor X", + * "Speed hack coprocessor X", + * "Setting 'Advanced > Speed hack coprocessor X' to 'true' or 'Turbo' provides increased performance at the expense of reduced accuracy", + * "Setting 'Speed hack coprocessor X' to 'true' or 'Turbo' provides increased performance at the expense of reduced accuracy", + * "advanced_settings", + * { + * { "false", NULL }, + * { "true", NULL }, + * { "unstable", "Turbo (Unstable)" }, + * { NULL, NULL }, + * }, + * "false" + * } + * + * Only strings are operated on. The possible values will + * generally be displayed and stored as-is by the frontend. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL 68 + /* const struct retro_core_options_v2_intl * -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION + * returns an API version of >= 2. + * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. + * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS. + * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL. + * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2. + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterwards it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * If RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION returns an API + * version of >= 2, this callback is guaranteed to succeed + * (i.e. callback return value does not indicate success) + * If callback returns true, frontend has core option category + * support. + * If callback returns false, frontend does not have core option + * category support. + * + * This is fundamentally the same as RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2, + * with the addition of localisation support. The description of the + * RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 callback should be consulted + * for further details. + * + * 'data' points to a retro_core_options_v2_intl struct. + * + * - retro_core_options_v2_intl::us is a pointer to a + * retro_core_options_v2 struct defining the US English + * core options implementation. It must point to a valid struct. + * + * - retro_core_options_v2_intl::local is a pointer to a + * retro_core_options_v2 struct defining core options for + * the current frontend language. It may be NULL (in which case + * retro_core_options_v2_intl::us is used by the frontend). Any items + * missing from this struct will be read from + * retro_core_options_v2_intl::us instead. + * + * NOTE: Default core option values are always taken from the + * retro_core_options_v2_intl::us struct. Any default values in + * the retro_core_options_v2_intl::local struct will be ignored. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK 69 + /* const struct retro_core_options_update_display_callback * -- + * Allows a frontend to signal that a core must update + * the visibility of any dynamically hidden core options, + * and enables the frontend to detect visibility changes. + * Used by the frontend to update the menu display status + * of core options without requiring a call of retro_run(). + * Must be called in retro_set_environment(). + */ + +#define RETRO_ENVIRONMENT_SET_VARIABLE 70 + /* const struct retro_variable * -- + * Allows an implementation to notify the frontend + * that a core option value has changed. + * + * retro_variable::key and retro_variable::value + * must match strings that have been set previously + * via one of the following: + * + * - RETRO_ENVIRONMENT_SET_VARIABLES + * - RETRO_ENVIRONMENT_SET_CORE_OPTIONS + * - RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL + * - RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + * - RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL + * + * After changing a core option value via this + * callback, RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE + * will return true. + * + * If data is NULL, no changes will be registered + * and the callback will return true; an + * implementation may therefore pass NULL in order + * to test whether the callback is supported. + */ + +#define RETRO_ENVIRONMENT_GET_THROTTLE_STATE (71 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_throttle_state * -- + * Allows an implementation to get details on the actual rate + * the frontend is attempting to call retro_run(). + */ + +#define RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT (72 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* int * -- + * Tells the core about the context the frontend is asking for savestate. + * (see enum retro_savestate_context) + */ + +#define RETRO_ENVIRONMENT_GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT (73 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_hw_render_context_negotiation_interface * -- + * Before calling SET_HW_RNEDER_CONTEXT_NEGOTIATION_INTERFACE, a core can query + * which version of the interface is supported. + * + * Frontend looks at interface_type and returns the maximum supported + * context negotiation interface version. + * If the interface_type is not supported or recognized by the frontend, a version of 0 + * must be returned in interface_version and true is returned by frontend. + * + * If this environment call returns true with interface_version greater than 0, + * a core can always use a negotiation interface version larger than what the frontend returns, but only + * earlier versions of the interface will be used by the frontend. + * A frontend must not reject a negotiation interface version that is larger than + * what the frontend supports. Instead, the frontend will use the older entry points that it recognizes. + * If this is incompatible with a particular core's requirements, it can error out early. + * + * Backwards compatibility note: + * This environment call was introduced after Vulkan v1 context negotiation. + * If this environment call is not supported by frontend - i.e. the environment call returns false - + * only Vulkan v1 context negotiation is supported (if Vulkan HW rendering is supported at all). + * If a core uses Vulkan negotiation interface with version > 1, negotiation may fail unexpectedly. + * All future updates to the context negotiation interface implies that frontend must support + * this environment call to query support. + */ + + +/* VFS functionality */ + +/* File paths: + * File paths passed as parameters when using this API shall be well formed UNIX-style, + * using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator. + * Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead). + * Other than the directory separator, cores shall not make assumptions about path format: + * "C:/path/game.bin", "http://example.com/game.bin", "#game/game.bin", "./game.bin" (without quotes) are all valid paths. + * Cores may replace the basename or remove path components from the end, and/or add new components; + * however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request to front end. + * The frontend is encouraged to make such paths work as well as it can, but is allowed to give up if the core alters paths too much. + * Frontends are encouraged, but not required, to support native file system paths (modulo replacing the directory separator, if applicable). + * Cores are allowed to try using them, but must remain functional if the front rejects such requests. + * Cores are encouraged to use the libretro-common filestream functions for file I/O, + * as they seamlessly integrate with VFS, deal with directory separator replacement as appropriate + * and provide platform-specific fallbacks in cases where front ends do not support VFS. */ + +/* Opaque file handle + * Introduced in VFS API v1 */ +struct retro_vfs_file_handle; + +/* Opaque directory handle + * Introduced in VFS API v3 */ +struct retro_vfs_dir_handle; + +/* File open flags + * Introduced in VFS API v1 */ +#define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */ +#define RETRO_VFS_FILE_ACCESS_WRITE (1 << 1) /* Write only mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified */ +#define RETRO_VFS_FILE_ACCESS_READ_WRITE (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) /* Read-write mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified*/ +#define RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING (1 << 2) /* Prevents discarding content of existing files opened for writing */ + +/* These are only hints. The frontend may choose to ignore them. Other than RAM/CPU/etc use, + and how they react to unlikely external interference (for example someone else writing to that file, + or the file's server going down), behavior will not change. */ +#define RETRO_VFS_FILE_ACCESS_HINT_NONE (0) +/* Indicate that the file will be accessed many times. The frontend should aggressively cache everything. */ +#define RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS (1 << 0) + +/* Seek positions */ +#define RETRO_VFS_SEEK_POSITION_START 0 +#define RETRO_VFS_SEEK_POSITION_CURRENT 1 +#define RETRO_VFS_SEEK_POSITION_END 2 + +/* stat() result flags + * Introduced in VFS API v3 */ +#define RETRO_VFS_STAT_IS_VALID (1 << 0) +#define RETRO_VFS_STAT_IS_DIRECTORY (1 << 1) +#define RETRO_VFS_STAT_IS_CHARACTER_SPECIAL (1 << 2) + +/* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle + * Introduced in VFS API v1 */ +typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream); + +/* Open a file for reading or writing. If path points to a directory, this will + * fail. Returns the opaque file handle, or NULL for error. + * Introduced in VFS API v1 */ +typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints); + +/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on success, -1 on failure. + * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. + * Introduced in VFS API v1 */ +typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream); + +/* Return the size of the file in bytes, or -1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream); + +/* Truncate file to specified size. Returns 0 on success or -1 on error + * Introduced in VFS API v2 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length); + +/* Get the current read / write position for the file. Returns -1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream); + +/* Set the current read/write position for the file. Returns the new position, -1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_seek_t)(struct retro_vfs_file_handle *stream, int64_t offset, int seek_position); + +/* Read data from a file. Returns the number of bytes read, or -1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_read_t)(struct retro_vfs_file_handle *stream, void *s, uint64_t len); + +/* Write data to a file. Returns the number of bytes written, or -1 for error. + * Introduced in VFS API v1 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_write_t)(struct retro_vfs_file_handle *stream, const void *s, uint64_t len); + +/* Flush pending writes to file, if using buffered IO. Returns 0 on sucess, or -1 on failure. + * Introduced in VFS API v1 */ +typedef int (RETRO_CALLCONV *retro_vfs_flush_t)(struct retro_vfs_file_handle *stream); + +/* Delete the specified file. Returns 0 on success, -1 on failure + * Introduced in VFS API v1 */ +typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path); + +/* Rename the specified file. Returns 0 on success, -1 on failure + * Introduced in VFS API v1 */ +typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path); + +/* Stat the specified file. Retruns a bitmask of RETRO_VFS_STAT_* flags, none are set if path was not valid. + * Additionally stores file size in given variable, unless NULL is given. + * Introduced in VFS API v3 */ +typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size); + +/* Create the specified directory. Returns 0 on success, -1 on unknown failure, -2 if already exists. + * Introduced in VFS API v3 */ +typedef int (RETRO_CALLCONV *retro_vfs_mkdir_t)(const char *dir); + +/* Open the specified directory for listing. Returns the opaque dir handle, or NULL for error. + * Support for the include_hidden argument may vary depending on the platform. + * Introduced in VFS API v3 */ +typedef struct retro_vfs_dir_handle *(RETRO_CALLCONV *retro_vfs_opendir_t)(const char *dir, bool include_hidden); + +/* Read the directory entry at the current position, and move the read pointer to the next position. + * Returns true on success, false if already on the last entry. + * Introduced in VFS API v3 */ +typedef bool (RETRO_CALLCONV *retro_vfs_readdir_t)(struct retro_vfs_dir_handle *dirstream); + +/* Get the name of the last entry read. Returns a string on success, or NULL for error. + * The returned string pointer is valid until the next call to readdir or closedir. + * Introduced in VFS API v3 */ +typedef const char *(RETRO_CALLCONV *retro_vfs_dirent_get_name_t)(struct retro_vfs_dir_handle *dirstream); + +/* Check if the last entry read was a directory. Returns true if it was, false otherwise (or on error). + * Introduced in VFS API v3 */ +typedef bool (RETRO_CALLCONV *retro_vfs_dirent_is_dir_t)(struct retro_vfs_dir_handle *dirstream); + +/* Close the directory and release its resources. Must be called if opendir returns non-NULL. Returns 0 on success, -1 on failure. + * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. + * Introduced in VFS API v3 */ +typedef int (RETRO_CALLCONV *retro_vfs_closedir_t)(struct retro_vfs_dir_handle *dirstream); + +struct retro_vfs_interface +{ + /* VFS API v1 */ + retro_vfs_get_path_t get_path; + retro_vfs_open_t open; + retro_vfs_close_t close; + retro_vfs_size_t size; + retro_vfs_tell_t tell; + retro_vfs_seek_t seek; + retro_vfs_read_t read; + retro_vfs_write_t write; + retro_vfs_flush_t flush; + retro_vfs_remove_t remove; + retro_vfs_rename_t rename; + /* VFS API v2 */ + retro_vfs_truncate_t truncate; + /* VFS API v3 */ + retro_vfs_stat_t stat; + retro_vfs_mkdir_t mkdir; + retro_vfs_opendir_t opendir; + retro_vfs_readdir_t readdir; + retro_vfs_dirent_get_name_t dirent_get_name; + retro_vfs_dirent_is_dir_t dirent_is_dir; + retro_vfs_closedir_t closedir; +}; + +struct retro_vfs_interface_info +{ + /* Set by core: should this be higher than the version the front end supports, + * front end will return false in the RETRO_ENVIRONMENT_GET_VFS_INTERFACE call + * Introduced in VFS API v1 */ + uint32_t required_interface_version; + + /* Frontend writes interface pointer here. The frontend also sets the actual + * version, must be at least required_interface_version. + * Introduced in VFS API v1 */ + struct retro_vfs_interface *iface; +}; + +enum retro_hw_render_interface_type +{ + RETRO_HW_RENDER_INTERFACE_VULKAN = 0, + RETRO_HW_RENDER_INTERFACE_D3D9 = 1, + RETRO_HW_RENDER_INTERFACE_D3D10 = 2, + RETRO_HW_RENDER_INTERFACE_D3D11 = 3, + RETRO_HW_RENDER_INTERFACE_D3D12 = 4, + RETRO_HW_RENDER_INTERFACE_GSKIT_PS2 = 5, + RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX +}; + +/* Base struct. All retro_hw_render_interface_* types + * contain at least these fields. */ +struct retro_hw_render_interface +{ + enum retro_hw_render_interface_type interface_type; + unsigned interface_version; +}; + +typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state); +struct retro_led_interface +{ + retro_set_led_state_t set_led_state; +}; + +/* Retrieves the current state of the MIDI input. + * Returns true if it's enabled, false otherwise. */ +typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void); + +/* Retrieves the current state of the MIDI output. + * Returns true if it's enabled, false otherwise */ +typedef bool (RETRO_CALLCONV *retro_midi_output_enabled_t)(void); + +/* Reads next byte from the input stream. + * Returns true if byte is read, false otherwise. */ +typedef bool (RETRO_CALLCONV *retro_midi_read_t)(uint8_t *byte); + +/* Writes byte to the output stream. + * 'delta_time' is in microseconds and represent time elapsed since previous write. + * Returns true if byte is written, false otherwise. */ +typedef bool (RETRO_CALLCONV *retro_midi_write_t)(uint8_t byte, uint32_t delta_time); + +/* Flushes previously written data. + * Returns true if successful, false otherwise. */ +typedef bool (RETRO_CALLCONV *retro_midi_flush_t)(void); + +struct retro_midi_interface +{ + retro_midi_input_enabled_t input_enabled; + retro_midi_output_enabled_t output_enabled; + retro_midi_read_t read; + retro_midi_write_t write; + retro_midi_flush_t flush; +}; + +enum retro_hw_render_context_negotiation_interface_type +{ + RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0, + RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX +}; + +/* Base struct. All retro_hw_render_context_negotiation_interface_* types + * contain at least these fields. */ +struct retro_hw_render_context_negotiation_interface +{ + enum retro_hw_render_context_negotiation_interface_type interface_type; + unsigned interface_version; +}; + +/* Serialized state is incomplete in some way. Set if serialization is + * usable in typical end-user cases but should not be relied upon to + * implement frame-sensitive frontend features such as netplay or + * rerecording. */ +#define RETRO_SERIALIZATION_QUIRK_INCOMPLETE (1 << 0) +/* The core must spend some time initializing before serialization is + * supported. retro_serialize() will initially fail; retro_unserialize() + * and retro_serialize_size() may or may not work correctly either. */ +#define RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE (1 << 1) +/* Serialization size may change within a session. */ +#define RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE (1 << 2) +/* Set by the frontend to acknowledge that it supports variable-sized + * states. */ +#define RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE (1 << 3) +/* Serialized state can only be loaded during the same session. */ +#define RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION (1 << 4) +/* Serialized state cannot be loaded on an architecture with a different + * endianness from the one it was saved on. */ +#define RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT (1 << 5) +/* Serialized state cannot be loaded on a different platform from the one it + * was saved on for reasons other than endianness, such as word size + * dependence */ +#define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6) + +#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ +#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ +#define RETRO_MEMDESC_SYSTEM_RAM (1 << 2) /* The memory area is system RAM. This is main RAM of the gaming system. */ +#define RETRO_MEMDESC_SAVE_RAM (1 << 3) /* The memory area is save RAM. This RAM is usually found on a game cartridge, backed up by a battery. */ +#define RETRO_MEMDESC_VIDEO_RAM (1 << 4) /* The memory area is video RAM (VRAM) */ +#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ +#define RETRO_MEMDESC_ALIGN_4 (2 << 16) +#define RETRO_MEMDESC_ALIGN_8 (3 << 16) +#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */ +#define RETRO_MEMDESC_MINSIZE_4 (2 << 24) +#define RETRO_MEMDESC_MINSIZE_8 (3 << 24) +struct retro_memory_descriptor +{ + uint64_t flags; + + /* Pointer to the start of the relevant ROM or RAM chip. + * It's strongly recommended to use 'offset' if possible, rather than + * doing math on the pointer. + * + * If the same byte is mapped my multiple descriptors, their descriptors + * must have the same pointer. + * If 'start' does not point to the first byte in the pointer, put the + * difference in 'offset' instead. + * + * May be NULL if there's nothing usable here (e.g. hardware registers and + * open bus). No flags should be set if the pointer is NULL. + * It's recommended to minimize the number of descriptors if possible, + * but not mandatory. */ + void *ptr; + size_t offset; + + /* This is the location in the emulated address space + * where the mapping starts. */ + size_t start; + + /* Which bits must be same as in 'start' for this mapping to apply. + * The first memory descriptor to claim a certain byte is the one + * that applies. + * A bit which is set in 'start' must also be set in this. + * Can be zero, in which case each byte is assumed mapped exactly once. + * In this case, 'len' must be a power of two. */ + size_t select; + + /* If this is nonzero, the set bits are assumed not connected to the + * memory chip's address pins. */ + size_t disconnect; + + /* This one tells the size of the current memory area. + * If, after start+disconnect are applied, the address is higher than + * this, the highest bit of the address is cleared. + * + * If the address is still too high, the next highest bit is cleared. + * Can be zero, in which case it's assumed to be infinite (as limited + * by 'select' and 'disconnect'). */ + size_t len; + + /* To go from emulated address to physical address, the following + * order applies: + * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */ + + /* The address space name must consist of only a-zA-Z0-9_-, + * should be as short as feasible (maximum length is 8 plus the NUL), + * and may not be any other address space plus one or more 0-9A-F + * at the end. + * However, multiple memory descriptors for the same address space is + * allowed, and the address space name can be empty. NULL is treated + * as empty. + * + * Address space names are case sensitive, but avoid lowercase if possible. + * The same pointer may exist in multiple address spaces. + * + * Examples: + * blank+blank - valid (multiple things may be mapped in the same namespace) + * 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace) + * 'A'+'B' - valid (neither is a prefix of each other) + * 'S'+blank - valid ('S' is not in 0-9A-F) + * 'a'+blank - valid ('a' is not in 0-9A-F) + * 'a'+'A' - valid (neither is a prefix of each other) + * 'AR'+blank - valid ('R' is not in 0-9A-F) + * 'ARB'+blank - valid (the B can't be part of the address either, because + * there is no namespace 'AR') + * blank+'B' - not valid, because it's ambigous which address space B1234 + * would refer to. + * The length can't be used for that purpose; the frontend may want + * to append arbitrary data to an address, without a separator. */ + const char *addrspace; + + /* TODO: When finalizing this one, add a description field, which should be + * "WRAM" or something roughly equally long. */ + + /* TODO: When finalizing this one, replace 'select' with 'limit', which tells + * which bits can vary and still refer to the same address (limit = ~select). + * TODO: limit? range? vary? something else? */ + + /* TODO: When finalizing this one, if 'len' is above what 'select' (or + * 'limit') allows, it's bankswitched. Bankswitched data must have both 'len' + * and 'select' != 0, and the mappings don't tell how the system switches the + * banks. */ + + /* TODO: When finalizing this one, fix the 'len' bit removal order. + * For len=0x1800, pointer 0x1C00 should go to 0x1400, not 0x0C00. + * Algorithm: Take bits highest to lowest, but if it goes above len, clear + * the most recent addition and continue on the next bit. + * TODO: Can the above be optimized? Is "remove the lowest bit set in both + * pointer and 'len'" equivalent? */ + + /* TODO: Some emulators (MAME?) emulate big endian systems by only accessing + * the emulated memory in 32-bit chunks, native endian. But that's nothing + * compared to Darek Mihocka + * (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE + * RAM backwards! I'll want to represent both of those, via some flags. + * + * I suspect MAME either didn't think of that idea, or don't want the #ifdef. + * Not sure which, nor do I really care. */ + + /* TODO: Some of those flags are unused and/or don't really make sense. Clean + * them up. */ +}; + +/* The frontend may use the largest value of 'start'+'select' in a + * certain namespace to infer the size of the address space. + * + * If the address space is larger than that, a mapping with .ptr=NULL + * should be at the end of the array, with .select set to all ones for + * as long as the address space is big. + * + * Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags): + * SNES WRAM: + * .start=0x7E0000, .len=0x20000 + * (Note that this must be mapped before the ROM in most cases; some of the + * ROM mappers + * try to claim $7E0000, or at least $7E8000.) + * SNES SPC700 RAM: + * .addrspace="S", .len=0x10000 + * SNES WRAM mirrors: + * .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000 + * .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000 + * SNES WRAM mirrors, alternate equivalent descriptor: + * .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF + * (Various similar constructions can be created by combining parts of + * the above two.) + * SNES LoROM (512KB, mirrored a couple of times): + * .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024 + * .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024 + * SNES HiROM (4MB): + * .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024 + * .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024 + * SNES ExHiROM (8MB): + * .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024 + * .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024 + * .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024 + * .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024 + * Clarify the size of the address space: + * .ptr=NULL, .select=0xFFFFFF + * .len can be implied by .select in many of them, but was included for clarity. + */ + +struct retro_memory_map +{ + const struct retro_memory_descriptor *descriptors; + unsigned num_descriptors; +}; + +struct retro_controller_description +{ + /* Human-readable description of the controller. Even if using a generic + * input device type, this can be set to the particular device type the + * core uses. */ + const char *desc; + + /* Device type passed to retro_set_controller_port_device(). If the device + * type is a sub-class of a generic input device type, use the + * RETRO_DEVICE_SUBCLASS macro to create an ID. + * + * E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1). */ + unsigned id; +}; + +struct retro_controller_info +{ + const struct retro_controller_description *types; + unsigned num_types; +}; + +struct retro_subsystem_memory_info +{ + /* The extension associated with a memory type, e.g. "psram". */ + const char *extension; + + /* The memory type for retro_get_memory(). This should be at + * least 0x100 to avoid conflict with standardized + * libretro memory types. */ + unsigned type; +}; + +struct retro_subsystem_rom_info +{ + /* Describes what the content is (SGB BIOS, GB ROM, etc). */ + const char *desc; + + /* Same definition as retro_get_system_info(). */ + const char *valid_extensions; + + /* Same definition as retro_get_system_info(). */ + bool need_fullpath; + + /* Same definition as retro_get_system_info(). */ + bool block_extract; + + /* This is set if the content is required to load a game. + * If this is set to false, a zeroed-out retro_game_info can be passed. */ + bool required; + + /* Content can have multiple associated persistent + * memory types (retro_get_memory()). */ + const struct retro_subsystem_memory_info *memory; + unsigned num_memory; +}; + +struct retro_subsystem_info +{ + /* Human-readable string of the subsystem type, e.g. "Super GameBoy" */ + const char *desc; + + /* A computer friendly short string identifier for the subsystem type. + * This name must be [a-z]. + * E.g. if desc is "Super GameBoy", this can be "sgb". + * This identifier can be used for command-line interfaces, etc. + */ + const char *ident; + + /* Infos for each content file. The first entry is assumed to be the + * "most significant" content for frontend purposes. + * E.g. with Super GameBoy, the first content should be the GameBoy ROM, + * as it is the most "significant" content to a user. + * If a frontend creates new file paths based on the content used + * (e.g. savestates), it should use the path for the first ROM to do so. */ + const struct retro_subsystem_rom_info *roms; + + /* Number of content files associated with a subsystem. */ + unsigned num_roms; + + /* The type passed to retro_load_game_special(). */ + unsigned id; +}; + +typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); + +/* libretro API extension functions: + * (None here so far). + * + * Get a symbol from a libretro core. + * Cores should only return symbols which are actual + * extensions to the libretro API. + * + * Frontends should not use this to obtain symbols to standard + * libretro entry points (static linking or dlsym). + * + * The symbol name must be equal to the function name, + * e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". + * The returned function pointer must be cast to the corresponding type. + */ +typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym); + +struct retro_get_proc_address_interface +{ + retro_get_proc_address_t get_proc_address; +}; + +enum retro_log_level +{ + RETRO_LOG_DEBUG = 0, + RETRO_LOG_INFO, + RETRO_LOG_WARN, + RETRO_LOG_ERROR, + + RETRO_LOG_DUMMY = INT_MAX +}; + +/* Logging function. Takes log level argument as well. */ +typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level, + const char *fmt, ...); + +struct retro_log_callback +{ + retro_log_printf_t log; +}; + +/* Performance related functions */ + +/* ID values for SIMD CPU features */ +#define RETRO_SIMD_SSE (1 << 0) +#define RETRO_SIMD_SSE2 (1 << 1) +#define RETRO_SIMD_VMX (1 << 2) +#define RETRO_SIMD_VMX128 (1 << 3) +#define RETRO_SIMD_AVX (1 << 4) +#define RETRO_SIMD_NEON (1 << 5) +#define RETRO_SIMD_SSE3 (1 << 6) +#define RETRO_SIMD_SSSE3 (1 << 7) +#define RETRO_SIMD_MMX (1 << 8) +#define RETRO_SIMD_MMXEXT (1 << 9) +#define RETRO_SIMD_SSE4 (1 << 10) +#define RETRO_SIMD_SSE42 (1 << 11) +#define RETRO_SIMD_AVX2 (1 << 12) +#define RETRO_SIMD_VFPU (1 << 13) +#define RETRO_SIMD_PS (1 << 14) +#define RETRO_SIMD_AES (1 << 15) +#define RETRO_SIMD_VFPV3 (1 << 16) +#define RETRO_SIMD_VFPV4 (1 << 17) +#define RETRO_SIMD_POPCNT (1 << 18) +#define RETRO_SIMD_MOVBE (1 << 19) +#define RETRO_SIMD_CMOV (1 << 20) +#define RETRO_SIMD_ASIMD (1 << 21) + +typedef uint64_t retro_perf_tick_t; +typedef int64_t retro_time_t; + +struct retro_perf_counter +{ + const char *ident; + retro_perf_tick_t start; + retro_perf_tick_t total; + retro_perf_tick_t call_cnt; + + bool registered; +}; + +/* Returns current time in microseconds. + * Tries to use the most accurate timer available. + */ +typedef retro_time_t (RETRO_CALLCONV *retro_perf_get_time_usec_t)(void); + +/* A simple counter. Usually nanoseconds, but can also be CPU cycles. + * Can be used directly if desired (when creating a more sophisticated + * performance counter system). + * */ +typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void); + +/* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */ +typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_t)(void); + +/* Asks frontend to log and/or display the state of performance counters. + * Performance counters can always be poked into manually as well. + */ +typedef void (RETRO_CALLCONV *retro_perf_log_t)(void); + +/* Register a performance counter. + * ident field must be set with a discrete value and other values in + * retro_perf_counter must be 0. + * Registering can be called multiple times. To avoid calling to + * frontend redundantly, you can check registered field first. */ +typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter); + +/* Starts a registered counter. */ +typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter); + +/* Stops a registered counter. */ +typedef void (RETRO_CALLCONV *retro_perf_stop_t)(struct retro_perf_counter *counter); + +/* For convenience it can be useful to wrap register, start and stop in macros. + * E.g.: + * #ifdef LOG_PERFORMANCE + * #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) + * #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) + * #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) + * #else + * ... Blank macros ... + * #endif + * + * These can then be used mid-functions around code snippets. + * + * extern struct retro_perf_callback perf_cb; * Somewhere in the core. + * + * void do_some_heavy_work(void) + * { + * RETRO_PERFORMANCE_INIT(cb, work_1; + * RETRO_PERFORMANCE_START(cb, work_1); + * heavy_work_1(); + * RETRO_PERFORMANCE_STOP(cb, work_1); + * + * RETRO_PERFORMANCE_INIT(cb, work_2); + * RETRO_PERFORMANCE_START(cb, work_2); + * heavy_work_2(); + * RETRO_PERFORMANCE_STOP(cb, work_2); + * } + * + * void retro_deinit(void) + * { + * perf_cb.perf_log(); * Log all perf counters here for example. + * } + */ + +struct retro_perf_callback +{ + retro_perf_get_time_usec_t get_time_usec; + retro_get_cpu_features_t get_cpu_features; + + retro_perf_get_counter_t get_perf_counter; + retro_perf_register_t perf_register; + retro_perf_start_t perf_start; + retro_perf_stop_t perf_stop; + retro_perf_log_t perf_log; +}; + +/* FIXME: Document the sensor API and work out behavior. + * It will be marked as experimental until then. + */ +enum retro_sensor_action +{ + RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, + RETRO_SENSOR_ACCELEROMETER_DISABLE, + RETRO_SENSOR_GYROSCOPE_ENABLE, + RETRO_SENSOR_GYROSCOPE_DISABLE, + RETRO_SENSOR_ILLUMINANCE_ENABLE, + RETRO_SENSOR_ILLUMINANCE_DISABLE, + + RETRO_SENSOR_DUMMY = INT_MAX +}; + +/* Id values for SENSOR types. */ +#define RETRO_SENSOR_ACCELEROMETER_X 0 +#define RETRO_SENSOR_ACCELEROMETER_Y 1 +#define RETRO_SENSOR_ACCELEROMETER_Z 2 +#define RETRO_SENSOR_GYROSCOPE_X 3 +#define RETRO_SENSOR_GYROSCOPE_Y 4 +#define RETRO_SENSOR_GYROSCOPE_Z 5 +#define RETRO_SENSOR_ILLUMINANCE 6 + +typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, + enum retro_sensor_action action, unsigned rate); + +typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id); + +struct retro_sensor_interface +{ + retro_set_sensor_state_t set_sensor_state; + retro_sensor_get_input_t get_sensor_input; +}; + +enum retro_camera_buffer +{ + RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0, + RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER, + + RETRO_CAMERA_BUFFER_DUMMY = INT_MAX +}; + +/* Starts the camera driver. Can only be called in retro_run(). */ +typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void); + +/* Stops the camera driver. Can only be called in retro_run(). */ +typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void); + +/* Callback which signals when the camera driver is initialized + * and/or deinitialized. + * retro_camera_start_t can be called in initialized callback. + */ +typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void); + +/* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. + * Width, height and pitch are similar to retro_video_refresh_t. + * First pixel is top-left origin. + */ +typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, + unsigned width, unsigned height, size_t pitch); + +/* A callback for when OpenGL textures are used. + * + * texture_id is a texture owned by camera driver. + * Its state or content should be considered immutable, except for things like + * texture filtering and clamping. + * + * texture_target is the texture target for the GL texture. + * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly + * more depending on extensions. + * + * affine points to a packed 3x3 column-major matrix used to apply an affine + * transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) + * After transform, normalized texture coord (0, 0) should be bottom-left + * and (1, 1) should be top-right (or (width, height) for RECTANGLE). + * + * GL-specific typedefs are avoided here to avoid relying on gl.h in + * the API definition. + */ +typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id, + unsigned texture_target, const float *affine); + +struct retro_camera_callback +{ + /* Set by libretro core. + * Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). + */ + uint64_t caps; + + /* Desired resolution for camera. Is only used as a hint. */ + unsigned width; + unsigned height; + + /* Set by frontend. */ + retro_camera_start_t start; + retro_camera_stop_t stop; + + /* Set by libretro core if raw framebuffer callbacks will be used. */ + retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; + + /* Set by libretro core if OpenGL texture callbacks will be used. */ + retro_camera_frame_opengl_texture_t frame_opengl_texture; + + /* Set by libretro core. Called after camera driver is initialized and + * ready to be started. + * Can be NULL, in which this callback is not called. + */ + retro_camera_lifetime_status_t initialized; + + /* Set by libretro core. Called right before camera driver is + * deinitialized. + * Can be NULL, in which this callback is not called. + */ + retro_camera_lifetime_status_t deinitialized; +}; + +/* Sets the interval of time and/or distance at which to update/poll + * location-based data. + * + * To ensure compatibility with all location-based implementations, + * values for both interval_ms and interval_distance should be provided. + * + * interval_ms is the interval expressed in milliseconds. + * interval_distance is the distance interval expressed in meters. + */ +typedef void (RETRO_CALLCONV *retro_location_set_interval_t)(unsigned interval_ms, + unsigned interval_distance); + +/* Start location services. The device will start listening for changes to the + * current location at regular intervals (which are defined with + * retro_location_set_interval_t). */ +typedef bool (RETRO_CALLCONV *retro_location_start_t)(void); + +/* Stop location services. The device will stop listening for changes + * to the current location. */ +typedef void (RETRO_CALLCONV *retro_location_stop_t)(void); + +/* Get the position of the current location. Will set parameters to + * 0 if no new location update has happened since the last time. */ +typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon, + double *horiz_accuracy, double *vert_accuracy); + +/* Callback which signals when the location driver is initialized + * and/or deinitialized. + * retro_location_start_t can be called in initialized callback. + */ +typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void); + +struct retro_location_callback +{ + retro_location_start_t start; + retro_location_stop_t stop; + retro_location_get_position_t get_position; + retro_location_set_interval_t set_interval; + + retro_location_lifetime_status_t initialized; + retro_location_lifetime_status_t deinitialized; +}; + +enum retro_rumble_effect +{ + RETRO_RUMBLE_STRONG = 0, + RETRO_RUMBLE_WEAK = 1, + + RETRO_RUMBLE_DUMMY = INT_MAX +}; + +/* Sets rumble state for joypad plugged in port 'port'. + * Rumble effects are controlled independently, + * and setting e.g. strong rumble does not override weak rumble. + * Strength has a range of [0, 0xffff]. + * + * Returns true if rumble state request was honored. + * Calling this before first retro_run() is likely to return false. */ +typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port, + enum retro_rumble_effect effect, uint16_t strength); + +struct retro_rumble_interface +{ + retro_set_rumble_state_t set_rumble_state; +}; + +/* Notifies libretro that audio data should be written. */ +typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void); + +/* True: Audio driver in frontend is active, and callback is + * expected to be called regularily. + * False: Audio driver in frontend is paused or inactive. + * Audio callback will not be called until set_state has been + * called with true. + * Initial state is false (inactive). + */ +typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled); + +struct retro_audio_callback +{ + retro_audio_callback_t callback; + retro_audio_set_state_callback_t set_state; +}; + +/* Notifies a libretro core of time spent since last invocation + * of retro_run() in microseconds. + * + * It will be called right before retro_run() every frame. + * The frontend can tamper with timing to support cases like + * fast-forward, slow-motion and framestepping. + * + * In those scenarios the reference frame time value will be used. */ +typedef int64_t retro_usec_t; +typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec); +struct retro_frame_time_callback +{ + retro_frame_time_callback_t callback; + /* Represents the time of one frame. It is computed as + * 1000000 / fps, but the implementation will resolve the + * rounding to ensure that framestepping, etc is exact. */ + retro_usec_t reference; +}; + +/* Notifies a libretro core of the current occupancy + * level of the frontend audio buffer. + * + * - active: 'true' if audio buffer is currently + * in use. Will be 'false' if audio is + * disabled in the frontend + * + * - occupancy: Given as a value in the range [0,100], + * corresponding to the occupancy percentage + * of the audio buffer + * + * - underrun_likely: 'true' if the frontend expects an + * audio buffer underrun during the + * next frame (indicates that a core + * should attempt frame skipping) + * + * It will be called right before retro_run() every frame. */ +typedef void (RETRO_CALLCONV *retro_audio_buffer_status_callback_t)( + bool active, unsigned occupancy, bool underrun_likely); +struct retro_audio_buffer_status_callback +{ + retro_audio_buffer_status_callback_t callback; +}; + +/* Pass this to retro_video_refresh_t if rendering to hardware. + * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. + * */ +#define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) + +/* Invalidates the current HW context. + * Any GL state is lost, and must not be deinitialized explicitly. + * If explicit deinitialization is desired by the libretro core, + * it should implement context_destroy callback. + * If called, all GPU resources must be reinitialized. + * Usually called when frontend reinits video driver. + * Also called first time video driver is initialized, + * allowing libretro core to initialize resources. + */ +typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void); + +/* Gets current framebuffer which is to be rendered to. + * Could change every frame potentially. + */ +typedef uintptr_t (RETRO_CALLCONV *retro_hw_get_current_framebuffer_t)(void); + +/* Get a symbol from HW context. */ +typedef retro_proc_address_t (RETRO_CALLCONV *retro_hw_get_proc_address_t)(const char *sym); + +enum retro_hw_context_type +{ + RETRO_HW_CONTEXT_NONE = 0, + /* OpenGL 2.x. Driver can choose to use latest compatibility context. */ + RETRO_HW_CONTEXT_OPENGL = 1, + /* OpenGL ES 2.0. */ + RETRO_HW_CONTEXT_OPENGLES2 = 2, + /* Modern desktop core GL context. Use version_major/ + * version_minor fields to set GL version. */ + RETRO_HW_CONTEXT_OPENGL_CORE = 3, + /* OpenGL ES 3.0 */ + RETRO_HW_CONTEXT_OPENGLES3 = 4, + /* OpenGL ES 3.1+. Set version_major/version_minor. For GLES2 and GLES3, + * use the corresponding enums directly. */ + RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, + + /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */ + RETRO_HW_CONTEXT_VULKAN = 6, + + /* Direct3D, set version_major to select the type of interface + * returned by RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */ + RETRO_HW_CONTEXT_DIRECT3D = 7, + + RETRO_HW_CONTEXT_DUMMY = INT_MAX +}; + +struct retro_hw_render_callback +{ + /* Which API to use. Set by libretro core. */ + enum retro_hw_context_type context_type; + + /* Called when a context has been created or when it has been reset. + * An OpenGL context is only valid after context_reset() has been called. + * + * When context_reset is called, OpenGL resources in the libretro + * implementation are guaranteed to be invalid. + * + * It is possible that context_reset is called multiple times during an + * application lifecycle. + * If context_reset is called without any notification (context_destroy), + * the OpenGL context was lost and resources should just be recreated + * without any attempt to "free" old resources. + */ + retro_hw_context_reset_t context_reset; + + /* Set by frontend. + * TODO: This is rather obsolete. The frontend should not + * be providing preallocated framebuffers. */ + retro_hw_get_current_framebuffer_t get_current_framebuffer; + + /* Set by frontend. + * Can return all relevant functions, including glClear on Windows. */ + retro_hw_get_proc_address_t get_proc_address; + + /* Set if render buffers should have depth component attached. + * TODO: Obsolete. */ + bool depth; + + /* Set if stencil buffers should be attached. + * TODO: Obsolete. */ + bool stencil; + + /* If depth and stencil are true, a packed 24/8 buffer will be added. + * Only attaching stencil is invalid and will be ignored. */ + + /* Use conventional bottom-left origin convention. If false, + * standard libretro top-left origin semantics are used. + * TODO: Move to GL specific interface. */ + bool bottom_left_origin; + + /* Major version number for core GL context or GLES 3.1+. */ + unsigned version_major; + + /* Minor version number for core GL context or GLES 3.1+. */ + unsigned version_minor; + + /* If this is true, the frontend will go very far to avoid + * resetting context in scenarios like toggling fullscreen, etc. + * TODO: Obsolete? Maybe frontend should just always assume this ... + */ + bool cache_context; + + /* The reset callback might still be called in extreme situations + * such as if the context is lost beyond recovery. + * + * For optimal stability, set this to false, and allow context to be + * reset at any time. + */ + + /* A callback to be called before the context is destroyed in a + * controlled way by the frontend. */ + retro_hw_context_reset_t context_destroy; + + /* OpenGL resources can be deinitialized cleanly at this step. + * context_destroy can be set to NULL, in which resources will + * just be destroyed without any notification. + * + * Even when context_destroy is non-NULL, it is possible that + * context_reset is called without any destroy notification. + * This happens if context is lost by external factors (such as + * notified by GL_ARB_robustness). + * + * In this case, the context is assumed to be already dead, + * and the libretro implementation must not try to free any OpenGL + * resources in the subsequent context_reset. + */ + + /* Creates a debug context. */ + bool debug_context; +}; + +/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. + * Called by the frontend in response to keyboard events. + * down is set if the key is being pressed, or false if it is being released. + * keycode is the RETROK value of the char. + * character is the text character of the pressed key. (UTF-32). + * key_modifiers is a set of RETROKMOD values or'ed together. + * + * The pressed/keycode state can be indepedent of the character. + * It is also possible that multiple characters are generated from a + * single keypress. + * Keycode events should be treated separately from character events. + * However, when possible, the frontend should try to synchronize these. + * If only a character is posted, keycode should be RETROK_UNKNOWN. + * + * Similarily if only a keycode event is generated with no corresponding + * character, character should be 0. + */ +typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode, + uint32_t character, uint16_t key_modifiers); + +struct retro_keyboard_callback +{ + retro_keyboard_event_t callback; +}; + +/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE & + * RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE. + * Should be set for implementations which can swap out multiple disk + * images in runtime. + * + * If the implementation can do this automatically, it should strive to do so. + * However, there are cases where the user must manually do so. + * + * Overview: To swap a disk image, eject the disk image with + * set_eject_state(true). + * Set the disk index with set_image_index(index). Insert the disk again + * with set_eject_state(false). + */ + +/* If ejected is true, "ejects" the virtual disk tray. + * When ejected, the disk image index can be set. + */ +typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected); + +/* Gets current eject state. The initial state is 'not ejected'. */ +typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void); + +/* Gets current disk index. First disk is index 0. + * If return value is >= get_num_images(), no disk is currently inserted. + */ +typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void); + +/* Sets image index. Can only be called when disk is ejected. + * The implementation supports setting "no disk" by using an + * index >= get_num_images(). + */ +typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); + +/* Gets total number of images which are available to use. */ +typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void); + +struct retro_game_info; + +/* Replaces the disk image associated with index. + * Arguments to pass in info have same requirements as retro_load_game(). + * Virtual disk tray must be ejected when calling this. + * + * Replacing a disk image with info = NULL will remove the disk image + * from the internal list. + * As a result, calls to get_image_index() can change. + * + * E.g. replace_image_index(1, NULL), and previous get_image_index() + * returned 4 before. + * Index 1 will be removed, and the new index is 3. + */ +typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index, + const struct retro_game_info *info); + +/* Adds a new valid index (get_num_images()) to the internal disk list. + * This will increment subsequent return values from get_num_images() by 1. + * This image index cannot be used until a disk image has been set + * with replace_image_index. */ +typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void); + +/* Sets initial image to insert in drive when calling + * core_load_game(). + * Since we cannot pass the initial index when loading + * content (this would require a major API change), this + * is set by the frontend *before* calling the core's + * retro_load_game()/retro_load_game_special() implementation. + * A core should therefore cache the index/path values and handle + * them inside retro_load_game()/retro_load_game_special(). + * - If 'index' is invalid (index >= get_num_images()), the + * core should ignore the set value and instead use 0 + * - 'path' is used purely for error checking - i.e. when + * content is loaded, the core should verify that the + * disk specified by 'index' has the specified file path. + * This is to guard against auto selecting the wrong image + * if (for example) the user should modify an existing M3U + * playlist. We have to let the core handle this because + * set_initial_image() must be called before loading content, + * i.e. the frontend cannot access image paths in advance + * and thus cannot perform the error check itself. + * If set path and content path do not match, the core should + * ignore the set 'index' value and instead use 0 + * Returns 'false' if index or 'path' are invalid, or core + * does not support this functionality + */ +typedef bool (RETRO_CALLCONV *retro_set_initial_image_t)(unsigned index, const char *path); + +/* Fetches the path of the specified disk image file. + * Returns 'false' if index is invalid (index >= get_num_images()) + * or path is otherwise unavailable. + */ +typedef bool (RETRO_CALLCONV *retro_get_image_path_t)(unsigned index, char *path, size_t len); + +/* Fetches a core-provided 'label' for the specified disk + * image file. In the simplest case this may be a file name + * (without extension), but for cores with more complex + * content requirements information may be provided to + * facilitate user disk swapping - for example, a core + * running floppy-disk-based content may uniquely label + * save disks, data disks, level disks, etc. with names + * corresponding to in-game disk change prompts (so the + * frontend can provide better user guidance than a 'dumb' + * disk index value). + * Returns 'false' if index is invalid (index >= get_num_images()) + * or label is otherwise unavailable. + */ +typedef bool (RETRO_CALLCONV *retro_get_image_label_t)(unsigned index, char *label, size_t len); + +struct retro_disk_control_callback +{ + retro_set_eject_state_t set_eject_state; + retro_get_eject_state_t get_eject_state; + + retro_get_image_index_t get_image_index; + retro_set_image_index_t set_image_index; + retro_get_num_images_t get_num_images; + + retro_replace_image_index_t replace_image_index; + retro_add_image_index_t add_image_index; +}; + +struct retro_disk_control_ext_callback +{ + retro_set_eject_state_t set_eject_state; + retro_get_eject_state_t get_eject_state; + + retro_get_image_index_t get_image_index; + retro_set_image_index_t set_image_index; + retro_get_num_images_t get_num_images; + + retro_replace_image_index_t replace_image_index; + retro_add_image_index_t add_image_index; + + /* NOTE: Frontend will only attempt to record/restore + * last used disk index if both set_initial_image() + * and get_image_path() are implemented */ + retro_set_initial_image_t set_initial_image; /* Optional - may be NULL */ + + retro_get_image_path_t get_image_path; /* Optional - may be NULL */ + retro_get_image_label_t get_image_label; /* Optional - may be NULL */ +}; + +enum retro_pixel_format +{ + /* 0RGB1555, native endian. + * 0 bit must be set to 0. + * This pixel format is default for compatibility concerns only. + * If a 15/16-bit pixel format is desired, consider using RGB565. */ + RETRO_PIXEL_FORMAT_0RGB1555 = 0, + + /* XRGB8888, native endian. + * X bits are ignored. */ + RETRO_PIXEL_FORMAT_XRGB8888 = 1, + + /* RGB565, native endian. + * This pixel format is the recommended format to use if a 15/16-bit + * format is desired as it is the pixel format that is typically + * available on a wide range of low-power devices. + * + * It is also natively supported in APIs like OpenGL ES. */ + RETRO_PIXEL_FORMAT_RGB565 = 2, + + /* Ensure sizeof() == sizeof(int). */ + RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX +}; + +enum retro_savestate_context +{ + /* Standard savestate written to disk. */ + RETRO_SAVESTATE_CONTEXT_NORMAL = 0, + + /* Savestate where you are guaranteed that the same instance will load the save state. + * You can store internal pointers to code or data. + * It's still a full serialization and deserialization, and could be loaded or saved at any time. + * It won't be written to disk or sent over the network. + */ + RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_INSTANCE = 1, + + /* Savestate where you are guaranteed that the same emulator binary will load that savestate. + * You can skip anything that would slow down saving or loading state but you can not store internal pointers. + * It won't be written to disk or sent over the network. + * Example: "Second Instance" runahead + */ + RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_BINARY = 2, + + /* Savestate used within a rollback netplay feature. + * You should skip anything that would unnecessarily increase bandwidth usage. + * It won't be written to disk but it will be sent over the network. + */ + RETRO_SAVESTATE_CONTEXT_ROLLBACK_NETPLAY = 3, + + /* Ensure sizeof() == sizeof(int). */ + RETRO_SAVESTATE_CONTEXT_UNKNOWN = INT_MAX +}; + +struct retro_message +{ + const char *msg; /* Message to be displayed. */ + unsigned frames; /* Duration in frames of message. */ +}; + +enum retro_message_target +{ + RETRO_MESSAGE_TARGET_ALL = 0, + RETRO_MESSAGE_TARGET_OSD, + RETRO_MESSAGE_TARGET_LOG +}; + +enum retro_message_type +{ + RETRO_MESSAGE_TYPE_NOTIFICATION = 0, + RETRO_MESSAGE_TYPE_NOTIFICATION_ALT, + RETRO_MESSAGE_TYPE_STATUS, + RETRO_MESSAGE_TYPE_PROGRESS +}; + +struct retro_message_ext +{ + /* Message string to be displayed/logged */ + const char *msg; + /* Duration (in ms) of message when targeting the OSD */ + unsigned duration; + /* Message priority when targeting the OSD + * > When multiple concurrent messages are sent to + * the frontend and the frontend does not have the + * capacity to display them all, messages with the + * *highest* priority value should be shown + * > There is no upper limit to a message priority + * value (within the bounds of the unsigned data type) + * > In the reference frontend (RetroArch), the same + * priority values are used for frontend-generated + * notifications, which are typically assigned values + * between 0 and 3 depending upon importance */ + unsigned priority; + /* Message logging level (info, warn, error, etc.) */ + enum retro_log_level level; + /* Message destination: OSD, logging interface or both */ + enum retro_message_target target; + /* Message 'type' when targeting the OSD + * > RETRO_MESSAGE_TYPE_NOTIFICATION: Specifies that a + * message should be handled in identical fashion to + * a standard frontend-generated notification + * > RETRO_MESSAGE_TYPE_NOTIFICATION_ALT: Specifies that + * message is a notification that requires user attention + * or action, but that it should be displayed in a manner + * that differs from standard frontend-generated notifications. + * This would typically correspond to messages that should be + * displayed immediately (independently from any internal + * frontend message queue), and/or which should be visually + * distinguishable from frontend-generated notifications. + * For example, a core may wish to inform the user of + * information related to a disk-change event. It is + * expected that the frontend itself may provide a + * notification in this case; if the core sends a + * message of type RETRO_MESSAGE_TYPE_NOTIFICATION, an + * uncomfortable 'double-notification' may occur. A message + * of RETRO_MESSAGE_TYPE_NOTIFICATION_ALT should therefore + * be presented such that visual conflict with regular + * notifications does not occur + * > RETRO_MESSAGE_TYPE_STATUS: Indicates that message + * is not a standard notification. This typically + * corresponds to 'status' indicators, such as a core's + * internal FPS, which are intended to be displayed + * either permanently while a core is running, or in + * a manner that does not suggest user attention or action + * is required. 'Status' type messages should therefore be + * displayed in a different on-screen location and in a manner + * easily distinguishable from both standard frontend-generated + * notifications and messages of type RETRO_MESSAGE_TYPE_NOTIFICATION_ALT + * > RETRO_MESSAGE_TYPE_PROGRESS: Indicates that message reports + * the progress of an internal core task. For example, in cases + * where a core itself handles the loading of content from a file, + * this may correspond to the percentage of the file that has been + * read. Alternatively, an audio/video playback core may use a + * message of type RETRO_MESSAGE_TYPE_PROGRESS to display the current + * playback position as a percentage of the runtime. 'Progress' type + * messages should therefore be displayed as a literal progress bar, + * where: + * - 'retro_message_ext.msg' is the progress bar title/label + * - 'retro_message_ext.progress' determines the length of + * the progress bar + * NOTE: Message type is a *hint*, and may be ignored + * by the frontend. If a frontend lacks support for + * displaying messages via alternate means than standard + * frontend-generated notifications, it will treat *all* + * messages as having the type RETRO_MESSAGE_TYPE_NOTIFICATION */ + enum retro_message_type type; + /* Task progress when targeting the OSD and message is + * of type RETRO_MESSAGE_TYPE_PROGRESS + * > -1: Unmetered/indeterminate + * > 0-100: Current progress percentage + * NOTE: Since message type is a hint, a frontend may ignore + * progress values. Where relevant, a core should therefore + * include progress percentage within the message string, + * such that the message intent remains clear when displayed + * as a standard frontend-generated notification */ + int8_t progress; +}; + +/* Describes how the libretro implementation maps a libretro input bind + * to its internal input system through a human readable string. + * This string can be used to better let a user configure input. */ +struct retro_input_descriptor +{ + /* Associates given parameters with a description. */ + unsigned port; + unsigned device; + unsigned index; + unsigned id; + + /* Human readable description for parameters. + * The pointer must remain valid until + * retro_unload_game() is called. */ + const char *description; +}; + +struct retro_system_info +{ + /* All pointers are owned by libretro implementation, and pointers must + * remain valid until it is unloaded. */ + + const char *library_name; /* Descriptive name of library. Should not + * contain any version numbers, etc. */ + const char *library_version; /* Descriptive version of core. */ + + const char *valid_extensions; /* A string listing probably content + * extensions the core will be able to + * load, separated with pipe. + * I.e. "bin|rom|iso". + * Typically used for a GUI to filter + * out extensions. */ + + /* Libretro cores that need to have direct access to their content + * files, including cores which use the path of the content files to + * determine the paths of other files, should set need_fullpath to true. + * + * Cores should strive for setting need_fullpath to false, + * as it allows the frontend to perform patching, etc. + * + * If need_fullpath is true and retro_load_game() is called: + * - retro_game_info::path is guaranteed to have a valid path + * - retro_game_info::data and retro_game_info::size are invalid + * + * If need_fullpath is false and retro_load_game() is called: + * - retro_game_info::path may be NULL + * - retro_game_info::data and retro_game_info::size are guaranteed + * to be valid + * + * See also: + * - RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY + * - RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY + */ + bool need_fullpath; + + /* If true, the frontend is not allowed to extract any archives before + * loading the real content. + * Necessary for certain libretro implementations that load games + * from zipped archives. */ + bool block_extract; +}; + +/* Defines overrides which modify frontend handling of + * specific content file types. + * An array of retro_system_content_info_override is + * passed to RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE + * NOTE: In the following descriptions, references to + * retro_load_game() may be replaced with + * retro_load_game_special() */ +struct retro_system_content_info_override +{ + /* A list of file extensions for which the override + * should apply, delimited by a 'pipe' character + * (e.g. "md|sms|gg") + * Permitted file extensions are limited to those + * included in retro_system_info::valid_extensions + * and/or retro_subsystem_rom_info::valid_extensions */ + const char *extensions; + + /* Overrides the need_fullpath value set in + * retro_system_info and/or retro_subsystem_rom_info. + * To reiterate: + * + * If need_fullpath is true and retro_load_game() is called: + * - retro_game_info::path is guaranteed to contain a valid + * path to an existent file + * - retro_game_info::data and retro_game_info::size are invalid + * + * If need_fullpath is false and retro_load_game() is called: + * - retro_game_info::path may be NULL + * - retro_game_info::data and retro_game_info::size are guaranteed + * to be valid + * + * In addition: + * + * If need_fullpath is true and retro_load_game() is called: + * - retro_game_info_ext::full_path is guaranteed to contain a valid + * path to an existent file + * - retro_game_info_ext::archive_path may be NULL + * - retro_game_info_ext::archive_file may be NULL + * - retro_game_info_ext::dir is guaranteed to contain a valid path + * to the directory in which the content file exists + * - retro_game_info_ext::name is guaranteed to contain the + * basename of the content file, without extension + * - retro_game_info_ext::ext is guaranteed to contain the + * extension of the content file in lower case format + * - retro_game_info_ext::data and retro_game_info_ext::size + * are invalid + * + * If need_fullpath is false and retro_load_game() is called: + * - If retro_game_info_ext::file_in_archive is false: + * - retro_game_info_ext::full_path is guaranteed to contain + * a valid path to an existent file + * - retro_game_info_ext::archive_path may be NULL + * - retro_game_info_ext::archive_file may be NULL + * - retro_game_info_ext::dir is guaranteed to contain a + * valid path to the directory in which the content file exists + * - retro_game_info_ext::name is guaranteed to contain the + * basename of the content file, without extension + * - retro_game_info_ext::ext is guaranteed to contain the + * extension of the content file in lower case format + * - If retro_game_info_ext::file_in_archive is true: + * - retro_game_info_ext::full_path may be NULL + * - retro_game_info_ext::archive_path is guaranteed to + * contain a valid path to an existent compressed file + * inside which the content file is located + * - retro_game_info_ext::archive_file is guaranteed to + * contain a valid path to an existent content file + * inside the compressed file referred to by + * retro_game_info_ext::archive_path + * e.g. for a compressed file '/path/to/foo.zip' + * containing 'bar.sfc' + * > retro_game_info_ext::archive_path will be '/path/to/foo.zip' + * > retro_game_info_ext::archive_file will be 'bar.sfc' + * - retro_game_info_ext::dir is guaranteed to contain a + * valid path to the directory in which the compressed file + * (containing the content file) exists + * - retro_game_info_ext::name is guaranteed to contain + * EITHER + * 1) the basename of the compressed file (containing + * the content file), without extension + * OR + * 2) the basename of the content file inside the + * compressed file, without extension + * In either case, a core should consider 'name' to + * be the canonical name/ID of the the content file + * - retro_game_info_ext::ext is guaranteed to contain the + * extension of the content file inside the compressed file, + * in lower case format + * - retro_game_info_ext::data and retro_game_info_ext::size are + * guaranteed to be valid */ + bool need_fullpath; + + /* If need_fullpath is false, specifies whether the content + * data buffer available in retro_load_game() is 'persistent' + * + * If persistent_data is false and retro_load_game() is called: + * - retro_game_info::data and retro_game_info::size + * are valid only until retro_load_game() returns + * - retro_game_info_ext::data and retro_game_info_ext::size + * are valid only until retro_load_game() returns + * + * If persistent_data is true and retro_load_game() is called: + * - retro_game_info::data and retro_game_info::size + * are valid until retro_deinit() returns + * - retro_game_info_ext::data and retro_game_info_ext::size + * are valid until retro_deinit() returns */ + bool persistent_data; +}; + +/* Similar to retro_game_info, but provides extended + * information about the source content file and + * game memory buffer status. + * And array of retro_game_info_ext is returned by + * RETRO_ENVIRONMENT_GET_GAME_INFO_EXT + * NOTE: In the following descriptions, references to + * retro_load_game() may be replaced with + * retro_load_game_special() */ +struct retro_game_info_ext +{ + /* - If file_in_archive is false, contains a valid + * path to an existent content file (UTF-8 encoded) + * - If file_in_archive is true, may be NULL */ + const char *full_path; + + /* - If file_in_archive is false, may be NULL + * - If file_in_archive is true, contains a valid path + * to an existent compressed file inside which the + * content file is located (UTF-8 encoded) */ + const char *archive_path; + + /* - If file_in_archive is false, may be NULL + * - If file_in_archive is true, contain a valid path + * to an existent content file inside the compressed + * file referred to by archive_path (UTF-8 encoded) + * e.g. for a compressed file '/path/to/foo.zip' + * containing 'bar.sfc' + * > archive_path will be '/path/to/foo.zip' + * > archive_file will be 'bar.sfc' */ + const char *archive_file; + + /* - If file_in_archive is false, contains a valid path + * to the directory in which the content file exists + * (UTF-8 encoded) + * - If file_in_archive is true, contains a valid path + * to the directory in which the compressed file + * (containing the content file) exists (UTF-8 encoded) */ + const char *dir; + + /* Contains the canonical name/ID of the content file + * (UTF-8 encoded). Intended for use when identifying + * 'complementary' content named after the loaded file - + * i.e. companion data of a different format (a CD image + * required by a ROM), texture packs, internally handled + * save files, etc. + * - If file_in_archive is false, contains the basename + * of the content file, without extension + * - If file_in_archive is true, then string is + * implementation specific. A frontend may choose to + * set a name value of: + * EITHER + * 1) the basename of the compressed file (containing + * the content file), without extension + * OR + * 2) the basename of the content file inside the + * compressed file, without extension + * RetroArch sets the 'name' value according to (1). + * A frontend that supports routine loading of + * content from archives containing multiple unrelated + * content files may set the 'name' value according + * to (2). */ + const char *name; + + /* - If file_in_archive is false, contains the extension + * of the content file in lower case format + * - If file_in_archive is true, contains the extension + * of the content file inside the compressed file, + * in lower case format */ + const char *ext; + + /* String of implementation specific meta-data. */ + const char *meta; + + /* Memory buffer of loaded game content. Will be NULL: + * IF + * - retro_system_info::need_fullpath is true and + * retro_system_content_info_override::need_fullpath + * is unset + * OR + * - retro_system_content_info_override::need_fullpath + * is true */ + const void *data; + + /* Size of game content memory buffer, in bytes */ + size_t size; + + /* True if loaded content file is inside a compressed + * archive */ + bool file_in_archive; + + /* - If data is NULL, value is unset/ignored + * - If data is non-NULL: + * - If persistent_data is false, data and size are + * valid only until retro_load_game() returns + * - If persistent_data is true, data and size are + * are valid until retro_deinit() returns */ + bool persistent_data; +}; + +struct retro_game_geometry +{ + unsigned base_width; /* Nominal video width of game. */ + unsigned base_height; /* Nominal video height of game. */ + unsigned max_width; /* Maximum possible width of game. */ + unsigned max_height; /* Maximum possible height of game. */ + + float aspect_ratio; /* Nominal aspect ratio of game. If + * aspect_ratio is <= 0.0, an aspect ratio + * of base_width / base_height is assumed. + * A frontend could override this setting, + * if desired. */ +}; + +struct retro_system_timing +{ + double fps; /* FPS of video content. */ + double sample_rate; /* Sampling rate of audio. */ +}; + +struct retro_system_av_info +{ + struct retro_game_geometry geometry; + struct retro_system_timing timing; +}; + +struct retro_variable +{ + /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + * If NULL, obtains the complete environment string if more + * complex parsing is necessary. + * The environment string is formatted as key-value pairs + * delimited by semicolons as so: + * "key1=value1;key2=value2;..." + */ + const char *key; + + /* Value to be obtained. If key does not exist, it is set to NULL. */ + const char *value; +}; + +struct retro_core_option_display +{ + /* Variable to configure in RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY */ + const char *key; + + /* Specifies whether variable should be displayed + * when presenting core options to the user */ + bool visible; +}; + +/* Maximum number of values permitted for a core option + * > Note: We have to set a maximum value due the limitations + * of the C language - i.e. it is not possible to create an + * array of structs each containing a variable sized array, + * so the retro_core_option_definition values array must + * have a fixed size. The size limit of 128 is a balancing + * act - it needs to be large enough to support all 'sane' + * core options, but setting it too large may impact low memory + * platforms. In practise, if a core option has more than + * 128 values then the implementation is likely flawed. + * To quote the above API reference: + * "The number of possible options should be very limited + * i.e. it should be feasible to cycle through options + * without a keyboard." + */ +#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128 + +struct retro_core_option_value +{ + /* Expected option value */ + const char *value; + + /* Human-readable value label. If NULL, value itself + * will be displayed by the frontend */ + const char *label; +}; + +struct retro_core_option_definition +{ + /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. */ + const char *key; + + /* Human-readable core option description (used as menu label) */ + const char *desc; + + /* Human-readable core option information (used as menu sublabel) */ + const char *info; + + /* Array of retro_core_option_value structs, terminated by NULL */ + struct retro_core_option_value values[RETRO_NUM_CORE_OPTION_VALUES_MAX]; + + /* Default core option value. Must match one of the values + * in the retro_core_option_value array, otherwise will be + * ignored */ + const char *default_value; +}; + +#ifdef __PS3__ +#undef local +#endif + +struct retro_core_options_intl +{ + /* Pointer to an array of retro_core_option_definition structs + * - US English implementation + * - Must point to a valid array */ + struct retro_core_option_definition *us; + + /* Pointer to an array of retro_core_option_definition structs + * - Implementation for current frontend language + * - May be NULL */ + struct retro_core_option_definition *local; +}; + +struct retro_core_option_v2_category +{ + /* Variable uniquely identifying the + * option category. Valid key characters + * are [a-z, A-Z, 0-9, _, -] */ + const char *key; + + /* Human-readable category description + * > Used as category menu label when + * frontend has core option category + * support */ + const char *desc; + + /* Human-readable category information + * > Used as category menu sublabel when + * frontend has core option category + * support + * > Optional (may be NULL or an empty + * string) */ + const char *info; +}; + +struct retro_core_option_v2_definition +{ + /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + * Valid key characters are [a-z, A-Z, 0-9, _, -] */ + const char *key; + + /* Human-readable core option description + * > Used as menu label when frontend does + * not have core option category support + * e.g. "Video > Aspect Ratio" */ + const char *desc; + + /* Human-readable core option description + * > Used as menu label when frontend has + * core option category support + * e.g. "Aspect Ratio", where associated + * retro_core_option_v2_category::desc + * is "Video" + * > If empty or NULL, the string specified by + * desc will be used as the menu label + * > Will be ignored (and may be set to NULL) + * if category_key is empty or NULL */ + const char *desc_categorized; + + /* Human-readable core option information + * > Used as menu sublabel */ + const char *info; + + /* Human-readable core option information + * > Used as menu sublabel when frontend + * has core option category support + * (e.g. may be required when info text + * references an option by name/desc, + * and the desc/desc_categorized text + * for that option differ) + * > If empty or NULL, the string specified by + * info will be used as the menu sublabel + * > Will be ignored (and may be set to NULL) + * if category_key is empty or NULL */ + const char *info_categorized; + + /* Variable specifying category (e.g. "video", + * "audio") that will be assigned to the option + * if frontend has core option category support. + * > Categorized options will be displayed in a + * subsection/submenu of the frontend core + * option interface + * > Specified string must match one of the + * retro_core_option_v2_category::key values + * in the associated retro_core_option_v2_category + * array; If no match is not found, specified + * string will be considered as NULL + * > If specified string is empty or NULL, option will + * have no category and will be shown at the top + * level of the frontend core option interface */ + const char *category_key; + + /* Array of retro_core_option_value structs, terminated by NULL */ + struct retro_core_option_value values[RETRO_NUM_CORE_OPTION_VALUES_MAX]; + + /* Default core option value. Must match one of the values + * in the retro_core_option_value array, otherwise will be + * ignored */ + const char *default_value; +}; + +struct retro_core_options_v2 +{ + /* Array of retro_core_option_v2_category structs, + * terminated by NULL + * > If NULL, all entries in definitions array + * will have no category and will be shown at + * the top level of the frontend core option + * interface + * > Will be ignored if frontend does not have + * core option category support */ + struct retro_core_option_v2_category *categories; + + /* Array of retro_core_option_v2_definition structs, + * terminated by NULL */ + struct retro_core_option_v2_definition *definitions; +}; + +struct retro_core_options_v2_intl +{ + /* Pointer to a retro_core_options_v2 struct + * > US English implementation + * > Must point to a valid struct */ + struct retro_core_options_v2 *us; + + /* Pointer to a retro_core_options_v2 struct + * - Implementation for current frontend language + * - May be NULL */ + struct retro_core_options_v2 *local; +}; + +/* Used by the frontend to monitor changes in core option + * visibility. May be called each time any core option + * value is set via the frontend. + * - On each invocation, the core must update the visibility + * of any dynamically hidden options using the + * RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY environment + * callback. + * - On the first invocation, returns 'true' if the visibility + * of any core option has changed since the last call of + * retro_load_game() or retro_load_game_special(). + * - On each subsequent invocation, returns 'true' if the + * visibility of any core option has changed since the last + * time the function was called. */ +typedef bool (RETRO_CALLCONV *retro_core_options_update_display_callback_t)(void); +struct retro_core_options_update_display_callback +{ + retro_core_options_update_display_callback_t callback; +}; + +struct retro_game_info +{ + const char *path; /* Path to game, UTF-8 encoded. + * Sometimes used as a reference for building other paths. + * May be NULL if game was loaded from stdin or similar, + * but in this case some cores will be unable to load `data`. + * So, it is preferable to fabricate something here instead + * of passing NULL, which will help more cores to succeed. + * retro_system_info::need_fullpath requires + * that this path is valid. */ + const void *data; /* Memory buffer of loaded game. Will be NULL + * if need_fullpath was set. */ + size_t size; /* Size of memory buffer. */ + const char *meta; /* String of implementation specific meta-data. */ +}; + +#define RETRO_MEMORY_ACCESS_WRITE (1 << 0) + /* The core will write to the buffer provided by retro_framebuffer::data. */ +#define RETRO_MEMORY_ACCESS_READ (1 << 1) + /* The core will read from retro_framebuffer::data. */ +#define RETRO_MEMORY_TYPE_CACHED (1 << 0) + /* The memory in data is cached. + * If not cached, random writes and/or reading from the buffer is expected to be very slow. */ +struct retro_framebuffer +{ + void *data; /* The framebuffer which the core can render into. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. + The initial contents of data are unspecified. */ + unsigned width; /* The framebuffer width used by the core. Set by core. */ + unsigned height; /* The framebuffer height used by the core. Set by core. */ + size_t pitch; /* The number of bytes between the beginning of a scanline, + and beginning of the next scanline. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + enum retro_pixel_format format; /* The pixel format the core must use to render into data. + This format could differ from the format used in + SET_PIXEL_FORMAT. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + + unsigned access_flags; /* How the core will access the memory in the framebuffer. + RETRO_MEMORY_ACCESS_* flags. + Set by core. */ + unsigned memory_flags; /* Flags telling core how the memory has been mapped. + RETRO_MEMORY_TYPE_* flags. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ +}; + +/* Used by a libretro core to override the current + * fastforwarding mode of the frontend */ +struct retro_fastforwarding_override +{ + /* Specifies the runtime speed multiplier that + * will be applied when 'fastforward' is true. + * For example, a value of 5.0 when running 60 FPS + * content will cap the fast-forward rate at 300 FPS. + * Note that the target multiplier may not be achieved + * if the host hardware has insufficient processing + * power. + * Setting a value of 0.0 (or greater than 0.0 but + * less than 1.0) will result in an uncapped + * fast-forward rate (limited only by hardware + * capacity). + * If the value is negative, it will be ignored + * (i.e. the frontend will use a runtime speed + * multiplier of its own choosing) */ + float ratio; + + /* If true, fastforwarding mode will be enabled. + * If false, fastforwarding mode will be disabled. */ + bool fastforward; + + /* If true, and if supported by the frontend, an + * on-screen notification will be displayed while + * 'fastforward' is true. + * If false, and if supported by the frontend, any + * on-screen fast-forward notifications will be + * suppressed */ + bool notification; + + /* If true, the core will have sole control over + * when fastforwarding mode is enabled/disabled; + * the frontend will not be able to change the + * state set by 'fastforward' until either + * 'inhibit_toggle' is set to false, or the core + * is unloaded */ + bool inhibit_toggle; +}; + +/* During normal operation. Rate will be equal to the core's internal FPS. */ +#define RETRO_THROTTLE_NONE 0 + +/* While paused or stepping single frames. Rate will be 0. */ +#define RETRO_THROTTLE_FRAME_STEPPING 1 + +/* During fast forwarding. + * Rate will be 0 if not specifically limited to a maximum speed. */ +#define RETRO_THROTTLE_FAST_FORWARD 2 + +/* During slow motion. Rate will be less than the core's internal FPS. */ +#define RETRO_THROTTLE_SLOW_MOTION 3 + +/* While rewinding recorded save states. Rate can vary depending on the rewind + * speed or be 0 if the frontend is not aiming for a specific rate. */ +#define RETRO_THROTTLE_REWINDING 4 + +/* While vsync is active in the video driver and the target refresh rate is + * lower than the core's internal FPS. Rate is the target refresh rate. */ +#define RETRO_THROTTLE_VSYNC 5 + +/* When the frontend does not throttle in any way. Rate will be 0. + * An example could be if no vsync or audio output is active. */ +#define RETRO_THROTTLE_UNBLOCKED 6 + +struct retro_throttle_state +{ + /* The current throttling mode. Should be one of the values above. */ + unsigned mode; + + /* How many times per second the frontend aims to call retro_run. + * Depending on the mode, it can be 0 if there is no known fixed rate. + * This won't be accurate if the total processing time of the core and + * the frontend is longer than what is available for one frame. */ + float rate; +}; + +/* Callbacks */ + +/* Environment callback. Gives implementations a way of performing + * uncommon tasks. Extensible. */ +typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); + +/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian + * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). + * + * Width and height specify dimensions of buffer. + * Pitch specifices length in bytes between two lines in buffer. + * + * For performance reasons, it is highly recommended to have a frame + * that is packed in memory, i.e. pitch == width * byte_per_pixel. + * Certain graphic APIs, such as OpenGL ES, do not like textures + * that are not packed in memory. + */ +typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width, + unsigned height, size_t pitch); + +/* Renders a single audio frame. Should only be used if implementation + * generates a single sample at a time. + * Format is signed 16-bit native endian. + */ +typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right); + +/* Renders multiple audio frames in one go. + * + * One frame is defined as a sample of left and right channels, interleaved. + * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. + * Only one of the audio callbacks must ever be used. + */ +typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data, + size_t frames); + +/* Polls input. */ +typedef void (RETRO_CALLCONV *retro_input_poll_t)(void); + +/* Queries for input for player 'port'. device will be masked with + * RETRO_DEVICE_MASK. + * + * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that + * have been set with retro_set_controller_port_device() + * will still use the higher level RETRO_DEVICE_JOYPAD to request input. + */ +typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device, + unsigned index, unsigned id); + +/* Sets callbacks. retro_set_environment() is guaranteed to be called + * before retro_init(). + * + * The rest of the set_* functions are guaranteed to have been called + * before the first call to retro_run() is made. */ +RETRO_API void retro_set_environment(retro_environment_t); +RETRO_API void retro_set_video_refresh(retro_video_refresh_t); +RETRO_API void retro_set_audio_sample(retro_audio_sample_t); +RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t); +RETRO_API void retro_set_input_poll(retro_input_poll_t); +RETRO_API void retro_set_input_state(retro_input_state_t); + +/* Library global initialization/deinitialization. */ +RETRO_API void retro_init(void); +RETRO_API void retro_deinit(void); + +/* Must return RETRO_API_VERSION. Used to validate ABI compatibility + * when the API is revised. */ +RETRO_API unsigned retro_api_version(void); + +/* Gets statically known system info. Pointers provided in *info + * must be statically allocated. + * Can be called at any time, even before retro_init(). */ +RETRO_API void retro_get_system_info(struct retro_system_info *info); + +/* Gets information about system audio/video timings and geometry. + * Can be called only after retro_load_game() has successfully completed. + * NOTE: The implementation of this function might not initialize every + * variable if needed. + * E.g. geom.aspect_ratio might not be initialized if core doesn't + * desire a particular aspect ratio. */ +RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info); + +/* Sets device to be used for player 'port'. + * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all + * available ports. + * Setting a particular device type is not a guarantee that libretro cores + * will only poll input based on that particular device type. It is only a + * hint to the libretro core when a core cannot automatically detect the + * appropriate input device type on its own. It is also relevant when a + * core can change its behavior depending on device type. + * + * As part of the core's implementation of retro_set_controller_port_device, + * the core should call RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS to notify the + * frontend if the descriptions for any controls have changed as a + * result of changing the device type. + */ +RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); + +/* Resets the current game. */ +RETRO_API void retro_reset(void); + +/* Runs the game for one video frame. + * During retro_run(), input_poll callback must be called at least once. + * + * If a frame is not rendered for reasons where a game "dropped" a frame, + * this still counts as a frame, and retro_run() should explicitly dupe + * a frame if GET_CAN_DUPE returns true. + * In this case, the video callback can take a NULL argument for data. + */ +RETRO_API void retro_run(void); + +/* Returns the amount of data the implementation requires to serialize + * internal state (save states). + * Between calls to retro_load_game() and retro_unload_game(), the + * returned size is never allowed to be larger than a previous returned + * value, to ensure that the frontend can allocate a save state buffer once. + */ +RETRO_API size_t retro_serialize_size(void); + +/* Serializes internal state. If failed, or size is lower than + * retro_serialize_size(), it should return false, true otherwise. */ +RETRO_API bool retro_serialize(void *data, size_t size); +RETRO_API bool retro_unserialize(const void *data, size_t size); + +RETRO_API void retro_cheat_reset(void); +RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code); + +/* Loads a game. + * Return true to indicate successful loading and false to indicate load failure. + */ +RETRO_API bool retro_load_game(const struct retro_game_info *game); + +/* Loads a "special" kind of game. Should not be used, + * except in extreme cases. */ +RETRO_API bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info +); + +/* Unloads the currently loaded game. Called before retro_deinit(void). */ +RETRO_API void retro_unload_game(void); + +/* Gets region of game. */ +RETRO_API unsigned retro_get_region(void); + +/* Gets region of memory. */ +RETRO_API void *retro_get_memory_data(unsigned id); +RETRO_API size_t retro_get_memory_size(unsigned id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/libretro/libretro_vulkan.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/libretro/libretro_vulkan.h new file mode 100644 index 00000000..bfc93af5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/platforms/libretro/libretro_vulkan.h @@ -0,0 +1,494 @@ +/* Copyright (C) 2010-2020 The RetroArch team + * + * --------------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro API header (libretro_vulkan.h) + * --------------------------------------------------------------------------------------------- + * + * 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. + */ + +#ifndef LIBRETRO_VULKAN_H__ +#define LIBRETRO_VULKAN_H__ + +#include +#include + +#define RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION 5 +#define RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION 2 + +struct retro_vulkan_image +{ + VkImageView image_view; + VkImageLayout image_layout; + VkImageViewCreateInfo create_info; +}; + +typedef void (*retro_vulkan_set_image_t)(void *handle, + const struct retro_vulkan_image *image, + uint32_t num_semaphores, + const VkSemaphore *semaphores, + uint32_t src_queue_family); + +typedef uint32_t (*retro_vulkan_get_sync_index_t)(void *handle); +typedef uint32_t (*retro_vulkan_get_sync_index_mask_t)(void *handle); +typedef void (*retro_vulkan_set_command_buffers_t)(void *handle, + uint32_t num_cmd, + const VkCommandBuffer *cmd); +typedef void (*retro_vulkan_wait_sync_index_t)(void *handle); +typedef void (*retro_vulkan_lock_queue_t)(void *handle); +typedef void (*retro_vulkan_unlock_queue_t)(void *handle); +typedef void (*retro_vulkan_set_signal_semaphore_t)(void *handle, VkSemaphore semaphore); + +typedef const VkApplicationInfo *(*retro_vulkan_get_application_info_t)(void); + +struct retro_vulkan_context +{ + VkPhysicalDevice gpu; + VkDevice device; + VkQueue queue; + uint32_t queue_family_index; + VkQueue presentation_queue; + uint32_t presentation_queue_family_index; +}; + +/* This is only used in v1 of the negotiation interface. + * It is deprecated since it cannot express PDF2 features or optional extensions. */ +typedef bool (*retro_vulkan_create_device_t)( + struct retro_vulkan_context *context, + VkInstance instance, + VkPhysicalDevice gpu, + VkSurfaceKHR surface, + PFN_vkGetInstanceProcAddr get_instance_proc_addr, + const char **required_device_extensions, + unsigned num_required_device_extensions, + const char **required_device_layers, + unsigned num_required_device_layers, + const VkPhysicalDeviceFeatures *required_features); + +typedef void (*retro_vulkan_destroy_device_t)(void); + +/* v2 CONTEXT_NEGOTIATION_INTERFACE only. */ +typedef VkInstance (*retro_vulkan_create_instance_wrapper_t)( + void *opaque, const VkInstanceCreateInfo *create_info); + +/* v2 CONTEXT_NEGOTIATION_INTERFACE only. */ +typedef VkInstance (*retro_vulkan_create_instance_t)( + PFN_vkGetInstanceProcAddr get_instance_proc_addr, + const VkApplicationInfo *app, + retro_vulkan_create_instance_wrapper_t create_instance_wrapper, + void *opaque); + +/* v2 CONTEXT_NEGOTIATION_INTERFACE only. */ +typedef VkDevice (*retro_vulkan_create_device_wrapper_t)( + VkPhysicalDevice gpu, void *opaque, + const VkDeviceCreateInfo *create_info); + +/* v2 CONTEXT_NEGOTIATION_INTERFACE only. */ +typedef bool (*retro_vulkan_create_device2_t)( + struct retro_vulkan_context *context, + VkInstance instance, + VkPhysicalDevice gpu, + VkSurfaceKHR surface, + PFN_vkGetInstanceProcAddr get_instance_proc_addr, + retro_vulkan_create_device_wrapper_t create_device_wrapper, + void *opaque); + +/* Note on thread safety: + * The Vulkan API is heavily designed around multi-threading, and + * the libretro interface for it should also be threading friendly. + * A core should be able to build command buffers and submit + * command buffers to the GPU from any thread. + */ + +struct retro_hw_render_context_negotiation_interface_vulkan +{ + /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN. */ + enum retro_hw_render_context_negotiation_interface_type interface_type; + /* Usually set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION, + * but can be lower depending on GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT. */ + unsigned interface_version; + + /* If non-NULL, returns a VkApplicationInfo struct that the frontend can use instead of + * its "default" application info. + * VkApplicationInfo::apiVersion also controls the target core Vulkan version for instance level functionality. + * Lifetime of the returned pointer must remain until the retro_vulkan_context is initialized. + * + * NOTE: For optimal compatibility with e.g. Android which is very slow to update its loader, + * a core version of 1.1 should be requested. Features beyond that can be requested with extensions. + * Vulkan 1.0 is only appropriate for legacy cores, but is still supported. + * A frontend is free to bump the instance creation apiVersion as necessary if the frontend requires more advanced core features. + * + * v2: This function must not be NULL, and must not return NULL. + * v1: It was not clearly defined if this function could return NULL. + * Frontends should be defensive and provide a default VkApplicationInfo + * if this function returns NULL or if this function is NULL. + */ + retro_vulkan_get_application_info_t get_application_info; + + /* If non-NULL, the libretro core will choose one or more physical devices, + * create one or more logical devices and create one or more queues. + * The core must prepare a designated PhysicalDevice, Device, Queue and queue family index + * which the frontend will use for its internal operation. + * + * If gpu is not VK_NULL_HANDLE, the physical device provided to the frontend must be this PhysicalDevice if the call succeeds. + * The core is still free to use other physical devices for other purposes that are private to the core. + * + * The frontend will request certain extensions and layers for a device which is created. + * The core must ensure that the queue and queue_family_index support GRAPHICS and COMPUTE. + * + * If surface is not VK_NULL_HANDLE, the core must consider presentation when creating the queues. + * If presentation to "surface" is supported on the queue, presentation_queue must be equal to queue. + * If not, a second queue must be provided in presentation_queue and presentation_queue_index. + * If surface is not VK_NULL_HANDLE, the instance from frontend will have been created with supported for + * VK_KHR_surface extension. + * + * The core is free to set its own queue priorities. + * Device provided to frontend is owned by the frontend, but any additional device resources must be freed by core + * in destroy_device callback. + * + * If this function returns true, a PhysicalDevice, Device and Queues are initialized. + * If false, none of the above have been initialized and the frontend will attempt + * to fallback to "default" device creation, as if this function was never called. + */ + retro_vulkan_create_device_t create_device; + + /* If non-NULL, this callback is called similar to context_destroy for HW_RENDER_INTERFACE. + * However, it will be called even if context_reset was not called. + * This can happen if the context never succeeds in being created. + * destroy_device will always be called before the VkInstance + * of the frontend is destroyed if create_device was called successfully so that the core has a chance of + * tearing down its own device resources. + * + * Only auxillary resources should be freed here, i.e. resources which are not part of retro_vulkan_context. + * v2: Auxillary instance resources created during create_instance can also be freed here. + */ + retro_vulkan_destroy_device_t destroy_device; + + /* v2 API: If interface_version is < 2, fields below must be ignored. + * If the frontend does not support interface version 2, the v1 entry points will be used instead. */ + + /* If non-NULL, this is called to create an instance, otherwise a VkInstance is created by the frontend. + * v1 interface bug: The only way to enable instance features is through core versions signalled in VkApplicationInfo. + * The frontend may request that certain extensions and layers + * are enabled on the VkInstance. Application may add additional features. + * If app is non-NULL, apiVersion controls the minimum core version required by the application. + * Return a VkInstance or VK_NULL_HANDLE. The VkInstance is owned by the frontend. + * + * Rather than call vkCreateInstance directly, a core must call the CreateInstance wrapper provided with: + * VkInstance instance = create_instance_wrapper(opaque, &create_info); + * If the core wishes to create a private instance for whatever reason (relying on shared memory for example), + * it may call vkCreateInstance directly. */ + retro_vulkan_create_instance_t create_instance; + + /* If non-NULL and frontend recognizes negotiation interface >= 2, create_device2 takes precedence over create_device. + * Similar to create_device, but is extended to better understand new core versions and PDF2 feature enablement. + * Requirements for create_device2 are the same as create_device unless a difference is mentioned. + * + * v2 consideration: + * If the chosen gpu by frontend cannot be supported, a core must return false. + * + * NOTE: "Cannot be supported" is intentionally vaguely defined. + * Refusing to run on an iGPU for a very intensive core with desktop GPU as a minimum spec may be in the gray area. + * Not supporting optional features is not a good reason to reject a physical device, however. + * + * On device creation feature with explicit gpu, a frontend should fall back create_device2 with gpu == VK_NULL_HANDLE and let core + * decide on a supported device if possible. + * + * A core must assume that the explicitly provided GPU is the only guaranteed attempt it has to create a device. + * A fallback may not be attempted if there are particular reasons why only a specific physical device can work, + * but these situations should be esoteric and rare in nature, e.g. a libretro frontend is implemented with external memory + * and only LUID matching would work. + * Cores and frontends should ensure "best effort" when negotiating like this and appropriate logging is encouraged. + * + * v1 note: In the v1 version of create_device, it was never expected that create_device would fail like this, + * and frontends are not expected to attempt fall backs. + * + * Rather than call vkCreateDevice directly, a core must call the CreateDevice wrapper provided with: + * VkDevice device = create_device_wrapper(gpu, opaque, &create_info); + * If the core wishes to create a private device for whatever reason (relying on shared memory for example), + * it may call vkCreateDevice directly. + * + * This allows the frontend to add additional extensions that it requires as well as adjust the PDF2 pNext as required. + * It is also possible adjust the queue create infos in case the frontend desires to allocate some private queues. + * + * The get_instance_proc_addr provided in create_device2 must be the same as create_instance. + * + * NOTE: The frontend must not disable features requested by application. + * NOTE: The frontend must not add any robustness features as some API behavior may change (VK_EXT_descriptor_buffer comes to mind). + * I.e. robustBufferAccess and the like. (nullDescriptor from robustness2 is allowed to be enabled). + */ + retro_vulkan_create_device2_t create_device2; +}; + +struct retro_hw_render_interface_vulkan +{ + /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN. */ + enum retro_hw_render_interface_type interface_type; + /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION. */ + unsigned interface_version; + + /* Opaque handle to the Vulkan backend in the frontend + * which must be passed along to all function pointers + * in this interface. + * + * The rationale for including a handle here (which libretro v1 + * doesn't currently do in general) is: + * + * - Vulkan cores should be able to be freely threaded without lots of fuzz. + * This would break frontends which currently rely on TLS + * to deal with multiple cores loaded at the same time. + * - Fixing this in general is TODO for an eventual libretro v2. + */ + void *handle; + + /* The Vulkan instance the context is using. */ + VkInstance instance; + /* The physical device used. */ + VkPhysicalDevice gpu; + /* The logical device used. */ + VkDevice device; + + /* Allows a core to fetch all its needed symbols without having to link + * against the loader itself. */ + PFN_vkGetDeviceProcAddr get_device_proc_addr; + PFN_vkGetInstanceProcAddr get_instance_proc_addr; + + /* The queue the core must use to submit data. + * This queue and index must remain constant throughout the lifetime + * of the context. + * + * This queue will be the queue that supports graphics and compute + * if the device supports compute. + */ + VkQueue queue; + unsigned queue_index; + + /* Before calling retro_video_refresh_t with RETRO_HW_FRAME_BUFFER_VALID, + * set which image to use for this frame. + * + * If num_semaphores is non-zero, the frontend will wait for the + * semaphores provided to be signaled before using the results further + * in the pipeline. + * + * Semaphores provided by a single call to set_image will only be + * waited for once (waiting for a semaphore resets it). + * E.g. set_image, video_refresh, and then another + * video_refresh without set_image, + * but same image will only wait for semaphores once. + * + * For this reason, ownership transfer will only occur if semaphores + * are waited on for a particular frame in the frontend. + * + * Using semaphores is optional for synchronization purposes, + * but if not using + * semaphores, an image memory barrier in vkCmdPipelineBarrier + * should be used in the graphics_queue. + * Example: + * + * vkCmdPipelineBarrier(cmd, + * srcStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + * dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + * image_memory_barrier = { + * srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + * dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + * }); + * + * The use of pipeline barriers instead of semaphores is encouraged + * as it is simpler and more fine-grained. A layout transition + * must generally happen anyways which requires a + * pipeline barrier. + * + * The image passed to set_image must have imageUsage flags set to at least + * VK_IMAGE_USAGE_TRANSFER_SRC_BIT and VK_IMAGE_USAGE_SAMPLED_BIT. + * The core will naturally want to use flags such as + * VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT and/or + * VK_IMAGE_USAGE_TRANSFER_DST_BIT depending + * on how the final image is created. + * + * The image must also have been created with MUTABLE_FORMAT bit set if + * 8-bit formats are used, so that the frontend can reinterpret sRGB + * formats as it sees fit. + * + * Images passed to set_image should be created with TILING_OPTIMAL. + * The image layout should be transitioned to either + * VK_IMAGE_LAYOUT_GENERIC or VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. + * The actual image layout used must be set in image_layout. + * + * The image must be a 2D texture which may or not be layered + * and/or mipmapped. + * + * The image must be suitable for linear sampling. + * While the image_view is typically the only field used, + * the frontend may want to reinterpret the texture as sRGB vs. + * non-sRGB for example so the VkImageViewCreateInfo used to + * create the image view must also be passed in. + * + * The data in the pointer to the image struct will not be copied + * as the pNext field in create_info cannot be reliably deep-copied. + * The image pointer passed to set_image must be valid until + * retro_video_refresh_t has returned. + * + * If frame duping is used when passing NULL to retro_video_refresh_t, + * the frontend is free to either use the latest image passed to + * set_image or reuse the older pointer passed to set_image the + * frame RETRO_HW_FRAME_BUFFER_VALID was last used. + * + * Essentially, the lifetime of the pointer passed to + * retro_video_refresh_t should be extended if frame duping is used + * so that the frontend can reuse the older pointer. + * + * The image itself however, must not be touched by the core until + * wait_sync_index has been completed later. The frontend may perform + * layout transitions on the image, so even read-only access is not defined. + * The exception to read-only rule is if GENERAL layout is used for the image. + * In this case, the frontend is not allowed to perform any layout transitions, + * so concurrent reads from core and frontend are allowed. + * + * If frame duping is used, or if set_command_buffers is used, + * the frontend will not wait for any semaphores. + * + * The src_queue_family is used to specify which queue family + * the image is currently owned by. If using multiple queue families + * (e.g. async compute), the frontend will need to acquire ownership of the + * image before rendering with it and release the image afterwards. + * + * If src_queue_family is equal to the queue family (queue_index), + * no ownership transfer will occur. + * Similarly, if src_queue_family is VK_QUEUE_FAMILY_IGNORED, + * no ownership transfer will occur. + * + * The frontend will always release ownership back to src_queue_family. + * Waiting for frontend to complete with wait_sync_index() ensures that + * the frontend has released ownership back to the application. + * Note that in Vulkan, transfering ownership is a two-part process. + * + * Example frame: + * - core releases ownership from src_queue_index to queue_index with VkImageMemoryBarrier. + * - core calls set_image with src_queue_index. + * - Frontend will acquire the image with src_queue_index -> queue_index as well, completing the ownership transfer. + * - Frontend renders the frame. + * - Frontend releases ownership with queue_index -> src_queue_index. + * - Next time image is used, core must acquire ownership from queue_index ... + * + * Since the frontend releases ownership, we cannot necessarily dupe the frame because + * the core needs to make the roundtrip of ownership transfer. + */ + retro_vulkan_set_image_t set_image; + + /* Get the current sync index for this frame which is obtained in + * frontend by calling e.g. vkAcquireNextImageKHR before calling + * retro_run(). + * + * This index will correspond to which swapchain buffer is currently + * the active one. + * + * Knowing this index is very useful for maintaining safe asynchronous CPU + * and GPU operation without stalling. + * + * The common pattern for synchronization is to receive fences when + * submitting command buffers to Vulkan (vkQueueSubmit) and add this fence + * to a list of fences for frame number get_sync_index(). + * + * Next time we receive the same get_sync_index(), we can wait for the + * fences from before, which will usually return immediately as the + * frontend will generally also avoid letting the GPU run ahead too much. + * + * After the fence has signaled, we know that the GPU has completed all + * GPU work related to work submitted in the frame we last saw get_sync_index(). + * + * This means we can safely reuse or free resources allocated in this frame. + * + * In theory, even if we wait for the fences correctly, it is not technically + * safe to write to the image we earlier passed to the frontend since we're + * not waiting for the frontend GPU jobs to complete. + * + * The frontend will guarantee that the appropriate pipeline barrier + * in graphics_queue has been used such that + * VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT cannot + * start until the frontend is done with the image. + */ + retro_vulkan_get_sync_index_t get_sync_index; + + /* Returns a bitmask of how many swapchain images we currently have + * in the frontend. + * + * If bit #N is set in the return value, get_sync_index can return N. + * Knowing this value is useful for preallocating per-frame management + * structures ahead of time. + * + * While this value will typically remain constant throughout the + * applications lifecycle, it may for example change if the frontend + * suddently changes fullscreen state and/or latency. + * + * If this value ever changes, it is safe to assume that the device + * is completely idle and all synchronization objects can be deleted + * right away as desired. + */ + retro_vulkan_get_sync_index_mask_t get_sync_index_mask; + + /* Instead of submitting the command buffer to the queue first, the core + * can pass along its command buffer to the frontend, and the frontend + * will submit the command buffer together with the frontends command buffers. + * + * This has the advantage that the overhead of vkQueueSubmit can be + * amortized into a single call. For this mode, semaphores in set_image + * will be ignored, so vkCmdPipelineBarrier must be used to synchronize + * the core and frontend. + * + * The command buffers in set_command_buffers are only executed once, + * even if frame duping is used. + * + * If frame duping is used, set_image should be used for the frames + * which should be duped instead. + * + * Command buffers passed to the frontend with set_command_buffers + * must not actually be submitted to the GPU until retro_video_refresh_t + * is called. + * + * The frontend must submit the command buffer before submitting any + * other command buffers provided by set_command_buffers. */ + retro_vulkan_set_command_buffers_t set_command_buffers; + + /* Waits on CPU for device activity for the current sync index to complete. + * This is useful since the core will not have a relevant fence to sync with + * when the frontend is submitting the command buffers. */ + retro_vulkan_wait_sync_index_t wait_sync_index; + + /* If the core submits command buffers itself to any of the queues provided + * in this interface, the core must lock and unlock the frontend from + * racing on the VkQueue. + * + * Queue submission can happen on any thread. + * Even if queue submission happens on the same thread as retro_run(), + * the lock/unlock functions must still be called. + * + * NOTE: Queue submissions are heavy-weight. */ + retro_vulkan_lock_queue_t lock_queue; + retro_vulkan_unlock_queue_t unlock_queue; + + /* Sets a semaphore which is signaled when the image in set_image can safely be reused. + * The semaphore is consumed next call to retro_video_refresh_t. + * The semaphore will be signalled even for duped frames. + * The semaphore will be signalled only once, so set_signal_semaphore should be called every frame. + * The semaphore may be VK_NULL_HANDLE, which disables semaphore signalling for next call to retro_video_refresh_t. + * + * This is mostly useful to support use cases where you're rendering to a single image that + * is recycled in a ping-pong fashion with the frontend to save memory (but potentially less throughput). + */ + retro_vulkan_set_signal_semaphore_t set_signal_semaphore; +}; + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/scene_viewer_application.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/scene_viewer_application.cpp new file mode 100644 index 00000000..01f95754 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/scene_viewer_application.cpp @@ -0,0 +1,1618 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "scene_viewer_application.hpp" +#include "light_export.hpp" +#include "muglm/matrix_helper.hpp" +#include "post/hdr.hpp" +#include "post/ssao.hpp" +#include "post/spd.hpp" +#include "rapidjson_wrapper.hpp" +#include "task_composer.hpp" +#include "thread_group.hpp" +#include "utils/image_utils.hpp" +#include "ocean.hpp" +#include "post/ssr.hpp" +#include +#include + +using namespace Vulkan; + +namespace Granite +{ + +static vec3 light_direction() +{ + return normalize(vec3(0.5f, 1.2f, 0.8f)); +} + +void SceneViewerApplication::read_lights() +{ + std::string json; + if (!GRANITE_FILESYSTEM()->read_file_to_string("assets://lights.json", json)) + return; + + auto &scene = scene_loader.get_scene(); + rapidjson::Document doc; + doc.Parse(json); + + if (doc.HasMember("directional")) + { + auto &dir = doc["directional"]; + auto &dir_lights = scene.get_entity_pool().get_component_group(); + DirectionalLightComponent *comp; + + if (dir_lights.empty()) + { + auto light = scene.create_entity(); + comp = light->allocate_component(); + } + else + comp = get_component(dir_lights.front()); + + for (int i = 0; i < 3; i++) + { + comp->direction[i] = -dir["direction"][i].GetFloat(); + comp->color[i] = dir["color"][i].GetFloat(); + } + } + + if (doc.HasMember("spot")) + { + auto &spots = doc["spot"]; + for (auto itr = spots.Begin(); itr != spots.End(); ++itr) + { + auto &spot = *itr; + SceneFormats::LightInfo info; + info.type = SceneFormats::LightInfo::Type::Spot; + info.inner_cone = spot["innerCone"].GetFloat(); + info.outer_cone = spot["outerCone"].GetFloat(); + for (int i = 0; i < 3; i++) + info.color[i] = spot["color"][i].GetFloat(); + if (spot.HasMember("range")) + info.range = spot["range"].GetFloat(); + + auto node = scene.create_node(); + for (int i = 0; i < 3; i++) + node->get_transform().translation[i] = spot["position"][i].GetFloat(); + + auto &dir = spot["direction"]; + node->get_transform().rotation = conjugate(look_at_arbitrary_up(vec3( + dir[0].GetFloat(), dir[1].GetFloat(), dir[2].GetFloat()))); + scene.get_root_node()->add_child(node); + auto entity = scene.create_light(info, node.get()); + entity->allocate_component(); + } + } + + if (doc.HasMember("point")) + { + auto &points = doc["point"]; + for (auto itr = points.Begin(); itr != points.End(); ++itr) + { + auto &point = *itr; + SceneFormats::LightInfo info; + info.type = SceneFormats::LightInfo::Type::Point; + for (int i = 0; i < 3; i++) + info.color[i] = point["color"][i].GetFloat(); + if (point.HasMember("range")) + info.range = point["range"].GetFloat(); + + auto node = scene.create_node(); + for (int i = 0; i < 3; i++) + node->get_transform().translation[i] = point["position"][i].GetFloat(); + scene.get_root_node()->add_child(node); + auto entity = scene.create_light(info, node.get()); + entity->allocate_component(); + } + } +} + +void SceneViewerApplication::read_quirks(const std::string &path) +{ + std::string json; + if (!GRANITE_FILESYSTEM()->read_file_to_string(path, json)) + { + LOGE("Failed to read quirks file. Assuming defaults.\n"); + return; + } + + rapidjson::Document doc; + doc.Parse(json); + + if (doc.HasMember("instanceDeferredLights")) + ImplementationQuirks::get().instance_deferred_lights = doc["instanceDeferredLights"].GetBool(); + if (doc.HasMember("mergeSubpasses")) + ImplementationQuirks::get().merge_subpasses = doc["mergeSubpasses"].GetBool(); + if (doc.HasMember("useTransientColor")) + ImplementationQuirks::get().use_transient_color = doc["useTransientColor"].GetBool(); + if (doc.HasMember("useTransientDepthStencil")) + ImplementationQuirks::get().use_transient_depth_stencil = doc["useTransientDepthStencil"].GetBool(); + if (doc.HasMember("queueWaitOnSubmission")) + ImplementationQuirks::get().queue_wait_on_submission = doc["queueWaitOnSubmission"].GetBool(); + if (doc.HasMember("useAsyncComputePost")) + ImplementationQuirks::get().use_async_compute_post = doc["useAsyncComputePost"].GetBool(); + if (doc.HasMember("renderGraphForceSingleQueue")) + ImplementationQuirks::get().render_graph_force_single_queue = doc["renderGraphForceSingleQueue"].GetBool(); + if (doc.HasMember("forceNoSubgroups")) + ImplementationQuirks::get().force_no_subgroups = doc["forceNoSubgroups"].GetBool(); + if (doc.HasMember("forceNoSubgroupShuffle")) + ImplementationQuirks::get().force_no_subgroup_shuffle = doc["forceNoSubgroupShuffle"].GetBool(); + if (doc.HasMember("forceNoSubgroupSizeControl")) + ImplementationQuirks::get().force_no_subgroup_size_control = doc["forceNoSubgroupSizeControl"].GetBool(); +} + +void SceneViewerApplication::read_config(const std::string &path) +{ + std::string json; + if (!GRANITE_FILESYSTEM()->read_file_to_string(path, json)) + { + LOGE("Failed to read config file. Assuming defaults.\n"); + return; + } + + rapidjson::Document doc; + doc.Parse(json); + + if (doc.HasMember("renderer")) + { + auto *renderer = doc["renderer"].GetString(); + if (strcmp(renderer, "forward") == 0) + config.renderer_type = RendererType::GeneralForward; + else if (strcmp(renderer, "deferred") == 0) + config.renderer_type = RendererType::GeneralDeferred; + else + throw std::invalid_argument("Invalid renderer option."); + } + + if (doc.HasMember("msaa")) + config.msaa = doc["msaa"].GetUint(); + + if (doc.HasMember("ssao")) + config.ssao = doc["ssao"].GetBool(); + + if (doc.HasMember("ssr")) + config.ssr = doc["ssr"].GetBool(); + + if (doc.HasMember("debugProbes")) + config.debug_probes = doc["debugProbes"].GetBool(); + + if (doc.HasMember("directionalLightShadows")) + config.directional_light_shadows = doc["directionalLightShadows"].GetBool(); + + if (doc.HasMember("directionalLightShadowsCascaded")) + config.directional_light_cascaded_shadows = doc["directionalLightShadowsCascaded"].GetBool(); + + if (doc.HasMember("directionalLightShadowsVSM")) + config.directional_light_shadows_vsm = doc["directionalLightShadowsVSM"].GetBool(); + + if (doc.HasMember("PCFKernelWide")) + { + bool wide = doc["PCFKernelWide"].GetBool(); + if (wide) + config.pcf_flags = SCENE_RENDERER_SHADOW_PCF_WIDE_BIT; + else + config.pcf_flags = 0; + renderer_suite_config.pcf_wide = wide; + } + if (doc.HasMember("clusteredLightsShadows")) + config.clustered_lights_shadows = doc["clusteredLightsShadows"].GetBool(); + if (doc.HasMember("clusteredLightsShadowsResolution")) + config.clustered_lights_shadow_resolution = doc["clusteredLightsShadowsResolution"].GetUint(); + if (doc.HasMember("clusteredLightsShadowsVSM")) + config.clustered_lights_shadows_vsm = doc["clusteredLightsShadowsVSM"].GetBool(); + if (doc.HasMember("hdrBloom")) + config.hdr_bloom = doc["hdrBloom"].GetBool(); + if (doc.HasMember("hdrBloomDynamicExposure")) + config.hdr_bloom_dynamic_exposure = doc["hdrBloomDynamicExposure"].GetBool(); + if (doc.HasMember("showUi")) + config.show_ui = doc["showUi"].GetBool(); + if (doc.HasMember("forwardDepthPrepass")) + config.forward_depth_prepass = doc["forwardDepthPrepass"].GetBool(); + + if (doc.HasMember("shadowMapResolution")) + config.shadow_map_resolution = doc["shadowMapResolution"].GetFloat(); + + if (doc.HasMember("renderTargetFp16")) + config.rt_fp16 = doc["renderTargetFp16"].GetBool(); + + if (doc.HasMember("rescaleScene")) + config.rescale_scene = doc["rescaleScene"].GetBool(); + + if (doc.HasMember("postAA")) + { + auto *aa = doc["postAA"].GetString(); + config.postaa_type = string_to_post_antialiasing_type(aa); + } + + if (doc.HasMember("resolutionScale")) + config.resolution_scale = doc["resolutionScale"].GetFloat(); + if (doc.HasMember("resolutionScaleSharpen")) + config.resolution_scale_sharpen = doc["resolutionScaleSharpen"].GetBool(); + + if (doc.HasMember("lodBias")) + config.lod_bias = doc["lodBias"].GetFloat(); + + if (doc.HasMember("volumetricFog")) + config.volumetric_fog = doc["volumetricFog"].GetBool(); + if (doc.HasMember("volumetricDiffuse")) + config.volumetric_diffuse = doc["volumetricDiffuse"].GetBool(); +} + +SceneViewerApplication::SceneViewerApplication(const std::string &path, const std::string &config_path, + const std::string &quirks_path, const CLIConfig &cli_config_) + : cli_config(cli_config_) +{ + GRANITE_ASSET_MANAGER()->enable_mesh_assets(); + + renderer_suite.set_default_renderers(); + if (!renderer_suite.load_variant_cache("assets://renderer_suite_variants.json")) + renderer_suite.load_variant_cache("cache://renderer_suite_variants.json"); + + if (!config_path.empty()) + read_config(config_path); + if (!quirks_path.empty()) + read_quirks(quirks_path); + renderer_suite_config.cascaded_directional_shadows = config.directional_light_cascaded_shadows; + renderer_suite_config.directional_light_vsm = config.directional_light_shadows_vsm; + + scene_loader.load_scene(path); + read_lights(); + + scene_transform_manager.init(scene_loader.get_scene()); + + if (cli_config.ocean) + { + OceanConfig ocean_config = {}; + //ocean_config.grid_count = 4; + //ocean_config.ocean_size = vec2(32.0f, 32.0f); + //ocean_config.fft_resolution = ocean_config.grid_count * ocean_config.grid_resolution; + //ocean_config.heightmap = true; + //ocean_config.lod_bias = -2.0f; + //auto &scene = scene_loader.get_scene(); + //auto node = scene.create_node(); + //node->transform.translation = vec3(30.0f, -5.0f, 40.0f); + //node->invalidate_cached_transform(); + //Ocean::add_to_scene(scene_loader.get_scene(), ocean_config, node); + Ocean::add_to_scene(scene_loader.get_scene(), ocean_config); + //scene.get_root_node()->add_child(std::move(node)); + } + + if (false && config.volumetric_diffuse) + { + auto &scene = scene_loader.get_scene(); + auto node = scene.create_node(); + node->get_transform().scale = vec3(32.0f, 8.0f, 32.0f); + node->get_transform().translation = vec3(0.0f, 3.5f, 0.0f); + node->invalidate_cached_transform(); + scene.create_volumetric_diffuse_light(uvec3(32, 8, 32), node.get()); + scene.get_root_node()->add_child(std::move(node)); + } + + if (config.volumetric_fog_regions && config.volumetric_fog) + { + auto &scene = scene_loader.get_scene(); + auto node = scene.create_node(); + node->get_transform().scale = vec3(40.0f); + node->get_transform().translation = vec3(0.0f, 20.0f, 0.0f); + node->invalidate_cached_transform(); + scene.create_volumetric_fog_region(node.get()); + scene.get_root_node()->add_child(std::move(node)); + } + +#if 0 + for (int z = -8; z <= 8; z++) + { + for (int x = -8; x <= 8; x++) + { + auto &scene = scene_loader.get_scene(); + auto node = scene.create_node(); + node->transform.scale = vec3(1.0f); + node->transform.translation = vec3(2.0f * x, 0.4f, 2.0f * z); + node->transform.rotation = angleAxis(half_pi(), vec3(1.0f, 0.0f, 0.0f)); + node->invalidate_cached_transform(); + scene.create_volumetric_decal(node.get()); + scene.get_root_node()->add_child(std::move(node)); + } + } +#endif + + animation_system = scene_loader.consume_animation_system(); + context.set_lighting_parameters(&lighting); + scene_transform_manager.register_persistent_render_context(&context); + fallback_depth_context.set_lighting_parameters(&fallback_lighting); + + scene_transform_manager.register_persistent_render_context(&fallback_depth_context); + for (auto &d : depth_contexts) + scene_transform_manager.register_persistent_render_context(&d); + cam.set_depth_range_infinite(1.0f / 16.0f); + + // Create a dummy background if there isn't any background. + if (scene_loader.get_scene().get_entity_pool().get_component_group().empty()) + { + auto dome = Util::make_handle(); + scene_loader.get_scene().create_renderable(dome, nullptr); + } + + auto *environment = scene_loader.get_scene().get_environment(); + if (environment) + lighting.fog = environment->fog; + else + lighting.fog = {}; + + cam.look_at(vec3(0.0f, 0.0f, 8.0f), vec3(0.0f)); + + // Pick a camera to show. + selected_camera = &cam; + + if (cli_config.camera_index >= 0) + { + auto &scene_cameras = scene_loader.get_scene().get_entity_pool().get_component_group(); + if (!scene_cameras.empty()) + { + if (unsigned(cli_config.camera_index) < scene_cameras.size()) + selected_camera = &get_component(scene_cameras[cli_config.camera_index])->camera; + else + LOGE("Camera index is out of bounds, using normal camera."); + } + } + + // Pick a directional light. + default_directional_light.color = vec3(6.0f, 5.5f, 4.5f); + default_directional_light.direction = light_direction(); + auto &dir_lights = scene_loader.get_scene().get_entity_pool().get_component_group(); + if (!dir_lights.empty()) + selected_directional = get_component(dir_lights.front()); + else + selected_directional = &default_directional_light; + + { + cluster = std::make_unique(); + auto entity = scene_loader.get_scene().create_entity(); + auto *refresh = entity->allocate_component(); + refresh->refresh = cluster.get(); + + auto *rp = entity->allocate_component(); + rp->creator = cluster.get(); + lighting.cluster = cluster.get(); + + cluster->set_enable_shadows(config.clustered_lights_shadows); + cluster->set_shadow_resolution(config.clustered_lights_shadow_resolution); + cluster->set_enable_volumetric_fog(config.volumetric_fog && config.volumetric_fog_regions); + + if (config.clustered_lights_shadows_vsm) + cluster->set_shadow_type(LightClusterer::ShadowType::VSM); + else + cluster->set_shadow_type(LightClusterer::ShadowType::PCF); + + cluster->set_resolution(128, 64, 4 * 1024); + } + + if (config.volumetric_fog) + { + volumetric_fog = std::make_unique(); + volumetric_fog->set_resolution(160, 92, 128); + volumetric_fog->set_z_range(80.0f); + lighting.volumetric_fog = volumetric_fog.get(); + auto entity = scene_loader.get_scene().create_entity(); + auto *rp = entity->allocate_component(); + rp->creator = volumetric_fog.get(); + + volumetric_fog->add_storage_buffer_dependency("cluster-bitmask"); + volumetric_fog->add_storage_buffer_dependency("cluster-range"); + volumetric_fog->add_storage_buffer_dependency("cluster-transforms"); + + if (config.directional_light_shadows) + volumetric_fog->add_texture_dependency("shadow-main"); + } + + if (config.volumetric_diffuse) + { + volumetric_diffuse = std::make_unique(); + lighting.volumetric_diffuse = volumetric_diffuse.get(); + + auto entity = scene_loader.get_scene().create_entity(); + + auto *rp = entity->allocate_component(); + rp->creator = volumetric_diffuse.get(); + + auto *update = entity->allocate_component(); + // Must come before clusterer since we're modifying volumetric light textures, + // which will affect clustering, since it writes new descriptors. + update->dependency_order = -1; + update->refresh = volumetric_diffuse.get(); + + volumetric_diffuse->set_fallback_render_context(&fallback_depth_context); + } + + if (cluster) + { + cluster->set_enable_volumetric_diffuse(config.volumetric_diffuse); + cluster->set_enable_volumetric_decals(false); + } + + context.set_camera(*selected_camera); + + graph.enable_timestamps(cli_config.timestamp); + + if (config.rescale_scene) + rescale_scene(10.0f); + + EVENT_MANAGER_REGISTER_LATCH(SceneViewerApplication, on_swapchain_changed, on_swapchain_destroyed, + SwapchainParameterEvent); + EVENT_MANAGER_REGISTER_LATCH(SceneViewerApplication, on_device_created, on_device_destroyed, DeviceCreatedEvent); + EVENT_MANAGER_REGISTER(SceneViewerApplication, on_key_down, KeyboardEvent); +} + +void SceneViewerApplication::export_lights() +{ + auto lights = export_lights_to_json(lighting.directional, scene_loader.get_scene()); + if (!GRANITE_FILESYSTEM()->write_string_to_file("cache://lights.json", lights)) + LOGE("Failed to export light data.\n"); +} + +void SceneViewerApplication::export_cameras() +{ + auto cameras = export_cameras_to_json(recorded_cameras); + if (!GRANITE_FILESYSTEM()->write_string_to_file("cache://cameras.json", cameras)) + LOGE("Failed to export camera data.\n"); +} + +SceneViewerApplication::~SceneViewerApplication() +{ + export_lights(); + export_cameras(); + renderer_suite.save_variant_cache("cache://renderer_suite_variants.json"); +} + +void SceneViewerApplication::loop_animations() +{ +} + +void SceneViewerApplication::rescale_scene(float radius) +{ + scene_loader.get_scene().update_all_transforms(); + + AABB aabb(vec3(FLT_MAX), vec3(-FLT_MAX)); + auto &objects = scene_loader.get_scene() + .get_entity_pool() + .get_component_group(); + for (auto &caster : objects) + aabb.expand(get_component(caster)->get_aabb()); + + float scale_factor = radius / aabb.get_radius(); + auto root_node = scene_loader.get_scene().get_root_node(); + auto new_root_node = scene_loader.get_scene().create_node(); + new_root_node->get_transform().scale = vec3(scale_factor); + new_root_node->add_child(root_node); + scene_loader.get_scene().set_root_node(new_root_node); +} + +void SceneViewerApplication::on_device_created(const DeviceCreatedEvent &device) +{ + graph.set_device(&device.get_device()); + context.set_device(&device.get_device()); + fallback_depth_context.set_device(&device.get_device()); +} + +void SceneViewerApplication::on_device_destroyed(const DeviceCreatedEvent &) +{ + graph.set_device(nullptr); +} + +bool SceneViewerApplication::on_key_down(const KeyboardEvent &e) +{ + if (e.get_key_state() != KeyState::Pressed) + return true; + + switch (e.get_key()) + { + case Key::O: + selected_camera->set_ortho(!selected_camera->get_ortho(), 5.0f); + break; + + case Key::X: + { + vec3 pos = selected_camera->get_position(); + auto &scene = scene_loader.get_scene(); + auto node = scene.create_node(); + scene.get_root_node()->add_child(node); + + SceneFormats::LightInfo light; + light.type = SceneFormats::LightInfo::Type::Spot; + light.outer_cone = 0.9f; + light.inner_cone = 0.92f; + light.color = vec3(10.0f); + + node->get_transform().translation = pos; + node->get_transform().rotation = conjugate(look_at_arbitrary_up(selected_camera->get_front())); + + auto *entity = scene.create_light(light, node.get()); + entity->allocate_component(); + break; + } + + case Key::C: + { + vec3 pos = selected_camera->get_position(); + auto &scene = scene_loader.get_scene(); + auto node = scene.create_node(); + scene.get_root_node()->add_child(node); + + SceneFormats::LightInfo light; + light.type = SceneFormats::LightInfo::Type::Point; + light.color = vec3(10.0f); + node->get_transform().translation = pos; + + auto *entity = scene.create_light(light, node.get()); + entity->allocate_component(); + break; + } + + case Key::V: + { + default_directional_light.direction = -selected_camera->get_front(); + selected_directional = &default_directional_light; + need_shadow_map_update = true; + break; + } + + case Key::B: + { + float fovy = selected_camera->get_fovy(); + float aspect = selected_camera->get_aspect(); + float znear = selected_camera->get_znear(); + float zfar = selected_camera->get_zfar(); + + RecordedCamera camera; + camera.direction = selected_camera->get_front(); + camera.position = selected_camera->get_position(); + camera.up = selected_camera->get_up(); + camera.aspect = aspect; + camera.fovy = fovy; + camera.znear = znear; + camera.zfar = zfar; + recorded_cameras.push_back(camera); + break; + } + + case Key::R: + { + auto &scene = scene_loader.get_scene(); + scene.remove_entities_with_component(); + break; + } + + case Key::K: + { + capture_environment_probe(); + break; + } + + case Key::Space: + { + auto mode = get_wsi().get_present_mode(); + if (mode == PresentMode::SyncToVBlank) + get_wsi().set_present_mode(PresentMode::UnlockedMaybeTear); + else + get_wsi().set_present_mode(PresentMode::SyncToVBlank); + break; + } + + case Key::M: + { + get_wsi().set_backbuffer_srgb(!get_wsi().get_backbuffer_srgb()); + break; + } + + case Key::H: + { + get_wsi().set_backbuffer_format(get_wsi().get_backbuffer_format() == Vulkan::BackbufferFormat::HDR10 ? + Vulkan::BackbufferFormat::sRGB : Vulkan::BackbufferFormat::HDR10); + break; + } + + default: + break; + } + + return true; +} + +void SceneViewerApplication::capture_environment_probe() +{ + ImageCreateInfo info = ImageCreateInfo::render_target(512, 512, VK_FORMAT_R16G16B16A16_SFLOAT); + info.levels = 1; + info.layers = 6; + info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + info.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; + auto &device = get_wsi().get_device(); + + auto handle = device.create_image(info, nullptr); + auto cmd = device.request_command_buffer(); + + VisibilityList visible; + + for (unsigned face = 0; face < 6; face++) + { + ImageViewCreateInfo view_info = {}; + view_info.layers = 1; + view_info.base_layer = face; + view_info.format = info.format; + view_info.levels = 1; + view_info.image = handle.get(); + auto rt_view = device.create_image_view(view_info); + + mat4 proj, view; + compute_cube_render_transform(selected_camera->get_position(), face, proj, view, 0.1f, 300.0f); + context.set_camera(proj, view); + + RenderPassInfo rp = {}; + rp.num_color_attachments = 1; + rp.color_attachments[0] = rt_view.get(); + rp.store_attachments = 1; + rp.clear_attachments = 1; + + auto depth_att = device.get_transient_attachment(512, 512, device.get_default_depth_format(), 0); + rp.depth_stencil = &depth_att->get_view(); + rp.op_flags = RENDER_PASS_OP_CLEAR_DEPTH_STENCIL_BIT; + rp.clear_depth_stencil.depth = 0.0f; + rp.clear_depth_stencil.stencil = 0; + rp.clear_color[0].float32[0] = 0.0f; + rp.clear_color[0].float32[1] = 0.0f; + rp.clear_color[0].float32[2] = 0.0f; + rp.clear_color[0].float32[3] = 1.0f; + cmd->begin_render_pass(rp); + + auto &scene = scene_loader.get_scene(); + visible.clear(); + scene.gather_visible_opaque_renderables(context.get_visibility_frustum(), visible); + scene.gather_visible_render_pass_sinks(context.get_render_parameters().camera_position, visible); + scene.gather_unbounded_renderables(visible); + + auto &forward_renderer = renderer_suite.get_renderer(RendererSuite::Type::ForwardOpaque); + forward_renderer.set_mesh_renderer_options_from_lighting(lighting); + forward_renderer.set_mesh_renderer_options(forward_renderer.get_mesh_renderer_options() | config.pcf_flags); + + forward_renderer.begin(queue); + queue.push_renderables(context, visible.data(), visible.size()); + + Renderer::RendererOptionFlags opt = Renderer::FRONT_FACE_CLOCKWISE_BIT; + forward_renderer.flush(*cmd, queue, context, opt); + + cmd->end_render_pass(); + } + + cmd->image_barrier(*handle, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_READ_BIT); + device.submit(cmd); + auto buffer = save_image_to_cpu_buffer(device, *handle, CommandBuffer::Type::Generic); + save_image_buffer_to_gtx(device, buffer, "cache://environment.gtx"); +} + +static inline std::string tagcat(const std::string &a, const std::string &b) +{ + return a + "-" + b; +} + +void SceneViewerApplication::add_mv_pass(const std::string &tag, const std::string &depth, bool full_mv) +{ + AttachmentInfo mv; + mv.size_class = SizeClass::InputRelative; + mv.size_relative_name = depth; + mv.format = VK_FORMAT_R16G16_SFLOAT; + + auto &mv_pass = graph.add_pass(tagcat("mv", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + mv_pass.set_depth_stencil_input(depth); + mv_pass.add_color_output(tagcat("mv", tag), mv); + culling_passes_info.motion_vector_pass = &mv_pass; + + if (full_mv) + mv_pass.add_attachment_input(depth); + + auto renderer = Util::make_handle(); + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.context = &context; + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_MOTION_VECTOR_BIT; + if (full_mv) + setup.flags |= SCENE_RENDERER_MOTION_VECTOR_FULL_BIT; + + // After normal rendering, the occlusion state buffer is exactly what we want. + // Main downside is that we have to split render pass if we're doing forward rendering with task, + // but that's fairly minor. + renderer->set_extra_flush_flags(Renderer::MESH_ASSET_PHASE_1_BIT); + + renderer->init(setup); + + mv_pass.set_render_pass_interface(std::move(renderer)); +} + +void SceneViewerApplication::add_main_pass_forward(Device &device, const std::string &tag) +{ + AttachmentInfo color, depth; + depth.format = device.get_default_depth_format(); + + color.size_x = config.resolution_scale; + color.size_y = config.resolution_scale; + depth.size_x = config.resolution_scale; + depth.size_y = config.resolution_scale; + + //bool use_ssao = config.forward_depth_prepass && config.ssao && config.msaa == 1; + const bool use_ssao = false; + + auto &phase1 = graph.add_pass(tagcat("depth-phase1", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + phase1.set_depth_stencil_output(tagcat("depth-prepass", tag), depth); + culling_passes_info.phase1_depth_output = tagcat("depth-prepass", tag); + + scene_loader.get_scene().add_render_pass_dependencies(graph, phase1, + RenderPassCreator::GEOMETRY_BIT | + RenderPassCreator::MATERIAL_BIT); + + { + auto renderer = Util::make_handle(); + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.context = &context; + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_Z_PREPASS_BIT; + if (config.debug_probes) + setup.flags |= SCENE_RENDERER_DEBUG_PROBES_BIT; + renderer->set_extra_flush_flags(Renderer::MESH_ASSET_PHASE_1_BIT); + renderer->init(setup); + phase1.set_render_pass_interface(std::move(renderer)); + } + + if (use_ssao) + { + auto &prepass_depth = graph.add_pass(tagcat("depth-transient", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + prepass_depth.set_depth_stencil_output(tagcat("depth-transient", tag), depth); + auto renderer = Util::make_handle(); + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.context = &context; + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_Z_PREPASS_BIT; + renderer->init(setup); + + // TODO: Find a good way to let the prepass renderer share renderer with opaque / transparent passes. + prepass_depth.set_render_pass_interface(std::move(renderer)); + scene_loader.get_scene().add_render_pass_dependencies(graph, prepass_depth, RenderPassCreator::GEOMETRY_BIT); + setup_ffx_cacao(graph, context, tagcat("ssao-output", tag), tagcat("depth-transient", tag), ""); + } + + bool supports_32bpp = + device.image_format_is_supported(VK_FORMAT_B10G11R11_UFLOAT_PACK32, + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); + + if (config.hdr_bloom || get_wsi().get_backbuffer_color_space() == VK_COLOR_SPACE_HDR10_ST2084_EXT) + color.format = + (config.rt_fp16 || !supports_32bpp) ? VK_FORMAT_R16G16B16A16_SFLOAT : VK_FORMAT_B10G11R11_UFLOAT_PACK32; + else + color.format = VK_FORMAT_UNDEFINED; // Swapchain format. + + color.samples = config.msaa; + depth.samples = config.msaa; + + auto resolved = color; + resolved.samples = 1; + + auto &lighting_pass = graph.add_pass(tagcat("lighting", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + + culling_passes_info.phase1_pass = &phase1; + culling_passes_info.phase2_pass = &lighting_pass; + culling_passes_info.force_visible_phase2 = true; + + if (color.samples > 1) + { + lighting_pass.add_color_output(tagcat("HDR-MS", tag), color); + lighting_pass.add_resolve_output(tagcat("HDR", tag), resolved); + } + else + lighting_pass.add_color_output(tagcat("HDR", tag), color); + + if (use_ssao) + { + ssao_output = &lighting_pass.add_texture_input(tagcat("ssao-output", tag)); + lighting_pass.set_depth_stencil_input(tagcat("depth-transient", tag)); + lighting_pass.add_fake_resource_write_alias(tagcat("depth-transient", tag), tagcat("depth", tag)); + } + else + { + ssao_output = nullptr; + lighting_pass.set_depth_stencil_output(tagcat("depth", tag), depth); + } + + auto renderer = Util::make_handle(); + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.context = &context; + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_FORWARD_OPAQUE_BIT | SCENE_RENDERER_FORWARD_TRANSPARENT_BIT | config.pcf_flags; + if (config.forward_depth_prepass && !use_ssao) + setup.flags |= SCENE_RENDERER_Z_PREPASS_BIT; + else if (config.forward_depth_prepass) + setup.flags |= SCENE_RENDERER_Z_EXISTING_PREPASS_BIT; + + if (config.debug_probes) + setup.flags |= SCENE_RENDERER_DEBUG_PROBES_BIT; + + renderer->set_extra_flush_flags(Renderer::MESH_ASSET_PHASE_2_BIT | Renderer::MESH_ASSET_FORCE_ALL_VISIBLE_BIT); + renderer->init(setup); + + lighting_pass.set_render_pass_interface(std::move(renderer)); + + shadows = nullptr; + if (config.directional_light_shadows) + shadows = &lighting_pass.add_texture_input("shadow-main"); + scene_loader.get_scene().add_render_pass_dependencies(graph, lighting_pass, + RenderPassCreator::LIGHTING_BIT | + RenderPassCreator::GEOMETRY_BIT | + RenderPassCreator::MATERIAL_BIT); +} + +void SceneViewerApplication::add_main_pass_deferred(Device &device, const std::string &tag) +{ + bool supports_32bpp = + device.image_format_is_supported(VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); + AttachmentInfo emissive, albedo, normal, pbr, depth; + if (config.hdr_bloom || get_wsi().get_backbuffer_color_space() == VK_COLOR_SPACE_HDR10_ST2084_EXT) + emissive.format = + (config.rt_fp16 || !supports_32bpp) ? VK_FORMAT_R16G16B16A16_SFLOAT : VK_FORMAT_B10G11R11_UFLOAT_PACK32; + else + emissive.format = VK_FORMAT_UNDEFINED; + + const auto set_scale = [&](AttachmentInfo &info) { + info.size_x = config.resolution_scale; + info.size_y = config.resolution_scale; + }; + set_scale(emissive); + set_scale(albedo); + set_scale(normal); + set_scale(pbr); + set_scale(depth); + + albedo.format = VK_FORMAT_R8G8B8A8_SRGB; + normal.format = VK_FORMAT_A2B10G10R10_UNORM_PACK32; + pbr.format = VK_FORMAT_R8G8_UNORM; + depth.format = device.get_default_depth_format(); + + culling_passes_info.phase1_depth_output = tagcat("depth-prepass", tag); + + auto &phase1 = graph.add_pass(tagcat("gbuffer-phase1", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + phase1.set_depth_stencil_output(culling_passes_info.phase1_depth_output, depth); + + scene_loader.get_scene().add_render_pass_dependencies(graph, phase1, + RenderPassCreator::GEOMETRY_BIT | + RenderPassCreator::MATERIAL_BIT); + + { + auto renderer = Util::make_handle(); + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.context = &context; + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_Z_PREPASS_BIT; + if (config.debug_probes) + setup.flags |= SCENE_RENDERER_DEBUG_PROBES_BIT; + renderer->set_extra_flush_flags(Renderer::MESH_ASSET_PHASE_1_BIT); + renderer->init(setup); + phase1.set_render_pass_interface(std::move(renderer)); + } + + auto &gbuffer = graph.add_pass(tagcat("gbuffer", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + gbuffer.add_color_output(tagcat("emissive", tag), emissive); + gbuffer.add_color_output(tagcat("albedo", tag), albedo); + gbuffer.add_color_output(tagcat("normal", tag), normal); + gbuffer.add_color_output(tagcat("pbr", tag), pbr); + gbuffer.set_depth_stencil_output(tagcat("depth-transient", tag), depth); + gbuffer.set_depth_stencil_input(tagcat("depth-prepass", tag)); + + culling_passes_info.phase1_pass = &phase1; + culling_passes_info.phase2_pass = &gbuffer; + + { + auto renderer = Util::make_handle(); + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.context = &context; + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_DEFERRED_GBUFFER_BIT; + if (config.debug_probes) + setup.flags |= SCENE_RENDERER_DEBUG_PROBES_BIT; + renderer->set_extra_flush_flags(Renderer::MESH_ASSET_PHASE_2_BIT | Renderer::MESH_ASSET_FORCE_ALL_VISIBLE_BIT); + renderer->init(setup); + gbuffer.set_render_pass_interface(std::move(renderer)); + } + + if (config.ssao) + { + setup_ffx_cacao(graph, context, tagcat("ssao-output", tag), tagcat("depth-transient", tag), + tagcat("normal", tag)); + } + + auto &lighting_pass = graph.add_pass(tagcat("lighting", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + lighting_pass.add_color_output(tagcat("HDR", tag), emissive, tagcat("emissive", tag)); + lighting_pass.add_attachment_input(tagcat("albedo", tag)); + lighting_pass.add_attachment_input(tagcat("normal", tag)); + lighting_pass.add_attachment_input(tagcat("pbr", tag)); + lighting_pass.add_attachment_input(tagcat("depth-transient", tag)); + lighting_pass.set_depth_stencil_input(tagcat("depth-transient", tag)); + lighting_pass.add_fake_resource_write_alias(tagcat("depth-transient", tag), tagcat("depth", tag)); + + { + auto renderer = Util::make_handle(); + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.context = &context; + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_DEFERRED_LIGHTING_BIT | SCENE_RENDERER_FORWARD_TRANSPARENT_BIT | config.pcf_flags; + renderer->init(setup); + + lighting_pass.set_render_pass_interface(std::move(renderer)); + } + + if (config.ssao) + ssao_output = &lighting_pass.add_texture_input(tagcat("ssao-output", tag)); + else + ssao_output = nullptr; + + shadows = nullptr; + if (config.directional_light_shadows) + shadows = &lighting_pass.add_texture_input("shadow-main"); + + scene_loader.get_scene().add_render_pass_dependencies(graph, gbuffer, + RenderPassCreator::GEOMETRY_BIT | + RenderPassCreator::MATERIAL_BIT); + scene_loader.get_scene().add_render_pass_dependencies(graph, lighting_pass, + RenderPassCreator::LIGHTING_BIT); +} + +void SceneViewerApplication::add_main_pass(Device &device, const std::string &tag) +{ + switch (config.renderer_type) + { + case RendererType::GeneralForward: + add_main_pass_forward(device, tag); + break; + + case RendererType::GeneralDeferred: + add_main_pass_deferred(device, tag); + break; + + default: + break; + } +} + +void SceneViewerApplication::add_shadow_pass_fallback(Vulkan::Device &, const std::string &tag) +{ + AttachmentInfo shadowmap; + shadowmap.format = VK_FORMAT_D16_UNORM; + shadowmap.size_class = SizeClass::Absolute; + shadowmap.size_x = 2048; + shadowmap.size_y = 2048; + + auto &shadowpass = graph.add_pass(tagcat("shadow", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + fallback_shadows = &shadowpass.set_depth_stencil_output(tagcat("shadow", tag), shadowmap); + + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_DEPTH_BIT | SCENE_RENDERER_DEPTH_DYNAMIC_BIT | SCENE_RENDERER_FALLBACK_DEPTH_BIT; + setup.context = &fallback_depth_context; + + auto handle = Util::make_handle(); + handle->init(setup); + shadowpass.set_render_pass_interface(std::move(handle)); + + scene_loader.get_scene().add_render_pass_dependencies(graph, shadowpass, + RenderPassCreator::GEOMETRY_BIT | + RenderPassCreator::MATERIAL_BIT); +} + +void SceneViewerApplication::add_shadow_pass(Device &, const std::string &tag) +{ + AttachmentInfo shadowmap; + shadowmap.format = VK_FORMAT_D16_UNORM; + shadowmap.samples = config.directional_light_shadows_vsm ? 4 : 1; + shadowmap.size_class = SizeClass::Absolute; + shadowmap.size_x = config.shadow_map_resolution; + shadowmap.size_y = config.shadow_map_resolution; + + if (config.directional_light_cascaded_shadows) + shadowmap.layers = NumShadowCascades; + + CullingPassesInfo culling = {}; + culling.phase1_depth_output = tagcat("shadow-prepass", tag); + culling.tag = "depth"; + + auto &phase1 = graph.add_pass(tagcat("shadow-phase1", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + phase1.set_depth_stencil_output(culling.phase1_depth_output, shadowmap); + + { + Util::IntrusivePtr handle; + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_DEPTH_BIT; + + setup.context = depth_contexts; + setup.flags |= SCENE_RENDERER_DEPTH_DYNAMIC_BIT; + setup.flags |= SCENE_RENDERER_SEPARATE_PER_LAYER_BIT; + setup.layers = NumShadowCascades; + + handle = Util::make_handle(); + handle->set_extra_flush_flags(Renderer::MESH_ASSET_PHASE_1_BIT); + handle->init(setup); + phase1.set_render_pass_interface(std::move(handle)); + } + + scene_loader.get_scene().add_render_pass_dependencies(graph, phase1, + RenderPassCreator::GEOMETRY_BIT | + RenderPassCreator::MATERIAL_BIT); + + auto &shadowpass = graph.add_pass(tagcat("shadow", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + + culling.phase1_pass = &phase1; + culling.phase2_pass = &shadowpass; + culling.contexts = depth_contexts; + culling.num_contexts = NumShadowCascades; + hiz_depth = &setup_culling_passes(graph, culling); + + if (config.directional_light_shadows_vsm) + { + auto shadowmap_vsm_color = shadowmap; + auto shadowmap_vsm_resolved_color = shadowmap; + shadowmap_vsm_color.format = VK_FORMAT_R32G32_SFLOAT; + shadowmap_vsm_color.samples = 4; + shadowmap_vsm_resolved_color.format = VK_FORMAT_R32G32_SFLOAT; + shadowmap_vsm_resolved_color.samples = 1; + + auto shadowmap_vsm_half = shadowmap_vsm_resolved_color; + shadowmap_vsm_half.size_x *= 0.5f; + shadowmap_vsm_half.size_y *= 0.5f; + + shadowpass.set_depth_stencil_output(tagcat("shadow-depth", tag), shadowmap); + shadowpass.set_depth_stencil_input(tagcat("shadow-prepass", tag)); + shadowpass.add_color_output(tagcat("shadow-msaa", tag), shadowmap_vsm_color); + shadowpass.add_resolve_output(tagcat("shadow-raw", tag), shadowmap_vsm_resolved_color); + + auto &down_pass = graph.add_pass(tagcat("shadow-down", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + down_pass.add_color_output(tagcat("shadow-down", tag), shadowmap_vsm_half); + auto &down_pass_res = down_pass.add_texture_input(tagcat("shadow-raw", tag)); + + auto &up_pass = graph.add_pass(tagcat("shadow-up", tag), RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + up_pass.add_color_output(tagcat("shadow", tag), shadowmap_vsm_resolved_color); + auto &up_pass_res = up_pass.add_texture_input(tagcat("shadow-down", tag)); + + down_pass.set_build_render_pass([&, layered = shadowmap.layers > 1](CommandBuffer &cmd) { + auto &input = graph.get_physical_texture_resource(down_pass_res); + vec2 inv_size(1.0f / input.get_image().get_create_info().width, + 1.0f / input.get_image().get_create_info().height); + cmd.push_constants(&inv_size, 0, sizeof(inv_size)); + cmd.set_texture(0, 0, input, StockSampler::LinearClamp); + CommandBufferUtil::draw_fullscreen_quad(cmd, "builtin://shaders/quad.vert", + "builtin://shaders/post/vsm_down_blur.frag", + {{ "LAYERED", layered ? 1 : 0 }}); + }); + + up_pass.set_build_render_pass([&, layered = shadowmap.layers > 1](CommandBuffer &cmd) { + auto &input = graph.get_physical_texture_resource(up_pass_res); + vec2 inv_size(1.0f / input.get_image().get_create_info().width, + 1.0f / input.get_image().get_create_info().height); + cmd.set_texture(0, 0, input, StockSampler::LinearClamp); + cmd.push_constants(&inv_size, 0, sizeof(inv_size)); + CommandBufferUtil::draw_fullscreen_quad(cmd, "builtin://shaders/quad.vert", + "builtin://shaders/post/vsm_up_blur.frag", + {{ "LAYERED", layered ? 1 : 0 }}); + }); + } + else + { + shadowpass.set_depth_stencil_output(tagcat("shadow", tag), shadowmap); + shadowpass.set_depth_stencil_input(tagcat("shadow-prepass", tag)); + } + + Util::IntrusivePtr handle; + RenderPassSceneRenderer::Setup setup = {}; + setup.scene = &scene_loader.get_scene(); + setup.suite = &renderer_suite; + setup.flags = SCENE_RENDERER_DEPTH_BIT; + if (config.directional_light_shadows_vsm) + setup.flags |= SCENE_RENDERER_SHADOW_VSM_BIT; + + setup.context = depth_contexts; + setup.flags |= SCENE_RENDERER_DEPTH_DYNAMIC_BIT; + setup.flags |= SCENE_RENDERER_SEPARATE_PER_LAYER_BIT; + setup.layers = NumShadowCascades; + + handle = Util::make_handle(); + handle->set_extra_flush_flags(Renderer::MESH_ASSET_PHASE_2_BIT); + handle->init(setup); + + VkClearColorValue value = {}; + value.float32[0] = 1.0f; + value.float32[1] = 1.0f; + handle->set_clear_color(value); + shadowpass.set_render_pass_interface(std::move(handle)); + + scene_loader.get_scene().add_render_pass_dependencies(graph, shadowpass, + RenderPassCreator::GEOMETRY_BIT | + RenderPassCreator::MATERIAL_BIT); +} + +void SceneViewerApplication::bake_render_graph(const SwapchainParameterEvent &swap) +{ + auto physical_buffers = graph.consume_physical_buffers(); + + shadows = nullptr; + ssao_output = nullptr; + const bool hdr10 = swap.get_color_space() == VK_COLOR_SPACE_HDR10_ST2084_EXT; + + graph.reset(); + + // Reclaims memory released by graph.reset(), before we bake and start allocating more. + //swap.get_device().wait_idle(); + swap.get_device().next_frame_context(); + + graph.set_device(&swap.get_device()); + + swap.get_device().configure_default_geometry_samplers(8.0f, config.lod_bias); + + ResourceDimensions dim; + dim.width = swap.get_width(); + dim.height = swap.get_height(); + dim.format = swap.get_format(); + dim.transform = swap.get_prerotate(); + graph.set_backbuffer_dimensions(dim); + + const char *ui_source = "HDR-main"; + + scene_loader.get_scene().add_render_passes(graph); + + if (config.directional_light_shadows) + { + add_shadow_pass(swap.get_device(), "main"); + add_shadow_pass_fallback(swap.get_device(), "fallback"); + } + + add_main_pass(swap.get_device(), "main"); + + const char *light_output = "HDR-main"; + + if (config.renderer_type == RendererType::GeneralDeferred && config.ssr) + { + setup_ssr_pass(graph, context, "depth-transient-main", + "albedo-main", "normal-main", "pbr-main", + light_output, "SSR"); + light_output = "SSR"; + } + + if (config.postaa_type == PostAAType::TAA_Low || + config.postaa_type == PostAAType::TAA_Medium || + config.postaa_type == PostAAType::TAA_High || + config.postaa_type == PostAAType::TAA_FSR2) + { + add_mv_pass("main", "depth-main", config.postaa_type == PostAAType::TAA_FSR2); + } + + culling_passes_info.contexts = &context; + culling_passes_info.num_contexts = 1; + culling_passes_info.tag = "main"; + culling_passes_info.force_visible_phase2 = true; + hiz_main = &setup_culling_passes(graph, culling_passes_info); + + if (config.hdr_bloom || hdr10) + { + bool resolved = setup_before_post_chain_antialiasing(config.postaa_type, graph, jitter, context, config.resolution_scale, + light_output, "depth-main", "mv-main", "HDR-resolved"); + + if (!hdr10) + { + HDROptions opts; + opts.dynamic_exposure = config.hdr_bloom_dynamic_exposure; + + if (ImplementationQuirks::get().use_async_compute_post) + { + setup_hdr_postprocess_compute(graph, context.get_frame_parameters(), + resolved ? "HDR-resolved" : light_output, "tonemapped", opts); + } + else + { + setup_hdr_postprocess(graph, context.get_frame_parameters(), resolved ? "HDR-resolved" : light_output, + "tonemapped", opts); + } + + ui_source = "tonemapped"; + } + else + { + ui_source = "HDR-resolved"; + } + } + + if (setup_after_post_chain_antialiasing(config.postaa_type, graph, jitter, config.resolution_scale, + ui_source, "depth-main", "post-aa-output")) + { + ui_source = "post-aa-output"; + } + + if (config.resolution_scale < 1.0f && config.postaa_type != PostAAType::TAA_FSR2 && + setup_after_post_chain_upscaling(graph, ui_source, "post-scale-output", + config.resolution_scale_sharpen)) + { + ui_source = "post-scale-output"; + } + + if (config.show_ui) + { + auto &ui = graph.add_pass("ui", config.hdr_bloom || config.postaa_type != PostAAType::None ? + RenderGraph::get_default_post_graphics_queue() : + RENDER_GRAPH_QUEUE_GRAPHICS_BIT); + AttachmentInfo ui_info; + + if (hdr10) + { + ui.add_color_output("ui-temporary", ui_info, ui_source); + ui_info.format = VK_FORMAT_R8G8B8A8_SRGB; + + // TODO: Make this dynamic. + HDR10PQEncodingConfig hdr10_config = {}; + hdr10_config.hdr_pre_exposure = 500.0f; + hdr10_config.ui_pre_exposure = 400.0f; + setup_hdr10_pq_encoding(graph, "ui-output", ui_source, "ui-temporary", hdr10_config, + get_wsi().get_hdr_metadata()); + } + else + { + ui_info.flags |= ATTACHMENT_INFO_SUPPORTS_PREROTATE_BIT; + ui.add_color_output("ui-output", ui_info, ui_source); + } + + graph.set_backbuffer_source("ui-output"); + + ui.set_get_clear_color([](unsigned, VkClearColorValue *value) { + value->float32[0] = 0.0f; + value->float32[1] = 0.0f; + value->float32[2] = 0.0f; + value->float32[3] = 1.0f; + return true; + }); + + ui.set_build_render_pass([this](CommandBuffer &cmd) { render_ui(cmd); }); + } + else + graph.set_backbuffer_source(ui_source); + + scene_loader.get_scene().add_render_pass_dependencies(graph); + graph.bake(); +#ifdef VULKAN_DEBUG + graph.log(); +#endif + graph.install_physical_buffers(std::move(physical_buffers)); + + need_shadow_map_update = true; +} + +void SceneViewerApplication::on_swapchain_changed(const Vulkan::SwapchainParameterEvent &e) +{ + pending_swapchain = &e; +} + +void SceneViewerApplication::on_swapchain_destroyed(const SwapchainParameterEvent &) +{ + pending_swapchain = nullptr; +} + +void SceneViewerApplication::update_shadow_scene_aabb() +{ + // Get the scene AABB for shadow casters. + auto &scene = scene_loader.get_scene(); + auto &shadow_casters = + scene.get_entity_pool() + .get_component_group(); + AABB aabb(vec3(FLT_MAX), vec3(-FLT_MAX)); + for (auto &caster : shadow_casters) + aabb.expand(get_component(caster)->get_aabb()); + shadow_scene_aabb = aabb; +} + +void SceneViewerApplication::setup_shadow_map() +{ + mat4 view = mat4_cast(look_at(-selected_directional->direction, vec3(0.0f, 1.0f, 0.0f))); + AABB ortho_range_depth = shadow_scene_aabb.transform(view); + + // For fallback context, we render the entire scene bounds. + // This is not going to work well for large scenes, but oh well. + fallback_depth_context.set_camera(ortho(ortho_range_depth), view); + fallback_lighting.shadow.transforms[0] = + translate(vec3(0.5f, 0.5f, 0.0f)) * + scale(vec3(0.5f, 0.5f, 1.0f)) * + fallback_depth_context.get_render_parameters().view_projection; + + // Project the scene AABB into the light and find our ortho ranges. + // This will serve as the culling bounding box. + // TODO: Make configurable. + constexpr float FIRST_SLICE_CUTOFF = 10.0f; + constexpr float BEGIN_LERP_FRACT = 0.8f; + + const float cascade_log_bias = 1.0f - muglm::log2(FIRST_SLICE_CUTOFF); + const auto compute_z = [&](float slice) -> float { + float slice_z = FIRST_SLICE_CUTOFF * muglm::exp2(slice - 1.0f); + return slice_z; + }; + + lighting.shadow.cascade_log_bias = cascade_log_bias; + + if (config.directional_light_cascaded_shadows) + { + for (int i = 0; i < NumShadowCascades; i++) + { + float cascade_cutoffs_lo; + float cascade_cutoffs_hi = compute_z(float(i + 1)); + if (i == 0) + cascade_cutoffs_lo = 0.0001f; + else + cascade_cutoffs_lo = compute_z(float(i - 1) + BEGIN_LERP_FRACT); + + auto near_camera = *selected_camera; + near_camera.set_depth_range(cascade_cutoffs_lo, cascade_cutoffs_hi); + vec4 sphere = Frustum::get_bounding_sphere(inverse(near_camera.get_projection()), inverse(near_camera.get_view())); + vec2 center_xy = (view * vec4(sphere.xyz(), 1.0f)).xy(); + sphere.w *= 1.01f; + + vec2 texel_size = vec2(2.0f * sphere.w) * vec2(1.0f / lighting.shadows->get_image().get_create_info().width, + 1.0f / lighting.shadows->get_image().get_create_info().height); + + // Snap to texel grid. + center_xy = round(center_xy / texel_size) * texel_size; + + AABB ortho_range = AABB(vec3(center_xy - vec2(sphere.w), ortho_range_depth.get_minimum().z), + vec3(center_xy + vec2(sphere.w), ortho_range_depth.get_maximum().z)); + + mat4 proj = ortho(ortho_range); + mat4 cascade_transform = proj * view; + lighting.shadow.transforms[i] = + translate(vec3(0.5f, 0.5f, 0.0f)) * + scale(vec3(0.5f, 0.5f, 1.0f)) * + cascade_transform; + + depth_contexts[i].set_camera(proj, view); + } + } + else + { + mat4 proj = ortho(ortho_range_depth); + depth_contexts[0].set_camera(proj, view); + lighting.shadow.transforms[0] = + translate(vec3(0.5f, 0.5f, 0.0f)) * + scale(vec3(0.5f, 0.5f, 1.0f)) * + proj * view; + } +} + +void SceneViewerApplication::update_scene(TaskComposer &composer, double frame_time, double elapsed_time) +{ + auto &scene = scene_loader.get_scene(); + + animation_system->animate(composer, frame_time, elapsed_time); + scene.update_transform_tree(composer); + + constexpr unsigned NumTasks = 8; + Threaded::scene_update_cached_transforms(scene, composer, NumTasks); + + // Perform updates which depend on node transforms. + auto &updates = composer.begin_pipeline_stage(); + updates.set_desc("scene-updates"); + updates.enqueue_task([this, need_update = need_shadow_map_update]() { + jitter.step(selected_camera->get_projection(), selected_camera->get_view()); + context.set_camera(jitter.get_jittered_projection(), selected_camera->get_view()); + context.set_motion_vector_projections(jitter); + + lighting.directional.direction = selected_directional->direction; + lighting.directional.color = selected_directional->color; + + if (lighting.shadows) + { + if (need_update) + update_shadow_scene_aabb(); + setup_shadow_map(); + } + }); + + need_shadow_map_update = false; + scene.refresh_per_frame(context, composer); +} + +void SceneViewerApplication::render_ui(CommandBuffer &cmd) +{ + auto &device = cmd.get_device(); + flat_renderer.begin(); + + unsigned count = std::min(last_frame_index, FrameWindowSize); + float total_time = 0.0f; + float min_time = FLT_MAX; + float max_time = 0.0f; + for (unsigned i = 0; i < count; i++) + { + total_time += last_frame_times[i]; + min_time = std::min(min_time, last_frame_times[i]); + max_time = std::max(max_time, last_frame_times[i]); + } + + char avg_text[64]; + sprintf(avg_text, "Frame: %10.3f ms", (total_time / count) * 1000.0f); + + char min_text[64]; + sprintf(min_text, "Min: %10.3f ms", min_time * 1000.0f); + + char max_text[64]; + sprintf(max_text, "Max: %10.3f ms", max_time * 1000.0f); + + char colorspace_text[64]; + sprintf(colorspace_text, "%s", + get_wsi().get_backbuffer_color_space() == VK_COLOR_SPACE_HDR10_ST2084_EXT ? "ST.2084 / PQ" : "sRGB"); + + char pos_text[256]; + char rot_text[256]; + char tex_text[256]; + auto cam_pos = selected_camera->get_position(); + auto cam_ori = selected_camera->get_rotation(); + snprintf(pos_text, sizeof(pos_text), "Pos: %.3f, %.3f, %.3f", cam_pos.x, cam_pos.y, cam_pos.z); + snprintf(rot_text, sizeof(rot_text), "Rot: %.3f, %.3f, %.3f, %.3f", cam_ori.x, cam_ori.y, cam_ori.z, cam_ori.w); + snprintf(tex_text, sizeof(tex_text), "Texture: %u MiB", + unsigned(GRANITE_ASSET_MANAGER()->get_current_total_consumed() / (1024 * 1024))); + + vec3 offset(5.0f, 5.0f, 0.0f); + vec2 size(cmd.get_viewport().width - 10.0f, cmd.get_viewport().height - 10.0f); + vec4 color(1.0f, 1.0f, 0.0f, 1.0f); + Font::Alignment alignment = Font::Alignment::TopRight; + + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Large), avg_text, offset, size, color, + alignment); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Large), min_text, + offset + vec3(0.0f, 20.0f, 0.0f), size, color, alignment); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Large), max_text, + offset + vec3(0.0f, 40.0f, 0.0f), size, color, alignment); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Normal), colorspace_text, + offset + vec3(0.0f, 65.0f, 0.0f), size, color, alignment); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Normal), pos_text, + offset + vec3(0.0f, 80.0f, 0.0f), size, color, alignment); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Normal), rot_text, + offset + vec3(0.0f, 95.0f, 0.0f), size, color, alignment); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Normal), tex_text, + offset + vec3(0.0f, 110.0f, 0.0f), size, color, alignment); + + HeapBudget budgets[VK_MAX_MEMORY_HEAPS]; + device.get_memory_budget(budgets); + for (uint32_t i = 0; i < device.get_memory_properties().memoryHeapCount; i++) + { + char heap_text[256]; + sprintf(heap_text, "Heap #%u: (%.1f MiB / %.1f MiB) [%.1f / %.1f]", i, + double(budgets[i].device_usage) / double(1024 * 1024), + double(budgets[i].budget_size) / double(1024 * 1024), + double(budgets[i].tracked_usage) / double(1024 * 1024), + double(budgets[i].max_size) / double(1024 * 1024)); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Normal), heap_text, + offset + vec3(0.0f, 145.0f + 15.0f * float(i), 0.0f), + size, color, alignment); + } + + flat_renderer.flush(cmd, vec3(0.0f), vec3(cmd.get_viewport().width, cmd.get_viewport().height, 1.0f)); +} + +void SceneViewerApplication::render_scene(TaskComposer &composer) +{ + auto &wsi = get_wsi(); + auto &device = wsi.get_device(); + graph.enqueue_render_passes(device, composer); +} + +void SceneViewerApplication::post_frame() +{ + Application::post_frame(); + scene_loader.get_scene().destroy_queued_entities(); +} + +void SceneViewerApplication::render_frame(double frame_time, double elapsed_time) +{ + TaskComposer composer(*GRANITE_THREAD_GROUP()); + + if (pending_swapchain) + { + GRANITE_SCOPED_TIMELINE_EVENT("bake-render-graph"); + bake_render_graph(*pending_swapchain); + pending_swapchain = nullptr; + } + + FrameParameters frame; + frame.elapsed_time = elapsed_time; + frame.frame_time = frame_time; + context.set_frame_parameters(frame); + + // Set up handles before we kick of task graph. + auto &device = get_wsi().get_device(); + auto &scene = scene_loader.get_scene(); + +#if 0 + // Hack to test per-object motion easily. + auto &t = scene.get_root_node()->get_transform(); + t.translation.x = std::sin(elapsed_time); + scene.get_root_node()->invalidate_cached_transform(); +#endif + + last_frame_times[last_frame_index++ & FrameWindowSizeMask] = float(frame_time); + + graph.setup_attachments(device, &device.get_swapchain_view()); + lighting.shadows = graph.maybe_get_physical_texture_resource(shadows); + lighting.ambient_occlusion = graph.maybe_get_physical_texture_resource(ssao_output); + context.set_scene_hiz_view(graph.maybe_get_physical_texture_resource(hiz_main), 1); + + // Somewhat crude. + if (auto *hiz = graph.maybe_get_physical_texture_resource(hiz_depth)) + { + hiz_depth_peel.clear(); + for (unsigned layer = 0; layer < hiz->get_create_info().layers; layer++) + { + auto info = hiz->get_create_info(); + info.view_type = VK_IMAGE_VIEW_TYPE_2D; + info.layers = 1; + info.base_layer = layer; + hiz_depth_peel.emplace_back(device.create_image_view(info)); + depth_contexts[layer].set_scene_hiz_view(hiz_depth_peel.back().get(), 1); + } + } + + scene_loader.get_scene().set_render_pass_data(&renderer_suite, &context); + scene.bind_render_graph_resources(graph); + renderer_suite.update_mesh_rendering_options(context, renderer_suite_config); + + fallback_lighting.shadows = graph.maybe_get_physical_texture_resource(fallback_shadows); + fallback_lighting.directional = lighting.directional; + fallback_lighting.cluster = lighting.cluster; + fallback_lighting.volumetric_diffuse = lighting.volumetric_diffuse; + + { + GRANITE_SCOPED_TIMELINE_EVENT("update-scene-enqueue"); + update_scene(composer, frame_time, elapsed_time); + } + + { + GRANITE_SCOPED_TIMELINE_EVENT("render-scene-enqueue"); + render_scene(composer); + } + + GRANITE_SCOPED_TIMELINE_EVENT("render-scene-wait"); + auto final = composer.get_outgoing_task(); + final->wait(); +} + +std::string SceneViewerApplication::get_name() +{ + return "scene-viewer"; +} + +} // namespace Granite diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/application/scene_viewer_application.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/scene_viewer_application.hpp new file mode 100644 index 00000000..4b84db1b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/application/scene_viewer_application.hpp @@ -0,0 +1,180 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "application.hpp" +#include "render_context.hpp" +#include "scene_loader.hpp" +#include "animation_system.hpp" +#include "renderer.hpp" +#include "timer.hpp" +#include "event.hpp" +#include "font.hpp" +#include "ui_manager.hpp" +#include "render_graph.hpp" +#include "mesh_util.hpp" +#include "scene_renderer.hpp" +#include "lights/clusterer.hpp" +#include "lights/volumetric_fog.hpp" +#include "lights/volumetric_diffuse.hpp" +#include "camera_export.hpp" +#include "post/aa.hpp" +#include "post/temporal.hpp" + +namespace Granite +{ +class TaskComposer; + +class SceneViewerApplication : public Application, public EventHandler +{ +public: + struct CLIConfig + { + bool timestamp = false; + bool ocean = false; + int camera_index = -1; + }; + SceneViewerApplication(const std::string &path, + const std::string &config_path, const std::string &quirks_path, + const CLIConfig &cli_config); + ~SceneViewerApplication(); + void render_frame(double frame_time, double elapsed_time) override; + void rescale_scene(float radius); + void loop_animations(); + +protected: + void update_scene(TaskComposer &composer, double frame_time, double elapsed_time); + void render_scene(TaskComposer &composer); + void post_frame() override; + + RenderContext context; + RenderContext depth_contexts[NumShadowCascades]; + RenderContext fallback_depth_context; + + RendererSuite renderer_suite; + RendererSuite::Config renderer_suite_config; + FlatRenderer flat_renderer; + LightingParameters lighting; + LightingParameters fallback_lighting; + FPSCamera cam; + SceneLoader scene_loader; + std::unique_ptr animation_system; + + Camera *selected_camera = nullptr; + DirectionalLightComponent *selected_directional = nullptr; + DirectionalLightComponent default_directional_light; + + SceneTransformManager scene_transform_manager; + + void on_device_created(const Vulkan::DeviceCreatedEvent &e); + void on_device_destroyed(const Vulkan::DeviceCreatedEvent &e); + void on_swapchain_changed(const Vulkan::SwapchainParameterEvent &e); + void on_swapchain_destroyed(const Vulkan::SwapchainParameterEvent &e); + bool on_key_down(const KeyboardEvent &e); + RenderGraph graph; + + bool need_shadow_map_update = true; + AABB shadow_scene_aabb; + + std::unique_ptr cluster; + std::unique_ptr volumetric_fog; + std::unique_ptr volumetric_diffuse; + RenderQueue queue; + + void setup_shadow_map(); + void update_shadow_scene_aabb(); + void render_ui(Vulkan::CommandBuffer &cmd); + + void add_main_pass(Vulkan::Device &device, const std::string &tag); + void add_main_pass_forward(Vulkan::Device &device, const std::string &tag); + void add_main_pass_deferred(Vulkan::Device &device, const std::string &tag); + void add_mv_pass(const std::string &tag, const std::string &depth, bool full_mv); + + void add_shadow_pass(Vulkan::Device &device, const std::string &tag); + void add_shadow_pass_fallback(Vulkan::Device &device, const std::string &tag); + + std::vector recorded_cameras; + + std::string get_name() override; + + void bake_render_graph(const Vulkan::SwapchainParameterEvent &swap); + const Vulkan::SwapchainParameterEvent *pending_swapchain = nullptr; + +private: + void read_config(const std::string &path); + void read_quirks(const std::string &path); + void read_lights(); + + struct Config + { + RendererType renderer_type = RendererType::GeneralDeferred; + unsigned msaa = 1; + float shadow_map_resolution = 2048.0f; + unsigned clustered_lights_shadow_resolution = 512; + + SceneRendererFlags pcf_flags = SCENE_RENDERER_SHADOW_PCF_WIDE_BIT; + float resolution_scale = 1.0f; + bool resolution_scale_sharpen = true; + float lod_bias = 0.0f; + bool directional_light_shadows = true; + bool directional_light_cascaded_shadows = true; + bool directional_light_shadows_vsm = false; + bool clustered_lights_shadows = true; + bool clustered_lights_shadows_vsm = false; + bool hdr_bloom = true; + bool hdr_bloom_dynamic_exposure = true; + bool forward_depth_prepass = true; + bool rt_fp16 = false; + bool rescale_scene = false; + bool show_ui = true; + bool volumetric_fog = false; + bool volumetric_fog_regions = true; + bool volumetric_diffuse = false; + bool ssao = true; + bool debug_probes = false; + bool ssr = false; + PostAAType postaa_type = PostAAType::None; + }; + Config config; + CLIConfig cli_config; + + void export_lights(); + void export_cameras(); + + enum { FrameWindowSize = 64, FrameWindowSizeMask = FrameWindowSize - 1 }; + float last_frame_times[FrameWindowSize] = {}; + unsigned last_frame_index = 0; + + TemporalJitter jitter; + void capture_environment_probe(); + + RenderTextureResource *ssao_output = nullptr; + RenderTextureResource *shadows = nullptr; + RenderTextureResource *fallback_shadows = nullptr; + RenderTextureResource *hiz_main = nullptr; + RenderTextureResource *hiz_depth = nullptr; + Util::SmallVector hiz_depth_peel; + + CullingPassesInfo culling_passes_info = {}; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/compiler/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/compiler/CMakeLists.txt new file mode 100644 index 00000000..ab31bd19 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/compiler/CMakeLists.txt @@ -0,0 +1,18 @@ +add_granite_internal_lib(granite-compiler compiler.cpp compiler.hpp) +target_include_directories(granite-compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-compiler + PUBLIC granite-application-global + PRIVATE SPIRV-Tools shaderc granite-path granite-util) + +if (GRANITE_SHADER_COMPILER_OPTIMIZE) + target_compile_definitions(granite-compiler PRIVATE GRANITE_COMPILER_OPTIMIZE=1) +else() + target_compile_definitions(granite-compiler PRIVATE GRANITE_COMPILER_OPTIMIZE=0) +endif() + +if (${CMAKE_BUILD_TYPE} MATCHES "Debug") + target_compile_definitions(granite-compiler PRIVATE GRANITE_COMPILER_DEBUG=1) +else() + target_compile_definitions(granite-compiler PRIVATE GRANITE_COMPILER_DEBUG=0) +endif() + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/compiler/compiler.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/compiler/compiler.cpp new file mode 100644 index 00000000..e4ba8079 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/compiler/compiler.cpp @@ -0,0 +1,381 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "compiler.hpp" +#include "shaderc/shaderc.hpp" +#include "path_utils.hpp" +#include "logging.hpp" +#include "string_helpers.hpp" + +#include "spirv-tools/libspirv.hpp" + +namespace Granite +{ +GLSLCompiler::GLSLCompiler(FilesystemInterface &iface_) + : iface(iface_) +{ +} + +static Stage stage_from_path(const std::string &path) +{ + auto ext = Path::ext(path); + if (ext == "vert") + return Stage::Vertex; + else if (ext == "frag") + return Stage::Fragment; + else if (ext == "comp") + return Stage::Compute; + else if (ext == "task") + return Stage::Task; + else if (ext == "mesh") + return Stage::Mesh; + else + return Stage::Unknown; +} + +static Stage convert_stage(const std::string &stage) +{ + if (stage == "vertex") + return Stage::Vertex; + else if (stage == "compute") + return Stage::Compute; + else if (stage == "fragment") + return Stage::Fragment; + else if (stage == "task") + return Stage::Task; + else if (stage == "mesh") + return Stage::Mesh; + else + return Stage::Unknown; +} + +bool GLSLCompiler::set_source_from_file(const std::string &path, Stage forced_stage) +{ + if (!iface.load_text_file(path, source)) + { + LOGE("Failed to load shader: %s\n", path.c_str()); + return false; + } + + source_path = path; + + if (forced_stage != Stage::Unknown) + stage = forced_stage; + else + stage = stage_from_path(path); + + return stage != Stage::Unknown; +} + +bool GLSLCompiler::set_source_from_file_multistage(const std::string &path) +{ + if (iface.load_text_file(path, source)) + { + LOGE("Failed to load shader: %s\n", path.c_str()); + return false; + } + + source_path = path; + stage = Stage::Unknown; + return true; +} + +void GLSLCompiler::set_include_directories(const std::vector *include_directories_) +{ + include_directories = include_directories_; +} + +bool GLSLCompiler::find_include_path(const std::string &source_path_, const std::string &include_path, + std::string &included_path, std::string &included_source) +{ + auto relpath = Path::relpath(source_path_, include_path); + if (iface.load_text_file(relpath, included_source)) + { + included_path = relpath; + return true; + } + + if (include_directories) + { + for (auto &include_dir : *include_directories) + { + auto path = Path::join(include_dir, include_path); + if (iface.load_text_file(path, included_source)) + { + included_path = path; + return true; + } + } + } + + return false; +} + +bool GLSLCompiler::parse_variants(const std::string &source_, const std::string &path) +{ + auto lines = Util::split(source_, "\n"); + + unsigned line_index = 1; + size_t offset; + + for (auto &line : lines) + { + // This check, followed by the include statement check below isn't even remotely correct, + // but we only have to care about shaders we control here. + if ((offset = line.find("//")) != std::string::npos) + line = line.substr(0, offset); + + if ((offset = line.find("#include \"")) != std::string::npos) + { + auto include_path = line.substr(offset + 10); + if (!include_path.empty() && include_path.back() == '"') + include_path.pop_back(); + + std::string included_source; + if (!find_include_path(path, include_path, include_path, included_source)) + { + LOGE("Failed to include GLSL file: %s\n", include_path.c_str()); + return false; + } + + preprocessed_source += Util::join("#line ", 1, " \"", include_path, "\"\n"); + if (!parse_variants(included_source, include_path)) + return false; + preprocessed_source += Util::join("#line ", line_index + 1, " \"", path, "\"\n"); + + dependencies.insert(include_path); + } + else if (line.find("#pragma optimize off") == 0) + { + optimization = Optimization::ForceOff; + preprocessed_source += "// #pragma optimize off"; + preprocessed_source += '\n'; + } + else if (line.find("#pragma optimize on") == 0) + { + optimization = Optimization::ForceOn; + preprocessed_source += "// #pragma optimize on"; + preprocessed_source += '\n'; + } + else if (line.find("#pragma stage ") == 0) + { + if (!preprocessed_source.empty()) + { + preprocessed_sections.push_back({ preprocessing_active_stage, std::move(preprocessed_source) }); + preprocessed_source = {}; + } + preprocessing_active_stage = convert_stage(line.substr(14)); + preprocessed_source += Util::join("#line ", line_index + 1, " \"", path, "\"\n"); + } + else if (line.find("#pragma ") == 0) + { + pragmas.push_back(line.substr(8)); + preprocessed_source += "// "; + preprocessed_source += line; + preprocessed_source += '\n'; + } + else + { + preprocessed_source += line; + preprocessed_source += '\n'; + + auto first_non_space = line.find_first_not_of(' '); + if (first_non_space != std::string::npos && line[first_non_space] == '#') + { + auto keywords = Util::split(line.substr(first_non_space + 1), " "); + if (keywords.size() == 1) + { + auto &word = keywords.front(); + if (word == "endif") + preprocessed_source += Util::join("#line ", line_index + 1, " \"", path, "\"\n"); + } + } + } + + line_index++; + } + return true; +} + +bool GLSLCompiler::preprocess() +{ + // Use a custom preprocessor where we only resolve includes once. + // The builtin glslang preprocessor is not suitable for this task, + // since we need to defer resolving defines. + + preprocessed_source.clear(); + pragmas.clear(); + preprocessed_sections.clear(); + preprocessing_active_stage = Stage::Unknown; + + bool ret = parse_variants(source, source_path); + + if (ret && !preprocessed_source.empty()) + { + preprocessed_sections.push_back({ preprocessing_active_stage, std::move(preprocessed_source) }); + preprocessed_source = {}; + } + + return ret; +} + +Util::Hash GLSLCompiler::get_source_hash() const +{ + Util::Hasher h; + for (auto §ion : preprocessed_sections) + { + h.u32(uint32_t(section.stage)); + h.string(section.source); + } + h.string(preprocessed_source); + return h.get(); +} + +std::vector GLSLCompiler::compile(std::string &error_message, const std::vector> *defines) const +{ + shaderc::Compiler compiler; + shaderc::CompileOptions options; + if (preprocessed_sections.empty()) + { + error_message = "Need to preprocess source first."; + return {}; + } + + if (defines) + for (auto &define : *defines) + options.AddMacroDefinition(define.first, std::to_string(define.second)); + +#if GRANITE_COMPILER_OPTIMIZE + if (optimization != Optimization::ForceOff) + options.SetOptimizationLevel(shaderc_optimization_level_performance); + else + options.SetOptimizationLevel(shaderc_optimization_level_zero); +#else + options.SetOptimizationLevel(shaderc_optimization_level_zero); +#endif + + if (!strip && (GRANITE_COMPILER_DEBUG || optimization == Optimization::ForceOff)) + options.SetGenerateDebugInfo(); + + shaderc_shader_kind kind; + switch (stage) + { + case Stage::Vertex: + kind = shaderc_glsl_vertex_shader; + options.AddMacroDefinition("STAGE_VERTEX", "1"); + break; + + case Stage::Fragment: + kind = shaderc_glsl_fragment_shader; + options.AddMacroDefinition("STAGE_FRAGMENT", "1"); + break; + + case Stage::Compute: + kind = shaderc_glsl_compute_shader; + options.AddMacroDefinition("STAGE_COMPUTE", "1"); + break; + + case Stage::Task: + kind = shaderc_glsl_task_shader; + options.AddMacroDefinition("STAGE_TASK", "1"); + break; + + case Stage::Mesh: + kind = shaderc_glsl_mesh_shader; + options.AddMacroDefinition("STAGE_MESH", "1"); + break; + + default: + error_message = "Invalid shader stage."; + return {}; + } + + auto env = shaderc_env_version_vulkan_1_1; + auto spv_version = shaderc_spirv_version_1_3; + + if (target == Target::Vulkan12) + { + env = shaderc_env_version_vulkan_1_2; + spv_version = shaderc_spirv_version_1_5; + } + else if (target == Target::Vulkan13) + { + env = shaderc_env_version_vulkan_1_3; + spv_version = shaderc_spirv_version_1_6; + } + + options.SetTargetEnvironment(shaderc_target_env_vulkan, env); + options.SetTargetSpirv(spv_version); + options.SetSourceLanguage(shaderc_source_language_glsl); + + shaderc::SpvCompilationResult result; + + if (preprocessed_sections.size() == 1) + { + if (preprocessed_sections.front().stage != Stage::Unknown && preprocessed_sections.front().stage != stage) + { + error_message = "No preprocessed sections available."; + return {}; + } + result = compiler.CompileGlslToSpv(preprocessed_sections.front().source, kind, source_path.c_str(), options); + } + else + { + std::string combined_source; + for (auto §ion : preprocessed_sections) + if (section.stage == Stage::Unknown || section.stage == stage) + combined_source += section.source; + if (combined_source.empty()) + { + error_message = "No preprocessed sections available."; + return {}; + } + result = compiler.CompileGlslToSpv(combined_source, kind, source_path.c_str(), options); + } + + error_message.clear(); + if (result.GetCompilationStatus() != shaderc_compilation_status_success) + { + error_message = result.GetErrorMessage(); + return {}; + } + + std::vector compiled_spirv(result.cbegin(), result.cend()); + +#if 0 + spvtools::SpirvTools core(target == Target::Vulkan13 ? SPV_ENV_VULKAN_1_3 : SPV_ENV_VULKAN_1_1); + core.SetMessageConsumer([&error_message](spv_message_level_t, const char *, const spv_position_t&, const char *message) { + error_message = message; + }); + + spvtools::ValidatorOptions opts; + opts.SetScalarBlockLayout(true); + if (!core.Validate(compiled_spirv.data(), compiled_spirv.size(), opts)) + { + error_message += "\nFailed to validate SPIR-V.\n"; + return {}; + } +#endif + + return compiled_spirv; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/compiler/compiler.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/compiler/compiler.hpp new file mode 100644 index 00000000..c016ef7d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/compiler/compiler.hpp @@ -0,0 +1,139 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include "small_vector.hpp" +#include "global_managers.hpp" +#include "hash.hpp" + +namespace Granite +{ +enum class Stage +{ + Vertex, + Fragment = 4, // Skip over tess/geom to match Vulkan ordering + Compute, + Task, + Mesh, + Unknown +}; + +enum class Target +{ + Vulkan11, + Vulkan12, + Vulkan13 +}; + +class GLSLCompiler +{ +public: + explicit GLSLCompiler(FilesystemInterface &iface); + + void set_target(Target target_) + { + target = target_; + } + + void set_stage(Stage stage_) + { + stage = stage_; + } + + void set_source(std::string source_, std::string path) + { + source = std::move(source_); + source_path = std::move(path); + } + + void set_include_directories(const std::vector *include_directories); + + bool set_source_from_file(const std::string &path, Stage stage = Stage::Unknown); + bool set_source_from_file_multistage(const std::string &path); + bool preprocess(); + Util::Hash get_source_hash() const; + + std::vector compile(std::string &error_message, const std::vector> *defines = nullptr) const; + + const std::unordered_set &get_dependencies() const + { + return dependencies; + } + + enum class Optimization + { + ForceOff, + ForceOn, + Default + }; + + void set_optimization(Optimization opt) + { + optimization = opt; + } + + void set_strip(bool strip_) + { + strip = strip_; + } + + const std::vector &get_user_pragmas() const + { + return pragmas; + } + +private: + FilesystemInterface &iface; + std::string source; + std::string source_path; + const std::vector *include_directories = nullptr; + Stage stage = Stage::Unknown; + + std::unordered_set dependencies; + struct Section + { + Stage stage; + std::string source; + }; + Util::SmallVector
preprocessed_sections; + std::string preprocessed_source; + Stage preprocessing_active_stage = Stage::Unknown; + + std::vector> preprocessed_lines; + std::vector pragmas; + + Target target = Target::Vulkan11; + + bool parse_variants(const std::string &source, const std::string &path); + + Optimization optimization = Optimization::Default; + bool strip = false; + + bool find_include_path(const std::string &source_path, const std::string &include_path, + std::string &included_path, std::string &included_source); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/ecs/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/ecs/CMakeLists.txt new file mode 100644 index 00000000..3bf1383b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/ecs/CMakeLists.txt @@ -0,0 +1,3 @@ +add_granite_internal_lib(granite-ecs ecs.hpp ecs.cpp) +target_include_directories(granite-ecs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-ecs PUBLIC granite-util) \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/ecs/ecs.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/ecs/ecs.cpp new file mode 100644 index 00000000..423cd404 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/ecs/ecs.cpp @@ -0,0 +1,138 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "ecs.hpp" + +namespace Granite +{ +Entity *EntityPool::create_entity() +{ + Util::Hasher hasher; + hasher.u64(++cookie); + auto *entity = entity_pool.allocate(this, hasher.get()); + entity->pool_offset = entities.size(); + entities.push_back(entity); + return entity; +} + +void EntityPool::free_component(Entity &entity, ComponentType id, ComponentNode *component) +{ + auto *c = component_types.find(id); + assert(c); + c->free_component(component->get()); + component_nodes.free(component); + + auto *component_groups = component_to_groups.find(id); + if (component_groups) + { + for (auto &group : *component_groups) + { + auto *g = groups.find(group.get_hash()); + if (g) + g->remove_entity(entity); + } + } +} + +void EntityPool::delete_entity(Entity *entity) +{ + { + auto &components = entity->get_components(); + auto &list = components.inner_list(); + auto itr = list.begin(); + while (itr != list.end()) + { + auto *component = itr.get(); + itr = list.erase(itr); + free_component(*entity, component->get_hash(), component); + } + } + + auto offset = entity->pool_offset; + assert(offset < entities.size()); + + entities[offset] = entities.back(); + entities[offset]->pool_offset = offset; + entities.pop_back(); + entity_pool.free(entity); +} + +EntityPool::~EntityPool() +{ + { + auto &list = component_types.inner_list(); + auto itr = list.begin(); + while (itr != list.end()) + { + auto *to_free = itr.get(); + itr = list.erase(itr); + delete to_free; + } + } + + reset_groups(); + free_groups(); +} + +void EntityDeleter::operator()(Entity *entity) +{ + entity->get_pool()->delete_entity(entity); +} + +void EntityPool::free_groups() +{ + auto &list = groups.inner_list(); + auto itr = list.begin(); + while (itr != list.end()) + { + auto *to_free = itr.get(); + itr = list.erase(itr); + delete to_free; + } + groups.clear(); +} + +void EntityPool::reset_groups() +{ + for (auto &group : groups) + group.reset(); +} + +void EntityPool::reset_groups_for_component_type(ComponentType id) +{ + auto *component_groups = component_to_groups.find(id); + if (component_groups) + { + for (auto &group : *component_groups) + { + auto *g = groups.find(group.get_hash()); + if (g) + g->reset(); + } + } +} + +void ComponentSet::insert(ComponentType type) +{ + set.emplace_yield(type); +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/ecs/ecs.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/ecs/ecs.hpp new file mode 100644 index 00000000..498ea2a7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/ecs/ecs.hpp @@ -0,0 +1,456 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include "object_pool.hpp" +#include "intrusive.hpp" +#include "intrusive_hash_map.hpp" +#include "compile_time_hash.hpp" +#include "enum_cast.hpp" +#include + +namespace Granite +{ +struct ComponentBase +{ +}; + +template +inline T *get_component(Tup &t) +{ + return std::get(t); +} + +template +inline T *get(const std::tuple &t) +{ + return std::get<0>(t); +} + +template +using ComponentGroupVector = std::vector>; + +class Entity; + +#define GRANITE_COMPONENT_TYPE_HASH(x) ::Util::compile_time_fnv1(#x) +using ComponentType = uint64_t; + +#define GRANITE_COMPONENT_TYPE_DECL(x) \ +enum class ComponentTypeWrapper : ::Granite::ComponentType { \ + type_id = GRANITE_COMPONENT_TYPE_HASH(x) \ +}; \ +static inline constexpr ::Granite::ComponentType get_component_id_hash() { \ + return ::Granite::ComponentType(ComponentTypeWrapper::type_id); \ +} + +struct ComponentSetKey : Util::IntrusiveHashMapEnabled +{ +}; + +class ComponentSet : public Util::IntrusiveHashMapEnabled +{ +public: + void insert(ComponentType type); + + Util::IntrusiveList::Iterator begin() + { + return set.begin(); + } + + Util::IntrusiveList::Iterator end() + { + return set.end(); + } + +private: + Util::IntrusiveHashMap set; +}; + +using ComponentNode = Util::IntrusivePODWrapper; +using ComponentHashMap = Util::IntrusiveHashMapHolder; +using ComponentGroupHashMap = Util::IntrusiveHashMap; + +struct ComponentIDMapping +{ + template + constexpr static Util::Hash get_id() + { + enum class Result : Util::Hash { result = T::get_component_id_hash() }; + return Util::Hash(Result::result); + } + + template + constexpr static Util::Hash get_group_id() + { + enum class Result : Util::Hash { result = Util::compile_time_fnv1_merged(Ts::get_component_id_hash()...) }; + return Util::Hash(Result::result); + } +}; + +class EntityGroupBase : public Util::IntrusiveHashMapEnabled +{ +public: + virtual ~EntityGroupBase() = default; + virtual void add_entity(Entity &entity) = 0; + virtual void remove_entity(const Entity &entity) = 0; + virtual void reset() = 0; +}; + +class EntityPool; + +struct EntityDeleter +{ + void operator()(Entity *entity); +}; + +class Entity : public Util::IntrusiveListEnabled +{ +public: + friend class EntityPool; + + Entity(EntityPool *pool_, Util::Hash hash_) + : pool(pool_), hash(hash_) + { + } + + bool has_component(ComponentType id) const + { + auto itr = components.find(id); + return itr != nullptr; + } + + template + bool has_component() const + { + return has_component(ComponentIDMapping::get_id()); + } + + template + T *get_component() + { + auto *t = components.find(ComponentIDMapping::get_id()); + if (t) + return static_cast(t->get()); + else + return nullptr; + } + + template + const T *get_component() const + { + auto *t = components.find(ComponentIDMapping::get_id()); + if (t) + return static_cast(t->get()); + else + return nullptr; + } + + template + T *allocate_component(Ts&&... ts); + + template + void free_component(); + + ComponentHashMap &get_components() + { + return components; + } + + EntityPool *get_pool() + { + return pool; + } + + Util::Hash get_hash() const + { + return hash; + } + + bool mark_for_destruction() + { + bool ret = !marked; + marked = true; + return ret; + } + +private: + EntityPool *pool; + Util::Hash hash; + size_t pool_offset = 0; + ComponentHashMap components; + bool marked = false; +}; + +template +class EntityGroup : public EntityGroupBase +{ +public: + void add_entity(Entity &entity) override final + { + if (has_all_components(entity)) + { + entity_to_index[entity.get_hash()].get() = entities.size(); + groups.push_back(std::make_tuple(entity.get_component()...)); + entities.push_back(&entity); + } + } + + void remove_entity(const Entity &entity) override final + { + size_t offset; + if (entity_to_index.find_and_consume_pod(entity.get_hash(), offset)) + { + entities[offset] = entities.back(); + groups[offset] = groups.back(); + entity_to_index[entities[offset]->get_hash()].get() = offset; + + entity_to_index.erase(entity.get_hash()); + entities.pop_back(); + groups.pop_back(); + } + } + + const ComponentGroupVector &get_groups() const + { + return groups; + } + + const std::vector &get_entities() const + { + return entities; + } + + void reset() override final + { + groups.clear(); + entities.clear(); + entity_to_index.clear(); + } + +private: + ComponentGroupVector groups; + std::vector entities; + Util::IntrusiveHashMap> entity_to_index; + + template + struct HasAllComponents; + + template + struct HasAllComponents + { + static bool has_component(const Entity &entity) + { + return entity.has_component(ComponentIDMapping::get_id()) && + HasAllComponents::has_component(entity); + } + }; + + template + struct HasAllComponents + { + static bool has_component(const Entity &entity) + { + return entity.has_component(ComponentIDMapping::get_id()); + } + }; + + template + bool has_all_components(const Entity &entity) + { + return HasAllComponents::has_component(entity); + } +}; + +class ComponentAllocatorBase : public Util::IntrusiveHashMapEnabled +{ +public: + virtual ~ComponentAllocatorBase() = default; + virtual void free_component(ComponentBase *component) = 0; +}; + +template +struct ComponentAllocator : public ComponentAllocatorBase +{ + Util::ObjectPool pool; + + void free_component(ComponentBase *component) override final + { + pool.free(static_cast(component)); + } +}; + +class EntityPool +{ +public: + ~EntityPool(); + + EntityPool() = default; + void operator=(const EntityPool &) = delete; + EntityPool(const EntityPool &) = delete; + + Entity *create_entity(); + void delete_entity(Entity *entity); + + template + EntityGroup *get_component_group_holder() + { + ComponentType group_id = ComponentIDMapping::get_group_id(); + auto *t = groups.find(group_id); + if (!t) + { + register_group(group_id); + + t = new EntityGroup(); + t->set_hash(group_id); + groups.insert_yield(t); + + auto *group = static_cast *>(t); + for (auto &entity : entities) + group->add_entity(*entity); + } + + return static_cast *>(t); + } + + template + const ComponentGroupVector &get_component_group() + { + auto *group = get_component_group_holder(); + return group->get_groups(); + } + + template + const std::vector &get_component_entities() + { + auto *group = get_component_group_holder(); + return group->get_entities(); + } + + template + T *allocate_component(Entity &entity, Ts&&... ts) + { + constexpr ComponentType id = ComponentIDMapping::get_id(); + auto *t = component_types.find(id); + if (!t) + { + t = new ComponentAllocator(); + t->set_hash(id); + component_types.insert_yield(t); + } + + auto *allocator = static_cast *>(t); + auto *existing = entity.components.find(id); + + if (existing) + { + auto *comp = static_cast(existing->get()); + // In-place modify. Destroy old data, and in-place construct. + // Do not need to fiddle with data structures internally. + comp->~T(); + return new (comp) T(std::forward(ts)...); + } + else + { + auto *comp = allocator->pool.allocate(std::forward(ts)...); + auto *node = component_nodes.allocate(comp); + node->set_hash(id); + entity.components.insert_replace(node); + + auto *component_groups = component_to_groups.find(id); + if (component_groups) + for (auto &group : *component_groups) + groups.find(group.get_hash())->add_entity(entity); + + return comp; + } + } + + void free_component(Entity &entity, ComponentType id, ComponentNode *component); + void reset_groups(); + void reset_groups_for_component_type(ComponentType id); + +private: + Util::ObjectPool entity_pool; + Util::IntrusiveHashMapHolder groups; + Util::IntrusiveHashMapHolder component_types; + Util::ObjectPool component_nodes; + ComponentGroupHashMap component_to_groups; + std::vector entities; + uint64_t cookie = 0; + + template + struct GroupRegisters; + + template + struct GroupRegisters + { + static void register_group(ComponentGroupHashMap &groups, + ComponentType group_id) + { + groups.emplace_yield(ComponentIDMapping::get_id())->insert(group_id); + GroupRegisters::register_group(groups, group_id); + } + }; + + template + struct GroupRegisters + { + static void register_group(ComponentGroupHashMap &groups, + ComponentType group_id) + { + groups.emplace_yield(ComponentIDMapping::get_id())->insert(group_id); + } + }; + + template + void register_group(ComponentType group_id) + { + GroupRegisters::register_group(component_to_groups, group_id); + } + + void free_groups(); +}; + +template +T *Entity::allocate_component(Ts&&... ts) +{ + return pool->allocate_component(*this, std::forward(ts)...); +} + +template +void Entity::free_component() +{ + auto id = ComponentIDMapping::get_id(); + auto *t = components.find(id); + if (t) + { + components.erase(t); + pool->free_component(*this, t->get_hash(), t); + } +} + +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/event/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/event/CMakeLists.txt new file mode 100644 index 00000000..f2e62d20 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/event/CMakeLists.txt @@ -0,0 +1,3 @@ +add_granite_internal_lib(granite-event event.hpp event.cpp) +target_include_directories(granite-event PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-event PUBLIC granite-util granite-application-global) \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/event/event.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/event/event.cpp new file mode 100644 index 00000000..d40467ae --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/event/event.cpp @@ -0,0 +1,213 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "event.hpp" +#include +#include + +namespace Granite +{ +EventManager::~EventManager() +{ + dispatch(); + for (auto &event_type : latched_events) + { + for (auto &handler : event_type.handlers) + { + dispatch_down_events(event_type.queued_events, handler); + // Before the event manager dies, make sure no stale EventHandler objects try to unregister themselves. + handler.unregister_key->release_manager_reference(); + } + } +} + +void EventManager::dispatch() +{ + for (auto &event_type : events) + { + auto &handlers = event_type.handlers; + auto &queued_events = event_type.queued_events; + auto itr = remove_if(begin(handlers), end(handlers), [&](const Handler &handler) { + for (auto &event : queued_events) + { + if (!handler.mem_fn(handler.handler, *event)) + { + handler.unregister_key->release_manager_reference(); + return true; + } + } + return false; + }); + + handlers.erase(itr, end(handlers)); + queued_events.clear(); + } +} + +void EventManager::dispatch_event(std::vector &handlers, const Event &e) +{ + auto itr = remove_if(begin(handlers), end(handlers), [&](const Handler &handler) -> bool { + bool to_remove = !handler.mem_fn(handler.handler, e); + if (to_remove) + handler.unregister_key->release_manager_reference(); + return to_remove; + }); + + handlers.erase(itr, end(handlers)); +} + +void EventManager::dispatch_up_events(std::vector> &up_events, const LatchHandler &handler) +{ + for (auto &event : up_events) + handler.up_fn(handler.handler, *event); +} + +void EventManager::dispatch_down_events(std::vector> &down_events, const LatchHandler &handler) +{ + for (auto &event : down_events) + handler.down_fn(handler.handler, *event); +} + +void EventManager::LatchEventTypeData::flush_recursive_handlers() +{ + handlers.insert(end(handlers), begin(recursive_handlers), end(recursive_handlers)); + recursive_handlers.clear(); +} + +void EventManager::EventTypeData::flush_recursive_handlers() +{ + handlers.insert(end(handlers), begin(recursive_handlers), end(recursive_handlers)); + recursive_handlers.clear(); +} + +void EventManager::dispatch_up_event(LatchEventTypeData &event_type, const Event &event) +{ + event_type.dispatching = true; + for (auto &handler : event_type.handlers) + handler.up_fn(handler.handler, event); + event_type.flush_recursive_handlers(); + event_type.dispatching = false; +} + +void EventManager::dispatch_down_event(LatchEventTypeData &event_type, const Event &event) +{ + event_type.dispatching = true; + for (auto &handler : event_type.handlers) + handler.down_fn(handler.handler, event); + event_type.flush_recursive_handlers(); + event_type.dispatching = false; +} + +void EventManager::unregister_handler(EventHandler *handler) +{ + for (auto &event_type : events) + { + auto itr = remove_if(begin(event_type.handlers), end(event_type.handlers), [&](const Handler &h) -> bool { + bool to_remove = h.unregister_key == handler; + if (to_remove) + h.unregister_key->release_manager_reference(); + return to_remove; + }); + + if (itr != end(event_type.handlers) && event_type.dispatching) + throw std::logic_error("Unregistering handlers while dispatching events."); + + if (itr != end(event_type.handlers)) + event_type.handlers.erase(itr, end(event_type.handlers)); + } +} + +void EventManager::unregister_latch_handler(EventHandler *handler) +{ + for (auto &event_type : latched_events) + { + auto itr = remove_if(begin(event_type.handlers), end(event_type.handlers), [&](const LatchHandler &h) -> bool { + bool to_remove = h.unregister_key == handler; + if (to_remove) + h.unregister_key->release_manager_reference(); + return to_remove; + }); + + if (itr != end(event_type.handlers)) + event_type.handlers.erase(itr, end(event_type.handlers)); + } +} + +void EventManager::dequeue_latched(uint64_t cookie) +{ + for (auto &event_type : latched_events) + { + auto &queued_events = event_type.queued_events; + if (event_type.enqueueing) + throw std::logic_error("Dequeueing latched while queueing events."); + event_type.enqueueing = true; + + auto itr = remove_if(begin(queued_events), end(queued_events), [&](const std::unique_ptr &event) { + bool signal = event->get_cookie() == cookie; + if (signal) + dispatch_down_event(event_type, *event); + return signal; + }); + + event_type.enqueueing = false; + queued_events.erase(itr, end(queued_events)); + } +} + +void EventManager::dequeue_all_latched(EventType type) +{ + auto &event_type = latched_events[type]; + if (event_type.enqueueing) + throw std::logic_error("Dequeueing latched while queueing events."); + + event_type.enqueueing = true; + for (auto &event : event_type.queued_events) + dispatch_down_event(event_type, *event); + event_type.queued_events.clear(); + event_type.enqueueing = false; +} + +void EventHandler::release_manager_reference() +{ + assert(event_manager_ref_count > 0); + assert(event_manager); + if (--event_manager_ref_count == 0) + event_manager = nullptr; +} + +void EventHandler::add_manager_reference(EventManager *manager) +{ + assert(!event_manager_ref_count || manager == event_manager); + event_manager = manager; + event_manager_ref_count++; +} + +EventHandler::~EventHandler() +{ + if (event_manager) + event_manager->unregister_handler(this); + // Splitting the branch is significant since event manager can release its last reference in between. + if (event_manager) + event_manager->unregister_latch_handler(this); + assert(event_manager_ref_count == 0 && !event_manager); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/event/event.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/event/event.hpp new file mode 100644 index 00000000..69d6375e --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/event/event.hpp @@ -0,0 +1,251 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include "compile_time_hash.hpp" +#include "intrusive_hash_map.hpp" +#include "global_managers.hpp" + +#define EVENT_MANAGER_REGISTER(clazz, member, event) \ + GRANITE_EVENT_MANAGER()->register_handler(this) +#define EVENT_MANAGER_REGISTER_LATCH(clazz, up_event, down_event, event) \ + GRANITE_EVENT_MANAGER()->register_latch_handler(this) + +namespace Granite +{ +class Event; + +template +Return member_function_invoker(void *object, const Event &e) +{ + return (static_cast(object)->*callback)(static_cast(e)); +} + +#define GRANITE_EVENT_TYPE_HASH(x) ::Util::compile_time_fnv1(#x) +using EventType = uint64_t; + +#define GRANITE_EVENT_TYPE_DECL(x) \ +enum class EventTypeWrapper : ::Granite::EventType { \ + type_id = GRANITE_EVENT_TYPE_HASH(x) \ +}; \ +static inline constexpr ::Granite::EventType get_type_id() { \ + return ::Granite::EventType(EventTypeWrapper::type_id); \ +} + +class Event +{ +public: + virtual ~Event() = default; + + Event() = default; + + // Doesn't have to be set unless type information is going to be lost. + // E.g. we're storing the Event some place and we have type-erasure. + // Having this set helps us recover type information for dispatch. + explicit Event(EventType type_) + : type(type_) + { + } + + EventType get_type_id() const + { + return type; + } + + void set_cookie(uint64_t cookie_) + { + cookie = cookie_; + } + + uint64_t get_cookie() const + { + return cookie; + } + +private: + EventType type = 0; + uint64_t cookie = 0; +}; + +class EventManager; + +class EventHandler +{ +public: + EventHandler(const EventHandler &) = delete; + void operator=(const EventHandler &) = delete; + EventHandler() = default; + ~EventHandler(); + + void add_manager_reference(EventManager *manager); + void release_manager_reference(); + +private: + EventManager *event_manager = nullptr; + uint32_t event_manager_ref_count = 0; +}; + +class EventManager final : public EventManagerInterface +{ +public: + template + void enqueue(P&&... p) + { + static constexpr auto type = T::get_type_id(); + auto &l = events[type]; + + auto ptr = std::unique_ptr(new T(std::forward

(p)...)); + l.queued_events.emplace_back(std::move(ptr)); + } + + template + uint64_t enqueue_latched(P&&... p) + { + static constexpr auto type = T::get_type_id(); + auto &l = latched_events[type]; + auto ptr = std::unique_ptr(new T(std::forward

(p)...)); + uint64_t cookie = ++cookie_counter; + ptr->set_cookie(cookie); + + if (l.enqueueing) + throw std::logic_error("Cannot enqueue more latched events while handling events."); + l.enqueueing = true; + + auto *event = ptr.get(); + l.queued_events.emplace_back(std::move(ptr)); + dispatch_up_event(l, *event); + l.enqueueing = false; + return cookie; + } + + void dequeue_latched(uint64_t cookie); + void dequeue_all_latched(EventType type); + + template + void dispatch_inline(const T &t) + { + static constexpr auto type = T::get_type_id(); + auto &l = events[type]; + dispatch_event(l.handlers, t); + } + + void dispatch_inline(const Event &e) + { + assert(e.get_type_id() != 0); + auto &l = events[e.get_type_id()]; + dispatch_event(l.handlers, e); + } + + void dispatch(); + + template + void register_handler(T *handler) + { + handler->add_manager_reference(this); + static constexpr auto type_id = EventType::get_type_id(); + auto &l = events[type_id]; + if (l.dispatching) + l.recursive_handlers.push_back({ member_function_invoker, handler, handler }); + else + l.handlers.push_back({ member_function_invoker, handler, handler }); + } + + void unregister_handler(EventHandler *handler); + + template + void register_latch_handler(T *handler) + { + handler->add_manager_reference(this); + LatchHandler h{ + member_function_invoker, + member_function_invoker, + handler, handler }; + + static constexpr auto type_id = EventType::get_type_id(); + auto &levents = latched_events[type_id]; + dispatch_up_events(levents.queued_events, h); + + auto &l = latched_events[type_id]; + if (l.dispatching) + l.recursive_handlers.push_back(h); + else + l.handlers.push_back(h); + } + + void unregister_latch_handler(EventHandler *handler); + + ~EventManager(); + +private: + struct Handler + { + bool (*mem_fn)(void *object, const Event &event); + void *handler; + EventHandler *unregister_key; + }; + + struct LatchHandler + { + void (*up_fn)(void *object, const Event &event); + void (*down_fn)(void *object, const Event &event); + void *handler; + EventHandler *unregister_key; + }; + + struct EventTypeData : Util::IntrusiveHashMapEnabled + { + std::vector> queued_events; + std::vector handlers; + std::vector recursive_handlers; + bool enqueueing = false; + bool dispatching = false; + + void flush_recursive_handlers(); + }; + + struct LatchEventTypeData : Util::IntrusiveHashMapEnabled + { + std::vector> queued_events; + std::vector handlers; + std::vector recursive_handlers; + bool enqueueing = false; + bool dispatching = false; + + void flush_recursive_handlers(); + }; + + void dispatch_event(std::vector &handlers, const Event &e); + void dispatch_up_events(std::vector> &events, const LatchHandler &handler); + void dispatch_down_events(std::vector> &events, const LatchHandler &handler); + void dispatch_up_event(LatchEventTypeData &event_type, const Event &event); + void dispatch_down_event(LatchEventTypeData &event_type, const Event &event); + + Util::IntrusiveHashMap events; + Util::IntrusiveHashMap latched_events; + uint64_t cookie_counter = 0; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/CMakeLists.txt new file mode 100644 index 00000000..f8ec1152 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/CMakeLists.txt @@ -0,0 +1,27 @@ +add_granite_internal_lib(granite-filesystem + volatile_source.hpp + filesystem.hpp filesystem.cpp + asset_manager.cpp asset_manager.hpp) + +if (WIN32) + target_sources(granite-filesystem PRIVATE windows/os_filesystem.cpp windows/os_filesystem.hpp) + target_include_directories(granite-filesystem PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/windows) +elseif (ANDROID) + target_sources(granite-filesystem PRIVATE linux/os_filesystem.cpp linux/os_filesystem.hpp) + target_sources(granite-filesystem PRIVATE android/android.cpp android/android.hpp) + target_include_directories(granite-filesystem PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/linux) + target_include_directories(granite-filesystem PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/android) +else() + target_sources(granite-filesystem PRIVATE linux/os_filesystem.cpp linux/os_filesystem.hpp) + target_include_directories(granite-filesystem PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/linux) +endif() + +target_include_directories(granite-filesystem PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-filesystem PUBLIC granite-util granite-path granite-application-global PRIVATE granite-threading) + +if (GRANITE_SHIPPING) + target_compile_definitions(granite-filesystem PRIVATE GRANITE_SHIPPING) +else() + target_compile_definitions(granite-filesystem PRIVATE GRANITE_DEFAULT_BUILTIN_DIRECTORY=\"${CMAKE_CURRENT_SOURCE_DIR}/../assets\") + target_compile_definitions(granite-filesystem PRIVATE GRANITE_DEFAULT_CACHE_DIRECTORY=\"${CMAKE_BINARY_DIR}/cache\") +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/android/android.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/android/android.cpp new file mode 100644 index 00000000..76b1471f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/android/android.cpp @@ -0,0 +1,156 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "android.hpp" +#include "path_utils.hpp" +#include "logging.hpp" +#include +#include + +namespace Granite +{ +bool AssetFile::init(AAssetManager *mgr, const std::string &path, FileMode mode) +{ + if (mode != FileMode::ReadOnly) + { + LOGE("Asset files must be opened read-only.\n"); + return false; + } + + asset = AAssetManager_open(mgr, path.c_str(), AASSET_MODE_BUFFER); + if (!asset) + return false; + + size = AAsset_getLength64(asset); + return true; +} + +FileHandle AssetFile::open(AAssetManager *mgr, const std::string &path, Granite::FileMode mode) +{ + auto file = Util::make_handle(); + if (!file->init(mgr, path, mode)) + file.reset(); + return file; +} + +FileMappingHandle AssetFile::map_subset(uint64_t offset, size_t range) +{ + if (offset + range > size) + return {}; + + auto *data = static_cast(const_cast(AAsset_getBuffer(asset))); + if (!data) + return {}; + + return Util::make_handle( + reference_from_this(), offset, + data + offset, range, + 0, range); +} + +uint64_t AssetFile::get_size() +{ + return size; +} + +FileMappingHandle AssetFile::map_write(size_t) +{ + return {}; +} + +void AssetFile::unmap(void *, size_t) +{ +} + +AssetFile::~AssetFile() +{ + if (asset) + AAsset_close(asset); +} + +AssetManagerFilesystem::AssetManagerFilesystem(const std::string &base_) + : base(base_), mgr(global_asset_manager) +{ +} + +FileHandle AssetManagerFilesystem::open(const std::string &path, FileMode mode) +{ + return AssetFile::open(mgr, Path::join(base, Path::canonicalize_path(path)), mode); +} + +int AssetManagerFilesystem::get_notification_fd() const +{ + return -1; +} + +void AssetManagerFilesystem::poll_notifications() +{ +} + +void AssetManagerFilesystem::uninstall_notification(FileNotifyHandle) +{ +} + +FileNotifyHandle AssetManagerFilesystem::install_notification(const std::string &, + std::function) +{ + return -1; +} + +std::vector AssetManagerFilesystem::list(const std::string &path) +{ + auto directory = Path::join(base, Path::canonicalize_path(path)); + auto *dir = AAssetManager_openDir(mgr, directory.c_str()); + + if (!dir) + return {}; + + std::vector entries; + + const char *entry; + while ((entry = AAssetDir_getNextFileName(dir))) + { + PathType type = PathType::File; + entries.push_back({ entry, type }); + } + + AAssetDir_close(dir); + return entries; +} + +bool AssetManagerFilesystem::stat(const std::string &path, FileStat &stat) +{ + auto resolved_path = Path::join(base, Path::canonicalize_path(path)); + + auto *asset = AAssetManager_open(mgr, resolved_path.c_str(), AASSET_MODE_UNKNOWN); + if (!asset) + return false; + + stat.size = AAsset_getLength(asset); + stat.type = PathType::File; + stat.last_modified = 0; + AAsset_close(asset); + return true; +} + +AAssetManager *AssetManagerFilesystem::global_asset_manager; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/android/android.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/android/android.hpp new file mode 100644 index 00000000..199871b1 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/android/android.hpp @@ -0,0 +1,64 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include "../filesystem.hpp" +#include +#include + +namespace Granite +{ +class AssetFile final : public File +{ +public: + static FileHandle open(AAssetManager *mgr, const std::string &path, FileMode mode); + ~AssetFile() override; + FileMappingHandle map_subset(uint64_t offset, size_t range) override; + FileMappingHandle map_write(size_t size) override; + void unmap(void *mapped, size_t mapped_range) override; + uint64_t get_size() override; + +private: + bool init(AAssetManager *mgr, const std::string &path, FileMode mode); + AAsset *asset = nullptr; + size_t size = 0; +}; + +class AssetManagerFilesystem : public FilesystemBackend +{ +public: + AssetManagerFilesystem(const std::string &base); + std::vector list(const std::string &path) override; + FileHandle open(const std::string &path, FileMode mode) override; + bool stat(const std::string &path, FileStat &stat) override; + FileNotifyHandle install_notification(const std::string &path, std::function func) override; + void uninstall_notification(FileNotifyHandle handle) override; + void poll_notifications() override; + int get_notification_fd() const override; + + static AAssetManager *global_asset_manager; + +private: + std::string base; + AAssetManager *mgr; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/asset_manager.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/asset_manager.cpp new file mode 100644 index 00000000..47b037c3 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/asset_manager.cpp @@ -0,0 +1,383 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "asset_manager.hpp" +#include "thread_group.hpp" +#include +#include + +namespace Granite +{ +AssetManager::AssetManager() +{ + asset_bank.reserve(AssetID::MaxIDs); + sorted_assets.reserve(AssetID::MaxIDs); + signal = std::make_unique(); + for (uint64_t i = 0; i < timestamp; i++) + signal->signal_increment(); +} + +AssetManager::~AssetManager() +{ + set_asset_instantiator_interface(nullptr); + signal->wait_until_at_least(timestamp); + for (uint32_t i = 0; i < id_count; i++) + pool.free(asset_bank[i]); +} + +AssetID AssetManager::register_asset_nolock(FileHandle file, AssetClass asset_class, int prio) +{ + auto *info = pool.allocate(); + info->handle = std::move(file); + info->id.id = id_count; + info->prio = prio; + info->asset_class = asset_class; + AssetID ret = info->id; + asset_bank[id_count++] = info; + if (iface) + { + iface->set_id_bounds(id_count); + iface->set_asset_class(info->id, asset_class); + } + return ret; +} + +void AssetInstantiatorInterface::set_asset_class(AssetID, AssetClass) +{ +} + +AssetID AssetManager::register_asset(FileHandle file, AssetClass asset_class, int prio) +{ + std::lock_guard holder{asset_bank_lock}; + return register_asset_nolock(std::move(file), asset_class, prio); +} + +AssetID AssetManager::register_asset(Filesystem &fs, const std::string &path, AssetClass asset_class, int prio) +{ + std::lock_guard holder{asset_bank_lock}; + + Util::Hasher h; + h.string(path); + if (auto *asset = file_to_assets.find(h.get())) + return asset->id; + + auto file = fs.open(path); + if (!file) + return {}; + + auto id = register_asset_nolock(std::move(file), asset_class, prio); + asset_bank[id.id]->set_hash(h.get()); + file_to_assets.insert_replace(asset_bank[id.id]); + return id; +} + +void AssetManager::update_cost(AssetID id, uint64_t cost) +{ + std::lock_guard holder{cost_update_lock}; + thread_cost_updates.push_back({ id, cost }); +} + +void AssetManager::set_asset_instantiator_interface(AssetInstantiatorInterface *iface_) +{ + if (iface) + { + signal->wait_until_at_least(timestamp); + for (uint32_t id = 0; id < id_count; id++) + iface->release_asset(AssetID{id}); + } + + for (uint32_t i = 0; i < id_count; i++) + { + auto *a = asset_bank[i]; + a->consumed = 0; + a->pending_consumed = 0; + a->last_used = 0; + } + total_consumed = 0; + + iface = iface_; + if (iface) + { + iface->set_id_bounds(id_count); + for (uint32_t i = 0; i < id_count; i++) + iface->set_asset_class(AssetID{i}, asset_bank[i]->asset_class); + } +} + +void AssetManager::mark_used_asset(AssetID id) +{ + lru_append.push(id); +} + +bool AssetManager::get_wants_mesh_assets() const +{ + return wants_mesh_assets; +} + +void AssetManager::enable_mesh_assets() +{ + wants_mesh_assets = true; +} + +void AssetManager::set_asset_budget(uint64_t cost) +{ + transfer_budget = cost; +} + +void AssetManager::set_asset_budget_per_iteration(uint64_t cost) +{ + transfer_budget_per_iteration = cost; +} + +bool AssetManager::set_asset_residency_priority(AssetID id, int prio) +{ + std::lock_guard holder{asset_bank_lock}; + if (id.id >= id_count) + return false; + asset_bank[id.id]->prio = prio; + return true; +} + +void AssetManager::adjust_update(const CostUpdate &update) +{ + if (update.id.id < id_count) + { + auto *a = asset_bank[update.id.id]; + total_consumed += update.cost - (a->consumed + a->pending_consumed); + a->consumed = update.cost; + a->pending_consumed = 0; + + // A recently paged in image shouldn't be paged out right away in a situation where we're thrashing, + // that'd be very dumb. + a->last_used = timestamp; + } +} + +uint64_t AssetManager::get_current_total_consumed() const +{ + return total_consumed; +} + +void AssetManager::update_costs_locked_assets() +{ + { + std::lock_guard holder_cost{cost_update_lock}; + std::swap(cost_updates, thread_cost_updates); + } + + for (auto &update : cost_updates) + adjust_update(update); + cost_updates.clear(); +} + +void AssetManager::update_lru_locked_assets() +{ + lru_append.for_each_ranged([this](const AssetID *id, size_t count) { + for (size_t i = 0; i < count; i++) + if (id[i].id < id_count) + asset_bank[id[i].id]->last_used = timestamp; + }); + lru_append.clear(); +} + +bool AssetManager::iterate_blocking(ThreadGroup &group, AssetID id) +{ + if (!iface) + return false; + + std::lock_guard holder{asset_bank_lock}; + update_costs_locked_assets(); + update_lru_locked_assets(); + + if (id.id >= id_count) + return false; + + auto *candidate = asset_bank[id.id]; + if (candidate->consumed != 0 || candidate->pending_consumed != 0) + return true; + + uint64_t estimate = iface->estimate_cost_asset(candidate->id, *candidate->handle); + auto task = group.create_task(); + task->set_task_class(TaskClass::Background); + task->set_fence_counter_signal(signal.get()); + task->set_desc("asset-manager-instantiate-single"); + iface->instantiate_asset(*this, task.get(), candidate->id, *candidate->handle); + candidate->pending_consumed = estimate; + candidate->last_used = timestamp; + total_consumed += estimate; + + // We cannot increment the timestamp here, remember this for later. + // We hold a lock on the asset bank here, so this is fine even if called concurrently. + blocking_signals++; + + return true; +} + +void AssetManager::iterate(ThreadGroup *group) +{ + if (!iface) + return; + + timestamp += blocking_signals; + blocking_signals = 0; + + // If there is too much pending work in flight, skip. + uint64_t current_count = signal->get_count(); + if (current_count + 3 < timestamp) + { + iface->latch_handles(); + LOGI("Asset manager skipping iteration due to too much pending work.\n"); + return; + } + + TaskGroupHandle task; + if (group) + { + task = group->create_task(); + task->set_desc("asset-manager-instantiate"); + task->set_fence_counter_signal(signal.get()); + task->set_task_class(TaskClass::Background); + } + else + signal->signal_increment(); + + std::lock_guard holder{asset_bank_lock}; + update_costs_locked_assets(); + update_lru_locked_assets(); + + memcpy(sorted_assets.data(), asset_bank.data(), id_count * sizeof(sorted_assets[0])); + std::sort(sorted_assets.data(), sorted_assets.data() + id_count, [](const AssetInfo *a, const AssetInfo *b) -> bool { + // High prios come first since they will be activated. + // Then we sort by LRU. + // High consumption should be moved last, so they are candidates to be paged out if we're over budget. + // High pending consumption should be moved early since we don't want to page out resources that + // are in the middle of being loaded anyway. + // Finally, the ID is used as a tie breaker. + + if (a->prio != b->prio) + return a->prio > b->prio; + else if (a->last_used != b->last_used) + return a->last_used > b->last_used; + else if (a->consumed != b->consumed) + return a->consumed < b->consumed; + else if (a->pending_consumed != b->pending_consumed) + return a->pending_consumed > b->pending_consumed; + else + return a->id.id < b->id.id; + }); + + size_t release_index = id_count; + uint64_t activated_cost_this_iteration = 0; + unsigned activation_count = 0; + size_t activate_index = 0; + + // Aim to activate resources as long as we're in budget. + // Activate in order from highest priority to lowest. + bool can_activate = true; + while (can_activate && + total_consumed < transfer_budget && + activated_cost_this_iteration < transfer_budget_per_iteration && + activate_index != release_index) + { + auto *candidate = sorted_assets[activate_index]; + if (candidate->prio <= 0) + break; + + // This resource is already active. + if (candidate->consumed != 0 || candidate->pending_consumed != 0) + { + activate_index++; + continue; + } + + uint64_t estimate = iface->estimate_cost_asset(candidate->id, *candidate->handle); + + can_activate = (total_consumed + estimate <= transfer_budget) || (candidate->prio >= persistent_prio()); + while (!can_activate && activate_index + 1 != release_index) + { + auto *release_candidate = sorted_assets[--release_index]; + if (release_candidate->consumed) + { + LOGI("Releasing ID %u due to page-in pressure.\n", release_candidate->id.id); + iface->release_asset(release_candidate->id); + total_consumed -= release_candidate->consumed; + release_candidate->consumed = 0; + } + can_activate = total_consumed + estimate <= transfer_budget; + } + + if (can_activate) + { + // We're trivially in budget. + iface->instantiate_asset(*this, task.get(), candidate->id, *candidate->handle); + activation_count++; + + candidate->pending_consumed = estimate; + total_consumed += estimate; + // Let this run over budget once. + // Ensures we can make forward progress no matter what the limit is. + activated_cost_this_iteration += estimate; + activate_index++; + } + } + + // If we're 75% of budget, start garbage collecting non-resident resources ahead of time. + const uint64_t low_image_budget = (transfer_budget * 3) / 4; + + const auto should_release = [&]() -> bool { + if (release_index == activate_index) + return false; + if (sorted_assets[release_index - 1]->prio == persistent_prio()) + return false; + + if (total_consumed > transfer_budget) + return true; + else if (total_consumed > low_image_budget && sorted_assets[release_index - 1]->prio == 0) + return true; + + return false; + }; + + // If we're over budget, deactivate resources. + while (should_release()) + { + auto *candidate = sorted_assets[--release_index]; + if (candidate->consumed) + { + LOGI("Releasing 0-prio ID %u due to page-in pressure.\n", candidate->id.id); + iface->release_asset(candidate->id); + total_consumed -= candidate->consumed; + candidate->consumed = 0; + candidate->last_used = 0; + } + } + + if (activated_cost_this_iteration) + { + LOGI("Activated %u resources for %llu KiB.\n", activation_count, + static_cast(activated_cost_this_iteration / 1024)); + } + + iface->latch_handles(); + timestamp++; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/asset_manager.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/asset_manager.hpp new file mode 100644 index 00000000..eff4f571 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/asset_manager.hpp @@ -0,0 +1,183 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include "atomic_append_buffer.hpp" +#include "global_managers.hpp" +#include "filesystem.hpp" +#include "object_pool.hpp" +#include "intrusive_hash_map.hpp" +#include "dynamic_array.hpp" +#include +#include +#include + +namespace Granite +{ +struct AssetID +{ + uint32_t id = uint32_t(-1); + enum { MaxIDs = 1u << 18 }; + AssetID() = default; + explicit AssetID(uint32_t id_) : id{id_} {} + explicit inline operator bool() const { return id != uint32_t(-1); } + inline bool operator==(const AssetID &other) const { return id == other.id; } + inline bool operator!=(const AssetID &other) const { return !(*this == other); } +}; + +class AssetManager; + +// If we have to fall back due to no image being present, +// lets asset instantiator know what to substitute. +enum class AssetClass +{ + // Substitute with 0. + ImageZeroable, + // Substitute with missing color. + ImageColor, + // Substitute with RG8_UNORM 0.5 + ImageNormal, + // Substitute with M = 0, R = 1. + ImageMetallicRoughness, + // Substitute with mid-gray (0.5, 0.5, 0.5, 1.0) UNORM8. + // Somewhat compatible with everything. + ImageGeneric, + Mesh +}; + +class ThreadGroup; +struct TaskGroup; +struct TaskSignal; + +class AssetInstantiatorInterface +{ +public: + virtual ~AssetInstantiatorInterface() = default; + + // This estimate should be an upper bound. + virtual uint64_t estimate_cost_asset(AssetID id, File &mapping) = 0; + + // When instantiation completes, manager.update_cost() must be called with the real cost. + // The real cost may only be known after async parsing of the file. + virtual void instantiate_asset(AssetManager &manager, TaskGroup *group, AssetID id, File &mapping) = 0; + + // Will only be called after an upload completes through manager.update_cost(). + virtual void release_asset(AssetID id) = 0; + + virtual void set_id_bounds(uint32_t bound) = 0; + virtual void set_asset_class(AssetID id, AssetClass asset_class); + + // Called in AssetManager::iterate(). + virtual void latch_handles() = 0; +}; + +class AssetManager final : public AssetManagerInterface +{ +public: + // Persistent prio means the resource is treated as an internal LUT that must always be resident, no matter what. + constexpr static int persistent_prio() { return 0x7fffffff; } + + AssetManager(); + ~AssetManager() override; + + void set_asset_instantiator_interface(AssetInstantiatorInterface *iface); + + // We might want to consider different budgets per asset class. + void set_asset_budget(uint64_t cost); + void set_asset_budget_per_iteration(uint64_t cost); + + // FileHandle is intended to be used with FileSlice or similar here so that we don't need + // a ton of open files at once. + AssetID register_asset(FileHandle file, AssetClass asset_class, int prio = 1); + AssetID register_asset(Filesystem &fs, const std::string &path, AssetClass asset_class, int prio = 1); + + // Prio 0: Not resident, resource may not exist. + bool set_asset_residency_priority(AssetID id, int prio); + + // Intended to be called in Application::post_frame(). Not thread safe. + // This function updates internal state. + void iterate(ThreadGroup *group); + bool iterate_blocking(ThreadGroup &group, AssetID id); + + // Always thread safe, used by AssetInstantiatorInterfaces to update cost estimates. + void update_cost(AssetID id, uint64_t cost); + + // May be called concurrently, except when calling iterate(). + uint64_t get_current_total_consumed() const; + + // May be called concurrently, except when calling iterate(). + // Intended to be called by asset instantiator interface or similar. + // When a resource is actually accessed, this is called. + void mark_used_asset(AssetID id); + + // Should be called in applications's constructor to make sure we initialize + // the mesh asset pool on device creation. + // FIXME: Could be made more flexible if need be. + void enable_mesh_assets(); + bool get_wants_mesh_assets() const; + +private: + struct AssetInfo : Util::IntrusiveHashMapEnabled + { + uint64_t pending_consumed = 0; + uint64_t consumed = 0; + uint64_t last_used = 0; + FileHandle handle; + AssetID id = {}; + AssetClass asset_class = AssetClass::ImageZeroable; + int prio = 0; + }; + + Util::DynamicArray sorted_assets; + Util::DynamicArray asset_bank; + std::mutex asset_bank_lock; + Util::ObjectPool pool; + Util::AtomicAppendBuffer lru_append; + Util::IntrusiveHashMapHolder file_to_assets; + + AssetInstantiatorInterface *iface = nullptr; + uint32_t id_count = 0; + uint64_t total_consumed = 0; + uint64_t transfer_budget = 0; + uint64_t transfer_budget_per_iteration = 0; + uint64_t timestamp = 1; + uint32_t blocking_signals = 0; + + struct CostUpdate + { + AssetID id; + uint64_t cost = 0; + }; + std::mutex cost_update_lock; + std::vector thread_cost_updates; + std::vector cost_updates; + + void adjust_update(const CostUpdate &update); + std::unique_ptr signal; + AssetID register_asset_nolock(FileHandle file, AssetClass asset_class, int prio); + + void update_costs_locked_assets(); + void update_lru_locked_assets(); + + bool wants_mesh_assets = false; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/filesystem.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/filesystem.cpp new file mode 100644 index 00000000..727fe075 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/filesystem.cpp @@ -0,0 +1,692 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "filesystem.hpp" +#include "path_utils.hpp" +#include "logging.hpp" +#include "os_filesystem.hpp" +#include "string_helpers.hpp" +#include "environment.hpp" +#include +#include +#include +#include + +namespace Granite +{ +std::vector FilesystemBackend::walk(const std::string &path) +{ + auto entries = list(path); + std::vector final_entries; + for (auto &e : entries) + { + if (e.type == PathType::Directory) + { + auto subentries = walk(e.path); + final_entries.push_back(std::move(e)); + for (auto &sub : subentries) + final_entries.push_back(std::move(sub)); + } + else if (e.type == PathType::File) + final_entries.push_back(std::move(e)); + } + return final_entries; +} + +bool FilesystemBackend::remove(const std::string &) +{ + return false; +} + +bool FilesystemBackend::move_replace(const std::string &, const std::string &) +{ + return false; +} + +bool FilesystemBackend::move_yield(const std::string &, const std::string &) +{ + return false; +} + +Filesystem::Filesystem() +{ + register_protocol("file", std::unique_ptr(new OSFilesystem("."))); + register_protocol("memory", std::unique_ptr(new ScratchFilesystem)); + +#ifdef GRANITE_DEFAULT_ASSET_DIRECTORY + auto asset_dir = Util::get_environment_string("GRANITE_DEFAULT_ASSET_DIRECTORY", GRANITE_DEFAULT_ASSET_DIRECTORY); +#else + auto asset_dir = Util::get_environment_string("GRANITE_DEFAULT_ASSET_DIRECTORY", ""); +#endif + if (!asset_dir.empty()) + register_protocol("builtin", std::unique_ptr(new OSFilesystem(asset_dir))); + +#ifdef GRANITE_DEFAULT_BUILTIN_DIRECTORY + auto builtin_dir = Util::get_environment_string("GRANITE_DEFAULT_BUILTIN_DIRECTORY", GRANITE_DEFAULT_BUILTIN_DIRECTORY); +#else + auto builtin_dir = Util::get_environment_string("GRANITE_DEFAULT_BUILTIN_DIRECTORY", ""); +#endif + if (!builtin_dir.empty()) + register_protocol("builtin", std::unique_ptr(new OSFilesystem(builtin_dir))); + +#ifdef GRANITE_DEFAULT_CACHE_DIRECTORY + auto cache_dir = Util::get_environment_string("GRANITE_DEFAULT_CACHE_DIRECTORY", GRANITE_DEFAULT_CACHE_DIRECTORY); +#else + auto cache_dir = Util::get_environment_string("GRANITE_DEFAULT_CACHE_DIRECTORY", ""); +#endif + if (!cache_dir.empty()) + register_protocol("cache", std::unique_ptr(new OSFilesystem(cache_dir))); +} + +void Filesystem::setup_default_filesystem(Filesystem *filesystem, const char *default_asset_directory) +{ + auto self_dir = Path::basedir(Path::get_executable_path()); + auto assets_dir = Path::join(self_dir, "assets"); + auto builtin_dir = Path::join(self_dir, "builtin/assets"); + + if (default_asset_directory) + { +#ifdef GRANITE_SHIPPING + LOGW("Default asset directory %s was provided, but this is only intended for non-shipping configs.\n", + default_asset_directory); +#else + filesystem->register_protocol("assets", + std::unique_ptr(new OSFilesystem(default_asset_directory))); +#endif + } + + FileStat s; + if (filesystem->stat(assets_dir, s) && s.type == PathType::Directory) + { + filesystem->register_protocol("assets", std::make_unique(assets_dir)); + LOGI("Redirecting filesystem \"assets\" to %s.\n", assets_dir.c_str()); + + auto cache_dir = Path::join(self_dir, "cache"); + filesystem->register_protocol("cache", std::make_unique(cache_dir)); + LOGI("Redirecting filesystem \"cache\" to %s.\n", cache_dir.c_str()); + } + + if (filesystem->stat(builtin_dir, s) && s.type == PathType::Directory) + { + filesystem->register_protocol("builtin", std::make_unique(builtin_dir)); + LOGI("Redirecting filesystem \"builtin\" to %s.\n", builtin_dir.c_str()); + } + + // These filesystems are core functionality. + if (!filesystem->get_backend("builtin")) + throw std::runtime_error("builtin filesystem was not initialized."); + if (!filesystem->get_backend("cache")) + throw std::runtime_error("cache filesystem was not initialized."); +} + +void Filesystem::register_protocol(const std::string &proto, std::unique_ptr fs) +{ + if (fs) + { + fs->set_protocol(proto); + protocols[proto] = std::move(fs); + } + else + protocols.erase(proto); +} + +FilesystemBackend *Filesystem::get_backend(const std::string &proto) +{ + auto itr = protocols.find(proto); + if (proto.empty()) + itr = protocols.find("file"); + + if (itr != end(protocols)) + return itr->second.get(); + else + return nullptr; +} + +std::vector Filesystem::walk(const std::string &path) +{ + auto paths = Path::protocol_split(path); + auto *backend = get_backend(paths.first); + if (!backend) + return {}; + + return backend->walk(paths.second); +} + +std::vector Filesystem::list(const std::string &path) +{ + auto paths = Path::protocol_split(path); + auto *backend = get_backend(paths.first); + if (!backend) + return {}; + + return backend->list(paths.second); +} + +bool Filesystem::remove(const std::string &path) +{ + auto paths = Path::protocol_split(path); + auto *backend = get_backend(paths.first); + if (!backend) + return false; + + return backend->remove(paths.second); +} + +bool Filesystem::move_yield(const std::string &dst, const std::string &src) +{ + auto paths_dst = Path::protocol_split(dst); + auto paths_src = Path::protocol_split(src); + auto *backend_dst = get_backend(paths_dst.first); + auto *backend_src = get_backend(paths_src.first); + if (!backend_dst || !backend_src || backend_dst != backend_src) + return false; + + return backend_dst->move_yield(paths_dst.second, paths_src.second); +} + +bool Filesystem::move_replace(const std::string &dst, const std::string &src) +{ + auto paths_dst = Path::protocol_split(dst); + auto paths_src = Path::protocol_split(src); + auto *backend_dst = get_backend(paths_dst.first); + auto *backend_src = get_backend(paths_src.first); + if (!backend_dst || !backend_src || backend_dst != backend_src) + return false; + + return backend_dst->move_replace(paths_dst.second, paths_src.second); +} + +FileMappingHandle Filesystem::open_readonly_mapping(const std::string &path) +{ + auto file = open(path, FileMode::ReadOnly); + if (!file) + return {}; + return file->map(); +} + +FileMappingHandle Filesystem::open_writeonly_mapping(const std::string &path, size_t size) +{ + auto file = open(path, FileMode::WriteOnly); + if (!file) + return {}; + return file->map_write(size); +} + +FileMappingHandle Filesystem::open_transactional_mapping(const std::string &path, size_t size) +{ + auto file = open(path, FileMode::WriteOnlyTransactional); + if (!file) + return {}; + return file->map_write(size); +} + +bool Filesystem::read_file_to_string(const std::string &path, std::string &str) +{ + auto mapping = open_readonly_mapping(path); + if (!mapping) + return false; + + auto size = mapping->get_size(); + str = std::string(mapping->data(), mapping->data() + size); + + // Remove DOS EOL. + str.erase(remove_if(begin(str), end(str), [](char c) { return c == '\r'; }), end(str)); + + return true; +} + +bool Filesystem::write_buffer_to_file(const std::string &path, const void *data, size_t size) +{ + auto file = open_transactional_mapping(path, size); + if (!file) + return false; + memcpy(file->mutable_data(), data, size); + return true; +} + +bool Filesystem::write_string_to_file(const std::string &path, const std::string &str) +{ + return write_buffer_to_file(path, str.data(), str.size()); +} + +FileHandle Filesystem::open(const std::string &path, FileMode mode) +{ + auto paths = Path::protocol_split(path); + auto *backend = get_backend(paths.first); + if (!backend) + return {}; + + auto file = backend->open(paths.second, mode); + return file; +} + +std::string Filesystem::get_filesystem_path(const std::string &path) +{ + auto paths = Path::protocol_split(path); + auto *backend = get_backend(paths.first); + if (!backend) + return ""; + + return backend->get_filesystem_path(paths.second); +} + +bool Filesystem::stat(const std::string &path, FileStat &stat) +{ + auto paths = Path::protocol_split(path); + auto *backend = get_backend(paths.first); + if (!backend) + return false; + + return backend->stat(paths.second, stat); +} + +void Filesystem::poll_notifications() +{ + for (auto &proto : protocols) + proto.second->poll_notifications(); +} + +bool Filesystem::load_text_file(const std::string &path, std::string &str) +{ + return read_file_to_string(path, str); +} + +int ScratchFilesystem::get_notification_fd() const +{ + return -1; +} + +FileNotifyHandle ScratchFilesystem::install_notification(const std::string &, + std::function) +{ + return -1; +} + +void ScratchFilesystem::poll_notifications() +{ +} + +void ScratchFilesystem::uninstall_notification(FileNotifyHandle) +{ +} + +bool ScratchFilesystem::stat(const std::string &path, FileStat &stat) +{ + auto itr = scratch_files.find(path); + if (itr == end(scratch_files)) + return false; + + stat.size = itr->second->data.size(); + stat.type = PathType::File; + return true; +} + +std::vector ScratchFilesystem::list(const std::string &) +{ + return {}; +} + +struct ScratchFilesystemFile final : File +{ + explicit ScratchFilesystemFile(std::vector &data_) + : data(data_) + { + } + + FileMappingHandle map_subset(uint64_t offset, size_t range) override + { + if (offset + range > data.size()) + return {}; + + return Util::make_handle( + FileHandle{}, offset, + data.data() + offset, range, + 0, range); + } + + FileMappingHandle map_write(size_t size) override + { + data.resize(size); + return map_subset(0, size); + } + + void unmap(void *, size_t) override + { + } + + uint64_t get_size() override + { + return data.size(); + } + + std::vector &data; +}; + +FileHandle ScratchFilesystem::open(const std::string &path, FileMode) +{ + auto itr = scratch_files.find(path); + if (itr == end(scratch_files)) + { + auto &file = scratch_files[path]; + file = std::make_unique(); + return Util::make_handle(file->data); + } + else + { + return Util::make_handle(itr->second->data); + } +} + +BlobFilesystem::BlobFilesystem(FileHandle file_) + : file(std::move(file_)) +{ + if (!file) + return; + + root = std::make_unique(); + parse(); +} + +uint8_t BlobFilesystem::read_u8(const uint8_t *&buf, size_t &size) +{ + if (size < 1) + throw std::range_error("Blob EOF."); + + uint8_t ret = *buf++; + size--; + return ret; +} + +uint64_t BlobFilesystem::read_u64(const uint8_t *&buf, size_t &size) +{ + if (size < 8) + throw std::range_error("Blob EOF."); + + uint64_t ret = 0; + for (unsigned i = 0; i < 8; i++) + ret |= uint64_t(buf[i]) << (8 * i); + size -= 8; + buf += 8; + return ret; +} + +std::string BlobFilesystem::read_string(const uint8_t *&buf, size_t &size, size_t len) +{ + if (size < len) + throw std::range_error("Blob EOF."); + + std::string ret; + ret.insert(ret.end(), reinterpret_cast(buf), reinterpret_cast(buf) + len); + size -= len; + buf += len; + return ret; +} + +void BlobFilesystem::add_entry(const std::string &path, size_t offset, size_t size) +{ + auto paths = Path::split(path); + auto *dir = find_directory(paths.first); + if (!dir) + dir = make_directory(paths.first); + dir->files.push_back({ Path::basename(path), offset, size }); +} + +void BlobFilesystem::parse() +{ + size_t mapped_size = file->get_size(); + if (mapped_size < 16) + throw std::runtime_error("Blob archive too small."); + + auto mapped_handle = file->map(); + if (!mapped_handle) + throw std::runtime_error("Failed to map blob archive."); + + auto *base_mapped = mapped_handle->data(); + auto *mapped = base_mapped; + + if (memcmp(mapped, "BLOBBY01", 8) != 0) + throw std::runtime_error("Invalid magic."); + mapped += 8; + mapped_size -= 8; + + uint64_t required_size = 0; + + while (mapped_size >= 4 && memcmp(mapped, "ENTR", 4) == 0) + { + mapped += 4; + mapped_size -= 4; + + uint8_t len = read_u8(mapped, mapped_size); + std::string path = Path::canonicalize_path(read_string(mapped, mapped_size, len)); + uint64_t blob_offset = read_u64(mapped, mapped_size); + uint64_t blob_size = read_u64(mapped, mapped_size); + required_size = std::max(required_size, blob_offset + blob_size); + + if (blob_offset + blob_size < blob_offset) + throw std::range_error("Overflow for blob offset + size."); + + if (blob_offset > SIZE_MAX || blob_size > SIZE_MAX) + throw std::range_error("Blob offset out of range."); + + add_entry(path, blob_offset, blob_size); + } + + if (mapped_size >= 4 && memcmp(mapped, "DATA", 4) == 0) + { + blob_base_offset = size_t((mapped + 4) - base_mapped); + mapped_size -= 4; + if (mapped_size < required_size) + throw std::range_error("Blob is not large enough for all files."); + } +} + +BlobFilesystem::Directory *BlobFilesystem::make_directory(const std::string &path) +{ + auto split = Util::split_no_empty(path, "/"); + auto *dir = root.get(); + + for (const auto &subpath : split) + { + auto dir_itr = std::find_if(dir->dirs.begin(), dir->dirs.end(), [&](const std::unique_ptr &dir_) { + return subpath == dir_->path; + }); + + if (dir_itr != dir->dirs.end()) + dir = dir_itr->get(); + else + { + dir->dirs.emplace_back(new Directory); + dir->dirs.back()->path = subpath; + dir = dir->dirs.back().get(); + } + } + + return dir; +} + +BlobFilesystem::Directory *BlobFilesystem::find_directory(const std::string &path) +{ + auto split = Util::split_no_empty(path, "/"); + auto *dir = root.get(); + + for (const auto &subpath : split) + { + auto dir_itr = std::find_if(dir->dirs.begin(), dir->dirs.end(), [&](const std::unique_ptr &dir_) { + return subpath == dir_->path; + }); + + if (dir_itr != dir->dirs.end()) + dir = dir_itr->get(); + else + return nullptr; + } + + return dir; +} + +BlobFilesystem::BlobFile *BlobFilesystem::find_file(const std::string &path) +{ + auto paths = Path::split(path); + auto *dir = find_directory(paths.first); + if (!dir) + return nullptr; + + auto file_itr = std::find_if(dir->files.begin(), dir->files.end(), [&](const BlobFile &zip_file) { + return paths.second == zip_file.path; + }); + + if (file_itr != dir->files.end()) + return &*file_itr; + else + return nullptr; +} + +std::vector BlobFilesystem::list(const std::string &path) +{ + auto canon_path = Path::canonicalize_path(path); + + std::vector entries; + if (const auto *zip_dir = find_directory(canon_path)) + { + entries.reserve(zip_dir->dirs.size() + zip_dir->files.size()); + for (auto &dir : zip_dir->dirs) + entries.push_back({ Path::join(path, dir->path), PathType::Directory }); + for (auto &f : zip_dir->files) + entries.push_back({ Path::join(path, f.path), PathType::File }); + } + return entries; +} + +bool BlobFilesystem::stat(const std::string &path, FileStat &stat) +{ + auto p = Path::canonicalize_path(path); + + if (const auto *zip_file = find_file(p)) + { + stat.size = zip_file->size; + stat.type = PathType::File; + stat.last_modified = 0; + return true; + } + else if (find_directory(p)) + { + stat.size = 0; + stat.last_modified = 0; + stat.type = PathType::Directory; + return true; + } + else + return false; +} + +FileHandle BlobFilesystem::open(const std::string &path, FileMode mode) +{ + if (mode != FileMode::ReadOnly) + return {}; + + auto p = Path::canonicalize_path(path); + auto *blob_file = find_file(p); + if (!blob_file) + return {}; + + return Util::make_handle(file, blob_base_offset + blob_file->offset, blob_file->size); +} + +FileNotifyHandle BlobFilesystem::install_notification(const std::string &, std::function) +{ + return -1; +} + +void BlobFilesystem::uninstall_notification(FileNotifyHandle) +{ +} + +void BlobFilesystem::poll_notifications() +{ +} + +int BlobFilesystem::get_notification_fd() const +{ + return -1; +} + +FileMapping::FileMapping(FileHandle handle_, uint64_t file_offset_, + void *mapped_, size_t mapped_size_, + size_t map_offset_, size_t accessible_size_) + : handle(std::move(handle_)) + , file_offset(file_offset_) + , mapped(mapped_) + , mapped_size(mapped_size_) + , map_offset(map_offset_) + , accessible_size(accessible_size_) +{ +} + +FileMapping::~FileMapping() +{ + if (handle) + handle->unmap(mapped, mapped_size); +} + +uint64_t FileMapping::get_file_offset() const +{ + return file_offset; +} + +uint64_t FileMapping::get_size() const +{ + return accessible_size; +} + +Util::IntrusivePtr File::map() +{ + return map_subset(0, get_size()); +} + +FileSlice::FileSlice(FileHandle handle_, uint64_t offset_, uint64_t range_) + : handle(std::move(handle_)), offset(offset_), range(range_) +{ +} + +FileMappingHandle FileSlice::map_subset(uint64_t offset_, size_t range_) +{ + if (offset_ + range_ > range) + return {}; + return handle->map_subset(offset + offset_, range_); +} + +FileMappingHandle FileSlice::map_write(size_t) +{ + return {}; +} + +uint64_t FileSlice::get_size() +{ + return range; +} + +void FileSlice::unmap(void *mapped, size_t mapped_size) +{ + handle->unmap(mapped, mapped_size); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/filesystem.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/filesystem.hpp new file mode 100644 index 00000000..234f5f5a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/filesystem.hpp @@ -0,0 +1,333 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include +#include +#include +#include +#include +#include +#include "global_managers.hpp" +#include "intrusive.hpp" + +namespace Granite +{ +class FileMapping; + +class File : public Util::ThreadSafeIntrusivePtrEnabled +{ +public: + virtual ~File() = default; + virtual Util::IntrusivePtr map_subset(uint64_t offset, size_t range) = 0; + virtual Util::IntrusivePtr map_write(size_t size) = 0; + virtual uint64_t get_size() = 0; + + // Only called by FileMapping. + virtual void unmap(void *mapped, size_t range) = 0; + + Util::IntrusivePtr map(); +}; +using FileHandle = Util::IntrusivePtr; + +class FileMapping : public Util::ThreadSafeIntrusivePtrEnabled +{ +public: + template + inline const T *data() const + { + void *ptr = static_cast(mapped) + map_offset; + return static_cast(ptr); + } + + template + inline T *mutable_data() + { + void *ptr = static_cast(mapped) + map_offset; + return static_cast(ptr); + } + + uint64_t get_file_offset() const; + uint64_t get_size() const; + + ~FileMapping(); + FileMapping(FileHandle handle, + uint64_t file_offset, + void *mapped, size_t mapped_size, + size_t map_offset, size_t accessible_size); + +private: + FileHandle handle; + uint64_t file_offset; + void *mapped; + size_t mapped_size; + // For non-page aligned maps. + size_t map_offset; + size_t accessible_size; +}; +using FileMappingHandle = Util::IntrusivePtr; + +enum class PathType +{ + File, + Directory, + Special +}; + +struct ListEntry +{ + std::string path; + PathType type; +}; + +struct FileStat +{ + uint64_t size; + PathType type; + uint64_t last_modified; +}; + +using FileNotifyHandle = int; + +enum class FileNotifyType +{ + FileChanged, + FileDeleted, + FileCreated, +}; + +struct FileNotifyInfo +{ + std::string path; + FileNotifyType type; + FileNotifyHandle handle; +}; + +enum class FileMode +{ + ReadOnly, + WriteOnly, + ReadWrite, + WriteOnlyTransactional +}; + +class FilesystemBackend +{ +public: + virtual ~FilesystemBackend() = default; + std::vector walk(const std::string &path); + virtual std::vector list(const std::string &path) = 0; + virtual FileHandle open(const std::string &path, FileMode mode = FileMode::ReadOnly) = 0; + virtual bool stat(const std::string &path, FileStat &stat) = 0; + + virtual FileNotifyHandle + install_notification(const std::string &path, std::function func) = 0; + + virtual void uninstall_notification(FileNotifyHandle handle) = 0; + virtual void poll_notifications() = 0; + virtual int get_notification_fd() const = 0; + + virtual bool remove(const std::string &path); + virtual bool move_replace(const std::string &dst, const std::string &src); + virtual bool move_yield(const std::string &dst, const std::string &src); + + inline virtual std::string get_filesystem_path(const std::string &) + { + return ""; + } + + void set_protocol(const std::string &proto) + { + protocol = proto; + } + +protected: + std::string protocol; +}; + +class Filesystem final : public FilesystemInterface +{ +public: + Filesystem(); + + void register_protocol(const std::string &proto, std::unique_ptr fs); + FilesystemBackend *get_backend(const std::string &proto); + std::vector walk(const std::string &path); + std::vector list(const std::string &path); + FileHandle open(const std::string &path, FileMode mode = FileMode::ReadOnly); + std::string get_filesystem_path(const std::string &path); + + bool read_file_to_string(const std::string &path, std::string &str); + bool write_string_to_file(const std::string &path, const std::string &str); + bool write_buffer_to_file(const std::string &path, const void *data, size_t size); + FileMappingHandle open_readonly_mapping(const std::string &path); + FileMappingHandle open_writeonly_mapping(const std::string &path, size_t size); + FileMappingHandle open_transactional_mapping(const std::string &path, size_t size); + + bool remove(const std::string &path); + bool move_replace(const std::string &dst, const std::string &src); + bool move_yield(const std::string &dst, const std::string &src); + + bool stat(const std::string &path, FileStat &stat); + + void poll_notifications(); + + const std::unordered_map> &get_protocols() const + { + return protocols; + } + + static void setup_default_filesystem(Filesystem *fs, const char *default_asset_directory); + +private: + std::unordered_map> protocols; + + bool load_text_file(const std::string &path, std::string &str) override; +}; + +class ScratchFilesystem final : public FilesystemBackend +{ +public: + std::vector list(const std::string &path) override; + + FileHandle open(const std::string &path, FileMode mode = FileMode::ReadOnly) override; + + bool stat(const std::string &path, FileStat &stat) override; + + FileNotifyHandle install_notification(const std::string &path, std::function func) override; + + void uninstall_notification(FileNotifyHandle handle) override; + + void poll_notifications() override; + + int get_notification_fd() const override; + +private: + struct ScratchFile + { + std::vector data; + }; + std::unordered_map> scratch_files; +}; + +class ConstantMemoryFile final : public Granite::File +{ +public: + ConstantMemoryFile(const void *mapped_, size_t size_) + : mapped(static_cast(mapped_)), size(size_) + { + } + + FileMappingHandle map_subset(uint64_t offset, size_t range) override + { + if (offset + range > size) + return {}; + + return Util::make_handle( + FileHandle{}, offset, + const_cast(mapped) + offset, range, + 0, range); + } + + FileMappingHandle map_write(size_t) override + { + return {}; + } + + void unmap(void *, size_t) override + { + } + + uint64_t get_size() override + { + return size; + } + +private: + const uint8_t *mapped; + size_t size; +}; + +class FileSlice final : public File +{ +public: + FileSlice(FileHandle handle, uint64_t offset, uint64_t range); + FileMappingHandle map_subset(uint64_t offset, size_t range) override; + FileMappingHandle map_write(size_t) override; + void unmap(void *, size_t) override; + uint64_t get_size() override; + +private: + FileHandle handle; + uint64_t offset; + uint64_t range; +}; + +class BlobFilesystem final : public FilesystemBackend +{ +public: + BlobFilesystem(FileHandle file); + + std::vector list(const std::string &path) override; + + FileHandle open(const std::string &path, FileMode mode) override; + + bool stat(const std::string &path, FileStat &stat) override; + + FileNotifyHandle install_notification(const std::string &path, std::function func) override; + + void uninstall_notification(FileNotifyHandle handle) override; + + void poll_notifications() override; + + int get_notification_fd() const override; + +private: + FileHandle file; + size_t blob_base_offset = 0; + + struct BlobFile + { + std::string path; + size_t offset; + size_t size; + }; + + struct Directory + { + std::string path; + std::vector> dirs; + std::vector files; + }; + std::unique_ptr root; + BlobFile *find_file(const std::string &path); + Directory *find_directory(const std::string &path); + Directory *make_directory(const std::string &path); + void parse(); + + static uint8_t read_u8(const uint8_t *&buf, size_t &size); + static uint64_t read_u64(const uint8_t *&buf, size_t &size); + static std::string read_string(const uint8_t *&buf, size_t &size, size_t len); + void add_entry(const std::string &path, size_t offset, size_t size); +}; + +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/linux/os_filesystem.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/linux/os_filesystem.cpp new file mode 100644 index 00000000..b47375e1 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/linux/os_filesystem.cpp @@ -0,0 +1,541 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "os_filesystem.hpp" +#include "path_utils.hpp" +#include "logging.hpp" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __linux__ +#include +#endif + +#if defined(__FreeBSD__) || defined(__APPLE__) +#define FSTAT64 fstat +#define FTRUNCATE64 ftruncate +#define MMAP64 mmap +#define STAT64 stat +#define off64_t off_t +#else +#define FSTAT64 fstat64 +#define FTRUNCATE64 ftruncate64 +#define MMAP64 mmap64 +#define STAT64 stat64 +#endif + +namespace Granite +{ +static bool ensure_directory_inner(const std::string &path) +{ + if (Path::is_root_path(path)) + return false; + + struct STAT64 s = {}; + if (::STAT64(path.c_str(), &s) >= 0 && S_ISDIR(s.st_mode)) + return true; + + auto basedir = Path::basedir(path); + if (!ensure_directory_inner(basedir)) + return false; + + return (mkdir(path.c_str(), 0750) >= 0) || (errno == EEXIST); +} + +static bool ensure_directory(const std::string &path) +{ + auto basedir = Path::basedir(path); + return ensure_directory_inner(basedir); +} + +FileHandle MMapFile::open(const std::string &path, FileMode mode) +{ + auto file = Util::make_handle(); + if (!file->init(path, mode)) + file.reset(); + return file; +} + +static std::atomic_uint32_t global_transaction_counter; + +bool MMapFile::init(const std::string &path, FileMode mode) +{ + int modeflags = 0; + switch (mode) + { + case FileMode::ReadOnly: + modeflags = O_RDONLY; + break; + + case FileMode::WriteOnly: + case FileMode::WriteOnlyTransactional: + if (!ensure_directory(path)) + { + LOGE("MMapFile failed to create directory.\n"); + return false; + } + modeflags = O_RDWR | O_CREAT | O_TRUNC; // Need read access for mmap. + break; + + case FileMode::ReadWrite: + if (!ensure_directory(path)) + { + LOGE("MMapFile failed to create directory.\n"); + return false; + } + modeflags = O_RDWR | O_CREAT; + break; + } + + const char *open_path = path.c_str(); + + if (mode == FileMode::WriteOnlyTransactional) + { + // Use atomic file rename to ensure that a file is written atomically. + rename_to_on_close = path; + rename_from_on_close = + path + ".tmp." + + std::to_string(getpid()) + "." + + std::to_string(global_transaction_counter.fetch_add(1, std::memory_order_relaxed)); + open_path = rename_from_on_close.c_str(); + } + + fd = ::open(open_path, modeflags, 0640); + if (fd < 0) + { + rename_to_on_close.clear(); + rename_from_on_close.clear(); + return false; + } + + if (!query_stat()) + { + close(fd); + rename_to_on_close.clear(); + rename_from_on_close.clear(); + return false; + } + + return true; +} + +FileMappingHandle MMapFile::map_write(size_t map_size) +{ + if (has_write_map) + return {}; + + if (FTRUNCATE64(fd, off64_t(map_size)) < 0) + { + LOGE("Failed to truncate.\n"); + report_error(); + return {}; + } + + size = map_size; + + void *mapped = MMAP64(nullptr, map_size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); + if (mapped == MAP_FAILED) + { + report_error(); + return {}; + } + + has_write_map = true; + + return Util::make_handle( + reference_from_this(), + 0, + mapped, map_size, + 0, map_size); +} + +void MMapFile::report_error() +{ +#ifdef __linux__ + int err = errno; + char fdpath[PATH_MAX]; + char path[PATH_MAX]; + snprintf(fdpath, sizeof(fdpath), "/proc/%u/fd/%d", getpid(), fd); + int ret = readlink(fdpath, path, sizeof(path) - 1); + if (ret > 0) + { + path[ret] = '\0'; + LOGE("mmap failed for \"%s\" (%s).\n", path, strerror(err)); + } +#endif +} + +FileMappingHandle MMapFile::map_subset(uint64_t offset, size_t range) +{ + uint64_t page_size = sysconf(_SC_PAGESIZE); + uint64_t begin_map = offset & ~(page_size - 1); + uint64_t end_map = offset + range; + size_t mapped_size = end_map - begin_map; + + // length need not be aligned. + + void *mapped = MMAP64(nullptr, mapped_size, PROT_READ, MAP_PRIVATE, fd, off64_t(begin_map)); + if (mapped == MAP_FAILED) + { + report_error(); + return {}; + } + + return Util::make_handle( + reference_from_this(), + offset, + mapped, mapped_size, + offset - begin_map, range); +} + +uint64_t MMapFile::get_size() +{ + return size; +} + +bool MMapFile::query_stat() +{ + struct STAT64 s = {}; + if (FSTAT64(fd, &s) < 0) + return false; + + if (uint64_t(s.st_size) > SIZE_MAX) + return false; + size = static_cast(s.st_size); + return true; +} + +void MMapFile::unmap(void *mapped, size_t mapped_size) +{ + munmap(mapped, mapped_size); +} + +MMapFile::~MMapFile() +{ + if (fd >= 0) + close(fd); + + if (!rename_from_on_close.empty() && !rename_to_on_close.empty()) + { + int ret = rename(rename_from_on_close.c_str(), rename_to_on_close.c_str()); + if (ret != 0) + LOGE("Failed to rename file %s -> %s.\n", rename_from_on_close.c_str(), rename_to_on_close.c_str()); + } +} + +OSFilesystem::OSFilesystem(const std::string &base_) + : base(base_) +{ +#ifdef __linux__ + notify_fd = inotify_init1(IN_NONBLOCK); + if (notify_fd < 0) + LOGE("Failed to init inotify.\n"); +#else + notify_fd = -1; +#endif +} + +OSFilesystem::~OSFilesystem() +{ +#ifdef __linux__ + if (notify_fd > 0) + { + for (auto &handler : handlers) + inotify_rm_watch(notify_fd, handler.first); + close(notify_fd); + } +#endif +} + +FileHandle OSFilesystem::open(const std::string &path, FileMode mode) +{ + return MMapFile::open(Path::join(base, path), mode); +} + +std::string OSFilesystem::get_filesystem_path(const std::string &path) +{ + return Path::join(base, path); +} + +int OSFilesystem::get_notification_fd() const +{ + return notify_fd; +} + +void OSFilesystem::poll_notifications() +{ +#ifdef __linux__ + if (notify_fd < 0) + return; + + for (;;) + { + alignas(inotify_event) char buffer[sizeof(inotify_event) + NAME_MAX + 1]; + ssize_t ret = read(notify_fd, buffer, sizeof(buffer)); + + if (ret < 0) + { + if (errno != EAGAIN) + LOGE("failed to read inotify fd.\n"); + break; + } + + struct inotify_event *current = nullptr; + for (ssize_t i = 0; i < ret; i += current->len + sizeof(struct inotify_event)) + { + current = reinterpret_cast(buffer + i); + auto mask = current->mask; + + int wd = current->wd; + auto itr = handlers.find(wd); + if (itr == end(handlers)) + continue; + + FileNotifyType type; + if (mask & IN_CLOSE_WRITE) + type = FileNotifyType::FileChanged; + else if (mask & (IN_CREATE | IN_MOVED_TO)) + type = FileNotifyType::FileCreated; + else if (mask & (IN_DELETE | IN_DELETE_SELF | IN_MOVED_FROM)) + type = FileNotifyType::FileDeleted; + else + continue; + + for (auto &func : itr->second.funcs) + { + if (func.func) + { + if (itr->second.directory) + { + auto notify_path = protocol + "://" + Path::join(func.path, current->name); + func.func({ std::move(notify_path), type, func.virtual_handle }); + } + else + func.func({ protocol + "://" + func.path, type, func.virtual_handle }); + } + } + } + } +#endif +} + +void OSFilesystem::uninstall_notification(FileNotifyHandle handle) +{ +#ifdef __linux__ + if (handle < 0) + return; + + if (notify_fd < 0) + return; + + //LOGI("Uninstalling notification: %d\n", handle); + + auto real = virtual_to_real.find(handle); + if (real == end(virtual_to_real)) + { + LOGE("unknown virtual inotify handler.\n"); + return; + } + + auto itr = handlers.find(static_cast(real->second)); + if (itr == end(handlers)) + { + LOGE("unknown inotify handler.\n"); + return; + } + + auto handler_instance = find_if(begin(itr->second.funcs), end(itr->second.funcs), [=](const VirtualHandler &v) { + return v.virtual_handle == handle; + }); + + if (handler_instance == end(itr->second.funcs)) + { + LOGE("unknown inotify handler path.\n"); + return; + } + + itr->second.funcs.erase(handler_instance); + + if (itr->second.funcs.empty()) + { + inotify_rm_watch(notify_fd, real->second); + handlers.erase(itr); + } + + virtual_to_real.erase(real); +#else + (void)handle; +#endif +} + +FileNotifyHandle OSFilesystem::install_notification(const std::string &path, + std::function func) +{ +#ifdef __linux__ + //LOGI("Installing notification for: %s\n", path.c_str()); + if (notify_fd < 0) + return -1; + + FileStat s = {}; + if (!stat(path, s)) + { + LOGE("inotify: path doesn't exist.\n"); + return -1; + } + + auto resolved_path = Path::join(base, path); + int wd = inotify_add_watch(notify_fd, resolved_path.c_str(), + IN_MOVE | IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_DELETE_SELF); + + if (wd < 0) + { + LOGE("Failed to create watch handle.\n"); + return -1; + } + + // We could have different paths which look different but resolve to the same wd, so handle that. + auto itr = handlers.find(wd); + if (itr == end(handlers)) + handlers[wd] = { {{ path, std::move(func), ++virtual_handle }}, s.type == PathType::Directory }; + else + itr->second.funcs.push_back({ path, std::move(func), ++virtual_handle }); + + //LOGI(" Got handle: %d\n", virtual_handle); + + virtual_to_real[virtual_handle] = wd; + return static_cast(virtual_handle); +#else + (void)path; + (void)func; + return -1; +#endif +} + +bool OSFilesystem::remove(const std::string &path) +{ + auto resolved_path = Path::join(base, path); + return unlink(resolved_path.c_str()) == 0; +} + +bool OSFilesystem::move_yield(const std::string &dst, const std::string &src) +{ + auto resolved_dst = Path::join(base, dst); + auto resolved_src = Path::join(base, src); +#if !defined(__linux__) || (defined(ANDROID) && (__ANDROID_API__ < __ANDROID_API_R__)) + // Workaround since Android does not have renameat2 until API level 30. + // If we can exclusive create a new file, we can rename with replace somewhat safely. + int fd = ::open(resolved_dst.c_str(), O_EXCL | O_RDWR | O_CREAT, 0600); + if (fd >= 0) + { + ::close(fd); + return rename(resolved_src.c_str(), resolved_dst.c_str()) == 0; + } + else + return false; +#else + return renameat2(AT_FDCWD, resolved_src.c_str(), AT_FDCWD, resolved_dst.c_str(), RENAME_NOREPLACE) == 0; +#endif +} + +bool OSFilesystem::move_replace(const std::string &dst, const std::string &src) +{ + auto resolved_dst = Path::join(base, dst); + auto resolved_src = Path::join(base, src); + return rename(resolved_src.c_str(), resolved_dst.c_str()) == 0; +} + +std::vector OSFilesystem::list(const std::string &path) +{ + auto directory = Path::join(base, path); + DIR *dir = opendir(directory.c_str()); + if (!dir) + { + LOGE("Failed to open directory %s\n", path.c_str()); + return {}; + } + + std::vector entries; + struct dirent *entry; + while ((entry = readdir(dir))) + { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + auto joined_path = Path::join(path, entry->d_name); + + PathType type; + if (entry->d_type == DT_DIR) + type = PathType::Directory; + else if (entry->d_type == DT_REG) + type = PathType::File; + else if (entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK) + type = PathType::Special; + else + { + FileStat s; + if (!stat(joined_path, s)) + { + LOGE("Failed to stat file: %s\n", joined_path.c_str()); + continue; + } + + type = s.type; + } + entries.push_back({ std::move(joined_path), type }); + } + closedir(dir); + return entries; +} + +bool OSFilesystem::stat(const std::string &path, FileStat &stat) +{ + auto resolved_path = Path::join(base, path); + struct STAT64 buf = {}; + if (::STAT64(resolved_path.c_str(), &buf) < 0) + return false; + + if (S_ISREG(buf.st_mode)) + stat.type = PathType::File; + else if (S_ISDIR(buf.st_mode)) + stat.type = PathType::Directory; + else + stat.type = PathType::Special; + + stat.size = uint64_t(buf.st_size); +#ifdef __linux__ + stat.last_modified = buf.st_mtim.tv_sec * 1000000000ull + buf.st_mtim.tv_nsec; +#else + stat.last_modified = buf.st_mtimespec.tv_sec * 1000000000ull + buf.st_mtimespec.tv_nsec; +#endif + return true; +} + +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/linux/os_filesystem.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/linux/os_filesystem.hpp new file mode 100644 index 00000000..08468758 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/linux/os_filesystem.hpp @@ -0,0 +1,92 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include "../filesystem.hpp" +#include + +namespace Granite +{ +class MMapFile final : public File +{ +public: + static FileHandle open(const std::string &path, FileMode mode); + ~MMapFile() override; + FileMappingHandle map_subset(uint64_t offset, size_t size) override; + FileMappingHandle map_write(size_t map_size) override; + void unmap(void *mapped, size_t size) override; + uint64_t get_size() override; + +private: + bool init(const std::string &path, FileMode mode); + bool query_stat(); + int fd = -1; + size_t size = 0; + bool has_write_map = false; + std::string rename_from_on_close; + std::string rename_to_on_close; + + void report_error(); +}; + +class OSFilesystem : public FilesystemBackend +{ +public: + OSFilesystem(const std::string &base); + ~OSFilesystem(); + std::vector list(const std::string &path) override; + FileHandle open(const std::string &path, FileMode mode) override; + bool stat(const std::string &path, FileStat &stat) override; + FileNotifyHandle install_notification(const std::string &path, std::function func) override; + void uninstall_notification(FileNotifyHandle handle) override; + void poll_notifications() override; + int get_notification_fd() const override; + std::string get_filesystem_path(const std::string &path) override; + + bool remove(const std::string &path) override; + // Must implement atomic renaming semantics. + // Atomically replaces dst. + bool move_replace(const std::string &dst, const std::string &src) override; + // If dst exists, nothing happens (and false is returned). + bool move_yield(const std::string &dst, const std::string &src) override; + +private: + std::string base; + + struct VirtualHandler + { + std::string path; + std::function func; + FileNotifyHandle virtual_handle; + }; + + struct Handler + { + std::vector funcs; + bool directory; + }; + std::unordered_map handlers; + std::unordered_map virtual_to_real; + int notify_fd; + FileNotifyHandle virtual_handle = 0; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/netfs/fs-netfs.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/netfs/fs-netfs.cpp new file mode 100644 index 00000000..a6645716 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/netfs/fs-netfs.cpp @@ -0,0 +1,895 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "fs-netfs.hpp" +#include "path_utils.hpp" +#include "logging.hpp" +#include +#include + +#define HOST_IP "localhost" + +namespace Granite +{ +struct FSNotifyCommand : LooperHandler +{ + FSNotifyCommand(const string &protocol, unique_ptr socket_) + : LooperHandler(move(socket_)), expected(false) + { + reply_queue.emplace(); + auto &reply = reply_queue.back(); + reply.builder.add_u32(NETFS_NOTIFICATION); + reply.builder.add_u32(NETFS_BEGIN_CHUNK_REQUEST); + reply.builder.add_string(protocol); + reply.writer.start(reply.builder.get_buffer()); + + result_reply.begin(4 * sizeof(uint32_t)); + command_reader.start(result_reply.get_buffer()); + + state = NotificationLoop; + } + + void expected_destruction() + { + expected = true; + } + + ~FSNotifyCommand() + { + if (!expected) + terminate(); + } + + void set_notify_cb(function func) + { + notify_cb = move(func); + } + + void push_register_notification(const string &path, promise result) + { + if (reply_queue.empty() && socket->get_parent_looper()) + socket->get_parent_looper()->modify_handler(EVENT_IN | EVENT_OUT, *this); + + reply_queue.emplace(); + auto &reply = reply_queue.back(); + reply.builder.add_u32(NETFS_REGISTER_NOTIFICATION); + reply.builder.add_string(path); + reply.writer.start(reply.builder.get_buffer()); + + replies.push(move(result)); + } + + void push_unregister_notification(FileNotifyHandle handler, promise result) + { + if (reply_queue.empty() && socket->get_parent_looper()) + socket->get_parent_looper()->modify_handler(EVENT_IN | EVENT_OUT, *this); + + reply_queue.emplace(); + auto &reply = reply_queue.back(); + reply.builder.add_u32(NETFS_UNREGISTER_NOTIFICATION); + reply.builder.add_u64(8); + reply.builder.add_u64(uint64_t(handler)); + reply.writer.start(reply.builder.get_buffer()); + replies.push(move(result)); + } + + void modify_looper(Looper &looper) + { + uint32_t mask = reply_queue.empty() ? EVENT_IN : (EVENT_IN | EVENT_OUT); + looper.modify_handler(mask, *this); + } + + bool read_reply_data(Looper &looper) + { + auto ret = command_reader.process(*socket); + if (command_reader.complete()) + { + if (last_cmd == NETFS_BEGIN_CHUNK_NOTIFICATION) + { + FileNotifyInfo info; + info.path = result_reply.read_string(); + info.handle = FileNotifyHandle(result_reply.read_u64()); + auto type = result_reply.read_u32(); + switch (type) + { + case NETFS_FILE_CHANGED: + info.type = FileNotifyType::FileChanged; + break; + case NETFS_FILE_DELETED: + info.type = FileNotifyType::FileDeleted; + break; + case NETFS_FILE_CREATED: + info.type = FileNotifyType::FileCreated; + break; + } + + notify_cb(info); + result_reply.begin(4 * sizeof(uint32_t)); + command_reader.start(result_reply.get_buffer()); + modify_looper(looper); + state = NotificationLoop; + return true; + } + else if (last_cmd == NETFS_BEGIN_CHUNK_REPLY) + { + auto handle = int(result_reply.read_u64()); + + try + { + replies.front().set_value(handle); + } + catch (...) + { + } + + assert(!replies.empty()); + replies.pop(); + + result_reply.begin(4 * sizeof(uint32_t)); + command_reader.start(result_reply.get_buffer()); + modify_looper(looper); + state = NotificationLoop; + return true; + } + else + return false; + } + + return (ret > 0) || (ret == Socket::ErrorWouldBlock); + } + + bool notification_loop(Looper &looper, EventFlags flags) + { + if (flags & EVENT_OUT) + { + if (reply_queue.empty()) + { + looper.modify_handler(EVENT_IN, *this); + return true; + } + + auto ret = reply_queue.front().writer.process(*socket); + if (reply_queue.front().writer.complete()) + reply_queue.pop(); + + if (reply_queue.empty()) + { + looper.modify_handler(EVENT_IN, *this); + return true; + } + else + return (ret > 0) || (ret == Socket::ErrorWouldBlock); + } + + if (flags & EVENT_IN) + { + auto ret = command_reader.process(*socket); + if (command_reader.complete()) + { + auto cmd = result_reply.read_u32(); + if (cmd == NETFS_BEGIN_CHUNK_NOTIFICATION || cmd == NETFS_BEGIN_CHUNK_REPLY) + { + if (result_reply.read_u32() != NETFS_ERROR_OK) + return false; + + last_cmd = cmd; + auto size = result_reply.read_u64(); + + if (size) + { + // Either receive notification or acknowledgement. + result_reply.begin(size); + command_reader.start(result_reply.get_buffer()); + state = ReadReplyData; + looper.modify_handler(EVENT_IN, *this); + } + else + { + // Acknowledge unregister notification. + try + { + replies.front().set_value(0); + } + catch (...) + { + } + + assert(!replies.empty()); + replies.pop(); + + result_reply.begin(4 * sizeof(uint32_t)); + command_reader.start(result_reply.get_buffer()); + modify_looper(looper); + state = NotificationLoop; + } + return true; + } + else + return false; + } + + return (ret > 0) || (ret == Socket::ErrorWouldBlock); + } + + return true; + } + + bool handle(Looper &looper, EventFlags flags) override + { + if (state == ReadReplyData) + return read_reply_data(looper); + else if (state == NotificationLoop) + return notification_loop(looper, flags); + else + return false; + } + + enum State + { + ReadReplyData, + NotificationLoop + }; + + State state = NotificationLoop; + SocketReader command_reader; + ReplyBuilder result_reply; + uint32_t last_cmd = 0; + + struct NotificationReply + { + SocketWriter writer; + ReplyBuilder builder; + }; + queue reply_queue; + queue> replies; + function notify_cb; + atomic_bool expected; +}; + +struct FSReadCommand : LooperHandler +{ + virtual ~FSReadCommand() = default; + + FSReadCommand(const string &path, NetFSCommand command, unique_ptr socket_) + : LooperHandler(move(socket_)) + { + reply_builder.begin(); + reply_builder.add_u32(command); + reply_builder.add_u32(NETFS_BEGIN_CHUNK_REQUEST); + reply_builder.add_string(path); + command_writer.start(reply_builder.get_buffer()); + state = WriteCommand; + } + + bool write_command(Looper &looper) + { + auto ret = command_writer.process(*socket); + if (command_writer.complete()) + { + state = ReadReplySize; + reply_builder.begin(4 * sizeof(uint32_t)); + command_reader.start(reply_builder.get_buffer()); + looper.modify_handler(EVENT_IN, *this); + return true; + } + + return (ret > 0) || (ret == Socket::ErrorWouldBlock); + } + + bool read_reply_size(Looper &) + { + auto ret = command_reader.process(*socket); + if (command_reader.complete()) + { + if (reply_builder.read_u32() != NETFS_BEGIN_CHUNK_REPLY) + return false; + + if (reply_builder.read_u32() != NETFS_ERROR_OK) + return false; + + uint64_t reply_size = reply_builder.read_u64(); + if (reply_size == 0) + return false; + + reply_builder.begin(reply_size); + command_reader.start(reply_builder.get_buffer()); + state = ReadReply; + return true; + } + + return (ret > 0) || (ret == Socket::ErrorWouldBlock); + } + + bool read_reply(Looper &) + { + auto ret = command_reader.process(*socket); + if (command_reader.complete()) + { + parse_reply(); + return false; + } + + return (ret > 0) || (ret == Socket::ErrorWouldBlock); + } + + bool handle(Looper &looper, EventFlags) override + { + if (state == WriteCommand) + return write_command(looper); + else if (state == ReadReplySize) + return read_reply_size(looper); + else if (state == ReadReply) + return read_reply(looper); + else + return false; + } + + enum State + { + WriteCommand, + ReadReplySize, + ReadReply + }; + State state = WriteCommand; + SocketReader command_reader; + SocketWriter command_writer; + ReplyBuilder reply_builder; + + virtual void parse_reply() = 0; +}; + +struct FSReader : FSReadCommand +{ + FSReader(const string &path, unique_ptr socket_) + : FSReadCommand(path, NETFS_READ_FILE, move(socket_)) + { + } + + ~FSReader() + { + if (!got_reply) + result.set_exception(make_exception_ptr(runtime_error("file read"))); + } + + void parse_reply() override + { + got_reply = true; + try + { + result.set_value(reply_builder.consume_buffer()); + } + catch (...) + { + } + } + + promise> result; + bool got_reply = false; +}; + +struct FSList : FSReadCommand +{ + FSList(const string &path, unique_ptr socket_) + : FSReadCommand(path, NETFS_LIST, move(socket_)) + { + } + + ~FSList() + { + if (!got_reply) + result.set_exception(make_exception_ptr(runtime_error("List failed"))); + } + + void parse_reply() override + { + uint32_t entries = reply_builder.read_u32(); + vector list; + for (uint32_t i = 0; i < entries; i++) + { + auto path = reply_builder.read_string(); + auto type = reply_builder.read_u32(); + + switch (type) + { + case NETFS_FILE_TYPE_PLAIN: + list.push_back({ move(path), PathType::File }); + break; + case NETFS_FILE_TYPE_DIRECTORY: + list.push_back({ move(path), PathType::Directory }); + break; + case NETFS_FILE_TYPE_SPECIAL: + list.push_back({ move(path), PathType::Special }); + break; + } + } + + got_reply = true; + try + { + result.set_value(move(list)); + } + catch (...) + { + } + } + + promise> result; + bool got_reply = false; +}; + +struct FSStat : FSReadCommand +{ + FSStat(const string &path, unique_ptr socket_) + : FSReadCommand(path, NETFS_STAT, move(socket_)) + { + } + + ~FSStat() + { + // Throw exception instead in calling thread. + if (!got_reply) + result.set_exception(make_exception_ptr(runtime_error("Failed stat"))); + } + + void parse_reply() override + { + uint64_t size = reply_builder.read_u64(); + uint32_t type = reply_builder.read_u32(); + uint64_t last_modified = reply_builder.read_u64(); + FileStat s; + s.size = size; + s.last_modified = last_modified; + + switch (type) + { + case NETFS_FILE_TYPE_PLAIN: + s.type = PathType::File; + break; + case NETFS_FILE_TYPE_DIRECTORY: + s.type = PathType::Directory; + break; + case NETFS_FILE_TYPE_SPECIAL: + s.type = PathType::Special; + break; + } + + got_reply = true; + try + { + result.set_value(s); + } + catch (...) + { + } + } + + std::promise result; + bool got_reply = false; +}; + +struct FSWriteCommand : LooperHandler +{ + FSWriteCommand(const string &path, const vector &buffer, unique_ptr socket_) + : LooperHandler(move(socket_)) + { + target_size = buffer.size(); + + reply_builder.begin(); + result_reply.begin(4 * sizeof(uint32_t)); + + reply_builder.add_u32(NETFS_WRITE_FILE); + reply_builder.add_u32(NETFS_BEGIN_CHUNK_REQUEST); + reply_builder.add_string(path); + reply_builder.add_u32(NETFS_BEGIN_CHUNK_REQUEST); + reply_builder.add_u64(buffer.size()); + reply_builder.add_buffer(buffer); + command_writer.start(reply_builder.get_buffer()); + command_reader.start(result_reply.get_buffer()); + state = WriteCommand; + } + + bool write_command(Looper &looper, EventFlags flags) + { + if (flags & EVENT_IN) + { + auto ret = command_reader.process(*socket); + // Received message before we completed the write, must be an error. + if (command_reader.complete()) + return false; + + return (ret > 0) || (ret == Socket::ErrorWouldBlock); + } + else if (flags & EVENT_OUT) + { + auto ret = command_writer.process(*socket); + if (command_writer.complete()) + { + // Done writing, wait for reply. + looper.modify_handler(EVENT_IN, *this); + state = ReadReply; + } + + return (ret > 0) || (ret == Socket::ErrorWouldBlock); + } + + return true; + } + + ~FSWriteCommand() + { + if (!got_reply) + result.set_exception(make_exception_ptr(runtime_error("Failed write"))); + } + + bool read_reply(Looper &) + { + auto ret = command_reader.process(*socket); + if (command_reader.complete()) + { + if (result_reply.read_u32() != NETFS_BEGIN_CHUNK_REPLY) + return false; + if (result_reply.read_u32() != NETFS_ERROR_OK) + return false; + if (result_reply.read_u64() != target_size) + return false; + + got_reply = true; + try + { + result.set_value(NETFS_ERROR_OK); + } + catch (...) + { + } + return false; + } + + return (ret > 0) || (ret == Socket::ErrorWouldBlock); + } + + bool handle(Looper &looper, EventFlags flags) override + { + if (state == WriteCommand) + return write_command(looper, flags); + else if (state == ReadReply) + return read_reply(looper); + else + return false; + } + + enum State + { + WriteCommand, + ReadReply + }; + + State state = WriteCommand; + SocketReader command_reader; + SocketWriter command_writer; + ReplyBuilder reply_builder; + ReplyBuilder result_reply; + size_t target_size = 0; + + promise result; + bool got_reply = false; +}; + +NetworkFilesystem::NetworkFilesystem() +{ + looper_thread = thread(&NetworkFilesystem::looper_entry, this); +} + +void NetworkFilesystem::looper_entry() +{ + while (looper.wait_idle(-1) >= 0); +} + +void NetworkFilesystem::setup_notification() +{ + auto socket = Socket::connect(HOST_IP, 7070); + if (!socket) + return; + notify = new FSNotifyCommand(protocol, move(socket)); + notify->set_notify_cb([this](const FileNotifyInfo &info) { + signal_notification(info); + }); + + // Move capture would be nice ... + looper.run_in_looper([this]() { + looper.register_handler(EVENT_OUT, unique_ptr(notify)); + }); +} + +void NetworkFilesystem::uninstall_notification(FileNotifyHandle handle) +{ + if (!notify) + setup_notification(); + if (!notify) + return; + + auto itr = handlers.find(handle); + if (itr == end(handlers)) + return; + handlers.erase(itr); + + auto *value = new promise; + auto result = value->get_future(); + looper.run_in_looper([this, value, handle]() { + notify->push_unregister_notification(handle, move(*value)); + delete value; + }); + + try + { + result.wait(); + } + catch (...) + { + } +} + +void NetworkFilesystem::signal_notification(const FileNotifyInfo &info) +{ + lock_guard holder{lock}; + pending.push_back(info); +} + +void NetworkFilesystem::poll_notifications() +{ + vector tmp_pending; + { + lock_guard holder{lock}; + swap(tmp_pending, pending); + } + + for (auto ¬ification : tmp_pending) + { + auto &func = handlers[notification.handle]; + if (func) + func(notification); + } +} + +FileNotifyHandle NetworkFilesystem::install_notification(const std::string &path, + std::function func) +{ + if (!notify) + setup_notification(); + if (!notify) + return -1; + + auto *value = new promise; + auto result = value->get_future(); + + looper.run_in_looper([this, value, path]() { + notify->push_register_notification(path, move(*value)); + delete value; + }); + + try + { + auto handle = result.get(); + handlers[handle] = move(func); + return handle; + } + catch (...) + { + return -1; + } +} + +vector NetworkFilesystem::list(const std::string &path) +{ + auto joined = protocol + "://" + path; + auto socket = Socket::connect(HOST_IP, 7070); + if (!socket) + return {}; + + unique_ptr handler(new FSList(joined, move(socket))); + auto fut = handler->result.get_future(); + + looper.run_in_looper([&]() { + looper.register_handler(EVENT_OUT, move(handler)); + }); + + try + { + return fut.get(); + } + catch (...) + { + return {}; + } +} + +NetworkFile::~NetworkFile() +{ + unmap(); +} + +NetworkFile *NetworkFile::open(Granite::Looper &looper, const std::string &path, Granite::FileMode mode) +{ + auto *file = new NetworkFile; + if (!file->init(looper, path, mode)) + { + delete file; + return nullptr; + } + else + return file; +} + +bool NetworkFile::init(Looper &looper_, const std::string &path_, FileMode mode_) +{ + path = path_; + mode = mode_; + looper = &looper_; + + if (mode == FileMode::ReadWrite) + { + LOGE("Unsupported file mode.\n"); + return false; + } + + if (mode == FileMode::ReadOnly) + { + if (!reopen()) + { + LOGE("Failed to connect to server.\n"); + return false; + } + } + + return true; +} + +void NetworkFile::unmap() +{ + if (mode == FileMode::WriteOnly && has_buffer && need_flush) + { + need_flush = false; + auto socket = Socket::connect(HOST_IP, 7070); + if (!socket) + throw runtime_error("Failed to connect to server."); + + auto handler = unique_ptr(new FSWriteCommand(path, buffer, move(socket))); + auto reply = handler->result.get_future(); + looper->run_in_looper([&handler, this]() { + looper->register_handler(EVENT_OUT | EVENT_IN, move(handler)); + }); + + try + { + NetFSError error = reply.get(); + if (error != NETFS_ERROR_OK) + LOGE("Failed to write file: %s\n", path.c_str()); + } + catch (...) + { + LOGE("Failed to write file: %s\n", path.c_str()); + } + } +} + +bool NetworkFile::reopen() +{ + if (mode == FileMode::ReadOnly) + { + has_buffer = false; + auto socket = Socket::connect(HOST_IP, 7070); + if (!socket) + return false; + + auto *handler = new FSReader(path, move(socket)); + future = handler->result.get_future(); + + // Capture-by-move would be nice here. + looper->run_in_looper([handler, this]() { + looper->register_handler(EVENT_OUT, unique_ptr(handler)); + }); + } + return true; +} + +void *NetworkFile::map_write(size_t size) +{ + has_buffer = true; + need_flush = true; + buffer.resize(size); + return buffer.empty() ? nullptr : buffer.data(); +} + +void *NetworkFile::map() +{ + try + { + if (!has_buffer) + { + buffer = future.get(); + has_buffer = true; + } + return buffer.empty() ? nullptr : buffer.data(); + } + catch (...) + { + return nullptr; + } +} + +size_t NetworkFile::get_size() +{ + try + { + if (!has_buffer) + { + buffer = future.get(); + has_buffer = true; + } + return buffer.size(); + } + catch (...) + { + return 0; + } +} + +unique_ptr NetworkFilesystem::open(const std::string &path, FileMode mode) +{ + auto joined = protocol + "://" + path; + return unique_ptr(NetworkFile::open(looper, move(joined), mode)); +} + +bool NetworkFilesystem::stat(const std::string &path, FileStat &stat) +{ + auto joined = protocol + "://" + path; + auto socket = Socket::connect(HOST_IP, 7070); + if (!socket) + return false; + + unique_ptr handler(new FSStat(joined, move(socket))); + auto fut = handler->result.get_future(); + + looper.run_in_looper([&]() { + looper.register_handler(EVENT_OUT, move(handler)); + }); + + try + { + stat = fut.get(); + return true; + } + catch (...) + { + return false; + } +} + +NetworkFilesystem::~NetworkFilesystem() +{ + if (notify) + notify->expected_destruction(); + + looper.kill(); + if (looper_thread.joinable()) + looper_thread.join(); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/netfs/fs-netfs.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/netfs/fs-netfs.hpp new file mode 100644 index 00000000..9e3885ee --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/netfs/fs-netfs.hpp @@ -0,0 +1,92 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include "fs-netfs.hpp" +#include "network.hpp" +#include "../filesystem.hpp" +#include "netfs.hpp" +#include +#include +#include + +namespace Granite +{ +struct FSReader; +class NetworkFile : public File +{ +public: + static NetworkFile *open(Looper &looper, const std::string &path, FileMode mode); + ~NetworkFile(); + void *map() override; + void *map_write(size_t size) override; + void unmap() override; + size_t get_size() override; + bool reopen() override; + +private: + NetworkFile() = default; + bool init(Looper &looper, const std::string &path, FileMode mode); + std::string path; + FileMode mode; + Looper *looper = nullptr; + std::future> future; + std::vector buffer; + bool has_buffer = false; + bool need_flush = false; +}; + +struct FSNotifyCommand; +class NetworkFilesystem : public FilesystemBackend +{ +public: + NetworkFilesystem(); + ~NetworkFilesystem(); + std::vector list(const std::string &path) override; + std::unique_ptr open(const std::string &path, FileMode mode) override; + bool stat(const std::string &path, FileStat &stat) override; + + FileNotifyHandle install_notification(const std::string &path, std::function func) override; + + void uninstall_notification(FileNotifyHandle handle) override; + + void poll_notifications() override; + + int get_notification_fd() const override + { + return -1; + } + +private: + std::thread looper_thread; + Looper looper; + void looper_entry(); + FSNotifyCommand *notify = nullptr; + + std::unordered_map> handlers; + std::mutex lock; + std::vector pending; + + void setup_notification(); + void signal_notification(const FileNotifyInfo &info); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/volatile_source.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/volatile_source.hpp new file mode 100644 index 00000000..e97863ee --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/volatile_source.hpp @@ -0,0 +1,111 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "path_utils.hpp" +#include "filesystem.hpp" +#include "intrusive.hpp" +#include "logging.hpp" +#include + +namespace Granite +{ +template +class VolatileSource : public Util::IntrusivePtrEnabled> +{ +public: + VolatileSource(Filesystem *fs_, const std::string &path_) + : fs(fs_), path(Path::enforce_protocol(path_)) + { + } + + VolatileSource() = default; + + ~VolatileSource() + { + deinit(); + } + +protected: + Filesystem *fs = nullptr; + std::string path; + void deinit() + { + if (notify_backend && notify_handle >= 0) + notify_backend->uninstall_notification(notify_handle); + notify_backend = nullptr; + notify_handle = -1; + } + + bool init() + { + if (path.empty() || !fs) + return false; + + auto file = fs->open_readonly_mapping(path); + if (!file) + { + LOGE("Failed to open volatile file: %s\n", path.c_str()); + return false; + } + + auto *self = static_cast(this); + self->update(std::move(file)); + + auto paths = Path::protocol_split(path); + auto *proto = fs->get_backend(paths.first); + if (proto) + { + // Listen to directory so we can track file moves properly. + notify_handle = proto->install_notification(Path::basedir(paths.second), [&](const FileNotifyInfo &info) { + if (info.type == FileNotifyType::FileDeleted) + return; + if (info.path != path) + return; + + try + { + auto f = fs->open_readonly_mapping(info.path); + if (!f) + return; + auto *s = static_cast(this); + s->update(std::move(f)); + } + catch (const std::exception &e) + { + LOGE("Caught update exception: %s\n", e.what()); + } + }); + } + + return true; + } + +private: + FileNotifyHandle notify_handle = -1; + FilesystemBackend *notify_backend = nullptr; +}; + +template +using VolatileHandle = Util::IntrusivePtr>; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/windows/os_filesystem.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/windows/os_filesystem.cpp new file mode 100644 index 00000000..091a4dc2 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/windows/os_filesystem.cpp @@ -0,0 +1,471 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "os_filesystem.hpp" +#include "path_utils.hpp" +#include "logging.hpp" +#include +#include +#include +#include + +namespace Granite +{ +static bool ensure_directory_inner(const std::string &path) +{ + if (Path::is_root_path(path)) + return false; + + auto wpath = Path::to_utf16(path); + + struct __stat64 s; + if (::_wstat64(wpath.c_str(), &s) >= 0 && (s.st_mode & _S_IFDIR) != 0) + return true; + + auto basedir = Path::basedir(path); + if (!ensure_directory_inner(basedir)) + return false; + + if (!CreateDirectoryW(wpath.c_str(), nullptr)) + return GetLastError() == ERROR_ALREADY_EXISTS; + return true; +} + +static bool ensure_directory(const std::string &path) +{ + auto basedir = Path::basedir(path); + return ensure_directory_inner(basedir); +} + +FileHandle MappedFile::open(const std::string &path, Granite::FileMode mode) +{ + auto file = Util::make_handle(); + if (!file->init(path, mode)) + file.reset(); + return file; +} + +static std::atomic_uint32_t global_transaction_counter; + +bool MappedFile::init(const std::string &path, FileMode mode) +{ + DWORD access = 0; + DWORD disposition = 0; + + switch (mode) + { + case FileMode::ReadOnly: + access = GENERIC_READ; + disposition = OPEN_EXISTING; + break; + + case FileMode::ReadWrite: + if (!ensure_directory(path)) + { + LOGE("MappedFile failed to create directory.\n"); + return false; + } + + access = GENERIC_READ | GENERIC_WRITE; + disposition = OPEN_ALWAYS; + break; + + case FileMode::WriteOnly: + case FileMode::WriteOnlyTransactional: + if (!ensure_directory(path)) + { + LOGE("MappedFile failed to create directory.\n"); + return false; + } + + access = GENERIC_READ | GENERIC_WRITE; + disposition = CREATE_ALWAYS; + break; + } + + if (mode == FileMode::WriteOnlyTransactional) + { + // Use atomic file rename to ensure that a file is written atomically. + rename_to_on_close = path; + rename_from_on_close = + path + ".tmp." + + std::to_string(GetCurrentProcessId()) + "." + + std::to_string(global_transaction_counter.fetch_add(1, std::memory_order_relaxed)); + } + + auto wpath = Path::to_utf16(rename_from_on_close.empty() ? path : rename_from_on_close); + + file = CreateFileW(wpath.c_str(), access, FILE_SHARE_READ, nullptr, disposition, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, INVALID_HANDLE_VALUE); + if (file == INVALID_HANDLE_VALUE) + { + rename_to_on_close.clear(); + rename_from_on_close.clear(); + return false; + } + + if (mode != FileMode::WriteOnly && mode != FileMode::WriteOnlyTransactional) + { + DWORD hi; + DWORD lo = GetFileSize(file, &hi); + size = (uint64_t(hi) << 32) | uint32_t(lo); + file_mapping = CreateFileMappingW(file, nullptr, PAGE_READONLY, 0, 0, nullptr); + } + + return true; +} + +uint64_t MappedFile::get_size() +{ + return size; +} + +struct PageSizeQuery +{ + PageSizeQuery() + { + SYSTEM_INFO system_info = {}; + GetSystemInfo(&system_info); + page_size = system_info.dwPageSize; + } + uint32_t page_size = 0; +}; +static PageSizeQuery static_page_size_query; + +FileMappingHandle MappedFile::map_subset(uint64_t offset, size_t range) +{ + if (offset + range > size) + return {}; + + if (!file_mapping) + return {}; + + uint64_t begin_map = offset & ~uint64_t(static_page_size_query.page_size - 1); + + DWORD hi = DWORD(begin_map >> 32); + DWORD lo = DWORD(begin_map & 0xffffffffu); + uint64_t end_mapping = offset + range; + size_t mapped_size = end_mapping - begin_map; + + void *mapped = MapViewOfFile(file_mapping, FILE_MAP_READ, hi, lo, mapped_size); + if (!mapped) + return {}; + + return Util::make_handle( + reference_from_this(), offset, + static_cast(mapped) + begin_map, mapped_size, + offset - begin_map, range); +} + +FileMappingHandle MappedFile::map_write(size_t map_size) +{ + size = map_size; + +#ifdef _WIN64 + DWORD hi = DWORD(size >> 32); + DWORD lo = DWORD(size & 0xffffffffu); +#else + DWORD hi = 0; + DWORD lo = DWORD(size); +#endif + + HANDLE file_view = CreateFileMappingW(file, nullptr, PAGE_READWRITE, hi, lo, nullptr); + if (!file_view) + return {}; + + void *mapped = MapViewOfFile(file_view, FILE_MAP_ALL_ACCESS, 0, 0, size); + CloseHandle(file_view); + + if (!mapped) + return {}; + + return Util::make_handle(reference_from_this(), 0, + static_cast(mapped), size, + 0, size); +} + +void MappedFile::unmap(void *mapped, size_t) +{ + if (mapped) + UnmapViewOfFile(mapped); +} + +MappedFile::~MappedFile() +{ + if (file_mapping) + CloseHandle(file_mapping); + if (file != INVALID_HANDLE_VALUE) + CloseHandle(file); + + if (!rename_from_on_close.empty() && !rename_to_on_close.empty()) + { + auto to_w16 = Path::to_utf16(rename_to_on_close); + auto from_w16 = Path::to_utf16(rename_from_on_close); + DWORD code = S_OK; + + if (!MoveFileW(from_w16.c_str(), to_w16.c_str())) + { + code = GetLastError(); + if (code == ERROR_ALREADY_EXISTS && !ReplaceFileW(to_w16.c_str(), from_w16.c_str(), nullptr, 0, nullptr, nullptr)) + code = GetLastError(); + } + + if (FAILED(code)) + LOGE("Failed to rename file %s -> %s (0x%lx).\n", rename_from_on_close.c_str(), rename_to_on_close.c_str(), code); + } +} + +OSFilesystem::OSFilesystem(const std::string &base_) + : base(base_) +{ +} + +OSFilesystem::~OSFilesystem() +{ + for (auto &handler : handlers) + { + CancelIo(handler.second.handle); + CloseHandle(handler.second.handle); + CloseHandle(handler.second.event); + } +} + +std::string OSFilesystem::get_filesystem_path(const std::string &path) +{ + return Path::join(base, path); +} + +FileHandle OSFilesystem::open(const std::string &path, FileMode mode) +{ + return MappedFile::open(Path::join(base, path), mode); +} + +void OSFilesystem::poll_notifications() +{ + for (auto &handler : handlers) + { + if (WaitForSingleObject(handler.second.event, 0) != WAIT_OBJECT_0) + continue; + + DWORD bytes_returned; + if (!GetOverlappedResult(handler.second.handle, &handler.second.overlapped, &bytes_returned, TRUE)) + continue; + + size_t offset = 0; + const FILE_NOTIFY_INFORMATION *info = nullptr; + do + { + info = reinterpret_cast( + reinterpret_cast(handler.second.async_buffer) + offset); + + FileNotifyInfo notify; + notify.handle = handler.first; + notify.path = Path::join(handler.second.path, + Path::to_utf8(info->FileName, + info->FileNameLength / sizeof(wchar_t))); + + switch (info->Action) + { + case FILE_ACTION_ADDED: + case FILE_ACTION_RENAMED_NEW_NAME: + notify.type = FileNotifyType::FileCreated; + if (handler.second.func) + handler.second.func(notify); + break; + + case FILE_ACTION_REMOVED: + case FILE_ACTION_RENAMED_OLD_NAME: + notify.type = FileNotifyType::FileDeleted; + if (handler.second.func) + handler.second.func(notify); + break; + + case FILE_ACTION_MODIFIED: + notify.type = FileNotifyType::FileChanged; + if (handler.second.func) + handler.second.func(notify); + break; + + default: + LOGE("Invalid notify type.\n"); + break; + } + + offset += info->NextEntryOffset; + } while (info->NextEntryOffset != 0); + + kick_async(handler.second); + } +} + +void OSFilesystem::uninstall_notification(FileNotifyHandle id) +{ + auto itr = handlers.find(id); + if (itr != end(handlers)) + { + CancelIo(itr->second.handle); + CloseHandle(itr->second.handle); + CloseHandle(itr->second.event); + handlers.erase(itr); + } +} + +void OSFilesystem::kick_async(Handler &handler) +{ + handler.overlapped = {}; + handler.overlapped.hEvent = handler.event; + + auto ret = ReadDirectoryChangesW(handler.handle, handler.async_buffer, sizeof(handler.async_buffer), FALSE, + FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME, + nullptr, &handler.overlapped, nullptr); + + if (!ret && GetLastError() != ERROR_IO_PENDING) + { + LOGE("Failed to read directory changes async.\n"); + } +} + +FileNotifyHandle OSFilesystem::install_notification(const std::string &path, std::function func) +{ + FileStat s = {}; + if (!stat(path, s)) + { + LOGE("Window inotify: path doesn't exist.\n"); + return -1; + } + + if (s.type != PathType::Directory) + { + LOGE("Windows inotify: Implementation only supports directories.\n"); + return -1; + } + + auto resolved_path = Path::to_utf16(Path::join(base, path)); + HANDLE handle = + CreateFileW(resolved_path.c_str(), FILE_LIST_DIRECTORY, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr); + if (handle == INVALID_HANDLE_VALUE) + { + LOGE("Failed to open directory for watching.\n"); + return -1; + } + + HANDLE event = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (event == nullptr) + { + CloseHandle(handle); + return -1; + } + + handle_id++; + Handler handler; + handler.path = protocol + "://" + path; + handler.func = std::move(func); + handler.handle = handle; + handler.event = event; + auto &h = handlers[handle_id]; + h = std::move(handler); + kick_async(h); + + return handle_id; +} + +bool OSFilesystem::remove(const std::string &path) +{ + auto joined = Path::to_utf16(Path::join(base, path)); + return bool(DeleteFileW(joined.c_str())); +} + +bool OSFilesystem::move_yield(const std::string &dst, const std::string &src) +{ + auto joined_dst = Path::to_utf16(Path::join(base, dst)); + auto joined_src = Path::to_utf16(Path::join(base, src)); + return bool(MoveFileW(joined_src.c_str(), joined_dst.c_str())); +} + +bool OSFilesystem::move_replace(const std::string &dst, const std::string &src) +{ + auto joined_dst = Path::to_utf16(Path::join(base, dst)); + auto joined_src = Path::to_utf16(Path::join(base, src)); + if (MoveFileW(joined_src.c_str(), joined_dst.c_str())) + return true; + if (GetLastError() != ERROR_ALREADY_EXISTS) + return false; + return bool(ReplaceFileW(joined_dst.c_str(), joined_src.c_str(), nullptr, 0, nullptr, nullptr)); +} + +std::vector OSFilesystem::list(const std::string &path) +{ + std::vector entries; + WIN32_FIND_DATAW result; + auto joined = Path::to_utf16(Path::join(base, path)); + joined += L"/*"; + + HANDLE handle = FindFirstFileW(joined.c_str(), &result); + if (handle == INVALID_HANDLE_VALUE) + return entries; + + do + { + ListEntry entry; + if (result.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + entry.type = PathType::Directory; + else + entry.type = PathType::File; + + auto utf8_path = Path::to_utf8(result.cFileName); + if (utf8_path == "." || utf8_path == "..") + continue; + + entry.path = Path::join(path, utf8_path); + entries.push_back(std::move(entry)); + } while (FindNextFileW(handle, &result)); + + FindClose(handle); + return entries; +} + +bool OSFilesystem::stat(const std::string &path, FileStat &stat) +{ + auto joined = Path::join(base, path); + struct __stat64 buf; + if (_wstat64(Path::to_utf16(joined).c_str(), &buf) < 0) + return false; + + if (buf.st_mode & _S_IFREG) + stat.type = PathType::File; + else if (buf.st_mode & _S_IFDIR) + stat.type = PathType::Directory; + else + stat.type = PathType::Special; + + stat.size = uint64_t(buf.st_size); + stat.last_modified = buf.st_mtime; + return true; +} + +int OSFilesystem::get_notification_fd() const +{ + return -1; +} + +} // namespace Granite diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/windows/os_filesystem.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/windows/os_filesystem.hpp new file mode 100644 index 00000000..557119d5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/filesystem/windows/os_filesystem.hpp @@ -0,0 +1,86 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include "filesystem.hpp" +#include +#define WIN32_LEAN_AND_MEAN +#include + +namespace Granite +{ +class MappedFile final : public File +{ +public: + static FileHandle open(const std::string &path, FileMode mode); + ~MappedFile() override; + + FileMappingHandle map_subset(uint64_t offset, size_t range) override; + FileMappingHandle map_write(size_t size) override; + void unmap(void *mapped, size_t range) override; + uint64_t get_size() override; + +private: + bool init(const std::string &path, FileMode mode); + HANDLE file = INVALID_HANDLE_VALUE; + HANDLE file_mapping = nullptr; + uint64_t size = 0; + std::string rename_from_on_close; + std::string rename_to_on_close; +}; + +class OSFilesystem : public FilesystemBackend +{ +public: + OSFilesystem(const std::string &base); + ~OSFilesystem(); + std::vector list(const std::string &path) override; + FileHandle open(const std::string &path, FileMode mode) override; + bool stat(const std::string &path, FileStat &stat) override; + FileNotifyHandle install_notification(const std::string &path, std::function func) override; + void uninstall_notification(FileNotifyHandle handle) override; + void poll_notifications() override; + int get_notification_fd() const override; + std::string get_filesystem_path(const std::string &path) override; + + bool remove(const std::string &str) override; + bool move_yield(const std::string &dst, const std::string &src) override; + bool move_replace(const std::string &dst, const std::string &src) override; + +private: + std::string base; + + struct Handler + { + std::string path; + std::function func; + HANDLE handle = nullptr; + HANDLE event = nullptr; + DWORD async_buffer[1024]; + OVERLAPPED overlapped; + }; + + std::unordered_map handlers; + FileNotifyHandle handle_id = 0; + void kick_async(Handler &handler); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/CMakeLists.txt new file mode 100644 index 00000000..df30747f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/CMakeLists.txt @@ -0,0 +1,12 @@ +add_granite_internal_lib(granite-math + math.hpp math.cpp + frustum.hpp frustum.cpp + aabb.cpp aabb.hpp + render_parameters.hpp + interpolation.cpp interpolation.hpp + muglm/muglm.cpp muglm/muglm.hpp + muglm/muglm_impl.hpp muglm/matrix_helper.hpp + transforms.cpp transforms.hpp + simd.hpp simd_headers.hpp) + +target_include_directories(granite-math PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/aabb.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/aabb.cpp new file mode 100644 index 00000000..bbb1b8b9 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/aabb.cpp @@ -0,0 +1,56 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "aabb.hpp" +#include + +namespace Granite +{ +AABB AABB::transform(const mat4 &m) const +{ + vec3 m0 = vec3(FLT_MAX); + vec3 m1 = vec3(-FLT_MAX); + + for (unsigned i = 0; i < 8; i++) + { + vec3 c = get_corner(i); + vec4 t = m * vec4(c, 1.0f); + vec3 v = t.xyz(); + m0 = min(v, m0); + m1 = max(v, m1); + } + + return AABB(m0, m1); +} + +vec3 AABB::get_coord(float dx, float dy, float dz) const +{ + return mix(minimum.v3, maximum.v3, vec3(dx, dy, dz)); +} + +void AABB::expand(const AABB &aabb) +{ + minimum.v3 = min(minimum.v3, aabb.minimum.v3); + maximum.v3 = max(maximum.v3, aabb.maximum.v3); +} + +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/aabb.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/aabb.hpp new file mode 100644 index 00000000..dff11117 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/aabb.hpp @@ -0,0 +1,101 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "math.hpp" +#include "muglm/muglm_impl.hpp" + +namespace Granite +{ +class AABB +{ +public: + AABB(vec3 minimum_, vec3 maximum_) + { + minimum.v4 = vec4(minimum_, 1.0f); + maximum.v4 = vec4(maximum_, 1.0f); + } + + AABB() = default; + + vec3 get_coord(float dx, float dy, float dz) const; + AABB transform(const mat4 &m) const; + + void expand(const AABB &aabb); + + const vec3 &get_minimum() const + { + return minimum.v3; + } + + const vec3 &get_maximum() const + { + return maximum.v3; + } + + const vec4 &get_minimum4() const + { + return minimum.v4; + } + + const vec4 &get_maximum4() const + { + return maximum.v4; + } + + vec4 &get_minimum4() + { + return minimum.v4; + } + + vec4 &get_maximum4() + { + return maximum.v4; + } + + vec3 get_corner(unsigned i) const + { + float x = i & 1 ? maximum.v3.x : minimum.v3.x; + float y = i & 2 ? maximum.v3.y : minimum.v3.y; + float z = i & 4 ? maximum.v3.z : minimum.v3.z; + return vec3(x, y, z); + } + + vec3 get_center() const + { + return minimum.v3 + (maximum.v3 - minimum.v3) * vec3(0.5f); + } + + float get_radius() const + { + return 0.5f * distance(minimum.v3, maximum.v3); + } + +private: + union + { + vec3 v3; + vec4 v4; + } minimum, maximum; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/docs/squad.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/docs/squad.md new file mode 100644 index 00000000..1c82d251 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/docs/squad.md @@ -0,0 +1,423 @@ +# Modified SQUAD for non-uniform timestamps + +The SQUAD algorithm is a well-known algorithm for smooth interpolation of rotations. + +The standard and simple algorithm for rotation is SLERP, +which ensures constant angular velocity over a given interpolation segment. +However, the flaw of SLERP for camera interpolation is that the angular velocity +is not continuous, and it will abruptly change on a new segment. +This problem is solved by SQUAD, but in its naive implementation, the length of +each segment must be uniform, otherwise the derivation fails. + +I spent some time studying the underlying math and derived a formula that works for +non-uniform timestamps as well. + +## The standard runtime algorithm + +In SQUAD, each key-frame point is represented as +a quaternion qk at timestamp tk. +At each timestamp, we also pre-compute a +helper control point qck, +which derivation will be explored further below. + +We are given the implementation: + +squadk(t) = slerp(slerp(qk, qk+1, t), + slerp(qck, qck+1, t), + 2t(1 - t)) + +t is given here in the range [0, 1), and is computed by: + +t = (T - tk) / (tk+1 - tk) + +where T is the global time for which to evaluate. +An animation clip is stitched together by many such splines, one for each k. + +### Analyze the expression + +To perform further calculus on the squad(t) function, we can simplify to scalars. +If we assume for the purposes of analysis that all +the rotations have the same axis of rotation, we can +rewrite squad(t) to a linear interpolation of rotation angle θ, which +each key-frame now represents: + +squadk(t) = lerp(lerp(θk, θk+1, t), + lerp(θck, θck+1, t), + 2t(1 - t)) + +All these lerps are trivial expressions: + +lerp(a, b, t) = (1 - t)a + tb + +We can expand the expression and compute their first and second order derivatives. + +vk(t) = + (-3 + 8t - 6t2) θk + + (-1 - 4t + 6t2) θk+1 + + (2 - 8t + 6t2) θck + + (4t - 6t2) θck+1 + +ak(t) = + (8 - 12t) θk + + (-4 + 12t) θk+1 + + (-8 + 12t) θck + + (4 - 12t) θck+1 + +It is important to note here that we derive with respect to the spline local parameter t. +To obtain the absolute angular velocity and acceleration at time t, we need to apply chain rules: + +Vk(t) = vk(t) (dt / dT) = vk(t) / dk + +where dk = tk+1 - tk, +and Vk(t) is absolute angular velocity, dθ / dT. + +Similarly, Ak(t) = ak(t) / dk2 is +absolute angular acceleration, d2θ / (dT)2. When dk is constant, +all uses of dk cancel out, +and this is the assumption various algorithms online make. +To ensure first order continuity we must satisfy +Vk(1) = Vk+1(0), or alternatively if dk is constant, +vk(1) = vk+1(0). Similarly, if we want to ensure continuous second order derivative, we must +satisfy Ak(1) = Ak+1(0). + +**vk+1(0)** = + -3θk+1 + + 1θk+2 + + 2θck+1 + + 0θck+2 =\ + **(θk+2 - θk+1) - + 2(θk+1 - θck+1)** + +**vk(1)** = + -1θk + + 3θk+1 + + 0θck - + 2θck+1 =\ + **(θk+1 - θk) + + 2(θk+1 - θck+1)** + +**ak+1(0)** = + 8θk+1 - + 4θk+2 - + 8θck+1 + + 4θck+2 =\ + **8(θk+1 - θck+1) - + 4(θk+2 - θck+2)** + +**ak(1)** = + -4θk + + 8θk+1 + + 4θck - + 8θck+1 =\ + **8(θk+1 - θck+1) - + 4(θk - θck)** + +Based on these expressions, we can already intuit what the relationship +between the control points and the key-frame points are. The difference expresses +acceleration. With positive acceleration, the control points lags behind the key-frame, and vice versa. +Looking at the velocity expressions, with positive acceleration, we also get larger velocity at t = 1 compared to t = 0, +as expected. + +To satisfy the velocity equations, we need to choose vk+1(0) = vk(1), so\ +(θk+2 - θk+1) - +2(θk+1 - θck+1) = +(θk+1 - θk) + +2(θk+1 - θck+1)\ +(θk+2 - θk+1) - +(θk+1 - θk) = +4(θk+1 - θck+1)\ +((θk+2 - θk+1) - +(θk+1 - θk)) / 4 = +θk+1 - θck+1\ +θk+1 - ((θk+2 - θk+1) - +(θk+1 - θk)) / 4 = +**θck+1** + +(θk+2 - θk+1) - (θk+1 - θk) +is quite recognizable and intuitive. +This is the discrete measurement of acceleration at tk+1. + +For simplicity of notation, we introduce the local delta, +Δk = θk - θck. +We can now rewrite the equations in a more digestable form: + +vk+1(0) = +(θk+2 - θk+1) - 2Δk+1 + +vk(1) = +(θk+1 - θk) + 2Δk+1 + +ak+1(0) = +8Δk+1 - 4Δk+2 + +ak(1) = +8Δk+1 - 4Δk + +This equation will only yield a continuous acceleration if +Δk = Δk+2, which is not guaranteed. +However, we have the nice property that a constant acceleration will +yield a constant ak(t) for any k equal to 4Δk. +As we deduced earlier, Δk is 1/4th the measured discrete acceleration, +so everything checks out. Continuous acceleration is a nice property, +but not required for smooth camera motion. + +## Going back to the quaternion domain + +We have found expressions for the control points, but the derivation +has been happening in the angular domain, we need to work with quaternions. + +Here, articles online will usually begin talking about logarithms and exponential functions of quaternions +which at first glance is pure non-sense, but it is actually fairly intuitive. +It took me a while to understand what the hell the article authors were smoking at first. + +The insight is that **multiplying** two quaternions **adds** their rotational angles. +This is exactly the same as complex numbers, where multiplying two complex numbers +add their angles. +For logarithms of quaternions to work, we need to convert them to a number where +adding the results will function similarly to angular addition. Taking the exponent +should give us back the result. + +qaqb = exp(ln(qaqb)) = +exp(ln(qa) + ln(qb)) + +As an aside, this extension also allows us to reason about powers of quaternions, since +ln(qac) = c⋅ln(qa). + +The logarithm for a unit quaternion is computed as: + +``` +// vec3 quat_log(q) + +if (abs(q.w) > 0.9999f) + return vec3(0.0f); +else + return normalize(q.as_vec4().xyz()) * acos(q.w); +``` + +The main confusion for me here is that quaternion multiplication does not commute, +but here the logarithm additions do. Subtraction might make more sense ... + +```c++ +// compute_inner_control_point_delta(q, delta) + +quat inv_q1 = conjugate(q1); +quat delta_k = inv_q1 * q2; // q2 - q1 +quat delta_k_minus1 = inv_q1 * q0; // q0 - q1 = -(q1 - q0) +vec3 delta_k_log = quat_log(delta_k); +vec3 delta_k_minus1_log = quat_log(delta_k_minus1); +vec3 delta = 0.25f * (delta_k_log + delta_k_minus1_log); +return delta; +``` + +The multiplication order seems somewhat arbitrary, +and I cannot prove exactly why we have to do it like this, but I cribbed +this part from the web. This document so far is trying to justify how it works. +At the very least, we can see similarities with the original derivation. +Here, `delta_k` and `delta_k_minus1` measure the velocities between key-frames. +Multiplying is "addition", but multiplying by conjugate is "subtraction". +By subtracting in the log-domain we can get an angular differential and measure acceleration. +As expected, we also take 1/4th since the delta is 1/4th measured acceleration. + +This delta is later used to construct the control point qck. + +```c++ +// compute_inner_control_point(q, delta) + +// Subtraction in angular domain. +return q * quat_exp(-delta); +``` + +which maps to the definition we made: + +θk - θck = +Δk \ +**θck = +θk - Δk** + +To my great surprise, this is actually delightfully simple. +The logarithm is a vec3 where the direction is axis of rotation, +and length is the angle θ. This is what allows us to add/subtract the rotations +together. This style of expressing rotation is basically how we would +express torque in physics, nice! + +The exponent just inverts what the log did. +We recover the angle by taking length of vector +and rebuilding the quaternion from that. + +``` +// quat quat_exp(q) + +float l = dot(q, q); +if (l < 0.000001f) +{ + return quat(1.0f, 0.0f, 0.0f, 0.0f); +} +else +{ + float vlen = length(q); + vec3 v = normalize(q) * sin(vlen); + return quat(cos(vlen), v); +} +``` + +## Non-uniform time deltas dk + +This is where it gets spicy and where I was initially stumped when +attempting to implement SQUAD. When constructing arbitrary camera paths, +it is helpful to be able to place key-frames at any timestamp. +What unfortunately happens now is that velocities are no longer +continuous over a spline boundary, because the splines are now swept at varying +rates. We will need to re-derive the control points, +based on Vk(t), not vk(t), in angular domain. + +Vk+1(0) = +((θk+2 - θk+1) - 2Δk+1) / dk+1 + +Vk(1) = +((θk+1 - θk) + 2Δk+1) / dk + +To be able to solve this, we need to consider that Δk+1 need +not be a single value. +When evaluating spline k and k + 1, it can take different values as needed. +This gives rise to the "incoming" and "outgoing" control points. +The incoming control point delta is used when evaluating the previous spline. + +Vk+1(0) = +((θk+2 - θk+1) - 2Δok+1) / dk+1 + +Vk(1) = +((θk+1 - θk) + 2Δik+1) / dk + +The superscript o and i denote outgoing and incoming respectively. +We can now solve this equation directly, similar to the derivation we did for constant dk earlier. + +((θk+2 - θk+1) - 2Δok+1) / dk+1 = +((θk+1 - θk) + 2Δik+1) / dk + +(θk+2 - θk+1) / dk+1 - +2Δok+1 / dk+1 = +(θk+1 - θk) / dk + +2Δik+1 / dk + +(θk+2 - θk+1) / dk+1 - +(θk+1 - θk) / dk - +2Δok+1 / dk+1 = +2Δik+1 / dk + +If we let the ratio r be dk / dk+1, we get + +Δik+1 = + ((θk+2 - θk+1)(dk / dk+1) - + (θk+1 - θk)) / 2 - + Δok+1(dk / dk+1) + +Which shows that we can actually select the outgoing control point rather freely, +and we can then use this formula to compensate the difference in +dk in the incoming control point. + +For the outgoing control point, we should modify the acceleration +computation to be aware of different step rates. Basically, +we normalize the discrete velocities in terms of global time T. +There might be better ways of computing this, but, meh. +From empiric testing, the result is pretty accurate. + +``` +quat inv_q1 = conjugate(q1); +quat delta_k = inv_q1 * q2; // q2 - q1 +quat delta_k_minus1 = inv_q1 * q0; // q0 - q1 = -(q1 - q0) +vec3 delta_k_log = quat_log(delta_k); +vec3 delta_k_minus1_log = quat_log(delta_k_minus1); + +// We sample velocity at the center of the segment when taking the difference. +// Future sample is at t = +1/2 dt +// Past sample is at t = -1/2 dt +float segment_time = 0.5f * (dt0 + dt1); +vec3 absolute_accel = (delta_k_log / dt1 + delta_k_minus1_log / dt0) / segment_time; +vec3 delta = (0.25f * dt1 * dt1) * absolute_accel; +``` + +``` +// Computed from snippet above +vec3 outgoing = tmp_spline_deltas[i]; + +float dt0 = new_linear_timestamps[i] - new_linear_timestamps[i - 1]; +float dt1 = i + 1 < n ? (new_linear_timestamps[i + 1] - new_linear_timestamps[i]) : dt0; +float t_ratio = dt0 / dt1; + +const quat &q0 = new_linear_values[i - 1]; +const quat &q1 = new_linear_values[i]; +const quat &q2 = i + 1 < n ? new_linear_values[i + 1] : q1; + +quat q12 = conjugate(q1) * q2; +quat q10 = conjugate(q1) * q0; // This is implicitly negated. +vec3 delta_q12 = quat_log(q12); +vec3 delta_q10 = quat_log(q10); + +vec3 incoming = 0.5f * (t_ratio * delta_q12 + delta_q10) - t_ratio * outgoing; + +spline_data[3 * spline + 0] = q1 * quat_exp(-incoming); +spline_data[3 * spline + 1] = q1; +spline_data[3 * spline + 2] = q1 * quat_exp(-outgoing); +``` + +Each key-frame gets 3 values. This is very similar to the +CUBICSPLINE formulation used in glTF. +When evalulating the spline in runtime we look at indices +3 * k + {1, 2, 3, 4}. + +### Modified SQUAD function + +squadk(t) = slerp(slerp(qk, qk+1, t), +slerp(qk·quatExp(-Δok), + qk+1·quatExp(-Δik+1), t), + 2t(1 - t)) + +Δ is in the log domain as we computed above with outgoing and incoming deltas. + +## Verification + +While doing this work, I also made a test bench of sorts to evaluate the results. +I tested 4 different scenarios with scalars. + +- Interpolate quadratic function with even timestamps. Should be 100% exact. +- Interpolate quadratic function with uneven timestamps. Will have some error. +- Interpolate cubic function with even timestamps. Expect some errors due to non-constant acceleration. +- Interpolate cubic function with uneven timestamps. Expect some errors due to non-constant acceleration. + +We want to validate: +- Average error of reference function f(t) and interpolated result. +- Continuity of measured first derivative (and second derivative). + +### Quadratic + +f(t) = 0.5t - 0.25t2 + +#### Even timestamps + +Key frames placed at t = {0, 0.5, 1.0, 2.0, 2.5, 3.0}.\ +Perfect result. As expected. + +#### Uneven timestamps +Key frames placed at t = {0, 1.0, 1.8, 2.1, 2.9, 3.0, 4.2, 4.3, 5.0, 6.0}.\ +Average error: 0.008141\ +Continuous first derivative, discontinuous second derivative. + +### Cubic + +f(t) = 0.5t - 0.25t2 + 0.25t3 + +#### Even timestamps +Key frames placed at t = {0, 0.5, 1.0, 2.0, 2.5, 3.0}.\ +Average error: 0.00195\ +Continuous first derivative, discontinuous second derivative. + +#### Uneven timestamps +Key frames placed at t = {0, 0.5, 0.9, 1.1, 1.4, 1.5, 2.1, 2.2, 2.5, 3.0}.\ +Average error: 0.008285\ +Continuous first derivative, discontinuous second derivative. + +### Summary + +The more even timestamps we have, the more accurate the spline becomes. +The error is also quite acceptable, and we see continuous first derivative, +which is the critical part to get right. \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/frustum.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/frustum.cpp new file mode 100644 index 00000000..38185837 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/frustum.cpp @@ -0,0 +1,155 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "frustum.hpp" + +namespace Granite +{ + +// For reference, should always use SIMD-version. +bool Frustum::intersects_slow(const AABB &aabb) const +{ + for (auto &plane : planes) + { + bool intersects_plane = false; + for (unsigned i = 0; i < 8; i++) + { + if (dot(vec4(aabb.get_corner(i), 1.0f), plane) >= 0.0f) + { + intersects_plane = true; + break; + } + } + + if (!intersects_plane) + return false; + } + + return true; +} + +bool Frustum::intersects_sphere(const AABB &aabb) const +{ + vec4 center(aabb.get_center(), 1.0f); + float radius = aabb.get_radius(); + + for (auto &plane : planes) + if (dot(plane, center) < -radius) + return false; + + return true; +} + +static constexpr float FarClipInfiniteClamp = 1e-10f; + +vec3 Frustum::get_coord(float dx, float dy, float dz) const +{ + dz = 1.0f - dz; + + bool infinite_z = inv_view_projection[3][3] == 0.0f; + if (infinite_z) + dz = muglm::max(dz, FarClipInfiniteClamp); + + vec4 clip = vec4(2.0f * dx - 1.0f, 2.0f * dy - 1.0f, dz, 1.0f); + clip = inv_view_projection * clip; + return clip.xyz() / clip.w; +} + +vec4 Frustum::get_bounding_sphere(const mat4 &inv_projection, const mat4 &inv_view) +{ + // Make sure that radius is numerically stable throughout, since we use that as a snapping factor potentially. + // Use the inverse projection to create the radius. + + const auto get_coord = [&](float x, float y, float z) -> vec3 { + vec4 clip = vec4(x, y, z, 1.0f); + clip = inv_projection * clip; + return clip.xyz() / clip.w; + }; + + vec3 center_near = get_coord(0.0f, 0.0f, 0.0f); + vec3 center_far = get_coord(0.0f, 0.0f, 1.0f); + + vec3 near_pos = get_coord(-1.0f, -1.0f, 0.0f); + vec3 far_pos = get_coord(+1.0f, +1.0f, 1.0f); + + float C = length(center_far - center_near); + float N = dot(near_pos - center_near, near_pos - center_near); + float F = dot(far_pos - center_far, far_pos - center_far); + + // Solve the equation: + // n^2 + x^2 == f^2 + (C - x)^2 => + // N + x^2 == F + C^2 - 2Cx + x^2. + // x = (F - N + C^2) / 2C + float center_distance = (F - N + C * C) / (2.0f * C); + float radius = muglm::sqrt(center_distance * center_distance + N); + vec3 view_space_center = center_near + center_distance * normalize(center_far - center_near); + vec3 center = (inv_view * vec4(view_space_center, 1.0f)).xyz(); + return vec4(center, radius); +} + +void Frustum::build_planes(const mat4 &inv_view_projection_) +{ + inv_view_projection = inv_view_projection_; + bool infinite_z = inv_view_projection[3][3] == 0.0f; + float far_clip_z = infinite_z ? FarClipInfiniteClamp : 0.0f; + const vec4 tln(-1.0f, -1.0f, 1.0f, 1.0f); + const vec4 bln(-1.0f, +1.0f, 1.0f, 1.0f); + const vec4 blf(-1.0f, +1.0f, far_clip_z, 1.0f); + const vec4 trn(+1.0f, -1.0f, 1.0f, 1.0f); + const vec4 trf(+1.0f, -1.0f, far_clip_z, 1.0f); + const vec4 brn(+1.0f, +1.0f, 1.0f, 1.0f); + const vec4 brf(+1.0f, +1.0f, far_clip_z, 1.0f); + const vec4 c(0.0f, 0.0f, 0.5f, 1.0f); + + const auto project = [](const vec4 &v) { + return v.xyz() / vec3(v.w); + }; + + vec3 TLN = project(inv_view_projection * tln); + vec3 BLN = project(inv_view_projection * bln); + vec3 BLF = project(inv_view_projection * blf); + vec3 TRN = project(inv_view_projection * trn); + vec3 TRF = project(inv_view_projection * trf); + vec3 BRN = project(inv_view_projection * brn); + vec3 BRF = project(inv_view_projection * brf); + vec4 center = inv_view_projection * c; + + vec3 l = normalize(cross(BLF - BLN, TLN - BLN)); + vec3 r = normalize(cross(TRF - TRN, BRN - TRN)); + vec3 n = normalize(cross(BLN - BRN, TRN - BRN)); + vec3 f = normalize(cross(TRF - BRF, BLF - BRF)); + vec3 t = normalize(cross(TLN - TRN, TRF - TRN)); + vec3 b = normalize(cross(BRF - BRN, BLN - BRN)); + + planes[0] = vec4(l, -dot(l, BLN)); + planes[1] = vec4(r, -dot(r, TRN)); + planes[2] = vec4(n, -dot(n, BRN)); + planes[3] = infinite_z ? vec4(0.0f) : vec4(f, -dot(f, BRF)); + planes[4] = vec4(t, -dot(t, TRN)); + planes[5] = vec4(b, -dot(b, BRN)); + + // Winding order checks. + for (auto &p : planes) + if (dot(center, p) < 0.0f) + p = -p; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/frustum.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/frustum.hpp new file mode 100644 index 00000000..b4a7eddb --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/frustum.hpp @@ -0,0 +1,50 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "math.hpp" +#include "aabb.hpp" + +namespace Granite +{ +class Frustum +{ +public: + void build_planes(const mat4& inv_view_projection); + bool intersects_sphere(const AABB &aabb) const; + bool intersects_slow(const AABB &aabb) const; + + vec3 get_coord(float dx, float dy, float dz) const; + + static vec4 get_bounding_sphere(const mat4 &inv_projection, const mat4 &inv_view); + + const vec4 *get_planes() const + { + return planes; + } + +private: + vec4 planes[6]; + mat4 inv_view_projection; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/interpolation.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/interpolation.cpp new file mode 100644 index 00000000..956b5962 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/interpolation.cpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "interpolation.hpp" + +namespace Granite +{ +float catmull_rom_spline(float c0, float c1, float c2, float c3, float phase) +{ + float phase2 = phase * phase; + float phase3 = phase2 * phase; + return c1 + + (c2 - c0) * 0.5f * phase + + (c0 - (2.5f * c1) + (2.0f * c2) - (0.5f * c3)) * phase2 + + ((-0.5f * c0) + (1.5f * c1) - (1.5f * c2) + (0.5f * c3)) * phase3; +} + +// Computes the analytic derivative of the spline dFd(phase). +float catmull_rom_spline_gradient(float c0, float c1, float c2, float c3, float phase) +{ + float phase2 = phase * phase; + return (c2 - c0) * 0.5f + + (c0 - (2.5f * c1) + (2.0f * c2) - (0.5f * c3)) * 2.0f * phase + + ((-0.5f * c0) + (1.5f * c1) - (1.5f * c2) + (0.5f * c3)) * 3.0f * phase2; +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/interpolation.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/interpolation.hpp new file mode 100644 index 00000000..b4718733 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/interpolation.hpp @@ -0,0 +1,29 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +namespace Granite +{ +float catmull_rom_spline(float c0, float c1, float c2, float c3, float phase); +float catmull_rom_spline_gradient(float c0, float c1, float c2, float c3, float phase); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/math.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/math.cpp new file mode 100644 index 00000000..b5ec4952 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/math.cpp @@ -0,0 +1,33 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "math.hpp" +#include "muglm/muglm_impl.hpp" + +namespace Granite +{ +void quantize_color(uint8_t *v, const vec4 &color) +{ + for (unsigned i = 0; i < 4; i++) + v[i] = uint8_t(muglm::round(muglm::clamp(color[i] * 255.0f, 0.0f, 255.0f))); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/math.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/math.hpp new file mode 100644 index 00000000..39b470b5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/math.hpp @@ -0,0 +1,31 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "muglm/muglm.hpp" + +namespace Granite +{ +using namespace muglm; +void quantize_color(uint8_t *v, const vec4 &color); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/matrix_helper.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/matrix_helper.hpp new file mode 100644 index 00000000..9b0b55fd --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/matrix_helper.hpp @@ -0,0 +1,52 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "muglm.hpp" +#include + +namespace muglm +{ +mat4 mat4_cast(const quat &q); +mat_affine mat_affine_cast(const quat &q); +mat3 mat3_cast(const quat &q); +mat4 translate(const vec3 &v); +mat4 scale(const vec3 &v); +mat_affine translate_affine(const vec3 &v); +mat_affine scale_affine(const vec3 &v); +mat2 inverse(const mat2 &m); +mat3 inverse(const mat3 &m); +mat4 inverse(const mat4 &m); + +float determinant(const mat2 &m); +float determinant(const mat3 &m); + +constexpr float InfiniteFarPlane = std::numeric_limits::max(); +mat4 perspective(float fovy, float aspect, float near, float far); +mat4 frustum(float left, float right, float bottom, float top, float near, float far); + +// Orthogonal projection cannot have infinite far-plane. +mat4 ortho(float left, float right, float bottom, float top, float near, float far); + +void decompose(const mat4 &m, vec3 &scale, quat &rot, vec3 &trans); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm.cpp new file mode 100644 index 00000000..a309d650 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm.cpp @@ -0,0 +1,460 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "matrix_helper.hpp" +#include "muglm_impl.hpp" +#include "simd_headers.hpp" + +namespace muglm +{ +mat3 mat3_cast(const quat &q_) +{ + auto &q = q_.as_vec4(); + + mat3 res(1.0f); + float qxx = q.x * q.x; + float qyy = q.y * q.y; + float qzz = q.z * q.z; + float qxz = q.x * q.z; + float qxy = q.x * q.y; + float qyz = q.y * q.z; + float qwx = q.w * q.x; + float qwy = q.w * q.y; + float qwz = q.w * q.z; + + res[0][0] = 1.0f - 2.0f * (qyy + qzz); + res[0][1] = 2.0f * (qxy + qwz); + res[0][2] = 2.0f * (qxz - qwy); + + res[1][0] = 2.0f * (qxy - qwz); + res[1][1] = 1.0f - 2.0f * (qxx + qzz); + res[1][2] = 2.0f * (qyz + qwx); + + res[2][0] = 2.0f * (qxz + qwy); + res[2][1] = 2.0f * (qyz - qwx); + res[2][2] = 1.0f - 2.0f * (qxx + qyy); + + return res; +} + +mat4 mat4_cast(const quat &q) +{ + return mat4(mat3_cast(q)); +} + +mat_affine mat_affine_cast(const quat &q) +{ + return mat_affine(mat3_cast(q)); +} + +mat4 translate(const vec3 &v) +{ + return mat4( + vec4(1.0f, 0.0f, 0.0f, 0.0f), + vec4(0.0f, 1.0f, 0.0f, 0.0f), + vec4(0.0f, 0.0f, 1.0f, 0.0f), + vec4(v, 1.0f)); +} + +mat4 scale(const vec3 &v) +{ + return mat4( + vec4(v.x, 0.0f, 0.0f, 0.0f), + vec4(0.0f, v.y, 0.0f, 0.0f), + vec4(0.0f, 0.0f, v.z, 0.0f), + vec4(0.0f, 0.0f, 0.0f, 1.0f)); +} + +mat_affine translate_affine(const vec3 &v) +{ + return mat_affine( + vec4(1.0f, 0.0f, 0.0f, v.x), + vec4(0.0f, 1.0f, 0.0f, v.y), + vec4(0.0f, 0.0f, 1.0f, v.z)); +} + +mat_affine scale_affine(const vec3 &v) +{ + return mat_affine( + vec4(v.x, 0.0f, 0.0f, 0.0f), + vec4(0.0f, v.y, 0.0f, 0.0f), + vec4(0.0f, 0.0f, v.z, 0.0f)); +} + +float determinant(const mat2 &m) +{ + return m[0][0] * m[1][1] - m[1][0] * m[0][1]; +} + +mat2 inverse(const mat2 &m) +{ + float OneOverDeterminant = 1.0f / determinant(m); + + mat2 Inverse( + vec2(m[1][1] * OneOverDeterminant, + -m[0][1] * OneOverDeterminant), + vec2(-m[1][0] * OneOverDeterminant, + m[0][0] * OneOverDeterminant)); + + return Inverse; +} + +float determinant(const mat3 &m) +{ + return m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); +} + +mat3 inverse(const mat3 &m) +{ + float OneOverDeterminant = 1.0f / determinant(m); + + mat3 Inverse; + Inverse[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDeterminant; + Inverse[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDeterminant; + Inverse[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDeterminant; + Inverse[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDeterminant; + Inverse[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDeterminant; + Inverse[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDeterminant; + Inverse[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDeterminant; + Inverse[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDeterminant; + Inverse[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDeterminant; + + return Inverse; +} + +mat4 inverse(const mat4 &m) +{ + float Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + float Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + float Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + float Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + float Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + float Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + float Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + float Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + float Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + float Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + float Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + float Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + float Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + float Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + float Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + float Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + float Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + float Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + vec4 Fac0(Coef00, Coef00, Coef02, Coef03); + vec4 Fac1(Coef04, Coef04, Coef06, Coef07); + vec4 Fac2(Coef08, Coef08, Coef10, Coef11); + vec4 Fac3(Coef12, Coef12, Coef14, Coef15); + vec4 Fac4(Coef16, Coef16, Coef18, Coef19); + vec4 Fac5(Coef20, Coef20, Coef22, Coef23); + + vec4 Vec0(m[1][0], m[0][0], m[0][0], m[0][0]); + vec4 Vec1(m[1][1], m[0][1], m[0][1], m[0][1]); + vec4 Vec2(m[1][2], m[0][2], m[0][2], m[0][2]); + vec4 Vec3(m[1][3], m[0][3], m[0][3], m[0][3]); + + vec4 Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2); + vec4 Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4); + vec4 Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5); + vec4 Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5); + + vec4 SignA(+1, -1, +1, -1); + vec4 SignB(-1, +1, -1, +1); + mat4 Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB); + + vec4 Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]); + + vec4 Dot0(m[0] * Row0); + float Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w); + + float OneOverDeterminant = 1.0f / Dot1; + + return Inverse * OneOverDeterminant; +} + +void decompose(const mat4 &m, vec3 &scale, quat &rotation, vec3 &trans) +{ + vec4 rot; + + // Make a lot of assumptions. + // We don't need skew, nor perspective. + + // Isolate translation. + trans = m[3].xyz(); + + vec3 cols[3]; + cols[0] = m[0].xyz(); + cols[1] = m[1].xyz(); + cols[2] = m[2].xyz(); + + scale.x = length(cols[0]); + scale.y = length(cols[1]); + scale.z = length(cols[2]); + + // Isolate scale. + cols[0] /= scale.x; + cols[1] /= scale.y; + cols[2] /= scale.z; + + vec3 pdum3 = cross(cols[1], cols[2]); + if (dot(cols[0], pdum3) < 0.0f) + { + scale = -scale; + cols[0] = -cols[0]; + cols[1] = -cols[1]; + cols[2] = -cols[2]; + } + + int i, j, k = 0; + float root, trace = cols[0].x + cols[1].y + cols[2].z; + if (trace > 0.0f) + { + root = sqrt(trace + 1.0f); + rot.w = 0.5f * root; + root = 0.5f / root; + rot.x = root * (cols[1].z - cols[2].y); + rot.y = root * (cols[2].x - cols[0].z); + rot.z = root * (cols[0].y - cols[1].x); + } + else + { + static const int Next[3] = {1, 2, 0}; + + i = 0; + if (cols[1].y > cols[0].x) i = 1; + if (cols[2].z > cols[i][i]) i = 2; + + j = Next[i]; + k = Next[j]; + + root = sqrt(cols[i][i] - cols[j][j] - cols[k][k] + 1.0f); + + rot[i] = 0.5f * root; + root = 0.5f / root; + rot[j] = root * (cols[i][j] + cols[j][i]); + rot[k] = root * (cols[i][k] + cols[k][i]); + rot.w = root * (cols[j][k] - cols[k][j]); + } + + rotation = quat(rot); +} + +mat4 ortho(float left, float right, float bottom, float top, float near, float far) +{ + mat4 result(1.0f); + result[0][0] = 2.0f / (right - left); + result[1][1] = 2.0f / (top - bottom); + result[3][0] = -(right + left) / (right - left); + result[3][1] = -(top + bottom) / (top - bottom); + + result[2][2] = 1.0f / (far - near); + result[3][2] = 1.0f + near / (far - near); + + result[0].y *= -1.0f; + result[1].y *= -1.0f; + result[2].y *= -1.0f; + result[3].y *= -1.0f; + + return result; +} + +mat4 frustum(float left, float right, float bottom, float top, float near, float far) +{ + mat4 result(0.0f); + result[0][0] = (2.0f * near) / (right - left); + result[1][1] = (2.0f * near) / (top - bottom); + result[2][0] = (right + left) / (right - left); + result[2][1] = (top + bottom) / (top - bottom); + + // Inverse Z + if (far == InfiniteFarPlane) + { + result[3][2] = -near; + } + else + { + result[2][2] = -1.0f - far / (near - far); + result[3][2] = -(far * near) / (near - far); + } + + result[2][3] = -1.0f; + + // Y-flip so we don't have to bother with negative viewport heights. + result[0].y *= -1.0f; + result[1].y *= -1.0f; + result[2].y *= -1.0f; + result[3].y *= -1.0f; + + return result; +} + +mat4 perspective(float fovy, float aspect, float near, float far) +{ + float tanHalfFovy = tan(fovy / 2.0f); + + mat4 result(0.0f); + result[0][0] = 1.0f / (aspect * tanHalfFovy); + result[1][1] = 1.0f / (tanHalfFovy); + + // Inverse Z + if (far == InfiniteFarPlane) + { + result[3][2] = near; + } + else + { + result[2][2] = -1.0f - far / (near - far); + result[3][2] = -(far * near) / (near - far); + } + + result[2][3] = -1.0f; + + // Y-flip so we don't have to bother with negative viewport heights. + result[0].y *= -1.0f; + result[1].y *= -1.0f; + result[2].y *= -1.0f; + result[3].y *= -1.0f; + + return result; +} + +void transpose(mat4 &dst, const mat4 &src) +{ +#if __SSE__ + __m128 r0 = _mm_loadu_ps(src[0].data); + __m128 r1 = _mm_loadu_ps(src[1].data); + __m128 r2 = _mm_loadu_ps(src[2].data); + __m128 r3 = _mm_loadu_ps(src[3].data); + _MM_TRANSPOSE4_PS(r0, r1, r2, r3); + _mm_storeu_ps(dst[0].data, r0); + _mm_storeu_ps(dst[1].data, r1); + _mm_storeu_ps(dst[2].data, r2); + _mm_storeu_ps(dst[3].data, r3); +#elif defined(__ARM_NEON) + float32x4x4_t a = vld4q_f32(src[0].data); + vst1q_f32(dst[0].data, a.val[0]); + vst1q_f32(dst[1].data, a.val[1]); + vst1q_f32(dst[2].data, a.val[2]); + vst1q_f32(dst[3].data, a.val[3]); +#else + dst = transpose(src); +#endif +} + +void transpose_to_affine(vec4 dst[3], const mat4 &src) +{ +#if __SSE__ + __m128 r0 = _mm_loadu_ps(src[0].data); + __m128 r1 = _mm_loadu_ps(src[1].data); + __m128 r2 = _mm_loadu_ps(src[2].data); + __m128 r3 = _mm_loadu_ps(src[3].data); + _MM_TRANSPOSE4_PS(r0, r1, r2, r3); + _mm_storeu_ps(dst[0].data, r0); + _mm_storeu_ps(dst[1].data, r1); + _mm_storeu_ps(dst[2].data, r2); +#elif defined(__ARM_NEON) + float32x4x4_t a = vld4q_f32(src[0].data); + vst1q_f32(dst[0].data, a.val[0]); + vst1q_f32(dst[1].data, a.val[1]); + vst1q_f32(dst[2].data, a.val[2]); +#else + mat4 m = transpose(src); + for (int i = 0; i < 3; i++) + dst[i] = m[i]; +#endif +} + +void transpose_from_affine(mat4 &dst, const vec4 src[3]) +{ +#if __SSE__ + __m128 r0 = _mm_loadu_ps(src[0].data); + __m128 r1 = _mm_loadu_ps(src[1].data); + __m128 r2 = _mm_loadu_ps(src[2].data); + __m128 r3 = _mm_set_ps(1, 0, 0, 0); + _MM_TRANSPOSE4_PS(r0, r1, r2, r3); + _mm_storeu_ps(dst[0].data, r0); + _mm_storeu_ps(dst[1].data, r1); + _mm_storeu_ps(dst[2].data, r2); + _mm_storeu_ps(dst[3].data, r3); +#elif defined(__ARM_NEON) + alignas(16) static const float r3_data[] = { 0, 0, 0, 1 }; + float32x4_t r0 = vld1q_f32(src[0].data); + float32x4_t r1 = vld1q_f32(src[1].data); + float32x4_t r2 = vld1q_f32(src[2].data); + float32x4_t r3 = vld1q_f32(r3_data); + float32x4x4_t r = { r0, r1, r2, r3 }; + vst4q_f32(dst[0].data, r); +#else + mat4 m = transpose(src); + for (int i = 0; i < 3; i++) + dst[i] = m[i]; +#endif +} + +void mat_affine::to_mat4(muglm::mat4 &m) const +{ + transpose_from_affine(m, vec); +} + +mat4 mat_affine::to_mat4() const +{ + mat4 m; + to_mat4(m); + return m; +} + +float mat_affine::get_uniform_scale() const +{ + return length(vec[0].xyz()); +} + +vec3 mat_affine::get_translation() const +{ + // this * vec4(0, 0, 0, 1) + return { vec[0].w, vec[1].w, vec[2].w }; +} + +vec3 mat_affine::get_forward() const +{ + // this * vec4(0, 0, -1, 0). + return { -vec[0].z, -vec[1].z, -vec[2].z }; +} + +vec3 mat_affine::get_right() const +{ + return { vec[0].x, vec[1].x, vec[2].x }; +} + +vec3 mat_affine::get_up() const +{ + return { vec[0].y, vec[1].y, vec[2].y }; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm.hpp new file mode 100644 index 00000000..5a0c5aff --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm.hpp @@ -0,0 +1,993 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include + +namespace muglm +{ +template struct tvec2; +template struct tvec3; +template struct tvec4; +template struct tmat2; +template struct tmat3; +template struct tmat4; + +template +struct tvec2 +{ + tvec2() = default; + tvec2(const tvec2 &) = default; + tvec2 &operator=(const tvec2 &) = default; + + explicit inline tvec2(T v) noexcept + { + x = v; + y = v; + } + + template + explicit inline tvec2(const tvec2 &u) noexcept + { + x = T(u.x); + y = T(u.y); + } + + inline tvec2(T x_, T y_) noexcept + { + x = x_; + y = y_; + } + + union + { + T data[2]; + struct + { + T x, y; + }; + }; + + inline T &operator[](size_t index) + { + return data[index]; + } + + inline const T &operator[](size_t index) const + { + return data[index]; + } + + inline tvec2 xx() const; + inline tvec2 xy() const; + inline tvec2 yx() const; + inline tvec2 yy() const; + + inline tvec3 xxx() const; + inline tvec3 xxy() const; + inline tvec3 xyx() const; + inline tvec3 xyy() const; + inline tvec3 yxx() const; + inline tvec3 yxy() const; + inline tvec3 yyx() const; + inline tvec3 yyy() const; + + inline tvec4 xxxx() const; + inline tvec4 xxxy() const; + inline tvec4 xxyx() const; + inline tvec4 xxyy() const; + inline tvec4 xyxx() const; + inline tvec4 xyxy() const; + inline tvec4 xyyx() const; + inline tvec4 xyyy() const; + inline tvec4 yxxx() const; + inline tvec4 yxxy() const; + inline tvec4 yxyx() const; + inline tvec4 yxyy() const; + inline tvec4 yyxx() const; + inline tvec4 yyxy() const; + inline tvec4 yyyx() const; + inline tvec4 yyyy() const; +}; + +template +struct tvec3 +{ + tvec3() = default; + tvec3(const tvec3 &) = default; + tvec3 &operator=(const tvec3 &) = default; + + template + explicit inline tvec3(const tvec3 &u) noexcept + { + x = T(u.x); + y = T(u.y); + z = T(u.z); + } + + inline tvec3(const tvec2 &a, T b) noexcept + { + x = a.x; + y = a.y; + z = b; + } + + inline tvec3(T a, const tvec2 &b) noexcept + { + x = a; + y = b.x; + z = b.y; + } + + explicit inline tvec3(T v) noexcept + { + x = v; + y = v; + z = v; + } + + inline tvec3(T x_, T y_, T z_) noexcept + { + x = x_; + y = y_; + z = z_; + } + + union + { + T data[3]; + struct + { + T x, y, z; + }; + }; + + inline T &operator[](size_t index) + { + return data[index]; + } + + inline const T &operator[](size_t index) const + { + return data[index]; + } + + inline tvec2 xx() const; + inline tvec2 xy() const; + inline tvec2 xz() const; + inline tvec2 yx() const; + inline tvec2 yy() const; + inline tvec2 yz() const; + inline tvec2 zx() const; + inline tvec2 zy() const; + inline tvec2 zz() const; + + inline tvec3 xxx() const; + inline tvec3 xxy() const; + inline tvec3 xxz() const; + inline tvec3 xyx() const; + inline tvec3 xyy() const; + inline tvec3 xyz() const; + inline tvec3 xzx() const; + inline tvec3 xzy() const; + inline tvec3 xzz() const; + inline tvec3 yxx() const; + inline tvec3 yxy() const; + inline tvec3 yxz() const; + inline tvec3 yyx() const; + inline tvec3 yyy() const; + inline tvec3 yyz() const; + inline tvec3 yzx() const; + inline tvec3 yzy() const; + inline tvec3 yzz() const; + inline tvec3 zxx() const; + inline tvec3 zxy() const; + inline tvec3 zxz() const; + inline tvec3 zyx() const; + inline tvec3 zyy() const; + inline tvec3 zyz() const; + inline tvec3 zzx() const; + inline tvec3 zzy() const; + inline tvec3 zzz() const; + + inline tvec4 xxxx() const; + inline tvec4 xxxy() const; + inline tvec4 xxxz() const; + inline tvec4 xxyx() const; + inline tvec4 xxyy() const; + inline tvec4 xxyz() const; + inline tvec4 xxzx() const; + inline tvec4 xxzy() const; + inline tvec4 xxzz() const; + inline tvec4 xyxx() const; + inline tvec4 xyxy() const; + inline tvec4 xyxz() const; + inline tvec4 xyyx() const; + inline tvec4 xyyy() const; + inline tvec4 xyyz() const; + inline tvec4 xyzx() const; + inline tvec4 xyzy() const; + inline tvec4 xyzz() const; + inline tvec4 xzxx() const; + inline tvec4 xzxy() const; + inline tvec4 xzxz() const; + inline tvec4 xzyx() const; + inline tvec4 xzyy() const; + inline tvec4 xzyz() const; + inline tvec4 xzzx() const; + inline tvec4 xzzy() const; + inline tvec4 xzzz() const; + inline tvec4 yxxx() const; + inline tvec4 yxxy() const; + inline tvec4 yxxz() const; + inline tvec4 yxyx() const; + inline tvec4 yxyy() const; + inline tvec4 yxyz() const; + inline tvec4 yxzx() const; + inline tvec4 yxzy() const; + inline tvec4 yxzz() const; + inline tvec4 yyxx() const; + inline tvec4 yyxy() const; + inline tvec4 yyxz() const; + inline tvec4 yyyx() const; + inline tvec4 yyyy() const; + inline tvec4 yyyz() const; + inline tvec4 yyzx() const; + inline tvec4 yyzy() const; + inline tvec4 yyzz() const; + inline tvec4 yzxx() const; + inline tvec4 yzxy() const; + inline tvec4 yzxz() const; + inline tvec4 yzyx() const; + inline tvec4 yzyy() const; + inline tvec4 yzyz() const; + inline tvec4 yzzx() const; + inline tvec4 yzzy() const; + inline tvec4 yzzz() const; + inline tvec4 zxxx() const; + inline tvec4 zxxy() const; + inline tvec4 zxxz() const; + inline tvec4 zxyx() const; + inline tvec4 zxyy() const; + inline tvec4 zxyz() const; + inline tvec4 zxzx() const; + inline tvec4 zxzy() const; + inline tvec4 zxzz() const; + inline tvec4 zyxx() const; + inline tvec4 zyxy() const; + inline tvec4 zyxz() const; + inline tvec4 zyyx() const; + inline tvec4 zyyy() const; + inline tvec4 zyyz() const; + inline tvec4 zyzx() const; + inline tvec4 zyzy() const; + inline tvec4 zyzz() const; + inline tvec4 zzxx() const; + inline tvec4 zzxy() const; + inline tvec4 zzxz() const; + inline tvec4 zzyx() const; + inline tvec4 zzyy() const; + inline tvec4 zzyz() const; + inline tvec4 zzzx() const; + inline tvec4 zzzy() const; + inline tvec4 zzzz() const; +}; + +template +struct tvec4 +{ + tvec4() = default; + tvec4(const tvec4 &) = default; + tvec4 &operator=(const tvec4 &) = default; + + template + explicit inline tvec4(const tvec4 &u) noexcept + { + x = T(u.x); + y = T(u.y); + z = T(u.z); + w = T(u.w); + } + + inline tvec4(const tvec2 &a, const tvec2 &b) noexcept + { + x = a.x; + y = a.y; + z = b.x; + w = b.y; + } + + inline tvec4(const tvec3 &a, T b) noexcept + { + x = a.x; + y = a.y; + z = a.z; + w = b; + } + + inline tvec4(T a, const tvec3 &b) noexcept + { + x = a; + y = b.x; + z = b.y; + w = b.z; + } + + inline tvec4(const tvec2 &a, T b, T c) noexcept + { + x = a.x; + y = a.y; + z = b; + w = c; + } + + inline tvec4(T a, const tvec2 &b, T c) noexcept + { + x = a; + y = b.x; + z = b.y; + w = c; + } + + inline tvec4(T a, T b, const tvec2 &c) noexcept + { + x = a; + y = b; + z = c.x; + w = c.y; + } + + explicit inline tvec4(T v) noexcept + { + x = v; + y = v; + z = v; + w = v; + } + + inline tvec4(T x_, T y_, T z_, T w_) noexcept + { + x = x_; + y = y_; + z = z_; + w = w_; + } + + inline T &operator[](size_t index) + { + return data[index]; + } + + inline const T &operator[](size_t index) const + { + return data[index]; + } + + union + { + T data[4]; + struct + { + T x, y, z, w; + }; + }; + + inline tvec2 xx() const; + inline tvec2 xy() const; + inline tvec2 xz() const; + inline tvec2 xw() const; + inline tvec2 yx() const; + inline tvec2 yy() const; + inline tvec2 yz() const; + inline tvec2 yw() const; + inline tvec2 zx() const; + inline tvec2 zy() const; + inline tvec2 zz() const; + inline tvec2 zw() const; + inline tvec2 wx() const; + inline tvec2 wy() const; + inline tvec2 wz() const; + inline tvec2 ww() const; + + inline tvec3 xxx() const; + inline tvec3 xxy() const; + inline tvec3 xxz() const; + inline tvec3 xxw() const; + inline tvec3 xyx() const; + inline tvec3 xyy() const; + inline tvec3 xyz() const; + inline tvec3 xyw() const; + inline tvec3 xzx() const; + inline tvec3 xzy() const; + inline tvec3 xzz() const; + inline tvec3 xzw() const; + inline tvec3 xwx() const; + inline tvec3 xwy() const; + inline tvec3 xwz() const; + inline tvec3 xww() const; + inline tvec3 yxx() const; + inline tvec3 yxy() const; + inline tvec3 yxz() const; + inline tvec3 yxw() const; + inline tvec3 yyx() const; + inline tvec3 yyy() const; + inline tvec3 yyz() const; + inline tvec3 yyw() const; + inline tvec3 yzx() const; + inline tvec3 yzy() const; + inline tvec3 yzz() const; + inline tvec3 yzw() const; + inline tvec3 ywx() const; + inline tvec3 ywy() const; + inline tvec3 ywz() const; + inline tvec3 yww() const; + inline tvec3 zxx() const; + inline tvec3 zxy() const; + inline tvec3 zxz() const; + inline tvec3 zxw() const; + inline tvec3 zyx() const; + inline tvec3 zyy() const; + inline tvec3 zyz() const; + inline tvec3 zyw() const; + inline tvec3 zzx() const; + inline tvec3 zzy() const; + inline tvec3 zzz() const; + inline tvec3 zzw() const; + inline tvec3 zwx() const; + inline tvec3 zwy() const; + inline tvec3 zwz() const; + inline tvec3 zww() const; + inline tvec3 wxx() const; + inline tvec3 wxy() const; + inline tvec3 wxz() const; + inline tvec3 wxw() const; + inline tvec3 wyx() const; + inline tvec3 wyy() const; + inline tvec3 wyz() const; + inline tvec3 wyw() const; + inline tvec3 wzx() const; + inline tvec3 wzy() const; + inline tvec3 wzz() const; + inline tvec3 wzw() const; + inline tvec3 wwx() const; + inline tvec3 wwy() const; + inline tvec3 wwz() const; + inline tvec3 www() const; + + inline tvec4 xxxx() const; + inline tvec4 xxxy() const; + inline tvec4 xxxz() const; + inline tvec4 xxxw() const; + inline tvec4 xxyx() const; + inline tvec4 xxyy() const; + inline tvec4 xxyz() const; + inline tvec4 xxyw() const; + inline tvec4 xxzx() const; + inline tvec4 xxzy() const; + inline tvec4 xxzz() const; + inline tvec4 xxzw() const; + inline tvec4 xxwx() const; + inline tvec4 xxwy() const; + inline tvec4 xxwz() const; + inline tvec4 xxww() const; + inline tvec4 xyxx() const; + inline tvec4 xyxy() const; + inline tvec4 xyxz() const; + inline tvec4 xyxw() const; + inline tvec4 xyyx() const; + inline tvec4 xyyy() const; + inline tvec4 xyyz() const; + inline tvec4 xyyw() const; + inline tvec4 xyzx() const; + inline tvec4 xyzy() const; + inline tvec4 xyzz() const; + inline tvec4 xyzw() const; + inline tvec4 xywx() const; + inline tvec4 xywy() const; + inline tvec4 xywz() const; + inline tvec4 xyww() const; + inline tvec4 xzxx() const; + inline tvec4 xzxy() const; + inline tvec4 xzxz() const; + inline tvec4 xzxw() const; + inline tvec4 xzyx() const; + inline tvec4 xzyy() const; + inline tvec4 xzyz() const; + inline tvec4 xzyw() const; + inline tvec4 xzzx() const; + inline tvec4 xzzy() const; + inline tvec4 xzzz() const; + inline tvec4 xzzw() const; + inline tvec4 xzwx() const; + inline tvec4 xzwy() const; + inline tvec4 xzwz() const; + inline tvec4 xzww() const; + inline tvec4 xwxx() const; + inline tvec4 xwxy() const; + inline tvec4 xwxz() const; + inline tvec4 xwxw() const; + inline tvec4 xwyx() const; + inline tvec4 xwyy() const; + inline tvec4 xwyz() const; + inline tvec4 xwyw() const; + inline tvec4 xwzx() const; + inline tvec4 xwzy() const; + inline tvec4 xwzz() const; + inline tvec4 xwzw() const; + inline tvec4 xwwx() const; + inline tvec4 xwwy() const; + inline tvec4 xwwz() const; + inline tvec4 xwww() const; + inline tvec4 yxxx() const; + inline tvec4 yxxy() const; + inline tvec4 yxxz() const; + inline tvec4 yxxw() const; + inline tvec4 yxyx() const; + inline tvec4 yxyy() const; + inline tvec4 yxyz() const; + inline tvec4 yxyw() const; + inline tvec4 yxzx() const; + inline tvec4 yxzy() const; + inline tvec4 yxzz() const; + inline tvec4 yxzw() const; + inline tvec4 yxwx() const; + inline tvec4 yxwy() const; + inline tvec4 yxwz() const; + inline tvec4 yxww() const; + inline tvec4 yyxx() const; + inline tvec4 yyxy() const; + inline tvec4 yyxz() const; + inline tvec4 yyxw() const; + inline tvec4 yyyx() const; + inline tvec4 yyyy() const; + inline tvec4 yyyz() const; + inline tvec4 yyyw() const; + inline tvec4 yyzx() const; + inline tvec4 yyzy() const; + inline tvec4 yyzz() const; + inline tvec4 yyzw() const; + inline tvec4 yywx() const; + inline tvec4 yywy() const; + inline tvec4 yywz() const; + inline tvec4 yyww() const; + inline tvec4 yzxx() const; + inline tvec4 yzxy() const; + inline tvec4 yzxz() const; + inline tvec4 yzxw() const; + inline tvec4 yzyx() const; + inline tvec4 yzyy() const; + inline tvec4 yzyz() const; + inline tvec4 yzyw() const; + inline tvec4 yzzx() const; + inline tvec4 yzzy() const; + inline tvec4 yzzz() const; + inline tvec4 yzzw() const; + inline tvec4 yzwx() const; + inline tvec4 yzwy() const; + inline tvec4 yzwz() const; + inline tvec4 yzww() const; + inline tvec4 ywxx() const; + inline tvec4 ywxy() const; + inline tvec4 ywxz() const; + inline tvec4 ywxw() const; + inline tvec4 ywyx() const; + inline tvec4 ywyy() const; + inline tvec4 ywyz() const; + inline tvec4 ywyw() const; + inline tvec4 ywzx() const; + inline tvec4 ywzy() const; + inline tvec4 ywzz() const; + inline tvec4 ywzw() const; + inline tvec4 ywwx() const; + inline tvec4 ywwy() const; + inline tvec4 ywwz() const; + inline tvec4 ywww() const; + inline tvec4 zxxx() const; + inline tvec4 zxxy() const; + inline tvec4 zxxz() const; + inline tvec4 zxxw() const; + inline tvec4 zxyx() const; + inline tvec4 zxyy() const; + inline tvec4 zxyz() const; + inline tvec4 zxyw() const; + inline tvec4 zxzx() const; + inline tvec4 zxzy() const; + inline tvec4 zxzz() const; + inline tvec4 zxzw() const; + inline tvec4 zxwx() const; + inline tvec4 zxwy() const; + inline tvec4 zxwz() const; + inline tvec4 zxww() const; + inline tvec4 zyxx() const; + inline tvec4 zyxy() const; + inline tvec4 zyxz() const; + inline tvec4 zyxw() const; + inline tvec4 zyyx() const; + inline tvec4 zyyy() const; + inline tvec4 zyyz() const; + inline tvec4 zyyw() const; + inline tvec4 zyzx() const; + inline tvec4 zyzy() const; + inline tvec4 zyzz() const; + inline tvec4 zyzw() const; + inline tvec4 zywx() const; + inline tvec4 zywy() const; + inline tvec4 zywz() const; + inline tvec4 zyww() const; + inline tvec4 zzxx() const; + inline tvec4 zzxy() const; + inline tvec4 zzxz() const; + inline tvec4 zzxw() const; + inline tvec4 zzyx() const; + inline tvec4 zzyy() const; + inline tvec4 zzyz() const; + inline tvec4 zzyw() const; + inline tvec4 zzzx() const; + inline tvec4 zzzy() const; + inline tvec4 zzzz() const; + inline tvec4 zzzw() const; + inline tvec4 zzwx() const; + inline tvec4 zzwy() const; + inline tvec4 zzwz() const; + inline tvec4 zzww() const; + inline tvec4 zwxx() const; + inline tvec4 zwxy() const; + inline tvec4 zwxz() const; + inline tvec4 zwxw() const; + inline tvec4 zwyx() const; + inline tvec4 zwyy() const; + inline tvec4 zwyz() const; + inline tvec4 zwyw() const; + inline tvec4 zwzx() const; + inline tvec4 zwzy() const; + inline tvec4 zwzz() const; + inline tvec4 zwzw() const; + inline tvec4 zwwx() const; + inline tvec4 zwwy() const; + inline tvec4 zwwz() const; + inline tvec4 zwww() const; + inline tvec4 wxxx() const; + inline tvec4 wxxy() const; + inline tvec4 wxxz() const; + inline tvec4 wxxw() const; + inline tvec4 wxyx() const; + inline tvec4 wxyy() const; + inline tvec4 wxyz() const; + inline tvec4 wxyw() const; + inline tvec4 wxzx() const; + inline tvec4 wxzy() const; + inline tvec4 wxzz() const; + inline tvec4 wxzw() const; + inline tvec4 wxwx() const; + inline tvec4 wxwy() const; + inline tvec4 wxwz() const; + inline tvec4 wxww() const; + inline tvec4 wyxx() const; + inline tvec4 wyxy() const; + inline tvec4 wyxz() const; + inline tvec4 wyxw() const; + inline tvec4 wyyx() const; + inline tvec4 wyyy() const; + inline tvec4 wyyz() const; + inline tvec4 wyyw() const; + inline tvec4 wyzx() const; + inline tvec4 wyzy() const; + inline tvec4 wyzz() const; + inline tvec4 wyzw() const; + inline tvec4 wywx() const; + inline tvec4 wywy() const; + inline tvec4 wywz() const; + inline tvec4 wyww() const; + inline tvec4 wzxx() const; + inline tvec4 wzxy() const; + inline tvec4 wzxz() const; + inline tvec4 wzxw() const; + inline tvec4 wzyx() const; + inline tvec4 wzyy() const; + inline tvec4 wzyz() const; + inline tvec4 wzyw() const; + inline tvec4 wzzx() const; + inline tvec4 wzzy() const; + inline tvec4 wzzz() const; + inline tvec4 wzzw() const; + inline tvec4 wzwx() const; + inline tvec4 wzwy() const; + inline tvec4 wzwz() const; + inline tvec4 wzww() const; + inline tvec4 wwxx() const; + inline tvec4 wwxy() const; + inline tvec4 wwxz() const; + inline tvec4 wwxw() const; + inline tvec4 wwyx() const; + inline tvec4 wwyy() const; + inline tvec4 wwyz() const; + inline tvec4 wwyw() const; + inline tvec4 wwzx() const; + inline tvec4 wwzy() const; + inline tvec4 wwzz() const; + inline tvec4 wwzw() const; + inline tvec4 wwwx() const; + inline tvec4 wwwy() const; + inline tvec4 wwwz() const; + inline tvec4 wwww() const; +}; + +template +struct tmat2 +{ + tmat2() = default; + tmat2(const tmat2 &) = default; + tmat2 &operator=(const tmat2 &) = default; + + explicit inline tmat2(T v) noexcept + { + vec[0] = tvec2(v, T(0)); + vec[1] = tvec2(T(0), v); + } + + inline tmat2(const tvec2 &a, const tvec2 &b) noexcept + { + vec[0] = a; + vec[1] = b; + } + + inline tvec2 &operator[](size_t index) + { + return vec[index]; + } + + inline const tvec2 &operator[](size_t index) const + { + return vec[index]; + } + +private: + tvec2 vec[2]; +}; + +template +struct tmat3 +{ + tmat3() = default; + tmat3(const tmat3 &) = default; + tmat3 &operator=(const tmat3 &) = default; + + explicit inline tmat3(T v) noexcept + { + vec[0] = tvec3(v, T(0), T(0)); + vec[1] = tvec3(T(0), v, T(0)); + vec[2] = tvec3(T(0), T(0), v); + } + + inline tmat3(const tvec3 &a, const tvec3 &b, const tvec3 &c) noexcept + { + vec[0] = a; + vec[1] = b; + vec[2] = c; + } + + explicit inline tmat3(const tmat4 &m) noexcept + { + for (int col = 0; col < 3; col++) + for (int row = 0; row < 3; row++) + vec[col][row] = m[col][row]; + } + + inline tvec3 &operator[](size_t index) + { + return vec[index]; + } + + inline const tvec3 &operator[](size_t index) const + { + return vec[index]; + } + +private: + tvec3 vec[3]; +}; + +template +struct tmat4 +{ + tmat4() = default; + tmat4(const tmat4 &) = default; + tmat4 &operator=(const tmat4 &) = default; + + explicit inline tmat4(T v) noexcept + { + vec[0] = tvec4(v, T(0), T(0), T(0)); + vec[1] = tvec4(T(0), v, T(0), T(0)); + vec[2] = tvec4(T(0), T(0), v, T(0)); + vec[3] = tvec4(T(0), T(0), T(0), v); + } + + explicit inline tmat4(const tmat3 &m) noexcept + { + vec[0] = tvec4(m[0], T(0)); + vec[1] = tvec4(m[1], T(0)); + vec[2] = tvec4(m[2], T(0)); + vec[3] = tvec4(T(0), T(0), T(0), T(1)); + } + + inline tmat4(const tvec4 &a, const tvec4 &b, const tvec4 &c, const tvec4 &d) noexcept + { + vec[0] = a; + vec[1] = b; + vec[2] = c; + vec[3] = d; + } + + inline tvec4 &operator[](size_t index) + { + return vec[index]; + } + + inline const tvec4 &operator[](size_t index) const + { + return vec[index]; + } + +private: + tvec4 vec[4]; +}; + +using uint = uint32_t; +using vec2 = tvec2; +using vec3 = tvec3; +using vec4 = tvec4; +using mat2 = tmat2; +using mat3 = tmat3; +using mat4 = tmat4; + +using dvec2 = tvec2; +using dvec3 = tvec3; +using dvec4 = tvec4; +using dmat2 = tmat2; +using dmat3 = tmat3; +using dmat4 = tmat4; + +using ivec2 = tvec2; +using ivec3 = tvec3; +using ivec4 = tvec4; +using uvec2 = tvec2; +using uvec3 = tvec3; +using uvec4 = tvec4; + +using u16vec2 = tvec2; +using u16vec3 = tvec3; +using u16vec4 = tvec4; +using i16vec2 = tvec2; +using i16vec3 = tvec3; +using i16vec4 = tvec4; + +using u8vec2 = tvec2; +using u8vec3 = tvec3; +using u8vec4 = tvec4; +using i8vec2 = tvec2; +using i8vec3 = tvec3; +using i8vec4 = tvec4; + +using bvec2 = tvec2; +using bvec3 = tvec3; +using bvec4 = tvec4; + +void transpose(mat4 &dst, const mat4 &src); +void transpose_to_affine(vec4 dst[3], const mat4 &src); + +struct mat_affine +{ + mat_affine() = default; + mat_affine(const mat_affine &) = default; + mat_affine &operator=(const mat_affine &) = default; + + explicit inline mat_affine(const mat4 &m) + { + transpose_to_affine(vec, m); + } + + explicit inline mat_affine(const mat3 &m) + : vec{{m[0][0], m[1][0], m[2][0], 0.0f}, + {m[0][1], m[1][1], m[2][1], 0.0f}, + {m[0][2], m[1][2], m[2][2], 0.0f}} + { + } + + explicit inline mat_affine(float v) + : vec{{v, 0, 0, 0}, {0, v, 0, 0}, {0, 0, v, 0}} + { + } + + inline mat_affine(const vec4 &r0, const vec4 &r1, const vec4 &r2) + : vec{r0, r1, r2} + { + } + + inline vec4 &operator[](size_t index) + { + return vec[index]; + } + + inline const vec4 &operator[](size_t index) const + { + return vec[index]; + } + + float get_uniform_scale() const; + vec3 get_translation() const; + // Based on identity view pointing to -Z axis, Y up. + vec3 get_forward() const; + vec3 get_right() const; + vec3 get_up() const; + + mat4 to_mat4() const; + void to_mat4(mat4 &m) const; + + inline mat3 to_mat3() const + { + return { + vec3(vec[0][0], vec[1][0], vec[2][0]), + vec3(vec[0][1], vec[1][1], vec[2][1]), + vec3(vec[0][2], vec[1][2], vec[2][2]), + }; + } + +private: + vec4 vec[3]; +}; + +struct quat : private vec4 +{ + quat() = default; + quat(const quat &) = default; + quat(float w_, float x_, float y_, float z_) + : vec4(x_, y_, z_, w_) + {} + + explicit inline quat(const vec4 &v) + : vec4(v) + {} + + inline quat(float w_, const vec3 &v_) + : vec4(v_, w_) + {} + + inline const vec4 &as_vec4() const + { + return *static_cast(this); + } + + quat &operator=(const quat &) = default; + + using vec4::x; + using vec4::y; + using vec4::z; + using vec4::w; +}; + +template constexpr inline T pi() { return T(3.1415926535897932384626433832795028841971); } +template constexpr inline T half_pi() { return T(0.5) * pi(); } +template constexpr inline T one_over_root_two() { return T(0.7071067811865476); } + +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm_impl.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm_impl.hpp new file mode 100644 index 00000000..0c6448ae --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm_impl.hpp @@ -0,0 +1,1037 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "muglm.hpp" +#include + +namespace muglm +{ +#define MUGLM_IMPL_SWIZZLE(ret_type, self_type, swiz, ...) template t##ret_type t##self_type::swiz() const { return t##ret_type(__VA_ARGS__); } + +// vec2 +MUGLM_IMPL_SWIZZLE(vec2, vec2, xx, x, x) +MUGLM_IMPL_SWIZZLE(vec2, vec2, xy, x, y) +MUGLM_IMPL_SWIZZLE(vec2, vec2, yx, y, x) +MUGLM_IMPL_SWIZZLE(vec2, vec2, yy, y, y) + +MUGLM_IMPL_SWIZZLE(vec3, vec2, xxx, x, x, x) +MUGLM_IMPL_SWIZZLE(vec3, vec2, xxy, x, x, y) +MUGLM_IMPL_SWIZZLE(vec3, vec2, xyx, x, y, x) +MUGLM_IMPL_SWIZZLE(vec3, vec2, xyy, x, y, y) +MUGLM_IMPL_SWIZZLE(vec3, vec2, yxx, y, x, x) +MUGLM_IMPL_SWIZZLE(vec3, vec2, yxy, y, x, y) +MUGLM_IMPL_SWIZZLE(vec3, vec2, yyx, y, y, x) +MUGLM_IMPL_SWIZZLE(vec3, vec2, yyy, y, y, y) + +MUGLM_IMPL_SWIZZLE(vec4, vec2, xxxx, x, x, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec2, xxxy, x, x, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec2, xxyx, x, x, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec2, xxyy, x, x, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec2, xyxx, x, y, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec2, xyxy, x, y, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec2, xyyx, x, y, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec2, xyyy, x, y, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec2, yxxx, y, x, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec2, yxxy, y, x, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec2, yxyx, y, x, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec2, yxyy, y, x, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec2, yyxx, y, y, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec2, yyxy, y, y, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec2, yyyx, y, y, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec2, yyyy, y, y, y, y) + +// vec3 +MUGLM_IMPL_SWIZZLE(vec2, vec3, xx, x, x) +MUGLM_IMPL_SWIZZLE(vec2, vec3, xy, x, y) +MUGLM_IMPL_SWIZZLE(vec2, vec3, xz, x, z) +MUGLM_IMPL_SWIZZLE(vec2, vec3, yx, y, x) +MUGLM_IMPL_SWIZZLE(vec2, vec3, yy, y, y) +MUGLM_IMPL_SWIZZLE(vec2, vec3, yz, y, z) +MUGLM_IMPL_SWIZZLE(vec2, vec3, zx, z, x) +MUGLM_IMPL_SWIZZLE(vec2, vec3, zy, z, y) +MUGLM_IMPL_SWIZZLE(vec2, vec3, zz, z, z) + +MUGLM_IMPL_SWIZZLE(vec3, vec3, xxx, x, x, x) +MUGLM_IMPL_SWIZZLE(vec3, vec3, xxy, x, x, y) +MUGLM_IMPL_SWIZZLE(vec3, vec3, xxz, x, x, z) +MUGLM_IMPL_SWIZZLE(vec3, vec3, xyx, x, y, x) +MUGLM_IMPL_SWIZZLE(vec3, vec3, xyy, x, y, y) +MUGLM_IMPL_SWIZZLE(vec3, vec3, xyz, x, y, z) +MUGLM_IMPL_SWIZZLE(vec3, vec3, xzx, x, z, x) +MUGLM_IMPL_SWIZZLE(vec3, vec3, xzy, x, z, y) +MUGLM_IMPL_SWIZZLE(vec3, vec3, xzz, x, z, z) +MUGLM_IMPL_SWIZZLE(vec3, vec3, yxx, y, x, x) +MUGLM_IMPL_SWIZZLE(vec3, vec3, yxy, y, x, y) +MUGLM_IMPL_SWIZZLE(vec3, vec3, yxz, y, x, z) +MUGLM_IMPL_SWIZZLE(vec3, vec3, yyx, y, y, x) +MUGLM_IMPL_SWIZZLE(vec3, vec3, yyy, y, y, y) +MUGLM_IMPL_SWIZZLE(vec3, vec3, yyz, y, y, z) +MUGLM_IMPL_SWIZZLE(vec3, vec3, yzx, y, z, x) +MUGLM_IMPL_SWIZZLE(vec3, vec3, yzy, y, z, y) +MUGLM_IMPL_SWIZZLE(vec3, vec3, yzz, y, z, z) +MUGLM_IMPL_SWIZZLE(vec3, vec3, zxx, z, x, x) +MUGLM_IMPL_SWIZZLE(vec3, vec3, zxy, z, x, y) +MUGLM_IMPL_SWIZZLE(vec3, vec3, zxz, z, x, z) +MUGLM_IMPL_SWIZZLE(vec3, vec3, zyx, z, y, x) +MUGLM_IMPL_SWIZZLE(vec3, vec3, zyy, z, y, y) +MUGLM_IMPL_SWIZZLE(vec3, vec3, zyz, z, y, z) +MUGLM_IMPL_SWIZZLE(vec3, vec3, zzx, z, z, x) +MUGLM_IMPL_SWIZZLE(vec3, vec3, zzy, z, z, y) +MUGLM_IMPL_SWIZZLE(vec3, vec3, zzz, z, z, z) + +MUGLM_IMPL_SWIZZLE(vec4, vec3, xxxx, x, x, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xxxy, x, x, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xxxz, x, x, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xxyx, x, x, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xxyy, x, x, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xxyz, x, x, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xxzx, x, x, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xxzy, x, x, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xxzz, x, x, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xyxx, x, y, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xyxy, x, y, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xyxz, x, y, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xyyx, x, y, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xyyy, x, y, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xyyz, x, y, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xyzx, x, y, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xyzy, x, y, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xyzz, x, y, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xzxx, x, z, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xzxy, x, z, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xzxz, x, z, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xzyx, x, z, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xzyy, x, z, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xzyz, x, z, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xzzx, x, z, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xzzy, x, z, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, xzzz, x, z, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yxxx, y, x, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yxxy, y, x, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yxxz, y, x, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yxyx, y, x, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yxyy, y, x, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yxyz, y, x, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yxzx, y, x, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yxzy, y, x, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yxzz, y, x, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yyxx, y, y, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yyxy, y, y, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yyxz, y, y, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yyyx, y, y, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yyyy, y, y, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yyyz, y, y, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yyzx, y, y, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yyzy, y, y, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yyzz, y, y, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yzxx, y, z, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yzxy, y, z, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yzxz, y, z, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yzyx, y, z, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yzyy, y, z, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yzyz, y, z, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yzzx, y, z, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yzzy, y, z, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, yzzz, y, z, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zxxx, z, x, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zxxy, z, x, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zxxz, z, x, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zxyx, z, x, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zxyy, z, x, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zxyz, z, x, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zxzx, z, x, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zxzy, z, x, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zxzz, z, x, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zyxx, z, y, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zyxy, z, y, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zyxz, z, y, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zyyx, z, y, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zyyy, z, y, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zyyz, z, y, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zyzx, z, y, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zyzy, z, y, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zyzz, z, y, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zzxx, z, z, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zzxy, z, z, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zzxz, z, z, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zzyx, z, z, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zzyy, z, z, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zzyz, z, z, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zzzx, z, z, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zzzy, z, z, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec3, zzzz, z, z, z, z) + +// vec4 +MUGLM_IMPL_SWIZZLE(vec2, vec4, xx, x, x) +MUGLM_IMPL_SWIZZLE(vec2, vec4, xy, x, y) +MUGLM_IMPL_SWIZZLE(vec2, vec4, xz, x, z) +MUGLM_IMPL_SWIZZLE(vec2, vec4, xw, x, w) +MUGLM_IMPL_SWIZZLE(vec2, vec4, yx, y, x) +MUGLM_IMPL_SWIZZLE(vec2, vec4, yy, y, y) +MUGLM_IMPL_SWIZZLE(vec2, vec4, yz, y, z) +MUGLM_IMPL_SWIZZLE(vec2, vec4, yw, y, w) +MUGLM_IMPL_SWIZZLE(vec2, vec4, zx, z, x) +MUGLM_IMPL_SWIZZLE(vec2, vec4, zy, z, y) +MUGLM_IMPL_SWIZZLE(vec2, vec4, zz, z, z) +MUGLM_IMPL_SWIZZLE(vec2, vec4, zw, z, w) +MUGLM_IMPL_SWIZZLE(vec2, vec4, wx, w, x) +MUGLM_IMPL_SWIZZLE(vec2, vec4, wy, w, y) +MUGLM_IMPL_SWIZZLE(vec2, vec4, wz, w, z) +MUGLM_IMPL_SWIZZLE(vec2, vec4, ww, w, w) + +MUGLM_IMPL_SWIZZLE(vec3, vec4, xxx, x, x, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xxy, x, x, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xxz, x, x, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xxw, x, x, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xyx, x, y, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xyy, x, y, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xyz, x, y, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xyw, x, y, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xzx, x, z, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xzy, x, z, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xzz, x, z, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xzw, x, z, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xwx, x, w, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xwy, x, w, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xwz, x, w, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, xww, x, w, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yxx, y, x, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yxy, y, x, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yxz, y, x, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yxw, y, x, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yyx, y, y, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yyy, y, y, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yyz, y, y, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yyw, y, y, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yzx, y, z, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yzy, y, z, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yzz, y, z, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yzw, y, z, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, ywx, y, w, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, ywy, y, w, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, ywz, y, w, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, yww, y, w, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zxx, z, x, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zxy, z, x, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zxz, z, x, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zxw, z, x, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zyx, z, y, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zyy, z, y, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zyz, z, y, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zyw, z, y, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zzx, z, z, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zzy, z, z, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zzz, z, z, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zzw, z, z, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zwx, z, w, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zwy, z, w, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zwz, z, w, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, zww, z, w, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wxx, w, x, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wxy, w, x, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wxz, w, x, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wxw, w, x, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wyx, w, y, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wyy, w, y, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wyz, w, y, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wyw, w, y, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wzx, w, z, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wzy, w, z, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wzz, w, z, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wzw, w, z, w) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wwx, w, w, x) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wwy, w, w, y) +MUGLM_IMPL_SWIZZLE(vec3, vec4, wwz, w, w, z) +MUGLM_IMPL_SWIZZLE(vec3, vec4, www, w, w, w) + +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxxx, x, x, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxxy, x, x, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxxz, x, x, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxxw, x, x, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxyx, x, x, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxyy, x, x, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxyz, x, x, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxyw, x, x, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxzx, x, x, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxzy, x, x, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxzz, x, x, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxzw, x, x, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxwx, x, x, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxwy, x, x, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxwz, x, x, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xxww, x, x, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyxx, x, y, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyxy, x, y, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyxz, x, y, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyxw, x, y, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyyx, x, y, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyyy, x, y, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyyz, x, y, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyyw, x, y, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyzx, x, y, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyzy, x, y, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyzz, x, y, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyzw, x, y, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xywx, x, y, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xywy, x, y, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xywz, x, y, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xyww, x, y, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzxx, x, z, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzxy, x, z, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzxz, x, z, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzxw, x, z, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzyx, x, z, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzyy, x, z, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzyz, x, z, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzyw, x, z, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzzx, x, z, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzzy, x, z, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzzz, x, z, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzzw, x, z, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzwx, x, z, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzwy, x, z, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzwz, x, z, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xzww, x, z, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwxx, x, w, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwxy, x, w, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwxz, x, w, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwxw, x, w, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwyx, x, w, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwyy, x, w, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwyz, x, w, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwyw, x, w, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwzx, x, w, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwzy, x, w, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwzz, x, w, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwzw, x, w, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwwx, x, w, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwwy, x, w, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwwz, x, w, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, xwww, x, w, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxxx, y, x, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxxy, y, x, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxxz, y, x, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxxw, y, x, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxyx, y, x, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxyy, y, x, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxyz, y, x, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxyw, y, x, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxzx, y, x, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxzy, y, x, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxzz, y, x, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxzw, y, x, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxwx, y, x, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxwy, y, x, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxwz, y, x, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yxww, y, x, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyxx, y, y, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyxy, y, y, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyxz, y, y, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyxw, y, y, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyyx, y, y, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyyy, y, y, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyyz, y, y, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyyw, y, y, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyzx, y, y, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyzy, y, y, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyzz, y, y, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyzw, y, y, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yywx, y, y, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yywy, y, y, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yywz, y, y, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yyww, y, y, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzxx, y, z, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzxy, y, z, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzxz, y, z, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzxw, y, z, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzyx, y, z, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzyy, y, z, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzyz, y, z, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzyw, y, z, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzzx, y, z, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzzy, y, z, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzzz, y, z, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzzw, y, z, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzwx, y, z, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzwy, y, z, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzwz, y, z, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, yzww, y, z, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywxx, y, w, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywxy, y, w, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywxz, y, w, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywxw, y, w, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywyx, y, w, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywyy, y, w, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywyz, y, w, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywyw, y, w, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywzx, y, w, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywzy, y, w, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywzz, y, w, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywzw, y, w, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywwx, y, w, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywwy, y, w, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywwz, y, w, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, ywww, y, w, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxxx, z, x, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxxy, z, x, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxxz, z, x, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxxw, z, x, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxyx, z, x, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxyy, z, x, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxyz, z, x, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxyw, z, x, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxzx, z, x, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxzy, z, x, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxzz, z, x, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxzw, z, x, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxwx, z, x, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxwy, z, x, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxwz, z, x, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zxww, z, x, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyxx, z, y, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyxy, z, y, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyxz, z, y, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyxw, z, y, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyyx, z, y, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyyy, z, y, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyyz, z, y, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyyw, z, y, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyzx, z, y, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyzy, z, y, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyzz, z, y, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyzw, z, y, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zywx, z, y, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zywy, z, y, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zywz, z, y, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zyww, z, y, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzxx, z, z, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzxy, z, z, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzxz, z, z, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzxw, z, z, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzyx, z, z, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzyy, z, z, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzyz, z, z, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzyw, z, z, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzzx, z, z, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzzy, z, z, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzzz, z, z, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzzw, z, z, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzwx, z, z, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzwy, z, z, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzwz, z, z, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zzww, z, z, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwxx, z, w, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwxy, z, w, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwxz, z, w, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwxw, z, w, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwyx, z, w, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwyy, z, w, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwyz, z, w, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwyw, z, w, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwzx, z, w, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwzy, z, w, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwzz, z, w, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwzw, z, w, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwwx, z, w, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwwy, z, w, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwwz, z, w, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, zwww, z, w, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxxx, w, x, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxxy, w, x, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxxz, w, x, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxxw, w, x, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxyx, w, x, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxyy, w, x, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxyz, w, x, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxyw, w, x, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxzx, w, x, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxzy, w, x, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxzz, w, x, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxzw, w, x, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxwx, w, x, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxwy, w, x, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxwz, w, x, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wxww, w, x, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyxx, w, y, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyxy, w, y, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyxz, w, y, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyxw, w, y, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyyx, w, y, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyyy, w, y, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyyz, w, y, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyyw, w, y, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyzx, w, y, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyzy, w, y, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyzz, w, y, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyzw, w, y, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wywx, w, y, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wywy, w, y, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wywz, w, y, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wyww, w, y, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzxx, w, z, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzxy, w, z, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzxz, w, z, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzxw, w, z, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzyx, w, z, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzyy, w, z, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzyz, w, z, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzyw, w, z, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzzx, w, z, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzzy, w, z, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzzz, w, z, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzzw, w, z, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzwx, w, z, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzwy, w, z, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzwz, w, z, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wzww, w, z, w, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwxx, w, w, x, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwxy, w, w, x, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwxz, w, w, x, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwxw, w, w, x, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwyx, w, w, y, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwyy, w, w, y, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwyz, w, w, y, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwyw, w, w, y, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwzx, w, w, z, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwzy, w, w, z, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwzz, w, w, z, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwzw, w, w, z, w) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwwx, w, w, w, x) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwwy, w, w, w, y) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwwz, w, w, w, z) +MUGLM_IMPL_SWIZZLE(vec4, vec4, wwww, w, w, w, w) + +// arithmetic operations +#define MUGLM_DEFINE_ARITH_OP(op) \ +template inline tvec2 operator op(const tvec2 &a, const tvec2 &b) { return tvec2(a.x op b.x, a.y op b.y); } \ +template inline tvec3 operator op(const tvec3 &a, const tvec3 &b) { return tvec3(a.x op b.x, a.y op b.y, a.z op b.z); } \ +template inline tvec4 operator op(const tvec4 &a, const tvec4 &b) { return tvec4(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); } \ +template inline tvec2 operator op(const tvec2 &a, T b) { return tvec2(a.x op b, a.y op b); } \ +template inline tvec3 operator op(const tvec3 &a, T b) { return tvec3(a.x op b, a.y op b, a.z op b); } \ +template inline tvec4 operator op(const tvec4 &a, T b) { return tvec4(a.x op b, a.y op b, a.z op b, a.w op b); } \ +template inline tvec2 operator op(T a, const tvec2 &b) { return tvec2(a op b.x, a op b.y); } \ +template inline tvec3 operator op(T a, const tvec3 &b) { return tvec3(a op b.x, a op b.y, a op b.z); } \ +template inline tvec4 operator op(T a, const tvec4 &b) { return tvec4(a op b.x, a op b.y, a op b.z, a op b.w); } +MUGLM_DEFINE_ARITH_OP(+) +MUGLM_DEFINE_ARITH_OP(-) +MUGLM_DEFINE_ARITH_OP(*) +MUGLM_DEFINE_ARITH_OP(/) +MUGLM_DEFINE_ARITH_OP(^) +MUGLM_DEFINE_ARITH_OP(&) +MUGLM_DEFINE_ARITH_OP(|) +MUGLM_DEFINE_ARITH_OP(>>) +MUGLM_DEFINE_ARITH_OP(<<) + +#define MUGLM_DEFINE_MATRIX_SCALAR_OP(op) \ +template inline tmat2 operator op(const tmat2 &m, T s) { return tmat2(m[0] op s, m[1] op s); } \ +template inline tmat3 operator op(const tmat3 &m, T s) { return tmat3(m[0] op s, m[1] op s, m[2] op s); } \ +template inline tmat4 operator op(const tmat4 &m, T s) { return tmat4(m[0] op s, m[1] op s, m[2] op s, m[3] op s); } +MUGLM_DEFINE_MATRIX_SCALAR_OP(+) +MUGLM_DEFINE_MATRIX_SCALAR_OP(-) +MUGLM_DEFINE_MATRIX_SCALAR_OP(*) +MUGLM_DEFINE_MATRIX_SCALAR_OP(/) + +#define MUGLM_DEFINE_BOOL_OP(bop, op) \ +template inline bvec2 bop(const tvec2 &a, const tvec2 &b) { return bvec2(a.x op b.x, a.y op b.y); } \ +template inline bvec3 bop(const tvec3 &a, const tvec3 &b) { return bvec3(a.x op b.x, a.y op b.y, a.z op b.z); } \ +template inline bvec4 bop(const tvec4 &a, const tvec4 &b) { return bvec4(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); } +MUGLM_DEFINE_BOOL_OP(notEqual, !=) +MUGLM_DEFINE_BOOL_OP(equal, ==) +MUGLM_DEFINE_BOOL_OP(lessThan, <) +MUGLM_DEFINE_BOOL_OP(lessThanEqual, <=) +MUGLM_DEFINE_BOOL_OP(greaterThan, >) +MUGLM_DEFINE_BOOL_OP(greaterThanEqual, >=) + +inline bool any(const bvec2 &v) { return v.x || v.y; } +inline bool any(const bvec3 &v) { return v.x || v.y || v.z; } +inline bool any(const bvec4 &v) { return v.x || v.y || v.z || v.w; } +inline bool all(const bvec2 &v) { return v.x && v.y; } +inline bool all(const bvec3 &v) { return v.x && v.y && v.z; } +inline bool all(const bvec4 &v) { return v.x && v.y && v.z && v.w; } + +template inline tvec2 operator-(const tvec2 &v) { return tvec2(-v.x, -v.y); } +template inline tvec3 operator-(const tvec3 &v) { return tvec3(-v.x, -v.y, -v.z); } +template inline tvec4 operator-(const tvec4 &v) { return tvec4(-v.x, -v.y, -v.z, -v.w); } +template inline tvec2 operator~(const tvec2 &v) { return tvec2(~v.x, ~v.y); } +template inline tvec3 operator~(const tvec3 &v) { return tvec3(~v.x, ~v.y, ~v.z); } +template inline tvec4 operator~(const tvec4 &v) { return tvec4(~v.x, ~v.y, ~v.z, ~v.w); } + +// arithmetic operations, inplace modify +#define MUGLM_DEFINE_ARITH_MOD_OP(op) \ +template inline tvec2 &operator op(tvec2 &a, const tvec2 &b) { a.x op b.x; a.y op b.y; return a; } \ +template inline tvec3 &operator op(tvec3 &a, const tvec3 &b) { a.x op b.x; a.y op b.y; a.z op b.z; return a; } \ +template inline tvec4 &operator op(tvec4 &a, const tvec4 &b) { a.x op b.x; a.y op b.y; a.z op b.z; a.w op b.w; return a; } \ +template inline tvec2 &operator op(tvec2 &a, T b) { a.x op b; a.y op b; return a; } \ +template inline tvec3 &operator op(tvec3 &a, T b) { a.x op b; a.y op b; a.z op b; return a; } \ +template inline tvec4 &operator op(tvec4 &a, T b) { a.x op b; a.y op b; a.z op b; a.w op b; return a; } +MUGLM_DEFINE_ARITH_MOD_OP(+=) +MUGLM_DEFINE_ARITH_MOD_OP(-=) +MUGLM_DEFINE_ARITH_MOD_OP(*=) +MUGLM_DEFINE_ARITH_MOD_OP(/=) +MUGLM_DEFINE_ARITH_MOD_OP(^=) +MUGLM_DEFINE_ARITH_MOD_OP(&=) +MUGLM_DEFINE_ARITH_MOD_OP(|=) +MUGLM_DEFINE_ARITH_MOD_OP(>>=) +MUGLM_DEFINE_ARITH_MOD_OP(<<=) + +// matrix multiply +inline vec2 operator*(const mat2 &m, const vec2 &v) +{ + return m[0] * v.x + m[1] * v.y; +} + +inline vec3 operator*(const mat3 &m, const vec3 &v) +{ + return m[0] * v.x + m[1] * v.y + m[2] * v.z; +} + +inline vec4 operator*(const mat4 &m, const vec4 &v) +{ + return m[0] * v.x + m[1] * v.y + m[2] * v.z + m[3] * v.w; +} + +inline mat2 operator*(const mat2 &a, const mat2 &b) +{ + return mat2(a * b[0], a * b[1]); +} + +inline mat3 operator*(const mat3 &a, const mat3 &b) +{ + return mat3(a * b[0], a * b[1], a * b[2]); +} + +inline mat4 operator*(const mat4 &a, const mat4 &b) +{ + return mat4(a * b[0], a * b[1], a * b[2], a * b[3]); +} + +inline mat2 transpose(const mat2 &m) +{ + return mat2(vec2(m[0].x, m[1].x), + vec2(m[0].y, m[1].y)); +} + +inline mat3 transpose(const mat3 &m) +{ + return mat3(vec3(m[0].x, m[1].x, m[2].x), + vec3(m[0].y, m[1].y, m[2].y), + vec3(m[0].z, m[1].z, m[2].z)); +} + +inline mat4 transpose(const mat4 &m) +{ + mat4 dst; + transpose(dst, m); + return dst; +} + +// dot +inline float dot(const vec2 &a, const vec2 &b) { return a.x * b.x + a.y * b.y; } +inline float dot(const vec3 &a, const vec3 &b) { return a.x * b.x + a.y * b.y + a.z * b.z; } +inline float dot(const vec4 &a, const vec4 &b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } + +#undef min +#undef max +#ifndef NOMINMAX +#define NOMINMAX +#endif + +// min, max, clamp +template T min(T a, T b) { return b < a ? b : a; } +template T max(T a, T b) { return a < b ? b : a; } +template T clamp(T v, T lo, T hi) { return v < lo ? lo : (v > hi ? hi : v); } +template T sign(T v) { return v < T(0) ? T(-1) : (v > T(0) ? T(1) : T(0)); } +template T sin(T v) { return std::sin(v); } +template T cos(T v) { return std::cos(v); } +template T tan(T v) { return std::tan(v); } +template T asin(T v) { return std::asin(v); } +template T acos(T v) { return std::acos(v); } +template T atan(T v) { return std::atan(v); } +template T log2(T v) { return std::log2(v); } +template T log10(T v) { return std::log10(v); } +template T log(T v) { return std::log(v); } +template T exp2(T v) { return std::exp2(v); } +template T exp(T v) { return std::exp(v); } +template T pow(T a, T b) { return std::pow(a, b); } +template T radians(T a) { return a * (T(pi() / T(180))); } +template T degrees(T a) { return a * (T(180) / pi()); } + +#define MUGLM_VECTORIZED_FUNC1(func) \ +template inline tvec2 func(const tvec2 &a) { return tvec2(func(a.x), func(a.y)); } \ +template inline tvec3 func(const tvec3 &a) { return tvec3(func(a.x), func(a.y), func(a.z)); } \ +template inline tvec4 func(const tvec4 &a) { return tvec4(func(a.x), func(a.y), func(a.z), func(a.w)); } + +#define MUGLM_VECTORIZED_FUNC2(func) \ +template inline tvec2 func(const tvec2 &a, const tvec2 &b) { return tvec2(func(a.x, b.x), func(a.y, b.y)); } \ +template inline tvec3 func(const tvec3 &a, const tvec3 &b) { return tvec3(func(a.x, b.x), func(a.y, b.y), func(a.z, b.z)); } \ +template inline tvec4 func(const tvec4 &a, const tvec4 &b) { return tvec4(func(a.x, b.x), func(a.y, b.y), func(a.z, b.z), func(a.w, b.w)); } + +#define MUGLM_VECTORIZED_FUNC3(func) \ +template inline tvec2 func(const tvec2 &a, const tvec2 &b, const tvec2 &c) { return tvec2(func(a.x, b.x, c.x), func(a.y, b.y, c.y)); } \ +template inline tvec3 func(const tvec3 &a, const tvec3 &b, const tvec3 &c) { return tvec3(func(a.x, b.x, c.x), func(a.y, b.y, c.y), func(a.z, b.z, c.z)); } \ +template inline tvec4 func(const tvec4 &a, const tvec4 &b, const tvec4 &c) { return tvec4(func(a.x, b.x, c.x), func(a.y, b.y, c.y), func(a.z, b.z, c.z), func(a.w, b.w, c.w)); } + +MUGLM_VECTORIZED_FUNC1(sign) +MUGLM_VECTORIZED_FUNC1(sin) +MUGLM_VECTORIZED_FUNC1(cos) +MUGLM_VECTORIZED_FUNC1(tan) +MUGLM_VECTORIZED_FUNC1(asin) +MUGLM_VECTORIZED_FUNC1(acos) +MUGLM_VECTORIZED_FUNC1(atan) +MUGLM_VECTORIZED_FUNC1(log2) +MUGLM_VECTORIZED_FUNC1(log10) +MUGLM_VECTORIZED_FUNC1(log) +MUGLM_VECTORIZED_FUNC1(exp2) +MUGLM_VECTORIZED_FUNC1(exp) +MUGLM_VECTORIZED_FUNC2(min) +MUGLM_VECTORIZED_FUNC2(max) +MUGLM_VECTORIZED_FUNC2(pow) +MUGLM_VECTORIZED_FUNC3(clamp) + +// mix +template inline T mix(const T &a, const T &b, const Lerp &lerp) { return a * (1.0f - lerp) + b * lerp; } + +template inline T select(T a, T b, bool lerp) +{ + return lerp ? b : a; +} + +template inline tvec2 select(const tvec2 &a, const tvec2 &b, const tvec2 &lerp) +{ + return tvec2(lerp.x ? b.x : a.x, lerp.y ? b.y : a.y); +} + +template inline tvec3 select(const tvec3 &a, const tvec3 &b, const tvec3 &lerp) +{ + return tvec3(lerp.x ? b.x : a.x, lerp.y ? b.y : a.y, lerp.z ? b.z : a.z); +} + +template inline tvec4 select(const tvec4 &a, const tvec4 &b, const tvec4 &lerp) +{ + return tvec4(lerp.x ? b.x : a.x, lerp.y ? b.y : a.y, lerp.z ? b.z : a.z, lerp.w ? b.w : a.w); +} + +// smoothstep +template inline T smoothstep(const T &lo, const T &hi, T val) +{ + val = clamp((val - lo) / (hi - lo), T(0.0f), T(1.0f)); + return val * val * (3.0f - 2.0f * val); +} + +// cross +inline vec3 cross(const vec3 &a, const vec3 &b) { return vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); } + +// sqrt +inline float sqrt(float v) { return std::sqrt(v); } +MUGLM_VECTORIZED_FUNC1(sqrt) + +// floor +inline float floor(float v) { return std::floor(v); } +inline double floor(double v) { return std::floor(v); } +MUGLM_VECTORIZED_FUNC1(floor) + +// fract +template +inline T fract(const T &v) { return v - floor(v); } + +// ceil +inline float ceil(float v) { return std::ceil(v); } +inline double ceil(double v) { return std::ceil(v); } +MUGLM_VECTORIZED_FUNC1(ceil) + +// round +inline float round(float v) { return std::round(v); } +inline double round(double v) { return std::round(v); } +MUGLM_VECTORIZED_FUNC1(round) + +// mod +inline float mod(float x, float y) { return x - y * floor(x / y); } +inline double mod(double x, double y) { return x - y * floor(x / y); } +MUGLM_VECTORIZED_FUNC2(mod) + +// abs +template +inline T abs(T v) { return std::abs(v); } +MUGLM_VECTORIZED_FUNC1(abs) + +inline uint floatBitsToUint(float v) +{ + union { float f32; uint u32; } u; + u.f32 = v; + return u.u32; +} +MUGLM_VECTORIZED_FUNC1(floatBitsToUint) + +inline float uintBitsToFloat(uint v) +{ + union { float f32; uint u32; } u; + u.u32 = v; + return u.f32; +} +MUGLM_VECTORIZED_FUNC1(uintBitsToFloat) + +inline float halfToFloat(uint16_t u16_value) +{ + // Based on the GLM implementation. + int s = (u16_value >> 15) & 0x1; + int e = (u16_value >> 10) & 0x1f; + int m = (u16_value >> 0) & 0x3ff; + + union { + float f32; + uint32_t u32; + } u; + + if (e == 0) + { + if (m == 0) + { + u.u32 = uint32_t(s) << 31; + return u.f32; + } + else + { + while ((m & 0x400) == 0) + { + m <<= 1; + e--; + } + + e++; + m &= ~0x400; + } + } + else if (e == 31) + { + if (m == 0) + { + u.u32 = (uint32_t(s) << 31) | 0x7f800000u; + return u.f32; + } + else + { + u.u32 = (uint32_t(s) << 31) | 0x7f800000u | (m << 13); + return u.f32; + } + } + + e += 127 - 15; + m <<= 13; + u.u32 = (uint32_t(s) << 31) | (e << 23) | m; + return u.f32; +} + +inline vec2 halfToFloat(const u16vec2 &v) +{ + return vec2(halfToFloat(v.x), halfToFloat(v.y)); +} + +inline vec3 floatToHalf(const u16vec3 &v) +{ + return vec3(halfToFloat(v.x), halfToFloat(v.y), halfToFloat(v.z)); +} + +inline vec4 floatToHalf(const u16vec4 &v) +{ + return vec4(halfToFloat(v.x), halfToFloat(v.y), halfToFloat(v.z), halfToFloat(v.w)); +} + +inline uint16_t floatToHalf(float v) +{ + int i = floatBitsToUint(v); + int s = (i >> 16) & 0x00008000; + int e = ((i >> 23) & 0x000000ff) - (127 - 15); + int m = i & 0x007fffff; + + if (e <= 0) + { + if (e < -10) + return uint16_t(s); + + m = (m | 0x00800000) >> (1 - e); + + if (m & 0x00001000) + m += 0x00002000; + + return uint16_t(s | (m >> 13)); + } + else if (e == 0xff - (127 - 15)) + { + if (m == 0) + return uint16_t(s | 0x7c00); + else + { + m >>= 13; + return uint16_t(s | 0x7c00 | m | (m == 0)); + } + } + else + { + if (m & 0x00001000) + { + m += 0x00002000; + + if (m & 0x00800000) + { + m = 0; + e += 1; + } + } + + if (e > 30) + return uint16_t(s | 0x7c00); + + return uint16_t(s | (e << 10) | (m >> 13)); + } +} + +inline u16vec2 floatToHalf(const vec2 &v) +{ + return u16vec2(floatToHalf(v.x), floatToHalf(v.y)); +} + +inline u16vec3 floatToHalf(const vec3 &v) +{ + return u16vec3(floatToHalf(v.x), floatToHalf(v.y), floatToHalf(v.z)); +} + +inline u16vec4 floatToHalf(const vec4 &v) +{ + return u16vec4(floatToHalf(v.x), floatToHalf(v.y), floatToHalf(v.z), floatToHalf(v.w)); +} + +// inversesqrt +template inline T inversesqrt(const T &v) { return T(1) / sqrt(v); } + +// normalize +template inline T normalize(const T &v) { return v * inversesqrt(dot(v, v)); } +inline quat normalize(const quat &q) { return quat(normalize(q.as_vec4())); } + +// length +template inline float length(const T &v) { return sqrt(dot(v, v)); } + +// distance +template inline float distance(const T &a, const T &b) { return length(a - b); } + +// quaternions +inline vec3 operator*(const quat &q, const vec3 &v) +{ + vec3 quat_vector = q.as_vec4().xyz(); + vec3 uv = cross(quat_vector, v); + vec3 uuv = cross(quat_vector, uv); + return v + ((uv * q.w) + uuv) * 2.0f; +} + +inline quat operator*(const quat &p, const quat &q) +{ + float w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z; + float x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y; + float y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z; + float z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x; + return quat(w, x, y, z); +} + +inline quat slerp(const quat &x, const quat &y, float l) +{ + quat z = y; + float cos_theta = dot(x.as_vec4(), y.as_vec4()); + if (cos_theta < 0.0f) + { + z = quat(-y.as_vec4()); + cos_theta = -cos_theta; + } + + if (cos_theta > 0.999f) + return normalize(quat(mix(x.as_vec4(), z.as_vec4(), l))); + + float angle = acos(cos_theta); + + auto &vz = z.as_vec4(); + auto &vx = x.as_vec4(); + auto res = (sin((1.0f - l) * angle) * vx + sin(l * angle) * vz) / sin(angle); + return quat(res); +} + +inline quat slerp_no_invert(const quat &x, const quat &y, float l) +{ + float cos_theta = dot(x.as_vec4(), y.as_vec4()); + if (cos_theta > 0.999f) + return normalize(quat(mix(x.as_vec4(), y.as_vec4(), l))); + + float angle = acos(cos_theta); + + auto &vy = y.as_vec4(); + auto &vx = x.as_vec4(); + auto res = (sin((1.0f - l) * angle) * vx + sin(l * angle) * vy) / sin(angle); + return quat(res); +} + +inline quat angleAxis(float angle, const vec3 &axis) +{ + return quat(cos(0.5f * angle), sin(0.5f * angle) * normalize(axis)); +} + +inline quat conjugate(const quat &q) +{ + return quat(q.w, -q.x, -q.y, -q.z); +} + +inline vec3 rotateX(const vec3 &v, float angle) +{ + return angleAxis(angle, vec3(1.0f, 0.0f, 0.0f)) * v; +} + +inline vec3 rotateY(const vec3 &v, float angle) +{ + return angleAxis(angle, vec3(0.0f, 1.0f, 0.0f)) * v; +} + +inline vec3 rotateZ(const vec3 &v, float angle) +{ + return angleAxis(angle, vec3(0.0f, 0.0f, 1.0f)) * v; +} + +inline vec3 quat_log(const quat &q) +{ + if (abs(q.w) > 0.9999f) + return vec3(0.0f); + else + return normalize(q.as_vec4().xyz()) * acos(q.w); +} + +inline quat quat_exp(const vec3 &q) +{ + float l = dot(q, q); + if (l < 0.000001f) + { + return quat(1.0f, 0.0f, 0.0f, 0.0f); + } + else + { + float vlen = length(q); + vec3 v = normalize(q) * sin(vlen); + return quat(cos(vlen), v); + } +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm_test.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm_test.cpp new file mode 100644 index 00000000..e53d0db7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/muglm/muglm_test.cpp @@ -0,0 +1,251 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "muglm_impl.hpp" +#include "matrix_helper.hpp" +#include "simd.hpp" +#include +#include +#include "aabb.hpp" + +using namespace muglm; + +#define MATH_ASSERT(x) do { \ + if (!bool(x)) \ + abort(); \ +} while(0) + +template +static void assert_equal_epsilon(const T &a, const T &b, float epsilon = 0.0001f) +{ + MATH_ASSERT(all(lessThanEqual(abs(a - b), T(epsilon)))); +} + +template +static void assert_equal(const T &a, const T &b) +{ + MATH_ASSERT(all(equal(a, b))); +} + +static void assert_equal_epsilon(const mat2 &a, const mat2 &b, float epsilon = 0.0001f) +{ + assert_equal_epsilon(a[0], b[0], epsilon); + assert_equal_epsilon(a[1], b[1], epsilon); +} + +static void assert_equal_epsilon(const mat3 &a, const mat3 &b, float epsilon = 0.0001f) +{ + assert_equal_epsilon(a[0], b[0], epsilon); + assert_equal_epsilon(a[1], b[1], epsilon); + assert_equal_epsilon(a[2], b[2], epsilon); +} + +static void assert_equal_epsilon(const mat4 &a, const mat4 &b, float epsilon = 0.0001f) +{ + assert_equal_epsilon(a[0], b[0], epsilon); + assert_equal_epsilon(a[1], b[1], epsilon); + assert_equal_epsilon(a[2], b[2], epsilon); + assert_equal_epsilon(a[3], b[3], epsilon); +} + +static void assert_equal_epsilon(const mat_affine &a, const mat_affine &b, float epsilon = 0.0001f) +{ + assert_equal_epsilon(a[0], b[0], epsilon); + assert_equal_epsilon(a[1], b[1], epsilon); + assert_equal_epsilon(a[2], b[2], epsilon); +} + +static void assert_equal(const mat2 &a, const mat2 &b) +{ + assert_equal_epsilon(a, b, 0.0f); +} + +static void assert_equal(const mat3 &a, const mat3 &b) +{ + assert_equal_epsilon(a, b, 0.0f); +} + +static void assert_equal(const mat4 &a, const mat4 &b) +{ + assert_equal_epsilon(a, b, 0.0f); +} + +static void test_mat2() +{ + mat2 m(vec2(2.0f, 0.5f), vec2(8.0f, 4.0f)); + mat2 inv_m = inverse(m); + mat2 mul0 = m * inv_m; + mat2 mul1 = inv_m * m; + assert_equal_epsilon(mul0, mat2(1.0f)); + assert_equal_epsilon(mul1, mat2(1.0f)); + assert_equal(transpose(transpose(m)), m); +} + +static void test_mat3() +{ + mat3 m(vec3(2.0f, 0.5f, -3.0f), vec3(8.0f, 4.0f, 0.25f), vec3(-20.0f, 5.0f, 1.0f)); + mat3 inv_m = inverse(m); + mat3 mul0 = m * inv_m; + mat3 mul1 = inv_m * m; + assert_equal_epsilon(mul0, mat3(1.0f)); + assert_equal_epsilon(mul1, mat3(1.0f)); + assert_equal(transpose(transpose(m)), m); +} + +static void test_mat4() +{ + mat4 m(vec4(2.0f, 0.5f, -3.0f, 1.0f), vec4(8.0f, 4.0f, 0.25f, 8.0f), vec4(8.0f, -20.0f, 5.0f, 1.0f), vec4(0.0f, 1.0f, 2.0f, 3.0f)); + mat4 inv_m = inverse(m); + mat4 mul0 = m * inv_m; + mat4 mul1 = inv_m * m; + assert_equal_epsilon(mul0, mat4(1.0f)); + assert_equal_epsilon(mul1, mat4(1.0f)); + assert_equal(transpose(transpose(m)), m); +} + +static void test_quat() +{ + // X + { + quat q = angleAxis(half_pi(), vec3(0.0f, 0.0f, 1.0f)); + vec3 y = q * vec3(1.0f, 0.0f, 0.0f); + assert_equal_epsilon(y, vec3(0.0f, 1.0f, 0.0f)); + + quat half_q = angleAxis(0.5f * half_pi(), vec3(0.0f, 0.0f, 1.0f)); + q = half_q * half_q; + y = q * vec3(1.0f, 0.0f, 0.0f); + assert_equal_epsilon(y, vec3(0.0f, 1.0f, 0.0f)); + } + + // Y + { + quat q = angleAxis(half_pi(), vec3(0.0f, 1.0f, 0.0f)); + vec3 y = q * vec3(1.0f, 0.0f, 0.0f); + assert_equal_epsilon(y, vec3(0.0f, 0.0f, -1.0f)); + + quat half_q = angleAxis(0.5f * half_pi(), vec3(0.0f, 1.0f, 0.0f)); + q = half_q * half_q; + y = q * vec3(1.0f, 0.0f, 0.0f); + assert_equal_epsilon(y, vec3(0.0f, 0.0f, -1.0f)); + } + + assert_equal_epsilon(mat3_cast(quat(1.0f, 0.0f, 0.0f, 0.0f)), mat3(1.0f)); + assert_equal_epsilon(mat4_cast(quat(1.0f, 0.0f, 0.0f, 0.0f)), mat4(1.0f)); +} + +static void test_decompose() +{ + vec3 scaling(4.0f, -3.0f, 2.0f); + quat rotate = angleAxis(0.543f, vec3(0.1f, 0.2f, -0.9f)); + vec3 trans(5.0f, 4.0f, 2.0f); + + mat4 original = translate(trans) * mat4_cast(rotate) * scale(scaling); + + vec3 s, t; + quat r; + decompose(original, s, r, t); + + mat4 reconstructed = translate(t) * mat4_cast(r) * scale(s); + assert_equal_epsilon(original, reconstructed); +} + +static void test_transpose() +{ + mat4 original(vec4(1, 2, 3, 4), vec4(5, 6, 7, 8), vec4(9, 10, 11, 12), vec4(13, 14, 15, 16)); + mat4 transposed = transpose(original); + mat_affine aff{original}; + + const mat4 expected_transposed( + vec4(1, 5, 9, 13), + vec4(2, 6, 10, 14), + vec4(3, 7, 11, 15), + vec4(4, 8, 12, 16)); + + mat_affine expected_aff; + for (int i = 0; i < 3; i++) + expected_aff[i] = expected_transposed[i]; + + assert_equal_epsilon(expected_transposed, transposed, 0.0f); + assert_equal_epsilon(expected_aff, aff, 0.0f); +} + +static void test_affine() +{ + mat4 a(vec4(1, 2, 3, 0), vec4(5, 6, 7, 0), + vec4(9, 10, 11, 0), vec4(13, 14, 15, 1)); + mat4 b(vec4(17, 18, 19, 0), vec4(21, 22, 23, 0), + vec4(25, 26, 27, 0), vec4(29, 30, 31, 1)); + + mat4 c = a * b; + mat_affine aff_c(c); + mat_affine aff_a(a); + mat_affine aff_b(b); + + mat_affine res; + Granite::SIMD::mul(res, aff_a, aff_b); + assert_equal_epsilon(res, aff_c, 0.0f); +} + +static void test_affine_mul() +{ + mat4 a(vec4(1, 2, 3, 0), vec4(5, 6, 7, 0), + vec4(9, 10, 11, 0), vec4(13, 14, 15, 1)); + vec4 b(1, 2, 3, 1); + + mat_affine aff_a(a); + + vec4 ref = a * b; + vec4 res4, res_affine; + Granite::SIMD::mul(res4, a, b); + Granite::SIMD::mul(res_affine, aff_a, b); + + assert_equal_epsilon(ref, res4, 0.0f); + assert_equal_epsilon(ref, res_affine, 0.0f); +} + +static void test_aabb_transform() +{ + mat4 m(vec4(1, 2, 3, 0), vec4(5, 6, 7, 0), + vec4(9, 10, 11, 0), vec4(13, 14, 15, 1)); + + Granite::AABB aabb{vec3(-1, -2, -4), vec3(3, 7, 4)}; + + Granite::AABB reference_aabb, affine_aabb; + Granite::SIMD::transform_aabb(reference_aabb, aabb, m); + Granite::SIMD::transform_aabb(affine_aabb, aabb, mat_affine(m)); + + assert_equal_epsilon(reference_aabb.get_maximum4(), affine_aabb.get_maximum4(), 0.0f); + assert_equal_epsilon(reference_aabb.get_minimum4(), affine_aabb.get_minimum4(), 0.0f); +} + +int main() +{ + test_mat2(); + test_mat3(); + test_mat4(); + test_quat(); + test_decompose(); + test_transpose(); + test_affine(); + test_affine_mul(); + test_aabb_transform(); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/render_parameters.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/render_parameters.hpp new file mode 100644 index 00000000..81e6a773 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/render_parameters.hpp @@ -0,0 +1,196 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "math.hpp" +#include "image.hpp" +#include "lights/light_info.hpp" +#include "limits.hpp" + +namespace Granite +{ +class LightClusterer; +class VolumetricFog; +class VolumetricDiffuseLightManager; +enum { NumShadowCascades = 4 }; + +struct RenderParameters +{ + mat4 projection; + mat4 view; + mat4 view_projection; + mat4 inv_projection; + mat4 inv_view; + mat4 inv_view_projection; + mat4 local_view_projection; + mat4 inv_local_view_projection; + + mat4 unjittered_view_projection; + mat4 unjittered_inv_view_projection; + mat4 unjittered_prev_view_projection; + + alignas(16) vec3 camera_position; + alignas(16) vec3 camera_front; + alignas(16) vec3 camera_right; + alignas(16) vec3 camera_up; + + float z_near; + float z_far; +}; + +struct ResolutionParameters +{ + alignas(8) vec2 resolution; + alignas(8) vec2 inv_resolution; +}; + +struct VolumetricFogParameters +{ + float slice_z_log2_scale; +}; + +struct FogParameters +{ + alignas(16) vec3 color; + float falloff; +}; + +struct DirectionalParameters +{ + alignas(16) vec3 color; + alignas(16) vec3 direction; +}; + +struct ShadowParameters +{ + alignas(16) mat4 transforms[NumShadowCascades]; + float cascade_log_bias; +}; + +struct ClustererParametersBindless +{ + alignas(16) mat4 transform; + alignas(16) vec4 clip_scale; + alignas(16) vec3 camera_base; + alignas(16) vec3 camera_front; + + alignas(8) vec2 xy_scale; + alignas(8) ivec2 resolution_xy; + alignas(8) vec2 inv_resolution_xy; + + uint32_t num_lights; + uint32_t num_lights_32; + uint32_t num_decals; + uint32_t num_decals_32; + uint32_t decals_texture_offset; + uint32_t z_max_index; + float z_scale; +}; + +struct DiffuseVolumeParameters +{ + mat_affine world_to_texture; + vec4 world_lo; + vec4 world_hi; + float lo_tex_coord_x; + float hi_tex_coord_x; + float guard_band_factor; + float guard_band_sharpen; +}; + +#define CLUSTERER_MAX_VOLUMES 128 +struct ClustererParametersVolumetric +{ + alignas(16) muglm::vec3 sun_direction; + uint32_t bindless_index_offset; + alignas(16) muglm::vec3 sun_color; + uint32_t num_volumes; + alignas(16) DiffuseVolumeParameters volumes[CLUSTERER_MAX_VOLUMES]; +}; + +struct FogRegionParameters +{ + mat_affine world_to_texture; + vec4 world_lo; + vec4 world_hi; +}; + +#define CLUSTERER_MAX_FOG_REGIONS 128 +struct ClustererParametersFogRegions +{ + uint32_t bindless_index_offset; + uint32_t num_regions; + alignas(16) FogRegionParameters regions[CLUSTERER_MAX_FOG_REGIONS]; +}; + +#define CLUSTERER_MAX_LIGHTS_BINDLESS 4096 +#define CLUSTERER_MAX_DECALS_BINDLESS 4096 +#define CLUSTERER_MAX_LIGHTS_GLOBAL 32 + +struct BindlessDecalTransform +{ + mat_affine world_to_texture; +}; + +struct ClustererBindlessTransforms +{ + PositionalFragmentInfo lights[CLUSTERER_MAX_LIGHTS_BINDLESS]; + mat4 shadow[CLUSTERER_MAX_LIGHTS_BINDLESS]; + mat_affine model[CLUSTERER_MAX_LIGHTS_BINDLESS]; + uint32_t type_mask[CLUSTERER_MAX_LIGHTS_BINDLESS / 32]; + BindlessDecalTransform decals[CLUSTERER_MAX_DECALS_BINDLESS]; +}; + +struct ClustererGlobalTransforms +{ + alignas(16) PositionalFragmentInfo lights[CLUSTERER_MAX_LIGHTS_GLOBAL]; + alignas(16) mat4 shadow[CLUSTERER_MAX_LIGHTS_GLOBAL]; + alignas(16) uint32_t type_mask[CLUSTERER_MAX_LIGHTS_GLOBAL / 32]; + uint32_t descriptor_offset; + uint32_t num_lights; +}; +static_assert(sizeof(ClustererGlobalTransforms) <= Vulkan::VULKAN_MAX_UBO_SIZE, "Global transforms is too large."); + +struct CombinedRenderParameters +{ + alignas(16) FogParameters fog; + alignas(16) ShadowParameters shadow; + alignas(16) VolumetricFogParameters volumetric_fog; + alignas(16) DirectionalParameters directional; + alignas(16) ResolutionParameters resolution; +}; +static_assert(sizeof(CombinedRenderParameters) <= Vulkan::VULKAN_MAX_UBO_SIZE, "CombinedRenderParameters cannot fit in min-spec."); + +struct LightingParameters +{ + FogParameters fog = {}; + DirectionalParameters directional; + ShadowParameters shadow; + + Vulkan::ImageView *shadows = nullptr; + Vulkan::ImageView *ambient_occlusion = nullptr; + const LightClusterer *cluster = nullptr; + const VolumetricFog *volumetric_fog = nullptr; + const VolumetricDiffuseLightManager *volumetric_diffuse = nullptr; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/simd.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/simd.hpp new file mode 100644 index 00000000..aee63d10 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/simd.hpp @@ -0,0 +1,602 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "math.hpp" +#include "aabb.hpp" +#include "simd_headers.hpp" +#include "muglm/matrix_helper.hpp" + +namespace Granite +{ +namespace SIMD +{ +static inline bool frustum_cull(const AABB &aabb, const vec4 *planes) +{ +#if defined(__SSE3__) + __m128 lo = _mm_loadu_ps(aabb.get_minimum4().data); + __m128 hi = _mm_loadu_ps(aabb.get_maximum4().data); + +#define COMPUTE_PLANE(i) \ + __m128 p##i = _mm_loadu_ps(planes[i].data); \ + __m128 mask##i = _mm_cmpgt_ps(p##i, _mm_setzero_ps()); \ + __m128 major_axis##i = _mm_or_ps(_mm_and_ps(mask##i, hi), _mm_andnot_ps(mask##i, lo)); \ + __m128 dotted##i = _mm_mul_ps(p##i, major_axis##i) + COMPUTE_PLANE(0); + COMPUTE_PLANE(1); + COMPUTE_PLANE(2); + COMPUTE_PLANE(3); + COMPUTE_PLANE(4); + COMPUTE_PLANE(5); + + __m128 merged01 = _mm_hadd_ps(dotted0, dotted1); + __m128 merged23 = _mm_hadd_ps(dotted2, dotted3); + __m128 merged45 = _mm_hadd_ps(dotted4, dotted5); + __m128 merged0123 = _mm_hadd_ps(merged01, merged23); + merged45 = _mm_hadd_ps(merged45, merged45); + __m128 merged = _mm_or_ps(merged0123, merged45); + // Sets bit if the sign bit is set. + int mask = _mm_movemask_ps(merged); + return mask == 0; +#elif defined(__ARM_NEON) + float32x4_t lo = vld1q_f32(aabb.get_minimum4().data); + float32x4_t hi = vld1q_f32(aabb.get_maximum4().data); + +#define COMPUTE_PLANE(i) \ + float32x4_t p##i = vld1q_f32(planes[i].data); \ + uint32x4_t mask##i = vcgtq_f32(p##i, vdupq_n_f32(0.0f)); \ + float32x4_t major_axis##i = vbslq_f32(mask##i, hi, lo); \ + float32x4_t dotted##i = vmulq_f32(p##i, major_axis##i) + COMPUTE_PLANE(0); + COMPUTE_PLANE(1); + COMPUTE_PLANE(2); + COMPUTE_PLANE(3); + COMPUTE_PLANE(4); + COMPUTE_PLANE(5); + +#if defined(__aarch64__) + float32x4_t merged01 = vpaddq_f32(dotted0, dotted1); + float32x4_t merged23 = vpaddq_f32(dotted2, dotted3); + float32x4_t merged45 = vpaddq_f32(dotted4, dotted5); + float32x4_t merged0123 = vpaddq_f32(merged01, merged23); + merged45 = vpaddq_f32(merged45, merged45); + float32x4_t merged = vminq_f32(merged0123, merged45); + float32x2_t merged_half = vmin_f32(vget_low_f32(merged), vget_high_f32(merged)); + merged_half = vpmin_f32(merged_half, merged_half); + return vget_lane_f32(merged_half, 0) >= 0.0f; +#else + float32x2_t merged0 = vpadd_f32(vget_low_f32(dotted0), vget_high_f32(dotted0)); + float32x2_t merged1 = vpadd_f32(vget_low_f32(dotted1), vget_high_f32(dotted1)); + float32x2_t merged2 = vpadd_f32(vget_low_f32(dotted2), vget_high_f32(dotted2)); + float32x2_t merged3 = vpadd_f32(vget_low_f32(dotted3), vget_high_f32(dotted3)); + float32x2_t merged4 = vpadd_f32(vget_low_f32(dotted4), vget_high_f32(dotted4)); + float32x2_t merged5 = vpadd_f32(vget_low_f32(dotted5), vget_high_f32(dotted5)); + float32x2_t merged01 = vpadd_f32(merged0, merged1); + float32x2_t merged23 = vpadd_f32(merged2, merged3); + float32x2_t merged45 = vpadd_f32(merged4, merged5); + float32x2_t merged = vmin_f32(merged01, merged23); + merged = vmin_f32(merged, merged45); + float32x2_t merged_half = vpmin_f32(merged, merged); + return vget_lane_f32(merged_half, 0) >= 0.0f; +#endif +#else +#error "Implement me." +#endif +} + +static inline void mul(vec4 &c, const mat_affine &a, const vec4 &b) +{ +#if defined(__SSE4_1__) + __m128 a0 = _mm_loadu_ps(a[0].data); + __m128 a1 = _mm_loadu_ps(a[1].data); + __m128 a2 = _mm_loadu_ps(a[2].data); + __m128 b0 = _mm_loadu_ps(b.data); + __m128 r0 = _mm_dp_ps(a0, b0, 0xf1); + __m128 r1 = _mm_dp_ps(a1, b0, 0xf2); + __m128 r2 = _mm_dp_ps(a2, b0, 0xf4); + __m128 r = _mm_or_ps(_mm_or_ps(r0, r1), r2); + r = _mm_insert_ps(r, _mm_set_ss(1.0f), 0x30); + _mm_storeu_ps(c.data, r); +#elif defined(__SSE__) + __m128 a0 = _mm_loadu_ps(a[0].data); + __m128 a1 = _mm_loadu_ps(a[1].data); + __m128 a2 = _mm_loadu_ps(a[2].data); + __m128 a3 = _mm_set_ps(1, 0, 0, 0); + _MM_TRANSPOSE4_PS(a0, a1, a2, a3); + __m128 b0 = _mm_loadu_ps(b.data); + + __m128 b00 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 b01 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 b02 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 b03 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 col0 = _mm_mul_ps(a0, b00); + col0 = _mm_add_ps(col0, _mm_mul_ps(a1, b01)); + col0 = _mm_add_ps(col0, _mm_mul_ps(a2, b02)); + col0 = _mm_add_ps(col0, _mm_mul_ps(a3, b03)); + + _mm_storeu_ps(c.data, col0); +#elif defined(__aarch64__) + alignas(16) static const float a3_data[] = { 0, 0, 0, 1 }; + float32x4_t a0 = vld1q_f32(a[0].data); + float32x4_t a1 = vld1q_f32(a[1].data); + float32x4_t a2 = vld1q_f32(a[2].data); + float32x4_t a3 = vld1q_f32(a3_data); + + // From sse2neon.h + float64x2_t r0 = (float64x2_t)vtrn1q_f32(a0, a1); + float64x2_t r1 = (float64x2_t)vtrn2q_f32(a0, a1); + float64x2_t r2 = (float64x2_t)vtrn1q_f32(a2, a3); + float64x2_t r3 = (float64x2_t)vtrn2q_f32(a2, a3); + + a0 = (float32x4_t)vtrn1q_f64(r0, r2); + a1 = (float32x4_t)vtrn1q_f64(r1, r3); + a2 = (float32x4_t)vtrn2q_f64(r0, r2); + a3 = (float32x4_t)vtrn2q_f64(r1, r3); + + float32x4_t b0 = vld1q_f32(b.data); + + float32x4_t col0 = vmulq_n_f32(a0, vgetq_lane_f32(b0, 0)); + col0 = vmlaq_n_f32(col0, a1, vgetq_lane_f32(b0, 1)); + col0 = vmlaq_n_f32(col0, a2, vgetq_lane_f32(b0, 2)); + col0 = vmlaq_n_f32(col0, a3, vgetq_lane_f32(b0, 3)); + + vst1q_f32(c.data, col0); +#else + c = transpose(mat4(a[0], a[1], a[2], vec4(0, 0, 0, 1))) * b; +#endif +} + +static inline void mul(vec4 &c, const mat4 &a, const vec4 &b) +{ +#if defined(__SSE__) + __m128 a0 = _mm_loadu_ps(a[0].data); + __m128 a1 = _mm_loadu_ps(a[1].data); + __m128 a2 = _mm_loadu_ps(a[2].data); + __m128 a3 = _mm_loadu_ps(a[3].data); + __m128 b0 = _mm_loadu_ps(b.data); + + __m128 b00 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 b01 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 b02 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 b03 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 col0 = _mm_mul_ps(a0, b00); + col0 = _mm_add_ps(col0, _mm_mul_ps(a1, b01)); + col0 = _mm_add_ps(col0, _mm_mul_ps(a2, b02)); + col0 = _mm_add_ps(col0, _mm_mul_ps(a3, b03)); + + _mm_storeu_ps(c.data, col0); +#elif defined(__ARM_NEON) + float32x4_t a0 = vld1q_f32(a[0].data); + float32x4_t a1 = vld1q_f32(a[1].data); + float32x4_t a2 = vld1q_f32(a[2].data); + float32x4_t a3 = vld1q_f32(a[3].data); + float32x4_t b0 = vld1q_f32(b.data); + + float32x4_t col0 = vmulq_n_f32(a0, vgetq_lane_f32(b0, 0)); + col0 = vmlaq_n_f32(col0, a1, vgetq_lane_f32(b0, 1)); + col0 = vmlaq_n_f32(col0, a2, vgetq_lane_f32(b0, 2)); + col0 = vmlaq_n_f32(col0, a3, vgetq_lane_f32(b0, 3)); + + vst1q_f32(c.data, col0); +#else + c = a * b; +#endif +} + +static inline void mul(mat_affine &c, const mat_affine &a, const mat_affine &b) +{ +#if defined(__SSE__) + // Swap the arguments to allow treating the multiplication as column-major. + __m128 a0 = _mm_loadu_ps(b[0].data); + __m128 a1 = _mm_loadu_ps(b[1].data); + __m128 a2 = _mm_loadu_ps(b[2].data); + __m128 b0 = _mm_loadu_ps(a[0].data); + __m128 b1 = _mm_loadu_ps(a[1].data); + __m128 b2 = _mm_loadu_ps(a[2].data); + const __m128 a3 = _mm_set_ps(1, 0, 0, 0); + + __m128 b00 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 b01 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 b02 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 b03 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 col0 = _mm_mul_ps(a0, b00); + col0 = _mm_add_ps(col0, _mm_mul_ps(a1, b01)); + col0 = _mm_add_ps(col0, _mm_mul_ps(a2, b02)); + col0 = _mm_add_ps(col0, _mm_mul_ps(a3, b03)); + __m128 b10 = _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 b11 = _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 b12 = _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 b13 = _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 col1 = _mm_mul_ps(a0, b10); + col1 = _mm_add_ps(col1, _mm_mul_ps(a1, b11)); + col1 = _mm_add_ps(col1, _mm_mul_ps(a2, b12)); + col1 = _mm_add_ps(col1, _mm_mul_ps(a3, b13)); + + __m128 b20 = _mm_shuffle_ps(b2, b2, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 b21 = _mm_shuffle_ps(b2, b2, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 b22 = _mm_shuffle_ps(b2, b2, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 b23 = _mm_shuffle_ps(b2, b2, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 col2 = _mm_mul_ps(a0, b20); + col2 = _mm_add_ps(col2, _mm_mul_ps(a1, b21)); + col2 = _mm_add_ps(col2, _mm_mul_ps(a2, b22)); + col2 = _mm_add_ps(col2, _mm_mul_ps(a3, b23)); + + _mm_storeu_ps(c[0].data, col0); + _mm_storeu_ps(c[1].data, col1); + _mm_storeu_ps(c[2].data, col2); + +#elif defined(__ARM_NEON) + alignas(16) static const float a3_data[] = { 0, 0, 0, 1 }; + float32x4_t a0 = vld1q_f32(b[0].data); + float32x4_t a1 = vld1q_f32(b[1].data); + float32x4_t a2 = vld1q_f32(b[2].data); + float32x4_t a3 = vld1q_f32(a3_data); + float32x4_t b0 = vld1q_f32(a[0].data); + float32x4_t b1 = vld1q_f32(a[1].data); + float32x4_t b2 = vld1q_f32(a[2].data); + + float32x4_t col0 = vmulq_n_f32(a0, vgetq_lane_f32(b0, 0)); + float32x4_t col1 = vmulq_n_f32(a0, vgetq_lane_f32(b1, 0)); + float32x4_t col2 = vmulq_n_f32(a0, vgetq_lane_f32(b2, 0)); + + col0 = vmlaq_n_f32(col0, a1, vgetq_lane_f32(b0, 1)); + col1 = vmlaq_n_f32(col1, a1, vgetq_lane_f32(b1, 1)); + col2 = vmlaq_n_f32(col2, a1, vgetq_lane_f32(b2, 1)); + + col0 = vmlaq_n_f32(col0, a2, vgetq_lane_f32(b0, 2)); + col1 = vmlaq_n_f32(col1, a2, vgetq_lane_f32(b1, 2)); + col2 = vmlaq_n_f32(col2, a2, vgetq_lane_f32(b2, 2)); + + col0 = vmlaq_n_f32(col0, a3, vgetq_lane_f32(b0, 3)); + col1 = vmlaq_n_f32(col1, a3, vgetq_lane_f32(b1, 3)); + col2 = vmlaq_n_f32(col2, a3, vgetq_lane_f32(b2, 3)); + + vst1q_f32(c[0].data, col0); + vst1q_f32(c[1].data, col1); + vst1q_f32(c[2].data, col2); +#else + mat4 a4(a[0], a[1], a[2], vec4(0.0f, 0.0f, 0.0f, 1.0f)); + mat4 b4(b[0], b[1], b[2], vec4(0.0f, 0.0f, 0.0f, 1.0f)); + mat4 c4 = b4 * a4; + for (int i = 0; i < 3; i++) + c[i] = c4[i]; +#endif +} + +static inline void mul(mat4 &c, const mat4 &a, const mat4 &b) +{ +#if defined(__SSE__) + __m128 a0 = _mm_loadu_ps(a[0].data); + __m128 a1 = _mm_loadu_ps(a[1].data); + __m128 a2 = _mm_loadu_ps(a[2].data); + __m128 a3 = _mm_loadu_ps(a[3].data); + __m128 b0 = _mm_loadu_ps(b[0].data); + __m128 b1 = _mm_loadu_ps(b[1].data); + __m128 b2 = _mm_loadu_ps(b[2].data); + __m128 b3 = _mm_loadu_ps(b[3].data); + + __m128 b00 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 b01 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 b02 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 b03 = _mm_shuffle_ps(b0, b0, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 col0 = _mm_mul_ps(a0, b00); + col0 = _mm_add_ps(col0, _mm_mul_ps(a1, b01)); + col0 = _mm_add_ps(col0, _mm_mul_ps(a2, b02)); + col0 = _mm_add_ps(col0, _mm_mul_ps(a3, b03)); + + __m128 b10 = _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 b11 = _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 b12 = _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 b13 = _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 col1 = _mm_mul_ps(a0, b10); + col1 = _mm_add_ps(col1, _mm_mul_ps(a1, b11)); + col1 = _mm_add_ps(col1, _mm_mul_ps(a2, b12)); + col1 = _mm_add_ps(col1, _mm_mul_ps(a3, b13)); + + __m128 b20 = _mm_shuffle_ps(b2, b2, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 b21 = _mm_shuffle_ps(b2, b2, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 b22 = _mm_shuffle_ps(b2, b2, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 b23 = _mm_shuffle_ps(b2, b2, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 col2 = _mm_mul_ps(a0, b20); + col2 = _mm_add_ps(col2, _mm_mul_ps(a1, b21)); + col2 = _mm_add_ps(col2, _mm_mul_ps(a2, b22)); + col2 = _mm_add_ps(col2, _mm_mul_ps(a3, b23)); + + __m128 b30 = _mm_shuffle_ps(b3, b3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 b31 = _mm_shuffle_ps(b3, b3, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 b32 = _mm_shuffle_ps(b3, b3, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 b33 = _mm_shuffle_ps(b3, b3, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 col3 = _mm_mul_ps(a0, b30); + col3 = _mm_add_ps(col3, _mm_mul_ps(a1, b31)); + col3 = _mm_add_ps(col3, _mm_mul_ps(a2, b32)); + col3 = _mm_add_ps(col3, _mm_mul_ps(a3, b33)); + + _mm_storeu_ps(c[0].data, col0); + _mm_storeu_ps(c[1].data, col1); + _mm_storeu_ps(c[2].data, col2); + _mm_storeu_ps(c[3].data, col3); +#elif defined(__ARM_NEON) + float32x4_t a0 = vld1q_f32(a[0].data); + float32x4_t a1 = vld1q_f32(a[1].data); + float32x4_t a2 = vld1q_f32(a[2].data); + float32x4_t a3 = vld1q_f32(a[3].data); + float32x4_t b0 = vld1q_f32(b[0].data); + float32x4_t b1 = vld1q_f32(b[1].data); + float32x4_t b2 = vld1q_f32(b[2].data); + float32x4_t b3 = vld1q_f32(b[3].data); + + float32x4_t col0 = vmulq_n_f32(a0, vgetq_lane_f32(b0, 0)); + float32x4_t col1 = vmulq_n_f32(a0, vgetq_lane_f32(b1, 0)); + float32x4_t col2 = vmulq_n_f32(a0, vgetq_lane_f32(b2, 0)); + float32x4_t col3 = vmulq_n_f32(a0, vgetq_lane_f32(b3, 0)); + + col0 = vmlaq_n_f32(col0, a1, vgetq_lane_f32(b0, 1)); + col1 = vmlaq_n_f32(col1, a1, vgetq_lane_f32(b1, 1)); + col2 = vmlaq_n_f32(col2, a1, vgetq_lane_f32(b2, 1)); + col3 = vmlaq_n_f32(col3, a1, vgetq_lane_f32(b3, 1)); + + col0 = vmlaq_n_f32(col0, a2, vgetq_lane_f32(b0, 2)); + col1 = vmlaq_n_f32(col1, a2, vgetq_lane_f32(b1, 2)); + col2 = vmlaq_n_f32(col2, a2, vgetq_lane_f32(b2, 2)); + col3 = vmlaq_n_f32(col3, a2, vgetq_lane_f32(b3, 2)); + + col0 = vmlaq_n_f32(col0, a3, vgetq_lane_f32(b0, 3)); + col1 = vmlaq_n_f32(col1, a3, vgetq_lane_f32(b1, 3)); + col2 = vmlaq_n_f32(col2, a3, vgetq_lane_f32(b2, 3)); + col3 = vmlaq_n_f32(col3, a3, vgetq_lane_f32(b3, 3)); + + vst1q_f32(c[0].data, col0); + vst1q_f32(c[1].data, col1); + vst1q_f32(c[2].data, col2); + vst1q_f32(c[3].data, col3); +#else + c = a * b; +#endif +} + +static inline void transform_aabb(AABB &output, const AABB &aabb, const mat_affine &m) +{ +#if defined(__SSE__) + __m128 lo = _mm_loadu_ps(aabb.get_minimum4().data); + __m128 hi = _mm_loadu_ps(aabb.get_maximum4().data); + + __m128 m0 = _mm_loadu_ps(m[0].data); + __m128 m1 = _mm_loadu_ps(m[1].data); + __m128 m2 = _mm_loadu_ps(m[2].data); + __m128 m3 = _mm_set_ps(1, 0, 0, 0); + _MM_TRANSPOSE4_PS(m0, m1, m2, m3); + + __m128 m0_pos = _mm_cmpgt_ps(m0, _mm_setzero_ps()); + __m128 m1_pos = _mm_cmpgt_ps(m1, _mm_setzero_ps()); + __m128 m2_pos = _mm_cmpgt_ps(m2, _mm_setzero_ps()); + + __m128 hi0 = _mm_shuffle_ps(hi, hi, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 hi1 = _mm_shuffle_ps(hi, hi, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 hi2 = _mm_shuffle_ps(hi, hi, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 lo0 = _mm_shuffle_ps(lo, lo, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 lo1 = _mm_shuffle_ps(lo, lo, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 lo2 = _mm_shuffle_ps(lo, lo, _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 hi_result = m3; + hi_result = _mm_add_ps(hi_result, _mm_mul_ps(m0, _mm_or_ps(_mm_and_ps(m0_pos, hi0), _mm_andnot_ps(m0_pos, lo0)))); + hi_result = _mm_add_ps(hi_result, _mm_mul_ps(m1, _mm_or_ps(_mm_and_ps(m1_pos, hi1), _mm_andnot_ps(m1_pos, lo1)))); + hi_result = _mm_add_ps(hi_result, _mm_mul_ps(m2, _mm_or_ps(_mm_and_ps(m2_pos, hi2), _mm_andnot_ps(m2_pos, lo2)))); + + __m128 lo_result = m3; + lo_result = _mm_add_ps(lo_result, _mm_mul_ps(m0, _mm_or_ps(_mm_andnot_ps(m0_pos, hi0), _mm_and_ps(m0_pos, lo0)))); + lo_result = _mm_add_ps(lo_result, _mm_mul_ps(m1, _mm_or_ps(_mm_andnot_ps(m1_pos, hi1), _mm_and_ps(m1_pos, lo1)))); + lo_result = _mm_add_ps(lo_result, _mm_mul_ps(m2, _mm_or_ps(_mm_andnot_ps(m2_pos, hi2), _mm_and_ps(m2_pos, lo2)))); + + _mm_storeu_ps(output.get_minimum4().data, lo_result); + _mm_storeu_ps(output.get_maximum4().data, hi_result); +#elif defined(__aarch64__) + alignas(16) static const float m3_data[] = { 0, 0, 0, 1 }; + float32x4_t lo = vld1q_f32(aabb.get_minimum4().data); + float32x4_t hi = vld1q_f32(aabb.get_maximum4().data); + + float32x4_t m0 = vld1q_f32(m[0].data); + float32x4_t m1 = vld1q_f32(m[1].data); + float32x4_t m2 = vld1q_f32(m[2].data); + float32x4_t m3 = vld1q_f32(m3_data); + + // From sse2neon.h + float64x2_t r0 = (float64x2_t)vtrn1q_f32(m0, m1); + float64x2_t r1 = (float64x2_t)vtrn2q_f32(m0, m1); + float64x2_t r2 = (float64x2_t)vtrn1q_f32(m2, m3); + float64x2_t r3 = (float64x2_t)vtrn2q_f32(m2, m3); + + m0 = (float32x4_t)vtrn1q_f64(r0, r2); + m1 = (float32x4_t)vtrn1q_f64(r1, r3); + m2 = (float32x4_t)vtrn2q_f64(r0, r2); + m3 = (float32x4_t)vtrn2q_f64(r1, r3); + + uint32x4_t m0_pos = vcgtq_f32(m0, vdupq_n_f32(0.0f)); + uint32x4_t m1_pos = vcgtq_f32(m1, vdupq_n_f32(0.0f)); + uint32x4_t m2_pos = vcgtq_f32(m2, vdupq_n_f32(0.0f)); + + float32x4_t lo0 = vdupq_lane_f32(vget_low_f32(lo), 0); + float32x4_t lo1 = vdupq_lane_f32(vget_low_f32(lo), 1); + float32x4_t lo2 = vdupq_lane_f32(vget_high_f32(lo), 0); + float32x4_t hi0 = vdupq_lane_f32(vget_low_f32(hi), 0); + float32x4_t hi1 = vdupq_lane_f32(vget_low_f32(hi), 1); + float32x4_t hi2 = vdupq_lane_f32(vget_high_f32(hi), 0); + + float32x4_t hi_result = m3; + hi_result = vmlaq_f32(hi_result, m0, vbslq_f32(m0_pos, hi0, lo0)); + hi_result = vmlaq_f32(hi_result, m1, vbslq_f32(m1_pos, hi1, lo1)); + hi_result = vmlaq_f32(hi_result, m2, vbslq_f32(m2_pos, hi2, lo2)); + + float32x4_t lo_result = m3; + lo_result = vmlaq_f32(lo_result, m0, vbslq_f32(m0_pos, lo0, hi0)); + lo_result = vmlaq_f32(lo_result, m1, vbslq_f32(m1_pos, lo1, hi1)); + lo_result = vmlaq_f32(lo_result, m2, vbslq_f32(m2_pos, lo2, hi2)); + + vst1q_f32(output.get_minimum4().data, lo_result); + vst1q_f32(output.get_maximum4().data, hi_result); +#else + output = aabb.transform(transpose(mat4(m[0], m[1], m[2], vec4(0, 0, 0, 1)))); +#endif +} + +static inline void transform_aabb(AABB &output, const AABB &aabb, const mat4 &m) +{ +#if defined(__SSE__) + __m128 lo = _mm_loadu_ps(aabb.get_minimum4().data); + __m128 hi = _mm_loadu_ps(aabb.get_maximum4().data); + + __m128 m0 = _mm_loadu_ps(m[0].data); + __m128 m1 = _mm_loadu_ps(m[1].data); + __m128 m2 = _mm_loadu_ps(m[2].data); + __m128 m3 = _mm_loadu_ps(m[3].data); + + __m128 m0_pos = _mm_cmpgt_ps(m0, _mm_setzero_ps()); + __m128 m1_pos = _mm_cmpgt_ps(m1, _mm_setzero_ps()); + __m128 m2_pos = _mm_cmpgt_ps(m2, _mm_setzero_ps()); + + __m128 hi0 = _mm_shuffle_ps(hi, hi, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 hi1 = _mm_shuffle_ps(hi, hi, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 hi2 = _mm_shuffle_ps(hi, hi, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 lo0 = _mm_shuffle_ps(lo, lo, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 lo1 = _mm_shuffle_ps(lo, lo, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 lo2 = _mm_shuffle_ps(lo, lo, _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 hi_result = m3; + hi_result = _mm_add_ps(hi_result, _mm_mul_ps(m0, _mm_or_ps(_mm_and_ps(m0_pos, hi0), _mm_andnot_ps(m0_pos, lo0)))); + hi_result = _mm_add_ps(hi_result, _mm_mul_ps(m1, _mm_or_ps(_mm_and_ps(m1_pos, hi1), _mm_andnot_ps(m1_pos, lo1)))); + hi_result = _mm_add_ps(hi_result, _mm_mul_ps(m2, _mm_or_ps(_mm_and_ps(m2_pos, hi2), _mm_andnot_ps(m2_pos, lo2)))); + + __m128 lo_result = m3; + lo_result = _mm_add_ps(lo_result, _mm_mul_ps(m0, _mm_or_ps(_mm_andnot_ps(m0_pos, hi0), _mm_and_ps(m0_pos, lo0)))); + lo_result = _mm_add_ps(lo_result, _mm_mul_ps(m1, _mm_or_ps(_mm_andnot_ps(m1_pos, hi1), _mm_and_ps(m1_pos, lo1)))); + lo_result = _mm_add_ps(lo_result, _mm_mul_ps(m2, _mm_or_ps(_mm_andnot_ps(m2_pos, hi2), _mm_and_ps(m2_pos, lo2)))); + + _mm_storeu_ps(output.get_minimum4().data, lo_result); + _mm_storeu_ps(output.get_maximum4().data, hi_result); +#elif defined(__ARM_NEON) + float32x4_t lo = vld1q_f32(aabb.get_minimum4().data); + float32x4_t hi = vld1q_f32(aabb.get_maximum4().data); + + float32x4_t m0 = vld1q_f32(m[0].data); + float32x4_t m1 = vld1q_f32(m[1].data); + float32x4_t m2 = vld1q_f32(m[2].data); + float32x4_t m3 = vld1q_f32(m[3].data); + + uint32x4_t m0_pos = vcgtq_f32(m0, vdupq_n_f32(0.0f)); + uint32x4_t m1_pos = vcgtq_f32(m1, vdupq_n_f32(0.0f)); + uint32x4_t m2_pos = vcgtq_f32(m2, vdupq_n_f32(0.0f)); + + float32x4_t lo0 = vdupq_lane_f32(vget_low_f32(lo), 0); + float32x4_t lo1 = vdupq_lane_f32(vget_low_f32(lo), 1); + float32x4_t lo2 = vdupq_lane_f32(vget_high_f32(lo), 0); + float32x4_t hi0 = vdupq_lane_f32(vget_low_f32(hi), 0); + float32x4_t hi1 = vdupq_lane_f32(vget_low_f32(hi), 1); + float32x4_t hi2 = vdupq_lane_f32(vget_high_f32(hi), 0); + + float32x4_t hi_result = m3; + hi_result = vmlaq_f32(hi_result, m0, vbslq_f32(m0_pos, hi0, lo0)); + hi_result = vmlaq_f32(hi_result, m1, vbslq_f32(m1_pos, hi1, lo1)); + hi_result = vmlaq_f32(hi_result, m2, vbslq_f32(m2_pos, hi2, lo2)); + + float32x4_t lo_result = m3; + lo_result = vmlaq_f32(lo_result, m0, vbslq_f32(m0_pos, lo0, hi0)); + lo_result = vmlaq_f32(lo_result, m1, vbslq_f32(m1_pos, lo1, hi1)); + lo_result = vmlaq_f32(lo_result, m2, vbslq_f32(m2_pos, lo2, hi2)); + + vst1q_f32(output.get_minimum4().data, lo_result); + vst1q_f32(output.get_maximum4().data, hi_result); +#else + output = aabb.transform(m); +#endif +} + +template +static inline void transform_and_expand_aabb(AABB &expandee, const AABB &aabb, const T &m) +{ + alignas(16) AABB tmp; + transform_aabb(tmp, aabb, m); +#if defined(__SSE__) + __m128 lo = _mm_min_ps(_mm_load_ps(tmp.get_minimum4().data), _mm_loadu_ps(expandee.get_minimum4().data)); + __m128 hi = _mm_max_ps(_mm_load_ps(tmp.get_maximum4().data), _mm_loadu_ps(expandee.get_maximum4().data)); + _mm_storeu_ps(expandee.get_minimum4().data, lo); + _mm_storeu_ps(expandee.get_maximum4().data, hi); +#elif defined(__ARM_NEON) + float32x4_t lo = vminq_f32(vld1q_f32(tmp.get_minimum4().data), vld1q_f32(expandee.get_minimum4().data)); + float32x4_t hi = vmaxq_f32(vld1q_f32(tmp.get_maximum4().data), vld1q_f32(expandee.get_maximum4().data)); + vst1q_f32(expandee.get_minimum4().data, lo); + vst1q_f32(expandee.get_maximum4().data, hi); +#else + auto &output_min = expandee.get_minimum4(); + auto &output_max = expandee.get_maximum4(); + output_min = min(output_min, tmp.get_minimum4()); + output_max = max(output_max, tmp.get_maximum4()); +#endif +} + +static inline void convert_quaternion_with_scale(vec4 *cols, const quat &q, const vec3 &scale) +{ +#if defined(__SSE3__) + __m128 quat = _mm_loadu_ps(q.as_vec4().data); + +#define SHUF(x, y, z) _mm_shuffle_ps(quat, quat, _MM_SHUFFLE(z, y, x, 3)) + __m128 q_yy_xz_xy = _mm_mul_ps(SHUF(1, 0, 0), SHUF(1, 2, 1)); + __m128 q_zz_wy_wz = _mm_mul_ps(SHUF(2, 3, 3), SHUF(2, 1, 2)); + __m128 col0 = _mm_mul_ps(_mm_set_ps(+2.0f, +2.0f, -2.0f, 0.0f), _mm_addsub_ps(q_yy_xz_xy, q_zz_wy_wz)); + col0 = _mm_shuffle_ps(col0, col0, _MM_SHUFFLE(0, 2, 3, 1)); + col0 = _mm_add_ps(col0, _mm_set_ss(1.0f)); + col0 = _mm_mul_ps(col0, _mm_set1_ps(scale.x)); + _mm_storeu_ps(cols[0].data, col0); + + __m128 q_xx_xy_yz = _mm_mul_ps(SHUF(0, 0, 1), SHUF(0, 1, 2)); + __m128 q_zz_wz_wx = _mm_mul_ps(SHUF(2, 3, 3), SHUF(2, 2, 0)); + __m128 col1 = _mm_mul_ps(_mm_set_ps(2.0f, 2.0f, -2.0f, 0.0f), _mm_addsub_ps(q_xx_xy_yz, q_zz_wz_wx)); + col1 = _mm_shuffle_ps(col1, col1, _MM_SHUFFLE(0, 3, 1, 2)); + col1 = _mm_add_ps(col1, _mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f)); + col1 = _mm_mul_ps(col1, _mm_set1_ps(scale.y)); + _mm_storeu_ps(cols[1].data, col1); + + __m128 q_xz_yz_xx = _mm_mul_ps(SHUF(0, 1, 0), SHUF(2, 2, 0)); + __m128 q_wy_wx_yy = _mm_mul_ps(SHUF(3, 3, 1), SHUF(1, 0, 1)); + __m128 col2 = _mm_mul_ps(_mm_set_ps(-2.0f, 2.0f, 2.0f, 0.0f), _mm_addsub_ps(q_xz_yz_xx, q_wy_wx_yy)); + col2 = _mm_shuffle_ps(col2, col2, _MM_SHUFFLE(0, 3, 2, 1)); + col2 = _mm_add_ps(col2, _mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f)); + col2 = _mm_mul_ps(col2, _mm_set1_ps(scale.z)); + _mm_storeu_ps(cols[2].data, col2); +#undef SHUF +#else + mat3 m = muglm::mat3_cast(q); + cols[0] = vec4(m[0] * scale.x, 0.0f); + cols[1] = vec4(m[1] * scale.y, 0.0f); + cols[2] = vec4(m[2] * scale.z, 0.0f); +#endif +} +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/simd_headers.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/simd_headers.hpp new file mode 100644 index 00000000..8afa5059 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/simd_headers.hpp @@ -0,0 +1,48 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#ifdef _MSC_VER + +#include +#if defined(_INCLUDED_PMM) && !defined(__SSE3__) +#define __SSE3__ 1 +#endif +#if !defined(__SSE__) +#define __SSE__ 1 +#endif +#if defined(_INCLUDED_IMM) && !defined(__AVX__) +#define __AVX__ 1 +#endif + +#elif defined(__AVX__) +#include +#elif defined(__SSE4_1__) +#include +#elif defined(__SSE3__) +#include +#elif defined(__SSE__) +#include +#elif defined(__ARM_NEON) +#include +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/transforms.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/transforms.cpp new file mode 100644 index 00000000..ac0a9dc7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/transforms.cpp @@ -0,0 +1,371 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "transforms.hpp" +#include "aabb.hpp" +#include "simd.hpp" +#include "muglm/matrix_helper.hpp" +#include + +namespace Granite +{ +bool compute_plane_reflection(mat4 &projection, mat4 &view, vec3 camera_pos, vec3 center, vec3 normal, vec3 look_up, + float radius_up, float radius_other, float &z_near, float z_far) +{ + normal = normalize(normal); + + // Reflect the camera position from the plane. + float over_plane = dot(normal, camera_pos - center); + if (over_plane <= 0.0f) + return false; + + camera_pos -= 2.0f * over_plane * normal; + + // The look direction is up through the plane direction. + // This way we avoid skewed near and far planes (i.e. oblique). + // Make sure look_up is perpendicular to normal. + vec3 look_pos_x = normalize(cross(normal, look_up)); + look_up = normalize(cross(look_pos_x, normal)); + + view = mat4_cast(look_at(normal, look_up)) * translate(-camera_pos); + + float dist_x = dot(look_pos_x, center - camera_pos); + float left = dist_x - radius_other; + float right = dist_x + radius_other; + + float dist_y = dot(look_up, center - camera_pos); + float bottom = dist_y - radius_up; + float top = dist_y + radius_up; + + z_near = over_plane; + projection = frustum(left, right, bottom, top, over_plane, z_far); + if (z_near >= z_far) + return false; + return true; +} + +bool compute_plane_refraction(mat4 &projection, mat4 &view, vec3 camera_pos, vec3 center, vec3 normal, vec3 look_up, + float radius_up, float radius_other, float &z_near, float z_far) +{ + normal = normalize(normal); + + // Reflect the camera position from the plane. + float over_plane = dot(normal, camera_pos - center); + if (over_plane <= 0.0f) + return false; + + normal = -normal; + + // The look direction is up through the plane direction. + // This way we avoid skewed near and far planes (i.e. oblique). + // Make sure look_up is perpendicular to normal. + vec3 look_pos_x = normalize(cross(normal, look_up)); + look_up = normalize(cross(look_pos_x, normal)); + + view = mat4_cast(look_at(normal, look_up)) * translate(-camera_pos); + + float dist_x = dot(look_pos_x, center - camera_pos); + float left = dist_x - radius_other; + float right = dist_x + radius_other; + + float dist_y = dot(look_up, center - camera_pos); + float bottom = dist_y - radius_up; + float top = dist_y + radius_up; + + z_near = over_plane; + projection = frustum(left, right, bottom, top, over_plane, z_far); + if (z_near >= z_far) + return false; + return true; +} + +void compute_model_transform(mat_affine &world, vec3 s, quat rot, vec3 trans, const mat_affine &parent) +{ + // TODO: Make this more affine friendly. + mat4 model; + model[3] = vec4(trans, 1.0f); + SIMD::convert_quaternion_with_scale(&model[0], rot, s); + + SIMD::mul(world, parent, mat_affine(model)); +} + +void compute_normal_transform(mat4 &normal, const mat4 &world) +{ + normal = mat4(transpose(inverse(mat3(world)))); +} + +void compute_normal_transform(mat_affine &normal, const mat_affine &world) +{ + // Can be done better, but not important unless it gets used a lot. + normal = mat_affine(mat4(transpose(inverse(world.to_mat3())))); +} + +quat rotate_vector(vec3 from, vec3 to) +{ + from = normalize(from); + to = normalize(to); + + float cos_angle = dot(from, to); + if (abs(cos_angle) > 0.9999f) + { + if (cos_angle > 0.9999f) + return quat(1.0f, 0.0f, 0.0f, 0.0f); + else + { + vec3 rotation = cross(vec3(1.0f, 0.0f, 0.0f), from); + if (dot(rotation, rotation) > 0.001f) + rotation = normalize(rotation); + else + rotation = normalize(cross(vec3(0.0f, 1.0f, 0.0f), from)); + return quat(0.0f, rotation); + } + } + + vec3 rotation = normalize(cross(from, to)); + vec3 half_vector = normalize(from + to); + float cos_half_range = clamp(dot(half_vector, from), 0.0f, 1.0f); + float sin_half_angle = sqrtf(1.0f - cos_half_range * cos_half_range); + return quat(cos_half_range, rotation * sin_half_angle); +} + +quat rotate_vector_axis(vec3 from, vec3 to, vec3 axis) +{ + axis = normalize(axis); + from = normalize(cross(axis, from)); + to = normalize(cross(axis, to)); + + if (dot(to, from) < -0.9999f) + return quat(0.0f, axis); + + // Rotate CCW or CW, we only find the angle of rotation below. + float quat_sign = sign(dot(axis, cross(from, to))); + + vec3 half_vector = normalize(from + to); + float cos_half_range = clamp(dot(half_vector, from), 0.0f, 1.0f); + float sin_half_angle = quat_sign * sqrtf(1.0f - cos_half_range * cos_half_range); + return quat(cos_half_range, axis * sin_half_angle); +} + +quat look_at(vec3 direction, vec3 up) +{ + static const vec3 z(0.0f, 0.0f, -1.0f); + static const vec3 y(0.0f, 1.0f, 0.0f); + direction = normalize(direction); + vec3 right = cross(direction, up); + vec3 actual_up = cross(right, direction); + quat look_transform = rotate_vector(direction, z); + quat up_transform = rotate_vector_axis(look_transform * actual_up, y, z); + return up_transform * look_transform; +} + +quat look_at_arbitrary_up(vec3 direction) +{ + return rotate_vector(normalize(direction), vec3(0.0f, 0.0f, -1.0f)); +} + +mat4 projection(float fovy, float aspect, float znear, float zfar) +{ + return perspective(fovy, aspect, znear, zfar); +} + +mat4 ortho(const AABB &aabb) +{ + vec3 min = aabb.get_minimum(); + vec3 max = aabb.get_maximum(); + + // Flip Z for RH, ortho zNear/zFar is LH style. + std::swap(max.z, min.z); + max.z = -max.z; + min.z = -min.z; + + return muglm::ortho(min.x, max.x, min.y, max.y, min.z, max.z); +} + +void compute_cube_render_transform(vec3 center, unsigned face, mat4 &proj, mat4 &view, float znear, float zfar) +{ + static const vec3 dirs[6] = { + vec3(1.0f, 0.0f, 0.0f), + vec3(-1.0f, 0.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, 0.0f, 1.0f), + vec3(0.0f, 0.0f, -1.0f), + }; + + static const vec3 ups[6] = { + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 0.0f, -1.0f), + vec3(0.0f, 0.0f, +1.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + }; + + view = mat4_cast(look_at(dirs[face], ups[face])) * translate(-center); + proj = scale(vec3(-1.0f, 1.0f, 1.0f)) * projection(0.5f * pi(), 1.0f, znear, zfar); +} + +vec3 PositionalSampler::sample(unsigned index, float l) const +{ + if (l == 0.0f) + return values[index]; + else if (l == 1.0f) + return values[index + 1]; + + assert(index + 1 < values.size()); + return mix(values[index], values[index + 1], l); +} + +template +static T compute_cubic_spline(const std::vector &values, unsigned index, float t, float dt) +{ + assert(3 * index + 4 < values.size()); + T p0 = values[3 * index + 1]; + T p1 = values[3 * index + 4]; + + // For t == 0.0f, the result must be exactly on the point as specified by glTF. + if (t == 0.0f) + return p0; + else if (t == 1.0f) + return p1; + + T m0 = dt * values[3 * index + 2]; + T m1 = dt * values[3 * index + 3]; + + float t2 = t * t; + float t3 = t2 * t; + + return (2.0f * t3 - 3.0f * t2 + 1.0f) * p0 + + (t3 - 2.0f * t2 + t) * m0 + + (-2.0f * t3 + 3.0f * t2) * p1 + + (t3 - t2) * m1; +} + +vec3 PositionalSampler::sample_spline(unsigned index, float t, float dt) const +{ + return compute_cubic_spline(values, index, t, dt); +} + +quat SphericalSampler::sample(unsigned index, float l) const +{ + if (l == 0.0f) + return quat(values[index]); + else if (l == 1.0f) + return quat(values[index + 1]); + + assert(index + 1 < values.size()); + return slerp(quat(values[index]), quat(values[index + 1]), l); +} + +quat SphericalSampler::sample_spline(unsigned index, float t, float dt) const +{ + // CUBICSPLINE for quaternion is defined as simple vec4 interpolation with normalization. + return normalize(quat(compute_cubic_spline(values, index, t, dt))); +} + +// See math/docs/squad.md for more detail and derivation. + +quat SphericalSampler::sample_squad(unsigned index, float l) const +{ + assert(3 * index + 4 < values.size()); + + if (l == 0.0f) + return quat(values[3 * index + 1]); + else if (l == 1.0f) + return quat(values[3 * index + 4]); + + quat q0 = quat(values[3 * index + 1]); + quat cp0 = quat(values[3 * index + 2]); + quat cp1 = quat(values[3 * index + 3]); + quat q1 = quat(values[3 * index + 4]); + + return slerp_no_invert(slerp_no_invert(q0, q1, l), slerp_no_invert(cp0, cp1, l), 2.0f * l * (1.0f - l)); +} + +quat compute_inner_control_point(const quat &q, const vec3 &delta) +{ + return q * quat_exp(-delta); +} + +vec3 compute_inner_control_point_delta(const quat &q0, const quat &q1, const quat &q2, + float dt0, float dt1) +{ + // This is almost gibberish, as this is just copy-pastaed from various implementations + // found on the interwebs. + // From studying it in greater detail, + // the basic gist is that quaternion log and exp are used to + // decompose what should be a series of multiplications (quat rotations) into additions, since + // ln(a * b) = ln(a) + ln(b), and exp(ln(a)) = a. + + // ln(q) means encoding a vec3 where the length encodes theta, and direction encodes direction. + // Summing ln(a) + ln(b) will therefore "add" the addition together, similar to how one + // would add torque vectors in physics. The exp must then re-encode the vector-magnitude encoding + // back to normal quaternion form. + + // In this domain we can average rotations, and go back again to a normal quaternion with exp. + // inv_q1 * q2 and inv_q1 * q0 both do some form of "differential" of the rotations. + // q12 and q10 estimate first derivative at the control points. + // q12 and q10 have opposing signs, + // so the sum of the logs is therefore seen as instantaneous acceleration at the q1. + + // quat_log() breaks down if q.w goes negative it seems, so that explains some shenanigans + // where some docs say that this only works for "normal" interpolation scenarios. + // Probably more than good enough for us though. + + // Weigh the deltas so that they compute absolute velocity and acceleration. + // Rescale back to spline time domain after. + + quat inv_q1 = conjugate(q1); + quat delta_k = inv_q1 * q2; // q2 - q1 + quat delta_k_minus1 = inv_q1 * q0; // q0 - q1 = -(q1 - q0) + vec3 delta_k_log = quat_log(delta_k); + vec3 delta_k_minus1_log = quat_log(delta_k_minus1); + + // We sample velocity at the center of the segment when taking the difference. + // Future sample is at t = +1/2 dt + // Past sample is at t = -1/2 dt + float segment_time = 0.5f * (dt0 + dt1); + vec3 absolute_accel = (delta_k_log / dt1 + delta_k_minus1_log / dt0) / segment_time; + vec3 delta = (0.25f * dt1 * dt1) * absolute_accel; + return delta; +} + +// From https://mina86.com/2019/srgb-xyz-matrix/ +static vec3 convert_primary(const vec2 &xy) +{ + float X = xy.x / xy.y; + float Y = 1.0f; + float Z = (1.0f - xy.x - xy.y) / xy.y; + return vec3(X, Y, Z); +} + +mat3 compute_xyz_matrix(const Primaries &primaries) +{ + vec3 red = convert_primary(primaries.red); + vec3 green = convert_primary(primaries.green); + vec3 blue = convert_primary(primaries.blue); + vec3 white = convert_primary(primaries.white_point); + + vec3 component_scale = inverse(mat3(red, green, blue)) * white; + return mat3(red * component_scale.x, green * component_scale.y, blue * component_scale.z); +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/math/transforms.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/transforms.hpp new file mode 100644 index 00000000..46a81c85 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/math/transforms.hpp @@ -0,0 +1,85 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "math.hpp" +#include + +namespace Granite +{ +class AABB; + +bool compute_plane_reflection(mat4 &projection, mat4 &view, vec3 camera_pos, vec3 center, vec3 normal, vec3 look_up, + float radius_up, float radius_other, float &z_near, float z_far); + +bool compute_plane_refraction(mat4 &projection, mat4 &view, vec3 camera_pos, vec3 center, vec3 normal, vec3 look_up, + float radius_up, float radius_other, float &z_near, float z_far); + +void compute_model_transform(mat_affine &world, vec3 scale, quat rotation, vec3 translation, const mat_affine &parent); + +void compute_normal_transform(mat4 &normal, const mat4 &world); +void compute_normal_transform(mat_affine &normal, const mat_affine &world); + +quat rotate_vector(vec3 from, vec3 to); + +quat look_at(vec3 direction, vec3 up); + +quat look_at_arbitrary_up(vec3 direction); + +quat rotate_vector_axis(vec3 from, vec3 to, vec3 axis); + +mat4 projection(float fovy, float aspect, float znear, float zfar); + +mat4 ortho(const AABB &aabb); + +void compute_cube_render_transform(vec3 center, unsigned face, mat4 &projection, mat4 &view, float znear, float zfar); + +struct PositionalSampler +{ + std::vector values; + vec3 sample(unsigned index, float l) const; + vec3 sample_spline(unsigned index, float l, float dt) const; +}; + +struct SphericalSampler +{ + std::vector values; + quat sample(unsigned index, float l) const; + quat sample_spline(unsigned index, float l, float dt) const; + quat sample_squad(unsigned index, float l) const; +}; + +// Compute control points for q1. +// dt0 is delta time between q0 and q1. +// dt1 is delta time between q1 and q2. +vec3 compute_inner_control_point_delta(const quat &q0, const quat &q1, const quat &q2, + float dt0, float dt1); +quat compute_inner_control_point(const quat &q, const vec3 &delta); + +struct Primaries +{ + vec2 red, green, blue, white_point; +}; + +mat3 compute_xyz_matrix(const Primaries &primaries); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/path/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/path/CMakeLists.txt new file mode 100644 index 00000000..2e2c75cf --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/path/CMakeLists.txt @@ -0,0 +1,3 @@ +add_granite_internal_lib(granite-path path_utils.hpp path_utils.cpp) +target_include_directories(granite-path PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-path PRIVATE granite-util) \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/path/path_utils.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/path/path_utils.cpp new file mode 100644 index 00000000..6cba0e50 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/path/path_utils.cpp @@ -0,0 +1,282 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "path_utils.hpp" +#include "string_helpers.hpp" +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#ifdef __linux__ +#include +#endif +#endif + +namespace Granite +{ +namespace Path +{ +std::string enforce_protocol(const std::string &path) +{ + if (path.empty()) + return ""; + + auto index = path.find("://"); + if (index == std::string::npos) + return std::string("file://") + path; + else + return path; +} + +std::string canonicalize_path(const std::string &path) +{ + std::string transformed; + transformed.resize(path.size()); + transform(begin(path), end(path), begin(transformed), [](char c) -> char { return c == '\\' ? '/' : c; }); + auto data = Util::split_no_empty(transformed, "/"); + + std::vector result; + for (auto &i : data) + { + if (i == "..") + { + if (!result.empty()) + result.pop_back(); + } + else if (i != ".") + result.push_back(std::move(i)); + } + + std::string res; + for (auto &i : result) + { + if (&i != result.data()) + res += "/"; + res += i; + } + return res; +} + +static size_t find_last_slash(const std::string &str) +{ +#ifdef _WIN32 + auto index = str.find_last_of("/\\"); +#else + auto index = str.find_last_of('/'); +#endif + return index; +} + +bool is_abspath(const std::string &path) +{ + if (path.empty()) + return false; + if (path.front() == '/') + return true; + +#ifdef _WIN32 + { + auto index = std::min(path.find(":/"), path.find(":\\")); + if (index != std::string::npos) + return true; + } +#endif + + return path.find("://") != std::string::npos; +} + +bool is_root_path(const std::string &path) +{ + if (path.empty()) + return false; + + if (path.front() == '/' && path.size() == 1) + return true; + +#ifdef _WIN32 + { + auto index = std::min(path.find(":/"), path.find(":\\")); + if (index != std::string::npos && (index + 2) == path.size()) + return true; + } +#endif + + auto index = path.find("://"); + return index != std::string::npos && (index + 3) == path.size(); +} + +std::string join(const std::string &base, const std::string &path) +{ + if (base.empty()) + return path; + if (path.empty()) + return base; + + if (is_abspath(path)) + return path; + + auto index = find_last_slash(base); + bool need_slash = index != base.size() - 1; + return Util::join(base, need_slash ? "/" : "", path); +} + +std::string basedir(const std::string &path) +{ + if (path.empty()) + return ""; + + if (is_root_path(path)) + return path; + + auto index = find_last_slash(path); + if (index == std::string::npos) + return "."; + + // Preserve the first slash. + if (index == 0 && is_abspath(path)) + index++; + + auto ret = path.substr(0, index + 1); + if (!is_root_path(ret)) + ret.pop_back(); + return ret; +} + +std::string basename(const std::string &path) +{ + if (path.empty()) + return ""; + + auto index = find_last_slash(path); + if (index == std::string::npos) + return path; + + auto base = path.substr(index + 1, std::string::npos); + return base; +} + +std::string relpath(const std::string &base, const std::string &path) +{ + return Path::join(basedir(base), path); +} + +std::string ext(const std::string &path) +{ + auto index = path.find_last_of('.'); + if (index == std::string::npos) + return ""; + else + return path.substr(index + 1, std::string::npos); +} + +std::pair split(const std::string &path) +{ + if (path.empty()) + return make_pair(std::string("."), std::string(".")); + + auto index = find_last_slash(path); + if (index == std::string::npos) + return make_pair(std::string("."), path); + + auto base = path.substr(index + 1, std::string::npos); + return make_pair(path.substr(0, index), base); +} + +std::pair protocol_split(const std::string &path) +{ + if (path.empty()) + return make_pair(std::string(""), std::string("")); + + auto index = path.find("://"); + if (index == std::string::npos) + return make_pair(std::string(""), path); + + return make_pair(path.substr(0, index), path.substr(index + 3, std::string::npos)); +} + +std::string get_executable_path() +{ +#ifdef _WIN32 + wchar_t target[4096]; + DWORD ret = GetModuleFileNameW(GetModuleHandle(nullptr), target, sizeof(target) / sizeof(wchar_t)); + return canonicalize_path(Path::to_utf8(target, ret)); +#else + pid_t pid = getpid(); + static const char *exts[] = { "exe", "file", "a.out" }; + char link_path[PATH_MAX]; + char target[PATH_MAX]; + + for (auto *ext : exts) + { + snprintf(link_path, sizeof(link_path), "/proc/%u/%s", + unsigned(pid), ext); + ssize_t ret = readlink(link_path, target, sizeof(target) - 1); + if (ret >= 0) + { + target[ret] = '\0'; + return std::string(target); + } + } + + return ""; +#endif +} + +#ifdef _WIN32 +std::string to_utf8(const wchar_t *wstr, size_t len) +{ + std::vector char_buffer; + auto ret = WideCharToMultiByte(CP_UTF8, 0, wstr, len, nullptr, 0, nullptr, nullptr); + if (ret < 0) + return ""; + char_buffer.resize(ret); + WideCharToMultiByte(CP_UTF8, 0, wstr, len, char_buffer.data(), char_buffer.size(), nullptr, nullptr); + return std::string(char_buffer.data(), char_buffer.size()); +} + +std::wstring to_utf16(const char *str, size_t len) +{ + std::vector wchar_buffer; + auto ret = MultiByteToWideChar(CP_UTF8, 0, str, len, nullptr, 0); + if (ret < 0) + return L""; + wchar_buffer.resize(ret); + MultiByteToWideChar(CP_UTF8, 0, str, len, wchar_buffer.data(), wchar_buffer.size()); + return std::wstring(wchar_buffer.data(), wchar_buffer.size()); +} + +std::string to_utf8(const std::wstring &wstr) +{ + return to_utf8(wstr.data(), wstr.size()); +} + +std::wstring to_utf16(const std::string &str) +{ + return to_utf16(str.data(), str.size()); +} +#endif +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/path/path_utils.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/path/path_utils.hpp new file mode 100644 index 00000000..460fae29 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/path/path_utils.hpp @@ -0,0 +1,51 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include +#include + +namespace Granite +{ +namespace Path +{ +std::string join(const std::string &base, const std::string &path); +std::string basedir(const std::string &path); +std::string basename(const std::string &path); +std::pair split(const std::string &path); +std::string relpath(const std::string &base, const std::string &path); +std::string ext(const std::string &path); +std::pair protocol_split(const std::string &path); +bool is_abspath(const std::string &path); +bool is_root_path(const std::string &path); +std::string canonicalize_path(const std::string &path); +std::string enforce_protocol(const std::string &path); +std::string get_executable_path(); + +#ifdef _WIN32 +std::string to_utf8(const wchar_t *wstr, size_t len); +std::wstring to_utf16(const char *str, size_t len); +std::string to_utf8(const std::wstring &wstr); +std::wstring to_utf16(const std::string &str); +#endif +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/self-test/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/self-test/CMakeLists.txt new file mode 100644 index 00000000..098df250 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/self-test/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.5) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_C_STANDARD 99) +project(Granite-Self-Test LANGUAGES CXX C) + +add_subdirectory(.. granite) +add_granite_offline_tool(link-test link_test.cpp) +granite_install_executable(link-test) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/self-test/link_test.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/self-test/link_test.cpp new file mode 100644 index 00000000..aff254a6 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/self-test/link_test.cpp @@ -0,0 +1,9 @@ +#include "global_managers_init.hpp" + +int main() +{ + Granite::Global::init(); + LOGI("Hello there! :)\n"); + Granite::Global::deinit(); + return 0; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/CMakeLists.txt new file mode 100644 index 00000000..1d426fa6 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/CMakeLists.txt @@ -0,0 +1,156 @@ +set(SKIP_GLSLANG_INSTALL ON CACHE BOOL "" FORCE) +set(SHADERC_SKIP_INSTALL ON CACHE BOOL "" FORCE) +set(SPIRV_HEADERS_SKIP_EXAMPLES ON CACHE BOOL "" FORCE) +set(SPIRV_HEADERS_SKIP_INSTALL ON CACHE BOOL "" FORCE) +set(ENABLE_HLSL ON CACHE BOOL "" FORCE) +set(ENABLE_OPT OFF CACHE BOOL "" FORCE) +set(ENABLE_GLSLANG_INSTALL OFF CACHE BOOL "" FORCE) +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) +set(SHADERC_THIRD_PARTY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE STRING "Third party path." FORCE) +set(SPIRV_CHECK_CONTEXT OFF CACHE BOOL "Disable SPIR-V IR context checking." FORCE) +set(SPIRV-Headers_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/spirv-headers" CACHE STRING "SPIRV-Headers path") +set(SHADERC_SKIP_TESTS ON CACHE BOOL "" FORCE) +set(FOSSILIZE_RAPIDJSON_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/include" CACHE STRING "Fossilize rapidjson path." FORCE) +set(MUFFT_ENABLE_FFTW OFF CACHE BOOL "Disable FFTW tests." FORCE) +set(SKIP_SPIRV_TOOLS_INSTALL ON CACHE BOOL "" FORCE) +set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "" FORCE) + +if (GRANITE_VULKAN_SPIRV_CROSS) + add_subdirectory(spirv-cross EXCLUDE_FROM_ALL) +endif() + +if (GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER) + add_subdirectory(shaderc EXCLUDE_FROM_ALL) +endif() + +add_subdirectory(renderdoc EXCLUDE_FROM_ALL) + +if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/stb/stb/stb_vorbis.c) + add_subdirectory(stb) +endif() + +if ((NOT ANDROID) AND GRANITE_ASTC_ENCODER_COMPRESSION) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + message("Enabling SSE 4.1 path for astcenc") + set(ISA_SSE41 ON CACHE BOOL "" FORCE) + else() + set(ISA_NONE ON CACHE BOOL "" FORCE) + endif() + set(DECOMPRESSOR OFF) + set(UNITTEST OFF) + set(CLI_BUILD OFF CACHE BOOL "" FORCE) + add_subdirectory(astc-encoder EXCLUDE_FROM_ALL) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + add_library(astc-encoder ALIAS astcenc-sse4.1-static) + else() + add_library(astc-encoder ALIAS astcenc-none-static) + endif() +endif() + +if (GRANITE_RENDERER) + add_subdirectory(meshoptimizer EXCLUDE_FROM_ALL) + add_subdirectory(mikktspace) + add_subdirectory(muFFT EXCLUDE_FROM_ALL) +endif() + +set(FOSSILIZE_CLI OFF CACHE BOOL "Fossilize CLI." FORCE) +set(FOSSILIZE_TESTS OFF CACHE BOOL "Fossilize tests." FORCE) + +if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/include/rapidjson/document.h) + add_library(granite-rapidjson INTERFACE) + target_include_directories(granite-rapidjson INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/include) +endif() + +if (NOT TARGET Vulkan::Headers) + add_subdirectory(khronos/vulkan-headers) +endif() + +add_library(granite-volk-headers INTERFACE) +target_include_directories(granite-volk-headers INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/volk) +target_link_libraries(granite-volk-headers INTERFACE Vulkan::Headers) + +if (GRANITE_VULKAN_FOSSILIZE) + # Some issues with Android build with missing shm_. Compile exactly what we need for now. + add_library(fossilize STATIC + fossilize/fossilize.hpp fossilize/fossilize.cpp + fossilize/fossilize_db.hpp fossilize/fossilize_db.cpp + fossilize/varint.hpp fossilize/varint.cpp + fossilize/fossilize_application_filter.hpp fossilize/fossilize_application_filter.cpp + fossilize/path.hpp fossilize/path.cpp + fossilize/miniz/miniz.h fossilize/miniz/miniz.c + fossilize/cli/fossilize_feature_filter.hpp fossilize/cli/fossilize_feature_filter.cpp) + granite_setup_default_link_libraries(fossilize) + + if (NOT TARGET SPIRV-Headers) + add_subdirectory(spirv-headers EXCLUDE_FROM_ALL) + endif() + + get_target_property(SPIRV_HEADERS_PATH SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES) + + target_include_directories(fossilize + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/fossilize + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/fossilize/miniz + PRIVATE ${SPIRV_HEADERS_PATH}/spirv/unified1) + target_link_libraries(fossilize PUBLIC granite-volk-headers PRIVATE granite-rapidjson) + if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) + target_compile_options(fossilize PRIVATE -fvisibility=hidden) + if (NOT APPLE) + target_compile_definitions(fossilize PRIVATE _LARGEFILE64_SOURCE) + endif() + if (WIN32) + target_compile_definitions(fossilize PRIVATE __USE_MINGW_ANSI_STDIO=1) + endif() + endif() + if (WIN32) + target_include_directories(fossilize PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dirent) + endif() +endif() + +# volk must be STATIC. +add_library(granite-volk STATIC volk/volk.c volk/volk.h) +if (WIN32) + target_compile_definitions(granite-volk PRIVATE VK_USE_PLATFORM_WIN32_KHR) +else() + target_link_libraries(granite-volk PRIVATE dl) +endif() +target_link_libraries(granite-volk PRIVATE granite-volk-headers) + +if ((NOT ANDROID) AND (${GRANITE_PLATFORM} MATCHES "SDL") AND (NOT GRANITE_SYSTEM_SDL)) + set(SDL_SHARED OFF CACHE BOOL "" FORCE) + set(SDL_STATIC ON CACHE BOOL "" FORCE) + set(SDL_TIMERS ON CACHE BOOL "" FORCE) + set(SDL_LIBC ON CACHE BOOL "" FORCE) + set(SDL_TEST_LIBRARY OFF CACHE BOOL "" FORCE) + set(SDL_DISABLE_INSTALL ON CACHE BOOL "" FORCE) + # Disable everything we don't care about. + set(SDL_ATOMIC OFF CACHE BOOL "" FORCE) + set(SDL_AUDIO OFF CACHE BOOL "" FORCE) + set(SDL_RENDER OFF CACHE BOOL "" FORCE) + set(SDL_HAPTIC OFF CACHE BOOL "" FORCE) + set(SDL_POWER OFF CACHE BOOL "" FORCE) + set(SDL_FILE OFF CACHE BOOL "" FORCE) + set(SDL_CPUINFO OFF CACHE BOOL "" FORCE) + set(SDL_FILESYSTEM OFF CACHE BOOL "" FORCE) + set(SDL_SENSOR OFF CACHE BOOL "" FORCE) + set(SDL_LOCALE OFF CACHE BOOL "" FORCE) + set(SDL_MISC OFF CACHE BOOL "" FORCE) + add_subdirectory(sdl3 EXCLUDE_FROM_ALL) +endif() + +if (ANDROID AND GRANITE_AUDIO) + add_subdirectory(oboe EXCLUDE_FROM_ALL) + target_compile_options(oboe PUBLIC -Wno-unused-parameter) + target_compile_features(oboe PRIVATE cxx_std_17) +endif() + +if (GRANITE_VULKAN_SYSTEM_HANDLES AND GRANITE_RENDERER) + # Custom integration, bypass all the noise. + add_subdirectory(fsr2/src/ffx-fsr2-api/granite) +endif() + +if (GRANITE_FFMPEG) + add_subdirectory(pyroenc EXCLUDE_FROM_ALL) + add_subdirectory(pyrowave EXCLUDE_FROM_ALL) +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/dirent/dirent.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/dirent/dirent.h new file mode 100644 index 00000000..f7a46daf --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/dirent/dirent.h @@ -0,0 +1,1160 @@ +/* + * Dirent interface for Microsoft Visual Studio + * + * Copyright (C) 1998-2019 Toni Ronkko + * This file is part of dirent. Dirent may be freely distributed + * under the MIT license. For all details and documentation, see + * https://github.com/tronkko/dirent + */ +#ifndef DIRENT_H +#define DIRENT_H + +/* Hide warnings about unreferenced local functions */ +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#elif defined(_MSC_VER) +# pragma warning(disable:4505) +#elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of the file name without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return the maximum size of a file name */ +#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX+1]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +/* Multi-byte character version */ +struct dirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX+1]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + + +/* Dirent functions */ +static DIR *opendir (const char *dirname); +static _WDIR *_wopendir (const wchar_t *dirname); + +static struct dirent *readdir (DIR *dirp); +static struct _wdirent *_wreaddir (_WDIR *dirp); + +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result); +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); + +static int closedir (DIR *dirp); +static int _wclosedir (_WDIR *dirp); + +static void rewinddir (DIR* dirp); +static void _wrewinddir (_WDIR* dirp); + +static int scandir (const char *dirname, struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)); + +static int alphasort (const struct dirent **a, const struct dirent **b); + +static int versionsort (const struct dirent **a, const struct dirent **b); + + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); + +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + +static void dirent_set_errno (int error); + + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir( + const wchar_t *dirname) +{ + _WDIR *dirp; + DWORD n; + wchar_t *p; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); + if (!dirp) { + return NULL; + } + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* + * Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, 0, NULL, NULL); +#else + /* WinRT */ + n = wcslen (dirname); +#endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); + if (dirp->patt == NULL) { + goto exit_closedir; + } + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, n, dirp->patt, NULL); + if (n <= 0) { + goto exit_closedir; + } +#else + /* WinRT */ + wcsncpy_s (dirp->patt, n+1, dirname, n); +#endif + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (!dirent_first (dirp)) { + goto exit_closedir; + } + + /* Success */ + return dirp; + + /* Failure */ +exit_closedir: + _wclosedir (dirp); + return NULL; +} + +/* + * Read next directory entry. + * + * Returns pointer to static directory entry which may be overwritten by + * subsequent calls to _wreaddir(). + */ +static struct _wdirent* +_wreaddir( + _WDIR *dirp) +{ + struct _wdirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) _wreaddir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry. + * + * Returns zero on success. If end of directory stream is reached, then sets + * result to NULL and returns zero. + */ +static int +_wreaddir_r( + _WDIR *dirp, + struct _wdirent *entry, + struct _wdirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp); + if (datap) { + size_t n; + DWORD attr; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n < PATH_MAX && datap->cFileName[n] != 0) { + entry->d_name[n] = datap->cFileName[n]; + n++; + } + entry->d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct _wdirent); + + /* Set result address */ + *result = entry; + + } else { + + /* Return NULL to indicate end of directory */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int +_wclosedir( + _WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Release search pattern */ + free (dirp->patt); + + /* Release directory structure */ + free (dirp); + ok = /*success*/0; + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void +_wrewinddir( + _WDIR* dirp) +{ + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Open new search handle */ + dirent_first (dirp); + } +} + +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + DWORD error; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } else { + + /* Failed to open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + /* Set error code */ + error = GetLastError (); + switch (error) { + case ERROR_ACCESS_DENIED: + /* No read access to directory */ + dirent_set_errno (EACCES); + break; + + case ERROR_DIRECTORY: + /* Directory name is invalid */ + dirent_set_errno (ENOTDIR); + break; + + case ERROR_PATH_NOT_FOUND: + default: + /* Cannot find the file */ + dirent_set_errno (ENOENT); + } + + } + return datap; +} + +/* + * Get next directory entry (internal). + * + * Returns + */ +static WIN32_FIND_DATAW* +dirent_next( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed or an error occurred */ + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; +} + +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir( + const char *dirname) +{ + struct DIR *dirp; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (!dirp) { + return NULL; + } + { + int error; + wchar_t wname[PATH_MAX + 1]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s( + &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1); + if (error) { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + goto exit_free; + } + + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir (wname); + if (!dirp->wdirp) { + goto exit_free; + } + + } + + /* Success */ + return dirp; + + /* Failure */ +exit_free: + free (dirp); + return NULL; +} + +/* + * Read next directory entry. + */ +static struct dirent* +readdir( + DIR *dirp) +{ + struct dirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) readdir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry into called-allocated buffer. + * + * Returns zero on success. If the end of directory stream is reached, then + * sets result to NULL and returns zero. + */ +static int +readdir_r( + DIR *dirp, + struct dirent *entry, + struct dirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cAlternateFileName, PATH_MAX + 1); + } + + if (!error) { + DWORD attr; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct dirent); + + } else { + + /* + * Cannot convert file name to multi-byte string so construct + * an erroneous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entry->d_name[0] = '?'; + entry->d_name[1] = '\0'; + entry->d_namlen = 1; + entry->d_type = DT_UNKNOWN; + entry->d_ino = 0; + entry->d_off = -1; + entry->d_reclen = 0; + + } + + /* Return pointer to directory entry */ + *result = entry; + + } else { + + /* No more directory entries */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream. + */ +static int +closedir( + DIR *dirp) +{ + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir (dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free (dirp); + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream to beginning. + */ +static void +rewinddir( + DIR* dirp) +{ + /* Rewind wide-character string directory stream */ + _wrewinddir (dirp->wdirp); +} + +/* + * Scan directory for entries. + */ +static int +scandir( + const char *dirname, + struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)) +{ + struct dirent **files = NULL; + size_t size = 0; + size_t allocated = 0; + const size_t init_size = 1; + DIR *dir = NULL; + struct dirent *entry; + struct dirent *tmp = NULL; + size_t i; + int result = 0; + + /* Open directory stream */ + dir = opendir (dirname); + if (dir) { + + /* Read directory entries to memory */ + while (1) { + + /* Enlarge pointer table to make room for another pointer */ + if (size >= allocated) { + void *p; + size_t num_entries; + + /* Compute number of entries in the enlarged pointer table */ + if (size < init_size) { + /* Allocate initial pointer table */ + num_entries = init_size; + } else { + /* Double the size */ + num_entries = size * 2; + } + + /* Allocate first pointer table or enlarge existing table */ + p = realloc (files, sizeof (void*) * num_entries); + if (p != NULL) { + /* Got the memory */ + files = (dirent**) p; + allocated = num_entries; + } else { + /* Out of memory */ + result = -1; + break; + } + + } + + /* Allocate room for temporary directory entry */ + if (tmp == NULL) { + tmp = (struct dirent*) malloc (sizeof (struct dirent)); + if (tmp == NULL) { + /* Cannot allocate temporary directory entry */ + result = -1; + break; + } + } + + /* Read directory entry to temporary area */ + if (readdir_r (dir, tmp, &entry) == /*OK*/0) { + + /* Did we get an entry? */ + if (entry != NULL) { + int pass; + + /* Determine whether to include the entry in result */ + if (filter) { + /* Let the filter function decide */ + pass = filter (tmp); + } else { + /* No filter function, include everything */ + pass = 1; + } + + if (pass) { + /* Store the temporary entry to pointer table */ + files[size++] = tmp; + tmp = NULL; + + /* Keep up with the number of files */ + result++; + } + + } else { + + /* + * End of directory stream reached => sort entries and + * exit. + */ + qsort (files, size, sizeof (void*), + (int (*) (const void*, const void*)) compare); + break; + + } + + } else { + /* Error reading directory entry */ + result = /*Error*/ -1; + break; + } + + } + + } else { + /* Cannot open directory */ + result = /*Error*/ -1; + } + + /* Release temporary directory entry */ + free (tmp); + + /* Release allocated memory on error */ + if (result < 0) { + for (i = 0; i < size; i++) { + free (files[i]); + } + free (files); + files = NULL; + } + + /* Close directory stream */ + if (dir) { + closedir (dir); + } + + /* Pass pointer table to caller */ + if (namelist) { + *namelist = files; + } + return result; +} + +/* Alphabetical sorting */ +static int +alphasort( + const struct dirent **a, const struct dirent **b) +{ + return strcoll ((*a)->d_name, (*b)->d_name); +} + +/* Sort versions */ +static int +versionsort( + const struct dirent **a, const struct dirent **b) +{ + /* FIXME: implement strverscmp and use that */ + return alphasort (a, b); +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs (wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resulting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Could not convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs (mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Set errno variable */ +static void +dirent_set_errno( + int error) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno (error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif +} + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.gitattributes b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.gitattributes new file mode 100644 index 00000000..41eae371 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.gitattributes @@ -0,0 +1,24 @@ +# ~~~ +# Copyright 2018-2023 The Khronos Group Inc. +# Copyright 2018-2023 Valve Corporation +# Copyright 2018-2023 LunarG, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# ~~~ + +# See https://git-scm.com/docs/gitattributes +# See https://help.github.com/articles/dealing-with-line-endings/ + +# Default behavior, if core.autocrlf is unset. +* text=auto + +# Files to be converted to native line endings on checkout. +*.cpp text +*.h text + +# Text files to always have CRLF (dos) line endings on checkout. +*.bat text eol=crlf + +# Text files to always have LF (unix) line endings on checkout. +*.sh text eol=lf + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/ISSUE_TEMPLATE/bug_report.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..df7450df --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,52 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Is this issue appropriate for the repository?** + +Vulkan-Headers exists as a publishing mechanism for headers and related material sourced from multiple other repositories. If you have a problem with that material, it should *not* be reported here, but in the appropriate repository: + +This repository is responsible for the following files + +* BUILD.gn +* BUILD.md +* CMakeLists.txt +* tests/* +* CODE_OF_CONDUCT.md +* LICENSE.txt +* README.md +* Non-API headers + * include/vulkan/vk_icd.h + * include/vulkan/vk_layer.h + +**Describe the bug** + +A clear and concise description of what the bug is. Please refer to specific files that are only in this repository, not copied from Vulkan-Docs or Vulkan-Hpp. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. + +**Code** + +

+code or terminal output + +```cpp +int main() +{ + return 0; +} +``` + +
diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/dependabot.yml b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/dependabot.yml new file mode 100644 index 00000000..b25b0ebd --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/dependabot.yml @@ -0,0 +1,12 @@ +# ~~~ +# Copyright 2023 LunarG, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# ~~~ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 3 diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/pull_request_template.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/pull_request_template.md new file mode 100644 index 00000000..8090943b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/pull_request_template.md @@ -0,0 +1,18 @@ + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/workflows/ci.yml b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/workflows/ci.yml new file mode 100644 index 00000000..d81d69cb --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/.github/workflows/ci.yml @@ -0,0 +1,128 @@ +# Copyright 2022-2023 LunarG, Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +name: ci + +on: + push: + pull_request: + +env: + CMAKE_GENERATOR: Ninja + +permissions: + contents: read + +jobs: + cmake-unix: + runs-on: ${{ matrix.os }} + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + strategy: + matrix: + os: [ ubuntu-latest, macos-latest ] + cmake-version: [ '3.22.1', 'latest'] + steps: + - uses: actions/checkout@v6 + - uses: lukka/get-cmake@latest + with: + cmakeVersion: ${{ matrix.cmake-version }} + - uses: ilammy/msvc-dev-cmd@v1 + - run: cmake -S . -B build -D VULKAN_HEADERS_ENABLE_TESTS=ON -D VULKAN_HEADERS_ENABLE_INSTALL=ON + - run: cmake --build ./build + - run: cmake --install build/ --prefix build/install + - run: ctest --output-on-failure + working-directory: build + + cmake-windows: + runs-on: windows-latest + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + strategy: + matrix: + cmake-version: [ '3.22.1', 'latest'] + steps: + - uses: actions/checkout@v6 + - uses: lukka/get-cmake@latest + with: + cmakeVersion: ${{ matrix.cmake-version }} + - uses: ilammy/msvc-dev-cmd@v1 + - run: cmake -S . -B build -D VULKAN_HEADERS_ENABLE_TESTS=ON -D VULKAN_HEADERS_ENABLE_INSTALL=ON + - run: cmake --build ./build + - run: cmake --install build/ --prefix build/install + - run: ctest --output-on-failure + working-directory: build + + windows_clang: + runs-on: windows-2022 + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + strategy: + matrix: + compiler: [ clang, clang-cl ] + steps: + - uses: actions/checkout@v6 + - uses: ilammy/msvc-dev-cmd@v1 + - run: | + cmake -S . -B build ` + -D CMAKE_C_COMPILER=${{matrix.compiler}} ` + -D CMAKE_CXX_COMPILER=${{matrix.compiler}} ` + -D CMAKE_BUILD_TYPE=Release ` + -D VULKAN_HEADERS_ENABLE_TESTS=ON ` + -D VULKAN_HEADERS_ENABLE_INSTALL=ON ` + - run: cmake --build ./build + - run: cmake --install build/ --prefix build/install + - run: ctest --output-on-failure + working-directory: build + + cmake-unix-modules: + runs-on: ${{ matrix.os }} + if: false + strategy: + matrix: + os: [ ubuntu-latest ] + cmake-version: [ 'latest' ] + compiler: [ clang++-18 ] + steps: + - uses: actions/checkout@v6 + - uses: lukka/get-cmake@latest + with: + cmakeVersion: ${{ matrix.cmake-version }} + - uses: ilammy/msvc-dev-cmd@v1 + - run: | + cmake -S . -B build \ + -D VULKAN_HEADERS_ENABLE_TESTS=ON \ + -D VULKAN_HEADERS_ENABLE_INSTALL=ON \ + -D CMAKE_CXX_COMPILER=${{ matrix.compiler }} \ + - run: cmake --build ./build + - run: cmake --install build/ --prefix build/install + - run: CXX=${{ matrix.compiler }} ctest --output-on-failure + working-directory: build + + cmake-windows-modules: + runs-on: ${{ matrix.os }} + if: false + strategy: + matrix: + os: [ windows-latest ] + cmake-version: [ 'latest' ] + steps: + - uses: actions/checkout@v6 + - uses: lukka/get-cmake@latest + with: + cmakeVersion: ${{ matrix.cmake-version }} + - uses: ilammy/msvc-dev-cmd@v1 + - run: | + cmake -S . -B build ` + -D VULKAN_HEADERS_ENABLE_TESTS=ON ` + -D VULKAN_HEADERS_ENABLE_INSTALL=ON ` + - run: cmake --build ./build + - run: cmake --install build/ --prefix build/install + - run: ctest --output-on-failure + working-directory: build + + reuse: + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + steps: + - uses: actions/checkout@v6 + - name: REUSE Compliance Check + uses: fsfe/reuse-action@v6 diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/BUILD.gn b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/BUILD.gn new file mode 100644 index 00000000..42a76b58 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/BUILD.gn @@ -0,0 +1,76 @@ +# Copyright 2018-2023 The ANGLE Project Authors. +# Copyright 2019-2023 LunarG, Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +import("//build_overrides/vulkan_headers.gni") + +config("vulkan_headers_config") { + include_dirs = [ "include" ] + defines = [] + + if (is_win) { + defines += [ "VK_USE_PLATFORM_WIN32_KHR" ] + } + if (defined(vulkan_use_x11) && vulkan_use_x11) { + defines += [ "VK_USE_PLATFORM_XCB_KHR" ] + if (!defined(vulkan_no_xlib_headers) || !vulkan_no_xlib_headers) { + defines += [ "VK_USE_PLATFORM_XLIB_KHR" ] + } + } + if (defined(vulkan_use_wayland) && vulkan_use_wayland) { + defines += [ "VK_USE_PLATFORM_WAYLAND_KHR" ] + if (defined(vulkan_wayland_include_dirs)) { + include_dirs += vulkan_wayland_include_dirs + } + } + if (is_android) { + defines += [ "VK_USE_PLATFORM_ANDROID_KHR" ] + } + if (is_fuchsia) { + defines += [ "VK_USE_PLATFORM_FUCHSIA" ] + } + if (is_apple) { + defines += [ "VK_USE_PLATFORM_METAL_EXT" ] + } + if (is_mac) { + defines += [ "VK_USE_PLATFORM_MACOS_MVK" ] + } + if (is_ios) { + defines += [ "VK_USE_PLATFORM_IOS_MVK" ] + } + if (defined(is_ggp) && is_ggp) { + defines += [ "VK_USE_PLATFORM_GGP" ] + } + if (is_clang) { + cflags = [ + "-Wno-redundant-parens", + ] + } +} + +# Vulkan headers only, no compiled sources. +source_set("vulkan_headers") { + sources = [ + "include/vulkan/vk_icd.h", + "include/vulkan/vk_layer.h", + "include/vulkan/vk_platform.h", + "include/vulkan/vulkan.h", + "include/vulkan/vulkan.hpp", + "include/vulkan/vulkan_core.h", + "include/vulkan/vulkan_screen.h", + "include/vk_video/vulkan_video_codec_av1std_decode.h", + "include/vk_video/vulkan_video_codec_av1std_encode.h", + "include/vk_video/vulkan_video_codec_av1std.h", + "include/vk_video/vulkan_video_codec_h264std_decode.h", + "include/vk_video/vulkan_video_codec_h264std_encode.h", + "include/vk_video/vulkan_video_codec_h264std.h", + "include/vk_video/vulkan_video_codec_h265std_decode.h", + "include/vk_video/vulkan_video_codec_h265std_encode.h", + "include/vk_video/vulkan_video_codec_h265std.h", + "include/vk_video/vulkan_video_codec_vp9std_decode.h", + "include/vk_video/vulkan_video_codec_vp9std.h", + "include/vk_video/vulkan_video_codecs_common.h", + ] + public_configs = [ ":vulkan_headers_config" ] +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/BUILD.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/BUILD.md new file mode 100644 index 00000000..a9ccd98f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/BUILD.md @@ -0,0 +1,46 @@ + + +# Build Instructions + +Instructions for building this repository. + +```bash +git clone https://github.com/KhronosGroup/Vulkan-Headers.git + +cd Vulkan-Headers/ + +# Configure the project +cmake -S . -B build/ + +# Because Vulkan-Headers is header only we don't need to build anything. +# Users can install it where they need to. +cmake --install build --prefix build/install +``` + +See the official [CMake documentation](https://cmake.org/cmake/help/latest/index.html) for more information. + +## Installed Files + +The `install` target installs the following files under the directory +indicated by *install_dir*: + +- *install_dir*`/include/vulkan` : The header files found in the + `include/vulkan` directory of this repository +- *install_dir*`/share/cmake/VulkanHeaders`: The CMake config files needed + for find_package support +- *install_dir*`/share/vulkan/registry` : The registry files found in the + `registry` directory of this repository + +## Usage in CMake + +```cmake +find_package(VulkanHeaders REQUIRED CONFIG) + +target_link_libraries(foobar PRIVATE Vulkan::Headers) + +message(STATUS "Vulkan Headers Version: ${VulkanHeaders_VERSION}") +``` diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/CMakeLists.txt new file mode 100644 index 00000000..3e5e8c19 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/CMakeLists.txt @@ -0,0 +1,125 @@ +# ~~~ +# Copyright 2018-2023 The Khronos Group Inc. +# Copyright 2018-2023 Valve Corporation +# Copyright 2018-2023 LunarG, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# ~~~ +cmake_minimum_required(VERSION 3.22.1) + +include(CMakeDependentOption) + + +# NOTE: Parsing the version like this is suboptimal but neccessary due to our release process: +# https://github.com/KhronosGroup/Vulkan-Headers/pull/346 +# +# As shown a more robust approach would be just to add basic test code to check the project version. +function(vlk_get_header_version) + set(vulkan_core_header_file "${CMAKE_CURRENT_SOURCE_DIR}/include/vulkan/vulkan_core.h") + if (NOT EXISTS ${vulkan_core_header_file}) + message(FATAL_ERROR "Couldn't find vulkan_core.h!") + endif() + + file(READ ${vulkan_core_header_file} ver) + + if (ver MATCHES "#define[ ]+VK_HEADER_VERSION_COMPLETE[ ]+VK_MAKE_API_VERSION\\([ ]*[0-9]+,[ ]*([0-9]+),[ ]*([0-9]+),[ ]*VK_HEADER_VERSION[ ]*\\)") + set(MAJOR_VERSION "${CMAKE_MATCH_1}") + set(MINOR_VERSION "${CMAKE_MATCH_2}") + else() + message(FATAL_ERROR "Couldn't get major/minor version") + endif() + + if (ver MATCHES "#define[ ]+VK_HEADER_VERSION[ ]+([0-9]+)") + set(PATCH_VERSION "${CMAKE_MATCH_1}") + else() + message(FATAL_ERROR "Couldn't get the patch version") + endif() + + set(VK_VERSION_STRING "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}" PARENT_SCOPE) +endfunction() +vlk_get_header_version() + +project(VULKAN_HEADERS LANGUAGES C CXX VERSION ${VK_VERSION_STRING}) + +# options for Vulkan-Headers and the Vulkan-Hpp C++20 module +option(VULKAN_HEADERS_ENABLE_TESTS "Test Vulkan-Headers" ${PROJECT_IS_TOP_LEVEL}) +option(VULKAN_HEADERS_ENABLE_INSTALL "Install Vulkan-Headers" ${PROJECT_IS_TOP_LEVEL}) +cmake_dependent_option(VULKAN_HEADERS_ENABLE_MODULE "Build and install the Vulkan-Hpp C++ named modules" ON [[ 23 IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD ]] OFF) +# This CMake target is only available when the entire stack (CMake, compiler, standard library) supports C++20 modules and supports importing the standard library as a module. +# See https://gitlab.kitware.com/ben.boeckel/cmake/-/blob/cxxmodules-docs/Help/manual/cmake-cxxmodules.7.rst?ref_type=heads&plain=1#L398 + +# set up Vulkan-Headers +add_library(Vulkan-Headers INTERFACE) +add_library(Vulkan::Headers ALIAS Vulkan-Headers) +target_include_directories(Vulkan-Headers INTERFACE $) + +if (VULKAN_HEADERS_ENABLE_MODULE) + add_library(Vulkan-HppModule OBJECT) + add_library(Vulkan::HppModule ALIAS Vulkan-HppModule) + target_sources(Vulkan-HppModule PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" + FILES + "${CMAKE_CURRENT_SOURCE_DIR}/include/vulkan/vulkan.cppm" + "${CMAKE_CURRENT_SOURCE_DIR}/include/vulkan/vulkan_video.cppm") + + target_compile_features(Vulkan-HppModule PUBLIC cxx_std_23) # C++23 is required for both the standard library module, and other details of Vulkan-Hpp such as std::expected + set_target_properties(Vulkan-HppModule PROPERTIES CXX_MODULE_STD ON) + target_link_libraries(Vulkan-HppModule PUBLIC Vulkan::Headers) + + # set up fallback targets to notify about name deprecation + add_library(Vulkan-Module INTERFACE) + add_library(Vulkan::Module ALIAS Vulkan-Module) + target_link_libraries(Vulkan-Module INTERFACE Vulkan::HppModule) + set_target_properties(Vulkan-Module PROPERTIES + DEPRECATION "The Vulkan-Module and Vulkan::Module targets have been deprecated by the Vulkan-HppModule and Vulkan::HppModule targets respectively and will be removed at a future date." + ) +endif() + +if (VULKAN_HEADERS_ENABLE_TESTS) + enable_testing() # This is only effective in the top level CMakeLists.txt file. + add_subdirectory(tests) +endif() + +if (VULKAN_HEADERS_ENABLE_INSTALL) + include(GNUInstallDirs) + include(CMakePackageConfigHelpers) + + # Remove the module interface files from the header target if the named module installation is ENABLED. + # This ensures that the module interface files are only installed once. + if(VULKAN_HEADERS_ENABLE_MODULE) + set(CPPM_PATTERN "*.cppm") + else() + set(CPPM_PATTERN "") + endif() + + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/vk_video" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} PATTERN "${CPPM_PATTERN}" EXCLUDE) + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/vulkan" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} PATTERN "${CPPM_PATTERN}" EXCLUDE) + # Preserve source permissions https://github.com/KhronosGroup/Vulkan-Headers/issues/336 + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/registry" DESTINATION "${CMAKE_INSTALL_DATADIR}/vulkan" USE_SOURCE_PERMISSIONS PATTERN "${CPPM_PATTERN}" EXCLUDE) + + set_target_properties(Vulkan-Headers PROPERTIES EXPORT_NAME "Headers") + install(TARGETS Vulkan-Headers + EXPORT VulkanHeadersConfig + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + + # Install the C++ module target and export it + if (VULKAN_HEADERS_ENABLE_MODULE) + set_target_properties(Vulkan-HppModule PROPERTIES EXPORT_NAME "HppModule") + install(TARGETS Vulkan-HppModule + EXPORT VulkanHeadersConfig + FILE_SET CXX_MODULES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(EXPORT VulkanHeadersConfig + NAMESPACE "Vulkan::" + DESTINATION "share/cmake/VulkanHeaders" + CXX_MODULES_DIRECTORY "") + else() + install(EXPORT VulkanHeadersConfig + NAMESPACE "Vulkan::" + DESTINATION "share/cmake/VulkanHeaders") + endif() + + set(version_config "${CMAKE_CURRENT_BINARY_DIR}/generated/VulkanHeadersConfigVersion.cmake") + write_basic_package_version_file("${version_config}" COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT) + install(FILES "${version_config}" DESTINATION "share/cmake/VulkanHeaders") +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/CODE_OF_CONDUCT.adoc b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/CODE_OF_CONDUCT.adoc new file mode 100644 index 00000000..bd635bb9 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/CODE_OF_CONDUCT.adoc @@ -0,0 +1,10 @@ +// Copyright 2018-2023 The Khronos Group Inc. +// SPDX-License-Identifier: MIT + += Code of Conduct + +A reminder that this repository is managed by the Khronos Group. +Interactions here should follow the +https://www.khronos.org/about/code-of-conduct[Khronos Code of Conduct], +which prohibits aggressive or derogatory language. Please keep the +discussion friendly and civil. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/CONTRIBUTING.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/CONTRIBUTING.md new file mode 100644 index 00000000..99b14c11 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/CONTRIBUTING.md @@ -0,0 +1,56 @@ + + +# CONTRIBUTING + +Please note when contributing what files this repository actually is responsible for. + +The majority for the Vulkan headers come from [Vulkan-Docs](https://github.com/KhronosGroup/Vulkan-Docs) or [Vulkan-Hpp](https://github.com/KhronosGroup/Vulkan-Hpp) + +### This repository (https://github.com/KhronosGroup/Vulkan-Headers) + +* BUILD.gn +* BUILD.md +* CMakeLists.txt +* tests/* +* CODE_OF_CONDUCT.md +* LICENSE.txt +* README.md +* Non-API headers + * include/vulkan/vk_icd.h + * include/vulkan/vk_layer.h + +### Specification repository (https://github.com/KhronosGroup/Vulkan-Docs) + +* registry/*.py +* registry/spec_tools/*.py +* registry/profiles/*.json +* All files under include/vulkan/ which are *not* listed explicitly as originating from another repository. + +### Vulkan C++ Binding Repository (https://github.com/KhronosGroup/Vulkan-Hpp) + +As of the Vulkan-Docs 1.2.182 spec update, the Vulkan-Hpp headers have been +split into multiple files. All of those files are now included in this +repository. + +* include/vulkan/*.hpp +* include/vulkan/*.cppm + +### **Contributor License Agreement (CLA)** + +You will be prompted with a one-time "click-through" CLA dialog as part of submitting your pull request +or other contribution to GitHub. + +### **AI-Assisted Contributions** + +By submitting a Contribution to this repository, you additionally represent +that, to the extent any of Your Contributions were developed with the +assistance of artificial intelligence tools or AI-generated code, You have +exercised sufficient review, judgment, and creative direction over such tools +and resulting material to reasonably consider it Your original creation, and +You are not aware of any third-party license, intellectual property claim, or +other restriction arising from such use that is associated with any part of +Your Contribution or use thereof. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSE.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSE.md new file mode 100644 index 00000000..d6a0648b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSE.md @@ -0,0 +1,18 @@ +Copyright 2015-2023 The Khronos Group Inc. + +Files in this repository fall under one of these licenses: + +- `Apache-2.0` +- `MIT` + +Note: With the exception of `parse_dependency.py` the files using `MIT` license +also fall under `Apache-2.0`. Example: + +``` +SPDX-License-Identifier: Apache-2.0 OR MIT +``` + +Full license text of these licenses is available at: + + * Apache-2.0: https://opensource.org/licenses/Apache-2.0 + * MIT: https://opensource.org/licenses/MIT diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSES/Apache-2.0.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSES/Apache-2.0.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSES/Apache-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSES/MIT.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSES/MIT.txt new file mode 100644 index 00000000..8495fe9e --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSES/MIT.txt @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2015-2023 The Khronos Group Inc. + +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. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/Makefile.release b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/Makefile.release new file mode 100644 index 00000000..7596cb25 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/Makefile.release @@ -0,0 +1,141 @@ +# Copyright 2024-2025 The Khronos Group Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Makefile.release - update external files generated in Vulkan spec +# repository when a public specification update is done. + +# Needed to get the right version of test, apparently +SHELL = /bin/bash + +REVISION = 999 + +# Location of other repository clones +GIT = .. +SPEC = $(GIT)/Vulkan-Docs +# As of 1.4.322 spec update, the build process has been changed to use a +# Vulkan-Hpp located underneath Vulkan-Docs (not a submodule). +# If you are using one located elsewhere then override HPP. +HPP = $(SPEC)/Vulkan-Hpp +REGISTRY = $(GIT)/registry/vulkan + +update: revision-check create-branch update-files push-branch + +# Working branch for the update, and a test if it exists +BRANCH = update-$(REVISION) + +# Switch to new branch which will contain the update +create-branch: revision-check + git switch -q main + git pull -q + # If branch already exists, do nothing + @if test `git branch -l $(BRANCH) | wc -l` == 1 ; then \ + echo "Branch $(BRANCH) already exists" ; \ + git switch $(BRANCH) ; \ + else \ + echo "Creating branch $(BRANCH)" ; \ + git switch -c $(BRANCH) ; \ + fi + +# Update headers and scripts in the new branch +update-files: remove-files update-headers update-scripts + +# To ensure updates are caught, old versions of installed files are +# removed. +# Files in include/ to keep +HEADERS_KEEP = \ + include/vulkan/vk_icd.h \ + include/vulkan/vk_layer.h + +remove-files: + rm -rf $(filter-out $(HEADERS_KEEP), $(wildcard include/vulkan/*)) + rm -rf include/vk_video + rm -rf registry + mkdir include/vk_video registry registry/profiles registry/spec_tools + +# Vulkan SC Vulkan-Hpp headers not published in the Vulkan-Headers repository +SCHPPFILES = \ + include/vulkan/vulkansc.hpp \ + include/vulkan/vulkansc.cppm \ + include/vulkan/vulkansc_*.hpp + +update-headers: + if test ! -d $(SPEC)/gen/include/ ; then \ + echo "No C header file source directory $(SPEC)/gen/include" ; \ + exit 1 ; \ + fi + if test ! -d $(HPP)/vulkan ; then \ + echo "No C++ header file source directory $(HPP)/vulkan" ; \ + exit 1 ; \ + fi + cp -r $(SPEC)/gen/include/* include/ + cp -r $(HPP)/vulkan/* include/vulkan/ + rm -f $(SCHPPFILES) + +# Top-level scripts / XML to install +SCRIPTS = \ + $(SPEC)/scripts/base_generator.py \ + $(SPEC)/scripts/cgenerator.py \ + $(SPEC)/scripts/generator.py \ + $(SPEC)/scripts/parse_dependency.py \ + $(SPEC)/scripts/reg.py \ + $(SPEC)/scripts/stripAPI.py \ + $(SPEC)/scripts/apiconventions.py \ + $(SPEC)/scripts/vkconventions.py \ + $(SPEC)/scripts/vulkan_object.py \ + $(SPEC)/xml/vk.xml \ + $(SPEC)/xml/video.xml \ + $(REGISTRY)/specs/latest/validation/validusage.json + +# Scripts in registry/spec_tools to install +SCRIPT_TOOLS = \ + $(SPEC)/scripts/spec_tools/conventions.py \ + $(SPEC)/scripts/spec_tools/util.py + +# Profiles to install +PROFILES = \ + $(wildcard $(SPEC)/xml/profiles/*) + +update-scripts: + cp $(SCRIPTS) registry/ + cp $(PROFILES) registry/profiles/ + cp $(SCRIPT_TOOLS) registry/spec_tools/ + +# Once the branch is updated, push it to upstream and create an MR +# This should be used cautiously after verifying the branch contents are +# indeed correct and updates. +# +# Ideally we could automatically create the github PR. +# This will require additional software, see e.g. +# https://medium.com/@ravipatel.it/creating-a-git-pull-request-using-the-command-line-a-detailed-guide-4ef1ea017fe2 +# https://gist.github.com/devinschumacher/bc66c162d9c6c167952f1943d0e6419c +# Gitlab supports this via 'git push' options e.g. +# -o merge_request.create -o merge_request.target=main -o merge_request.remove_source_branch \ +# -o merge_request.title="Update for Vulkan-Docs 1.4.$(REVISION)" \ +# -o merge_request.assign=oddhack +# But for github we must manually create a PR after pushing +push-branch: revision-check + git switch $(BRANCH) + git add -u + echo "Detect new files and add them. This may not always succeed." + echo "Adding new files:" `git diff --name-only main` + git add `git diff --name-only main` + git commit -m "Update for Vulkan-Docs 1.4.$(REVISION)" + git push --set-upstream origin $(BRANCH) + git switch main + git branch -d $(BRANCH) + echo "Now create a pull request by going to the URL:" + echo " https://github.com/KhronosGroup/Vulkan-Headers/pull/new/$(BRANCH)" + echo "After accepting this PR, continue with:" + echo " cd $(shell pwd) && make -f Makefile.release REVISION=$(REVISION) tag-branch" + +# Tag main for the update after accepting the update PR +TAG = v1.4.$(REVISION) +tag-branch: + git switch main + git pull + git tag -a $(TAG) -m "Update for Vulkan-Docs 1.4.$(REVISION)" + git push origin $(TAG) + echo "Now continue with Step 12 of the process (update public registry) from the wiki, until more scripting is done" + +revision-check: + @if test $(REVISION) = 999 ; then echo "Must specify explicit REVISION= in make invocation" ; exit 1 ; fi diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/README.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/README.md new file mode 100644 index 00000000..d2d74ed3 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/README.md @@ -0,0 +1,52 @@ + + +# Vulkan-Headers + +Vulkan header files and API registry + +This repository contains Vulkan header files, include files for C and C++, +and related scripts and tests. + +Most of the files in this repository are sourced from, or generated from, +other repositories as described in [CONTRIBUTING.md](CONTRIBUTING.md). +Vulkan-Headers exists as a staging area for these files, most of which are +then consumed by downstream repositories used to build SDK components such +as the Vulkan Validation Layers and Conformance Test Suite. + +Developers normally obtain headers from the official +[Vulkan-SDK](https://www.lunarg.com/vulkan-sdk/). +They can also use headers from, or packaged from, this repository. + +In most cases, developers should only need the headers, not the scripts and +other material in this repository. +If you need to run the scripts, please use them from their canonical source +in the [Vulkan Specification +repository](https://github.com/KhronosGroup/Vulkan-Docs). + +## Contributing + +See the [CONTRIBUTING.md](CONTRIBUTING.md) + +## Building + +See [BUILD.md](BUILD.md) + +## SDK Support + +Vulkan-Headers are shipped as part of the official [Vulkan-SDK](https://www.lunarg.com/vulkan-sdk/) + +## C/C++ Package Manager Support + +`Vulkan-Headers` are also supported by both [conan](https://conan.io/) & [vcpkg](https://learn.microsoft.com/en-us/vcpkg/). + +## Version Tagging Scheme + +Updates to this repository which correspond to a new Vulkan specification release are tagged using the following format: `v<`_`version`_`>` (e.g., `v1.3.266`). + +**Note**: Marked version releases have undergone thorough testing but do not imply the same quality level as SDK tags. SDK tags follow the `vulkan-sdk-<`_`version`_`>.<`_`patch`_`>` format (e.g., `vulkan-sdk-1.3.266.0`). + +This scheme was adopted following the `1.3.266` Vulkan specification release. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/REUSE.toml b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/REUSE.toml new file mode 100644 index 00000000..fa456efd --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/REUSE.toml @@ -0,0 +1,21 @@ +version = 1 +SPDX-PackageName = "Vulkan-Headers" +SPDX-PackageDownloadLocation = "https://github.com/KhronosGroup/Vulkan-Headers" + +[[annotations]] +path = "registry/profiles/VP_KHR_roadmap.json" +precedence = "aggregate" +SPDX-FileCopyrightText = "2022-2024 The Khronos Group Inc." +SPDX-License-Identifier = "Apache-2.0" + +[[annotations]] +path = "registry/validusage.json" +precedence = "aggregate" +SPDX-FileCopyrightText = "2018-2024 The Khronos Group Inc." +SPDX-License-Identifier = "Apache-2.0" + +[[annotations]] +path = [".github/ISSUE_TEMPLATE/bug_report.md", ".github/pull_request_template.md"] +precedence = "aggregate" +SPDX-FileCopyrightText = "2022-2024 The Khronos Group Inc." +SPDX-License-Identifier = "Apache-2.0" diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/SECURITY.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/SECURITY.md new file mode 100644 index 00000000..44533792 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/SECURITY.md @@ -0,0 +1,11 @@ + + +# Security Policy + +To report a security issue, please disclose it at [security advisory](https://github.com/KhronosGroup/Vulkan-Headers/security/advisories/new). + +This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_av1std.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_av1std.h new file mode 100644 index 00000000..75cebd74 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_av1std.h @@ -0,0 +1,394 @@ +#ifndef VULKAN_VIDEO_CODEC_AV1STD_H_ +#define VULKAN_VIDEO_CODEC_AV1STD_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_av1std is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_av1std 1 +#include "vulkan_video_codecs_common.h" +#define STD_VIDEO_AV1_NUM_REF_FRAMES 8U +#define STD_VIDEO_AV1_REFS_PER_FRAME 7U +#define STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME 8U +#define STD_VIDEO_AV1_MAX_TILE_COLS 64U +#define STD_VIDEO_AV1_MAX_TILE_ROWS 64U +#define STD_VIDEO_AV1_MAX_SEGMENTS 8U +#define STD_VIDEO_AV1_SEG_LVL_MAX 8U +#define STD_VIDEO_AV1_PRIMARY_REF_NONE 7U +#define STD_VIDEO_AV1_SELECT_INTEGER_MV 2U +#define STD_VIDEO_AV1_SELECT_SCREEN_CONTENT_TOOLS 2U +#define STD_VIDEO_AV1_SKIP_MODE_FRAMES 2U +#define STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS 4U +#define STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS 2U +#define STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS 8U +#define STD_VIDEO_AV1_MAX_NUM_PLANES 3U +#define STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS 6U +#define STD_VIDEO_AV1_MAX_NUM_Y_POINTS 14U +#define STD_VIDEO_AV1_MAX_NUM_CB_POINTS 10U +#define STD_VIDEO_AV1_MAX_NUM_CR_POINTS 10U +#define STD_VIDEO_AV1_MAX_NUM_POS_LUMA 24U +#define STD_VIDEO_AV1_MAX_NUM_POS_CHROMA 25U + +typedef enum StdVideoAV1Profile { + STD_VIDEO_AV1_PROFILE_MAIN = 0, + STD_VIDEO_AV1_PROFILE_HIGH = 1, + STD_VIDEO_AV1_PROFILE_PROFESSIONAL = 2, + STD_VIDEO_AV1_PROFILE_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_PROFILE_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1Profile; + +typedef enum StdVideoAV1Level { + STD_VIDEO_AV1_LEVEL_2_0 = 0, + STD_VIDEO_AV1_LEVEL_2_1 = 1, + STD_VIDEO_AV1_LEVEL_2_2 = 2, + STD_VIDEO_AV1_LEVEL_2_3 = 3, + STD_VIDEO_AV1_LEVEL_3_0 = 4, + STD_VIDEO_AV1_LEVEL_3_1 = 5, + STD_VIDEO_AV1_LEVEL_3_2 = 6, + STD_VIDEO_AV1_LEVEL_3_3 = 7, + STD_VIDEO_AV1_LEVEL_4_0 = 8, + STD_VIDEO_AV1_LEVEL_4_1 = 9, + STD_VIDEO_AV1_LEVEL_4_2 = 10, + STD_VIDEO_AV1_LEVEL_4_3 = 11, + STD_VIDEO_AV1_LEVEL_5_0 = 12, + STD_VIDEO_AV1_LEVEL_5_1 = 13, + STD_VIDEO_AV1_LEVEL_5_2 = 14, + STD_VIDEO_AV1_LEVEL_5_3 = 15, + STD_VIDEO_AV1_LEVEL_6_0 = 16, + STD_VIDEO_AV1_LEVEL_6_1 = 17, + STD_VIDEO_AV1_LEVEL_6_2 = 18, + STD_VIDEO_AV1_LEVEL_6_3 = 19, + STD_VIDEO_AV1_LEVEL_7_0 = 20, + STD_VIDEO_AV1_LEVEL_7_1 = 21, + STD_VIDEO_AV1_LEVEL_7_2 = 22, + STD_VIDEO_AV1_LEVEL_7_3 = 23, + STD_VIDEO_AV1_LEVEL_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_LEVEL_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1Level; + +typedef enum StdVideoAV1FrameType { + STD_VIDEO_AV1_FRAME_TYPE_KEY = 0, + STD_VIDEO_AV1_FRAME_TYPE_INTER = 1, + STD_VIDEO_AV1_FRAME_TYPE_INTRA_ONLY = 2, + STD_VIDEO_AV1_FRAME_TYPE_SWITCH = 3, + STD_VIDEO_AV1_FRAME_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_FRAME_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1FrameType; + +typedef enum StdVideoAV1ReferenceName { + STD_VIDEO_AV1_REFERENCE_NAME_INTRA_FRAME = 0, + STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME = 1, + STD_VIDEO_AV1_REFERENCE_NAME_LAST2_FRAME = 2, + STD_VIDEO_AV1_REFERENCE_NAME_LAST3_FRAME = 3, + STD_VIDEO_AV1_REFERENCE_NAME_GOLDEN_FRAME = 4, + STD_VIDEO_AV1_REFERENCE_NAME_BWDREF_FRAME = 5, + STD_VIDEO_AV1_REFERENCE_NAME_ALTREF2_FRAME = 6, + STD_VIDEO_AV1_REFERENCE_NAME_ALTREF_FRAME = 7, + STD_VIDEO_AV1_REFERENCE_NAME_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_REFERENCE_NAME_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1ReferenceName; + +typedef enum StdVideoAV1InterpolationFilter { + STD_VIDEO_AV1_INTERPOLATION_FILTER_EIGHTTAP = 0, + STD_VIDEO_AV1_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH = 1, + STD_VIDEO_AV1_INTERPOLATION_FILTER_EIGHTTAP_SHARP = 2, + STD_VIDEO_AV1_INTERPOLATION_FILTER_BILINEAR = 3, + STD_VIDEO_AV1_INTERPOLATION_FILTER_SWITCHABLE = 4, + STD_VIDEO_AV1_INTERPOLATION_FILTER_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_INTERPOLATION_FILTER_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1InterpolationFilter; + +typedef enum StdVideoAV1TxMode { + STD_VIDEO_AV1_TX_MODE_ONLY_4X4 = 0, + STD_VIDEO_AV1_TX_MODE_LARGEST = 1, + STD_VIDEO_AV1_TX_MODE_SELECT = 2, + STD_VIDEO_AV1_TX_MODE_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_TX_MODE_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1TxMode; + +typedef enum StdVideoAV1FrameRestorationType { + STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE = 0, + STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_WIENER = 1, + STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SGRPROJ = 2, + STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SWITCHABLE = 3, + STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1FrameRestorationType; + +typedef enum StdVideoAV1ColorPrimaries { + STD_VIDEO_AV1_COLOR_PRIMARIES_BT_709 = 1, + STD_VIDEO_AV1_COLOR_PRIMARIES_UNSPECIFIED = 2, + STD_VIDEO_AV1_COLOR_PRIMARIES_BT_470_M = 4, + STD_VIDEO_AV1_COLOR_PRIMARIES_BT_470_B_G = 5, + STD_VIDEO_AV1_COLOR_PRIMARIES_BT_601 = 6, + STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_240 = 7, + STD_VIDEO_AV1_COLOR_PRIMARIES_GENERIC_FILM = 8, + STD_VIDEO_AV1_COLOR_PRIMARIES_BT_2020 = 9, + STD_VIDEO_AV1_COLOR_PRIMARIES_XYZ = 10, + STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_431 = 11, + STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_432 = 12, + STD_VIDEO_AV1_COLOR_PRIMARIES_EBU_3213 = 22, + STD_VIDEO_AV1_COLOR_PRIMARIES_INVALID = 0x7FFFFFFF, + // STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED is a legacy alias + STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED = STD_VIDEO_AV1_COLOR_PRIMARIES_UNSPECIFIED, + STD_VIDEO_AV1_COLOR_PRIMARIES_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1ColorPrimaries; + +typedef enum StdVideoAV1TransferCharacteristics { + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_RESERVED_0 = 0, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_709 = 1, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_UNSPECIFIED = 2, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_RESERVED_3 = 3, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_470_M = 4, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_470_B_G = 5, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_601 = 6, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SMPTE_240 = 7, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_LINEAR = 8, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_LOG_100 = 9, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_LOG_100_SQRT10 = 10, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_IEC_61966 = 11, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_1361 = 12, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SRGB = 13, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_2020_10_BIT = 14, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_2020_12_BIT = 15, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SMPTE_2084 = 16, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SMPTE_428 = 17, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_HLG = 18, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1TransferCharacteristics; + +typedef enum StdVideoAV1MatrixCoefficients { + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_IDENTITY = 0, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_709 = 1, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_UNSPECIFIED = 2, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_RESERVED_3 = 3, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_FCC = 4, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_470_B_G = 5, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_601 = 6, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_SMPTE_240 = 7, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_SMPTE_YCGCO = 8, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_2020_NCL = 9, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_2020_CL = 10, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_SMPTE_2085 = 11, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_CHROMAT_NCL = 12, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_CHROMAT_CL = 13, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_ICTCP = 14, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_MATRIX_COEFFICIENTS_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1MatrixCoefficients; + +typedef enum StdVideoAV1ChromaSamplePosition { + STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_UNKNOWN = 0, + STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_VERTICAL = 1, + STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_COLOCATED = 2, + STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_RESERVED = 3, + STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_INVALID = 0x7FFFFFFF, + STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_MAX_ENUM = 0x7FFFFFFF +} StdVideoAV1ChromaSamplePosition; +typedef struct StdVideoAV1ColorConfigFlags { + uint32_t mono_chrome : 1; + uint32_t color_range : 1; + uint32_t separate_uv_delta_q : 1; + uint32_t color_description_present_flag : 1; + uint32_t reserved : 28; +} StdVideoAV1ColorConfigFlags; + +typedef struct StdVideoAV1ColorConfig { + StdVideoAV1ColorConfigFlags flags; + uint8_t BitDepth; + uint8_t subsampling_x; + uint8_t subsampling_y; + uint8_t reserved1; + StdVideoAV1ColorPrimaries color_primaries; + StdVideoAV1TransferCharacteristics transfer_characteristics; + StdVideoAV1MatrixCoefficients matrix_coefficients; + StdVideoAV1ChromaSamplePosition chroma_sample_position; +} StdVideoAV1ColorConfig; + +typedef struct StdVideoAV1TimingInfoFlags { + uint32_t equal_picture_interval : 1; + uint32_t reserved : 31; +} StdVideoAV1TimingInfoFlags; + +typedef struct StdVideoAV1TimingInfo { + StdVideoAV1TimingInfoFlags flags; + uint32_t num_units_in_display_tick; + uint32_t time_scale; + uint32_t num_ticks_per_picture_minus_1; +} StdVideoAV1TimingInfo; + +typedef struct StdVideoAV1LoopFilterFlags { + uint32_t loop_filter_delta_enabled : 1; + uint32_t loop_filter_delta_update : 1; + uint32_t reserved : 30; +} StdVideoAV1LoopFilterFlags; + +typedef struct StdVideoAV1LoopFilter { + StdVideoAV1LoopFilterFlags flags; + uint8_t loop_filter_level[STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS]; + uint8_t loop_filter_sharpness; + uint8_t update_ref_delta; + int8_t loop_filter_ref_deltas[STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME]; + uint8_t update_mode_delta; + int8_t loop_filter_mode_deltas[STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS]; +} StdVideoAV1LoopFilter; + +typedef struct StdVideoAV1QuantizationFlags { + uint32_t using_qmatrix : 1; + uint32_t diff_uv_delta : 1; + uint32_t reserved : 30; +} StdVideoAV1QuantizationFlags; + +typedef struct StdVideoAV1Quantization { + StdVideoAV1QuantizationFlags flags; + uint8_t base_q_idx; + int8_t DeltaQYDc; + int8_t DeltaQUDc; + int8_t DeltaQUAc; + int8_t DeltaQVDc; + int8_t DeltaQVAc; + uint8_t qm_y; + uint8_t qm_u; + uint8_t qm_v; +} StdVideoAV1Quantization; + +typedef struct StdVideoAV1Segmentation { + uint8_t FeatureEnabled[STD_VIDEO_AV1_MAX_SEGMENTS]; + int16_t FeatureData[STD_VIDEO_AV1_MAX_SEGMENTS][STD_VIDEO_AV1_SEG_LVL_MAX]; +} StdVideoAV1Segmentation; + +typedef struct StdVideoAV1TileInfoFlags { + uint32_t uniform_tile_spacing_flag : 1; + uint32_t reserved : 31; +} StdVideoAV1TileInfoFlags; + +typedef struct StdVideoAV1TileInfo { + StdVideoAV1TileInfoFlags flags; + uint8_t TileCols; + uint8_t TileRows; + uint16_t context_update_tile_id; + uint8_t tile_size_bytes_minus_1; + uint8_t reserved1[7]; + const uint16_t* pMiColStarts; + const uint16_t* pMiRowStarts; + const uint16_t* pWidthInSbsMinus1; + const uint16_t* pHeightInSbsMinus1; +} StdVideoAV1TileInfo; + +typedef struct StdVideoAV1CDEF { + uint8_t cdef_damping_minus_3; + uint8_t cdef_bits; + uint8_t cdef_y_pri_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS]; + uint8_t cdef_y_sec_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS]; + uint8_t cdef_uv_pri_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS]; + uint8_t cdef_uv_sec_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS]; +} StdVideoAV1CDEF; + +typedef struct StdVideoAV1LoopRestoration { + StdVideoAV1FrameRestorationType FrameRestorationType[STD_VIDEO_AV1_MAX_NUM_PLANES]; + uint16_t LoopRestorationSize[STD_VIDEO_AV1_MAX_NUM_PLANES]; +} StdVideoAV1LoopRestoration; + +typedef struct StdVideoAV1GlobalMotion { + uint8_t GmType[STD_VIDEO_AV1_NUM_REF_FRAMES]; + int32_t gm_params[STD_VIDEO_AV1_NUM_REF_FRAMES][STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS]; +} StdVideoAV1GlobalMotion; + +typedef struct StdVideoAV1FilmGrainFlags { + uint32_t chroma_scaling_from_luma : 1; + uint32_t overlap_flag : 1; + uint32_t clip_to_restricted_range : 1; + uint32_t update_grain : 1; + uint32_t reserved : 28; +} StdVideoAV1FilmGrainFlags; + +typedef struct StdVideoAV1FilmGrain { + StdVideoAV1FilmGrainFlags flags; + uint8_t grain_scaling_minus_8; + uint8_t ar_coeff_lag; + uint8_t ar_coeff_shift_minus_6; + uint8_t grain_scale_shift; + uint16_t grain_seed; + uint8_t film_grain_params_ref_idx; + uint8_t num_y_points; + uint8_t point_y_value[STD_VIDEO_AV1_MAX_NUM_Y_POINTS]; + uint8_t point_y_scaling[STD_VIDEO_AV1_MAX_NUM_Y_POINTS]; + uint8_t num_cb_points; + uint8_t point_cb_value[STD_VIDEO_AV1_MAX_NUM_CB_POINTS]; + uint8_t point_cb_scaling[STD_VIDEO_AV1_MAX_NUM_CB_POINTS]; + uint8_t num_cr_points; + uint8_t point_cr_value[STD_VIDEO_AV1_MAX_NUM_CR_POINTS]; + uint8_t point_cr_scaling[STD_VIDEO_AV1_MAX_NUM_CR_POINTS]; + int8_t ar_coeffs_y_plus_128[STD_VIDEO_AV1_MAX_NUM_POS_LUMA]; + int8_t ar_coeffs_cb_plus_128[STD_VIDEO_AV1_MAX_NUM_POS_CHROMA]; + int8_t ar_coeffs_cr_plus_128[STD_VIDEO_AV1_MAX_NUM_POS_CHROMA]; + uint8_t cb_mult; + uint8_t cb_luma_mult; + uint16_t cb_offset; + uint8_t cr_mult; + uint8_t cr_luma_mult; + uint16_t cr_offset; +} StdVideoAV1FilmGrain; + +typedef struct StdVideoAV1SequenceHeaderFlags { + uint32_t still_picture : 1; + uint32_t reduced_still_picture_header : 1; + uint32_t use_128x128_superblock : 1; + uint32_t enable_filter_intra : 1; + uint32_t enable_intra_edge_filter : 1; + uint32_t enable_interintra_compound : 1; + uint32_t enable_masked_compound : 1; + uint32_t enable_warped_motion : 1; + uint32_t enable_dual_filter : 1; + uint32_t enable_order_hint : 1; + uint32_t enable_jnt_comp : 1; + uint32_t enable_ref_frame_mvs : 1; + uint32_t frame_id_numbers_present_flag : 1; + uint32_t enable_superres : 1; + uint32_t enable_cdef : 1; + uint32_t enable_restoration : 1; + uint32_t film_grain_params_present : 1; + uint32_t timing_info_present_flag : 1; + uint32_t initial_display_delay_present_flag : 1; + uint32_t reserved : 13; +} StdVideoAV1SequenceHeaderFlags; + +typedef struct StdVideoAV1SequenceHeader { + StdVideoAV1SequenceHeaderFlags flags; + StdVideoAV1Profile seq_profile; + uint8_t frame_width_bits_minus_1; + uint8_t frame_height_bits_minus_1; + uint16_t max_frame_width_minus_1; + uint16_t max_frame_height_minus_1; + uint8_t delta_frame_id_length_minus_2; + uint8_t additional_frame_id_length_minus_1; + uint8_t order_hint_bits_minus_1; + uint8_t seq_force_integer_mv; + uint8_t seq_force_screen_content_tools; + uint8_t reserved1[5]; + const StdVideoAV1ColorConfig* pColorConfig; + const StdVideoAV1TimingInfo* pTimingInfo; +} StdVideoAV1SequenceHeader; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_av1std_decode.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_av1std_decode.h new file mode 100644 index 00000000..60bf2c03 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_av1std_decode.h @@ -0,0 +1,109 @@ +#ifndef VULKAN_VIDEO_CODEC_AV1STD_DECODE_H_ +#define VULKAN_VIDEO_CODEC_AV1STD_DECODE_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_av1std_decode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_av1std_decode 1 +#include "vulkan_video_codec_av1std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_av1_decode" +typedef struct StdVideoDecodeAV1PictureInfoFlags { + uint32_t error_resilient_mode : 1; + uint32_t disable_cdf_update : 1; + uint32_t use_superres : 1; + uint32_t render_and_frame_size_different : 1; + uint32_t allow_screen_content_tools : 1; + uint32_t is_filter_switchable : 1; + uint32_t force_integer_mv : 1; + uint32_t frame_size_override_flag : 1; + uint32_t buffer_removal_time_present_flag : 1; + uint32_t allow_intrabc : 1; + uint32_t frame_refs_short_signaling : 1; + uint32_t allow_high_precision_mv : 1; + uint32_t is_motion_mode_switchable : 1; + uint32_t use_ref_frame_mvs : 1; + uint32_t disable_frame_end_update_cdf : 1; + uint32_t allow_warped_motion : 1; + uint32_t reduced_tx_set : 1; + uint32_t reference_select : 1; + uint32_t skip_mode_present : 1; + uint32_t delta_q_present : 1; + uint32_t delta_lf_present : 1; + uint32_t delta_lf_multi : 1; + uint32_t segmentation_enabled : 1; + uint32_t segmentation_update_map : 1; + uint32_t segmentation_temporal_update : 1; + uint32_t segmentation_update_data : 1; + uint32_t UsesLr : 1; + uint32_t usesChromaLr : 1; + uint32_t apply_grain : 1; + uint32_t reserved : 3; +} StdVideoDecodeAV1PictureInfoFlags; + +typedef struct StdVideoDecodeAV1PictureInfo { + StdVideoDecodeAV1PictureInfoFlags flags; + StdVideoAV1FrameType frame_type; + uint32_t current_frame_id; + uint8_t OrderHint; + uint8_t primary_ref_frame; + uint8_t refresh_frame_flags; + uint8_t reserved1; + StdVideoAV1InterpolationFilter interpolation_filter; + StdVideoAV1TxMode TxMode; + uint8_t delta_q_res; + uint8_t delta_lf_res; + uint8_t SkipModeFrame[STD_VIDEO_AV1_SKIP_MODE_FRAMES]; + uint8_t coded_denom; + uint8_t reserved2[3]; + uint8_t OrderHints[STD_VIDEO_AV1_NUM_REF_FRAMES]; + uint32_t expectedFrameId[STD_VIDEO_AV1_NUM_REF_FRAMES]; + const StdVideoAV1TileInfo* pTileInfo; + const StdVideoAV1Quantization* pQuantization; + const StdVideoAV1Segmentation* pSegmentation; + const StdVideoAV1LoopFilter* pLoopFilter; + const StdVideoAV1CDEF* pCDEF; + const StdVideoAV1LoopRestoration* pLoopRestoration; + const StdVideoAV1GlobalMotion* pGlobalMotion; + const StdVideoAV1FilmGrain* pFilmGrain; +} StdVideoDecodeAV1PictureInfo; + +typedef struct StdVideoDecodeAV1ReferenceInfoFlags { + uint32_t disable_frame_end_update_cdf : 1; + uint32_t segmentation_enabled : 1; + uint32_t reserved : 30; +} StdVideoDecodeAV1ReferenceInfoFlags; + +typedef struct StdVideoDecodeAV1ReferenceInfo { + StdVideoDecodeAV1ReferenceInfoFlags flags; + uint8_t frame_type; + uint8_t RefFrameSignBias; + uint8_t OrderHint; + uint8_t SavedOrderHints[STD_VIDEO_AV1_NUM_REF_FRAMES]; +} StdVideoDecodeAV1ReferenceInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_av1std_encode.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_av1std_encode.h new file mode 100644 index 00000000..3602fe12 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_av1std_encode.h @@ -0,0 +1,143 @@ +#ifndef VULKAN_VIDEO_CODEC_AV1STD_ENCODE_H_ +#define VULKAN_VIDEO_CODEC_AV1STD_ENCODE_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_av1std_encode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_av1std_encode 1 +#include "vulkan_video_codec_av1std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_av1_encode" +typedef struct StdVideoEncodeAV1DecoderModelInfo { + uint8_t buffer_delay_length_minus_1; + uint8_t buffer_removal_time_length_minus_1; + uint8_t frame_presentation_time_length_minus_1; + uint8_t reserved1; + uint32_t num_units_in_decoding_tick; +} StdVideoEncodeAV1DecoderModelInfo; + +typedef struct StdVideoEncodeAV1ExtensionHeader { + uint8_t temporal_id; + uint8_t spatial_id; +} StdVideoEncodeAV1ExtensionHeader; + +typedef struct StdVideoEncodeAV1OperatingPointInfoFlags { + uint32_t decoder_model_present_for_this_op : 1; + uint32_t low_delay_mode_flag : 1; + uint32_t initial_display_delay_present_for_this_op : 1; + uint32_t reserved : 29; +} StdVideoEncodeAV1OperatingPointInfoFlags; + +typedef struct StdVideoEncodeAV1OperatingPointInfo { + StdVideoEncodeAV1OperatingPointInfoFlags flags; + uint16_t operating_point_idc; + uint8_t seq_level_idx; + uint8_t seq_tier; + uint32_t decoder_buffer_delay; + uint32_t encoder_buffer_delay; + uint8_t initial_display_delay_minus_1; +} StdVideoEncodeAV1OperatingPointInfo; + +typedef struct StdVideoEncodeAV1PictureInfoFlags { + uint32_t error_resilient_mode : 1; + uint32_t disable_cdf_update : 1; + uint32_t use_superres : 1; + uint32_t render_and_frame_size_different : 1; + uint32_t allow_screen_content_tools : 1; + uint32_t is_filter_switchable : 1; + uint32_t force_integer_mv : 1; + uint32_t frame_size_override_flag : 1; + uint32_t buffer_removal_time_present_flag : 1; + uint32_t allow_intrabc : 1; + uint32_t frame_refs_short_signaling : 1; + uint32_t allow_high_precision_mv : 1; + uint32_t is_motion_mode_switchable : 1; + uint32_t use_ref_frame_mvs : 1; + uint32_t disable_frame_end_update_cdf : 1; + uint32_t allow_warped_motion : 1; + uint32_t reduced_tx_set : 1; + uint32_t skip_mode_present : 1; + uint32_t delta_q_present : 1; + uint32_t delta_lf_present : 1; + uint32_t delta_lf_multi : 1; + uint32_t segmentation_enabled : 1; + uint32_t segmentation_update_map : 1; + uint32_t segmentation_temporal_update : 1; + uint32_t segmentation_update_data : 1; + uint32_t UsesLr : 1; + uint32_t usesChromaLr : 1; + uint32_t show_frame : 1; + uint32_t showable_frame : 1; + uint32_t reserved : 3; +} StdVideoEncodeAV1PictureInfoFlags; + +typedef struct StdVideoEncodeAV1PictureInfo { + StdVideoEncodeAV1PictureInfoFlags flags; + StdVideoAV1FrameType frame_type; + uint32_t frame_presentation_time; + uint32_t current_frame_id; + uint8_t order_hint; + uint8_t primary_ref_frame; + uint8_t refresh_frame_flags; + uint8_t coded_denom; + uint16_t render_width_minus_1; + uint16_t render_height_minus_1; + StdVideoAV1InterpolationFilter interpolation_filter; + StdVideoAV1TxMode TxMode; + uint8_t delta_q_res; + uint8_t delta_lf_res; + uint8_t ref_order_hint[STD_VIDEO_AV1_NUM_REF_FRAMES]; + int8_t ref_frame_idx[STD_VIDEO_AV1_REFS_PER_FRAME]; + uint8_t reserved1[3]; + uint32_t delta_frame_id_minus_1[STD_VIDEO_AV1_REFS_PER_FRAME]; + const StdVideoAV1TileInfo* pTileInfo; + const StdVideoAV1Quantization* pQuantization; + const StdVideoAV1Segmentation* pSegmentation; + const StdVideoAV1LoopFilter* pLoopFilter; + const StdVideoAV1CDEF* pCDEF; + const StdVideoAV1LoopRestoration* pLoopRestoration; + const StdVideoAV1GlobalMotion* pGlobalMotion; + const StdVideoEncodeAV1ExtensionHeader* pExtensionHeader; + const uint32_t* pBufferRemovalTimes; +} StdVideoEncodeAV1PictureInfo; + +typedef struct StdVideoEncodeAV1ReferenceInfoFlags { + uint32_t disable_frame_end_update_cdf : 1; + uint32_t segmentation_enabled : 1; + uint32_t reserved : 30; +} StdVideoEncodeAV1ReferenceInfoFlags; + +typedef struct StdVideoEncodeAV1ReferenceInfo { + StdVideoEncodeAV1ReferenceInfoFlags flags; + uint32_t RefFrameId; + StdVideoAV1FrameType frame_type; + uint8_t OrderHint; + uint8_t reserved1[3]; + const StdVideoEncodeAV1ExtensionHeader* pExtensionHeader; +} StdVideoEncodeAV1ReferenceInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h264std.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h264std.h new file mode 100644 index 00000000..48621b69 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h264std.h @@ -0,0 +1,312 @@ +#ifndef VULKAN_VIDEO_CODEC_H264STD_H_ +#define VULKAN_VIDEO_CODEC_H264STD_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h264std is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h264std 1 +#include "vulkan_video_codecs_common.h" +#define STD_VIDEO_H264_CPB_CNT_LIST_SIZE 32U +#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS 6U +#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS 16U +#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS 6U +#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS 64U +#define STD_VIDEO_H264_MAX_NUM_LIST_REF 32U +#define STD_VIDEO_H264_MAX_CHROMA_PLANES 2U +#define STD_VIDEO_H264_NO_REFERENCE_PICTURE 0xFFU + +typedef enum StdVideoH264ChromaFormatIdc { + STD_VIDEO_H264_CHROMA_FORMAT_IDC_MONOCHROME = 0, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_420 = 1, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_422 = 2, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_444 = 3, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_CHROMA_FORMAT_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264ChromaFormatIdc; + +typedef enum StdVideoH264ProfileIdc { + STD_VIDEO_H264_PROFILE_IDC_BASELINE = 66, + STD_VIDEO_H264_PROFILE_IDC_MAIN = 77, + STD_VIDEO_H264_PROFILE_IDC_HIGH = 100, + STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE = 244, + STD_VIDEO_H264_PROFILE_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_PROFILE_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264ProfileIdc; + +typedef enum StdVideoH264LevelIdc { + STD_VIDEO_H264_LEVEL_IDC_1_0 = 0, + STD_VIDEO_H264_LEVEL_IDC_1_1 = 1, + STD_VIDEO_H264_LEVEL_IDC_1_2 = 2, + STD_VIDEO_H264_LEVEL_IDC_1_3 = 3, + STD_VIDEO_H264_LEVEL_IDC_2_0 = 4, + STD_VIDEO_H264_LEVEL_IDC_2_1 = 5, + STD_VIDEO_H264_LEVEL_IDC_2_2 = 6, + STD_VIDEO_H264_LEVEL_IDC_3_0 = 7, + STD_VIDEO_H264_LEVEL_IDC_3_1 = 8, + STD_VIDEO_H264_LEVEL_IDC_3_2 = 9, + STD_VIDEO_H264_LEVEL_IDC_4_0 = 10, + STD_VIDEO_H264_LEVEL_IDC_4_1 = 11, + STD_VIDEO_H264_LEVEL_IDC_4_2 = 12, + STD_VIDEO_H264_LEVEL_IDC_5_0 = 13, + STD_VIDEO_H264_LEVEL_IDC_5_1 = 14, + STD_VIDEO_H264_LEVEL_IDC_5_2 = 15, + STD_VIDEO_H264_LEVEL_IDC_6_0 = 16, + STD_VIDEO_H264_LEVEL_IDC_6_1 = 17, + STD_VIDEO_H264_LEVEL_IDC_6_2 = 18, + STD_VIDEO_H264_LEVEL_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_LEVEL_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264LevelIdc; + +typedef enum StdVideoH264PocType { + STD_VIDEO_H264_POC_TYPE_0 = 0, + STD_VIDEO_H264_POC_TYPE_1 = 1, + STD_VIDEO_H264_POC_TYPE_2 = 2, + STD_VIDEO_H264_POC_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_POC_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264PocType; + +typedef enum StdVideoH264AspectRatioIdc { + STD_VIDEO_H264_ASPECT_RATIO_IDC_UNSPECIFIED = 0, + STD_VIDEO_H264_ASPECT_RATIO_IDC_SQUARE = 1, + STD_VIDEO_H264_ASPECT_RATIO_IDC_12_11 = 2, + STD_VIDEO_H264_ASPECT_RATIO_IDC_10_11 = 3, + STD_VIDEO_H264_ASPECT_RATIO_IDC_16_11 = 4, + STD_VIDEO_H264_ASPECT_RATIO_IDC_40_33 = 5, + STD_VIDEO_H264_ASPECT_RATIO_IDC_24_11 = 6, + STD_VIDEO_H264_ASPECT_RATIO_IDC_20_11 = 7, + STD_VIDEO_H264_ASPECT_RATIO_IDC_32_11 = 8, + STD_VIDEO_H264_ASPECT_RATIO_IDC_80_33 = 9, + STD_VIDEO_H264_ASPECT_RATIO_IDC_18_11 = 10, + STD_VIDEO_H264_ASPECT_RATIO_IDC_15_11 = 11, + STD_VIDEO_H264_ASPECT_RATIO_IDC_64_33 = 12, + STD_VIDEO_H264_ASPECT_RATIO_IDC_160_99 = 13, + STD_VIDEO_H264_ASPECT_RATIO_IDC_4_3 = 14, + STD_VIDEO_H264_ASPECT_RATIO_IDC_3_2 = 15, + STD_VIDEO_H264_ASPECT_RATIO_IDC_2_1 = 16, + STD_VIDEO_H264_ASPECT_RATIO_IDC_EXTENDED_SAR = 255, + STD_VIDEO_H264_ASPECT_RATIO_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_ASPECT_RATIO_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264AspectRatioIdc; + +typedef enum StdVideoH264WeightedBipredIdc { + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_DEFAULT = 0, + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_EXPLICIT = 1, + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_IMPLICIT = 2, + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264WeightedBipredIdc; + +typedef enum StdVideoH264ModificationOfPicNumsIdc { + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_SHORT_TERM_SUBTRACT = 0, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_SHORT_TERM_ADD = 1, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_LONG_TERM = 2, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_END = 3, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264ModificationOfPicNumsIdc; + +typedef enum StdVideoH264MemMgmtControlOp { + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_END = 0, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_SHORT_TERM = 1, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_LONG_TERM = 2, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MARK_LONG_TERM = 3, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_SET_MAX_LONG_TERM_INDEX = 4, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_ALL = 5, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MARK_CURRENT_AS_LONG_TERM = 6, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264MemMgmtControlOp; + +typedef enum StdVideoH264CabacInitIdc { + STD_VIDEO_H264_CABAC_INIT_IDC_0 = 0, + STD_VIDEO_H264_CABAC_INIT_IDC_1 = 1, + STD_VIDEO_H264_CABAC_INIT_IDC_2 = 2, + STD_VIDEO_H264_CABAC_INIT_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_CABAC_INIT_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264CabacInitIdc; + +typedef enum StdVideoH264DisableDeblockingFilterIdc { + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_DISABLED = 0, + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_ENABLED = 1, + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_PARTIAL = 2, + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264DisableDeblockingFilterIdc; + +typedef enum StdVideoH264SliceType { + STD_VIDEO_H264_SLICE_TYPE_P = 0, + STD_VIDEO_H264_SLICE_TYPE_B = 1, + STD_VIDEO_H264_SLICE_TYPE_I = 2, + STD_VIDEO_H264_SLICE_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_SLICE_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264SliceType; + +typedef enum StdVideoH264PictureType { + STD_VIDEO_H264_PICTURE_TYPE_P = 0, + STD_VIDEO_H264_PICTURE_TYPE_B = 1, + STD_VIDEO_H264_PICTURE_TYPE_I = 2, + STD_VIDEO_H264_PICTURE_TYPE_IDR = 5, + STD_VIDEO_H264_PICTURE_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_PICTURE_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264PictureType; + +typedef enum StdVideoH264NonVclNaluType { + STD_VIDEO_H264_NON_VCL_NALU_TYPE_SPS = 0, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_PPS = 1, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_AUD = 2, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_PREFIX = 3, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_END_OF_SEQUENCE = 4, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_END_OF_STREAM = 5, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_PRECODED = 6, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H264_NON_VCL_NALU_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH264NonVclNaluType; +typedef struct StdVideoH264SpsVuiFlags { + uint32_t aspect_ratio_info_present_flag : 1; + uint32_t overscan_info_present_flag : 1; + uint32_t overscan_appropriate_flag : 1; + uint32_t video_signal_type_present_flag : 1; + uint32_t video_full_range_flag : 1; + uint32_t color_description_present_flag : 1; + uint32_t chroma_loc_info_present_flag : 1; + uint32_t timing_info_present_flag : 1; + uint32_t fixed_frame_rate_flag : 1; + uint32_t bitstream_restriction_flag : 1; + uint32_t nal_hrd_parameters_present_flag : 1; + uint32_t vcl_hrd_parameters_present_flag : 1; +} StdVideoH264SpsVuiFlags; + +typedef struct StdVideoH264HrdParameters { + uint8_t cpb_cnt_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t reserved1; + uint32_t bit_rate_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE]; + uint32_t cpb_size_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE]; + uint8_t cbr_flag[STD_VIDEO_H264_CPB_CNT_LIST_SIZE]; + uint32_t initial_cpb_removal_delay_length_minus1; + uint32_t cpb_removal_delay_length_minus1; + uint32_t dpb_output_delay_length_minus1; + uint32_t time_offset_length; +} StdVideoH264HrdParameters; + +typedef struct StdVideoH264SequenceParameterSetVui { + StdVideoH264SpsVuiFlags flags; + StdVideoH264AspectRatioIdc aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + uint8_t video_format; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + uint32_t num_units_in_tick; + uint32_t time_scale; + uint8_t max_num_reorder_frames; + uint8_t max_dec_frame_buffering; + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + uint32_t reserved1; + const StdVideoH264HrdParameters* pHrdParameters; +} StdVideoH264SequenceParameterSetVui; + +typedef struct StdVideoH264SpsFlags { + uint32_t constraint_set0_flag : 1; + uint32_t constraint_set1_flag : 1; + uint32_t constraint_set2_flag : 1; + uint32_t constraint_set3_flag : 1; + uint32_t constraint_set4_flag : 1; + uint32_t constraint_set5_flag : 1; + uint32_t direct_8x8_inference_flag : 1; + uint32_t mb_adaptive_frame_field_flag : 1; + uint32_t frame_mbs_only_flag : 1; + uint32_t delta_pic_order_always_zero_flag : 1; + uint32_t separate_colour_plane_flag : 1; + uint32_t gaps_in_frame_num_value_allowed_flag : 1; + uint32_t qpprime_y_zero_transform_bypass_flag : 1; + uint32_t frame_cropping_flag : 1; + uint32_t seq_scaling_matrix_present_flag : 1; + uint32_t vui_parameters_present_flag : 1; +} StdVideoH264SpsFlags; + +typedef struct StdVideoH264ScalingLists { + uint16_t scaling_list_present_mask; + uint16_t use_default_scaling_matrix_mask; + uint8_t ScalingList4x4[STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS]; + uint8_t ScalingList8x8[STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS]; +} StdVideoH264ScalingLists; + +typedef struct StdVideoH264SequenceParameterSet { + StdVideoH264SpsFlags flags; + StdVideoH264ProfileIdc profile_idc; + StdVideoH264LevelIdc level_idc; + StdVideoH264ChromaFormatIdc chroma_format_idc; + uint8_t seq_parameter_set_id; + uint8_t bit_depth_luma_minus8; + uint8_t bit_depth_chroma_minus8; + uint8_t log2_max_frame_num_minus4; + StdVideoH264PocType pic_order_cnt_type; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + uint8_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t num_ref_frames_in_pic_order_cnt_cycle; + uint8_t max_num_ref_frames; + uint8_t reserved1; + uint32_t pic_width_in_mbs_minus1; + uint32_t pic_height_in_map_units_minus1; + uint32_t frame_crop_left_offset; + uint32_t frame_crop_right_offset; + uint32_t frame_crop_top_offset; + uint32_t frame_crop_bottom_offset; + uint32_t reserved2; + const int32_t* pOffsetForRefFrame; + const StdVideoH264ScalingLists* pScalingLists; + const StdVideoH264SequenceParameterSetVui* pSequenceParameterSetVui; +} StdVideoH264SequenceParameterSet; + +typedef struct StdVideoH264PpsFlags { + uint32_t transform_8x8_mode_flag : 1; + uint32_t redundant_pic_cnt_present_flag : 1; + uint32_t constrained_intra_pred_flag : 1; + uint32_t deblocking_filter_control_present_flag : 1; + uint32_t weighted_pred_flag : 1; + uint32_t bottom_field_pic_order_in_frame_present_flag : 1; + uint32_t entropy_coding_mode_flag : 1; + uint32_t pic_scaling_matrix_present_flag : 1; +} StdVideoH264PpsFlags; + +typedef struct StdVideoH264PictureParameterSet { + StdVideoH264PpsFlags flags; + uint8_t seq_parameter_set_id; + uint8_t pic_parameter_set_id; + uint8_t num_ref_idx_l0_default_active_minus1; + uint8_t num_ref_idx_l1_default_active_minus1; + StdVideoH264WeightedBipredIdc weighted_bipred_idc; + int8_t pic_init_qp_minus26; + int8_t pic_init_qs_minus26; + int8_t chroma_qp_index_offset; + int8_t second_chroma_qp_index_offset; + const StdVideoH264ScalingLists* pScalingLists; +} StdVideoH264PictureParameterSet; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h264std_decode.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h264std_decode.h new file mode 100644 index 00000000..a6bfe9d8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h264std_decode.h @@ -0,0 +1,77 @@ +#ifndef VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ +#define VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h264std_decode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h264std_decode 1 +#include "vulkan_video_codec_h264std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_decode" +#define STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE 2U + +typedef enum StdVideoDecodeH264FieldOrderCount { + STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_TOP = 0, + STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_BOTTOM = 1, + STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_INVALID = 0x7FFFFFFF, + STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_MAX_ENUM = 0x7FFFFFFF +} StdVideoDecodeH264FieldOrderCount; +typedef struct StdVideoDecodeH264PictureInfoFlags { + uint32_t field_pic_flag : 1; + uint32_t is_intra : 1; + uint32_t IdrPicFlag : 1; + uint32_t bottom_field_flag : 1; + uint32_t is_reference : 1; + uint32_t complementary_field_pair : 1; +} StdVideoDecodeH264PictureInfoFlags; + +typedef struct StdVideoDecodeH264PictureInfo { + StdVideoDecodeH264PictureInfoFlags flags; + uint8_t seq_parameter_set_id; + uint8_t pic_parameter_set_id; + uint8_t reserved1; + uint8_t reserved2; + uint16_t frame_num; + uint16_t idr_pic_id; + int32_t PicOrderCnt[STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE]; +} StdVideoDecodeH264PictureInfo; + +typedef struct StdVideoDecodeH264ReferenceInfoFlags { + uint32_t top_field_flag : 1; + uint32_t bottom_field_flag : 1; + uint32_t used_for_long_term_reference : 1; + uint32_t is_non_existing : 1; +} StdVideoDecodeH264ReferenceInfoFlags; + +typedef struct StdVideoDecodeH264ReferenceInfo { + StdVideoDecodeH264ReferenceInfoFlags flags; + uint16_t FrameNum; + uint16_t reserved; + int32_t PicOrderCnt[STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE]; +} StdVideoDecodeH264ReferenceInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h264std_encode.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h264std_encode.h new file mode 100644 index 00000000..2d42ac32 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h264std_encode.h @@ -0,0 +1,147 @@ +#ifndef VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ +#define VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h264std_encode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h264std_encode 1 +#include "vulkan_video_codec_h264std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_encode" +typedef struct StdVideoEncodeH264WeightTableFlags { + uint32_t luma_weight_l0_flag; + uint32_t chroma_weight_l0_flag; + uint32_t luma_weight_l1_flag; + uint32_t chroma_weight_l1_flag; +} StdVideoEncodeH264WeightTableFlags; + +typedef struct StdVideoEncodeH264WeightTable { + StdVideoEncodeH264WeightTableFlags flags; + uint8_t luma_log2_weight_denom; + uint8_t chroma_log2_weight_denom; + int8_t luma_weight_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + int8_t luma_offset_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + int8_t chroma_weight_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES]; + int8_t chroma_offset_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES]; + int8_t luma_weight_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + int8_t luma_offset_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + int8_t chroma_weight_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES]; + int8_t chroma_offset_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES]; +} StdVideoEncodeH264WeightTable; + +typedef struct StdVideoEncodeH264SliceHeaderFlags { + uint32_t direct_spatial_mv_pred_flag : 1; + uint32_t num_ref_idx_active_override_flag : 1; + uint32_t reserved : 30; +} StdVideoEncodeH264SliceHeaderFlags; + +typedef struct StdVideoEncodeH264PictureInfoFlags { + uint32_t IdrPicFlag : 1; + uint32_t is_reference : 1; + uint32_t no_output_of_prior_pics_flag : 1; + uint32_t long_term_reference_flag : 1; + uint32_t adaptive_ref_pic_marking_mode_flag : 1; + uint32_t reserved : 27; +} StdVideoEncodeH264PictureInfoFlags; + +typedef struct StdVideoEncodeH264ReferenceInfoFlags { + uint32_t used_for_long_term_reference : 1; + uint32_t reserved : 31; +} StdVideoEncodeH264ReferenceInfoFlags; + +typedef struct StdVideoEncodeH264ReferenceListsInfoFlags { + uint32_t ref_pic_list_modification_flag_l0 : 1; + uint32_t ref_pic_list_modification_flag_l1 : 1; + uint32_t reserved : 30; +} StdVideoEncodeH264ReferenceListsInfoFlags; + +typedef struct StdVideoEncodeH264RefListModEntry { + StdVideoH264ModificationOfPicNumsIdc modification_of_pic_nums_idc; + uint16_t abs_diff_pic_num_minus1; + uint16_t long_term_pic_num; +} StdVideoEncodeH264RefListModEntry; + +typedef struct StdVideoEncodeH264RefPicMarkingEntry { + StdVideoH264MemMgmtControlOp memory_management_control_operation; + uint16_t difference_of_pic_nums_minus1; + uint16_t long_term_pic_num; + uint16_t long_term_frame_idx; + uint16_t max_long_term_frame_idx_plus1; +} StdVideoEncodeH264RefPicMarkingEntry; + +typedef struct StdVideoEncodeH264ReferenceListsInfo { + StdVideoEncodeH264ReferenceListsInfoFlags flags; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + uint8_t RefPicList0[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + uint8_t RefPicList1[STD_VIDEO_H264_MAX_NUM_LIST_REF]; + uint8_t refList0ModOpCount; + uint8_t refList1ModOpCount; + uint8_t refPicMarkingOpCount; + uint8_t reserved1[7]; + const StdVideoEncodeH264RefListModEntry* pRefList0ModOperations; + const StdVideoEncodeH264RefListModEntry* pRefList1ModOperations; + const StdVideoEncodeH264RefPicMarkingEntry* pRefPicMarkingOperations; +} StdVideoEncodeH264ReferenceListsInfo; + +typedef struct StdVideoEncodeH264PictureInfo { + StdVideoEncodeH264PictureInfoFlags flags; + uint8_t seq_parameter_set_id; + uint8_t pic_parameter_set_id; + uint16_t idr_pic_id; + StdVideoH264PictureType primary_pic_type; + uint32_t frame_num; + int32_t PicOrderCnt; + uint8_t temporal_id; + uint8_t reserved1[3]; + const StdVideoEncodeH264ReferenceListsInfo* pRefLists; +} StdVideoEncodeH264PictureInfo; + +typedef struct StdVideoEncodeH264ReferenceInfo { + StdVideoEncodeH264ReferenceInfoFlags flags; + StdVideoH264PictureType primary_pic_type; + uint32_t FrameNum; + int32_t PicOrderCnt; + uint16_t long_term_pic_num; + uint16_t long_term_frame_idx; + uint8_t temporal_id; +} StdVideoEncodeH264ReferenceInfo; + +typedef struct StdVideoEncodeH264SliceHeader { + StdVideoEncodeH264SliceHeaderFlags flags; + uint32_t first_mb_in_slice; + StdVideoH264SliceType slice_type; + int8_t slice_alpha_c0_offset_div2; + int8_t slice_beta_offset_div2; + int8_t slice_qp_delta; + uint8_t reserved1; + StdVideoH264CabacInitIdc cabac_init_idc; + StdVideoH264DisableDeblockingFilterIdc disable_deblocking_filter_idc; + const StdVideoEncodeH264WeightTable* pWeightTable; +} StdVideoEncodeH264SliceHeader; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h265std.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h265std.h new file mode 100644 index 00000000..23617b8f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h265std.h @@ -0,0 +1,446 @@ +#ifndef VULKAN_VIDEO_CODEC_H265STD_H_ +#define VULKAN_VIDEO_CODEC_H265STD_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h265std is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h265std 1 +#include "vulkan_video_codecs_common.h" +#define STD_VIDEO_H265_CPB_CNT_LIST_SIZE 32U +#define STD_VIDEO_H265_SUBLAYERS_LIST_SIZE 7U +#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS 6U +#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS 16U +#define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS 6U +#define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS 64U +#define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS 6U +#define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS 64U +#define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS 2U +#define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS 64U +#define STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE 6U +#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE 19U +#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE 21U +#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE 3U +#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE 128U +#define STD_VIDEO_H265_MAX_NUM_LIST_REF 15U +#define STD_VIDEO_H265_MAX_CHROMA_PLANES 2U +#define STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS 64U +#define STD_VIDEO_H265_MAX_DPB_SIZE 16U +#define STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS 32U +#define STD_VIDEO_H265_MAX_LONG_TERM_PICS 16U +#define STD_VIDEO_H265_MAX_DELTA_POC 48U +#define STD_VIDEO_H265_NO_REFERENCE_PICTURE 0xFFU + +typedef enum StdVideoH265ChromaFormatIdc { + STD_VIDEO_H265_CHROMA_FORMAT_IDC_MONOCHROME = 0, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_420 = 1, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_422 = 2, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_444 = 3, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_CHROMA_FORMAT_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265ChromaFormatIdc; + +typedef enum StdVideoH265ProfileIdc { + STD_VIDEO_H265_PROFILE_IDC_MAIN = 1, + STD_VIDEO_H265_PROFILE_IDC_MAIN_10 = 2, + STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE = 3, + STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS = 4, + STD_VIDEO_H265_PROFILE_IDC_SCC_EXTENSIONS = 9, + STD_VIDEO_H265_PROFILE_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_PROFILE_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265ProfileIdc; + +typedef enum StdVideoH265LevelIdc { + STD_VIDEO_H265_LEVEL_IDC_1_0 = 0, + STD_VIDEO_H265_LEVEL_IDC_2_0 = 1, + STD_VIDEO_H265_LEVEL_IDC_2_1 = 2, + STD_VIDEO_H265_LEVEL_IDC_3_0 = 3, + STD_VIDEO_H265_LEVEL_IDC_3_1 = 4, + STD_VIDEO_H265_LEVEL_IDC_4_0 = 5, + STD_VIDEO_H265_LEVEL_IDC_4_1 = 6, + STD_VIDEO_H265_LEVEL_IDC_5_0 = 7, + STD_VIDEO_H265_LEVEL_IDC_5_1 = 8, + STD_VIDEO_H265_LEVEL_IDC_5_2 = 9, + STD_VIDEO_H265_LEVEL_IDC_6_0 = 10, + STD_VIDEO_H265_LEVEL_IDC_6_1 = 11, + STD_VIDEO_H265_LEVEL_IDC_6_2 = 12, + STD_VIDEO_H265_LEVEL_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_LEVEL_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265LevelIdc; + +typedef enum StdVideoH265SliceType { + STD_VIDEO_H265_SLICE_TYPE_B = 0, + STD_VIDEO_H265_SLICE_TYPE_P = 1, + STD_VIDEO_H265_SLICE_TYPE_I = 2, + STD_VIDEO_H265_SLICE_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_SLICE_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265SliceType; + +typedef enum StdVideoH265PictureType { + STD_VIDEO_H265_PICTURE_TYPE_P = 0, + STD_VIDEO_H265_PICTURE_TYPE_B = 1, + STD_VIDEO_H265_PICTURE_TYPE_I = 2, + STD_VIDEO_H265_PICTURE_TYPE_IDR = 3, + STD_VIDEO_H265_PICTURE_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_PICTURE_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265PictureType; + +typedef enum StdVideoH265AspectRatioIdc { + STD_VIDEO_H265_ASPECT_RATIO_IDC_UNSPECIFIED = 0, + STD_VIDEO_H265_ASPECT_RATIO_IDC_SQUARE = 1, + STD_VIDEO_H265_ASPECT_RATIO_IDC_12_11 = 2, + STD_VIDEO_H265_ASPECT_RATIO_IDC_10_11 = 3, + STD_VIDEO_H265_ASPECT_RATIO_IDC_16_11 = 4, + STD_VIDEO_H265_ASPECT_RATIO_IDC_40_33 = 5, + STD_VIDEO_H265_ASPECT_RATIO_IDC_24_11 = 6, + STD_VIDEO_H265_ASPECT_RATIO_IDC_20_11 = 7, + STD_VIDEO_H265_ASPECT_RATIO_IDC_32_11 = 8, + STD_VIDEO_H265_ASPECT_RATIO_IDC_80_33 = 9, + STD_VIDEO_H265_ASPECT_RATIO_IDC_18_11 = 10, + STD_VIDEO_H265_ASPECT_RATIO_IDC_15_11 = 11, + STD_VIDEO_H265_ASPECT_RATIO_IDC_64_33 = 12, + STD_VIDEO_H265_ASPECT_RATIO_IDC_160_99 = 13, + STD_VIDEO_H265_ASPECT_RATIO_IDC_4_3 = 14, + STD_VIDEO_H265_ASPECT_RATIO_IDC_3_2 = 15, + STD_VIDEO_H265_ASPECT_RATIO_IDC_2_1 = 16, + STD_VIDEO_H265_ASPECT_RATIO_IDC_EXTENDED_SAR = 255, + STD_VIDEO_H265_ASPECT_RATIO_IDC_INVALID = 0x7FFFFFFF, + STD_VIDEO_H265_ASPECT_RATIO_IDC_MAX_ENUM = 0x7FFFFFFF +} StdVideoH265AspectRatioIdc; +typedef struct StdVideoH265DecPicBufMgr { + uint32_t max_latency_increase_plus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; + uint8_t max_dec_pic_buffering_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; + uint8_t max_num_reorder_pics[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; +} StdVideoH265DecPicBufMgr; + +typedef struct StdVideoH265SubLayerHrdParameters { + uint32_t bit_rate_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; + uint32_t cpb_size_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; + uint32_t cpb_size_du_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; + uint32_t bit_rate_du_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; + uint32_t cbr_flag; +} StdVideoH265SubLayerHrdParameters; + +typedef struct StdVideoH265HrdFlags { + uint32_t nal_hrd_parameters_present_flag : 1; + uint32_t vcl_hrd_parameters_present_flag : 1; + uint32_t sub_pic_hrd_params_present_flag : 1; + uint32_t sub_pic_cpb_params_in_pic_timing_sei_flag : 1; + uint32_t fixed_pic_rate_general_flag : 8; + uint32_t fixed_pic_rate_within_cvs_flag : 8; + uint32_t low_delay_hrd_flag : 8; +} StdVideoH265HrdFlags; + +typedef struct StdVideoH265HrdParameters { + StdVideoH265HrdFlags flags; + uint8_t tick_divisor_minus2; + uint8_t du_cpb_removal_delay_increment_length_minus1; + uint8_t dpb_output_delay_du_length_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t cpb_size_du_scale; + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t au_cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + uint8_t cpb_cnt_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; + uint16_t elemental_duration_in_tc_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; + uint16_t reserved[3]; + const StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersNal; + const StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersVcl; +} StdVideoH265HrdParameters; + +typedef struct StdVideoH265VpsFlags { + uint32_t vps_temporal_id_nesting_flag : 1; + uint32_t vps_sub_layer_ordering_info_present_flag : 1; + uint32_t vps_timing_info_present_flag : 1; + uint32_t vps_poc_proportional_to_timing_flag : 1; +} StdVideoH265VpsFlags; + +typedef struct StdVideoH265ProfileTierLevelFlags { + uint32_t general_tier_flag : 1; + uint32_t general_progressive_source_flag : 1; + uint32_t general_interlaced_source_flag : 1; + uint32_t general_non_packed_constraint_flag : 1; + uint32_t general_frame_only_constraint_flag : 1; +} StdVideoH265ProfileTierLevelFlags; + +typedef struct StdVideoH265ProfileTierLevel { + StdVideoH265ProfileTierLevelFlags flags; + StdVideoH265ProfileIdc general_profile_idc; + StdVideoH265LevelIdc general_level_idc; +} StdVideoH265ProfileTierLevel; + +typedef struct StdVideoH265VideoParameterSet { + StdVideoH265VpsFlags flags; + uint8_t vps_video_parameter_set_id; + uint8_t vps_max_sub_layers_minus1; + uint8_t reserved1; + uint8_t reserved2; + uint32_t vps_num_units_in_tick; + uint32_t vps_time_scale; + uint32_t vps_num_ticks_poc_diff_one_minus1; + uint32_t reserved3; + const StdVideoH265DecPicBufMgr* pDecPicBufMgr; + const StdVideoH265HrdParameters* pHrdParameters; + const StdVideoH265ProfileTierLevel* pProfileTierLevel; +} StdVideoH265VideoParameterSet; + +typedef struct StdVideoH265ScalingLists { + uint8_t ScalingList4x4[STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS]; + uint8_t ScalingList8x8[STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS]; + uint8_t ScalingList16x16[STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS]; + uint8_t ScalingList32x32[STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS]; + uint8_t ScalingListDCCoef16x16[STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS]; + uint8_t ScalingListDCCoef32x32[STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS]; +} StdVideoH265ScalingLists; + +typedef struct StdVideoH265SpsVuiFlags { + uint32_t aspect_ratio_info_present_flag : 1; + uint32_t overscan_info_present_flag : 1; + uint32_t overscan_appropriate_flag : 1; + uint32_t video_signal_type_present_flag : 1; + uint32_t video_full_range_flag : 1; + uint32_t colour_description_present_flag : 1; + uint32_t chroma_loc_info_present_flag : 1; + uint32_t neutral_chroma_indication_flag : 1; + uint32_t field_seq_flag : 1; + uint32_t frame_field_info_present_flag : 1; + uint32_t default_display_window_flag : 1; + uint32_t vui_timing_info_present_flag : 1; + uint32_t vui_poc_proportional_to_timing_flag : 1; + uint32_t vui_hrd_parameters_present_flag : 1; + uint32_t bitstream_restriction_flag : 1; + uint32_t tiles_fixed_structure_flag : 1; + uint32_t motion_vectors_over_pic_boundaries_flag : 1; + uint32_t restricted_ref_pic_lists_flag : 1; +} StdVideoH265SpsVuiFlags; + +typedef struct StdVideoH265SequenceParameterSetVui { + StdVideoH265SpsVuiFlags flags; + StdVideoH265AspectRatioIdc aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + uint8_t video_format; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coeffs; + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + uint8_t reserved1; + uint8_t reserved2; + uint16_t def_disp_win_left_offset; + uint16_t def_disp_win_right_offset; + uint16_t def_disp_win_top_offset; + uint16_t def_disp_win_bottom_offset; + uint32_t vui_num_units_in_tick; + uint32_t vui_time_scale; + uint32_t vui_num_ticks_poc_diff_one_minus1; + uint16_t min_spatial_segmentation_idc; + uint16_t reserved3; + uint8_t max_bytes_per_pic_denom; + uint8_t max_bits_per_min_cu_denom; + uint8_t log2_max_mv_length_horizontal; + uint8_t log2_max_mv_length_vertical; + const StdVideoH265HrdParameters* pHrdParameters; +} StdVideoH265SequenceParameterSetVui; + +typedef struct StdVideoH265PredictorPaletteEntries { + uint16_t PredictorPaletteEntries[STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE][STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE]; +} StdVideoH265PredictorPaletteEntries; + +typedef struct StdVideoH265SpsFlags { + uint32_t sps_temporal_id_nesting_flag : 1; + uint32_t separate_colour_plane_flag : 1; + uint32_t conformance_window_flag : 1; + uint32_t sps_sub_layer_ordering_info_present_flag : 1; + uint32_t scaling_list_enabled_flag : 1; + uint32_t sps_scaling_list_data_present_flag : 1; + uint32_t amp_enabled_flag : 1; + uint32_t sample_adaptive_offset_enabled_flag : 1; + uint32_t pcm_enabled_flag : 1; + uint32_t pcm_loop_filter_disabled_flag : 1; + uint32_t long_term_ref_pics_present_flag : 1; + uint32_t sps_temporal_mvp_enabled_flag : 1; + uint32_t strong_intra_smoothing_enabled_flag : 1; + uint32_t vui_parameters_present_flag : 1; + uint32_t sps_extension_present_flag : 1; + uint32_t sps_range_extension_flag : 1; + uint32_t transform_skip_rotation_enabled_flag : 1; + uint32_t transform_skip_context_enabled_flag : 1; + uint32_t implicit_rdpcm_enabled_flag : 1; + uint32_t explicit_rdpcm_enabled_flag : 1; + uint32_t extended_precision_processing_flag : 1; + uint32_t intra_smoothing_disabled_flag : 1; + uint32_t high_precision_offsets_enabled_flag : 1; + uint32_t persistent_rice_adaptation_enabled_flag : 1; + uint32_t cabac_bypass_alignment_enabled_flag : 1; + uint32_t sps_scc_extension_flag : 1; + uint32_t sps_curr_pic_ref_enabled_flag : 1; + uint32_t palette_mode_enabled_flag : 1; + uint32_t sps_palette_predictor_initializers_present_flag : 1; + uint32_t intra_boundary_filtering_disabled_flag : 1; +} StdVideoH265SpsFlags; + +typedef struct StdVideoH265ShortTermRefPicSetFlags { + uint32_t inter_ref_pic_set_prediction_flag : 1; + uint32_t delta_rps_sign : 1; +} StdVideoH265ShortTermRefPicSetFlags; + +typedef struct StdVideoH265ShortTermRefPicSet { + StdVideoH265ShortTermRefPicSetFlags flags; + uint32_t delta_idx_minus1; + uint16_t use_delta_flag; + uint16_t abs_delta_rps_minus1; + uint16_t used_by_curr_pic_flag; + uint16_t used_by_curr_pic_s0_flag; + uint16_t used_by_curr_pic_s1_flag; + uint16_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + uint8_t num_negative_pics; + uint8_t num_positive_pics; + uint16_t delta_poc_s0_minus1[STD_VIDEO_H265_MAX_DPB_SIZE]; + uint16_t delta_poc_s1_minus1[STD_VIDEO_H265_MAX_DPB_SIZE]; +} StdVideoH265ShortTermRefPicSet; + +typedef struct StdVideoH265LongTermRefPicsSps { + uint32_t used_by_curr_pic_lt_sps_flag; + uint32_t lt_ref_pic_poc_lsb_sps[STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS]; +} StdVideoH265LongTermRefPicsSps; + +typedef struct StdVideoH265SequenceParameterSet { + StdVideoH265SpsFlags flags; + StdVideoH265ChromaFormatIdc chroma_format_idc; + uint32_t pic_width_in_luma_samples; + uint32_t pic_height_in_luma_samples; + uint8_t sps_video_parameter_set_id; + uint8_t sps_max_sub_layers_minus1; + uint8_t sps_seq_parameter_set_id; + uint8_t bit_depth_luma_minus8; + uint8_t bit_depth_chroma_minus8; + uint8_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t log2_min_luma_coding_block_size_minus3; + uint8_t log2_diff_max_min_luma_coding_block_size; + uint8_t log2_min_luma_transform_block_size_minus2; + uint8_t log2_diff_max_min_luma_transform_block_size; + uint8_t max_transform_hierarchy_depth_inter; + uint8_t max_transform_hierarchy_depth_intra; + uint8_t num_short_term_ref_pic_sets; + uint8_t num_long_term_ref_pics_sps; + uint8_t pcm_sample_bit_depth_luma_minus1; + uint8_t pcm_sample_bit_depth_chroma_minus1; + uint8_t log2_min_pcm_luma_coding_block_size_minus3; + uint8_t log2_diff_max_min_pcm_luma_coding_block_size; + uint8_t reserved1; + uint8_t reserved2; + uint8_t palette_max_size; + uint8_t delta_palette_max_predictor_size; + uint8_t motion_vector_resolution_control_idc; + uint8_t sps_num_palette_predictor_initializers_minus1; + uint32_t conf_win_left_offset; + uint32_t conf_win_right_offset; + uint32_t conf_win_top_offset; + uint32_t conf_win_bottom_offset; + const StdVideoH265ProfileTierLevel* pProfileTierLevel; + const StdVideoH265DecPicBufMgr* pDecPicBufMgr; + const StdVideoH265ScalingLists* pScalingLists; + const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet; + const StdVideoH265LongTermRefPicsSps* pLongTermRefPicsSps; + const StdVideoH265SequenceParameterSetVui* pSequenceParameterSetVui; + const StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries; +} StdVideoH265SequenceParameterSet; + +typedef struct StdVideoH265PpsFlags { + uint32_t dependent_slice_segments_enabled_flag : 1; + uint32_t output_flag_present_flag : 1; + uint32_t sign_data_hiding_enabled_flag : 1; + uint32_t cabac_init_present_flag : 1; + uint32_t constrained_intra_pred_flag : 1; + uint32_t transform_skip_enabled_flag : 1; + uint32_t cu_qp_delta_enabled_flag : 1; + uint32_t pps_slice_chroma_qp_offsets_present_flag : 1; + uint32_t weighted_pred_flag : 1; + uint32_t weighted_bipred_flag : 1; + uint32_t transquant_bypass_enabled_flag : 1; + uint32_t tiles_enabled_flag : 1; + uint32_t entropy_coding_sync_enabled_flag : 1; + uint32_t uniform_spacing_flag : 1; + uint32_t loop_filter_across_tiles_enabled_flag : 1; + uint32_t pps_loop_filter_across_slices_enabled_flag : 1; + uint32_t deblocking_filter_control_present_flag : 1; + uint32_t deblocking_filter_override_enabled_flag : 1; + uint32_t pps_deblocking_filter_disabled_flag : 1; + uint32_t pps_scaling_list_data_present_flag : 1; + uint32_t lists_modification_present_flag : 1; + uint32_t slice_segment_header_extension_present_flag : 1; + uint32_t pps_extension_present_flag : 1; + uint32_t cross_component_prediction_enabled_flag : 1; + uint32_t chroma_qp_offset_list_enabled_flag : 1; + uint32_t pps_curr_pic_ref_enabled_flag : 1; + uint32_t residual_adaptive_colour_transform_enabled_flag : 1; + uint32_t pps_slice_act_qp_offsets_present_flag : 1; + uint32_t pps_palette_predictor_initializers_present_flag : 1; + uint32_t monochrome_palette_flag : 1; + uint32_t pps_range_extension_flag : 1; +} StdVideoH265PpsFlags; + +typedef struct StdVideoH265PictureParameterSet { + StdVideoH265PpsFlags flags; + uint8_t pps_pic_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + uint8_t sps_video_parameter_set_id; + uint8_t num_extra_slice_header_bits; + uint8_t num_ref_idx_l0_default_active_minus1; + uint8_t num_ref_idx_l1_default_active_minus1; + int8_t init_qp_minus26; + uint8_t diff_cu_qp_delta_depth; + int8_t pps_cb_qp_offset; + int8_t pps_cr_qp_offset; + int8_t pps_beta_offset_div2; + int8_t pps_tc_offset_div2; + uint8_t log2_parallel_merge_level_minus2; + uint8_t log2_max_transform_skip_block_size_minus2; + uint8_t diff_cu_chroma_qp_offset_depth; + uint8_t chroma_qp_offset_list_len_minus1; + int8_t cb_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE]; + int8_t cr_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE]; + uint8_t log2_sao_offset_scale_luma; + uint8_t log2_sao_offset_scale_chroma; + int8_t pps_act_y_qp_offset_plus5; + int8_t pps_act_cb_qp_offset_plus5; + int8_t pps_act_cr_qp_offset_plus3; + uint8_t pps_num_palette_predictor_initializers; + uint8_t luma_bit_depth_entry_minus8; + uint8_t chroma_bit_depth_entry_minus8; + uint8_t num_tile_columns_minus1; + uint8_t num_tile_rows_minus1; + uint8_t reserved1; + uint8_t reserved2; + uint16_t column_width_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE]; + uint16_t row_height_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE]; + uint32_t reserved3; + const StdVideoH265ScalingLists* pScalingLists; + const StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries; +} StdVideoH265PictureParameterSet; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h265std_decode.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h265std_decode.h new file mode 100644 index 00000000..1758d4a8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h265std_decode.h @@ -0,0 +1,67 @@ +#ifndef VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ +#define VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h265std_decode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h265std_decode 1 +#include "vulkan_video_codec_h265std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_decode" +#define STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE 8U +typedef struct StdVideoDecodeH265PictureInfoFlags { + uint32_t IrapPicFlag : 1; + uint32_t IdrPicFlag : 1; + uint32_t IsReference : 1; + uint32_t short_term_ref_pic_set_sps_flag : 1; +} StdVideoDecodeH265PictureInfoFlags; + +typedef struct StdVideoDecodeH265PictureInfo { + StdVideoDecodeH265PictureInfoFlags flags; + uint8_t sps_video_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + uint8_t pps_pic_parameter_set_id; + uint8_t NumDeltaPocsOfRefRpsIdx; + int32_t PicOrderCntVal; + uint16_t NumBitsForSTRefPicSetInSlice; + uint16_t reserved; + uint8_t RefPicSetStCurrBefore[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE]; + uint8_t RefPicSetStCurrAfter[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE]; + uint8_t RefPicSetLtCurr[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE]; +} StdVideoDecodeH265PictureInfo; + +typedef struct StdVideoDecodeH265ReferenceInfoFlags { + uint32_t used_for_long_term_reference : 1; + uint32_t unused_for_reference : 1; +} StdVideoDecodeH265ReferenceInfoFlags; + +typedef struct StdVideoDecodeH265ReferenceInfo { + StdVideoDecodeH265ReferenceInfoFlags flags; + int32_t PicOrderCntVal; +} StdVideoDecodeH265ReferenceInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h265std_encode.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h265std_encode.h new file mode 100644 index 00000000..e584a726 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_h265std_encode.h @@ -0,0 +1,157 @@ +#ifndef VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_ +#define VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_h265std_encode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_h265std_encode 1 +#include "vulkan_video_codec_h265std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_encode" +typedef struct StdVideoEncodeH265WeightTableFlags { + uint16_t luma_weight_l0_flag; + uint16_t chroma_weight_l0_flag; + uint16_t luma_weight_l1_flag; + uint16_t chroma_weight_l1_flag; +} StdVideoEncodeH265WeightTableFlags; + +typedef struct StdVideoEncodeH265WeightTable { + StdVideoEncodeH265WeightTableFlags flags; + uint8_t luma_log2_weight_denom; + int8_t delta_chroma_log2_weight_denom; + int8_t delta_luma_weight_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + int8_t luma_offset_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + int8_t delta_chroma_weight_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES]; + int8_t delta_chroma_offset_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES]; + int8_t delta_luma_weight_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + int8_t luma_offset_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + int8_t delta_chroma_weight_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES]; + int8_t delta_chroma_offset_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES]; +} StdVideoEncodeH265WeightTable; + +typedef struct StdVideoEncodeH265SliceSegmentHeaderFlags { + uint32_t first_slice_segment_in_pic_flag : 1; + uint32_t dependent_slice_segment_flag : 1; + uint32_t slice_sao_luma_flag : 1; + uint32_t slice_sao_chroma_flag : 1; + uint32_t num_ref_idx_active_override_flag : 1; + uint32_t mvd_l1_zero_flag : 1; + uint32_t cabac_init_flag : 1; + uint32_t cu_chroma_qp_offset_enabled_flag : 1; + uint32_t deblocking_filter_override_flag : 1; + uint32_t slice_deblocking_filter_disabled_flag : 1; + uint32_t collocated_from_l0_flag : 1; + uint32_t slice_loop_filter_across_slices_enabled_flag : 1; + uint32_t reserved : 20; +} StdVideoEncodeH265SliceSegmentHeaderFlags; + +typedef struct StdVideoEncodeH265SliceSegmentHeader { + StdVideoEncodeH265SliceSegmentHeaderFlags flags; + StdVideoH265SliceType slice_type; + uint32_t slice_segment_address; + uint8_t collocated_ref_idx; + uint8_t MaxNumMergeCand; + int8_t slice_cb_qp_offset; + int8_t slice_cr_qp_offset; + int8_t slice_beta_offset_div2; + int8_t slice_tc_offset_div2; + int8_t slice_act_y_qp_offset; + int8_t slice_act_cb_qp_offset; + int8_t slice_act_cr_qp_offset; + int8_t slice_qp_delta; + uint16_t reserved1; + const StdVideoEncodeH265WeightTable* pWeightTable; +} StdVideoEncodeH265SliceSegmentHeader; + +typedef struct StdVideoEncodeH265ReferenceListsInfoFlags { + uint32_t ref_pic_list_modification_flag_l0 : 1; + uint32_t ref_pic_list_modification_flag_l1 : 1; + uint32_t reserved : 30; +} StdVideoEncodeH265ReferenceListsInfoFlags; + +typedef struct StdVideoEncodeH265ReferenceListsInfo { + StdVideoEncodeH265ReferenceListsInfoFlags flags; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + uint8_t RefPicList0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + uint8_t RefPicList1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + uint8_t list_entry_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; + uint8_t list_entry_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; +} StdVideoEncodeH265ReferenceListsInfo; + +typedef struct StdVideoEncodeH265PictureInfoFlags { + uint32_t is_reference : 1; + uint32_t IrapPicFlag : 1; + uint32_t used_for_long_term_reference : 1; + uint32_t discardable_flag : 1; + uint32_t cross_layer_bla_flag : 1; + uint32_t pic_output_flag : 1; + uint32_t no_output_of_prior_pics_flag : 1; + uint32_t short_term_ref_pic_set_sps_flag : 1; + uint32_t slice_temporal_mvp_enabled_flag : 1; + uint32_t reserved : 23; +} StdVideoEncodeH265PictureInfoFlags; + +typedef struct StdVideoEncodeH265LongTermRefPics { + uint8_t num_long_term_sps; + uint8_t num_long_term_pics; + uint8_t lt_idx_sps[STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS]; + uint8_t poc_lsb_lt[STD_VIDEO_H265_MAX_LONG_TERM_PICS]; + uint16_t used_by_curr_pic_lt_flag; + uint8_t delta_poc_msb_present_flag[STD_VIDEO_H265_MAX_DELTA_POC]; + uint8_t delta_poc_msb_cycle_lt[STD_VIDEO_H265_MAX_DELTA_POC]; +} StdVideoEncodeH265LongTermRefPics; + +typedef struct StdVideoEncodeH265PictureInfo { + StdVideoEncodeH265PictureInfoFlags flags; + StdVideoH265PictureType pic_type; + uint8_t sps_video_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + uint8_t pps_pic_parameter_set_id; + uint8_t short_term_ref_pic_set_idx; + int32_t PicOrderCntVal; + uint8_t TemporalId; + uint8_t reserved1[7]; + const StdVideoEncodeH265ReferenceListsInfo* pRefLists; + const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet; + const StdVideoEncodeH265LongTermRefPics* pLongTermRefPics; +} StdVideoEncodeH265PictureInfo; + +typedef struct StdVideoEncodeH265ReferenceInfoFlags { + uint32_t used_for_long_term_reference : 1; + uint32_t unused_for_reference : 1; + uint32_t reserved : 30; +} StdVideoEncodeH265ReferenceInfoFlags; + +typedef struct StdVideoEncodeH265ReferenceInfo { + StdVideoEncodeH265ReferenceInfoFlags flags; + StdVideoH265PictureType pic_type; + int32_t PicOrderCntVal; + uint8_t TemporalId; +} StdVideoEncodeH265ReferenceInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_vp9std.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_vp9std.h new file mode 100644 index 00000000..3c62f287 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_vp9std.h @@ -0,0 +1,151 @@ +#ifndef VULKAN_VIDEO_CODEC_VP9STD_H_ +#define VULKAN_VIDEO_CODEC_VP9STD_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_vp9std is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_vp9std 1 +#include "vulkan_video_codecs_common.h" +#define STD_VIDEO_VP9_NUM_REF_FRAMES 8U +#define STD_VIDEO_VP9_REFS_PER_FRAME 3U +#define STD_VIDEO_VP9_MAX_REF_FRAMES 4U +#define STD_VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS 2U +#define STD_VIDEO_VP9_MAX_SEGMENTS 8U +#define STD_VIDEO_VP9_SEG_LVL_MAX 4U +#define STD_VIDEO_VP9_MAX_SEGMENTATION_TREE_PROBS 7U +#define STD_VIDEO_VP9_MAX_SEGMENTATION_PRED_PROB 3U + +typedef enum StdVideoVP9Profile { + STD_VIDEO_VP9_PROFILE_0 = 0, + STD_VIDEO_VP9_PROFILE_1 = 1, + STD_VIDEO_VP9_PROFILE_2 = 2, + STD_VIDEO_VP9_PROFILE_3 = 3, + STD_VIDEO_VP9_PROFILE_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_PROFILE_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9Profile; + +typedef enum StdVideoVP9Level { + STD_VIDEO_VP9_LEVEL_1_0 = 0, + STD_VIDEO_VP9_LEVEL_1_1 = 1, + STD_VIDEO_VP9_LEVEL_2_0 = 2, + STD_VIDEO_VP9_LEVEL_2_1 = 3, + STD_VIDEO_VP9_LEVEL_3_0 = 4, + STD_VIDEO_VP9_LEVEL_3_1 = 5, + STD_VIDEO_VP9_LEVEL_4_0 = 6, + STD_VIDEO_VP9_LEVEL_4_1 = 7, + STD_VIDEO_VP9_LEVEL_5_0 = 8, + STD_VIDEO_VP9_LEVEL_5_1 = 9, + STD_VIDEO_VP9_LEVEL_5_2 = 10, + STD_VIDEO_VP9_LEVEL_6_0 = 11, + STD_VIDEO_VP9_LEVEL_6_1 = 12, + STD_VIDEO_VP9_LEVEL_6_2 = 13, + STD_VIDEO_VP9_LEVEL_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_LEVEL_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9Level; + +typedef enum StdVideoVP9FrameType { + STD_VIDEO_VP9_FRAME_TYPE_KEY = 0, + STD_VIDEO_VP9_FRAME_TYPE_NON_KEY = 1, + STD_VIDEO_VP9_FRAME_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_FRAME_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9FrameType; + +typedef enum StdVideoVP9ReferenceName { + STD_VIDEO_VP9_REFERENCE_NAME_INTRA_FRAME = 0, + STD_VIDEO_VP9_REFERENCE_NAME_LAST_FRAME = 1, + STD_VIDEO_VP9_REFERENCE_NAME_GOLDEN_FRAME = 2, + STD_VIDEO_VP9_REFERENCE_NAME_ALTREF_FRAME = 3, + STD_VIDEO_VP9_REFERENCE_NAME_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_REFERENCE_NAME_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9ReferenceName; + +typedef enum StdVideoVP9InterpolationFilter { + STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP = 0, + STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH = 1, + STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP_SHARP = 2, + STD_VIDEO_VP9_INTERPOLATION_FILTER_BILINEAR = 3, + STD_VIDEO_VP9_INTERPOLATION_FILTER_SWITCHABLE = 4, + STD_VIDEO_VP9_INTERPOLATION_FILTER_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_INTERPOLATION_FILTER_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9InterpolationFilter; + +typedef enum StdVideoVP9ColorSpace { + STD_VIDEO_VP9_COLOR_SPACE_UNKNOWN = 0, + STD_VIDEO_VP9_COLOR_SPACE_BT_601 = 1, + STD_VIDEO_VP9_COLOR_SPACE_BT_709 = 2, + STD_VIDEO_VP9_COLOR_SPACE_SMPTE_170 = 3, + STD_VIDEO_VP9_COLOR_SPACE_SMPTE_240 = 4, + STD_VIDEO_VP9_COLOR_SPACE_BT_2020 = 5, + STD_VIDEO_VP9_COLOR_SPACE_RESERVED = 6, + STD_VIDEO_VP9_COLOR_SPACE_RGB = 7, + STD_VIDEO_VP9_COLOR_SPACE_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_COLOR_SPACE_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9ColorSpace; +typedef struct StdVideoVP9ColorConfigFlags { + uint32_t color_range : 1; + uint32_t reserved : 31; +} StdVideoVP9ColorConfigFlags; + +typedef struct StdVideoVP9ColorConfig { + StdVideoVP9ColorConfigFlags flags; + uint8_t BitDepth; + uint8_t subsampling_x; + uint8_t subsampling_y; + uint8_t reserved1; + StdVideoVP9ColorSpace color_space; +} StdVideoVP9ColorConfig; + +typedef struct StdVideoVP9LoopFilterFlags { + uint32_t loop_filter_delta_enabled : 1; + uint32_t loop_filter_delta_update : 1; + uint32_t reserved : 30; +} StdVideoVP9LoopFilterFlags; + +typedef struct StdVideoVP9LoopFilter { + StdVideoVP9LoopFilterFlags flags; + uint8_t loop_filter_level; + uint8_t loop_filter_sharpness; + uint8_t update_ref_delta; + int8_t loop_filter_ref_deltas[STD_VIDEO_VP9_MAX_REF_FRAMES]; + uint8_t update_mode_delta; + int8_t loop_filter_mode_deltas[STD_VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS]; +} StdVideoVP9LoopFilter; + +typedef struct StdVideoVP9SegmentationFlags { + uint32_t segmentation_update_map : 1; + uint32_t segmentation_temporal_update : 1; + uint32_t segmentation_update_data : 1; + uint32_t segmentation_abs_or_delta_update : 1; + uint32_t reserved : 28; +} StdVideoVP9SegmentationFlags; + +typedef struct StdVideoVP9Segmentation { + StdVideoVP9SegmentationFlags flags; + uint8_t segmentation_tree_probs[STD_VIDEO_VP9_MAX_SEGMENTATION_TREE_PROBS]; + uint8_t segmentation_pred_prob[STD_VIDEO_VP9_MAX_SEGMENTATION_PRED_PROB]; + uint8_t FeatureEnabled[STD_VIDEO_VP9_MAX_SEGMENTS]; + int16_t FeatureData[STD_VIDEO_VP9_MAX_SEGMENTS][STD_VIDEO_VP9_SEG_LVL_MAX]; +} StdVideoVP9Segmentation; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_vp9std_decode.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_vp9std_decode.h new file mode 100644 index 00000000..ac7fa7be --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codec_vp9std_decode.h @@ -0,0 +1,68 @@ +#ifndef VULKAN_VIDEO_CODEC_VP9STD_DECODE_H_ +#define VULKAN_VIDEO_CODEC_VP9STD_DECODE_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_vp9std_decode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_vp9std_decode 1 +#include "vulkan_video_codec_vp9std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_vp9_decode" +typedef struct StdVideoDecodeVP9PictureInfoFlags { + uint32_t error_resilient_mode : 1; + uint32_t intra_only : 1; + uint32_t allow_high_precision_mv : 1; + uint32_t refresh_frame_context : 1; + uint32_t frame_parallel_decoding_mode : 1; + uint32_t segmentation_enabled : 1; + uint32_t show_frame : 1; + uint32_t UsePrevFrameMvs : 1; + uint32_t reserved : 24; +} StdVideoDecodeVP9PictureInfoFlags; + +typedef struct StdVideoDecodeVP9PictureInfo { + StdVideoDecodeVP9PictureInfoFlags flags; + StdVideoVP9Profile profile; + StdVideoVP9FrameType frame_type; + uint8_t frame_context_idx; + uint8_t reset_frame_context; + uint8_t refresh_frame_flags; + uint8_t ref_frame_sign_bias_mask; + StdVideoVP9InterpolationFilter interpolation_filter; + uint8_t base_q_idx; + int8_t delta_q_y_dc; + int8_t delta_q_uv_dc; + int8_t delta_q_uv_ac; + uint8_t tile_cols_log2; + uint8_t tile_rows_log2; + uint16_t reserved1[3]; + const StdVideoVP9ColorConfig* pColorConfig; + const StdVideoVP9LoopFilter* pLoopFilter; + const StdVideoVP9Segmentation* pSegmentation; +} StdVideoDecodeVP9PictureInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codecs_common.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codecs_common.h new file mode 100644 index 00000000..3c4d0553 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vk_video/vulkan_video_codecs_common.h @@ -0,0 +1,36 @@ +#ifndef VULKAN_VIDEO_CODECS_COMMON_H_ +#define VULKAN_VIDEO_CODECS_COMMON_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codecs_common is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codecs_common 1 +#if !defined(VK_NO_STDINT_H) + #include +#endif + +#define VK_MAKE_VIDEO_STD_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vk_icd.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vk_icd.h new file mode 100644 index 00000000..d71f5682 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vk_icd.h @@ -0,0 +1,245 @@ +/* + * Copyright 2015-2023 The Khronos Group Inc. + * Copyright 2015-2023 Valve Corporation + * Copyright 2015-2023 LunarG, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "vulkan.h" +#include + +// Loader-ICD version negotiation API. Versions add the following features: +// Version 0 - Initial. Doesn't support vk_icdGetInstanceProcAddr +// or vk_icdNegotiateLoaderICDInterfaceVersion. +// Version 1 - Add support for vk_icdGetInstanceProcAddr. +// Version 2 - Add Loader/ICD Interface version negotiation +// via vk_icdNegotiateLoaderICDInterfaceVersion. +// Version 3 - Add ICD creation/destruction of KHR_surface objects. +// Version 4 - Add unknown physical device extension querying via +// vk_icdGetPhysicalDeviceProcAddr. +// Version 5 - Tells ICDs that the loader is now paying attention to the +// application version of Vulkan passed into the ApplicationInfo +// structure during vkCreateInstance. This will tell the ICD +// that if the loader is older, it should automatically fail a +// call for any API version > 1.0. Otherwise, the loader will +// manually determine if it can support the expected version. +// Version 6 - Add support for vk_icdEnumerateAdapterPhysicalDevices. +// Version 7 - If an ICD supports any of the following functions, they must be +// queryable with vk_icdGetInstanceProcAddr: +// vk_icdNegotiateLoaderICDInterfaceVersion +// vk_icdGetPhysicalDeviceProcAddr +// vk_icdEnumerateAdapterPhysicalDevices (Windows only) +// In addition, these functions no longer need to be exported directly. +// This version allows drivers provided through the extension +// VK_LUNARG_direct_driver_loading be able to support the entire +// Driver-Loader interface. + +#define CURRENT_LOADER_ICD_INTERFACE_VERSION 7 +#define MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION 0 +#define MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION 4 + +// Old typedefs that don't follow a proper naming convention but are preserved for compatibility +typedef VkResult(VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion); +// This is defined in vk_layer.h which will be found by the loader, but if an ICD is building against this +// file directly, it won't be found. +#ifndef IS_DEFINED_PFN_GetPhysicalDeviceProcAddr +typedef PFN_vkVoidFunction(VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char *pName); +#define IS_DEFINED_PFN_GetPhysicalDeviceProcAddr +#endif + +// Typedefs for loader/ICD interface +typedef VkResult (VKAPI_PTR *PFN_vk_icdNegotiateLoaderICDInterfaceVersion)(uint32_t* pVersion); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vk_icdGetInstanceProcAddr)(VkInstance instance, const char* pName); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vk_icdGetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName); +#if defined(VK_USE_PLATFORM_WIN32_KHR) +typedef VkResult (VKAPI_PTR *PFN_vk_icdEnumerateAdapterPhysicalDevices)(VkInstance instance, LUID adapterLUID, + uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); +#endif + +// Prototypes for loader/ICD interface +#if !defined(VK_NO_PROTOTYPES) +#ifdef __cplusplus +extern "C" { +#endif + VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pVersion); + VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName); + VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName); +#if defined(VK_USE_PLATFORM_WIN32_KHR) + VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID, + uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); +#endif +#ifdef __cplusplus +} +#endif +#endif + +/* + * The ICD must reserve space for a pointer for the loader's dispatch + * table, at the start of . + * The ICD must initialize this variable using the SET_LOADER_MAGIC_VALUE macro. + */ + +#define ICD_LOADER_MAGIC 0x01CDC0DE + +typedef union { + uintptr_t loaderMagic; + void *loaderData; +} VK_LOADER_DATA; + +static inline void set_loader_magic_value(void *pNewObject) { + VK_LOADER_DATA *loader_info = (VK_LOADER_DATA *)pNewObject; + loader_info->loaderMagic = ICD_LOADER_MAGIC; +} + +static inline bool valid_loader_magic_value(void *pNewObject) { + const VK_LOADER_DATA *loader_info = (VK_LOADER_DATA *)pNewObject; + return (loader_info->loaderMagic & 0xffffffff) == ICD_LOADER_MAGIC; +} + +/* + * Windows and Linux ICDs will treat VkSurfaceKHR as a pointer to a struct that + * contains the platform-specific connection and surface information. + */ +typedef enum { + VK_ICD_WSI_PLATFORM_MIR, + VK_ICD_WSI_PLATFORM_WAYLAND, + VK_ICD_WSI_PLATFORM_WIN32, + VK_ICD_WSI_PLATFORM_XCB, + VK_ICD_WSI_PLATFORM_XLIB, + VK_ICD_WSI_PLATFORM_ANDROID, + VK_ICD_WSI_PLATFORM_MACOS, + VK_ICD_WSI_PLATFORM_IOS, + VK_ICD_WSI_PLATFORM_DISPLAY, + VK_ICD_WSI_PLATFORM_HEADLESS, + VK_ICD_WSI_PLATFORM_METAL, + VK_ICD_WSI_PLATFORM_DIRECTFB, + VK_ICD_WSI_PLATFORM_VI, + VK_ICD_WSI_PLATFORM_GGP, + VK_ICD_WSI_PLATFORM_SCREEN, + VK_ICD_WSI_PLATFORM_FUCHSIA, +} VkIcdWsiPlatform; + +typedef struct { + VkIcdWsiPlatform platform; +} VkIcdSurfaceBase; + +#ifdef VK_USE_PLATFORM_MIR_KHR +typedef struct { + VkIcdSurfaceBase base; + MirConnection *connection; + MirSurface *mirSurface; +} VkIcdSurfaceMir; +#endif // VK_USE_PLATFORM_MIR_KHR + +#ifdef VK_USE_PLATFORM_WAYLAND_KHR +typedef struct { + VkIcdSurfaceBase base; + struct wl_display *display; + struct wl_surface *surface; +} VkIcdSurfaceWayland; +#endif // VK_USE_PLATFORM_WAYLAND_KHR + +#ifdef VK_USE_PLATFORM_WIN32_KHR +typedef struct { + VkIcdSurfaceBase base; + HINSTANCE hinstance; + HWND hwnd; +} VkIcdSurfaceWin32; +#endif // VK_USE_PLATFORM_WIN32_KHR + +#ifdef VK_USE_PLATFORM_XCB_KHR +typedef struct { + VkIcdSurfaceBase base; + xcb_connection_t *connection; + xcb_window_t window; +} VkIcdSurfaceXcb; +#endif // VK_USE_PLATFORM_XCB_KHR + +#ifdef VK_USE_PLATFORM_XLIB_KHR +typedef struct { + VkIcdSurfaceBase base; + Display *dpy; + Window window; +} VkIcdSurfaceXlib; +#endif // VK_USE_PLATFORM_XLIB_KHR + +#ifdef VK_USE_PLATFORM_DIRECTFB_EXT +typedef struct { + VkIcdSurfaceBase base; + IDirectFB *dfb; + IDirectFBSurface *surface; +} VkIcdSurfaceDirectFB; +#endif // VK_USE_PLATFORM_DIRECTFB_EXT + +#ifdef VK_USE_PLATFORM_ANDROID_KHR +typedef struct { + VkIcdSurfaceBase base; + struct ANativeWindow *window; +} VkIcdSurfaceAndroid; +#endif // VK_USE_PLATFORM_ANDROID_KHR + +#ifdef VK_USE_PLATFORM_MACOS_MVK +typedef struct { + VkIcdSurfaceBase base; + const void *pView; +} VkIcdSurfaceMacOS; +#endif // VK_USE_PLATFORM_MACOS_MVK + +#ifdef VK_USE_PLATFORM_IOS_MVK +typedef struct { + VkIcdSurfaceBase base; + const void *pView; +} VkIcdSurfaceIOS; +#endif // VK_USE_PLATFORM_IOS_MVK + +#ifdef VK_USE_PLATFORM_GGP +typedef struct { + VkIcdSurfaceBase base; + GgpStreamDescriptor streamDescriptor; +} VkIcdSurfaceGgp; +#endif // VK_USE_PLATFORM_GGP + +typedef struct { + VkIcdSurfaceBase base; + VkDisplayModeKHR displayMode; + uint32_t planeIndex; + uint32_t planeStackIndex; + VkSurfaceTransformFlagBitsKHR transform; + float globalAlpha; + VkDisplayPlaneAlphaFlagBitsKHR alphaMode; + VkExtent2D imageExtent; +} VkIcdSurfaceDisplay; + +typedef struct { + VkIcdSurfaceBase base; +} VkIcdSurfaceHeadless; + +#ifdef VK_USE_PLATFORM_METAL_EXT +typedef struct { + VkIcdSurfaceBase base; + const CAMetalLayer *pLayer; +} VkIcdSurfaceMetal; +#endif // VK_USE_PLATFORM_METAL_EXT + +#ifdef VK_USE_PLATFORM_VI_NN +typedef struct { + VkIcdSurfaceBase base; + void *window; +} VkIcdSurfaceVi; +#endif // VK_USE_PLATFORM_VI_NN + +#ifdef VK_USE_PLATFORM_SCREEN_QNX +typedef struct { + VkIcdSurfaceBase base; + struct _screen_context *context; + struct _screen_window *window; +} VkIcdSurfaceScreen; +#endif // VK_USE_PLATFORM_SCREEN_QNX + +#ifdef VK_USE_PLATFORM_FUCHSIA +typedef struct { + VkIcdSurfaceBase base; +} VkIcdSurfaceImagePipe; +#endif // VK_USE_PLATFORM_FUCHSIA diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vk_layer.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vk_layer.h new file mode 100644 index 00000000..19cf5880 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vk_layer.h @@ -0,0 +1,192 @@ +/* + * Copyright 2015-2023 The Khronos Group Inc. + * Copyright 2015-2023 Valve Corporation + * Copyright 2015-2023 LunarG, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +/* Need to define dispatch table + * Core struct can then have ptr to dispatch table at the top + * Along with object ptrs for current and next OBJ + */ + +#include "vulkan_core.h" + +#define MAX_NUM_UNKNOWN_EXTS 250 + + // Loader-Layer version negotiation API. Versions add the following features: + // Versions 0/1 - Initial. Doesn't support vk_layerGetPhysicalDeviceProcAddr + // or vk_icdNegotiateLoaderLayerInterfaceVersion. + // Version 2 - Add support for vk_layerGetPhysicalDeviceProcAddr and + // vk_icdNegotiateLoaderLayerInterfaceVersion. +#define CURRENT_LOADER_LAYER_INTERFACE_VERSION 2 +#define MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION 1 + +#define VK_CURRENT_CHAIN_VERSION 1 + +// Typedef for use in the interfaces below +#ifndef IS_DEFINED_PFN_GetPhysicalDeviceProcAddr +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName); +#define IS_DEFINED_PFN_GetPhysicalDeviceProcAddr +#endif + +// Version negotiation values +typedef enum VkNegotiateLayerStructType { + LAYER_NEGOTIATE_UNINTIALIZED = 0, + LAYER_NEGOTIATE_INTERFACE_STRUCT = 1, +} VkNegotiateLayerStructType; + +// Version negotiation structures +typedef struct VkNegotiateLayerInterface { + VkNegotiateLayerStructType sType; + void *pNext; + uint32_t loaderLayerInterfaceVersion; + PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr; + PFN_GetPhysicalDeviceProcAddr pfnGetPhysicalDeviceProcAddr; +} VkNegotiateLayerInterface; + +// Version negotiation functions +typedef VkResult (VKAPI_PTR *PFN_vkNegotiateLoaderLayerInterfaceVersion)(VkNegotiateLayerInterface *pVersionStruct); + +// Function prototype for unknown physical device extension command +typedef VkResult(VKAPI_PTR *PFN_PhysDevExt)(VkPhysicalDevice phys_device); + +// ------------------------------------------------------------------------------------------------ +// CreateInstance and CreateDevice support structures + +/* Sub type of structure for instance and device loader ext of CreateInfo. + * When sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO + * or sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO + * then VkLayerFunction indicates struct type pointed to by pNext + */ +typedef enum VkLayerFunction_ { + VK_LAYER_LINK_INFO = 0, + VK_LOADER_DATA_CALLBACK = 1, + VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK = 2, + VK_LOADER_FEATURES = 3, +} VkLayerFunction; + +typedef struct VkLayerInstanceLink_ { + struct VkLayerInstanceLink_ *pNext; + PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr; + PFN_GetPhysicalDeviceProcAddr pfnNextGetPhysicalDeviceProcAddr; +} VkLayerInstanceLink; + +/* + * When creating the device chain the loader needs to pass + * down information about it's device structure needed at + * the end of the chain. Passing the data via the + * VkLayerDeviceInfo avoids issues with finding the + * exact instance being used. + */ +typedef struct VkLayerDeviceInfo_ { + void *device_info; + PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr; +} VkLayerDeviceInfo; + +typedef VkResult (VKAPI_PTR *PFN_vkSetInstanceLoaderData)(VkInstance instance, + void *object); +typedef VkResult (VKAPI_PTR *PFN_vkSetDeviceLoaderData)(VkDevice device, + void *object); +typedef VkResult (VKAPI_PTR *PFN_vkLayerCreateDevice)(VkInstance instance, VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, PFN_vkGetInstanceProcAddr layerGIPA, PFN_vkGetDeviceProcAddr *nextGDPA); +typedef void (VKAPI_PTR *PFN_vkLayerDestroyDevice)(VkDevice physicalDevice, const VkAllocationCallbacks *pAllocator, PFN_vkDestroyDevice destroyFunction); + +typedef enum VkLoaderFeastureFlagBits { + VK_LOADER_FEATURE_PHYSICAL_DEVICE_SORTING = 0x00000001, +} VkLoaderFlagBits; +typedef VkFlags VkLoaderFeatureFlags; + +typedef struct { + VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO + const void *pNext; + VkLayerFunction function; + union { + VkLayerInstanceLink *pLayerInfo; + PFN_vkSetInstanceLoaderData pfnSetInstanceLoaderData; + struct { + PFN_vkLayerCreateDevice pfnLayerCreateDevice; + PFN_vkLayerDestroyDevice pfnLayerDestroyDevice; + } layerDevice; + VkLoaderFeatureFlags loaderFeatures; + } u; +} VkLayerInstanceCreateInfo; + +typedef struct VkLayerDeviceLink_ { + struct VkLayerDeviceLink_ *pNext; + PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr pfnNextGetDeviceProcAddr; +} VkLayerDeviceLink; + +typedef struct { + VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO + const void *pNext; + VkLayerFunction function; + union { + VkLayerDeviceLink *pLayerInfo; + PFN_vkSetDeviceLoaderData pfnSetDeviceLoaderData; + } u; +} VkLayerDeviceCreateInfo; + +#ifdef __cplusplus +extern "C" { +#endif + +VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct); + +typedef enum VkChainType { + VK_CHAIN_TYPE_UNKNOWN = 0, + VK_CHAIN_TYPE_ENUMERATE_INSTANCE_EXTENSION_PROPERTIES = 1, + VK_CHAIN_TYPE_ENUMERATE_INSTANCE_LAYER_PROPERTIES = 2, + VK_CHAIN_TYPE_ENUMERATE_INSTANCE_VERSION = 3, +} VkChainType; + +typedef struct VkChainHeader { + VkChainType type; + uint32_t version; + uint32_t size; +} VkChainHeader; + +typedef struct VkEnumerateInstanceExtensionPropertiesChain { + VkChainHeader header; + VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceExtensionPropertiesChain *, const char *, uint32_t *, + VkExtensionProperties *); + const struct VkEnumerateInstanceExtensionPropertiesChain *pNextLink; + +#if defined(__cplusplus) + inline VkResult CallDown(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) const { + return pfnNextLayer(pNextLink, pLayerName, pPropertyCount, pProperties); + } +#endif +} VkEnumerateInstanceExtensionPropertiesChain; + +typedef struct VkEnumerateInstanceLayerPropertiesChain { + VkChainHeader header; + VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceLayerPropertiesChain *, uint32_t *, VkLayerProperties *); + const struct VkEnumerateInstanceLayerPropertiesChain *pNextLink; + +#if defined(__cplusplus) + inline VkResult CallDown(uint32_t *pPropertyCount, VkLayerProperties *pProperties) const { + return pfnNextLayer(pNextLink, pPropertyCount, pProperties); + } +#endif +} VkEnumerateInstanceLayerPropertiesChain; + +typedef struct VkEnumerateInstanceVersionChain { + VkChainHeader header; + VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceVersionChain *, uint32_t *); + const struct VkEnumerateInstanceVersionChain *pNextLink; + +#if defined(__cplusplus) + inline VkResult CallDown(uint32_t *pApiVersion) const { + return pfnNextLayer(pNextLink, pApiVersion); + } +#endif +} VkEnumerateInstanceVersionChain; + +#ifdef __cplusplus +} +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vk_platform.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vk_platform.h new file mode 100644 index 00000000..e431c763 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vk_platform.h @@ -0,0 +1,84 @@ +// +// File: vk_platform.h +// +/* +** Copyright 2014-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + + +#ifndef VK_PLATFORM_H_ +#define VK_PLATFORM_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/* +*************************************************************************************************** +* Platform-specific directives and type declarations +*************************************************************************************************** +*/ + +/* Platform-specific calling convention macros. + * + * Platforms should define these so that Vulkan clients call Vulkan commands + * with the same calling conventions that the Vulkan implementation expects. + * + * VKAPI_ATTR - Placed before the return type in function declarations. + * Useful for C++11 and GCC/Clang-style function attribute syntax. + * VKAPI_CALL - Placed after the return type in function declarations. + * Useful for MSVC-style calling convention syntax. + * VKAPI_PTR - Placed between the '(' and '*' in function pointer types. + * + * Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void); + * Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void); + */ +#if defined(_WIN32) + // On Windows, Vulkan commands use the stdcall convention + #define VKAPI_ATTR + #define VKAPI_CALL __stdcall + #define VKAPI_PTR VKAPI_CALL +#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7 + #error "Vulkan is not supported for the 'armeabi' NDK ABI" +#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE) + // On Android 32-bit ARM targets, Vulkan functions use the "hardfloat" + // calling convention, i.e. float parameters are passed in registers. This + // is true even if the rest of the application passes floats on the stack, + // as it does by default when compiling for the armeabi-v7a NDK ABI. + #define VKAPI_ATTR __attribute__((pcs("aapcs-vfp"))) + #define VKAPI_CALL + #define VKAPI_PTR VKAPI_ATTR +#else + // On other platforms, use the default calling convention + #define VKAPI_ATTR + #define VKAPI_CALL + #define VKAPI_PTR +#endif + +#if !defined(VK_NO_STDDEF_H) + #include +#endif // !defined(VK_NO_STDDEF_H) + +#if !defined(VK_NO_STDINT_H) + #if defined(_MSC_VER) && (_MSC_VER < 1600) + typedef signed __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef signed __int16 int16_t; + typedef unsigned __int16 uint16_t; + typedef signed __int32 int32_t; + typedef unsigned __int32 uint32_t; + typedef signed __int64 int64_t; + typedef unsigned __int64 uint64_t; + #else + #include + #endif +#endif // !defined(VK_NO_STDINT_H) + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan.h new file mode 100644 index 00000000..2ed8d9c7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan.h @@ -0,0 +1,103 @@ +#ifndef VULKAN_H_ +#define VULKAN_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +#include "vk_platform.h" +#include "vulkan_core.h" + +#ifdef VK_USE_PLATFORM_ANDROID_KHR +#include "vulkan_android.h" +#endif + +#ifdef VK_USE_PLATFORM_FUCHSIA +#include +#include "vulkan_fuchsia.h" +#endif + +#ifdef VK_USE_PLATFORM_IOS_MVK +#include "vulkan_ios.h" +#endif + + +#ifdef VK_USE_PLATFORM_MACOS_MVK +#include "vulkan_macos.h" +#endif + +#ifdef VK_USE_PLATFORM_METAL_EXT +#include "vulkan_metal.h" +#endif + +#ifdef VK_USE_PLATFORM_VI_NN +#include "vulkan_vi.h" +#endif + + +#ifdef VK_USE_PLATFORM_WAYLAND_KHR +#include "vulkan_wayland.h" +#endif + + +#ifdef VK_USE_PLATFORM_WIN32_KHR +#include +#include "vulkan_win32.h" +#endif + + +#ifdef VK_USE_PLATFORM_XCB_KHR +#include +#include "vulkan_xcb.h" +#endif + + +#ifdef VK_USE_PLATFORM_XLIB_KHR +#include +#include "vulkan_xlib.h" +#endif + + +#ifdef VK_USE_PLATFORM_DIRECTFB_EXT +#include +#include "vulkan_directfb.h" +#endif + + +#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT +#include +#include +#include "vulkan_xlib_xrandr.h" +#endif + + +#ifdef VK_USE_PLATFORM_GGP +#include +#include "vulkan_ggp.h" +#endif + + +#ifdef VK_USE_PLATFORM_SCREEN_QNX +#include +#include "vulkan_screen.h" +#endif + + +#ifdef VK_USE_PLATFORM_SCI +#include +#include +#include "vulkan_sci.h" +#endif + + +#ifdef VK_ENABLE_BETA_EXTENSIONS +#include "vulkan_beta.h" +#endif + +#ifdef VK_USE_PLATFORM_OHOS +#include "vulkan_ohos.h" +#endif + +#endif // VULKAN_H_ diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_android.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_android.h new file mode 100644 index 00000000..1d8265e8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_android.h @@ -0,0 +1,159 @@ +#ifndef VULKAN_ANDROID_H_ +#define VULKAN_ANDROID_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_KHR_android_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_android_surface 1 +struct ANativeWindow; +#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6 +#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface" +typedef VkFlags VkAndroidSurfaceCreateFlagsKHR; +typedef struct VkAndroidSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkAndroidSurfaceCreateFlagsKHR flags; + struct ANativeWindow* window; +} VkAndroidSurfaceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAndroidSurfaceKHR)(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR( + VkInstance instance, + const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + + +// VK_ANDROID_external_memory_android_hardware_buffer is a preprocessor guard. Do not pass it to API calls. +#define VK_ANDROID_external_memory_android_hardware_buffer 1 +struct AHardwareBuffer; +#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 5 +#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer" +typedef struct VkAndroidHardwareBufferUsageANDROID { + VkStructureType sType; + void* pNext; + uint64_t androidHardwareBufferUsage; +} VkAndroidHardwareBufferUsageANDROID; + +typedef struct VkAndroidHardwareBufferPropertiesANDROID { + VkStructureType sType; + void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeBits; +} VkAndroidHardwareBufferPropertiesANDROID; + +typedef struct VkAndroidHardwareBufferFormatPropertiesANDROID { + VkStructureType sType; + void* pNext; + VkFormat format; + uint64_t externalFormat; + VkFormatFeatureFlags formatFeatures; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkAndroidHardwareBufferFormatPropertiesANDROID; + +typedef struct VkImportAndroidHardwareBufferInfoANDROID { + VkStructureType sType; + const void* pNext; + struct AHardwareBuffer* buffer; +} VkImportAndroidHardwareBufferInfoANDROID; + +typedef struct VkMemoryGetAndroidHardwareBufferInfoANDROID { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; +} VkMemoryGetAndroidHardwareBufferInfoANDROID; + +typedef struct VkExternalFormatANDROID { + VkStructureType sType; + void* pNext; + uint64_t externalFormat; +} VkExternalFormatANDROID; + +typedef struct VkAndroidHardwareBufferFormatProperties2ANDROID { + VkStructureType sType; + void* pNext; + VkFormat format; + uint64_t externalFormat; + VkFormatFeatureFlags2 formatFeatures; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkAndroidHardwareBufferFormatProperties2ANDROID; + +typedef VkResult (VKAPI_PTR *PFN_vkGetAndroidHardwareBufferPropertiesANDROID)(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryAndroidHardwareBufferANDROID)(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetAndroidHardwareBufferPropertiesANDROID( + VkDevice device, + const struct AHardwareBuffer* buffer, + VkAndroidHardwareBufferPropertiesANDROID* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID( + VkDevice device, + const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, + struct AHardwareBuffer** pBuffer); +#endif +#endif + + +// VK_ANDROID_external_format_resolve is a preprocessor guard. Do not pass it to API calls. +#define VK_ANDROID_external_format_resolve 1 +#define VK_ANDROID_EXTERNAL_FORMAT_RESOLVE_SPEC_VERSION 1 +#define VK_ANDROID_EXTERNAL_FORMAT_RESOLVE_EXTENSION_NAME "VK_ANDROID_external_format_resolve" +typedef struct VkPhysicalDeviceExternalFormatResolveFeaturesANDROID { + VkStructureType sType; + void* pNext; + VkBool32 externalFormatResolve; +} VkPhysicalDeviceExternalFormatResolveFeaturesANDROID; + +typedef struct VkPhysicalDeviceExternalFormatResolvePropertiesANDROID { + VkStructureType sType; + void* pNext; + VkBool32 nullColorAttachmentWithExternalFormatResolve; + VkChromaLocation externalFormatResolveChromaOffsetX; + VkChromaLocation externalFormatResolveChromaOffsetY; +} VkPhysicalDeviceExternalFormatResolvePropertiesANDROID; + +typedef struct VkAndroidHardwareBufferFormatResolvePropertiesANDROID { + VkStructureType sType; + void* pNext; + VkFormat colorAttachmentFormat; +} VkAndroidHardwareBufferFormatResolvePropertiesANDROID; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_beta.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_beta.h new file mode 100644 index 00000000..147a3f3c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_beta.h @@ -0,0 +1,375 @@ +#ifndef VULKAN_BETA_H_ +#define VULKAN_BETA_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_KHR_portability_subset is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_portability_subset 1 +#define VK_KHR_PORTABILITY_SUBSET_SPEC_VERSION 1 +#define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset" +typedef struct VkPhysicalDevicePortabilitySubsetFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 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; +} VkPhysicalDevicePortabilitySubsetFeaturesKHR; + +typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t minVertexInputBindingStrideAlignment; +} VkPhysicalDevicePortabilitySubsetPropertiesKHR; + + + +// VK_AMDX_shader_enqueue is a preprocessor guard. Do not pass it to API calls. +#define VK_AMDX_shader_enqueue 1 +#define VK_AMDX_SHADER_ENQUEUE_SPEC_VERSION 2 +#define VK_AMDX_SHADER_ENQUEUE_EXTENSION_NAME "VK_AMDX_shader_enqueue" +#define VK_SHADER_INDEX_UNUSED_AMDX (~0U) +typedef struct VkPhysicalDeviceShaderEnqueueFeaturesAMDX { + VkStructureType sType; + void* pNext; + VkBool32 shaderEnqueue; + VkBool32 shaderMeshEnqueue; +} VkPhysicalDeviceShaderEnqueueFeaturesAMDX; + +typedef struct VkPhysicalDeviceShaderEnqueuePropertiesAMDX { + VkStructureType sType; + void* pNext; + uint32_t maxExecutionGraphDepth; + uint32_t maxExecutionGraphShaderOutputNodes; + uint32_t maxExecutionGraphShaderPayloadSize; + uint32_t maxExecutionGraphShaderPayloadCount; + uint32_t executionGraphDispatchAddressAlignment; + uint32_t maxExecutionGraphWorkgroupCount[3]; + uint32_t maxExecutionGraphWorkgroups; +} VkPhysicalDeviceShaderEnqueuePropertiesAMDX; + +typedef struct VkExecutionGraphPipelineScratchSizeAMDX { + VkStructureType sType; + void* pNext; + VkDeviceSize minSize; + VkDeviceSize maxSize; + VkDeviceSize sizeGranularity; +} VkExecutionGraphPipelineScratchSizeAMDX; + +typedef struct VkExecutionGraphPipelineCreateInfoAMDX { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineLibraryCreateInfoKHR* pLibraryInfo; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkExecutionGraphPipelineCreateInfoAMDX; + +typedef union VkDeviceOrHostAddressConstAMDX { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstAMDX; + +typedef struct VkDispatchGraphInfoAMDX { + uint32_t nodeIndex; + uint32_t payloadCount; + VkDeviceOrHostAddressConstAMDX payloads; + uint64_t payloadStride; +} VkDispatchGraphInfoAMDX; + +typedef struct VkDispatchGraphCountInfoAMDX { + uint32_t count; + VkDeviceOrHostAddressConstAMDX infos; + uint64_t stride; +} VkDispatchGraphCountInfoAMDX; + +typedef struct VkPipelineShaderStageNodeCreateInfoAMDX { + VkStructureType sType; + const void* pNext; + const char* pName; + uint32_t index; +} VkPipelineShaderStageNodeCreateInfoAMDX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateExecutionGraphPipelinesAMDX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)(VkDevice device, VkPipeline executionGraph, VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)(VkDevice device, VkPipeline executionGraph, const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, uint32_t* pNodeIndex); +typedef void (VKAPI_PTR *PFN_vkCmdInitializeGraphScratchMemoryAMDX)(VkCommandBuffer commandBuffer, VkPipeline executionGraph, VkDeviceAddress scratch, VkDeviceSize scratchSize); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, const VkDispatchGraphCountInfoAMDX* pCountInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, const VkDispatchGraphCountInfoAMDX* pCountInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectCountAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, VkDeviceAddress countInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateExecutionGraphPipelinesAMDX( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineScratchSizeAMDX( + VkDevice device, + VkPipeline executionGraph, + VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineNodeIndexAMDX( + VkDevice device, + VkPipeline executionGraph, + const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, + uint32_t* pNodeIndex); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdInitializeGraphScratchMemoryAMDX( + VkCommandBuffer commandBuffer, + VkPipeline executionGraph, + VkDeviceAddress scratch, + VkDeviceSize scratchSize); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceSize scratchSize, + const VkDispatchGraphCountInfoAMDX* pCountInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceSize scratchSize, + const VkDispatchGraphCountInfoAMDX* pCountInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectCountAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceSize scratchSize, + VkDeviceAddress countInfo); +#endif +#endif + + +// VK_NV_cuda_kernel_launch is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cuda_kernel_launch 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaModuleNV) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaFunctionNV) +#define VK_NV_CUDA_KERNEL_LAUNCH_SPEC_VERSION 2 +#define VK_NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME "VK_NV_cuda_kernel_launch" +typedef struct VkCudaModuleCreateInfoNV { + VkStructureType sType; + const void* pNext; + size_t dataSize; + const void* pData; +} VkCudaModuleCreateInfoNV; + +typedef struct VkCudaFunctionCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkCudaModuleNV module; + const char* pName; +} VkCudaFunctionCreateInfoNV; + +typedef struct VkCudaLaunchInfoNV { + VkStructureType sType; + const void* pNext; + VkCudaFunctionNV function; + uint32_t gridDimX; + uint32_t gridDimY; + uint32_t gridDimZ; + uint32_t blockDimX; + uint32_t blockDimY; + uint32_t blockDimZ; + uint32_t sharedMemBytes; + size_t paramCount; + const void* const * pParams; + size_t extraCount; + const void* const * pExtras; +} VkCudaLaunchInfoNV; + +typedef struct VkPhysicalDeviceCudaKernelLaunchFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cudaKernelLaunchFeatures; +} VkPhysicalDeviceCudaKernelLaunchFeaturesNV; + +typedef struct VkPhysicalDeviceCudaKernelLaunchPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t computeCapabilityMinor; + uint32_t computeCapabilityMajor; +} VkPhysicalDeviceCudaKernelLaunchPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaModuleNV)(VkDevice device, const VkCudaModuleCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaModuleNV* pModule); +typedef VkResult (VKAPI_PTR *PFN_vkGetCudaModuleCacheNV)(VkDevice device, VkCudaModuleNV module, size_t* pCacheSize, void* pCacheData); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaFunctionNV)(VkDevice device, const VkCudaFunctionCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaFunctionNV* pFunction); +typedef void (VKAPI_PTR *PFN_vkDestroyCudaModuleNV)(VkDevice device, VkCudaModuleNV module, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyCudaFunctionNV)(VkDevice device, VkCudaFunctionNV function, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdCudaLaunchKernelNV)(VkCommandBuffer commandBuffer, const VkCudaLaunchInfoNV* pLaunchInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaModuleNV( + VkDevice device, + const VkCudaModuleCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCudaModuleNV* pModule); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetCudaModuleCacheNV( + VkDevice device, + VkCudaModuleNV module, + size_t* pCacheSize, + void* pCacheData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaFunctionNV( + VkDevice device, + const VkCudaFunctionCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCudaFunctionNV* pFunction); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyCudaModuleNV( + VkDevice device, + VkCudaModuleNV module, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyCudaFunctionNV( + VkDevice device, + VkCudaFunctionNV function, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCudaLaunchKernelNV( + VkCommandBuffer commandBuffer, + const VkCudaLaunchInfoNV* pLaunchInfo); +#endif +#endif + + +// VK_NV_displacement_micromap is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_displacement_micromap 1 +#define VK_NV_DISPLACEMENT_MICROMAP_SPEC_VERSION 2 +#define VK_NV_DISPLACEMENT_MICROMAP_EXTENSION_NAME "VK_NV_displacement_micromap" + +typedef enum VkDisplacementMicromapFormatNV { + VK_DISPLACEMENT_MICROMAP_FORMAT_64_TRIANGLES_64_BYTES_NV = 1, + VK_DISPLACEMENT_MICROMAP_FORMAT_256_TRIANGLES_128_BYTES_NV = 2, + VK_DISPLACEMENT_MICROMAP_FORMAT_1024_TRIANGLES_128_BYTES_NV = 3, + VK_DISPLACEMENT_MICROMAP_FORMAT_MAX_ENUM_NV = 0x7FFFFFFF +} VkDisplacementMicromapFormatNV; +typedef struct VkPhysicalDeviceDisplacementMicromapFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 displacementMicromap; +} VkPhysicalDeviceDisplacementMicromapFeaturesNV; + +typedef struct VkPhysicalDeviceDisplacementMicromapPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxDisplacementMicromapSubdivisionLevel; +} VkPhysicalDeviceDisplacementMicromapPropertiesNV; + +typedef struct VkAccelerationStructureTrianglesDisplacementMicromapNV { + VkStructureType sType; + void* pNext; + VkFormat displacementBiasAndScaleFormat; + VkFormat displacementVectorFormat; + VkDeviceOrHostAddressConstKHR displacementBiasAndScaleBuffer; + VkDeviceSize displacementBiasAndScaleStride; + VkDeviceOrHostAddressConstKHR displacementVectorBuffer; + VkDeviceSize displacementVectorStride; + VkDeviceOrHostAddressConstKHR displacedMicromapPrimitiveFlags; + VkDeviceSize displacedMicromapPrimitiveFlagsStride; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexBuffer; + VkDeviceSize indexStride; + uint32_t baseTriangle; + uint32_t usageCountsCount; + const VkMicromapUsageEXT* pUsageCounts; + const VkMicromapUsageEXT* const* ppUsageCounts; + VkMicromapEXT micromap; +} VkAccelerationStructureTrianglesDisplacementMicromapNV; + + + +// VK_AMDX_dense_geometry_format is a preprocessor guard. Do not pass it to API calls. +#define VK_AMDX_dense_geometry_format 1 +#define VK_AMDX_DENSE_GEOMETRY_FORMAT_SPEC_VERSION 1 +#define VK_AMDX_DENSE_GEOMETRY_FORMAT_EXTENSION_NAME "VK_AMDX_dense_geometry_format" +#define VK_COMPRESSED_TRIANGLE_FORMAT_DGF1_BYTE_ALIGNMENT_AMDX 128U +#define VK_COMPRESSED_TRIANGLE_FORMAT_DGF1_BYTE_STRIDE_AMDX 128U + +typedef enum VkCompressedTriangleFormatAMDX { + VK_COMPRESSED_TRIANGLE_FORMAT_DGF1_AMDX = 0, + VK_COMPRESSED_TRIANGLE_FORMAT_MAX_ENUM_AMDX = 0x7FFFFFFF +} VkCompressedTriangleFormatAMDX; +typedef struct VkPhysicalDeviceDenseGeometryFormatFeaturesAMDX { + VkStructureType sType; + void* pNext; + VkBool32 denseGeometryFormat; +} VkPhysicalDeviceDenseGeometryFormatFeaturesAMDX; + +typedef struct VkAccelerationStructureDenseGeometryFormatTrianglesDataAMDX { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR compressedData; + VkDeviceSize dataSize; + uint32_t numTriangles; + uint32_t numVertices; + uint32_t maxPrimitiveIndex; + uint32_t maxGeometryIndex; + VkCompressedTriangleFormatAMDX format; +} VkAccelerationStructureDenseGeometryFormatTrianglesDataAMDX; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_core.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_core.h new file mode 100644 index 00000000..005e9c97 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_core.h @@ -0,0 +1,26746 @@ +#ifndef VULKAN_CORE_H_ +#define VULKAN_CORE_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_VERSION_1_0 is a preprocessor guard. Do not pass it to API calls. +#define VK_VERSION_1_0 1 +#include "vk_platform.h" + +#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; + + +#ifndef VK_USE_64_BIT_PTR_DEFINES + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) && __riscv_xlen == 64) + #define VK_USE_64_BIT_PTR_DEFINES 1 + #else + #define VK_USE_64_BIT_PTR_DEFINES 0 + #endif +#endif + + +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) + #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)) + #define VK_NULL_HANDLE nullptr + #else + #define VK_NULL_HANDLE ((void*)0) + #endif + #else + #define VK_NULL_HANDLE 0ULL + #endif +#endif +#ifndef VK_NULL_HANDLE + #define VK_NULL_HANDLE 0 +#endif + + +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; + #else + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; + #endif +#endif + +#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) + + +//#define VK_API_VERSION VK_MAKE_API_VERSION(0, 1, 0, 0) // Patch version should always be set to 0 + +// Version of this file +#define VK_HEADER_VERSION 352 + +// Complete version of this file +#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 4, VK_HEADER_VERSION) + + +#define VK_MAKE_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) + + +#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22U) + + +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) + + +#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) + +#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29U) +#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22U) & 0x7FU) +#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) +#define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) +// Vulkan 1.0 version number +#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 + +typedef uint32_t VkBool32; +typedef uint64_t VkDeviceAddress; +typedef uint64_t VkDeviceSize; +typedef uint32_t VkFlags; +typedef uint32_t VkSampleMask; +VK_DEFINE_HANDLE(VkInstance) +VK_DEFINE_HANDLE(VkPhysicalDevice) +VK_DEFINE_HANDLE(VkDevice) +VK_DEFINE_HANDLE(VkQueue) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) +VK_DEFINE_HANDLE(VkCommandBuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) +#define VK_FALSE 0U +#define VK_LOD_CLAMP_NONE 1000.0F +#define VK_QUEUE_FAMILY_IGNORED (~0U) +#define VK_REMAINING_ARRAY_LAYERS (~0U) +#define VK_REMAINING_MIP_LEVELS (~0U) +#define VK_TRUE 1U +#define VK_WHOLE_SIZE (~0ULL) +#define VK_MAX_MEMORY_TYPES 32U +#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256U +#define VK_UUID_SIZE 16U +#define VK_MAX_EXTENSION_NAME_SIZE 256U +#define VK_MAX_DESCRIPTION_SIZE 256U +#define VK_MAX_MEMORY_HEAPS 16U +#define VK_ATTACHMENT_UNUSED (~0U) +#define VK_SUBPASS_EXTERNAL (~0U) + +typedef enum VkResult { + VK_SUCCESS = 0, + VK_NOT_READY = 1, + VK_TIMEOUT = 2, + VK_EVENT_SET = 3, + VK_EVENT_RESET = 4, + VK_INCOMPLETE = 5, + VK_ERROR_OUT_OF_HOST_MEMORY = -1, + VK_ERROR_OUT_OF_DEVICE_MEMORY = -2, + VK_ERROR_INITIALIZATION_FAILED = -3, + VK_ERROR_DEVICE_LOST = -4, + VK_ERROR_MEMORY_MAP_FAILED = -5, + VK_ERROR_LAYER_NOT_PRESENT = -6, + VK_ERROR_EXTENSION_NOT_PRESENT = -7, + VK_ERROR_FEATURE_NOT_PRESENT = -8, + VK_ERROR_INCOMPATIBLE_DRIVER = -9, + VK_ERROR_TOO_MANY_OBJECTS = -10, + VK_ERROR_FORMAT_NOT_SUPPORTED = -11, + VK_ERROR_FRAGMENTED_POOL = -12, + VK_ERROR_UNKNOWN = -13, + VK_ERROR_VALIDATION_FAILED = -1000011001, + VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000, + VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003, + VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000, + VK_ERROR_FRAGMENTATION = -1000161000, + VK_PIPELINE_COMPILE_REQUIRED = 1000297000, + VK_ERROR_NOT_PERMITTED = -1000174001, + VK_ERROR_SURFACE_LOST_KHR = -1000000000, + VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, + VK_SUBOPTIMAL_KHR = 1000001003, + VK_ERROR_OUT_OF_DATE_KHR = -1000001004, + VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, + VK_ERROR_INVALID_SHADER_NV = -1000012000, + VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR = -1000023000, + VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR = -1000023001, + VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR = -1000023002, + VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR = -1000023003, + VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR = -1000023004, + VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR = -1000023005, + VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000, + VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT = -1000208000, + VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, + VK_THREAD_IDLE_KHR = 1000268000, + VK_THREAD_DONE_KHR = 1000268001, + VK_OPERATION_DEFERRED_KHR = 1000268002, + VK_OPERATION_NOT_DEFERRED_KHR = 1000268003, + VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR = -1000299000, + VK_ERROR_COMPRESSION_EXHAUSTED_EXT = -1000338000, + VK_INCOMPATIBLE_SHADER_BINARY_EXT = 1000482000, + VK_PIPELINE_BINARY_MISSING_KHR = 1000483000, + VK_ERROR_NOT_ENOUGH_SPACE_KHR = -1000483000, + VK_ERROR_VALIDATION_FAILED_EXT = VK_ERROR_VALIDATION_FAILED, + VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, + VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, + VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION, + VK_ERROR_NOT_PERMITTED_EXT = VK_ERROR_NOT_PERMITTED, + VK_ERROR_NOT_PERMITTED_KHR = VK_ERROR_NOT_PERMITTED, + VK_ERROR_INVALID_DEVICE_ADDRESS_EXT = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, + VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, + VK_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED, + VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED, + // VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT is a legacy alias + VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT = VK_INCOMPATIBLE_SHADER_BINARY_EXT, + VK_RESULT_MAX_ENUM = 0x7FFFFFFF +} VkResult; + +typedef enum VkStructureType { + 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_BIND_BUFFER_MEMORY_INFO = 1000157000, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001, + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000, + 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_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000, + VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001, + 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_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_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002, + 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_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_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000, + VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES = 1000112001, + VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO = 1000113000, + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000, + VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000, + VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001, + 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_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000, + VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001, + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003, + 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_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000, + 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_IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000, + 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_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO = 1000244001, + 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_8BIT_STORAGE_FEATURES = 1000177000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000, + 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_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000, + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000, + 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_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001, + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000, + 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_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_VULKAN_1_3_FEATURES = 53, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000, + 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_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_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_BUFFER_COPY_2 = 1000337006, + VK_STRUCTURE_TYPE_IMAGE_COPY_2 = 1000337007, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2 = 1000337009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 = 1000360000, + 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_PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000, + 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_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_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_PROPERTIES = 1000281001, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2 = 1000337004, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2 = 1000337005, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2 = 1000337008, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2 = 1000337010, + 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_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES = 55, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_PROPERTIES = 56, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO = 1000174000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES = 1000388000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES = 1000388001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES = 1000265000, + VK_STRUCTURE_TYPE_MEMORY_MAP_INFO = 1000271000, + VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO = 1000271001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES = 1000470000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES = 1000470001, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_SUBRESOURCE_INFO = 1000470004, + VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2 = 1000338002, + VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2 = 1000338003, + VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO = 1000470006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES = 1000545000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES = 1000545001, + VK_STRUCTURE_TYPE_BIND_MEMORY_STATUS = 1000545002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES = 1000270000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES = 1000270001, + VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY = 1000270002, + VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY = 1000270003, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO = 1000270004, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO = 1000270005, + VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO = 1000270006, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_IMAGE_INFO = 1000270007, + VK_STRUCTURE_TYPE_SUBRESOURCE_HOST_MEMCPY_SIZE = 1000270008, + VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY = 1000270009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES = 1000416000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES = 1000528000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES = 1000544000, + VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO = 1000470005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES = 1000080000, + VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO = 1000545003, + VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO = 1000545004, + VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_INFO = 1000545005, + VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO = 1000545006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES = 1000466000, + VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO = 1000068000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES = 1000068001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES = 1000068002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES = 1000259000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO = 1000259001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES = 1000259002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES = 1000525000, + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO = 1000190001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES = 1000190002, + VK_STRUCTURE_TYPE_RENDERING_AREA_INFO = 1000470003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES = 1000232000, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO = 1000232001, + VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO = 1000232002, + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, + 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_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_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_CU_MODULE_TEXTURING_MODE_CREATE_INFO_NVX = 1000029004, + 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_KHR = 1000038000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000038001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR = 1000038002, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PICTURE_INFO_KHR = 1000038003, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_KHR = 1000038004, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_KHR = 1000038005, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_GOP_REMAINING_FRAME_INFO_KHR = 1000038006, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_KHR = 1000038007, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_KHR = 1000038008, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_KHR = 1000038009, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_KHR = 1000038010, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_KHR = 1000038011, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_KHR = 1000038012, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000038013, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_KHR = 1000039000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000039001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR = 1000039002, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_KHR = 1000039003, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_KHR = 1000039004, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_KHR = 1000039005, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_GOP_REMAINING_FRAME_INFO_KHR = 1000039006, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_KHR = 1000039007, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_KHR = 1000039009, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_KHR = 1000039010, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_CREATE_INFO_KHR = 1000039011, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_KHR = 1000039012, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_KHR = 1000039013, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000039014, + 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_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, + 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_VALIDATION_FLAGS_EXT = 1000061000, + VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001, + 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_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_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_PRESENT_REGIONS_KHR = 1000084000, + 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_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000, + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009, + 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_RELAXED_LINE_RASTERIZATION_FEATURES_IMG = 1000110000, + VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000, + 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_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_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_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_GPA_FEATURES_AMD = 1000133000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_PROPERTIES_AMD = 1000133001, + VK_STRUCTURE_TYPE_GPA_SAMPLE_BEGIN_INFO_AMD = 1000133002, + VK_STRUCTURE_TYPE_GPA_SESSION_CREATE_INFO_AMD = 1000133003, + VK_STRUCTURE_TYPE_GPA_DEVICE_CLOCK_MODE_INFO_AMD = 1000133004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_PROPERTIES_2_AMD = 1000133005, + VK_STRUCTURE_TYPE_GPA_DEVICE_GET_CLOCK_INFO_AMD = 1000133006, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX = 1000134000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_PROPERTIES_AMDX = 1000134001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_EXECUTION_GRAPH_PIPELINE_SCRATCH_SIZE_AMDX = 1000134002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_EXECUTION_GRAPH_PIPELINE_CREATE_INFO_AMDX = 1000134003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NODE_CREATE_INFO_AMDX = 1000134004, +#endif + VK_STRUCTURE_TYPE_TEXEL_BUFFER_DESCRIPTOR_INFO_EXT = 1000135000, + VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT = 1000135001, + VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT = 1000135002, + VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT = 1000135003, + VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT = 1000135004, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_AND_BINDING_MAPPING_EXT = 1000135005, + VK_STRUCTURE_TYPE_SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT = 1000135006, + VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DATA_CREATE_INFO_EXT = 1000135007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_HEAP_PROPERTIES_EXT = 1000135008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_HEAP_FEATURES_EXT = 1000135009, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_DESCRIPTOR_HEAP_INFO_EXT = 1000135010, + VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_INDEX_CREATE_INFO_EXT = 1000135011, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_PUSH_DATA_TOKEN_NV = 1000135012, + VK_STRUCTURE_TYPE_SUBSAMPLED_IMAGE_FORMAT_PROPERTIES_EXT = 1000135013, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_HEAP_TENSOR_PROPERTIES_ARM = 1000135014, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_BFLOAT16_FEATURES_KHR = 1000141000, + 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_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_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000150007, + 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_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_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR = 1000150020, + 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_RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015, + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR = 1000348013, + 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_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, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR = 1000163000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR = 1000163001, +#endif + 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_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000, + VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_CONVERSION_FEATURES_QCOM = 1000172000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ELAPSED_TIMER_QUERY_FEATURES_QCOM = 1000173000, + 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_CLOCK_FEATURES_KHR = 1000181000, + VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000, + 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_PRESENT_FRAME_TOKEN_GGP = 1000191000, + 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_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_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008, + VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV = 1000314009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_TIMING_FEATURES_EXT = 1000208000, + VK_STRUCTURE_TYPE_SWAPCHAIN_TIMING_PROPERTIES_EXT = 1000208001, + VK_STRUCTURE_TYPE_SWAPCHAIN_TIME_DOMAIN_PROPERTIES_EXT = 1000208002, + VK_STRUCTURE_TYPE_PRESENT_TIMINGS_INFO_EXT = 1000208003, + VK_STRUCTURE_TYPE_PRESENT_TIMING_INFO_EXT = 1000208004, + VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_INFO_EXT = 1000208005, + VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_PROPERTIES_EXT = 1000208006, + VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_EXT = 1000208007, + VK_STRUCTURE_TYPE_PRESENT_TIMING_SURFACE_CAPABILITIES_EXT = 1000208008, + VK_STRUCTURE_TYPE_SWAPCHAIN_CALIBRATED_TIMESTAMP_INFO_EXT = 1000208009, + 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_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_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_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007, + 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_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, + 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_CONSTANT_DATA_FEATURES_KHR = 1000231000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ABORT_FEATURES_KHR = 1000233000, + VK_STRUCTURE_TYPE_DEVICE_FAULT_SHADER_ABORT_MESSAGE_INFO_KHR = 1000233001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ABORT_PROPERTIES_KHR = 1000233002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_QUAD_CONTROL_FEATURES_KHR = 1000235000, + 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_BUFFER_DEVICE_ADDRESS_FEATURES_EXT = 1000244000, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002, + 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_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_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT = 1000255002, + VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT = 1000255001, + VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT = 1000260000, + 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_MAP_MEMORY_PLACED_FEATURES_EXT = 1000272000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT = 1000272001, + VK_STRUCTURE_TYPE_MEMORY_MAP_PLACED_INFO_EXT = 1000272002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, + 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_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, + 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_DEPTH_BIAS_CONTROL_FEATURES_EXT = 1000283000, + VK_STRUCTURE_TYPE_DEPTH_BIAS_INFO_EXT = 1000283001, + VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT = 1000283002, + 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_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_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_3D_FEATURES_EXT = 1000288000, + 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_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_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR = 1000299005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299006, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_PROPERTIES_KHR = 1000299007, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299008, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR = 1000299009, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000299010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, + VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, + VK_STRUCTURE_TYPE_PERF_HINT_INFO_QCOM = 1000302000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_QUEUE_PERF_HINT_FEATURES_QCOM = 1000302001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_QUEUE_PERF_HINT_PROPERTIES_QCOM = 1000302002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_3_FEATURES_QCOM = 1000303000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MULTIPLE_WAIT_QUEUES_FEATURES_QCOM = 1000304000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MULTIPLE_WAIT_QUEUES_PROPERTIES_QCOM = 1000304001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SPLIT_BARRIER_FEATURES_EXT = 1000305000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SPLIT_BARRIER_PROPERTIES_EXT = 1000305001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_CUDA_MODULE_CREATE_INFO_NV = 1000307000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_CUDA_FUNCTION_CREATE_INFO_NV = 1000307001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_CUDA_LAUNCH_INFO_NV = 1000307002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_FEATURES_NV = 1000307003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_PROPERTIES_NV = 1000307004, +#endif + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_SHADING_FEATURES_QCOM = 1000309000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_SHADING_PROPERTIES_QCOM = 1000309001, + VK_STRUCTURE_TYPE_RENDER_PASS_TILE_SHADING_CREATE_INFO_QCOM = 1000309002, + VK_STRUCTURE_TYPE_PER_TILE_BEGIN_INFO_QCOM = 1000309003, + VK_STRUCTURE_TYPE_PER_TILE_END_INFO_QCOM = 1000309004, + VK_STRUCTURE_TYPE_DISPATCH_TILE_INFO_QCOM = 1000309005, + VK_STRUCTURE_TYPE_QUERY_LOW_LATENCY_SUPPORT_NV = 1000310000, + 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_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_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_ACCELERATION_STRUCTURE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316009, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_COPY_KHR = 1000318000, + VK_STRUCTURE_TYPE_COPY_DEVICE_MEMORY_INFO_KHR = 1000318001, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_IMAGE_COPY_KHR = 1000318002, + VK_STRUCTURE_TYPE_COPY_DEVICE_MEMORY_IMAGE_INFO_KHR = 1000318003, + VK_STRUCTURE_TYPE_MEMORY_RANGE_BARRIERS_INFO_KHR = 1000318004, + VK_STRUCTURE_TYPE_MEMORY_RANGE_BARRIER_KHR = 1000318005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_ADDRESS_COMMANDS_FEATURES_KHR = 1000318006, + VK_STRUCTURE_TYPE_BIND_INDEX_BUFFER_3_INFO_KHR = 1000318007, + VK_STRUCTURE_TYPE_BIND_VERTEX_BUFFER_3_INFO_KHR = 1000318008, + VK_STRUCTURE_TYPE_DRAW_INDIRECT_2_INFO_KHR = 1000318009, + VK_STRUCTURE_TYPE_DRAW_INDIRECT_COUNT_2_INFO_KHR = 1000318010, + VK_STRUCTURE_TYPE_DISPATCH_INDIRECT_2_INFO_KHR = 1000318011, + VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_2_EXT = 1000318012, + VK_STRUCTURE_TYPE_BIND_TRANSFORM_FEEDBACK_BUFFER_2_INFO_EXT = 1000318013, + VK_STRUCTURE_TYPE_MEMORY_MARKER_INFO_AMD = 1000318014, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_2_KHR = 1000318015, + 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_FEATURES_KHR = 1000203000, + 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_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_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT = 1000338000, + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT = 1000338001, + 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_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000, + VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000, + 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_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_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT = 1000375000, + VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT = 1000375001, + 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_SHADER_UNTYPED_POINTERS_FEATURES_KHR = 1000387000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_RGB_CONVERSION_FEATURES_VALVE = 1000390000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_RGB_CONVERSION_CAPABILITIES_VALVE = 1000390001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_PROFILE_RGB_CONVERSION_INFO_VALVE = 1000390002, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_RGB_CONVERSION_CREATE_INFO_VALVE = 1000390003, + 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_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT = 1000395000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT = 1000395001, + 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, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV = 1000397000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV = 1000397001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV = 1000397002, +#endif + 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_CLUSTER_CULLING_SHADER_VRS_FEATURES_HUAWEI = 1000404002, + 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_SHADER_CORE_PROPERTIES_ARM = 1000415000, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_SHADER_CORE_CONTROL_CREATE_INFO_ARM = 1000417000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FEATURES_ARM = 1000417001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_PROPERTIES_ARM = 1000417002, + VK_STRUCTURE_TYPE_DISPATCH_PARAMETERS_ARM = 1000417003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_DISPATCH_PARAMETERS_PROPERTIES_ARM = 1000417004, + 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_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RENDER_PASS_STRIPED_FEATURES_ARM = 1000424000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RENDER_PASS_STRIPED_PROPERTIES_ARM = 1000424001, + VK_STRUCTURE_TYPE_RENDER_PASS_STRIPE_BEGIN_INFO_ARM = 1000424002, + VK_STRUCTURE_TYPE_RENDER_PASS_STRIPE_INFO_ARM = 1000424003, + VK_STRUCTURE_TYPE_RENDER_PASS_STRIPE_SUBMIT_INFO_ARM = 1000424004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV = 1000426000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV = 1000428000, + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_INDIRECT_BUFFER_INFO_NV = 1000428001, + VK_STRUCTURE_TYPE_PIPELINE_INDIRECT_DEVICE_ADDRESS_INFO_NV = 1000428002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_LINEAR_SWEPT_SPHERES_FEATURES_NV = 1000429008, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_LINEAR_SWEPT_SPHERES_DATA_NV = 1000429009, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_SPHERES_DATA_NV = 1000429010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV = 1000430000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MAXIMAL_RECONVERGENCE_FEATURES_KHR = 1000434000, + 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_NESTED_COMMAND_BUFFER_FEATURES_EXT = 1000451000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT = 1000451001, + VK_STRUCTURE_TYPE_NATIVE_BUFFER_USAGE_OHOS = 1000452000, + VK_STRUCTURE_TYPE_NATIVE_BUFFER_PROPERTIES_OHOS = 1000452001, + VK_STRUCTURE_TYPE_NATIVE_BUFFER_FORMAT_PROPERTIES_OHOS = 1000452002, + VK_STRUCTURE_TYPE_IMPORT_NATIVE_BUFFER_INFO_OHOS = 1000452003, + VK_STRUCTURE_TYPE_MEMORY_GET_NATIVE_BUFFER_INFO_OHOS = 1000452004, + VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OHOS = 1000452005, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT = 1000453000, + 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_TENSOR_CREATE_INFO_ARM = 1000460000, + VK_STRUCTURE_TYPE_TENSOR_VIEW_CREATE_INFO_ARM = 1000460001, + VK_STRUCTURE_TYPE_BIND_TENSOR_MEMORY_INFO_ARM = 1000460002, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_TENSOR_ARM = 1000460003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TENSOR_PROPERTIES_ARM = 1000460004, + VK_STRUCTURE_TYPE_TENSOR_FORMAT_PROPERTIES_ARM = 1000460005, + VK_STRUCTURE_TYPE_TENSOR_DESCRIPTION_ARM = 1000460006, + VK_STRUCTURE_TYPE_TENSOR_MEMORY_REQUIREMENTS_INFO_ARM = 1000460007, + VK_STRUCTURE_TYPE_TENSOR_MEMORY_BARRIER_ARM = 1000460008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TENSOR_FEATURES_ARM = 1000460009, + VK_STRUCTURE_TYPE_DEVICE_TENSOR_MEMORY_REQUIREMENTS_ARM = 1000460010, + VK_STRUCTURE_TYPE_COPY_TENSOR_INFO_ARM = 1000460011, + VK_STRUCTURE_TYPE_TENSOR_COPY_ARM = 1000460012, + VK_STRUCTURE_TYPE_TENSOR_DEPENDENCY_INFO_ARM = 1000460013, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_TENSOR_ARM = 1000460014, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_TENSOR_INFO_ARM = 1000460015, + VK_STRUCTURE_TYPE_EXTERNAL_TENSOR_PROPERTIES_ARM = 1000460016, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_TENSOR_CREATE_INFO_ARM = 1000460017, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_TENSOR_FEATURES_ARM = 1000460018, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_TENSOR_PROPERTIES_ARM = 1000460019, + VK_STRUCTURE_TYPE_DESCRIPTOR_GET_TENSOR_INFO_ARM = 1000460020, + VK_STRUCTURE_TYPE_TENSOR_CAPTURE_DESCRIPTOR_DATA_INFO_ARM = 1000460021, + VK_STRUCTURE_TYPE_TENSOR_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_ARM = 1000460022, + VK_STRUCTURE_TYPE_FRAME_BOUNDARY_TENSORS_ARM = 1000460023, + 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_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT = 1000342000, + 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_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID = 1000468000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468001, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ANTI_LAG_FEATURES_AMD = 1000476000, + VK_STRUCTURE_TYPE_ANTI_LAG_DATA_AMD = 1000476001, + VK_STRUCTURE_TYPE_ANTI_LAG_PRESENTATION_INFO_AMD = 1000476002, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DENSE_GEOMETRY_FORMAT_FEATURES_AMDX = 1000478000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DENSE_GEOMETRY_FORMAT_TRIANGLES_DATA_AMDX = 1000478001, +#endif + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_ID_2_KHR = 1000479000, + VK_STRUCTURE_TYPE_PRESENT_ID_2_KHR = 1000479001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_2_FEATURES_KHR = 1000479002, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_WAIT_2_KHR = 1000480000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_2_FEATURES_KHR = 1000480001, + VK_STRUCTURE_TYPE_PRESENT_WAIT_2_INFO_KHR = 1000480002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR = 1000481000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT = 1000482000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT = 1000482001, + VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT = 1000482002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_BINARY_FEATURES_KHR = 1000483000, + VK_STRUCTURE_TYPE_PIPELINE_BINARY_CREATE_INFO_KHR = 1000483001, + VK_STRUCTURE_TYPE_PIPELINE_BINARY_INFO_KHR = 1000483002, + VK_STRUCTURE_TYPE_PIPELINE_BINARY_KEY_KHR = 1000483003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_BINARY_PROPERTIES_KHR = 1000483004, + VK_STRUCTURE_TYPE_RELEASE_CAPTURED_PIPELINE_DATA_INFO_KHR = 1000483005, + VK_STRUCTURE_TYPE_PIPELINE_BINARY_DATA_INFO_KHR = 1000483006, + VK_STRUCTURE_TYPE_PIPELINE_CREATE_INFO_KHR = 1000483007, + VK_STRUCTURE_TYPE_DEVICE_PIPELINE_BINARY_INTERNAL_CACHE_CONTROL_KHR = 1000483008, + VK_STRUCTURE_TYPE_PIPELINE_BINARY_HANDLES_INFO_KHR = 1000483009, + 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_SURFACE_PRESENT_MODE_KHR = 1000274000, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_KHR = 1000274001, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_KHR = 1000274002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR = 1000275000, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_KHR = 1000275001, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_KHR = 1000275002, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_KHR = 1000275003, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_KHR = 1000275004, + VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_KHR = 1000275005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM = 1000488000, + 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_COOPERATIVE_VECTOR_FEATURES_NV = 1000491000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_VECTOR_PROPERTIES_NV = 1000491001, + VK_STRUCTURE_TYPE_COOPERATIVE_VECTOR_PROPERTIES_NV = 1000491002, + VK_STRUCTURE_TYPE_CONVERT_COOPERATIVE_VECTOR_MATRIX_INFO_NV = 1000491004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV = 1000492000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV = 1000492001, + 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_LEGACY_VERTEX_ATTRIBUTES_FEATURES_EXT = 1000495000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_VERTEX_ATTRIBUTES_PROPERTIES_EXT = 1000495001, + VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT = 1000496000, + 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_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT = 1000499000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INTERNALLY_SYNCHRONIZED_QUEUES_FEATURES_KHR = 1000504000, + VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV = 1000505000, + VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV = 1000505001, + VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV = 1000505002, + VK_STRUCTURE_TYPE_GET_LATENCY_MARKER_INFO_NV = 1000505003, + VK_STRUCTURE_TYPE_LATENCY_TIMINGS_FRAME_REPORT_NV = 1000505004, + VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV = 1000505005, + VK_STRUCTURE_TYPE_OUT_OF_BAND_QUEUE_TYPE_INFO_NV = 1000505006, + VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV = 1000505007, + VK_STRUCTURE_TYPE_LATENCY_SURFACE_CAPABILITIES_NV = 1000505008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR = 1000506000, + VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506002, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_CREATE_INFO_ARM = 1000507000, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_CREATE_INFO_ARM = 1000507001, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_RESOURCE_INFO_ARM = 1000507002, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_CONSTANT_ARM = 1000507003, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_MEMORY_REQUIREMENTS_INFO_ARM = 1000507004, + VK_STRUCTURE_TYPE_BIND_DATA_GRAPH_PIPELINE_SESSION_MEMORY_INFO_ARM = 1000507005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DATA_GRAPH_FEATURES_ARM = 1000507006, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SHADER_MODULE_CREATE_INFO_ARM = 1000507007, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_PROPERTY_QUERY_RESULT_ARM = 1000507008, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_INFO_ARM = 1000507009, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_COMPILER_CONTROL_CREATE_INFO_ARM = 1000507010, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_REQUIREMENTS_INFO_ARM = 1000507011, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_REQUIREMENT_ARM = 1000507012, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_IDENTIFIER_CREATE_INFO_ARM = 1000507013, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_DISPATCH_INFO_ARM = 1000507014, + VK_STRUCTURE_TYPE_DATA_GRAPH_PROCESSING_ENGINE_CREATE_INFO_ARM = 1000507016, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_PROCESSING_ENGINE_PROPERTIES_ARM = 1000507017, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_PROPERTIES_ARM = 1000507018, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_QUEUE_FAMILY_DATA_GRAPH_PROCESSING_ENGINE_INFO_ARM = 1000507019, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_CONSTANT_TENSOR_SEMI_STRUCTURED_SPARSITY_INFO_ARM = 1000507015, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_TOSA_PROPERTIES_ARM = 1000508000, + 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, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR = 1000201000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_PROPERTIES_KHR = 1000511000, + VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_KHR = 1000512000, + VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PICTURE_INFO_KHR = 1000512001, + VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR = 1000512003, + VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000512004, + VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR = 1000512005, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_CAPABILITIES_KHR = 1000513000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000513001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_PICTURE_INFO_KHR = 1000513002, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_DPB_SLOT_INFO_KHR = 1000513003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_AV1_FEATURES_KHR = 1000513004, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_PROFILE_INFO_KHR = 1000513005, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_RATE_CONTROL_INFO_KHR = 1000513006, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_RATE_CONTROL_LAYER_INFO_KHR = 1000513007, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_QUALITY_LEVEL_PROPERTIES_KHR = 1000513008, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_SESSION_CREATE_INFO_KHR = 1000513009, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_GOP_REMAINING_FRAME_INFO_KHR = 1000513010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_DECODE_VP9_FEATURES_KHR = 1000514000, + VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_CAPABILITIES_KHR = 1000514001, + VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PICTURE_INFO_KHR = 1000514002, + VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PROFILE_INFO_KHR = 1000514003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR = 1000515000, + VK_STRUCTURE_TYPE_VIDEO_INLINE_QUERY_INFO_KHR = 1000515001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PER_STAGE_DESCRIPTOR_SET_FEATURES_NV = 1000516000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM = 1000518000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM = 1000518001, + VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM = 1000518002, + VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM = 1000519000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM = 1000519001, + VK_STRUCTURE_TYPE_BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM = 1000519002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM = 1000520000, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM = 1000520001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM = 1000521000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT = 1000524000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFIED_IMAGE_LAYOUTS_FEATURES_KHR = 1000527000, + VK_STRUCTURE_TYPE_ATTACHMENT_FEEDBACK_LOOP_INFO_EXT = 1000527001, + VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX = 1000529000, + VK_STRUCTURE_TYPE_SCREEN_BUFFER_FORMAT_PROPERTIES_QNX = 1000529001, + VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX = 1000529002, + VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_QNX = 1000529003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX = 1000529004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT = 1000530000, + VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_KHR = 1000184000, + VK_STRUCTURE_TYPE_SET_DESCRIPTOR_BUFFER_OFFSETS_INFO_EXT = 1000545007, + VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_BUFFER_EMBEDDED_SAMPLERS_INFO_EXT = 1000545008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV = 1000546000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_MEMORY_HEAP_FEATURES_QCOM = 1000547000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_MEMORY_HEAP_PROPERTIES_QCOM = 1000547001, + VK_STRUCTURE_TYPE_TILE_MEMORY_REQUIREMENTS_QCOM = 1000547002, + VK_STRUCTURE_TYPE_TILE_MEMORY_BIND_INFO_QCOM = 1000547003, + VK_STRUCTURE_TYPE_TILE_MEMORY_SIZE_INFO_QCOM = 1000547004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_KHR = 1000549000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_KHR = 1000426001, + VK_STRUCTURE_TYPE_COPY_MEMORY_INDIRECT_INFO_KHR = 1000549002, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INDIRECT_INFO_KHR = 1000549003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_EXT = 1000427000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_EXT = 1000427001, + VK_STRUCTURE_TYPE_DECOMPRESS_MEMORY_INFO_EXT = 1000550002, + VK_STRUCTURE_TYPE_DISPLAY_SURFACE_STEREO_CREATE_INFO_NV = 1000551000, + VK_STRUCTURE_TYPE_DISPLAY_MODE_STEREO_PROPERTIES_NV = 1000551001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_INTRA_REFRESH_CAPABILITIES_KHR = 1000552000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_INTRA_REFRESH_CREATE_INFO_KHR = 1000552001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_INTRA_REFRESH_INFO_KHR = 1000552002, + VK_STRUCTURE_TYPE_VIDEO_REFERENCE_INTRA_REFRESH_INFO_KHR = 1000552003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_INTRA_REFRESH_FEATURES_KHR = 1000552004, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553000, + VK_STRUCTURE_TYPE_VIDEO_FORMAT_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUANTIZATION_MAP_INFO_KHR = 1000553002, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUANTIZATION_MAP_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000553005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_QUANTIZATION_MAP_FEATURES_KHR = 1000553009, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553003, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553004, + VK_STRUCTURE_TYPE_VIDEO_FORMAT_H265_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553006, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553007, + VK_STRUCTURE_TYPE_VIDEO_FORMAT_AV1_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAW_ACCESS_CHAINS_FEATURES_NV = 1000555000, + VK_STRUCTURE_TYPE_EXTERNAL_COMPUTE_QUEUE_DEVICE_CREATE_INFO_NV = 1000556000, + VK_STRUCTURE_TYPE_EXTERNAL_COMPUTE_QUEUE_CREATE_INFO_NV = 1000556001, + VK_STRUCTURE_TYPE_EXTERNAL_COMPUTE_QUEUE_DATA_PARAMS_NV = 1000556002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_COMPUTE_QUEUE_PROPERTIES_NV = 1000556003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR = 1000558000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMMAND_BUFFER_INHERITANCE_FEATURES_NV = 1000559000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_7_FEATURES_KHR = 1000562000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_7_PROPERTIES_KHR = 1000562001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_API_PROPERTIES_LIST_KHR = 1000562002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_API_PROPERTIES_KHR = 1000562003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_API_VULKAN_PROPERTIES_KHR = 1000562004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT16_VECTOR_FEATURES_NV = 1000563000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_REPLICATED_COMPOSITES_FEATURES_EXT = 1000564000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT8_FEATURES_EXT = 1000567000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_VALIDATION_FEATURES_NV = 1000568000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_FEATURES_NV = 1000569000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_PROPERTIES_NV = 1000569001, + VK_STRUCTURE_TYPE_CLUSTER_ACCELERATION_STRUCTURE_CLUSTERS_BOTTOM_LEVEL_INPUT_NV = 1000569002, + VK_STRUCTURE_TYPE_CLUSTER_ACCELERATION_STRUCTURE_TRIANGLE_CLUSTER_INPUT_NV = 1000569003, + VK_STRUCTURE_TYPE_CLUSTER_ACCELERATION_STRUCTURE_MOVE_OBJECTS_INPUT_NV = 1000569004, + VK_STRUCTURE_TYPE_CLUSTER_ACCELERATION_STRUCTURE_INPUT_INFO_NV = 1000569005, + VK_STRUCTURE_TYPE_CLUSTER_ACCELERATION_STRUCTURE_COMMANDS_INFO_NV = 1000569006, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CLUSTER_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000569007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PARTITIONED_ACCELERATION_STRUCTURE_FEATURES_NV = 1000570000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PARTITIONED_ACCELERATION_STRUCTURE_PROPERTIES_NV = 1000570001, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570002, + VK_STRUCTURE_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_INSTANCES_INPUT_NV = 1000570003, + VK_STRUCTURE_TYPE_BUILD_PARTITIONED_ACCELERATION_STRUCTURE_INFO_NV = 1000570004, + VK_STRUCTURE_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_FLAGS_NV = 1000570005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_EXT = 1000572000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_EXT = 1000572001, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_EXT = 1000572002, + VK_STRUCTURE_TYPE_INDIRECT_EXECUTION_SET_CREATE_INFO_EXT = 1000572003, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_EXT = 1000572004, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_EXT = 1000572006, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_EXT = 1000572007, + VK_STRUCTURE_TYPE_WRITE_INDIRECT_EXECUTION_SET_PIPELINE_EXT = 1000572008, + VK_STRUCTURE_TYPE_WRITE_INDIRECT_EXECUTION_SET_SHADER_EXT = 1000572009, + VK_STRUCTURE_TYPE_INDIRECT_EXECUTION_SET_PIPELINE_INFO_EXT = 1000572010, + VK_STRUCTURE_TYPE_INDIRECT_EXECUTION_SET_SHADER_INFO_EXT = 1000572011, + VK_STRUCTURE_TYPE_INDIRECT_EXECUTION_SET_SHADER_LAYOUT_INFO_EXT = 1000572012, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_PIPELINE_INFO_EXT = 1000572013, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_SHADER_INFO_EXT = 1000572014, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_KHR = 1000573000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_PROPERTIES_KHR = 1000573001, + VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_KHR = 1000573002, + VK_STRUCTURE_TYPE_DEVICE_FAULT_DEBUG_INFO_KHR = 1000573003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_8_FEATURES_KHR = 1000574000, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_ACCESS_FLAGS_3_KHR = 1000574002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_FEATURES_MESA = 1000575000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_PROPERTIES_MESA = 1000575001, + VK_STRUCTURE_TYPE_IMAGE_ALIGNMENT_CONTROL_CREATE_INFO_MESA = 1000575002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FMA_FEATURES_KHR = 1000579000, + VK_STRUCTURE_TYPE_PUSH_CONSTANT_BANK_INFO_NV = 1000580000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_CONSTANT_BANK_FEATURES_NV = 1000580001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_CONSTANT_BANK_PROPERTIES_NV = 1000580002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_EXT = 1000581000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_EXT = 1000581001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_CONTROL_FEATURES_EXT = 1000582000, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLAMP_CONTROL_CREATE_INFO_EXT = 1000582001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_9_FEATURES_KHR = 1000584000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_9_PROPERTIES_KHR = 1000584001, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_OWNERSHIP_TRANSFER_PROPERTIES_KHR = 1000584002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_2_FEATURES_KHR = 1000586000, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586001, + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586002, + VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586003, + VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS = 1000685000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HDR_VIVID_FEATURES_HUAWEI = 1000590000, + VK_STRUCTURE_TYPE_HDR_VIVID_DYNAMIC_METADATA_HUAWEI = 1000590001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_FEATURES_NV = 1000593000, + VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_FLEXIBLE_DIMENSIONS_PROPERTIES_NV = 1000593001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_PROPERTIES_NV = 1000593002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_OPACITY_MICROMAP_FEATURES_ARM = 1000596000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT = 1000602000, + VK_STRUCTURE_TYPE_MEMORY_METAL_HANDLE_PROPERTIES_EXT = 1000602001, + VK_STRUCTURE_TYPE_MEMORY_GET_METAL_HANDLE_INFO_EXT = 1000602002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR = 1000421000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_COUNTERS_BY_REGION_FEATURES_ARM = 1000605000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_COUNTERS_BY_REGION_PROPERTIES_ARM = 1000605001, + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_ARM = 1000605002, + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_ARM = 1000605003, + VK_STRUCTURE_TYPE_RENDER_PASS_PERFORMANCE_COUNTERS_BY_REGION_BEGIN_INFO_ARM = 1000605004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INSTRUMENTATION_FEATURES_ARM = 1000607000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INSTRUMENTATION_PROPERTIES_ARM = 1000607001, + VK_STRUCTURE_TYPE_SHADER_INSTRUMENTATION_CREATE_INFO_ARM = 1000607002, + VK_STRUCTURE_TYPE_SHADER_INSTRUMENTATION_METRIC_DESCRIPTION_ARM = 1000607003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_ROBUSTNESS_FEATURES_EXT = 1000608000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FORMAT_PACK_FEATURES_ARM = 1000609000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_LAYERED_FEATURES_VALVE = 1000611000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_LAYERED_PROPERTIES_VALVE = 1000611001, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_DENSITY_MAP_LAYERED_CREATE_INFO_VALVE = 1000611002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_KHR = 1000286000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_KHR = 1000286001, + VK_STRUCTURE_TYPE_SET_PRESENT_CONFIG_NV = 1000613000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_METERING_FEATURES_NV = 1000613001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_EXT = 1000425000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_EXT = 1000425001, + VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_EXT = 1000425002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_DEVICE_MEMORY_FEATURES_EXT = 1000620000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_KHR = 1000361000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_KHR = 1000623000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_KHR = 1000623001, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MICROMAP_DATA_KHR = 1000623002, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_KHR = 1000623003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_64_BIT_INDEXING_FEATURES_EXT = 1000627000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_RESOLVE_FEATURES_EXT = 1000628000, + VK_STRUCTURE_TYPE_BEGIN_CUSTOM_RESOLVE_INFO_EXT = 1000628001, + VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT = 1000628002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DATA_GRAPH_MODEL_FEATURES_QCOM = 1000629000, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_BUILTIN_MODEL_CREATE_INFO_QCOM = 1000629001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_10_FEATURES_KHR = 1000630000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_10_PROPERTIES_KHR = 1000630001, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_FLAGS_INFO_KHR = 1000630002, + VK_STRUCTURE_TYPE_RENDERING_END_INFO_KHR = 1000619003, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_MODE_INFO_KHR = 1000630004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DATA_GRAPH_OPTICAL_FLOW_FEATURES_ARM = 1000631000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_OPTICAL_FLOW_PROPERTIES_ARM = 1000631001, + VK_STRUCTURE_TYPE_DATA_GRAPH_OPTICAL_FLOW_IMAGE_FORMAT_INFO_ARM = 1000631003, + VK_STRUCTURE_TYPE_DATA_GRAPH_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_ARM = 1000631004, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_OPTICAL_FLOW_DISPATCH_INFO_ARM = 1000631005, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_OPTICAL_FLOW_CREATE_INFO_ARM = 1000631002, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_RESOURCE_INFO_IMAGE_LAYOUT_ARM = 1000631006, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SINGLE_NODE_CREATE_INFO_ARM = 1000631007, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SINGLE_NODE_CONNECTION_ARM = 1000631008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_FEATURES_EXT = 1000635000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_PROPERTIES_EXT = 1000635001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CACHE_INCREMENTAL_MODE_FEATURES_SEC = 1000637000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_UNIFORM_BUFFER_UNSIZED_ARRAY_FEATURES_EXT = 1000642000, + VK_STRUCTURE_TYPE_COMPUTE_OCCUPANCY_PRIORITY_PARAMETERS_NV = 1000645000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_OCCUPANCY_PRIORITY_FEATURES_NV = 1000645001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_11_FEATURES_KHR = 1000657000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_OPTIMAL_IMAGE_TRANSFER_GRANULARITY_PROPERTIES_KHR = 1000657001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_PARTITIONED_FEATURES_EXT = 1000662000, + VK_STRUCTURE_TYPE_UBM_SURFACE_CREATE_INFO_SEC = 1000664000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MIXED_FLOAT_DOT_PRODUCT_FEATURES_VALVE = 1000673000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_THROTTLE_HINT_FEATURES_SEC = 1000674000, + VK_STRUCTURE_TYPE_THROTTLE_HINT_SUBMIT_INFO_SEC = 1000674001, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_NEURAL_STATISTICS_CREATE_INFO_ARM = 1000676000, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_NEURAL_STATISTICS_CREATE_INFO_ARM = 1000676001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DATA_GRAPH_NEURAL_ACCELERATOR_STATISTICS_FEATURES_ARM = 1000676002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_RESTART_INDEX_FEATURES_EXT = 1000678000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_DECODE_VECTOR_FEATURES_NV = 1000689000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, + // VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT is a legacy alias + VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_RENDERING_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_INFO, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO, + VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES, + VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES, + VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, + VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, + // VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT is a legacy alias + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO_KHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, + VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, + VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, + VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO, + VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR = VK_STRUCTURE_TYPE_SUBPASS_END_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, + VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES, + VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, + VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK, + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, + VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2, + VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_NV = VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, + VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, + VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES, + VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_KHR, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES, + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES, + VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, + // VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL is a legacy alias + VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO, + VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES, + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO, + VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES, + VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY, + VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT = VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO, + VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_IMAGE_INFO_EXT = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_IMAGE_INFO, + VK_STRUCTURE_TYPE_SUBRESOURCE_HOST_MEMCPY_SIZE_EXT = VK_STRUCTURE_TYPE_SUBRESOURCE_HOST_MEMCPY_SIZE, + VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT = VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY, + VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_MAP_INFO, + VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_KHR, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_KHR, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT = VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_KHR, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_KHR, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT = VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_KHR, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_KHR, + VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT = VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES, + VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO, + VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES, + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2, + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR = VK_STRUCTURE_TYPE_BUFFER_COPY_2, + VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR = VK_STRUCTURE_TYPE_IMAGE_COPY_2, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2, + VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT = VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2, + VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT = VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT, + VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_KHR, + VK_STRUCTURE_TYPE_PIPELINE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES, + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_EXT, + VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM = VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES, + VK_STRUCTURE_TYPE_RENDERING_AREA_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_AREA_INFO, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_SUBRESOURCE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_IMAGE_SUBRESOURCE_INFO, + VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_KHR = VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2, + VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_KHR = VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2, + VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO, + VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO, + VK_STRUCTURE_TYPE_SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES, + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES, + VK_STRUCTURE_TYPE_BIND_MEMORY_STATUS_KHR = VK_STRUCTURE_TYPE_BIND_MEMORY_STATUS, + VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO_KHR = VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO, + VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO_KHR = VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO, + VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_INFO_KHR = VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_INFO, + VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO_KHR = VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO, + VK_STRUCTURE_TYPE_RENDERING_END_INFO_EXT = VK_STRUCTURE_TYPE_RENDERING_END_INFO_KHR, + VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkStructureType; + +typedef enum VkObjectType { + 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_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT = 1000295000, + 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_DEBUG_UTILS_MESSENGER_EXT = 1000128000, + VK_OBJECT_TYPE_GPA_SESSION_AMD = 1000133000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, + 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, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_OBJECT_TYPE_CUDA_MODULE_NV = 1000307000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_OBJECT_TYPE_CUDA_FUNCTION_NV = 1000307001, +#endif + VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000, + VK_OBJECT_TYPE_MICROMAP_EXT = 1000396000, + VK_OBJECT_TYPE_TENSOR_ARM = 1000460000, + VK_OBJECT_TYPE_TENSOR_VIEW_ARM = 1000460001, + VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV = 1000464000, + VK_OBJECT_TYPE_SHADER_EXT = 1000482000, + VK_OBJECT_TYPE_PIPELINE_BINARY_KHR = 1000483000, + VK_OBJECT_TYPE_DATA_GRAPH_PIPELINE_SESSION_ARM = 1000507000, + VK_OBJECT_TYPE_EXTERNAL_COMPUTE_QUEUE_NV = 1000556000, + VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_EXT = 1000572000, + VK_OBJECT_TYPE_INDIRECT_EXECUTION_SET_EXT = 1000572001, + VK_OBJECT_TYPE_SHADER_INSTRUMENTATION_ARM = 1000607000, + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = VK_OBJECT_TYPE_PRIVATE_DATA_SLOT, + VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkObjectType; + +typedef enum VkVendorId { + VK_VENDOR_ID_KHRONOS = 0x10000, + VK_VENDOR_ID_VIV = 0x10001, + VK_VENDOR_ID_VSI = 0x10002, + VK_VENDOR_ID_KAZAN = 0x10003, + VK_VENDOR_ID_CODEPLAY = 0x10004, + VK_VENDOR_ID_MESA = 0x10005, + VK_VENDOR_ID_POCL = 0x10006, + VK_VENDOR_ID_MOBILEYE = 0x10007, + VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF +} VkVendorId; + +typedef enum VkSystemAllocationScope { + 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, + VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF +} VkSystemAllocationScope; + +typedef enum VkInternalAllocationType { + VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0, + VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkInternalAllocationType; + +typedef enum VkFormat { + 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_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_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_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_A1B5G5R5_UNORM_PACK16 = 1000470000, + VK_FORMAT_A8_UNORM = 1000470001, + 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_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_R8_BOOL_ARM = 1000460000, + VK_FORMAT_R16_SFLOAT_FPENCODING_BFLOAT16_ARM = 1000460001, + VK_FORMAT_R8_SFLOAT_FPENCODING_FLOAT8E4M3_ARM = 1000460002, + VK_FORMAT_R8_SFLOAT_FPENCODING_FLOAT8E5M2_ARM = 1000460003, + VK_FORMAT_R16G16_SFIXED5_NV = 1000464000, + VK_FORMAT_R10X6_UINT_PACK16_ARM = 1000609000, + VK_FORMAT_R10X6G10X6_UINT_2PACK16_ARM = 1000609001, + VK_FORMAT_R10X6G10X6B10X6A10X6_UINT_4PACK16_ARM = 1000609002, + VK_FORMAT_R12X4_UINT_PACK16_ARM = 1000609003, + VK_FORMAT_R12X4G12X4_UINT_2PACK16_ARM = 1000609004, + VK_FORMAT_R12X4G12X4B12X4A12X4_UINT_4PACK16_ARM = 1000609005, + VK_FORMAT_R14X2_UINT_PACK16_ARM = 1000609006, + VK_FORMAT_R14X2G14X2_UINT_2PACK16_ARM = 1000609007, + VK_FORMAT_R14X2G14X2B14X2A14X2_UINT_4PACK16_ARM = 1000609008, + VK_FORMAT_R14X2_UNORM_PACK16_ARM = 1000609009, + VK_FORMAT_R14X2G14X2_UNORM_2PACK16_ARM = 1000609010, + VK_FORMAT_R14X2G14X2B14X2A14X2_UNORM_4PACK16_ARM = 1000609011, + VK_FORMAT_G14X2_B14X2R14X2_2PLANE_420_UNORM_3PACK16_ARM = 1000609012, + VK_FORMAT_G14X2_B14X2R14X2_2PLANE_422_UNORM_3PACK16_ARM = 1000609013, + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK, + VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK, + VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK, + VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK, + VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK, + VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK, + VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK, + VK_FORMAT_G8B8G8R8_422_UNORM_KHR = VK_FORMAT_G8B8G8R8_422_UNORM, + VK_FORMAT_B8G8R8G8_422_UNORM_KHR = VK_FORMAT_B8G8R8G8_422_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, + VK_FORMAT_R10X6_UNORM_PACK16_KHR = VK_FORMAT_R10X6_UNORM_PACK16, + VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR = VK_FORMAT_R10X6G10X6_UNORM_2PACK16, + VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, + VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, + VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, + VK_FORMAT_R12X4_UNORM_PACK16_KHR = VK_FORMAT_R12X4_UNORM_PACK16, + VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR = VK_FORMAT_R12X4G12X4_UNORM_2PACK16, + VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, + VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, + VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, + VK_FORMAT_G16B16G16R16_422_UNORM_KHR = VK_FORMAT_G16B16G16R16_422_UNORM, + VK_FORMAT_B16G16R16G16_422_UNORM_KHR = VK_FORMAT_B16G16R16G16_422_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, + VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, + VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT = VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, + VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = VK_FORMAT_A4R4G4B4_UNORM_PACK16, + VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = VK_FORMAT_A4B4G4R4_UNORM_PACK16, + // VK_FORMAT_R16G16_S10_5_NV is a legacy alias + VK_FORMAT_R16G16_S10_5_NV = VK_FORMAT_R16G16_SFIXED5_NV, + VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR = VK_FORMAT_A1B5G5R5_UNORM_PACK16, + VK_FORMAT_A8_UNORM_KHR = VK_FORMAT_A8_UNORM, + VK_FORMAT_MAX_ENUM = 0x7FFFFFFF +} VkFormat; + +typedef enum VkImageTiling { + VK_IMAGE_TILING_OPTIMAL = 0, + VK_IMAGE_TILING_LINEAR = 1, + VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT = 1000158000, + VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF +} VkImageTiling; + +typedef enum VkImageType { + VK_IMAGE_TYPE_1D = 0, + VK_IMAGE_TYPE_2D = 1, + VK_IMAGE_TYPE_3D = 2, + VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkImageType; + +typedef enum VkPhysicalDeviceType { + 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, + VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkPhysicalDeviceType; + +typedef enum VkQueryType { + 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_TIME_ELAPSED_QCOM = 1000173000, + VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, + VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_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, + VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkQueryType; + +typedef enum VkSharingMode { + VK_SHARING_MODE_EXCLUSIVE = 0, + VK_SHARING_MODE_CONCURRENT = 1, + VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSharingMode; + +typedef enum VkImageLayout { + 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_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, + 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_READ_ONLY_OPTIMAL = 1000314000, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL = 1000314001, + VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ = 1000232000, + 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_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, + VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = 1000164003, + 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_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT = 1000339000, + VK_IMAGE_LAYOUT_TENSOR_ALIASING_ARM = 1000460000, + VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR = 1000553000, + VK_IMAGE_LAYOUT_ZERO_INITIALIZED_EXT = 1000620000, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, + VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF +} VkImageLayout; + +typedef enum VkComponentSwizzle { + 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, + VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF +} VkComponentSwizzle; + +typedef enum VkImageViewType { + 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, + VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkImageViewType; + +typedef enum VkCommandBufferLevel { + VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, + VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, + VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferLevel; + +typedef enum VkIndexType { + VK_INDEX_TYPE_UINT16 = 0, + VK_INDEX_TYPE_UINT32 = 1, + VK_INDEX_TYPE_UINT8 = 1000265000, + VK_INDEX_TYPE_NONE_KHR = 1000165000, + VK_INDEX_TYPE_NONE_NV = VK_INDEX_TYPE_NONE_KHR, + VK_INDEX_TYPE_UINT8_EXT = VK_INDEX_TYPE_UINT8, + VK_INDEX_TYPE_UINT8_KHR = VK_INDEX_TYPE_UINT8, + VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkIndexType; + +typedef enum VkPipelineCacheHeaderVersion { + VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, + VK_PIPELINE_CACHE_HEADER_VERSION_DATA_GRAPH_QCOM = 1000629000, + VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheHeaderVersion; + +typedef enum VkBorderColor { + 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, + VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF +} VkBorderColor; + +typedef enum VkFilter { + VK_FILTER_NEAREST = 0, + VK_FILTER_LINEAR = 1, + VK_FILTER_CUBIC_EXT = 1000015000, + VK_FILTER_CUBIC_IMG = VK_FILTER_CUBIC_EXT, + VK_FILTER_MAX_ENUM = 0x7FFFFFFF +} VkFilter; + +typedef enum VkSamplerAddressMode { + 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, + // VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR is a legacy alias + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, + VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerAddressMode; + +typedef enum VkCompareOp { + 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, + VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF +} VkCompareOp; + +typedef enum VkSamplerMipmapMode { + VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, + VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, + VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerMipmapMode; + +typedef enum VkDescriptorType { + 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_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000, + VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001, + VK_DESCRIPTOR_TYPE_TENSOR_ARM = 1000460000, + VK_DESCRIPTOR_TYPE_MUTABLE_EXT = 1000351000, + VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570000, + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, + VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = VK_DESCRIPTOR_TYPE_MUTABLE_EXT, + VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorType; + +typedef enum VkPipelineBindPoint { + VK_PIPELINE_BIND_POINT_GRAPHICS = 0, + VK_PIPELINE_BIND_POINT_COMPUTE = 1, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_PIPELINE_BIND_POINT_EXECUTION_GRAPH_AMDX = 1000134000, +#endif + VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, + VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003, + VK_PIPELINE_BIND_POINT_DATA_GRAPH_ARM = 1000507000, + VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, + VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF +} VkPipelineBindPoint; + +typedef enum VkBlendFactor { + 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, + VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF +} VkBlendFactor; + +typedef enum VkBlendOp { + 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, + VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF +} VkBlendOp; + +typedef enum VkDynamicState { + 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_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_RASTERIZER_DISCARD_ENABLE = 1000377001, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE = 1000377002, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE = 1000377004, + VK_DYNAMIC_STATE_LINE_STIPPLE = 1000259000, + 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_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000, + 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_VERTEX_INPUT_EXT = 1000352000, + VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT = 1000377000, + VK_DYNAMIC_STATE_LOGIC_OP_EXT = 1000377003, + VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT = 1000381000, + 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_TESSELLATION_DOMAIN_ORIGIN_EXT = 1000455002, + 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, + VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT = 1000524000, + VK_DYNAMIC_STATE_DEPTH_CLAMP_RANGE_EXT = 1000582000, + VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = VK_DYNAMIC_STATE_LINE_STIPPLE, + VK_DYNAMIC_STATE_CULL_MODE_EXT = VK_DYNAMIC_STATE_CULL_MODE, + VK_DYNAMIC_STATE_FRONT_FACE_EXT = VK_DYNAMIC_STATE_FRONT_FACE, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT, + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT = VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE, + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT = VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT = VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, + VK_DYNAMIC_STATE_STENCIL_OP_EXT = VK_DYNAMIC_STATE_STENCIL_OP, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE, + VK_DYNAMIC_STATE_LINE_STIPPLE_KHR = VK_DYNAMIC_STATE_LINE_STIPPLE, + VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF +} VkDynamicState; + +typedef enum VkFrontFace { + VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, + VK_FRONT_FACE_CLOCKWISE = 1, + VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF +} VkFrontFace; + +typedef enum VkLogicOp { + 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, + VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF +} VkLogicOp; + +typedef enum VkStencilOp { + 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, + VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF +} VkStencilOp; + +typedef enum VkVertexInputRate { + VK_VERTEX_INPUT_RATE_VERTEX = 0, + VK_VERTEX_INPUT_RATE_INSTANCE = 1, + VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF +} VkVertexInputRate; + +typedef enum VkPrimitiveTopology { + 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, + VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF +} VkPrimitiveTopology; + +typedef enum VkPolygonMode { + VK_POLYGON_MODE_FILL = 0, + VK_POLYGON_MODE_LINE = 1, + VK_POLYGON_MODE_POINT = 2, + VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000, + VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF +} VkPolygonMode; + +typedef enum VkAttachmentLoadOp { + VK_ATTACHMENT_LOAD_OP_LOAD = 0, + VK_ATTACHMENT_LOAD_OP_CLEAR = 1, + VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2, + VK_ATTACHMENT_LOAD_OP_NONE = 1000400000, + VK_ATTACHMENT_LOAD_OP_NONE_EXT = VK_ATTACHMENT_LOAD_OP_NONE, + VK_ATTACHMENT_LOAD_OP_NONE_KHR = VK_ATTACHMENT_LOAD_OP_NONE, + VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF +} VkAttachmentLoadOp; + +typedef enum VkAttachmentStoreOp { + VK_ATTACHMENT_STORE_OP_STORE = 0, + VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, + VK_ATTACHMENT_STORE_OP_NONE = 1000301000, + VK_ATTACHMENT_STORE_OP_NONE_KHR = VK_ATTACHMENT_STORE_OP_NONE, + VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE, + VK_ATTACHMENT_STORE_OP_NONE_EXT = VK_ATTACHMENT_STORE_OP_NONE, + VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF +} VkAttachmentStoreOp; + +typedef enum VkSubpassContents { + VK_SUBPASS_CONTENTS_INLINE = 0, + VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, + VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR = 1000451000, + VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT = VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR, + VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF +} VkSubpassContents; + +typedef enum VkFormatFeatureFlagBits { + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001, + VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002, + VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004, + VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008, + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010, + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020, + VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040, + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080, + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200, + VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400, + VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000, + VK_FORMAT_FEATURE_TRANSFER_SRC_BIT = 0x00004000, + VK_FORMAT_FEATURE_TRANSFER_DST_BIT = 0x00008000, + VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000, + VK_FORMAT_FEATURE_DISJOINT_BIT = 0x00400000, + VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000, + VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000, + VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000, + VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 0x00002000, + VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000, + VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000, + VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000, + VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT, + VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, + VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT, + VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT, + VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = VK_FORMAT_FEATURE_DISJOINT_BIT, + VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, + VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFormatFeatureFlagBits; +typedef VkFlags VkFormatFeatureFlags; + +typedef enum VkImageCreateFlagBits { + VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001, + VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, + VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004, + VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008, + VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010, + VK_IMAGE_CREATE_ALIAS_BIT = 0x00000400, + VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT = 0x00000040, + VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT = 0x00000020, + VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 0x00000080, + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100, + VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800, + VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200, + VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000, + VK_IMAGE_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_EXT = 0x00010000, + VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000, + VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0x00004000, + VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT = 0x00040000, + VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT = 0x00020000, + VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR = 0x00100000, + VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_EXT = 0x00008000, + VK_IMAGE_CREATE_ALIAS_SINGLE_LAYER_DESCRIPTOR_BIT_KHR = 0x00400000, + VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT, + VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, + VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT, + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = VK_IMAGE_CREATE_EXTENDED_USAGE_BIT, + VK_IMAGE_CREATE_DISJOINT_BIT_KHR = VK_IMAGE_CREATE_DISJOINT_BIT, + VK_IMAGE_CREATE_ALIAS_BIT_KHR = VK_IMAGE_CREATE_ALIAS_BIT, + VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = VK_IMAGE_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_EXT, + VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM = VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_EXT, + VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageCreateFlagBits; +typedef VkFlags VkImageCreateFlags; + +typedef enum VkSampleCountFlagBits { + VK_SAMPLE_COUNT_1_BIT = 0x00000001, + VK_SAMPLE_COUNT_2_BIT = 0x00000002, + VK_SAMPLE_COUNT_4_BIT = 0x00000004, + VK_SAMPLE_COUNT_8_BIT = 0x00000008, + VK_SAMPLE_COUNT_16_BIT = 0x00000010, + VK_SAMPLE_COUNT_32_BIT = 0x00000020, + VK_SAMPLE_COUNT_64_BIT = 0x00000040, + VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSampleCountFlagBits; +typedef VkFlags VkSampleCountFlags; + +typedef enum VkImageUsageFlagBits { + VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001, + VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002, + VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004, + VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, + VK_IMAGE_USAGE_HOST_TRANSFER_BIT = 0x00400000, + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00000400, + VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00000800, + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR = 0x00001000, + VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200, + VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00000100, + VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00002000, + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0x00004000, + VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR = 0x00008000, + VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x00080000, + VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI = 0x00040000, + VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM = 0x00100000, + VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM = 0x00200000, + VK_IMAGE_USAGE_TENSOR_ALIASING_BIT_ARM = 0x00800000, + VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM = 0x08000000, + VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR = 0x02000000, + VK_IMAGE_USAGE_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR = 0x04000000, + VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT = VK_IMAGE_USAGE_HOST_TRANSFER_BIT, + VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageUsageFlagBits; +typedef VkFlags VkImageUsageFlags; + +typedef enum VkInstanceCreateFlagBits { + VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR = 0x00000001, + VK_INSTANCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkInstanceCreateFlagBits; +typedef VkFlags VkInstanceCreateFlags; + +typedef enum VkMemoryHeapFlagBits { + VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001, + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002, + VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM = 0x00000008, + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT, + VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryHeapFlagBits; +typedef VkFlags VkMemoryHeapFlags; + +typedef enum VkMemoryPropertyFlagBits { + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002, + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008, + VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010, + VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020, + VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD = 0x00000040, + VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD = 0x00000080, + VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV = 0x00000100, + VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryPropertyFlagBits; +typedef VkFlags VkMemoryPropertyFlags; + +typedef enum VkQueueFlagBits { + VK_QUEUE_GRAPHICS_BIT = 0x00000001, + VK_QUEUE_COMPUTE_BIT = 0x00000002, + VK_QUEUE_TRANSFER_BIT = 0x00000004, + VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, + VK_QUEUE_PROTECTED_BIT = 0x00000010, + VK_QUEUE_VIDEO_DECODE_BIT_KHR = 0x00000020, + VK_QUEUE_VIDEO_ENCODE_BIT_KHR = 0x00000040, + VK_QUEUE_OPTICAL_FLOW_BIT_NV = 0x00000100, + VK_QUEUE_DATA_GRAPH_BIT_ARM = 0x00000400, + VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueueFlagBits; +typedef VkFlags VkQueueFlags; + +typedef enum VkShaderStageFlagBits { + VK_SHADER_STAGE_VERTEX_BIT = 0x00000001, + VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002, + VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004, + VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, + VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, + VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, + VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, + VK_SHADER_STAGE_ALL = 0x7FFFFFFF, + VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100, + VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400, + VK_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, + VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, + VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, + VK_SHADER_STAGE_TASK_BIT_EXT = 0x00000040, + VK_SHADER_STAGE_MESH_BIT_EXT = 0x00000080, + VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0x00004000, + VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI = 0x00080000, + VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, + VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, + VK_SHADER_STAGE_MISS_BIT_NV = VK_SHADER_STAGE_MISS_BIT_KHR, + VK_SHADER_STAGE_INTERSECTION_BIT_NV = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, + VK_SHADER_STAGE_CALLABLE_BIT_NV = VK_SHADER_STAGE_CALLABLE_BIT_KHR, + VK_SHADER_STAGE_TASK_BIT_NV = VK_SHADER_STAGE_TASK_BIT_EXT, + VK_SHADER_STAGE_MESH_BIT_NV = VK_SHADER_STAGE_MESH_BIT_EXT, + VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkShaderStageFlagBits; +typedef VkFlags VkShaderStageFlags; +typedef VkFlags VkDeviceCreateFlags; + +typedef enum VkDeviceQueueCreateFlagBits { + VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0x00000001, + VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR = 0x00000004, + VK_DEVICE_QUEUE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDeviceQueueCreateFlagBits; +typedef VkFlags VkDeviceQueueCreateFlags; + +typedef enum VkPipelineStageFlagBits { + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008, + VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010, + VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020, + VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100, + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800, + VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000, + VK_PIPELINE_STAGE_HOST_BIT = 0x00004000, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, + VK_PIPELINE_STAGE_NONE = 0, + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000, + VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000, + VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000, + VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000, + VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT = 0x00080000, + VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT = 0x00100000, + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT = 0x00020000, + VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT, + VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT, + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT, + VK_PIPELINE_STAGE_NONE_KHR = VK_PIPELINE_STAGE_NONE, + VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineStageFlagBits; +typedef VkFlags VkPipelineStageFlags; + +typedef enum VkMemoryMapFlagBits { + VK_MEMORY_MAP_PLACED_BIT_EXT = 0x00000001, + VK_MEMORY_MAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryMapFlagBits; +typedef VkFlags VkMemoryMapFlags; + +typedef enum VkImageAspectFlagBits { + VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, + VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, + VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, + VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, + VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, + VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, + VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, + VK_IMAGE_ASPECT_NONE = 0, + VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080, + VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100, + VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200, + VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0x00000400, + VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, + VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, + VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, + VK_IMAGE_ASPECT_NONE_KHR = VK_IMAGE_ASPECT_NONE, + VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageAspectFlagBits; +typedef VkFlags VkImageAspectFlags; + +typedef enum VkSparseImageFormatFlagBits { + VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001, + VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002, + VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004, + VK_SPARSE_IMAGE_FORMAT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSparseImageFormatFlagBits; +typedef VkFlags VkSparseImageFormatFlags; + +typedef enum VkSparseMemoryBindFlagBits { + VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, + VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSparseMemoryBindFlagBits; +typedef VkFlags VkSparseMemoryBindFlags; + +typedef enum VkFenceCreateFlagBits { + VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001, + VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFenceCreateFlagBits; +typedef VkFlags VkFenceCreateFlags; +typedef VkFlags VkSemaphoreCreateFlags; + +typedef enum VkQueryPoolCreateFlagBits { + VK_QUERY_POOL_CREATE_RESET_BIT_KHR = 0x00000001, + VK_QUERY_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryPoolCreateFlagBits; +typedef VkFlags VkQueryPoolCreateFlags; + +typedef enum VkQueryPipelineStatisticFlagBits { + VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001, + VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0x00000002, + VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0x00000004, + VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0x00000008, + VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0x00000010, + VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0x00000020, + VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0x00000040, + VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0x00000080, + VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100, + VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200, + VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400, + VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT = 0x00000800, + VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT = 0x00001000, + VK_QUERY_PIPELINE_STATISTIC_CLUSTER_CULLING_SHADER_INVOCATIONS_BIT_HUAWEI = 0x00002000, + VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryPipelineStatisticFlagBits; +typedef VkFlags VkQueryPipelineStatisticFlags; + +typedef enum VkQueryResultFlagBits { + VK_QUERY_RESULT_64_BIT = 0x00000001, + VK_QUERY_RESULT_WAIT_BIT = 0x00000002, + VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004, + VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008, + VK_QUERY_RESULT_WITH_STATUS_BIT_KHR = 0x00000010, + VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryResultFlagBits; +typedef VkFlags VkQueryResultFlags; + +typedef enum VkBufferCreateFlagBits { + VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001, + VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, + VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004, + VK_BUFFER_CREATE_PROTECTED_BIT = 0x00000008, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000010, + VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000020, + VK_BUFFER_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR = 0x00000040, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, + VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkBufferCreateFlagBits; +typedef VkFlags VkBufferCreateFlags; + +typedef enum VkBufferUsageFlagBits { + VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001, + VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002, + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004, + VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, + VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 0x00020000, + VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000, + VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00004000, + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800, + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000, + VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_EXECUTION_GRAPH_SCRATCH_BIT_AMDX = 0x02000000, +#endif + VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT = 0x10000000, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000, + VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400, + VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00008000, + VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000, + VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT = 0x00200000, + VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00400000, + VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0x04000000, + VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0x00800000, + VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT = 0x01000000, + VK_BUFFER_USAGE_TILE_MEMORY_BIT_QCOM = 0x08000000, + VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkBufferUsageFlagBits; +typedef VkFlags VkBufferUsageFlags; + +typedef enum VkImageViewCreateFlagBits { + VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001, + VK_IMAGE_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000004, + VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT = 0x00000002, + VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageViewCreateFlagBits; +typedef VkFlags VkImageViewCreateFlags; + +typedef enum VkAccessFlagBits { + VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, + VK_ACCESS_INDEX_READ_BIT = 0x00000002, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, + VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, + VK_ACCESS_SHADER_READ_BIT = 0x00000020, + VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, + VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, + VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, + VK_ACCESS_HOST_READ_BIT = 0x00002000, + VK_ACCESS_HOST_WRITE_BIT = 0x00004000, + VK_ACCESS_MEMORY_READ_BIT = 0x00008000, + VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, + VK_ACCESS_NONE = 0, + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, + VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000, + VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000, + VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000, + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000, + VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT = 0x00020000, + VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT = 0x00040000, + VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, + VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT, + VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT, + VK_ACCESS_NONE_KHR = VK_ACCESS_NONE, + VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkAccessFlagBits; +typedef VkFlags VkAccessFlags; + +typedef enum VkDependencyFlagBits { + VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, + VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004, + VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002, + VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT = 0x00000008, + VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR = 0x00000020, + VK_DEPENDENCY_ASYMMETRIC_EVENT_BIT_KHR = 0x00000040, + VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT, + VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT, + VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDependencyFlagBits; +typedef VkFlags VkDependencyFlags; + +typedef enum VkCommandPoolCreateFlagBits { + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, + VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004, + VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandPoolCreateFlagBits; +typedef VkFlags VkCommandPoolCreateFlags; + +typedef enum VkCommandPoolResetFlagBits { + VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001, + VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandPoolResetFlagBits; +typedef VkFlags VkCommandPoolResetFlags; + +typedef enum VkQueryControlFlagBits { + VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001, + VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryControlFlagBits; +typedef VkFlags VkQueryControlFlags; + +typedef enum VkCommandBufferUsageFlagBits { + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001, + VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002, + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004, + VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferUsageFlagBits; +typedef VkFlags VkCommandBufferUsageFlags; + +typedef enum VkCommandBufferResetFlagBits { + VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001, + VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferResetFlagBits; +typedef VkFlags VkCommandBufferResetFlags; + +typedef enum VkEventCreateFlagBits { + VK_EVENT_CREATE_DEVICE_ONLY_BIT = 0x00000001, + VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = VK_EVENT_CREATE_DEVICE_ONLY_BIT, + VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkEventCreateFlagBits; +typedef VkFlags VkEventCreateFlags; +typedef VkFlags VkBufferViewCreateFlags; +typedef VkFlags VkShaderModuleCreateFlags; + +typedef enum VkPipelineCacheCreateFlagBits { + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001, + VK_PIPELINE_CACHE_CREATE_INTERNALLY_SYNCHRONIZED_MERGE_BIT_KHR = 0x00000008, + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT = VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT, + VK_PIPELINE_CACHE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheCreateFlagBits; +typedef VkFlags VkPipelineCacheCreateFlags; + +typedef enum VkPipelineCreateFlagBits { + VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001, + VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002, + VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, + VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT = 0x00000100, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT = 0x00000200, + VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT = 0x08000000, + VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT = 0x40000000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000, + VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0x00080000, + VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020, + VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000, + VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000, + VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0x00000040, + VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080, + VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00040000, + VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0x00000800, + VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0x20000000, + VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT = 0x00800000, + VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT = 0x00000400, + VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000, + VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x02000000, + VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x04000000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_PIPELINE_CREATE_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000, +#endif + VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_KHR = 0x01000000, + // VK_PIPELINE_CREATE_DISPATCH_BASE is a legacy alias + VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, + VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, + VK_PIPELINE_CREATE_DISPATCH_BASE_BIT_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, + // VK_PIPELINE_CREATE_DISPATCH_BASE_KHR is a legacy alias + VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, + // VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT is a legacy alias + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT, + // VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR is a legacy alias + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT, + VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_KHR, + VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT = VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT, + VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT = VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT, + VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCreateFlagBits; +typedef VkFlags VkPipelineCreateFlags; + +typedef enum VkPipelineLayoutCreateFlagBits { + VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT = 0x00000002, + VK_PIPELINE_LAYOUT_CREATE_NO_TASK_SHADER_BIT_KHR = 0x00000004, + VK_PIPELINE_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineLayoutCreateFlagBits; +typedef VkFlags VkPipelineLayoutCreateFlags; + +typedef enum VkPipelineShaderStageCreateFlagBits { + VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT = 0x00000001, + VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT = 0x00000002, + VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT, + VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT, + VK_PIPELINE_SHADER_STAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineShaderStageCreateFlagBits; +typedef VkFlags VkPipelineShaderStageCreateFlags; + +typedef enum VkSamplerCreateFlagBits { + VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001, + VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002, + VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000008, + VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT = 0x00000004, + VK_SAMPLER_CREATE_IMAGE_PROCESSING_BIT_QCOM = 0x00000010, + VK_SAMPLER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSamplerCreateFlagBits; +typedef VkFlags VkSamplerCreateFlags; + +typedef enum VkDescriptorPoolCreateFlagBits { + VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, + VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002, + VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT = 0x00000004, + VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV = 0x00000008, + VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV = 0x00000010, + VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, + VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT, + VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorPoolCreateFlagBits; +typedef VkFlags VkDescriptorPoolCreateFlags; +typedef VkFlags VkDescriptorPoolResetFlags; + +typedef enum VkDescriptorSetLayoutCreateFlagBits { + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT = 0x00000001, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00000010, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT = 0x00000020, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00000080, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT = 0x00000004, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PER_STAGE_BIT_NV = 0x00000040, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE = VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorSetLayoutCreateFlagBits; +typedef VkFlags VkDescriptorSetLayoutCreateFlags; + +typedef enum VkColorComponentFlagBits { + VK_COLOR_COMPONENT_R_BIT = 0x00000001, + VK_COLOR_COMPONENT_G_BIT = 0x00000002, + VK_COLOR_COMPONENT_B_BIT = 0x00000004, + VK_COLOR_COMPONENT_A_BIT = 0x00000008, + VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkColorComponentFlagBits; +typedef VkFlags VkColorComponentFlags; + +typedef enum VkCullModeFlagBits { + VK_CULL_MODE_NONE = 0, + VK_CULL_MODE_FRONT_BIT = 0x00000001, + VK_CULL_MODE_BACK_BIT = 0x00000002, + VK_CULL_MODE_FRONT_AND_BACK = 0x00000003, + VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCullModeFlagBits; +typedef VkFlags VkCullModeFlags; + +typedef enum VkPipelineColorBlendStateCreateFlagBits { + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT = 0x00000001, + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT, + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineColorBlendStateCreateFlagBits; +typedef VkFlags VkPipelineColorBlendStateCreateFlags; + +typedef enum VkPipelineDepthStencilStateCreateFlagBits { + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0x00000001, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0x00000002, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineDepthStencilStateCreateFlagBits; +typedef VkFlags VkPipelineDepthStencilStateCreateFlags; +typedef VkFlags VkPipelineDynamicStateCreateFlags; +typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; +typedef VkFlags VkPipelineMultisampleStateCreateFlags; +typedef VkFlags VkPipelineRasterizationStateCreateFlags; +typedef VkFlags VkPipelineTessellationStateCreateFlags; +typedef VkFlags VkPipelineVertexInputStateCreateFlags; +typedef VkFlags VkPipelineViewportStateCreateFlags; + +typedef enum VkAttachmentDescriptionFlagBits { + VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001, + VK_ATTACHMENT_DESCRIPTION_RESOLVE_SKIP_TRANSFER_FUNCTION_BIT_KHR = 0x00000002, + VK_ATTACHMENT_DESCRIPTION_RESOLVE_ENABLE_TRANSFER_FUNCTION_BIT_KHR = 0x00000004, + VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkAttachmentDescriptionFlagBits; +typedef VkFlags VkAttachmentDescriptionFlags; + +typedef enum VkFramebufferCreateFlagBits { + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 0x00000001, + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, + VK_FRAMEBUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFramebufferCreateFlagBits; +typedef VkFlags VkFramebufferCreateFlags; + +typedef enum VkRenderPassCreateFlagBits { + VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM = 0x00000002, + VK_RENDER_PASS_CREATE_PER_LAYER_FRAGMENT_DENSITY_BIT_VALVE = 0x00000004, + VK_RENDER_PASS_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkRenderPassCreateFlagBits; +typedef VkFlags VkRenderPassCreateFlags; + +typedef enum VkSubpassDescriptionFlagBits { + VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001, + VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, + VK_SUBPASS_DESCRIPTION_TILE_SHADING_APRON_BIT_QCOM = 0x00000100, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT = 0x00000010, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0x00000020, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0x00000040, + VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x00000080, + VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_EXT = 0x00000004, + VK_SUBPASS_DESCRIPTION_CUSTOM_RESOLVE_BIT_EXT = 0x00000008, + VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM = VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_EXT, + VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM = VK_SUBPASS_DESCRIPTION_CUSTOM_RESOLVE_BIT_EXT, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT, + VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubpassDescriptionFlagBits; +typedef VkFlags VkSubpassDescriptionFlags; + +typedef enum VkStencilFaceFlagBits { + VK_STENCIL_FACE_FRONT_BIT = 0x00000001, + VK_STENCIL_FACE_BACK_BIT = 0x00000002, + VK_STENCIL_FACE_FRONT_AND_BACK = 0x00000003, + // VK_STENCIL_FRONT_AND_BACK is a legacy alias + VK_STENCIL_FRONT_AND_BACK = VK_STENCIL_FACE_FRONT_AND_BACK, + VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkStencilFaceFlagBits; +typedef VkFlags VkStencilFaceFlags; +typedef struct VkExtent2D { + uint32_t width; + uint32_t height; +} VkExtent2D; + +typedef struct VkExtent3D { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkExtent3D; + +typedef struct VkOffset2D { + int32_t x; + int32_t y; +} VkOffset2D; + +typedef struct VkOffset3D { + int32_t x; + int32_t y; + int32_t z; +} VkOffset3D; + +typedef struct VkRect2D { + VkOffset2D offset; + VkExtent2D extent; +} VkRect2D; + +typedef struct VkBaseInStructure { + VkStructureType sType; + const struct VkBaseInStructure* pNext; +} VkBaseInStructure; + +typedef struct VkBaseOutStructure { + VkStructureType sType; + struct VkBaseOutStructure* pNext; +} VkBaseOutStructure; + +typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( + void* pUserData, + size_t size, + size_t alignment, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkFreeFunction)( + void* pUserData, + void* pMemory); + +typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)( + void* pUserData, + size_t size, + VkInternalAllocationType allocationType, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)( + void* pUserData, + size_t size, + VkInternalAllocationType allocationType, + VkSystemAllocationScope allocationScope); + +typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)( + void* pUserData, + void* pOriginal, + size_t size, + size_t alignment, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void); +typedef struct VkAllocationCallbacks { + void* pUserData; + PFN_vkAllocationFunction pfnAllocation; + PFN_vkReallocationFunction pfnReallocation; + PFN_vkFreeFunction pfnFree; + PFN_vkInternalAllocationNotification pfnInternalAllocation; + PFN_vkInternalFreeNotification pfnInternalFree; +} VkAllocationCallbacks; + +typedef struct VkApplicationInfo { + VkStructureType sType; + const void* pNext; + const char* pApplicationName; + uint32_t applicationVersion; + const char* pEngineName; + uint32_t engineVersion; + uint32_t apiVersion; +} VkApplicationInfo; + +typedef struct VkFormatProperties { + VkFormatFeatureFlags linearTilingFeatures; + VkFormatFeatureFlags optimalTilingFeatures; + VkFormatFeatureFlags bufferFeatures; +} VkFormatProperties; + +typedef struct VkImageFormatProperties { + VkExtent3D maxExtent; + uint32_t maxMipLevels; + uint32_t maxArrayLayers; + VkSampleCountFlags sampleCounts; + VkDeviceSize maxResourceSize; +} VkImageFormatProperties; + +typedef struct VkInstanceCreateInfo { + VkStructureType sType; + const void* pNext; + VkInstanceCreateFlags flags; + const VkApplicationInfo* pApplicationInfo; + uint32_t enabledLayerCount; + const char* const* ppEnabledLayerNames; + uint32_t enabledExtensionCount; + const char* const* ppEnabledExtensionNames; +} VkInstanceCreateInfo; + +typedef struct VkMemoryHeap { + VkDeviceSize size; + VkMemoryHeapFlags flags; +} VkMemoryHeap; + +typedef struct VkMemoryType { + VkMemoryPropertyFlags propertyFlags; + uint32_t heapIndex; +} VkMemoryType; + +typedef struct VkPhysicalDeviceFeatures { + VkBool32 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; +} VkPhysicalDeviceFeatures; + +typedef struct VkPhysicalDeviceLimits { + uint32_t maxImageDimension1D; + uint32_t maxImageDimension2D; + uint32_t maxImageDimension3D; + uint32_t maxImageDimensionCube; + uint32_t maxImageArrayLayers; + uint32_t maxTexelBufferElements; + uint32_t maxUniformBufferRange; + uint32_t maxStorageBufferRange; + uint32_t maxPushConstantsSize; + uint32_t maxMemoryAllocationCount; + uint32_t maxSamplerAllocationCount; + VkDeviceSize bufferImageGranularity; + VkDeviceSize sparseAddressSpaceSize; + uint32_t maxBoundDescriptorSets; + uint32_t maxPerStageDescriptorSamplers; + uint32_t maxPerStageDescriptorUniformBuffers; + uint32_t maxPerStageDescriptorStorageBuffers; + uint32_t maxPerStageDescriptorSampledImages; + uint32_t maxPerStageDescriptorStorageImages; + uint32_t maxPerStageDescriptorInputAttachments; + uint32_t maxPerStageResources; + uint32_t maxDescriptorSetSamplers; + uint32_t maxDescriptorSetUniformBuffers; + uint32_t maxDescriptorSetUniformBuffersDynamic; + uint32_t maxDescriptorSetStorageBuffers; + uint32_t maxDescriptorSetStorageBuffersDynamic; + uint32_t maxDescriptorSetSampledImages; + uint32_t maxDescriptorSetStorageImages; + uint32_t maxDescriptorSetInputAttachments; + uint32_t maxVertexInputAttributes; + uint32_t maxVertexInputBindings; + uint32_t maxVertexInputAttributeOffset; + uint32_t maxVertexInputBindingStride; + uint32_t maxVertexOutputComponents; + uint32_t maxTessellationGenerationLevel; + uint32_t maxTessellationPatchSize; + uint32_t maxTessellationControlPerVertexInputComponents; + uint32_t maxTessellationControlPerVertexOutputComponents; + uint32_t maxTessellationControlPerPatchOutputComponents; + uint32_t maxTessellationControlTotalOutputComponents; + uint32_t maxTessellationEvaluationInputComponents; + uint32_t maxTessellationEvaluationOutputComponents; + uint32_t maxGeometryShaderInvocations; + uint32_t maxGeometryInputComponents; + uint32_t maxGeometryOutputComponents; + uint32_t maxGeometryOutputVertices; + uint32_t maxGeometryTotalOutputComponents; + uint32_t maxFragmentInputComponents; + uint32_t maxFragmentOutputAttachments; + uint32_t maxFragmentDualSrcAttachments; + uint32_t maxFragmentCombinedOutputResources; + uint32_t maxComputeSharedMemorySize; + uint32_t maxComputeWorkGroupCount[3]; + uint32_t maxComputeWorkGroupInvocations; + uint32_t maxComputeWorkGroupSize[3]; + uint32_t subPixelPrecisionBits; + uint32_t subTexelPrecisionBits; + uint32_t mipmapPrecisionBits; + uint32_t maxDrawIndexedIndexValue; + uint32_t maxDrawIndirectCount; + float maxSamplerLodBias; + float maxSamplerAnisotropy; + uint32_t maxViewports; + uint32_t maxViewportDimensions[2]; + float viewportBoundsRange[2]; + uint32_t viewportSubPixelBits; + size_t minMemoryMapAlignment; + VkDeviceSize minTexelBufferOffsetAlignment; + VkDeviceSize minUniformBufferOffsetAlignment; + VkDeviceSize minStorageBufferOffsetAlignment; + int32_t minTexelOffset; + uint32_t maxTexelOffset; + int32_t minTexelGatherOffset; + uint32_t maxTexelGatherOffset; + float minInterpolationOffset; + float maxInterpolationOffset; + uint32_t subPixelInterpolationOffsetBits; + uint32_t maxFramebufferWidth; + uint32_t maxFramebufferHeight; + uint32_t maxFramebufferLayers; + VkSampleCountFlags framebufferColorSampleCounts; + VkSampleCountFlags framebufferDepthSampleCounts; + VkSampleCountFlags framebufferStencilSampleCounts; + VkSampleCountFlags framebufferNoAttachmentsSampleCounts; + uint32_t maxColorAttachments; + VkSampleCountFlags sampledImageColorSampleCounts; + VkSampleCountFlags sampledImageIntegerSampleCounts; + VkSampleCountFlags sampledImageDepthSampleCounts; + VkSampleCountFlags sampledImageStencilSampleCounts; + VkSampleCountFlags storageImageSampleCounts; + uint32_t maxSampleMaskWords; + VkBool32 timestampComputeAndGraphics; + float timestampPeriod; + uint32_t maxClipDistances; + uint32_t maxCullDistances; + uint32_t maxCombinedClipAndCullDistances; + uint32_t discreteQueuePriorities; + float pointSizeRange[2]; + float lineWidthRange[2]; + float pointSizeGranularity; + float lineWidthGranularity; + VkBool32 strictLines; + VkBool32 standardSampleLocations; + VkDeviceSize optimalBufferCopyOffsetAlignment; + VkDeviceSize optimalBufferCopyRowPitchAlignment; + VkDeviceSize nonCoherentAtomSize; +} VkPhysicalDeviceLimits; + +typedef struct VkPhysicalDeviceMemoryProperties { + uint32_t memoryTypeCount; + VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; + uint32_t memoryHeapCount; + VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryProperties; + +typedef struct VkPhysicalDeviceSparseProperties { + VkBool32 residencyStandard2DBlockShape; + VkBool32 residencyStandard2DMultisampleBlockShape; + VkBool32 residencyStandard3DBlockShape; + VkBool32 residencyAlignedMipSize; + VkBool32 residencyNonResidentStrict; +} VkPhysicalDeviceSparseProperties; + +typedef struct VkPhysicalDeviceProperties { + uint32_t apiVersion; + uint32_t driverVersion; + uint32_t vendorID; + uint32_t deviceID; + VkPhysicalDeviceType deviceType; + char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; + VkPhysicalDeviceLimits limits; + VkPhysicalDeviceSparseProperties sparseProperties; +} VkPhysicalDeviceProperties; + +typedef struct VkQueueFamilyProperties { + VkQueueFlags queueFlags; + uint32_t queueCount; + uint32_t timestampValidBits; + VkExtent3D minImageTransferGranularity; +} VkQueueFamilyProperties; + +typedef struct VkDeviceQueueCreateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceQueueCreateFlags flags; + uint32_t queueFamilyIndex; + uint32_t queueCount; + const float* pQueuePriorities; +} VkDeviceQueueCreateInfo; + +typedef struct VkDeviceCreateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceCreateFlags flags; + uint32_t queueCreateInfoCount; + const VkDeviceQueueCreateInfo* pQueueCreateInfos; + // enabledLayerCount is legacy and not used + uint32_t enabledLayerCount; + // ppEnabledLayerNames is legacy and not used + const char* const* ppEnabledLayerNames; + uint32_t enabledExtensionCount; + const char* const* ppEnabledExtensionNames; + const VkPhysicalDeviceFeatures* pEnabledFeatures; +} VkDeviceCreateInfo; + +typedef struct VkExtensionProperties { + char extensionName[VK_MAX_EXTENSION_NAME_SIZE]; + uint32_t specVersion; +} VkExtensionProperties; + +typedef struct VkLayerProperties { + char layerName[VK_MAX_EXTENSION_NAME_SIZE]; + uint32_t specVersion; + uint32_t implementationVersion; + char description[VK_MAX_DESCRIPTION_SIZE]; +} VkLayerProperties; + +typedef struct VkSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + const VkPipelineStageFlags* pWaitDstStageMask; + uint32_t commandBufferCount; + const VkCommandBuffer* pCommandBuffers; + uint32_t signalSemaphoreCount; + const VkSemaphore* pSignalSemaphores; +} VkSubmitInfo; + +typedef struct VkMappedMemoryRange { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkDeviceSize offset; + VkDeviceSize size; +} VkMappedMemoryRange; + +typedef struct VkMemoryAllocateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeIndex; +} VkMemoryAllocateInfo; + +typedef struct VkMemoryRequirements { + VkDeviceSize size; + VkDeviceSize alignment; + uint32_t memoryTypeBits; +} VkMemoryRequirements; + +typedef struct VkImageSubresource { + VkImageAspectFlags aspectMask; + uint32_t mipLevel; + uint32_t arrayLayer; +} VkImageSubresource; + +typedef struct VkSparseImageFormatProperties { + VkImageAspectFlags aspectMask; + VkExtent3D imageGranularity; + VkSparseImageFormatFlags flags; +} VkSparseImageFormatProperties; + +typedef struct VkSparseImageMemoryBind { + VkImageSubresource subresource; + VkOffset3D offset; + VkExtent3D extent; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkSparseMemoryBindFlags flags; +} VkSparseImageMemoryBind; + +typedef struct VkSparseImageMemoryBindInfo { + VkImage image; + uint32_t bindCount; + const VkSparseImageMemoryBind* pBinds; +} VkSparseImageMemoryBindInfo; + +typedef struct VkSparseImageMemoryRequirements { + VkSparseImageFormatProperties formatProperties; + uint32_t imageMipTailFirstLod; + VkDeviceSize imageMipTailSize; + VkDeviceSize imageMipTailOffset; + VkDeviceSize imageMipTailStride; +} VkSparseImageMemoryRequirements; + +typedef struct VkSparseMemoryBind { + VkDeviceSize resourceOffset; + VkDeviceSize size; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkSparseMemoryBindFlags flags; +} VkSparseMemoryBind; + +typedef struct VkSparseBufferMemoryBindInfo { + VkBuffer buffer; + uint32_t bindCount; + const VkSparseMemoryBind* pBinds; +} VkSparseBufferMemoryBindInfo; + +typedef struct VkSparseImageOpaqueMemoryBindInfo { + VkImage image; + uint32_t bindCount; + const VkSparseMemoryBind* pBinds; +} VkSparseImageOpaqueMemoryBindInfo; + +typedef struct VkBindSparseInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + uint32_t bufferBindCount; + const VkSparseBufferMemoryBindInfo* pBufferBinds; + uint32_t imageOpaqueBindCount; + const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds; + uint32_t imageBindCount; + const VkSparseImageMemoryBindInfo* pImageBinds; + uint32_t signalSemaphoreCount; + const VkSemaphore* pSignalSemaphores; +} VkBindSparseInfo; + +typedef struct VkFenceCreateInfo { + VkStructureType sType; + const void* pNext; + VkFenceCreateFlags flags; +} VkFenceCreateInfo; + +typedef struct VkSemaphoreCreateInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreCreateFlags flags; +} VkSemaphoreCreateInfo; + +typedef struct VkQueryPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkQueryPoolCreateFlags flags; + VkQueryType queryType; + uint32_t queryCount; + VkQueryPipelineStatisticFlags pipelineStatistics; +} VkQueryPoolCreateInfo; + +typedef struct VkBufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkBufferCreateFlags flags; + VkDeviceSize size; + VkBufferUsageFlags usage; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; +} VkBufferCreateInfo; + +typedef struct VkImageCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageCreateFlags flags; + VkImageType imageType; + VkFormat format; + VkExtent3D extent; + uint32_t mipLevels; + uint32_t arrayLayers; + VkSampleCountFlagBits samples; + VkImageTiling tiling; + VkImageUsageFlags usage; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; + VkImageLayout initialLayout; +} VkImageCreateInfo; + +typedef struct VkSubresourceLayout { + VkDeviceSize offset; + VkDeviceSize size; + VkDeviceSize rowPitch; + VkDeviceSize arrayPitch; + VkDeviceSize depthPitch; +} VkSubresourceLayout; + +typedef struct VkComponentMapping { + VkComponentSwizzle r; + VkComponentSwizzle g; + VkComponentSwizzle b; + VkComponentSwizzle a; +} VkComponentMapping; + +typedef struct VkImageSubresourceRange { + VkImageAspectFlags aspectMask; + uint32_t baseMipLevel; + uint32_t levelCount; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceRange; + +typedef struct VkImageViewCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageViewCreateFlags flags; + VkImage image; + VkImageViewType viewType; + VkFormat format; + VkComponentMapping components; + VkImageSubresourceRange subresourceRange; +} VkImageViewCreateInfo; + +typedef struct VkCommandPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkCommandPoolCreateFlags flags; + uint32_t queueFamilyIndex; +} VkCommandPoolCreateInfo; + +typedef struct VkCommandBufferAllocateInfo { + VkStructureType sType; + const void* pNext; + VkCommandPool commandPool; + VkCommandBufferLevel level; + uint32_t commandBufferCount; +} VkCommandBufferAllocateInfo; + +typedef struct VkCommandBufferInheritanceInfo { + VkStructureType sType; + const void* pNext; + VkRenderPass renderPass; + uint32_t subpass; + VkFramebuffer framebuffer; + VkBool32 occlusionQueryEnable; + VkQueryControlFlags queryFlags; + VkQueryPipelineStatisticFlags pipelineStatistics; +} VkCommandBufferInheritanceInfo; + +typedef struct VkCommandBufferBeginInfo { + VkStructureType sType; + const void* pNext; + VkCommandBufferUsageFlags flags; + const VkCommandBufferInheritanceInfo* pInheritanceInfo; +} VkCommandBufferBeginInfo; + +typedef struct VkBufferCopy { + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy; + +typedef struct VkImageSubresourceLayers { + VkImageAspectFlags aspectMask; + uint32_t mipLevel; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceLayers; + +typedef struct VkBufferImageCopy { + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy; + +typedef struct VkImageCopy { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy; + +typedef struct VkBufferMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier; + +typedef struct VkImageMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier; + +typedef struct VkMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; +} VkMemoryBarrier; + +typedef struct VkDispatchIndirectCommand { + uint32_t x; + uint32_t y; + uint32_t z; +} VkDispatchIndirectCommand; + +typedef struct VkPipelineCacheHeaderVersionOne { + uint32_t headerSize; + VkPipelineCacheHeaderVersion headerVersion; + uint32_t vendorID; + uint32_t deviceID; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; +} VkPipelineCacheHeaderVersionOne; + +typedef struct VkEventCreateInfo { + VkStructureType sType; + const void* pNext; + VkEventCreateFlags flags; +} VkEventCreateInfo; + +typedef struct VkBufferViewCreateInfo { + VkStructureType sType; + const void* pNext; + VkBufferViewCreateFlags flags; + VkBuffer buffer; + VkFormat format; + VkDeviceSize offset; + VkDeviceSize range; +} VkBufferViewCreateInfo; + +typedef struct VkShaderModuleCreateInfo { + VkStructureType sType; + const void* pNext; + VkShaderModuleCreateFlags flags; + size_t codeSize; + const uint32_t* pCode; +} VkShaderModuleCreateInfo; + +typedef struct VkPipelineCacheCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCacheCreateFlags flags; + size_t initialDataSize; + const void* pInitialData; +} VkPipelineCacheCreateInfo; + +typedef struct VkSpecializationMapEntry { + uint32_t constantID; + uint32_t offset; + size_t size; +} VkSpecializationMapEntry; + +typedef struct VkSpecializationInfo { + uint32_t mapEntryCount; + const VkSpecializationMapEntry* pMapEntries; + size_t dataSize; + const void* pData; +} VkSpecializationInfo; + +typedef struct VkPipelineShaderStageCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineShaderStageCreateFlags flags; + VkShaderStageFlagBits stage; + VkShaderModule module; + const char* pName; + const VkSpecializationInfo* pSpecializationInfo; +} VkPipelineShaderStageCreateInfo; + +typedef struct VkComputePipelineCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + VkPipelineShaderStageCreateInfo stage; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkComputePipelineCreateInfo; + +typedef struct VkPushConstantRange { + VkShaderStageFlags stageFlags; + uint32_t offset; + uint32_t size; +} VkPushConstantRange; + +typedef struct VkPipelineLayoutCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineLayoutCreateFlags flags; + uint32_t setLayoutCount; + const VkDescriptorSetLayout* pSetLayouts; + uint32_t pushConstantRangeCount; + const VkPushConstantRange* pPushConstantRanges; +} VkPipelineLayoutCreateInfo; + +typedef struct VkSamplerCreateInfo { + VkStructureType sType; + const void* pNext; + VkSamplerCreateFlags flags; + VkFilter magFilter; + VkFilter minFilter; + VkSamplerMipmapMode mipmapMode; + VkSamplerAddressMode addressModeU; + VkSamplerAddressMode addressModeV; + VkSamplerAddressMode addressModeW; + float mipLodBias; + VkBool32 anisotropyEnable; + float maxAnisotropy; + VkBool32 compareEnable; + VkCompareOp compareOp; + float minLod; + float maxLod; + VkBorderColor borderColor; + VkBool32 unnormalizedCoordinates; +} VkSamplerCreateInfo; + +typedef struct VkCopyDescriptorSet { + VkStructureType sType; + const void* pNext; + VkDescriptorSet srcSet; + uint32_t srcBinding; + uint32_t srcArrayElement; + VkDescriptorSet dstSet; + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; +} VkCopyDescriptorSet; + +typedef struct VkDescriptorBufferInfo { + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize range; +} VkDescriptorBufferInfo; + +typedef struct VkDescriptorImageInfo { + VkSampler sampler; + VkImageView imageView; + VkImageLayout imageLayout; +} VkDescriptorImageInfo; + +typedef struct VkDescriptorPoolSize { + VkDescriptorType type; + uint32_t descriptorCount; +} VkDescriptorPoolSize; + +typedef struct VkDescriptorPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorPoolCreateFlags flags; + uint32_t maxSets; + uint32_t poolSizeCount; + const VkDescriptorPoolSize* pPoolSizes; +} VkDescriptorPoolCreateInfo; + +typedef struct VkDescriptorSetAllocateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorPool descriptorPool; + uint32_t descriptorSetCount; + const VkDescriptorSetLayout* pSetLayouts; +} VkDescriptorSetAllocateInfo; + +typedef struct VkDescriptorSetLayoutBinding { + uint32_t binding; + VkDescriptorType descriptorType; + uint32_t descriptorCount; + VkShaderStageFlags stageFlags; + const VkSampler* pImmutableSamplers; +} VkDescriptorSetLayoutBinding; + +typedef struct VkDescriptorSetLayoutCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorSetLayoutCreateFlags flags; + uint32_t bindingCount; + const VkDescriptorSetLayoutBinding* pBindings; +} VkDescriptorSetLayoutCreateInfo; + +typedef struct VkWriteDescriptorSet { + VkStructureType sType; + const void* pNext; + VkDescriptorSet dstSet; + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; + VkDescriptorType descriptorType; + const VkDescriptorImageInfo* pImageInfo; + const VkDescriptorBufferInfo* pBufferInfo; + const VkBufferView* pTexelBufferView; +} VkWriteDescriptorSet; + +typedef union VkClearColorValue { + float float32[4]; + int32_t int32[4]; + uint32_t uint32[4]; +} VkClearColorValue; + +typedef struct VkDrawIndexedIndirectCommand { + uint32_t indexCount; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t vertexOffset; + uint32_t firstInstance; +} VkDrawIndexedIndirectCommand; + +typedef struct VkDrawIndirectCommand { + uint32_t vertexCount; + uint32_t instanceCount; + uint32_t firstVertex; + uint32_t firstInstance; +} VkDrawIndirectCommand; + +typedef struct VkStencilOpState { + VkStencilOp failOp; + VkStencilOp passOp; + VkStencilOp depthFailOp; + VkCompareOp compareOp; + uint32_t compareMask; + uint32_t writeMask; + uint32_t reference; +} VkStencilOpState; + +typedef struct VkVertexInputAttributeDescription { + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; +} VkVertexInputAttributeDescription; + +typedef struct VkVertexInputBindingDescription { + uint32_t binding; + uint32_t stride; + VkVertexInputRate inputRate; +} VkVertexInputBindingDescription; + +typedef struct VkViewport { + float x; + float y; + float width; + float height; + float minDepth; + float maxDepth; +} VkViewport; + +typedef struct VkPipelineColorBlendAttachmentState { + VkBool32 blendEnable; + VkBlendFactor srcColorBlendFactor; + VkBlendFactor dstColorBlendFactor; + VkBlendOp colorBlendOp; + VkBlendFactor srcAlphaBlendFactor; + VkBlendFactor dstAlphaBlendFactor; + VkBlendOp alphaBlendOp; + VkColorComponentFlags colorWriteMask; +} VkPipelineColorBlendAttachmentState; + +typedef struct VkPipelineColorBlendStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineColorBlendStateCreateFlags flags; + VkBool32 logicOpEnable; + VkLogicOp logicOp; + uint32_t attachmentCount; + const VkPipelineColorBlendAttachmentState* pAttachments; + float blendConstants[4]; +} VkPipelineColorBlendStateCreateInfo; + +typedef struct VkPipelineDepthStencilStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineDepthStencilStateCreateFlags flags; + VkBool32 depthTestEnable; + VkBool32 depthWriteEnable; + VkCompareOp depthCompareOp; + VkBool32 depthBoundsTestEnable; + VkBool32 stencilTestEnable; + VkStencilOpState front; + VkStencilOpState back; + float minDepthBounds; + float maxDepthBounds; +} VkPipelineDepthStencilStateCreateInfo; + +typedef struct VkPipelineDynamicStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineDynamicStateCreateFlags flags; + uint32_t dynamicStateCount; + const VkDynamicState* pDynamicStates; +} VkPipelineDynamicStateCreateInfo; + +typedef struct VkPipelineInputAssemblyStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineInputAssemblyStateCreateFlags flags; + VkPrimitiveTopology topology; + VkBool32 primitiveRestartEnable; +} VkPipelineInputAssemblyStateCreateInfo; + +typedef struct VkPipelineMultisampleStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineMultisampleStateCreateFlags flags; + VkSampleCountFlagBits rasterizationSamples; + VkBool32 sampleShadingEnable; + float minSampleShading; + const VkSampleMask* pSampleMask; + VkBool32 alphaToCoverageEnable; + VkBool32 alphaToOneEnable; +} VkPipelineMultisampleStateCreateInfo; + +typedef struct VkPipelineRasterizationStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationStateCreateFlags flags; + VkBool32 depthClampEnable; + VkBool32 rasterizerDiscardEnable; + VkPolygonMode polygonMode; + VkCullModeFlags cullMode; + VkFrontFace frontFace; + VkBool32 depthBiasEnable; + float depthBiasConstantFactor; + float depthBiasClamp; + float depthBiasSlopeFactor; + float lineWidth; +} VkPipelineRasterizationStateCreateInfo; + +typedef struct VkPipelineTessellationStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineTessellationStateCreateFlags flags; + uint32_t patchControlPoints; +} VkPipelineTessellationStateCreateInfo; + +typedef struct VkPipelineVertexInputStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineVertexInputStateCreateFlags flags; + uint32_t vertexBindingDescriptionCount; + const VkVertexInputBindingDescription* pVertexBindingDescriptions; + uint32_t vertexAttributeDescriptionCount; + const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; +} VkPipelineVertexInputStateCreateInfo; + +typedef struct VkPipelineViewportStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineViewportStateCreateFlags flags; + uint32_t viewportCount; + const VkViewport* pViewports; + uint32_t scissorCount; + const VkRect2D* pScissors; +} VkPipelineViewportStateCreateInfo; + +typedef struct VkGraphicsPipelineCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; + const VkPipelineViewportStateCreateInfo* pViewportState; + const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + const VkPipelineDynamicStateCreateInfo* pDynamicState; + VkPipelineLayout layout; + VkRenderPass renderPass; + uint32_t subpass; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkGraphicsPipelineCreateInfo; + +typedef struct VkAttachmentDescription { + VkAttachmentDescriptionFlags flags; + VkFormat format; + VkSampleCountFlagBits samples; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkAttachmentLoadOp stencilLoadOp; + VkAttachmentStoreOp stencilStoreOp; + VkImageLayout initialLayout; + VkImageLayout finalLayout; +} VkAttachmentDescription; + +typedef struct VkAttachmentReference { + uint32_t attachment; + VkImageLayout layout; +} VkAttachmentReference; + +typedef struct VkFramebufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkFramebufferCreateFlags flags; + VkRenderPass renderPass; + uint32_t attachmentCount; + const VkImageView* pAttachments; + uint32_t width; + uint32_t height; + uint32_t layers; +} VkFramebufferCreateInfo; + +typedef struct VkSubpassDependency { + uint32_t srcSubpass; + uint32_t dstSubpass; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkDependencyFlags dependencyFlags; +} VkSubpassDependency; + +typedef struct VkSubpassDescription { + VkSubpassDescriptionFlags flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t inputAttachmentCount; + const VkAttachmentReference* pInputAttachments; + uint32_t colorAttachmentCount; + const VkAttachmentReference* pColorAttachments; + const VkAttachmentReference* pResolveAttachments; + const VkAttachmentReference* pDepthStencilAttachment; + uint32_t preserveAttachmentCount; + const uint32_t* pPreserveAttachments; +} VkSubpassDescription; + +typedef struct VkRenderPassCreateInfo { + VkStructureType sType; + const void* pNext; + VkRenderPassCreateFlags flags; + uint32_t attachmentCount; + const VkAttachmentDescription* pAttachments; + uint32_t subpassCount; + const VkSubpassDescription* pSubpasses; + uint32_t dependencyCount; + const VkSubpassDependency* pDependencies; +} VkRenderPassCreateInfo; + +typedef struct VkClearDepthStencilValue { + float depth; + uint32_t stencil; +} VkClearDepthStencilValue; + +typedef struct VkClearRect { + VkRect2D rect; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkClearRect; + +typedef union VkClearValue { + VkClearColorValue color; + VkClearDepthStencilValue depthStencil; +} VkClearValue; + +typedef struct VkClearAttachment { + VkImageAspectFlags aspectMask; + uint32_t colorAttachment; + VkClearValue clearValue; +} VkClearAttachment; + +typedef struct VkImageBlit { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit; + +typedef struct VkImageResolve { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve; + +typedef struct VkRenderPassBeginInfo { + VkStructureType sType; + const void* pNext; + VkRenderPass renderPass; + VkFramebuffer framebuffer; + VkRect2D renderArea; + uint32_t clearValueCount; + const VkClearValue* pClearValues; +} VkRenderPassBeginInfo; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance); +typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetDeviceProcAddr)(VkDevice device, const char* pName); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice); +typedef void (VKAPI_PTR *PFN_vkDestroyDevice)(VkDevice device, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceExtensionProperties)(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceLayerProperties)(uint32_t* pPropertyCount, VkLayerProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceLayerProperties)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkQueueWaitIdle)(VkQueue queue); +typedef VkResult (VKAPI_PTR *PFN_vkDeviceWaitIdle)(VkDevice device); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateMemory)(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory); +typedef void (VKAPI_PTR *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData); +typedef void (VKAPI_PTR *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory memory); +typedef VkResult (VKAPI_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges); +typedef VkResult (VKAPI_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges); +typedef void (VKAPI_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes); +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory)(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory)(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements)(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkQueueBindSparse)(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef void (VKAPI_PTR *PFN_vkDestroyFence)(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceStatus)(VkDevice device, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore); +typedef void (VKAPI_PTR *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool); +typedef void (VKAPI_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer); +typedef void (VKAPI_PTR *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage); +typedef void (VKAPI_PTR *PFN_vkDestroyImage)(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout); +typedef VkResult (VKAPI_PTR *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView); +typedef void (VKAPI_PTR *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool); +typedef void (VKAPI_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers); +typedef void (VKAPI_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); +typedef VkResult (VKAPI_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo); +typedef VkResult (VKAPI_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer); +typedef VkResult (VKAPI_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); +typedef void (VKAPI_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query); +typedef void (VKAPI_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query); +typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); +typedef VkResult (VKAPI_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent); +typedef void (VKAPI_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView); +typedef void (VKAPI_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule); +typedef void (VKAPI_PTR *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache); +typedef void (VKAPI_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches); +typedef VkResult (VKAPI_PTR *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef void (VKAPI_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler); +typedef void (VKAPI_PTR *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorSetLayout)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorSetLayout)(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorPool)(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateDescriptorSets)(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets); +typedef VkResult (VKAPI_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); +typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); +typedef void (VKAPI_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues); +typedef VkResult (VKAPI_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer); +typedef void (VKAPI_PTR *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor); +typedef void (VKAPI_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer commandBuffer, const float blendConstants[4]); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference); +typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter); +typedef void (VKAPI_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); +typedef void (VKAPI_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance); + +VKAPI_ATTR void VKAPI_CALL vkDestroyInstance( + VkInstance instance, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices( + VkInstance instance, + uint32_t* pPhysicalDeviceCount, + VkPhysicalDevice* pPhysicalDevices); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures* pFeatures); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties* pFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkImageFormatProperties* pImageFormatProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties* pQueueFamilyProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties* pMemoryProperties); + +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr( + VkInstance instance, + const char* pName); + +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr( + VkDevice device, + const char* pName); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice( + VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDevice( + VkDevice device, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties( + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties( + VkPhysicalDevice physicalDevice, + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties( + uint32_t* pPropertyCount, + VkLayerProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkLayerProperties* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue( + VkDevice device, + uint32_t queueFamilyIndex, + uint32_t queueIndex, + VkQueue* pQueue); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo* pSubmits, + VkFence fence); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle( + VkQueue queue); + +VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle( + VkDevice device); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory( + VkDevice device, + const VkMemoryAllocateInfo* pAllocateInfo, + const VkAllocationCallbacks* pAllocator, + VkDeviceMemory* pMemory); + +VKAPI_ATTR void VKAPI_CALL vkFreeMemory( + VkDevice device, + VkDeviceMemory memory, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory( + VkDevice device, + VkDeviceMemory memory, + VkDeviceSize offset, + VkDeviceSize size, + VkMemoryMapFlags flags, + void** ppData); + +VKAPI_ATTR void VKAPI_CALL vkUnmapMemory( + VkDevice device, + VkDeviceMemory memory); + +VKAPI_ATTR VkResult VKAPI_CALL vkFlushMappedMemoryRanges( + VkDevice device, + uint32_t memoryRangeCount, + const VkMappedMemoryRange* pMemoryRanges); + +VKAPI_ATTR VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges( + VkDevice device, + uint32_t memoryRangeCount, + const VkMappedMemoryRange* pMemoryRanges); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceMemoryCommitment( + VkDevice device, + VkDeviceMemory memory, + VkDeviceSize* pCommittedMemoryInBytes); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory( + VkDevice device, + VkBuffer buffer, + VkDeviceMemory memory, + VkDeviceSize memoryOffset); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory( + VkDevice device, + VkImage image, + VkDeviceMemory memory, + VkDeviceSize memoryOffset); + +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements( + VkDevice device, + VkBuffer buffer, + VkMemoryRequirements* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements( + VkDevice device, + VkImage image, + VkMemoryRequirements* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements( + VkDevice device, + VkImage image, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements* pSparseMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkSampleCountFlagBits samples, + VkImageUsageFlags usage, + VkImageTiling tiling, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse( + VkQueue queue, + uint32_t bindInfoCount, + const VkBindSparseInfo* pBindInfo, + VkFence fence); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence( + VkDevice device, + const VkFenceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); + +VKAPI_ATTR void VKAPI_CALL vkDestroyFence( + VkDevice device, + VkFence fence, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetFences( + VkDevice device, + uint32_t fenceCount, + const VkFence* pFences); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus( + VkDevice device, + VkFence fence); + +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences( + VkDevice device, + uint32_t fenceCount, + const VkFence* pFences, + VkBool32 waitAll, + uint64_t timeout); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore( + VkDevice device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSemaphore* pSemaphore); + +VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore( + VkDevice device, + VkSemaphore semaphore, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool( + VkDevice device, + const VkQueryPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkQueryPool* pQueryPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool( + VkDevice device, + VkQueryPool queryPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + size_t dataSize, + void* pData, + VkDeviceSize stride, + VkQueryResultFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer( + VkDevice device, + const VkBufferCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBuffer* pBuffer); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer( + VkDevice device, + VkBuffer buffer, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage( + VkDevice device, + const VkImageCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImage* pImage); + +VKAPI_ATTR void VKAPI_CALL vkDestroyImage( + VkDevice device, + VkImage image, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout( + VkDevice device, + VkImage image, + const VkImageSubresource* pSubresource, + VkSubresourceLayout* pLayout); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView( + VkDevice device, + const VkImageViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImageView* pView); + +VKAPI_ATTR void VKAPI_CALL vkDestroyImageView( + VkDevice device, + VkImageView imageView, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool( + VkDevice device, + const VkCommandPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCommandPool* pCommandPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool( + VkDevice device, + VkCommandPool commandPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolResetFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers( + VkDevice device, + const VkCommandBufferAllocateInfo* pAllocateInfo, + VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers( + VkDevice device, + VkCommandPool commandPool, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer( + VkCommandBuffer commandBuffer, + const VkCommandBufferBeginInfo* pBeginInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer( + VkCommandBuffer commandBuffer, + VkCommandBufferResetFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer( + VkCommandBuffer commandBuffer, + VkBuffer srcBuffer, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage( + VkCommandBuffer commandBuffer, + VkBuffer srcBuffer, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkBufferImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer( + VkCommandBuffer commandBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize dataSize, + const void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer( + VkCommandBuffer commandBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize size, + uint32_t data); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp( + VkCommandBuffer commandBuffer, + VkPipelineStageFlagBits pipelineStage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize stride, + VkQueryResultFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( + VkCommandBuffer commandBuffer, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent( + VkDevice device, + const VkEventCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkEvent* pEvent); + +VKAPI_ATTR void VKAPI_CALL vkDestroyEvent( + VkDevice device, + VkEvent event, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView( + VkDevice device, + const VkBufferViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferView* pView); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView( + VkDevice device, + VkBufferView bufferView, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule( + VkDevice device, + const VkShaderModuleCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkShaderModule* pShaderModule); + +VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule( + VkDevice device, + VkShaderModule shaderModule, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache( + VkDevice device, + const VkPipelineCacheCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPipelineCache* pPipelineCache); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache( + VkDevice device, + VkPipelineCache pipelineCache, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData( + VkDevice device, + VkPipelineCache pipelineCache, + size_t* pDataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches( + VkDevice device, + VkPipelineCache dstCache, + uint32_t srcCacheCount, + const VkPipelineCache* pSrcCaches); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkComputePipelineCreateInfo* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline( + VkDevice device, + VkPipeline pipeline, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout( + VkDevice device, + const VkPipelineLayoutCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPipelineLayout* pPipelineLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout( + VkDevice device, + VkPipelineLayout pipelineLayout, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler( + VkDevice device, + const VkSamplerCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSampler* pSampler); + +VKAPI_ATTR void VKAPI_CALL vkDestroySampler( + VkDevice device, + VkSampler sampler, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorSetLayout* pSetLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout( + VkDevice device, + VkDescriptorSetLayout descriptorSetLayout, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool( + VkDevice device, + const VkDescriptorPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorPool* pDescriptorPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool( + VkDevice device, + VkDescriptorPool descriptorPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool( + VkDevice device, + VkDescriptorPool descriptorPool, + VkDescriptorPoolResetFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets( + VkDevice device, + const VkDescriptorSetAllocateInfo* pAllocateInfo, + VkDescriptorSet* pDescriptorSets); + +VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets( + VkDevice device, + VkDescriptorPool descriptorPool, + uint32_t descriptorSetCount, + const VkDescriptorSet* pDescriptorSets); + +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets( + VkDevice device, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites, + uint32_t descriptorCopyCount, + const VkCopyDescriptorSet* pDescriptorCopies); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t firstSet, + uint32_t descriptorSetCount, + const VkDescriptorSet* pDescriptorSets, + uint32_t dynamicOffsetCount, + const uint32_t* pDynamicOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage( + VkCommandBuffer commandBuffer, + VkImage image, + VkImageLayout imageLayout, + const VkClearColorValue* pColor, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatch( + VkCommandBuffer commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants( + VkCommandBuffer commandBuffer, + VkPipelineLayout layout, + VkShaderStageFlags stageFlags, + uint32_t offset, + uint32_t size, + const void* pValues); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkGraphicsPipelineCreateInfo* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer( + VkDevice device, + const VkFramebufferCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkFramebuffer* pFramebuffer); + +VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer( + VkDevice device, + VkFramebuffer framebuffer, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass( + VkDevice device, + const VkRenderPassCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); + +VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass( + VkDevice device, + VkRenderPass renderPass, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity( + VkDevice device, + VkRenderPass renderPass, + VkExtent2D* pGranularity); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewport* pViewports); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor( + VkCommandBuffer commandBuffer, + uint32_t firstScissor, + uint32_t scissorCount, + const VkRect2D* pScissors); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth( + VkCommandBuffer commandBuffer, + float lineWidth); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias( + VkCommandBuffer commandBuffer, + float depthBiasConstantFactor, + float depthBiasClamp, + float depthBiasSlopeFactor); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants( + VkCommandBuffer commandBuffer, + const float blendConstants[4]); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds( + VkCommandBuffer commandBuffer, + float minDepthBounds, + float maxDepthBounds); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t compareMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t writeMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t reference); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkIndexType indexType); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdDraw( + VkCommandBuffer commandBuffer, + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t firstVertex, + uint32_t firstInstance); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed( + VkCommandBuffer commandBuffer, + uint32_t indexCount, + uint32_t instanceCount, + uint32_t firstIndex, + int32_t vertexOffset, + uint32_t firstInstance); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageBlit* pRegions, + VkFilter filter); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage( + VkCommandBuffer commandBuffer, + VkImage image, + VkImageLayout imageLayout, + const VkClearDepthStencilValue* pDepthStencil, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments( + VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkClearAttachment* pAttachments, + uint32_t rectCount, + const VkClearRect* pRects); + +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageResolve* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + VkSubpassContents contents); + +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass( + VkCommandBuffer commandBuffer, + VkSubpassContents contents); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass( + VkCommandBuffer commandBuffer); +#endif + + +// VK_VERSION_1_1 is a preprocessor guard. Do not pass it to API calls. +#define VK_VERSION_1_1 1 +// Vulkan 1.1 version number +#define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)// Patch version should always be set to 0 + +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion) +#define VK_MAX_DEVICE_GROUP_SIZE 32U +#define VK_LUID_SIZE 8U +#define VK_QUEUE_FAMILY_EXTERNAL (~1U) + +typedef enum VkPointClippingBehavior { + VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0, + VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1, + VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, + VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, + VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF +} VkPointClippingBehavior; + +typedef enum VkDescriptorUpdateTemplateType { + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS = 1, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorUpdateTemplateType; + +typedef enum VkSamplerYcbcrModelConversion { + 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, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF +} VkSamplerYcbcrModelConversion; + +typedef enum VkSamplerYcbcrRange { + VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0, + VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1, + VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL, + VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, + VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerYcbcrRange; + +typedef enum VkChromaLocation { + VK_CHROMA_LOCATION_COSITED_EVEN = 0, + VK_CHROMA_LOCATION_MIDPOINT = 1, + VK_CHROMA_LOCATION_COSITED_EVEN_KHR = VK_CHROMA_LOCATION_COSITED_EVEN, + VK_CHROMA_LOCATION_MIDPOINT_KHR = VK_CHROMA_LOCATION_MIDPOINT, + VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF +} VkChromaLocation; + +typedef enum VkTessellationDomainOrigin { + VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0, + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1, + VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF +} VkTessellationDomainOrigin; + +typedef enum VkSubgroupFeatureFlagBits { + VK_SUBGROUP_FEATURE_BASIC_BIT = 0x00000001, + VK_SUBGROUP_FEATURE_VOTE_BIT = 0x00000002, + VK_SUBGROUP_FEATURE_ARITHMETIC_BIT = 0x00000004, + VK_SUBGROUP_FEATURE_BALLOT_BIT = 0x00000008, + VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 0x00000010, + VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0x00000020, + VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0x00000040, + VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080, + VK_SUBGROUP_FEATURE_ROTATE_BIT = 0x00000200, + VK_SUBGROUP_FEATURE_ROTATE_CLUSTERED_BIT = 0x00000400, + VK_SUBGROUP_FEATURE_PARTITIONED_BIT_EXT = 0x00000100, + VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV = VK_SUBGROUP_FEATURE_PARTITIONED_BIT_EXT, + VK_SUBGROUP_FEATURE_ROTATE_BIT_KHR = VK_SUBGROUP_FEATURE_ROTATE_BIT, + VK_SUBGROUP_FEATURE_ROTATE_CLUSTERED_BIT_KHR = VK_SUBGROUP_FEATURE_ROTATE_CLUSTERED_BIT, + VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubgroupFeatureFlagBits; +typedef VkFlags VkSubgroupFeatureFlags; + +typedef enum VkPeerMemoryFeatureFlagBits { + VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0x00000001, + VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0x00000002, + VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0x00000004, + VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0x00000008, + VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT, + VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_DST_BIT, + VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT, + VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT, + VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPeerMemoryFeatureFlagBits; +typedef VkFlags VkPeerMemoryFeatureFlags; + +typedef enum VkMemoryAllocateFlagBits { + VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 0x00000002, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000004, + VK_MEMORY_ALLOCATE_ZERO_INITIALIZE_BIT_EXT = 0x00000008, + VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, + VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryAllocateFlagBits; +typedef VkFlags VkMemoryAllocateFlags; +typedef VkFlags VkCommandPoolTrimFlags; + +typedef enum VkExternalMemoryHandleTypeFlagBits { + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 0x00000008, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 0x00000010, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0x00000020, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0x00000040, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT = 0x00000200, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID = 0x00000400, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT = 0x00000080, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA = 0x00000800, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV = 0x00001000, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OH_NATIVE_BUFFER_BIT_OHOS = 0x00008000, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX = 0x00004000, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT = 0x00010000, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT = 0x00020000, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT = 0x00040000, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalMemoryHandleTypeFlagBits; +typedef VkFlags VkExternalMemoryHandleTypeFlags; + +typedef enum VkExternalMemoryFeatureFlagBits { + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 0x00000001, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 0x00000002, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 0x00000004, + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT, + VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalMemoryFeatureFlagBits; +typedef VkFlags VkExternalMemoryFeatureFlags; + +typedef enum VkExternalFenceHandleTypeFlagBits { + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000008, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalFenceHandleTypeFlagBits; +typedef VkFlags VkExternalFenceHandleTypeFlags; + +typedef enum VkExternalFenceFeatureFlagBits { + VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 0x00000001, + VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 0x00000002, + VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT, + VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT, + VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalFenceFeatureFlagBits; +typedef VkFlags VkExternalFenceFeatureFlags; + +typedef enum VkFenceImportFlagBits { + VK_FENCE_IMPORT_TEMPORARY_BIT = 0x00000001, + VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = VK_FENCE_IMPORT_TEMPORARY_BIT, + VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFenceImportFlagBits; +typedef VkFlags VkFenceImportFlags; + +typedef enum VkSemaphoreImportFlagBits { + VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001, + VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, + VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreImportFlagBits; +typedef VkFlags VkSemaphoreImportFlags; + +typedef enum VkExternalSemaphoreHandleTypeFlagBits { + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA = 0x00000080, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalSemaphoreHandleTypeFlagBits; +typedef VkFlags VkExternalSemaphoreHandleTypeFlags; + +typedef enum VkExternalSemaphoreFeatureFlagBits { + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 0x00000001, + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 0x00000002, + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT, + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT, + VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalSemaphoreFeatureFlagBits; +typedef VkFlags VkExternalSemaphoreFeatureFlags; +typedef VkFlags VkDescriptorUpdateTemplateCreateFlags; +typedef struct VkBindBufferMemoryInfo { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindBufferMemoryInfo; + +typedef struct VkBindImageMemoryInfo { + VkStructureType sType; + const void* pNext; + VkImage image; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindImageMemoryInfo; + +typedef struct VkMemoryDedicatedRequirements { + VkStructureType sType; + void* pNext; + VkBool32 prefersDedicatedAllocation; + VkBool32 requiresDedicatedAllocation; +} VkMemoryDedicatedRequirements; + +typedef struct VkMemoryDedicatedAllocateInfo { + VkStructureType sType; + const void* pNext; + VkImage image; + VkBuffer buffer; +} VkMemoryDedicatedAllocateInfo; + +typedef struct VkMemoryAllocateFlagsInfo { + VkStructureType sType; + const void* pNext; + VkMemoryAllocateFlags flags; + uint32_t deviceMask; +} VkMemoryAllocateFlagsInfo; + +typedef struct VkDeviceGroupCommandBufferBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceMask; +} VkDeviceGroupCommandBufferBeginInfo; + +typedef struct VkDeviceGroupSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const uint32_t* pWaitSemaphoreDeviceIndices; + uint32_t commandBufferCount; + const uint32_t* pCommandBufferDeviceMasks; + uint32_t signalSemaphoreCount; + const uint32_t* pSignalSemaphoreDeviceIndices; +} VkDeviceGroupSubmitInfo; + +typedef struct VkDeviceGroupBindSparseInfo { + VkStructureType sType; + const void* pNext; + uint32_t resourceDeviceIndex; + uint32_t memoryDeviceIndex; +} VkDeviceGroupBindSparseInfo; + +typedef struct VkBindBufferMemoryDeviceGroupInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindBufferMemoryDeviceGroupInfo; + +typedef struct VkBindImageMemoryDeviceGroupInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; + uint32_t splitInstanceBindRegionCount; + const VkRect2D* pSplitInstanceBindRegions; +} VkBindImageMemoryDeviceGroupInfo; + +typedef struct VkPhysicalDeviceGroupProperties { + VkStructureType sType; + void* pNext; + uint32_t physicalDeviceCount; + VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE]; + VkBool32 subsetAllocation; +} VkPhysicalDeviceGroupProperties; + +typedef struct VkDeviceGroupDeviceCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t physicalDeviceCount; + const VkPhysicalDevice* pPhysicalDevices; +} VkDeviceGroupDeviceCreateInfo; + +typedef struct VkBufferMemoryRequirementsInfo2 { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; +} VkBufferMemoryRequirementsInfo2; + +typedef struct VkImageMemoryRequirementsInfo2 { + VkStructureType sType; + const void* pNext; + VkImage image; +} VkImageMemoryRequirementsInfo2; + +typedef struct VkImageSparseMemoryRequirementsInfo2 { + VkStructureType sType; + const void* pNext; + VkImage image; +} VkImageSparseMemoryRequirementsInfo2; + +typedef struct VkMemoryRequirements2 { + VkStructureType sType; + void* pNext; + VkMemoryRequirements memoryRequirements; +} VkMemoryRequirements2; + +typedef struct VkSparseImageMemoryRequirements2 { + VkStructureType sType; + void* pNext; + VkSparseImageMemoryRequirements memoryRequirements; +} VkSparseImageMemoryRequirements2; + +typedef struct VkPhysicalDeviceFeatures2 { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceFeatures features; +} VkPhysicalDeviceFeatures2; + +typedef struct VkPhysicalDeviceProperties2 { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceProperties properties; +} VkPhysicalDeviceProperties2; + +typedef struct VkFormatProperties2 { + VkStructureType sType; + void* pNext; + VkFormatProperties formatProperties; +} VkFormatProperties2; + +typedef struct VkImageFormatProperties2 { + VkStructureType sType; + void* pNext; + VkImageFormatProperties imageFormatProperties; +} VkImageFormatProperties2; + +typedef struct VkPhysicalDeviceImageFormatInfo2 { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkImageType type; + VkImageTiling tiling; + VkImageUsageFlags usage; + VkImageCreateFlags flags; +} VkPhysicalDeviceImageFormatInfo2; + +typedef struct VkQueueFamilyProperties2 { + VkStructureType sType; + void* pNext; + VkQueueFamilyProperties queueFamilyProperties; +} VkQueueFamilyProperties2; + +typedef struct VkPhysicalDeviceMemoryProperties2 { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceMemoryProperties memoryProperties; +} VkPhysicalDeviceMemoryProperties2; + +typedef struct VkSparseImageFormatProperties2 { + VkStructureType sType; + void* pNext; + VkSparseImageFormatProperties properties; +} VkSparseImageFormatProperties2; + +typedef struct VkPhysicalDeviceSparseImageFormatInfo2 { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkImageType type; + VkSampleCountFlagBits samples; + VkImageUsageFlags usage; + VkImageTiling tiling; +} VkPhysicalDeviceSparseImageFormatInfo2; + +typedef struct VkImageViewUsageCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageUsageFlags usage; +} VkImageViewUsageCreateInfo; + +typedef struct VkPhysicalDeviceProtectedMemoryFeatures { + VkStructureType sType; + void* pNext; + VkBool32 protectedMemory; +} VkPhysicalDeviceProtectedMemoryFeatures; + +typedef struct VkPhysicalDeviceProtectedMemoryProperties { + VkStructureType sType; + void* pNext; + VkBool32 protectedNoFault; +} VkPhysicalDeviceProtectedMemoryProperties; + +typedef struct VkDeviceQueueInfo2 { + VkStructureType sType; + const void* pNext; + VkDeviceQueueCreateFlags flags; + uint32_t queueFamilyIndex; + uint32_t queueIndex; +} VkDeviceQueueInfo2; + +typedef struct VkProtectedSubmitInfo { + VkStructureType sType; + const void* pNext; + VkBool32 protectedSubmit; +} VkProtectedSubmitInfo; + +typedef struct VkBindImagePlaneMemoryInfo { + VkStructureType sType; + const void* pNext; + VkImageAspectFlagBits planeAspect; +} VkBindImagePlaneMemoryInfo; + +typedef struct VkImagePlaneMemoryRequirementsInfo { + VkStructureType sType; + const void* pNext; + VkImageAspectFlagBits planeAspect; +} VkImagePlaneMemoryRequirementsInfo; + +typedef struct VkExternalMemoryProperties { + VkExternalMemoryFeatureFlags externalMemoryFeatures; + VkExternalMemoryHandleTypeFlags exportFromImportedHandleTypes; + VkExternalMemoryHandleTypeFlags compatibleHandleTypes; +} VkExternalMemoryProperties; + +typedef struct VkPhysicalDeviceExternalImageFormatInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalImageFormatInfo; + +typedef struct VkExternalImageFormatProperties { + VkStructureType sType; + void* pNext; + VkExternalMemoryProperties externalMemoryProperties; +} VkExternalImageFormatProperties; + +typedef struct VkPhysicalDeviceExternalBufferInfo { + VkStructureType sType; + const void* pNext; + VkBufferCreateFlags flags; + VkBufferUsageFlags usage; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalBufferInfo; + +typedef struct VkExternalBufferProperties { + VkStructureType sType; + void* pNext; + VkExternalMemoryProperties externalMemoryProperties; +} VkExternalBufferProperties; + +typedef struct VkPhysicalDeviceIDProperties { + VkStructureType sType; + void* pNext; + uint8_t deviceUUID[VK_UUID_SIZE]; + uint8_t driverUUID[VK_UUID_SIZE]; + uint8_t deviceLUID[VK_LUID_SIZE]; + uint32_t deviceNodeMask; + VkBool32 deviceLUIDValid; +} VkPhysicalDeviceIDProperties; + +typedef struct VkExternalMemoryImageCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExternalMemoryImageCreateInfo; + +typedef struct VkExternalMemoryBufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExternalMemoryBufferCreateInfo; + +typedef struct VkExportMemoryAllocateInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExportMemoryAllocateInfo; + +typedef struct VkPhysicalDeviceExternalFenceInfo { + VkStructureType sType; + const void* pNext; + VkExternalFenceHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalFenceInfo; + +typedef struct VkExternalFenceProperties { + VkStructureType sType; + void* pNext; + VkExternalFenceHandleTypeFlags exportFromImportedHandleTypes; + VkExternalFenceHandleTypeFlags compatibleHandleTypes; + VkExternalFenceFeatureFlags externalFenceFeatures; +} VkExternalFenceProperties; + +typedef struct VkExportFenceCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalFenceHandleTypeFlags handleTypes; +} VkExportFenceCreateInfo; + +typedef struct VkExportSemaphoreCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalSemaphoreHandleTypeFlags handleTypes; +} VkExportSemaphoreCreateInfo; + +typedef struct VkPhysicalDeviceExternalSemaphoreInfo { + VkStructureType sType; + const void* pNext; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalSemaphoreInfo; + +typedef struct VkExternalSemaphoreProperties { + VkStructureType sType; + void* pNext; + VkExternalSemaphoreHandleTypeFlags exportFromImportedHandleTypes; + VkExternalSemaphoreHandleTypeFlags compatibleHandleTypes; + VkExternalSemaphoreFeatureFlags externalSemaphoreFeatures; +} VkExternalSemaphoreProperties; + +typedef struct VkPhysicalDeviceSubgroupProperties { + VkStructureType sType; + void* pNext; + uint32_t subgroupSize; + VkShaderStageFlags supportedStages; + VkSubgroupFeatureFlags supportedOperations; + VkBool32 quadOperationsInAllStages; +} VkPhysicalDeviceSubgroupProperties; + +typedef struct VkPhysicalDevice16BitStorageFeatures { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer16BitAccess; + VkBool32 uniformAndStorageBuffer16BitAccess; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; +} VkPhysicalDevice16BitStorageFeatures; + +typedef struct VkPhysicalDeviceVariablePointersFeatures { + VkStructureType sType; + void* pNext; + VkBool32 variablePointersStorageBuffer; + VkBool32 variablePointers; +} VkPhysicalDeviceVariablePointersFeatures; + +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeatures; + +typedef struct VkDescriptorUpdateTemplateEntry { + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; + VkDescriptorType descriptorType; + size_t offset; + size_t stride; +} VkDescriptorUpdateTemplateEntry; + +typedef struct VkDescriptorUpdateTemplateCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorUpdateTemplateCreateFlags flags; + uint32_t descriptorUpdateEntryCount; + const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries; + VkDescriptorUpdateTemplateType templateType; + VkDescriptorSetLayout descriptorSetLayout; + VkPipelineBindPoint pipelineBindPoint; + VkPipelineLayout pipelineLayout; + uint32_t set; +} VkDescriptorUpdateTemplateCreateInfo; + +typedef struct VkPhysicalDeviceMaintenance3Properties { + VkStructureType sType; + void* pNext; + uint32_t maxPerSetDescriptors; + VkDeviceSize maxMemoryAllocationSize; +} VkPhysicalDeviceMaintenance3Properties; + +typedef struct VkDescriptorSetLayoutSupport { + VkStructureType sType; + void* pNext; + VkBool32 supported; +} VkDescriptorSetLayoutSupport; + +typedef struct VkSamplerYcbcrConversionCreateInfo { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkSamplerYcbcrModelConversion ycbcrModel; + VkSamplerYcbcrRange ycbcrRange; + VkComponentMapping components; + VkChromaLocation xChromaOffset; + VkChromaLocation yChromaOffset; + VkFilter chromaFilter; + VkBool32 forceExplicitReconstruction; +} VkSamplerYcbcrConversionCreateInfo; + +typedef struct VkSamplerYcbcrConversionInfo { + VkStructureType sType; + const void* pNext; + VkSamplerYcbcrConversion conversion; +} VkSamplerYcbcrConversionInfo; + +typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures { + VkStructureType sType; + void* pNext; + VkBool32 samplerYcbcrConversion; +} VkPhysicalDeviceSamplerYcbcrConversionFeatures; + +typedef struct VkSamplerYcbcrConversionImageFormatProperties { + VkStructureType sType; + void* pNext; + uint32_t combinedImageSamplerDescriptorCount; +} VkSamplerYcbcrConversionImageFormatProperties; + +typedef struct VkDeviceGroupRenderPassBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceMask; + uint32_t deviceRenderAreaCount; + const VkRect2D* pDeviceRenderAreas; +} VkDeviceGroupRenderPassBeginInfo; + +typedef struct VkPhysicalDevicePointClippingProperties { + VkStructureType sType; + void* pNext; + VkPointClippingBehavior pointClippingBehavior; +} VkPhysicalDevicePointClippingProperties; + +typedef struct VkInputAttachmentAspectReference { + uint32_t subpass; + uint32_t inputAttachmentIndex; + VkImageAspectFlags aspectMask; +} VkInputAttachmentAspectReference; + +typedef struct VkRenderPassInputAttachmentAspectCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t aspectReferenceCount; + const VkInputAttachmentAspectReference* pAspectReferences; +} VkRenderPassInputAttachmentAspectCreateInfo; + +typedef struct VkPipelineTessellationDomainOriginStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkTessellationDomainOrigin domainOrigin; +} VkPipelineTessellationDomainOriginStateCreateInfo; + +typedef struct VkRenderPassMultiviewCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t subpassCount; + const uint32_t* pViewMasks; + uint32_t dependencyCount; + const int32_t* pViewOffsets; + uint32_t correlationMaskCount; + const uint32_t* pCorrelationMasks; +} VkRenderPassMultiviewCreateInfo; + +typedef struct VkPhysicalDeviceMultiviewFeatures { + VkStructureType sType; + void* pNext; + VkBool32 multiview; + VkBool32 multiviewGeometryShader; + VkBool32 multiviewTessellationShader; +} VkPhysicalDeviceMultiviewFeatures; + +typedef struct VkPhysicalDeviceMultiviewProperties { + VkStructureType sType; + void* pNext; + uint32_t maxMultiviewViewCount; + uint32_t maxMultiviewInstanceIndex; +} VkPhysicalDeviceMultiviewProperties; + +typedef struct VkPhysicalDeviceShaderDrawParametersFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderDrawParameters; +} VkPhysicalDeviceShaderDrawParametersFeatures; + +typedef VkPhysicalDeviceShaderDrawParametersFeatures VkPhysicalDeviceShaderDrawParameterFeatures; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t* pApiVersion); +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); +typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer commandBuffer, uint32_t deviceMask); +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroups)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkTrimCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); +typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue2)(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFenceProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); +typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion( + uint32_t* pApiVersion); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2( + VkDevice device, + uint32_t bindInfoCount, + const VkBindBufferMemoryInfo* pBindInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2( + VkDevice device, + uint32_t bindInfoCount, + const VkBindImageMemoryInfo* pBindInfos); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeatures( + VkDevice device, + uint32_t heapIndex, + uint32_t localDeviceIndex, + uint32_t remoteDeviceIndex, + VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask( + VkCommandBuffer commandBuffer, + uint32_t deviceMask); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups( + VkInstance instance, + uint32_t* pPhysicalDeviceGroupCount, + VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2( + VkDevice device, + const VkImageMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2( + VkDevice device, + const VkBufferMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2( + VkDevice device, + const VkImageSparseMemoryRequirementsInfo2* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures2* pFeatures); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties2* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties2* pFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, + VkImageFormatProperties2* pImageFormatProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties2* pQueueFamilyProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties2* pMemoryProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties2* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkTrimCommandPool( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolTrimFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue2( + VkDevice device, + const VkDeviceQueueInfo2* pQueueInfo, + VkQueue* pQueue); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, + VkExternalBufferProperties* pExternalBufferProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, + VkExternalFenceProperties* pExternalFenceProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, + VkExternalSemaphoreProperties* pExternalSemaphoreProperties); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase( + VkCommandBuffer commandBuffer, + uint32_t baseGroupX, + uint32_t baseGroupY, + uint32_t baseGroupZ, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplate( + VkDevice device, + const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplate( + VkDevice device, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplate( + VkDevice device, + VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const void* pData); + +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + VkDescriptorSetLayoutSupport* pSupport); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion( + VkDevice device, + const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSamplerYcbcrConversion* pYcbcrConversion); + +VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion( + VkDevice device, + VkSamplerYcbcrConversion ycbcrConversion, + const VkAllocationCallbacks* pAllocator); +#endif + + +// VK_VERSION_1_2 is a preprocessor guard. Do not pass it to API calls. +#define VK_VERSION_1_2 1 +// Vulkan 1.2 version number +#define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)// Patch version should always be set to 0 + +#define VK_MAX_DRIVER_NAME_SIZE 256U +#define VK_MAX_DRIVER_INFO_SIZE 256U + +typedef enum VkDriverId { + 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, + VK_DRIVER_ID_MESA_HONEYKRISP = 26, + VK_DRIVER_ID_VULKAN_SC_EMULATION_ON_VULKAN = 27, + VK_DRIVER_ID_MESA_KOSMICKRISP = 28, + VK_DRIVER_ID_MESA_GFXSTREAM = 29, + VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY, + VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE, + VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV, + VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = VK_DRIVER_ID_NVIDIA_PROPRIETARY, + VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, + VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA, + VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = VK_DRIVER_ID_IMAGINATION_PROPRIETARY, + VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = VK_DRIVER_ID_QUALCOMM_PROPRIETARY, + VK_DRIVER_ID_ARM_PROPRIETARY_KHR = VK_DRIVER_ID_ARM_PROPRIETARY, + VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR = VK_DRIVER_ID_GOOGLE_SWIFTSHADER, + VK_DRIVER_ID_GGP_PROPRIETARY_KHR = VK_DRIVER_ID_GGP_PROPRIETARY, + VK_DRIVER_ID_BROADCOM_PROPRIETARY_KHR = VK_DRIVER_ID_BROADCOM_PROPRIETARY, + VK_DRIVER_ID_MAX_ENUM = 0x7FFFFFFF +} VkDriverId; + +typedef enum VkShaderFloatControlsIndependence { + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY = 0, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL = 1, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE = 2, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_MAX_ENUM = 0x7FFFFFFF +} VkShaderFloatControlsIndependence; + +typedef enum VkSemaphoreType { + VK_SEMAPHORE_TYPE_BINARY = 0, + VK_SEMAPHORE_TYPE_TIMELINE = 1, + VK_SEMAPHORE_TYPE_BINARY_KHR = VK_SEMAPHORE_TYPE_BINARY, + VK_SEMAPHORE_TYPE_TIMELINE_KHR = VK_SEMAPHORE_TYPE_TIMELINE, + VK_SEMAPHORE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreType; + +typedef enum VkSamplerReductionMode { + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0, + VK_SAMPLER_REDUCTION_MODE_MIN = 1, + VK_SAMPLER_REDUCTION_MODE_MAX = 2, + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM = 1000521000, + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, + VK_SAMPLER_REDUCTION_MODE_MIN_EXT = VK_SAMPLER_REDUCTION_MODE_MIN, + VK_SAMPLER_REDUCTION_MODE_MAX_EXT = VK_SAMPLER_REDUCTION_MODE_MAX, + VK_SAMPLER_REDUCTION_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerReductionMode; + +typedef enum VkResolveModeFlagBits { + VK_RESOLVE_MODE_NONE = 0, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT = 0x00000001, + VK_RESOLVE_MODE_AVERAGE_BIT = 0x00000002, + VK_RESOLVE_MODE_MIN_BIT = 0x00000004, + VK_RESOLVE_MODE_MAX_BIT = 0x00000008, + VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_BIT_ANDROID = 0x00000010, + VK_RESOLVE_MODE_CUSTOM_BIT_EXT = 0x00000020, + VK_RESOLVE_MODE_NONE_KHR = VK_RESOLVE_MODE_NONE, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, + VK_RESOLVE_MODE_AVERAGE_BIT_KHR = VK_RESOLVE_MODE_AVERAGE_BIT, + VK_RESOLVE_MODE_MIN_BIT_KHR = VK_RESOLVE_MODE_MIN_BIT, + VK_RESOLVE_MODE_MAX_BIT_KHR = VK_RESOLVE_MODE_MAX_BIT, + // VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID is a legacy alias + VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID = VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_BIT_ANDROID, + VK_RESOLVE_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkResolveModeFlagBits; +typedef VkFlags VkResolveModeFlags; + +typedef enum VkSemaphoreWaitFlagBits { + VK_SEMAPHORE_WAIT_ANY_BIT = 0x00000001, + VK_SEMAPHORE_WAIT_ANY_BIT_KHR = VK_SEMAPHORE_WAIT_ANY_BIT, + VK_SEMAPHORE_WAIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreWaitFlagBits; +typedef VkFlags VkSemaphoreWaitFlags; + +typedef enum VkDescriptorBindingFlagBits { + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0x00000001, + VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0x00000004, + VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0x00000008, + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, + VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, + VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT, + VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorBindingFlagBits; +typedef VkFlags VkDescriptorBindingFlags; +typedef struct VkConformanceVersion { + uint8_t major; + uint8_t minor; + uint8_t subminor; + uint8_t patch; +} VkConformanceVersion; + +typedef struct VkPhysicalDeviceDriverProperties { + VkStructureType sType; + void* pNext; + VkDriverId driverID; + char driverName[VK_MAX_DRIVER_NAME_SIZE]; + char driverInfo[VK_MAX_DRIVER_INFO_SIZE]; + VkConformanceVersion conformanceVersion; +} VkPhysicalDeviceDriverProperties; + +typedef struct VkPhysicalDeviceVulkan11Features { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer16BitAccess; + VkBool32 uniformAndStorageBuffer16BitAccess; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; + VkBool32 multiview; + VkBool32 multiviewGeometryShader; + VkBool32 multiviewTessellationShader; + VkBool32 variablePointersStorageBuffer; + VkBool32 variablePointers; + VkBool32 protectedMemory; + VkBool32 samplerYcbcrConversion; + VkBool32 shaderDrawParameters; +} VkPhysicalDeviceVulkan11Features; + +typedef struct VkPhysicalDeviceVulkan11Properties { + VkStructureType sType; + void* pNext; + uint8_t deviceUUID[VK_UUID_SIZE]; + uint8_t driverUUID[VK_UUID_SIZE]; + uint8_t deviceLUID[VK_LUID_SIZE]; + uint32_t deviceNodeMask; + VkBool32 deviceLUIDValid; + uint32_t subgroupSize; + VkShaderStageFlags subgroupSupportedStages; + VkSubgroupFeatureFlags subgroupSupportedOperations; + VkBool32 subgroupQuadOperationsInAllStages; + VkPointClippingBehavior pointClippingBehavior; + uint32_t maxMultiviewViewCount; + uint32_t maxMultiviewInstanceIndex; + VkBool32 protectedNoFault; + uint32_t maxPerSetDescriptors; + VkDeviceSize maxMemoryAllocationSize; +} VkPhysicalDeviceVulkan11Properties; + +typedef struct VkPhysicalDeviceVulkan12Features { + VkStructureType sType; + void* pNext; + VkBool32 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; +} VkPhysicalDeviceVulkan12Features; + +typedef struct VkPhysicalDeviceVulkan12Properties { + VkStructureType sType; + void* pNext; + VkDriverId driverID; + char driverName[VK_MAX_DRIVER_NAME_SIZE]; + char driverInfo[VK_MAX_DRIVER_INFO_SIZE]; + VkConformanceVersion conformanceVersion; + VkShaderFloatControlsIndependence denormBehaviorIndependence; + VkShaderFloatControlsIndependence roundingModeIndependence; + VkBool32 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; + uint32_t maxUpdateAfterBindDescriptorsInAllPools; + VkBool32 shaderUniformBufferArrayNonUniformIndexingNative; + VkBool32 shaderSampledImageArrayNonUniformIndexingNative; + VkBool32 shaderStorageBufferArrayNonUniformIndexingNative; + VkBool32 shaderStorageImageArrayNonUniformIndexingNative; + VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative; + VkBool32 robustBufferAccessUpdateAfterBind; + VkBool32 quadDivergentImplicitLod; + uint32_t maxPerStageDescriptorUpdateAfterBindSamplers; + uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages; + uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments; + uint32_t maxPerStageUpdateAfterBindResources; + uint32_t maxDescriptorSetUpdateAfterBindSamplers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindSampledImages; + uint32_t maxDescriptorSetUpdateAfterBindStorageImages; + uint32_t maxDescriptorSetUpdateAfterBindInputAttachments; + VkResolveModeFlags supportedDepthResolveModes; + VkResolveModeFlags supportedStencilResolveModes; + VkBool32 independentResolveNone; + VkBool32 independentResolve; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; + uint64_t maxTimelineSemaphoreValueDifference; + VkSampleCountFlags framebufferIntegerColorSampleCounts; +} VkPhysicalDeviceVulkan12Properties; + +typedef struct VkImageFormatListCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t viewFormatCount; + const VkFormat* pViewFormats; +} VkImageFormatListCreateInfo; + +typedef struct VkPhysicalDeviceVulkanMemoryModelFeatures { + VkStructureType sType; + void* pNext; + VkBool32 vulkanMemoryModel; + VkBool32 vulkanMemoryModelDeviceScope; + VkBool32 vulkanMemoryModelAvailabilityVisibilityChains; +} VkPhysicalDeviceVulkanMemoryModelFeatures; + +typedef struct VkPhysicalDeviceHostQueryResetFeatures { + VkStructureType sType; + void* pNext; + VkBool32 hostQueryReset; +} VkPhysicalDeviceHostQueryResetFeatures; + +typedef struct VkPhysicalDeviceTimelineSemaphoreFeatures { + VkStructureType sType; + void* pNext; + VkBool32 timelineSemaphore; +} VkPhysicalDeviceTimelineSemaphoreFeatures; + +typedef struct VkPhysicalDeviceTimelineSemaphoreProperties { + VkStructureType sType; + void* pNext; + uint64_t maxTimelineSemaphoreValueDifference; +} VkPhysicalDeviceTimelineSemaphoreProperties; + +typedef struct VkSemaphoreTypeCreateInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreType semaphoreType; + uint64_t initialValue; +} VkSemaphoreTypeCreateInfo; + +typedef struct VkTimelineSemaphoreSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreValueCount; + const uint64_t* pWaitSemaphoreValues; + uint32_t signalSemaphoreValueCount; + const uint64_t* pSignalSemaphoreValues; +} VkTimelineSemaphoreSubmitInfo; + +typedef struct VkSemaphoreWaitInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreWaitFlags flags; + uint32_t semaphoreCount; + const VkSemaphore* pSemaphores; + const uint64_t* pValues; +} VkSemaphoreWaitInfo; + +typedef struct VkSemaphoreSignalInfo { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + uint64_t value; +} VkSemaphoreSignalInfo; + +typedef struct VkPhysicalDeviceBufferDeviceAddressFeatures { + VkStructureType sType; + void* pNext; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; +} VkPhysicalDeviceBufferDeviceAddressFeatures; + +typedef struct VkBufferDeviceAddressInfo { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; +} VkBufferDeviceAddressInfo; + +typedef struct VkBufferOpaqueCaptureAddressCreateInfo { + VkStructureType sType; + const void* pNext; + uint64_t opaqueCaptureAddress; +} VkBufferOpaqueCaptureAddressCreateInfo; + +typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo { + VkStructureType sType; + const void* pNext; + uint64_t opaqueCaptureAddress; +} VkMemoryOpaqueCaptureAddressAllocateInfo; + +typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; +} VkDeviceMemoryOpaqueCaptureAddressInfo; + +typedef struct VkPhysicalDevice8BitStorageFeatures { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer8BitAccess; + VkBool32 uniformAndStorageBuffer8BitAccess; + VkBool32 storagePushConstant8; +} VkPhysicalDevice8BitStorageFeatures; + +typedef struct VkPhysicalDeviceShaderAtomicInt64Features { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferInt64Atomics; + VkBool32 shaderSharedInt64Atomics; +} VkPhysicalDeviceShaderAtomicInt64Features; + +typedef struct VkPhysicalDeviceShaderFloat16Int8Features { + VkStructureType sType; + void* pNext; + VkBool32 shaderFloat16; + VkBool32 shaderInt8; +} VkPhysicalDeviceShaderFloat16Int8Features; + +typedef struct VkPhysicalDeviceFloatControlsProperties { + VkStructureType sType; + void* pNext; + VkShaderFloatControlsIndependence denormBehaviorIndependence; + VkShaderFloatControlsIndependence roundingModeIndependence; + VkBool32 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; +} VkPhysicalDeviceFloatControlsProperties; + +typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t bindingCount; + const VkDescriptorBindingFlags* pBindingFlags; +} VkDescriptorSetLayoutBindingFlagsCreateInfo; + +typedef struct VkPhysicalDeviceDescriptorIndexingFeatures { + VkStructureType sType; + void* pNext; + 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; +} VkPhysicalDeviceDescriptorIndexingFeatures; + +typedef struct VkPhysicalDeviceDescriptorIndexingProperties { + VkStructureType sType; + void* pNext; + uint32_t maxUpdateAfterBindDescriptorsInAllPools; + VkBool32 shaderUniformBufferArrayNonUniformIndexingNative; + VkBool32 shaderSampledImageArrayNonUniformIndexingNative; + VkBool32 shaderStorageBufferArrayNonUniformIndexingNative; + VkBool32 shaderStorageImageArrayNonUniformIndexingNative; + VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative; + VkBool32 robustBufferAccessUpdateAfterBind; + VkBool32 quadDivergentImplicitLod; + uint32_t maxPerStageDescriptorUpdateAfterBindSamplers; + uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages; + uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments; + uint32_t maxPerStageUpdateAfterBindResources; + uint32_t maxDescriptorSetUpdateAfterBindSamplers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindSampledImages; + uint32_t maxDescriptorSetUpdateAfterBindStorageImages; + uint32_t maxDescriptorSetUpdateAfterBindInputAttachments; +} VkPhysicalDeviceDescriptorIndexingProperties; + +typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfo { + VkStructureType sType; + const void* pNext; + uint32_t descriptorSetCount; + const uint32_t* pDescriptorCounts; +} VkDescriptorSetVariableDescriptorCountAllocateInfo; + +typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupport { + VkStructureType sType; + void* pNext; + uint32_t maxVariableDescriptorCount; +} VkDescriptorSetVariableDescriptorCountLayoutSupport; + +typedef struct VkPhysicalDeviceScalarBlockLayoutFeatures { + VkStructureType sType; + void* pNext; + VkBool32 scalarBlockLayout; +} VkPhysicalDeviceScalarBlockLayoutFeatures; + +typedef struct VkSamplerReductionModeCreateInfo { + VkStructureType sType; + const void* pNext; + VkSamplerReductionMode reductionMode; +} VkSamplerReductionModeCreateInfo; + +typedef struct VkPhysicalDeviceSamplerFilterMinmaxProperties { + VkStructureType sType; + void* pNext; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; +} VkPhysicalDeviceSamplerFilterMinmaxProperties; + +typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeatures { + VkStructureType sType; + void* pNext; + VkBool32 uniformBufferStandardLayout; +} VkPhysicalDeviceUniformBufferStandardLayoutFeatures; + +typedef struct VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupExtendedTypes; +} VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures; + +typedef struct VkAttachmentDescription2 { + VkStructureType sType; + const void* pNext; + VkAttachmentDescriptionFlags flags; + VkFormat format; + VkSampleCountFlagBits samples; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkAttachmentLoadOp stencilLoadOp; + VkAttachmentStoreOp stencilStoreOp; + VkImageLayout initialLayout; + VkImageLayout finalLayout; +} VkAttachmentDescription2; + +typedef struct VkAttachmentReference2 { + VkStructureType sType; + const void* pNext; + uint32_t attachment; + VkImageLayout layout; + VkImageAspectFlags aspectMask; +} VkAttachmentReference2; + +typedef struct VkSubpassDescription2 { + VkStructureType sType; + const void* pNext; + VkSubpassDescriptionFlags flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t viewMask; + uint32_t inputAttachmentCount; + const VkAttachmentReference2* pInputAttachments; + uint32_t colorAttachmentCount; + const VkAttachmentReference2* pColorAttachments; + const VkAttachmentReference2* pResolveAttachments; + const VkAttachmentReference2* pDepthStencilAttachment; + uint32_t preserveAttachmentCount; + const uint32_t* pPreserveAttachments; +} VkSubpassDescription2; + +typedef struct VkSubpassDependency2 { + VkStructureType sType; + const void* pNext; + uint32_t srcSubpass; + uint32_t dstSubpass; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkDependencyFlags dependencyFlags; + int32_t viewOffset; +} VkSubpassDependency2; + +typedef struct VkSubpassBeginInfo { + VkStructureType sType; + const void* pNext; + VkSubpassContents contents; +} VkSubpassBeginInfo; + +typedef struct VkSubpassEndInfo { + VkStructureType sType; + const void* pNext; +} VkSubpassEndInfo; + +typedef struct VkRenderPassCreateInfo2 { + VkStructureType sType; + const void* pNext; + VkRenderPassCreateFlags flags; + uint32_t attachmentCount; + const VkAttachmentDescription2* pAttachments; + uint32_t subpassCount; + const VkSubpassDescription2* pSubpasses; + uint32_t dependencyCount; + const VkSubpassDependency2* pDependencies; + uint32_t correlatedViewMaskCount; + const uint32_t* pCorrelatedViewMasks; +} VkRenderPassCreateInfo2; + +typedef struct VkSubpassDescriptionDepthStencilResolve { + VkStructureType sType; + const void* pNext; + VkResolveModeFlagBits depthResolveMode; + VkResolveModeFlagBits stencilResolveMode; + const VkAttachmentReference2* pDepthStencilResolveAttachment; +} VkSubpassDescriptionDepthStencilResolve; + +typedef struct VkPhysicalDeviceDepthStencilResolveProperties { + VkStructureType sType; + void* pNext; + VkResolveModeFlags supportedDepthResolveModes; + VkResolveModeFlags supportedStencilResolveModes; + VkBool32 independentResolveNone; + VkBool32 independentResolve; +} VkPhysicalDeviceDepthStencilResolveProperties; + +typedef struct VkImageStencilUsageCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageUsageFlags stencilUsage; +} VkImageStencilUsageCreateInfo; + +typedef struct VkPhysicalDeviceImagelessFramebufferFeatures { + VkStructureType sType; + void* pNext; + VkBool32 imagelessFramebuffer; +} VkPhysicalDeviceImagelessFramebufferFeatures; + +typedef struct VkFramebufferAttachmentImageInfo { + VkStructureType sType; + const void* pNext; + VkImageCreateFlags flags; + VkImageUsageFlags usage; + uint32_t width; + uint32_t height; + uint32_t layerCount; + uint32_t viewFormatCount; + const VkFormat* pViewFormats; +} VkFramebufferAttachmentImageInfo; + +typedef struct VkRenderPassAttachmentBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t attachmentCount; + const VkImageView* pAttachments; +} VkRenderPassAttachmentBeginInfo; + +typedef struct VkFramebufferAttachmentsCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t attachmentImageInfoCount; + const VkFramebufferAttachmentImageInfo* pAttachmentImageInfos; +} VkFramebufferAttachmentsCreateInfo; + +typedef struct VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures { + VkStructureType sType; + void* pNext; + VkBool32 separateDepthStencilLayouts; +} VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures; + +typedef struct VkAttachmentReferenceStencilLayout { + VkStructureType sType; + void* pNext; + VkImageLayout stencilLayout; +} VkAttachmentReferenceStencilLayout; + +typedef struct VkAttachmentDescriptionStencilLayout { + VkStructureType sType; + void* pNext; + VkImageLayout stencilInitialLayout; + VkImageLayout stencilFinalLayout; +} VkAttachmentDescriptionStencilLayout; + +typedef void (VKAPI_PTR *PFN_vkResetQueryPool)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValue)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue); +typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphores)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphore)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddress)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkResetQueryPool( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValue( + VkDevice device, + VkSemaphore semaphore, + uint64_t* pValue); + +VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphores( + VkDevice device, + const VkSemaphoreWaitInfo* pWaitInfo, + uint64_t timeout); + +VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphore( + VkDevice device, + const VkSemaphoreSignalInfo* pSignalInfo); + +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddress( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddress( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress( + VkDevice device, + const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCount( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCount( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2( + VkDevice device, + const VkRenderPassCreateInfo2* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + const VkSubpassBeginInfo* pSubpassBeginInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2( + VkCommandBuffer commandBuffer, + const VkSubpassBeginInfo* pSubpassBeginInfo, + const VkSubpassEndInfo* pSubpassEndInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2( + VkCommandBuffer commandBuffer, + const VkSubpassEndInfo* pSubpassEndInfo); +#endif + + +// VK_VERSION_1_3 is a preprocessor guard. Do not pass it to API calls. +#define VK_VERSION_1_3 1 +// Vulkan 1.3 version number +#define VK_API_VERSION_1_3 VK_MAKE_API_VERSION(0, 1, 3, 0)// Patch version should always be set to 0 + +typedef uint64_t VkFlags64; +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPrivateDataSlot) + +typedef enum VkToolPurposeFlagBits { + VK_TOOL_PURPOSE_VALIDATION_BIT = 0x00000001, + VK_TOOL_PURPOSE_PROFILING_BIT = 0x00000002, + VK_TOOL_PURPOSE_TRACING_BIT = 0x00000004, + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT = 0x00000008, + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT = 0x00000010, + VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT = 0x00000020, + VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT = 0x00000040, + VK_TOOL_PURPOSE_VALIDATION_BIT_EXT = VK_TOOL_PURPOSE_VALIDATION_BIT, + VK_TOOL_PURPOSE_PROFILING_BIT_EXT = VK_TOOL_PURPOSE_PROFILING_BIT, + VK_TOOL_PURPOSE_TRACING_BIT_EXT = VK_TOOL_PURPOSE_TRACING_BIT, + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT, + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT, + VK_TOOL_PURPOSE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkToolPurposeFlagBits; +typedef VkFlags VkToolPurposeFlags; +typedef VkFlags VkPrivateDataSlotCreateFlags; +typedef VkFlags64 VkPipelineStageFlags2; + +// Flag bits for VkPipelineStageFlagBits2 +typedef VkFlags64 VkPipelineStageFlagBits2; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE = 0ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT = 0x00000001ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT = 0x00000002ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT = 0x00000004ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT = 0x00000008ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT = 0x00000040ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT = 0x00000080ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT = 0x00000100ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT = 0x00000200ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT = 0x00000800ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT = 0x00002000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT = 0x00004000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT = 0x00008000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT = 0x00010000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT = 0x100000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT = 0x200000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT = 0x400000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT = 0x800000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT = 0x1000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT = 0x2000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT = 0x4000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0x04000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0x08000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE_KHR = 0ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 0x00000001ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 0x00000002ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 0x00000004ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 0x00000008ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 0x00000010ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 0x00000020ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 0x00000040ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 0x00000080ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 0x00000100ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 0x00000200ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 0x00000400ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 0x00000800ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 0x00002000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 0x00004000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 0x00008000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 0x00010000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 0x100000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 0x200000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 0x400000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 0x800000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 0x1000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 0x2000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 0x4000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0x00020000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT = 0x00020000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV = 0x00400000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0x00200000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV = 0x00200000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0x00080000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT = 0x00080000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT = 0x00100000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI = 0x8000000000ULL; +// VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI is a legacy alias +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0x10000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT = 0x40000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI = 0x20000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV = 0x20000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CONVERT_COOPERATIVE_VECTOR_MATRIX_BIT_NV = 0x100000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DATA_GRAPH_BIT_ARM = 0x40000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_INDIRECT_BIT_KHR = 0x400000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MEMORY_DECOMPRESSION_BIT_EXT = 0x200000000000ULL; + +typedef VkFlags64 VkAccessFlags2; + +// Flag bits for VkAccessFlagBits2 +typedef VkFlags64 VkAccessFlagBits2; +static const VkAccessFlagBits2 VK_ACCESS_2_NONE = 0ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT = 0x00000001ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT = 0x00000002ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT = 0x00000008ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT = 0x00000010ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT = 0x00000020ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT = 0x00000040ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT = 0x00000080ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT = 0x00000800ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT = 0x00001000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT = 0x00002000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT = 0x00004000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT = 0x00008000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT = 0x00010000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT = 0x100000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 0x200000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 0x400000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0x800000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0x1000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SAMPLER_HEAP_READ_BIT_EXT = 0x200000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_RESOURCE_HEAP_READ_BIT_EXT = 0x400000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0x2000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0x4000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_TILE_ATTACHMENT_READ_BIT_QCOM = 0x8000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_TILE_ATTACHMENT_WRITE_BIT_QCOM = 0x10000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_NONE_KHR = 0ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 0x00000004ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 0x00000008ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 0x00000010ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT_KHR = 0x00000020ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 0x00000040ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 0x00000080ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 0x00000100ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 0x00000200ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 0x00000400ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 0x00000800ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 0x00001000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT_KHR = 0x00002000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT_KHR = 0x00004000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT_KHR = 0x00008000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 0x00010000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 0x100000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 0x200000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 0x400000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_EXT = 0x00020000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_EXT = 0x00040000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT = 0x20000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0x8000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR = 0x10000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_READ_BIT_EXT = 0x100000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT = 0x200000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV = 0x40000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV = 0x80000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DATA_GRAPH_READ_BIT_ARM = 0x800000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DATA_GRAPH_WRITE_BIT_ARM = 0x1000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_DECOMPRESSION_READ_BIT_EXT = 0x80000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_DECOMPRESSION_WRITE_BIT_EXT = 0x100000000000000ULL; + + +typedef enum VkSubmitFlagBits { + VK_SUBMIT_PROTECTED_BIT = 0x00000001, + VK_SUBMIT_PROTECTED_BIT_KHR = VK_SUBMIT_PROTECTED_BIT, + VK_SUBMIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubmitFlagBits; +typedef VkFlags VkSubmitFlags; +typedef VkFlags64 VkFormatFeatureFlags2; + +// Flag bits for VkFormatFeatureFlagBits2 +typedef VkFlags64 VkFormatFeatureFlagBits2; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT = 0x00000001ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT = 0x00000002ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT = 0x00000010ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT = 0x00000040ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT = 0x00000080ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT = 0x00000400ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT = 0x00000800ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT = 0x00004000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT = 0x00008000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT = 0x00400000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT = 0x00800000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT = 0x80000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT = 0x100000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT = 0x200000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT = 0x00002000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT = 0x400000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT = 0x400000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLOCK_MATCHING_SXD_BIT_QCOM = 0x100000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR = 0x00000001ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR = 0x00000002ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT_KHR = 0x00000004ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000010ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT_KHR = 0x00000020ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT_KHR = 0x00000040ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT_KHR = 0x00000080ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT_KHR = 0x00000100ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT_KHR = 0x00000200ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT_KHR = 0x00000400ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT_KHR = 0x00000800ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT_KHR = 0x00001000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT_KHR = 0x00004000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT_KHR = 0x00008000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 0x00020000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 0x00040000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 0x00080000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 0x00100000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 0x00200000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT_KHR = 0x00400000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR = 0x00800000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR = 0x80000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR = 0x100000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR = 0x200000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT_KHR = 0x00010000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 0x00002000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_RADIUS_BUFFER_BIT_NV = 0x8000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV = 0x4000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM = 0x400000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM = 0x800000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM = 0x1000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM = 0x2000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TENSOR_SHADER_BIT_ARM = 0x8000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TENSOR_IMAGE_ALIASING_BIT_ARM = 0x80000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV = 0x10000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV = 0x20000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV = 0x40000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TENSOR_DATA_GRAPH_BIT_ARM = 0x1000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COPY_IMAGE_INDIRECT_DST_BIT_KHR = 0x800000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR = 0x2000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR = 0x4000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_COPY_ON_COMPUTE_QUEUE_BIT_KHR = 0x10000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_COPY_ON_TRANSFER_QUEUE_BIT_KHR = 0x20000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STENCIL_COPY_ON_COMPUTE_QUEUE_BIT_KHR = 0x40000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STENCIL_COPY_ON_TRANSFER_QUEUE_BIT_KHR = 0x80000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DATA_GRAPH_OPTICAL_FLOW_IMAGE_BIT_ARM = 0x100000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DATA_GRAPH_OPTICAL_FLOW_VECTOR_BIT_ARM = 0x200000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DATA_GRAPH_OPTICAL_FLOW_COST_BIT_ARM = 0x400000000000000ULL; + + +typedef enum VkPipelineCreationFeedbackFlagBits { + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT = 0x00000001, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT = 0x00000002, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT = 0x00000004, + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT, + VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCreationFeedbackFlagBits; +typedef VkFlags VkPipelineCreationFeedbackFlags; + +typedef enum VkRenderingFlagBits { + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 0x00000001, + VK_RENDERING_SUSPENDING_BIT = 0x00000002, + VK_RENDERING_RESUMING_BIT = 0x00000004, + VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x00000008, + VK_RENDERING_CONTENTS_INLINE_BIT_KHR = 0x00000010, + VK_RENDERING_PER_LAYER_FRAGMENT_DENSITY_BIT_VALVE = 0x00000020, + VK_RENDERING_FRAGMENT_REGION_BIT_EXT = 0x00000040, + VK_RENDERING_CUSTOM_RESOLVE_BIT_EXT = 0x00000080, + VK_RENDERING_LOCAL_READ_CONCURRENT_ACCESS_CONTROL_BIT_KHR = 0x00000100, + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, + VK_RENDERING_SUSPENDING_BIT_KHR = VK_RENDERING_SUSPENDING_BIT, + VK_RENDERING_RESUMING_BIT_KHR = VK_RENDERING_RESUMING_BIT, + VK_RENDERING_CONTENTS_INLINE_BIT_EXT = VK_RENDERING_CONTENTS_INLINE_BIT_KHR, + VK_RENDERING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkRenderingFlagBits; +typedef VkFlags VkRenderingFlags; +typedef struct VkPhysicalDeviceVulkan13Features { + VkStructureType sType; + void* pNext; + VkBool32 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; +} VkPhysicalDeviceVulkan13Features; + +typedef struct VkPhysicalDeviceVulkan13Properties { + VkStructureType sType; + void* pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; + uint32_t maxInlineUniformTotalSize; + VkBool32 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; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceVulkan13Properties; + +typedef struct VkPhysicalDeviceToolProperties { + VkStructureType sType; + void* pNext; + char name[VK_MAX_EXTENSION_NAME_SIZE]; + char version[VK_MAX_EXTENSION_NAME_SIZE]; + VkToolPurposeFlags purposes; + char description[VK_MAX_DESCRIPTION_SIZE]; + char layer[VK_MAX_EXTENSION_NAME_SIZE]; +} VkPhysicalDeviceToolProperties; + +typedef struct VkPhysicalDevicePrivateDataFeatures { + VkStructureType sType; + void* pNext; + VkBool32 privateData; +} VkPhysicalDevicePrivateDataFeatures; + +typedef struct VkDevicePrivateDataCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t privateDataSlotRequestCount; +} VkDevicePrivateDataCreateInfo; + +typedef struct VkPrivateDataSlotCreateInfo { + VkStructureType sType; + const void* pNext; + VkPrivateDataSlotCreateFlags flags; +} VkPrivateDataSlotCreateInfo; + +typedef struct VkMemoryBarrier2 { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; +} VkMemoryBarrier2; + +typedef struct VkBufferMemoryBarrier2 { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier2; + +typedef struct VkImageMemoryBarrier2 { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier2; + +typedef struct VkDependencyInfo { + VkStructureType sType; + const void* pNext; + VkDependencyFlags dependencyFlags; + uint32_t memoryBarrierCount; + const VkMemoryBarrier2* pMemoryBarriers; + uint32_t bufferMemoryBarrierCount; + const VkBufferMemoryBarrier2* pBufferMemoryBarriers; + uint32_t imageMemoryBarrierCount; + const VkImageMemoryBarrier2* pImageMemoryBarriers; +} VkDependencyInfo; + +typedef struct VkSemaphoreSubmitInfo { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + uint64_t value; + VkPipelineStageFlags2 stageMask; + uint32_t deviceIndex; +} VkSemaphoreSubmitInfo; + +typedef struct VkCommandBufferSubmitInfo { + VkStructureType sType; + const void* pNext; + VkCommandBuffer commandBuffer; + uint32_t deviceMask; +} VkCommandBufferSubmitInfo; + +typedef struct VkSubmitInfo2 { + VkStructureType sType; + const void* pNext; + VkSubmitFlags flags; + uint32_t waitSemaphoreInfoCount; + const VkSemaphoreSubmitInfo* pWaitSemaphoreInfos; + uint32_t commandBufferInfoCount; + const VkCommandBufferSubmitInfo* pCommandBufferInfos; + uint32_t signalSemaphoreInfoCount; + const VkSemaphoreSubmitInfo* pSignalSemaphoreInfos; +} VkSubmitInfo2; + +typedef struct VkPhysicalDeviceSynchronization2Features { + VkStructureType sType; + void* pNext; + VkBool32 synchronization2; +} VkPhysicalDeviceSynchronization2Features; + +typedef struct VkBufferCopy2 { + VkStructureType sType; + const void* pNext; + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy2; + +typedef struct VkCopyBufferInfo2 { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferCopy2* pRegions; +} VkCopyBufferInfo2; + +typedef struct VkImageCopy2 { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy2; + +typedef struct VkCopyImageInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageCopy2* pRegions; +} VkCopyImageInfo2; + +typedef struct VkBufferImageCopy2 { + VkStructureType sType; + const void* pNext; + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy2; + +typedef struct VkCopyBufferToImageInfo2 { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkBufferImageCopy2* pRegions; +} VkCopyBufferToImageInfo2; + +typedef struct VkCopyImageToBufferInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferImageCopy2* pRegions; +} VkCopyImageToBufferInfo2; + +typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeatures { + VkStructureType sType; + void* pNext; + VkBool32 textureCompressionASTC_HDR; +} VkPhysicalDeviceTextureCompressionASTCHDRFeatures; + +typedef struct VkFormatProperties3 { + VkStructureType sType; + void* pNext; + VkFormatFeatureFlags2 linearTilingFeatures; + VkFormatFeatureFlags2 optimalTilingFeatures; + VkFormatFeatureFlags2 bufferFeatures; +} VkFormatProperties3; + +typedef struct VkPhysicalDeviceMaintenance4Features { + VkStructureType sType; + void* pNext; + VkBool32 maintenance4; +} VkPhysicalDeviceMaintenance4Features; + +typedef struct VkPhysicalDeviceMaintenance4Properties { + VkStructureType sType; + void* pNext; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceMaintenance4Properties; + +typedef struct VkDeviceBufferMemoryRequirements { + VkStructureType sType; + const void* pNext; + const VkBufferCreateInfo* pCreateInfo; +} VkDeviceBufferMemoryRequirements; + +typedef struct VkDeviceImageMemoryRequirements { + VkStructureType sType; + const void* pNext; + const VkImageCreateInfo* pCreateInfo; + VkImageAspectFlagBits planeAspect; +} VkDeviceImageMemoryRequirements; + +typedef struct VkPipelineCreationFeedback { + VkPipelineCreationFeedbackFlags flags; + uint64_t duration; +} VkPipelineCreationFeedback; + +typedef struct VkPipelineCreationFeedbackCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreationFeedback* pPipelineCreationFeedback; + uint32_t pipelineStageCreationFeedbackCount; + VkPipelineCreationFeedback* pPipelineStageCreationFeedbacks; +} VkPipelineCreationFeedbackCreateInfo; + +typedef struct VkPhysicalDeviceShaderTerminateInvocationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderTerminateInvocation; +} VkPhysicalDeviceShaderTerminateInvocationFeatures; + +typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderDemoteToHelperInvocation; +} VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures; + +typedef struct VkPhysicalDevicePipelineCreationCacheControlFeatures { + VkStructureType sType; + void* pNext; + VkBool32 pipelineCreationCacheControl; +} VkPhysicalDevicePipelineCreationCacheControlFeatures; + +typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderZeroInitializeWorkgroupMemory; +} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures; + +typedef struct VkPhysicalDeviceImageRobustnessFeatures { + VkStructureType sType; + void* pNext; + VkBool32 robustImageAccess; +} VkPhysicalDeviceImageRobustnessFeatures; + +typedef struct VkPhysicalDeviceSubgroupSizeControlFeatures { + VkStructureType sType; + void* pNext; + VkBool32 subgroupSizeControl; + VkBool32 computeFullSubgroups; +} VkPhysicalDeviceSubgroupSizeControlFeatures; + +typedef struct VkPhysicalDeviceSubgroupSizeControlProperties { + VkStructureType sType; + void* pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; +} VkPhysicalDeviceSubgroupSizeControlProperties; + +typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t requiredSubgroupSize; +} VkPipelineShaderStageRequiredSubgroupSizeCreateInfo; + +typedef struct VkPhysicalDeviceInlineUniformBlockFeatures { + VkStructureType sType; + void* pNext; + VkBool32 inlineUniformBlock; + VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; +} VkPhysicalDeviceInlineUniformBlockFeatures; + +typedef struct VkPhysicalDeviceInlineUniformBlockProperties { + VkStructureType sType; + void* pNext; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; +} VkPhysicalDeviceInlineUniformBlockProperties; + +typedef struct VkWriteDescriptorSetInlineUniformBlock { + VkStructureType sType; + const void* pNext; + uint32_t dataSize; + const void* pData; +} VkWriteDescriptorSetInlineUniformBlock; + +typedef struct VkDescriptorPoolInlineUniformBlockCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t maxInlineUniformBlockBindings; +} VkDescriptorPoolInlineUniformBlockCreateInfo; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerDotProduct; +} VkPhysicalDeviceShaderIntegerDotProductFeatures; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductProperties { + VkStructureType sType; + void* pNext; + VkBool32 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; +} VkPhysicalDeviceShaderIntegerDotProductProperties; + +typedef struct VkPhysicalDeviceTexelBufferAlignmentProperties { + VkStructureType sType; + void* pNext; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; +} VkPhysicalDeviceTexelBufferAlignmentProperties; + +typedef struct VkImageBlit2 { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit2; + +typedef struct VkBlitImageInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageBlit2* pRegions; + VkFilter filter; +} VkBlitImageInfo2; + +typedef struct VkImageResolve2 { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve2; + +typedef struct VkResolveImageInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageResolve2* pRegions; +} VkResolveImageInfo2; + +typedef struct VkRenderingAttachmentInfo { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkResolveModeFlagBits resolveMode; + VkImageView resolveImageView; + VkImageLayout resolveImageLayout; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkClearValue clearValue; +} VkRenderingAttachmentInfo; + +typedef struct VkRenderingInfo { + VkStructureType sType; + const void* pNext; + VkRenderingFlags flags; + VkRect2D renderArea; + uint32_t layerCount; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkRenderingAttachmentInfo* pColorAttachments; + const VkRenderingAttachmentInfo* pDepthAttachment; + const VkRenderingAttachmentInfo* pStencilAttachment; +} VkRenderingInfo; + +typedef struct VkPipelineRenderingCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkPipelineRenderingCreateInfo; + +typedef struct VkPhysicalDeviceDynamicRenderingFeatures { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRendering; +} VkPhysicalDeviceDynamicRenderingFeatures; + +typedef struct VkCommandBufferInheritanceRenderingInfo { + VkStructureType sType; + const void* pNext; + VkRenderingFlags flags; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; + VkSampleCountFlagBits rasterizationSamples; +} VkCommandBufferInheritanceRenderingInfo; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolProperties)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlot)(VkDevice device, const VkPrivateDataSlotCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlot* pPrivateDataSlot); +typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlot)(VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data); +typedef void (VKAPI_PTR *PFN_vkGetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t* pData); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2)(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2* pCopyBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2* pCopyImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirements)(VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRendering)(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRendering)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdSetCullMode)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetFrontFace)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveTopology)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWithCount)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissorWithCount)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers2)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthWriteEnable)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthCompareOp)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBoundsTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnable)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOp)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnable)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnable)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pToolCount, + VkPhysicalDeviceToolProperties* pToolProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlot( + VkDevice device, + const VkPrivateDataSlotCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPrivateDataSlot* pPrivateDataSlot); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlot( + VkDevice device, + VkPrivateDataSlot privateDataSlot, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateData( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t data); + +VKAPI_ATTR void VKAPI_CALL vkGetPrivateData( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2( + VkCommandBuffer commandBuffer, + const VkDependencyInfo* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2 stage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo2* pSubmits, + VkFence fence); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2( + VkCommandBuffer commandBuffer, + const VkCopyBufferInfo2* pCopyBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2* pCopyImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirements( + VkDevice device, + const VkDeviceBufferMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirements( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirements( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfo* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2 stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfo* pDependencyInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2( + VkCommandBuffer commandBuffer, + const VkBlitImageInfo2* pBlitImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2* pResolveImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRendering( + VkCommandBuffer commandBuffer, + const VkRenderingInfo* pRenderingInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRendering( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetCullMode( + VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFace( + VkCommandBuffer commandBuffer, + VkFrontFace frontFace); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopology( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCount( + VkCommandBuffer commandBuffer, + uint32_t viewportCount, + const VkViewport* pViewports); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCount( + VkCommandBuffer commandBuffer, + uint32_t scissorCount, + const VkRect2D* pScissors); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes, + const VkDeviceSize* pStrides); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOp( + VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnable( + VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOp( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnable( + VkCommandBuffer commandBuffer, + VkBool32 rasterizerDiscardEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthBiasEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnable( + VkCommandBuffer commandBuffer, + VkBool32 primitiveRestartEnable); +#endif + + +// VK_VERSION_1_4 is a preprocessor guard. Do not pass it to API calls. +#define VK_VERSION_1_4 1 +// Vulkan 1.4 version number +#define VK_API_VERSION_1_4 VK_MAKE_API_VERSION(0, 1, 4, 0)// Patch version should always be set to 0 + +#define VK_MAX_GLOBAL_PRIORITY_SIZE 16U + +typedef enum VkPipelineRobustnessBufferBehavior { + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT = 0, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED = 1, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS = 2, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2 = 3, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2, + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF +} VkPipelineRobustnessBufferBehavior; + +typedef enum VkPipelineRobustnessImageBehavior { + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT = 0, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED = 1, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS = 2, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2 = 3, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT = VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT = VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_EXT = VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2_EXT = VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2, + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF +} VkPipelineRobustnessImageBehavior; + +typedef enum VkQueueGlobalPriority { + VK_QUEUE_GLOBAL_PRIORITY_LOW = 128, + VK_QUEUE_GLOBAL_PRIORITY_MEDIUM = 256, + VK_QUEUE_GLOBAL_PRIORITY_HIGH = 512, + VK_QUEUE_GLOBAL_PRIORITY_REALTIME = 1024, + VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT = VK_QUEUE_GLOBAL_PRIORITY_LOW, + VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM, + VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT = VK_QUEUE_GLOBAL_PRIORITY_HIGH, + VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = VK_QUEUE_GLOBAL_PRIORITY_REALTIME, + VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR = VK_QUEUE_GLOBAL_PRIORITY_LOW, + VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM, + VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR = VK_QUEUE_GLOBAL_PRIORITY_HIGH, + VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR = VK_QUEUE_GLOBAL_PRIORITY_REALTIME, + VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM = 0x7FFFFFFF +} VkQueueGlobalPriority; + +typedef enum VkLineRasterizationMode { + VK_LINE_RASTERIZATION_MODE_DEFAULT = 0, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR = 1, + VK_LINE_RASTERIZATION_MODE_BRESENHAM = 2, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH = 3, + VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT = VK_LINE_RASTERIZATION_MODE_DEFAULT, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = VK_LINE_RASTERIZATION_MODE_RECTANGULAR, + VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = VK_LINE_RASTERIZATION_MODE_BRESENHAM, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH, + VK_LINE_RASTERIZATION_MODE_DEFAULT_KHR = VK_LINE_RASTERIZATION_MODE_DEFAULT, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_KHR = VK_LINE_RASTERIZATION_MODE_RECTANGULAR, + VK_LINE_RASTERIZATION_MODE_BRESENHAM_KHR = VK_LINE_RASTERIZATION_MODE_BRESENHAM, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_KHR = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH, + VK_LINE_RASTERIZATION_MODE_MAX_ENUM = 0x7FFFFFFF +} VkLineRasterizationMode; + +typedef enum VkMemoryUnmapFlagBits { + VK_MEMORY_UNMAP_RESERVE_BIT_EXT = 0x00000001, + VK_MEMORY_UNMAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryUnmapFlagBits; +typedef VkFlags VkMemoryUnmapFlags; +typedef VkFlags64 VkBufferUsageFlags2; + +// Flag bits for VkBufferUsageFlagBits2 +typedef VkFlags64 VkBufferUsageFlagBits2; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT = 0x00000001ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_DST_BIT = 0x00000002ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT = 0x00000008ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT = 0x00000010ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT = 0x00000020ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT = 0x00000040ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT = 0x00000080ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT = 0x00000100ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT = 0x00020000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_EXECUTION_GRAPH_SCRATCH_BIT_AMDX = 0x02000000ULL; +#endif +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT = 0x10000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0x00800000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_MICROMAP_STORAGE_BIT_EXT = 0x01000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT_KHR = 0x00000001ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_DST_BIT_KHR = 0x00000002ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000004ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR = 0x00000010ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR = 0x00000020ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR = 0x00000040ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR = 0x00000080ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR = 0x00000100ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_RAY_TRACING_BIT_NV = 0x00000400ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR = 0x00004000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR = 0x00008000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR = 0x00020000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT = 0x00200000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00400000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0x04000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_COMPRESSED_DATA_DGF1_BIT_AMDX = 0x200000000ULL; +#endif +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_DATA_GRAPH_FOREIGN_DESCRIPTOR_BIT_ARM = 0x20000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TILE_MEMORY_BIT_QCOM = 0x08000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT = 0x100000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_PREPROCESS_BUFFER_BIT_EXT = 0x80000000ULL; + + +typedef enum VkHostImageCopyFlagBits { + VK_HOST_IMAGE_COPY_MEMCPY_BIT = 0x00000001, + // VK_HOST_IMAGE_COPY_MEMCPY is a legacy alias + VK_HOST_IMAGE_COPY_MEMCPY = VK_HOST_IMAGE_COPY_MEMCPY_BIT, + VK_HOST_IMAGE_COPY_MEMCPY_BIT_EXT = VK_HOST_IMAGE_COPY_MEMCPY_BIT, + // VK_HOST_IMAGE_COPY_MEMCPY_EXT is a legacy alias + VK_HOST_IMAGE_COPY_MEMCPY_EXT = VK_HOST_IMAGE_COPY_MEMCPY_BIT, + VK_HOST_IMAGE_COPY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkHostImageCopyFlagBits; +typedef VkFlags VkHostImageCopyFlags; +typedef VkFlags64 VkPipelineCreateFlags2; + +// Flag bits for VkPipelineCreateFlagBits2 +typedef VkFlags64 VkPipelineCreateFlagBits2; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT = 0x00000001ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_ALLOW_DERIVATIVES_BIT = 0x00000002ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DERIVATIVE_BIT = 0x00000004ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DISPATCH_BASE_BIT = 0x00000010ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT = 0x00000100ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT = 0x00000200ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_BIT = 0x08000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT = 0x40000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_EXECUTION_GRAPH_BIT_AMDX = 0x100000000ULL; +#endif +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT = 0x1000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_BUILT_IN_PRIMITIVES_BIT_KHR = 0x00001000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0x01000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_SPHERES_AND_LINEAR_SWEPT_SPHERES_BIT_NV = 0x200000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x400000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT_KHR = 0x00000001ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_ALLOW_DERIVATIVES_BIT_KHR = 0x00000002ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DERIVATIVE_BIT_KHR = 0x00000004ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = 0x00000008ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DISPATCH_BASE_BIT_KHR = 0x00000010ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DEFER_COMPILE_BIT_NV = 0x00000020ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_CAPTURE_STATISTICS_BIT_KHR = 0x00000040ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR = 0x00000100ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT_KHR = 0x00000200ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT = 0x00000400ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT = 0x00800000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR = 0x00000800ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0x00080000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_NV = 0x00040000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x02000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x04000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_BIT_EXT = 0x08000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT_EXT = 0x40000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000ULL; +#endif +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT = 0x20000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DISALLOW_OPACITY_MICROMAP_BIT_ARM = 0x2000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_INSTRUMENT_SHADERS_BIT_ARM = 0x8000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_CAPTURE_DATA_BIT_KHR = 0x80000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT = 0x4000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_PER_LAYER_FRAGMENT_DENSITY_BIT_VALVE = 0x10000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_KHR = 0x01000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_OPACITY_MICROMAP_DISALLOW_MIXED_SPECIAL_INDEX_BIT_KHR = 0x20000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_64_BIT_INDEXING_BIT_EXT = 0x80000000000ULL; + +typedef struct VkPhysicalDeviceVulkan14Features { + VkStructureType sType; + void* pNext; + VkBool32 globalPriorityQuery; + VkBool32 shaderSubgroupRotate; + VkBool32 shaderSubgroupRotateClustered; + VkBool32 shaderFloatControls2; + VkBool32 shaderExpectAssume; + VkBool32 rectangularLines; + VkBool32 bresenhamLines; + VkBool32 smoothLines; + VkBool32 stippledRectangularLines; + VkBool32 stippledBresenhamLines; + VkBool32 stippledSmoothLines; + VkBool32 vertexAttributeInstanceRateDivisor; + VkBool32 vertexAttributeInstanceRateZeroDivisor; + VkBool32 indexTypeUint8; + VkBool32 dynamicRenderingLocalRead; + VkBool32 maintenance5; + VkBool32 maintenance6; + VkBool32 pipelineProtectedAccess; + VkBool32 pipelineRobustness; + VkBool32 hostImageCopy; + VkBool32 pushDescriptor; +} VkPhysicalDeviceVulkan14Features; + +typedef struct VkPhysicalDeviceVulkan14Properties { + VkStructureType sType; + void* pNext; + uint32_t lineSubPixelPrecisionBits; + uint32_t maxVertexAttribDivisor; + VkBool32 supportsNonZeroFirstInstance; + uint32_t maxPushDescriptors; + VkBool32 dynamicRenderingLocalReadDepthStencilAttachments; + VkBool32 dynamicRenderingLocalReadMultisampledAttachments; + VkBool32 earlyFragmentMultisampleCoverageAfterSampleCounting; + VkBool32 earlyFragmentSampleMaskTestBeforeSampleCounting; + VkBool32 depthStencilSwizzleOneSupport; + VkBool32 polygonModePointSize; + VkBool32 nonStrictSinglePixelWideLinesUseParallelogram; + VkBool32 nonStrictWideLinesUseParallelogram; + VkBool32 blockTexelViewCompatibleMultipleLayers; + uint32_t maxCombinedImageSamplerDescriptorCount; + VkBool32 fragmentShadingRateClampCombinerInputs; + VkPipelineRobustnessBufferBehavior defaultRobustnessStorageBuffers; + VkPipelineRobustnessBufferBehavior defaultRobustnessUniformBuffers; + VkPipelineRobustnessBufferBehavior defaultRobustnessVertexInputs; + VkPipelineRobustnessImageBehavior defaultRobustnessImages; + uint32_t copySrcLayoutCount; + VkImageLayout* pCopySrcLayouts; + uint32_t copyDstLayoutCount; + VkImageLayout* pCopyDstLayouts; + uint8_t optimalTilingLayoutUUID[VK_UUID_SIZE]; + VkBool32 identicalMemoryTypeRequirements; +} VkPhysicalDeviceVulkan14Properties; + +typedef struct VkDeviceQueueGlobalPriorityCreateInfo { + VkStructureType sType; + const void* pNext; + VkQueueGlobalPriority globalPriority; +} VkDeviceQueueGlobalPriorityCreateInfo; + +typedef struct VkPhysicalDeviceGlobalPriorityQueryFeatures { + VkStructureType sType; + void* pNext; + VkBool32 globalPriorityQuery; +} VkPhysicalDeviceGlobalPriorityQueryFeatures; + +typedef struct VkQueueFamilyGlobalPriorityProperties { + VkStructureType sType; + void* pNext; + uint32_t priorityCount; + VkQueueGlobalPriority priorities[VK_MAX_GLOBAL_PRIORITY_SIZE]; +} VkQueueFamilyGlobalPriorityProperties; + +typedef struct VkPhysicalDeviceIndexTypeUint8Features { + VkStructureType sType; + void* pNext; + VkBool32 indexTypeUint8; +} VkPhysicalDeviceIndexTypeUint8Features; + +typedef struct VkMemoryMapInfo { + VkStructureType sType; + const void* pNext; + VkMemoryMapFlags flags; + VkDeviceMemory memory; + VkDeviceSize offset; + VkDeviceSize size; +} VkMemoryMapInfo; + +typedef struct VkMemoryUnmapInfo { + VkStructureType sType; + const void* pNext; + VkMemoryUnmapFlags flags; + VkDeviceMemory memory; +} VkMemoryUnmapInfo; + +typedef struct VkPhysicalDeviceMaintenance5Features { + VkStructureType sType; + void* pNext; + VkBool32 maintenance5; +} VkPhysicalDeviceMaintenance5Features; + +typedef struct VkPhysicalDeviceMaintenance5Properties { + VkStructureType sType; + void* pNext; + VkBool32 earlyFragmentMultisampleCoverageAfterSampleCounting; + VkBool32 earlyFragmentSampleMaskTestBeforeSampleCounting; + VkBool32 depthStencilSwizzleOneSupport; + VkBool32 polygonModePointSize; + VkBool32 nonStrictSinglePixelWideLinesUseParallelogram; + VkBool32 nonStrictWideLinesUseParallelogram; +} VkPhysicalDeviceMaintenance5Properties; + +typedef struct VkSubresourceLayout2 { + VkStructureType sType; + void* pNext; + VkSubresourceLayout subresourceLayout; +} VkSubresourceLayout2; + +typedef struct VkImageSubresource2 { + VkStructureType sType; + void* pNext; + VkImageSubresource imageSubresource; +} VkImageSubresource2; + +typedef struct VkDeviceImageSubresourceInfo { + VkStructureType sType; + const void* pNext; + const VkImageCreateInfo* pCreateInfo; + const VkImageSubresource2* pSubresource; +} VkDeviceImageSubresourceInfo; + +typedef struct VkBufferUsageFlags2CreateInfo { + VkStructureType sType; + const void* pNext; + VkBufferUsageFlags2 usage; +} VkBufferUsageFlags2CreateInfo; + +typedef struct VkPhysicalDeviceMaintenance6Features { + VkStructureType sType; + void* pNext; + VkBool32 maintenance6; +} VkPhysicalDeviceMaintenance6Features; + +typedef struct VkPhysicalDeviceMaintenance6Properties { + VkStructureType sType; + void* pNext; + VkBool32 blockTexelViewCompatibleMultipleLayers; + uint32_t maxCombinedImageSamplerDescriptorCount; + VkBool32 fragmentShadingRateClampCombinerInputs; +} VkPhysicalDeviceMaintenance6Properties; + +typedef struct VkBindMemoryStatus { + VkStructureType sType; + const void* pNext; + VkResult* pResult; +} VkBindMemoryStatus; + +typedef struct VkPhysicalDeviceHostImageCopyFeatures { + VkStructureType sType; + void* pNext; + VkBool32 hostImageCopy; +} VkPhysicalDeviceHostImageCopyFeatures; + +typedef struct VkPhysicalDeviceHostImageCopyProperties { + VkStructureType sType; + void* pNext; + uint32_t copySrcLayoutCount; + VkImageLayout* pCopySrcLayouts; + uint32_t copyDstLayoutCount; + VkImageLayout* pCopyDstLayouts; + uint8_t optimalTilingLayoutUUID[VK_UUID_SIZE]; + VkBool32 identicalMemoryTypeRequirements; +} VkPhysicalDeviceHostImageCopyProperties; + +typedef struct VkMemoryToImageCopy { + VkStructureType sType; + const void* pNext; + const void* pHostPointer; + uint32_t memoryRowLength; + uint32_t memoryImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkMemoryToImageCopy; + +typedef struct VkImageToMemoryCopy { + VkStructureType sType; + const void* pNext; + void* pHostPointer; + uint32_t memoryRowLength; + uint32_t memoryImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkImageToMemoryCopy; + +typedef struct VkCopyMemoryToImageInfo { + VkStructureType sType; + const void* pNext; + VkHostImageCopyFlags flags; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkMemoryToImageCopy* pRegions; +} VkCopyMemoryToImageInfo; + +typedef struct VkCopyImageToMemoryInfo { + VkStructureType sType; + const void* pNext; + VkHostImageCopyFlags flags; + VkImage srcImage; + VkImageLayout srcImageLayout; + uint32_t regionCount; + const VkImageToMemoryCopy* pRegions; +} VkCopyImageToMemoryInfo; + +typedef struct VkCopyImageToImageInfo { + VkStructureType sType; + const void* pNext; + VkHostImageCopyFlags flags; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageCopy2* pRegions; +} VkCopyImageToImageInfo; + +typedef struct VkHostImageLayoutTransitionInfo { + VkStructureType sType; + const void* pNext; + VkImage image; + VkImageLayout oldLayout; + VkImageLayout newLayout; + VkImageSubresourceRange subresourceRange; +} VkHostImageLayoutTransitionInfo; + +typedef struct VkSubresourceHostMemcpySize { + VkStructureType sType; + void* pNext; + VkDeviceSize size; +} VkSubresourceHostMemcpySize; + +typedef struct VkHostImageCopyDevicePerformanceQuery { + VkStructureType sType; + void* pNext; + VkBool32 optimalDeviceAccess; + VkBool32 identicalMemoryLayout; +} VkHostImageCopyDevicePerformanceQuery; + +typedef struct VkPhysicalDeviceShaderSubgroupRotateFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupRotate; + VkBool32 shaderSubgroupRotateClustered; +} VkPhysicalDeviceShaderSubgroupRotateFeatures; + +typedef struct VkPhysicalDeviceShaderFloatControls2Features { + VkStructureType sType; + void* pNext; + VkBool32 shaderFloatControls2; +} VkPhysicalDeviceShaderFloatControls2Features; + +typedef struct VkPhysicalDeviceShaderExpectAssumeFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderExpectAssume; +} VkPhysicalDeviceShaderExpectAssumeFeatures; + +typedef struct VkPipelineCreateFlags2CreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags2 flags; +} VkPipelineCreateFlags2CreateInfo; + +typedef struct VkPhysicalDevicePushDescriptorProperties { + VkStructureType sType; + void* pNext; + uint32_t maxPushDescriptors; +} VkPhysicalDevicePushDescriptorProperties; + +typedef struct VkBindDescriptorSetsInfo { + VkStructureType sType; + const void* pNext; + VkShaderStageFlags stageFlags; + VkPipelineLayout layout; + uint32_t firstSet; + uint32_t descriptorSetCount; + const VkDescriptorSet* pDescriptorSets; + uint32_t dynamicOffsetCount; + const uint32_t* pDynamicOffsets; +} VkBindDescriptorSetsInfo; + +typedef struct VkPushConstantsInfo { + VkStructureType sType; + const void* pNext; + VkPipelineLayout layout; + VkShaderStageFlags stageFlags; + uint32_t offset; + uint32_t size; + const void* pValues; +} VkPushConstantsInfo; + +typedef struct VkPushDescriptorSetInfo { + VkStructureType sType; + const void* pNext; + VkShaderStageFlags stageFlags; + VkPipelineLayout layout; + uint32_t set; + uint32_t descriptorWriteCount; + const VkWriteDescriptorSet* pDescriptorWrites; +} VkPushDescriptorSetInfo; + +typedef struct VkPushDescriptorSetWithTemplateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorUpdateTemplate descriptorUpdateTemplate; + VkPipelineLayout layout; + uint32_t set; + const void* pData; +} VkPushDescriptorSetWithTemplateInfo; + +typedef struct VkPhysicalDevicePipelineProtectedAccessFeatures { + VkStructureType sType; + void* pNext; + VkBool32 pipelineProtectedAccess; +} VkPhysicalDevicePipelineProtectedAccessFeatures; + +typedef struct VkPhysicalDevicePipelineRobustnessFeatures { + VkStructureType sType; + void* pNext; + VkBool32 pipelineRobustness; +} VkPhysicalDevicePipelineRobustnessFeatures; + +typedef struct VkPhysicalDevicePipelineRobustnessProperties { + VkStructureType sType; + void* pNext; + VkPipelineRobustnessBufferBehavior defaultRobustnessStorageBuffers; + VkPipelineRobustnessBufferBehavior defaultRobustnessUniformBuffers; + VkPipelineRobustnessBufferBehavior defaultRobustnessVertexInputs; + VkPipelineRobustnessImageBehavior defaultRobustnessImages; +} VkPhysicalDevicePipelineRobustnessProperties; + +typedef struct VkPipelineRobustnessCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineRobustnessBufferBehavior storageBuffers; + VkPipelineRobustnessBufferBehavior uniformBuffers; + VkPipelineRobustnessBufferBehavior vertexInputs; + VkPipelineRobustnessImageBehavior images; +} VkPipelineRobustnessCreateInfo; + +typedef struct VkPhysicalDeviceLineRasterizationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 rectangularLines; + VkBool32 bresenhamLines; + VkBool32 smoothLines; + VkBool32 stippledRectangularLines; + VkBool32 stippledBresenhamLines; + VkBool32 stippledSmoothLines; +} VkPhysicalDeviceLineRasterizationFeatures; + +typedef struct VkPhysicalDeviceLineRasterizationProperties { + VkStructureType sType; + void* pNext; + uint32_t lineSubPixelPrecisionBits; +} VkPhysicalDeviceLineRasterizationProperties; + +typedef struct VkPipelineRasterizationLineStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkLineRasterizationMode lineRasterizationMode; + VkBool32 stippledLineEnable; + uint32_t lineStippleFactor; + uint16_t lineStipplePattern; +} VkPipelineRasterizationLineStateCreateInfo; + +typedef struct VkPhysicalDeviceVertexAttributeDivisorProperties { + VkStructureType sType; + void* pNext; + uint32_t maxVertexAttribDivisor; + VkBool32 supportsNonZeroFirstInstance; +} VkPhysicalDeviceVertexAttributeDivisorProperties; + +typedef struct VkVertexInputBindingDivisorDescription { + uint32_t binding; + uint32_t divisor; +} VkVertexInputBindingDivisorDescription; + +typedef struct VkPipelineVertexInputDivisorStateCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t vertexBindingDivisorCount; + const VkVertexInputBindingDivisorDescription* pVertexBindingDivisors; +} VkPipelineVertexInputDivisorStateCreateInfo; + +typedef struct VkPhysicalDeviceVertexAttributeDivisorFeatures { + VkStructureType sType; + void* pNext; + VkBool32 vertexAttributeInstanceRateDivisor; + VkBool32 vertexAttributeInstanceRateZeroDivisor; +} VkPhysicalDeviceVertexAttributeDivisorFeatures; + +typedef struct VkRenderingAreaInfo { + VkStructureType sType; + const void* pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkRenderingAreaInfo; + +typedef struct VkPhysicalDeviceDynamicRenderingLocalReadFeatures { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRenderingLocalRead; +} VkPhysicalDeviceDynamicRenderingLocalReadFeatures; + +typedef struct VkRenderingAttachmentLocationInfo { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const uint32_t* pColorAttachmentLocations; +} VkRenderingAttachmentLocationInfo; + +typedef struct VkRenderingInputAttachmentIndexInfo { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const uint32_t* pColorAttachmentInputIndices; + const uint32_t* pDepthInputAttachmentIndex; + const uint32_t* pStencilInputAttachmentIndex; +} VkRenderingInputAttachmentIndexInfo; + +typedef VkResult (VKAPI_PTR *PFN_vkMapMemory2)(VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData); +typedef VkResult (VKAPI_PTR *PFN_vkUnmapMemory2)(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSubresourceLayout)(VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, VkSubresourceLayout2* pLayout); +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2)(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToImage)(VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToMemory)(VkDevice device, const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToImage)(VkDevice device, const VkCopyImageToImageInfo* pCopyImageToImageInfo); +typedef VkResult (VKAPI_PTR *PFN_vkTransitionImageLayout)(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSet)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplate)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets2)(VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushConstants2)(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSet2)(VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplate2)(VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo); +typedef void (VKAPI_PTR *PFN_vkCmdSetLineStipple)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); +typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer2)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType); +typedef void (VKAPI_PTR *PFN_vkGetRenderingAreaGranularity)(VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity); +typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingAttachmentLocations)(VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo); +typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingInputAttachmentIndices)(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory2( + VkDevice device, + const VkMemoryMapInfo* pMemoryMapInfo, + void** ppData); + +VKAPI_ATTR VkResult VKAPI_CALL vkUnmapMemory2( + VkDevice device, + const VkMemoryUnmapInfo* pMemoryUnmapInfo); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSubresourceLayout( + VkDevice device, + const VkDeviceImageSubresourceInfo* pInfo, + VkSubresourceLayout2* pLayout); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2( + VkDevice device, + VkImage image, + const VkImageSubresource2* pSubresource, + VkSubresourceLayout2* pLayout); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToImage( + VkDevice device, + const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToMemory( + VkDevice device, + const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToImage( + VkDevice device, + const VkCopyImageToImageInfo* pCopyImageToImageInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkTransitionImageLayout( + VkDevice device, + uint32_t transitionCount, + const VkHostImageLayoutTransitionInfo* pTransitions); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSet( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplate( + VkCommandBuffer commandBuffer, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets2( + VkCommandBuffer commandBuffer, + const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants2( + VkCommandBuffer commandBuffer, + const VkPushConstantsInfo* pPushConstantsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSet2( + VkCommandBuffer commandBuffer, + const VkPushDescriptorSetInfo* pPushDescriptorSetInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplate2( + VkCommandBuffer commandBuffer, + const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStipple( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer2( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkIndexType indexType); + +VKAPI_ATTR void VKAPI_CALL vkGetRenderingAreaGranularity( + VkDevice device, + const VkRenderingAreaInfo* pRenderingAreaInfo, + VkExtent2D* pGranularity); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingAttachmentLocations( + VkCommandBuffer commandBuffer, + const VkRenderingAttachmentLocationInfo* pLocationInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingInputAttachmentIndices( + VkCommandBuffer commandBuffer, + const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); +#endif + + +// VK_KHR_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_surface 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) +#define VK_KHR_SURFACE_SPEC_VERSION 25 +#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" + +typedef enum VkPresentModeKHR { + 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, + VK_PRESENT_MODE_FIFO_LATEST_READY_KHR = 1000361000, + VK_PRESENT_MODE_FIFO_LATEST_READY_EXT = VK_PRESENT_MODE_FIFO_LATEST_READY_KHR, + VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentModeKHR; + +typedef enum VkColorSpaceKHR { + 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 is legacy, but no reason was given in the API XML + 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, + // VK_COLORSPACE_SRGB_NONLINEAR_KHR is a legacy alias + VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, + // VK_COLOR_SPACE_DCI_P3_LINEAR_EXT is a legacy alias + VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT, + VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkColorSpaceKHR; + +typedef enum VkSurfaceTransformFlagBitsKHR { + VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001, + VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002, + VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004, + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080, + VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, + VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSurfaceTransformFlagBitsKHR; +typedef VkFlags VkSurfaceTransformFlagsKHR; + +typedef enum VkCompositeAlphaFlagBitsKHR { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008, + VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCompositeAlphaFlagBitsKHR; +typedef VkFlags VkCompositeAlphaFlagsKHR; +typedef struct VkSurfaceCapabilitiesKHR { + uint32_t minImageCount; + uint32_t maxImageCount; + VkExtent2D currentExtent; + VkExtent2D minImageExtent; + VkExtent2D maxImageExtent; + uint32_t maxImageArrayLayers; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkSurfaceTransformFlagBitsKHR currentTransform; + VkCompositeAlphaFlagsKHR supportedCompositeAlpha; + VkImageUsageFlags supportedUsageFlags; +} VkSurfaceCapabilitiesKHR; + +typedef struct VkSurfaceFormatKHR { + VkFormat format; + VkColorSpaceKHR colorSpace; +} VkSurfaceFormatKHR; + +typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR( + VkInstance instance, + VkSurfaceKHR surface, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + VkSurfaceKHR surface, + VkBool32* pSupported); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pSurfaceFormatCount, + VkSurfaceFormatKHR* pSurfaceFormats); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pPresentModeCount, + VkPresentModeKHR* pPresentModes); +#endif +#endif + + +// VK_KHR_swapchain is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_swapchain 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) +#define VK_KHR_SWAPCHAIN_SPEC_VERSION 70 +#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" + +typedef enum VkSwapchainCreateFlagBitsKHR { + VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001, + VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002, + VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004, + VK_SWAPCHAIN_CREATE_PRESENT_TIMING_BIT_EXT = 0x00000200, + VK_SWAPCHAIN_CREATE_PRESENT_ID_2_BIT_KHR = 0x00000040, + VK_SWAPCHAIN_CREATE_PRESENT_WAIT_2_BIT_KHR = 0x00000080, + VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_KHR = 0x00000008, + VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT = VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_KHR, + VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSwapchainCreateFlagBitsKHR; +typedef VkFlags VkSwapchainCreateFlagsKHR; + +typedef enum VkDeviceGroupPresentModeFlagBitsKHR { + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0x00000001, + VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0x00000002, + VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0x00000004, + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008, + VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceGroupPresentModeFlagBitsKHR; +typedef VkFlags VkDeviceGroupPresentModeFlagsKHR; +typedef struct VkSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainCreateFlagsKHR flags; + VkSurfaceKHR surface; + uint32_t minImageCount; + VkFormat imageFormat; + VkColorSpaceKHR imageColorSpace; + VkExtent2D imageExtent; + uint32_t imageArrayLayers; + VkImageUsageFlags imageUsage; + VkSharingMode imageSharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; + VkSurfaceTransformFlagBitsKHR preTransform; + VkCompositeAlphaFlagBitsKHR compositeAlpha; + VkPresentModeKHR presentMode; + VkBool32 clipped; + VkSwapchainKHR oldSwapchain; +} VkSwapchainCreateInfoKHR; + +typedef struct VkPresentInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + uint32_t swapchainCount; + const VkSwapchainKHR* pSwapchains; + const uint32_t* pImageIndices; + VkResult* pResults; +} VkPresentInfoKHR; + +typedef struct VkImageSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; +} VkImageSwapchainCreateInfoKHR; + +typedef struct VkBindImageMemorySwapchainInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint32_t imageIndex; +} VkBindImageMemorySwapchainInfoKHR; + +typedef struct VkAcquireNextImageInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint64_t timeout; + VkSemaphore semaphore; + VkFence fence; + uint32_t deviceMask; +} VkAcquireNextImageInfoKHR; + +typedef struct VkDeviceGroupPresentCapabilitiesKHR { + VkStructureType sType; + void* pNext; + uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE]; + VkDeviceGroupPresentModeFlagsKHR modes; +} VkDeviceGroupPresentCapabilitiesKHR; + +typedef struct VkDeviceGroupPresentInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint32_t* pDeviceMasks; + VkDeviceGroupPresentModeFlagBitsKHR mode; +} VkDeviceGroupPresentInfoKHR; + +typedef struct VkDeviceGroupSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceGroupPresentModeFlagsKHR modes; +} VkDeviceGroupSwapchainCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain); +typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex); +typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( + VkDevice device, + const VkSwapchainCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchain); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR( + VkDevice device, + VkSwapchainKHR swapchain, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pSwapchainImageCount, + VkImage* pSwapchainImages); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t timeout, + VkSemaphore semaphore, + VkFence fence, + uint32_t* pImageIndex); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( + VkQueue queue, + const VkPresentInfoKHR* pPresentInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR( + VkDevice device, + VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR( + VkDevice device, + VkSurfaceKHR surface, + VkDeviceGroupPresentModeFlagsKHR* pModes); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pRectCount, + VkRect2D* pRects); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR( + VkDevice device, + const VkAcquireNextImageInfoKHR* pAcquireInfo, + uint32_t* pImageIndex); +#endif +#endif + + +// VK_KHR_display is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_display 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR) +#define VK_KHR_DISPLAY_SPEC_VERSION 23 +#define VK_KHR_DISPLAY_EXTENSION_NAME "VK_KHR_display" +typedef VkFlags VkDisplayModeCreateFlagsKHR; + +typedef enum VkDisplayPlaneAlphaFlagBitsKHR { + VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, + VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008, + VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDisplayPlaneAlphaFlagBitsKHR; +typedef VkFlags VkDisplayPlaneAlphaFlagsKHR; +typedef VkFlags VkDisplaySurfaceCreateFlagsKHR; +typedef struct VkDisplayModeParametersKHR { + VkExtent2D visibleRegion; + uint32_t refreshRate; +} VkDisplayModeParametersKHR; + +typedef struct VkDisplayModeCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDisplayModeCreateFlagsKHR flags; + VkDisplayModeParametersKHR parameters; +} VkDisplayModeCreateInfoKHR; + +typedef struct VkDisplayModePropertiesKHR { + VkDisplayModeKHR displayMode; + VkDisplayModeParametersKHR parameters; +} VkDisplayModePropertiesKHR; + +typedef struct VkDisplayPlaneCapabilitiesKHR { + VkDisplayPlaneAlphaFlagsKHR supportedAlpha; + VkOffset2D minSrcPosition; + VkOffset2D maxSrcPosition; + VkExtent2D minSrcExtent; + VkExtent2D maxSrcExtent; + VkOffset2D minDstPosition; + VkOffset2D maxDstPosition; + VkExtent2D minDstExtent; + VkExtent2D maxDstExtent; +} VkDisplayPlaneCapabilitiesKHR; + +typedef struct VkDisplayPlanePropertiesKHR { + VkDisplayKHR currentDisplay; + uint32_t currentStackIndex; +} VkDisplayPlanePropertiesKHR; + +typedef struct VkDisplayPropertiesKHR { + VkDisplayKHR display; + const char* displayName; + VkExtent2D physicalDimensions; + VkExtent2D physicalResolution; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkBool32 planeReorderPossible; + VkBool32 persistentContent; +} VkDisplayPropertiesKHR; + +typedef struct VkDisplaySurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDisplaySurfaceCreateFlagsKHR flags; + VkDisplayModeKHR displayMode; + uint32_t planeIndex; + uint32_t planeStackIndex; + VkSurfaceTransformFlagBitsKHR transform; + float globalAlpha; + VkDisplayPlaneAlphaFlagBitsKHR alphaMode; + VkExtent2D imageExtent; +} VkDisplaySurfaceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPropertiesKHR* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPlanePropertiesKHR* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR( + VkPhysicalDevice physicalDevice, + uint32_t planeIndex, + uint32_t* pDisplayCount, + VkDisplayKHR* pDisplays); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + uint32_t* pPropertyCount, + VkDisplayModePropertiesKHR* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + const VkDisplayModeCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDisplayModeKHR* pMode); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkDisplayModeKHR mode, + uint32_t planeIndex, + VkDisplayPlaneCapabilitiesKHR* pCapabilities); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR( + VkInstance instance, + const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + + +// VK_KHR_display_swapchain is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_display_swapchain 1 +#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 10 +#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain" +typedef struct VkDisplayPresentInfoKHR { + VkStructureType sType; + const void* pNext; + VkRect2D srcRect; + VkRect2D dstRect; + VkBool32 persistent; +} VkDisplayPresentInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchains); +#endif +#endif + + +// VK_KHR_sampler_mirror_clamp_to_edge is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_sampler_mirror_clamp_to_edge 1 +#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 3 +#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" + + +// VK_KHR_video_queue is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_queue 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionKHR) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionParametersKHR) +#define VK_KHR_VIDEO_QUEUE_SPEC_VERSION 8 +#define VK_KHR_VIDEO_QUEUE_EXTENSION_NAME "VK_KHR_video_queue" + +typedef enum VkQueryResultStatusKHR { + VK_QUERY_RESULT_STATUS_ERROR_KHR = -1, + VK_QUERY_RESULT_STATUS_NOT_READY_KHR = 0, + VK_QUERY_RESULT_STATUS_COMPLETE_KHR = 1, + VK_QUERY_RESULT_STATUS_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_KHR = -1000299000, + VK_QUERY_RESULT_STATUS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkQueryResultStatusKHR; + +typedef enum VkVideoCodecOperationFlagBitsKHR { + VK_VIDEO_CODEC_OPERATION_NONE_KHR = 0, + VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR = 0x00010000, + VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR = 0x00020000, + VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR = 0x00000001, + VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR = 0x00000002, + VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR = 0x00000004, + VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR = 0x00040000, + VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR = 0x00000008, + VK_VIDEO_CODEC_OPERATION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodecOperationFlagBitsKHR; +typedef VkFlags VkVideoCodecOperationFlagsKHR; + +typedef enum VkVideoChromaSubsamplingFlagBitsKHR { + VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR = 0, + VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR = 0x00000001, + VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR = 0x00000002, + VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR = 0x00000004, + VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR = 0x00000008, + VK_VIDEO_CHROMA_SUBSAMPLING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoChromaSubsamplingFlagBitsKHR; +typedef VkFlags VkVideoChromaSubsamplingFlagsKHR; + +typedef enum VkVideoComponentBitDepthFlagBitsKHR { + VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR = 0, + VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR = 0x00000001, + VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR = 0x00000004, + VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR = 0x00000010, + VK_VIDEO_COMPONENT_BIT_DEPTH_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoComponentBitDepthFlagBitsKHR; +typedef VkFlags VkVideoComponentBitDepthFlagsKHR; + +typedef enum VkVideoCapabilityFlagBitsKHR { + VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR = 0x00000001, + VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR = 0x00000002, + VK_VIDEO_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCapabilityFlagBitsKHR; +typedef VkFlags VkVideoCapabilityFlagsKHR; + +typedef enum VkVideoSessionCreateFlagBitsKHR { + VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0x00000001, + VK_VIDEO_SESSION_CREATE_ALLOW_ENCODE_PARAMETER_OPTIMIZATIONS_BIT_KHR = 0x00000002, + VK_VIDEO_SESSION_CREATE_INLINE_QUERIES_BIT_KHR = 0x00000004, + VK_VIDEO_SESSION_CREATE_ALLOW_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR = 0x00000008, + VK_VIDEO_SESSION_CREATE_ALLOW_ENCODE_EMPHASIS_MAP_BIT_KHR = 0x00000010, + VK_VIDEO_SESSION_CREATE_INLINE_SESSION_PARAMETERS_BIT_KHR = 0x00000020, + VK_VIDEO_SESSION_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoSessionCreateFlagBitsKHR; +typedef VkFlags VkVideoSessionCreateFlagsKHR; + +typedef enum VkVideoSessionParametersCreateFlagBitsKHR { + VK_VIDEO_SESSION_PARAMETERS_CREATE_QUANTIZATION_MAP_COMPATIBLE_BIT_KHR = 0x00000001, + VK_VIDEO_SESSION_PARAMETERS_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoSessionParametersCreateFlagBitsKHR; +typedef VkFlags VkVideoSessionParametersCreateFlagsKHR; +typedef VkFlags VkVideoBeginCodingFlagsKHR; +typedef VkFlags VkVideoEndCodingFlagsKHR; + +typedef enum VkVideoCodingControlFlagBitsKHR { + VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR = 0x00000001, + VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR = 0x00000002, + VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR = 0x00000004, + VK_VIDEO_CODING_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodingControlFlagBitsKHR; +typedef VkFlags VkVideoCodingControlFlagsKHR; +typedef struct VkQueueFamilyQueryResultStatusPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 queryResultStatusSupport; +} VkQueueFamilyQueryResultStatusPropertiesKHR; + +typedef struct VkQueueFamilyVideoPropertiesKHR { + VkStructureType sType; + void* pNext; + VkVideoCodecOperationFlagsKHR videoCodecOperations; +} VkQueueFamilyVideoPropertiesKHR; + +typedef struct VkVideoProfileInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoCodecOperationFlagBitsKHR videoCodecOperation; + VkVideoChromaSubsamplingFlagsKHR chromaSubsampling; + VkVideoComponentBitDepthFlagsKHR lumaBitDepth; + VkVideoComponentBitDepthFlagsKHR chromaBitDepth; +} VkVideoProfileInfoKHR; + +typedef struct VkVideoProfileListInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t profileCount; + const VkVideoProfileInfoKHR* pProfiles; +} VkVideoProfileListInfoKHR; + +typedef struct VkVideoCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoCapabilityFlagsKHR flags; + VkDeviceSize minBitstreamBufferOffsetAlignment; + VkDeviceSize minBitstreamBufferSizeAlignment; + VkExtent2D pictureAccessGranularity; + VkExtent2D minCodedExtent; + VkExtent2D maxCodedExtent; + uint32_t maxDpbSlots; + uint32_t maxActiveReferencePictures; + VkExtensionProperties stdHeaderVersion; +} VkVideoCapabilitiesKHR; + +typedef struct VkPhysicalDeviceVideoFormatInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageUsageFlags imageUsage; +} VkPhysicalDeviceVideoFormatInfoKHR; + +typedef struct VkVideoFormatPropertiesKHR { + VkStructureType sType; + void* pNext; + VkFormat format; + VkComponentMapping componentMapping; + VkImageCreateFlags imageCreateFlags; + VkImageType imageType; + VkImageTiling imageTiling; + VkImageUsageFlags imageUsageFlags; +} VkVideoFormatPropertiesKHR; + +typedef struct VkVideoPictureResourceInfoKHR { + VkStructureType sType; + const void* pNext; + VkOffset2D codedOffset; + VkExtent2D codedExtent; + uint32_t baseArrayLayer; + VkImageView imageViewBinding; +} VkVideoPictureResourceInfoKHR; + +typedef struct VkVideoReferenceSlotInfoKHR { + VkStructureType sType; + const void* pNext; + int32_t slotIndex; + const VkVideoPictureResourceInfoKHR* pPictureResource; +} VkVideoReferenceSlotInfoKHR; + +typedef struct VkVideoSessionMemoryRequirementsKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryBindIndex; + VkMemoryRequirements memoryRequirements; +} VkVideoSessionMemoryRequirementsKHR; + +typedef struct VkBindVideoSessionMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t memoryBindIndex; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkDeviceSize memorySize; +} VkBindVideoSessionMemoryInfoKHR; + +typedef struct VkVideoSessionCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + VkVideoSessionCreateFlagsKHR flags; + const VkVideoProfileInfoKHR* pVideoProfile; + VkFormat pictureFormat; + VkExtent2D maxCodedExtent; + VkFormat referencePictureFormat; + uint32_t maxDpbSlots; + uint32_t maxActiveReferencePictures; + const VkExtensionProperties* pStdHeaderVersion; +} VkVideoSessionCreateInfoKHR; + +typedef struct VkVideoSessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoSessionParametersCreateFlagsKHR flags; + VkVideoSessionParametersKHR videoSessionParametersTemplate; + VkVideoSessionKHR videoSession; +} VkVideoSessionParametersCreateInfoKHR; + +typedef struct VkVideoSessionParametersUpdateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t updateSequenceCount; +} VkVideoSessionParametersUpdateInfoKHR; + +typedef struct VkVideoBeginCodingInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoBeginCodingFlagsKHR flags; + VkVideoSessionKHR videoSession; + VkVideoSessionParametersKHR videoSessionParameters; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotInfoKHR* pReferenceSlots; +} VkVideoBeginCodingInfoKHR; + +typedef struct VkVideoEndCodingInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEndCodingFlagsKHR flags; +} VkVideoEndCodingInfoKHR; + +typedef struct VkVideoCodingControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoCodingControlFlagsKHR flags; +} VkVideoCodingControlInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)(VkPhysicalDevice physicalDevice, const VkVideoProfileInfoKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, uint32_t* pVideoFormatPropertyCount, VkVideoFormatPropertiesKHR* pVideoFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionKHR)(VkDevice device, const VkVideoSessionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionKHR* pVideoSession); +typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionKHR)(VkDevice device, VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetVideoSessionMemoryRequirementsKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t* pMemoryRequirementsCount, VkVideoSessionMemoryRequirementsKHR* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindVideoSessionMemoryKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t bindSessionMemoryInfoCount, const VkBindVideoSessionMemoryInfoKHR* pBindSessionMemoryInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionParametersKHR)(VkDevice device, const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionParametersKHR* pVideoSessionParameters); +typedef VkResult (VKAPI_PTR *PFN_vkUpdateVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); +typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBeginVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoBeginCodingInfoKHR* pBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoEndCodingInfoKHR* pEndCodingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdControlVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoCodingControlInfoKHR* pCodingControlInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + const VkVideoProfileInfoKHR* pVideoProfile, + VkVideoCapabilitiesKHR* pCapabilities); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoFormatPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, + uint32_t* pVideoFormatPropertyCount, + VkVideoFormatPropertiesKHR* pVideoFormatProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionKHR( + VkDevice device, + const VkVideoSessionCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkVideoSessionKHR* pVideoSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionKHR( + VkDevice device, + VkVideoSessionKHR videoSession, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetVideoSessionMemoryRequirementsKHR( + VkDevice device, + VkVideoSessionKHR videoSession, + uint32_t* pMemoryRequirementsCount, + VkVideoSessionMemoryRequirementsKHR* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindVideoSessionMemoryKHR( + VkDevice device, + VkVideoSessionKHR videoSession, + uint32_t bindSessionMemoryInfoCount, + const VkBindVideoSessionMemoryInfoKHR* pBindSessionMemoryInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionParametersKHR( + VkDevice device, + const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkVideoSessionParametersKHR* pVideoSessionParameters); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkUpdateVideoSessionParametersKHR( + VkDevice device, + VkVideoSessionParametersKHR videoSessionParameters, + const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionParametersKHR( + VkDevice device, + VkVideoSessionParametersKHR videoSessionParameters, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoBeginCodingInfoKHR* pBeginInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoEndCodingInfoKHR* pEndCodingInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdControlVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoCodingControlInfoKHR* pCodingControlInfo); +#endif +#endif + + +// VK_KHR_video_decode_queue is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_decode_queue 1 +#define VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION 8 +#define VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME "VK_KHR_video_decode_queue" + +typedef enum VkVideoDecodeCapabilityFlagBitsKHR { + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR = 0x00000001, + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR = 0x00000002, + VK_VIDEO_DECODE_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoDecodeCapabilityFlagBitsKHR; +typedef VkFlags VkVideoDecodeCapabilityFlagsKHR; + +typedef enum VkVideoDecodeUsageFlagBitsKHR { + VK_VIDEO_DECODE_USAGE_DEFAULT_KHR = 0, + VK_VIDEO_DECODE_USAGE_TRANSCODING_BIT_KHR = 0x00000001, + VK_VIDEO_DECODE_USAGE_OFFLINE_BIT_KHR = 0x00000002, + VK_VIDEO_DECODE_USAGE_STREAMING_BIT_KHR = 0x00000004, + VK_VIDEO_DECODE_USAGE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoDecodeUsageFlagBitsKHR; +typedef VkFlags VkVideoDecodeUsageFlagsKHR; +typedef VkFlags VkVideoDecodeFlagsKHR; +typedef struct VkVideoDecodeCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoDecodeCapabilityFlagsKHR flags; +} VkVideoDecodeCapabilitiesKHR; + +typedef struct VkVideoDecodeUsageInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoDecodeUsageFlagsKHR videoUsageHints; +} VkVideoDecodeUsageInfoKHR; + +typedef struct VkVideoDecodeInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoDecodeFlagsKHR flags; + VkBuffer srcBuffer; + VkDeviceSize srcBufferOffset; + VkDeviceSize srcBufferRange; + VkVideoPictureResourceInfoKHR dstPictureResource; + const VkVideoReferenceSlotInfoKHR* pSetupReferenceSlot; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotInfoKHR* pReferenceSlots; +} VkVideoDecodeInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pDecodeInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR( + VkCommandBuffer commandBuffer, + const VkVideoDecodeInfoKHR* pDecodeInfo); +#endif +#endif + + +// VK_KHR_video_encode_h264 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_encode_h264 1 +#include "vk_video/vulkan_video_codec_h264std.h" +#include "vk_video/vulkan_video_codec_h264std_encode.h" +#define VK_KHR_VIDEO_ENCODE_H264_SPEC_VERSION 14 +#define VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME "VK_KHR_video_encode_h264" + +typedef enum VkVideoEncodeH264CapabilityFlagBitsKHR { + VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR = 0x00000010, + VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR = 0x00000020, + VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR = 0x00000040, + VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR = 0x00000080, + VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR = 0x00000100, + VK_VIDEO_ENCODE_H264_CAPABILITY_B_PICTURE_INTRA_REFRESH_BIT_KHR = 0x00000400, + VK_VIDEO_ENCODE_H264_CAPABILITY_MB_QP_DIFF_WRAPAROUND_BIT_KHR = 0x00000200, + VK_VIDEO_ENCODE_H264_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeH264CapabilityFlagBitsKHR; +typedef VkFlags VkVideoEncodeH264CapabilityFlagsKHR; + +typedef enum VkVideoEncodeH264StdFlagBitsKHR { + VK_VIDEO_ENCODE_H264_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_H264_STD_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG_SET_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_H264_STD_SCALING_MATRIX_PRESENT_FLAG_SET_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_H264_STD_CHROMA_QP_INDEX_OFFSET_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_H264_STD_SECOND_CHROMA_QP_INDEX_OFFSET_BIT_KHR = 0x00000010, + VK_VIDEO_ENCODE_H264_STD_PIC_INIT_QP_MINUS26_BIT_KHR = 0x00000020, + VK_VIDEO_ENCODE_H264_STD_WEIGHTED_PRED_FLAG_SET_BIT_KHR = 0x00000040, + VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_EXPLICIT_BIT_KHR = 0x00000080, + VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_IMPLICIT_BIT_KHR = 0x00000100, + VK_VIDEO_ENCODE_H264_STD_TRANSFORM_8X8_MODE_FLAG_SET_BIT_KHR = 0x00000200, + VK_VIDEO_ENCODE_H264_STD_DIRECT_SPATIAL_MV_PRED_FLAG_UNSET_BIT_KHR = 0x00000400, + VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_UNSET_BIT_KHR = 0x00000800, + VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_SET_BIT_KHR = 0x00001000, + VK_VIDEO_ENCODE_H264_STD_DIRECT_8X8_INFERENCE_FLAG_UNSET_BIT_KHR = 0x00002000, + VK_VIDEO_ENCODE_H264_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR = 0x00004000, + VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_DISABLED_BIT_KHR = 0x00008000, + VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_ENABLED_BIT_KHR = 0x00010000, + VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_KHR = 0x00020000, + VK_VIDEO_ENCODE_H264_STD_SLICE_QP_DELTA_BIT_KHR = 0x00080000, + VK_VIDEO_ENCODE_H264_STD_DIFFERENT_SLICE_QP_DELTA_BIT_KHR = 0x00100000, + VK_VIDEO_ENCODE_H264_STD_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeH264StdFlagBitsKHR; +typedef VkFlags VkVideoEncodeH264StdFlagsKHR; + +typedef enum VkVideoEncodeH264RateControlFlagBitsKHR { + VK_VIDEO_ENCODE_H264_RATE_CONTROL_ATTEMPT_HRD_COMPLIANCE_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_REGULAR_GOP_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_DYADIC_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_TEMPORAL_LAYER_PATTERN_DYADIC_BIT_KHR = 0x00000010, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeH264RateControlFlagBitsKHR; +typedef VkFlags VkVideoEncodeH264RateControlFlagsKHR; +typedef struct VkVideoEncodeH264CapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeH264CapabilityFlagsKHR flags; + StdVideoH264LevelIdc maxLevelIdc; + uint32_t maxSliceCount; + uint32_t maxPPictureL0ReferenceCount; + uint32_t maxBPictureL0ReferenceCount; + uint32_t maxL1ReferenceCount; + uint32_t maxTemporalLayerCount; + VkBool32 expectDyadicTemporalLayerPattern; + int32_t minQp; + int32_t maxQp; + VkBool32 prefersGopRemainingFrames; + VkBool32 requiresGopRemainingFrames; + VkVideoEncodeH264StdFlagsKHR stdSyntaxFlags; +} VkVideoEncodeH264CapabilitiesKHR; + +typedef struct VkVideoEncodeH264QpKHR { + int32_t qpI; + int32_t qpP; + int32_t qpB; +} VkVideoEncodeH264QpKHR; + +typedef struct VkVideoEncodeH264QualityLevelPropertiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeH264RateControlFlagsKHR preferredRateControlFlags; + uint32_t preferredGopFrameCount; + uint32_t preferredIdrPeriod; + uint32_t preferredConsecutiveBFrameCount; + uint32_t preferredTemporalLayerCount; + VkVideoEncodeH264QpKHR preferredConstantQp; + uint32_t preferredMaxL0ReferenceCount; + uint32_t preferredMaxL1ReferenceCount; + VkBool32 preferredStdEntropyCodingModeFlag; +} VkVideoEncodeH264QualityLevelPropertiesKHR; + +typedef struct VkVideoEncodeH264SessionCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 useMaxLevelIdc; + StdVideoH264LevelIdc maxLevelIdc; +} VkVideoEncodeH264SessionCreateInfoKHR; + +typedef struct VkVideoEncodeH264SessionParametersAddInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t stdSPSCount; + const StdVideoH264SequenceParameterSet* pStdSPSs; + uint32_t stdPPSCount; + const StdVideoH264PictureParameterSet* pStdPPSs; +} VkVideoEncodeH264SessionParametersAddInfoKHR; + +typedef struct VkVideoEncodeH264SessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxStdSPSCount; + uint32_t maxStdPPSCount; + const VkVideoEncodeH264SessionParametersAddInfoKHR* pParametersAddInfo; +} VkVideoEncodeH264SessionParametersCreateInfoKHR; + +typedef struct VkVideoEncodeH264SessionParametersGetInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 writeStdSPS; + VkBool32 writeStdPPS; + uint32_t stdSPSId; + uint32_t stdPPSId; +} VkVideoEncodeH264SessionParametersGetInfoKHR; + +typedef struct VkVideoEncodeH264SessionParametersFeedbackInfoKHR { + VkStructureType sType; + void* pNext; + VkBool32 hasStdSPSOverrides; + VkBool32 hasStdPPSOverrides; +} VkVideoEncodeH264SessionParametersFeedbackInfoKHR; + +typedef struct VkVideoEncodeH264NaluSliceInfoKHR { + VkStructureType sType; + const void* pNext; + int32_t constantQp; + const StdVideoEncodeH264SliceHeader* pStdSliceHeader; +} VkVideoEncodeH264NaluSliceInfoKHR; + +typedef struct VkVideoEncodeH264PictureInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t naluSliceEntryCount; + const VkVideoEncodeH264NaluSliceInfoKHR* pNaluSliceEntries; + const StdVideoEncodeH264PictureInfo* pStdPictureInfo; + VkBool32 generatePrefixNalu; +} VkVideoEncodeH264PictureInfoKHR; + +typedef struct VkVideoEncodeH264DpbSlotInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoEncodeH264ReferenceInfo* pStdReferenceInfo; +} VkVideoEncodeH264DpbSlotInfoKHR; + +typedef struct VkVideoEncodeH264ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoH264ProfileIdc stdProfileIdc; +} VkVideoEncodeH264ProfileInfoKHR; + +typedef struct VkVideoEncodeH264RateControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH264RateControlFlagsKHR flags; + uint32_t gopFrameCount; + uint32_t idrPeriod; + uint32_t consecutiveBFrameCount; + uint32_t temporalLayerCount; +} VkVideoEncodeH264RateControlInfoKHR; + +typedef struct VkVideoEncodeH264FrameSizeKHR { + uint32_t frameISize; + uint32_t framePSize; + uint32_t frameBSize; +} VkVideoEncodeH264FrameSizeKHR; + +typedef struct VkVideoEncodeH264RateControlLayerInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 useMinQp; + VkVideoEncodeH264QpKHR minQp; + VkBool32 useMaxQp; + VkVideoEncodeH264QpKHR maxQp; + VkBool32 useMaxFrameSize; + VkVideoEncodeH264FrameSizeKHR maxFrameSize; +} VkVideoEncodeH264RateControlLayerInfoKHR; + +typedef struct VkVideoEncodeH264GopRemainingFrameInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 useGopRemainingFrames; + uint32_t gopRemainingI; + uint32_t gopRemainingP; + uint32_t gopRemainingB; +} VkVideoEncodeH264GopRemainingFrameInfoKHR; + + + +// VK_KHR_video_encode_h265 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_encode_h265 1 +#include "vk_video/vulkan_video_codec_h265std.h" +#include "vk_video/vulkan_video_codec_h265std_encode.h" +#define VK_KHR_VIDEO_ENCODE_H265_SPEC_VERSION 14 +#define VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME "VK_KHR_video_encode_h265" + +typedef enum VkVideoEncodeH265CapabilityFlagBitsKHR { + VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_H265_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_SEGMENT_TYPE_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR = 0x00000010, + VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR = 0x00000020, + VK_VIDEO_ENCODE_H265_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR = 0x00000040, + VK_VIDEO_ENCODE_H265_CAPABILITY_PER_SLICE_SEGMENT_CONSTANT_QP_BIT_KHR = 0x00000080, + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILES_PER_SLICE_SEGMENT_BIT_KHR = 0x00000100, + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_SEGMENTS_PER_TILE_BIT_KHR = 0x00000200, + VK_VIDEO_ENCODE_H265_CAPABILITY_B_PICTURE_INTRA_REFRESH_BIT_KHR = 0x00000800, + VK_VIDEO_ENCODE_H265_CAPABILITY_CU_QP_DIFF_WRAPAROUND_BIT_KHR = 0x00000400, + VK_VIDEO_ENCODE_H265_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeH265CapabilityFlagBitsKHR; +typedef VkFlags VkVideoEncodeH265CapabilityFlagsKHR; + +typedef enum VkVideoEncodeH265StdFlagBitsKHR { + VK_VIDEO_ENCODE_H265_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_H265_STD_SCALING_LIST_DATA_PRESENT_FLAG_SET_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_H265_STD_PCM_ENABLED_FLAG_SET_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_H265_STD_SPS_TEMPORAL_MVP_ENABLED_FLAG_SET_BIT_KHR = 0x00000010, + VK_VIDEO_ENCODE_H265_STD_INIT_QP_MINUS26_BIT_KHR = 0x00000020, + VK_VIDEO_ENCODE_H265_STD_WEIGHTED_PRED_FLAG_SET_BIT_KHR = 0x00000040, + VK_VIDEO_ENCODE_H265_STD_WEIGHTED_BIPRED_FLAG_SET_BIT_KHR = 0x00000080, + VK_VIDEO_ENCODE_H265_STD_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_KHR = 0x00000100, + VK_VIDEO_ENCODE_H265_STD_SIGN_DATA_HIDING_ENABLED_FLAG_SET_BIT_KHR = 0x00000200, + VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_KHR = 0x00000400, + VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_UNSET_BIT_KHR = 0x00000800, + VK_VIDEO_ENCODE_H265_STD_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG_SET_BIT_KHR = 0x00001000, + VK_VIDEO_ENCODE_H265_STD_TRANSQUANT_BYPASS_ENABLED_FLAG_SET_BIT_KHR = 0x00002000, + VK_VIDEO_ENCODE_H265_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR = 0x00004000, + VK_VIDEO_ENCODE_H265_STD_ENTROPY_CODING_SYNC_ENABLED_FLAG_SET_BIT_KHR = 0x00008000, + VK_VIDEO_ENCODE_H265_STD_DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_SET_BIT_KHR = 0x00010000, + VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG_SET_BIT_KHR = 0x00020000, + VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_KHR = 0x00040000, + VK_VIDEO_ENCODE_H265_STD_SLICE_QP_DELTA_BIT_KHR = 0x00080000, + VK_VIDEO_ENCODE_H265_STD_DIFFERENT_SLICE_QP_DELTA_BIT_KHR = 0x00100000, + VK_VIDEO_ENCODE_H265_STD_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeH265StdFlagBitsKHR; +typedef VkFlags VkVideoEncodeH265StdFlagsKHR; + +typedef enum VkVideoEncodeH265CtbSizeFlagBitsKHR { + VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_H265_CTB_SIZE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeH265CtbSizeFlagBitsKHR; +typedef VkFlags VkVideoEncodeH265CtbSizeFlagsKHR; + +typedef enum VkVideoEncodeH265TransformBlockSizeFlagBitsKHR { + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeH265TransformBlockSizeFlagBitsKHR; +typedef VkFlags VkVideoEncodeH265TransformBlockSizeFlagsKHR; + +typedef enum VkVideoEncodeH265RateControlFlagBitsKHR { + VK_VIDEO_ENCODE_H265_RATE_CONTROL_ATTEMPT_HRD_COMPLIANCE_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_REGULAR_GOP_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_REFERENCE_PATTERN_DYADIC_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_TEMPORAL_SUB_LAYER_PATTERN_DYADIC_BIT_KHR = 0x00000010, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeH265RateControlFlagBitsKHR; +typedef VkFlags VkVideoEncodeH265RateControlFlagsKHR; +typedef struct VkVideoEncodeH265CapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeH265CapabilityFlagsKHR flags; + StdVideoH265LevelIdc maxLevelIdc; + uint32_t maxSliceSegmentCount; + VkExtent2D maxTiles; + VkVideoEncodeH265CtbSizeFlagsKHR ctbSizes; + VkVideoEncodeH265TransformBlockSizeFlagsKHR transformBlockSizes; + uint32_t maxPPictureL0ReferenceCount; + uint32_t maxBPictureL0ReferenceCount; + uint32_t maxL1ReferenceCount; + uint32_t maxSubLayerCount; + VkBool32 expectDyadicTemporalSubLayerPattern; + int32_t minQp; + int32_t maxQp; + VkBool32 prefersGopRemainingFrames; + VkBool32 requiresGopRemainingFrames; + VkVideoEncodeH265StdFlagsKHR stdSyntaxFlags; +} VkVideoEncodeH265CapabilitiesKHR; + +typedef struct VkVideoEncodeH265SessionCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 useMaxLevelIdc; + StdVideoH265LevelIdc maxLevelIdc; +} VkVideoEncodeH265SessionCreateInfoKHR; + +typedef struct VkVideoEncodeH265QpKHR { + int32_t qpI; + int32_t qpP; + int32_t qpB; +} VkVideoEncodeH265QpKHR; + +typedef struct VkVideoEncodeH265QualityLevelPropertiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeH265RateControlFlagsKHR preferredRateControlFlags; + uint32_t preferredGopFrameCount; + uint32_t preferredIdrPeriod; + uint32_t preferredConsecutiveBFrameCount; + uint32_t preferredSubLayerCount; + VkVideoEncodeH265QpKHR preferredConstantQp; + uint32_t preferredMaxL0ReferenceCount; + uint32_t preferredMaxL1ReferenceCount; +} VkVideoEncodeH265QualityLevelPropertiesKHR; + +typedef struct VkVideoEncodeH265SessionParametersAddInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t stdVPSCount; + const StdVideoH265VideoParameterSet* pStdVPSs; + uint32_t stdSPSCount; + const StdVideoH265SequenceParameterSet* pStdSPSs; + uint32_t stdPPSCount; + const StdVideoH265PictureParameterSet* pStdPPSs; +} VkVideoEncodeH265SessionParametersAddInfoKHR; + +typedef struct VkVideoEncodeH265SessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxStdVPSCount; + uint32_t maxStdSPSCount; + uint32_t maxStdPPSCount; + const VkVideoEncodeH265SessionParametersAddInfoKHR* pParametersAddInfo; +} VkVideoEncodeH265SessionParametersCreateInfoKHR; + +typedef struct VkVideoEncodeH265SessionParametersGetInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 writeStdVPS; + VkBool32 writeStdSPS; + VkBool32 writeStdPPS; + uint32_t stdVPSId; + uint32_t stdSPSId; + uint32_t stdPPSId; +} VkVideoEncodeH265SessionParametersGetInfoKHR; + +typedef struct VkVideoEncodeH265SessionParametersFeedbackInfoKHR { + VkStructureType sType; + void* pNext; + VkBool32 hasStdVPSOverrides; + VkBool32 hasStdSPSOverrides; + VkBool32 hasStdPPSOverrides; +} VkVideoEncodeH265SessionParametersFeedbackInfoKHR; + +typedef struct VkVideoEncodeH265NaluSliceSegmentInfoKHR { + VkStructureType sType; + const void* pNext; + int32_t constantQp; + const StdVideoEncodeH265SliceSegmentHeader* pStdSliceSegmentHeader; +} VkVideoEncodeH265NaluSliceSegmentInfoKHR; + +typedef struct VkVideoEncodeH265PictureInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t naluSliceSegmentEntryCount; + const VkVideoEncodeH265NaluSliceSegmentInfoKHR* pNaluSliceSegmentEntries; + const StdVideoEncodeH265PictureInfo* pStdPictureInfo; +} VkVideoEncodeH265PictureInfoKHR; + +typedef struct VkVideoEncodeH265DpbSlotInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoEncodeH265ReferenceInfo* pStdReferenceInfo; +} VkVideoEncodeH265DpbSlotInfoKHR; + +typedef struct VkVideoEncodeH265ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoH265ProfileIdc stdProfileIdc; +} VkVideoEncodeH265ProfileInfoKHR; + +typedef struct VkVideoEncodeH265RateControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH265RateControlFlagsKHR flags; + uint32_t gopFrameCount; + uint32_t idrPeriod; + uint32_t consecutiveBFrameCount; + uint32_t subLayerCount; +} VkVideoEncodeH265RateControlInfoKHR; + +typedef struct VkVideoEncodeH265FrameSizeKHR { + uint32_t frameISize; + uint32_t framePSize; + uint32_t frameBSize; +} VkVideoEncodeH265FrameSizeKHR; + +typedef struct VkVideoEncodeH265RateControlLayerInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 useMinQp; + VkVideoEncodeH265QpKHR minQp; + VkBool32 useMaxQp; + VkVideoEncodeH265QpKHR maxQp; + VkBool32 useMaxFrameSize; + VkVideoEncodeH265FrameSizeKHR maxFrameSize; +} VkVideoEncodeH265RateControlLayerInfoKHR; + +typedef struct VkVideoEncodeH265GopRemainingFrameInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 useGopRemainingFrames; + uint32_t gopRemainingI; + uint32_t gopRemainingP; + uint32_t gopRemainingB; +} VkVideoEncodeH265GopRemainingFrameInfoKHR; + + + +// VK_KHR_video_decode_h264 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_decode_h264 1 +#include "vk_video/vulkan_video_codec_h264std_decode.h" +#define VK_KHR_VIDEO_DECODE_H264_SPEC_VERSION 9 +#define VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME "VK_KHR_video_decode_h264" + +typedef enum VkVideoDecodeH264PictureLayoutFlagBitsKHR { + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR = 0, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR = 0x00000001, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR = 0x00000002, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoDecodeH264PictureLayoutFlagBitsKHR; +typedef VkFlags VkVideoDecodeH264PictureLayoutFlagsKHR; +typedef struct VkVideoDecodeH264ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoH264ProfileIdc stdProfileIdc; + VkVideoDecodeH264PictureLayoutFlagBitsKHR pictureLayout; +} VkVideoDecodeH264ProfileInfoKHR; + +typedef struct VkVideoDecodeH264CapabilitiesKHR { + VkStructureType sType; + void* pNext; + StdVideoH264LevelIdc maxLevelIdc; + VkOffset2D fieldOffsetGranularity; +} VkVideoDecodeH264CapabilitiesKHR; + +typedef struct VkVideoDecodeH264SessionParametersAddInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t stdSPSCount; + const StdVideoH264SequenceParameterSet* pStdSPSs; + uint32_t stdPPSCount; + const StdVideoH264PictureParameterSet* pStdPPSs; +} VkVideoDecodeH264SessionParametersAddInfoKHR; + +typedef struct VkVideoDecodeH264SessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxStdSPSCount; + uint32_t maxStdPPSCount; + const VkVideoDecodeH264SessionParametersAddInfoKHR* pParametersAddInfo; +} VkVideoDecodeH264SessionParametersCreateInfoKHR; + +typedef struct VkVideoDecodeH264PictureInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264PictureInfo* pStdPictureInfo; + uint32_t sliceCount; + const uint32_t* pSliceOffsets; +} VkVideoDecodeH264PictureInfoKHR; + +typedef struct VkVideoDecodeH264DpbSlotInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264ReferenceInfo* pStdReferenceInfo; +} VkVideoDecodeH264DpbSlotInfoKHR; + + + +// VK_KHR_dynamic_rendering is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_dynamic_rendering 1 +#define VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION 1 +#define VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME "VK_KHR_dynamic_rendering" +typedef VkRenderingFlags VkRenderingFlagsKHR; + +typedef VkRenderingFlagBits VkRenderingFlagBitsKHR; + +typedef VkRenderingInfo VkRenderingInfoKHR; + +typedef VkRenderingAttachmentInfo VkRenderingAttachmentInfoKHR; + +typedef VkPipelineRenderingCreateInfo VkPipelineRenderingCreateInfoKHR; + +typedef VkPhysicalDeviceDynamicRenderingFeatures VkPhysicalDeviceDynamicRenderingFeaturesKHR; + +typedef VkCommandBufferInheritanceRenderingInfo VkCommandBufferInheritanceRenderingInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderingKHR)(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderingKHR)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderingKHR( + VkCommandBuffer commandBuffer, + const VkRenderingInfo* pRenderingInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderingKHR( + VkCommandBuffer commandBuffer); +#endif +#endif + + +// VK_KHR_multiview is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_multiview 1 +#define VK_KHR_MULTIVIEW_SPEC_VERSION 1 +#define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview" +typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR; + +typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR; + +typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesKHR; + + + +// VK_KHR_get_physical_device_properties2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_get_physical_device_properties2 1 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 2 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2" +typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR; + +typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR; + +typedef VkFormatProperties2 VkFormatProperties2KHR; + +typedef VkImageFormatProperties2 VkImageFormatProperties2KHR; + +typedef VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR; + +typedef VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR; + +typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR; + +typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR; + +typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR; + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures2* pFeatures); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties2* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties2* pFormatProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, + VkImageFormatProperties2* pImageFormatProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties2* pQueueFamilyProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties2* pProperties); +#endif +#endif + + +// VK_KHR_device_group is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_device_group 1 +#define VK_KHR_DEVICE_GROUP_SPEC_VERSION 4 +#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group" +typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR; + +typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR; + +typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR; + +typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR; + +typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR; + +typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR; + +typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR; + +typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR; + +typedef VkDeviceGroupBindSparseInfo VkDeviceGroupBindSparseInfoKHR; + +typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR; + +typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); +typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR( + VkDevice device, + uint32_t heapIndex, + uint32_t localDeviceIndex, + uint32_t remoteDeviceIndex, + VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR( + VkCommandBuffer commandBuffer, + uint32_t deviceMask); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( + VkCommandBuffer commandBuffer, + uint32_t baseGroupX, + uint32_t baseGroupY, + uint32_t baseGroupZ, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); +#endif +#endif + + +// VK_KHR_shader_draw_parameters is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_draw_parameters 1 +#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1 +#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters" + + +// VK_KHR_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance1 1 +#define VK_KHR_MAINTENANCE_1_SPEC_VERSION 2 +#define VK_KHR_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_maintenance1" +// VK_KHR_MAINTENANCE1_SPEC_VERSION is a legacy alias +#define VK_KHR_MAINTENANCE1_SPEC_VERSION VK_KHR_MAINTENANCE_1_SPEC_VERSION +// VK_KHR_MAINTENANCE1_EXTENSION_NAME is a legacy alias +#define VK_KHR_MAINTENANCE1_EXTENSION_NAME VK_KHR_MAINTENANCE_1_EXTENSION_NAME +typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR; + +typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolTrimFlags flags); +#endif +#endif + + +// VK_KHR_device_group_creation is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_device_group_creation 1 +#define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1 +#define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation" +#define VK_MAX_DEVICE_GROUP_SIZE_KHR VK_MAX_DEVICE_GROUP_SIZE +typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR; + +typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR( + VkInstance instance, + uint32_t* pPhysicalDeviceGroupCount, + VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); +#endif +#endif + + +// VK_KHR_external_memory_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_memory_capabilities 1 +#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities" +#define VK_LUID_SIZE_KHR VK_LUID_SIZE +typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR; + +typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR; + +typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR; + +typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR; + +typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR; + +typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR; + +typedef VkExternalImageFormatProperties VkExternalImageFormatPropertiesKHR; + +typedef VkPhysicalDeviceExternalBufferInfo VkPhysicalDeviceExternalBufferInfoKHR; + +typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR; + +typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, + VkExternalBufferProperties* pExternalBufferProperties); +#endif +#endif + + +// VK_KHR_external_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_memory 1 +#define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory" +#define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL +typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR; + +typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR; + +typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR; + + + +// VK_KHR_external_memory_fd is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_memory_fd 1 +#define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd" +typedef struct VkImportMemoryFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + int fd; +} VkImportMemoryFdInfoKHR; + +typedef struct VkMemoryFdPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryFdPropertiesKHR; + +typedef struct VkMemoryGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetFdInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR( + VkDevice device, + const VkMemoryGetFdInfoKHR* pGetFdInfo, + int* pFd); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + int fd, + VkMemoryFdPropertiesKHR* pMemoryFdProperties); +#endif +#endif + + +// VK_KHR_external_semaphore_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_semaphore_capabilities 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities" +typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR; + +typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR; + +typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR; + +typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR; + +typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR; + +typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, + VkExternalSemaphoreProperties* pExternalSemaphoreProperties); +#endif +#endif + + +// VK_KHR_external_semaphore is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_semaphore 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore" +typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR; + +typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR; + +typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR; + + + +// VK_KHR_external_semaphore_fd is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_semaphore_fd 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd" +typedef struct VkImportSemaphoreFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + int fd; +} VkImportSemaphoreFdInfoKHR; + +typedef struct VkSemaphoreGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetFdInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR( + VkDevice device, + const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR( + VkDevice device, + const VkSemaphoreGetFdInfoKHR* pGetFdInfo, + int* pFd); +#endif +#endif + + +// VK_KHR_push_descriptor is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_push_descriptor 1 +#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2 +#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor" +typedef VkPhysicalDevicePushDescriptorProperties VkPhysicalDevicePushDescriptorPropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( + VkCommandBuffer commandBuffer, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData); +#endif +#endif + + +// VK_KHR_shader_float16_int8 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_float16_int8 1 +#define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1 +#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8" +typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceShaderFloat16Int8FeaturesKHR; + +typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceFloat16Int8FeaturesKHR; + + + +// VK_KHR_16bit_storage is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_16bit_storage 1 +#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1 +#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage" +typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR; + + + +// VK_KHR_incremental_present is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_incremental_present 1 +#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 2 +#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" +typedef struct VkRectLayerKHR { + VkOffset2D offset; + VkExtent2D extent; + uint32_t layer; +} VkRectLayerKHR; + +typedef struct VkPresentRegionKHR { + uint32_t rectangleCount; + const VkRectLayerKHR* pRectangles; +} VkPresentRegionKHR; + +typedef struct VkPresentRegionsKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentRegionKHR* pRegions; +} VkPresentRegionsKHR; + + + +// VK_KHR_descriptor_update_template is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_descriptor_update_template 1 +typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR; + +#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1 +#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template" +typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR; + +typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR; + +typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR; + +typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR( + VkDevice device, + const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR( + VkDevice device, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR( + VkDevice device, + VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const void* pData); +#endif +#endif + + +// VK_KHR_imageless_framebuffer is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_imageless_framebuffer 1 +#define VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION 1 +#define VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME "VK_KHR_imageless_framebuffer" +typedef VkPhysicalDeviceImagelessFramebufferFeatures VkPhysicalDeviceImagelessFramebufferFeaturesKHR; + +typedef VkFramebufferAttachmentsCreateInfo VkFramebufferAttachmentsCreateInfoKHR; + +typedef VkFramebufferAttachmentImageInfo VkFramebufferAttachmentImageInfoKHR; + +typedef VkRenderPassAttachmentBeginInfo VkRenderPassAttachmentBeginInfoKHR; + + + +// VK_KHR_create_renderpass2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_create_renderpass2 1 +#define VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION 1 +#define VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME "VK_KHR_create_renderpass2" +typedef VkRenderPassCreateInfo2 VkRenderPassCreateInfo2KHR; + +typedef VkAttachmentDescription2 VkAttachmentDescription2KHR; + +typedef VkAttachmentReference2 VkAttachmentReference2KHR; + +typedef VkSubpassDescription2 VkSubpassDescription2KHR; + +typedef VkSubpassDependency2 VkSubpassDependency2KHR; + +typedef VkSubpassBeginInfo VkSubpassBeginInfoKHR; + +typedef VkSubpassEndInfo VkSubpassEndInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2KHR)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR( + VkDevice device, + const VkRenderPassCreateInfo2* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + const VkSubpassBeginInfo* pSubpassBeginInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR( + VkCommandBuffer commandBuffer, + const VkSubpassBeginInfo* pSubpassBeginInfo, + const VkSubpassEndInfo* pSubpassEndInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR( + VkCommandBuffer commandBuffer, + const VkSubpassEndInfo* pSubpassEndInfo); +#endif +#endif + + +// VK_KHR_shared_presentable_image is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shared_presentable_image 1 +#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1 +#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image" +typedef struct VkSharedPresentSurfaceCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags sharedPresentSupportedUsageFlags; +} VkSharedPresentSurfaceCapabilitiesKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR( + VkDevice device, + VkSwapchainKHR swapchain); +#endif +#endif + + +// VK_KHR_external_fence_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_fence_capabilities 1 +#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities" +typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR; + +typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR; + +typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR; + +typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR; + +typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR; + +typedef VkExternalFenceProperties VkExternalFencePropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, + VkExternalFenceProperties* pExternalFenceProperties); +#endif +#endif + + +// VK_KHR_external_fence is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_fence 1 +#define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence" +typedef VkFenceImportFlags VkFenceImportFlagsKHR; + +typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR; + +typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR; + + + +// VK_KHR_external_fence_fd is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_fence_fd 1 +#define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd" +typedef struct VkImportFenceFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkFenceImportFlags flags; + VkExternalFenceHandleTypeFlagBits handleType; + int fd; +} VkImportFenceFdInfoKHR; + +typedef struct VkFenceGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkExternalFenceHandleTypeFlagBits handleType; +} VkFenceGetFdInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceFdKHR( + VkDevice device, + const VkImportFenceFdInfoKHR* pImportFenceFdInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR( + VkDevice device, + const VkFenceGetFdInfoKHR* pGetFdInfo, + int* pFd); +#endif +#endif + + +// VK_KHR_performance_query is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_performance_query 1 +#define VK_KHR_PERFORMANCE_QUERY_SPEC_VERSION 1 +#define VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME "VK_KHR_performance_query" + +typedef enum VkPerformanceCounterUnitKHR { + 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, + VK_PERFORMANCE_COUNTER_UNIT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterUnitKHR; + +typedef enum VkPerformanceCounterScopeKHR { + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR = 0, + VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR = 1, + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR = 2, + // VK_QUERY_SCOPE_COMMAND_BUFFER_KHR is a legacy alias + VK_QUERY_SCOPE_COMMAND_BUFFER_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR, + // VK_QUERY_SCOPE_RENDER_PASS_KHR is a legacy alias + VK_QUERY_SCOPE_RENDER_PASS_KHR = VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR, + // VK_QUERY_SCOPE_COMMAND_KHR is a legacy alias + VK_QUERY_SCOPE_COMMAND_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR, + VK_PERFORMANCE_COUNTER_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterScopeKHR; + +typedef enum VkPerformanceCounterStorageKHR { + 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, + VK_PERFORMANCE_COUNTER_STORAGE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterStorageKHR; + +typedef enum VkPerformanceCounterDescriptionFlagBitsKHR { + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0x00000001, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0x00000002, + // VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR is a legacy alias + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR, + // VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR is a legacy alias + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR, + VK_PERFORMANCE_COUNTER_DESCRIPTION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterDescriptionFlagBitsKHR; +typedef VkFlags VkPerformanceCounterDescriptionFlagsKHR; + +typedef enum VkAcquireProfilingLockFlagBitsKHR { + VK_ACQUIRE_PROFILING_LOCK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAcquireProfilingLockFlagBitsKHR; +typedef VkFlags VkAcquireProfilingLockFlagsKHR; +typedef struct VkPhysicalDevicePerformanceQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 performanceCounterQueryPools; + VkBool32 performanceCounterMultipleQueryPools; +} VkPhysicalDevicePerformanceQueryFeaturesKHR; + +typedef struct VkPhysicalDevicePerformanceQueryPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 allowCommandBufferQueryCopies; +} VkPhysicalDevicePerformanceQueryPropertiesKHR; + +typedef struct VkPerformanceCounterKHR { + VkStructureType sType; + void* pNext; + VkPerformanceCounterUnitKHR unit; + VkPerformanceCounterScopeKHR scope; + VkPerformanceCounterStorageKHR storage; + uint8_t uuid[VK_UUID_SIZE]; +} VkPerformanceCounterKHR; + +typedef struct VkPerformanceCounterDescriptionKHR { + VkStructureType sType; + void* pNext; + VkPerformanceCounterDescriptionFlagsKHR flags; + char name[VK_MAX_DESCRIPTION_SIZE]; + char category[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; +} VkPerformanceCounterDescriptionKHR; + +typedef struct VkQueryPoolPerformanceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + uint32_t counterIndexCount; + const uint32_t* pCounterIndices; +} VkQueryPoolPerformanceCreateInfoKHR; + +typedef union VkPerformanceCounterResultKHR { + int32_t int32; + int64_t int64; + uint32_t uint32; + uint64_t uint64; + float float32; + double float64; +} VkPerformanceCounterResultKHR; + +typedef struct VkAcquireProfilingLockInfoKHR { + VkStructureType sType; + const void* pNext; + VkAcquireProfilingLockFlagsKHR flags; + uint64_t timeout; +} VkAcquireProfilingLockInfoKHR; + +typedef struct VkPerformanceQuerySubmitInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t counterPassIndex; +} VkPerformanceQuerySubmitInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterKHR* pCounters, VkPerformanceCounterDescriptionKHR* pCounterDescriptions); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)(VkPhysicalDevice physicalDevice, const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireProfilingLockKHR)(VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkReleaseProfilingLockKHR)(VkDevice device); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + uint32_t* pCounterCount, + VkPerformanceCounterKHR* pCounters, + VkPerformanceCounterDescriptionKHR* pCounterDescriptions); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( + VkPhysicalDevice physicalDevice, + const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, + uint32_t* pNumPasses); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireProfilingLockKHR( + VkDevice device, + const VkAcquireProfilingLockInfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkReleaseProfilingLockKHR( + VkDevice device); +#endif +#endif + + +// VK_KHR_maintenance2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance2 1 +#define VK_KHR_MAINTENANCE_2_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_2_EXTENSION_NAME "VK_KHR_maintenance2" +// VK_KHR_MAINTENANCE2_SPEC_VERSION is a legacy alias +#define VK_KHR_MAINTENANCE2_SPEC_VERSION VK_KHR_MAINTENANCE_2_SPEC_VERSION +// VK_KHR_MAINTENANCE2_EXTENSION_NAME is a legacy alias +#define VK_KHR_MAINTENANCE2_EXTENSION_NAME VK_KHR_MAINTENANCE_2_EXTENSION_NAME +typedef VkPointClippingBehavior VkPointClippingBehaviorKHR; + +typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR; + +typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR; + +typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR; + +typedef VkInputAttachmentAspectReference VkInputAttachmentAspectReferenceKHR; + +typedef VkImageViewUsageCreateInfo VkImageViewUsageCreateInfoKHR; + +typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellationDomainOriginStateCreateInfoKHR; + + + +// VK_KHR_get_surface_capabilities2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_get_surface_capabilities2 1 +#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2" +typedef struct VkPhysicalDeviceSurfaceInfo2KHR { + VkStructureType sType; + const void* pNext; + VkSurfaceKHR surface; +} VkPhysicalDeviceSurfaceInfo2KHR; + +typedef struct VkSurfaceCapabilities2KHR { + VkStructureType sType; + void* pNext; + VkSurfaceCapabilitiesKHR surfaceCapabilities; +} VkSurfaceCapabilities2KHR; + +typedef struct VkSurfaceFormat2KHR { + VkStructureType sType; + void* pNext; + VkSurfaceFormatKHR surfaceFormat; +} VkSurfaceFormat2KHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + VkSurfaceCapabilities2KHR* pSurfaceCapabilities); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + uint32_t* pSurfaceFormatCount, + VkSurfaceFormat2KHR* pSurfaceFormats); +#endif +#endif + + +// VK_KHR_variable_pointers is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_variable_pointers 1 +#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1 +#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers" +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeaturesKHR; + +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointersFeaturesKHR; + + + +// VK_KHR_get_display_properties2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_get_display_properties2 1 +#define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2" +typedef struct VkDisplayProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPropertiesKHR displayProperties; +} VkDisplayProperties2KHR; + +typedef struct VkDisplayPlaneProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPlanePropertiesKHR displayPlaneProperties; +} VkDisplayPlaneProperties2KHR; + +typedef struct VkDisplayModeProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayModePropertiesKHR displayModeProperties; +} VkDisplayModeProperties2KHR; + +typedef struct VkDisplayPlaneInfo2KHR { + VkStructureType sType; + const void* pNext; + VkDisplayModeKHR mode; + uint32_t planeIndex; +} VkDisplayPlaneInfo2KHR; + +typedef struct VkDisplayPlaneCapabilities2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPlaneCapabilitiesKHR capabilities; +} VkDisplayPlaneCapabilities2KHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModeProperties2KHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayProperties2KHR* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPlaneProperties2KHR* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + uint32_t* pPropertyCount, + VkDisplayModeProperties2KHR* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR( + VkPhysicalDevice physicalDevice, + const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, + VkDisplayPlaneCapabilities2KHR* pCapabilities); +#endif +#endif + + +// VK_KHR_dedicated_allocation is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_dedicated_allocation 1 +#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3 +#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation" +typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR; + +typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR; + + + +// VK_KHR_storage_buffer_storage_class is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_storage_buffer_storage_class 1 +#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1 +#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class" + + +// VK_KHR_shader_bfloat16 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_bfloat16 1 +#define VK_KHR_SHADER_BFLOAT16_SPEC_VERSION 1 +#define VK_KHR_SHADER_BFLOAT16_EXTENSION_NAME "VK_KHR_shader_bfloat16" +typedef struct VkPhysicalDeviceShaderBfloat16FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderBFloat16Type; + VkBool32 shaderBFloat16DotProduct; + VkBool32 shaderBFloat16CooperativeMatrix; +} VkPhysicalDeviceShaderBfloat16FeaturesKHR; + + + +// VK_KHR_relaxed_block_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_relaxed_block_layout 1 +#define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout" + + +// VK_KHR_get_memory_requirements2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_get_memory_requirements2 1 +#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1 +#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2" +typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR; + +typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR; + +typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR; + +typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; + +typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR; + +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR( + VkDevice device, + const VkImageMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR( + VkDevice device, + const VkBufferMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR( + VkDevice device, + const VkImageSparseMemoryRequirementsInfo2* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif +#endif + + +// VK_KHR_image_format_list is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_image_format_list 1 +#define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1 +#define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list" +typedef VkImageFormatListCreateInfo VkImageFormatListCreateInfoKHR; + + + +// VK_KHR_sampler_ycbcr_conversion is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_sampler_ycbcr_conversion 1 +typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR; + +#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 14 +#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion" +typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR; + +typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR; + +typedef VkChromaLocation VkChromaLocationKHR; + +typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR; + +typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR; + +typedef VkBindImagePlaneMemoryInfo VkBindImagePlaneMemoryInfoKHR; + +typedef VkImagePlaneMemoryRequirementsInfo VkImagePlaneMemoryRequirementsInfoKHR; + +typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR; + +typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); +typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR( + VkDevice device, + const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSamplerYcbcrConversion* pYcbcrConversion); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR( + VkDevice device, + VkSamplerYcbcrConversion ycbcrConversion, + const VkAllocationCallbacks* pAllocator); +#endif +#endif + + +// VK_KHR_bind_memory2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_bind_memory2 1 +#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1 +#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2" +typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR; + +typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR( + VkDevice device, + uint32_t bindInfoCount, + const VkBindBufferMemoryInfo* pBindInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( + VkDevice device, + uint32_t bindInfoCount, + const VkBindImageMemoryInfo* pBindInfos); +#endif +#endif + + +// VK_KHR_maintenance3 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance3 1 +#define VK_KHR_MAINTENANCE_3_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_3_EXTENSION_NAME "VK_KHR_maintenance3" +// VK_KHR_MAINTENANCE3_SPEC_VERSION is a legacy alias +#define VK_KHR_MAINTENANCE3_SPEC_VERSION VK_KHR_MAINTENANCE_3_SPEC_VERSION +// VK_KHR_MAINTENANCE3_EXTENSION_NAME is a legacy alias +#define VK_KHR_MAINTENANCE3_EXTENSION_NAME VK_KHR_MAINTENANCE_3_EXTENSION_NAME +typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR; + +typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR; + +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + VkDescriptorSetLayoutSupport* pSupport); +#endif +#endif + + +// VK_KHR_draw_indirect_count is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_draw_indirect_count 1 +#define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 +#define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count" +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif +#endif + + +// VK_KHR_shader_subgroup_extended_types is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_subgroup_extended_types 1 +#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION 1 +#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME "VK_KHR_shader_subgroup_extended_types" +typedef VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR; + + + +// VK_KHR_8bit_storage is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_8bit_storage 1 +#define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1 +#define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage" +typedef VkPhysicalDevice8BitStorageFeatures VkPhysicalDevice8BitStorageFeaturesKHR; + + + +// VK_KHR_shader_atomic_int64 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_atomic_int64 1 +#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64" +typedef VkPhysicalDeviceShaderAtomicInt64Features VkPhysicalDeviceShaderAtomicInt64FeaturesKHR; + + + +// VK_KHR_shader_clock is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_clock 1 +#define VK_KHR_SHADER_CLOCK_SPEC_VERSION 1 +#define VK_KHR_SHADER_CLOCK_EXTENSION_NAME "VK_KHR_shader_clock" +typedef struct VkPhysicalDeviceShaderClockFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupClock; + VkBool32 shaderDeviceClock; +} VkPhysicalDeviceShaderClockFeaturesKHR; + + + +// VK_KHR_video_decode_h265 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_decode_h265 1 +#include "vk_video/vulkan_video_codec_h265std_decode.h" +#define VK_KHR_VIDEO_DECODE_H265_SPEC_VERSION 8 +#define VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME "VK_KHR_video_decode_h265" +typedef struct VkVideoDecodeH265ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoH265ProfileIdc stdProfileIdc; +} VkVideoDecodeH265ProfileInfoKHR; + +typedef struct VkVideoDecodeH265CapabilitiesKHR { + VkStructureType sType; + void* pNext; + StdVideoH265LevelIdc maxLevelIdc; +} VkVideoDecodeH265CapabilitiesKHR; + +typedef struct VkVideoDecodeH265SessionParametersAddInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t stdVPSCount; + const StdVideoH265VideoParameterSet* pStdVPSs; + uint32_t stdSPSCount; + const StdVideoH265SequenceParameterSet* pStdSPSs; + uint32_t stdPPSCount; + const StdVideoH265PictureParameterSet* pStdPPSs; +} VkVideoDecodeH265SessionParametersAddInfoKHR; + +typedef struct VkVideoDecodeH265SessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxStdVPSCount; + uint32_t maxStdSPSCount; + uint32_t maxStdPPSCount; + const VkVideoDecodeH265SessionParametersAddInfoKHR* pParametersAddInfo; +} VkVideoDecodeH265SessionParametersCreateInfoKHR; + +typedef struct VkVideoDecodeH265PictureInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH265PictureInfo* pStdPictureInfo; + uint32_t sliceSegmentCount; + const uint32_t* pSliceSegmentOffsets; +} VkVideoDecodeH265PictureInfoKHR; + +typedef struct VkVideoDecodeH265DpbSlotInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH265ReferenceInfo* pStdReferenceInfo; +} VkVideoDecodeH265DpbSlotInfoKHR; + + + +// VK_KHR_global_priority is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_global_priority 1 +#define VK_KHR_GLOBAL_PRIORITY_SPEC_VERSION 1 +#define VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME "VK_KHR_global_priority" +#define VK_MAX_GLOBAL_PRIORITY_SIZE_KHR VK_MAX_GLOBAL_PRIORITY_SIZE +typedef VkQueueGlobalPriority VkQueueGlobalPriorityKHR; + +typedef VkDeviceQueueGlobalPriorityCreateInfo VkDeviceQueueGlobalPriorityCreateInfoKHR; + +typedef VkPhysicalDeviceGlobalPriorityQueryFeatures VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR; + +typedef VkQueueFamilyGlobalPriorityProperties VkQueueFamilyGlobalPriorityPropertiesKHR; + + + +// VK_KHR_driver_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_driver_properties 1 +#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1 +#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties" +#define VK_MAX_DRIVER_NAME_SIZE_KHR VK_MAX_DRIVER_NAME_SIZE +#define VK_MAX_DRIVER_INFO_SIZE_KHR VK_MAX_DRIVER_INFO_SIZE +typedef VkDriverId VkDriverIdKHR; + +typedef VkConformanceVersion VkConformanceVersionKHR; + +typedef VkPhysicalDeviceDriverProperties VkPhysicalDeviceDriverPropertiesKHR; + + + +// VK_KHR_shader_float_controls is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_float_controls 1 +#define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 4 +#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls" +typedef VkShaderFloatControlsIndependence VkShaderFloatControlsIndependenceKHR; + +typedef VkPhysicalDeviceFloatControlsProperties VkPhysicalDeviceFloatControlsPropertiesKHR; + + + +// VK_KHR_depth_stencil_resolve is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_depth_stencil_resolve 1 +#define VK_KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION 1 +#define VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME "VK_KHR_depth_stencil_resolve" +typedef VkResolveModeFlagBits VkResolveModeFlagBitsKHR; + +typedef VkResolveModeFlags VkResolveModeFlagsKHR; + +typedef VkSubpassDescriptionDepthStencilResolve VkSubpassDescriptionDepthStencilResolveKHR; + +typedef VkPhysicalDeviceDepthStencilResolveProperties VkPhysicalDeviceDepthStencilResolvePropertiesKHR; + + + +// VK_KHR_swapchain_mutable_format is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_swapchain_mutable_format 1 +#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1 +#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format" + + +// VK_KHR_timeline_semaphore is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_timeline_semaphore 1 +#define VK_KHR_TIMELINE_SEMAPHORE_SPEC_VERSION 2 +#define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME "VK_KHR_timeline_semaphore" +typedef VkSemaphoreType VkSemaphoreTypeKHR; + +typedef VkSemaphoreWaitFlagBits VkSemaphoreWaitFlagBitsKHR; + +typedef VkSemaphoreWaitFlags VkSemaphoreWaitFlagsKHR; + +typedef VkPhysicalDeviceTimelineSemaphoreFeatures VkPhysicalDeviceTimelineSemaphoreFeaturesKHR; + +typedef VkPhysicalDeviceTimelineSemaphoreProperties VkPhysicalDeviceTimelineSemaphorePropertiesKHR; + +typedef VkSemaphoreTypeCreateInfo VkSemaphoreTypeCreateInfoKHR; + +typedef VkTimelineSemaphoreSubmitInfo VkTimelineSemaphoreSubmitInfoKHR; + +typedef VkSemaphoreWaitInfo VkSemaphoreWaitInfoKHR; + +typedef VkSemaphoreSignalInfo VkSemaphoreSignalInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValueKHR)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue); +typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphoresKHR)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphoreKHR)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValueKHR( + VkDevice device, + VkSemaphore semaphore, + uint64_t* pValue); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphoresKHR( + VkDevice device, + const VkSemaphoreWaitInfo* pWaitInfo, + uint64_t timeout); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphoreKHR( + VkDevice device, + const VkSemaphoreSignalInfo* pSignalInfo); +#endif +#endif + + +// VK_KHR_vulkan_memory_model is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_vulkan_memory_model 1 +#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 3 +#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model" +typedef VkPhysicalDeviceVulkanMemoryModelFeatures VkPhysicalDeviceVulkanMemoryModelFeaturesKHR; + + + +// VK_KHR_shader_terminate_invocation is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_terminate_invocation 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME "VK_KHR_shader_terminate_invocation" +typedef VkPhysicalDeviceShaderTerminateInvocationFeatures VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR; + + + +// VK_KHR_fragment_shading_rate is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_fragment_shading_rate 1 +#define VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION 2 +#define VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME "VK_KHR_fragment_shading_rate" + +typedef enum VkFragmentShadingRateCombinerOpKHR { + 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, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_ENUM_KHR = 0x7FFFFFFF +} VkFragmentShadingRateCombinerOpKHR; +typedef struct VkFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + const VkAttachmentReference2* pFragmentShadingRateAttachment; + VkExtent2D shadingRateAttachmentTexelSize; +} VkFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkPipelineFragmentShadingRateStateCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkExtent2D fragmentSize; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateStateCreateInfoKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineFragmentShadingRate; + VkBool32 primitiveFragmentShadingRate; + VkBool32 attachmentFragmentShadingRate; +} VkPhysicalDeviceFragmentShadingRateFeaturesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRatePropertiesKHR { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentShadingRateAttachmentTexelSize; + VkExtent2D maxFragmentShadingRateAttachmentTexelSize; + uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio; + VkBool32 primitiveFragmentShadingRateWithMultipleViewports; + VkBool32 layeredShadingRateAttachments; + VkBool32 fragmentShadingRateNonTrivialCombinerOps; + VkExtent2D maxFragmentSize; + uint32_t maxFragmentSizeAspectRatio; + uint32_t maxFragmentShadingRateCoverageSamples; + VkSampleCountFlagBits maxFragmentShadingRateRasterizationSamples; + VkBool32 fragmentShadingRateWithShaderDepthStencilWrites; + VkBool32 fragmentShadingRateWithSampleMask; + VkBool32 fragmentShadingRateWithShaderSampleMask; + VkBool32 fragmentShadingRateWithConservativeRasterization; + VkBool32 fragmentShadingRateWithFragmentShaderInterlock; + VkBool32 fragmentShadingRateWithCustomSampleLocations; + VkBool32 fragmentShadingRateStrictMultiplyCombiner; +} VkPhysicalDeviceFragmentShadingRatePropertiesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateKHR { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleCounts; + VkExtent2D fragmentSize; +} VkPhysicalDeviceFragmentShadingRateKHR; + +typedef struct VkRenderingFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkExtent2D shadingRateAttachmentTexelSize; +} VkRenderingFragmentShadingRateAttachmentInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pFragmentShadingRateCount, VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateKHR)(VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceFragmentShadingRatesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pFragmentShadingRateCount, + VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateKHR( + VkCommandBuffer commandBuffer, + const VkExtent2D* pFragmentSize, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif +#endif + + +// VK_KHR_shader_constant_data is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_constant_data 1 +#define VK_KHR_SHADER_CONSTANT_DATA_SPEC_VERSION 1 +#define VK_KHR_SHADER_CONSTANT_DATA_EXTENSION_NAME "VK_KHR_shader_constant_data" +typedef struct VkPhysicalDeviceShaderConstantDataFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderConstantData; +} VkPhysicalDeviceShaderConstantDataFeaturesKHR; + + + +// VK_KHR_dynamic_rendering_local_read is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_dynamic_rendering_local_read 1 +#define VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_SPEC_VERSION 1 +#define VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME "VK_KHR_dynamic_rendering_local_read" +typedef VkPhysicalDeviceDynamicRenderingLocalReadFeatures VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR; + +typedef VkRenderingAttachmentLocationInfo VkRenderingAttachmentLocationInfoKHR; + +typedef VkRenderingInputAttachmentIndexInfo VkRenderingInputAttachmentIndexInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingAttachmentLocationsKHR)(VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo); +typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingInputAttachmentIndicesKHR)(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingAttachmentLocationsKHR( + VkCommandBuffer commandBuffer, + const VkRenderingAttachmentLocationInfo* pLocationInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingInputAttachmentIndicesKHR( + VkCommandBuffer commandBuffer, + const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); +#endif +#endif + + +// VK_KHR_shader_abort is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_abort 1 +#define VK_KHR_SHADER_ABORT_SPEC_VERSION 1 +#define VK_KHR_SHADER_ABORT_EXTENSION_NAME "VK_KHR_shader_abort" +typedef struct VkPhysicalDeviceShaderAbortFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderAbort; +} VkPhysicalDeviceShaderAbortFeaturesKHR; + +typedef struct VkDeviceFaultShaderAbortMessageInfoKHR { + VkStructureType sType; + void* pNext; + uint64_t messageDataSize; + void* pMessageData; +} VkDeviceFaultShaderAbortMessageInfoKHR; + +typedef struct VkPhysicalDeviceShaderAbortPropertiesKHR { + VkStructureType sType; + void* pNext; + uint64_t maxShaderAbortMessageSize; +} VkPhysicalDeviceShaderAbortPropertiesKHR; + + + +// VK_KHR_shader_quad_control is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_quad_control 1 +#define VK_KHR_SHADER_QUAD_CONTROL_SPEC_VERSION 1 +#define VK_KHR_SHADER_QUAD_CONTROL_EXTENSION_NAME "VK_KHR_shader_quad_control" +typedef struct VkPhysicalDeviceShaderQuadControlFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderQuadControl; +} VkPhysicalDeviceShaderQuadControlFeaturesKHR; + + + +// VK_KHR_spirv_1_4 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_spirv_1_4 1 +#define VK_KHR_SPIRV_1_4_SPEC_VERSION 1 +#define VK_KHR_SPIRV_1_4_EXTENSION_NAME "VK_KHR_spirv_1_4" + + +// VK_KHR_surface_protected_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_surface_protected_capabilities 1 +#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME "VK_KHR_surface_protected_capabilities" +typedef struct VkSurfaceProtectedCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 supportsProtected; +} VkSurfaceProtectedCapabilitiesKHR; + + + +// VK_KHR_separate_depth_stencil_layouts is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_separate_depth_stencil_layouts 1 +#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION 1 +#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME "VK_KHR_separate_depth_stencil_layouts" +typedef VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR; + +typedef VkAttachmentReferenceStencilLayout VkAttachmentReferenceStencilLayoutKHR; + +typedef VkAttachmentDescriptionStencilLayout VkAttachmentDescriptionStencilLayoutKHR; + + + +// VK_KHR_present_wait is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_wait 1 +#define VK_KHR_PRESENT_WAIT_SPEC_VERSION 1 +#define VK_KHR_PRESENT_WAIT_EXTENSION_NAME "VK_KHR_present_wait" +typedef struct VkPhysicalDevicePresentWaitFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentWait; +} VkPhysicalDevicePresentWaitFeaturesKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkWaitForPresentKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t presentId, uint64_t timeout); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresentKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t presentId, + uint64_t timeout); +#endif +#endif + + +// VK_KHR_uniform_buffer_standard_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_uniform_buffer_standard_layout 1 +#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout" +typedef VkPhysicalDeviceUniformBufferStandardLayoutFeatures VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR; + + + +// VK_KHR_buffer_device_address is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_buffer_device_address 1 +#define VK_KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 1 +#define VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_KHR_buffer_device_address" +typedef VkPhysicalDeviceBufferDeviceAddressFeatures VkPhysicalDeviceBufferDeviceAddressFeaturesKHR; + +typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoKHR; + +typedef VkBufferOpaqueCaptureAddressCreateInfo VkBufferOpaqueCaptureAddressCreateInfoKHR; + +typedef VkMemoryOpaqueCaptureAddressAllocateInfo VkMemoryOpaqueCaptureAddressAllocateInfoKHR; + +typedef VkDeviceMemoryOpaqueCaptureAddressInfo VkDeviceMemoryOpaqueCaptureAddressInfoKHR; + +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressKHR( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddressKHR( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR( + VkDevice device, + const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); +#endif +#endif + + +// VK_KHR_deferred_host_operations is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_deferred_host_operations 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) +#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 4 +#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations" +typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); +typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); +typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( + VkDevice device, + const VkAllocationCallbacks* pAllocator, + VkDeferredOperationKHR* pDeferredOperation); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( + VkDevice device, + VkDeferredOperationKHR operation, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( + VkDevice device, + VkDeferredOperationKHR operation); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( + VkDevice device, + VkDeferredOperationKHR operation); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( + VkDevice device, + VkDeferredOperationKHR operation); +#endif +#endif + + +// VK_KHR_pipeline_executable_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_pipeline_executable_properties 1 +#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME "VK_KHR_pipeline_executable_properties" + +typedef enum VkPipelineExecutableStatisticFormatKHR { + 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, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPipelineExecutableStatisticFormatKHR; +typedef struct VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineExecutableInfo; +} VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR; + +typedef struct VkPipelineInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipeline pipeline; +} VkPipelineInfoKHR; + +typedef struct VkPipelineExecutablePropertiesKHR { + VkStructureType sType; + void* pNext; + VkShaderStageFlags stages; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + uint32_t subgroupSize; +} VkPipelineExecutablePropertiesKHR; + +typedef struct VkPipelineExecutableInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipeline pipeline; + uint32_t executableIndex; +} VkPipelineExecutableInfoKHR; + +typedef union VkPipelineExecutableStatisticValueKHR { + VkBool32 b32; + int64_t i64; + uint64_t u64; + double f64; +} VkPipelineExecutableStatisticValueKHR; + +typedef struct VkPipelineExecutableStatisticKHR { + VkStructureType sType; + void* pNext; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkPipelineExecutableStatisticFormatKHR format; + VkPipelineExecutableStatisticValueKHR value; +} VkPipelineExecutableStatisticKHR; + +typedef struct VkPipelineExecutableInternalRepresentationKHR { + VkStructureType sType; + void* pNext; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkBool32 isText; + size_t dataSize; + void* pData; +} VkPipelineExecutableInternalRepresentationKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutablePropertiesKHR)(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableStatisticsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableInternalRepresentationsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutablePropertiesKHR( + VkDevice device, + const VkPipelineInfoKHR* pPipelineInfo, + uint32_t* pExecutableCount, + VkPipelineExecutablePropertiesKHR* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableStatisticsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pStatisticCount, + VkPipelineExecutableStatisticKHR* pStatistics); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pInternalRepresentationCount, + VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); +#endif +#endif + + +// VK_KHR_map_memory2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_map_memory2 1 +#define VK_KHR_MAP_MEMORY_2_SPEC_VERSION 1 +#define VK_KHR_MAP_MEMORY_2_EXTENSION_NAME "VK_KHR_map_memory2" +typedef VkMemoryUnmapFlagBits VkMemoryUnmapFlagBitsKHR; + +typedef VkMemoryUnmapFlags VkMemoryUnmapFlagsKHR; + +typedef VkMemoryMapInfo VkMemoryMapInfoKHR; + +typedef VkMemoryUnmapInfo VkMemoryUnmapInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkMapMemory2KHR)(VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData); +typedef VkResult (VKAPI_PTR *PFN_vkUnmapMemory2KHR)(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory2KHR( + VkDevice device, + const VkMemoryMapInfo* pMemoryMapInfo, + void** ppData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkUnmapMemory2KHR( + VkDevice device, + const VkMemoryUnmapInfo* pMemoryUnmapInfo); +#endif +#endif + + +// VK_KHR_shader_integer_dot_product is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_integer_dot_product 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME "VK_KHR_shader_integer_dot_product" +typedef VkPhysicalDeviceShaderIntegerDotProductFeatures VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR; + +typedef VkPhysicalDeviceShaderIntegerDotProductProperties VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR; + + + +// VK_KHR_pipeline_library is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_pipeline_library 1 +#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" +typedef struct VkPipelineLibraryCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t libraryCount; + const VkPipeline* pLibraries; +} VkPipelineLibraryCreateInfoKHR; + + + +// VK_KHR_shader_non_semantic_info is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_non_semantic_info 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME "VK_KHR_shader_non_semantic_info" + + +// VK_KHR_present_id is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_id 1 +#define VK_KHR_PRESENT_ID_SPEC_VERSION 1 +#define VK_KHR_PRESENT_ID_EXTENSION_NAME "VK_KHR_present_id" +typedef struct VkPresentIdKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint64_t* pPresentIds; +} VkPresentIdKHR; + +typedef struct VkPhysicalDevicePresentIdFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentId; +} VkPhysicalDevicePresentIdFeaturesKHR; + + + +// VK_KHR_video_encode_queue is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_encode_queue 1 +#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 12 +#define VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME "VK_KHR_video_encode_queue" + +typedef enum VkVideoEncodeTuningModeKHR { + 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, + VK_VIDEO_ENCODE_TUNING_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeTuningModeKHR; + +typedef enum VkVideoEncodeFlagBitsKHR { + VK_VIDEO_ENCODE_INTRA_REFRESH_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_WITH_QUANTIZATION_DELTA_MAP_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_WITH_EMPHASIS_MAP_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeFlagBitsKHR; +typedef VkFlags VkVideoEncodeFlagsKHR; + +typedef enum VkVideoEncodeCapabilityFlagBitsKHR { + VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_CAPABILITY_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_DETECTION_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_CAPABILITY_EMPHASIS_MAP_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeCapabilityFlagBitsKHR; +typedef VkFlags VkVideoEncodeCapabilityFlagsKHR; + +typedef enum VkVideoEncodeRateControlModeFlagBitsKHR { + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeRateControlModeFlagBitsKHR; +typedef VkFlags VkVideoEncodeRateControlModeFlagsKHR; + +typedef enum VkVideoEncodeFeedbackFlagBitsKHR { + VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_FEEDBACK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeFeedbackFlagBitsKHR; +typedef VkFlags VkVideoEncodeFeedbackFlagsKHR; + +typedef enum VkVideoEncodeUsageFlagBitsKHR { + VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_USAGE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeUsageFlagBitsKHR; +typedef VkFlags VkVideoEncodeUsageFlagsKHR; + +typedef enum VkVideoEncodeContentFlagBitsKHR { + VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_CONTENT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeContentFlagBitsKHR; +typedef VkFlags VkVideoEncodeContentFlagsKHR; +typedef VkFlags VkVideoEncodeRateControlFlagsKHR; +typedef struct VkVideoEncodeInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeFlagsKHR flags; + VkBuffer dstBuffer; + VkDeviceSize dstBufferOffset; + VkDeviceSize dstBufferRange; + VkVideoPictureResourceInfoKHR srcPictureResource; + const VkVideoReferenceSlotInfoKHR* pSetupReferenceSlot; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotInfoKHR* pReferenceSlots; + uint32_t precedingExternallyEncodedBytes; +} VkVideoEncodeInfoKHR; + +typedef struct VkVideoEncodeCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeCapabilityFlagsKHR flags; + VkVideoEncodeRateControlModeFlagsKHR rateControlModes; + uint32_t maxRateControlLayers; + uint64_t maxBitrate; + uint32_t maxQualityLevels; + VkExtent2D encodeInputPictureGranularity; + VkVideoEncodeFeedbackFlagsKHR supportedEncodeFeedbackFlags; +} VkVideoEncodeCapabilitiesKHR; + +typedef struct VkQueryPoolVideoEncodeFeedbackCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeFeedbackFlagsKHR encodeFeedbackFlags; +} VkQueryPoolVideoEncodeFeedbackCreateInfoKHR; + +typedef struct VkVideoEncodeUsageInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeUsageFlagsKHR videoUsageHints; + VkVideoEncodeContentFlagsKHR videoContentHints; + VkVideoEncodeTuningModeKHR tuningMode; +} VkVideoEncodeUsageInfoKHR; + +typedef struct VkVideoEncodeRateControlLayerInfoKHR { + VkStructureType sType; + const void* pNext; + uint64_t averageBitrate; + uint64_t maxBitrate; + uint32_t frameRateNumerator; + uint32_t frameRateDenominator; +} VkVideoEncodeRateControlLayerInfoKHR; + +typedef struct VkVideoEncodeRateControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeRateControlFlagsKHR flags; + VkVideoEncodeRateControlModeFlagBitsKHR rateControlMode; + uint32_t layerCount; + const VkVideoEncodeRateControlLayerInfoKHR* pLayers; + uint32_t virtualBufferSizeInMs; + uint32_t initialVirtualBufferSizeInMs; +} VkVideoEncodeRateControlInfoKHR; + +typedef struct VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR { + VkStructureType sType; + const void* pNext; + const VkVideoProfileInfoKHR* pVideoProfile; + uint32_t qualityLevel; +} VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR; + +typedef struct VkVideoEncodeQualityLevelPropertiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeRateControlModeFlagBitsKHR preferredRateControlMode; + uint32_t preferredRateControlLayerCount; +} VkVideoEncodeQualityLevelPropertiesKHR; + +typedef struct VkVideoEncodeQualityLevelInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t qualityLevel; +} VkVideoEncodeQualityLevelInfoKHR; + +typedef struct VkVideoEncodeSessionParametersGetInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoSessionParametersKHR videoSessionParameters; +} VkVideoEncodeSessionParametersGetInfoKHR; + +typedef struct VkVideoEncodeSessionParametersFeedbackInfoKHR { + VkStructureType sType; + void* pNext; + VkBool32 hasOverrides; +} VkVideoEncodeSessionParametersFeedbackInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR* pQualityLevelInfo, VkVideoEncodeQualityLevelPropertiesKHR* pQualityLevelProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetEncodedVideoSessionParametersKHR)(VkDevice device, const VkVideoEncodeSessionParametersGetInfoKHR* pVideoSessionParametersInfo, VkVideoEncodeSessionParametersFeedbackInfoKHR* pFeedbackInfo, size_t* pDataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdEncodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR* pQualityLevelInfo, + VkVideoEncodeQualityLevelPropertiesKHR* pQualityLevelProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetEncodedVideoSessionParametersKHR( + VkDevice device, + const VkVideoEncodeSessionParametersGetInfoKHR* pVideoSessionParametersInfo, + VkVideoEncodeSessionParametersFeedbackInfoKHR* pFeedbackInfo, + size_t* pDataSize, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR( + VkCommandBuffer commandBuffer, + const VkVideoEncodeInfoKHR* pEncodeInfo); +#endif +#endif + + +// VK_KHR_synchronization2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_synchronization2 1 +#define VK_KHR_SYNCHRONIZATION_2_SPEC_VERSION 1 +#define VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME "VK_KHR_synchronization2" +typedef VkPipelineStageFlags2 VkPipelineStageFlags2KHR; + +typedef VkPipelineStageFlagBits2 VkPipelineStageFlagBits2KHR; + +typedef VkAccessFlags2 VkAccessFlags2KHR; + +typedef VkAccessFlagBits2 VkAccessFlagBits2KHR; + +typedef VkSubmitFlagBits VkSubmitFlagBitsKHR; + +typedef VkSubmitFlags VkSubmitFlagsKHR; + +typedef VkMemoryBarrier2 VkMemoryBarrier2KHR; + +typedef VkBufferMemoryBarrier2 VkBufferMemoryBarrier2KHR; + +typedef VkImageMemoryBarrier2 VkImageMemoryBarrier2KHR; + +typedef VkDependencyInfo VkDependencyInfoKHR; + +typedef VkSubmitInfo2 VkSubmitInfo2KHR; + +typedef VkSemaphoreSubmitInfo VkSemaphoreSubmitInfoKHR; + +typedef VkCommandBufferSubmitInfo VkCommandBufferSubmitInfoKHR; + +typedef VkPhysicalDeviceSynchronization2Features VkPhysicalDeviceSynchronization2FeaturesKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2KHR)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2KHR)(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2KHR)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2KHR)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfo* pDependencyInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2 stageMask); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2KHR( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfo* pDependencyInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2KHR( + VkCommandBuffer commandBuffer, + const VkDependencyInfo* pDependencyInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2KHR( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2 stage, + VkQueryPool queryPool, + uint32_t query); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2KHR( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo2* pSubmits, + VkFence fence); +#endif +#endif + + +// VK_KHR_device_address_commands is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_device_address_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) +#define VK_KHR_DEVICE_ADDRESS_COMMANDS_SPEC_VERSION 1 +#define VK_KHR_DEVICE_ADDRESS_COMMANDS_EXTENSION_NAME "VK_KHR_device_address_commands" + +typedef enum VkAccelerationStructureTypeKHR { + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, + VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2, + VK_ACCELERATION_STRUCTURE_TYPE_OPACITY_MICROMAP_KHR = 1000623000, + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureTypeKHR; + +typedef enum VkAddressCommandFlagBitsKHR { + VK_ADDRESS_COMMAND_PROTECTED_BIT_KHR = 0x00000001, + VK_ADDRESS_COMMAND_FULLY_BOUND_BIT_KHR = 0x00000002, + VK_ADDRESS_COMMAND_STORAGE_BUFFER_USAGE_BIT_KHR = 0x00000004, + VK_ADDRESS_COMMAND_UNKNOWN_STORAGE_BUFFER_USAGE_BIT_KHR = 0x00000008, + VK_ADDRESS_COMMAND_TRANSFORM_FEEDBACK_BUFFER_USAGE_BIT_KHR = 0x00000010, + VK_ADDRESS_COMMAND_UNKNOWN_TRANSFORM_FEEDBACK_BUFFER_USAGE_BIT_KHR = 0x00000020, + VK_ADDRESS_COMMAND_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAddressCommandFlagBitsKHR; +typedef VkFlags VkAddressCommandFlagsKHR; + +typedef enum VkConditionalRenderingFlagBitsEXT { + VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001, + VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkConditionalRenderingFlagBitsEXT; +typedef VkFlags VkConditionalRenderingFlagsEXT; + +typedef enum VkAccelerationStructureCreateFlagBitsKHR { + VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0x00000001, + VK_ACCELERATION_STRUCTURE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000008, + VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV = 0x00000004, + VK_ACCELERATION_STRUCTURE_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCreateFlagBitsKHR; +typedef VkFlags VkAccelerationStructureCreateFlagsKHR; +typedef struct VkDeviceAddressRangeKHR { + VkDeviceAddress address; + VkDeviceSize size; +} VkDeviceAddressRangeKHR; + +typedef struct VkStridedDeviceAddressRangeKHR { + VkDeviceAddress address; + VkDeviceSize size; + VkDeviceSize stride; +} VkStridedDeviceAddressRangeKHR; + +typedef struct VkDeviceMemoryCopyKHR { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR srcRange; + VkAddressCommandFlagsKHR srcFlags; + VkDeviceAddressRangeKHR dstRange; + VkAddressCommandFlagsKHR dstFlags; +} VkDeviceMemoryCopyKHR; + +typedef struct VkCopyDeviceMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t regionCount; + const VkDeviceMemoryCopyKHR* pRegions; +} VkCopyDeviceMemoryInfoKHR; + +typedef struct VkDeviceMemoryImageCopyKHR { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + uint32_t addressRowLength; + uint32_t addressImageHeight; + VkImageSubresourceLayers imageSubresource; + VkImageLayout imageLayout; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkDeviceMemoryImageCopyKHR; + +typedef struct VkCopyDeviceMemoryImageInfoKHR { + VkStructureType sType; + const void* pNext; + VkImage image; + uint32_t regionCount; + const VkDeviceMemoryImageCopyKHR* pRegions; +} VkCopyDeviceMemoryImageInfoKHR; + +typedef struct VkMemoryRangeBarrierKHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; +} VkMemoryRangeBarrierKHR; + +typedef struct VkMemoryRangeBarriersInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t memoryRangeBarrierCount; + const VkMemoryRangeBarrierKHR* pMemoryRangeBarriers; +} VkMemoryRangeBarriersInfoKHR; + +typedef struct VkPhysicalDeviceDeviceAddressCommandsFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 deviceAddressCommands; +} VkPhysicalDeviceDeviceAddressCommandsFeaturesKHR; + +typedef struct VkBindIndexBuffer3InfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + VkIndexType indexType; +} VkBindIndexBuffer3InfoKHR; + +typedef struct VkBindVertexBuffer3InfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 setStride; + VkStridedDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; +} VkBindVertexBuffer3InfoKHR; + +typedef struct VkDrawIndirect2InfoKHR { + VkStructureType sType; + const void* pNext; + VkStridedDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + uint32_t drawCount; +} VkDrawIndirect2InfoKHR; + +typedef struct VkDrawIndirectCount2InfoKHR { + VkStructureType sType; + const void* pNext; + VkStridedDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + VkDeviceAddressRangeKHR countAddressRange; + VkAddressCommandFlagsKHR countAddressFlags; + uint32_t maxDrawCount; +} VkDrawIndirectCount2InfoKHR; + +typedef struct VkDispatchIndirect2InfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; +} VkDispatchIndirect2InfoKHR; + +typedef struct VkConditionalRenderingBeginInfo2EXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + VkConditionalRenderingFlagsEXT flags; +} VkConditionalRenderingBeginInfo2EXT; + +typedef struct VkBindTransformFeedbackBuffer2InfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; +} VkBindTransformFeedbackBuffer2InfoEXT; + +typedef struct VkMemoryMarkerInfoAMD { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR stage; + VkDeviceAddressRangeKHR dstRange; + VkAddressCommandFlagsKHR dstFlags; + uint32_t marker; +} VkMemoryMarkerInfoAMD; + +typedef struct VkAccelerationStructureCreateInfo2KHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureCreateFlagsKHR createFlags; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + VkAccelerationStructureTypeKHR type; +} VkAccelerationStructureCreateInfo2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer3KHR)(VkCommandBuffer commandBuffer, const VkBindIndexBuffer3InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers3KHR)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBindVertexBuffer3InfoKHR* pBindingInfos); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect2KHR)(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect2KHR)(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect2KHR)(VkCommandBuffer commandBuffer, const VkDispatchIndirect2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyDeviceMemoryInfoKHR* pCopyMemoryInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToImageKHR)(VkCommandBuffer commandBuffer, const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo); +typedef void (VKAPI_PTR *PFN_vkCmdUpdateMemoryKHR)(VkCommandBuffer commandBuffer, const VkDeviceAddressRangeKHR* pDstRange, VkAddressCommandFlagsKHR dstFlags, VkDeviceSize dataSize, const void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdFillMemoryKHR)(VkCommandBuffer commandBuffer, const VkDeviceAddressRangeKHR* pDstRange, VkAddressCommandFlagsKHR dstFlags, uint32_t data); +typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResultsToMemoryKHR)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, const VkStridedDeviceAddressRangeKHR* pDstRange, VkAddressCommandFlagsKHR dstFlags, VkQueryResultFlags queryResultFlags); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCount2KHR)(VkCommandBuffer commandBuffer, const VkDrawIndirectCount2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCount2KHR)(VkCommandBuffer commandBuffer, const VkDrawIndirectCount2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRendering2EXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfo2EXT* pConditionalRenderingBegin); +typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffers2EXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBindTransformFeedbackBuffer2InfoEXT* pBindingInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedback2EXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterRange, uint32_t counterRangeCount, const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos); +typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedback2EXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterRange, uint32_t counterRangeCount, const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCount2EXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfo, uint32_t counterOffset, uint32_t vertexStride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirect2EXT)(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCount2EXT)(VkCommandBuffer commandBuffer, const VkDrawIndirectCount2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteMarkerToMemoryAMD)(VkCommandBuffer commandBuffer, const VkMemoryMarkerInfoAMD* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructure2KHR)(VkDevice device, const VkAccelerationStructureCreateInfo2KHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer3KHR( + VkCommandBuffer commandBuffer, + const VkBindIndexBuffer3InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers3KHR( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBindVertexBuffer3InfoKHR* pBindingInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect2KHR( + VkCommandBuffer commandBuffer, + const VkDrawIndirect2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect2KHR( + VkCommandBuffer commandBuffer, + const VkDrawIndirect2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect2KHR( + VkCommandBuffer commandBuffer, + const VkDispatchIndirect2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyDeviceMemoryInfoKHR* pCopyMemoryInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageKHR( + VkCommandBuffer commandBuffer, + const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdUpdateMemoryKHR( + VkCommandBuffer commandBuffer, + const VkDeviceAddressRangeKHR* pDstRange, + VkAddressCommandFlagsKHR dstFlags, + VkDeviceSize dataSize, + const void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdFillMemoryKHR( + VkCommandBuffer commandBuffer, + const VkDeviceAddressRangeKHR* pDstRange, + VkAddressCommandFlagsKHR dstFlags, + uint32_t data); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResultsToMemoryKHR( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + const VkStridedDeviceAddressRangeKHR* pDstRange, + VkAddressCommandFlagsKHR dstFlags, + VkQueryResultFlags queryResultFlags); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCount2KHR( + VkCommandBuffer commandBuffer, + const VkDrawIndirectCount2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCount2KHR( + VkCommandBuffer commandBuffer, + const VkDrawIndirectCount2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRendering2EXT( + VkCommandBuffer commandBuffer, + const VkConditionalRenderingBeginInfo2EXT* pConditionalRenderingBegin); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffers2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBindTransformFeedbackBuffer2InfoEXT* pBindingInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedback2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterRange, + uint32_t counterRangeCount, + const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedback2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterRange, + uint32_t counterRangeCount, + const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCount2EXT( + VkCommandBuffer commandBuffer, + uint32_t instanceCount, + uint32_t firstInstance, + const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfo, + uint32_t counterOffset, + uint32_t vertexStride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirect2EXT( + VkCommandBuffer commandBuffer, + const VkDrawIndirect2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCount2EXT( + VkCommandBuffer commandBuffer, + const VkDrawIndirectCount2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteMarkerToMemoryAMD( + VkCommandBuffer commandBuffer, + const VkMemoryMarkerInfoAMD* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructure2KHR( + VkDevice device, + const VkAccelerationStructureCreateInfo2KHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureKHR* pAccelerationStructure); +#endif +#endif + + +// VK_KHR_fragment_shader_barycentric is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_fragment_shader_barycentric 1 +#define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 +#define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_KHR_fragment_shader_barycentric" +typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShaderBarycentric; +} VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR; + +typedef struct VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 triStripVertexOrderIndependentOfProvokingVertex; +} VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR; + + + +// VK_KHR_shader_subgroup_uniform_control_flow is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_subgroup_uniform_control_flow 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME "VK_KHR_shader_subgroup_uniform_control_flow" +typedef struct VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupUniformControlFlow; +} VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR; + + + +// VK_KHR_zero_initialize_workgroup_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_zero_initialize_workgroup_memory 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME "VK_KHR_zero_initialize_workgroup_memory" +typedef VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR; + + + +// VK_KHR_workgroup_memory_explicit_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_workgroup_memory_explicit_layout 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME "VK_KHR_workgroup_memory_explicit_layout" +typedef struct VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 workgroupMemoryExplicitLayout; + VkBool32 workgroupMemoryExplicitLayoutScalarBlockLayout; + VkBool32 workgroupMemoryExplicitLayout8BitAccess; + VkBool32 workgroupMemoryExplicitLayout16BitAccess; +} VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR; + + + +// VK_KHR_copy_commands2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_copy_commands2 1 +#define VK_KHR_COPY_COMMANDS_2_SPEC_VERSION 1 +#define VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME "VK_KHR_copy_commands2" +typedef VkCopyBufferInfo2 VkCopyBufferInfo2KHR; + +typedef VkCopyImageInfo2 VkCopyImageInfo2KHR; + +typedef VkCopyBufferToImageInfo2 VkCopyBufferToImageInfo2KHR; + +typedef VkCopyImageToBufferInfo2 VkCopyImageToBufferInfo2KHR; + +typedef VkBlitImageInfo2 VkBlitImageInfo2KHR; + +typedef VkResolveImageInfo2 VkResolveImageInfo2KHR; + +typedef VkBufferCopy2 VkBufferCopy2KHR; + +typedef VkImageCopy2 VkImageCopy2KHR; + +typedef VkImageBlit2 VkImageBlit2KHR; + +typedef VkBufferImageCopy2 VkBufferImageCopy2KHR; + +typedef VkImageResolve2 VkImageResolve2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2* pCopyBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2* pCopyImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2KHR)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2KHR)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferInfo2* pCopyBufferInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2* pCopyImageInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2KHR( + VkCommandBuffer commandBuffer, + const VkBlitImageInfo2* pBlitImageInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2KHR( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2* pResolveImageInfo); +#endif +#endif + + +// VK_KHR_format_feature_flags2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_format_feature_flags2 1 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_SPEC_VERSION 2 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME "VK_KHR_format_feature_flags2" +typedef VkFormatFeatureFlags2 VkFormatFeatureFlags2KHR; + +typedef VkFormatFeatureFlagBits2 VkFormatFeatureFlagBits2KHR; + +typedef VkFormatProperties3 VkFormatProperties3KHR; + + + +// VK_KHR_ray_tracing_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_ray_tracing_maintenance1 1 +#define VK_KHR_RAY_TRACING_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_ray_tracing_maintenance1" +typedef struct VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingMaintenance1; + VkBool32 rayTracingPipelineTraceRaysIndirect2; +} VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR; + +typedef struct VkTraceRaysIndirectCommand2KHR { + VkDeviceAddress raygenShaderRecordAddress; + VkDeviceSize raygenShaderRecordSize; + VkDeviceAddress missShaderBindingTableAddress; + VkDeviceSize missShaderBindingTableSize; + VkDeviceSize missShaderBindingTableStride; + VkDeviceAddress hitShaderBindingTableAddress; + VkDeviceSize hitShaderBindingTableSize; + VkDeviceSize hitShaderBindingTableStride; + VkDeviceAddress callableShaderBindingTableAddress; + VkDeviceSize callableShaderBindingTableSize; + VkDeviceSize callableShaderBindingTableStride; + uint32_t width; + uint32_t height; + uint32_t depth; +} VkTraceRaysIndirectCommand2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirect2KHR)(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirect2KHR( + VkCommandBuffer commandBuffer, + VkDeviceAddress indirectDeviceAddress); +#endif +#endif + + +// VK_KHR_shader_untyped_pointers is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_untyped_pointers 1 +#define VK_KHR_SHADER_UNTYPED_POINTERS_SPEC_VERSION 1 +#define VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME "VK_KHR_shader_untyped_pointers" +typedef struct VkPhysicalDeviceShaderUntypedPointersFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderUntypedPointers; +} VkPhysicalDeviceShaderUntypedPointersFeaturesKHR; + + + +// VK_KHR_portability_enumeration is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_portability_enumeration 1 +#define VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION 1 +#define VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME "VK_KHR_portability_enumeration" + + +// VK_KHR_maintenance4 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance4 1 +#define VK_KHR_MAINTENANCE_4_SPEC_VERSION 2 +#define VK_KHR_MAINTENANCE_4_EXTENSION_NAME "VK_KHR_maintenance4" +typedef VkPhysicalDeviceMaintenance4Features VkPhysicalDeviceMaintenance4FeaturesKHR; + +typedef VkPhysicalDeviceMaintenance4Properties VkPhysicalDeviceMaintenance4PropertiesKHR; + +typedef VkDeviceBufferMemoryRequirements VkDeviceBufferMemoryRequirementsKHR; + +typedef VkDeviceImageMemoryRequirements VkDeviceImageMemoryRequirementsKHR; + +typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirementsKHR)(VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirementsKHR( + VkDevice device, + const VkDeviceBufferMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif +#endif + + +// VK_KHR_shader_subgroup_rotate is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_subgroup_rotate 1 +#define VK_KHR_SHADER_SUBGROUP_ROTATE_SPEC_VERSION 2 +#define VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME "VK_KHR_shader_subgroup_rotate" +typedef VkPhysicalDeviceShaderSubgroupRotateFeatures VkPhysicalDeviceShaderSubgroupRotateFeaturesKHR; + + + +// VK_KHR_shader_maximal_reconvergence is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_maximal_reconvergence 1 +#define VK_KHR_SHADER_MAXIMAL_RECONVERGENCE_SPEC_VERSION 1 +#define VK_KHR_SHADER_MAXIMAL_RECONVERGENCE_EXTENSION_NAME "VK_KHR_shader_maximal_reconvergence" +typedef struct VkPhysicalDeviceShaderMaximalReconvergenceFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderMaximalReconvergence; +} VkPhysicalDeviceShaderMaximalReconvergenceFeaturesKHR; + + + +// VK_KHR_maintenance5 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance5 1 +#define VK_KHR_MAINTENANCE_5_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_5_EXTENSION_NAME "VK_KHR_maintenance5" +typedef VkPipelineCreateFlags2 VkPipelineCreateFlags2KHR; + +typedef VkPipelineCreateFlagBits2 VkPipelineCreateFlagBits2KHR; + +typedef VkBufferUsageFlags2 VkBufferUsageFlags2KHR; + +typedef VkBufferUsageFlagBits2 VkBufferUsageFlagBits2KHR; + +typedef VkPhysicalDeviceMaintenance5Features VkPhysicalDeviceMaintenance5FeaturesKHR; + +typedef VkPhysicalDeviceMaintenance5Properties VkPhysicalDeviceMaintenance5PropertiesKHR; + +typedef VkRenderingAreaInfo VkRenderingAreaInfoKHR; + +typedef VkDeviceImageSubresourceInfo VkDeviceImageSubresourceInfoKHR; + +typedef VkImageSubresource2 VkImageSubresource2KHR; + +typedef VkSubresourceLayout2 VkSubresourceLayout2KHR; + +typedef VkPipelineCreateFlags2CreateInfo VkPipelineCreateFlags2CreateInfoKHR; + +typedef VkBufferUsageFlags2CreateInfo VkBufferUsageFlags2CreateInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer2KHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType); +typedef void (VKAPI_PTR *PFN_vkGetRenderingAreaGranularityKHR)(VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSubresourceLayoutKHR)(VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, VkSubresourceLayout2* pLayout); +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2KHR)(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer2KHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkIndexType indexType); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetRenderingAreaGranularityKHR( + VkDevice device, + const VkRenderingAreaInfo* pRenderingAreaInfo, + VkExtent2D* pGranularity); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSubresourceLayoutKHR( + VkDevice device, + const VkDeviceImageSubresourceInfo* pInfo, + VkSubresourceLayout2* pLayout); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2KHR( + VkDevice device, + VkImage image, + const VkImageSubresource2* pSubresource, + VkSubresourceLayout2* pLayout); +#endif +#endif + + +// VK_KHR_present_id2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_id2 1 +#define VK_KHR_PRESENT_ID_2_SPEC_VERSION 1 +#define VK_KHR_PRESENT_ID_2_EXTENSION_NAME "VK_KHR_present_id2" +typedef struct VkSurfaceCapabilitiesPresentId2KHR { + VkStructureType sType; + void* pNext; + VkBool32 presentId2Supported; +} VkSurfaceCapabilitiesPresentId2KHR; + +typedef struct VkPresentId2KHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint64_t* pPresentIds; +} VkPresentId2KHR; + +typedef struct VkPhysicalDevicePresentId2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentId2; +} VkPhysicalDevicePresentId2FeaturesKHR; + + + +// VK_KHR_present_wait2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_wait2 1 +#define VK_KHR_PRESENT_WAIT_2_SPEC_VERSION 1 +#define VK_KHR_PRESENT_WAIT_2_EXTENSION_NAME "VK_KHR_present_wait2" +typedef struct VkSurfaceCapabilitiesPresentWait2KHR { + VkStructureType sType; + void* pNext; + VkBool32 presentWait2Supported; +} VkSurfaceCapabilitiesPresentWait2KHR; + +typedef struct VkPhysicalDevicePresentWait2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentWait2; +} VkPhysicalDevicePresentWait2FeaturesKHR; + +typedef struct VkPresentWait2InfoKHR { + VkStructureType sType; + const void* pNext; + uint64_t presentId; + uint64_t timeout; +} VkPresentWait2InfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkWaitForPresent2KHR)(VkDevice device, VkSwapchainKHR swapchain, const VkPresentWait2InfoKHR* pPresentWait2Info); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresent2KHR( + VkDevice device, + VkSwapchainKHR swapchain, + const VkPresentWait2InfoKHR* pPresentWait2Info); +#endif +#endif + + +// VK_KHR_ray_tracing_position_fetch is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_ray_tracing_position_fetch 1 +#define VK_KHR_RAY_TRACING_POSITION_FETCH_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_POSITION_FETCH_EXTENSION_NAME "VK_KHR_ray_tracing_position_fetch" +typedef struct VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingPositionFetch; +} VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR; + + + +// VK_KHR_pipeline_binary is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_pipeline_binary 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineBinaryKHR) +#define VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR 32U +#define VK_KHR_PIPELINE_BINARY_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_BINARY_EXTENSION_NAME "VK_KHR_pipeline_binary" +typedef struct VkPhysicalDevicePipelineBinaryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineBinaries; +} VkPhysicalDevicePipelineBinaryFeaturesKHR; + +typedef struct VkPhysicalDevicePipelineBinaryPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineBinaryInternalCache; + VkBool32 pipelineBinaryInternalCacheControl; + VkBool32 pipelineBinaryPrefersInternalCache; + VkBool32 pipelineBinaryPrecompiledInternalCache; + VkBool32 pipelineBinaryCompressedData; +} VkPhysicalDevicePipelineBinaryPropertiesKHR; + +typedef struct VkDevicePipelineBinaryInternalCacheControlKHR { + VkStructureType sType; + const void* pNext; + VkBool32 disableInternalCache; +} VkDevicePipelineBinaryInternalCacheControlKHR; + +typedef struct VkPipelineBinaryKeyKHR { + VkStructureType sType; + void* pNext; + uint32_t keySize; + uint8_t key[VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR]; +} VkPipelineBinaryKeyKHR; + +typedef struct VkPipelineBinaryDataKHR { + size_t dataSize; + void* pData; +} VkPipelineBinaryDataKHR; + +typedef struct VkPipelineBinaryKeysAndDataKHR { + uint32_t binaryCount; + const VkPipelineBinaryKeyKHR* pPipelineBinaryKeys; + const VkPipelineBinaryDataKHR* pPipelineBinaryData; +} VkPipelineBinaryKeysAndDataKHR; + +typedef struct VkPipelineCreateInfoKHR { + VkStructureType sType; + void* pNext; +} VkPipelineCreateInfoKHR; + +typedef struct VkPipelineBinaryCreateInfoKHR { + VkStructureType sType; + const void* pNext; + const VkPipelineBinaryKeysAndDataKHR* pKeysAndDataInfo; + VkPipeline pipeline; + const VkPipelineCreateInfoKHR* pPipelineCreateInfo; +} VkPipelineBinaryCreateInfoKHR; + +typedef struct VkPipelineBinaryInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t binaryCount; + const VkPipelineBinaryKHR* pPipelineBinaries; +} VkPipelineBinaryInfoKHR; + +typedef struct VkReleaseCapturedPipelineDataInfoKHR { + VkStructureType sType; + void* pNext; + VkPipeline pipeline; +} VkReleaseCapturedPipelineDataInfoKHR; + +typedef struct VkPipelineBinaryDataInfoKHR { + VkStructureType sType; + void* pNext; + VkPipelineBinaryKHR pipelineBinary; +} VkPipelineBinaryDataInfoKHR; + +typedef struct VkPipelineBinaryHandlesInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t pipelineBinaryCount; + VkPipelineBinaryKHR* pPipelineBinaries; +} VkPipelineBinaryHandlesInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineBinariesKHR)(VkDevice device, const VkPipelineBinaryCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineBinaryHandlesInfoKHR* pBinaries); +typedef void (VKAPI_PTR *PFN_vkDestroyPipelineBinaryKHR)(VkDevice device, VkPipelineBinaryKHR pipelineBinary, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineKeyKHR)(VkDevice device, const VkPipelineCreateInfoKHR* pPipelineCreateInfo, VkPipelineBinaryKeyKHR* pPipelineKey); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineBinaryDataKHR)(VkDevice device, const VkPipelineBinaryDataInfoKHR* pInfo, VkPipelineBinaryKeyKHR* pPipelineBinaryKey, size_t* pPipelineBinaryDataSize, void* pPipelineBinaryData); +typedef VkResult (VKAPI_PTR *PFN_vkReleaseCapturedPipelineDataKHR)(VkDevice device, const VkReleaseCapturedPipelineDataInfoKHR* pInfo, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineBinariesKHR( + VkDevice device, + const VkPipelineBinaryCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPipelineBinaryHandlesInfoKHR* pBinaries); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineBinaryKHR( + VkDevice device, + VkPipelineBinaryKHR pipelineBinary, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineKeyKHR( + VkDevice device, + const VkPipelineCreateInfoKHR* pPipelineCreateInfo, + VkPipelineBinaryKeyKHR* pPipelineKey); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineBinaryDataKHR( + VkDevice device, + const VkPipelineBinaryDataInfoKHR* pInfo, + VkPipelineBinaryKeyKHR* pPipelineBinaryKey, + size_t* pPipelineBinaryDataSize, + void* pPipelineBinaryData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseCapturedPipelineDataKHR( + VkDevice device, + const VkReleaseCapturedPipelineDataInfoKHR* pInfo, + const VkAllocationCallbacks* pAllocator); +#endif +#endif + + +// VK_KHR_surface_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_surface_maintenance1 1 +#define VK_KHR_SURFACE_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_KHR_SURFACE_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_surface_maintenance1" + +typedef enum VkPresentScalingFlagBitsKHR { + VK_PRESENT_SCALING_ONE_TO_ONE_BIT_KHR = 0x00000001, + VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_KHR = 0x00000002, + VK_PRESENT_SCALING_STRETCH_BIT_KHR = 0x00000004, + VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT = VK_PRESENT_SCALING_ONE_TO_ONE_BIT_KHR, + VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT = VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_KHR, + VK_PRESENT_SCALING_STRETCH_BIT_EXT = VK_PRESENT_SCALING_STRETCH_BIT_KHR, + VK_PRESENT_SCALING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentScalingFlagBitsKHR; +typedef VkFlags VkPresentScalingFlagsKHR; + +typedef enum VkPresentGravityFlagBitsKHR { + VK_PRESENT_GRAVITY_MIN_BIT_KHR = 0x00000001, + VK_PRESENT_GRAVITY_MAX_BIT_KHR = 0x00000002, + VK_PRESENT_GRAVITY_CENTERED_BIT_KHR = 0x00000004, + VK_PRESENT_GRAVITY_MIN_BIT_EXT = VK_PRESENT_GRAVITY_MIN_BIT_KHR, + VK_PRESENT_GRAVITY_MAX_BIT_EXT = VK_PRESENT_GRAVITY_MAX_BIT_KHR, + VK_PRESENT_GRAVITY_CENTERED_BIT_EXT = VK_PRESENT_GRAVITY_CENTERED_BIT_KHR, + VK_PRESENT_GRAVITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentGravityFlagBitsKHR; +typedef VkFlags VkPresentGravityFlagsKHR; +typedef struct VkSurfacePresentModeKHR { + VkStructureType sType; + void* pNext; + VkPresentModeKHR presentMode; +} VkSurfacePresentModeKHR; + +typedef struct VkSurfacePresentScalingCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkPresentScalingFlagsKHR supportedPresentScaling; + VkPresentGravityFlagsKHR supportedPresentGravityX; + VkPresentGravityFlagsKHR supportedPresentGravityY; + VkExtent2D minScaledImageExtent; + VkExtent2D maxScaledImageExtent; +} VkSurfacePresentScalingCapabilitiesKHR; + +typedef struct VkSurfacePresentModeCompatibilityKHR { + VkStructureType sType; + void* pNext; + uint32_t presentModeCount; + VkPresentModeKHR* pPresentModes; +} VkSurfacePresentModeCompatibilityKHR; + + + +// VK_KHR_swapchain_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_swapchain_maintenance1 1 +#define VK_KHR_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_swapchain_maintenance1" +typedef struct VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 swapchainMaintenance1; +} VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR; + +typedef struct VkSwapchainPresentFenceInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkFence* pFences; +} VkSwapchainPresentFenceInfoKHR; + +typedef struct VkSwapchainPresentModesCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t presentModeCount; + const VkPresentModeKHR* pPresentModes; +} VkSwapchainPresentModesCreateInfoKHR; + +typedef struct VkSwapchainPresentModeInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentModeKHR* pPresentModes; +} VkSwapchainPresentModeInfoKHR; + +typedef struct VkSwapchainPresentScalingCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkPresentScalingFlagsKHR scalingBehavior; + VkPresentGravityFlagsKHR presentGravityX; + VkPresentGravityFlagsKHR presentGravityY; +} VkSwapchainPresentScalingCreateInfoKHR; + +typedef struct VkReleaseSwapchainImagesInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint32_t imageIndexCount; + const uint32_t* pImageIndices; +} VkReleaseSwapchainImagesInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkReleaseSwapchainImagesKHR)(VkDevice device, const VkReleaseSwapchainImagesInfoKHR* pReleaseInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseSwapchainImagesKHR( + VkDevice device, + const VkReleaseSwapchainImagesInfoKHR* pReleaseInfo); +#endif +#endif + + +// VK_KHR_internally_synchronized_queues is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_internally_synchronized_queues 1 +#define VK_KHR_INTERNALLY_SYNCHRONIZED_QUEUES_SPEC_VERSION 1 +#define VK_KHR_INTERNALLY_SYNCHRONIZED_QUEUES_EXTENSION_NAME "VK_KHR_internally_synchronized_queues" +typedef struct VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 internallySynchronizedQueues; +} VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR; + + + +// VK_KHR_cooperative_matrix is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_cooperative_matrix 1 +#define VK_KHR_COOPERATIVE_MATRIX_SPEC_VERSION 2 +#define VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_KHR_cooperative_matrix" + +typedef enum VkComponentTypeKHR { + VK_COMPONENT_TYPE_FLOAT16_KHR = 0, + VK_COMPONENT_TYPE_FLOAT32_KHR = 1, + VK_COMPONENT_TYPE_FLOAT64_KHR = 2, + VK_COMPONENT_TYPE_SINT8_KHR = 3, + VK_COMPONENT_TYPE_SINT16_KHR = 4, + VK_COMPONENT_TYPE_SINT32_KHR = 5, + VK_COMPONENT_TYPE_SINT64_KHR = 6, + VK_COMPONENT_TYPE_UINT8_KHR = 7, + VK_COMPONENT_TYPE_UINT16_KHR = 8, + VK_COMPONENT_TYPE_UINT32_KHR = 9, + VK_COMPONENT_TYPE_UINT64_KHR = 10, + VK_COMPONENT_TYPE_BFLOAT16_KHR = 1000141000, + VK_COMPONENT_TYPE_SINT8_PACKED_NV = 1000491000, + VK_COMPONENT_TYPE_UINT8_PACKED_NV = 1000491001, + VK_COMPONENT_TYPE_FLOAT8_E4M3_EXT = 1000491002, + VK_COMPONENT_TYPE_FLOAT8_E5M2_EXT = 1000491003, + VK_COMPONENT_TYPE_FLOAT16_NV = VK_COMPONENT_TYPE_FLOAT16_KHR, + VK_COMPONENT_TYPE_FLOAT32_NV = VK_COMPONENT_TYPE_FLOAT32_KHR, + VK_COMPONENT_TYPE_FLOAT64_NV = VK_COMPONENT_TYPE_FLOAT64_KHR, + VK_COMPONENT_TYPE_SINT8_NV = VK_COMPONENT_TYPE_SINT8_KHR, + VK_COMPONENT_TYPE_SINT16_NV = VK_COMPONENT_TYPE_SINT16_KHR, + VK_COMPONENT_TYPE_SINT32_NV = VK_COMPONENT_TYPE_SINT32_KHR, + VK_COMPONENT_TYPE_SINT64_NV = VK_COMPONENT_TYPE_SINT64_KHR, + VK_COMPONENT_TYPE_UINT8_NV = VK_COMPONENT_TYPE_UINT8_KHR, + VK_COMPONENT_TYPE_UINT16_NV = VK_COMPONENT_TYPE_UINT16_KHR, + VK_COMPONENT_TYPE_UINT32_NV = VK_COMPONENT_TYPE_UINT32_KHR, + VK_COMPONENT_TYPE_UINT64_NV = VK_COMPONENT_TYPE_UINT64_KHR, + VK_COMPONENT_TYPE_FLOAT_E4M3_NV = VK_COMPONENT_TYPE_FLOAT8_E4M3_EXT, + VK_COMPONENT_TYPE_FLOAT_E5M2_NV = VK_COMPONENT_TYPE_FLOAT8_E5M2_EXT, + VK_COMPONENT_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkComponentTypeKHR; + +typedef enum VkScopeKHR { + VK_SCOPE_DEVICE_KHR = 1, + VK_SCOPE_WORKGROUP_KHR = 2, + VK_SCOPE_SUBGROUP_KHR = 3, + VK_SCOPE_QUEUE_FAMILY_KHR = 5, + VK_SCOPE_DEVICE_NV = VK_SCOPE_DEVICE_KHR, + VK_SCOPE_WORKGROUP_NV = VK_SCOPE_WORKGROUP_KHR, + VK_SCOPE_SUBGROUP_NV = VK_SCOPE_SUBGROUP_KHR, + VK_SCOPE_QUEUE_FAMILY_NV = VK_SCOPE_QUEUE_FAMILY_KHR, + VK_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkScopeKHR; +typedef struct VkCooperativeMatrixPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t MSize; + uint32_t NSize; + uint32_t KSize; + VkComponentTypeKHR AType; + VkComponentTypeKHR BType; + VkComponentTypeKHR CType; + VkComponentTypeKHR ResultType; + VkBool32 saturatingAccumulation; + VkScopeKHR scope; +} VkCooperativeMatrixPropertiesKHR; + +typedef struct VkPhysicalDeviceCooperativeMatrixFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrix; + VkBool32 cooperativeMatrixRobustBufferAccess; +} VkPhysicalDeviceCooperativeMatrixFeaturesKHR; + +typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesKHR { + VkStructureType sType; + void* pNext; + VkShaderStageFlags cooperativeMatrixSupportedStages; +} VkPhysicalDeviceCooperativeMatrixPropertiesKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesKHR* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkCooperativeMatrixPropertiesKHR* pProperties); +#endif +#endif + + +// VK_KHR_compute_shader_derivatives is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_compute_shader_derivatives 1 +#define VK_KHR_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1 +#define VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_KHR_compute_shader_derivatives" +typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 computeDerivativeGroupQuads; + VkBool32 computeDerivativeGroupLinear; +} VkPhysicalDeviceComputeShaderDerivativesFeaturesKHR; + +typedef struct VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 meshAndTaskShaderDerivatives; +} VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR; + + + +// VK_KHR_video_decode_av1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_decode_av1 1 +#include "vk_video/vulkan_video_codec_av1std.h" +#include "vk_video/vulkan_video_codec_av1std_decode.h" +#define VK_MAX_VIDEO_AV1_REFERENCES_PER_FRAME_KHR 7U +#define VK_KHR_VIDEO_DECODE_AV1_SPEC_VERSION 1 +#define VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME "VK_KHR_video_decode_av1" +typedef struct VkVideoDecodeAV1ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoAV1Profile stdProfile; + VkBool32 filmGrainSupport; +} VkVideoDecodeAV1ProfileInfoKHR; + +typedef struct VkVideoDecodeAV1CapabilitiesKHR { + VkStructureType sType; + void* pNext; + StdVideoAV1Level maxLevel; +} VkVideoDecodeAV1CapabilitiesKHR; + +typedef struct VkVideoDecodeAV1SessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoAV1SequenceHeader* pStdSequenceHeader; +} VkVideoDecodeAV1SessionParametersCreateInfoKHR; + +typedef struct VkVideoDecodeAV1PictureInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeAV1PictureInfo* pStdPictureInfo; + int32_t referenceNameSlotIndices[VK_MAX_VIDEO_AV1_REFERENCES_PER_FRAME_KHR]; + uint32_t frameHeaderOffset; + uint32_t tileCount; + const uint32_t* pTileOffsets; + const uint32_t* pTileSizes; +} VkVideoDecodeAV1PictureInfoKHR; + +typedef struct VkVideoDecodeAV1DpbSlotInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeAV1ReferenceInfo* pStdReferenceInfo; +} VkVideoDecodeAV1DpbSlotInfoKHR; + + + +// VK_KHR_video_encode_av1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_encode_av1 1 +#include "vk_video/vulkan_video_codec_av1std_encode.h" +#define VK_KHR_VIDEO_ENCODE_AV1_SPEC_VERSION 1 +#define VK_KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME "VK_KHR_video_encode_av1" + +typedef enum VkVideoEncodeAV1PredictionModeKHR { + VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_INTRA_ONLY_KHR = 0, + VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_SINGLE_REFERENCE_KHR = 1, + VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_UNIDIRECTIONAL_COMPOUND_KHR = 2, + VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_BIDIRECTIONAL_COMPOUND_KHR = 3, + VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeAV1PredictionModeKHR; + +typedef enum VkVideoEncodeAV1RateControlGroupKHR { + VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_INTRA_KHR = 0, + VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_PREDICTIVE_KHR = 1, + VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_BIPREDICTIVE_KHR = 2, + VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeAV1RateControlGroupKHR; + +typedef enum VkVideoEncodeAV1CapabilityFlagBitsKHR { + VK_VIDEO_ENCODE_AV1_CAPABILITY_PER_RATE_CONTROL_GROUP_MIN_MAX_Q_INDEX_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_AV1_CAPABILITY_GENERATE_OBU_EXTENSION_HEADER_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_AV1_CAPABILITY_PRIMARY_REFERENCE_CDF_ONLY_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_AV1_CAPABILITY_FRAME_SIZE_OVERRIDE_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_AV1_CAPABILITY_MOTION_VECTOR_SCALING_BIT_KHR = 0x00000010, + VK_VIDEO_ENCODE_AV1_CAPABILITY_COMPOUND_PREDICTION_INTRA_REFRESH_BIT_KHR = 0x00000020, + VK_VIDEO_ENCODE_AV1_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeAV1CapabilityFlagBitsKHR; +typedef VkFlags VkVideoEncodeAV1CapabilityFlagsKHR; + +typedef enum VkVideoEncodeAV1StdFlagBitsKHR { + VK_VIDEO_ENCODE_AV1_STD_UNIFORM_TILE_SPACING_FLAG_SET_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_AV1_STD_SKIP_MODE_PRESENT_UNSET_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_AV1_STD_PRIMARY_REF_FRAME_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_AV1_STD_DELTA_Q_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_AV1_STD_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeAV1StdFlagBitsKHR; +typedef VkFlags VkVideoEncodeAV1StdFlagsKHR; + +typedef enum VkVideoEncodeAV1SuperblockSizeFlagBitsKHR { + VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeAV1SuperblockSizeFlagBitsKHR; +typedef VkFlags VkVideoEncodeAV1SuperblockSizeFlagsKHR; + +typedef enum VkVideoEncodeAV1RateControlFlagBitsKHR { + VK_VIDEO_ENCODE_AV1_RATE_CONTROL_REGULAR_GOP_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_AV1_RATE_CONTROL_TEMPORAL_LAYER_PATTERN_DYADIC_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_AV1_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_AV1_RATE_CONTROL_REFERENCE_PATTERN_DYADIC_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_AV1_RATE_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeAV1RateControlFlagBitsKHR; +typedef VkFlags VkVideoEncodeAV1RateControlFlagsKHR; +typedef struct VkPhysicalDeviceVideoEncodeAV1FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 videoEncodeAV1; +} VkPhysicalDeviceVideoEncodeAV1FeaturesKHR; + +typedef struct VkVideoEncodeAV1CapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeAV1CapabilityFlagsKHR flags; + StdVideoAV1Level maxLevel; + VkExtent2D codedPictureAlignment; + VkExtent2D maxTiles; + VkExtent2D minTileSize; + VkExtent2D maxTileSize; + VkVideoEncodeAV1SuperblockSizeFlagsKHR superblockSizes; + uint32_t maxSingleReferenceCount; + uint32_t singleReferenceNameMask; + uint32_t maxUnidirectionalCompoundReferenceCount; + uint32_t maxUnidirectionalCompoundGroup1ReferenceCount; + uint32_t unidirectionalCompoundReferenceNameMask; + uint32_t maxBidirectionalCompoundReferenceCount; + uint32_t maxBidirectionalCompoundGroup1ReferenceCount; + uint32_t maxBidirectionalCompoundGroup2ReferenceCount; + uint32_t bidirectionalCompoundReferenceNameMask; + uint32_t maxTemporalLayerCount; + uint32_t maxSpatialLayerCount; + uint32_t maxOperatingPoints; + uint32_t minQIndex; + uint32_t maxQIndex; + VkBool32 prefersGopRemainingFrames; + VkBool32 requiresGopRemainingFrames; + VkVideoEncodeAV1StdFlagsKHR stdSyntaxFlags; +} VkVideoEncodeAV1CapabilitiesKHR; + +typedef struct VkVideoEncodeAV1QIndexKHR { + uint32_t intraQIndex; + uint32_t predictiveQIndex; + uint32_t bipredictiveQIndex; +} VkVideoEncodeAV1QIndexKHR; + +typedef struct VkVideoEncodeAV1QualityLevelPropertiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeAV1RateControlFlagsKHR preferredRateControlFlags; + uint32_t preferredGopFrameCount; + uint32_t preferredKeyFramePeriod; + uint32_t preferredConsecutiveBipredictiveFrameCount; + uint32_t preferredTemporalLayerCount; + VkVideoEncodeAV1QIndexKHR preferredConstantQIndex; + uint32_t preferredMaxSingleReferenceCount; + uint32_t preferredSingleReferenceNameMask; + uint32_t preferredMaxUnidirectionalCompoundReferenceCount; + uint32_t preferredMaxUnidirectionalCompoundGroup1ReferenceCount; + uint32_t preferredUnidirectionalCompoundReferenceNameMask; + uint32_t preferredMaxBidirectionalCompoundReferenceCount; + uint32_t preferredMaxBidirectionalCompoundGroup1ReferenceCount; + uint32_t preferredMaxBidirectionalCompoundGroup2ReferenceCount; + uint32_t preferredBidirectionalCompoundReferenceNameMask; +} VkVideoEncodeAV1QualityLevelPropertiesKHR; + +typedef struct VkVideoEncodeAV1SessionCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 useMaxLevel; + StdVideoAV1Level maxLevel; +} VkVideoEncodeAV1SessionCreateInfoKHR; + +typedef struct VkVideoEncodeAV1SessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoAV1SequenceHeader* pStdSequenceHeader; + const StdVideoEncodeAV1DecoderModelInfo* pStdDecoderModelInfo; + uint32_t stdOperatingPointCount; + const StdVideoEncodeAV1OperatingPointInfo* pStdOperatingPoints; +} VkVideoEncodeAV1SessionParametersCreateInfoKHR; + +typedef struct VkVideoEncodeAV1PictureInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeAV1PredictionModeKHR predictionMode; + VkVideoEncodeAV1RateControlGroupKHR rateControlGroup; + uint32_t constantQIndex; + const StdVideoEncodeAV1PictureInfo* pStdPictureInfo; + int32_t referenceNameSlotIndices[VK_MAX_VIDEO_AV1_REFERENCES_PER_FRAME_KHR]; + VkBool32 primaryReferenceCdfOnly; + VkBool32 generateObuExtensionHeader; +} VkVideoEncodeAV1PictureInfoKHR; + +typedef struct VkVideoEncodeAV1DpbSlotInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoEncodeAV1ReferenceInfo* pStdReferenceInfo; +} VkVideoEncodeAV1DpbSlotInfoKHR; + +typedef struct VkVideoEncodeAV1ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoAV1Profile stdProfile; +} VkVideoEncodeAV1ProfileInfoKHR; + +typedef struct VkVideoEncodeAV1FrameSizeKHR { + uint32_t intraFrameSize; + uint32_t predictiveFrameSize; + uint32_t bipredictiveFrameSize; +} VkVideoEncodeAV1FrameSizeKHR; + +typedef struct VkVideoEncodeAV1GopRemainingFrameInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 useGopRemainingFrames; + uint32_t gopRemainingIntra; + uint32_t gopRemainingPredictive; + uint32_t gopRemainingBipredictive; +} VkVideoEncodeAV1GopRemainingFrameInfoKHR; + +typedef struct VkVideoEncodeAV1RateControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeAV1RateControlFlagsKHR flags; + uint32_t gopFrameCount; + uint32_t keyFramePeriod; + uint32_t consecutiveBipredictiveFrameCount; + uint32_t temporalLayerCount; +} VkVideoEncodeAV1RateControlInfoKHR; + +typedef struct VkVideoEncodeAV1RateControlLayerInfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 useMinQIndex; + VkVideoEncodeAV1QIndexKHR minQIndex; + VkBool32 useMaxQIndex; + VkVideoEncodeAV1QIndexKHR maxQIndex; + VkBool32 useMaxFrameSize; + VkVideoEncodeAV1FrameSizeKHR maxFrameSize; +} VkVideoEncodeAV1RateControlLayerInfoKHR; + + + +// VK_KHR_video_decode_vp9 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_decode_vp9 1 +#include "vk_video/vulkan_video_codec_vp9std.h" +#include "vk_video/vulkan_video_codec_vp9std_decode.h" +#define VK_MAX_VIDEO_VP9_REFERENCES_PER_FRAME_KHR 3U +#define VK_KHR_VIDEO_DECODE_VP9_SPEC_VERSION 1 +#define VK_KHR_VIDEO_DECODE_VP9_EXTENSION_NAME "VK_KHR_video_decode_vp9" +typedef struct VkPhysicalDeviceVideoDecodeVP9FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 videoDecodeVP9; +} VkPhysicalDeviceVideoDecodeVP9FeaturesKHR; + +typedef struct VkVideoDecodeVP9ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoVP9Profile stdProfile; +} VkVideoDecodeVP9ProfileInfoKHR; + +typedef struct VkVideoDecodeVP9CapabilitiesKHR { + VkStructureType sType; + void* pNext; + StdVideoVP9Level maxLevel; +} VkVideoDecodeVP9CapabilitiesKHR; + +typedef struct VkVideoDecodeVP9PictureInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeVP9PictureInfo* pStdPictureInfo; + int32_t referenceNameSlotIndices[VK_MAX_VIDEO_VP9_REFERENCES_PER_FRAME_KHR]; + uint32_t uncompressedHeaderOffset; + uint32_t compressedHeaderOffset; + uint32_t tilesOffset; +} VkVideoDecodeVP9PictureInfoKHR; + + + +// VK_KHR_video_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_maintenance1 1 +#define VK_KHR_VIDEO_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_video_maintenance1" +typedef struct VkPhysicalDeviceVideoMaintenance1FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 videoMaintenance1; +} VkPhysicalDeviceVideoMaintenance1FeaturesKHR; + +typedef struct VkVideoInlineQueryInfoKHR { + VkStructureType sType; + const void* pNext; + VkQueryPool queryPool; + uint32_t firstQuery; + uint32_t queryCount; +} VkVideoInlineQueryInfoKHR; + + + +// VK_KHR_vertex_attribute_divisor is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_vertex_attribute_divisor 1 +#define VK_KHR_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 1 +#define VK_KHR_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_KHR_vertex_attribute_divisor" +typedef VkPhysicalDeviceVertexAttributeDivisorProperties VkPhysicalDeviceVertexAttributeDivisorPropertiesKHR; + +typedef VkVertexInputBindingDivisorDescription VkVertexInputBindingDivisorDescriptionKHR; + +typedef VkPipelineVertexInputDivisorStateCreateInfo VkPipelineVertexInputDivisorStateCreateInfoKHR; + +typedef VkPhysicalDeviceVertexAttributeDivisorFeatures VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR; + + + +// VK_KHR_load_store_op_none is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_load_store_op_none 1 +#define VK_KHR_LOAD_STORE_OP_NONE_SPEC_VERSION 1 +#define VK_KHR_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_KHR_load_store_op_none" + + +// VK_KHR_unified_image_layouts is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_unified_image_layouts 1 +#define VK_KHR_UNIFIED_IMAGE_LAYOUTS_SPEC_VERSION 1 +#define VK_KHR_UNIFIED_IMAGE_LAYOUTS_EXTENSION_NAME "VK_KHR_unified_image_layouts" +typedef struct VkPhysicalDeviceUnifiedImageLayoutsFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 unifiedImageLayouts; + VkBool32 unifiedImageLayoutsVideo; +} VkPhysicalDeviceUnifiedImageLayoutsFeaturesKHR; + +typedef struct VkAttachmentFeedbackLoopInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 feedbackLoopEnable; +} VkAttachmentFeedbackLoopInfoEXT; + + + +// VK_KHR_shader_float_controls2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_float_controls2 1 +#define VK_KHR_SHADER_FLOAT_CONTROLS_2_SPEC_VERSION 1 +#define VK_KHR_SHADER_FLOAT_CONTROLS_2_EXTENSION_NAME "VK_KHR_shader_float_controls2" +typedef VkPhysicalDeviceShaderFloatControls2Features VkPhysicalDeviceShaderFloatControls2FeaturesKHR; + + + +// VK_KHR_index_type_uint8 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_index_type_uint8 1 +#define VK_KHR_INDEX_TYPE_UINT8_SPEC_VERSION 1 +#define VK_KHR_INDEX_TYPE_UINT8_EXTENSION_NAME "VK_KHR_index_type_uint8" +typedef VkPhysicalDeviceIndexTypeUint8Features VkPhysicalDeviceIndexTypeUint8FeaturesKHR; + + + +// VK_KHR_line_rasterization is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_line_rasterization 1 +#define VK_KHR_LINE_RASTERIZATION_SPEC_VERSION 1 +#define VK_KHR_LINE_RASTERIZATION_EXTENSION_NAME "VK_KHR_line_rasterization" +typedef VkLineRasterizationMode VkLineRasterizationModeKHR; + +typedef VkPhysicalDeviceLineRasterizationFeatures VkPhysicalDeviceLineRasterizationFeaturesKHR; + +typedef VkPhysicalDeviceLineRasterizationProperties VkPhysicalDeviceLineRasterizationPropertiesKHR; + +typedef VkPipelineRasterizationLineStateCreateInfo VkPipelineRasterizationLineStateCreateInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleKHR)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleKHR( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern); +#endif +#endif + + +// VK_KHR_calibrated_timestamps is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_calibrated_timestamps 1 +#define VK_KHR_CALIBRATED_TIMESTAMPS_SPEC_VERSION 1 +#define VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_KHR_calibrated_timestamps" + +typedef enum VkTimeDomainKHR { + VK_TIME_DOMAIN_DEVICE_KHR = 0, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR = 1, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR = 2, + VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR = 3, + VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT = 1000208000, + VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT = 1000208001, + VK_TIME_DOMAIN_DEVICE_EXT = VK_TIME_DOMAIN_DEVICE_KHR, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR, + VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR, + VK_TIME_DOMAIN_MAX_ENUM_KHR = 0x7FFFFFFF +} VkTimeDomainKHR; +typedef struct VkCalibratedTimestampInfoKHR { + VkStructureType sType; + const void* pNext; + VkTimeDomainKHR timeDomain; +} VkCalibratedTimestampInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR)(VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainKHR* pTimeDomains); +typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsKHR)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoKHR* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pTimeDomainCount, + VkTimeDomainKHR* pTimeDomains); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsKHR( + VkDevice device, + uint32_t timestampCount, + const VkCalibratedTimestampInfoKHR* pTimestampInfos, + uint64_t* pTimestamps, + uint64_t* pMaxDeviation); +#endif +#endif + + +// VK_KHR_shader_expect_assume is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_expect_assume 1 +#define VK_KHR_SHADER_EXPECT_ASSUME_SPEC_VERSION 1 +#define VK_KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME "VK_KHR_shader_expect_assume" +typedef VkPhysicalDeviceShaderExpectAssumeFeatures VkPhysicalDeviceShaderExpectAssumeFeaturesKHR; + + + +// VK_KHR_maintenance6 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance6 1 +#define VK_KHR_MAINTENANCE_6_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_6_EXTENSION_NAME "VK_KHR_maintenance6" +typedef VkPhysicalDeviceMaintenance6Features VkPhysicalDeviceMaintenance6FeaturesKHR; + +typedef VkPhysicalDeviceMaintenance6Properties VkPhysicalDeviceMaintenance6PropertiesKHR; + +typedef VkBindMemoryStatus VkBindMemoryStatusKHR; + +typedef VkBindDescriptorSetsInfo VkBindDescriptorSetsInfoKHR; + +typedef VkPushConstantsInfo VkPushConstantsInfoKHR; + +typedef VkPushDescriptorSetInfo VkPushDescriptorSetInfoKHR; + +typedef VkPushDescriptorSetWithTemplateInfo VkPushDescriptorSetWithTemplateInfoKHR; + +typedef struct VkSetDescriptorBufferOffsetsInfoEXT { + VkStructureType sType; + const void* pNext; + VkShaderStageFlags stageFlags; + VkPipelineLayout layout; + uint32_t firstSet; + uint32_t setCount; + const uint32_t* pBufferIndices; + const VkDeviceSize* pOffsets; +} VkSetDescriptorBufferOffsetsInfoEXT; + +typedef struct VkBindDescriptorBufferEmbeddedSamplersInfoEXT { + VkStructureType sType; + const void* pNext; + VkShaderStageFlags stageFlags; + VkPipelineLayout layout; + uint32_t set; +} VkBindDescriptorBufferEmbeddedSamplersInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets2KHR)(VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushConstants2KHR)(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSet2KHR)(VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplate2KHR)(VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo); +typedef void (VKAPI_PTR *PFN_vkCmdSetDescriptorBufferOffsets2EXT)(VkCommandBuffer commandBuffer, const VkSetDescriptorBufferOffsetsInfoEXT* pSetDescriptorBufferOffsetsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT)(VkCommandBuffer commandBuffer, const VkBindDescriptorBufferEmbeddedSamplersInfoEXT* pBindDescriptorBufferEmbeddedSamplersInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets2KHR( + VkCommandBuffer commandBuffer, + const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants2KHR( + VkCommandBuffer commandBuffer, + const VkPushConstantsInfo* pPushConstantsInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSet2KHR( + VkCommandBuffer commandBuffer, + const VkPushDescriptorSetInfo* pPushDescriptorSetInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplate2KHR( + VkCommandBuffer commandBuffer, + const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDescriptorBufferOffsets2EXT( + VkCommandBuffer commandBuffer, + const VkSetDescriptorBufferOffsetsInfoEXT* pSetDescriptorBufferOffsetsInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorBufferEmbeddedSamplers2EXT( + VkCommandBuffer commandBuffer, + const VkBindDescriptorBufferEmbeddedSamplersInfoEXT* pBindDescriptorBufferEmbeddedSamplersInfo); +#endif +#endif + + +// VK_KHR_copy_memory_indirect is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_copy_memory_indirect 1 +#define VK_KHR_COPY_MEMORY_INDIRECT_SPEC_VERSION 1 +#define VK_KHR_COPY_MEMORY_INDIRECT_EXTENSION_NAME "VK_KHR_copy_memory_indirect" + +typedef enum VkAddressCopyFlagBitsKHR { + VK_ADDRESS_COPY_DEVICE_LOCAL_BIT_KHR = 0x00000001, + VK_ADDRESS_COPY_SPARSE_BIT_KHR = 0x00000002, + VK_ADDRESS_COPY_PROTECTED_BIT_KHR = 0x00000004, + VK_ADDRESS_COPY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAddressCopyFlagBitsKHR; +typedef VkFlags VkAddressCopyFlagsKHR; +typedef struct VkCopyMemoryIndirectCommandKHR { + VkDeviceAddress srcAddress; + VkDeviceAddress dstAddress; + VkDeviceSize size; +} VkCopyMemoryIndirectCommandKHR; + +typedef struct VkCopyMemoryIndirectInfoKHR { + VkStructureType sType; + const void* pNext; + VkAddressCopyFlagsKHR srcCopyFlags; + VkAddressCopyFlagsKHR dstCopyFlags; + uint32_t copyCount; + VkStridedDeviceAddressRangeKHR copyAddressRange; +} VkCopyMemoryIndirectInfoKHR; + +typedef struct VkCopyMemoryToImageIndirectCommandKHR { + VkDeviceAddress srcAddress; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkCopyMemoryToImageIndirectCommandKHR; + +typedef struct VkCopyMemoryToImageIndirectInfoKHR { + VkStructureType sType; + const void* pNext; + VkAddressCopyFlagsKHR srcCopyFlags; + uint32_t copyCount; + VkStridedDeviceAddressRangeKHR copyAddressRange; + VkImage dstImage; + VkImageLayout dstImageLayout; + const VkImageSubresourceLayers* pImageSubresources; +} VkCopyMemoryToImageIndirectInfoKHR; + +typedef struct VkPhysicalDeviceCopyMemoryIndirectFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 indirectMemoryCopy; + VkBool32 indirectMemoryToImageCopy; +} VkPhysicalDeviceCopyMemoryIndirectFeaturesKHR; + +typedef struct VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR { + VkStructureType sType; + void* pNext; + VkQueueFlags supportedQueues; +} VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryIndirectKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryIndirectInfoKHR* pCopyMemoryIndirectInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToImageIndirectKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToImageIndirectInfoKHR* pCopyMemoryToImageIndirectInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryIndirectKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryIndirectInfoKHR* pCopyMemoryIndirectInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageIndirectKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryToImageIndirectInfoKHR* pCopyMemoryToImageIndirectInfo); +#endif +#endif + + +// VK_KHR_video_encode_intra_refresh is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_encode_intra_refresh 1 +#define VK_KHR_VIDEO_ENCODE_INTRA_REFRESH_SPEC_VERSION 1 +#define VK_KHR_VIDEO_ENCODE_INTRA_REFRESH_EXTENSION_NAME "VK_KHR_video_encode_intra_refresh" + +typedef enum VkVideoEncodeIntraRefreshModeFlagBitsKHR { + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_NONE_KHR = 0, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_PER_PICTURE_PARTITION_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_BASED_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_ROW_BASED_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_COLUMN_BASED_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeIntraRefreshModeFlagBitsKHR; +typedef VkFlags VkVideoEncodeIntraRefreshModeFlagsKHR; +typedef struct VkVideoEncodeIntraRefreshCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeIntraRefreshModeFlagsKHR intraRefreshModes; + uint32_t maxIntraRefreshCycleDuration; + uint32_t maxIntraRefreshActiveReferencePictures; + VkBool32 partitionIndependentIntraRefreshRegions; + VkBool32 nonRectangularIntraRefreshRegions; +} VkVideoEncodeIntraRefreshCapabilitiesKHR; + +typedef struct VkVideoEncodeSessionIntraRefreshCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeIntraRefreshModeFlagBitsKHR intraRefreshMode; +} VkVideoEncodeSessionIntraRefreshCreateInfoKHR; + +typedef struct VkVideoEncodeIntraRefreshInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t intraRefreshCycleDuration; + uint32_t intraRefreshIndex; +} VkVideoEncodeIntraRefreshInfoKHR; + +typedef struct VkVideoReferenceIntraRefreshInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t dirtyIntraRefreshRegions; +} VkVideoReferenceIntraRefreshInfoKHR; + +typedef struct VkPhysicalDeviceVideoEncodeIntraRefreshFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 videoEncodeIntraRefresh; +} VkPhysicalDeviceVideoEncodeIntraRefreshFeaturesKHR; + + + +// VK_KHR_video_encode_quantization_map is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_encode_quantization_map 1 +#define VK_KHR_VIDEO_ENCODE_QUANTIZATION_MAP_SPEC_VERSION 2 +#define VK_KHR_VIDEO_ENCODE_QUANTIZATION_MAP_EXTENSION_NAME "VK_KHR_video_encode_quantization_map" +typedef struct VkVideoEncodeQuantizationMapCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkExtent2D maxQuantizationMapExtent; +} VkVideoEncodeQuantizationMapCapabilitiesKHR; + +typedef struct VkVideoFormatQuantizationMapPropertiesKHR { + VkStructureType sType; + void* pNext; + VkExtent2D quantizationMapTexelSize; +} VkVideoFormatQuantizationMapPropertiesKHR; + +typedef struct VkVideoEncodeQuantizationMapInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView quantizationMap; + VkExtent2D quantizationMapExtent; +} VkVideoEncodeQuantizationMapInfoKHR; + +typedef struct VkVideoEncodeQuantizationMapSessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkExtent2D quantizationMapTexelSize; +} VkVideoEncodeQuantizationMapSessionParametersCreateInfoKHR; + +typedef struct VkPhysicalDeviceVideoEncodeQuantizationMapFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 videoEncodeQuantizationMap; +} VkPhysicalDeviceVideoEncodeQuantizationMapFeaturesKHR; + +typedef struct VkVideoEncodeH264QuantizationMapCapabilitiesKHR { + VkStructureType sType; + void* pNext; + int32_t minQpDelta; + int32_t maxQpDelta; +} VkVideoEncodeH264QuantizationMapCapabilitiesKHR; + +typedef struct VkVideoEncodeH265QuantizationMapCapabilitiesKHR { + VkStructureType sType; + void* pNext; + int32_t minQpDelta; + int32_t maxQpDelta; +} VkVideoEncodeH265QuantizationMapCapabilitiesKHR; + +typedef struct VkVideoFormatH265QuantizationMapPropertiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeH265CtbSizeFlagsKHR compatibleCtbSizes; +} VkVideoFormatH265QuantizationMapPropertiesKHR; + +typedef struct VkVideoEncodeAV1QuantizationMapCapabilitiesKHR { + VkStructureType sType; + void* pNext; + int32_t minQIndexDelta; + int32_t maxQIndexDelta; +} VkVideoEncodeAV1QuantizationMapCapabilitiesKHR; + +typedef struct VkVideoFormatAV1QuantizationMapPropertiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeAV1SuperblockSizeFlagsKHR compatibleSuperblockSizes; +} VkVideoFormatAV1QuantizationMapPropertiesKHR; + + + +// VK_KHR_shader_relaxed_extended_instruction is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_relaxed_extended_instruction 1 +#define VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_SPEC_VERSION 1 +#define VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME "VK_KHR_shader_relaxed_extended_instruction" +typedef struct VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderRelaxedExtendedInstruction; +} VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR; + + + +// VK_KHR_maintenance7 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance7 1 +#define VK_KHR_MAINTENANCE_7_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_7_EXTENSION_NAME "VK_KHR_maintenance7" + +typedef enum VkPhysicalDeviceLayeredApiKHR { + VK_PHYSICAL_DEVICE_LAYERED_API_VULKAN_KHR = 0, + VK_PHYSICAL_DEVICE_LAYERED_API_D3D12_KHR = 1, + VK_PHYSICAL_DEVICE_LAYERED_API_METAL_KHR = 2, + VK_PHYSICAL_DEVICE_LAYERED_API_OPENGL_KHR = 3, + VK_PHYSICAL_DEVICE_LAYERED_API_OPENGLES_KHR = 4, + VK_PHYSICAL_DEVICE_LAYERED_API_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPhysicalDeviceLayeredApiKHR; +typedef struct VkPhysicalDeviceMaintenance7FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance7; +} VkPhysicalDeviceMaintenance7FeaturesKHR; + +typedef struct VkPhysicalDeviceMaintenance7PropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 robustFragmentShadingRateAttachmentAccess; + VkBool32 separateDepthStencilAttachmentAccess; + uint32_t maxDescriptorSetTotalUniformBuffersDynamic; + uint32_t maxDescriptorSetTotalStorageBuffersDynamic; + uint32_t maxDescriptorSetTotalBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindTotalUniformBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindTotalStorageBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindTotalBuffersDynamic; +} VkPhysicalDeviceMaintenance7PropertiesKHR; + +typedef struct VkPhysicalDeviceLayeredApiPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t vendorID; + uint32_t deviceID; + VkPhysicalDeviceLayeredApiKHR layeredAPI; + char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; +} VkPhysicalDeviceLayeredApiPropertiesKHR; + +typedef struct VkPhysicalDeviceLayeredApiPropertiesListKHR { + VkStructureType sType; + void* pNext; + uint32_t layeredApiCount; + VkPhysicalDeviceLayeredApiPropertiesKHR* pLayeredApis; +} VkPhysicalDeviceLayeredApiPropertiesListKHR; + +typedef struct VkPhysicalDeviceLayeredApiVulkanPropertiesKHR { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceProperties2 properties; +} VkPhysicalDeviceLayeredApiVulkanPropertiesKHR; + + + +// VK_KHR_device_fault is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_device_fault 1 +#define VK_KHR_DEVICE_FAULT_SPEC_VERSION 1 +#define VK_KHR_DEVICE_FAULT_EXTENSION_NAME "VK_KHR_device_fault" + +typedef enum VkDeviceFaultAddressTypeKHR { + VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_KHR = 0, + VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_KHR = 1, + VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_KHR = 2, + VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_KHR = 3, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_KHR = 4, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_KHR = 5, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_KHR = 6, + VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceFaultAddressTypeKHR; + +typedef enum VkDeviceFaultVendorBinaryHeaderVersionKHR { + VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_KHR = 1, + VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_EXT = VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_KHR, + VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceFaultVendorBinaryHeaderVersionKHR; + +typedef enum VkDeviceFaultFlagBitsKHR { + VK_DEVICE_FAULT_FLAG_DEVICE_LOST_KHR = 0x00000001, + VK_DEVICE_FAULT_FLAG_MEMORY_ADDRESS_KHR = 0x00000002, + VK_DEVICE_FAULT_FLAG_INSTRUCTION_ADDRESS_KHR = 0x00000004, + VK_DEVICE_FAULT_FLAG_VENDOR_KHR = 0x00000008, + VK_DEVICE_FAULT_FLAG_WATCHDOG_TIMEOUT_KHR = 0x00000010, + VK_DEVICE_FAULT_FLAG_OVERFLOW_KHR = 0x00000020, + VK_DEVICE_FAULT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceFaultFlagBitsKHR; +typedef VkFlags VkDeviceFaultFlagsKHR; +typedef struct VkPhysicalDeviceFaultFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 deviceFault; + VkBool32 deviceFaultVendorBinary; + VkBool32 deviceFaultReportMasked; + VkBool32 deviceFaultDeviceLostOnMasked; +} VkPhysicalDeviceFaultFeaturesKHR; + +typedef struct VkPhysicalDeviceFaultPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t maxDeviceFaultCount; +} VkPhysicalDeviceFaultPropertiesKHR; + +typedef struct VkDeviceFaultAddressInfoKHR { + VkDeviceFaultAddressTypeKHR addressType; + VkDeviceAddress reportedAddress; + VkDeviceSize addressPrecision; +} VkDeviceFaultAddressInfoKHR; + +typedef struct VkDeviceFaultVendorInfoKHR { + char description[VK_MAX_DESCRIPTION_SIZE]; + uint64_t vendorFaultCode; + uint64_t vendorFaultData; +} VkDeviceFaultVendorInfoKHR; + +typedef struct VkDeviceFaultInfoKHR { + VkStructureType sType; + void* pNext; + VkDeviceFaultFlagsKHR flags; + uint64_t groupId; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkDeviceFaultAddressInfoKHR faultAddressInfo; + VkDeviceFaultAddressInfoKHR instructionAddressInfo; + VkDeviceFaultVendorInfoKHR vendorInfo; +} VkDeviceFaultInfoKHR; + +typedef struct VkDeviceFaultDebugInfoKHR { + VkStructureType sType; + void* pNext; + uint32_t vendorBinarySize; + void* pVendorBinaryData; +} VkDeviceFaultDebugInfoKHR; + +typedef struct VkDeviceFaultVendorBinaryHeaderVersionOneKHR { + uint32_t headerSize; + VkDeviceFaultVendorBinaryHeaderVersionKHR headerVersion; + uint32_t vendorID; + uint32_t deviceID; + uint32_t driverVersion; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; + uint32_t applicationNameOffset; + uint32_t applicationVersion; + uint32_t engineNameOffset; + uint32_t engineVersion; + uint32_t apiVersion; +} VkDeviceFaultVendorBinaryHeaderVersionOneKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceFaultReportsKHR)(VkDevice device, uint64_t timeout, uint32_t* pFaultCounts, VkDeviceFaultInfoKHR* pFaultInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceFaultDebugInfoKHR)(VkDevice device, VkDeviceFaultDebugInfoKHR* pDebugInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceFaultReportsKHR( + VkDevice device, + uint64_t timeout, + uint32_t* pFaultCounts, + VkDeviceFaultInfoKHR* pFaultInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceFaultDebugInfoKHR( + VkDevice device, + VkDeviceFaultDebugInfoKHR* pDebugInfo); +#endif +#endif + + +// VK_KHR_maintenance8 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance8 1 +#define VK_KHR_MAINTENANCE_8_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_8_EXTENSION_NAME "VK_KHR_maintenance8" +typedef VkFlags64 VkAccessFlags3KHR; + +// Flag bits for VkAccessFlagBits3KHR +typedef VkFlags64 VkAccessFlagBits3KHR; +static const VkAccessFlagBits3KHR VK_ACCESS_3_NONE_KHR = 0ULL; + +typedef struct VkMemoryBarrierAccessFlags3KHR { + VkStructureType sType; + const void* pNext; + VkAccessFlags3KHR srcAccessMask3; + VkAccessFlags3KHR dstAccessMask3; +} VkMemoryBarrierAccessFlags3KHR; + +typedef struct VkPhysicalDeviceMaintenance8FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance8; +} VkPhysicalDeviceMaintenance8FeaturesKHR; + + + +// VK_KHR_shader_fma is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_fma 1 +#define VK_KHR_SHADER_FMA_SPEC_VERSION 1 +#define VK_KHR_SHADER_FMA_EXTENSION_NAME "VK_KHR_shader_fma" +typedef struct VkPhysicalDeviceShaderFmaFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderFmaFloat16; + VkBool32 shaderFmaFloat32; + VkBool32 shaderFmaFloat64; +} VkPhysicalDeviceShaderFmaFeaturesKHR; + + + +// VK_KHR_maintenance9 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance9 1 +#define VK_KHR_MAINTENANCE_9_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_9_EXTENSION_NAME "VK_KHR_maintenance9" + +typedef enum VkDefaultVertexAttributeValueKHR { + VK_DEFAULT_VERTEX_ATTRIBUTE_VALUE_ZERO_ZERO_ZERO_ZERO_KHR = 0, + VK_DEFAULT_VERTEX_ATTRIBUTE_VALUE_ZERO_ZERO_ZERO_ONE_KHR = 1, + VK_DEFAULT_VERTEX_ATTRIBUTE_VALUE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDefaultVertexAttributeValueKHR; +typedef struct VkPhysicalDeviceMaintenance9FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance9; +} VkPhysicalDeviceMaintenance9FeaturesKHR; + +typedef struct VkPhysicalDeviceMaintenance9PropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 image2DViewOf3DSparse; + VkDefaultVertexAttributeValueKHR defaultVertexAttributeValue; +} VkPhysicalDeviceMaintenance9PropertiesKHR; + +typedef struct VkQueueFamilyOwnershipTransferPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t optimalImageTransferToQueueFamilies; +} VkQueueFamilyOwnershipTransferPropertiesKHR; + + + +// VK_KHR_video_maintenance2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_maintenance2 1 +#define VK_KHR_VIDEO_MAINTENANCE_2_SPEC_VERSION 1 +#define VK_KHR_VIDEO_MAINTENANCE_2_EXTENSION_NAME "VK_KHR_video_maintenance2" +typedef struct VkPhysicalDeviceVideoMaintenance2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 videoMaintenance2; +} VkPhysicalDeviceVideoMaintenance2FeaturesKHR; + +typedef struct VkVideoDecodeH264InlineSessionParametersInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoH264SequenceParameterSet* pStdSPS; + const StdVideoH264PictureParameterSet* pStdPPS; +} VkVideoDecodeH264InlineSessionParametersInfoKHR; + +typedef struct VkVideoDecodeH265InlineSessionParametersInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoH265VideoParameterSet* pStdVPS; + const StdVideoH265SequenceParameterSet* pStdSPS; + const StdVideoH265PictureParameterSet* pStdPPS; +} VkVideoDecodeH265InlineSessionParametersInfoKHR; + +typedef struct VkVideoDecodeAV1InlineSessionParametersInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoAV1SequenceHeader* pStdSequenceHeader; +} VkVideoDecodeAV1InlineSessionParametersInfoKHR; + + + +// VK_KHR_depth_clamp_zero_one is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_depth_clamp_zero_one 1 +#define VK_KHR_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION 1 +#define VK_KHR_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME "VK_KHR_depth_clamp_zero_one" +typedef struct VkPhysicalDeviceDepthClampZeroOneFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 depthClampZeroOne; +} VkPhysicalDeviceDepthClampZeroOneFeaturesKHR; + + + +// VK_KHR_robustness2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_robustness2 1 +#define VK_KHR_ROBUSTNESS_2_SPEC_VERSION 1 +#define VK_KHR_ROBUSTNESS_2_EXTENSION_NAME "VK_KHR_robustness2" +typedef struct VkPhysicalDeviceRobustness2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 robustBufferAccess2; + VkBool32 robustImageAccess2; + VkBool32 nullDescriptor; +} VkPhysicalDeviceRobustness2FeaturesKHR; + +typedef struct VkPhysicalDeviceRobustness2PropertiesKHR { + VkStructureType sType; + void* pNext; + VkDeviceSize robustStorageBufferAccessSizeAlignment; + VkDeviceSize robustUniformBufferAccessSizeAlignment; +} VkPhysicalDeviceRobustness2PropertiesKHR; + + + +// VK_KHR_present_mode_fifo_latest_ready is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_mode_fifo_latest_ready 1 +#define VK_KHR_PRESENT_MODE_FIFO_LATEST_READY_SPEC_VERSION 1 +#define VK_KHR_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME "VK_KHR_present_mode_fifo_latest_ready" +typedef struct VkPhysicalDevicePresentModeFifoLatestReadyFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentModeFifoLatestReady; +} VkPhysicalDevicePresentModeFifoLatestReadyFeaturesKHR; + + + +// VK_KHR_opacity_micromap is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_opacity_micromap 1 +#define VK_KHR_OPACITY_MICROMAP_SPEC_VERSION 1 +#define VK_KHR_OPACITY_MICROMAP_EXTENSION_NAME "VK_KHR_opacity_micromap" + +typedef enum VkOpacityMicromapFormatKHR { + VK_OPACITY_MICROMAP_FORMAT_2_STATE_KHR = 1, + VK_OPACITY_MICROMAP_FORMAT_4_STATE_KHR = 2, + VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT = VK_OPACITY_MICROMAP_FORMAT_2_STATE_KHR, + VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT = VK_OPACITY_MICROMAP_FORMAT_4_STATE_KHR, + VK_OPACITY_MICROMAP_FORMAT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkOpacityMicromapFormatKHR; + +typedef enum VkOpacityMicromapSpecialIndexKHR { + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_KHR = -1, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_KHR = -2, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_KHR = -3, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_KHR = -4, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_CLUSTER_GEOMETRY_DISABLE_OPACITY_MICROMAP_NV = -5, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT = VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_KHR, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT = VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_KHR, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT = VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_KHR, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT = VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_KHR, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_MAX_ENUM_KHR = 0x7FFFFFFF +} VkOpacityMicromapSpecialIndexKHR; + +typedef enum VkAccelerationStructureSerializedBlockTypeKHR { + VK_ACCELERATION_STRUCTURE_SERIALIZED_BLOCK_TYPE_OPACITY_MICROMAP_KHR = 0, + VK_ACCELERATION_STRUCTURE_SERIALIZED_BLOCK_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureSerializedBlockTypeKHR; +typedef struct VkMicromapUsageKHR { + uint32_t count; + uint32_t subdivisionLevel; + VkOpacityMicromapFormatKHR format; +} VkMicromapUsageKHR; + +typedef struct VkAccelerationStructureGeometryMicromapDataKHR { + VkStructureType sType; + const void* pNext; + uint32_t usageCountsCount; + const VkMicromapUsageKHR* pUsageCounts; + const VkMicromapUsageKHR* const* ppUsageCounts; + VkDeviceAddress data; + VkDeviceAddress triangleArray; + VkDeviceSize triangleArrayStride; +} VkAccelerationStructureGeometryMicromapDataKHR; + +typedef struct VkPhysicalDeviceOpacityMicromapFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 micromap; +} VkPhysicalDeviceOpacityMicromapFeaturesKHR; + +typedef struct VkPhysicalDeviceOpacityMicromapPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t maxOpacity2StateSubdivisionLevel; + uint32_t maxOpacity4StateSubdivisionLevel; + uint32_t maxOpacityLossy4StateSubdivisionLevel; + uint64_t maxMicromapTriangles; +} VkPhysicalDeviceOpacityMicromapPropertiesKHR; + +typedef struct VkMicromapTriangleKHR { + uint32_t dataOffset; + uint16_t subdivisionLevel; + uint16_t format; +} VkMicromapTriangleKHR; + +typedef struct VkAccelerationStructureTrianglesOpacityMicromapKHR { + VkStructureType sType; + void* pNext; + VkIndexType indexType; + VkDeviceAddress indexBuffer; + VkDeviceSize indexStride; + uint32_t baseTriangle; + VkAccelerationStructureKHR micromap; +} VkAccelerationStructureTrianglesOpacityMicromapKHR; + + + +// VK_KHR_maintenance10 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance10 1 +#define VK_KHR_MAINTENANCE_10_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_10_EXTENSION_NAME "VK_KHR_maintenance10" + +typedef enum VkRenderingAttachmentFlagBitsKHR { + VK_RENDERING_ATTACHMENT_INPUT_ATTACHMENT_FEEDBACK_BIT_KHR = 0x00000001, + VK_RENDERING_ATTACHMENT_RESOLVE_SKIP_TRANSFER_FUNCTION_BIT_KHR = 0x00000002, + VK_RENDERING_ATTACHMENT_RESOLVE_ENABLE_TRANSFER_FUNCTION_BIT_KHR = 0x00000004, + VK_RENDERING_ATTACHMENT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRenderingAttachmentFlagBitsKHR; +typedef VkFlags VkRenderingAttachmentFlagsKHR; + +typedef enum VkResolveImageFlagBitsKHR { + VK_RESOLVE_IMAGE_SKIP_TRANSFER_FUNCTION_BIT_KHR = 0x00000001, + VK_RESOLVE_IMAGE_ENABLE_TRANSFER_FUNCTION_BIT_KHR = 0x00000002, + VK_RESOLVE_IMAGE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkResolveImageFlagBitsKHR; +typedef VkFlags VkResolveImageFlagsKHR; +typedef struct VkPhysicalDeviceMaintenance10FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance10; +} VkPhysicalDeviceMaintenance10FeaturesKHR; + +typedef struct VkPhysicalDeviceMaintenance10PropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rgba4OpaqueBlackSwizzled; + VkBool32 resolveSrgbFormatAppliesTransferFunction; + VkBool32 resolveSrgbFormatSupportsTransferFunctionControl; +} VkPhysicalDeviceMaintenance10PropertiesKHR; + +typedef struct VkRenderingEndInfoKHR { + VkStructureType sType; + const void* pNext; +} VkRenderingEndInfoKHR; + +typedef struct VkRenderingAttachmentFlagsInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingAttachmentFlagsKHR flags; +} VkRenderingAttachmentFlagsInfoKHR; + +typedef struct VkResolveImageModeInfoKHR { + VkStructureType sType; + const void* pNext; + VkResolveImageFlagsKHR flags; + VkResolveModeFlagBits resolveMode; + VkResolveModeFlagBits stencilResolveMode; +} VkResolveImageModeInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdEndRendering2KHR)(VkCommandBuffer commandBuffer, const VkRenderingEndInfoKHR* pRenderingEndInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndRendering2KHR( + VkCommandBuffer commandBuffer, + const VkRenderingEndInfoKHR* pRenderingEndInfo); +#endif +#endif + + +// VK_KHR_maintenance11 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance11 1 +#define VK_KHR_MAINTENANCE_11_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_11_EXTENSION_NAME "VK_KHR_maintenance11" +typedef struct VkPhysicalDeviceMaintenance11FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance11; +} VkPhysicalDeviceMaintenance11FeaturesKHR; + +typedef struct VkQueueFamilyOptimalImageTransferGranularityPropertiesKHR { + VkStructureType sType; + void* pNext; + VkExtent3D optimalImageTransferGranularity; +} VkQueueFamilyOptimalImageTransferGranularityPropertiesKHR; + + + +// VK_EXT_debug_report is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_debug_report 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) +#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10 +#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" + +typedef enum VkDebugReportObjectTypeEXT { + 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_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, + 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_ACCELERATION_STRUCTURE_KHR_EXT = 1000150000, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000, + VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_MODULE_NV_EXT = 1000307000, + VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_FUNCTION_NV_EXT = 1000307001, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT = 1000366000, + // VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT is a legacy alias + VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, + // VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT is a legacy alias + VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugReportObjectTypeEXT; + +typedef enum VkDebugReportFlagBitsEXT { + VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001, + VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002, + VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004, + VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008, + VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010, + VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugReportFlagBitsEXT; +typedef VkFlags VkDebugReportFlagsEXT; +typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, + void* pUserData); + +typedef struct VkDebugReportCallbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportFlagsEXT flags; + PFN_vkDebugReportCallbackEXT pfnCallback; + void* pUserData; +} VkDebugReportCallbackCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); +typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT( + VkInstance instance, + const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugReportCallbackEXT* pCallback); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT( + VkInstance instance, + VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( + VkInstance instance, + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage); +#endif +#endif + + +// VK_NV_glsl_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_glsl_shader 1 +#define VK_NV_GLSL_SHADER_SPEC_VERSION 1 +#define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader" + + +// VK_EXT_depth_range_unrestricted is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_range_unrestricted 1 +#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION 1 +#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME "VK_EXT_depth_range_unrestricted" + + +// VK_IMG_filter_cubic is a preprocessor guard. Do not pass it to API calls. +#define VK_IMG_filter_cubic 1 +#define VK_IMG_FILTER_CUBIC_SPEC_VERSION 1 +#define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic" + + +// VK_AMD_rasterization_order is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_rasterization_order 1 +#define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1 +#define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order" + +typedef enum VkRasterizationOrderAMD { + VK_RASTERIZATION_ORDER_STRICT_AMD = 0, + VK_RASTERIZATION_ORDER_RELAXED_AMD = 1, + VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF +} VkRasterizationOrderAMD; +typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { + VkStructureType sType; + const void* pNext; + VkRasterizationOrderAMD rasterizationOrder; +} VkPipelineRasterizationStateRasterizationOrderAMD; + + + +// VK_AMD_shader_trinary_minmax is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_trinary_minmax 1 +#define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1 +#define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax" + + +// VK_AMD_shader_explicit_vertex_parameter is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_explicit_vertex_parameter 1 +#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1 +#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter" + + +// VK_EXT_debug_marker is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_debug_marker 1 +#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4 +#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker" +typedef struct VkDebugMarkerObjectNameInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportObjectTypeEXT objectType; + uint64_t object; + const char* pObjectName; +} VkDebugMarkerObjectNameInfoEXT; + +typedef struct VkDebugMarkerObjectTagInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportObjectTypeEXT objectType; + uint64_t object; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugMarkerObjectTagInfoEXT; + +typedef struct VkDebugMarkerMarkerInfoEXT { + VkStructureType sType; + const void* pNext; + const char* pMarkerName; + float color[4]; +} VkDebugMarkerMarkerInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectTagEXT)(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo); +typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectNameEXT)(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerBeginEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerEndEXT)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerInsertEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectTagEXT( + VkDevice device, + const VkDebugMarkerObjectTagInfoEXT* pTagInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectNameEXT( + VkDevice device, + const VkDebugMarkerObjectNameInfoEXT* pNameInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerBeginEXT( + VkCommandBuffer commandBuffer, + const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerEndEXT( + VkCommandBuffer commandBuffer); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( + VkCommandBuffer commandBuffer, + const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +#endif +#endif + + +// VK_AMD_gcn_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_gcn_shader 1 +#define VK_AMD_GCN_SHADER_SPEC_VERSION 1 +#define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader" + + +// VK_NV_dedicated_allocation is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_dedicated_allocation 1 +#define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1 +#define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation" +typedef struct VkDedicatedAllocationImageCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 dedicatedAllocation; +} VkDedicatedAllocationImageCreateInfoNV; + +typedef struct VkDedicatedAllocationBufferCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 dedicatedAllocation; +} VkDedicatedAllocationBufferCreateInfoNV; + +typedef struct VkDedicatedAllocationMemoryAllocateInfoNV { + VkStructureType sType; + const void* pNext; + VkImage image; + VkBuffer buffer; +} VkDedicatedAllocationMemoryAllocateInfoNV; + + + +// VK_EXT_transform_feedback is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_transform_feedback 1 +#define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback" +typedef VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT; +typedef struct VkPhysicalDeviceTransformFeedbackFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 transformFeedback; + VkBool32 geometryStreams; +} VkPhysicalDeviceTransformFeedbackFeaturesEXT; + +typedef struct VkPhysicalDeviceTransformFeedbackPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxTransformFeedbackStreams; + uint32_t maxTransformFeedbackBuffers; + VkDeviceSize maxTransformFeedbackBufferSize; + uint32_t maxTransformFeedbackStreamDataSize; + uint32_t maxTransformFeedbackBufferDataSize; + uint32_t maxTransformFeedbackBufferDataStride; + VkBool32 transformFeedbackQueries; + VkBool32 transformFeedbackStreamsLinesTriangles; + VkBool32 transformFeedbackRasterizationStreamSelect; + VkBool32 transformFeedbackDraw; +} VkPhysicalDeviceTransformFeedbackPropertiesEXT; + +typedef struct VkPipelineRasterizationStateStreamCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationStateStreamCreateFlagsEXT flags; + uint32_t rasterizationStream; +} VkPipelineRasterizationStateStreamCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes); +typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdBeginQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdEndQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCountEXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedbackEXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedbackEXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags, + uint32_t index); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + uint32_t index); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( + VkCommandBuffer commandBuffer, + uint32_t instanceCount, + uint32_t firstInstance, + VkBuffer counterBuffer, + VkDeviceSize counterBufferOffset, + uint32_t counterOffset, + uint32_t vertexStride); +#endif +#endif + + +// VK_NVX_binary_import is a preprocessor guard. Do not pass it to API calls. +#define VK_NVX_binary_import 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuModuleNVX) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuFunctionNVX) +#define VK_NVX_BINARY_IMPORT_SPEC_VERSION 2 +#define VK_NVX_BINARY_IMPORT_EXTENSION_NAME "VK_NVX_binary_import" +typedef struct VkCuModuleCreateInfoNVX { + VkStructureType sType; + const void* pNext; + size_t dataSize; + const void* pData; +} VkCuModuleCreateInfoNVX; + +typedef struct VkCuModuleTexturingModeCreateInfoNVX { + VkStructureType sType; + const void* pNext; + VkBool32 use64bitTexturing; +} VkCuModuleTexturingModeCreateInfoNVX; + +typedef struct VkCuFunctionCreateInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuModuleNVX module; + const char* pName; +} VkCuFunctionCreateInfoNVX; + +typedef struct VkCuLaunchInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuFunctionNVX function; + uint32_t gridDimX; + uint32_t gridDimY; + uint32_t gridDimZ; + uint32_t blockDimX; + uint32_t blockDimY; + uint32_t blockDimZ; + uint32_t sharedMemBytes; + size_t paramCount; + const void* const * pParams; + size_t extraCount; + const void* const * pExtras; +} VkCuLaunchInfoNVX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuModuleNVX)(VkDevice device, const VkCuModuleCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuModuleNVX* pModule); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuFunctionNVX)(VkDevice device, const VkCuFunctionCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuFunctionNVX* pFunction); +typedef void (VKAPI_PTR *PFN_vkDestroyCuModuleNVX)(VkDevice device, VkCuModuleNVX module, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyCuFunctionNVX)(VkDevice device, VkCuFunctionNVX function, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdCuLaunchKernelNVX)(VkCommandBuffer commandBuffer, const VkCuLaunchInfoNVX* pLaunchInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuModuleNVX( + VkDevice device, + const VkCuModuleCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuModuleNVX* pModule); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuFunctionNVX( + VkDevice device, + const VkCuFunctionCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuFunctionNVX* pFunction); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyCuModuleNVX( + VkDevice device, + VkCuModuleNVX module, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyCuFunctionNVX( + VkDevice device, + VkCuFunctionNVX function, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCuLaunchKernelNVX( + VkCommandBuffer commandBuffer, + const VkCuLaunchInfoNVX* pLaunchInfo); +#endif +#endif + + +// VK_NVX_image_view_handle is a preprocessor guard. Do not pass it to API calls. +#define VK_NVX_image_view_handle 1 +#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 4 +#define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle" +typedef struct VkImageViewHandleInfoNVX { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkDescriptorType descriptorType; + VkSampler sampler; +} VkImageViewHandleInfoNVX; + +typedef struct VkImageViewAddressPropertiesNVX { + VkStructureType sType; + void* pNext; + VkDeviceAddress deviceAddress; + VkDeviceSize size; +} VkImageViewAddressPropertiesNVX; + +typedef uint32_t (VKAPI_PTR *PFN_vkGetImageViewHandleNVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetImageViewHandle64NVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewAddressNVX)(VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties); +typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceCombinedImageSamplerIndexNVX)(VkDevice device, uint64_t imageViewIndex, uint64_t samplerIndex); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR uint32_t VKAPI_CALL vkGetImageViewHandleNVX( + VkDevice device, + const VkImageViewHandleInfoNVX* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR uint64_t VKAPI_CALL vkGetImageViewHandle64NVX( + VkDevice device, + const VkImageViewHandleInfoNVX* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewAddressNVX( + VkDevice device, + VkImageView imageView, + VkImageViewAddressPropertiesNVX* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceCombinedImageSamplerIndexNVX( + VkDevice device, + uint64_t imageViewIndex, + uint64_t samplerIndex); +#endif +#endif + + +// VK_AMD_draw_indirect_count is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_draw_indirect_count 1 +#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 2 +#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif +#endif + + +// VK_AMD_negative_viewport_height is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_negative_viewport_height 1 +#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1 +#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height" + + +// VK_AMD_gpu_shader_half_float is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_gpu_shader_half_float 1 +#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 2 +#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float" + + +// VK_AMD_shader_ballot is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_ballot 1 +#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1 +#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot" + + +// VK_AMD_texture_gather_bias_lod is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_texture_gather_bias_lod 1 +#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1 +#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod" +typedef struct VkTextureLODGatherFormatPropertiesAMD { + VkStructureType sType; + void* pNext; + VkBool32 supportsTextureGatherLODBiasAMD; +} VkTextureLODGatherFormatPropertiesAMD; + + + +// VK_AMD_shader_info is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_info 1 +#define VK_AMD_SHADER_INFO_SPEC_VERSION 1 +#define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info" + +typedef enum VkShaderInfoTypeAMD { + VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0, + VK_SHADER_INFO_TYPE_BINARY_AMD = 1, + VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2, + VK_SHADER_INFO_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkShaderInfoTypeAMD; +typedef struct VkShaderResourceUsageAMD { + uint32_t numUsedVgprs; + uint32_t numUsedSgprs; + uint32_t ldsSizePerLocalWorkGroup; + size_t ldsUsageSizeInBytes; + size_t scratchMemUsageInBytes; +} VkShaderResourceUsageAMD; + +typedef struct VkShaderStatisticsInfoAMD { + VkShaderStageFlags shaderStageMask; + VkShaderResourceUsageAMD resourceUsage; + uint32_t numPhysicalVgprs; + uint32_t numPhysicalSgprs; + uint32_t numAvailableVgprs; + uint32_t numAvailableSgprs; + uint32_t computeWorkGroupSize[3]; +} VkShaderStatisticsInfoAMD; + +typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInfoAMD)(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( + VkDevice device, + VkPipeline pipeline, + VkShaderStageFlagBits shaderStage, + VkShaderInfoTypeAMD infoType, + size_t* pInfoSize, + void* pInfo); +#endif +#endif + + +// VK_AMD_shader_image_load_store_lod is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_image_load_store_lod 1 +#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1 +#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod" + + +// VK_NV_corner_sampled_image is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_corner_sampled_image 1 +#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2 +#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image" +typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cornerSampledImage; +} VkPhysicalDeviceCornerSampledImageFeaturesNV; + + + +// VK_IMG_format_pvrtc is a preprocessor guard. Do not pass it to API calls. +#define VK_IMG_format_pvrtc 1 +#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1 +#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc" + + +// VK_NV_external_memory_capabilities is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_external_memory_capabilities 1 +#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities" + +typedef enum VkExternalMemoryHandleTypeFlagBitsNV { + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkExternalMemoryHandleTypeFlagBitsNV; +typedef VkFlags VkExternalMemoryHandleTypeFlagsNV; + +typedef enum VkExternalMemoryFeatureFlagBitsNV { + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004, + VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkExternalMemoryFeatureFlagBitsNV; +typedef VkFlags VkExternalMemoryFeatureFlagsNV; +typedef struct VkExternalImageFormatPropertiesNV { + VkImageFormatProperties imageFormatProperties; + VkExternalMemoryFeatureFlagsNV externalMemoryFeatures; + VkExternalMemoryHandleTypeFlagsNV exportFromImportedHandleTypes; + VkExternalMemoryHandleTypeFlagsNV compatibleHandleTypes; +} VkExternalImageFormatPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkExternalMemoryHandleTypeFlagsNV externalHandleType, + VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); +#endif +#endif + + +// VK_NV_external_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_external_memory 1 +#define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory" +typedef struct VkExternalMemoryImageCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleTypes; +} VkExternalMemoryImageCreateInfoNV; + +typedef struct VkExportMemoryAllocateInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleTypes; +} VkExportMemoryAllocateInfoNV; + + + +// VK_EXT_validation_flags is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_validation_flags 1 +#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 3 +#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags" + +typedef enum VkValidationCheckEXT { + VK_VALIDATION_CHECK_ALL_EXT = 0, + VK_VALIDATION_CHECK_SHADERS_EXT = 1, + VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationCheckEXT; +typedef struct VkValidationFlagsEXT { + VkStructureType sType; + const void* pNext; + uint32_t disabledValidationCheckCount; + const VkValidationCheckEXT* pDisabledValidationChecks; +} VkValidationFlagsEXT; + + + +// VK_EXT_shader_subgroup_ballot is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_subgroup_ballot 1 +#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot" + + +// VK_EXT_shader_subgroup_vote is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_subgroup_vote 1 +#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote" + + +// VK_EXT_texture_compression_astc_hdr is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_texture_compression_astc_hdr 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME "VK_EXT_texture_compression_astc_hdr" +typedef VkPhysicalDeviceTextureCompressionASTCHDRFeatures VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT; + + + +// VK_EXT_astc_decode_mode is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_astc_decode_mode 1 +#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1 +#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode" +typedef struct VkImageViewASTCDecodeModeEXT { + VkStructureType sType; + const void* pNext; + VkFormat decodeMode; +} VkImageViewASTCDecodeModeEXT; + +typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 decodeModeSharedExponent; +} VkPhysicalDeviceASTCDecodeFeaturesEXT; + + + +// VK_EXT_pipeline_robustness is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_robustness 1 +#define VK_EXT_PIPELINE_ROBUSTNESS_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_pipeline_robustness" +typedef VkPipelineRobustnessBufferBehavior VkPipelineRobustnessBufferBehaviorEXT; + +typedef VkPipelineRobustnessImageBehavior VkPipelineRobustnessImageBehaviorEXT; + +typedef VkPhysicalDevicePipelineRobustnessFeatures VkPhysicalDevicePipelineRobustnessFeaturesEXT; + +typedef VkPhysicalDevicePipelineRobustnessProperties VkPhysicalDevicePipelineRobustnessPropertiesEXT; + +typedef VkPipelineRobustnessCreateInfo VkPipelineRobustnessCreateInfoEXT; + + + +// VK_EXT_conditional_rendering is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_conditional_rendering 1 +#define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 2 +#define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering" +typedef struct VkConditionalRenderingBeginInfoEXT { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; + VkDeviceSize offset; + VkConditionalRenderingFlagsEXT flags; +} VkConditionalRenderingBeginInfoEXT; + +typedef struct VkPhysicalDeviceConditionalRenderingFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 conditionalRendering; + VkBool32 inheritedConditionalRendering; +} VkPhysicalDeviceConditionalRenderingFeaturesEXT; + +typedef struct VkCommandBufferInheritanceConditionalRenderingInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 conditionalRenderingEnable; +} VkCommandBufferInheritanceConditionalRenderingInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRenderingEXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); +typedef void (VKAPI_PTR *PFN_vkCmdEndConditionalRenderingEXT)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRenderingEXT( + VkCommandBuffer commandBuffer, + const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT( + VkCommandBuffer commandBuffer); +#endif +#endif + + +// VK_NV_clip_space_w_scaling is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_clip_space_w_scaling 1 +#define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 +#define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" +typedef struct VkViewportWScalingNV { + float xcoeff; + float ycoeff; +} VkViewportWScalingNV; + +typedef struct VkPipelineViewportWScalingStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 viewportWScalingEnable; + uint32_t viewportCount; + const VkViewportWScalingNV* pViewportWScalings; +} VkPipelineViewportWScalingStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewportWScalingNV* pViewportWScalings); +#endif +#endif + + +// VK_EXT_direct_mode_display is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_direct_mode_display 1 +#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display" +typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); +#endif +#endif + + +// VK_EXT_display_surface_counter is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_display_surface_counter 1 +#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1 +#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" + +typedef enum VkSurfaceCounterFlagBitsEXT { + VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0x00000001, + // VK_SURFACE_COUNTER_VBLANK_EXT is a legacy alias + VK_SURFACE_COUNTER_VBLANK_EXT = VK_SURFACE_COUNTER_VBLANK_BIT_EXT, + VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSurfaceCounterFlagBitsEXT; +typedef VkFlags VkSurfaceCounterFlagsEXT; +typedef struct VkSurfaceCapabilities2EXT { + VkStructureType sType; + void* pNext; + uint32_t minImageCount; + uint32_t maxImageCount; + VkExtent2D currentExtent; + VkExtent2D minImageExtent; + VkExtent2D maxImageExtent; + uint32_t maxImageArrayLayers; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkSurfaceTransformFlagBitsKHR currentTransform; + VkCompositeAlphaFlagsKHR supportedCompositeAlpha; + VkImageUsageFlags supportedUsageFlags; + VkSurfaceCounterFlagsEXT supportedSurfaceCounters; +} VkSurfaceCapabilities2EXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilities2EXT* pSurfaceCapabilities); +#endif +#endif + + +// VK_EXT_display_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_display_control 1 +#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control" + +typedef enum VkDisplayPowerStateEXT { + VK_DISPLAY_POWER_STATE_OFF_EXT = 0, + VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1, + VK_DISPLAY_POWER_STATE_ON_EXT = 2, + VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDisplayPowerStateEXT; + +typedef enum VkDeviceEventTypeEXT { + VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0, + VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceEventTypeEXT; + +typedef enum VkDisplayEventTypeEXT { + VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0, + VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDisplayEventTypeEXT; +typedef struct VkDisplayPowerInfoEXT { + VkStructureType sType; + const void* pNext; + VkDisplayPowerStateEXT powerState; +} VkDisplayPowerInfoEXT; + +typedef struct VkDeviceEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceEventTypeEXT deviceEvent; +} VkDeviceEventInfoEXT; + +typedef struct VkDisplayEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkDisplayEventTypeEXT displayEvent; +} VkDisplayEventInfoEXT; + +typedef struct VkSwapchainCounterCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkSurfaceCounterFlagsEXT surfaceCounters; +} VkSwapchainCounterCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT( + VkDevice device, + VkDisplayKHR display, + const VkDisplayPowerInfoEXT* pDisplayPowerInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT( + VkDevice device, + const VkDeviceEventInfoEXT* pDeviceEventInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT( + VkDevice device, + VkDisplayKHR display, + const VkDisplayEventInfoEXT* pDisplayEventInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT( + VkDevice device, + VkSwapchainKHR swapchain, + VkSurfaceCounterFlagBitsEXT counter, + uint64_t* pCounterValue); +#endif +#endif + + +// VK_GOOGLE_display_timing is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_display_timing 1 +#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1 +#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing" +typedef struct VkRefreshCycleDurationGOOGLE { + uint64_t refreshDuration; +} VkRefreshCycleDurationGOOGLE; + +typedef struct VkPastPresentationTimingGOOGLE { + uint32_t presentID; + uint64_t desiredPresentTime; + uint64_t actualPresentTime; + uint64_t earliestPresentTime; + uint64_t presentMargin; +} VkPastPresentationTimingGOOGLE; + +typedef struct VkPresentTimeGOOGLE { + uint32_t presentID; + uint64_t desiredPresentTime; +} VkPresentTimeGOOGLE; + +typedef struct VkPresentTimesInfoGOOGLE { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentTimeGOOGLE* pTimes; +} VkPresentTimesInfoGOOGLE; + +typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE( + VkDevice device, + VkSwapchainKHR swapchain, + VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pPresentationTimingCount, + VkPastPresentationTimingGOOGLE* pPresentationTimings); +#endif +#endif + + +// VK_NV_sample_mask_override_coverage is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_sample_mask_override_coverage 1 +#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1 +#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage" + + +// VK_NV_geometry_shader_passthrough is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_geometry_shader_passthrough 1 +#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1 +#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough" + + +// VK_NV_viewport_array2 is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_viewport_array2 1 +#define VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME "VK_NV_viewport_array2" +// VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION is a legacy alias +#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION +// VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME is a legacy alias +#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME + + +// VK_NVX_multiview_per_view_attributes is a preprocessor guard. Do not pass it to API calls. +#define VK_NVX_multiview_per_view_attributes 1 +#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1 +#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes" +typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX { + VkStructureType sType; + void* pNext; + VkBool32 perViewPositionAllComponents; +} VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX; + +typedef struct VkMultiviewPerViewAttributesInfoNVX { + VkStructureType sType; + const void* pNext; + VkBool32 perViewAttributes; + VkBool32 perViewAttributesPositionXOnly; +} VkMultiviewPerViewAttributesInfoNVX; + + + +// VK_NV_viewport_swizzle is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_viewport_swizzle 1 +#define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle" + +typedef enum VkViewportCoordinateSwizzleNV { + 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, + VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF +} VkViewportCoordinateSwizzleNV; +typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV; +typedef struct VkViewportSwizzleNV { + VkViewportCoordinateSwizzleNV x; + VkViewportCoordinateSwizzleNV y; + VkViewportCoordinateSwizzleNV z; + VkViewportCoordinateSwizzleNV w; +} VkViewportSwizzleNV; + +typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineViewportSwizzleStateCreateFlagsNV flags; + uint32_t viewportCount; + const VkViewportSwizzleNV* pViewportSwizzles; +} VkPipelineViewportSwizzleStateCreateInfoNV; + + + +// VK_EXT_discard_rectangles is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_discard_rectangles 1 +#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 2 +#define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles" + +typedef enum VkDiscardRectangleModeEXT { + VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0, + VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1, + VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDiscardRectangleModeEXT; +typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxDiscardRectangles; +} VkPhysicalDeviceDiscardRectanglePropertiesEXT; + +typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineDiscardRectangleStateCreateFlagsEXT flags; + VkDiscardRectangleModeEXT discardRectangleMode; + uint32_t discardRectangleCount; + const VkRect2D* pDiscardRectangles; +} VkPipelineDiscardRectangleStateCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 discardRectangleEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleModeEXT)(VkCommandBuffer commandBuffer, VkDiscardRectangleModeEXT discardRectangleMode); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( + VkCommandBuffer commandBuffer, + uint32_t firstDiscardRectangle, + uint32_t discardRectangleCount, + const VkRect2D* pDiscardRectangles); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 discardRectangleEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleModeEXT( + VkCommandBuffer commandBuffer, + VkDiscardRectangleModeEXT discardRectangleMode); +#endif +#endif + + +// VK_EXT_conservative_rasterization is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_conservative_rasterization 1 +#define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1 +#define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization" + +typedef enum VkConservativeRasterizationModeEXT { + VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0, + VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1, + VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2, + VK_CONSERVATIVE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkConservativeRasterizationModeEXT; +typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceConservativeRasterizationPropertiesEXT { + VkStructureType sType; + void* pNext; + float primitiveOverestimationSize; + float maxExtraPrimitiveOverestimationSize; + float extraPrimitiveOverestimationSizeGranularity; + VkBool32 primitiveUnderestimation; + VkBool32 conservativePointAndLineRasterization; + VkBool32 degenerateTrianglesRasterized; + VkBool32 degenerateLinesRasterized; + VkBool32 fullyCoveredFragmentShaderInputVariable; + VkBool32 conservativeRasterizationPostDepthCoverage; +} VkPhysicalDeviceConservativeRasterizationPropertiesEXT; + +typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationConservativeStateCreateFlagsEXT flags; + VkConservativeRasterizationModeEXT conservativeRasterizationMode; + float extraPrimitiveOverestimationSize; +} VkPipelineRasterizationConservativeStateCreateInfoEXT; + + + +// VK_EXT_depth_clip_enable is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_clip_enable 1 +#define VK_EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME "VK_EXT_depth_clip_enable" +typedef VkFlags VkPipelineRasterizationDepthClipStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceDepthClipEnableFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 depthClipEnable; +} VkPhysicalDeviceDepthClipEnableFeaturesEXT; + +typedef struct VkPipelineRasterizationDepthClipStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationDepthClipStateCreateFlagsEXT flags; + VkBool32 depthClipEnable; +} VkPipelineRasterizationDepthClipStateCreateInfoEXT; + + + +// VK_EXT_swapchain_colorspace is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_swapchain_colorspace 1 +#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 5 +#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace" + + +// VK_EXT_hdr_metadata is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_hdr_metadata 1 +#define VK_EXT_HDR_METADATA_SPEC_VERSION 3 +#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" +typedef struct VkXYColorEXT { + float x; + float y; +} VkXYColorEXT; + +typedef struct VkHdrMetadataEXT { + VkStructureType sType; + const void* pNext; + VkXYColorEXT displayPrimaryRed; + VkXYColorEXT displayPrimaryGreen; + VkXYColorEXT displayPrimaryBlue; + VkXYColorEXT whitePoint; + float maxLuminance; + float minLuminance; + float maxContentLightLevel; + float maxFrameAverageLightLevel; +} VkHdrMetadataEXT; + +typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainKHR* pSwapchains, + const VkHdrMetadataEXT* pMetadata); +#endif +#endif + + +// VK_IMG_relaxed_line_rasterization is a preprocessor guard. Do not pass it to API calls. +#define VK_IMG_relaxed_line_rasterization 1 +#define VK_IMG_RELAXED_LINE_RASTERIZATION_SPEC_VERSION 1 +#define VK_IMG_RELAXED_LINE_RASTERIZATION_EXTENSION_NAME "VK_IMG_relaxed_line_rasterization" +typedef struct VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG { + VkStructureType sType; + void* pNext; + VkBool32 relaxedLineRasterization; +} VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG; + + + +// VK_EXT_external_memory_dma_buf is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_external_memory_dma_buf 1 +#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf" + + +// VK_EXT_queue_family_foreign is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_queue_family_foreign 1 +#define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1 +#define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign" +#define VK_QUEUE_FAMILY_FOREIGN_EXT (~2U) + + +// VK_EXT_debug_utils is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_debug_utils 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT) +#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 2 +#define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils" +typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT; + +typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT { + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugUtilsMessageSeverityFlagBitsEXT; + +typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001, + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002, + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004, + VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT = 0x00000008, + VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugUtilsMessageTypeFlagBitsEXT; +typedef VkFlags VkDebugUtilsMessageTypeFlagsEXT; +typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT; +typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT; +typedef struct VkDebugUtilsLabelEXT { + VkStructureType sType; + const void* pNext; + const char* pLabelName; + float color[4]; +} VkDebugUtilsLabelEXT; + +typedef struct VkDebugUtilsObjectNameInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + const char* pObjectName; +} VkDebugUtilsObjectNameInfoEXT; + +typedef struct VkDebugUtilsMessengerCallbackDataEXT { + VkStructureType sType; + const void* pNext; + VkDebugUtilsMessengerCallbackDataFlagsEXT flags; + const char* pMessageIdName; + int32_t messageIdNumber; + const char* pMessage; + uint32_t queueLabelCount; + const VkDebugUtilsLabelEXT* pQueueLabels; + uint32_t cmdBufLabelCount; + const VkDebugUtilsLabelEXT* pCmdBufLabels; + uint32_t objectCount; + const VkDebugUtilsObjectNameInfoEXT* pObjects; +} VkDebugUtilsMessengerCallbackDataEXT; + +typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData); + +typedef struct VkDebugUtilsMessengerCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugUtilsMessengerCreateFlagsEXT flags; + VkDebugUtilsMessageSeverityFlagsEXT messageSeverity; + VkDebugUtilsMessageTypeFlagsEXT messageType; + PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback; + void* pUserData; +} VkDebugUtilsMessengerCreateInfoEXT; + +typedef struct VkDebugUtilsObjectTagInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugUtilsObjectTagInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo); +typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo); +typedef void (VKAPI_PTR *PFN_vkQueueBeginDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkQueueEndDebugUtilsLabelEXT)(VkQueue queue); +typedef void (VKAPI_PTR *PFN_vkQueueInsertDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdInsertDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugUtilsMessengerEXT)(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger); +typedef void (VKAPI_PTR *PFN_vkDestroyDebugUtilsMessengerEXT)(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkSubmitDebugUtilsMessageEXT)(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectNameEXT( + VkDevice device, + const VkDebugUtilsObjectNameInfoEXT* pNameInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectTagEXT( + VkDevice device, + const VkDebugUtilsObjectTagInfoEXT* pTagInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkQueueBeginDebugUtilsLabelEXT( + VkQueue queue, + const VkDebugUtilsLabelEXT* pLabelInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkQueueEndDebugUtilsLabelEXT( + VkQueue queue); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkQueueInsertDebugUtilsLabelEXT( + VkQueue queue, + const VkDebugUtilsLabelEXT* pLabelInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT* pLabelInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdInsertDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT* pLabelInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( + VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugUtilsMessengerEXT* pMessenger); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( + VkInstance instance, + VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT( + VkInstance instance, + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); +#endif +#endif + + +// VK_EXT_sampler_filter_minmax is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_sampler_filter_minmax 1 +#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 2 +#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax" +typedef VkSamplerReductionMode VkSamplerReductionModeEXT; + +typedef VkSamplerReductionModeCreateInfo VkSamplerReductionModeCreateInfoEXT; + +typedef VkPhysicalDeviceSamplerFilterMinmaxProperties VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT; + + + +// VK_AMD_gpu_shader_int16 is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_gpu_shader_int16 1 +#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 2 +#define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16" + + +// VK_AMD_gpa_interface is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_gpa_interface 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkGpaSessionAMD) +#define VK_AMD_GPA_INTERFACE_SPEC_VERSION 1 +#define VK_AMD_GPA_INTERFACE_EXTENSION_NAME "VK_AMD_gpa_interface" + +typedef enum VkGpaPerfBlockAMD { + VK_GPA_PERF_BLOCK_CPF_AMD = 0, + VK_GPA_PERF_BLOCK_IA_AMD = 1, + VK_GPA_PERF_BLOCK_VGT_AMD = 2, + VK_GPA_PERF_BLOCK_PA_AMD = 3, + VK_GPA_PERF_BLOCK_SC_AMD = 4, + VK_GPA_PERF_BLOCK_SPI_AMD = 5, + VK_GPA_PERF_BLOCK_SQ_AMD = 6, + VK_GPA_PERF_BLOCK_SX_AMD = 7, + VK_GPA_PERF_BLOCK_TA_AMD = 8, + VK_GPA_PERF_BLOCK_TD_AMD = 9, + VK_GPA_PERF_BLOCK_TCP_AMD = 10, + VK_GPA_PERF_BLOCK_TCC_AMD = 11, + VK_GPA_PERF_BLOCK_TCA_AMD = 12, + VK_GPA_PERF_BLOCK_DB_AMD = 13, + VK_GPA_PERF_BLOCK_CB_AMD = 14, + VK_GPA_PERF_BLOCK_GDS_AMD = 15, + VK_GPA_PERF_BLOCK_SRBM_AMD = 16, + VK_GPA_PERF_BLOCK_GRBM_AMD = 17, + VK_GPA_PERF_BLOCK_GRBM_SE_AMD = 18, + VK_GPA_PERF_BLOCK_RLC_AMD = 19, + VK_GPA_PERF_BLOCK_DMA_AMD = 20, + VK_GPA_PERF_BLOCK_MC_AMD = 21, + VK_GPA_PERF_BLOCK_CPG_AMD = 22, + VK_GPA_PERF_BLOCK_CPC_AMD = 23, + VK_GPA_PERF_BLOCK_WD_AMD = 24, + VK_GPA_PERF_BLOCK_TCS_AMD = 25, + VK_GPA_PERF_BLOCK_ATC_AMD = 26, + VK_GPA_PERF_BLOCK_ATC_L2_AMD = 27, + VK_GPA_PERF_BLOCK_MC_VM_L2_AMD = 28, + VK_GPA_PERF_BLOCK_EA_AMD = 29, + VK_GPA_PERF_BLOCK_RPB_AMD = 30, + VK_GPA_PERF_BLOCK_RMI_AMD = 31, + VK_GPA_PERF_BLOCK_UMCCH_AMD = 32, + VK_GPA_PERF_BLOCK_GE_AMD = 33, + VK_GPA_PERF_BLOCK_GL1A_AMD = 34, + VK_GPA_PERF_BLOCK_GL1C_AMD = 35, + VK_GPA_PERF_BLOCK_GL1CG_AMD = 36, + VK_GPA_PERF_BLOCK_GL2A_AMD = 37, + VK_GPA_PERF_BLOCK_GL2C_AMD = 38, + VK_GPA_PERF_BLOCK_CHA_AMD = 39, + VK_GPA_PERF_BLOCK_CHC_AMD = 40, + VK_GPA_PERF_BLOCK_CHCG_AMD = 41, + VK_GPA_PERF_BLOCK_GUS_AMD = 42, + VK_GPA_PERF_BLOCK_GCR_AMD = 43, + VK_GPA_PERF_BLOCK_PH_AMD = 44, + VK_GPA_PERF_BLOCK_UTCL1_AMD = 45, + VK_GPA_PERF_BLOCK_GE_DIST_AMD = 46, + VK_GPA_PERF_BLOCK_GE_SE_AMD = 47, + VK_GPA_PERF_BLOCK_DF_MALL_AMD = 48, + VK_GPA_PERF_BLOCK_SQ_WGP_AMD = 49, + VK_GPA_PERF_BLOCK_PC_AMD = 50, + VK_GPA_PERF_BLOCK_GL1XA_AMD = 51, + VK_GPA_PERF_BLOCK_GL1XC_AMD = 52, + VK_GPA_PERF_BLOCK_WGS_AMD = 53, + VK_GPA_PERF_BLOCK_EACPWD_AMD = 54, + VK_GPA_PERF_BLOCK_EASE_AMD = 55, + VK_GPA_PERF_BLOCK_RLCUSER_AMD = 56, + VK_GPA_PERF_BLOCK_GE1_AMD = VK_GPA_PERF_BLOCK_GE_AMD, + VK_GPA_PERF_BLOCK_RLCLOCAL_AMD = VK_GPA_PERF_BLOCK_RLCUSER_AMD, + VK_GPA_PERF_BLOCK_MAX_ENUM_AMD = 0x7FFFFFFF +} VkGpaPerfBlockAMD; + +typedef enum VkGpaSampleTypeAMD { + VK_GPA_SAMPLE_TYPE_CUMULATIVE_AMD = 0, + VK_GPA_SAMPLE_TYPE_TRACE_AMD = 1, + VK_GPA_SAMPLE_TYPE_TIMING_AMD = 2, + VK_GPA_SAMPLE_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkGpaSampleTypeAMD; + +typedef enum VkGpaDeviceClockModeAMD { + VK_GPA_DEVICE_CLOCK_MODE_DEFAULT_AMD = 0, + VK_GPA_DEVICE_CLOCK_MODE_QUERY_AMD = 1, + VK_GPA_DEVICE_CLOCK_MODE_PROFILING_AMD = 2, + VK_GPA_DEVICE_CLOCK_MODE_MIN_MEMORY_AMD = 3, + VK_GPA_DEVICE_CLOCK_MODE_MIN_ENGINE_AMD = 4, + VK_GPA_DEVICE_CLOCK_MODE_PEAK_AMD = 5, + VK_GPA_DEVICE_CLOCK_MODE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkGpaDeviceClockModeAMD; + +typedef enum VkGpaSqShaderStageFlagBitsAMD { + VK_GPA_SQ_SHADER_STAGE_PS_BIT_AMD = 0x00000001, + VK_GPA_SQ_SHADER_STAGE_VS_BIT_AMD = 0x00000002, + VK_GPA_SQ_SHADER_STAGE_GS_BIT_AMD = 0x00000004, + VK_GPA_SQ_SHADER_STAGE_ES_BIT_AMD = 0x00000008, + VK_GPA_SQ_SHADER_STAGE_HS_BIT_AMD = 0x00000010, + VK_GPA_SQ_SHADER_STAGE_LS_BIT_AMD = 0x00000020, + VK_GPA_SQ_SHADER_STAGE_CS_BIT_AMD = 0x00000040, + VK_GPA_SQ_SHADER_STAGE_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkGpaSqShaderStageFlagBitsAMD; +typedef VkFlags VkGpaSqShaderStageFlagsAMD; +typedef VkFlags VkGpaPerfBlockPropertiesFlagsAMD; +typedef VkFlags VkPhysicalDeviceGpaPropertiesFlagsAMD; +typedef struct VkGpaPerfBlockPropertiesAMD { + VkGpaPerfBlockAMD blockType; + VkGpaPerfBlockPropertiesFlagsAMD flags; + uint32_t instanceCount; + uint32_t maxEventID; + uint32_t maxGlobalOnlyCounters; + uint32_t maxGlobalSharedCounters; + uint32_t maxStreamingCounters; +} VkGpaPerfBlockPropertiesAMD; + +typedef struct VkPhysicalDeviceGpaFeaturesAMD { + VkStructureType sType; + void* pNext; + VkBool32 perfCounters; + VkBool32 streamingPerfCounters; + VkBool32 sqThreadTracing; + VkBool32 clockModes; +} VkPhysicalDeviceGpaFeaturesAMD; + +typedef struct VkPhysicalDeviceGpaPropertiesAMD { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceGpaPropertiesFlagsAMD flags; + VkDeviceSize maxSqttSeBufferSize; + uint32_t shaderEngineCount; + uint32_t perfBlockCount; + VkGpaPerfBlockPropertiesAMD* pPerfBlocks; +} VkPhysicalDeviceGpaPropertiesAMD; + +typedef struct VkPhysicalDeviceGpaProperties2AMD { + VkStructureType sType; + void* pNext; + uint32_t revisionId; +} VkPhysicalDeviceGpaProperties2AMD; + +typedef struct VkGpaPerfCounterAMD { + VkGpaPerfBlockAMD blockType; + uint32_t blockInstance; + uint32_t eventID; +} VkGpaPerfCounterAMD; + +typedef struct VkGpaSampleBeginInfoAMD { + VkStructureType sType; + const void* pNext; + VkGpaSampleTypeAMD sampleType; + VkBool32 sampleInternalOperations; + VkBool32 cacheFlushOnCounterCollection; + VkBool32 sqShaderMaskEnable; + VkGpaSqShaderStageFlagsAMD sqShaderMask; + uint32_t perfCounterCount; + const VkGpaPerfCounterAMD* pPerfCounters; + uint32_t streamingPerfTraceSampleInterval; + VkDeviceSize perfCounterDeviceMemoryLimit; + VkBool32 sqThreadTraceEnable; + VkBool32 sqThreadTraceSuppressInstructionTokens; + VkDeviceSize sqThreadTraceDeviceMemoryLimit; + VkPipelineStageFlags timingPreSample; + VkPipelineStageFlags timingPostSample; +} VkGpaSampleBeginInfoAMD; + +typedef struct VkGpaDeviceClockModeInfoAMD { + VkStructureType sType; + const void* pNext; + VkGpaDeviceClockModeAMD clockMode; + float memoryClockRatioToPeak; + float engineClockRatioToPeak; +} VkGpaDeviceClockModeInfoAMD; + +typedef struct VkGpaDeviceGetClockInfoAMD { + VkStructureType sType; + void* pNext; + float memoryClockRatioToPeak; + float engineClockRatioToPeak; + uint32_t memoryClockFrequency; + uint32_t engineClockFrequency; +} VkGpaDeviceGetClockInfoAMD; + +typedef struct VkGpaSessionCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkGpaSessionAMD secondaryCopySource; +} VkGpaSessionCreateInfoAMD; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateGpaSessionAMD)(VkDevice device, const VkGpaSessionCreateInfoAMD* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkGpaSessionAMD* pGpaSession); +typedef void (VKAPI_PTR *PFN_vkDestroyGpaSessionAMD)(VkDevice device, VkGpaSessionAMD gpaSession, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetGpaDeviceClockModeAMD)(VkDevice device, VkGpaDeviceClockModeInfoAMD* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetGpaDeviceClockInfoAMD)(VkDevice device, VkGpaDeviceGetClockInfoAMD* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdBeginGpaSessionAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession); +typedef VkResult (VKAPI_PTR *PFN_vkCmdEndGpaSessionAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession); +typedef VkResult (VKAPI_PTR *PFN_vkCmdBeginGpaSampleAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession, const VkGpaSampleBeginInfoAMD* pGpaSampleBeginInfo, uint32_t* pSampleID); +typedef void (VKAPI_PTR *PFN_vkCmdEndGpaSampleAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession, uint32_t sampleID); +typedef VkResult (VKAPI_PTR *PFN_vkGetGpaSessionStatusAMD)(VkDevice device, VkGpaSessionAMD gpaSession); +typedef VkResult (VKAPI_PTR *PFN_vkGetGpaSessionResultsAMD)(VkDevice device, VkGpaSessionAMD gpaSession, uint32_t sampleID, size_t* pSizeInBytes, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkResetGpaSessionAMD)(VkDevice device, VkGpaSessionAMD gpaSession); +typedef void (VKAPI_PTR *PFN_vkCmdCopyGpaSessionResultsAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateGpaSessionAMD( + VkDevice device, + const VkGpaSessionCreateInfoAMD* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkGpaSessionAMD* pGpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyGpaSessionAMD( + VkDevice device, + VkGpaSessionAMD gpaSession, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetGpaDeviceClockModeAMD( + VkDevice device, + VkGpaDeviceClockModeInfoAMD* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetGpaDeviceClockInfoAMD( + VkDevice device, + VkGpaDeviceGetClockInfoAMD* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCmdBeginGpaSessionAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCmdEndGpaSessionAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCmdBeginGpaSampleAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession, + const VkGpaSampleBeginInfoAMD* pGpaSampleBeginInfo, + uint32_t* pSampleID); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndGpaSampleAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession, + uint32_t sampleID); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetGpaSessionStatusAMD( + VkDevice device, + VkGpaSessionAMD gpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetGpaSessionResultsAMD( + VkDevice device, + VkGpaSessionAMD gpaSession, + uint32_t sampleID, + size_t* pSizeInBytes, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkResetGpaSessionAMD( + VkDevice device, + VkGpaSessionAMD gpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyGpaSessionResultsAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession); +#endif +#endif + + +// VK_EXT_descriptor_heap is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_descriptor_heap 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkTensorARM) +#define VK_EXT_DESCRIPTOR_HEAP_SPEC_VERSION 1 +#define VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME "VK_EXT_descriptor_heap" + +typedef enum VkDescriptorMappingSourceEXT { + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT = 0, + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT = 1, + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT = 2, + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT = 3, + VK_DESCRIPTOR_MAPPING_SOURCE_RESOURCE_HEAP_DATA_EXT = 4, + VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT = 5, + VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_ADDRESS_EXT = 6, + VK_DESCRIPTOR_MAPPING_SOURCE_INDIRECT_ADDRESS_EXT = 7, + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT = 8, + VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_DATA_EXT = 9, + VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_ADDRESS_EXT = 10, + VK_DESCRIPTOR_MAPPING_SOURCE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDescriptorMappingSourceEXT; +typedef VkFlags64 VkTensorViewCreateFlagsARM; + +// Flag bits for VkTensorViewCreateFlagBitsARM +typedef VkFlags64 VkTensorViewCreateFlagBitsARM; +static const VkTensorViewCreateFlagBitsARM VK_TENSOR_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM = 0x00000001ULL; + + +typedef enum VkSpirvResourceTypeFlagBitsEXT { + VK_SPIRV_RESOURCE_TYPE_ALL_EXT = 0x7FFFFFFF, + VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT = 0x00000001, + VK_SPIRV_RESOURCE_TYPE_SAMPLED_IMAGE_BIT_EXT = 0x00000002, + VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT = 0x00000004, + VK_SPIRV_RESOURCE_TYPE_READ_WRITE_IMAGE_BIT_EXT = 0x00000008, + VK_SPIRV_RESOURCE_TYPE_COMBINED_SAMPLED_IMAGE_BIT_EXT = 0x00000010, + VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT = 0x00000020, + VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT = 0x00000040, + VK_SPIRV_RESOURCE_TYPE_READ_WRITE_STORAGE_BUFFER_BIT_EXT = 0x00000080, + VK_SPIRV_RESOURCE_TYPE_ACCELERATION_STRUCTURE_BIT_EXT = 0x00000100, + VK_SPIRV_RESOURCE_TYPE_TENSOR_BIT_ARM = 0x00000200, + VK_SPIRV_RESOURCE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSpirvResourceTypeFlagBitsEXT; +typedef VkFlags VkSpirvResourceTypeFlagsEXT; +typedef struct VkHostAddressRangeEXT { + void* address; + size_t size; +} VkHostAddressRangeEXT; + +typedef struct VkHostAddressRangeConstEXT { + const void* address; + size_t size; +} VkHostAddressRangeConstEXT; + +typedef VkDeviceAddressRangeKHR VkDeviceAddressRangeEXT; + +typedef struct VkTexelBufferDescriptorInfoEXT { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkDeviceAddressRangeEXT addressRange; +} VkTexelBufferDescriptorInfoEXT; + +typedef struct VkImageDescriptorInfoEXT { + VkStructureType sType; + const void* pNext; + const VkImageViewCreateInfo* pView; + VkImageLayout layout; +} VkImageDescriptorInfoEXT; + +typedef struct VkTensorViewCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorViewCreateFlagsARM flags; + VkTensorARM tensor; + VkFormat format; +} VkTensorViewCreateInfoARM; + +typedef union VkResourceDescriptorDataEXT { + const VkImageDescriptorInfoEXT* pImage; + const VkTexelBufferDescriptorInfoEXT* pTexelBuffer; + const VkDeviceAddressRangeEXT* pAddressRange; + const VkTensorViewCreateInfoARM* pTensorARM; +} VkResourceDescriptorDataEXT; + +typedef struct VkResourceDescriptorInfoEXT { + VkStructureType sType; + const void* pNext; + VkDescriptorType type; + VkResourceDescriptorDataEXT data; +} VkResourceDescriptorInfoEXT; + +typedef struct VkBindHeapInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeEXT heapRange; + VkDeviceSize reservedRangeOffset; + VkDeviceSize reservedRangeSize; +} VkBindHeapInfoEXT; + +typedef struct VkPushDataInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t offset; + VkHostAddressRangeConstEXT data; +} VkPushDataInfoEXT; + +typedef struct VkDescriptorMappingSourceConstantOffsetEXT { + uint32_t heapOffset; + uint32_t heapArrayStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + uint32_t samplerHeapOffset; + uint32_t samplerHeapArrayStride; +} VkDescriptorMappingSourceConstantOffsetEXT; + +typedef struct VkDescriptorMappingSourcePushIndexEXT { + uint32_t heapOffset; + uint32_t pushOffset; + uint32_t heapIndexStride; + uint32_t heapArrayStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + VkBool32 useCombinedImageSamplerIndex; + uint32_t samplerHeapOffset; + uint32_t samplerPushOffset; + uint32_t samplerHeapIndexStride; + uint32_t samplerHeapArrayStride; +} VkDescriptorMappingSourcePushIndexEXT; + +typedef struct VkDescriptorMappingSourceIndirectIndexEXT { + uint32_t heapOffset; + uint32_t pushOffset; + uint32_t addressOffset; + uint32_t heapIndexStride; + uint32_t heapArrayStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + VkBool32 useCombinedImageSamplerIndex; + uint32_t samplerHeapOffset; + uint32_t samplerPushOffset; + uint32_t samplerAddressOffset; + uint32_t samplerHeapIndexStride; + uint32_t samplerHeapArrayStride; +} VkDescriptorMappingSourceIndirectIndexEXT; + +typedef struct VkDescriptorMappingSourceHeapDataEXT { + uint32_t heapOffset; + uint32_t pushOffset; +} VkDescriptorMappingSourceHeapDataEXT; + +typedef struct VkDescriptorMappingSourceIndirectAddressEXT { + uint32_t pushOffset; + uint32_t addressOffset; +} VkDescriptorMappingSourceIndirectAddressEXT; + +typedef struct VkDescriptorMappingSourceShaderRecordIndexEXT { + uint32_t heapOffset; + uint32_t shaderRecordOffset; + uint32_t heapIndexStride; + uint32_t heapArrayStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + VkBool32 useCombinedImageSamplerIndex; + uint32_t samplerHeapOffset; + uint32_t samplerShaderRecordOffset; + uint32_t samplerHeapIndexStride; + uint32_t samplerHeapArrayStride; +} VkDescriptorMappingSourceShaderRecordIndexEXT; + +typedef struct VkDescriptorMappingSourceIndirectIndexArrayEXT { + uint32_t heapOffset; + uint32_t pushOffset; + uint32_t addressOffset; + uint32_t heapIndexStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + VkBool32 useCombinedImageSamplerIndex; + uint32_t samplerHeapOffset; + uint32_t samplerPushOffset; + uint32_t samplerAddressOffset; + uint32_t samplerHeapIndexStride; +} VkDescriptorMappingSourceIndirectIndexArrayEXT; + +typedef union VkDescriptorMappingSourceDataEXT { + VkDescriptorMappingSourceConstantOffsetEXT constantOffset; + VkDescriptorMappingSourcePushIndexEXT pushIndex; + VkDescriptorMappingSourceIndirectIndexEXT indirectIndex; + VkDescriptorMappingSourceIndirectIndexArrayEXT indirectIndexArray; + VkDescriptorMappingSourceHeapDataEXT heapData; + uint32_t pushDataOffset; + uint32_t pushAddressOffset; + VkDescriptorMappingSourceIndirectAddressEXT indirectAddress; + VkDescriptorMappingSourceShaderRecordIndexEXT shaderRecordIndex; + uint32_t shaderRecordDataOffset; + uint32_t shaderRecordAddressOffset; +} VkDescriptorMappingSourceDataEXT; + +typedef struct VkDescriptorSetAndBindingMappingEXT { + VkStructureType sType; + const void* pNext; + uint32_t descriptorSet; + uint32_t firstBinding; + uint32_t bindingCount; + VkSpirvResourceTypeFlagsEXT resourceMask; + VkDescriptorMappingSourceEXT source; + VkDescriptorMappingSourceDataEXT sourceData; +} VkDescriptorSetAndBindingMappingEXT; + +typedef struct VkShaderDescriptorSetAndBindingMappingInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t mappingCount; + const VkDescriptorSetAndBindingMappingEXT* pMappings; +} VkShaderDescriptorSetAndBindingMappingInfoEXT; + +typedef struct VkOpaqueCaptureDataCreateInfoEXT { + VkStructureType sType; + const void* pNext; + const VkHostAddressRangeConstEXT* pData; +} VkOpaqueCaptureDataCreateInfoEXT; + +typedef struct VkPhysicalDeviceDescriptorHeapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 descriptorHeap; + VkBool32 descriptorHeapCaptureReplay; +} VkPhysicalDeviceDescriptorHeapFeaturesEXT; + +typedef struct VkPhysicalDeviceDescriptorHeapPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize samplerHeapAlignment; + VkDeviceSize resourceHeapAlignment; + VkDeviceSize maxSamplerHeapSize; + VkDeviceSize maxResourceHeapSize; + VkDeviceSize minSamplerHeapReservedRange; + VkDeviceSize minSamplerHeapReservedRangeWithEmbedded; + VkDeviceSize minResourceHeapReservedRange; + VkDeviceSize samplerDescriptorSize; + VkDeviceSize imageDescriptorSize; + VkDeviceSize bufferDescriptorSize; + VkDeviceSize samplerDescriptorAlignment; + VkDeviceSize imageDescriptorAlignment; + VkDeviceSize bufferDescriptorAlignment; + VkDeviceSize maxPushDataSize; + size_t imageCaptureReplayOpaqueDataSize; + uint32_t maxDescriptorHeapEmbeddedSamplers; + uint32_t samplerYcbcrConversionCount; + VkBool32 sparseDescriptorHeaps; + VkBool32 protectedDescriptorHeaps; +} VkPhysicalDeviceDescriptorHeapPropertiesEXT; + +typedef struct VkCommandBufferInheritanceDescriptorHeapInfoEXT { + VkStructureType sType; + const void* pNext; + const VkBindHeapInfoEXT* pSamplerHeapBindInfo; + const VkBindHeapInfoEXT* pResourceHeapBindInfo; +} VkCommandBufferInheritanceDescriptorHeapInfoEXT; + +typedef struct VkSamplerCustomBorderColorIndexCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t index; +} VkSamplerCustomBorderColorIndexCreateInfoEXT; + +typedef struct VkSamplerCustomBorderColorCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkClearColorValue customBorderColor; + VkFormat format; +} VkSamplerCustomBorderColorCreateInfoEXT; + +typedef struct VkIndirectCommandsLayoutPushDataTokenNV { + VkStructureType sType; + const void* pNext; + uint32_t pushDataOffset; + uint32_t pushDataSize; +} VkIndirectCommandsLayoutPushDataTokenNV; + +typedef struct VkSubsampledImageFormatPropertiesEXT { + VkStructureType sType; + const void* pNext; + uint32_t subsampledImageDescriptorCount; +} VkSubsampledImageFormatPropertiesEXT; + +typedef struct VkPhysicalDeviceDescriptorHeapTensorPropertiesARM { + VkStructureType sType; + void* pNext; + VkDeviceSize tensorDescriptorSize; + VkDeviceSize tensorDescriptorAlignment; + size_t tensorCaptureReplayOpaqueDataSize; +} VkPhysicalDeviceDescriptorHeapTensorPropertiesARM; + +typedef VkResult (VKAPI_PTR *PFN_vkWriteSamplerDescriptorsEXT)(VkDevice device, uint32_t samplerCount, const VkSamplerCreateInfo* pSamplers, const VkHostAddressRangeEXT* pDescriptors); +typedef VkResult (VKAPI_PTR *PFN_vkWriteResourceDescriptorsEXT)(VkDevice device, uint32_t resourceCount, const VkResourceDescriptorInfoEXT* pResources, const VkHostAddressRangeEXT* pDescriptors); +typedef void (VKAPI_PTR *PFN_vkCmdBindSamplerHeapEXT)(VkCommandBuffer commandBuffer, const VkBindHeapInfoEXT* pBindInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindResourceHeapEXT)(VkCommandBuffer commandBuffer, const VkBindHeapInfoEXT* pBindInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushDataEXT)(VkCommandBuffer commandBuffer, const VkPushDataInfoEXT* pPushDataInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageOpaqueCaptureDataEXT)(VkDevice device, uint32_t imageCount, const VkImage* pImages, VkHostAddressRangeEXT* pDatas); +typedef VkDeviceSize (VKAPI_PTR *PFN_vkGetPhysicalDeviceDescriptorSizeEXT)(VkPhysicalDevice physicalDevice, VkDescriptorType descriptorType); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterCustomBorderColorEXT)(VkDevice device, const VkSamplerCustomBorderColorCreateInfoEXT* pBorderColor, VkBool32 requestIndex, uint32_t* pIndex); +typedef void (VKAPI_PTR *PFN_vkUnregisterCustomBorderColorEXT)(VkDevice device, uint32_t index); +typedef VkResult (VKAPI_PTR *PFN_vkGetTensorOpaqueCaptureDataARM)(VkDevice device, uint32_t tensorCount, const VkTensorARM* pTensors, VkHostAddressRangeEXT* pDatas); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWriteSamplerDescriptorsEXT( + VkDevice device, + uint32_t samplerCount, + const VkSamplerCreateInfo* pSamplers, + const VkHostAddressRangeEXT* pDescriptors); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWriteResourceDescriptorsEXT( + VkDevice device, + uint32_t resourceCount, + const VkResourceDescriptorInfoEXT* pResources, + const VkHostAddressRangeEXT* pDescriptors); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindSamplerHeapEXT( + VkCommandBuffer commandBuffer, + const VkBindHeapInfoEXT* pBindInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindResourceHeapEXT( + VkCommandBuffer commandBuffer, + const VkBindHeapInfoEXT* pBindInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPushDataEXT( + VkCommandBuffer commandBuffer, + const VkPushDataInfoEXT* pPushDataInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageOpaqueCaptureDataEXT( + VkDevice device, + uint32_t imageCount, + const VkImage* pImages, + VkHostAddressRangeEXT* pDatas); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkDeviceSize VKAPI_CALL vkGetPhysicalDeviceDescriptorSizeEXT( + VkPhysicalDevice physicalDevice, + VkDescriptorType descriptorType); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterCustomBorderColorEXT( + VkDevice device, + const VkSamplerCustomBorderColorCreateInfoEXT* pBorderColor, + VkBool32 requestIndex, + uint32_t* pIndex); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkUnregisterCustomBorderColorEXT( + VkDevice device, + uint32_t index); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetTensorOpaqueCaptureDataARM( + VkDevice device, + uint32_t tensorCount, + const VkTensorARM* pTensors, + VkHostAddressRangeEXT* pDatas); +#endif +#endif + + +// VK_AMD_mixed_attachment_samples is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_mixed_attachment_samples 1 +#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1 +#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples" +typedef struct VkAttachmentSampleCountInfoAMD { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const VkSampleCountFlagBits* pColorAttachmentSamples; + VkSampleCountFlagBits depthStencilAttachmentSamples; +} VkAttachmentSampleCountInfoAMD; + + + +// VK_AMD_shader_fragment_mask is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_fragment_mask 1 +#define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1 +#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask" + + +// VK_EXT_inline_uniform_block is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_inline_uniform_block 1 +#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1 +#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block" +typedef VkPhysicalDeviceInlineUniformBlockFeatures VkPhysicalDeviceInlineUniformBlockFeaturesEXT; + +typedef VkPhysicalDeviceInlineUniformBlockProperties VkPhysicalDeviceInlineUniformBlockPropertiesEXT; + +typedef VkWriteDescriptorSetInlineUniformBlock VkWriteDescriptorSetInlineUniformBlockEXT; + +typedef VkDescriptorPoolInlineUniformBlockCreateInfo VkDescriptorPoolInlineUniformBlockCreateInfoEXT; + + + +// VK_EXT_shader_stencil_export is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_stencil_export 1 +#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1 +#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export" + + +// VK_EXT_sample_locations is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_sample_locations 1 +#define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1 +#define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations" +typedef struct VkSampleLocationEXT { + float x; + float y; +} VkSampleLocationEXT; + +typedef struct VkSampleLocationsInfoEXT { + VkStructureType sType; + const void* pNext; + VkSampleCountFlagBits sampleLocationsPerPixel; + VkExtent2D sampleLocationGridSize; + uint32_t sampleLocationsCount; + const VkSampleLocationEXT* pSampleLocations; +} VkSampleLocationsInfoEXT; + +typedef struct VkAttachmentSampleLocationsEXT { + uint32_t attachmentIndex; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkAttachmentSampleLocationsEXT; + +typedef struct VkSubpassSampleLocationsEXT { + uint32_t subpassIndex; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkSubpassSampleLocationsEXT; + +typedef struct VkRenderPassSampleLocationsBeginInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t attachmentInitialSampleLocationsCount; + const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations; + uint32_t postSubpassSampleLocationsCount; + const VkSubpassSampleLocationsEXT* pPostSubpassSampleLocations; +} VkRenderPassSampleLocationsBeginInfoEXT; + +typedef struct VkPipelineSampleLocationsStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 sampleLocationsEnable; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkPipelineSampleLocationsStateCreateInfoEXT; + +typedef struct VkPhysicalDeviceSampleLocationsPropertiesEXT { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleLocationSampleCounts; + VkExtent2D maxSampleLocationGridSize; + float sampleLocationCoordinateRange[2]; + uint32_t sampleLocationSubPixelBits; + VkBool32 variableSampleLocations; +} VkPhysicalDeviceSampleLocationsPropertiesEXT; + +typedef struct VkMultisamplePropertiesEXT { + VkStructureType sType; + void* pNext; + VkExtent2D maxSampleLocationGridSize; +} VkMultisamplePropertiesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEXT( + VkCommandBuffer commandBuffer, + const VkSampleLocationsInfoEXT* pSampleLocationsInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT( + VkPhysicalDevice physicalDevice, + VkSampleCountFlagBits samples, + VkMultisamplePropertiesEXT* pMultisampleProperties); +#endif +#endif + + +// VK_EXT_blend_operation_advanced is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_blend_operation_advanced 1 +#define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2 +#define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced" + +typedef enum VkBlendOverlapEXT { + VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0, + VK_BLEND_OVERLAP_DISJOINT_EXT = 1, + VK_BLEND_OVERLAP_CONJOINT_EXT = 2, + VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF +} VkBlendOverlapEXT; +typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 advancedBlendCoherentOperations; +} VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT; + +typedef struct VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t advancedBlendMaxColorAttachments; + VkBool32 advancedBlendIndependentBlend; + VkBool32 advancedBlendNonPremultipliedSrcColor; + VkBool32 advancedBlendNonPremultipliedDstColor; + VkBool32 advancedBlendCorrelatedOverlap; + VkBool32 advancedBlendAllOperations; +} VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT; + +typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 srcPremultiplied; + VkBool32 dstPremultiplied; + VkBlendOverlapEXT blendOverlap; +} VkPipelineColorBlendAdvancedStateCreateInfoEXT; + + + +// VK_NV_fragment_coverage_to_color is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_fragment_coverage_to_color 1 +#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color" +typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV; +typedef struct VkPipelineCoverageToColorStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageToColorStateCreateFlagsNV flags; + VkBool32 coverageToColorEnable; + uint32_t coverageToColorLocation; +} VkPipelineCoverageToColorStateCreateInfoNV; + + + +// VK_NV_framebuffer_mixed_samples is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_framebuffer_mixed_samples 1 +#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1 +#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples" + +typedef enum VkCoverageModulationModeNV { + 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, + VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoverageModulationModeNV; +typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV; +typedef struct VkPipelineCoverageModulationStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageModulationStateCreateFlagsNV flags; + VkCoverageModulationModeNV coverageModulationMode; + VkBool32 coverageModulationTableEnable; + uint32_t coverageModulationTableCount; + const float* pCoverageModulationTable; +} VkPipelineCoverageModulationStateCreateInfoNV; + +typedef VkAttachmentSampleCountInfoAMD VkAttachmentSampleCountInfoNV; + + + +// VK_NV_fill_rectangle is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_fill_rectangle 1 +#define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1 +#define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle" + + +// VK_NV_shader_sm_builtins is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_shader_sm_builtins 1 +#define VK_NV_SHADER_SM_BUILTINS_SPEC_VERSION 1 +#define VK_NV_SHADER_SM_BUILTINS_EXTENSION_NAME "VK_NV_shader_sm_builtins" +typedef struct VkPhysicalDeviceShaderSMBuiltinsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t shaderSMCount; + uint32_t shaderWarpsPerSM; +} VkPhysicalDeviceShaderSMBuiltinsPropertiesNV; + +typedef struct VkPhysicalDeviceShaderSMBuiltinsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shaderSMBuiltins; +} VkPhysicalDeviceShaderSMBuiltinsFeaturesNV; + + + +// VK_EXT_post_depth_coverage is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_post_depth_coverage 1 +#define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1 +#define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage" + + +// VK_EXT_image_drm_format_modifier is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_drm_format_modifier 1 +#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 2 +#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier" +typedef struct VkDrmFormatModifierPropertiesEXT { + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + VkFormatFeatureFlags drmFormatModifierTilingFeatures; +} VkDrmFormatModifierPropertiesEXT; + +typedef struct VkDrmFormatModifierPropertiesListEXT { + VkStructureType sType; + void* pNext; + uint32_t drmFormatModifierCount; + VkDrmFormatModifierPropertiesEXT* pDrmFormatModifierProperties; +} VkDrmFormatModifierPropertiesListEXT; + +typedef struct VkPhysicalDeviceImageDrmFormatModifierInfoEXT { + VkStructureType sType; + const void* pNext; + uint64_t drmFormatModifier; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; +} VkPhysicalDeviceImageDrmFormatModifierInfoEXT; + +typedef struct VkImageDrmFormatModifierListCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t drmFormatModifierCount; + const uint64_t* pDrmFormatModifiers; +} VkImageDrmFormatModifierListCreateInfoEXT; + +typedef struct VkImageDrmFormatModifierExplicitCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + const VkSubresourceLayout* pPlaneLayouts; +} VkImageDrmFormatModifierExplicitCreateInfoEXT; + +typedef struct VkImageDrmFormatModifierPropertiesEXT { + VkStructureType sType; + void* pNext; + uint64_t drmFormatModifier; +} VkImageDrmFormatModifierPropertiesEXT; + +typedef struct VkDrmFormatModifierProperties2EXT { + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + VkFormatFeatureFlags2 drmFormatModifierTilingFeatures; +} VkDrmFormatModifierProperties2EXT; + +typedef struct VkDrmFormatModifierPropertiesList2EXT { + VkStructureType sType; + void* pNext; + uint32_t drmFormatModifierCount; + VkDrmFormatModifierProperties2EXT* pDrmFormatModifierProperties; +} VkDrmFormatModifierPropertiesList2EXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetImageDrmFormatModifierPropertiesEXT)(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageDrmFormatModifierPropertiesEXT( + VkDevice device, + VkImage image, + VkImageDrmFormatModifierPropertiesEXT* pProperties); +#endif +#endif + + +// VK_EXT_validation_cache is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_validation_cache 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT) +#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1 +#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache" + +typedef enum VkValidationCacheHeaderVersionEXT { + VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1, + VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationCacheHeaderVersionEXT; +typedef VkFlags VkValidationCacheCreateFlagsEXT; +typedef struct VkValidationCacheCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkValidationCacheCreateFlagsEXT flags; + size_t initialDataSize; + const void* pInitialData; +} VkValidationCacheCreateInfoEXT; + +typedef struct VkShaderModuleValidationCacheCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkValidationCacheEXT validationCache; +} VkShaderModuleValidationCacheCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateValidationCacheEXT)(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache); +typedef void (VKAPI_PTR *PFN_vkDestroyValidationCacheEXT)(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches); +typedef VkResult (VKAPI_PTR *PFN_vkGetValidationCacheDataEXT)(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateValidationCacheEXT( + VkDevice device, + const VkValidationCacheCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkValidationCacheEXT* pValidationCache); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyValidationCacheEXT( + VkDevice device, + VkValidationCacheEXT validationCache, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkMergeValidationCachesEXT( + VkDevice device, + VkValidationCacheEXT dstCache, + uint32_t srcCacheCount, + const VkValidationCacheEXT* pSrcCaches); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT( + VkDevice device, + VkValidationCacheEXT validationCache, + size_t* pDataSize, + void* pData); +#endif +#endif + + +// VK_EXT_descriptor_indexing is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_descriptor_indexing 1 +#define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2 +#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing" +typedef VkDescriptorBindingFlagBits VkDescriptorBindingFlagBitsEXT; + +typedef VkDescriptorBindingFlags VkDescriptorBindingFlagsEXT; + +typedef VkDescriptorSetLayoutBindingFlagsCreateInfo VkDescriptorSetLayoutBindingFlagsCreateInfoEXT; + +typedef VkPhysicalDeviceDescriptorIndexingFeatures VkPhysicalDeviceDescriptorIndexingFeaturesEXT; + +typedef VkPhysicalDeviceDescriptorIndexingProperties VkPhysicalDeviceDescriptorIndexingPropertiesEXT; + +typedef VkDescriptorSetVariableDescriptorCountAllocateInfo VkDescriptorSetVariableDescriptorCountAllocateInfoEXT; + +typedef VkDescriptorSetVariableDescriptorCountLayoutSupport VkDescriptorSetVariableDescriptorCountLayoutSupportEXT; + + + +// VK_EXT_shader_viewport_index_layer is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_viewport_index_layer 1 +#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1 +#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer" + + +// VK_NV_shading_rate_image is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_shading_rate_image 1 +#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3 +#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image" + +typedef enum VkShadingRatePaletteEntryNV { + 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, + VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF +} VkShadingRatePaletteEntryNV; + +typedef enum VkCoarseSampleOrderTypeNV { + 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, + VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoarseSampleOrderTypeNV; +typedef struct VkShadingRatePaletteNV { + uint32_t shadingRatePaletteEntryCount; + const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries; +} VkShadingRatePaletteNV; + +typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 shadingRateImageEnable; + uint32_t viewportCount; + const VkShadingRatePaletteNV* pShadingRatePalettes; +} VkPipelineViewportShadingRateImageStateCreateInfoNV; + +typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shadingRateImage; + VkBool32 shadingRateCoarseSampleOrder; +} VkPhysicalDeviceShadingRateImageFeaturesNV; + +typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV { + VkStructureType sType; + void* pNext; + VkExtent2D shadingRateTexelSize; + uint32_t shadingRatePaletteSize; + uint32_t shadingRateMaxCoarseSamples; +} VkPhysicalDeviceShadingRateImagePropertiesNV; + +typedef struct VkCoarseSampleLocationNV { + uint32_t pixelX; + uint32_t pixelY; + uint32_t sample; +} VkCoarseSampleLocationNV; + +typedef struct VkCoarseSampleOrderCustomNV { + VkShadingRatePaletteEntryNV shadingRate; + uint32_t sampleCount; + uint32_t sampleLocationCount; + const VkCoarseSampleLocationNV* pSampleLocations; +} VkCoarseSampleOrderCustomNV; + +typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkCoarseSampleOrderTypeNV sampleOrderType; + uint32_t customSampleOrderCount; + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders; +} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkShadingRatePaletteNV* pShadingRatePalettes); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( + VkCommandBuffer commandBuffer, + VkCoarseSampleOrderTypeNV sampleOrderType, + uint32_t customSampleOrderCount, + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); +#endif +#endif + + +// VK_NV_ray_tracing is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_ray_tracing 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) +#define VK_NV_RAY_TRACING_SPEC_VERSION 3 +#define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing" +#define VK_SHADER_UNUSED_KHR (~0U) +#define VK_SHADER_UNUSED_NV VK_SHADER_UNUSED_KHR + +typedef enum VkRayTracingShaderGroupTypeKHR { + 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, + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRayTracingShaderGroupTypeKHR; +typedef VkRayTracingShaderGroupTypeKHR VkRayTracingShaderGroupTypeNV; + + +typedef enum VkGeometryTypeKHR { + VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0, + VK_GEOMETRY_TYPE_AABBS_KHR = 1, + VK_GEOMETRY_TYPE_INSTANCES_KHR = 2, + VK_GEOMETRY_TYPE_SPHERES_NV = 1000429004, + VK_GEOMETRY_TYPE_LINEAR_SWEPT_SPHERES_NV = 1000429005, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_GEOMETRY_TYPE_DENSE_GEOMETRY_FORMAT_TRIANGLES_AMDX = 1000478000, +#endif + VK_GEOMETRY_TYPE_MICROMAP_KHR = 1000623000, + VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR, + VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryTypeKHR; +typedef VkGeometryTypeKHR VkGeometryTypeNV; + +typedef VkAccelerationStructureTypeKHR VkAccelerationStructureTypeNV; + + +typedef enum VkCopyAccelerationStructureModeKHR { + 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, + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCopyAccelerationStructureModeKHR; +typedef VkCopyAccelerationStructureModeKHR VkCopyAccelerationStructureModeNV; + + +typedef enum VkAccelerationStructureMemoryRequirementsTypeNV { + 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, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMemoryRequirementsTypeNV; + +typedef enum VkGeometryFlagBitsKHR { + VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0x00000002, + VK_GEOMETRY_OPAQUE_BIT_NV = VK_GEOMETRY_OPAQUE_BIT_KHR, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR, + VK_GEOMETRY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryFlagBitsKHR; +typedef VkFlags VkGeometryFlagsKHR; +typedef VkGeometryFlagsKHR VkGeometryFlagsNV; + +typedef VkGeometryFlagBitsKHR VkGeometryFlagBitsNV; + + +typedef enum VkGeometryInstanceFlagBitsKHR { + VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001, + VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0x00000002, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008, + VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_BIT_KHR = 0x00000010, + VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_BIT_KHR = 0x00000020, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_BIT_EXT = VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_BIT_KHR, + // VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT is a legacy alias + VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT = VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_BIT_EXT, + VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_BIT_EXT = VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_BIT_KHR, + // VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT is a legacy alias + VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT = VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_BIT_EXT, + VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryInstanceFlagBitsKHR; +typedef VkFlags VkGeometryInstanceFlagsKHR; +typedef VkGeometryInstanceFlagsKHR VkGeometryInstanceFlagsNV; + +typedef VkGeometryInstanceFlagBitsKHR VkGeometryInstanceFlagBitsNV; + + +typedef enum VkBuildAccelerationStructureFlagBitsKHR { + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0x00000001, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0x00000002, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, + VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV = 0x00000020, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_BIT_EXT = 0x00000100, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_BIT_NV = 0x00000200, +#endif + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_BIT_KHR = 0x00000800, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_CLUSTER_OPACITY_MICROMAPS_BIT_NV = 0x00001000, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_BIT_KHR = 0x00000040, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_BIT_KHR = 0x00000080, + VK_BUILD_ACCELERATION_STRUCTURE_MICROMAP_LOSSY_BIT_KHR = 0x00000400, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_BIT_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_BIT_KHR, + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_BIT_EXT, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_BIT_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_BIT_KHR, + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_BIT_EXT, + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_BIT_EXT, +#ifdef VK_ENABLE_BETA_EXTENSIONS + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_BIT_NV, +#endif + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureFlagBitsKHR; +typedef VkFlags VkBuildAccelerationStructureFlagsKHR; +typedef VkBuildAccelerationStructureFlagBitsKHR VkBuildAccelerationStructureFlagBitsNV; + +typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV; + +typedef struct VkRayTracingShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; +} VkRayTracingShaderGroupCreateInfoNV; + +typedef struct VkRayTracingPipelineCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoNV* pGroups; + uint32_t maxRecursionDepth; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoNV; + +typedef struct VkGeometryTrianglesNV { + VkStructureType sType; + const void* pNext; + VkBuffer vertexData; + VkDeviceSize vertexOffset; + uint32_t vertexCount; + VkDeviceSize vertexStride; + VkFormat vertexFormat; + VkBuffer indexData; + VkDeviceSize indexOffset; + uint32_t indexCount; + VkIndexType indexType; + VkBuffer transformData; + VkDeviceSize transformOffset; +} VkGeometryTrianglesNV; + +typedef struct VkGeometryAABBNV { + VkStructureType sType; + const void* pNext; + VkBuffer aabbData; + uint32_t numAABBs; + uint32_t stride; + VkDeviceSize offset; +} VkGeometryAABBNV; + +typedef struct VkGeometryDataNV { + VkGeometryTrianglesNV triangles; + VkGeometryAABBNV aabbs; +} VkGeometryDataNV; + +typedef struct VkGeometryNV { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkGeometryDataNV geometry; + VkGeometryFlagsKHR flags; +} VkGeometryNV; + +typedef struct VkAccelerationStructureInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeNV type; + VkBuildAccelerationStructureFlagsKHR flags; + uint32_t instanceCount; + uint32_t geometryCount; + const VkGeometryNV* pGeometries; +} VkAccelerationStructureInfoNV; + +typedef struct VkAccelerationStructureCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceSize compactedSize; + VkAccelerationStructureInfoNV info; +} VkAccelerationStructureCreateInfoNV; + +typedef struct VkBindAccelerationStructureMemoryInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureNV accelerationStructure; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindAccelerationStructureMemoryInfoNV; + +typedef struct VkWriteDescriptorSetAccelerationStructureNV { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureNV* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureNV; + +typedef struct VkAccelerationStructureMemoryRequirementsInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureMemoryRequirementsTypeNV type; + VkAccelerationStructureNV accelerationStructure; +} VkAccelerationStructureMemoryRequirementsInfoNV; + +typedef struct VkPhysicalDeviceRayTracingPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxTriangleCount; + uint32_t maxDescriptorSetAccelerationStructures; +} VkPhysicalDeviceRayTracingPropertiesNV; + +typedef struct VkTransformMatrixKHR { + float matrix[3][4]; +} VkTransformMatrixKHR; + +typedef VkTransformMatrixKHR VkTransformMatrixNV; + +typedef struct VkAabbPositionsKHR { + float minX; + float minY; + float minZ; + float maxX; + float maxY; + float maxZ; +} VkAabbPositionsKHR; + +typedef VkAabbPositionsKHR VkAabbPositionsNV; + +typedef struct VkAccelerationStructureInstanceKHR { + VkTransformMatrixKHR transform; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureInstanceKHR; + +typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV( + VkDevice device, + const VkAccelerationStructureCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureNV* pAccelerationStructure); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV( + VkDevice device, + VkAccelerationStructureNV accelerationStructure, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( + VkDevice device, + const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV( + VkDevice device, + uint32_t bindInfoCount, + const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( + VkCommandBuffer commandBuffer, + const VkAccelerationStructureInfoNV* pInfo, + VkBuffer instanceData, + VkDeviceSize instanceOffset, + VkBool32 update, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, + VkBuffer scratch, + VkDeviceSize scratchOffset); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV( + VkCommandBuffer commandBuffer, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, + VkCopyAccelerationStructureModeKHR mode); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( + VkCommandBuffer commandBuffer, + VkBuffer raygenShaderBindingTableBuffer, + VkDeviceSize raygenShaderBindingOffset, + VkBuffer missShaderBindingTableBuffer, + VkDeviceSize missShaderBindingOffset, + VkDeviceSize missShaderBindingStride, + VkBuffer hitShaderBindingTableBuffer, + VkDeviceSize hitShaderBindingOffset, + VkDeviceSize hitShaderBindingStride, + VkBuffer callableShaderBindingTableBuffer, + VkDeviceSize callableShaderBindingOffset, + VkDeviceSize callableShaderBindingStride, + uint32_t width, + uint32_t height, + uint32_t depth); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoNV* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV( + VkDevice device, + VkAccelerationStructureNV accelerationStructure, + size_t dataSize, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureNV* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV( + VkDevice device, + VkPipeline pipeline, + uint32_t shader); +#endif +#endif + + +// VK_NV_representative_fragment_test is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_representative_fragment_test 1 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 2 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test" +typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 representativeFragmentTest; +} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV; + +typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 representativeFragmentTestEnable; +} VkPipelineRepresentativeFragmentTestStateCreateInfoNV; + + + +// VK_EXT_filter_cubic is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_filter_cubic 1 +#define VK_EXT_FILTER_CUBIC_SPEC_VERSION 3 +#define VK_EXT_FILTER_CUBIC_EXTENSION_NAME "VK_EXT_filter_cubic" +typedef struct VkPhysicalDeviceImageViewImageFormatInfoEXT { + VkStructureType sType; + void* pNext; + VkImageViewType imageViewType; +} VkPhysicalDeviceImageViewImageFormatInfoEXT; + +typedef struct VkFilterCubicImageViewImageFormatPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 filterCubic; + VkBool32 filterCubicMinmax; +} VkFilterCubicImageViewImageFormatPropertiesEXT; + + + +// VK_QCOM_render_pass_shader_resolve is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_render_pass_shader_resolve 1 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_SPEC_VERSION 4 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME "VK_QCOM_render_pass_shader_resolve" + + +// VK_QCOM_cooperative_matrix_conversion is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_cooperative_matrix_conversion 1 +#define VK_QCOM_COOPERATIVE_MATRIX_CONVERSION_SPEC_VERSION 1 +#define VK_QCOM_COOPERATIVE_MATRIX_CONVERSION_EXTENSION_NAME "VK_QCOM_cooperative_matrix_conversion" +typedef struct VkPhysicalDeviceCooperativeMatrixConversionFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrixConversion; +} VkPhysicalDeviceCooperativeMatrixConversionFeaturesQCOM; + + + +// VK_QCOM_elapsed_timer_query is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_elapsed_timer_query 1 +#define VK_QCOM_ELAPSED_TIMER_QUERY_SPEC_VERSION 1 +#define VK_QCOM_ELAPSED_TIMER_QUERY_EXTENSION_NAME "VK_QCOM_elapsed_timer_query" +typedef struct VkPhysicalDeviceElapsedTimerQueryFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 elapsedTimerQuery; +} VkPhysicalDeviceElapsedTimerQueryFeaturesQCOM; + + + +// VK_EXT_global_priority is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_global_priority 1 +#define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 +#define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority" +typedef VkQueueGlobalPriority VkQueueGlobalPriorityEXT; + +typedef VkDeviceQueueGlobalPriorityCreateInfo VkDeviceQueueGlobalPriorityCreateInfoEXT; + + + +// VK_EXT_external_memory_host is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_external_memory_host 1 +#define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host" +typedef struct VkImportMemoryHostPointerInfoEXT { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + void* pHostPointer; +} VkImportMemoryHostPointerInfoEXT; + +typedef struct VkMemoryHostPointerPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryHostPointerPropertiesEXT; + +typedef struct VkPhysicalDeviceExternalMemoryHostPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize minImportedHostPointerAlignment; +} VkPhysicalDeviceExternalMemoryHostPropertiesEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostPointerPropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + const void* pHostPointer, + VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); +#endif +#endif + + +// VK_AMD_buffer_marker is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_buffer_marker 1 +#define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1 +#define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker" +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarker2AMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlagBits pipelineStage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarker2AMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2 stage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); +#endif +#endif + + +// VK_AMD_pipeline_compiler_control is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_pipeline_compiler_control 1 +#define VK_AMD_PIPELINE_COMPILER_CONTROL_SPEC_VERSION 1 +#define VK_AMD_PIPELINE_COMPILER_CONTROL_EXTENSION_NAME "VK_AMD_pipeline_compiler_control" + +typedef enum VkPipelineCompilerControlFlagBitsAMD { + VK_PIPELINE_COMPILER_CONTROL_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkPipelineCompilerControlFlagBitsAMD; +typedef VkFlags VkPipelineCompilerControlFlagsAMD; +typedef struct VkPipelineCompilerControlCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkPipelineCompilerControlFlagsAMD compilerControlFlags; +} VkPipelineCompilerControlCreateInfoAMD; + + + +// VK_EXT_calibrated_timestamps is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_calibrated_timestamps 1 +#define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 2 +#define VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_EXT_calibrated_timestamps" +typedef VkTimeDomainKHR VkTimeDomainEXT; + +typedef VkCalibratedTimestampInfoKHR VkCalibratedTimestampInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)(VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainKHR* pTimeDomains); +typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsEXT)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoKHR* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( + VkPhysicalDevice physicalDevice, + uint32_t* pTimeDomainCount, + VkTimeDomainKHR* pTimeDomains); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT( + VkDevice device, + uint32_t timestampCount, + const VkCalibratedTimestampInfoKHR* pTimestampInfos, + uint64_t* pTimestamps, + uint64_t* pMaxDeviation); +#endif +#endif + + +// VK_AMD_shader_core_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_core_properties 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 2 +#define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties" +typedef struct VkPhysicalDeviceShaderCorePropertiesAMD { + VkStructureType sType; + void* pNext; + uint32_t shaderEngineCount; + uint32_t shaderArraysPerEngineCount; + uint32_t computeUnitsPerShaderArray; + uint32_t simdPerComputeUnit; + uint32_t wavefrontsPerSimd; + uint32_t wavefrontSize; + uint32_t sgprsPerSimd; + uint32_t minSgprAllocation; + uint32_t maxSgprAllocation; + uint32_t sgprAllocationGranularity; + uint32_t vgprsPerSimd; + uint32_t minVgprAllocation; + uint32_t maxVgprAllocation; + uint32_t vgprAllocationGranularity; +} VkPhysicalDeviceShaderCorePropertiesAMD; + + + +// VK_AMD_memory_overallocation_behavior is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_memory_overallocation_behavior 1 +#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1 +#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior" + +typedef enum VkMemoryOverallocationBehaviorAMD { + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_MAX_ENUM_AMD = 0x7FFFFFFF +} VkMemoryOverallocationBehaviorAMD; +typedef struct VkDeviceMemoryOverallocationCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkMemoryOverallocationBehaviorAMD overallocationBehavior; +} VkDeviceMemoryOverallocationCreateInfoAMD; + + + +// VK_EXT_vertex_attribute_divisor is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_vertex_attribute_divisor 1 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor" +typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxVertexAttribDivisor; +} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT; + +typedef VkVertexInputBindingDivisorDescription VkVertexInputBindingDivisorDescriptionEXT; + +typedef VkPipelineVertexInputDivisorStateCreateInfo VkPipelineVertexInputDivisorStateCreateInfoEXT; + +typedef VkPhysicalDeviceVertexAttributeDivisorFeatures VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT; + + + +// VK_EXT_pipeline_creation_feedback is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_creation_feedback 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME "VK_EXT_pipeline_creation_feedback" +typedef VkPipelineCreationFeedbackFlagBits VkPipelineCreationFeedbackFlagBitsEXT; + +typedef VkPipelineCreationFeedbackFlags VkPipelineCreationFeedbackFlagsEXT; + +typedef VkPipelineCreationFeedbackCreateInfo VkPipelineCreationFeedbackCreateInfoEXT; + +typedef VkPipelineCreationFeedback VkPipelineCreationFeedbackEXT; + + + +// VK_NV_shader_subgroup_partitioned is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_shader_subgroup_partitioned 1 +#define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1 +#define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned" + + +// VK_NV_compute_shader_derivatives is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_compute_shader_derivatives 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives" +typedef VkPhysicalDeviceComputeShaderDerivativesFeaturesKHR VkPhysicalDeviceComputeShaderDerivativesFeaturesNV; + + + +// VK_NV_mesh_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_mesh_shader 1 +#define VK_NV_MESH_SHADER_SPEC_VERSION 1 +#define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader" +typedef struct VkPhysicalDeviceMeshShaderFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 taskShader; + VkBool32 meshShader; +} VkPhysicalDeviceMeshShaderFeaturesNV; + +typedef struct VkPhysicalDeviceMeshShaderPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxDrawMeshTasksCount; + uint32_t maxTaskWorkGroupInvocations; + uint32_t maxTaskWorkGroupSize[3]; + uint32_t maxTaskTotalMemorySize; + uint32_t maxTaskOutputCount; + uint32_t maxMeshWorkGroupInvocations; + uint32_t maxMeshWorkGroupSize[3]; + uint32_t maxMeshTotalMemorySize; + uint32_t maxMeshOutputVertices; + uint32_t maxMeshOutputPrimitives; + uint32_t maxMeshMultiviewViewCount; + uint32_t meshOutputPerVertexGranularity; + uint32_t meshOutputPerPrimitiveGranularity; +} VkPhysicalDeviceMeshShaderPropertiesNV; + +typedef struct VkDrawMeshTasksIndirectCommandNV { + uint32_t taskCount; + uint32_t firstTask; +} VkDrawMeshTasksIndirectCommandNV; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV( + VkCommandBuffer commandBuffer, + uint32_t taskCount, + uint32_t firstTask); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif +#endif + + +// VK_NV_fragment_shader_barycentric is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_fragment_shader_barycentric 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric" +typedef VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV; + + + +// VK_NV_shader_image_footprint is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_shader_image_footprint 1 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 2 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint" +typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 imageFootprint; +} VkPhysicalDeviceShaderImageFootprintFeaturesNV; + + + +// VK_NV_scissor_exclusive is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_scissor_exclusive 1 +#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 2 +#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive" +typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t exclusiveScissorCount; + const VkRect2D* pExclusiveScissors; +} VkPipelineViewportExclusiveScissorStateCreateInfoNV; + +typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 exclusiveScissor; +} VkPhysicalDeviceExclusiveScissorFeaturesNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorEnableNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkBool32* pExclusiveScissorEnables); +typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorEnableNV( + VkCommandBuffer commandBuffer, + uint32_t firstExclusiveScissor, + uint32_t exclusiveScissorCount, + const VkBool32* pExclusiveScissorEnables); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( + VkCommandBuffer commandBuffer, + uint32_t firstExclusiveScissor, + uint32_t exclusiveScissorCount, + const VkRect2D* pExclusiveScissors); +#endif +#endif + + +// VK_NV_device_diagnostic_checkpoints is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_device_diagnostic_checkpoints 1 +#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2 +#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints" +typedef struct VkQueueFamilyCheckpointPropertiesNV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags checkpointExecutionStageMask; +} VkQueueFamilyCheckpointPropertiesNV; + +typedef struct VkCheckpointDataNV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlagBits stage; + void* pCheckpointMarker; +} VkCheckpointDataNV; + +typedef struct VkQueueFamilyCheckpointProperties2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2 checkpointExecutionStageMask; +} VkQueueFamilyCheckpointProperties2NV; + +typedef struct VkCheckpointData2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2 stage; + void* pCheckpointMarker; +} VkCheckpointData2NV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetCheckpointNV)(VkCommandBuffer commandBuffer, const void* pCheckpointMarker); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointDataNV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointData2NV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointData2NV* pCheckpointData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCheckpointNV( + VkCommandBuffer commandBuffer, + const void* pCheckpointMarker); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointDataNV* pCheckpointData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointData2NV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointData2NV* pCheckpointData); +#endif +#endif + + +// VK_EXT_present_timing is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_present_timing 1 +#define VK_EXT_PRESENT_TIMING_SPEC_VERSION 3 +#define VK_EXT_PRESENT_TIMING_EXTENSION_NAME "VK_EXT_present_timing" + +typedef enum VkPresentStageFlagBitsEXT { + VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT = 0x00000001, + VK_PRESENT_STAGE_REQUEST_DEQUEUED_BIT_EXT = 0x00000002, + VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT = 0x00000004, + VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT = 0x00000008, + VK_PRESENT_STAGE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPresentStageFlagBitsEXT; +typedef VkFlags VkPresentStageFlagsEXT; + +typedef enum VkPastPresentationTimingFlagBitsEXT { + VK_PAST_PRESENTATION_TIMING_ALLOW_PARTIAL_RESULTS_BIT_EXT = 0x00000001, + VK_PAST_PRESENTATION_TIMING_ALLOW_OUT_OF_ORDER_RESULTS_BIT_EXT = 0x00000002, + VK_PAST_PRESENTATION_TIMING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPastPresentationTimingFlagBitsEXT; +typedef VkFlags VkPastPresentationTimingFlagsEXT; + +typedef enum VkPresentTimingInfoFlagBitsEXT { + VK_PRESENT_TIMING_INFO_PRESENT_AT_RELATIVE_TIME_BIT_EXT = 0x00000001, + VK_PRESENT_TIMING_INFO_PRESENT_AT_NEAREST_REFRESH_CYCLE_BIT_EXT = 0x00000002, + VK_PRESENT_TIMING_INFO_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPresentTimingInfoFlagBitsEXT; +typedef VkFlags VkPresentTimingInfoFlagsEXT; +typedef struct VkPhysicalDevicePresentTimingFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 presentTiming; + VkBool32 presentAtAbsoluteTime; + VkBool32 presentAtRelativeTime; +} VkPhysicalDevicePresentTimingFeaturesEXT; + +typedef struct VkPresentTimingSurfaceCapabilitiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 presentTimingSupported; + VkBool32 presentAtAbsoluteTimeSupported; + VkBool32 presentAtRelativeTimeSupported; + VkPresentStageFlagsEXT presentStageQueries; +} VkPresentTimingSurfaceCapabilitiesEXT; + +typedef struct VkSwapchainCalibratedTimestampInfoEXT { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + VkPresentStageFlagsEXT presentStage; + uint64_t timeDomainId; +} VkSwapchainCalibratedTimestampInfoEXT; + +typedef struct VkSwapchainTimingPropertiesEXT { + VkStructureType sType; + void* pNext; + uint64_t refreshDuration; + uint64_t refreshInterval; +} VkSwapchainTimingPropertiesEXT; + +typedef struct VkSwapchainTimeDomainPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t timeDomainCount; + VkTimeDomainKHR* pTimeDomains; + uint64_t* pTimeDomainIds; +} VkSwapchainTimeDomainPropertiesEXT; + +typedef struct VkPastPresentationTimingInfoEXT { + VkStructureType sType; + const void* pNext; + VkPastPresentationTimingFlagsEXT flags; + VkSwapchainKHR swapchain; +} VkPastPresentationTimingInfoEXT; + +typedef struct VkPresentStageTimeEXT { + VkPresentStageFlagsEXT stage; + uint64_t time; +} VkPresentStageTimeEXT; + +typedef struct VkPastPresentationTimingEXT { + VkStructureType sType; + void* pNext; + uint64_t presentId; + uint64_t targetTime; + uint32_t presentStageCount; + VkPresentStageTimeEXT* pPresentStages; + VkTimeDomainKHR timeDomain; + uint64_t timeDomainId; + VkBool32 reportComplete; +} VkPastPresentationTimingEXT; + +typedef struct VkPastPresentationTimingPropertiesEXT { + VkStructureType sType; + void* pNext; + uint64_t timingPropertiesCounter; + uint64_t timeDomainsCounter; + uint32_t presentationTimingCount; + VkPastPresentationTimingEXT* pPresentationTimings; +} VkPastPresentationTimingPropertiesEXT; + +typedef struct VkPresentTimingInfoEXT { + VkStructureType sType; + const void* pNext; + VkPresentTimingInfoFlagsEXT flags; + uint64_t targetTime; + uint64_t timeDomainId; + VkPresentStageFlagsEXT presentStageQueries; + VkPresentStageFlagsEXT targetTimeDomainPresentStage; +} VkPresentTimingInfoEXT; + +typedef struct VkPresentTimingsInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentTimingInfoEXT* pTimingInfos; +} VkPresentTimingsInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkSetSwapchainPresentTimingQueueSizeEXT)(VkDevice device, VkSwapchainKHR swapchain, uint32_t size); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainTimingPropertiesEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSwapchainTimingPropertiesEXT* pSwapchainTimingProperties, uint64_t* pSwapchainTimingPropertiesCounter); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainTimeDomainPropertiesEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSwapchainTimeDomainPropertiesEXT* pSwapchainTimeDomainProperties, uint64_t* pTimeDomainsCounter); +typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingEXT)(VkDevice device, const VkPastPresentationTimingInfoEXT* pPastPresentationTimingInfo, VkPastPresentationTimingPropertiesEXT* pPastPresentationTimingProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetSwapchainPresentTimingQueueSizeEXT( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t size); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainTimingPropertiesEXT( + VkDevice device, + VkSwapchainKHR swapchain, + VkSwapchainTimingPropertiesEXT* pSwapchainTimingProperties, + uint64_t* pSwapchainTimingPropertiesCounter); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainTimeDomainPropertiesEXT( + VkDevice device, + VkSwapchainKHR swapchain, + VkSwapchainTimeDomainPropertiesEXT* pSwapchainTimeDomainProperties, + uint64_t* pTimeDomainsCounter); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingEXT( + VkDevice device, + const VkPastPresentationTimingInfoEXT* pPastPresentationTimingInfo, + VkPastPresentationTimingPropertiesEXT* pPastPresentationTimingProperties); +#endif +#endif + + +// VK_INTEL_shader_integer_functions2 is a preprocessor guard. Do not pass it to API calls. +#define VK_INTEL_shader_integer_functions2 1 +#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION 1 +#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME "VK_INTEL_shader_integer_functions2" +typedef struct VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerFunctions2; +} VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL; + + + +// VK_INTEL_performance_query is a preprocessor guard. Do not pass it to API calls. +#define VK_INTEL_performance_query 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL) +#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 2 +#define VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME "VK_INTEL_performance_query" + +typedef enum VkPerformanceConfigurationTypeINTEL { + VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0, + VK_PERFORMANCE_CONFIGURATION_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceConfigurationTypeINTEL; + +typedef enum VkQueryPoolSamplingModeINTEL { + VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0, + VK_QUERY_POOL_SAMPLING_MODE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkQueryPoolSamplingModeINTEL; + +typedef enum VkPerformanceOverrideTypeINTEL { + VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL = 0, + VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL = 1, + VK_PERFORMANCE_OVERRIDE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceOverrideTypeINTEL; + +typedef enum VkPerformanceParameterTypeINTEL { + VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL = 0, + VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL = 1, + VK_PERFORMANCE_PARAMETER_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceParameterTypeINTEL; + +typedef enum VkPerformanceValueTypeINTEL { + 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, + VK_PERFORMANCE_VALUE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceValueTypeINTEL; +typedef union VkPerformanceValueDataINTEL { + uint32_t value32; + uint64_t value64; + float valueFloat; + VkBool32 valueBool; + const char* valueString; +} VkPerformanceValueDataINTEL; + +typedef struct VkPerformanceValueINTEL { + VkPerformanceValueTypeINTEL type; + VkPerformanceValueDataINTEL data; +} VkPerformanceValueINTEL; + +typedef struct VkInitializePerformanceApiInfoINTEL { + VkStructureType sType; + const void* pNext; + void* pUserData; +} VkInitializePerformanceApiInfoINTEL; + +typedef struct VkQueryPoolPerformanceQueryCreateInfoINTEL { + VkStructureType sType; + const void* pNext; + VkQueryPoolSamplingModeINTEL performanceCountersSampling; +} VkQueryPoolPerformanceQueryCreateInfoINTEL; + +typedef VkQueryPoolPerformanceQueryCreateInfoINTEL VkQueryPoolCreateInfoINTEL; + +typedef struct VkPerformanceMarkerInfoINTEL { + VkStructureType sType; + const void* pNext; + uint64_t marker; +} VkPerformanceMarkerInfoINTEL; + +typedef struct VkPerformanceStreamMarkerInfoINTEL { + VkStructureType sType; + const void* pNext; + uint32_t marker; +} VkPerformanceStreamMarkerInfoINTEL; + +typedef struct VkPerformanceOverrideInfoINTEL { + VkStructureType sType; + const void* pNext; + VkPerformanceOverrideTypeINTEL type; + VkBool32 enable; + uint64_t parameter; +} VkPerformanceOverrideInfoINTEL; + +typedef struct VkPerformanceConfigurationAcquireInfoINTEL { + VkStructureType sType; + const void* pNext; + VkPerformanceConfigurationTypeINTEL type; +} VkPerformanceConfigurationAcquireInfoINTEL; + +typedef VkResult (VKAPI_PTR *PFN_vkInitializePerformanceApiINTEL)(VkDevice device, const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); +typedef void (VKAPI_PTR *PFN_vkUninitializePerformanceApiINTEL)(VkDevice device); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceMarkerInfoINTEL* pMarkerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceStreamMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceOverrideINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceOverrideInfoINTEL* pOverrideInfo); +typedef VkResult (VKAPI_PTR *PFN_vkAcquirePerformanceConfigurationINTEL)(VkDevice device, const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VkPerformanceConfigurationINTEL* pConfiguration); +typedef VkResult (VKAPI_PTR *PFN_vkReleasePerformanceConfigurationINTEL)(VkDevice device, VkPerformanceConfigurationINTEL configuration); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSetPerformanceConfigurationINTEL)(VkQueue queue, VkPerformanceConfigurationINTEL configuration); +typedef VkResult (VKAPI_PTR *PFN_vkGetPerformanceParameterINTEL)(VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkInitializePerformanceApiINTEL( + VkDevice device, + const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkUninitializePerformanceApiINTEL( + VkDevice device); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceMarkerINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceMarkerInfoINTEL* pMarkerInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceStreamMarkerINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceOverrideINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceOverrideInfoINTEL* pOverrideInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquirePerformanceConfigurationINTEL( + VkDevice device, + const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, + VkPerformanceConfigurationINTEL* pConfiguration); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleasePerformanceConfigurationINTEL( + VkDevice device, + VkPerformanceConfigurationINTEL configuration); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSetPerformanceConfigurationINTEL( + VkQueue queue, + VkPerformanceConfigurationINTEL configuration); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceParameterINTEL( + VkDevice device, + VkPerformanceParameterTypeINTEL parameter, + VkPerformanceValueINTEL* pValue); +#endif +#endif + + +// VK_EXT_pci_bus_info is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pci_bus_info 1 +#define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2 +#define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info" +typedef struct VkPhysicalDevicePCIBusInfoPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t pciDomain; + uint32_t pciBus; + uint32_t pciDevice; + uint32_t pciFunction; +} VkPhysicalDevicePCIBusInfoPropertiesEXT; + + + +// VK_AMD_display_native_hdr is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_display_native_hdr 1 +#define VK_AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION 1 +#define VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME "VK_AMD_display_native_hdr" +typedef struct VkDisplayNativeHdrSurfaceCapabilitiesAMD { + VkStructureType sType; + void* pNext; + VkBool32 localDimmingSupport; +} VkDisplayNativeHdrSurfaceCapabilitiesAMD; + +typedef struct VkSwapchainDisplayNativeHdrCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkBool32 localDimmingEnable; +} VkSwapchainDisplayNativeHdrCreateInfoAMD; + +typedef void (VKAPI_PTR *PFN_vkSetLocalDimmingAMD)(VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetLocalDimmingAMD( + VkDevice device, + VkSwapchainKHR swapChain, + VkBool32 localDimmingEnable); +#endif +#endif + + +// VK_EXT_fragment_density_map is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_fragment_density_map 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 3 +#define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map" +typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMap; + VkBool32 fragmentDensityMapDynamic; + VkBool32 fragmentDensityMapNonSubsampledImages; +} VkPhysicalDeviceFragmentDensityMapFeaturesEXT; + +typedef struct VkPhysicalDeviceFragmentDensityMapPropertiesEXT { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentDensityTexelSize; + VkExtent2D maxFragmentDensityTexelSize; + VkBool32 fragmentDensityInvocations; +} VkPhysicalDeviceFragmentDensityMapPropertiesEXT; + +typedef struct VkRenderPassFragmentDensityMapCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkAttachmentReference fragmentDensityMapAttachment; +} VkRenderPassFragmentDensityMapCreateInfoEXT; + +typedef struct VkRenderingFragmentDensityMapAttachmentInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; +} VkRenderingFragmentDensityMapAttachmentInfoEXT; + + + +// VK_EXT_scalar_block_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_scalar_block_layout 1 +#define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1 +#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout" +typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLayoutFeaturesEXT; + + + +// VK_GOOGLE_hlsl_functionality1 is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_hlsl_functionality1 1 +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION 1 +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1" +// VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION is a legacy alias +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION +// VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME is a legacy alias +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME + + +// VK_GOOGLE_decorate_string is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_decorate_string 1 +#define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1 +#define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string" + + +// VK_EXT_subgroup_size_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_subgroup_size_control 1 +#define VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION 2 +#define VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME "VK_EXT_subgroup_size_control" +typedef VkPhysicalDeviceSubgroupSizeControlFeatures VkPhysicalDeviceSubgroupSizeControlFeaturesEXT; + +typedef VkPhysicalDeviceSubgroupSizeControlProperties VkPhysicalDeviceSubgroupSizeControlPropertiesEXT; + +typedef VkPipelineShaderStageRequiredSubgroupSizeCreateInfo VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT; + + + +// VK_AMD_shader_core_properties2 is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_core_properties2 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_2_SPEC_VERSION 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME "VK_AMD_shader_core_properties2" + +typedef enum VkShaderCorePropertiesFlagBitsAMD { + VK_SHADER_CORE_PROPERTIES_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkShaderCorePropertiesFlagBitsAMD; +typedef VkFlags VkShaderCorePropertiesFlagsAMD; +typedef struct VkPhysicalDeviceShaderCoreProperties2AMD { + VkStructureType sType; + void* pNext; + VkShaderCorePropertiesFlagsAMD shaderCoreFeatures; + uint32_t activeComputeUnitCount; +} VkPhysicalDeviceShaderCoreProperties2AMD; + + + +// VK_AMD_device_coherent_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_device_coherent_memory 1 +#define VK_AMD_DEVICE_COHERENT_MEMORY_SPEC_VERSION 1 +#define VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME "VK_AMD_device_coherent_memory" +typedef struct VkPhysicalDeviceCoherentMemoryFeaturesAMD { + VkStructureType sType; + void* pNext; + VkBool32 deviceCoherentMemory; +} VkPhysicalDeviceCoherentMemoryFeaturesAMD; + + + +// VK_EXT_shader_image_atomic_int64 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_image_atomic_int64 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME "VK_EXT_shader_image_atomic_int64" +typedef struct VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderImageInt64Atomics; + VkBool32 sparseImageInt64Atomics; +} VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT; + + + +// VK_EXT_memory_budget is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_memory_budget 1 +#define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1 +#define VK_EXT_MEMORY_BUDGET_EXTENSION_NAME "VK_EXT_memory_budget" +typedef struct VkPhysicalDeviceMemoryBudgetPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize heapBudget[VK_MAX_MEMORY_HEAPS]; + VkDeviceSize heapUsage[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryBudgetPropertiesEXT; + + + +// VK_EXT_memory_priority is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_memory_priority 1 +#define VK_EXT_MEMORY_PRIORITY_SPEC_VERSION 1 +#define VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME "VK_EXT_memory_priority" +typedef struct VkPhysicalDeviceMemoryPriorityFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 memoryPriority; +} VkPhysicalDeviceMemoryPriorityFeaturesEXT; + +typedef struct VkMemoryPriorityAllocateInfoEXT { + VkStructureType sType; + const void* pNext; + float priority; +} VkMemoryPriorityAllocateInfoEXT; + + + +// VK_NV_dedicated_allocation_image_aliasing is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_dedicated_allocation_image_aliasing 1 +#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_SPEC_VERSION 1 +#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME "VK_NV_dedicated_allocation_image_aliasing" +typedef struct VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 dedicatedAllocationImageAliasing; +} VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV; + + + +// VK_EXT_buffer_device_address is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_buffer_device_address 1 +#define VK_EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 2 +#define VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_EXT_buffer_device_address" +typedef struct VkPhysicalDeviceBufferDeviceAddressFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; +} VkPhysicalDeviceBufferDeviceAddressFeaturesEXT; + +typedef VkPhysicalDeviceBufferDeviceAddressFeaturesEXT VkPhysicalDeviceBufferAddressFeaturesEXT; + +typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoEXT; + +typedef struct VkBufferDeviceAddressCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddress deviceAddress; +} VkBufferDeviceAddressCreateInfoEXT; + +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressEXT)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressEXT( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); +#endif +#endif + + +// VK_EXT_tooling_info is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_tooling_info 1 +#define VK_EXT_TOOLING_INFO_SPEC_VERSION 1 +#define VK_EXT_TOOLING_INFO_EXTENSION_NAME "VK_EXT_tooling_info" +typedef VkToolPurposeFlagBits VkToolPurposeFlagBitsEXT; + +typedef VkToolPurposeFlags VkToolPurposeFlagsEXT; + +typedef VkPhysicalDeviceToolProperties VkPhysicalDeviceToolPropertiesEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolPropertiesEXT)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolPropertiesEXT( + VkPhysicalDevice physicalDevice, + uint32_t* pToolCount, + VkPhysicalDeviceToolProperties* pToolProperties); +#endif +#endif + + +// VK_EXT_separate_stencil_usage is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_separate_stencil_usage 1 +#define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1 +#define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage" +typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT; + + + +// VK_EXT_validation_features is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_validation_features 1 +#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 6 +#define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" + +typedef enum VkValidationFeatureEnableEXT { + 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, + VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureEnableEXT; + +typedef enum VkValidationFeatureDisableEXT { + 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, + VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureDisableEXT; +typedef struct VkValidationFeaturesEXT { + VkStructureType sType; + const void* pNext; + uint32_t enabledValidationFeatureCount; + const VkValidationFeatureEnableEXT* pEnabledValidationFeatures; + uint32_t disabledValidationFeatureCount; + const VkValidationFeatureDisableEXT* pDisabledValidationFeatures; +} VkValidationFeaturesEXT; + + + +// VK_NV_cooperative_matrix is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cooperative_matrix 1 +#define VK_NV_COOPERATIVE_MATRIX_SPEC_VERSION 1 +#define VK_NV_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_NV_cooperative_matrix" +typedef VkComponentTypeKHR VkComponentTypeNV; + +typedef VkScopeKHR VkScopeNV; + +typedef struct VkCooperativeMatrixPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t MSize; + uint32_t NSize; + uint32_t KSize; + VkComponentTypeNV AType; + VkComponentTypeNV BType; + VkComponentTypeNV CType; + VkComponentTypeNV DType; + VkScopeNV scope; +} VkCooperativeMatrixPropertiesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrixFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrix; + VkBool32 cooperativeMatrixRobustBufferAccess; +} VkPhysicalDeviceCooperativeMatrixFeaturesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesNV { + VkStructureType sType; + void* pNext; + VkShaderStageFlags cooperativeMatrixSupportedStages; +} VkPhysicalDeviceCooperativeMatrixPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkCooperativeMatrixPropertiesNV* pProperties); +#endif +#endif + + +// VK_NV_coverage_reduction_mode is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_coverage_reduction_mode 1 +#define VK_NV_COVERAGE_REDUCTION_MODE_SPEC_VERSION 1 +#define VK_NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME "VK_NV_coverage_reduction_mode" + +typedef enum VkCoverageReductionModeNV { + VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0, + VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1, + VK_COVERAGE_REDUCTION_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoverageReductionModeNV; +typedef VkFlags VkPipelineCoverageReductionStateCreateFlagsNV; +typedef struct VkPhysicalDeviceCoverageReductionModeFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 coverageReductionMode; +} VkPhysicalDeviceCoverageReductionModeFeaturesNV; + +typedef struct VkPipelineCoverageReductionStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageReductionStateCreateFlagsNV flags; + VkCoverageReductionModeNV coverageReductionMode; +} VkPipelineCoverageReductionStateCreateInfoNV; + +typedef struct VkFramebufferMixedSamplesCombinationNV { + VkStructureType sType; + void* pNext; + VkCoverageReductionModeNV coverageReductionMode; + VkSampleCountFlagBits rasterizationSamples; + VkSampleCountFlags depthStencilSamples; + VkSampleCountFlags colorSamples; +} VkFramebufferMixedSamplesCombinationNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)(VkPhysicalDevice physicalDevice, uint32_t* pCombinationCount, VkFramebufferMixedSamplesCombinationNV* pCombinations); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( + VkPhysicalDevice physicalDevice, + uint32_t* pCombinationCount, + VkFramebufferMixedSamplesCombinationNV* pCombinations); +#endif +#endif + + +// VK_EXT_fragment_shader_interlock is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_fragment_shader_interlock 1 +#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME "VK_EXT_fragment_shader_interlock" +typedef struct VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShaderSampleInterlock; + VkBool32 fragmentShaderPixelInterlock; + VkBool32 fragmentShaderShadingRateInterlock; +} VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT; + + + +// VK_EXT_ycbcr_image_arrays is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_ycbcr_image_arrays 1 +#define VK_EXT_YCBCR_IMAGE_ARRAYS_SPEC_VERSION 1 +#define VK_EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME "VK_EXT_ycbcr_image_arrays" +typedef struct VkPhysicalDeviceYcbcrImageArraysFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 ycbcrImageArrays; +} VkPhysicalDeviceYcbcrImageArraysFeaturesEXT; + + + +// VK_EXT_provoking_vertex is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_provoking_vertex 1 +#define VK_EXT_PROVOKING_VERTEX_SPEC_VERSION 1 +#define VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME "VK_EXT_provoking_vertex" + +typedef enum VkProvokingVertexModeEXT { + VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT = 0, + VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT = 1, + VK_PROVOKING_VERTEX_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkProvokingVertexModeEXT; +typedef struct VkPhysicalDeviceProvokingVertexFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexLast; + VkBool32 transformFeedbackPreservesProvokingVertex; +} VkPhysicalDeviceProvokingVertexFeaturesEXT; + +typedef struct VkPhysicalDeviceProvokingVertexPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexModePerPipeline; + VkBool32 transformFeedbackPreservesTriangleFanProvokingVertex; +} VkPhysicalDeviceProvokingVertexPropertiesEXT; + +typedef struct VkPipelineRasterizationProvokingVertexStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkProvokingVertexModeEXT provokingVertexMode; +} VkPipelineRasterizationProvokingVertexStateCreateInfoEXT; + + + +// VK_EXT_headless_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_headless_surface 1 +#define VK_EXT_HEADLESS_SURFACE_SPEC_VERSION 1 +#define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface" +typedef VkFlags VkHeadlessSurfaceCreateFlagsEXT; +typedef struct VkHeadlessSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkHeadlessSurfaceCreateFlagsEXT flags; +} VkHeadlessSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT( + VkInstance instance, + const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + + +// VK_EXT_line_rasterization is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_line_rasterization 1 +#define VK_EXT_LINE_RASTERIZATION_SPEC_VERSION 1 +#define VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME "VK_EXT_line_rasterization" +typedef VkLineRasterizationMode VkLineRasterizationModeEXT; + +typedef VkPhysicalDeviceLineRasterizationFeatures VkPhysicalDeviceLineRasterizationFeaturesEXT; + +typedef VkPhysicalDeviceLineRasterizationProperties VkPhysicalDeviceLineRasterizationPropertiesEXT; + +typedef VkPipelineRasterizationLineStateCreateInfo VkPipelineRasterizationLineStateCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleEXT)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEXT( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern); +#endif +#endif + + +// VK_EXT_shader_atomic_float is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_atomic_float 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME "VK_EXT_shader_atomic_float" +typedef struct VkPhysicalDeviceShaderAtomicFloatFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat32Atomics; + VkBool32 shaderBufferFloat32AtomicAdd; + VkBool32 shaderBufferFloat64Atomics; + VkBool32 shaderBufferFloat64AtomicAdd; + VkBool32 shaderSharedFloat32Atomics; + VkBool32 shaderSharedFloat32AtomicAdd; + VkBool32 shaderSharedFloat64Atomics; + VkBool32 shaderSharedFloat64AtomicAdd; + VkBool32 shaderImageFloat32Atomics; + VkBool32 shaderImageFloat32AtomicAdd; + VkBool32 sparseImageFloat32Atomics; + VkBool32 sparseImageFloat32AtomicAdd; +} VkPhysicalDeviceShaderAtomicFloatFeaturesEXT; + + + +// VK_EXT_host_query_reset is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_host_query_reset 1 +#define VK_EXT_HOST_QUERY_RESET_SPEC_VERSION 1 +#define VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME "VK_EXT_host_query_reset" +typedef VkPhysicalDeviceHostQueryResetFeatures VkPhysicalDeviceHostQueryResetFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkResetQueryPoolEXT)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); +#endif +#endif + + +// VK_EXT_index_type_uint8 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_index_type_uint8 1 +#define VK_EXT_INDEX_TYPE_UINT8_SPEC_VERSION 1 +#define VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME "VK_EXT_index_type_uint8" +typedef VkPhysicalDeviceIndexTypeUint8Features VkPhysicalDeviceIndexTypeUint8FeaturesEXT; + + + +// VK_EXT_extended_dynamic_state is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_extended_dynamic_state 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_extended_dynamic_state" +typedef struct VkPhysicalDeviceExtendedDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState; +} VkPhysicalDeviceExtendedDynamicStateFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetCullModeEXT)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetFrontFaceEXT)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveTopologyEXT)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissorWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers2EXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthWriteEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthCompareOpEXT)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBoundsTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOpEXT)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCullModeEXT( + VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFaceEXT( + VkCommandBuffer commandBuffer, + VkFrontFace frontFace); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopologyEXT( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t viewportCount, + const VkViewport* pViewports); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t scissorCount, + const VkRect2D* pScissors); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes, + const VkDeviceSize* pStrides); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOpEXT( + VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp); +#endif +#endif + + +// VK_EXT_host_image_copy is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_host_image_copy 1 +#define VK_EXT_HOST_IMAGE_COPY_SPEC_VERSION 1 +#define VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME "VK_EXT_host_image_copy" +typedef VkHostImageCopyFlagBits VkHostImageCopyFlagBitsEXT; + +typedef VkHostImageCopyFlags VkHostImageCopyFlagsEXT; + +typedef VkPhysicalDeviceHostImageCopyFeatures VkPhysicalDeviceHostImageCopyFeaturesEXT; + +typedef VkPhysicalDeviceHostImageCopyProperties VkPhysicalDeviceHostImageCopyPropertiesEXT; + +typedef VkMemoryToImageCopy VkMemoryToImageCopyEXT; + +typedef VkImageToMemoryCopy VkImageToMemoryCopyEXT; + +typedef VkCopyMemoryToImageInfo VkCopyMemoryToImageInfoEXT; + +typedef VkCopyImageToMemoryInfo VkCopyImageToMemoryInfoEXT; + +typedef VkCopyImageToImageInfo VkCopyImageToImageInfoEXT; + +typedef VkHostImageLayoutTransitionInfo VkHostImageLayoutTransitionInfoEXT; + +typedef VkSubresourceHostMemcpySize VkSubresourceHostMemcpySizeEXT; + +typedef VkHostImageCopyDevicePerformanceQuery VkHostImageCopyDevicePerformanceQueryEXT; + +typedef VkSubresourceLayout2 VkSubresourceLayout2EXT; + +typedef VkImageSubresource2 VkImageSubresource2EXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToImageEXT)(VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToMemoryEXT)(VkDevice device, const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToImageEXT)(VkDevice device, const VkCopyImageToImageInfo* pCopyImageToImageInfo); +typedef VkResult (VKAPI_PTR *PFN_vkTransitionImageLayoutEXT)(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions); +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2EXT)(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToImageEXT( + VkDevice device, + const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToMemoryEXT( + VkDevice device, + const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToImageEXT( + VkDevice device, + const VkCopyImageToImageInfo* pCopyImageToImageInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkTransitionImageLayoutEXT( + VkDevice device, + uint32_t transitionCount, + const VkHostImageLayoutTransitionInfo* pTransitions); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2EXT( + VkDevice device, + VkImage image, + const VkImageSubresource2* pSubresource, + VkSubresourceLayout2* pLayout); +#endif +#endif + + +// VK_EXT_map_memory_placed is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_map_memory_placed 1 +#define VK_EXT_MAP_MEMORY_PLACED_SPEC_VERSION 1 +#define VK_EXT_MAP_MEMORY_PLACED_EXTENSION_NAME "VK_EXT_map_memory_placed" +typedef struct VkPhysicalDeviceMapMemoryPlacedFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 memoryMapPlaced; + VkBool32 memoryMapRangePlaced; + VkBool32 memoryUnmapReserve; +} VkPhysicalDeviceMapMemoryPlacedFeaturesEXT; + +typedef struct VkPhysicalDeviceMapMemoryPlacedPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize minPlacedMemoryMapAlignment; +} VkPhysicalDeviceMapMemoryPlacedPropertiesEXT; + +typedef struct VkMemoryMapPlacedInfoEXT { + VkStructureType sType; + const void* pNext; + void* pPlacedAddress; +} VkMemoryMapPlacedInfoEXT; + + + +// VK_EXT_shader_atomic_float2 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_atomic_float2 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME "VK_EXT_shader_atomic_float2" +typedef struct VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat16Atomics; + VkBool32 shaderBufferFloat16AtomicAdd; + VkBool32 shaderBufferFloat16AtomicMinMax; + VkBool32 shaderBufferFloat32AtomicMinMax; + VkBool32 shaderBufferFloat64AtomicMinMax; + VkBool32 shaderSharedFloat16Atomics; + VkBool32 shaderSharedFloat16AtomicAdd; + VkBool32 shaderSharedFloat16AtomicMinMax; + VkBool32 shaderSharedFloat32AtomicMinMax; + VkBool32 shaderSharedFloat64AtomicMinMax; + VkBool32 shaderImageFloat32AtomicMinMax; + VkBool32 sparseImageFloat32AtomicMinMax; +} VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT; + + + +// VK_EXT_surface_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_surface_maintenance1 1 +#define VK_EXT_SURFACE_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME "VK_EXT_surface_maintenance1" +typedef VkPresentScalingFlagBitsKHR VkPresentScalingFlagBitsEXT; + +typedef VkPresentScalingFlagsKHR VkPresentScalingFlagsEXT; + +typedef VkPresentGravityFlagBitsKHR VkPresentGravityFlagBitsEXT; + +typedef VkPresentGravityFlagsKHR VkPresentGravityFlagsEXT; + +typedef VkSurfacePresentModeKHR VkSurfacePresentModeEXT; + +typedef VkSurfacePresentScalingCapabilitiesKHR VkSurfacePresentScalingCapabilitiesEXT; + +typedef VkSurfacePresentModeCompatibilityKHR VkSurfacePresentModeCompatibilityEXT; + + + +// VK_EXT_swapchain_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_swapchain_maintenance1 1 +#define VK_EXT_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME "VK_EXT_swapchain_maintenance1" +typedef VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT; + +typedef VkSwapchainPresentFenceInfoKHR VkSwapchainPresentFenceInfoEXT; + +typedef VkSwapchainPresentModesCreateInfoKHR VkSwapchainPresentModesCreateInfoEXT; + +typedef VkSwapchainPresentModeInfoKHR VkSwapchainPresentModeInfoEXT; + +typedef VkSwapchainPresentScalingCreateInfoKHR VkSwapchainPresentScalingCreateInfoEXT; + +typedef VkReleaseSwapchainImagesInfoKHR VkReleaseSwapchainImagesInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkReleaseSwapchainImagesEXT)(VkDevice device, const VkReleaseSwapchainImagesInfoKHR* pReleaseInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseSwapchainImagesEXT( + VkDevice device, + const VkReleaseSwapchainImagesInfoKHR* pReleaseInfo); +#endif +#endif + + +// VK_EXT_shader_demote_to_helper_invocation is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_demote_to_helper_invocation 1 +#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION 1 +#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME "VK_EXT_shader_demote_to_helper_invocation" +typedef VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT; + + + +// VK_NV_device_generated_commands is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_device_generated_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV) +#define VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 +#define VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NV_device_generated_commands" + +typedef enum VkIndirectCommandsTokenTypeNV { + 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_PUSH_DATA_NV = 1000135000, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV = 1000328000, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV = 1000428003, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV = 1000428004, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsTokenTypeNV; + +typedef enum VkIndirectStateFlagBitsNV { + VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0x00000001, + VK_INDIRECT_STATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectStateFlagBitsNV; +typedef VkFlags VkIndirectStateFlagsNV; + +typedef enum VkIndirectCommandsLayoutUsageFlagBitsNV { + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0x00000001, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0x00000002, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0x00000004, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsLayoutUsageFlagBitsNV; +typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNV; +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxGraphicsShaderGroupCount; + uint32_t maxIndirectSequenceCount; + uint32_t maxIndirectCommandsTokenCount; + uint32_t maxIndirectCommandsStreamCount; + uint32_t maxIndirectCommandsTokenOffset; + uint32_t maxIndirectCommandsStreamStride; + uint32_t minSequencesCountBufferOffsetAlignment; + uint32_t minSequencesIndexBufferOffsetAlignment; + uint32_t minIndirectCommandsBufferOffsetAlignment; +} VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV; + +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 deviceGeneratedCommands; +} VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV; + +typedef struct VkGraphicsShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; +} VkGraphicsShaderGroupCreateInfoNV; + +typedef struct VkGraphicsPipelineShaderGroupsCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t groupCount; + const VkGraphicsShaderGroupCreateInfoNV* pGroups; + uint32_t pipelineCount; + const VkPipeline* pPipelines; +} VkGraphicsPipelineShaderGroupsCreateInfoNV; + +typedef struct VkBindShaderGroupIndirectCommandNV { + uint32_t groupIndex; +} VkBindShaderGroupIndirectCommandNV; + +typedef struct VkBindIndexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + VkIndexType indexType; +} VkBindIndexBufferIndirectCommandNV; + +typedef struct VkBindVertexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + uint32_t stride; +} VkBindVertexBufferIndirectCommandNV; + +typedef struct VkSetStateFlagsIndirectCommandNV { + uint32_t data; +} VkSetStateFlagsIndirectCommandNV; + +typedef struct VkIndirectCommandsStreamNV { + VkBuffer buffer; + VkDeviceSize offset; +} VkIndirectCommandsStreamNV; + +typedef struct VkIndirectCommandsLayoutTokenNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsTokenTypeNV tokenType; + uint32_t stream; + uint32_t offset; + uint32_t vertexBindingUnit; + VkBool32 vertexDynamicStride; + VkPipelineLayout pushconstantPipelineLayout; + VkShaderStageFlags pushconstantShaderStageFlags; + uint32_t pushconstantOffset; + uint32_t pushconstantSize; + VkIndirectStateFlagsNV indirectStateFlags; + uint32_t indexTypeCount; + const VkIndexType* pIndexTypes; + const uint32_t* pIndexTypeValues; +} VkIndirectCommandsLayoutTokenNV; + +typedef struct VkIndirectCommandsLayoutCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsLayoutUsageFlagsNV flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t tokenCount; + const VkIndirectCommandsLayoutTokenNV* pTokens; + uint32_t streamCount; + const uint32_t* pStreamStrides; +} VkIndirectCommandsLayoutCreateInfoNV; + +typedef struct VkGeneratedCommandsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t streamCount; + const VkIndirectCommandsStreamNV* pStreams; + uint32_t sequencesCount; + VkBuffer preprocessBuffer; + VkDeviceSize preprocessOffset; + VkDeviceSize preprocessSize; + VkBuffer sequencesCountBuffer; + VkDeviceSize sequencesCountOffset; + VkBuffer sequencesIndexBuffer; + VkDeviceSize sequencesIndexOffset; +} VkGeneratedCommandsInfoNV; + +typedef struct VkGeneratedCommandsMemoryRequirementsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t maxSequencesCount; +} VkGeneratedCommandsMemoryRequirementsInfoNV; + +typedef void (VKAPI_PTR *PFN_vkGetGeneratedCommandsMemoryRequirementsNV)(VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdPreprocessGeneratedCommandsNV)(VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteGeneratedCommandsNV)(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipelineShaderGroupNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex); +typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNV)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNV)(VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsNV( + VkDevice device, + const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + VkBool32 isPreprocessed, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipelineShaderGroupNV( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline, + uint32_t groupIndex); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNV( + VkDevice device, + const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( + VkDevice device, + VkIndirectCommandsLayoutNV indirectCommandsLayout, + const VkAllocationCallbacks* pAllocator); +#endif +#endif + + +// VK_NV_inherited_viewport_scissor is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_inherited_viewport_scissor 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME "VK_NV_inherited_viewport_scissor" +typedef struct VkPhysicalDeviceInheritedViewportScissorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 inheritedViewportScissor2D; +} VkPhysicalDeviceInheritedViewportScissorFeaturesNV; + +typedef struct VkCommandBufferInheritanceViewportScissorInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 viewportScissor2D; + uint32_t viewportDepthCount; + const VkViewport* pViewportDepths; +} VkCommandBufferInheritanceViewportScissorInfoNV; + + + +// VK_EXT_texel_buffer_alignment is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_texel_buffer_alignment 1 +#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1 +#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment" +typedef struct VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 texelBufferAlignment; +} VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT; + +typedef VkPhysicalDeviceTexelBufferAlignmentProperties VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT; + + + +// VK_QCOM_render_pass_transform is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_render_pass_transform 1 +#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 5 +#define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" +typedef struct VkRenderPassTransformBeginInfoQCOM { + VkStructureType sType; + const void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkRenderPassTransformBeginInfoQCOM; + +typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { + VkStructureType sType; + const void* pNext; + VkSurfaceTransformFlagBitsKHR transform; + VkRect2D renderArea; +} VkCommandBufferInheritanceRenderPassTransformInfoQCOM; + + + +// VK_EXT_depth_bias_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_bias_control 1 +#define VK_EXT_DEPTH_BIAS_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME "VK_EXT_depth_bias_control" + +typedef enum VkDepthBiasRepresentationEXT { + VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT = 0, + VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT = 1, + VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT = 2, + VK_DEPTH_BIAS_REPRESENTATION_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDepthBiasRepresentationEXT; +typedef struct VkPhysicalDeviceDepthBiasControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 depthBiasControl; + VkBool32 leastRepresentableValueForceUnormRepresentation; + VkBool32 floatRepresentation; + VkBool32 depthBiasExact; +} VkPhysicalDeviceDepthBiasControlFeaturesEXT; + +typedef struct VkDepthBiasInfoEXT { + VkStructureType sType; + const void* pNext; + float depthBiasConstantFactor; + float depthBiasClamp; + float depthBiasSlopeFactor; +} VkDepthBiasInfoEXT; + +typedef struct VkDepthBiasRepresentationInfoEXT { + VkStructureType sType; + const void* pNext; + VkDepthBiasRepresentationEXT depthBiasRepresentation; + VkBool32 depthBiasExact; +} VkDepthBiasRepresentationInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias2EXT)(VkCommandBuffer commandBuffer, const VkDepthBiasInfoEXT* pDepthBiasInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias2EXT( + VkCommandBuffer commandBuffer, + const VkDepthBiasInfoEXT* pDepthBiasInfo); +#endif +#endif + + +// VK_EXT_device_memory_report is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_device_memory_report 1 +#define VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION 2 +#define VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME "VK_EXT_device_memory_report" + +typedef enum VkDeviceMemoryReportEventTypeEXT { + 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, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceMemoryReportEventTypeEXT; +typedef VkFlags VkDeviceMemoryReportFlagsEXT; +typedef struct VkPhysicalDeviceDeviceMemoryReportFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 deviceMemoryReport; +} VkPhysicalDeviceDeviceMemoryReportFeaturesEXT; + +typedef struct VkDeviceMemoryReportCallbackDataEXT { + VkStructureType sType; + void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + VkDeviceMemoryReportEventTypeEXT type; + uint64_t memoryObjectId; + VkDeviceSize size; + VkObjectType objectType; + uint64_t objectHandle; + uint32_t heapIndex; +} VkDeviceMemoryReportCallbackDataEXT; + +typedef void (VKAPI_PTR *PFN_vkDeviceMemoryReportCallbackEXT)( + const VkDeviceMemoryReportCallbackDataEXT* pCallbackData, + void* pUserData); + +typedef struct VkDeviceDeviceMemoryReportCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + PFN_vkDeviceMemoryReportCallbackEXT pfnUserCallback; + void* pUserData; +} VkDeviceDeviceMemoryReportCreateInfoEXT; + + + +// VK_EXT_acquire_drm_display is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_acquire_drm_display 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_drm_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, uint32_t connectorId, VkDisplayKHR* display); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireDrmDisplayEXT( + VkPhysicalDevice physicalDevice, + int32_t drmFd, + VkDisplayKHR display); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDrmDisplayEXT( + VkPhysicalDevice physicalDevice, + int32_t drmFd, + uint32_t connectorId, + VkDisplayKHR* display); +#endif +#endif + + +// VK_EXT_robustness2 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_robustness2 1 +#define VK_EXT_ROBUSTNESS_2_SPEC_VERSION 1 +#define VK_EXT_ROBUSTNESS_2_EXTENSION_NAME "VK_EXT_robustness2" +typedef VkPhysicalDeviceRobustness2FeaturesKHR VkPhysicalDeviceRobustness2FeaturesEXT; + +typedef VkPhysicalDeviceRobustness2PropertiesKHR VkPhysicalDeviceRobustness2PropertiesEXT; + + + +// VK_EXT_custom_border_color is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_custom_border_color 1 +#define VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION 12 +#define VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME "VK_EXT_custom_border_color" +typedef struct VkPhysicalDeviceCustomBorderColorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxCustomBorderColorSamplers; +} VkPhysicalDeviceCustomBorderColorPropertiesEXT; + +typedef struct VkPhysicalDeviceCustomBorderColorFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 customBorderColors; + VkBool32 customBorderColorWithoutFormat; +} VkPhysicalDeviceCustomBorderColorFeaturesEXT; + + + +// VK_EXT_texture_compression_astc_3d is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_texture_compression_astc_3d 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_3D_SPEC_VERSION 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_3D_EXTENSION_NAME "VK_EXT_texture_compression_astc_3d" +typedef struct VkPhysicalDeviceTextureCompressionASTC3DFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 textureCompressionASTC_3D; +} VkPhysicalDeviceTextureCompressionASTC3DFeaturesEXT; + + + +// VK_GOOGLE_user_type is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_user_type 1 +#define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1 +#define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type" + + +// VK_NV_present_barrier is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_present_barrier 1 +#define VK_NV_PRESENT_BARRIER_SPEC_VERSION 1 +#define VK_NV_PRESENT_BARRIER_EXTENSION_NAME "VK_NV_present_barrier" +typedef struct VkPhysicalDevicePresentBarrierFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 presentBarrier; +} VkPhysicalDevicePresentBarrierFeaturesNV; + +typedef struct VkSurfaceCapabilitiesPresentBarrierNV { + VkStructureType sType; + void* pNext; + VkBool32 presentBarrierSupported; +} VkSurfaceCapabilitiesPresentBarrierNV; + +typedef struct VkSwapchainPresentBarrierCreateInfoNV { + VkStructureType sType; + void* pNext; + VkBool32 presentBarrierEnable; +} VkSwapchainPresentBarrierCreateInfoNV; + + + +// VK_EXT_private_data is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_private_data 1 +typedef VkPrivateDataSlot VkPrivateDataSlotEXT; + +#define VK_EXT_PRIVATE_DATA_SPEC_VERSION 1 +#define VK_EXT_PRIVATE_DATA_EXTENSION_NAME "VK_EXT_private_data" +typedef VkPrivateDataSlotCreateFlags VkPrivateDataSlotCreateFlagsEXT; + +typedef VkPhysicalDevicePrivateDataFeatures VkPhysicalDevicePrivateDataFeaturesEXT; + +typedef VkDevicePrivateDataCreateInfo VkDevicePrivateDataCreateInfoEXT; + +typedef VkPrivateDataSlotCreateInfo VkPrivateDataSlotCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlotEXT)(VkDevice device, const VkPrivateDataSlotCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlot* pPrivateDataSlot); +typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlotEXT)(VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data); +typedef void (VKAPI_PTR *PFN_vkGetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlotEXT( + VkDevice device, + const VkPrivateDataSlotCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPrivateDataSlot* pPrivateDataSlot); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlotEXT( + VkDevice device, + VkPrivateDataSlot privateDataSlot, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t data); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t* pData); +#endif +#endif + + +// VK_EXT_pipeline_creation_cache_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_creation_cache_control 1 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION 3 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME "VK_EXT_pipeline_creation_cache_control" +typedef VkPhysicalDevicePipelineCreationCacheControlFeatures VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT; + + + +// VK_NV_device_diagnostics_config is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_device_diagnostics_config 1 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION 2 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME "VK_NV_device_diagnostics_config" + +typedef enum VkDeviceDiagnosticsConfigFlagBitsNV { + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0x00000001, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0x00000002, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0x00000004, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV = 0x00000008, + VK_DEVICE_DIAGNOSTICS_CONFIG_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkDeviceDiagnosticsConfigFlagBitsNV; +typedef VkFlags VkDeviceDiagnosticsConfigFlagsNV; +typedef struct VkPhysicalDeviceDiagnosticsConfigFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 diagnosticsConfig; +} VkPhysicalDeviceDiagnosticsConfigFeaturesNV; + +typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceDiagnosticsConfigFlagsNV flags; +} VkDeviceDiagnosticsConfigCreateInfoNV; + + + +// VK_QCOM_render_pass_store_ops is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_render_pass_store_ops 1 +#define VK_QCOM_RENDER_PASS_STORE_OPS_SPEC_VERSION 2 +#define VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" + + +// VK_QCOM_queue_perf_hint is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_queue_perf_hint 1 +#define VK_QCOM_QUEUE_PERF_HINT_SPEC_VERSION 1 +#define VK_QCOM_QUEUE_PERF_HINT_EXTENSION_NAME "VK_QCOM_queue_perf_hint" + +typedef enum VkPerfHintTypeQCOM { + VK_PERF_HINT_TYPE_DEFAULT_QCOM = 0, + VK_PERF_HINT_TYPE_FREQUENCY_MIN_QCOM = 1, + VK_PERF_HINT_TYPE_FREQUENCY_MAX_QCOM = 2, + VK_PERF_HINT_TYPE_FREQUENCY_SCALED_QCOM = 3, + VK_PERF_HINT_TYPE_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkPerfHintTypeQCOM; +typedef struct VkPerfHintInfoQCOM { + VkStructureType sType; + void* pNext; + VkPerfHintTypeQCOM type; + uint32_t scale; +} VkPerfHintInfoQCOM; + +typedef struct VkPhysicalDeviceQueuePerfHintFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 queuePerfHint; +} VkPhysicalDeviceQueuePerfHintFeaturesQCOM; + +typedef struct VkPhysicalDeviceQueuePerfHintPropertiesQCOM { + VkStructureType sType; + void* pNext; + VkQueueFlags supportedQueues; +} VkPhysicalDeviceQueuePerfHintPropertiesQCOM; + +typedef VkResult (VKAPI_PTR *PFN_vkQueueSetPerfHintQCOM)(VkQueue queue, const VkPerfHintInfoQCOM* pPerfHintInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSetPerfHintQCOM( + VkQueue queue, + const VkPerfHintInfoQCOM* pPerfHintInfo); +#endif +#endif + + +// VK_QCOM_image_processing3 is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_image_processing3 1 +#define VK_QCOM_IMAGE_PROCESSING_3_SPEC_VERSION 1 +#define VK_QCOM_IMAGE_PROCESSING_3_EXTENSION_NAME "VK_QCOM_image_processing3" +typedef struct VkPhysicalDeviceImageProcessing3FeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 imageGatherLinear; + VkBool32 imageGatherExtendedModes; + VkBool32 blockMatchExtendedClampToEdge; +} VkPhysicalDeviceImageProcessing3FeaturesQCOM; + + + +// VK_QCOM_shader_multiple_wait_queues is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_shader_multiple_wait_queues 1 +#define VK_QCOM_SHADER_MULTIPLE_WAIT_QUEUES_SPEC_VERSION 1 +#define VK_QCOM_SHADER_MULTIPLE_WAIT_QUEUES_EXTENSION_NAME "VK_QCOM_shader_multiple_wait_queues" +typedef struct VkPhysicalDeviceShaderMultipleWaitQueuesFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 shaderMultipleWaitQueues; +} VkPhysicalDeviceShaderMultipleWaitQueuesFeaturesQCOM; + +typedef struct VkPhysicalDeviceShaderMultipleWaitQueuesPropertiesQCOM { + VkStructureType sType; + void* pNext; + uint32_t maxShaderWaitQueues; +} VkPhysicalDeviceShaderMultipleWaitQueuesPropertiesQCOM; + + + +// VK_EXT_shader_split_barrier is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_split_barrier 1 +#define VK_EXT_SHADER_SPLIT_BARRIER_SPEC_VERSION 1 +#define VK_EXT_SHADER_SPLIT_BARRIER_EXTENSION_NAME "VK_EXT_shader_split_barrier" +typedef struct VkPhysicalDeviceShaderSplitBarrierFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderSplitBarrier; +} VkPhysicalDeviceShaderSplitBarrierFeaturesEXT; + +typedef struct VkPhysicalDeviceShaderSplitBarrierPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t splitBarrierReservedSharedMemory; +} VkPhysicalDeviceShaderSplitBarrierPropertiesEXT; + + + +// VK_QCOM_tile_shading is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_tile_shading 1 +#define VK_QCOM_TILE_SHADING_SPEC_VERSION 2 +#define VK_QCOM_TILE_SHADING_EXTENSION_NAME "VK_QCOM_tile_shading" + +typedef enum VkTileShadingRenderPassFlagBitsQCOM { + VK_TILE_SHADING_RENDER_PASS_ENABLE_BIT_QCOM = 0x00000001, + VK_TILE_SHADING_RENDER_PASS_PER_TILE_EXECUTION_BIT_QCOM = 0x00000002, + VK_TILE_SHADING_RENDER_PASS_FLAG_BITS_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkTileShadingRenderPassFlagBitsQCOM; +typedef VkFlags VkTileShadingRenderPassFlagsQCOM; +typedef struct VkPhysicalDeviceTileShadingFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 tileShading; + VkBool32 tileShadingFragmentStage; + VkBool32 tileShadingColorAttachments; + VkBool32 tileShadingDepthAttachments; + VkBool32 tileShadingStencilAttachments; + VkBool32 tileShadingInputAttachments; + VkBool32 tileShadingSampledAttachments; + VkBool32 tileShadingPerTileDraw; + VkBool32 tileShadingPerTileDispatch; + VkBool32 tileShadingDispatchTile; + VkBool32 tileShadingApron; + VkBool32 tileShadingAnisotropicApron; + VkBool32 tileShadingAtomicOps; + VkBool32 tileShadingImageProcessing; +} VkPhysicalDeviceTileShadingFeaturesQCOM; + +typedef struct VkPhysicalDeviceTileShadingPropertiesQCOM { + VkStructureType sType; + void* pNext; + uint32_t maxApronSize; + VkBool32 preferNonCoherent; + VkExtent2D tileGranularity; + VkExtent2D maxTileShadingRate; +} VkPhysicalDeviceTileShadingPropertiesQCOM; + +typedef struct VkRenderPassTileShadingCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + VkTileShadingRenderPassFlagsQCOM flags; + VkExtent2D tileApronSize; +} VkRenderPassTileShadingCreateInfoQCOM; + +typedef struct VkPerTileBeginInfoQCOM { + VkStructureType sType; + const void* pNext; +} VkPerTileBeginInfoQCOM; + +typedef struct VkPerTileEndInfoQCOM { + VkStructureType sType; + const void* pNext; +} VkPerTileEndInfoQCOM; + +typedef struct VkDispatchTileInfoQCOM { + VkStructureType sType; + const void* pNext; +} VkDispatchTileInfoQCOM; + +typedef void (VKAPI_PTR *PFN_vkCmdDispatchTileQCOM)(VkCommandBuffer commandBuffer, const VkDispatchTileInfoQCOM* pDispatchTileInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginPerTileExecutionQCOM)(VkCommandBuffer commandBuffer, const VkPerTileBeginInfoQCOM* pPerTileBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndPerTileExecutionQCOM)(VkCommandBuffer commandBuffer, const VkPerTileEndInfoQCOM* pPerTileEndInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchTileQCOM( + VkCommandBuffer commandBuffer, + const VkDispatchTileInfoQCOM* pDispatchTileInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginPerTileExecutionQCOM( + VkCommandBuffer commandBuffer, + const VkPerTileBeginInfoQCOM* pPerTileBeginInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndPerTileExecutionQCOM( + VkCommandBuffer commandBuffer, + const VkPerTileEndInfoQCOM* pPerTileEndInfo); +#endif +#endif + + +// VK_NV_low_latency is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_low_latency 1 +#define VK_NV_LOW_LATENCY_SPEC_VERSION 1 +#define VK_NV_LOW_LATENCY_EXTENSION_NAME "VK_NV_low_latency" +typedef struct VkQueryLowLatencySupportNV { + VkStructureType sType; + const void* pNext; + void* pQueriedLowLatencyData; +} VkQueryLowLatencySupportNV; + + + +// VK_EXT_descriptor_buffer is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_descriptor_buffer 1 +#define VK_EXT_DESCRIPTOR_BUFFER_SPEC_VERSION 1 +#define VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME "VK_EXT_descriptor_buffer" +typedef struct VkPhysicalDeviceDescriptorBufferPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 combinedImageSamplerDescriptorSingleArray; + VkBool32 bufferlessPushDescriptors; + VkBool32 allowSamplerImageViewPostSubmitCreation; + VkDeviceSize descriptorBufferOffsetAlignment; + uint32_t maxDescriptorBufferBindings; + uint32_t maxResourceDescriptorBufferBindings; + uint32_t maxSamplerDescriptorBufferBindings; + uint32_t maxEmbeddedImmutableSamplerBindings; + uint32_t maxEmbeddedImmutableSamplers; + size_t bufferCaptureReplayDescriptorDataSize; + size_t imageCaptureReplayDescriptorDataSize; + size_t imageViewCaptureReplayDescriptorDataSize; + size_t samplerCaptureReplayDescriptorDataSize; + size_t accelerationStructureCaptureReplayDescriptorDataSize; + size_t samplerDescriptorSize; + size_t combinedImageSamplerDescriptorSize; + size_t sampledImageDescriptorSize; + size_t storageImageDescriptorSize; + size_t uniformTexelBufferDescriptorSize; + size_t robustUniformTexelBufferDescriptorSize; + size_t storageTexelBufferDescriptorSize; + size_t robustStorageTexelBufferDescriptorSize; + size_t uniformBufferDescriptorSize; + size_t robustUniformBufferDescriptorSize; + size_t storageBufferDescriptorSize; + size_t robustStorageBufferDescriptorSize; + size_t inputAttachmentDescriptorSize; + size_t accelerationStructureDescriptorSize; + VkDeviceSize maxSamplerDescriptorBufferRange; + VkDeviceSize maxResourceDescriptorBufferRange; + VkDeviceSize samplerDescriptorBufferAddressSpaceSize; + VkDeviceSize resourceDescriptorBufferAddressSpaceSize; + VkDeviceSize descriptorBufferAddressSpaceSize; +} VkPhysicalDeviceDescriptorBufferPropertiesEXT; + +typedef struct VkPhysicalDeviceDescriptorBufferFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 descriptorBuffer; + VkBool32 descriptorBufferCaptureReplay; + VkBool32 descriptorBufferImageLayoutIgnored; + VkBool32 descriptorBufferPushDescriptors; +} VkPhysicalDeviceDescriptorBufferFeaturesEXT; + +typedef struct VkDescriptorAddressInfoEXT { + VkStructureType sType; + void* pNext; + VkDeviceAddress address; + VkDeviceSize range; + VkFormat format; +} VkDescriptorAddressInfoEXT; + +typedef struct VkDescriptorBufferBindingInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddress address; + VkBufferUsageFlags usage; +} VkDescriptorBufferBindingInfoEXT; + +typedef struct VkDescriptorBufferBindingPushDescriptorBufferHandleEXT { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; +} VkDescriptorBufferBindingPushDescriptorBufferHandleEXT; + +typedef union VkDescriptorDataEXT { + const VkSampler* pSampler; + const VkDescriptorImageInfo* pCombinedImageSampler; + const VkDescriptorImageInfo* pInputAttachmentImage; + const VkDescriptorImageInfo* pSampledImage; + const VkDescriptorImageInfo* pStorageImage; + const VkDescriptorAddressInfoEXT* pUniformTexelBuffer; + const VkDescriptorAddressInfoEXT* pStorageTexelBuffer; + const VkDescriptorAddressInfoEXT* pUniformBuffer; + const VkDescriptorAddressInfoEXT* pStorageBuffer; + VkDeviceAddress accelerationStructure; +} VkDescriptorDataEXT; + +typedef struct VkDescriptorGetInfoEXT { + VkStructureType sType; + const void* pNext; + VkDescriptorType type; + VkDescriptorDataEXT data; +} VkDescriptorGetInfoEXT; + +typedef struct VkBufferCaptureDescriptorDataInfoEXT { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; +} VkBufferCaptureDescriptorDataInfoEXT; + +typedef struct VkImageCaptureDescriptorDataInfoEXT { + VkStructureType sType; + const void* pNext; + VkImage image; +} VkImageCaptureDescriptorDataInfoEXT; + +typedef struct VkImageViewCaptureDescriptorDataInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageView imageView; +} VkImageViewCaptureDescriptorDataInfoEXT; + +typedef struct VkSamplerCaptureDescriptorDataInfoEXT { + VkStructureType sType; + const void* pNext; + VkSampler sampler; +} VkSamplerCaptureDescriptorDataInfoEXT; + +typedef struct VkOpaqueCaptureDescriptorDataCreateInfoEXT { + VkStructureType sType; + const void* pNext; + const void* opaqueCaptureDescriptorData; +} VkOpaqueCaptureDescriptorDataCreateInfoEXT; + +typedef struct VkAccelerationStructureCaptureDescriptorDataInfoEXT { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR accelerationStructure; + VkAccelerationStructureNV accelerationStructureNV; +} VkAccelerationStructureCaptureDescriptorDataInfoEXT; + +typedef struct VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT { + VkStructureType sType; + void* pNext; + size_t combinedImageSamplerDensityMapDescriptorSize; +} VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT; + +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSizeEXT)(VkDevice device, VkDescriptorSetLayout layout, VkDeviceSize* pLayoutSizeInBytes); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutBindingOffsetEXT)(VkDevice device, VkDescriptorSetLayout layout, uint32_t binding, VkDeviceSize* pOffset); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorEXT)(VkDevice device, const VkDescriptorGetInfoEXT* pDescriptorInfo, size_t dataSize, void* pDescriptor); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t bufferCount, const VkDescriptorBufferBindingInfoEXT* pBindingInfos); +typedef void (VKAPI_PTR *PFN_vkCmdSetDescriptorBufferOffsetsEXT)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const uint32_t* pBufferIndices, const VkDeviceSize* pOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set); +typedef VkResult (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkBufferCaptureDescriptorDataInfoEXT* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkImageCaptureDescriptorDataInfoEXT* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkImageViewCaptureDescriptorDataInfoEXT* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkSamplerCaptureDescriptorDataInfoEXT* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkAccelerationStructureCaptureDescriptorDataInfoEXT* pInfo, void* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSizeEXT( + VkDevice device, + VkDescriptorSetLayout layout, + VkDeviceSize* pLayoutSizeInBytes); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutBindingOffsetEXT( + VkDevice device, + VkDescriptorSetLayout layout, + uint32_t binding, + VkDeviceSize* pOffset); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorEXT( + VkDevice device, + const VkDescriptorGetInfoEXT* pDescriptorInfo, + size_t dataSize, + void* pDescriptor); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorBuffersEXT( + VkCommandBuffer commandBuffer, + uint32_t bufferCount, + const VkDescriptorBufferBindingInfoEXT* pBindingInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDescriptorBufferOffsetsEXT( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t firstSet, + uint32_t setCount, + const uint32_t* pBufferIndices, + const VkDeviceSize* pOffsets); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorBufferEmbeddedSamplersEXT( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferOpaqueCaptureDescriptorDataEXT( + VkDevice device, + const VkBufferCaptureDescriptorDataInfoEXT* pInfo, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageOpaqueCaptureDescriptorDataEXT( + VkDevice device, + const VkImageCaptureDescriptorDataInfoEXT* pInfo, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewOpaqueCaptureDescriptorDataEXT( + VkDevice device, + const VkImageViewCaptureDescriptorDataInfoEXT* pInfo, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSamplerOpaqueCaptureDescriptorDataEXT( + VkDevice device, + const VkSamplerCaptureDescriptorDataInfoEXT* pInfo, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT( + VkDevice device, + const VkAccelerationStructureCaptureDescriptorDataInfoEXT* pInfo, + void* pData); +#endif +#endif + + +// VK_EXT_graphics_pipeline_library is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_graphics_pipeline_library 1 +#define VK_EXT_GRAPHICS_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME "VK_EXT_graphics_pipeline_library" + +typedef enum VkGraphicsPipelineLibraryFlagBitsEXT { + VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT = 0x00000001, + VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT = 0x00000002, + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT = 0x00000004, + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT = 0x00000008, + VK_GRAPHICS_PIPELINE_LIBRARY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkGraphicsPipelineLibraryFlagBitsEXT; +typedef VkFlags VkGraphicsPipelineLibraryFlagsEXT; +typedef struct VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 graphicsPipelineLibrary; +} VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT; + +typedef struct VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 graphicsPipelineLibraryFastLinking; + VkBool32 graphicsPipelineLibraryIndependentInterpolationDecoration; +} VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT; + +typedef struct VkGraphicsPipelineLibraryCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkGraphicsPipelineLibraryFlagsEXT flags; +} VkGraphicsPipelineLibraryCreateInfoEXT; + + + +// VK_AMD_shader_early_and_late_fragment_tests is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_shader_early_and_late_fragment_tests 1 +#define VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_SPEC_VERSION 1 +#define VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_EXTENSION_NAME "VK_AMD_shader_early_and_late_fragment_tests" +typedef struct VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD { + VkStructureType sType; + void* pNext; + VkBool32 shaderEarlyAndLateFragmentTests; +} VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD; + + + +// VK_NV_fragment_shading_rate_enums is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_fragment_shading_rate_enums 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME "VK_NV_fragment_shading_rate_enums" + +typedef enum VkFragmentShadingRateTypeNV { + VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0, + VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1, + VK_FRAGMENT_SHADING_RATE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateTypeNV; + +typedef enum VkFragmentShadingRateNV { + 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, + VK_FRAGMENT_SHADING_RATE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateNV; +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShadingRateEnums; + VkBool32 supersampleFragmentShadingRates; + VkBool32 noInvocationFragmentShadingRates; +} VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV; + +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV { + VkStructureType sType; + void* pNext; + VkSampleCountFlagBits maxFragmentShadingRateInvocationCount; +} VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV; + +typedef struct VkPipelineFragmentShadingRateEnumStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkFragmentShadingRateTypeNV shadingRateType; + VkFragmentShadingRateNV shadingRate; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateEnumStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateEnumNV)(VkCommandBuffer commandBuffer, VkFragmentShadingRateNV shadingRate, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateEnumNV( + VkCommandBuffer commandBuffer, + VkFragmentShadingRateNV shadingRate, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif +#endif + + +// VK_NV_ray_tracing_motion_blur is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_ray_tracing_motion_blur 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME "VK_NV_ray_tracing_motion_blur" + +typedef enum VkAccelerationStructureMotionInstanceTypeNV { + 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, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMotionInstanceTypeNV; +typedef VkFlags VkAccelerationStructureMotionInfoFlagsNV; +typedef VkFlags VkAccelerationStructureMotionInstanceFlagsNV; +typedef union VkDeviceOrHostAddressConstKHR { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstKHR; + +typedef struct VkAccelerationStructureGeometryMotionTrianglesDataNV { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR vertexData; +} VkAccelerationStructureGeometryMotionTrianglesDataNV; + +typedef struct VkAccelerationStructureMotionInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t maxInstances; + VkAccelerationStructureMotionInfoFlagsNV flags; +} VkAccelerationStructureMotionInfoNV; + +typedef struct VkAccelerationStructureMatrixMotionInstanceNV { + VkTransformMatrixKHR transformT0; + VkTransformMatrixKHR transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureMatrixMotionInstanceNV; + +typedef struct VkSRTDataNV { + float sx; + float a; + float b; + float pvx; + float sy; + float c; + float pvy; + float sz; + float pvz; + float qx; + float qy; + float qz; + float qw; + float tx; + float ty; + float tz; +} VkSRTDataNV; + +typedef struct VkAccelerationStructureSRTMotionInstanceNV { + VkSRTDataNV transformT0; + VkSRTDataNV transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureSRTMotionInstanceNV; + +typedef union VkAccelerationStructureMotionInstanceDataNV { + VkAccelerationStructureInstanceKHR staticInstance; + VkAccelerationStructureMatrixMotionInstanceNV matrixMotionInstance; + VkAccelerationStructureSRTMotionInstanceNV srtMotionInstance; +} VkAccelerationStructureMotionInstanceDataNV; + +typedef struct VkAccelerationStructureMotionInstanceNV { + VkAccelerationStructureMotionInstanceTypeNV type; + VkAccelerationStructureMotionInstanceFlagsNV flags; + VkAccelerationStructureMotionInstanceDataNV data; +} VkAccelerationStructureMotionInstanceNV; + +typedef struct VkPhysicalDeviceRayTracingMotionBlurFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingMotionBlur; + VkBool32 rayTracingMotionBlurPipelineTraceRaysIndirect; +} VkPhysicalDeviceRayTracingMotionBlurFeaturesNV; + + + +// VK_EXT_ycbcr_2plane_444_formats is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_ycbcr_2plane_444_formats 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME "VK_EXT_ycbcr_2plane_444_formats" +typedef struct VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 ycbcr2plane444Formats; +} VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT; + + + +// VK_EXT_fragment_density_map2 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_fragment_density_map2 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME "VK_EXT_fragment_density_map2" +typedef struct VkPhysicalDeviceFragmentDensityMap2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapDeferred; +} VkPhysicalDeviceFragmentDensityMap2FeaturesEXT; + +typedef struct VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 subsampledLoads; + VkBool32 subsampledCoarseReconstructionEarlyAccess; + uint32_t maxSubsampledArrayLayers; + uint32_t maxDescriptorSetSubsampledSamplers; +} VkPhysicalDeviceFragmentDensityMap2PropertiesEXT; + + + +// VK_QCOM_rotated_copy_commands is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_rotated_copy_commands 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION 2 +#define VK_QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME "VK_QCOM_rotated_copy_commands" +typedef struct VkCopyCommandTransformInfoQCOM { + VkStructureType sType; + const void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkCopyCommandTransformInfoQCOM; + + + +// VK_EXT_image_robustness is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_robustness 1 +#define VK_EXT_IMAGE_ROBUSTNESS_SPEC_VERSION 1 +#define VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_image_robustness" +typedef VkPhysicalDeviceImageRobustnessFeatures VkPhysicalDeviceImageRobustnessFeaturesEXT; + + + +// VK_EXT_image_compression_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_compression_control 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_SPEC_VERSION 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME "VK_EXT_image_compression_control" + +typedef enum VkImageCompressionFlagBitsEXT { + VK_IMAGE_COMPRESSION_DEFAULT_EXT = 0, + VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT = 0x00000001, + VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT = 0x00000002, + VK_IMAGE_COMPRESSION_DISABLED_EXT = 0x00000004, + VK_IMAGE_COMPRESSION_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkImageCompressionFlagBitsEXT; +typedef VkFlags VkImageCompressionFlagsEXT; + +typedef enum VkImageCompressionFixedRateFlagBitsEXT { + VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT = 0, + VK_IMAGE_COMPRESSION_FIXED_RATE_1BPC_BIT_EXT = 0x00000001, + VK_IMAGE_COMPRESSION_FIXED_RATE_2BPC_BIT_EXT = 0x00000002, + VK_IMAGE_COMPRESSION_FIXED_RATE_3BPC_BIT_EXT = 0x00000004, + VK_IMAGE_COMPRESSION_FIXED_RATE_4BPC_BIT_EXT = 0x00000008, + VK_IMAGE_COMPRESSION_FIXED_RATE_5BPC_BIT_EXT = 0x00000010, + VK_IMAGE_COMPRESSION_FIXED_RATE_6BPC_BIT_EXT = 0x00000020, + VK_IMAGE_COMPRESSION_FIXED_RATE_7BPC_BIT_EXT = 0x00000040, + VK_IMAGE_COMPRESSION_FIXED_RATE_8BPC_BIT_EXT = 0x00000080, + VK_IMAGE_COMPRESSION_FIXED_RATE_9BPC_BIT_EXT = 0x00000100, + VK_IMAGE_COMPRESSION_FIXED_RATE_10BPC_BIT_EXT = 0x00000200, + VK_IMAGE_COMPRESSION_FIXED_RATE_11BPC_BIT_EXT = 0x00000400, + VK_IMAGE_COMPRESSION_FIXED_RATE_12BPC_BIT_EXT = 0x00000800, + VK_IMAGE_COMPRESSION_FIXED_RATE_13BPC_BIT_EXT = 0x00001000, + VK_IMAGE_COMPRESSION_FIXED_RATE_14BPC_BIT_EXT = 0x00002000, + VK_IMAGE_COMPRESSION_FIXED_RATE_15BPC_BIT_EXT = 0x00004000, + VK_IMAGE_COMPRESSION_FIXED_RATE_16BPC_BIT_EXT = 0x00008000, + VK_IMAGE_COMPRESSION_FIXED_RATE_17BPC_BIT_EXT = 0x00010000, + VK_IMAGE_COMPRESSION_FIXED_RATE_18BPC_BIT_EXT = 0x00020000, + VK_IMAGE_COMPRESSION_FIXED_RATE_19BPC_BIT_EXT = 0x00040000, + VK_IMAGE_COMPRESSION_FIXED_RATE_20BPC_BIT_EXT = 0x00080000, + VK_IMAGE_COMPRESSION_FIXED_RATE_21BPC_BIT_EXT = 0x00100000, + VK_IMAGE_COMPRESSION_FIXED_RATE_22BPC_BIT_EXT = 0x00200000, + VK_IMAGE_COMPRESSION_FIXED_RATE_23BPC_BIT_EXT = 0x00400000, + VK_IMAGE_COMPRESSION_FIXED_RATE_24BPC_BIT_EXT = 0x00800000, + VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkImageCompressionFixedRateFlagBitsEXT; +typedef VkFlags VkImageCompressionFixedRateFlagsEXT; +typedef struct VkPhysicalDeviceImageCompressionControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 imageCompressionControl; +} VkPhysicalDeviceImageCompressionControlFeaturesEXT; + +typedef struct VkImageCompressionControlEXT { + VkStructureType sType; + const void* pNext; + VkImageCompressionFlagsEXT flags; + uint32_t compressionControlPlaneCount; + VkImageCompressionFixedRateFlagsEXT* pFixedRateFlags; +} VkImageCompressionControlEXT; + +typedef struct VkImageCompressionPropertiesEXT { + VkStructureType sType; + void* pNext; + VkImageCompressionFlagsEXT imageCompressionFlags; + VkImageCompressionFixedRateFlagsEXT imageCompressionFixedRateFlags; +} VkImageCompressionPropertiesEXT; + + + +// VK_EXT_attachment_feedback_loop_layout is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_attachment_feedback_loop_layout 1 +#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_SPEC_VERSION 2 +#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME "VK_EXT_attachment_feedback_loop_layout" +typedef struct VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 attachmentFeedbackLoopLayout; +} VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT; + + + +// VK_EXT_4444_formats is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_4444_formats 1 +#define VK_EXT_4444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_4444_FORMATS_EXTENSION_NAME "VK_EXT_4444_formats" +typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 formatA4R4G4B4; + VkBool32 formatA4B4G4R4; +} VkPhysicalDevice4444FormatsFeaturesEXT; + + + +// VK_EXT_device_fault is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_device_fault 1 +#define VK_EXT_DEVICE_FAULT_SPEC_VERSION 2 +#define VK_EXT_DEVICE_FAULT_EXTENSION_NAME "VK_EXT_device_fault" +typedef VkDeviceFaultAddressTypeKHR VkDeviceFaultAddressTypeEXT; + +typedef VkDeviceFaultVendorBinaryHeaderVersionKHR VkDeviceFaultVendorBinaryHeaderVersionEXT; + +typedef struct VkPhysicalDeviceFaultFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 deviceFault; + VkBool32 deviceFaultVendorBinary; +} VkPhysicalDeviceFaultFeaturesEXT; + +typedef struct VkDeviceFaultCountsEXT { + VkStructureType sType; + void* pNext; + uint32_t addressInfoCount; + uint32_t vendorInfoCount; + VkDeviceSize vendorBinarySize; +} VkDeviceFaultCountsEXT; + +typedef struct VkDeviceFaultInfoEXT { + VkStructureType sType; + void* pNext; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkDeviceFaultAddressInfoKHR* pAddressInfos; + VkDeviceFaultVendorInfoKHR* pVendorInfos; + void* pVendorBinaryData; +} VkDeviceFaultInfoEXT; + +typedef VkDeviceFaultAddressInfoKHR VkDeviceFaultAddressInfoEXT; + +typedef VkDeviceFaultVendorInfoKHR VkDeviceFaultVendorInfoEXT; + +typedef VkDeviceFaultVendorBinaryHeaderVersionOneKHR VkDeviceFaultVendorBinaryHeaderVersionOneEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceFaultInfoEXT)(VkDevice device, VkDeviceFaultCountsEXT* pFaultCounts, VkDeviceFaultInfoEXT* pFaultInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceFaultInfoEXT( + VkDevice device, + VkDeviceFaultCountsEXT* pFaultCounts, + VkDeviceFaultInfoEXT* pFaultInfo); +#endif +#endif + + +// VK_ARM_rasterization_order_attachment_access is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_rasterization_order_attachment_access 1 +#define VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION 1 +#define VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME "VK_ARM_rasterization_order_attachment_access" +typedef struct VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 rasterizationOrderColorAttachmentAccess; + VkBool32 rasterizationOrderDepthAttachmentAccess; + VkBool32 rasterizationOrderStencilAttachmentAccess; +} VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT; + +typedef VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM; + + + +// VK_EXT_rgba10x6_formats is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_rgba10x6_formats 1 +#define VK_EXT_RGBA10X6_FORMATS_SPEC_VERSION 1 +#define VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME "VK_EXT_rgba10x6_formats" +typedef struct VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 formatRgba10x6WithoutYCbCrSampler; +} VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT; + + + +// VK_VALVE_mutable_descriptor_type is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_mutable_descriptor_type 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_VALVE_mutable_descriptor_type" +typedef struct VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 mutableDescriptorType; +} VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT; + +typedef VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE; + +typedef struct VkMutableDescriptorTypeListEXT { + uint32_t descriptorTypeCount; + const VkDescriptorType* pDescriptorTypes; +} VkMutableDescriptorTypeListEXT; + +typedef VkMutableDescriptorTypeListEXT VkMutableDescriptorTypeListVALVE; + +typedef struct VkMutableDescriptorTypeCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t mutableDescriptorTypeListCount; + const VkMutableDescriptorTypeListEXT* pMutableDescriptorTypeLists; +} VkMutableDescriptorTypeCreateInfoEXT; + +typedef VkMutableDescriptorTypeCreateInfoEXT VkMutableDescriptorTypeCreateInfoVALVE; + + + +// VK_EXT_vertex_input_dynamic_state is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_vertex_input_dynamic_state 1 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION 2 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_vertex_input_dynamic_state" +typedef struct VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 vertexInputDynamicState; +} VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT; + +typedef struct VkVertexInputBindingDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t binding; + uint32_t stride; + VkVertexInputRate inputRate; + uint32_t divisor; +} VkVertexInputBindingDescription2EXT; + +typedef struct VkVertexInputAttributeDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; +} VkVertexInputAttributeDescription2EXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetVertexInputEXT)(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT( + VkCommandBuffer commandBuffer, + uint32_t vertexBindingDescriptionCount, + const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, + uint32_t vertexAttributeDescriptionCount, + const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); +#endif +#endif + + +// VK_EXT_physical_device_drm is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_physical_device_drm 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME "VK_EXT_physical_device_drm" +typedef struct VkPhysicalDeviceDrmPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 hasPrimary; + VkBool32 hasRender; + int64_t primaryMajor; + int64_t primaryMinor; + int64_t renderMajor; + int64_t renderMinor; +} VkPhysicalDeviceDrmPropertiesEXT; + + + +// VK_EXT_device_address_binding_report is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_device_address_binding_report 1 +#define VK_EXT_DEVICE_ADDRESS_BINDING_REPORT_SPEC_VERSION 1 +#define VK_EXT_DEVICE_ADDRESS_BINDING_REPORT_EXTENSION_NAME "VK_EXT_device_address_binding_report" + +typedef enum VkDeviceAddressBindingTypeEXT { + VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT = 0, + VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT = 1, + VK_DEVICE_ADDRESS_BINDING_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceAddressBindingTypeEXT; + +typedef enum VkDeviceAddressBindingFlagBitsEXT { + VK_DEVICE_ADDRESS_BINDING_INTERNAL_OBJECT_BIT_EXT = 0x00000001, + VK_DEVICE_ADDRESS_BINDING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceAddressBindingFlagBitsEXT; +typedef VkFlags VkDeviceAddressBindingFlagsEXT; +typedef struct VkPhysicalDeviceAddressBindingReportFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 reportAddressBinding; +} VkPhysicalDeviceAddressBindingReportFeaturesEXT; + +typedef struct VkDeviceAddressBindingCallbackDataEXT { + VkStructureType sType; + void* pNext; + VkDeviceAddressBindingFlagsEXT flags; + VkDeviceAddress baseAddress; + VkDeviceSize size; + VkDeviceAddressBindingTypeEXT bindingType; +} VkDeviceAddressBindingCallbackDataEXT; + + + +// VK_EXT_depth_clip_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_clip_control 1 +#define VK_EXT_DEPTH_CLIP_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME "VK_EXT_depth_clip_control" +typedef struct VkPhysicalDeviceDepthClipControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 depthClipControl; +} VkPhysicalDeviceDepthClipControlFeaturesEXT; + +typedef struct VkPipelineViewportDepthClipControlCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 negativeOneToOne; +} VkPipelineViewportDepthClipControlCreateInfoEXT; + + + +// VK_EXT_primitive_topology_list_restart is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_primitive_topology_list_restart 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME "VK_EXT_primitive_topology_list_restart" +typedef struct VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 primitiveTopologyListRestart; + VkBool32 primitiveTopologyPatchListRestart; +} VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT; + + + +// VK_EXT_present_mode_fifo_latest_ready is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_present_mode_fifo_latest_ready 1 +#define VK_EXT_PRESENT_MODE_FIFO_LATEST_READY_SPEC_VERSION 1 +#define VK_EXT_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME "VK_EXT_present_mode_fifo_latest_ready" +typedef VkPhysicalDevicePresentModeFifoLatestReadyFeaturesKHR VkPhysicalDevicePresentModeFifoLatestReadyFeaturesEXT; + + + +// VK_HUAWEI_subpass_shading is a preprocessor guard. Do not pass it to API calls. +#define VK_HUAWEI_subpass_shading 1 +#define VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION 3 +#define VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME "VK_HUAWEI_subpass_shading" +typedef struct VkSubpassShadingPipelineCreateInfoHUAWEI { + VkStructureType sType; + void* pNext; + VkRenderPass renderPass; + uint32_t subpass; +} VkSubpassShadingPipelineCreateInfoHUAWEI; + +typedef struct VkPhysicalDeviceSubpassShadingFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 subpassShading; +} VkPhysicalDeviceSubpassShadingFeaturesHUAWEI; + +typedef struct VkPhysicalDeviceSubpassShadingPropertiesHUAWEI { + VkStructureType sType; + void* pNext; + uint32_t maxSubpassShadingWorkgroupSizeAspectRatio; +} VkPhysicalDeviceSubpassShadingPropertiesHUAWEI; + +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)(VkDevice device, VkRenderPass renderpass, VkExtent2D* pMaxWorkgroupSize); +typedef void (VKAPI_PTR *PFN_vkCmdSubpassShadingHUAWEI)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI( + VkDevice device, + VkRenderPass renderpass, + VkExtent2D* pMaxWorkgroupSize); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSubpassShadingHUAWEI( + VkCommandBuffer commandBuffer); +#endif +#endif + + +// VK_HUAWEI_invocation_mask is a preprocessor guard. Do not pass it to API calls. +#define VK_HUAWEI_invocation_mask 1 +#define VK_HUAWEI_INVOCATION_MASK_SPEC_VERSION 1 +#define VK_HUAWEI_INVOCATION_MASK_EXTENSION_NAME "VK_HUAWEI_invocation_mask" +typedef struct VkPhysicalDeviceInvocationMaskFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 invocationMask; +} VkPhysicalDeviceInvocationMaskFeaturesHUAWEI; + +typedef void (VKAPI_PTR *PFN_vkCmdBindInvocationMaskHUAWEI)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindInvocationMaskHUAWEI( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); +#endif +#endif + + +// VK_NV_external_memory_rdma is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_external_memory_rdma 1 +typedef void* VkRemoteAddressNV; +#define VK_NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_RDMA_EXTENSION_NAME "VK_NV_external_memory_rdma" +typedef struct VkMemoryGetRemoteAddressInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetRemoteAddressInfoNV; + +typedef struct VkPhysicalDeviceExternalMemoryRDMAFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 externalMemoryRDMA; +} VkPhysicalDeviceExternalMemoryRDMAFeaturesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryRemoteAddressNV)(VkDevice device, const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, VkRemoteAddressNV* pAddress); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryRemoteAddressNV( + VkDevice device, + const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, + VkRemoteAddressNV* pAddress); +#endif +#endif + + +// VK_EXT_pipeline_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_properties 1 +#define VK_EXT_PIPELINE_PROPERTIES_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_PROPERTIES_EXTENSION_NAME "VK_EXT_pipeline_properties" +typedef VkPipelineInfoKHR VkPipelineInfoEXT; + +typedef struct VkPipelinePropertiesIdentifierEXT { + VkStructureType sType; + void* pNext; + uint8_t pipelineIdentifier[VK_UUID_SIZE]; +} VkPipelinePropertiesIdentifierEXT; + +typedef struct VkPhysicalDevicePipelinePropertiesFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pipelinePropertiesIdentifier; +} VkPhysicalDevicePipelinePropertiesFeaturesEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelinePropertiesEXT)(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, VkBaseOutStructure* pPipelineProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelinePropertiesEXT( + VkDevice device, + const VkPipelineInfoKHR* pPipelineInfo, + VkBaseOutStructure* pPipelineProperties); +#endif +#endif + + +// VK_EXT_frame_boundary is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_frame_boundary 1 +#define VK_EXT_FRAME_BOUNDARY_SPEC_VERSION 1 +#define VK_EXT_FRAME_BOUNDARY_EXTENSION_NAME "VK_EXT_frame_boundary" + +typedef enum VkFrameBoundaryFlagBitsEXT { + VK_FRAME_BOUNDARY_FRAME_END_BIT_EXT = 0x00000001, + VK_FRAME_BOUNDARY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkFrameBoundaryFlagBitsEXT; +typedef VkFlags VkFrameBoundaryFlagsEXT; +typedef struct VkPhysicalDeviceFrameBoundaryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 frameBoundary; +} VkPhysicalDeviceFrameBoundaryFeaturesEXT; + +typedef struct VkFrameBoundaryEXT { + VkStructureType sType; + const void* pNext; + VkFrameBoundaryFlagsEXT flags; + uint64_t frameID; + uint32_t imageCount; + const VkImage* pImages; + uint32_t bufferCount; + const VkBuffer* pBuffers; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkFrameBoundaryEXT; + + + +// VK_EXT_multisampled_render_to_single_sampled is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_multisampled_render_to_single_sampled 1 +#define VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_SPEC_VERSION 1 +#define VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME "VK_EXT_multisampled_render_to_single_sampled" +typedef struct VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 multisampledRenderToSingleSampled; +} VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT; + +typedef struct VkSubpassResolvePerformanceQueryEXT { + VkStructureType sType; + void* pNext; + VkBool32 optimal; +} VkSubpassResolvePerformanceQueryEXT; + +typedef struct VkMultisampledRenderToSingleSampledInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 multisampledRenderToSingleSampledEnable; + VkSampleCountFlagBits rasterizationSamples; +} VkMultisampledRenderToSingleSampledInfoEXT; + + + +// VK_EXT_extended_dynamic_state2 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_extended_dynamic_state2 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME "VK_EXT_extended_dynamic_state2" +typedef struct VkPhysicalDeviceExtendedDynamicState2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState2; + VkBool32 extendedDynamicState2LogicOp; + VkBool32 extendedDynamicState2PatchControlPoints; +} VkPhysicalDeviceExtendedDynamicState2FeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetPatchControlPointsEXT)(VkCommandBuffer commandBuffer, uint32_t patchControlPoints); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetLogicOpEXT)(VkCommandBuffer commandBuffer, VkLogicOp logicOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPatchControlPointsEXT( + VkCommandBuffer commandBuffer, + uint32_t patchControlPoints); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 rasterizerDiscardEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBiasEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEXT( + VkCommandBuffer commandBuffer, + VkLogicOp logicOp); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 primitiveRestartEnable); +#endif +#endif + + +// VK_EXT_color_write_enable is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_color_write_enable 1 +#define VK_EXT_COLOR_WRITE_ENABLE_SPEC_VERSION 1 +#define VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME "VK_EXT_color_write_enable" +typedef struct VkPhysicalDeviceColorWriteEnableFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 colorWriteEnable; +} VkPhysicalDeviceColorWriteEnableFeaturesEXT; + +typedef struct VkPipelineColorWriteCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t attachmentCount; + const VkBool32* pColorWriteEnables; +} VkPipelineColorWriteCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteEnableEXT)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkBool32* pColorWriteEnables); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteEnableEXT( + VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkBool32* pColorWriteEnables); +#endif +#endif + + +// VK_EXT_primitives_generated_query is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_primitives_generated_query 1 +#define VK_EXT_PRIMITIVES_GENERATED_QUERY_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME "VK_EXT_primitives_generated_query" +typedef struct VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 primitivesGeneratedQuery; + VkBool32 primitivesGeneratedQueryWithRasterizerDiscard; + VkBool32 primitivesGeneratedQueryWithNonZeroStreams; +} VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT; + + + +// VK_EXT_global_priority_query is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_global_priority_query 1 +#define VK_EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION 1 +#define VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME "VK_EXT_global_priority_query" +#define VK_MAX_GLOBAL_PRIORITY_SIZE_EXT VK_MAX_GLOBAL_PRIORITY_SIZE +typedef VkPhysicalDeviceGlobalPriorityQueryFeatures VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT; + +typedef VkQueueFamilyGlobalPriorityProperties VkQueueFamilyGlobalPriorityPropertiesEXT; + + + +// VK_VALVE_video_encode_rgb_conversion is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_video_encode_rgb_conversion 1 +#define VK_VALVE_VIDEO_ENCODE_RGB_CONVERSION_SPEC_VERSION 1 +#define VK_VALVE_VIDEO_ENCODE_RGB_CONVERSION_EXTENSION_NAME "VK_VALVE_video_encode_rgb_conversion" + +typedef enum VkVideoEncodeRgbModelConversionFlagBitsVALVE { + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_RGB_IDENTITY_BIT_VALVE = 0x00000001, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_IDENTITY_BIT_VALVE = 0x00000002, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_709_BIT_VALVE = 0x00000004, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_601_BIT_VALVE = 0x00000008, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_2020_BIT_VALVE = 0x00000010, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_FLAG_BITS_MAX_ENUM_VALVE = 0x7FFFFFFF +} VkVideoEncodeRgbModelConversionFlagBitsVALVE; +typedef VkFlags VkVideoEncodeRgbModelConversionFlagsVALVE; + +typedef enum VkVideoEncodeRgbRangeCompressionFlagBitsVALVE { + VK_VIDEO_ENCODE_RGB_RANGE_COMPRESSION_FULL_RANGE_BIT_VALVE = 0x00000001, + VK_VIDEO_ENCODE_RGB_RANGE_COMPRESSION_NARROW_RANGE_BIT_VALVE = 0x00000002, + VK_VIDEO_ENCODE_RGB_RANGE_COMPRESSION_FLAG_BITS_MAX_ENUM_VALVE = 0x7FFFFFFF +} VkVideoEncodeRgbRangeCompressionFlagBitsVALVE; +typedef VkFlags VkVideoEncodeRgbRangeCompressionFlagsVALVE; + +typedef enum VkVideoEncodeRgbChromaOffsetFlagBitsVALVE { + VK_VIDEO_ENCODE_RGB_CHROMA_OFFSET_COSITED_EVEN_BIT_VALVE = 0x00000001, + VK_VIDEO_ENCODE_RGB_CHROMA_OFFSET_MIDPOINT_BIT_VALVE = 0x00000002, + VK_VIDEO_ENCODE_RGB_CHROMA_OFFSET_FLAG_BITS_MAX_ENUM_VALVE = 0x7FFFFFFF +} VkVideoEncodeRgbChromaOffsetFlagBitsVALVE; +typedef VkFlags VkVideoEncodeRgbChromaOffsetFlagsVALVE; +typedef struct VkPhysicalDeviceVideoEncodeRgbConversionFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 videoEncodeRgbConversion; +} VkPhysicalDeviceVideoEncodeRgbConversionFeaturesVALVE; + +typedef struct VkVideoEncodeRgbConversionCapabilitiesVALVE { + VkStructureType sType; + void* pNext; + VkVideoEncodeRgbModelConversionFlagsVALVE rgbModels; + VkVideoEncodeRgbRangeCompressionFlagsVALVE rgbRanges; + VkVideoEncodeRgbChromaOffsetFlagsVALVE xChromaOffsets; + VkVideoEncodeRgbChromaOffsetFlagsVALVE yChromaOffsets; +} VkVideoEncodeRgbConversionCapabilitiesVALVE; + +typedef struct VkVideoEncodeProfileRgbConversionInfoVALVE { + VkStructureType sType; + const void* pNext; + VkBool32 performEncodeRgbConversion; +} VkVideoEncodeProfileRgbConversionInfoVALVE; + +typedef struct VkVideoEncodeSessionRgbConversionCreateInfoVALVE { + VkStructureType sType; + const void* pNext; + VkVideoEncodeRgbModelConversionFlagBitsVALVE rgbModel; + VkVideoEncodeRgbRangeCompressionFlagBitsVALVE rgbRange; + VkVideoEncodeRgbChromaOffsetFlagBitsVALVE xChromaOffset; + VkVideoEncodeRgbChromaOffsetFlagBitsVALVE yChromaOffset; +} VkVideoEncodeSessionRgbConversionCreateInfoVALVE; + + + +// VK_EXT_image_view_min_lod is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_view_min_lod 1 +#define VK_EXT_IMAGE_VIEW_MIN_LOD_SPEC_VERSION 1 +#define VK_EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME "VK_EXT_image_view_min_lod" +typedef struct VkPhysicalDeviceImageViewMinLodFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 minLod; +} VkPhysicalDeviceImageViewMinLodFeaturesEXT; + +typedef struct VkImageViewMinLodCreateInfoEXT { + VkStructureType sType; + const void* pNext; + float minLod; +} VkImageViewMinLodCreateInfoEXT; + + + +// VK_EXT_multi_draw is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_multi_draw 1 +#define VK_EXT_MULTI_DRAW_SPEC_VERSION 1 +#define VK_EXT_MULTI_DRAW_EXTENSION_NAME "VK_EXT_multi_draw" +typedef struct VkPhysicalDeviceMultiDrawFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 multiDraw; +} VkPhysicalDeviceMultiDrawFeaturesEXT; + +typedef struct VkPhysicalDeviceMultiDrawPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxMultiDrawCount; +} VkPhysicalDeviceMultiDrawPropertiesEXT; + +typedef struct VkMultiDrawInfoEXT { + uint32_t firstVertex; + uint32_t vertexCount; +} VkMultiDrawInfoEXT; + +typedef struct VkMultiDrawIndexedInfoEXT { + uint32_t firstIndex; + uint32_t indexCount; + int32_t vertexOffset; +} VkMultiDrawIndexedInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawInfoEXT* pVertexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiIndexedEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawInfoEXT* pVertexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiIndexedEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawIndexedInfoEXT* pIndexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride, + const int32_t* pVertexOffset); +#endif +#endif + + +// VK_EXT_image_2d_view_of_3d is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_2d_view_of_3d 1 +#define VK_EXT_IMAGE_2D_VIEW_OF_3D_SPEC_VERSION 1 +#define VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME "VK_EXT_image_2d_view_of_3d" +typedef struct VkPhysicalDeviceImage2DViewOf3DFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 image2DViewOf3D; + VkBool32 sampler2DViewOf3D; +} VkPhysicalDeviceImage2DViewOf3DFeaturesEXT; + + + +// VK_EXT_shader_tile_image is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_tile_image 1 +#define VK_EXT_SHADER_TILE_IMAGE_SPEC_VERSION 1 +#define VK_EXT_SHADER_TILE_IMAGE_EXTENSION_NAME "VK_EXT_shader_tile_image" +typedef struct VkPhysicalDeviceShaderTileImageFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderTileImageColorReadAccess; + VkBool32 shaderTileImageDepthReadAccess; + VkBool32 shaderTileImageStencilReadAccess; +} VkPhysicalDeviceShaderTileImageFeaturesEXT; + +typedef struct VkPhysicalDeviceShaderTileImagePropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderTileImageCoherentReadAccelerated; + VkBool32 shaderTileImageReadSampleFromPixelRateInvocation; + VkBool32 shaderTileImageReadFromHelperInvocation; +} VkPhysicalDeviceShaderTileImagePropertiesEXT; + + + +// VK_EXT_opacity_micromap is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_opacity_micromap 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkMicromapEXT) +#define VK_EXT_OPACITY_MICROMAP_SPEC_VERSION 2 +#define VK_EXT_OPACITY_MICROMAP_EXTENSION_NAME "VK_EXT_opacity_micromap" + +typedef enum VkMicromapTypeEXT { + VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT = 0, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_MICROMAP_TYPE_DISPLACEMENT_MICROMAP_NV = 1000397000, +#endif + VK_MICROMAP_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkMicromapTypeEXT; + +typedef enum VkBuildMicromapModeEXT { + VK_BUILD_MICROMAP_MODE_BUILD_EXT = 0, + VK_BUILD_MICROMAP_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkBuildMicromapModeEXT; + +typedef enum VkCopyMicromapModeEXT { + 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, + VK_COPY_MICROMAP_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkCopyMicromapModeEXT; +typedef VkOpacityMicromapFormatKHR VkOpacityMicromapFormatEXT; + +typedef VkOpacityMicromapSpecialIndexKHR VkOpacityMicromapSpecialIndexEXT; + + +typedef enum VkAccelerationStructureCompatibilityKHR { + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCompatibilityKHR; + +typedef enum VkAccelerationStructureBuildTypeKHR { + 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, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureBuildTypeKHR; + +typedef enum VkBuildMicromapFlagBitsEXT { + VK_BUILD_MICROMAP_PREFER_FAST_TRACE_BIT_EXT = 0x00000001, + VK_BUILD_MICROMAP_PREFER_FAST_BUILD_BIT_EXT = 0x00000002, + VK_BUILD_MICROMAP_ALLOW_COMPACTION_BIT_EXT = 0x00000004, + VK_BUILD_MICROMAP_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkBuildMicromapFlagBitsEXT; +typedef VkFlags VkBuildMicromapFlagsEXT; + +typedef enum VkMicromapCreateFlagBitsEXT { + VK_MICROMAP_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT = 0x00000001, + VK_MICROMAP_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkMicromapCreateFlagBitsEXT; +typedef VkFlags VkMicromapCreateFlagsEXT; +typedef struct VkMicromapUsageEXT { + uint32_t count; + uint32_t subdivisionLevel; + uint32_t format; +} VkMicromapUsageEXT; + +typedef union VkDeviceOrHostAddressKHR { + VkDeviceAddress deviceAddress; + void* hostAddress; +} VkDeviceOrHostAddressKHR; + +typedef struct VkMicromapBuildInfoEXT { + VkStructureType sType; + const void* pNext; + VkMicromapTypeEXT type; + VkBuildMicromapFlagsEXT flags; + VkBuildMicromapModeEXT mode; + VkMicromapEXT dstMicromap; + uint32_t usageCountsCount; + const VkMicromapUsageEXT* pUsageCounts; + const VkMicromapUsageEXT* const* ppUsageCounts; + VkDeviceOrHostAddressConstKHR data; + VkDeviceOrHostAddressKHR scratchData; + VkDeviceOrHostAddressConstKHR triangleArray; + VkDeviceSize triangleArrayStride; +} VkMicromapBuildInfoEXT; + +typedef struct VkMicromapCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkMicromapCreateFlagsEXT createFlags; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; + VkMicromapTypeEXT type; + VkDeviceAddress deviceAddress; +} VkMicromapCreateInfoEXT; + +typedef struct VkPhysicalDeviceOpacityMicromapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 micromap; + VkBool32 micromapCaptureReplay; + VkBool32 micromapHostCommands; +} VkPhysicalDeviceOpacityMicromapFeaturesEXT; + +typedef struct VkPhysicalDeviceOpacityMicromapPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxOpacity2StateSubdivisionLevel; + uint32_t maxOpacity4StateSubdivisionLevel; +} VkPhysicalDeviceOpacityMicromapPropertiesEXT; + +typedef struct VkMicromapVersionInfoEXT { + VkStructureType sType; + const void* pNext; + const uint8_t* pVersionData; +} VkMicromapVersionInfoEXT; + +typedef struct VkCopyMicromapToMemoryInfoEXT { + VkStructureType sType; + const void* pNext; + VkMicromapEXT src; + VkDeviceOrHostAddressKHR dst; + VkCopyMicromapModeEXT mode; +} VkCopyMicromapToMemoryInfoEXT; + +typedef struct VkCopyMemoryToMicromapInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR src; + VkMicromapEXT dst; + VkCopyMicromapModeEXT mode; +} VkCopyMemoryToMicromapInfoEXT; + +typedef struct VkCopyMicromapInfoEXT { + VkStructureType sType; + const void* pNext; + VkMicromapEXT src; + VkMicromapEXT dst; + VkCopyMicromapModeEXT mode; +} VkCopyMicromapInfoEXT; + +typedef struct VkMicromapBuildSizesInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceSize micromapSize; + VkDeviceSize buildScratchSize; + VkBool32 discardable; +} VkMicromapBuildSizesInfoEXT; + +typedef struct VkAccelerationStructureTrianglesOpacityMicromapEXT { + VkStructureType sType; + void* pNext; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexBuffer; + VkDeviceSize indexStride; + uint32_t baseTriangle; + uint32_t usageCountsCount; + const VkMicromapUsageEXT* pUsageCounts; + const VkMicromapUsageEXT* const* ppUsageCounts; + VkMicromapEXT micromap; +} VkAccelerationStructureTrianglesOpacityMicromapEXT; + +typedef VkMicromapTriangleKHR VkMicromapTriangleEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateMicromapEXT)(VkDevice device, const VkMicromapCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkMicromapEXT* pMicromap); +typedef void (VKAPI_PTR *PFN_vkDestroyMicromapEXT)(VkDevice device, VkMicromapEXT micromap, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBuildMicromapsEXT)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBuildMicromapsEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMicromapEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapInfoEXT* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMicromapToMemoryEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapToMemoryInfoEXT* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToMicromapEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToMicromapInfoEXT* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWriteMicromapsPropertiesEXT)(VkDevice device, uint32_t micromapCount, const VkMicromapEXT* pMicromaps, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMicromapEXT)(VkCommandBuffer commandBuffer, const VkCopyMicromapInfoEXT* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMicromapToMemoryEXT)(VkCommandBuffer commandBuffer, const VkCopyMicromapToMemoryInfoEXT* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToMicromapEXT)(VkCommandBuffer commandBuffer, const VkCopyMemoryToMicromapInfoEXT* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteMicromapsPropertiesEXT)(VkCommandBuffer commandBuffer, uint32_t micromapCount, const VkMicromapEXT* pMicromaps, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef void (VKAPI_PTR *PFN_vkGetDeviceMicromapCompatibilityEXT)(VkDevice device, const VkMicromapVersionInfoEXT* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +typedef void (VKAPI_PTR *PFN_vkGetMicromapBuildSizesEXT)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkMicromapBuildInfoEXT* pBuildInfo, VkMicromapBuildSizesInfoEXT* pSizeInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateMicromapEXT( + VkDevice device, + const VkMicromapCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkMicromapEXT* pMicromap); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyMicromapEXT( + VkDevice device, + VkMicromapEXT micromap, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBuildMicromapsEXT( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkMicromapBuildInfoEXT* pInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBuildMicromapsEXT( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + uint32_t infoCount, + const VkMicromapBuildInfoEXT* pInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMicromapEXT( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMicromapInfoEXT* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMicromapToMemoryEXT( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMicromapToMemoryInfoEXT* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToMicromapEXT( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMemoryToMicromapInfoEXT* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWriteMicromapsPropertiesEXT( + VkDevice device, + uint32_t micromapCount, + const VkMicromapEXT* pMicromaps, + VkQueryType queryType, + size_t dataSize, + void* pData, + size_t stride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMicromapEXT( + VkCommandBuffer commandBuffer, + const VkCopyMicromapInfoEXT* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMicromapToMemoryEXT( + VkCommandBuffer commandBuffer, + const VkCopyMicromapToMemoryInfoEXT* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToMicromapEXT( + VkCommandBuffer commandBuffer, + const VkCopyMemoryToMicromapInfoEXT* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteMicromapsPropertiesEXT( + VkCommandBuffer commandBuffer, + uint32_t micromapCount, + const VkMicromapEXT* pMicromaps, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceMicromapCompatibilityEXT( + VkDevice device, + const VkMicromapVersionInfoEXT* pVersionInfo, + VkAccelerationStructureCompatibilityKHR* pCompatibility); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetMicromapBuildSizesEXT( + VkDevice device, + VkAccelerationStructureBuildTypeKHR buildType, + const VkMicromapBuildInfoEXT* pBuildInfo, + VkMicromapBuildSizesInfoEXT* pSizeInfo); +#endif +#endif + + +// VK_EXT_load_store_op_none is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_load_store_op_none 1 +#define VK_EXT_LOAD_STORE_OP_NONE_SPEC_VERSION 1 +#define VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_EXT_load_store_op_none" + + +// VK_HUAWEI_cluster_culling_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_HUAWEI_cluster_culling_shader 1 +#define VK_HUAWEI_CLUSTER_CULLING_SHADER_SPEC_VERSION 3 +#define VK_HUAWEI_CLUSTER_CULLING_SHADER_EXTENSION_NAME "VK_HUAWEI_cluster_culling_shader" +typedef struct VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 clustercullingShader; + VkBool32 multiviewClusterCullingShader; +} VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI; + +typedef struct VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI { + VkStructureType sType; + void* pNext; + uint32_t maxWorkGroupCount[3]; + uint32_t maxWorkGroupSize[3]; + uint32_t maxOutputClusterCount; + VkDeviceSize indirectBufferOffsetAlignment; +} VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI; + +typedef struct VkPhysicalDeviceClusterCullingShaderVrsFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 clusterShadingRate; +} VkPhysicalDeviceClusterCullingShaderVrsFeaturesHUAWEI; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawClusterHUAWEI)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkCmdDrawClusterIndirectHUAWEI)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawClusterHUAWEI( + VkCommandBuffer commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawClusterIndirectHUAWEI( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset); +#endif +#endif + + +// VK_EXT_border_color_swizzle is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_border_color_swizzle 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME "VK_EXT_border_color_swizzle" +typedef struct VkPhysicalDeviceBorderColorSwizzleFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 borderColorSwizzle; + VkBool32 borderColorSwizzleFromImage; +} VkPhysicalDeviceBorderColorSwizzleFeaturesEXT; + +typedef struct VkSamplerBorderColorComponentMappingCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkComponentMapping components; + VkBool32 srgb; +} VkSamplerBorderColorComponentMappingCreateInfoEXT; + + + +// VK_EXT_pageable_device_local_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pageable_device_local_memory 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_SPEC_VERSION 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME "VK_EXT_pageable_device_local_memory" +typedef struct VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pageableDeviceLocalMemory; +} VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkSetDeviceMemoryPriorityEXT)(VkDevice device, VkDeviceMemory memory, float priority); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetDeviceMemoryPriorityEXT( + VkDevice device, + VkDeviceMemory memory, + float priority); +#endif +#endif + + +// VK_ARM_shader_core_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_shader_core_properties 1 +#define VK_ARM_SHADER_CORE_PROPERTIES_SPEC_VERSION 1 +#define VK_ARM_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_ARM_shader_core_properties" +typedef struct VkPhysicalDeviceShaderCorePropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t pixelRate; + uint32_t texelRate; + uint32_t fmaRate; +} VkPhysicalDeviceShaderCorePropertiesARM; + + + +// VK_ARM_scheduling_controls is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_scheduling_controls 1 +#define VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION 2 +#define VK_ARM_SCHEDULING_CONTROLS_EXTENSION_NAME "VK_ARM_scheduling_controls" +typedef VkFlags64 VkPhysicalDeviceSchedulingControlsFlagsARM; + +// Flag bits for VkPhysicalDeviceSchedulingControlsFlagBitsARM +typedef VkFlags64 VkPhysicalDeviceSchedulingControlsFlagBitsARM; +static const VkPhysicalDeviceSchedulingControlsFlagBitsARM VK_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_SHADER_CORE_COUNT_ARM = 0x00000001ULL; +static const VkPhysicalDeviceSchedulingControlsFlagBitsARM VK_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_DISPATCH_PARAMETERS_ARM = 0x00000002ULL; + +typedef struct VkDeviceQueueShaderCoreControlCreateInfoARM { + VkStructureType sType; + void* pNext; + uint32_t shaderCoreCount; +} VkDeviceQueueShaderCoreControlCreateInfoARM; + +typedef struct VkPhysicalDeviceSchedulingControlsFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 schedulingControls; +} VkPhysicalDeviceSchedulingControlsFeaturesARM; + +typedef struct VkPhysicalDeviceSchedulingControlsPropertiesARM { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceSchedulingControlsFlagsARM schedulingControlsFlags; +} VkPhysicalDeviceSchedulingControlsPropertiesARM; + +typedef struct VkDispatchParametersARM { + VkStructureType sType; + void* pNext; + uint32_t workGroupBatchSize; + uint32_t maxQueuedWorkGroupBatches; + uint32_t maxWarpsPerShaderCore; +} VkDispatchParametersARM; + +typedef struct VkPhysicalDeviceSchedulingControlsDispatchParametersPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t schedulingControlsMaxWarpsCount; + uint32_t schedulingControlsMaxQueuedBatchesCount; + uint32_t schedulingControlsMaxWorkGroupBatchSize; +} VkPhysicalDeviceSchedulingControlsDispatchParametersPropertiesARM; + +typedef void (VKAPI_PTR *PFN_vkCmdSetDispatchParametersARM)(VkCommandBuffer commandBuffer, const VkDispatchParametersARM* pDispatchParameters); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDispatchParametersARM( + VkCommandBuffer commandBuffer, + const VkDispatchParametersARM* pDispatchParameters); +#endif +#endif + + +// VK_EXT_image_sliced_view_of_3d is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_sliced_view_of_3d 1 +#define VK_EXT_IMAGE_SLICED_VIEW_OF_3D_SPEC_VERSION 1 +#define VK_EXT_IMAGE_SLICED_VIEW_OF_3D_EXTENSION_NAME "VK_EXT_image_sliced_view_of_3d" +#define VK_REMAINING_3D_SLICES_EXT (~0U) +typedef struct VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 imageSlicedViewOf3D; +} VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT; + +typedef struct VkImageViewSlicedCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t sliceOffset; + uint32_t sliceCount; +} VkImageViewSlicedCreateInfoEXT; + + + +// VK_VALVE_descriptor_set_host_mapping is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_descriptor_set_host_mapping 1 +#define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_SPEC_VERSION 1 +#define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_EXTENSION_NAME "VK_VALVE_descriptor_set_host_mapping" +typedef struct VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 descriptorSetHostMapping; +} VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE; + +typedef struct VkDescriptorSetBindingReferenceVALVE { + VkStructureType sType; + const void* pNext; + VkDescriptorSetLayout descriptorSetLayout; + uint32_t binding; +} VkDescriptorSetBindingReferenceVALVE; + +typedef struct VkDescriptorSetLayoutHostMappingInfoVALVE { + VkStructureType sType; + void* pNext; + size_t descriptorOffset; + uint32_t descriptorSize; +} VkDescriptorSetLayoutHostMappingInfoVALVE; + +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)(VkDevice device, const VkDescriptorSetBindingReferenceVALVE* pBindingReference, VkDescriptorSetLayoutHostMappingInfoVALVE* pHostMapping); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetHostMappingVALVE)(VkDevice device, VkDescriptorSet descriptorSet, void** ppData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutHostMappingInfoVALVE( + VkDevice device, + const VkDescriptorSetBindingReferenceVALVE* pBindingReference, + VkDescriptorSetLayoutHostMappingInfoVALVE* pHostMapping); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetHostMappingVALVE( + VkDevice device, + VkDescriptorSet descriptorSet, + void** ppData); +#endif +#endif + + +// VK_EXT_depth_clamp_zero_one is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_clamp_zero_one 1 +#define VK_EXT_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME "VK_EXT_depth_clamp_zero_one" +typedef VkPhysicalDeviceDepthClampZeroOneFeaturesKHR VkPhysicalDeviceDepthClampZeroOneFeaturesEXT; + + + +// VK_EXT_non_seamless_cube_map is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_non_seamless_cube_map 1 +#define VK_EXT_NON_SEAMLESS_CUBE_MAP_SPEC_VERSION 1 +#define VK_EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME "VK_EXT_non_seamless_cube_map" +typedef struct VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 nonSeamlessCubeMap; +} VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT; + + + +// VK_ARM_render_pass_striped is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_render_pass_striped 1 +#define VK_ARM_RENDER_PASS_STRIPED_SPEC_VERSION 1 +#define VK_ARM_RENDER_PASS_STRIPED_EXTENSION_NAME "VK_ARM_render_pass_striped" +typedef struct VkPhysicalDeviceRenderPassStripedFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 renderPassStriped; +} VkPhysicalDeviceRenderPassStripedFeaturesARM; + +typedef struct VkPhysicalDeviceRenderPassStripedPropertiesARM { + VkStructureType sType; + void* pNext; + VkExtent2D renderPassStripeGranularity; + uint32_t maxRenderPassStripes; +} VkPhysicalDeviceRenderPassStripedPropertiesARM; + +typedef struct VkRenderPassStripeInfoARM { + VkStructureType sType; + const void* pNext; + VkRect2D stripeArea; +} VkRenderPassStripeInfoARM; + +typedef struct VkRenderPassStripeBeginInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t stripeInfoCount; + const VkRenderPassStripeInfoARM* pStripeInfos; +} VkRenderPassStripeBeginInfoARM; + +typedef struct VkRenderPassStripeSubmitInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t stripeSemaphoreInfoCount; + const VkSemaphoreSubmitInfo* pStripeSemaphoreInfos; +} VkRenderPassStripeSubmitInfoARM; + + + +// VK_QCOM_fragment_density_map_offset is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_fragment_density_map_offset 1 +#define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION 3 +#define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME "VK_QCOM_fragment_density_map_offset" +typedef struct VkPhysicalDeviceFragmentDensityMapOffsetFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapOffset; +} VkPhysicalDeviceFragmentDensityMapOffsetFeaturesEXT; + +typedef VkPhysicalDeviceFragmentDensityMapOffsetFeaturesEXT VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM; + +typedef struct VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT { + VkStructureType sType; + void* pNext; + VkExtent2D fragmentDensityOffsetGranularity; +} VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT; + +typedef VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM; + +typedef struct VkRenderPassFragmentDensityMapOffsetEndInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t fragmentDensityOffsetCount; + const VkOffset2D* pFragmentDensityOffsets; +} VkRenderPassFragmentDensityMapOffsetEndInfoEXT; + +typedef VkRenderPassFragmentDensityMapOffsetEndInfoEXT VkSubpassFragmentDensityMapOffsetEndInfoQCOM; + + + +// VK_NV_copy_memory_indirect is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_copy_memory_indirect 1 +#define VK_NV_COPY_MEMORY_INDIRECT_SPEC_VERSION 1 +#define VK_NV_COPY_MEMORY_INDIRECT_EXTENSION_NAME "VK_NV_copy_memory_indirect" +typedef VkCopyMemoryIndirectCommandKHR VkCopyMemoryIndirectCommandNV; + +typedef VkCopyMemoryToImageIndirectCommandKHR VkCopyMemoryToImageIndirectCommandNV; + +typedef struct VkPhysicalDeviceCopyMemoryIndirectFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 indirectCopy; +} VkPhysicalDeviceCopyMemoryIndirectFeaturesNV; + +typedef VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR VkPhysicalDeviceCopyMemoryIndirectPropertiesNV; + +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryIndirectNV)(VkCommandBuffer commandBuffer, VkDeviceAddress copyBufferAddress, uint32_t copyCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToImageIndirectNV)(VkCommandBuffer commandBuffer, VkDeviceAddress copyBufferAddress, uint32_t copyCount, uint32_t stride, VkImage dstImage, VkImageLayout dstImageLayout, const VkImageSubresourceLayers* pImageSubresources); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryIndirectNV( + VkCommandBuffer commandBuffer, + VkDeviceAddress copyBufferAddress, + uint32_t copyCount, + uint32_t stride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageIndirectNV( + VkCommandBuffer commandBuffer, + VkDeviceAddress copyBufferAddress, + uint32_t copyCount, + uint32_t stride, + VkImage dstImage, + VkImageLayout dstImageLayout, + const VkImageSubresourceLayers* pImageSubresources); +#endif +#endif + + +// VK_NV_memory_decompression is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_memory_decompression 1 +#define VK_NV_MEMORY_DECOMPRESSION_SPEC_VERSION 1 +#define VK_NV_MEMORY_DECOMPRESSION_EXTENSION_NAME "VK_NV_memory_decompression" + +// Flag bits for VkMemoryDecompressionMethodFlagBitsEXT +typedef VkFlags64 VkMemoryDecompressionMethodFlagBitsEXT; +static const VkMemoryDecompressionMethodFlagBitsEXT VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT = 0x00000001ULL; +static const VkMemoryDecompressionMethodFlagBitsEXT VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV = 0x00000001ULL; + +typedef VkMemoryDecompressionMethodFlagBitsEXT VkMemoryDecompressionMethodFlagBitsNV; + +typedef VkFlags64 VkMemoryDecompressionMethodFlagsEXT; +typedef VkMemoryDecompressionMethodFlagsEXT VkMemoryDecompressionMethodFlagsNV; + +typedef struct VkDecompressMemoryRegionNV { + VkDeviceAddress srcAddress; + VkDeviceAddress dstAddress; + VkDeviceSize compressedSize; + VkDeviceSize decompressedSize; + VkMemoryDecompressionMethodFlagsEXT decompressionMethod; +} VkDecompressMemoryRegionNV; + +typedef struct VkPhysicalDeviceMemoryDecompressionFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 memoryDecompression; +} VkPhysicalDeviceMemoryDecompressionFeaturesEXT; + +typedef VkPhysicalDeviceMemoryDecompressionFeaturesEXT VkPhysicalDeviceMemoryDecompressionFeaturesNV; + +typedef struct VkPhysicalDeviceMemoryDecompressionPropertiesEXT { + VkStructureType sType; + void* pNext; + VkMemoryDecompressionMethodFlagsEXT decompressionMethods; + uint64_t maxDecompressionIndirectCount; +} VkPhysicalDeviceMemoryDecompressionPropertiesEXT; + +typedef VkPhysicalDeviceMemoryDecompressionPropertiesEXT VkPhysicalDeviceMemoryDecompressionPropertiesNV; + +typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryNV)(VkCommandBuffer commandBuffer, uint32_t decompressRegionCount, const VkDecompressMemoryRegionNV* pDecompressMemoryRegions); +typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryIndirectCountNV)(VkCommandBuffer commandBuffer, VkDeviceAddress indirectCommandsAddress, VkDeviceAddress indirectCommandsCountAddress, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryNV( + VkCommandBuffer commandBuffer, + uint32_t decompressRegionCount, + const VkDecompressMemoryRegionNV* pDecompressMemoryRegions); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryIndirectCountNV( + VkCommandBuffer commandBuffer, + VkDeviceAddress indirectCommandsAddress, + VkDeviceAddress indirectCommandsCountAddress, + uint32_t stride); +#endif +#endif + + +// VK_NV_device_generated_commands_compute is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_device_generated_commands_compute 1 +#define VK_NV_DEVICE_GENERATED_COMMANDS_COMPUTE_SPEC_VERSION 2 +#define VK_NV_DEVICE_GENERATED_COMMANDS_COMPUTE_EXTENSION_NAME "VK_NV_device_generated_commands_compute" +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 deviceGeneratedCompute; + VkBool32 deviceGeneratedComputePipelines; + VkBool32 deviceGeneratedComputeCaptureReplay; +} VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV; + +typedef struct VkComputePipelineIndirectBufferInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceAddress deviceAddress; + VkDeviceSize size; + VkDeviceAddress pipelineDeviceAddressCaptureReplay; +} VkComputePipelineIndirectBufferInfoNV; + +typedef struct VkPipelineIndirectDeviceAddressInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; +} VkPipelineIndirectDeviceAddressInfoNV; + +typedef struct VkBindPipelineIndirectCommandNV { + VkDeviceAddress pipelineAddress; +} VkBindPipelineIndirectCommandNV; + +typedef void (VKAPI_PTR *PFN_vkGetPipelineIndirectMemoryRequirementsNV)(VkDevice device, const VkComputePipelineCreateInfo* pCreateInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdUpdatePipelineIndirectBufferNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetPipelineIndirectDeviceAddressNV)(VkDevice device, const VkPipelineIndirectDeviceAddressInfoNV* pInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPipelineIndirectMemoryRequirementsNV( + VkDevice device, + const VkComputePipelineCreateInfo* pCreateInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdUpdatePipelineIndirectBufferNV( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetPipelineIndirectDeviceAddressNV( + VkDevice device, + const VkPipelineIndirectDeviceAddressInfoNV* pInfo); +#endif +#endif + + +// VK_NV_ray_tracing_linear_swept_spheres is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_ray_tracing_linear_swept_spheres 1 +#define VK_NV_RAY_TRACING_LINEAR_SWEPT_SPHERES_SPEC_VERSION 1 +#define VK_NV_RAY_TRACING_LINEAR_SWEPT_SPHERES_EXTENSION_NAME "VK_NV_ray_tracing_linear_swept_spheres" + +typedef enum VkRayTracingLssIndexingModeNV { + VK_RAY_TRACING_LSS_INDEXING_MODE_LIST_NV = 0, + VK_RAY_TRACING_LSS_INDEXING_MODE_SUCCESSIVE_NV = 1, + VK_RAY_TRACING_LSS_INDEXING_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkRayTracingLssIndexingModeNV; + +typedef enum VkRayTracingLssPrimitiveEndCapsModeNV { + VK_RAY_TRACING_LSS_PRIMITIVE_END_CAPS_MODE_NONE_NV = 0, + VK_RAY_TRACING_LSS_PRIMITIVE_END_CAPS_MODE_CHAINED_NV = 1, + VK_RAY_TRACING_LSS_PRIMITIVE_END_CAPS_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkRayTracingLssPrimitiveEndCapsModeNV; +typedef struct VkPhysicalDeviceRayTracingLinearSweptSpheresFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 spheres; + VkBool32 linearSweptSpheres; +} VkPhysicalDeviceRayTracingLinearSweptSpheresFeaturesNV; + +typedef struct VkAccelerationStructureGeometryLinearSweptSpheresDataNV { + VkStructureType sType; + const void* pNext; + VkFormat vertexFormat; + VkDeviceOrHostAddressConstKHR vertexData; + VkDeviceSize vertexStride; + VkFormat radiusFormat; + VkDeviceOrHostAddressConstKHR radiusData; + VkDeviceSize radiusStride; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexData; + VkDeviceSize indexStride; + VkRayTracingLssIndexingModeNV indexingMode; + VkRayTracingLssPrimitiveEndCapsModeNV endCapsMode; +} VkAccelerationStructureGeometryLinearSweptSpheresDataNV; + +typedef struct VkAccelerationStructureGeometrySpheresDataNV { + VkStructureType sType; + const void* pNext; + VkFormat vertexFormat; + VkDeviceOrHostAddressConstKHR vertexData; + VkDeviceSize vertexStride; + VkFormat radiusFormat; + VkDeviceOrHostAddressConstKHR radiusData; + VkDeviceSize radiusStride; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexData; + VkDeviceSize indexStride; +} VkAccelerationStructureGeometrySpheresDataNV; + + + +// VK_NV_linear_color_attachment is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_linear_color_attachment 1 +#define VK_NV_LINEAR_COLOR_ATTACHMENT_SPEC_VERSION 1 +#define VK_NV_LINEAR_COLOR_ATTACHMENT_EXTENSION_NAME "VK_NV_linear_color_attachment" +typedef struct VkPhysicalDeviceLinearColorAttachmentFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 linearColorAttachment; +} VkPhysicalDeviceLinearColorAttachmentFeaturesNV; + + + +// VK_GOOGLE_surfaceless_query is a preprocessor guard. Do not pass it to API calls. +#define VK_GOOGLE_surfaceless_query 1 +#define VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION 2 +#define VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME "VK_GOOGLE_surfaceless_query" + + +// VK_EXT_image_compression_control_swapchain is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_image_compression_control_swapchain 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_SPEC_VERSION 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME "VK_EXT_image_compression_control_swapchain" +typedef struct VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 imageCompressionControlSwapchain; +} VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT; + + + +// VK_QCOM_image_processing is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_image_processing 1 +#define VK_QCOM_IMAGE_PROCESSING_SPEC_VERSION 1 +#define VK_QCOM_IMAGE_PROCESSING_EXTENSION_NAME "VK_QCOM_image_processing" +typedef struct VkImageViewSampleWeightCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + VkOffset2D filterCenter; + VkExtent2D filterSize; + uint32_t numPhases; +} VkImageViewSampleWeightCreateInfoQCOM; + +typedef struct VkPhysicalDeviceImageProcessingFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 textureSampleWeighted; + VkBool32 textureBoxFilter; + VkBool32 textureBlockMatch; +} VkPhysicalDeviceImageProcessingFeaturesQCOM; + +typedef struct VkPhysicalDeviceImageProcessingPropertiesQCOM { + VkStructureType sType; + void* pNext; + uint32_t maxWeightFilterPhases; + VkExtent2D maxWeightFilterDimension; + VkExtent2D maxBlockMatchRegion; + VkExtent2D maxBoxFilterBlockSize; +} VkPhysicalDeviceImageProcessingPropertiesQCOM; + + + +// VK_EXT_nested_command_buffer is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_nested_command_buffer 1 +#define VK_EXT_NESTED_COMMAND_BUFFER_SPEC_VERSION 1 +#define VK_EXT_NESTED_COMMAND_BUFFER_EXTENSION_NAME "VK_EXT_nested_command_buffer" +typedef struct VkPhysicalDeviceNestedCommandBufferFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 nestedCommandBuffer; + VkBool32 nestedCommandBufferRendering; + VkBool32 nestedCommandBufferSimultaneousUse; +} VkPhysicalDeviceNestedCommandBufferFeaturesEXT; + +typedef struct VkPhysicalDeviceNestedCommandBufferPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxCommandBufferNestingLevel; +} VkPhysicalDeviceNestedCommandBufferPropertiesEXT; + + + +// VK_EXT_external_memory_acquire_unmodified is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_external_memory_acquire_unmodified 1 +#define VK_EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXTENSION_NAME "VK_EXT_external_memory_acquire_unmodified" +typedef struct VkExternalMemoryAcquireUnmodifiedEXT { + VkStructureType sType; + const void* pNext; + VkBool32 acquireUnmodifiedMemory; +} VkExternalMemoryAcquireUnmodifiedEXT; + + + +// VK_EXT_extended_dynamic_state3 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_extended_dynamic_state3 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_3_SPEC_VERSION 2 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME "VK_EXT_extended_dynamic_state3" +typedef struct VkPhysicalDeviceExtendedDynamicState3FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 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; +} VkPhysicalDeviceExtendedDynamicState3FeaturesEXT; + +typedef struct VkPhysicalDeviceExtendedDynamicState3PropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 dynamicPrimitiveTopologyUnrestricted; +} VkPhysicalDeviceExtendedDynamicState3PropertiesEXT; + +typedef struct VkColorBlendEquationEXT { + VkBlendFactor srcColorBlendFactor; + VkBlendFactor dstColorBlendFactor; + VkBlendOp colorBlendOp; + VkBlendFactor srcAlphaBlendFactor; + VkBlendFactor dstAlphaBlendFactor; + VkBlendOp alphaBlendOp; +} VkColorBlendEquationEXT; + +typedef struct VkColorBlendAdvancedEXT { + VkBlendOp advancedBlendOp; + VkBool32 srcPremultiplied; + VkBool32 dstPremultiplied; + VkBlendOverlapEXT blendOverlap; + VkBool32 clampResults; +} VkColorBlendAdvancedEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthClampEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthClampEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetPolygonModeEXT)(VkCommandBuffer commandBuffer, VkPolygonMode polygonMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizationSamplesEXT)(VkCommandBuffer commandBuffer, VkSampleCountFlagBits rasterizationSamples); +typedef void (VKAPI_PTR *PFN_vkCmdSetSampleMaskEXT)(VkCommandBuffer commandBuffer, VkSampleCountFlagBits samples, const VkSampleMask* pSampleMask); +typedef void (VKAPI_PTR *PFN_vkCmdSetAlphaToCoverageEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 alphaToCoverageEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetAlphaToOneEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 alphaToOneEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetLogicOpEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 logicOpEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetColorBlendEnableEXT)(VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkBool32* pColorBlendEnables); +typedef void (VKAPI_PTR *PFN_vkCmdSetColorBlendEquationEXT)(VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendEquationEXT* pColorBlendEquations); +typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteMaskEXT)(VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkColorComponentFlags* pColorWriteMasks); +typedef void (VKAPI_PTR *PFN_vkCmdSetTessellationDomainOriginEXT)(VkCommandBuffer commandBuffer, VkTessellationDomainOrigin domainOrigin); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizationStreamEXT)(VkCommandBuffer commandBuffer, uint32_t rasterizationStream); +typedef void (VKAPI_PTR *PFN_vkCmdSetConservativeRasterizationModeEXT)(VkCommandBuffer commandBuffer, VkConservativeRasterizationModeEXT conservativeRasterizationMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)(VkCommandBuffer commandBuffer, float extraPrimitiveOverestimationSize); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthClipEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthClipEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 sampleLocationsEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetColorBlendAdvancedEXT)(VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendAdvancedEXT* pColorBlendAdvanced); +typedef void (VKAPI_PTR *PFN_vkCmdSetProvokingVertexModeEXT)(VkCommandBuffer commandBuffer, VkProvokingVertexModeEXT provokingVertexMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetLineRasterizationModeEXT)(VkCommandBuffer commandBuffer, VkLineRasterizationModeEXT lineRasterizationMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 stippledLineEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthClipNegativeOneToOneEXT)(VkCommandBuffer commandBuffer, VkBool32 negativeOneToOne); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingEnableNV)(VkCommandBuffer commandBuffer, VkBool32 viewportWScalingEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportSwizzleNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportSwizzleNV* pViewportSwizzles); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageToColorEnableNV)(VkCommandBuffer commandBuffer, VkBool32 coverageToColorEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageToColorLocationNV)(VkCommandBuffer commandBuffer, uint32_t coverageToColorLocation); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageModulationModeNV)(VkCommandBuffer commandBuffer, VkCoverageModulationModeNV coverageModulationMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageModulationTableEnableNV)(VkCommandBuffer commandBuffer, VkBool32 coverageModulationTableEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageModulationTableNV)(VkCommandBuffer commandBuffer, uint32_t coverageModulationTableCount, const float* pCoverageModulationTable); +typedef void (VKAPI_PTR *PFN_vkCmdSetShadingRateImageEnableNV)(VkCommandBuffer commandBuffer, VkBool32 shadingRateImageEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetRepresentativeFragmentTestEnableNV)(VkCommandBuffer commandBuffer, VkBool32 representativeFragmentTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageReductionModeNV)(VkCommandBuffer commandBuffer, VkCoverageReductionModeNV coverageReductionMode); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClampEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthClampEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPolygonModeEXT( + VkCommandBuffer commandBuffer, + VkPolygonMode polygonMode); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizationSamplesEXT( + VkCommandBuffer commandBuffer, + VkSampleCountFlagBits rasterizationSamples); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleMaskEXT( + VkCommandBuffer commandBuffer, + VkSampleCountFlagBits samples, + const VkSampleMask* pSampleMask); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetAlphaToCoverageEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 alphaToCoverageEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetAlphaToOneEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 alphaToOneEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 logicOpEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendEnableEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkBool32* pColorBlendEnables); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendEquationEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorBlendEquationEXT* pColorBlendEquations); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteMaskEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorComponentFlags* pColorWriteMasks); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetTessellationDomainOriginEXT( + VkCommandBuffer commandBuffer, + VkTessellationDomainOrigin domainOrigin); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizationStreamEXT( + VkCommandBuffer commandBuffer, + uint32_t rasterizationStream); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetConservativeRasterizationModeEXT( + VkCommandBuffer commandBuffer, + VkConservativeRasterizationModeEXT conservativeRasterizationMode); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetExtraPrimitiveOverestimationSizeEXT( + VkCommandBuffer commandBuffer, + float extraPrimitiveOverestimationSize); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClipEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthClipEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 sampleLocationsEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendAdvancedEXT( + VkCommandBuffer commandBuffer, + uint32_t firstAttachment, + uint32_t attachmentCount, + const VkColorBlendAdvancedEXT* pColorBlendAdvanced); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetProvokingVertexModeEXT( + VkCommandBuffer commandBuffer, + VkProvokingVertexModeEXT provokingVertexMode); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineRasterizationModeEXT( + VkCommandBuffer commandBuffer, + VkLineRasterizationModeEXT lineRasterizationMode); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 stippledLineEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClipNegativeOneToOneEXT( + VkCommandBuffer commandBuffer, + VkBool32 negativeOneToOne); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 viewportWScalingEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportSwizzleNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewportSwizzleNV* pViewportSwizzles); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageToColorEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 coverageToColorEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageToColorLocationNV( + VkCommandBuffer commandBuffer, + uint32_t coverageToColorLocation); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageModulationModeNV( + VkCommandBuffer commandBuffer, + VkCoverageModulationModeNV coverageModulationMode); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageModulationTableEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 coverageModulationTableEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageModulationTableNV( + VkCommandBuffer commandBuffer, + uint32_t coverageModulationTableCount, + const float* pCoverageModulationTable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetShadingRateImageEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 shadingRateImageEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetRepresentativeFragmentTestEnableNV( + VkCommandBuffer commandBuffer, + VkBool32 representativeFragmentTestEnable); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageReductionModeNV( + VkCommandBuffer commandBuffer, + VkCoverageReductionModeNV coverageReductionMode); +#endif +#endif + + +// VK_EXT_subpass_merge_feedback is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_subpass_merge_feedback 1 +#define VK_EXT_SUBPASS_MERGE_FEEDBACK_SPEC_VERSION 2 +#define VK_EXT_SUBPASS_MERGE_FEEDBACK_EXTENSION_NAME "VK_EXT_subpass_merge_feedback" + +typedef enum VkSubpassMergeStatusEXT { + 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, + VK_SUBPASS_MERGE_STATUS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSubpassMergeStatusEXT; +typedef struct VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 subpassMergeFeedback; +} VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT; + +typedef struct VkRenderPassCreationControlEXT { + VkStructureType sType; + const void* pNext; + VkBool32 disallowMerging; +} VkRenderPassCreationControlEXT; + +typedef struct VkRenderPassCreationFeedbackInfoEXT { + uint32_t postMergeSubpassCount; +} VkRenderPassCreationFeedbackInfoEXT; + +typedef struct VkRenderPassCreationFeedbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkRenderPassCreationFeedbackInfoEXT* pRenderPassFeedback; +} VkRenderPassCreationFeedbackCreateInfoEXT; + +typedef struct VkRenderPassSubpassFeedbackInfoEXT { + VkSubpassMergeStatusEXT subpassMergeStatus; + char description[VK_MAX_DESCRIPTION_SIZE]; + uint32_t postMergeIndex; +} VkRenderPassSubpassFeedbackInfoEXT; + +typedef struct VkRenderPassSubpassFeedbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkRenderPassSubpassFeedbackInfoEXT* pSubpassFeedback; +} VkRenderPassSubpassFeedbackCreateInfoEXT; + + + +// VK_LUNARG_direct_driver_loading is a preprocessor guard. Do not pass it to API calls. +#define VK_LUNARG_direct_driver_loading 1 +#define VK_LUNARG_DIRECT_DRIVER_LOADING_SPEC_VERSION 1 +#define VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME "VK_LUNARG_direct_driver_loading" + +typedef enum VkDirectDriverLoadingModeLUNARG { + VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG = 0, + VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG = 1, + VK_DIRECT_DRIVER_LOADING_MODE_MAX_ENUM_LUNARG = 0x7FFFFFFF +} VkDirectDriverLoadingModeLUNARG; +typedef VkFlags VkDirectDriverLoadingFlagsLUNARG; +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddrLUNARG)( + VkInstance instance, + const char* pName); + +typedef struct VkDirectDriverLoadingInfoLUNARG { + VkStructureType sType; + void* pNext; + VkDirectDriverLoadingFlagsLUNARG flags; + PFN_vkGetInstanceProcAddrLUNARG pfnGetInstanceProcAddr; +} VkDirectDriverLoadingInfoLUNARG; + +typedef struct VkDirectDriverLoadingListLUNARG { + VkStructureType sType; + const void* pNext; + VkDirectDriverLoadingModeLUNARG mode; + uint32_t driverCount; + const VkDirectDriverLoadingInfoLUNARG* pDrivers; +} VkDirectDriverLoadingListLUNARG; + + + +// VK_ARM_tensors is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_tensors 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkTensorViewARM) +#define VK_ARM_TENSORS_SPEC_VERSION 2 +#define VK_ARM_TENSORS_EXTENSION_NAME "VK_ARM_tensors" + +typedef enum VkTensorTilingARM { + VK_TENSOR_TILING_OPTIMAL_ARM = 0, + VK_TENSOR_TILING_LINEAR_ARM = 1, + VK_TENSOR_TILING_MAX_ENUM_ARM = 0x7FFFFFFF +} VkTensorTilingARM; +typedef VkFlags64 VkTensorCreateFlagsARM; + +// Flag bits for VkTensorCreateFlagBitsARM +typedef VkFlags64 VkTensorCreateFlagBitsARM; +static const VkTensorCreateFlagBitsARM VK_TENSOR_CREATE_MUTABLE_FORMAT_BIT_ARM = 0x00000001ULL; +static const VkTensorCreateFlagBitsARM VK_TENSOR_CREATE_PROTECTED_BIT_ARM = 0x00000002ULL; +static const VkTensorCreateFlagBitsARM VK_TENSOR_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_ARM = 0x00000008ULL; +static const VkTensorCreateFlagBitsARM VK_TENSOR_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM = 0x00000004ULL; + +typedef VkFlags64 VkTensorUsageFlagsARM; + +// Flag bits for VkTensorUsageFlagBitsARM +typedef VkFlags64 VkTensorUsageFlagBitsARM; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_SHADER_BIT_ARM = 0x00000002ULL; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_TRANSFER_SRC_BIT_ARM = 0x00000004ULL; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_TRANSFER_DST_BIT_ARM = 0x00000008ULL; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_IMAGE_ALIASING_BIT_ARM = 0x00000010ULL; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_DATA_GRAPH_BIT_ARM = 0x00000020ULL; + +typedef struct VkTensorDescriptionARM { + VkStructureType sType; + const void* pNext; + VkTensorTilingARM tiling; + VkFormat format; + uint32_t dimensionCount; + const int64_t* pDimensions; + const int64_t* pStrides; + VkTensorUsageFlagsARM usage; +} VkTensorDescriptionARM; + +typedef struct VkTensorCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorCreateFlagsARM flags; + const VkTensorDescriptionARM* pDescription; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; +} VkTensorCreateInfoARM; + +typedef struct VkTensorMemoryRequirementsInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorARM tensor; +} VkTensorMemoryRequirementsInfoARM; + +typedef struct VkBindTensorMemoryInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorARM tensor; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindTensorMemoryInfoARM; + +typedef struct VkWriteDescriptorSetTensorARM { + VkStructureType sType; + const void* pNext; + uint32_t tensorViewCount; + const VkTensorViewARM* pTensorViews; +} VkWriteDescriptorSetTensorARM; + +typedef struct VkTensorFormatPropertiesARM { + VkStructureType sType; + void* pNext; + VkFormatFeatureFlags2 optimalTilingTensorFeatures; + VkFormatFeatureFlags2 linearTilingTensorFeatures; +} VkTensorFormatPropertiesARM; + +typedef struct VkPhysicalDeviceTensorPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t maxTensorDimensionCount; + uint64_t maxTensorElements; + uint64_t maxPerDimensionTensorElements; + int64_t maxTensorStride; + uint64_t maxTensorSize; + uint32_t maxTensorShaderAccessArrayLength; + uint32_t maxTensorShaderAccessSize; + uint32_t maxDescriptorSetStorageTensors; + uint32_t maxPerStageDescriptorSetStorageTensors; + uint32_t maxDescriptorSetUpdateAfterBindStorageTensors; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageTensors; + VkBool32 shaderStorageTensorArrayNonUniformIndexingNative; + VkShaderStageFlags shaderTensorSupportedStages; +} VkPhysicalDeviceTensorPropertiesARM; + +typedef struct VkTensorMemoryBarrierARM { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkTensorARM tensor; +} VkTensorMemoryBarrierARM; + +typedef struct VkTensorDependencyInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t tensorMemoryBarrierCount; + const VkTensorMemoryBarrierARM* pTensorMemoryBarriers; +} VkTensorDependencyInfoARM; + +typedef struct VkPhysicalDeviceTensorFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 tensorNonPacked; + VkBool32 shaderTensorAccess; + VkBool32 shaderStorageTensorArrayDynamicIndexing; + VkBool32 shaderStorageTensorArrayNonUniformIndexing; + VkBool32 descriptorBindingStorageTensorUpdateAfterBind; + VkBool32 tensors; +} VkPhysicalDeviceTensorFeaturesARM; + +typedef struct VkDeviceTensorMemoryRequirementsARM { + VkStructureType sType; + const void* pNext; + const VkTensorCreateInfoARM* pCreateInfo; +} VkDeviceTensorMemoryRequirementsARM; + +typedef struct VkTensorCopyARM { + VkStructureType sType; + const void* pNext; + uint32_t dimensionCount; + const uint64_t* pSrcOffset; + const uint64_t* pDstOffset; + const uint64_t* pExtent; +} VkTensorCopyARM; + +typedef struct VkCopyTensorInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorARM srcTensor; + VkTensorARM dstTensor; + uint32_t regionCount; + const VkTensorCopyARM* pRegions; +} VkCopyTensorInfoARM; + +typedef struct VkMemoryDedicatedAllocateInfoTensorARM { + VkStructureType sType; + const void* pNext; + VkTensorARM tensor; +} VkMemoryDedicatedAllocateInfoTensorARM; + +typedef struct VkPhysicalDeviceExternalTensorInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorCreateFlagsARM flags; + const VkTensorDescriptionARM* pDescription; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalTensorInfoARM; + +typedef struct VkExternalTensorPropertiesARM { + VkStructureType sType; + const void* pNext; + VkExternalMemoryProperties externalMemoryProperties; +} VkExternalTensorPropertiesARM; + +typedef struct VkExternalMemoryTensorCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExternalMemoryTensorCreateInfoARM; + +typedef struct VkPhysicalDeviceDescriptorBufferTensorFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 descriptorBufferTensorDescriptors; +} VkPhysicalDeviceDescriptorBufferTensorFeaturesARM; + +typedef struct VkPhysicalDeviceDescriptorBufferTensorPropertiesARM { + VkStructureType sType; + void* pNext; + size_t tensorCaptureReplayDescriptorDataSize; + size_t tensorViewCaptureReplayDescriptorDataSize; + size_t tensorDescriptorSize; +} VkPhysicalDeviceDescriptorBufferTensorPropertiesARM; + +typedef struct VkDescriptorGetTensorInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorViewARM tensorView; +} VkDescriptorGetTensorInfoARM; + +typedef struct VkTensorCaptureDescriptorDataInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorARM tensor; +} VkTensorCaptureDescriptorDataInfoARM; + +typedef struct VkTensorViewCaptureDescriptorDataInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorViewARM tensorView; +} VkTensorViewCaptureDescriptorDataInfoARM; + +typedef struct VkFrameBoundaryTensorsARM { + VkStructureType sType; + const void* pNext; + uint32_t tensorCount; + const VkTensorARM* pTensors; +} VkFrameBoundaryTensorsARM; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateTensorARM)(VkDevice device, const VkTensorCreateInfoARM* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkTensorARM* pTensor); +typedef void (VKAPI_PTR *PFN_vkDestroyTensorARM)(VkDevice device, VkTensorARM tensor, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateTensorViewARM)(VkDevice device, const VkTensorViewCreateInfoARM* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkTensorViewARM* pView); +typedef void (VKAPI_PTR *PFN_vkDestroyTensorViewARM)(VkDevice device, VkTensorViewARM tensorView, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetTensorMemoryRequirementsARM)(VkDevice device, const VkTensorMemoryRequirementsInfoARM* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindTensorMemoryARM)(VkDevice device, uint32_t bindInfoCount, const VkBindTensorMemoryInfoARM* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkGetDeviceTensorMemoryRequirementsARM)(VkDevice device, const VkDeviceTensorMemoryRequirementsARM* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdCopyTensorARM)(VkCommandBuffer commandBuffer, const VkCopyTensorInfoARM* pCopyTensorInfo); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalTensorInfoARM* pExternalTensorInfo, VkExternalTensorPropertiesARM* pExternalTensorProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetTensorOpaqueCaptureDescriptorDataARM)(VkDevice device, const VkTensorCaptureDescriptorDataInfoARM* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM)(VkDevice device, const VkTensorViewCaptureDescriptorDataInfoARM* pInfo, void* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateTensorARM( + VkDevice device, + const VkTensorCreateInfoARM* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkTensorARM* pTensor); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyTensorARM( + VkDevice device, + VkTensorARM tensor, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateTensorViewARM( + VkDevice device, + const VkTensorViewCreateInfoARM* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkTensorViewARM* pView); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyTensorViewARM( + VkDevice device, + VkTensorViewARM tensorView, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetTensorMemoryRequirementsARM( + VkDevice device, + const VkTensorMemoryRequirementsInfoARM* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindTensorMemoryARM( + VkDevice device, + uint32_t bindInfoCount, + const VkBindTensorMemoryInfoARM* pBindInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceTensorMemoryRequirementsARM( + VkDevice device, + const VkDeviceTensorMemoryRequirementsARM* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyTensorARM( + VkCommandBuffer commandBuffer, + const VkCopyTensorInfoARM* pCopyTensorInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalTensorPropertiesARM( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalTensorInfoARM* pExternalTensorInfo, + VkExternalTensorPropertiesARM* pExternalTensorProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetTensorOpaqueCaptureDescriptorDataARM( + VkDevice device, + const VkTensorCaptureDescriptorDataInfoARM* pInfo, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetTensorViewOpaqueCaptureDescriptorDataARM( + VkDevice device, + const VkTensorViewCaptureDescriptorDataInfoARM* pInfo, + void* pData); +#endif +#endif + + +// VK_EXT_shader_module_identifier is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_module_identifier 1 +#define VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT 32U +#define VK_EXT_SHADER_MODULE_IDENTIFIER_SPEC_VERSION 1 +#define VK_EXT_SHADER_MODULE_IDENTIFIER_EXTENSION_NAME "VK_EXT_shader_module_identifier" +typedef struct VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderModuleIdentifier; +} VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT; + +typedef struct VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT { + VkStructureType sType; + void* pNext; + uint8_t shaderModuleIdentifierAlgorithmUUID[VK_UUID_SIZE]; +} VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT; + +typedef struct VkPipelineShaderStageModuleIdentifierCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t identifierSize; + const uint8_t* pIdentifier; +} VkPipelineShaderStageModuleIdentifierCreateInfoEXT; + +typedef struct VkShaderModuleIdentifierEXT { + VkStructureType sType; + void* pNext; + uint32_t identifierSize; + uint8_t identifier[VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT]; +} VkShaderModuleIdentifierEXT; + +typedef void (VKAPI_PTR *PFN_vkGetShaderModuleIdentifierEXT)(VkDevice device, VkShaderModule shaderModule, VkShaderModuleIdentifierEXT* pIdentifier); +typedef void (VKAPI_PTR *PFN_vkGetShaderModuleCreateInfoIdentifierEXT)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModuleIdentifierEXT* pIdentifier); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetShaderModuleIdentifierEXT( + VkDevice device, + VkShaderModule shaderModule, + VkShaderModuleIdentifierEXT* pIdentifier); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetShaderModuleCreateInfoIdentifierEXT( + VkDevice device, + const VkShaderModuleCreateInfo* pCreateInfo, + VkShaderModuleIdentifierEXT* pIdentifier); +#endif +#endif + + +// VK_EXT_rasterization_order_attachment_access is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_rasterization_order_attachment_access 1 +#define VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION 1 +#define VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME "VK_EXT_rasterization_order_attachment_access" + + +// VK_NV_optical_flow is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_optical_flow 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkOpticalFlowSessionNV) +#define VK_NV_OPTICAL_FLOW_SPEC_VERSION 1 +#define VK_NV_OPTICAL_FLOW_EXTENSION_NAME "VK_NV_optical_flow" + +typedef enum VkOpticalFlowPerformanceLevelNV { + 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, + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowPerformanceLevelNV; + +typedef enum VkOpticalFlowSessionBindingPointNV { + 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, + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowSessionBindingPointNV; + +typedef enum VkOpticalFlowGridSizeFlagBitsNV { + VK_OPTICAL_FLOW_GRID_SIZE_UNKNOWN_NV = 0, + VK_OPTICAL_FLOW_GRID_SIZE_1X1_BIT_NV = 0x00000001, + VK_OPTICAL_FLOW_GRID_SIZE_2X2_BIT_NV = 0x00000002, + VK_OPTICAL_FLOW_GRID_SIZE_4X4_BIT_NV = 0x00000004, + VK_OPTICAL_FLOW_GRID_SIZE_8X8_BIT_NV = 0x00000008, + VK_OPTICAL_FLOW_GRID_SIZE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowGridSizeFlagBitsNV; +typedef VkFlags VkOpticalFlowGridSizeFlagsNV; + +typedef enum VkOpticalFlowUsageFlagBitsNV { + VK_OPTICAL_FLOW_USAGE_UNKNOWN_NV = 0, + VK_OPTICAL_FLOW_USAGE_INPUT_BIT_NV = 0x00000001, + VK_OPTICAL_FLOW_USAGE_OUTPUT_BIT_NV = 0x00000002, + VK_OPTICAL_FLOW_USAGE_HINT_BIT_NV = 0x00000004, + VK_OPTICAL_FLOW_USAGE_COST_BIT_NV = 0x00000008, + VK_OPTICAL_FLOW_USAGE_GLOBAL_FLOW_BIT_NV = 0x00000010, + VK_OPTICAL_FLOW_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowUsageFlagBitsNV; +typedef VkFlags VkOpticalFlowUsageFlagsNV; + +typedef enum VkOpticalFlowSessionCreateFlagBitsNV { + VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_HINT_BIT_NV = 0x00000001, + VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_COST_BIT_NV = 0x00000002, + VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_GLOBAL_FLOW_BIT_NV = 0x00000004, + VK_OPTICAL_FLOW_SESSION_CREATE_ALLOW_REGIONS_BIT_NV = 0x00000008, + VK_OPTICAL_FLOW_SESSION_CREATE_BOTH_DIRECTIONS_BIT_NV = 0x00000010, + VK_OPTICAL_FLOW_SESSION_CREATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowSessionCreateFlagBitsNV; +typedef VkFlags VkOpticalFlowSessionCreateFlagsNV; + +typedef enum VkOpticalFlowExecuteFlagBitsNV { + VK_OPTICAL_FLOW_EXECUTE_DISABLE_TEMPORAL_HINTS_BIT_NV = 0x00000001, + VK_OPTICAL_FLOW_EXECUTE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkOpticalFlowExecuteFlagBitsNV; +typedef VkFlags VkOpticalFlowExecuteFlagsNV; +typedef struct VkPhysicalDeviceOpticalFlowFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 opticalFlow; +} VkPhysicalDeviceOpticalFlowFeaturesNV; + +typedef struct VkPhysicalDeviceOpticalFlowPropertiesNV { + VkStructureType sType; + void* pNext; + VkOpticalFlowGridSizeFlagsNV supportedOutputGridSizes; + VkOpticalFlowGridSizeFlagsNV supportedHintGridSizes; + VkBool32 hintSupported; + VkBool32 costSupported; + VkBool32 bidirectionalFlowSupported; + VkBool32 globalFlowSupported; + uint32_t minWidth; + uint32_t minHeight; + uint32_t maxWidth; + uint32_t maxHeight; + uint32_t maxNumRegionsOfInterest; +} VkPhysicalDeviceOpticalFlowPropertiesNV; + +typedef struct VkOpticalFlowImageFormatInfoNV { + VkStructureType sType; + const void* pNext; + VkOpticalFlowUsageFlagsNV usage; +} VkOpticalFlowImageFormatInfoNV; + +typedef struct VkOpticalFlowImageFormatPropertiesNV { + VkStructureType sType; + void* pNext; + VkFormat format; +} VkOpticalFlowImageFormatPropertiesNV; + +typedef struct VkOpticalFlowSessionCreateInfoNV { + VkStructureType sType; + void* pNext; + uint32_t width; + uint32_t height; + VkFormat imageFormat; + VkFormat flowVectorFormat; + VkFormat costFormat; + VkOpticalFlowGridSizeFlagsNV outputGridSize; + VkOpticalFlowGridSizeFlagsNV hintGridSize; + VkOpticalFlowPerformanceLevelNV performanceLevel; + VkOpticalFlowSessionCreateFlagsNV flags; +} VkOpticalFlowSessionCreateInfoNV; + +typedef struct VkOpticalFlowSessionCreatePrivateDataInfoNV { + VkStructureType sType; + void* pNext; + uint32_t id; + uint32_t size; + const void* pPrivateData; +} VkOpticalFlowSessionCreatePrivateDataInfoNV; + +typedef struct VkOpticalFlowExecuteInfoNV { + VkStructureType sType; + void* pNext; + VkOpticalFlowExecuteFlagsNV flags; + uint32_t regionCount; + const VkRect2D* pRegions; +} VkOpticalFlowExecuteInfoNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV)(VkPhysicalDevice physicalDevice, const VkOpticalFlowImageFormatInfoNV* pOpticalFlowImageFormatInfo, uint32_t* pFormatCount, VkOpticalFlowImageFormatPropertiesNV* pImageFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateOpticalFlowSessionNV)(VkDevice device, const VkOpticalFlowSessionCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkOpticalFlowSessionNV* pSession); +typedef void (VKAPI_PTR *PFN_vkDestroyOpticalFlowSessionNV)(VkDevice device, VkOpticalFlowSessionNV session, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkBindOpticalFlowSessionImageNV)(VkDevice device, VkOpticalFlowSessionNV session, VkOpticalFlowSessionBindingPointNV bindingPoint, VkImageView view, VkImageLayout layout); +typedef void (VKAPI_PTR *PFN_vkCmdOpticalFlowExecuteNV)(VkCommandBuffer commandBuffer, VkOpticalFlowSessionNV session, const VkOpticalFlowExecuteInfoNV* pExecuteInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceOpticalFlowImageFormatsNV( + VkPhysicalDevice physicalDevice, + const VkOpticalFlowImageFormatInfoNV* pOpticalFlowImageFormatInfo, + uint32_t* pFormatCount, + VkOpticalFlowImageFormatPropertiesNV* pImageFormatProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateOpticalFlowSessionNV( + VkDevice device, + const VkOpticalFlowSessionCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkOpticalFlowSessionNV* pSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyOpticalFlowSessionNV( + VkDevice device, + VkOpticalFlowSessionNV session, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindOpticalFlowSessionImageNV( + VkDevice device, + VkOpticalFlowSessionNV session, + VkOpticalFlowSessionBindingPointNV bindingPoint, + VkImageView view, + VkImageLayout layout); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdOpticalFlowExecuteNV( + VkCommandBuffer commandBuffer, + VkOpticalFlowSessionNV session, + const VkOpticalFlowExecuteInfoNV* pExecuteInfo); +#endif +#endif + + +// VK_EXT_legacy_dithering is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_legacy_dithering 1 +#define VK_EXT_LEGACY_DITHERING_SPEC_VERSION 2 +#define VK_EXT_LEGACY_DITHERING_EXTENSION_NAME "VK_EXT_legacy_dithering" +typedef struct VkPhysicalDeviceLegacyDitheringFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 legacyDithering; +} VkPhysicalDeviceLegacyDitheringFeaturesEXT; + + + +// VK_EXT_pipeline_protected_access is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_protected_access 1 +#define VK_EXT_PIPELINE_PROTECTED_ACCESS_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_PROTECTED_ACCESS_EXTENSION_NAME "VK_EXT_pipeline_protected_access" +typedef VkPhysicalDevicePipelineProtectedAccessFeatures VkPhysicalDevicePipelineProtectedAccessFeaturesEXT; + + + +// VK_AMD_anti_lag is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_anti_lag 1 +#define VK_AMD_ANTI_LAG_SPEC_VERSION 1 +#define VK_AMD_ANTI_LAG_EXTENSION_NAME "VK_AMD_anti_lag" + +typedef enum VkAntiLagModeAMD { + VK_ANTI_LAG_MODE_DRIVER_CONTROL_AMD = 0, + VK_ANTI_LAG_MODE_ON_AMD = 1, + VK_ANTI_LAG_MODE_OFF_AMD = 2, + VK_ANTI_LAG_MODE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkAntiLagModeAMD; + +typedef enum VkAntiLagStageAMD { + VK_ANTI_LAG_STAGE_INPUT_AMD = 0, + VK_ANTI_LAG_STAGE_PRESENT_AMD = 1, + VK_ANTI_LAG_STAGE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkAntiLagStageAMD; +typedef struct VkPhysicalDeviceAntiLagFeaturesAMD { + VkStructureType sType; + void* pNext; + VkBool32 antiLag; +} VkPhysicalDeviceAntiLagFeaturesAMD; + +typedef struct VkAntiLagPresentationInfoAMD { + VkStructureType sType; + void* pNext; + VkAntiLagStageAMD stage; + uint64_t frameIndex; +} VkAntiLagPresentationInfoAMD; + +typedef struct VkAntiLagDataAMD { + VkStructureType sType; + const void* pNext; + VkAntiLagModeAMD mode; + uint32_t maxFPS; + const VkAntiLagPresentationInfoAMD* pPresentationInfo; +} VkAntiLagDataAMD; + +typedef void (VKAPI_PTR *PFN_vkAntiLagUpdateAMD)(VkDevice device, const VkAntiLagDataAMD* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkAntiLagUpdateAMD( + VkDevice device, + const VkAntiLagDataAMD* pData); +#endif +#endif + + +// VK_EXT_shader_object is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_object 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderEXT) +#define VK_EXT_SHADER_OBJECT_SPEC_VERSION 1 +#define VK_EXT_SHADER_OBJECT_EXTENSION_NAME "VK_EXT_shader_object" + +typedef enum VkShaderCodeTypeEXT { + VK_SHADER_CODE_TYPE_BINARY_EXT = 0, + VK_SHADER_CODE_TYPE_SPIRV_EXT = 1, + VK_SHADER_CODE_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkShaderCodeTypeEXT; + +typedef enum VkDepthClampModeEXT { + VK_DEPTH_CLAMP_MODE_VIEWPORT_RANGE_EXT = 0, + VK_DEPTH_CLAMP_MODE_USER_DEFINED_RANGE_EXT = 1, + VK_DEPTH_CLAMP_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDepthClampModeEXT; + +typedef enum VkShaderCreateFlagBitsEXT { + VK_SHADER_CREATE_LINK_STAGE_BIT_EXT = 0x00000001, + VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT = 0x00000400, + VK_SHADER_CREATE_INSTRUMENT_SHADER_BIT_ARM = 0x00000800, + VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = 0x00000002, + VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = 0x00000004, + VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT = 0x00000008, + VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT = 0x00000010, + VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT = 0x00000020, + VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00000040, + VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT = 0x00000080, + VK_SHADER_CREATE_OPACITY_MICROMAP_DISALLOW_MIXED_SPECIAL_INDEX_BIT_EXT = 0x00001000, + VK_SHADER_CREATE_64_BIT_INDEXING_BIT_EXT = 0x00008000, + VK_SHADER_CREATE_INDEPENDENT_SETS_BIT_KHR = 0x00040000, + VK_SHADER_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkShaderCreateFlagBitsEXT; +typedef VkFlags VkShaderCreateFlagsEXT; +typedef struct VkPhysicalDeviceShaderObjectFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderObject; +} VkPhysicalDeviceShaderObjectFeaturesEXT; + +typedef struct VkPhysicalDeviceShaderObjectPropertiesEXT { + VkStructureType sType; + void* pNext; + uint8_t shaderBinaryUUID[VK_UUID_SIZE]; + uint32_t shaderBinaryVersion; +} VkPhysicalDeviceShaderObjectPropertiesEXT; + +typedef struct VkShaderCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkShaderCreateFlagsEXT flags; + VkShaderStageFlagBits stage; + VkShaderStageFlags nextStage; + VkShaderCodeTypeEXT codeType; + size_t codeSize; + const void* pCode; + const char* pName; + uint32_t setLayoutCount; + const VkDescriptorSetLayout* pSetLayouts; + uint32_t pushConstantRangeCount; + const VkPushConstantRange* pPushConstantRanges; + const VkSpecializationInfo* pSpecializationInfo; +} VkShaderCreateInfoEXT; + +typedef VkPipelineShaderStageRequiredSubgroupSizeCreateInfo VkShaderRequiredSubgroupSizeCreateInfoEXT; + +typedef struct VkDepthClampRangeEXT { + float minDepthClamp; + float maxDepthClamp; +} VkDepthClampRangeEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateShadersEXT)(VkDevice device, uint32_t createInfoCount, const VkShaderCreateInfoEXT* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkShaderEXT* pShaders); +typedef void (VKAPI_PTR *PFN_vkDestroyShaderEXT)(VkDevice device, VkShaderEXT shader, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetShaderBinaryDataEXT)(VkDevice device, VkShaderEXT shader, size_t* pDataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdBindShadersEXT)(VkCommandBuffer commandBuffer, uint32_t stageCount, const VkShaderStageFlagBits* pStages, const VkShaderEXT* pShaders); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthClampRangeEXT)(VkCommandBuffer commandBuffer, VkDepthClampModeEXT depthClampMode, const VkDepthClampRangeEXT* pDepthClampRange); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateShadersEXT( + VkDevice device, + uint32_t createInfoCount, + const VkShaderCreateInfoEXT* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkShaderEXT* pShaders); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyShaderEXT( + VkDevice device, + VkShaderEXT shader, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderBinaryDataEXT( + VkDevice device, + VkShaderEXT shader, + size_t* pDataSize, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindShadersEXT( + VkCommandBuffer commandBuffer, + uint32_t stageCount, + const VkShaderStageFlagBits* pStages, + const VkShaderEXT* pShaders); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClampRangeEXT( + VkCommandBuffer commandBuffer, + VkDepthClampModeEXT depthClampMode, + const VkDepthClampRangeEXT* pDepthClampRange); +#endif +#endif + + +// VK_QCOM_tile_properties is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_tile_properties 1 +#define VK_QCOM_TILE_PROPERTIES_SPEC_VERSION 1 +#define VK_QCOM_TILE_PROPERTIES_EXTENSION_NAME "VK_QCOM_tile_properties" +typedef struct VkPhysicalDeviceTilePropertiesFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 tileProperties; +} VkPhysicalDeviceTilePropertiesFeaturesQCOM; + +typedef struct VkTilePropertiesQCOM { + VkStructureType sType; + void* pNext; + VkExtent3D tileSize; + VkExtent2D apronSize; + VkOffset2D origin; +} VkTilePropertiesQCOM; + +typedef VkResult (VKAPI_PTR *PFN_vkGetFramebufferTilePropertiesQCOM)(VkDevice device, VkFramebuffer framebuffer, uint32_t* pPropertiesCount, VkTilePropertiesQCOM* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDynamicRenderingTilePropertiesQCOM)(VkDevice device, const VkRenderingInfo* pRenderingInfo, VkTilePropertiesQCOM* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetFramebufferTilePropertiesQCOM( + VkDevice device, + VkFramebuffer framebuffer, + uint32_t* pPropertiesCount, + VkTilePropertiesQCOM* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDynamicRenderingTilePropertiesQCOM( + VkDevice device, + const VkRenderingInfo* pRenderingInfo, + VkTilePropertiesQCOM* pProperties); +#endif +#endif + + +// VK_SEC_amigo_profiling is a preprocessor guard. Do not pass it to API calls. +#define VK_SEC_amigo_profiling 1 +#define VK_SEC_AMIGO_PROFILING_SPEC_VERSION 1 +#define VK_SEC_AMIGO_PROFILING_EXTENSION_NAME "VK_SEC_amigo_profiling" +typedef struct VkPhysicalDeviceAmigoProfilingFeaturesSEC { + VkStructureType sType; + void* pNext; + VkBool32 amigoProfiling; +} VkPhysicalDeviceAmigoProfilingFeaturesSEC; + +typedef struct VkAmigoProfilingSubmitInfoSEC { + VkStructureType sType; + const void* pNext; + uint64_t firstDrawTimestamp; + uint64_t swapBufferTimestamp; +} VkAmigoProfilingSubmitInfoSEC; + + + +// VK_QCOM_multiview_per_view_viewports is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_multiview_per_view_viewports 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_VIEWPORTS_SPEC_VERSION 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_VIEWPORTS_EXTENSION_NAME "VK_QCOM_multiview_per_view_viewports" +typedef struct VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 multiviewPerViewViewports; +} VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM; + + + +// VK_NV_ray_tracing_invocation_reorder is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_ray_tracing_invocation_reorder 1 +#define VK_NV_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION 1 +#define VK_NV_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME "VK_NV_ray_tracing_invocation_reorder" + +typedef enum VkRayTracingInvocationReorderModeEXT { + VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_EXT = 0, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_EXT = 1, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_NV = VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_EXT, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_NV = VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_EXT, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkRayTracingInvocationReorderModeEXT; +typedef VkRayTracingInvocationReorderModeEXT VkRayTracingInvocationReorderModeNV; + +typedef struct VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV { + VkStructureType sType; + void* pNext; + VkRayTracingInvocationReorderModeEXT rayTracingInvocationReorderReorderingHint; +} VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV; + +typedef struct VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingInvocationReorder; +} VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV; + + + +// VK_NV_cooperative_vector is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cooperative_vector 1 +#define VK_NV_COOPERATIVE_VECTOR_SPEC_VERSION 4 +#define VK_NV_COOPERATIVE_VECTOR_EXTENSION_NAME "VK_NV_cooperative_vector" + +typedef enum VkCooperativeVectorMatrixLayoutNV { + VK_COOPERATIVE_VECTOR_MATRIX_LAYOUT_ROW_MAJOR_NV = 0, + VK_COOPERATIVE_VECTOR_MATRIX_LAYOUT_COLUMN_MAJOR_NV = 1, + VK_COOPERATIVE_VECTOR_MATRIX_LAYOUT_INFERENCING_OPTIMAL_NV = 2, + VK_COOPERATIVE_VECTOR_MATRIX_LAYOUT_TRAINING_OPTIMAL_NV = 3, + VK_COOPERATIVE_VECTOR_MATRIX_LAYOUT_MAX_ENUM_NV = 0x7FFFFFFF +} VkCooperativeVectorMatrixLayoutNV; +typedef struct VkPhysicalDeviceCooperativeVectorPropertiesNV { + VkStructureType sType; + void* pNext; + VkShaderStageFlags cooperativeVectorSupportedStages; + VkBool32 cooperativeVectorTrainingFloat16Accumulation; + VkBool32 cooperativeVectorTrainingFloat32Accumulation; + uint32_t maxCooperativeVectorComponents; +} VkPhysicalDeviceCooperativeVectorPropertiesNV; + +typedef struct VkPhysicalDeviceCooperativeVectorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeVector; + VkBool32 cooperativeVectorTraining; +} VkPhysicalDeviceCooperativeVectorFeaturesNV; + +typedef struct VkCooperativeVectorPropertiesNV { + VkStructureType sType; + void* pNext; + VkComponentTypeKHR inputType; + VkComponentTypeKHR inputInterpretation; + VkComponentTypeKHR matrixInterpretation; + VkComponentTypeKHR biasInterpretation; + VkComponentTypeKHR resultType; + VkBool32 transpose; +} VkCooperativeVectorPropertiesNV; + +typedef struct VkConvertCooperativeVectorMatrixInfoNV { + VkStructureType sType; + const void* pNext; + size_t srcSize; + VkDeviceOrHostAddressConstKHR srcData; + size_t* pDstSize; + VkDeviceOrHostAddressKHR dstData; + VkComponentTypeKHR srcComponentType; + VkComponentTypeKHR dstComponentType; + uint32_t numRows; + uint32_t numColumns; + VkCooperativeVectorMatrixLayoutNV srcLayout; + size_t srcStride; + VkCooperativeVectorMatrixLayoutNV dstLayout; + size_t dstStride; +} VkConvertCooperativeVectorMatrixInfoNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeVectorPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeVectorPropertiesNV* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkConvertCooperativeVectorMatrixNV)(VkDevice device, const VkConvertCooperativeVectorMatrixInfoNV* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdConvertCooperativeVectorMatrixNV)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkConvertCooperativeVectorMatrixInfoNV* pInfos); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeVectorPropertiesNV( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkCooperativeVectorPropertiesNV* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkConvertCooperativeVectorMatrixNV( + VkDevice device, + const VkConvertCooperativeVectorMatrixInfoNV* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdConvertCooperativeVectorMatrixNV( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkConvertCooperativeVectorMatrixInfoNV* pInfos); +#endif +#endif + + +// VK_NV_extended_sparse_address_space is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_extended_sparse_address_space 1 +#define VK_NV_EXTENDED_SPARSE_ADDRESS_SPACE_SPEC_VERSION 1 +#define VK_NV_EXTENDED_SPARSE_ADDRESS_SPACE_EXTENSION_NAME "VK_NV_extended_sparse_address_space" +typedef struct VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 extendedSparseAddressSpace; +} VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV; + +typedef struct VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV { + VkStructureType sType; + void* pNext; + VkDeviceSize extendedSparseAddressSpaceSize; + VkImageUsageFlags extendedSparseImageUsageFlags; + VkBufferUsageFlags extendedSparseBufferUsageFlags; +} VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV; + + + +// VK_EXT_mutable_descriptor_type is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_mutable_descriptor_type 1 +#define VK_EXT_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 +#define VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_EXT_mutable_descriptor_type" + + +// VK_EXT_legacy_vertex_attributes is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_legacy_vertex_attributes 1 +#define VK_EXT_LEGACY_VERTEX_ATTRIBUTES_SPEC_VERSION 1 +#define VK_EXT_LEGACY_VERTEX_ATTRIBUTES_EXTENSION_NAME "VK_EXT_legacy_vertex_attributes" +typedef struct VkPhysicalDeviceLegacyVertexAttributesFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 legacyVertexAttributes; +} VkPhysicalDeviceLegacyVertexAttributesFeaturesEXT; + +typedef struct VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 nativeUnalignedPerformance; +} VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT; + + + +// VK_EXT_layer_settings is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_layer_settings 1 +#define VK_EXT_LAYER_SETTINGS_SPEC_VERSION 2 +#define VK_EXT_LAYER_SETTINGS_EXTENSION_NAME "VK_EXT_layer_settings" + +typedef enum VkLayerSettingTypeEXT { + VK_LAYER_SETTING_TYPE_BOOL32_EXT = 0, + VK_LAYER_SETTING_TYPE_INT32_EXT = 1, + VK_LAYER_SETTING_TYPE_INT64_EXT = 2, + VK_LAYER_SETTING_TYPE_UINT32_EXT = 3, + VK_LAYER_SETTING_TYPE_UINT64_EXT = 4, + VK_LAYER_SETTING_TYPE_FLOAT32_EXT = 5, + VK_LAYER_SETTING_TYPE_FLOAT64_EXT = 6, + VK_LAYER_SETTING_TYPE_STRING_EXT = 7, + VK_LAYER_SETTING_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkLayerSettingTypeEXT; +typedef struct VkLayerSettingEXT { + const char* pLayerName; + const char* pSettingName; + VkLayerSettingTypeEXT type; + uint32_t valueCount; + const void* pValues; +} VkLayerSettingEXT; + +typedef struct VkLayerSettingsCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t settingCount; + const VkLayerSettingEXT* pSettings; +} VkLayerSettingsCreateInfoEXT; + + + +// VK_ARM_shader_core_builtins is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_shader_core_builtins 1 +#define VK_ARM_SHADER_CORE_BUILTINS_SPEC_VERSION 2 +#define VK_ARM_SHADER_CORE_BUILTINS_EXTENSION_NAME "VK_ARM_shader_core_builtins" +typedef struct VkPhysicalDeviceShaderCoreBuiltinsFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 shaderCoreBuiltins; +} VkPhysicalDeviceShaderCoreBuiltinsFeaturesARM; + +typedef struct VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM { + VkStructureType sType; + void* pNext; + uint64_t shaderCoreMask; + uint32_t shaderCoreCount; + uint32_t shaderWarpsPerCore; +} VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM; + + + +// VK_EXT_pipeline_library_group_handles is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_pipeline_library_group_handles 1 +#define VK_EXT_PIPELINE_LIBRARY_GROUP_HANDLES_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_LIBRARY_GROUP_HANDLES_EXTENSION_NAME "VK_EXT_pipeline_library_group_handles" +typedef struct VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pipelineLibraryGroupHandles; +} VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT; + + + +// VK_EXT_dynamic_rendering_unused_attachments is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_dynamic_rendering_unused_attachments 1 +#define VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_SPEC_VERSION 1 +#define VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME "VK_EXT_dynamic_rendering_unused_attachments" +typedef struct VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRenderingUnusedAttachments; +} VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT; + + + +// VK_NV_low_latency2 is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_low_latency2 1 +#define VK_NV_LOW_LATENCY_2_SPEC_VERSION 2 +#define VK_NV_LOW_LATENCY_2_EXTENSION_NAME "VK_NV_low_latency2" + +typedef enum VkLatencyMarkerNV { + VK_LATENCY_MARKER_SIMULATION_START_NV = 0, + VK_LATENCY_MARKER_SIMULATION_END_NV = 1, + VK_LATENCY_MARKER_RENDERSUBMIT_START_NV = 2, + VK_LATENCY_MARKER_RENDERSUBMIT_END_NV = 3, + VK_LATENCY_MARKER_PRESENT_START_NV = 4, + VK_LATENCY_MARKER_PRESENT_END_NV = 5, + VK_LATENCY_MARKER_INPUT_SAMPLE_NV = 6, + VK_LATENCY_MARKER_TRIGGER_FLASH_NV = 7, + VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_START_NV = 8, + VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_END_NV = 9, + VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_START_NV = 10, + VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_END_NV = 11, + VK_LATENCY_MARKER_MAX_ENUM_NV = 0x7FFFFFFF +} VkLatencyMarkerNV; + +typedef enum VkOutOfBandQueueTypeNV { + VK_OUT_OF_BAND_QUEUE_TYPE_RENDER_NV = 0, + VK_OUT_OF_BAND_QUEUE_TYPE_PRESENT_NV = 1, + VK_OUT_OF_BAND_QUEUE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkOutOfBandQueueTypeNV; +typedef struct VkLatencySleepModeInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 lowLatencyMode; + VkBool32 lowLatencyBoost; + uint32_t minimumIntervalUs; +} VkLatencySleepModeInfoNV; + +typedef struct VkLatencySleepInfoNV { + VkStructureType sType; + const void* pNext; + VkSemaphore signalSemaphore; + uint64_t value; +} VkLatencySleepInfoNV; + +typedef struct VkSetLatencyMarkerInfoNV { + VkStructureType sType; + const void* pNext; + uint64_t presentID; + VkLatencyMarkerNV marker; +} VkSetLatencyMarkerInfoNV; + +typedef struct VkLatencyTimingsFrameReportNV { + VkStructureType sType; + void* pNext; + uint64_t presentID; + uint64_t inputSampleTimeUs; + uint64_t simStartTimeUs; + uint64_t simEndTimeUs; + uint64_t renderSubmitStartTimeUs; + uint64_t renderSubmitEndTimeUs; + uint64_t presentStartTimeUs; + uint64_t presentEndTimeUs; + uint64_t driverStartTimeUs; + uint64_t driverEndTimeUs; + uint64_t osRenderQueueStartTimeUs; + uint64_t osRenderQueueEndTimeUs; + uint64_t gpuRenderStartTimeUs; + uint64_t gpuRenderEndTimeUs; +} VkLatencyTimingsFrameReportNV; + +typedef struct VkGetLatencyMarkerInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t timingCount; + VkLatencyTimingsFrameReportNV* pTimings; +} VkGetLatencyMarkerInfoNV; + +typedef struct VkLatencySubmissionPresentIdNV { + VkStructureType sType; + const void* pNext; + uint64_t presentID; +} VkLatencySubmissionPresentIdNV; + +typedef struct VkSwapchainLatencyCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 latencyModeEnable; +} VkSwapchainLatencyCreateInfoNV; + +typedef struct VkOutOfBandQueueTypeInfoNV { + VkStructureType sType; + const void* pNext; + VkOutOfBandQueueTypeNV queueType; +} VkOutOfBandQueueTypeInfoNV; + +typedef struct VkLatencySurfaceCapabilitiesNV { + VkStructureType sType; + const void* pNext; + uint32_t presentModeCount; + VkPresentModeKHR* pPresentModes; +} VkLatencySurfaceCapabilitiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkSetLatencySleepModeNV)(VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepModeInfoNV* pSleepModeInfo); +typedef VkResult (VKAPI_PTR *PFN_vkLatencySleepNV)(VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepInfoNV* pSleepInfo); +typedef void (VKAPI_PTR *PFN_vkSetLatencyMarkerNV)(VkDevice device, VkSwapchainKHR swapchain, const VkSetLatencyMarkerInfoNV* pLatencyMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkGetLatencyTimingsNV)(VkDevice device, VkSwapchainKHR swapchain, VkGetLatencyMarkerInfoNV* pLatencyMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkQueueNotifyOutOfBandNV)(VkQueue queue, const VkOutOfBandQueueTypeInfoNV* pQueueTypeInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetLatencySleepModeNV( + VkDevice device, + VkSwapchainKHR swapchain, + const VkLatencySleepModeInfoNV* pSleepModeInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkLatencySleepNV( + VkDevice device, + VkSwapchainKHR swapchain, + const VkLatencySleepInfoNV* pSleepInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetLatencyMarkerNV( + VkDevice device, + VkSwapchainKHR swapchain, + const VkSetLatencyMarkerInfoNV* pLatencyMarkerInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetLatencyTimingsNV( + VkDevice device, + VkSwapchainKHR swapchain, + VkGetLatencyMarkerInfoNV* pLatencyMarkerInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkQueueNotifyOutOfBandNV( + VkQueue queue, + const VkOutOfBandQueueTypeInfoNV* pQueueTypeInfo); +#endif +#endif + + +// VK_ARM_data_graph is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_data_graph 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDataGraphPipelineSessionARM) +#define VK_MAX_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_SET_NAME_SIZE_ARM 128U +#define VK_ARM_DATA_GRAPH_SPEC_VERSION 1 +#define VK_ARM_DATA_GRAPH_EXTENSION_NAME "VK_ARM_data_graph" + +typedef enum VkDataGraphPipelineSessionBindPointARM { + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_TRANSIENT_ARM = 0, + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_OPTICAL_FLOW_CACHE_ARM = 1000631001, + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_NEURAL_ACCELERATOR_STATISTICS_ARM = 1000676000, + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelineSessionBindPointARM; + +typedef enum VkDataGraphPipelineSessionBindPointTypeARM { + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_TYPE_MEMORY_ARM = 0, + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelineSessionBindPointTypeARM; + +typedef enum VkDataGraphPipelinePropertyARM { + VK_DATA_GRAPH_PIPELINE_PROPERTY_CREATION_LOG_ARM = 0, + VK_DATA_GRAPH_PIPELINE_PROPERTY_IDENTIFIER_ARM = 1, + VK_DATA_GRAPH_PIPELINE_PROPERTY_NEURAL_ACCELERATOR_DEBUG_DATABASE_ARM = 1000676000, + VK_DATA_GRAPH_PIPELINE_PROPERTY_NEURAL_ACCELERATOR_STATISTICS_INFO_ARM = 1000676001, + VK_DATA_GRAPH_PIPELINE_PROPERTY_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelinePropertyARM; + +typedef enum VkPhysicalDeviceDataGraphProcessingEngineTypeARM { + VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_DEFAULT_ARM = 0, + VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_NEURAL_QCOM = 1000629000, + VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_COMPUTE_QCOM = 1000629001, + VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkPhysicalDeviceDataGraphProcessingEngineTypeARM; + +typedef enum VkPhysicalDeviceDataGraphOperationTypeARM { + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_SPIRV_EXTENDED_INSTRUCTION_SET_ARM = 0, + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_NEURAL_MODEL_QCOM = 1000629000, + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_BUILTIN_MODEL_QCOM = 1000629001, + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_OPTICAL_FLOW_ARM = 1000631000, + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkPhysicalDeviceDataGraphOperationTypeARM; +typedef VkFlags64 VkDataGraphPipelineSessionCreateFlagsARM; + +// Flag bits for VkDataGraphPipelineSessionCreateFlagBitsARM +typedef VkFlags64 VkDataGraphPipelineSessionCreateFlagBitsARM; +static const VkDataGraphPipelineSessionCreateFlagBitsARM VK_DATA_GRAPH_PIPELINE_SESSION_CREATE_PROTECTED_BIT_ARM = 0x00000001ULL; +static const VkDataGraphPipelineSessionCreateFlagBitsARM VK_DATA_GRAPH_PIPELINE_SESSION_CREATE_OPTICAL_FLOW_CACHE_BIT_ARM = 0x00000002ULL; + +typedef VkFlags64 VkDataGraphPipelineDispatchFlagsARM; + +// Flag bits for VkDataGraphPipelineDispatchFlagBitsARM +typedef VkFlags64 VkDataGraphPipelineDispatchFlagBitsARM; + +typedef struct VkPhysicalDeviceDataGraphFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 dataGraph; + VkBool32 dataGraphUpdateAfterBind; + VkBool32 dataGraphSpecializationConstants; + VkBool32 dataGraphDescriptorBuffer; + VkBool32 dataGraphShaderModule; +} VkPhysicalDeviceDataGraphFeaturesARM; + +typedef struct VkDataGraphPipelineConstantARM { + VkStructureType sType; + const void* pNext; + uint32_t id; + const void* pConstantData; +} VkDataGraphPipelineConstantARM; + +typedef struct VkDataGraphPipelineResourceInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t descriptorSet; + uint32_t binding; + uint32_t arrayElement; +} VkDataGraphPipelineResourceInfoARM; + +typedef struct VkDataGraphPipelineCompilerControlCreateInfoARM { + VkStructureType sType; + const void* pNext; + const char* pVendorOptions; +} VkDataGraphPipelineCompilerControlCreateInfoARM; + +typedef struct VkDataGraphPipelineCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags2 flags; + VkPipelineLayout layout; + uint32_t resourceInfoCount; + const VkDataGraphPipelineResourceInfoARM* pResourceInfos; +} VkDataGraphPipelineCreateInfoARM; + +typedef struct VkDataGraphPipelineShaderModuleCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkShaderModule module; + const char* pName; + const VkSpecializationInfo* pSpecializationInfo; + uint32_t constantCount; + const VkDataGraphPipelineConstantARM* pConstants; +} VkDataGraphPipelineShaderModuleCreateInfoARM; + +typedef struct VkDataGraphPipelineSessionCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphPipelineSessionCreateFlagsARM flags; + VkPipeline dataGraphPipeline; +} VkDataGraphPipelineSessionCreateInfoARM; + +typedef struct VkDataGraphPipelineSessionBindPointRequirementsInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphPipelineSessionARM session; +} VkDataGraphPipelineSessionBindPointRequirementsInfoARM; + +typedef struct VkDataGraphPipelineSessionBindPointRequirementARM { + VkStructureType sType; + void* pNext; + VkDataGraphPipelineSessionBindPointARM bindPoint; + VkDataGraphPipelineSessionBindPointTypeARM bindPointType; + uint32_t numObjects; +} VkDataGraphPipelineSessionBindPointRequirementARM; + +typedef struct VkDataGraphPipelineSessionMemoryRequirementsInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphPipelineSessionARM session; + VkDataGraphPipelineSessionBindPointARM bindPoint; + uint32_t objectIndex; +} VkDataGraphPipelineSessionMemoryRequirementsInfoARM; + +typedef struct VkBindDataGraphPipelineSessionMemoryInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphPipelineSessionARM session; + VkDataGraphPipelineSessionBindPointARM bindPoint; + uint32_t objectIndex; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindDataGraphPipelineSessionMemoryInfoARM; + +typedef struct VkDataGraphPipelineInfoARM { + VkStructureType sType; + const void* pNext; + VkPipeline dataGraphPipeline; +} VkDataGraphPipelineInfoARM; + +typedef struct VkDataGraphPipelinePropertyQueryResultARM { + VkStructureType sType; + void* pNext; + VkDataGraphPipelinePropertyARM property; + VkBool32 isText; + size_t dataSize; + void* pData; +} VkDataGraphPipelinePropertyQueryResultARM; + +typedef struct VkDataGraphPipelineIdentifierCreateInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t identifierSize; + const uint8_t* pIdentifier; +} VkDataGraphPipelineIdentifierCreateInfoARM; + +typedef struct VkDataGraphPipelineDispatchInfoARM { + VkStructureType sType; + void* pNext; + VkDataGraphPipelineDispatchFlagsARM flags; +} VkDataGraphPipelineDispatchInfoARM; + +typedef struct VkPhysicalDeviceDataGraphProcessingEngineARM { + VkPhysicalDeviceDataGraphProcessingEngineTypeARM type; + VkBool32 isForeign; +} VkPhysicalDeviceDataGraphProcessingEngineARM; + +typedef struct VkPhysicalDeviceDataGraphOperationSupportARM { + VkPhysicalDeviceDataGraphOperationTypeARM operationType; + char name[VK_MAX_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_SET_NAME_SIZE_ARM]; + uint32_t version; +} VkPhysicalDeviceDataGraphOperationSupportARM; + +typedef struct VkQueueFamilyDataGraphPropertiesARM { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceDataGraphProcessingEngineARM engine; + VkPhysicalDeviceDataGraphOperationSupportARM operation; +} VkQueueFamilyDataGraphPropertiesARM; + +typedef struct VkDataGraphProcessingEngineCreateInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t processingEngineCount; + VkPhysicalDeviceDataGraphProcessingEngineARM* pProcessingEngines; +} VkDataGraphProcessingEngineCreateInfoARM; + +typedef struct VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + VkPhysicalDeviceDataGraphProcessingEngineTypeARM engineType; +} VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM; + +typedef struct VkQueueFamilyDataGraphProcessingEnginePropertiesARM { + VkStructureType sType; + void* pNext; + VkExternalSemaphoreHandleTypeFlags foreignSemaphoreHandleTypes; + VkExternalMemoryHandleTypeFlags foreignMemoryHandleTypes; +} VkQueueFamilyDataGraphProcessingEnginePropertiesARM; + +typedef struct VkDataGraphPipelineConstantTensorSemiStructuredSparsityInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t dimension; + uint32_t zeroCount; + uint32_t groupSize; +} VkDataGraphPipelineConstantTensorSemiStructuredSparsityInfoARM; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDataGraphPipelinesARM)(VkDevice device, VkDeferredOperationKHR deferredOperation, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkDataGraphPipelineCreateInfoARM* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDataGraphPipelineSessionARM)(VkDevice device, const VkDataGraphPipelineSessionCreateInfoARM* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDataGraphPipelineSessionARM* pSession); +typedef VkResult (VKAPI_PTR *PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM)(VkDevice device, const VkDataGraphPipelineSessionBindPointRequirementsInfoARM* pInfo, uint32_t* pBindPointRequirementCount, VkDataGraphPipelineSessionBindPointRequirementARM* pBindPointRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM)(VkDevice device, const VkDataGraphPipelineSessionMemoryRequirementsInfoARM* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindDataGraphPipelineSessionMemoryARM)(VkDevice device, uint32_t bindInfoCount, const VkBindDataGraphPipelineSessionMemoryInfoARM* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkDestroyDataGraphPipelineSessionARM)(VkDevice device, VkDataGraphPipelineSessionARM session, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchDataGraphARM)(VkCommandBuffer commandBuffer, VkDataGraphPipelineSessionARM session, const VkDataGraphPipelineDispatchInfoARM* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetDataGraphPipelineAvailablePropertiesARM)(VkDevice device, const VkDataGraphPipelineInfoARM* pPipelineInfo, uint32_t* pPropertiesCount, VkDataGraphPipelinePropertyARM* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDataGraphPipelinePropertiesARM)(VkDevice device, const VkDataGraphPipelineInfoARM* pPipelineInfo, uint32_t propertiesCount, VkDataGraphPipelinePropertyQueryResultARM* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pQueueFamilyDataGraphPropertyCount, VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM* pQueueFamilyDataGraphProcessingEngineInfo, VkQueueFamilyDataGraphProcessingEnginePropertiesARM* pQueueFamilyDataGraphProcessingEngineProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDataGraphPipelinesARM( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkDataGraphPipelineCreateInfoARM* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDataGraphPipelineSessionARM( + VkDevice device, + const VkDataGraphPipelineSessionCreateInfoARM* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDataGraphPipelineSessionARM* pSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDataGraphPipelineSessionBindPointRequirementsARM( + VkDevice device, + const VkDataGraphPipelineSessionBindPointRequirementsInfoARM* pInfo, + uint32_t* pBindPointRequirementCount, + VkDataGraphPipelineSessionBindPointRequirementARM* pBindPointRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDataGraphPipelineSessionMemoryRequirementsARM( + VkDevice device, + const VkDataGraphPipelineSessionMemoryRequirementsInfoARM* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindDataGraphPipelineSessionMemoryARM( + VkDevice device, + uint32_t bindInfoCount, + const VkBindDataGraphPipelineSessionMemoryInfoARM* pBindInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyDataGraphPipelineSessionARM( + VkDevice device, + VkDataGraphPipelineSessionARM session, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchDataGraphARM( + VkCommandBuffer commandBuffer, + VkDataGraphPipelineSessionARM session, + const VkDataGraphPipelineDispatchInfoARM* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDataGraphPipelineAvailablePropertiesARM( + VkDevice device, + const VkDataGraphPipelineInfoARM* pPipelineInfo, + uint32_t* pPropertiesCount, + VkDataGraphPipelinePropertyARM* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDataGraphPipelinePropertiesARM( + VkDevice device, + const VkDataGraphPipelineInfoARM* pPipelineInfo, + uint32_t propertiesCount, + VkDataGraphPipelinePropertyQueryResultARM* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + uint32_t* pQueueFamilyDataGraphPropertyCount, + VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM* pQueueFamilyDataGraphProcessingEngineInfo, + VkQueueFamilyDataGraphProcessingEnginePropertiesARM* pQueueFamilyDataGraphProcessingEngineProperties); +#endif +#endif + + +// VK_ARM_data_graph_instruction_set_tosa is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_data_graph_instruction_set_tosa 1 +#define VK_MAX_DATA_GRAPH_TOSA_NAME_SIZE_ARM 128U +#define VK_ARM_DATA_GRAPH_INSTRUCTION_SET_TOSA_SPEC_VERSION 1 +#define VK_ARM_DATA_GRAPH_INSTRUCTION_SET_TOSA_EXTENSION_NAME "VK_ARM_data_graph_instruction_set_tosa" + +typedef enum VkDataGraphTOSALevelARM { + VK_DATA_GRAPH_TOSA_LEVEL_NONE_ARM = 0, + VK_DATA_GRAPH_TOSA_LEVEL_8K_ARM = 1, + VK_DATA_GRAPH_TOSALEVEL_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphTOSALevelARM; + +typedef enum VkDataGraphTOSAQualityFlagBitsARM { + VK_DATA_GRAPH_TOSA_QUALITY_ACCELERATED_ARM = 0x00000001, + VK_DATA_GRAPH_TOSA_QUALITY_CONFORMANT_ARM = 0x00000002, + VK_DATA_GRAPH_TOSA_QUALITY_EXPERIMENTAL_ARM = 0x00000004, + VK_DATA_GRAPH_TOSA_QUALITY_DEPRECATED_ARM = 0x00000008, + VK_DATA_GRAPH_TOSAQUALITY_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphTOSAQualityFlagBitsARM; +typedef VkFlags VkDataGraphTOSAQualityFlagsARM; +typedef struct VkDataGraphTOSANameQualityARM { + char name[VK_MAX_DATA_GRAPH_TOSA_NAME_SIZE_ARM]; + VkDataGraphTOSAQualityFlagsARM qualityFlags; +} VkDataGraphTOSANameQualityARM; + +typedef struct VkQueueFamilyDataGraphTOSAPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t profileCount; + const VkDataGraphTOSANameQualityARM* pProfiles; + uint32_t extensionCount; + const VkDataGraphTOSANameQualityARM* pExtensions; + VkDataGraphTOSALevelARM level; +} VkQueueFamilyDataGraphTOSAPropertiesARM; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties, VkBaseOutStructure* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + const VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties, + VkBaseOutStructure* pProperties); +#endif +#endif + + +// VK_QCOM_multiview_per_view_render_areas is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_multiview_per_view_render_areas 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_SPEC_VERSION 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_EXTENSION_NAME "VK_QCOM_multiview_per_view_render_areas" +typedef struct VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 multiviewPerViewRenderAreas; +} VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM; + +typedef struct VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { + VkStructureType sType; + const void* pNext; + uint32_t perViewRenderAreaCount; + const VkRect2D* pPerViewRenderAreas; +} VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM; + + + +// VK_NV_per_stage_descriptor_set is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_per_stage_descriptor_set 1 +#define VK_NV_PER_STAGE_DESCRIPTOR_SET_SPEC_VERSION 1 +#define VK_NV_PER_STAGE_DESCRIPTOR_SET_EXTENSION_NAME "VK_NV_per_stage_descriptor_set" +typedef struct VkPhysicalDevicePerStageDescriptorSetFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 perStageDescriptorSet; + VkBool32 dynamicPipelineLayout; +} VkPhysicalDevicePerStageDescriptorSetFeaturesNV; + + + +// VK_QCOM_image_processing2 is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_image_processing2 1 +#define VK_QCOM_IMAGE_PROCESSING_2_SPEC_VERSION 1 +#define VK_QCOM_IMAGE_PROCESSING_2_EXTENSION_NAME "VK_QCOM_image_processing2" + +typedef enum VkBlockMatchWindowCompareModeQCOM { + VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MIN_QCOM = 0, + VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_QCOM = 1, + VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkBlockMatchWindowCompareModeQCOM; +typedef struct VkPhysicalDeviceImageProcessing2FeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 textureBlockMatch2; +} VkPhysicalDeviceImageProcessing2FeaturesQCOM; + +typedef struct VkPhysicalDeviceImageProcessing2PropertiesQCOM { + VkStructureType sType; + void* pNext; + VkExtent2D maxBlockMatchWindow; +} VkPhysicalDeviceImageProcessing2PropertiesQCOM; + +typedef struct VkSamplerBlockMatchWindowCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + VkExtent2D windowExtent; + VkBlockMatchWindowCompareModeQCOM windowCompareMode; +} VkSamplerBlockMatchWindowCreateInfoQCOM; + + + +// VK_QCOM_filter_cubic_weights is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_filter_cubic_weights 1 +#define VK_QCOM_FILTER_CUBIC_WEIGHTS_SPEC_VERSION 1 +#define VK_QCOM_FILTER_CUBIC_WEIGHTS_EXTENSION_NAME "VK_QCOM_filter_cubic_weights" + +typedef enum VkCubicFilterWeightsQCOM { + VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM = 0, + VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM = 1, + VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM = 2, + VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM = 3, + VK_CUBIC_FILTER_WEIGHTS_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkCubicFilterWeightsQCOM; +typedef struct VkPhysicalDeviceCubicWeightsFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 selectableCubicWeights; +} VkPhysicalDeviceCubicWeightsFeaturesQCOM; + +typedef struct VkSamplerCubicWeightsCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + VkCubicFilterWeightsQCOM cubicWeights; +} VkSamplerCubicWeightsCreateInfoQCOM; + +typedef struct VkBlitImageCubicWeightsInfoQCOM { + VkStructureType sType; + const void* pNext; + VkCubicFilterWeightsQCOM cubicWeights; +} VkBlitImageCubicWeightsInfoQCOM; + + + +// VK_QCOM_ycbcr_degamma is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_ycbcr_degamma 1 +#define VK_QCOM_YCBCR_DEGAMMA_SPEC_VERSION 1 +#define VK_QCOM_YCBCR_DEGAMMA_EXTENSION_NAME "VK_QCOM_ycbcr_degamma" +typedef struct VkPhysicalDeviceYcbcrDegammaFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 ycbcrDegamma; +} VkPhysicalDeviceYcbcrDegammaFeaturesQCOM; + +typedef struct VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM { + VkStructureType sType; + void* pNext; + VkBool32 enableYDegamma; + VkBool32 enableCbCrDegamma; +} VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM; + + + +// VK_QCOM_filter_cubic_clamp is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_filter_cubic_clamp 1 +#define VK_QCOM_FILTER_CUBIC_CLAMP_SPEC_VERSION 1 +#define VK_QCOM_FILTER_CUBIC_CLAMP_EXTENSION_NAME "VK_QCOM_filter_cubic_clamp" +typedef struct VkPhysicalDeviceCubicClampFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 cubicRangeClamp; +} VkPhysicalDeviceCubicClampFeaturesQCOM; + + + +// VK_EXT_attachment_feedback_loop_dynamic_state is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_attachment_feedback_loop_dynamic_state 1 +#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_SPEC_VERSION 1 +#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_attachment_feedback_loop_dynamic_state" +typedef struct VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 attachmentFeedbackLoopDynamicState; +} VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)(VkCommandBuffer commandBuffer, VkImageAspectFlags aspectMask); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetAttachmentFeedbackLoopEnableEXT( + VkCommandBuffer commandBuffer, + VkImageAspectFlags aspectMask); +#endif +#endif + + +// VK_MSFT_layered_driver is a preprocessor guard. Do not pass it to API calls. +#define VK_MSFT_layered_driver 1 +#define VK_MSFT_LAYERED_DRIVER_SPEC_VERSION 1 +#define VK_MSFT_LAYERED_DRIVER_EXTENSION_NAME "VK_MSFT_layered_driver" + +typedef enum VkLayeredDriverUnderlyingApiMSFT { + VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT = 0, + VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT = 1, + VK_LAYERED_DRIVER_UNDERLYING_API_MAX_ENUM_MSFT = 0x7FFFFFFF +} VkLayeredDriverUnderlyingApiMSFT; +typedef struct VkPhysicalDeviceLayeredDriverPropertiesMSFT { + VkStructureType sType; + void* pNext; + VkLayeredDriverUnderlyingApiMSFT underlyingAPI; +} VkPhysicalDeviceLayeredDriverPropertiesMSFT; + + + +// VK_NV_descriptor_pool_overallocation is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_descriptor_pool_overallocation 1 +#define VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_SPEC_VERSION 1 +#define VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME "VK_NV_descriptor_pool_overallocation" +typedef struct VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 descriptorPoolOverallocation; +} VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV; + + + +// VK_QCOM_tile_memory_heap is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_tile_memory_heap 1 +#define VK_QCOM_TILE_MEMORY_HEAP_SPEC_VERSION 1 +#define VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME "VK_QCOM_tile_memory_heap" +typedef struct VkPhysicalDeviceTileMemoryHeapFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 tileMemoryHeap; +} VkPhysicalDeviceTileMemoryHeapFeaturesQCOM; + +typedef struct VkPhysicalDeviceTileMemoryHeapPropertiesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 queueSubmitBoundary; + VkBool32 tileBufferTransfers; +} VkPhysicalDeviceTileMemoryHeapPropertiesQCOM; + +typedef struct VkTileMemoryRequirementsQCOM { + VkStructureType sType; + void* pNext; + VkDeviceSize size; + VkDeviceSize alignment; +} VkTileMemoryRequirementsQCOM; + +typedef struct VkTileMemoryBindInfoQCOM { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; +} VkTileMemoryBindInfoQCOM; + +typedef struct VkTileMemorySizeInfoQCOM { + VkStructureType sType; + const void* pNext; + VkDeviceSize size; +} VkTileMemorySizeInfoQCOM; + +typedef void (VKAPI_PTR *PFN_vkCmdBindTileMemoryQCOM)(VkCommandBuffer commandBuffer, const VkTileMemoryBindInfoQCOM* pTileMemoryBindInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindTileMemoryQCOM( + VkCommandBuffer commandBuffer, + const VkTileMemoryBindInfoQCOM* pTileMemoryBindInfo); +#endif +#endif + + +// VK_EXT_memory_decompression is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_memory_decompression 1 +#define VK_EXT_MEMORY_DECOMPRESSION_SPEC_VERSION 1 +#define VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME "VK_EXT_memory_decompression" +typedef struct VkDecompressMemoryRegionEXT { + VkDeviceAddress srcAddress; + VkDeviceAddress dstAddress; + VkDeviceSize compressedSize; + VkDeviceSize decompressedSize; +} VkDecompressMemoryRegionEXT; + +typedef struct VkDecompressMemoryInfoEXT { + VkStructureType sType; + const void* pNext; + VkMemoryDecompressionMethodFlagsEXT decompressionMethod; + uint32_t regionCount; + const VkDecompressMemoryRegionEXT* pRegions; +} VkDecompressMemoryInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryEXT)(VkCommandBuffer commandBuffer, const VkDecompressMemoryInfoEXT* pDecompressMemoryInfoEXT); +typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryIndirectCountEXT)(VkCommandBuffer commandBuffer, VkMemoryDecompressionMethodFlagsEXT decompressionMethod, VkDeviceAddress indirectCommandsAddress, VkDeviceAddress indirectCommandsCountAddress, uint32_t maxDecompressionCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryEXT( + VkCommandBuffer commandBuffer, + const VkDecompressMemoryInfoEXT* pDecompressMemoryInfoEXT); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryIndirectCountEXT( + VkCommandBuffer commandBuffer, + VkMemoryDecompressionMethodFlagsEXT decompressionMethod, + VkDeviceAddress indirectCommandsAddress, + VkDeviceAddress indirectCommandsCountAddress, + uint32_t maxDecompressionCount, + uint32_t stride); +#endif +#endif + + +// VK_NV_display_stereo is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_display_stereo 1 +#define VK_NV_DISPLAY_STEREO_SPEC_VERSION 1 +#define VK_NV_DISPLAY_STEREO_EXTENSION_NAME "VK_NV_display_stereo" + +typedef enum VkDisplaySurfaceStereoTypeNV { + VK_DISPLAY_SURFACE_STEREO_TYPE_NONE_NV = 0, + VK_DISPLAY_SURFACE_STEREO_TYPE_ONBOARD_DIN_NV = 1, + VK_DISPLAY_SURFACE_STEREO_TYPE_HDMI_3D_NV = 2, + VK_DISPLAY_SURFACE_STEREO_TYPE_INBAND_DISPLAYPORT_NV = 3, + VK_DISPLAY_SURFACE_STEREO_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkDisplaySurfaceStereoTypeNV; +typedef struct VkDisplaySurfaceStereoCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDisplaySurfaceStereoTypeNV stereoType; +} VkDisplaySurfaceStereoCreateInfoNV; + +typedef struct VkDisplayModeStereoPropertiesNV { + VkStructureType sType; + void* pNext; + VkBool32 hdmi3DSupported; +} VkDisplayModeStereoPropertiesNV; + + + +// VK_NV_raw_access_chains is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_raw_access_chains 1 +#define VK_NV_RAW_ACCESS_CHAINS_SPEC_VERSION 1 +#define VK_NV_RAW_ACCESS_CHAINS_EXTENSION_NAME "VK_NV_raw_access_chains" +typedef struct VkPhysicalDeviceRawAccessChainsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shaderRawAccessChains; +} VkPhysicalDeviceRawAccessChainsFeaturesNV; + + + +// VK_NV_external_compute_queue is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_external_compute_queue 1 +VK_DEFINE_HANDLE(VkExternalComputeQueueNV) +#define VK_NV_EXTERNAL_COMPUTE_QUEUE_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_COMPUTE_QUEUE_EXTENSION_NAME "VK_NV_external_compute_queue" +typedef struct VkExternalComputeQueueDeviceCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t reservedExternalQueues; +} VkExternalComputeQueueDeviceCreateInfoNV; + +typedef struct VkExternalComputeQueueCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkQueue preferredQueue; +} VkExternalComputeQueueCreateInfoNV; + +typedef struct VkExternalComputeQueueDataParamsNV { + VkStructureType sType; + const void* pNext; + uint32_t deviceIndex; +} VkExternalComputeQueueDataParamsNV; + +typedef struct VkPhysicalDeviceExternalComputeQueuePropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t externalDataSize; + uint32_t maxExternalQueues; +} VkPhysicalDeviceExternalComputeQueuePropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateExternalComputeQueueNV)(VkDevice device, const VkExternalComputeQueueCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkExternalComputeQueueNV* pExternalQueue); +typedef void (VKAPI_PTR *PFN_vkDestroyExternalComputeQueueNV)(VkDevice device, VkExternalComputeQueueNV externalQueue, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetExternalComputeQueueDataNV)(VkExternalComputeQueueNV externalQueue, VkExternalComputeQueueDataParamsNV* params, void* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateExternalComputeQueueNV( + VkDevice device, + const VkExternalComputeQueueCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkExternalComputeQueueNV* pExternalQueue); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyExternalComputeQueueNV( + VkDevice device, + VkExternalComputeQueueNV externalQueue, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetExternalComputeQueueDataNV( + VkExternalComputeQueueNV externalQueue, + VkExternalComputeQueueDataParamsNV* params, + void* pData); +#endif +#endif + + +// VK_NV_command_buffer_inheritance is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_command_buffer_inheritance 1 +#define VK_NV_COMMAND_BUFFER_INHERITANCE_SPEC_VERSION 1 +#define VK_NV_COMMAND_BUFFER_INHERITANCE_EXTENSION_NAME "VK_NV_command_buffer_inheritance" +typedef struct VkPhysicalDeviceCommandBufferInheritanceFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 commandBufferInheritance; +} VkPhysicalDeviceCommandBufferInheritanceFeaturesNV; + + + +// VK_NV_shader_atomic_float16_vector is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_shader_atomic_float16_vector 1 +#define VK_NV_SHADER_ATOMIC_FLOAT16_VECTOR_SPEC_VERSION 1 +#define VK_NV_SHADER_ATOMIC_FLOAT16_VECTOR_EXTENSION_NAME "VK_NV_shader_atomic_float16_vector" +typedef struct VkPhysicalDeviceShaderAtomicFloat16VectorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shaderFloat16VectorAtomics; +} VkPhysicalDeviceShaderAtomicFloat16VectorFeaturesNV; + + + +// VK_EXT_shader_replicated_composites is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_replicated_composites 1 +#define VK_EXT_SHADER_REPLICATED_COMPOSITES_SPEC_VERSION 1 +#define VK_EXT_SHADER_REPLICATED_COMPOSITES_EXTENSION_NAME "VK_EXT_shader_replicated_composites" +typedef struct VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderReplicatedComposites; +} VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT; + + + +// VK_EXT_shader_float8 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_float8 1 +#define VK_EXT_SHADER_FLOAT8_SPEC_VERSION 1 +#define VK_EXT_SHADER_FLOAT8_EXTENSION_NAME "VK_EXT_shader_float8" +typedef struct VkPhysicalDeviceShaderFloat8FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderFloat8; + VkBool32 shaderFloat8CooperativeMatrix; +} VkPhysicalDeviceShaderFloat8FeaturesEXT; + + + +// VK_NV_ray_tracing_validation is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_ray_tracing_validation 1 +#define VK_NV_RAY_TRACING_VALIDATION_SPEC_VERSION 1 +#define VK_NV_RAY_TRACING_VALIDATION_EXTENSION_NAME "VK_NV_ray_tracing_validation" +typedef struct VkPhysicalDeviceRayTracingValidationFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingValidation; +} VkPhysicalDeviceRayTracingValidationFeaturesNV; + + + +// VK_NV_cluster_acceleration_structure is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cluster_acceleration_structure 1 +#define VK_NV_CLUSTER_ACCELERATION_STRUCTURE_SPEC_VERSION 4 +#define VK_NV_CLUSTER_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_NV_cluster_acceleration_structure" + +typedef enum VkClusterAccelerationStructureTypeNV { + VK_CLUSTER_ACCELERATION_STRUCTURE_TYPE_CLUSTERS_BOTTOM_LEVEL_NV = 0, + VK_CLUSTER_ACCELERATION_STRUCTURE_TYPE_TRIANGLE_CLUSTER_NV = 1, + VK_CLUSTER_ACCELERATION_STRUCTURE_TYPE_TRIANGLE_CLUSTER_TEMPLATE_NV = 2, + VK_CLUSTER_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkClusterAccelerationStructureTypeNV; + +typedef enum VkClusterAccelerationStructureOpTypeNV { + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_MOVE_OBJECTS_NV = 0, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_BUILD_CLUSTERS_BOTTOM_LEVEL_NV = 1, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_BUILD_TRIANGLE_CLUSTER_NV = 2, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_BUILD_TRIANGLE_CLUSTER_TEMPLATE_NV = 3, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_INSTANTIATE_TRIANGLE_CLUSTER_NV = 4, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_GET_CLUSTER_TEMPLATE_INDICES_NV = 5, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkClusterAccelerationStructureOpTypeNV; + +typedef enum VkClusterAccelerationStructureOpModeNV { + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_MODE_IMPLICIT_DESTINATIONS_NV = 0, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_MODE_EXPLICIT_DESTINATIONS_NV = 1, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_MODE_COMPUTE_SIZES_NV = 2, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkClusterAccelerationStructureOpModeNV; + +typedef enum VkClusterAccelerationStructureAddressResolutionFlagBitsNV { + VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_NONE_NV = 0, + VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_INDIRECTED_DST_IMPLICIT_DATA_BIT_NV = 0x00000001, + VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_INDIRECTED_SCRATCH_DATA_BIT_NV = 0x00000002, + VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_INDIRECTED_DST_ADDRESS_ARRAY_BIT_NV = 0x00000004, + VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_INDIRECTED_DST_SIZES_ARRAY_BIT_NV = 0x00000008, + VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_INDIRECTED_SRC_INFOS_ARRAY_BIT_NV = 0x00000010, + VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_INDIRECTED_SRC_INFOS_COUNT_BIT_NV = 0x00000020, + VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkClusterAccelerationStructureAddressResolutionFlagBitsNV; +typedef VkFlags VkClusterAccelerationStructureAddressResolutionFlagsNV; + +typedef enum VkClusterAccelerationStructureClusterFlagBitsNV { + VK_CLUSTER_ACCELERATION_STRUCTURE_CLUSTER_ALLOW_DISABLE_OPACITY_MICROMAPS_NV = 0x00000001, + VK_CLUSTER_ACCELERATION_STRUCTURE_CLUSTER_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkClusterAccelerationStructureClusterFlagBitsNV; +typedef VkFlags VkClusterAccelerationStructureClusterFlagsNV; + +typedef enum VkClusterAccelerationStructureGeometryFlagBitsNV { + VK_CLUSTER_ACCELERATION_STRUCTURE_GEOMETRY_CULL_DISABLE_BIT_NV = 0x00000001, + VK_CLUSTER_ACCELERATION_STRUCTURE_GEOMETRY_NO_DUPLICATE_ANYHIT_INVOCATION_BIT_NV = 0x00000002, + VK_CLUSTER_ACCELERATION_STRUCTURE_GEOMETRY_OPAQUE_BIT_NV = 0x00000004, + VK_CLUSTER_ACCELERATION_STRUCTURE_GEOMETRY_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkClusterAccelerationStructureGeometryFlagBitsNV; +typedef VkFlags VkClusterAccelerationStructureGeometryFlagsNV; + +typedef enum VkClusterAccelerationStructureIndexFormatFlagBitsNV { + VK_CLUSTER_ACCELERATION_STRUCTURE_INDEX_FORMAT_8BIT_NV = 0x00000001, + VK_CLUSTER_ACCELERATION_STRUCTURE_INDEX_FORMAT_16BIT_NV = 0x00000002, + VK_CLUSTER_ACCELERATION_STRUCTURE_INDEX_FORMAT_32BIT_NV = 0x00000004, + VK_CLUSTER_ACCELERATION_STRUCTURE_INDEX_FORMAT_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkClusterAccelerationStructureIndexFormatFlagBitsNV; +typedef VkFlags VkClusterAccelerationStructureIndexFormatFlagsNV; +typedef struct VkPhysicalDeviceClusterAccelerationStructureFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 clusterAccelerationStructure; +} VkPhysicalDeviceClusterAccelerationStructureFeaturesNV; + +typedef struct VkPhysicalDeviceClusterAccelerationStructurePropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxVerticesPerCluster; + uint32_t maxTrianglesPerCluster; + uint32_t clusterScratchByteAlignment; + uint32_t clusterByteAlignment; + uint32_t clusterTemplateByteAlignment; + uint32_t clusterBottomLevelByteAlignment; + uint32_t clusterTemplateBoundsByteAlignment; + uint32_t maxClusterGeometryIndex; +} VkPhysicalDeviceClusterAccelerationStructurePropertiesNV; + +typedef struct VkClusterAccelerationStructureClustersBottomLevelInputNV { + VkStructureType sType; + void* pNext; + uint32_t maxTotalClusterCount; + uint32_t maxClusterCountPerAccelerationStructure; +} VkClusterAccelerationStructureClustersBottomLevelInputNV; + +typedef struct VkClusterAccelerationStructureTriangleClusterInputNV { + VkStructureType sType; + void* pNext; + VkFormat vertexFormat; + uint32_t maxGeometryIndexValue; + uint32_t maxClusterUniqueGeometryCount; + uint32_t maxClusterTriangleCount; + uint32_t maxClusterVertexCount; + uint32_t maxTotalTriangleCount; + uint32_t maxTotalVertexCount; + uint32_t minPositionTruncateBitCount; +} VkClusterAccelerationStructureTriangleClusterInputNV; + +typedef struct VkClusterAccelerationStructureMoveObjectsInputNV { + VkStructureType sType; + void* pNext; + VkClusterAccelerationStructureTypeNV type; + VkBool32 noMoveOverlap; + VkDeviceSize maxMovedBytes; +} VkClusterAccelerationStructureMoveObjectsInputNV; + +typedef union VkClusterAccelerationStructureOpInputNV { + VkClusterAccelerationStructureClustersBottomLevelInputNV* pClustersBottomLevel; + VkClusterAccelerationStructureTriangleClusterInputNV* pTriangleClusters; + VkClusterAccelerationStructureMoveObjectsInputNV* pMoveObjects; +} VkClusterAccelerationStructureOpInputNV; + +typedef struct VkClusterAccelerationStructureInputInfoNV { + VkStructureType sType; + void* pNext; + uint32_t maxAccelerationStructureCount; + VkBuildAccelerationStructureFlagsKHR flags; + VkClusterAccelerationStructureOpTypeNV opType; + VkClusterAccelerationStructureOpModeNV opMode; + VkClusterAccelerationStructureOpInputNV opInput; +} VkClusterAccelerationStructureInputInfoNV; + +typedef struct VkStridedDeviceAddressRegionKHR { + VkDeviceAddress deviceAddress; + VkDeviceSize stride; + VkDeviceSize size; +} VkStridedDeviceAddressRegionKHR; + +typedef struct VkClusterAccelerationStructureCommandsInfoNV { + VkStructureType sType; + void* pNext; + VkClusterAccelerationStructureInputInfoNV input; + VkDeviceAddress dstImplicitData; + VkDeviceAddress scratchData; + VkStridedDeviceAddressRegionKHR dstAddressesArray; + VkStridedDeviceAddressRegionKHR dstSizesArray; + VkStridedDeviceAddressRegionKHR srcInfosArray; + VkDeviceAddress srcInfosCount; + VkClusterAccelerationStructureAddressResolutionFlagsNV addressResolutionFlags; +} VkClusterAccelerationStructureCommandsInfoNV; + +typedef struct VkStridedDeviceAddressNV { + VkDeviceAddress startAddress; + VkDeviceSize strideInBytes; +} VkStridedDeviceAddressNV; + +typedef struct VkClusterAccelerationStructureGeometryIndexAndGeometryFlagsNV { + uint32_t geometryIndex:24; + uint32_t reserved:5; + uint32_t geometryFlags:3; +} VkClusterAccelerationStructureGeometryIndexAndGeometryFlagsNV; + +typedef struct VkClusterAccelerationStructureMoveObjectsInfoNV { + VkDeviceAddress srcAccelerationStructure; +} VkClusterAccelerationStructureMoveObjectsInfoNV; + +typedef struct VkClusterAccelerationStructureBuildClustersBottomLevelInfoNV { + uint32_t clusterReferencesCount; + uint32_t clusterReferencesStride; + VkDeviceAddress clusterReferences; +} VkClusterAccelerationStructureBuildClustersBottomLevelInfoNV; + +typedef struct VkClusterAccelerationStructureBuildTriangleClusterInfoNV { + uint32_t clusterID; + VkClusterAccelerationStructureClusterFlagsNV clusterFlags; + uint32_t triangleCount:9; + uint32_t vertexCount:9; + uint32_t positionTruncateBitCount:6; + uint32_t indexType:4; + uint32_t opacityMicromapIndexType:4; + VkClusterAccelerationStructureGeometryIndexAndGeometryFlagsNV baseGeometryIndexAndGeometryFlags; + uint16_t indexBufferStride; + uint16_t vertexBufferStride; + uint16_t geometryIndexAndFlagsBufferStride; + uint16_t opacityMicromapIndexBufferStride; + VkDeviceAddress indexBuffer; + VkDeviceAddress vertexBuffer; + VkDeviceAddress geometryIndexAndFlagsBuffer; + VkDeviceAddress opacityMicromapArray; + VkDeviceAddress opacityMicromapIndexBuffer; +} VkClusterAccelerationStructureBuildTriangleClusterInfoNV; + +typedef struct VkClusterAccelerationStructureBuildTriangleClusterTemplateInfoNV { + uint32_t clusterID; + VkClusterAccelerationStructureClusterFlagsNV clusterFlags; + uint32_t triangleCount:9; + uint32_t vertexCount:9; + uint32_t positionTruncateBitCount:6; + uint32_t indexType:4; + uint32_t opacityMicromapIndexType:4; + VkClusterAccelerationStructureGeometryIndexAndGeometryFlagsNV baseGeometryIndexAndGeometryFlags; + uint16_t indexBufferStride; + uint16_t vertexBufferStride; + uint16_t geometryIndexAndFlagsBufferStride; + uint16_t opacityMicromapIndexBufferStride; + VkDeviceAddress indexBuffer; + VkDeviceAddress vertexBuffer; + VkDeviceAddress geometryIndexAndFlagsBuffer; + VkDeviceAddress opacityMicromapArray; + VkDeviceAddress opacityMicromapIndexBuffer; + VkDeviceAddress instantiationBoundingBoxLimit; +} VkClusterAccelerationStructureBuildTriangleClusterTemplateInfoNV; + +typedef struct VkClusterAccelerationStructureInstantiateClusterInfoNV { + uint32_t clusterIdOffset; + uint32_t geometryIndexOffset:24; + uint32_t reserved:8; + VkDeviceAddress clusterTemplateAddress; + VkStridedDeviceAddressNV vertexBuffer; +} VkClusterAccelerationStructureInstantiateClusterInfoNV; + +typedef struct VkClusterAccelerationStructureGetTemplateIndicesInfoNV { + VkDeviceAddress clusterTemplateAddress; +} VkClusterAccelerationStructureGetTemplateIndicesInfoNV; + +typedef struct VkAccelerationStructureBuildSizesInfoKHR { + VkStructureType sType; + void* pNext; + VkDeviceSize accelerationStructureSize; + VkDeviceSize updateScratchSize; + VkDeviceSize buildScratchSize; +} VkAccelerationStructureBuildSizesInfoKHR; + +typedef struct VkRayTracingPipelineClusterAccelerationStructureCreateInfoNV { + VkStructureType sType; + void* pNext; + VkBool32 allowClusterAccelerationStructure; +} VkRayTracingPipelineClusterAccelerationStructureCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkGetClusterAccelerationStructureBuildSizesNV)(VkDevice device, const VkClusterAccelerationStructureInputInfoNV* pInfo, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBuildClusterAccelerationStructureIndirectNV)(VkCommandBuffer commandBuffer, const VkClusterAccelerationStructureCommandsInfoNV* pCommandInfos); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetClusterAccelerationStructureBuildSizesNV( + VkDevice device, + const VkClusterAccelerationStructureInputInfoNV* pInfo, + VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBuildClusterAccelerationStructureIndirectNV( + VkCommandBuffer commandBuffer, + const VkClusterAccelerationStructureCommandsInfoNV* pCommandInfos); +#endif +#endif + + +// VK_NV_partitioned_acceleration_structure is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_partitioned_acceleration_structure 1 +#define VK_NV_PARTITIONED_ACCELERATION_STRUCTURE_SPEC_VERSION 1 +#define VK_NV_PARTITIONED_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_NV_partitioned_acceleration_structure" +#define VK_PARTITIONED_ACCELERATION_STRUCTURE_PARTITION_INDEX_GLOBAL_NV (~0U) + +typedef enum VkPartitionedAccelerationStructureOpTypeNV { + VK_PARTITIONED_ACCELERATION_STRUCTURE_OP_TYPE_WRITE_INSTANCE_NV = 0, + VK_PARTITIONED_ACCELERATION_STRUCTURE_OP_TYPE_UPDATE_INSTANCE_NV = 1, + VK_PARTITIONED_ACCELERATION_STRUCTURE_OP_TYPE_WRITE_PARTITION_TRANSLATION_NV = 2, + VK_PARTITIONED_ACCELERATION_STRUCTURE_OP_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkPartitionedAccelerationStructureOpTypeNV; + +typedef enum VkPartitionedAccelerationStructureInstanceFlagBitsNV { + VK_PARTITIONED_ACCELERATION_STRUCTURE_INSTANCE_FLAG_TRIANGLE_FACING_CULL_DISABLE_BIT_NV = 0x00000001, + VK_PARTITIONED_ACCELERATION_STRUCTURE_INSTANCE_FLAG_TRIANGLE_FLIP_FACING_BIT_NV = 0x00000002, + VK_PARTITIONED_ACCELERATION_STRUCTURE_INSTANCE_FLAG_FORCE_OPAQUE_BIT_NV = 0x00000004, + VK_PARTITIONED_ACCELERATION_STRUCTURE_INSTANCE_FLAG_FORCE_NO_OPAQUE_BIT_NV = 0x00000008, + VK_PARTITIONED_ACCELERATION_STRUCTURE_INSTANCE_FLAG_ENABLE_EXPLICIT_BOUNDING_BOX_NV = 0x00000010, + VK_PARTITIONED_ACCELERATION_STRUCTURE_INSTANCE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkPartitionedAccelerationStructureInstanceFlagBitsNV; +typedef VkFlags VkPartitionedAccelerationStructureInstanceFlagsNV; +typedef struct VkPhysicalDevicePartitionedAccelerationStructureFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 partitionedAccelerationStructure; +} VkPhysicalDevicePartitionedAccelerationStructureFeaturesNV; + +typedef struct VkPhysicalDevicePartitionedAccelerationStructurePropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxPartitionCount; +} VkPhysicalDevicePartitionedAccelerationStructurePropertiesNV; + +typedef struct VkPartitionedAccelerationStructureFlagsNV { + VkStructureType sType; + void* pNext; + VkBool32 enablePartitionTranslation; +} VkPartitionedAccelerationStructureFlagsNV; + +typedef struct VkBuildPartitionedAccelerationStructureIndirectCommandNV { + VkPartitionedAccelerationStructureOpTypeNV opType; + uint32_t argCount; + VkStridedDeviceAddressNV argData; +} VkBuildPartitionedAccelerationStructureIndirectCommandNV; + +typedef struct VkPartitionedAccelerationStructureWriteInstanceDataNV { + VkTransformMatrixKHR transform; + float explicitAABB[6]; + uint32_t instanceID; + uint32_t instanceMask; + uint32_t instanceContributionToHitGroupIndex; + VkPartitionedAccelerationStructureInstanceFlagsNV instanceFlags; + uint32_t instanceIndex; + uint32_t partitionIndex; + VkDeviceAddress accelerationStructure; +} VkPartitionedAccelerationStructureWriteInstanceDataNV; + +typedef struct VkPartitionedAccelerationStructureUpdateInstanceDataNV { + uint32_t instanceIndex; + uint32_t instanceContributionToHitGroupIndex; + VkDeviceAddress accelerationStructure; +} VkPartitionedAccelerationStructureUpdateInstanceDataNV; + +typedef struct VkPartitionedAccelerationStructureWritePartitionTranslationDataNV { + uint32_t partitionIndex; + float partitionTranslation[3]; +} VkPartitionedAccelerationStructureWritePartitionTranslationDataNV; + +typedef struct VkWriteDescriptorSetPartitionedAccelerationStructureNV { + VkStructureType sType; + void* pNext; + uint32_t accelerationStructureCount; + const VkDeviceAddress* pAccelerationStructures; +} VkWriteDescriptorSetPartitionedAccelerationStructureNV; + +typedef struct VkPartitionedAccelerationStructureInstancesInputNV { + VkStructureType sType; + void* pNext; + VkBuildAccelerationStructureFlagsKHR flags; + uint32_t instanceCount; + uint32_t maxInstancePerPartitionCount; + uint32_t partitionCount; + uint32_t maxInstanceInGlobalPartitionCount; +} VkPartitionedAccelerationStructureInstancesInputNV; + +typedef struct VkBuildPartitionedAccelerationStructureInfoNV { + VkStructureType sType; + void* pNext; + VkPartitionedAccelerationStructureInstancesInputNV input; + VkDeviceAddress srcAccelerationStructureData; + VkDeviceAddress dstAccelerationStructureData; + VkDeviceAddress scratchData; + VkDeviceAddress srcInfos; + VkDeviceAddress srcInfosCount; +} VkBuildPartitionedAccelerationStructureInfoNV; + +typedef void (VKAPI_PTR *PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV)(VkDevice device, const VkPartitionedAccelerationStructureInstancesInputNV* pInfo, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBuildPartitionedAccelerationStructuresNV)(VkCommandBuffer commandBuffer, const VkBuildPartitionedAccelerationStructureInfoNV* pBuildInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPartitionedAccelerationStructuresBuildSizesNV( + VkDevice device, + const VkPartitionedAccelerationStructureInstancesInputNV* pInfo, + VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBuildPartitionedAccelerationStructuresNV( + VkCommandBuffer commandBuffer, + const VkBuildPartitionedAccelerationStructureInfoNV* pBuildInfo); +#endif +#endif + + +// VK_EXT_device_generated_commands is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_device_generated_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectExecutionSetEXT) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutEXT) +#define VK_EXT_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 1 +#define VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_EXT_device_generated_commands" + +typedef enum VkIndirectExecutionSetInfoTypeEXT { + VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXT = 0, + VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXT = 1, + VK_INDIRECT_EXECUTION_SET_INFO_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkIndirectExecutionSetInfoTypeEXT; + +typedef enum VkIndirectCommandsTokenTypeEXT { + VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT = 0, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT = 1, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_SEQUENCE_INDEX_EXT = 2, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_EXT = 3, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXT = 4, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_EXT = 5, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT = 6, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_COUNT_EXT = 7, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_COUNT_EXT = 8, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT = 9, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_DATA_EXT = 1000135000, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_DATA_SEQUENCE_INDEX_EXT = 1000135001, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV_EXT = 1000202002, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_COUNT_NV_EXT = 1000202003, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_EXT = 1000328000, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_COUNT_EXT = 1000328001, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_TRACE_RAYS2_EXT = 1000386004, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkIndirectCommandsTokenTypeEXT; + +typedef enum VkIndirectCommandsInputModeFlagBitsEXT { + VK_INDIRECT_COMMANDS_INPUT_MODE_VULKAN_INDEX_BUFFER_EXT = 0x00000001, + VK_INDIRECT_COMMANDS_INPUT_MODE_DXGI_INDEX_BUFFER_EXT = 0x00000002, + VK_INDIRECT_COMMANDS_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkIndirectCommandsInputModeFlagBitsEXT; +typedef VkFlags VkIndirectCommandsInputModeFlagsEXT; + +typedef enum VkIndirectCommandsLayoutUsageFlagBitsEXT { + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_EXT = 0x00000001, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_EXT = 0x00000002, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkIndirectCommandsLayoutUsageFlagBitsEXT; +typedef VkFlags VkIndirectCommandsLayoutUsageFlagsEXT; +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 deviceGeneratedCommands; + VkBool32 dynamicGeneratedPipelineLayout; +} VkPhysicalDeviceDeviceGeneratedCommandsFeaturesEXT; + +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxIndirectPipelineCount; + uint32_t maxIndirectShaderObjectCount; + uint32_t maxIndirectSequenceCount; + uint32_t maxIndirectCommandsTokenCount; + uint32_t maxIndirectCommandsTokenOffset; + uint32_t maxIndirectCommandsIndirectStride; + VkIndirectCommandsInputModeFlagsEXT supportedIndirectCommandsInputModes; + VkShaderStageFlags supportedIndirectCommandsShaderStages; + VkShaderStageFlags supportedIndirectCommandsShaderStagesPipelineBinding; + VkShaderStageFlags supportedIndirectCommandsShaderStagesShaderBinding; + VkBool32 deviceGeneratedCommandsTransformFeedback; + VkBool32 deviceGeneratedCommandsMultiDrawIndirectCount; +} VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT; + +typedef struct VkGeneratedCommandsMemoryRequirementsInfoEXT { + VkStructureType sType; + const void* pNext; + VkIndirectExecutionSetEXT indirectExecutionSet; + VkIndirectCommandsLayoutEXT indirectCommandsLayout; + uint32_t maxSequenceCount; + uint32_t maxDrawCount; +} VkGeneratedCommandsMemoryRequirementsInfoEXT; + +typedef struct VkIndirectExecutionSetPipelineInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipeline initialPipeline; + uint32_t maxPipelineCount; +} VkIndirectExecutionSetPipelineInfoEXT; + +typedef struct VkIndirectExecutionSetShaderLayoutInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t setLayoutCount; + const VkDescriptorSetLayout* pSetLayouts; +} VkIndirectExecutionSetShaderLayoutInfoEXT; + +typedef struct VkIndirectExecutionSetShaderInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t shaderCount; + const VkShaderEXT* pInitialShaders; + const VkIndirectExecutionSetShaderLayoutInfoEXT* pSetLayoutInfos; + uint32_t maxShaderCount; + uint32_t pushConstantRangeCount; + const VkPushConstantRange* pPushConstantRanges; +} VkIndirectExecutionSetShaderInfoEXT; + +typedef union VkIndirectExecutionSetInfoEXT { + const VkIndirectExecutionSetPipelineInfoEXT* pPipelineInfo; + const VkIndirectExecutionSetShaderInfoEXT* pShaderInfo; +} VkIndirectExecutionSetInfoEXT; + +typedef struct VkIndirectExecutionSetCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkIndirectExecutionSetInfoTypeEXT type; + VkIndirectExecutionSetInfoEXT info; +} VkIndirectExecutionSetCreateInfoEXT; + +typedef struct VkGeneratedCommandsInfoEXT { + VkStructureType sType; + const void* pNext; + VkShaderStageFlags shaderStages; + VkIndirectExecutionSetEXT indirectExecutionSet; + VkIndirectCommandsLayoutEXT indirectCommandsLayout; + VkDeviceAddress indirectAddress; + VkDeviceSize indirectAddressSize; + VkDeviceAddress preprocessAddress; + VkDeviceSize preprocessSize; + uint32_t maxSequenceCount; + VkDeviceAddress sequenceCountAddress; + uint32_t maxDrawCount; +} VkGeneratedCommandsInfoEXT; + +typedef struct VkWriteIndirectExecutionSetPipelineEXT { + VkStructureType sType; + const void* pNext; + uint32_t index; + VkPipeline pipeline; +} VkWriteIndirectExecutionSetPipelineEXT; + +typedef struct VkIndirectCommandsPushConstantTokenEXT { + VkPushConstantRange updateRange; +} VkIndirectCommandsPushConstantTokenEXT; + +typedef struct VkIndirectCommandsVertexBufferTokenEXT { + uint32_t vertexBindingUnit; +} VkIndirectCommandsVertexBufferTokenEXT; + +typedef struct VkIndirectCommandsIndexBufferTokenEXT { + VkIndirectCommandsInputModeFlagBitsEXT mode; +} VkIndirectCommandsIndexBufferTokenEXT; + +typedef struct VkIndirectCommandsExecutionSetTokenEXT { + VkIndirectExecutionSetInfoTypeEXT type; + VkShaderStageFlags shaderStages; +} VkIndirectCommandsExecutionSetTokenEXT; + +typedef union VkIndirectCommandsTokenDataEXT { + const VkIndirectCommandsPushConstantTokenEXT* pPushConstant; + const VkIndirectCommandsVertexBufferTokenEXT* pVertexBuffer; + const VkIndirectCommandsIndexBufferTokenEXT* pIndexBuffer; + const VkIndirectCommandsExecutionSetTokenEXT* pExecutionSet; +} VkIndirectCommandsTokenDataEXT; + +typedef struct VkIndirectCommandsLayoutTokenEXT { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsTokenTypeEXT type; + VkIndirectCommandsTokenDataEXT data; + uint32_t offset; +} VkIndirectCommandsLayoutTokenEXT; + +typedef struct VkIndirectCommandsLayoutCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsLayoutUsageFlagsEXT flags; + VkShaderStageFlags shaderStages; + uint32_t indirectStride; + VkPipelineLayout pipelineLayout; + uint32_t tokenCount; + const VkIndirectCommandsLayoutTokenEXT* pTokens; +} VkIndirectCommandsLayoutCreateInfoEXT; + +typedef struct VkDrawIndirectCountIndirectCommandEXT { + VkDeviceAddress bufferAddress; + uint32_t stride; + uint32_t commandCount; +} VkDrawIndirectCountIndirectCommandEXT; + +typedef struct VkBindVertexBufferIndirectCommandEXT { + VkDeviceAddress bufferAddress; + uint32_t size; + uint32_t stride; +} VkBindVertexBufferIndirectCommandEXT; + +typedef struct VkBindIndexBufferIndirectCommandEXT { + VkDeviceAddress bufferAddress; + uint32_t size; + VkIndexType indexType; +} VkBindIndexBufferIndirectCommandEXT; + +typedef struct VkGeneratedCommandsPipelineInfoEXT { + VkStructureType sType; + void* pNext; + VkPipeline pipeline; +} VkGeneratedCommandsPipelineInfoEXT; + +typedef struct VkGeneratedCommandsShaderInfoEXT { + VkStructureType sType; + void* pNext; + uint32_t shaderCount; + const VkShaderEXT* pShaders; +} VkGeneratedCommandsShaderInfoEXT; + +typedef struct VkWriteIndirectExecutionSetShaderEXT { + VkStructureType sType; + const void* pNext; + uint32_t index; + VkShaderEXT shader; +} VkWriteIndirectExecutionSetShaderEXT; + +typedef void (VKAPI_PTR *PFN_vkGetGeneratedCommandsMemoryRequirementsEXT)(VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoEXT* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdPreprocessGeneratedCommandsEXT)(VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoEXT* pGeneratedCommandsInfo, VkCommandBuffer stateCommandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteGeneratedCommandsEXT)(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoEXT* pGeneratedCommandsInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutEXT)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutEXT* pIndirectCommandsLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutEXT)(VkDevice device, VkIndirectCommandsLayoutEXT indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectExecutionSetEXT)(VkDevice device, const VkIndirectExecutionSetCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectExecutionSetEXT* pIndirectExecutionSet); +typedef void (VKAPI_PTR *PFN_vkDestroyIndirectExecutionSetEXT)(VkDevice device, VkIndirectExecutionSetEXT indirectExecutionSet, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkUpdateIndirectExecutionSetPipelineEXT)(VkDevice device, VkIndirectExecutionSetEXT indirectExecutionSet, uint32_t executionSetWriteCount, const VkWriteIndirectExecutionSetPipelineEXT* pExecutionSetWrites); +typedef void (VKAPI_PTR *PFN_vkUpdateIndirectExecutionSetShaderEXT)(VkDevice device, VkIndirectExecutionSetEXT indirectExecutionSet, uint32_t executionSetWriteCount, const VkWriteIndirectExecutionSetShaderEXT* pExecutionSetWrites); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsEXT( + VkDevice device, + const VkGeneratedCommandsMemoryRequirementsInfoEXT* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsEXT( + VkCommandBuffer commandBuffer, + const VkGeneratedCommandsInfoEXT* pGeneratedCommandsInfo, + VkCommandBuffer stateCommandBuffer); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsEXT( + VkCommandBuffer commandBuffer, + VkBool32 isPreprocessed, + const VkGeneratedCommandsInfoEXT* pGeneratedCommandsInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutEXT( + VkDevice device, + const VkIndirectCommandsLayoutCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkIndirectCommandsLayoutEXT* pIndirectCommandsLayout); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutEXT( + VkDevice device, + VkIndirectCommandsLayoutEXT indirectCommandsLayout, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectExecutionSetEXT( + VkDevice device, + const VkIndirectExecutionSetCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkIndirectExecutionSetEXT* pIndirectExecutionSet); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectExecutionSetEXT( + VkDevice device, + VkIndirectExecutionSetEXT indirectExecutionSet, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkUpdateIndirectExecutionSetPipelineEXT( + VkDevice device, + VkIndirectExecutionSetEXT indirectExecutionSet, + uint32_t executionSetWriteCount, + const VkWriteIndirectExecutionSetPipelineEXT* pExecutionSetWrites); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkUpdateIndirectExecutionSetShaderEXT( + VkDevice device, + VkIndirectExecutionSetEXT indirectExecutionSet, + uint32_t executionSetWriteCount, + const VkWriteIndirectExecutionSetShaderEXT* pExecutionSetWrites); +#endif +#endif + + +// VK_MESA_image_alignment_control is a preprocessor guard. Do not pass it to API calls. +#define VK_MESA_image_alignment_control 1 +#define VK_MESA_IMAGE_ALIGNMENT_CONTROL_SPEC_VERSION 1 +#define VK_MESA_IMAGE_ALIGNMENT_CONTROL_EXTENSION_NAME "VK_MESA_image_alignment_control" +typedef struct VkPhysicalDeviceImageAlignmentControlFeaturesMESA { + VkStructureType sType; + void* pNext; + VkBool32 imageAlignmentControl; +} VkPhysicalDeviceImageAlignmentControlFeaturesMESA; + +typedef struct VkPhysicalDeviceImageAlignmentControlPropertiesMESA { + VkStructureType sType; + void* pNext; + uint32_t supportedImageAlignmentMask; +} VkPhysicalDeviceImageAlignmentControlPropertiesMESA; + +typedef struct VkImageAlignmentControlCreateInfoMESA { + VkStructureType sType; + const void* pNext; + uint32_t maximumRequestedAlignment; +} VkImageAlignmentControlCreateInfoMESA; + + + +// VK_NV_push_constant_bank is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_push_constant_bank 1 +#define VK_NV_PUSH_CONSTANT_BANK_SPEC_VERSION 1 +#define VK_NV_PUSH_CONSTANT_BANK_EXTENSION_NAME "VK_NV_push_constant_bank" +typedef struct VkPushConstantBankInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t bank; +} VkPushConstantBankInfoNV; + +typedef struct VkPhysicalDevicePushConstantBankFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 pushConstantBank; +} VkPhysicalDevicePushConstantBankFeaturesNV; + +typedef struct VkPhysicalDevicePushConstantBankPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxGraphicsPushConstantBanks; + uint32_t maxComputePushConstantBanks; + uint32_t maxGraphicsPushDataBanks; + uint32_t maxComputePushDataBanks; +} VkPhysicalDevicePushConstantBankPropertiesNV; + + + +// VK_EXT_ray_tracing_invocation_reorder is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_ray_tracing_invocation_reorder 1 +#define VK_EXT_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION 2 +#define VK_EXT_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME "VK_EXT_ray_tracing_invocation_reorder" +typedef struct VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT { + VkStructureType sType; + void* pNext; + VkRayTracingInvocationReorderModeEXT rayTracingInvocationReorderReorderingHint; + uint32_t maxShaderBindingTableRecordIndex; +} VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT; + +typedef struct VkPhysicalDeviceRayTracingInvocationReorderFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingInvocationReorder; +} VkPhysicalDeviceRayTracingInvocationReorderFeaturesEXT; + + + +// VK_EXT_depth_clamp_control is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_depth_clamp_control 1 +#define VK_EXT_DEPTH_CLAMP_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME "VK_EXT_depth_clamp_control" +typedef struct VkPhysicalDeviceDepthClampControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 depthClampControl; +} VkPhysicalDeviceDepthClampControlFeaturesEXT; + +typedef struct VkPipelineViewportDepthClampControlCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDepthClampModeEXT depthClampMode; + const VkDepthClampRangeEXT* pDepthClampRange; +} VkPipelineViewportDepthClampControlCreateInfoEXT; + + + +// VK_HUAWEI_hdr_vivid is a preprocessor guard. Do not pass it to API calls. +#define VK_HUAWEI_hdr_vivid 1 +#define VK_HUAWEI_HDR_VIVID_SPEC_VERSION 1 +#define VK_HUAWEI_HDR_VIVID_EXTENSION_NAME "VK_HUAWEI_hdr_vivid" +typedef struct VkPhysicalDeviceHdrVividFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 hdrVivid; +} VkPhysicalDeviceHdrVividFeaturesHUAWEI; + +typedef struct VkHdrVividDynamicMetadataHUAWEI { + VkStructureType sType; + const void* pNext; + size_t dynamicMetadataSize; + const void* pDynamicMetadata; +} VkHdrVividDynamicMetadataHUAWEI; + + + +// VK_NV_cooperative_matrix2 is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cooperative_matrix2 1 +#define VK_NV_COOPERATIVE_MATRIX_2_SPEC_VERSION 1 +#define VK_NV_COOPERATIVE_MATRIX_2_EXTENSION_NAME "VK_NV_cooperative_matrix2" +typedef struct VkCooperativeMatrixFlexibleDimensionsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t MGranularity; + uint32_t NGranularity; + uint32_t KGranularity; + VkComponentTypeKHR AType; + VkComponentTypeKHR BType; + VkComponentTypeKHR CType; + VkComponentTypeKHR ResultType; + VkBool32 saturatingAccumulation; + VkScopeKHR scope; + uint32_t workgroupInvocations; +} VkCooperativeMatrixFlexibleDimensionsPropertiesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrix2FeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrixWorkgroupScope; + VkBool32 cooperativeMatrixFlexibleDimensions; + VkBool32 cooperativeMatrixReductions; + VkBool32 cooperativeMatrixConversions; + VkBool32 cooperativeMatrixPerElementOperations; + VkBool32 cooperativeMatrixTensorAddressing; + VkBool32 cooperativeMatrixBlockLoads; +} VkPhysicalDeviceCooperativeMatrix2FeaturesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrix2PropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t cooperativeMatrixWorkgroupScopeMaxWorkgroupSize; + uint32_t cooperativeMatrixFlexibleDimensionsMaxDimension; + uint32_t cooperativeMatrixWorkgroupScopeReservedSharedMemory; +} VkPhysicalDeviceCooperativeMatrix2PropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixFlexibleDimensionsPropertiesNV* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkCooperativeMatrixFlexibleDimensionsPropertiesNV* pProperties); +#endif +#endif + + +// VK_ARM_pipeline_opacity_micromap is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_pipeline_opacity_micromap 1 +#define VK_ARM_PIPELINE_OPACITY_MICROMAP_SPEC_VERSION 1 +#define VK_ARM_PIPELINE_OPACITY_MICROMAP_EXTENSION_NAME "VK_ARM_pipeline_opacity_micromap" +typedef struct VkPhysicalDevicePipelineOpacityMicromapFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 pipelineOpacityMicromap; +} VkPhysicalDevicePipelineOpacityMicromapFeaturesARM; + + + +// VK_ARM_performance_counters_by_region is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_performance_counters_by_region 1 +#define VK_ARM_PERFORMANCE_COUNTERS_BY_REGION_SPEC_VERSION 1 +#define VK_ARM_PERFORMANCE_COUNTERS_BY_REGION_EXTENSION_NAME "VK_ARM_performance_counters_by_region" +typedef VkFlags VkPerformanceCounterDescriptionFlagsARM; +typedef struct VkPhysicalDevicePerformanceCountersByRegionFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 performanceCountersByRegion; +} VkPhysicalDevicePerformanceCountersByRegionFeaturesARM; + +typedef struct VkPhysicalDevicePerformanceCountersByRegionPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t maxPerRegionPerformanceCounters; + VkExtent2D performanceCounterRegionSize; + uint32_t rowStrideAlignment; + uint32_t regionAlignment; + VkBool32 identityTransformOrder; +} VkPhysicalDevicePerformanceCountersByRegionPropertiesARM; + +typedef struct VkPerformanceCounterARM { + VkStructureType sType; + void* pNext; + uint32_t counterID; +} VkPerformanceCounterARM; + +typedef struct VkPerformanceCounterDescriptionARM { + VkStructureType sType; + void* pNext; + VkPerformanceCounterDescriptionFlagsARM flags; + char name[VK_MAX_DESCRIPTION_SIZE]; +} VkPerformanceCounterDescriptionARM; + +typedef struct VkRenderPassPerformanceCountersByRegionBeginInfoARM { + VkStructureType sType; + void* pNext; + uint32_t counterAddressCount; + const VkDeviceAddress* pCounterAddresses; + VkBool32 serializeRegions; + uint32_t counterIndexCount; + uint32_t* pCounterIndices; +} VkRenderPassPerformanceCountersByRegionBeginInfoARM; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterARM* pCounters, VkPerformanceCounterDescriptionARM* pCounterDescriptions); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + uint32_t* pCounterCount, + VkPerformanceCounterARM* pCounters, + VkPerformanceCounterDescriptionARM* pCounterDescriptions); +#endif +#endif + + +// VK_ARM_shader_instrumentation is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_shader_instrumentation 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderInstrumentationARM) +#define VK_ARM_SHADER_INSTRUMENTATION_SPEC_VERSION 1 +#define VK_ARM_SHADER_INSTRUMENTATION_EXTENSION_NAME "VK_ARM_shader_instrumentation" +typedef VkFlags VkShaderInstrumentationValuesFlagsARM; +typedef struct VkPhysicalDeviceShaderInstrumentationFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 shaderInstrumentation; +} VkPhysicalDeviceShaderInstrumentationFeaturesARM; + +typedef struct VkPhysicalDeviceShaderInstrumentationPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t numMetrics; + VkBool32 perBasicBlockGranularity; +} VkPhysicalDeviceShaderInstrumentationPropertiesARM; + +typedef struct VkShaderInstrumentationCreateInfoARM { + VkStructureType sType; + void* pNext; +} VkShaderInstrumentationCreateInfoARM; + +typedef struct VkShaderInstrumentationMetricDescriptionARM { + VkStructureType sType; + void* pNext; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; +} VkShaderInstrumentationMetricDescriptionARM; + +typedef struct VkShaderInstrumentationMetricDataHeaderARM { + uint32_t resultIndex; + uint32_t resultSubIndex; + VkShaderStageFlags stages; + uint32_t basicBlockIndex; +} VkShaderInstrumentationMetricDataHeaderARM; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM)(VkPhysicalDevice physicalDevice, uint32_t* pDescriptionCount, VkShaderInstrumentationMetricDescriptionARM* pDescriptions); +typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderInstrumentationARM)(VkDevice device, const VkShaderInstrumentationCreateInfoARM* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderInstrumentationARM* pInstrumentation); +typedef void (VKAPI_PTR *PFN_vkDestroyShaderInstrumentationARM)(VkDevice device, VkShaderInstrumentationARM instrumentation, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBeginShaderInstrumentationARM)(VkCommandBuffer commandBuffer, VkShaderInstrumentationARM instrumentation); +typedef void (VKAPI_PTR *PFN_vkCmdEndShaderInstrumentationARM)(VkCommandBuffer commandBuffer); +typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInstrumentationValuesARM)(VkDevice device, VkShaderInstrumentationARM instrumentation, uint32_t* pMetricBlockCount, void* pMetricValues, VkShaderInstrumentationValuesFlagsARM flags); +typedef void (VKAPI_PTR *PFN_vkClearShaderInstrumentationMetricsARM)(VkDevice device, VkShaderInstrumentationARM instrumentation); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM( + VkPhysicalDevice physicalDevice, + uint32_t* pDescriptionCount, + VkShaderInstrumentationMetricDescriptionARM* pDescriptions); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderInstrumentationARM( + VkDevice device, + const VkShaderInstrumentationCreateInfoARM* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkShaderInstrumentationARM* pInstrumentation); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyShaderInstrumentationARM( + VkDevice device, + VkShaderInstrumentationARM instrumentation, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginShaderInstrumentationARM( + VkCommandBuffer commandBuffer, + VkShaderInstrumentationARM instrumentation); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndShaderInstrumentationARM( + VkCommandBuffer commandBuffer); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInstrumentationValuesARM( + VkDevice device, + VkShaderInstrumentationARM instrumentation, + uint32_t* pMetricBlockCount, + void* pMetricValues, + VkShaderInstrumentationValuesFlagsARM flags); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkClearShaderInstrumentationMetricsARM( + VkDevice device, + VkShaderInstrumentationARM instrumentation); +#endif +#endif + + +// VK_EXT_vertex_attribute_robustness is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_vertex_attribute_robustness 1 +#define VK_EXT_VERTEX_ATTRIBUTE_ROBUSTNESS_SPEC_VERSION 1 +#define VK_EXT_VERTEX_ATTRIBUTE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_vertex_attribute_robustness" +typedef struct VkPhysicalDeviceVertexAttributeRobustnessFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 vertexAttributeRobustness; +} VkPhysicalDeviceVertexAttributeRobustnessFeaturesEXT; + + + +// VK_ARM_format_pack is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_format_pack 1 +#define VK_ARM_FORMAT_PACK_SPEC_VERSION 1 +#define VK_ARM_FORMAT_PACK_EXTENSION_NAME "VK_ARM_format_pack" +typedef struct VkPhysicalDeviceFormatPackFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 formatPack; +} VkPhysicalDeviceFormatPackFeaturesARM; + + + +// VK_VALVE_fragment_density_map_layered is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_fragment_density_map_layered 1 +#define VK_VALVE_FRAGMENT_DENSITY_MAP_LAYERED_SPEC_VERSION 1 +#define VK_VALVE_FRAGMENT_DENSITY_MAP_LAYERED_EXTENSION_NAME "VK_VALVE_fragment_density_map_layered" +typedef struct VkPhysicalDeviceFragmentDensityMapLayeredFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapLayered; +} VkPhysicalDeviceFragmentDensityMapLayeredFeaturesVALVE; + +typedef struct VkPhysicalDeviceFragmentDensityMapLayeredPropertiesVALVE { + VkStructureType sType; + void* pNext; + uint32_t maxFragmentDensityMapLayers; +} VkPhysicalDeviceFragmentDensityMapLayeredPropertiesVALVE; + +typedef struct VkPipelineFragmentDensityMapLayeredCreateInfoVALVE { + VkStructureType sType; + const void* pNext; + uint32_t maxFragmentDensityMapLayers; +} VkPipelineFragmentDensityMapLayeredCreateInfoVALVE; + + + +// VK_NV_present_metering is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_present_metering 1 +#define VK_NV_PRESENT_METERING_SPEC_VERSION 1 +#define VK_NV_PRESENT_METERING_EXTENSION_NAME "VK_NV_present_metering" +typedef struct VkSetPresentConfigNV { + VkStructureType sType; + const void* pNext; + uint32_t numFramesPerBatch; + uint32_t presentConfigFeedback; +} VkSetPresentConfigNV; + +typedef struct VkPhysicalDevicePresentMeteringFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 presentMetering; +} VkPhysicalDevicePresentMeteringFeaturesNV; + + + +// VK_EXT_fragment_density_map_offset is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_fragment_density_map_offset 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME "VK_EXT_fragment_density_map_offset" +typedef VkRenderingEndInfoKHR VkRenderingEndInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdEndRendering2EXT)(VkCommandBuffer commandBuffer, const VkRenderingEndInfoKHR* pRenderingEndInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndRendering2EXT( + VkCommandBuffer commandBuffer, + const VkRenderingEndInfoKHR* pRenderingEndInfo); +#endif +#endif + + +// VK_EXT_zero_initialize_device_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_zero_initialize_device_memory 1 +#define VK_EXT_ZERO_INITIALIZE_DEVICE_MEMORY_SPEC_VERSION 1 +#define VK_EXT_ZERO_INITIALIZE_DEVICE_MEMORY_EXTENSION_NAME "VK_EXT_zero_initialize_device_memory" +typedef struct VkPhysicalDeviceZeroInitializeDeviceMemoryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 zeroInitializeDeviceMemory; +} VkPhysicalDeviceZeroInitializeDeviceMemoryFeaturesEXT; + + + +// VK_EXT_shader_64bit_indexing is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_64bit_indexing 1 +#define VK_EXT_SHADER_64BIT_INDEXING_SPEC_VERSION 1 +#define VK_EXT_SHADER_64BIT_INDEXING_EXTENSION_NAME "VK_EXT_shader_64bit_indexing" +typedef struct VkPhysicalDeviceShader64BitIndexingFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shader64BitIndexing; +} VkPhysicalDeviceShader64BitIndexingFeaturesEXT; + + + +// VK_EXT_custom_resolve is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_custom_resolve 1 +#define VK_EXT_CUSTOM_RESOLVE_SPEC_VERSION 1 +#define VK_EXT_CUSTOM_RESOLVE_EXTENSION_NAME "VK_EXT_custom_resolve" +typedef struct VkPhysicalDeviceCustomResolveFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 customResolve; +} VkPhysicalDeviceCustomResolveFeaturesEXT; + +typedef struct VkBeginCustomResolveInfoEXT { + VkStructureType sType; + void* pNext; +} VkBeginCustomResolveInfoEXT; + +typedef struct VkCustomResolveCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 customResolve; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkCustomResolveCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginCustomResolveEXT)(VkCommandBuffer commandBuffer, const VkBeginCustomResolveInfoEXT* pBeginCustomResolveInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginCustomResolveEXT( + VkCommandBuffer commandBuffer, + const VkBeginCustomResolveInfoEXT* pBeginCustomResolveInfo); +#endif +#endif + + +// VK_QCOM_data_graph_model is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_data_graph_model 1 +#define VK_DATA_GRAPH_MODEL_TOOLCHAIN_VERSION_LENGTH_QCOM 3U +#define VK_QCOM_DATA_GRAPH_MODEL_SPEC_VERSION 1 +#define VK_QCOM_DATA_GRAPH_MODEL_EXTENSION_NAME "VK_QCOM_data_graph_model" + +typedef enum VkDataGraphModelCacheTypeQCOM { + VK_DATA_GRAPH_MODEL_CACHE_TYPE_GENERIC_BINARY_QCOM = 0, + VK_DATA_GRAPH_MODEL_CACHE_TYPE_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkDataGraphModelCacheTypeQCOM; +typedef struct VkPipelineCacheHeaderVersionDataGraphQCOM { + uint32_t headerSize; + VkPipelineCacheHeaderVersion headerVersion; + VkDataGraphModelCacheTypeQCOM cacheType; + uint32_t cacheVersion; + uint32_t toolchainVersion[VK_DATA_GRAPH_MODEL_TOOLCHAIN_VERSION_LENGTH_QCOM]; +} VkPipelineCacheHeaderVersionDataGraphQCOM; + +typedef struct VkDataGraphPipelineBuiltinModelCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + const VkPhysicalDeviceDataGraphOperationSupportARM* pOperation; +} VkDataGraphPipelineBuiltinModelCreateInfoQCOM; + +typedef struct VkPhysicalDeviceDataGraphModelFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 dataGraphModel; +} VkPhysicalDeviceDataGraphModelFeaturesQCOM; + + + +// VK_ARM_data_graph_optical_flow is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_data_graph_optical_flow 1 +#define VK_ARM_DATA_GRAPH_OPTICAL_FLOW_SPEC_VERSION 1 +#define VK_ARM_DATA_GRAPH_OPTICAL_FLOW_EXTENSION_NAME "VK_ARM_data_graph_optical_flow" + +typedef enum VkDataGraphOpticalFlowPerformanceLevelARM { + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_UNKNOWN_ARM = 0, + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_SLOW_ARM = 1, + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_MEDIUM_ARM = 2, + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_FAST_ARM = 3, + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowPerformanceLevelARM; + +typedef enum VkDataGraphPipelineNodeTypeARM { + VK_DATA_GRAPH_PIPELINE_NODE_TYPE_OPTICAL_FLOW_ARM = 1000631000, + VK_DATA_GRAPH_PIPELINE_NODE_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelineNodeTypeARM; + +typedef enum VkDataGraphPipelineNodeConnectionTypeARM { + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_INPUT_ARM = 1000631000, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_REFERENCE_ARM = 1000631001, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_HINT_ARM = 1000631002, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_FLOW_VECTOR_ARM = 1000631003, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_COST_ARM = 1000631004, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelineNodeConnectionTypeARM; + +typedef enum VkDataGraphOpticalFlowGridSizeFlagBitsARM { + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_UNKNOWN_ARM = 0, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_1X1_BIT_ARM = 0x00000001, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_2X2_BIT_ARM = 0x00000002, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_4X4_BIT_ARM = 0x00000004, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_8X8_BIT_ARM = 0x00000008, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowGridSizeFlagBitsARM; +typedef VkFlags VkDataGraphOpticalFlowGridSizeFlagsARM; + +typedef enum VkDataGraphOpticalFlowCreateFlagBitsARM { + VK_DATA_GRAPH_OPTICAL_FLOW_CREATE_ENABLE_HINT_BIT_ARM = 0x00000001, + VK_DATA_GRAPH_OPTICAL_FLOW_CREATE_ENABLE_COST_BIT_ARM = 0x00000002, + VK_DATA_GRAPH_OPTICAL_FLOW_CREATE_RESERVED_30_BIT_ARM = 0x40000000, + VK_DATA_GRAPH_OPTICAL_FLOW_CREATE_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowCreateFlagBitsARM; +typedef VkFlags VkDataGraphOpticalFlowCreateFlagsARM; + +typedef enum VkDataGraphOpticalFlowImageUsageFlagBitsARM { + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_UNKNOWN_ARM = 0, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_INPUT_BIT_ARM = 0x00000001, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_OUTPUT_BIT_ARM = 0x00000002, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_HINT_BIT_ARM = 0x00000004, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_COST_BIT_ARM = 0x00000008, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowImageUsageFlagBitsARM; +typedef VkFlags VkDataGraphOpticalFlowImageUsageFlagsARM; + +typedef enum VkDataGraphOpticalFlowExecuteFlagBitsARM { + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_DISABLE_TEMPORAL_HINTS_BIT_ARM = 0x00000001, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_INPUT_UNCHANGED_BIT_ARM = 0x00000002, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_REFERENCE_UNCHANGED_BIT_ARM = 0x00000004, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_INPUT_IS_PREVIOUS_REFERENCE_BIT_ARM = 0x00000008, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_REFERENCE_IS_PREVIOUS_INPUT_BIT_ARM = 0x00000010, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowExecuteFlagBitsARM; +typedef VkFlags VkDataGraphOpticalFlowExecuteFlagsARM; +typedef struct VkPhysicalDeviceDataGraphOpticalFlowFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 dataGraphOpticalFlow; +} VkPhysicalDeviceDataGraphOpticalFlowFeaturesARM; + +typedef struct VkQueueFamilyDataGraphOpticalFlowPropertiesARM { + VkStructureType sType; + void* pNext; + VkDataGraphOpticalFlowGridSizeFlagsARM supportedOutputGridSizes; + VkDataGraphOpticalFlowGridSizeFlagsARM supportedHintGridSizes; + VkBool32 hintSupported; + VkBool32 costSupported; + uint32_t minWidth; + uint32_t minHeight; + uint32_t maxWidth; + uint32_t maxHeight; +} VkQueueFamilyDataGraphOpticalFlowPropertiesARM; + +typedef struct VkDataGraphPipelineOpticalFlowCreateInfoARM { + VkStructureType sType; + void* pNext; + uint32_t width; + uint32_t height; + VkFormat imageFormat; + VkFormat flowVectorFormat; + VkFormat costFormat; + VkDataGraphOpticalFlowGridSizeFlagsARM outputGridSize; + VkDataGraphOpticalFlowGridSizeFlagsARM hintGridSize; + VkDataGraphOpticalFlowPerformanceLevelARM performanceLevel; + VkDataGraphOpticalFlowCreateFlagsARM flags; +} VkDataGraphPipelineOpticalFlowCreateInfoARM; + +typedef struct VkDataGraphOpticalFlowImageFormatPropertiesARM { + VkStructureType sType; + void* pNext; + VkFormat format; +} VkDataGraphOpticalFlowImageFormatPropertiesARM; + +typedef struct VkDataGraphOpticalFlowImageFormatInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphOpticalFlowImageUsageFlagsARM usage; +} VkDataGraphOpticalFlowImageFormatInfoARM; + +typedef struct VkDataGraphPipelineOpticalFlowDispatchInfoARM { + VkStructureType sType; + void* pNext; + VkDataGraphOpticalFlowExecuteFlagsARM flags; + uint32_t meanFlowL1NormHint; +} VkDataGraphPipelineOpticalFlowDispatchInfoARM; + +typedef struct VkDataGraphPipelineResourceInfoImageLayoutARM { + VkStructureType sType; + const void* pNext; + VkImageLayout layout; +} VkDataGraphPipelineResourceInfoImageLayoutARM; + +typedef struct VkDataGraphPipelineSingleNodeConnectionARM { + VkStructureType sType; + void* pNext; + uint32_t set; + uint32_t binding; + VkDataGraphPipelineNodeConnectionTypeARM connection; +} VkDataGraphPipelineSingleNodeConnectionARM; + +typedef struct VkDataGraphPipelineSingleNodeCreateInfoARM { + VkStructureType sType; + void* pNext; + VkDataGraphPipelineNodeTypeARM nodeType; + uint32_t connectionCount; + const VkDataGraphPipelineSingleNodeConnectionARM* pConnections; +} VkDataGraphPipelineSingleNodeCreateInfoARM; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties, const VkDataGraphOpticalFlowImageFormatInfoARM* pOpticalFlowImageFormatInfo, uint32_t* pFormatCount, VkDataGraphOpticalFlowImageFormatPropertiesARM* pImageFormatProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + const VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties, + const VkDataGraphOpticalFlowImageFormatInfoARM* pOpticalFlowImageFormatInfo, + uint32_t* pFormatCount, + VkDataGraphOpticalFlowImageFormatPropertiesARM* pImageFormatProperties); +#endif +#endif + + +// VK_EXT_shader_long_vector is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_long_vector 1 +#define VK_EXT_SHADER_LONG_VECTOR_SPEC_VERSION 1 +#define VK_EXT_SHADER_LONG_VECTOR_EXTENSION_NAME "VK_EXT_shader_long_vector" +typedef struct VkPhysicalDeviceShaderLongVectorFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 longVector; +} VkPhysicalDeviceShaderLongVectorFeaturesEXT; + +typedef struct VkPhysicalDeviceShaderLongVectorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxVectorComponents; +} VkPhysicalDeviceShaderLongVectorPropertiesEXT; + + + +// VK_SEC_pipeline_cache_incremental_mode is a preprocessor guard. Do not pass it to API calls. +#define VK_SEC_pipeline_cache_incremental_mode 1 +#define VK_SEC_PIPELINE_CACHE_INCREMENTAL_MODE_SPEC_VERSION 1 +#define VK_SEC_PIPELINE_CACHE_INCREMENTAL_MODE_EXTENSION_NAME "VK_SEC_pipeline_cache_incremental_mode" +typedef struct VkPhysicalDevicePipelineCacheIncrementalModeFeaturesSEC { + VkStructureType sType; + void* pNext; + VkBool32 pipelineCacheIncrementalMode; +} VkPhysicalDevicePipelineCacheIncrementalModeFeaturesSEC; + + + +// VK_EXT_shader_uniform_buffer_unsized_array is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_uniform_buffer_unsized_array 1 +#define VK_EXT_SHADER_UNIFORM_BUFFER_UNSIZED_ARRAY_SPEC_VERSION 1 +#define VK_EXT_SHADER_UNIFORM_BUFFER_UNSIZED_ARRAY_EXTENSION_NAME "VK_EXT_shader_uniform_buffer_unsized_array" +typedef struct VkPhysicalDeviceShaderUniformBufferUnsizedArrayFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderUniformBufferUnsizedArray; +} VkPhysicalDeviceShaderUniformBufferUnsizedArrayFeaturesEXT; + + + +// VK_NV_compute_occupancy_priority is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_compute_occupancy_priority 1 +#define VK_NV_COMPUTE_OCCUPANCY_PRIORITY_SPEC_VERSION 1 +#define VK_NV_COMPUTE_OCCUPANCY_PRIORITY_EXTENSION_NAME "VK_NV_compute_occupancy_priority" +#define VK_COMPUTE_OCCUPANCY_PRIORITY_LOW_NV 0.25f +#define VK_COMPUTE_OCCUPANCY_PRIORITY_NORMAL_NV 0.50f +#define VK_COMPUTE_OCCUPANCY_PRIORITY_HIGH_NV 0.75f +typedef struct VkComputeOccupancyPriorityParametersNV { + VkStructureType sType; + const void* pNext; + float occupancyPriority; + float occupancyThrottling; +} VkComputeOccupancyPriorityParametersNV; + +typedef struct VkPhysicalDeviceComputeOccupancyPriorityFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 computeOccupancyPriority; +} VkPhysicalDeviceComputeOccupancyPriorityFeaturesNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetComputeOccupancyPriorityNV)(VkCommandBuffer commandBuffer, const VkComputeOccupancyPriorityParametersNV* pParameters); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetComputeOccupancyPriorityNV( + VkCommandBuffer commandBuffer, + const VkComputeOccupancyPriorityParametersNV* pParameters); +#endif +#endif + + +// VK_EXT_shader_subgroup_partitioned is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_subgroup_partitioned 1 +#define VK_EXT_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_EXT_shader_subgroup_partitioned" +typedef struct VkPhysicalDeviceShaderSubgroupPartitionedFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupPartitioned; +} VkPhysicalDeviceShaderSubgroupPartitionedFeaturesEXT; + + + +// VK_VALVE_shader_mixed_float_dot_product is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_shader_mixed_float_dot_product 1 +#define VK_VALVE_SHADER_MIXED_FLOAT_DOT_PRODUCT_SPEC_VERSION 1 +#define VK_VALVE_SHADER_MIXED_FLOAT_DOT_PRODUCT_EXTENSION_NAME "VK_VALVE_shader_mixed_float_dot_product" +typedef struct VkPhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 shaderMixedFloatDotProductFloat16AccFloat32; + VkBool32 shaderMixedFloatDotProductFloat16AccFloat16; + VkBool32 shaderMixedFloatDotProductBFloat16Acc; + VkBool32 shaderMixedFloatDotProductFloat8AccFloat32; +} VkPhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE; + + + +// VK_SEC_throttle_hint is a preprocessor guard. Do not pass it to API calls. +#define VK_SEC_throttle_hint 1 +#define VK_SEC_THROTTLE_HINT_SPEC_VERSION 1 +#define VK_SEC_THROTTLE_HINT_EXTENSION_NAME "VK_SEC_throttle_hint" + +typedef enum VkThrottleHintTypeSEC { + VK_THROTTLE_HINT_TYPE_DEFAULT_SEC = 0, + VK_THROTTLE_HINT_TYPE_LOW_SEC = 1, + VK_THROTTLE_HINT_TYPE_HIGH_SEC = 2, + VK_THROTTLE_HINT_TYPE_MAX_ENUM_SEC = 0x7FFFFFFF +} VkThrottleHintTypeSEC; +typedef struct VkThrottleHintSubmitInfoSEC { + VkStructureType sType; + const void* pNext; + VkThrottleHintTypeSEC throttleHint; +} VkThrottleHintSubmitInfoSEC; + +typedef struct VkPhysicalDeviceThrottleHintFeaturesSEC { + VkStructureType sType; + void* pNext; + VkBool32 throttleHint; +} VkPhysicalDeviceThrottleHintFeaturesSEC; + + + +// VK_ARM_data_graph_neural_accelerator_statistics is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_data_graph_neural_accelerator_statistics 1 +#define VK_ARM_DATA_GRAPH_NEURAL_ACCELERATOR_STATISTICS_SPEC_VERSION 1 +#define VK_ARM_DATA_GRAPH_NEURAL_ACCELERATOR_STATISTICS_EXTENSION_NAME "VK_ARM_data_graph_neural_accelerator_statistics" + +typedef enum VkNeuralAcceleratorStatisticsModeARM { + VK_NEURAL_ACCELERATOR_STATISTICS_MODE_DISABLED_ARM = 0, + VK_NEURAL_ACCELERATOR_STATISTICS_MODE_STATISTICS0_ARM = 1, + VK_NEURAL_ACCELERATOR_STATISTICS_MODE_STATISTICS1_ARM = 2, + VK_NEURAL_ACCELERATOR_STATISTICS_MODE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkNeuralAcceleratorStatisticsModeARM; +typedef struct VkPhysicalDeviceDataGraphNeuralAcceleratorStatisticsFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 dataGraphNeuralAcceleratorStatistics; +} VkPhysicalDeviceDataGraphNeuralAcceleratorStatisticsFeaturesARM; + +typedef struct VkDataGraphPipelineNeuralStatisticsCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkBool32 allowNeuralStatistics; +} VkDataGraphPipelineNeuralStatisticsCreateInfoARM; + +typedef struct VkDataGraphPipelineSessionNeuralStatisticsCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkNeuralAcceleratorStatisticsModeARM mode; +} VkDataGraphPipelineSessionNeuralStatisticsCreateInfoARM; + + + +// VK_EXT_primitive_restart_index is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_primitive_restart_index 1 +#define VK_EXT_PRIMITIVE_RESTART_INDEX_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVE_RESTART_INDEX_EXTENSION_NAME "VK_EXT_primitive_restart_index" +typedef struct VkPhysicalDevicePrimitiveRestartIndexFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 primitiveRestartIndex; +} VkPhysicalDevicePrimitiveRestartIndexFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartIndexEXT)(VkCommandBuffer commandBuffer, uint32_t primitiveRestartIndex); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartIndexEXT( + VkCommandBuffer commandBuffer, + uint32_t primitiveRestartIndex); +#endif +#endif + + +// VK_NV_cooperative_matrix_decode_vector is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cooperative_matrix_decode_vector 1 +#define VK_NV_COOPERATIVE_MATRIX_DECODE_VECTOR_SPEC_VERSION 1 +#define VK_NV_COOPERATIVE_MATRIX_DECODE_VECTOR_EXTENSION_NAME "VK_NV_cooperative_matrix_decode_vector" +typedef struct VkPhysicalDeviceCooperativeMatrixDecodeVectorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrixDecodeVector; +} VkPhysicalDeviceCooperativeMatrixDecodeVectorFeaturesNV; + + + +// VK_KHR_acceleration_structure is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_acceleration_structure 1 +#define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 13 +#define VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_KHR_acceleration_structure" + +typedef enum VkBuildAccelerationStructureModeKHR { + VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR = 0, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR = 1, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureModeKHR; +typedef struct VkAccelerationStructureBuildRangeInfoKHR { + uint32_t primitiveCount; + uint32_t primitiveOffset; + uint32_t firstVertex; + uint32_t transformOffset; +} VkAccelerationStructureBuildRangeInfoKHR; + +typedef struct VkAccelerationStructureGeometryTrianglesDataKHR { + VkStructureType sType; + const void* pNext; + VkFormat vertexFormat; + VkDeviceOrHostAddressConstKHR vertexData; + VkDeviceSize vertexStride; + uint32_t maxVertex; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexData; + VkDeviceOrHostAddressConstKHR transformData; +} VkAccelerationStructureGeometryTrianglesDataKHR; + +typedef struct VkAccelerationStructureGeometryAabbsDataKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR data; + VkDeviceSize stride; +} VkAccelerationStructureGeometryAabbsDataKHR; + +typedef struct VkAccelerationStructureGeometryInstancesDataKHR { + VkStructureType sType; + const void* pNext; + VkBool32 arrayOfPointers; + VkDeviceOrHostAddressConstKHR data; +} VkAccelerationStructureGeometryInstancesDataKHR; + +typedef union VkAccelerationStructureGeometryDataKHR { + VkAccelerationStructureGeometryTrianglesDataKHR triangles; + VkAccelerationStructureGeometryAabbsDataKHR aabbs; + VkAccelerationStructureGeometryInstancesDataKHR instances; +} VkAccelerationStructureGeometryDataKHR; + +typedef struct VkAccelerationStructureGeometryKHR { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkAccelerationStructureGeometryDataKHR geometry; + VkGeometryFlagsKHR flags; +} VkAccelerationStructureGeometryKHR; + +typedef struct VkAccelerationStructureBuildGeometryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeKHR type; + VkBuildAccelerationStructureFlagsKHR flags; + VkBuildAccelerationStructureModeKHR mode; + VkAccelerationStructureKHR srcAccelerationStructure; + VkAccelerationStructureKHR dstAccelerationStructure; + uint32_t geometryCount; + const VkAccelerationStructureGeometryKHR* pGeometries; + const VkAccelerationStructureGeometryKHR* const* ppGeometries; + VkDeviceOrHostAddressKHR scratchData; +} VkAccelerationStructureBuildGeometryInfoKHR; + +typedef struct VkAccelerationStructureCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureCreateFlagsKHR createFlags; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; + VkAccelerationStructureTypeKHR type; + VkDeviceAddress deviceAddress; +} VkAccelerationStructureCreateInfoKHR; + +typedef struct VkWriteDescriptorSetAccelerationStructureKHR { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureKHR* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureKHR; + +typedef struct VkPhysicalDeviceAccelerationStructureFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 accelerationStructure; + VkBool32 accelerationStructureCaptureReplay; + VkBool32 accelerationStructureIndirectBuild; + VkBool32 accelerationStructureHostCommands; + VkBool32 descriptorBindingAccelerationStructureUpdateAfterBind; +} VkPhysicalDeviceAccelerationStructureFeaturesKHR; + +typedef struct VkPhysicalDeviceAccelerationStructurePropertiesKHR { + VkStructureType sType; + void* pNext; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxPrimitiveCount; + uint32_t maxPerStageDescriptorAccelerationStructures; + uint32_t maxPerStageDescriptorUpdateAfterBindAccelerationStructures; + uint32_t maxDescriptorSetAccelerationStructures; + uint32_t maxDescriptorSetUpdateAfterBindAccelerationStructures; + uint32_t minAccelerationStructureScratchOffsetAlignment; +} VkPhysicalDeviceAccelerationStructurePropertiesKHR; + +typedef struct VkAccelerationStructureDeviceAddressInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR accelerationStructure; +} VkAccelerationStructureDeviceAddressInfoKHR; + +typedef struct VkAccelerationStructureVersionInfoKHR { + VkStructureType sType; + const void* pNext; + const uint8_t* pVersionData; +} VkAccelerationStructureVersionInfoKHR; + +typedef struct VkCopyAccelerationStructureToMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkDeviceOrHostAddressKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureToMemoryInfoKHR; + +typedef struct VkCopyMemoryToAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyMemoryToAccelerationStructureInfoKHR; + +typedef struct VkCopyAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureKHR)(VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureKHR)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresIndirectKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkDeviceAddress* pIndirectDeviceAddresses, const uint32_t* pIndirectStrides, const uint32_t* const* ppMaxPrimitiveCounts); +typedef VkResult (VKAPI_PTR *PFN_vkBuildAccelerationStructuresKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureToMemoryKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWriteAccelerationStructuresPropertiesKHR)(VkDevice device, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetAccelerationStructureDeviceAddressKHR)(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef void (VKAPI_PTR *PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)(VkDevice device, const VkAccelerationStructureVersionInfoKHR* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureBuildSizesKHR)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureKHR( + VkDevice device, + const VkAccelerationStructureCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureKHR* pAccelerationStructure); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureKHR( + VkDevice device, + VkAccelerationStructureKHR accelerationStructure, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresIndirectKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkDeviceAddress* pIndirectDeviceAddresses, + const uint32_t* pIndirectStrides, + const uint32_t* const* ppMaxPrimitiveCounts); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBuildAccelerationStructuresKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureInfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureToMemoryKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR( + VkDevice device, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + size_t dataSize, + void* pData, + size_t stride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureInfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureToMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetAccelerationStructureDeviceAddressKHR( + VkDevice device, + const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceAccelerationStructureCompatibilityKHR( + VkDevice device, + const VkAccelerationStructureVersionInfoKHR* pVersionInfo, + VkAccelerationStructureCompatibilityKHR* pCompatibility); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureBuildSizesKHR( + VkDevice device, + VkAccelerationStructureBuildTypeKHR buildType, + const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, + const uint32_t* pMaxPrimitiveCounts, + VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +#endif +#endif + + +// VK_KHR_ray_tracing_pipeline is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_ray_tracing_pipeline 1 +#define VK_KHR_RAY_TRACING_PIPELINE_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME "VK_KHR_ray_tracing_pipeline" + +typedef enum VkShaderGroupShaderKHR { + 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, + VK_SHADER_GROUP_SHADER_MAX_ENUM_KHR = 0x7FFFFFFF +} VkShaderGroupShaderKHR; +typedef struct VkRayTracingShaderGroupCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; + const void* pShaderGroupCaptureReplayHandle; +} VkRayTracingShaderGroupCreateInfoKHR; + +typedef struct VkRayTracingPipelineInterfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxPipelineRayPayloadSize; + uint32_t maxPipelineRayHitAttributeSize; +} VkRayTracingPipelineInterfaceCreateInfoKHR; + +typedef struct VkRayTracingPipelineCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoKHR* pGroups; + uint32_t maxPipelineRayRecursionDepth; + const VkPipelineLibraryCreateInfoKHR* pLibraryInfo; + const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface; + const VkPipelineDynamicStateCreateInfo* pDynamicState; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelineFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingPipeline; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplay; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplayMixed; + VkBool32 rayTracingPipelineTraceRaysIndirect; + VkBool32 rayTraversalPrimitiveCulling; +} VkPhysicalDeviceRayTracingPipelineFeaturesKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelinePropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRayRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint32_t shaderGroupHandleCaptureReplaySize; + uint32_t maxRayDispatchInvocationCount; + uint32_t shaderGroupHandleAlignment; + uint32_t maxRayHitAttributeSize; +} VkPhysicalDeviceRayTracingPipelinePropertiesKHR; + +typedef struct VkTraceRaysIndirectCommandKHR { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkTraceRaysIndirectCommandKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirectKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, VkDeviceAddress indirectDeviceAddress); +typedef VkDeviceSize (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupStackSizeKHR)(VkDevice device, VkPipeline pipeline, uint32_t group, VkShaderGroupShaderKHR groupShader); +typedef void (VKAPI_PTR *PFN_vkCmdSetRayTracingPipelineStackSizeKHR)(VkCommandBuffer commandBuffer, uint32_t pipelineStackSize); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + uint32_t width, + uint32_t height, + uint32_t depth); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + VkDeviceAddress indirectDeviceAddress); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkDeviceSize VKAPI_CALL vkGetRayTracingShaderGroupStackSizeKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t group, + VkShaderGroupShaderKHR groupShader); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetRayTracingPipelineStackSizeKHR( + VkCommandBuffer commandBuffer, + uint32_t pipelineStackSize); +#endif +#endif + + +// VK_KHR_ray_query is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_ray_query 1 +#define VK_KHR_RAY_QUERY_SPEC_VERSION 1 +#define VK_KHR_RAY_QUERY_EXTENSION_NAME "VK_KHR_ray_query" +typedef struct VkPhysicalDeviceRayQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayQuery; +} VkPhysicalDeviceRayQueryFeaturesKHR; + + + +// VK_EXT_mesh_shader is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_mesh_shader 1 +#define VK_EXT_MESH_SHADER_SPEC_VERSION 1 +#define VK_EXT_MESH_SHADER_EXTENSION_NAME "VK_EXT_mesh_shader" +typedef struct VkPhysicalDeviceMeshShaderFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 taskShader; + VkBool32 meshShader; + VkBool32 multiviewMeshShader; + VkBool32 primitiveFragmentShadingRateMeshShader; + VkBool32 meshShaderQueries; +} VkPhysicalDeviceMeshShaderFeaturesEXT; + +typedef struct VkPhysicalDeviceMeshShaderPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxTaskWorkGroupTotalCount; + uint32_t maxTaskWorkGroupCount[3]; + uint32_t maxTaskWorkGroupInvocations; + uint32_t maxTaskWorkGroupSize[3]; + uint32_t maxTaskPayloadSize; + uint32_t maxTaskSharedMemorySize; + uint32_t maxTaskPayloadAndSharedMemorySize; + uint32_t maxMeshWorkGroupTotalCount; + uint32_t maxMeshWorkGroupCount[3]; + uint32_t maxMeshWorkGroupInvocations; + uint32_t maxMeshWorkGroupSize[3]; + uint32_t maxMeshSharedMemorySize; + uint32_t maxMeshPayloadAndSharedMemorySize; + uint32_t maxMeshOutputMemorySize; + uint32_t maxMeshPayloadAndOutputMemorySize; + uint32_t maxMeshOutputComponents; + uint32_t maxMeshOutputVertices; + uint32_t maxMeshOutputPrimitives; + uint32_t maxMeshOutputLayers; + uint32_t maxMeshMultiviewViewCount; + uint32_t meshOutputPerVertexGranularity; + uint32_t meshOutputPerPrimitiveGranularity; + uint32_t maxPreferredTaskWorkGroupInvocations; + uint32_t maxPreferredMeshWorkGroupInvocations; + VkBool32 prefersLocalInvocationVertexOutput; + VkBool32 prefersLocalInvocationPrimitiveOutput; + VkBool32 prefersCompactVertexOutput; + VkBool32 prefersCompactPrimitiveOutput; +} VkPhysicalDeviceMeshShaderPropertiesEXT; + +typedef struct VkDrawMeshTasksIndirectCommandEXT { + uint32_t groupCountX; + uint32_t groupCountY; + uint32_t groupCountZ; +} VkDrawMeshTasksIndirectCommandEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksEXT)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectEXT)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountEXT)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksEXT( + VkCommandBuffer commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectEXT( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountEXT( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_directfb.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_directfb.h new file mode 100644 index 00000000..b96e957e --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_directfb.h @@ -0,0 +1,59 @@ +#ifndef VULKAN_DIRECTFB_H_ +#define VULKAN_DIRECTFB_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_EXT_directfb_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_directfb_surface 1 +#define VK_EXT_DIRECTFB_SURFACE_SPEC_VERSION 1 +#define VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME "VK_EXT_directfb_surface" +typedef VkFlags VkDirectFBSurfaceCreateFlagsEXT; +typedef struct VkDirectFBSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDirectFBSurfaceCreateFlagsEXT flags; + IDirectFB* dfb; + IDirectFBSurface* surface; +} VkDirectFBSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDirectFBSurfaceEXT)(VkInstance instance, const VkDirectFBSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, IDirectFB* dfb); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDirectFBSurfaceEXT( + VkInstance instance, + const VkDirectFBSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceDirectFBPresentationSupportEXT( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + IDirectFB* dfb); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_fuchsia.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_fuchsia.h new file mode 100644 index 00000000..ccca6271 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_fuchsia.h @@ -0,0 +1,282 @@ +#ifndef VULKAN_FUCHSIA_H_ +#define VULKAN_FUCHSIA_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_FUCHSIA_imagepipe_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_FUCHSIA_imagepipe_surface 1 +#define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1 +#define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface" +typedef VkFlags VkImagePipeSurfaceCreateFlagsFUCHSIA; +typedef struct VkImagePipeSurfaceCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkImagePipeSurfaceCreateFlagsFUCHSIA flags; + zx_handle_t imagePipeHandle; +} VkImagePipeSurfaceCreateInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateImagePipeSurfaceFUCHSIA)(VkInstance instance, const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateImagePipeSurfaceFUCHSIA( + VkInstance instance, + const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + + +// VK_FUCHSIA_external_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_FUCHSIA_external_memory 1 +#define VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME "VK_FUCHSIA_external_memory" +typedef struct VkImportMemoryZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + zx_handle_t handle; +} VkImportMemoryZirconHandleInfoFUCHSIA; + +typedef struct VkMemoryZirconHandlePropertiesFUCHSIA { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryZirconHandlePropertiesFUCHSIA; + +typedef struct VkMemoryGetZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetZirconHandleInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryZirconHandleFUCHSIA)(VkDevice device, const VkMemoryGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, zx_handle_t* pZirconHandle); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, zx_handle_t zirconHandle, VkMemoryZirconHandlePropertiesFUCHSIA* pMemoryZirconHandleProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandleFUCHSIA( + VkDevice device, + const VkMemoryGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, + zx_handle_t* pZirconHandle); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandlePropertiesFUCHSIA( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + zx_handle_t zirconHandle, + VkMemoryZirconHandlePropertiesFUCHSIA* pMemoryZirconHandleProperties); +#endif +#endif + + +// VK_FUCHSIA_external_semaphore is a preprocessor guard. Do not pass it to API calls. +#define VK_FUCHSIA_external_semaphore 1 +#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 +#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_FUCHSIA_external_semaphore" +typedef struct VkImportSemaphoreZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + zx_handle_t zirconHandle; +} VkImportSemaphoreZirconHandleInfoFUCHSIA; + +typedef struct VkSemaphoreGetZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetZirconHandleInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreZirconHandleFUCHSIA)(VkDevice device, const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreZirconHandleFUCHSIA)(VkDevice device, const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, zx_handle_t* pZirconHandle); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreZirconHandleFUCHSIA( + VkDevice device, + const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreZirconHandleFUCHSIA( + VkDevice device, + const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, + zx_handle_t* pZirconHandle); +#endif +#endif + + +// VK_FUCHSIA_buffer_collection is a preprocessor guard. Do not pass it to API calls. +#define VK_FUCHSIA_buffer_collection 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA) +#define VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION 2 +#define VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME "VK_FUCHSIA_buffer_collection" +typedef VkFlags VkImageFormatConstraintsFlagsFUCHSIA; + +typedef enum VkImageConstraintsInfoFlagBitsFUCHSIA { + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA = 0x00000001, + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA = 0x00000002, + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA = 0x00000004, + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA = 0x00000008, + VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA = 0x00000010, + VK_IMAGE_CONSTRAINTS_INFO_FLAG_BITS_MAX_ENUM_FUCHSIA = 0x7FFFFFFF +} VkImageConstraintsInfoFlagBitsFUCHSIA; +typedef VkFlags VkImageConstraintsInfoFlagsFUCHSIA; +typedef struct VkBufferCollectionCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + zx_handle_t collectionToken; +} VkBufferCollectionCreateInfoFUCHSIA; + +typedef struct VkImportMemoryBufferCollectionFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkImportMemoryBufferCollectionFUCHSIA; + +typedef struct VkBufferCollectionImageCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionImageCreateInfoFUCHSIA; + +typedef struct VkBufferCollectionConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t minBufferCount; + uint32_t maxBufferCount; + uint32_t minBufferCountForCamping; + uint32_t minBufferCountForDedicatedSlack; + uint32_t minBufferCountForSharedSlack; +} VkBufferCollectionConstraintsInfoFUCHSIA; + +typedef struct VkBufferConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCreateInfo createInfo; + VkFormatFeatureFlags requiredFormatFeatures; + VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints; +} VkBufferConstraintsInfoFUCHSIA; + +typedef struct VkBufferCollectionBufferCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionBufferCreateInfoFUCHSIA; + +typedef struct VkSysmemColorSpaceFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t colorSpace; +} VkSysmemColorSpaceFUCHSIA; + +typedef struct VkBufferCollectionPropertiesFUCHSIA { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; + uint32_t bufferCount; + uint32_t createInfoIndex; + uint64_t sysmemPixelFormat; + VkFormatFeatureFlags formatFeatures; + VkSysmemColorSpaceFUCHSIA sysmemColorSpaceIndex; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkBufferCollectionPropertiesFUCHSIA; + +typedef struct VkImageFormatConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkImageCreateInfo imageCreateInfo; + VkFormatFeatureFlags requiredFormatFeatures; + VkImageFormatConstraintsFlagsFUCHSIA flags; + uint64_t sysmemPixelFormat; + uint32_t colorSpaceCount; + const VkSysmemColorSpaceFUCHSIA* pColorSpaces; +} VkImageFormatConstraintsInfoFUCHSIA; + +typedef struct VkImageConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t formatConstraintsCount; + const VkImageFormatConstraintsInfoFUCHSIA* pFormatConstraints; + VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints; + VkImageConstraintsInfoFlagsFUCHSIA flags; +} VkImageConstraintsInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferCollectionFUCHSIA)(VkDevice device, const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferCollectionFUCHSIA* pCollection); +typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo); +typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo); +typedef void (VKAPI_PTR *PFN_vkDestroyBufferCollectionFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetBufferCollectionPropertiesFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, VkBufferCollectionPropertiesFUCHSIA* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferCollectionFUCHSIA( + VkDevice device, + const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferCollectionFUCHSIA* pCollection); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionImageConstraintsFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionBufferConstraintsFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyBufferCollectionFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferCollectionPropertiesFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_ggp.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_ggp.h new file mode 100644 index 00000000..f8a48ec8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_ggp.h @@ -0,0 +1,62 @@ +#ifndef VULKAN_GGP_H_ +#define VULKAN_GGP_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_GGP_stream_descriptor_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_GGP_stream_descriptor_surface 1 +#define VK_GGP_STREAM_DESCRIPTOR_SURFACE_SPEC_VERSION 1 +#define VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME "VK_GGP_stream_descriptor_surface" +typedef VkFlags VkStreamDescriptorSurfaceCreateFlagsGGP; +typedef struct VkStreamDescriptorSurfaceCreateInfoGGP { + VkStructureType sType; + const void* pNext; + VkStreamDescriptorSurfaceCreateFlagsGGP flags; + GgpStreamDescriptor streamDescriptor; +} VkStreamDescriptorSurfaceCreateInfoGGP; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateStreamDescriptorSurfaceGGP)(VkInstance instance, const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateStreamDescriptorSurfaceGGP( + VkInstance instance, + const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + + +// VK_GGP_frame_token is a preprocessor guard. Do not pass it to API calls. +#define VK_GGP_frame_token 1 +#define VK_GGP_FRAME_TOKEN_SPEC_VERSION 1 +#define VK_GGP_FRAME_TOKEN_EXTENSION_NAME "VK_GGP_frame_token" +typedef struct VkPresentFrameTokenGGP { + VkStructureType sType; + const void* pNext; + GgpFrameToken frameToken; +} VkPresentFrameTokenGGP; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_ios.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_ios.h new file mode 100644 index 00000000..089991a4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_ios.h @@ -0,0 +1,50 @@ +#ifndef VULKAN_IOS_H_ +#define VULKAN_IOS_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_MVK_ios_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_MVK_ios_surface 1 +#define VK_MVK_IOS_SURFACE_SPEC_VERSION 3 +#define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface" +typedef VkFlags VkIOSSurfaceCreateFlagsMVK; +typedef struct VkIOSSurfaceCreateInfoMVK { + VkStructureType sType; + const void* pNext; + VkIOSSurfaceCreateFlagsMVK flags; + const void* pView; +} VkIOSSurfaceCreateInfoMVK; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateIOSSurfaceMVK)(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK( + VkInstance instance, + const VkIOSSurfaceCreateInfoMVK* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_macos.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_macos.h new file mode 100644 index 00000000..7d5d8a1b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_macos.h @@ -0,0 +1,50 @@ +#ifndef VULKAN_MACOS_H_ +#define VULKAN_MACOS_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_MVK_macos_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_MVK_macos_surface 1 +#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 3 +#define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface" +typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; +typedef struct VkMacOSSurfaceCreateInfoMVK { + VkStructureType sType; + const void* pNext; + VkMacOSSurfaceCreateFlagsMVK flags; + const void* pView; +} VkMacOSSurfaceCreateInfoMVK; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateMacOSSurfaceMVK)(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK( + VkInstance instance, + const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_metal.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_metal.h new file mode 100644 index 00000000..501c3638 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_metal.h @@ -0,0 +1,244 @@ +#ifndef VULKAN_METAL_H_ +#define VULKAN_METAL_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_EXT_metal_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_metal_surface 1 +#ifdef __OBJC__ +@class CAMetalLayer; +#else +typedef void CAMetalLayer; +#endif + +#define VK_EXT_METAL_SURFACE_SPEC_VERSION 1 +#define VK_EXT_METAL_SURFACE_EXTENSION_NAME "VK_EXT_metal_surface" +typedef VkFlags VkMetalSurfaceCreateFlagsEXT; +typedef struct VkMetalSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkMetalSurfaceCreateFlagsEXT flags; + const CAMetalLayer* pLayer; +} VkMetalSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateMetalSurfaceEXT)(VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT( + VkInstance instance, + const VkMetalSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + + +// VK_EXT_metal_objects is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_metal_objects 1 +#ifdef __OBJC__ +@protocol MTLDevice; +typedef __unsafe_unretained id MTLDevice_id; +#else +typedef void* MTLDevice_id; +#endif + +#ifdef __OBJC__ +@protocol MTLCommandQueue; +typedef __unsafe_unretained id MTLCommandQueue_id; +#else +typedef void* MTLCommandQueue_id; +#endif + +#ifdef __OBJC__ +@protocol MTLBuffer; +typedef __unsafe_unretained id MTLBuffer_id; +#else +typedef void* MTLBuffer_id; +#endif + +#ifdef __OBJC__ +@protocol MTLTexture; +typedef __unsafe_unretained id MTLTexture_id; +#else +typedef void* MTLTexture_id; +#endif + +typedef struct __IOSurface* IOSurfaceRef; +#ifdef __OBJC__ +@protocol MTLSharedEvent; +typedef __unsafe_unretained id MTLSharedEvent_id; +#else +typedef void* MTLSharedEvent_id; +#endif + +#define VK_EXT_METAL_OBJECTS_SPEC_VERSION 2 +#define VK_EXT_METAL_OBJECTS_EXTENSION_NAME "VK_EXT_metal_objects" + +typedef enum VkExportMetalObjectTypeFlagBitsEXT { + VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT = 0x00000001, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT = 0x00000002, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT = 0x00000004, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT = 0x00000008, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT = 0x00000010, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT = 0x00000020, + VK_EXPORT_METAL_OBJECT_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkExportMetalObjectTypeFlagBitsEXT; +typedef VkFlags VkExportMetalObjectTypeFlagsEXT; +typedef struct VkExportMetalObjectCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkExportMetalObjectTypeFlagBitsEXT exportObjectType; +} VkExportMetalObjectCreateInfoEXT; + +typedef struct VkExportMetalObjectsInfoEXT { + VkStructureType sType; + const void* pNext; +} VkExportMetalObjectsInfoEXT; + +typedef struct VkExportMetalDeviceInfoEXT { + VkStructureType sType; + const void* pNext; + MTLDevice_id mtlDevice; +} VkExportMetalDeviceInfoEXT; + +typedef struct VkExportMetalCommandQueueInfoEXT { + VkStructureType sType; + const void* pNext; + VkQueue queue; + MTLCommandQueue_id mtlCommandQueue; +} VkExportMetalCommandQueueInfoEXT; + +typedef struct VkExportMetalBufferInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + MTLBuffer_id mtlBuffer; +} VkExportMetalBufferInfoEXT; + +typedef struct VkImportMetalBufferInfoEXT { + VkStructureType sType; + const void* pNext; + MTLBuffer_id mtlBuffer; +} VkImportMetalBufferInfoEXT; + +typedef struct VkExportMetalTextureInfoEXT { + VkStructureType sType; + const void* pNext; + VkImage image; + VkImageView imageView; + VkBufferView bufferView; + VkImageAspectFlagBits plane; + MTLTexture_id mtlTexture; +} VkExportMetalTextureInfoEXT; + +typedef struct VkImportMetalTextureInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageAspectFlagBits plane; + MTLTexture_id mtlTexture; +} VkImportMetalTextureInfoEXT; + +typedef struct VkExportMetalIOSurfaceInfoEXT { + VkStructureType sType; + const void* pNext; + VkImage image; + IOSurfaceRef ioSurface; +} VkExportMetalIOSurfaceInfoEXT; + +typedef struct VkImportMetalIOSurfaceInfoEXT { + VkStructureType sType; + const void* pNext; + IOSurfaceRef ioSurface; +} VkImportMetalIOSurfaceInfoEXT; + +typedef struct VkExportMetalSharedEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkEvent event; + MTLSharedEvent_id mtlSharedEvent; +} VkExportMetalSharedEventInfoEXT; + +typedef struct VkImportMetalSharedEventInfoEXT { + VkStructureType sType; + const void* pNext; + MTLSharedEvent_id mtlSharedEvent; +} VkImportMetalSharedEventInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkExportMetalObjectsEXT)(VkDevice device, VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkExportMetalObjectsEXT( + VkDevice device, + VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); +#endif +#endif + + +// VK_EXT_external_memory_metal is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_external_memory_metal 1 +#define VK_EXT_EXTERNAL_MEMORY_METAL_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME "VK_EXT_external_memory_metal" +typedef struct VkImportMemoryMetalHandleInfoEXT { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + void* handle; +} VkImportMemoryMetalHandleInfoEXT; + +typedef struct VkMemoryMetalHandlePropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryMetalHandlePropertiesEXT; + +typedef struct VkMemoryGetMetalHandleInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetMetalHandleInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryMetalHandleEXT)(VkDevice device, const VkMemoryGetMetalHandleInfoEXT* pGetMetalHandleInfo, void** pHandle); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryMetalHandlePropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHandle, VkMemoryMetalHandlePropertiesEXT* pMemoryMetalHandleProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryMetalHandleEXT( + VkDevice device, + const VkMemoryGetMetalHandleInfoEXT* pGetMetalHandleInfo, + void** pHandle); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryMetalHandlePropertiesEXT( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + const void* pHandle, + VkMemoryMetalHandlePropertiesEXT* pMemoryMetalHandleProperties); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_ohos.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_ohos.h new file mode 100644 index 00000000..3bde0114 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_ohos.h @@ -0,0 +1,120 @@ +#ifndef VULKAN_OHOS_H_ +#define VULKAN_OHOS_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_OHOS_external_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_OHOS_external_memory 1 +struct OH_NativeBuffer; +#define VK_OHOS_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_OHOS_EXTERNAL_MEMORY_EXTENSION_NAME "VK_OHOS_external_memory" +typedef struct VkNativeBufferUsageOHOS { + VkStructureType sType; + void* pNext; + uint64_t OHOSNativeBufferUsage; +} VkNativeBufferUsageOHOS; + +typedef struct VkNativeBufferPropertiesOHOS { + VkStructureType sType; + void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeBits; +} VkNativeBufferPropertiesOHOS; + +typedef struct VkNativeBufferFormatPropertiesOHOS { + VkStructureType sType; + void* pNext; + VkFormat format; + uint64_t externalFormat; + VkFormatFeatureFlags formatFeatures; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkNativeBufferFormatPropertiesOHOS; + +typedef struct VkImportNativeBufferInfoOHOS { + VkStructureType sType; + const void* pNext; + struct OH_NativeBuffer* buffer; +} VkImportNativeBufferInfoOHOS; + +typedef struct VkMemoryGetNativeBufferInfoOHOS { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; +} VkMemoryGetNativeBufferInfoOHOS; + +typedef struct VkExternalFormatOHOS { + VkStructureType sType; + void* pNext; + uint64_t externalFormat; +} VkExternalFormatOHOS; + +typedef VkResult (VKAPI_PTR *PFN_vkGetNativeBufferPropertiesOHOS)(VkDevice device, const struct OH_NativeBuffer* buffer, VkNativeBufferPropertiesOHOS* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryNativeBufferOHOS)(VkDevice device, const VkMemoryGetNativeBufferInfoOHOS* pInfo, struct OH_NativeBuffer** pBuffer); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetNativeBufferPropertiesOHOS( + VkDevice device, + const struct OH_NativeBuffer* buffer, + VkNativeBufferPropertiesOHOS* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryNativeBufferOHOS( + VkDevice device, + const VkMemoryGetNativeBufferInfoOHOS* pInfo, + struct OH_NativeBuffer** pBuffer); +#endif +#endif + + +// VK_OHOS_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_OHOS_surface 1 +typedef struct NativeWindow OHNativeWindow; +#define VK_OHOS_SURFACE_SPEC_VERSION 1 +#define VK_OHOS_SURFACE_EXTENSION_NAME "VK_OHOS_surface" +typedef VkFlags VkSurfaceCreateFlagsOHOS; +typedef struct VkSurfaceCreateInfoOHOS { + VkStructureType sType; + const void* pNext; + VkSurfaceCreateFlagsOHOS flags; + OHNativeWindow* window; +} VkSurfaceCreateInfoOHOS; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSurfaceOHOS)(VkInstance instance, const VkSurfaceCreateInfoOHOS* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSurfaceOHOS( + VkInstance instance, + const VkSurfaceCreateInfoOHOS* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_screen.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_screen.h new file mode 100644 index 00000000..15e9d090 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_screen.h @@ -0,0 +1,114 @@ +#ifndef VULKAN_SCREEN_H_ +#define VULKAN_SCREEN_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_QNX_screen_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_QNX_screen_surface 1 +#define VK_QNX_SCREEN_SURFACE_SPEC_VERSION 1 +#define VK_QNX_SCREEN_SURFACE_EXTENSION_NAME "VK_QNX_screen_surface" +typedef VkFlags VkScreenSurfaceCreateFlagsQNX; +typedef struct VkScreenSurfaceCreateInfoQNX { + VkStructureType sType; + const void* pNext; + VkScreenSurfaceCreateFlagsQNX flags; + struct _screen_context* context; + struct _screen_window* window; +} VkScreenSurfaceCreateInfoQNX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateScreenSurfaceQNX)(VkInstance instance, const VkScreenSurfaceCreateInfoQNX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct _screen_window* window); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateScreenSurfaceQNX( + VkInstance instance, + const VkScreenSurfaceCreateInfoQNX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceScreenPresentationSupportQNX( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + struct _screen_window* window); +#endif +#endif + + +// VK_QNX_external_memory_screen_buffer is a preprocessor guard. Do not pass it to API calls. +#define VK_QNX_external_memory_screen_buffer 1 +#define VK_QNX_EXTERNAL_MEMORY_SCREEN_BUFFER_SPEC_VERSION 1 +#define VK_QNX_EXTERNAL_MEMORY_SCREEN_BUFFER_EXTENSION_NAME "VK_QNX_external_memory_screen_buffer" +typedef struct VkScreenBufferPropertiesQNX { + VkStructureType sType; + void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeBits; +} VkScreenBufferPropertiesQNX; + +typedef struct VkScreenBufferFormatPropertiesQNX { + VkStructureType sType; + void* pNext; + VkFormat format; + uint64_t externalFormat; + uint64_t screenUsage; + VkFormatFeatureFlags formatFeatures; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkScreenBufferFormatPropertiesQNX; + +typedef struct VkImportScreenBufferInfoQNX { + VkStructureType sType; + const void* pNext; + struct _screen_buffer* buffer; +} VkImportScreenBufferInfoQNX; + +typedef struct VkExternalFormatQNX { + VkStructureType sType; + void* pNext; + uint64_t externalFormat; +} VkExternalFormatQNX; + +typedef struct VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX { + VkStructureType sType; + void* pNext; + VkBool32 screenBufferImport; +} VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX; + +typedef VkResult (VKAPI_PTR *PFN_vkGetScreenBufferPropertiesQNX)(VkDevice device, const struct _screen_buffer* buffer, VkScreenBufferPropertiesQNX* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetScreenBufferPropertiesQNX( + VkDevice device, + const struct _screen_buffer* buffer, + VkScreenBufferPropertiesQNX* pProperties); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_vi.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_vi.h new file mode 100644 index 00000000..97d1a3c5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_vi.h @@ -0,0 +1,50 @@ +#ifndef VULKAN_VI_H_ +#define VULKAN_VI_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_NN_vi_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_NN_vi_surface 1 +#define VK_NN_VI_SURFACE_SPEC_VERSION 1 +#define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface" +typedef VkFlags VkViSurfaceCreateFlagsNN; +typedef struct VkViSurfaceCreateInfoNN { + VkStructureType sType; + const void* pNext; + VkViSurfaceCreateFlagsNN flags; + void* window; +} VkViSurfaceCreateInfoNN; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateViSurfaceNN)(VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN( + VkInstance instance, + const VkViSurfaceCreateInfoNN* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_wayland.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_wayland.h new file mode 100644 index 00000000..41025db4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_wayland.h @@ -0,0 +1,59 @@ +#ifndef VULKAN_WAYLAND_H_ +#define VULKAN_WAYLAND_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_KHR_wayland_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_wayland_surface 1 +#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6 +#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface" +typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; +typedef struct VkWaylandSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkWaylandSurfaceCreateFlagsKHR flags; + struct wl_display* display; + struct wl_surface* surface; +} VkWaylandSurfaceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR( + VkInstance instance, + const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + struct wl_display* display); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_win32.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_win32.h new file mode 100644 index 00000000..5c7e8bd6 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_win32.h @@ -0,0 +1,372 @@ +#ifndef VULKAN_WIN32_H_ +#define VULKAN_WIN32_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_KHR_win32_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_win32_surface 1 +#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6 +#define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface" +typedef VkFlags VkWin32SurfaceCreateFlagsKHR; +typedef struct VkWin32SurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkWin32SurfaceCreateFlagsKHR flags; + HINSTANCE hinstance; + HWND hwnd; +} VkWin32SurfaceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR( + VkInstance instance, + const VkWin32SurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex); +#endif +#endif + + +// VK_KHR_external_memory_win32 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_memory_win32 1 +#define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32" +typedef struct VkImportMemoryWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + HANDLE handle; + LPCWSTR name; +} VkImportMemoryWin32HandleInfoKHR; + +typedef struct VkExportMemoryWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; + LPCWSTR name; +} VkExportMemoryWin32HandleInfoKHR; + +typedef struct VkMemoryWin32HandlePropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryWin32HandlePropertiesKHR; + +typedef struct VkMemoryGetWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetWin32HandleInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR( + VkDevice device, + const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, + HANDLE* pHandle); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + HANDLE handle, + VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); +#endif +#endif + + +// VK_KHR_win32_keyed_mutex is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_win32_keyed_mutex 1 +#define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1 +#define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex" +typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t acquireCount; + const VkDeviceMemory* pAcquireSyncs; + const uint64_t* pAcquireKeys; + const uint32_t* pAcquireTimeouts; + uint32_t releaseCount; + const VkDeviceMemory* pReleaseSyncs; + const uint64_t* pReleaseKeys; +} VkWin32KeyedMutexAcquireReleaseInfoKHR; + + + +// VK_KHR_external_semaphore_win32 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_semaphore_win32 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32" +typedef struct VkImportSemaphoreWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + HANDLE handle; + LPCWSTR name; +} VkImportSemaphoreWin32HandleInfoKHR; + +typedef struct VkExportSemaphoreWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; + LPCWSTR name; +} VkExportSemaphoreWin32HandleInfoKHR; + +typedef struct VkD3D12FenceSubmitInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreValuesCount; + const uint64_t* pWaitSemaphoreValues; + uint32_t signalSemaphoreValuesCount; + const uint64_t* pSignalSemaphoreValues; +} VkD3D12FenceSubmitInfoKHR; + +typedef struct VkSemaphoreGetWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetWin32HandleInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR( + VkDevice device, + const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR( + VkDevice device, + const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, + HANDLE* pHandle); +#endif +#endif + + +// VK_KHR_external_fence_win32 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_external_fence_win32 1 +#define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32" +typedef struct VkImportFenceWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkFenceImportFlags flags; + VkExternalFenceHandleTypeFlagBits handleType; + HANDLE handle; + LPCWSTR name; +} VkImportFenceWin32HandleInfoKHR; + +typedef struct VkExportFenceWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; + LPCWSTR name; +} VkExportFenceWin32HandleInfoKHR; + +typedef struct VkFenceGetWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkExternalFenceHandleTypeFlagBits handleType; +} VkFenceGetWin32HandleInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR( + VkDevice device, + const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR( + VkDevice device, + const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, + HANDLE* pHandle); +#endif +#endif + + +// VK_NV_external_memory_win32 is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_external_memory_win32 1 +#define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32" +typedef struct VkImportMemoryWin32HandleInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleType; + HANDLE handle; +} VkImportMemoryWin32HandleInfoNV; + +typedef struct VkExportMemoryWin32HandleInfoNV { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; +} VkExportMemoryWin32HandleInfoNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV( + VkDevice device, + VkDeviceMemory memory, + VkExternalMemoryHandleTypeFlagsNV handleType, + HANDLE* pHandle); +#endif +#endif + + +// VK_NV_win32_keyed_mutex is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_win32_keyed_mutex 1 +#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 2 +#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex" +typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t acquireCount; + const VkDeviceMemory* pAcquireSyncs; + const uint64_t* pAcquireKeys; + const uint32_t* pAcquireTimeoutMilliseconds; + uint32_t releaseCount; + const VkDeviceMemory* pReleaseSyncs; + const uint64_t* pReleaseKeys; +} VkWin32KeyedMutexAcquireReleaseInfoNV; + + + +// VK_EXT_full_screen_exclusive is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_full_screen_exclusive 1 +#define VK_EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION 4 +#define VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME "VK_EXT_full_screen_exclusive" + +typedef enum VkFullScreenExclusiveEXT { + 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, + VK_FULL_SCREEN_EXCLUSIVE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkFullScreenExclusiveEXT; +typedef struct VkSurfaceFullScreenExclusiveInfoEXT { + VkStructureType sType; + void* pNext; + VkFullScreenExclusiveEXT fullScreenExclusive; +} VkSurfaceFullScreenExclusiveInfoEXT; + +typedef struct VkSurfaceCapabilitiesFullScreenExclusiveEXT { + VkStructureType sType; + void* pNext; + VkBool32 fullScreenExclusiveSupported; +} VkSurfaceCapabilitiesFullScreenExclusiveEXT; + +typedef struct VkSurfaceFullScreenExclusiveWin32InfoEXT { + VkStructureType sType; + const void* pNext; + HMONITOR hmonitor; +} VkSurfaceFullScreenExclusiveWin32InfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain); +typedef VkResult (VKAPI_PTR *PFN_vkReleaseFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModes2EXT)(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModes2EXT( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + uint32_t* pPresentModeCount, + VkPresentModeKHR* pPresentModes); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireFullScreenExclusiveModeEXT( + VkDevice device, + VkSwapchainKHR swapchain); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseFullScreenExclusiveModeEXT( + VkDevice device, + VkSwapchainKHR swapchain); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes2EXT( + VkDevice device, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + VkDeviceGroupPresentModeFlagsKHR* pModes); +#endif +#endif + + +// VK_NV_acquire_winrt_display is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_acquire_winrt_display 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME "VK_NV_acquire_winrt_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireWinrtDisplayNV)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetWinrtDisplayNV)(VkPhysicalDevice physicalDevice, uint32_t deviceRelativeId, VkDisplayKHR* pDisplay); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + uint32_t deviceRelativeId, + VkDisplayKHR* pDisplay); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_xcb.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_xcb.h new file mode 100644 index 00000000..473f8c28 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_xcb.h @@ -0,0 +1,60 @@ +#ifndef VULKAN_XCB_H_ +#define VULKAN_XCB_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_KHR_xcb_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_xcb_surface 1 +#define VK_KHR_XCB_SURFACE_SPEC_VERSION 6 +#define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface" +typedef VkFlags VkXcbSurfaceCreateFlagsKHR; +typedef struct VkXcbSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkXcbSurfaceCreateFlagsKHR flags; + xcb_connection_t* connection; + xcb_window_t window; +} VkXcbSurfaceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR( + VkInstance instance, + const VkXcbSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + xcb_connection_t* connection, + xcb_visualid_t visual_id); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_xlib.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_xlib.h new file mode 100644 index 00000000..dfd107c3 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_xlib.h @@ -0,0 +1,60 @@ +#ifndef VULKAN_XLIB_H_ +#define VULKAN_XLIB_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_KHR_xlib_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_xlib_surface 1 +#define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6 +#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface" +typedef VkFlags VkXlibSurfaceCreateFlagsKHR; +typedef struct VkXlibSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkXlibSurfaceCreateFlagsKHR flags; + Display* dpy; + Window window; +} VkXlibSurfaceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR( + VkInstance instance, + const VkXlibSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + Display* dpy, + VisualID visualID); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_xlib_xrandr.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_xlib_xrandr.h new file mode 100644 index 00000000..a272e246 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/include/vulkan/vulkan_xlib_xrandr.h @@ -0,0 +1,50 @@ +#ifndef VULKAN_XLIB_XRANDR_H_ +#define VULKAN_XLIB_XRANDR_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_EXT_acquire_xlib_display is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_acquire_xlib_display 1 +#define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireXlibDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetRandROutputDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireXlibDisplayEXT( + VkPhysicalDevice physicalDevice, + Display* dpy, + VkDisplayKHR display); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetRandROutputDisplayEXT( + VkPhysicalDevice physicalDevice, + Display* dpy, + RROutput rrOutput, + VkDisplayKHR* pDisplay); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/rapidjson_wrapper.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/rapidjson_wrapper.hpp new file mode 100644 index 00000000..6d1b2279 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/rapidjson_wrapper.hpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "logging.hpp" +#ifndef RAPIDJSON_HAS_STDSTRING +#define RAPIDJSON_HAS_STDSTRING 1 +#endif + +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS (kParseIterativeFlag) +#endif + +#include +#undef RAPIDJSON_ASSERT +#define RAPIDJSON_ASSERT(x) do { \ + if (!(x)) { \ + LOGE("Rapidjson assert: %s\n", #x); \ + std::terminate(); \ + } \ +} while(0) + +#include "rapidjson/document.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/writer.h" diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/renderdoc/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/renderdoc/CMakeLists.txt new file mode 100644 index 00000000..7a1aa43c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/renderdoc/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(granite-renderdoc-app INTERFACE) +target_include_directories(granite-renderdoc-app INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_definitions(granite-renderdoc-app INTERFACE GRANITE_RENDERDOC_CAPTURE) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/renderdoc/renderdoc_app.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/renderdoc/renderdoc_app.h new file mode 100644 index 00000000..075306c0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/renderdoc/renderdoc_app.h @@ -0,0 +1,688 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2019-2020 Baldur Karlsson + * + * 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. + ******************************************************************************/ + +#pragma once + +////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Documentation for the API is available at https://renderdoc.org/docs/in_application_api.html +// + +#if !defined(RENDERDOC_NO_STDINT) +#include +#endif + +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define RENDERDOC_CC __cdecl +#elif defined(__linux__) +#define RENDERDOC_CC +#elif defined(__APPLE__) +#define RENDERDOC_CC +#else +#error "Unknown platform" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////////////////////////////////////////////////// +// Constants not used directly in below API + +// This is a GUID/magic value used for when applications pass a path where shader debug +// information can be found to match up with a stripped shader. +// the define can be used like so: const GUID RENDERDOC_ShaderDebugMagicValue = +// RENDERDOC_ShaderDebugMagicValue_value +#define RENDERDOC_ShaderDebugMagicValue_struct \ + { \ + 0xeab25520, 0x6670, 0x4865, 0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff \ + } + +// as an alternative when you want a byte array (assuming x86 endianness): +#define RENDERDOC_ShaderDebugMagicValue_bytearray \ + { \ + 0x20, 0x55, 0xb2, 0xea, 0x70, 0x66, 0x65, 0x48, 0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff \ + } + +// truncated version when only a uint64_t is available (e.g. Vulkan tags): +#define RENDERDOC_ShaderDebugMagicValue_truncated 0x48656670eab25520ULL + +////////////////////////////////////////////////////////////////////////////////////////////////// +// RenderDoc capture options +// + +typedef enum RENDERDOC_CaptureOption { + // Allow the application to enable vsync + // + // Default - enabled + // + // 1 - The application can enable or disable vsync at will + // 0 - vsync is force disabled + eRENDERDOC_Option_AllowVSync = 0, + + // Allow the application to enable fullscreen + // + // Default - enabled + // + // 1 - The application can enable or disable fullscreen at will + // 0 - fullscreen is force disabled + eRENDERDOC_Option_AllowFullscreen = 1, + + // Record API debugging events and messages + // + // Default - disabled + // + // 1 - Enable built-in API debugging features and records the results into + // the capture, which is matched up with events on replay + // 0 - no API debugging is forcibly enabled + eRENDERDOC_Option_APIValidation = 2, + eRENDERDOC_Option_DebugDeviceMode = 2, // deprecated name of this enum + + // Capture CPU callstacks for API events + // + // Default - disabled + // + // 1 - Enables capturing of callstacks + // 0 - no callstacks are captured + eRENDERDOC_Option_CaptureCallstacks = 3, + + // When capturing CPU callstacks, only capture them from drawcalls. + // This option does nothing without the above option being enabled + // + // Default - disabled + // + // 1 - Only captures callstacks for drawcall type API events. + // Ignored if CaptureCallstacks is disabled + // 0 - Callstacks, if enabled, are captured for every event. + eRENDERDOC_Option_CaptureCallstacksOnlyDraws = 4, + + // Specify a delay in seconds to wait for a debugger to attach, after + // creating or injecting into a process, before continuing to allow it to run. + // + // 0 indicates no delay, and the process will run immediately after injection + // + // Default - 0 seconds + // + eRENDERDOC_Option_DelayForDebugger = 5, + + // Verify buffer access. This includes checking the memory returned by a Map() call to + // detect any out-of-bounds modification, as well as initialising buffers with undefined contents + // to a marker value to catch use of uninitialised memory. + // + // NOTE: This option is only valid for OpenGL and D3D11. Explicit APIs such as D3D12 and Vulkan do + // not do the same kind of interception & checking and undefined contents are really undefined. + // + // Default - disabled + // + // 1 - Verify buffer access + // 0 - No verification is performed, and overwriting bounds may cause crashes or corruption in + // RenderDoc. + eRENDERDOC_Option_VerifyBufferAccess = 6, + + // The old name for eRENDERDOC_Option_VerifyBufferAccess was eRENDERDOC_Option_VerifyMapWrites. + // This option now controls the filling of uninitialised buffers with 0xdddddddd which was + // previously always enabled + eRENDERDOC_Option_VerifyMapWrites = eRENDERDOC_Option_VerifyBufferAccess, + + // Hooks any system API calls that create child processes, and injects + // RenderDoc into them recursively with the same options. + // + // Default - disabled + // + // 1 - Hooks into spawned child processes + // 0 - Child processes are not hooked by RenderDoc + eRENDERDOC_Option_HookIntoChildren = 7, + + // By default RenderDoc only includes resources in the final capture necessary + // for that frame, this allows you to override that behaviour. + // + // Default - disabled + // + // 1 - all live resources at the time of capture are included in the capture + // and available for inspection + // 0 - only the resources referenced by the captured frame are included + eRENDERDOC_Option_RefAllResources = 8, + + // **NOTE**: As of RenderDoc v1.1 this option has been deprecated. Setting or + // getting it will be ignored, to allow compatibility with older versions. + // In v1.1 the option acts as if it's always enabled. + // + // By default RenderDoc skips saving initial states for resources where the + // previous contents don't appear to be used, assuming that writes before + // reads indicate previous contents aren't used. + // + // Default - disabled + // + // 1 - initial contents at the start of each captured frame are saved, even if + // they are later overwritten or cleared before being used. + // 0 - unless a read is detected, initial contents will not be saved and will + // appear as black or empty data. + eRENDERDOC_Option_SaveAllInitials = 9, + + // In APIs that allow for the recording of command lists to be replayed later, + // RenderDoc may choose to not capture command lists before a frame capture is + // triggered, to reduce overheads. This means any command lists recorded once + // and replayed many times will not be available and may cause a failure to + // capture. + // + // NOTE: This is only true for APIs where multithreading is difficult or + // discouraged. Newer APIs like Vulkan and D3D12 will ignore this option + // and always capture all command lists since the API is heavily oriented + // around it and the overheads have been reduced by API design. + // + // 1 - All command lists are captured from the start of the application + // 0 - Command lists are only captured if their recording begins during + // the period when a frame capture is in progress. + eRENDERDOC_Option_CaptureAllCmdLists = 10, + + // Mute API debugging output when the API validation mode option is enabled + // + // Default - enabled + // + // 1 - Mute any API debug messages from being displayed or passed through + // 0 - API debugging is displayed as normal + eRENDERDOC_Option_DebugOutputMute = 11, + + // Option to allow vendor extensions to be used even when they may be + // incompatible with RenderDoc and cause corrupted replays or crashes. + // + // Default - inactive + // + // No values are documented, this option should only be used when absolutely + // necessary as directed by a RenderDoc developer. + eRENDERDOC_Option_AllowUnsupportedVendorExtensions = 12, + +} RENDERDOC_CaptureOption; + +// Sets an option that controls how RenderDoc behaves on capture. +// +// Returns 1 if the option and value are valid +// Returns 0 if either is invalid and the option is unchanged +typedef int(RENDERDOC_CC *pRENDERDOC_SetCaptureOptionU32)(RENDERDOC_CaptureOption opt, uint32_t val); +typedef int(RENDERDOC_CC *pRENDERDOC_SetCaptureOptionF32)(RENDERDOC_CaptureOption opt, float val); + +// Gets the current value of an option as a uint32_t +// +// If the option is invalid, 0xffffffff is returned +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetCaptureOptionU32)(RENDERDOC_CaptureOption opt); + +// Gets the current value of an option as a float +// +// If the option is invalid, -FLT_MAX is returned +typedef float(RENDERDOC_CC *pRENDERDOC_GetCaptureOptionF32)(RENDERDOC_CaptureOption opt); + +typedef enum RENDERDOC_InputButton { + // '0' - '9' matches ASCII values + eRENDERDOC_Key_0 = 0x30, + eRENDERDOC_Key_1 = 0x31, + eRENDERDOC_Key_2 = 0x32, + eRENDERDOC_Key_3 = 0x33, + eRENDERDOC_Key_4 = 0x34, + eRENDERDOC_Key_5 = 0x35, + eRENDERDOC_Key_6 = 0x36, + eRENDERDOC_Key_7 = 0x37, + eRENDERDOC_Key_8 = 0x38, + eRENDERDOC_Key_9 = 0x39, + + // 'A' - 'Z' matches ASCII values + eRENDERDOC_Key_A = 0x41, + eRENDERDOC_Key_B = 0x42, + eRENDERDOC_Key_C = 0x43, + eRENDERDOC_Key_D = 0x44, + eRENDERDOC_Key_E = 0x45, + eRENDERDOC_Key_F = 0x46, + eRENDERDOC_Key_G = 0x47, + eRENDERDOC_Key_H = 0x48, + eRENDERDOC_Key_I = 0x49, + eRENDERDOC_Key_J = 0x4A, + eRENDERDOC_Key_K = 0x4B, + eRENDERDOC_Key_L = 0x4C, + eRENDERDOC_Key_M = 0x4D, + eRENDERDOC_Key_N = 0x4E, + eRENDERDOC_Key_O = 0x4F, + eRENDERDOC_Key_P = 0x50, + eRENDERDOC_Key_Q = 0x51, + eRENDERDOC_Key_R = 0x52, + eRENDERDOC_Key_S = 0x53, + eRENDERDOC_Key_T = 0x54, + eRENDERDOC_Key_U = 0x55, + eRENDERDOC_Key_V = 0x56, + eRENDERDOC_Key_W = 0x57, + eRENDERDOC_Key_X = 0x58, + eRENDERDOC_Key_Y = 0x59, + eRENDERDOC_Key_Z = 0x5A, + + // leave the rest of the ASCII range free + // in case we want to use it later + eRENDERDOC_Key_NonPrintable = 0x100, + + eRENDERDOC_Key_Divide, + eRENDERDOC_Key_Multiply, + eRENDERDOC_Key_Subtract, + eRENDERDOC_Key_Plus, + + eRENDERDOC_Key_F1, + eRENDERDOC_Key_F2, + eRENDERDOC_Key_F3, + eRENDERDOC_Key_F4, + eRENDERDOC_Key_F5, + eRENDERDOC_Key_F6, + eRENDERDOC_Key_F7, + eRENDERDOC_Key_F8, + eRENDERDOC_Key_F9, + eRENDERDOC_Key_F10, + eRENDERDOC_Key_F11, + eRENDERDOC_Key_F12, + + eRENDERDOC_Key_Home, + eRENDERDOC_Key_End, + eRENDERDOC_Key_Insert, + eRENDERDOC_Key_Delete, + eRENDERDOC_Key_PageUp, + eRENDERDOC_Key_PageDn, + + eRENDERDOC_Key_Backspace, + eRENDERDOC_Key_Tab, + eRENDERDOC_Key_PrtScrn, + eRENDERDOC_Key_Pause, + + eRENDERDOC_Key_Max, +} RENDERDOC_InputButton; + +// Sets which key or keys can be used to toggle focus between multiple windows +// +// If keys is NULL or num is 0, toggle keys will be disabled +typedef void(RENDERDOC_CC *pRENDERDOC_SetFocusToggleKeys)(RENDERDOC_InputButton *keys, int num); + +// Sets which key or keys can be used to capture the next frame +// +// If keys is NULL or num is 0, captures keys will be disabled +typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureKeys)(RENDERDOC_InputButton *keys, int num); + +typedef enum RENDERDOC_OverlayBits { + // This single bit controls whether the overlay is enabled or disabled globally + eRENDERDOC_Overlay_Enabled = 0x1, + + // Show the average framerate over several seconds as well as min/max + eRENDERDOC_Overlay_FrameRate = 0x2, + + // Show the current frame number + eRENDERDOC_Overlay_FrameNumber = 0x4, + + // Show a list of recent captures, and how many captures have been made + eRENDERDOC_Overlay_CaptureList = 0x8, + + // Default values for the overlay mask + eRENDERDOC_Overlay_Default = (eRENDERDOC_Overlay_Enabled | eRENDERDOC_Overlay_FrameRate | + eRENDERDOC_Overlay_FrameNumber | eRENDERDOC_Overlay_CaptureList), + + // Enable all bits + eRENDERDOC_Overlay_All = ~0U, + + // Disable all bits + eRENDERDOC_Overlay_None = 0, +} RENDERDOC_OverlayBits; + +// returns the overlay bits that have been set +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetOverlayBits)(); +// sets the overlay bits with an and & or mask +typedef void(RENDERDOC_CC *pRENDERDOC_MaskOverlayBits)(uint32_t And, uint32_t Or); + +// this function will attempt to remove RenderDoc's hooks in the application. +// +// Note: that this can only work correctly if done immediately after +// the module is loaded, before any API work happens. RenderDoc will remove its +// injected hooks and shut down. Behaviour is undefined if this is called +// after any API functions have been called, and there is still no guarantee of +// success. +typedef void(RENDERDOC_CC *pRENDERDOC_RemoveHooks)(); + +// DEPRECATED: compatibility for code compiled against pre-1.4.1 headers. +typedef pRENDERDOC_RemoveHooks pRENDERDOC_Shutdown; + +// This function will unload RenderDoc's crash handler. +// +// If you use your own crash handler and don't want RenderDoc's handler to +// intercede, you can call this function to unload it and any unhandled +// exceptions will pass to the next handler. +typedef void(RENDERDOC_CC *pRENDERDOC_UnloadCrashHandler)(); + +// Sets the capture file path template +// +// pathtemplate is a UTF-8 string that gives a template for how captures will be named +// and where they will be saved. +// +// Any extension is stripped off the path, and captures are saved in the directory +// specified, and named with the filename and the frame number appended. If the +// directory does not exist it will be created, including any parent directories. +// +// If pathtemplate is NULL, the template will remain unchanged +// +// Example: +// +// SetCaptureFilePathTemplate("my_captures/example"); +// +// Capture #1 -> my_captures/example_frame123.rdc +// Capture #2 -> my_captures/example_frame456.rdc +typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureFilePathTemplate)(const char *pathtemplate); + +// returns the current capture path template, see SetCaptureFileTemplate above, as a UTF-8 string +typedef const char *(RENDERDOC_CC *pRENDERDOC_GetCaptureFilePathTemplate)(); + +// DEPRECATED: compatibility for code compiled against pre-1.1.2 headers. +typedef pRENDERDOC_SetCaptureFilePathTemplate pRENDERDOC_SetLogFilePathTemplate; +typedef pRENDERDOC_GetCaptureFilePathTemplate pRENDERDOC_GetLogFilePathTemplate; + +// returns the number of captures that have been made +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetNumCaptures)(); + +// This function returns the details of a capture, by index. New captures are added +// to the end of the list. +// +// filename will be filled with the absolute path to the capture file, as a UTF-8 string +// pathlength will be written with the length in bytes of the filename string +// timestamp will be written with the time of the capture, in seconds since the Unix epoch +// +// Any of the parameters can be NULL and they'll be skipped. +// +// The function will return 1 if the capture index is valid, or 0 if the index is invalid +// If the index is invalid, the values will be unchanged +// +// Note: when captures are deleted in the UI they will remain in this list, so the +// capture path may not exist anymore. +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetCapture)(uint32_t idx, char *filename, + uint32_t *pathlength, uint64_t *timestamp); + +// Sets the comments associated with a capture file. These comments are displayed in the +// UI program when opening. +// +// filePath should be a path to the capture file to add comments to. If set to NULL or "" +// the most recent capture file created made will be used instead. +// comments should be a NULL-terminated UTF-8 string to add as comments. +// +// Any existing comments will be overwritten. +typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureFileComments)(const char *filePath, + const char *comments); + +// returns 1 if the RenderDoc UI is connected to this application, 0 otherwise +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsTargetControlConnected)(); + +// DEPRECATED: compatibility for code compiled against pre-1.1.1 headers. +// This was renamed to IsTargetControlConnected in API 1.1.1, the old typedef is kept here for +// backwards compatibility with old code, it is castable either way since it's ABI compatible +// as the same function pointer type. +typedef pRENDERDOC_IsTargetControlConnected pRENDERDOC_IsRemoteAccessConnected; + +// This function will launch the Replay UI associated with the RenderDoc library injected +// into the running application. +// +// if connectTargetControl is 1, the Replay UI will be launched with a command line parameter +// to connect to this application +// cmdline is the rest of the command line, as a UTF-8 string. E.g. a captures to open +// if cmdline is NULL, the command line will be empty. +// +// returns the PID of the replay UI if successful, 0 if not successful. +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_LaunchReplayUI)(uint32_t connectTargetControl, + const char *cmdline); + +// RenderDoc can return a higher version than requested if it's backwards compatible, +// this function returns the actual version returned. If a parameter is NULL, it will be +// ignored and the others will be filled out. +typedef void(RENDERDOC_CC *pRENDERDOC_GetAPIVersion)(int *major, int *minor, int *patch); + +////////////////////////////////////////////////////////////////////////// +// Capturing functions +// + +// A device pointer is a pointer to the API's root handle. +// +// This would be an ID3D11Device, HGLRC/GLXContext, ID3D12Device, etc +typedef void *RENDERDOC_DevicePointer; + +// A window handle is the OS's native window handle +// +// This would be an HWND, GLXDrawable, etc +typedef void *RENDERDOC_WindowHandle; + +// A helper macro for Vulkan, where the device handle cannot be used directly. +// +// Passing the VkInstance to this macro will return the RENDERDOC_DevicePointer to use. +// +// Specifically, the value needed is the dispatch table pointer, which sits as the first +// pointer-sized object in the memory pointed to by the VkInstance. Thus we cast to a void** and +// indirect once. +#define RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(inst) (*((void **)(inst))) + +// This sets the RenderDoc in-app overlay in the API/window pair as 'active' and it will +// respond to keypresses. Neither parameter can be NULL +typedef void(RENDERDOC_CC *pRENDERDOC_SetActiveWindow)(RENDERDOC_DevicePointer device, + RENDERDOC_WindowHandle wndHandle); + +// capture the next frame on whichever window and API is currently considered active +typedef void(RENDERDOC_CC *pRENDERDOC_TriggerCapture)(); + +// capture the next N frames on whichever window and API is currently considered active +typedef void(RENDERDOC_CC *pRENDERDOC_TriggerMultiFrameCapture)(uint32_t numFrames); + +// When choosing either a device pointer or a window handle to capture, you can pass NULL. +// Passing NULL specifies a 'wildcard' match against anything. This allows you to specify +// any API rendering to a specific window, or a specific API instance rendering to any window, +// or in the simplest case of one window and one API, you can just pass NULL for both. +// +// In either case, if there are two or more possible matching (device,window) pairs it +// is undefined which one will be captured. +// +// Note: for headless rendering you can pass NULL for the window handle and either specify +// a device pointer or leave it NULL as above. + +// Immediately starts capturing API calls on the specified device pointer and window handle. +// +// If there is no matching thing to capture (e.g. no supported API has been initialised), +// this will do nothing. +// +// The results are undefined (including crashes) if two captures are started overlapping, +// even on separate devices and/oror windows. +typedef void(RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(RENDERDOC_DevicePointer device, + RENDERDOC_WindowHandle wndHandle); + +// Returns whether or not a frame capture is currently ongoing anywhere. +// +// This will return 1 if a capture is ongoing, and 0 if there is no capture running +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsFrameCapturing)(); + +// Ends capturing immediately. +// +// This will return 1 if the capture succeeded, and 0 if there was an error capturing. +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_EndFrameCapture)(RENDERDOC_DevicePointer device, + RENDERDOC_WindowHandle wndHandle); + +// Ends capturing immediately and discard any data stored without saving to disk. +// +// This will return 1 if the capture was discarded, and 0 if there was an error or no capture +// was in progress +typedef uint32_t(RENDERDOC_CC *pRENDERDOC_DiscardFrameCapture)(RENDERDOC_DevicePointer device, + RENDERDOC_WindowHandle wndHandle); + +////////////////////////////////////////////////////////////////////////////////////////////////// +// RenderDoc API versions +// + +// RenderDoc uses semantic versioning (http://semver.org/). +// +// MAJOR version is incremented when incompatible API changes happen. +// MINOR version is incremented when functionality is added in a backwards-compatible manner. +// PATCH version is incremented when backwards-compatible bug fixes happen. +// +// Note that this means the API returned can be higher than the one you might have requested. +// e.g. if you are running against a newer RenderDoc that supports 1.0.1, it will be returned +// instead of 1.0.0. You can check this with the GetAPIVersion entry point +typedef enum RENDERDOC_Version { + eRENDERDOC_API_Version_1_0_0 = 10000, // RENDERDOC_API_1_0_0 = 1 00 00 + eRENDERDOC_API_Version_1_0_1 = 10001, // RENDERDOC_API_1_0_1 = 1 00 01 + eRENDERDOC_API_Version_1_0_2 = 10002, // RENDERDOC_API_1_0_2 = 1 00 02 + eRENDERDOC_API_Version_1_1_0 = 10100, // RENDERDOC_API_1_1_0 = 1 01 00 + eRENDERDOC_API_Version_1_1_1 = 10101, // RENDERDOC_API_1_1_1 = 1 01 01 + eRENDERDOC_API_Version_1_1_2 = 10102, // RENDERDOC_API_1_1_2 = 1 01 02 + eRENDERDOC_API_Version_1_2_0 = 10200, // RENDERDOC_API_1_2_0 = 1 02 00 + eRENDERDOC_API_Version_1_3_0 = 10300, // RENDERDOC_API_1_3_0 = 1 03 00 + eRENDERDOC_API_Version_1_4_0 = 10400, // RENDERDOC_API_1_4_0 = 1 04 00 + eRENDERDOC_API_Version_1_4_1 = 10401, // RENDERDOC_API_1_4_1 = 1 04 01 +} RENDERDOC_Version; + +// API version changelog: +// +// 1.0.0 - initial release +// 1.0.1 - Bugfix: IsFrameCapturing() was returning false for captures that were triggered +// by keypress or TriggerCapture, instead of Start/EndFrameCapture. +// 1.0.2 - Refactor: Renamed eRENDERDOC_Option_DebugDeviceMode to eRENDERDOC_Option_APIValidation +// 1.1.0 - Add feature: TriggerMultiFrameCapture(). Backwards compatible with 1.0.x since the new +// function pointer is added to the end of the struct, the original layout is identical +// 1.1.1 - Refactor: Renamed remote access to target control (to better disambiguate from remote +// replay/remote server concept in replay UI) +// 1.1.2 - Refactor: Renamed "log file" in function names to just capture, to clarify that these +// are captures and not debug logging files. This is the first API version in the v1.0 +// branch. +// 1.2.0 - Added feature: SetCaptureFileComments() to add comments to a capture file that will be +// displayed in the UI program on load. +// 1.3.0 - Added feature: New capture option eRENDERDOC_Option_AllowUnsupportedVendorExtensions +// which allows users to opt-in to allowing unsupported vendor extensions to function. +// Should be used at the user's own risk. +// Refactor: Renamed eRENDERDOC_Option_VerifyMapWrites to +// eRENDERDOC_Option_VerifyBufferAccess, which now also controls initialisation to +// 0xdddddddd of uninitialised buffer contents. +// 1.4.0 - Added feature: DiscardFrameCapture() to discard a frame capture in progress and stop +// capturing without saving anything to disk. +// 1.4.1 - Refactor: Renamed Shutdown to RemoveHooks to better clarify what is happening + +typedef struct RENDERDOC_API_1_4_1 +{ + pRENDERDOC_GetAPIVersion GetAPIVersion; + + pRENDERDOC_SetCaptureOptionU32 SetCaptureOptionU32; + pRENDERDOC_SetCaptureOptionF32 SetCaptureOptionF32; + + pRENDERDOC_GetCaptureOptionU32 GetCaptureOptionU32; + pRENDERDOC_GetCaptureOptionF32 GetCaptureOptionF32; + + pRENDERDOC_SetFocusToggleKeys SetFocusToggleKeys; + pRENDERDOC_SetCaptureKeys SetCaptureKeys; + + pRENDERDOC_GetOverlayBits GetOverlayBits; + pRENDERDOC_MaskOverlayBits MaskOverlayBits; + + // Shutdown was renamed to RemoveHooks in 1.4.1. + // These unions allow old code to continue compiling without changes + union + { + pRENDERDOC_Shutdown Shutdown; + pRENDERDOC_RemoveHooks RemoveHooks; + }; + pRENDERDOC_UnloadCrashHandler UnloadCrashHandler; + + // Get/SetLogFilePathTemplate was renamed to Get/SetCaptureFilePathTemplate in 1.1.2. + // These unions allow old code to continue compiling without changes + union + { + // deprecated name + pRENDERDOC_SetLogFilePathTemplate SetLogFilePathTemplate; + // current name + pRENDERDOC_SetCaptureFilePathTemplate SetCaptureFilePathTemplate; + }; + union + { + // deprecated name + pRENDERDOC_GetLogFilePathTemplate GetLogFilePathTemplate; + // current name + pRENDERDOC_GetCaptureFilePathTemplate GetCaptureFilePathTemplate; + }; + + pRENDERDOC_GetNumCaptures GetNumCaptures; + pRENDERDOC_GetCapture GetCapture; + + pRENDERDOC_TriggerCapture TriggerCapture; + + // IsRemoteAccessConnected was renamed to IsTargetControlConnected in 1.1.1. + // This union allows old code to continue compiling without changes + union + { + // deprecated name + pRENDERDOC_IsRemoteAccessConnected IsRemoteAccessConnected; + // current name + pRENDERDOC_IsTargetControlConnected IsTargetControlConnected; + }; + pRENDERDOC_LaunchReplayUI LaunchReplayUI; + + pRENDERDOC_SetActiveWindow SetActiveWindow; + + pRENDERDOC_StartFrameCapture StartFrameCapture; + pRENDERDOC_IsFrameCapturing IsFrameCapturing; + pRENDERDOC_EndFrameCapture EndFrameCapture; + + // new function in 1.1.0 + pRENDERDOC_TriggerMultiFrameCapture TriggerMultiFrameCapture; + + // new function in 1.2.0 + pRENDERDOC_SetCaptureFileComments SetCaptureFileComments; + + // new function in 1.4.0 + pRENDERDOC_DiscardFrameCapture DiscardFrameCapture; +} RENDERDOC_API_1_4_1; + +typedef RENDERDOC_API_1_4_1 RENDERDOC_API_1_0_0; +typedef RENDERDOC_API_1_4_1 RENDERDOC_API_1_0_1; +typedef RENDERDOC_API_1_4_1 RENDERDOC_API_1_0_2; +typedef RENDERDOC_API_1_4_1 RENDERDOC_API_1_1_0; +typedef RENDERDOC_API_1_4_1 RENDERDOC_API_1_1_1; +typedef RENDERDOC_API_1_4_1 RENDERDOC_API_1_1_2; +typedef RENDERDOC_API_1_4_1 RENDERDOC_API_1_2_0; +typedef RENDERDOC_API_1_4_1 RENDERDOC_API_1_3_0; +typedef RENDERDOC_API_1_4_1 RENDERDOC_API_1_4_0; + +////////////////////////////////////////////////////////////////////////////////////////////////// +// RenderDoc API entry point +// +// This entry point can be obtained via GetProcAddress/dlsym if RenderDoc is available. +// +// The name is the same as the typedef - "RENDERDOC_GetAPI" +// +// This function is not thread safe, and should not be called on multiple threads at once. +// Ideally, call this once as early as possible in your application's startup, before doing +// any API work, since some configuration functionality etc has to be done also before +// initialising any APIs. +// +// Parameters: +// version is a single value from the RENDERDOC_Version above. +// +// outAPIPointers will be filled out with a pointer to the corresponding struct of function +// pointers. +// +// Returns: +// 1 - if the outAPIPointers has been filled with a pointer to the API struct requested +// 0 - if the requested version is not supported or the arguments are invalid. +// +typedef int(RENDERDOC_CC *pRENDERDOC_GetAPI)(RENDERDOC_Version version, void **outAPIPointers); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/CMakeLists.txt new file mode 100644 index 00000000..2ac5ee09 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/CMakeLists.txt @@ -0,0 +1,12 @@ +add_granite_third_party_lib(granite-stb stb_image.c stb_truetype.c) +target_include_directories(granite-stb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/stb) +if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") + target_compile_options(granite-stb PRIVATE -Wno-backslash-newline-escape) +endif() + +add_granite_third_party_lib(granite-stb-vorbis stb_vorbis.h stb/stb_vorbis.c) +target_include_directories(granite-stb-vorbis PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") + target_compile_options(granite-stb-vorbis PRIVATE -Wno-backslash-newline-escape) +endif() + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/stb_image.c b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/stb_image.c new file mode 100644 index 00000000..b9287d46 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/stb_image.c @@ -0,0 +1,5 @@ +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image.h" +#include "stb_image_write.h" + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/stb_truetype.c b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/stb_truetype.c new file mode 100644 index 00000000..6ab25e5d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/stb_truetype.c @@ -0,0 +1,3 @@ +#define STB_TRUETYPE_IMPLEMENTATION +#include "stb_truetype.h" + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/stb_vorbis.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/stb_vorbis.h new file mode 100644 index 00000000..71ed3280 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/stb/stb_vorbis.h @@ -0,0 +1,4 @@ +#pragma once + +#define STB_VORBIS_HEADER_ONLY +#include "stb/stb_vorbis.c" \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/.github/workflows/build.yml b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/.github/workflows/build.yml new file mode 100644 index 00000000..b23930ad --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/.github/workflows/build.yml @@ -0,0 +1,97 @@ +name: build + +on: + push: + branches: + - 'master' + paths-ignore: + - '*.md' + pull_request: + paths-ignore: + - '*.md' + +jobs: + build: + strategy: + matrix: + os: [ubuntu, macos, windows] + name: ${{matrix.os}} + runs-on: ${{matrix.os}}-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + with: + repository: KhronosGroup/Vulkan-Headers + ref: main + path: Vulkan-Headers + fetch-depth: 0 + fetch-tags: true + - name: move sdk + shell: bash + run: | + mv Vulkan-Headers ~/Vulkan-Headers + - name: install deps for tests + run: sudo apt update && sudo apt install -y xorg-dev + if: matrix.os == 'ubuntu' + - name: build main + shell: bash + run: | + export VULKAN_SDK=~/Vulkan-Headers + git -C ~/Vulkan-Headers checkout main + test/run_tests.sh + - name: build 1.1.101 + shell: bash + run: | + export VULKAN_SDK=~/Vulkan-Headers + git -C ~/Vulkan-Headers checkout sdk-1.1.101 + test/run_tests.sh + - name: build 1.2.131 + shell: bash + run: | + export VULKAN_SDK=~/Vulkan-Headers + git -C ~/Vulkan-Headers checkout sdk-1.2.131 + test/run_tests.sh + - name: build 1.2.182 + shell: bash + run: | + export VULKAN_SDK=~/Vulkan-Headers + git -C ~/Vulkan-Headers checkout sdk-1.2.182 + test/run_tests.sh + - name: build 1.3.204 + shell: bash + run: | + export VULKAN_SDK=~/Vulkan-Headers + git -C ~/Vulkan-Headers checkout sdk-1.3.204 + test/run_tests.sh + - name: build 1.3.239 + shell: bash + run: | + export VULKAN_SDK=~/Vulkan-Headers + git -C ~/Vulkan-Headers checkout sdk-1.3.239 + test/run_tests.sh + - name: build 1.3.268 + shell: bash + run: | + export VULKAN_SDK=~/Vulkan-Headers + git -C ~/Vulkan-Headers checkout vulkan-sdk-1.3.268 + test/run_tests.sh + - name: build 1.3.296 + shell: bash + run: | + export VULKAN_SDK=~/Vulkan-Headers + git -C ~/Vulkan-Headers checkout vulkan-sdk-1.3.296 + test/run_tests.sh + android: + name: android + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: build android arm64 + shell: bash + run: | + cmake -S . -B _build/android \ + -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" \ + -DANDROID_ABI=arm64-v8a \ + -DANDROID_PLATFORM=21 \ + -DVOLK_STATIC_DEFINES=VK_USE_PLATFORM_ANDROID_KHR + cmake --build _build/android diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/.github/workflows/update.yml b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/.github/workflows/update.yml new file mode 100644 index 00000000..0f3c8f24 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/.github/workflows/update.yml @@ -0,0 +1,36 @@ +name: update + +on: + schedule: + - cron: '0 16 * * *' + workflow_dispatch: + +jobs: + update: + if: github.repository == 'zeux/volk' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ssh-key: ${{ secrets.SSH_PRIVATE_KEY }} + - name: update + run: | + python3 generate.py >version.txt + echo "VOLK_VERSION=`cat version.txt`" >> $GITHUB_ENV + rm version.txt + - name: create pr + uses: peter-evans/create-pull-request@v6 + with: + branch: update/${{env.VOLK_VERSION}} + delete-branch: true + commit-message: Update to 1.4.${{env.VOLK_VERSION}} + title: Update to 1.4.${{env.VOLK_VERSION}} + author: GitHub + token: ${{ secrets.REPO_SCOPED_TOKEN }} + - name: enable pr automerge + run: | + sleep 60 + gh pr merge --merge --auto ${{env.PULL_REQUEST_NUMBER}} + env: + GH_TOKEN: ${{ github.token }} + continue-on-error: true diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/CMakeLists.txt new file mode 100644 index 00000000..b9da144d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/CMakeLists.txt @@ -0,0 +1,145 @@ +cmake_minimum_required(VERSION 3.5...3.30) + +project(volk VERSION +# VOLK_GENERATE_VERSION +352 +# VOLK_GENERATE_VERSION + LANGUAGES C +) + +# CMake 3.12 changes the default behaviour of option() to leave local variables +# unchanged if they exist (which we want), but we must work with older CMake versions. +if(NOT DEFINED VOLK_STATIC_DEFINES) + set(VOLK_STATIC_DEFINES "" CACHE STRING "Additional defines for building the volk static library, e.g. Vulkan platform defines") +endif() +if(NOT DEFINED VOLK_PULL_IN_VULKAN) + option(VOLK_PULL_IN_VULKAN "Vulkan as a transitive dependency" ON) +endif() +if(NOT DEFINED VOLK_INSTALL) + option(VOLK_INSTALL "Create installation targets" OFF) +endif() +if(NOT DEFINED VOLK_NAMESPACE) + option(VOLK_NAMESPACE "Use C++ namespace for vk* functions" OFF) +endif() +if(NOT DEFINED VOLK_HEADERS_ONLY) + option(VOLK_HEADERS_ONLY "Add interface library only" OFF) +endif() +if(NOT DEFINED VULKAN_HEADERS_INSTALL_DIR) + set(VULKAN_HEADERS_INSTALL_DIR "" CACHE PATH "Where to get the Vulkan headers") +endif() + +# ----------------------------------------------------- +# Static library + +if(NOT VOLK_HEADERS_ONLY OR VOLK_INSTALL) + add_library(volk STATIC volk.h volk.c) + add_library(volk::volk ALIAS volk) + target_include_directories(volk PUBLIC + $ + $ + ) + if(VOLK_NAMESPACE) + target_compile_definitions(volk PUBLIC VOLK_NAMESPACE) + set_source_files_properties(volk.c PROPERTIES LANGUAGE CXX) + endif() + if(VOLK_STATIC_DEFINES) + target_compile_definitions(volk PUBLIC ${VOLK_STATIC_DEFINES}) + endif() + if (NOT WIN32) + target_link_libraries(volk PUBLIC ${CMAKE_DL_LIBS}) + endif() +endif() + +# ----------------------------------------------------- +# Interface library + +add_library(volk_headers INTERFACE) +add_library(volk::volk_headers ALIAS volk_headers) +target_include_directories(volk_headers INTERFACE + $ + $ +) +if (NOT WIN32) + target_link_libraries(volk_headers INTERFACE ${CMAKE_DL_LIBS}) +endif() + +# ----------------------------------------------------- +# Vulkan transitive dependency + +if(VOLK_PULL_IN_VULKAN) + # Try an explicit CMake variable first, then any Vulkan paths + # discovered by FindVulkan.cmake, then the $VULKAN_SDK environment + # variable if nothing else works. + if(VULKAN_HEADERS_INSTALL_DIR) + message("volk: using VULKAN_HEADERS_INSTALL_DIR option") + set(VOLK_INCLUDES "${VULKAN_HEADERS_INSTALL_DIR}/include") + else() + # If CMake has the FindVulkan module and it works, use it. + find_package(Vulkan QUIET) + if(Vulkan_INCLUDE_DIRS) + message("volk: using Vulkan_INCLUDE_DIRS from FindVulkan module") + set(VOLK_INCLUDES "${Vulkan_INCLUDE_DIRS}") + elseif(DEFINED ENV{VULKAN_SDK}) + message("volk: using VULKAN_SDK environment variable") + set(VOLK_INCLUDES "$ENV{VULKAN_SDK}/include") + elseif(TARGET Vulkan-Headers) + message("volk: using Vulkan-Headers include directories") + get_target_property(VOLK_INCLUDES Vulkan-Headers INTERFACE_INCLUDE_DIRECTORIES) + endif() + endif() + + if(VOLK_INCLUDES) + if(TARGET volk) + target_include_directories(volk PUBLIC "${VOLK_INCLUDES}") + endif() + target_include_directories(volk_headers INTERFACE "${VOLK_INCLUDES}") + endif() +endif() + +# ----------------------------------------------------- +# Installation + +if(VOLK_INSTALL) + + include(GNUInstallDirs) + set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/volk) + + # Install files + install(FILES volk.h volk.c DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + + # Install library target and add it and any dependencies to export set. + install(TARGETS volk volk_headers + EXPORT volk-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ) + + # Actually write exported config w/ imported targets + install(EXPORT volk-targets + FILE volkTargets.cmake + NAMESPACE volk:: + DESTINATION ${INSTALL_CONFIGDIR} + ) + + # Create a ConfigVersion.cmake file: + include(CMakePackageConfigHelpers) + write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/volkConfigVersion.cmake + COMPATIBILITY AnyNewerVersion + ) + + # Configure config file + configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/cmake/volkConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/volkConfig.cmake + INSTALL_DESTINATION ${INSTALL_CONFIGDIR} + ) + + # Install the fully generated config and configVersion files + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/volkConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/volkConfigVersion.cmake + DESTINATION ${INSTALL_CONFIGDIR} + ) + +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/LICENSE.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/LICENSE.md new file mode 100644 index 00000000..b310a6e5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (c) 2018-2026 Arseny Kapoulkine + +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. diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/README.md b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/README.md new file mode 100644 index 00000000..05ae34e9 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/README.md @@ -0,0 +1,105 @@ +# 🐺 volk [![Build Status](https://github.com/zeux/volk/workflows/build/badge.svg)](https://github.com/zeux/volk/actions) + +## Purpose + +volk is a meta-loader for Vulkan. It allows you to dynamically load entrypoints required to use Vulkan +without linking to vulkan-1.dll or statically linking Vulkan loader. Additionally, volk simplifies the use of Vulkan extensions by automatically loading all associated entrypoints. Finally, volk enables loading +Vulkan entrypoints directly from the driver which can increase performance by skipping loader dispatch overhead. + +volk is written in C89 and supports Windows, Linux, Android and macOS (via MoltenVK). + +## Building + +There are multiple ways to use volk in your project: + +1. You can add `volk.c` to your build system. Note that the usual preprocessor defines that enable Vulkan's platform-specific functions (VK_USE_PLATFORM_WIN32_KHR, VK_USE_PLATFORM_XLIB_KHR, VK_USE_PLATFORM_MACOS_MVK, etc) must be passed as desired to the compiler when building `volk.c`. +2. You can use provided CMake files, with the usage detailed below. +3. You can use volk in header-only fashion. Include `volk.h` wherever you want to use Vulkan functions. In exactly one source file, define `VOLK_IMPLEMENTATION` before including `volk.h`. Do not build `volk.c` at all in this case - however, `volk.c` must still be in the same directory as `volk.h`. This method of integrating volk makes it possible to set the platform defines mentioned above with arbitrary (preprocessor) logic in your code. + +## Basic usage + +To use volk, you have to include `volk.h` instead of `vulkan/vulkan.h`; this is necessary to use function definitions from volk. + +If some files in your application include `vulkan/vulkan.h` and don't include `volk.h`, this can result in symbol conflicts; consider defining `VK_NO_PROTOTYPES` when compiling code that uses Vulkan to make sure this doesn't happen. It's also important to make sure that `vulkan-1` is not linked into the application, as this results in symbol name conflicts as well. + +To initialize volk, call this function first: + +```c++ +VkResult volkInitialize(); +``` + +This will attempt to load Vulkan loader from the system; if this function returns `VK_SUCCESS` you can proceed to create Vulkan instance. +If this function fails, this means Vulkan loader isn't installed on your system. + +After creating the Vulkan instance using Vulkan API, call this function: + +```c++ +void volkLoadInstance(VkInstance instance); +``` + +This function will load all required Vulkan entrypoints, including all extensions; you can use Vulkan from here on as usual. + +## Optimizing device calls + +If you use volk as described in the previous section, all device-related function calls, such as `vkCmdDraw`, will go through Vulkan loader dispatch code. +This allows you to transparently support multiple VkDevice objects in the same application, but comes at a price of dispatch overhead which can be as high as 7% depending on the driver and application. + +To avoid this, you have two options: + +1. For applications that use just one VkDevice object, load device-related Vulkan entrypoints directly from the driver with this function: + +```c++ +void volkLoadDevice(VkDevice device); +``` + +2. For applications that use multiple VkDevice objects, load device-related Vulkan entrypoints into a table: + +```c++ +void volkLoadDeviceTable(struct VolkDeviceTable* table, VkDevice device); +``` + +The second option requires you to change the application code to store one `VolkDeviceTable` per `VkDevice` and call functions from this table instead. + +Device entrypoints are loaded using `vkGetDeviceProcAddr`; when no layers are present, this commonly results in most function pointers pointing directly at the driver functions, minimizing the call overhead. When layers are loaded, the entrypoints will point at the implementations in the first applicable layer, so this is compatible with any layers including validation layers. + +Since `volkLoadDevice` overwrites some function pointers with device-specific versions, you can choose to use `volkLoadInstanceOnly` instead of `volkLoadInstance`; when using table-based interface this can also help enforce the usage of the function tables as `volkLoadInstanceOnly` will leave device-specific functions as `NULL`. + +## CMake support + +If your project uses CMake, volk provides you with targets corresponding to the different use cases: + +1. Target `volk` is a static library. Any platform defines can be passed to the compiler by setting `VOLK_STATIC_DEFINES`. Example: +```cmake +if (WIN32) + set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_WIN32_KHR) +elseif() + ... +endif() +add_subdirectory(volk) +target_link_library(my_application PRIVATE volk) +``` +2. Target `volk_headers` is an interface target for the header-only style. Example: +```cmake +add_subdirectory(volk) +target_link_library(my_application PRIVATE volk_headers) +``` +and in the code: +```c +/* ...any logic setting VK_USE_PLATFORM_WIN32_KHR and friends... */ +#define VOLK_IMPLEMENTATION +#include "volk.h" +``` + +The above example use `add_subdirectory` to include volk into CMake's build tree. This is a good choice if you copy the volk files into your project tree or as a git submodule. + +volk also supports installation and config-file packages. Installation is disabled by default (so as to not pollute user projects with install rules), and can be enabled by passing `-DVOLK_INSTALL=ON` to CMake. Once installed, do something like `find_package(volk CONFIG REQUIRED)` in your project's CMakeLists.txt. The imported volk targets are called `volk::volk` and `volk::volk_headers`. + +## Configuration + +By default, volk is compiled as a C library and exposes all Vulkan function pointers as globals. This can result in symbol conflicts if some libraries in the application are still linking to Vulkan libraries directly. While generally speaking it's desirable to not mix & match volk with direct usage of Vulkan - for example, mixed usage means the application still links directly to Vulkan libraries and will fail to launch if Vulkan is not available on the user's system - it's possible to enable `VOLK_NAMESPACE` CMake option (or `VOLK_NAMESPACE` define when building volk manually), which places all volk symbols into `volk::` namespace. This requires compiling `volk.c` in C++ mode, which happens automatically when using CMake, but doesn'trequire any other changes. + +Device level functions can be hidden by defining `VOLK_NO_DEVICE_PROTOTYPES`. When using `volkLoadInstanceOnly` and `volkLoadDeviceTable` the device level functions are never loaded and when not used correctly would trigger a runtime error. By hiding the device prototypes mistakes can be checked by the compiler. + +## License + +This library is available to anybody free of charge, under the terms of MIT License (see LICENSE.md). diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/cmake/volkConfig.cmake.in b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/cmake/volkConfig.cmake.in new file mode 100644 index 00000000..6e45c379 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/cmake/volkConfig.cmake.in @@ -0,0 +1,21 @@ +get_filename_component(volk_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +if(NOT TARGET volk::volk) + include("${volk_CMAKE_DIR}/volkTargets.cmake") +endif() + +# Mirror the default behaviour of the respective option. +if(NOT DEFINED VOLK_PULL_IN_VULKAN) + set(VOLK_PULL_IN_VULKAN ON) +endif() + +if(VOLK_PULL_IN_VULKAN) + find_package(Vulkan QUIET) + if(TARGET Vulkan::Vulkan) + add_dependencies(volk::volk Vulkan::Vulkan) + add_dependencies(volk::volk_headers Vulkan::Vulkan) + elseif(DEFINED ENV{VULKAN_SDK}) + target_include_directories(volk::volk INTERFACE "$ENV{VULKAN_SDK}/include") + target_include_directories(volk::volk_headers INTERFACE "$ENV{VULKAN_SDK}/include") + endif() +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/generate.py b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/generate.py new file mode 100755 index 00000000..eebffc94 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/generate.py @@ -0,0 +1,239 @@ +#!/usr/bin/python3 +# This file is part of volk library; see volk.h for version/license details + +from collections import OrderedDict +import re +import sys +import urllib +import xml.etree.ElementTree as etree +import urllib.request +import zlib + +cmdversions = { + "vkCmdSetDiscardRectangleEnableEXT": 2, + "vkCmdSetDiscardRectangleModeEXT": 2, + "vkCmdSetExclusiveScissorEnableNV": 2, + "vkGetImageViewAddressNVX": 2, + "vkGetImageViewHandle64NVX": 3, + "vkGetDeviceCombinedImageSamplerIndexNVX": 4, + "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI": 2, + "vkCmdSetDispatchParametersARM": 2, +} + +def parse_xml(path): + file = urllib.request.urlopen(path) if path.startswith("http") else open(path, 'r') + with file: + tree = etree.parse(file) + return tree + +def patch_file(path, blocks): + result = [] + block = None + + with open(path, 'r') as file: + for line in file.readlines(): + if block: + if line == block: + result.append(line) + block = None + else: + result.append(line) + # C comment marker + if line.strip().startswith('/* VOLK_GENERATE_'): + block = line + result.append(blocks[line.strip()[17:-3]]) + # Shell/CMake comment marker + elif line.strip().startswith('# VOLK_GENERATE_'): + block = line + result.append(blocks[line.strip()[16:]]) + + with open(path, 'w', newline='\n') as file: + for line in result: + file.write(line) + +def is_descendant_type(types, name, base): + if name == base: + return True + type = types.get(name) + if type is None: + return False + parents = type.get('parent') + if not parents: + return False + return any([is_descendant_type(types, parent, base) for parent in parents.split(',')]) + +def defined(key): + return 'defined(' + key + ')' + +def cdepends(key): + return re.sub(r'[a-zA-Z0-9_]+', lambda m: defined(m.group(0)), key).replace(',', ' || ').replace('+', ' && ') + +if __name__ == "__main__": + specpath = "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Docs/main/xml/vk.xml" + + if len(sys.argv) > 1: + specpath = sys.argv[1] + + spec = parse_xml(specpath) + + block_keys = ('INSTANCE_TABLE', 'DEVICE_TABLE', 'PROTOTYPES_H', 'PROTOTYPES_H_DEVICE', 'PROTOTYPES_C', 'LOAD_LOADER', 'LOAD_INSTANCE', 'LOAD_INSTANCE_TABLE', 'LOAD_DEVICE', 'LOAD_DEVICE_TABLE') + + blocks = {} + + version = spec.find('types/type[name="VK_HEADER_VERSION"]') + blocks['VERSION'] = version.find('name').tail.strip() + '\n' + blocks['VERSION_DEFINE'] = '#define VOLK_HEADER_VERSION ' + version.find('name').tail.strip() + '\n' + + command_groups = OrderedDict() + instance_commands = set() + + for feature in spec.findall('feature'): + api = feature.get('api') + if 'vulkan' not in api.split(','): + continue + name = feature.get('name') + name = re.sub(r'VK_(BASE|COMPUTE|GRAPHICS)_VERSION_', 'VK_VERSION_', name) # strip Vulkan Base prefixes for compatibility + key = defined(name) + cmdrefs = feature.findall('require/command') + command_groups.setdefault(key, []).extend([cmdref.get('name') for cmdref in cmdrefs]) + + for ext in sorted(spec.findall('extensions/extension'), key=lambda ext: ext.get('name')): + supported = ext.get('supported') + if 'vulkan' not in supported.split(','): + continue + name = ext.get('name') + type = ext.get('type') + for req in ext.findall('require'): + key = defined(name) + if req.get('feature'): # old-style XML depends specification + for i in req.get('feature').split(','): + key += ' && ' + defined(i) + if req.get('extension'): # old-style XML depends specification + for i in req.get('extension').split(','): + key += ' && ' + defined(i) + if req.get('depends'): # new-style XML depends specification + dep = cdepends(req.get('depends')) + key += ' && ' + ('(' + dep + ')' if '||' in dep else dep) + cmdrefs = req.findall('command') + for cmdref in cmdrefs: + ver = cmdversions.get(cmdref.get('name')) + if ver: + command_groups.setdefault(key + ' && ' + name.upper() + '_SPEC_VERSION >= ' + str(ver), []).append(cmdref.get('name')) + else: + command_groups.setdefault(key, []).append(cmdref.get('name')) + if type == 'instance': + for cmdref in cmdrefs: + instance_commands.add(cmdref.get('name')) + + commands_to_groups = OrderedDict() + + for (group, cmdnames) in command_groups.items(): + for name in cmdnames: + commands_to_groups.setdefault(name, []).append(group) + + for (group, cmdnames) in command_groups.items(): + command_groups[group] = [name for name in cmdnames if len(commands_to_groups[name]) == 1] + + for (name, groups) in commands_to_groups.items(): + if len(groups) == 1: + continue + key = ' || '.join(['(' + g + ')' for g in groups]) + command_groups.setdefault(key, []).append(name) + + commands = {} + + for cmd in spec.findall('commands/command'): + if not cmd.get('alias'): + name = cmd.findtext('proto/name') + commands[name] = cmd + + for cmd in spec.findall('commands/command'): + if cmd.get('alias'): + name = cmd.get('name') + commands[name] = commands[cmd.get('alias')] + + types = {} + + for type in spec.findall('types/type'): + name = type.findtext('name') + if name: + types[name] = type + + for key in block_keys: + blocks[key] = '' + + devp = {} + instp = {} + + for (group, cmdnames) in command_groups.items(): + ifdef = '#if ' + group + '\n' + + for key in block_keys: + blocks[key] += ifdef + + devt = 0 + devo = len(blocks['DEVICE_TABLE']) + instt = 0 + insto = len(blocks['INSTANCE_TABLE']) + + for name in sorted(cmdnames): + cmd = commands[name] + type = cmd.findtext('param[1]/type') + + if name == 'vkGetInstanceProcAddr': + type = '' + if name == 'vkGetDeviceProcAddr': + type = 'VkInstance' + + extern_fn = 'extern PFN_' + name + ' ' + name + ';\n' + load_fn = '\t' + name + ' = (PFN_' + name + ')load(context, "' + name + '");\n' + def_table = '\tPFN_' + name + ' ' + name + ';\n' + load_table = '\ttable->' + name + ' = (PFN_' + name + ')load(context, "' + name + '");\n' + + if is_descendant_type(types, type, 'VkDevice') and name not in instance_commands: + blocks['LOAD_DEVICE'] += load_fn + blocks['DEVICE_TABLE'] += def_table + blocks['LOAD_DEVICE_TABLE'] += load_table + blocks['PROTOTYPES_H_DEVICE'] += extern_fn + devt += 1 + elif is_descendant_type(types, type, 'VkInstance'): + blocks['LOAD_INSTANCE'] += load_fn + blocks['PROTOTYPES_H'] += extern_fn + blocks['INSTANCE_TABLE'] += def_table + blocks['LOAD_INSTANCE_TABLE'] += load_table + instt += 1 + elif type != '': + blocks['LOAD_LOADER'] += load_fn + blocks['PROTOTYPES_H'] += extern_fn + else: + blocks['PROTOTYPES_H'] += extern_fn + + blocks['PROTOTYPES_C'] += 'PFN_' + name + ' ' + name + ';\n' + + for key in block_keys: + if blocks[key].endswith(ifdef): + blocks[key] = blocks[key][:-len(ifdef)] + elif key == 'DEVICE_TABLE': + devh = zlib.crc32(blocks[key][devo:].encode()) + assert(devh not in devp) + devp[devh] = True + + blocks[key] += '#else\n' + blocks[key] += f'\tPFN_vkVoidFunction padding_{devh:x}[{devt}];\n' + blocks[key] += '#endif /* ' + group + ' */\n' + elif key == 'INSTANCE_TABLE': + insth = zlib.crc32(blocks[key][insto:].encode()) + assert(insth not in instp) + instp[insth] = True + + blocks[key] += '#else\n' + blocks[key] += f'\tPFN_vkVoidFunction padding_{insth:x}[{instt}];\n' + blocks[key] += '#endif /* ' + group + ' */\n' + else: + blocks[key] += '#endif /* ' + group + ' */\n' + + patch_file('volk.h', blocks) + patch_file('volk.c', blocks) + patch_file('CMakeLists.txt', blocks) + + print(version.find('name').tail.strip()) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_cpp_namespace/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_cpp_namespace/CMakeLists.txt new file mode 100644 index 00000000..8610f888 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_cpp_namespace/CMakeLists.txt @@ -0,0 +1,26 @@ +# Include the volk target through add_subdirectory, use the static lib target. +# We must set platform defines. +# By default, Vulkan is pulled in as transitive dependency if found. +# Also use C++ namespace feature to make it so that volk doesn't override vk* symbols + +cmake_minimum_required(VERSION 3.5...3.30) +project(volk_test LANGUAGES CXX) + +# Set a suitable platform define to compile volk with. +if(CMAKE_SYSTEM_NAME STREQUAL Windows) + set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_WIN32_KHR) +elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) + set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_XLIB_KHR) +elseif(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_MACOS_MVK) +endif() + +# Enable volk C++ namespace feature; this only works when volk is compiled and used from C++ +set(VOLK_NAMESPACE ON) + +# Include volk as part of the build tree to make the target known. +# The two-argument version of add_subdirectory allows adding non-subdirs. +add_subdirectory(../.. volk) + +add_executable(volk_test main.cpp) +target_link_libraries(volk_test PRIVATE volk) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_cpp_namespace/main.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_cpp_namespace/main.cpp new file mode 100644 index 00000000..6ce41ea0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_cpp_namespace/main.cpp @@ -0,0 +1,41 @@ +#include "volk.h" + +#include "stdio.h" +#include "stdlib.h" + +int main() +{ + VkResult r; + uint32_t version; + void* ptr; + + /* This won't compile if the appropriate Vulkan platform define isn't set. */ + ptr = +#if defined(_WIN32) + &vkCreateWin32SurfaceKHR; +#elif defined(__linux__) || defined(__unix__) + &vkCreateXlibSurfaceKHR; +#elif defined(__APPLE__) + &vkCreateMacOSSurfaceMVK; +#else + /* Platform not recogized for testing. */ + NULL; +#endif + + /* Try to initialize volk. This might not work on CI builds, but the + * above should have compiled at least. */ + r = volkInitialize(); + if (r != VK_SUCCESS) { + printf("volkInitialize failed!\n"); + return -1; + } + + version = volkGetInstanceVersion(); + printf("Vulkan version %d.%d.%d initialized.\n", + VK_VERSION_MAJOR(version), + VK_VERSION_MINOR(version), + VK_VERSION_PATCH(version)); + + return 0; +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_installed_headers/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_installed_headers/CMakeLists.txt new file mode 100644 index 00000000..5e1b0d6d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_installed_headers/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.5...3.30) +project(volk_test LANGUAGES C) + +# Include volk from a CMake package config. +# CMAKE_PREFIX_PATH or volk_DIR must be set properly. +find_package(volk CONFIG REQUIRED) + +add_executable(volk_test main.c) +target_link_libraries(volk_test PRIVATE volk::volk_headers) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_installed_headers/main.c b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_installed_headers/main.c new file mode 100644 index 00000000..0f772d85 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_installed_headers/main.c @@ -0,0 +1,54 @@ +/* Set platform defines at build time for volk to pick up. */ +#if defined(_WIN32) +# define VK_USE_PLATFORM_WIN32_KHR +#elif defined(__linux__) || defined(__unix__) +# define VK_USE_PLATFORM_XLIB_KHR +#elif defined(__APPLE__) +# define VK_USE_PLATFORM_MACOS_MVK +#else +# error "Platform not supported by this example." +#endif + +#define VOLK_IMPLEMENTATION +#include "volk.h" + +#include "stdio.h" +#include "stdlib.h" + +int main() +{ + VkResult r; + uint32_t version; + void* ptr; + + /* This won't compile if the appropriate Vulkan platform define isn't set. */ + ptr = +#if defined(_WIN32) + &vkCreateWin32SurfaceKHR; +#elif defined(__linux__) || defined(__unix__) + &vkCreateXlibSurfaceKHR; +#elif defined(__APPLE__) + &vkCreateMacOSSurfaceMVK; +#else + /* Platform not recogized for testing. */ + NULL; +#endif + + /* Try to initialize volk. This might not work on CI builds, but the + * above should have compiled at least. */ + r = volkInitialize(); + if (r != VK_SUCCESS) { + printf("volkInitialize failed!\n"); + return -1; + } + + version = volkGetInstanceVersion(); + printf("Vulkan version %d.%d.%d initialized.\n", + VK_VERSION_MAJOR(version), + VK_VERSION_MINOR(version), + VK_VERSION_PATCH(version)); + + + return 0; +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_source_directly/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_source_directly/CMakeLists.txt new file mode 100644 index 00000000..033d61d9 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_source_directly/CMakeLists.txt @@ -0,0 +1,40 @@ +# Compiles the volk sources as part of a user project. +# Volk comes with a volk.c for this purpose. +# Note that for volk to properly handle platform defines, +# those have to be set at build time. +# Also note that this way the Vulkan headers must +# handled by the user project as well as linking to dl on +# non-Windows platforms. +# For these reasons it's recommended to use one of +# the other ways to include volk (see the other examples). + +cmake_minimum_required(VERSION 3.5...3.30) +project(volk_test LANGUAGES C) + +add_executable(volk_test main.c ../../volk.c) + +# Set include path for volk.h +target_include_directories(volk_test PRIVATE ../..) + +# Set suitable platform defines +if(CMAKE_SYSTEM_NAME STREQUAL Windows) + target_compile_definitions(volk_test PRIVATE VK_USE_PLATFORM_WIN32_KHR) +elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) + target_compile_definitions(volk_test PRIVATE VK_USE_PLATFORM_XLIB_KHR) +elseif(CMAKE_SYSTEM_NAME STREQUAL Darwin) + target_compile_definitions(volk_test PRIVATE VK_USE_PLATFORM_MACOS_MVK) +endif() + +# Link requires libraries +if(NOT WIN32) + target_link_libraries(volk_test PRIVATE dl) +endif() + +# Get Vulkan dependency +find_package(Vulkan QUIET) +if(TARGET Vulkan::Vulkan) + # Note: We don't use target_link_libraries for Vulkan::Vulkan to avoid a static dependency on libvulkan1 + target_include_directories(volk_test PRIVATE ${Vulkan_INCLUDE_DIRS}) +elseif(DEFINED ENV{VULKAN_SDK}) + target_include_directories(volk_test PRIVATE "$ENV{VULKAN_SDK}/include") +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_source_directly/main.c b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_source_directly/main.c new file mode 100644 index 00000000..6ce41ea0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_source_directly/main.c @@ -0,0 +1,41 @@ +#include "volk.h" + +#include "stdio.h" +#include "stdlib.h" + +int main() +{ + VkResult r; + uint32_t version; + void* ptr; + + /* This won't compile if the appropriate Vulkan platform define isn't set. */ + ptr = +#if defined(_WIN32) + &vkCreateWin32SurfaceKHR; +#elif defined(__linux__) || defined(__unix__) + &vkCreateXlibSurfaceKHR; +#elif defined(__APPLE__) + &vkCreateMacOSSurfaceMVK; +#else + /* Platform not recogized for testing. */ + NULL; +#endif + + /* Try to initialize volk. This might not work on CI builds, but the + * above should have compiled at least. */ + r = volkInitialize(); + if (r != VK_SUCCESS) { + printf("volkInitialize failed!\n"); + return -1; + } + + version = volkGetInstanceVersion(); + printf("Vulkan version %d.%d.%d initialized.\n", + VK_VERSION_MAJOR(version), + VK_VERSION_MINOR(version), + VK_VERSION_PATCH(version)); + + return 0; +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_headers/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_headers/CMakeLists.txt new file mode 100644 index 00000000..7e85bb66 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_headers/CMakeLists.txt @@ -0,0 +1,11 @@ +# Include the volk target through add_subdirectory. + +cmake_minimum_required(VERSION 3.5...3.30) +project(volk_test LANGUAGES C) + +# Include volk as part of the build tree to make the target known. +# The two-argument version of add_subdirectory allows adding non-subdirs. +add_subdirectory(../.. volk) + +add_executable(volk_test main.c) +target_link_libraries(volk_test PRIVATE volk_headers) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_headers/main.c b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_headers/main.c new file mode 100644 index 00000000..bc0ce90f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_headers/main.c @@ -0,0 +1,53 @@ +/* Set platform defines at build time for volk to pick up. */ +#if defined(_WIN32) +# define VK_USE_PLATFORM_WIN32_KHR +#elif defined(__linux__) || defined(__unix__) +# define VK_USE_PLATFORM_XLIB_KHR +#elif defined(__APPLE__) +# define VK_USE_PLATFORM_MACOS_MVK +#else +# error "Platform not supported by this example." +#endif + +#define VOLK_IMPLEMENTATION +#include "volk.h" + +#include "stdio.h" +#include "stdlib.h" + +int main() +{ + VkResult r; + uint32_t version; + void* ptr; + + /* This won't compile if the appropriate Vulkan platform define isn't set. */ + ptr = +#if defined(_WIN32) + &vkCreateWin32SurfaceKHR; +#elif defined(__linux__) || defined(__unix__) + &vkCreateXlibSurfaceKHR; +#elif defined(__APPLE__) + &vkCreateMacOSSurfaceMVK; +#else + /* Platform not recogized for testing. */ + NULL; +#endif + + /* Try to initialize volk. This might not work on CI builds, but the + * above should have compiled at least. */ + r = volkInitialize(); + if (r != VK_SUCCESS) { + printf("volkInitialize failed!\n"); + return -1; + } + + version = volkGetInstanceVersion(); + printf("Vulkan version %d.%d.%d initialized.\n", + VK_VERSION_MAJOR(version), + VK_VERSION_MINOR(version), + VK_VERSION_PATCH(version)); + + return 0; +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_static/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_static/CMakeLists.txt new file mode 100644 index 00000000..1b548881 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_static/CMakeLists.txt @@ -0,0 +1,22 @@ +# Include the volk target through add_subdirectory, use the static lib target. +# We must set platform defines. +# By default, Vulkan is pulled in as transitive dependency if found. + +cmake_minimum_required(VERSION 3.5...3.30) +project(volk_test LANGUAGES C) + +# Set a suitable platform define to compile volk with. +if(CMAKE_SYSTEM_NAME STREQUAL Windows) + set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_WIN32_KHR) +elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) + set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_XLIB_KHR) +elseif(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_MACOS_MVK) +endif() + +# Include volk as part of the build tree to make the target known. +# The two-argument version of add_subdirectory allows adding non-subdirs. +add_subdirectory(../.. volk) + +add_executable(volk_test main.c) +target_link_libraries(volk_test PRIVATE volk) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_static/main.c b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_static/main.c new file mode 100644 index 00000000..6ce41ea0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/cmake_using_subdir_static/main.c @@ -0,0 +1,41 @@ +#include "volk.h" + +#include "stdio.h" +#include "stdlib.h" + +int main() +{ + VkResult r; + uint32_t version; + void* ptr; + + /* This won't compile if the appropriate Vulkan platform define isn't set. */ + ptr = +#if defined(_WIN32) + &vkCreateWin32SurfaceKHR; +#elif defined(__linux__) || defined(__unix__) + &vkCreateXlibSurfaceKHR; +#elif defined(__APPLE__) + &vkCreateMacOSSurfaceMVK; +#else + /* Platform not recogized for testing. */ + NULL; +#endif + + /* Try to initialize volk. This might not work on CI builds, but the + * above should have compiled at least. */ + r = volkInitialize(); + if (r != VK_SUCCESS) { + printf("volkInitialize failed!\n"); + return -1; + } + + version = volkGetInstanceVersion(); + printf("Vulkan version %d.%d.%d initialized.\n", + VK_VERSION_MAJOR(version), + VK_VERSION_MINOR(version), + VK_VERSION_PATCH(version)); + + return 0; +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/run_tests.sh b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/run_tests.sh new file mode 100755 index 00000000..bc66cdf8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/test/run_tests.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +function reset_build { + for DIR in "_build" "_installed" + do + if [ -d $DIR ]; then + rm -rf $DIR + fi + mkdir -p $DIR + done +} +function run_volk_test { + for FILE in "./volk_test" "./volk_test.exe" "Debug/volk_test.exe" "Release/volk_test.exe" + do + if [ -f $FILE ]; then + echo "Running test:" + $FILE + RC=$? + break + fi + done + echo "volk_test return code: $RC" +} + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +pushd $SCRIPT_DIR/.. + +reset_build +pushd _build +cmake -DCMAKE_INSTALL_PREFIX=../_installed -DVOLK_INSTALL=ON .. || exit 1 +cmake --build . --target install || exit 1 +popd + +echo +echo "cmake_using_source_directly =======================================>" +echo + +pushd test/cmake_using_source_directly +reset_build +pushd _build +cmake .. || exit 1 +cmake --build . || exit 1 +run_volk_test +popd +popd + +echo +echo "cmake_using_subdir_static =======================================>" +echo + +pushd test/cmake_using_subdir_static +reset_build +pushd _build +cmake .. || exit 1 +cmake --build . || exit 1 +run_volk_test +popd +popd + +echo +echo "cmake_using_subdir_headers =======================================>" +echo + +pushd test/cmake_using_subdir_headers +reset_build +pushd _build +cmake .. || exit 1 +cmake --build . || exit 1 +run_volk_test +popd +popd + +echo +echo "cmake_using_installed_headers =======================================>" +echo + +pushd test/cmake_using_installed_headers +reset_build +pushd _build +cmake -DCMAKE_INSTALL_PREFIX=../../../_installed/lib/cmake .. || exit 1 +cmake --build . || exit 1 +run_volk_test +popd +popd + +echo +echo "cmake_cpp_namespace =================================================>" +echo + +pushd test/cmake_cpp_namespace +reset_build +pushd _build +cmake .. || exit 1 +cmake --build . || exit 1 +run_volk_test +popd +popd + +popd + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/volk.c b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/volk.c new file mode 100644 index 00000000..a0aa951a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/volk.c @@ -0,0 +1,4248 @@ +/* This file is part of volk library; see volk.h for version/license details */ +/* clang-format off */ +#include "volk.h" + +#ifdef _WIN32 + typedef const char* LPCSTR; + typedef struct HINSTANCE__* HINSTANCE; + typedef HINSTANCE HMODULE; + #if defined(_MINWINDEF_) + /* minwindef.h defines FARPROC, and attempting to redefine it may conflict with -Wstrict-prototypes */ + #elif defined(_WIN64) + typedef __int64 (__stdcall* FARPROC)(void); + #else + typedef int (__stdcall* FARPROC)(void); + #endif +#else +# include +#endif + +#ifdef __APPLE__ +# include +#endif + +#include + +#ifdef _WIN32 +#ifdef __cplusplus +extern "C" { +#endif +__declspec(dllimport) HMODULE __stdcall LoadLibraryA(LPCSTR); +__declspec(dllimport) FARPROC __stdcall GetProcAddress(HMODULE, LPCSTR); +__declspec(dllimport) int __stdcall FreeLibrary(HMODULE); +#ifdef __cplusplus +} +#endif +#endif + +#ifdef __cplusplus +#ifdef VOLK_NAMESPACE +namespace volk { +#else +extern "C" { +#endif +#endif + +#if defined(__GNUC__) +# define VOLK_DISABLE_GCC_PEDANTIC_WARNINGS \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wpedantic\"") +# define VOLK_RESTORE_GCC_PEDANTIC_WARNINGS \ + _Pragma("GCC diagnostic pop") +#else +# define VOLK_DISABLE_GCC_PEDANTIC_WARNINGS +# define VOLK_RESTORE_GCC_PEDANTIC_WARNINGS +#endif + +static void* loadedModule = NULL; +static VkInstance loadedInstance = VK_NULL_HANDLE; +static VkDevice loadedDevice = VK_NULL_HANDLE; + +static void volkGenLoadLoader(void* context, PFN_vkVoidFunction (*load)(void*, const char*)); +static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, const char*)); +static void volkGenLoadInstanceTable(struct VolkInstanceTable* table, void* context, PFN_vkVoidFunction (*load)(void*, const char*)); +static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, const char*)); +static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, PFN_vkVoidFunction (*load)(void*, const char*)); + +static PFN_vkVoidFunction vkGetInstanceProcAddrStub(void* context, const char* name) +{ + return vkGetInstanceProcAddr((VkInstance)context, name); +} + +static PFN_vkVoidFunction vkGetDeviceProcAddrStub(void* context, const char* name) +{ + return vkGetDeviceProcAddr((VkDevice)context, name); +} + +static PFN_vkVoidFunction nullProcAddrStub(void* context, const char* name) +{ + (void)context; + (void)name; + return NULL; +} + +VkResult volkInitialize(void) +{ +#if defined(_WIN32) + HMODULE module = LoadLibraryA("vulkan-1.dll"); + if (!module) + return VK_ERROR_INITIALIZATION_FAILED; + + // note: function pointer is cast through void function pointer to silence cast-function-type warning on gcc8 + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)(void(*)(void))GetProcAddress(module, "vkGetInstanceProcAddr"); +#elif defined(__APPLE__) + void* module = dlopen("libvulkan.dylib", RTLD_NOW | RTLD_LOCAL); + if (!module) + module = dlopen("libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL); + // modern versions of macOS don't search /usr/local/lib automatically contrary to what man dlopen says + // Vulkan SDK uses this as the system-wide installation location, so we're going to fallback to this if all else fails + if (!module && getenv("DYLD_FALLBACK_LIBRARY_PATH") == NULL) + module = dlopen("/usr/local/lib/libvulkan.dylib", RTLD_NOW | RTLD_LOCAL); + if (!module) + module = dlopen("libMoltenVK.dylib", RTLD_NOW | RTLD_LOCAL); + // Add support for using Vulkan and MoltenVK in a Framework. App store rules for iOS + // strictly enforce no .dylib's. If they aren't found it just falls through + if (!module) + module = dlopen("vulkan.framework/vulkan", RTLD_NOW | RTLD_LOCAL); + if (!module) + module = dlopen("MoltenVK.framework/MoltenVK", RTLD_NOW | RTLD_LOCAL); + if (!module) + return VK_ERROR_INITIALIZATION_FAILED; + + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(module, "vkGetInstanceProcAddr"); +#elif defined(__ANDROID__) + void* module = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL); + if (!module) + module = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); + if (!module) + return VK_ERROR_INITIALIZATION_FAILED; + VOLK_DISABLE_GCC_PEDANTIC_WARNINGS + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(module, "vkGetInstanceProcAddr"); + VOLK_RESTORE_GCC_PEDANTIC_WARNINGS +#else + int flags = RTLD_NOW | RTLD_LOCAL; +#ifdef VOLK_USE_DEEPBIND + flags |= RTLD_DEEPBIND; // Prevent libvulkan.so from resolving Vulkan symbols via volk's own exports +#endif + void* module = dlopen("libvulkan.so.1", flags); + if (!module) + module = dlopen("libvulkan.so", flags); + if (!module) + return VK_ERROR_INITIALIZATION_FAILED; + VOLK_DISABLE_GCC_PEDANTIC_WARNINGS + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(module, "vkGetInstanceProcAddr"); + VOLK_RESTORE_GCC_PEDANTIC_WARNINGS +#endif + + loadedModule = module; + volkGenLoadLoader(NULL, vkGetInstanceProcAddrStub); + + return VK_SUCCESS; +} + +void volkInitializeCustom(PFN_vkGetInstanceProcAddr handler) +{ + vkGetInstanceProcAddr = handler; + + loadedModule = NULL; + volkGenLoadLoader(NULL, vkGetInstanceProcAddrStub); +} + +void volkFinalize(void) +{ + if (loadedModule) + { +#if defined(_WIN32) + FreeLibrary((HMODULE)loadedModule); +#else + dlclose(loadedModule); +#endif + } + + vkGetInstanceProcAddr = NULL; + volkGenLoadLoader(NULL, nullProcAddrStub); + volkGenLoadInstance(NULL, nullProcAddrStub); + volkGenLoadDevice(NULL, nullProcAddrStub); + + loadedModule = NULL; + loadedInstance = VK_NULL_HANDLE; + loadedDevice = VK_NULL_HANDLE; +} + +uint32_t volkGetInstanceVersion(void) +{ +#if defined(VK_VERSION_1_1) + uint32_t apiVersion = 0; + if (vkEnumerateInstanceVersion && vkEnumerateInstanceVersion(&apiVersion) == VK_SUCCESS) + return apiVersion; +#endif + + if (vkCreateInstance) + return VK_API_VERSION_1_0; + + return 0; +} + +void volkLoadInstance(VkInstance instance) +{ + loadedInstance = instance; + volkGenLoadInstance(instance, vkGetInstanceProcAddrStub); + volkGenLoadDevice(instance, vkGetInstanceProcAddrStub); +} + +void volkLoadInstanceOnly(VkInstance instance) +{ + loadedInstance = instance; + volkGenLoadInstance(instance, vkGetInstanceProcAddrStub); +} + +VkInstance volkGetLoadedInstance(void) +{ + return loadedInstance; +} + +void volkLoadDevice(VkDevice device) +{ + loadedDevice = device; + volkGenLoadDevice(device, vkGetDeviceProcAddrStub); +} + +VkDevice volkGetLoadedDevice(void) +{ + return loadedDevice; +} + +void volkLoadInstanceTable(struct VolkInstanceTable* table, VkInstance instance) +{ + /* vkGetDeviceProcAddr is used by volkLoadDeviceTable; for now we load this global pointer even though it might be instance-specific */ + vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr(instance, "vkGetDeviceProcAddr"); + + memset(table, 0, sizeof(*table)); + volkGenLoadInstanceTable(table, instance, vkGetInstanceProcAddrStub); +} + +void volkLoadDeviceTable(struct VolkDeviceTable* table, VkDevice device) +{ + memset(table, 0, sizeof(*table)); + volkGenLoadDeviceTable(table, device, vkGetDeviceProcAddrStub); +} + +static void volkGenLoadLoader(void* context, PFN_vkVoidFunction (*load)(void*, const char*)) +{ + /* VOLK_GENERATE_LOAD_LOADER */ +#if defined(VK_VERSION_1_0) + vkCreateInstance = (PFN_vkCreateInstance)load(context, "vkCreateInstance"); + vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)load(context, "vkEnumerateInstanceExtensionProperties"); + vkEnumerateInstanceLayerProperties = (PFN_vkEnumerateInstanceLayerProperties)load(context, "vkEnumerateInstanceLayerProperties"); +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) + vkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion)load(context, "vkEnumerateInstanceVersion"); +#endif /* defined(VK_VERSION_1_1) */ + /* VOLK_GENERATE_LOAD_LOADER */ +} + +static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, const char*)) +{ + /* VOLK_GENERATE_LOAD_INSTANCE */ +#if defined(VK_VERSION_1_0) + vkCreateDevice = (PFN_vkCreateDevice)load(context, "vkCreateDevice"); + vkDestroyInstance = (PFN_vkDestroyInstance)load(context, "vkDestroyInstance"); + vkEnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties)load(context, "vkEnumerateDeviceExtensionProperties"); + vkEnumerateDeviceLayerProperties = (PFN_vkEnumerateDeviceLayerProperties)load(context, "vkEnumerateDeviceLayerProperties"); + vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)load(context, "vkEnumeratePhysicalDevices"); + vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)load(context, "vkGetDeviceProcAddr"); + vkGetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures)load(context, "vkGetPhysicalDeviceFeatures"); + vkGetPhysicalDeviceFormatProperties = (PFN_vkGetPhysicalDeviceFormatProperties)load(context, "vkGetPhysicalDeviceFormatProperties"); + vkGetPhysicalDeviceImageFormatProperties = (PFN_vkGetPhysicalDeviceImageFormatProperties)load(context, "vkGetPhysicalDeviceImageFormatProperties"); + vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)load(context, "vkGetPhysicalDeviceMemoryProperties"); + vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)load(context, "vkGetPhysicalDeviceProperties"); + vkGetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties)load(context, "vkGetPhysicalDeviceQueueFamilyProperties"); + vkGetPhysicalDeviceSparseImageFormatProperties = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties)load(context, "vkGetPhysicalDeviceSparseImageFormatProperties"); +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) + vkEnumeratePhysicalDeviceGroups = (PFN_vkEnumeratePhysicalDeviceGroups)load(context, "vkEnumeratePhysicalDeviceGroups"); + vkGetPhysicalDeviceExternalBufferProperties = (PFN_vkGetPhysicalDeviceExternalBufferProperties)load(context, "vkGetPhysicalDeviceExternalBufferProperties"); + vkGetPhysicalDeviceExternalFenceProperties = (PFN_vkGetPhysicalDeviceExternalFenceProperties)load(context, "vkGetPhysicalDeviceExternalFenceProperties"); + vkGetPhysicalDeviceExternalSemaphoreProperties = (PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)load(context, "vkGetPhysicalDeviceExternalSemaphoreProperties"); + vkGetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2)load(context, "vkGetPhysicalDeviceFeatures2"); + vkGetPhysicalDeviceFormatProperties2 = (PFN_vkGetPhysicalDeviceFormatProperties2)load(context, "vkGetPhysicalDeviceFormatProperties2"); + vkGetPhysicalDeviceImageFormatProperties2 = (PFN_vkGetPhysicalDeviceImageFormatProperties2)load(context, "vkGetPhysicalDeviceImageFormatProperties2"); + vkGetPhysicalDeviceMemoryProperties2 = (PFN_vkGetPhysicalDeviceMemoryProperties2)load(context, "vkGetPhysicalDeviceMemoryProperties2"); + vkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2)load(context, "vkGetPhysicalDeviceProperties2"); + vkGetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2)load(context, "vkGetPhysicalDeviceQueueFamilyProperties2"); + vkGetPhysicalDeviceSparseImageFormatProperties2 = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)load(context, "vkGetPhysicalDeviceSparseImageFormatProperties2"); +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_3) + vkGetPhysicalDeviceToolProperties = (PFN_vkGetPhysicalDeviceToolProperties)load(context, "vkGetPhysicalDeviceToolProperties"); +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_ARM_data_graph) + vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM"); + vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM"); +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_data_graph_optical_flow) + vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM"); +#endif /* defined(VK_ARM_data_graph_optical_flow) */ +#if defined(VK_ARM_performance_counters_by_region) + vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM = (PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM)load(context, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM"); +#endif /* defined(VK_ARM_performance_counters_by_region) */ +#if defined(VK_ARM_shader_instrumentation) + vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM = (PFN_vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM)load(context, "vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM"); +#endif /* defined(VK_ARM_shader_instrumentation) */ +#if defined(VK_ARM_tensors) + vkGetPhysicalDeviceExternalTensorPropertiesARM = (PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM)load(context, "vkGetPhysicalDeviceExternalTensorPropertiesARM"); +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_EXT_acquire_drm_display) + vkAcquireDrmDisplayEXT = (PFN_vkAcquireDrmDisplayEXT)load(context, "vkAcquireDrmDisplayEXT"); + vkGetDrmDisplayEXT = (PFN_vkGetDrmDisplayEXT)load(context, "vkGetDrmDisplayEXT"); +#endif /* defined(VK_EXT_acquire_drm_display) */ +#if defined(VK_EXT_acquire_xlib_display) + vkAcquireXlibDisplayEXT = (PFN_vkAcquireXlibDisplayEXT)load(context, "vkAcquireXlibDisplayEXT"); + vkGetRandROutputDisplayEXT = (PFN_vkGetRandROutputDisplayEXT)load(context, "vkGetRandROutputDisplayEXT"); +#endif /* defined(VK_EXT_acquire_xlib_display) */ +#if defined(VK_EXT_calibrated_timestamps) + vkGetPhysicalDeviceCalibrateableTimeDomainsEXT = (PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)load(context, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT"); +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_debug_report) + vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)load(context, "vkCreateDebugReportCallbackEXT"); + vkDebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)load(context, "vkDebugReportMessageEXT"); + vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)load(context, "vkDestroyDebugReportCallbackEXT"); +#endif /* defined(VK_EXT_debug_report) */ +#if defined(VK_EXT_debug_utils) + vkCmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)load(context, "vkCmdBeginDebugUtilsLabelEXT"); + vkCmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)load(context, "vkCmdEndDebugUtilsLabelEXT"); + vkCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)load(context, "vkCmdInsertDebugUtilsLabelEXT"); + vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)load(context, "vkCreateDebugUtilsMessengerEXT"); + vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)load(context, "vkDestroyDebugUtilsMessengerEXT"); + vkQueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT)load(context, "vkQueueBeginDebugUtilsLabelEXT"); + vkQueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT)load(context, "vkQueueEndDebugUtilsLabelEXT"); + vkQueueInsertDebugUtilsLabelEXT = (PFN_vkQueueInsertDebugUtilsLabelEXT)load(context, "vkQueueInsertDebugUtilsLabelEXT"); + vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)load(context, "vkSetDebugUtilsObjectNameEXT"); + vkSetDebugUtilsObjectTagEXT = (PFN_vkSetDebugUtilsObjectTagEXT)load(context, "vkSetDebugUtilsObjectTagEXT"); + vkSubmitDebugUtilsMessageEXT = (PFN_vkSubmitDebugUtilsMessageEXT)load(context, "vkSubmitDebugUtilsMessageEXT"); +#endif /* defined(VK_EXT_debug_utils) */ +#if defined(VK_EXT_descriptor_heap) + vkGetPhysicalDeviceDescriptorSizeEXT = (PFN_vkGetPhysicalDeviceDescriptorSizeEXT)load(context, "vkGetPhysicalDeviceDescriptorSizeEXT"); +#endif /* defined(VK_EXT_descriptor_heap) */ +#if defined(VK_EXT_direct_mode_display) + vkReleaseDisplayEXT = (PFN_vkReleaseDisplayEXT)load(context, "vkReleaseDisplayEXT"); +#endif /* defined(VK_EXT_direct_mode_display) */ +#if defined(VK_EXT_directfb_surface) + vkCreateDirectFBSurfaceEXT = (PFN_vkCreateDirectFBSurfaceEXT)load(context, "vkCreateDirectFBSurfaceEXT"); + vkGetPhysicalDeviceDirectFBPresentationSupportEXT = (PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT)load(context, "vkGetPhysicalDeviceDirectFBPresentationSupportEXT"); +#endif /* defined(VK_EXT_directfb_surface) */ +#if defined(VK_EXT_display_surface_counter) + vkGetPhysicalDeviceSurfaceCapabilities2EXT = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)load(context, "vkGetPhysicalDeviceSurfaceCapabilities2EXT"); +#endif /* defined(VK_EXT_display_surface_counter) */ +#if defined(VK_EXT_full_screen_exclusive) + vkGetPhysicalDeviceSurfacePresentModes2EXT = (PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)load(context, "vkGetPhysicalDeviceSurfacePresentModes2EXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_headless_surface) + vkCreateHeadlessSurfaceEXT = (PFN_vkCreateHeadlessSurfaceEXT)load(context, "vkCreateHeadlessSurfaceEXT"); +#endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_metal_surface) + vkCreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT)load(context, "vkCreateMetalSurfaceEXT"); +#endif /* defined(VK_EXT_metal_surface) */ +#if defined(VK_EXT_sample_locations) + vkGetPhysicalDeviceMultisamplePropertiesEXT = (PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)load(context, "vkGetPhysicalDeviceMultisamplePropertiesEXT"); +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_tooling_info) + vkGetPhysicalDeviceToolPropertiesEXT = (PFN_vkGetPhysicalDeviceToolPropertiesEXT)load(context, "vkGetPhysicalDeviceToolPropertiesEXT"); +#endif /* defined(VK_EXT_tooling_info) */ +#if defined(VK_FUCHSIA_imagepipe_surface) + vkCreateImagePipeSurfaceFUCHSIA = (PFN_vkCreateImagePipeSurfaceFUCHSIA)load(context, "vkCreateImagePipeSurfaceFUCHSIA"); +#endif /* defined(VK_FUCHSIA_imagepipe_surface) */ +#if defined(VK_GGP_stream_descriptor_surface) + vkCreateStreamDescriptorSurfaceGGP = (PFN_vkCreateStreamDescriptorSurfaceGGP)load(context, "vkCreateStreamDescriptorSurfaceGGP"); +#endif /* defined(VK_GGP_stream_descriptor_surface) */ +#if defined(VK_KHR_android_surface) + vkCreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)load(context, "vkCreateAndroidSurfaceKHR"); +#endif /* defined(VK_KHR_android_surface) */ +#if defined(VK_KHR_calibrated_timestamps) + vkGetPhysicalDeviceCalibrateableTimeDomainsKHR = (PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR)load(context, "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR"); +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_cooperative_matrix) + vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR = (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR)load(context, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR"); +#endif /* defined(VK_KHR_cooperative_matrix) */ +#if defined(VK_KHR_device_group_creation) + vkEnumeratePhysicalDeviceGroupsKHR = (PFN_vkEnumeratePhysicalDeviceGroupsKHR)load(context, "vkEnumeratePhysicalDeviceGroupsKHR"); +#endif /* defined(VK_KHR_device_group_creation) */ +#if defined(VK_KHR_display) + vkCreateDisplayModeKHR = (PFN_vkCreateDisplayModeKHR)load(context, "vkCreateDisplayModeKHR"); + vkCreateDisplayPlaneSurfaceKHR = (PFN_vkCreateDisplayPlaneSurfaceKHR)load(context, "vkCreateDisplayPlaneSurfaceKHR"); + vkGetDisplayModePropertiesKHR = (PFN_vkGetDisplayModePropertiesKHR)load(context, "vkGetDisplayModePropertiesKHR"); + vkGetDisplayPlaneCapabilitiesKHR = (PFN_vkGetDisplayPlaneCapabilitiesKHR)load(context, "vkGetDisplayPlaneCapabilitiesKHR"); + vkGetDisplayPlaneSupportedDisplaysKHR = (PFN_vkGetDisplayPlaneSupportedDisplaysKHR)load(context, "vkGetDisplayPlaneSupportedDisplaysKHR"); + vkGetPhysicalDeviceDisplayPlanePropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)load(context, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"); + vkGetPhysicalDeviceDisplayPropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)load(context, "vkGetPhysicalDeviceDisplayPropertiesKHR"); +#endif /* defined(VK_KHR_display) */ +#if defined(VK_KHR_external_fence_capabilities) + vkGetPhysicalDeviceExternalFencePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)load(context, "vkGetPhysicalDeviceExternalFencePropertiesKHR"); +#endif /* defined(VK_KHR_external_fence_capabilities) */ +#if defined(VK_KHR_external_memory_capabilities) + vkGetPhysicalDeviceExternalBufferPropertiesKHR = (PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)load(context, "vkGetPhysicalDeviceExternalBufferPropertiesKHR"); +#endif /* defined(VK_KHR_external_memory_capabilities) */ +#if defined(VK_KHR_external_semaphore_capabilities) + vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)load(context, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"); +#endif /* defined(VK_KHR_external_semaphore_capabilities) */ +#if defined(VK_KHR_fragment_shading_rate) + vkGetPhysicalDeviceFragmentShadingRatesKHR = (PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)load(context, "vkGetPhysicalDeviceFragmentShadingRatesKHR"); +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_display_properties2) + vkGetDisplayModeProperties2KHR = (PFN_vkGetDisplayModeProperties2KHR)load(context, "vkGetDisplayModeProperties2KHR"); + vkGetDisplayPlaneCapabilities2KHR = (PFN_vkGetDisplayPlaneCapabilities2KHR)load(context, "vkGetDisplayPlaneCapabilities2KHR"); + vkGetPhysicalDeviceDisplayPlaneProperties2KHR = (PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)load(context, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR"); + vkGetPhysicalDeviceDisplayProperties2KHR = (PFN_vkGetPhysicalDeviceDisplayProperties2KHR)load(context, "vkGetPhysicalDeviceDisplayProperties2KHR"); +#endif /* defined(VK_KHR_get_display_properties2) */ +#if defined(VK_KHR_get_physical_device_properties2) + vkGetPhysicalDeviceFeatures2KHR = (PFN_vkGetPhysicalDeviceFeatures2KHR)load(context, "vkGetPhysicalDeviceFeatures2KHR"); + vkGetPhysicalDeviceFormatProperties2KHR = (PFN_vkGetPhysicalDeviceFormatProperties2KHR)load(context, "vkGetPhysicalDeviceFormatProperties2KHR"); + vkGetPhysicalDeviceImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)load(context, "vkGetPhysicalDeviceImageFormatProperties2KHR"); + vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)load(context, "vkGetPhysicalDeviceMemoryProperties2KHR"); + vkGetPhysicalDeviceProperties2KHR = (PFN_vkGetPhysicalDeviceProperties2KHR)load(context, "vkGetPhysicalDeviceProperties2KHR"); + vkGetPhysicalDeviceQueueFamilyProperties2KHR = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)load(context, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"); + vkGetPhysicalDeviceSparseImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)load(context, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"); +#endif /* defined(VK_KHR_get_physical_device_properties2) */ +#if defined(VK_KHR_get_surface_capabilities2) + vkGetPhysicalDeviceSurfaceCapabilities2KHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)load(context, "vkGetPhysicalDeviceSurfaceCapabilities2KHR"); + vkGetPhysicalDeviceSurfaceFormats2KHR = (PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)load(context, "vkGetPhysicalDeviceSurfaceFormats2KHR"); +#endif /* defined(VK_KHR_get_surface_capabilities2) */ +#if defined(VK_KHR_performance_query) + vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = (PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)load(context, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR"); + vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = (PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)load(context, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR"); +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_surface) + vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)load(context, "vkDestroySurfaceKHR"); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)load(context, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); + vkGetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)load(context, "vkGetPhysicalDeviceSurfaceFormatsKHR"); + vkGetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)load(context, "vkGetPhysicalDeviceSurfacePresentModesKHR"); + vkGetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)load(context, "vkGetPhysicalDeviceSurfaceSupportKHR"); +#endif /* defined(VK_KHR_surface) */ +#if defined(VK_KHR_video_encode_queue) + vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR = (PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR)load(context, "vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR"); +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) + vkGetPhysicalDeviceVideoCapabilitiesKHR = (PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)load(context, "vkGetPhysicalDeviceVideoCapabilitiesKHR"); + vkGetPhysicalDeviceVideoFormatPropertiesKHR = (PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)load(context, "vkGetPhysicalDeviceVideoFormatPropertiesKHR"); +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_KHR_wayland_surface) + vkCreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)load(context, "vkCreateWaylandSurfaceKHR"); + vkGetPhysicalDeviceWaylandPresentationSupportKHR = (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)load(context, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"); +#endif /* defined(VK_KHR_wayland_surface) */ +#if defined(VK_KHR_win32_surface) + vkCreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)load(context, "vkCreateWin32SurfaceKHR"); + vkGetPhysicalDeviceWin32PresentationSupportKHR = (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)load(context, "vkGetPhysicalDeviceWin32PresentationSupportKHR"); +#endif /* defined(VK_KHR_win32_surface) */ +#if defined(VK_KHR_xcb_surface) + vkCreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)load(context, "vkCreateXcbSurfaceKHR"); + vkGetPhysicalDeviceXcbPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)load(context, "vkGetPhysicalDeviceXcbPresentationSupportKHR"); +#endif /* defined(VK_KHR_xcb_surface) */ +#if defined(VK_KHR_xlib_surface) + vkCreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)load(context, "vkCreateXlibSurfaceKHR"); + vkGetPhysicalDeviceXlibPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)load(context, "vkGetPhysicalDeviceXlibPresentationSupportKHR"); +#endif /* defined(VK_KHR_xlib_surface) */ +#if defined(VK_MVK_ios_surface) + vkCreateIOSSurfaceMVK = (PFN_vkCreateIOSSurfaceMVK)load(context, "vkCreateIOSSurfaceMVK"); +#endif /* defined(VK_MVK_ios_surface) */ +#if defined(VK_MVK_macos_surface) + vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)load(context, "vkCreateMacOSSurfaceMVK"); +#endif /* defined(VK_MVK_macos_surface) */ +#if defined(VK_NN_vi_surface) + vkCreateViSurfaceNN = (PFN_vkCreateViSurfaceNN)load(context, "vkCreateViSurfaceNN"); +#endif /* defined(VK_NN_vi_surface) */ +#if defined(VK_NV_acquire_winrt_display) + vkAcquireWinrtDisplayNV = (PFN_vkAcquireWinrtDisplayNV)load(context, "vkAcquireWinrtDisplayNV"); + vkGetWinrtDisplayNV = (PFN_vkGetWinrtDisplayNV)load(context, "vkGetWinrtDisplayNV"); +#endif /* defined(VK_NV_acquire_winrt_display) */ +#if defined(VK_NV_cooperative_matrix) + vkGetPhysicalDeviceCooperativeMatrixPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV"); +#endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_cooperative_matrix2) + vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV"); +#endif /* defined(VK_NV_cooperative_matrix2) */ +#if defined(VK_NV_cooperative_vector) + vkGetPhysicalDeviceCooperativeVectorPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeVectorPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeVectorPropertiesNV"); +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_coverage_reduction_mode) + vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = (PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)load(context, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV"); +#endif /* defined(VK_NV_coverage_reduction_mode) */ +#if defined(VK_NV_external_memory_capabilities) + vkGetPhysicalDeviceExternalImageFormatPropertiesNV = (PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)load(context, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV"); +#endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_optical_flow) + vkGetPhysicalDeviceOpticalFlowImageFormatsNV = (PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV)load(context, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV"); +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_OHOS_surface) + vkCreateSurfaceOHOS = (PFN_vkCreateSurfaceOHOS)load(context, "vkCreateSurfaceOHOS"); +#endif /* defined(VK_OHOS_surface) */ +#if defined(VK_QNX_screen_surface) + vkCreateScreenSurfaceQNX = (PFN_vkCreateScreenSurfaceQNX)load(context, "vkCreateScreenSurfaceQNX"); + vkGetPhysicalDeviceScreenPresentationSupportQNX = (PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX)load(context, "vkGetPhysicalDeviceScreenPresentationSupportQNX"); +#endif /* defined(VK_QNX_screen_surface) */ +#if defined(VK_SEC_ubm_surface) + vkCreateUbmSurfaceSEC = (PFN_vkCreateUbmSurfaceSEC)load(context, "vkCreateUbmSurfaceSEC"); + vkGetPhysicalDeviceUbmPresentationSupportSEC = (PFN_vkGetPhysicalDeviceUbmPresentationSupportSEC)load(context, "vkGetPhysicalDeviceUbmPresentationSupportSEC"); +#endif /* defined(VK_SEC_ubm_surface) */ +#if (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) + vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM"); +#endif /* (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) + vkGetPhysicalDevicePresentRectanglesKHR = (PFN_vkGetPhysicalDevicePresentRectanglesKHR)load(context, "vkGetPhysicalDevicePresentRectanglesKHR"); +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ + /* VOLK_GENERATE_LOAD_INSTANCE */ +} + +static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, const char*)) +{ + /* VOLK_GENERATE_LOAD_DEVICE */ +#if defined(VK_VERSION_1_0) + vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)load(context, "vkAllocateCommandBuffers"); + vkAllocateDescriptorSets = (PFN_vkAllocateDescriptorSets)load(context, "vkAllocateDescriptorSets"); + vkAllocateMemory = (PFN_vkAllocateMemory)load(context, "vkAllocateMemory"); + vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)load(context, "vkBeginCommandBuffer"); + vkBindBufferMemory = (PFN_vkBindBufferMemory)load(context, "vkBindBufferMemory"); + vkBindImageMemory = (PFN_vkBindImageMemory)load(context, "vkBindImageMemory"); + vkCmdBeginQuery = (PFN_vkCmdBeginQuery)load(context, "vkCmdBeginQuery"); + vkCmdBeginRenderPass = (PFN_vkCmdBeginRenderPass)load(context, "vkCmdBeginRenderPass"); + vkCmdBindDescriptorSets = (PFN_vkCmdBindDescriptorSets)load(context, "vkCmdBindDescriptorSets"); + vkCmdBindIndexBuffer = (PFN_vkCmdBindIndexBuffer)load(context, "vkCmdBindIndexBuffer"); + vkCmdBindPipeline = (PFN_vkCmdBindPipeline)load(context, "vkCmdBindPipeline"); + vkCmdBindVertexBuffers = (PFN_vkCmdBindVertexBuffers)load(context, "vkCmdBindVertexBuffers"); + vkCmdBlitImage = (PFN_vkCmdBlitImage)load(context, "vkCmdBlitImage"); + vkCmdClearAttachments = (PFN_vkCmdClearAttachments)load(context, "vkCmdClearAttachments"); + vkCmdClearColorImage = (PFN_vkCmdClearColorImage)load(context, "vkCmdClearColorImage"); + vkCmdClearDepthStencilImage = (PFN_vkCmdClearDepthStencilImage)load(context, "vkCmdClearDepthStencilImage"); + vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)load(context, "vkCmdCopyBuffer"); + vkCmdCopyBufferToImage = (PFN_vkCmdCopyBufferToImage)load(context, "vkCmdCopyBufferToImage"); + vkCmdCopyImage = (PFN_vkCmdCopyImage)load(context, "vkCmdCopyImage"); + vkCmdCopyImageToBuffer = (PFN_vkCmdCopyImageToBuffer)load(context, "vkCmdCopyImageToBuffer"); + vkCmdCopyQueryPoolResults = (PFN_vkCmdCopyQueryPoolResults)load(context, "vkCmdCopyQueryPoolResults"); + vkCmdDispatch = (PFN_vkCmdDispatch)load(context, "vkCmdDispatch"); + vkCmdDispatchIndirect = (PFN_vkCmdDispatchIndirect)load(context, "vkCmdDispatchIndirect"); + vkCmdDraw = (PFN_vkCmdDraw)load(context, "vkCmdDraw"); + vkCmdDrawIndexed = (PFN_vkCmdDrawIndexed)load(context, "vkCmdDrawIndexed"); + vkCmdDrawIndexedIndirect = (PFN_vkCmdDrawIndexedIndirect)load(context, "vkCmdDrawIndexedIndirect"); + vkCmdDrawIndirect = (PFN_vkCmdDrawIndirect)load(context, "vkCmdDrawIndirect"); + vkCmdEndQuery = (PFN_vkCmdEndQuery)load(context, "vkCmdEndQuery"); + vkCmdEndRenderPass = (PFN_vkCmdEndRenderPass)load(context, "vkCmdEndRenderPass"); + vkCmdExecuteCommands = (PFN_vkCmdExecuteCommands)load(context, "vkCmdExecuteCommands"); + vkCmdFillBuffer = (PFN_vkCmdFillBuffer)load(context, "vkCmdFillBuffer"); + vkCmdNextSubpass = (PFN_vkCmdNextSubpass)load(context, "vkCmdNextSubpass"); + vkCmdPipelineBarrier = (PFN_vkCmdPipelineBarrier)load(context, "vkCmdPipelineBarrier"); + vkCmdPushConstants = (PFN_vkCmdPushConstants)load(context, "vkCmdPushConstants"); + vkCmdResetEvent = (PFN_vkCmdResetEvent)load(context, "vkCmdResetEvent"); + vkCmdResetQueryPool = (PFN_vkCmdResetQueryPool)load(context, "vkCmdResetQueryPool"); + vkCmdResolveImage = (PFN_vkCmdResolveImage)load(context, "vkCmdResolveImage"); + vkCmdSetBlendConstants = (PFN_vkCmdSetBlendConstants)load(context, "vkCmdSetBlendConstants"); + vkCmdSetDepthBias = (PFN_vkCmdSetDepthBias)load(context, "vkCmdSetDepthBias"); + vkCmdSetDepthBounds = (PFN_vkCmdSetDepthBounds)load(context, "vkCmdSetDepthBounds"); + vkCmdSetEvent = (PFN_vkCmdSetEvent)load(context, "vkCmdSetEvent"); + vkCmdSetLineWidth = (PFN_vkCmdSetLineWidth)load(context, "vkCmdSetLineWidth"); + vkCmdSetScissor = (PFN_vkCmdSetScissor)load(context, "vkCmdSetScissor"); + vkCmdSetStencilCompareMask = (PFN_vkCmdSetStencilCompareMask)load(context, "vkCmdSetStencilCompareMask"); + vkCmdSetStencilReference = (PFN_vkCmdSetStencilReference)load(context, "vkCmdSetStencilReference"); + vkCmdSetStencilWriteMask = (PFN_vkCmdSetStencilWriteMask)load(context, "vkCmdSetStencilWriteMask"); + vkCmdSetViewport = (PFN_vkCmdSetViewport)load(context, "vkCmdSetViewport"); + vkCmdUpdateBuffer = (PFN_vkCmdUpdateBuffer)load(context, "vkCmdUpdateBuffer"); + vkCmdWaitEvents = (PFN_vkCmdWaitEvents)load(context, "vkCmdWaitEvents"); + vkCmdWriteTimestamp = (PFN_vkCmdWriteTimestamp)load(context, "vkCmdWriteTimestamp"); + vkCreateBuffer = (PFN_vkCreateBuffer)load(context, "vkCreateBuffer"); + vkCreateBufferView = (PFN_vkCreateBufferView)load(context, "vkCreateBufferView"); + vkCreateCommandPool = (PFN_vkCreateCommandPool)load(context, "vkCreateCommandPool"); + vkCreateComputePipelines = (PFN_vkCreateComputePipelines)load(context, "vkCreateComputePipelines"); + vkCreateDescriptorPool = (PFN_vkCreateDescriptorPool)load(context, "vkCreateDescriptorPool"); + vkCreateDescriptorSetLayout = (PFN_vkCreateDescriptorSetLayout)load(context, "vkCreateDescriptorSetLayout"); + vkCreateEvent = (PFN_vkCreateEvent)load(context, "vkCreateEvent"); + vkCreateFence = (PFN_vkCreateFence)load(context, "vkCreateFence"); + vkCreateFramebuffer = (PFN_vkCreateFramebuffer)load(context, "vkCreateFramebuffer"); + vkCreateGraphicsPipelines = (PFN_vkCreateGraphicsPipelines)load(context, "vkCreateGraphicsPipelines"); + vkCreateImage = (PFN_vkCreateImage)load(context, "vkCreateImage"); + vkCreateImageView = (PFN_vkCreateImageView)load(context, "vkCreateImageView"); + vkCreatePipelineCache = (PFN_vkCreatePipelineCache)load(context, "vkCreatePipelineCache"); + vkCreatePipelineLayout = (PFN_vkCreatePipelineLayout)load(context, "vkCreatePipelineLayout"); + vkCreateQueryPool = (PFN_vkCreateQueryPool)load(context, "vkCreateQueryPool"); + vkCreateRenderPass = (PFN_vkCreateRenderPass)load(context, "vkCreateRenderPass"); + vkCreateSampler = (PFN_vkCreateSampler)load(context, "vkCreateSampler"); + vkCreateSemaphore = (PFN_vkCreateSemaphore)load(context, "vkCreateSemaphore"); + vkCreateShaderModule = (PFN_vkCreateShaderModule)load(context, "vkCreateShaderModule"); + vkDestroyBuffer = (PFN_vkDestroyBuffer)load(context, "vkDestroyBuffer"); + vkDestroyBufferView = (PFN_vkDestroyBufferView)load(context, "vkDestroyBufferView"); + vkDestroyCommandPool = (PFN_vkDestroyCommandPool)load(context, "vkDestroyCommandPool"); + vkDestroyDescriptorPool = (PFN_vkDestroyDescriptorPool)load(context, "vkDestroyDescriptorPool"); + vkDestroyDescriptorSetLayout = (PFN_vkDestroyDescriptorSetLayout)load(context, "vkDestroyDescriptorSetLayout"); + vkDestroyDevice = (PFN_vkDestroyDevice)load(context, "vkDestroyDevice"); + vkDestroyEvent = (PFN_vkDestroyEvent)load(context, "vkDestroyEvent"); + vkDestroyFence = (PFN_vkDestroyFence)load(context, "vkDestroyFence"); + vkDestroyFramebuffer = (PFN_vkDestroyFramebuffer)load(context, "vkDestroyFramebuffer"); + vkDestroyImage = (PFN_vkDestroyImage)load(context, "vkDestroyImage"); + vkDestroyImageView = (PFN_vkDestroyImageView)load(context, "vkDestroyImageView"); + vkDestroyPipeline = (PFN_vkDestroyPipeline)load(context, "vkDestroyPipeline"); + vkDestroyPipelineCache = (PFN_vkDestroyPipelineCache)load(context, "vkDestroyPipelineCache"); + vkDestroyPipelineLayout = (PFN_vkDestroyPipelineLayout)load(context, "vkDestroyPipelineLayout"); + vkDestroyQueryPool = (PFN_vkDestroyQueryPool)load(context, "vkDestroyQueryPool"); + vkDestroyRenderPass = (PFN_vkDestroyRenderPass)load(context, "vkDestroyRenderPass"); + vkDestroySampler = (PFN_vkDestroySampler)load(context, "vkDestroySampler"); + vkDestroySemaphore = (PFN_vkDestroySemaphore)load(context, "vkDestroySemaphore"); + vkDestroyShaderModule = (PFN_vkDestroyShaderModule)load(context, "vkDestroyShaderModule"); + vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)load(context, "vkDeviceWaitIdle"); + vkEndCommandBuffer = (PFN_vkEndCommandBuffer)load(context, "vkEndCommandBuffer"); + vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)load(context, "vkFlushMappedMemoryRanges"); + vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)load(context, "vkFreeCommandBuffers"); + vkFreeDescriptorSets = (PFN_vkFreeDescriptorSets)load(context, "vkFreeDescriptorSets"); + vkFreeMemory = (PFN_vkFreeMemory)load(context, "vkFreeMemory"); + vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)load(context, "vkGetBufferMemoryRequirements"); + vkGetDeviceMemoryCommitment = (PFN_vkGetDeviceMemoryCommitment)load(context, "vkGetDeviceMemoryCommitment"); + vkGetDeviceQueue = (PFN_vkGetDeviceQueue)load(context, "vkGetDeviceQueue"); + vkGetEventStatus = (PFN_vkGetEventStatus)load(context, "vkGetEventStatus"); + vkGetFenceStatus = (PFN_vkGetFenceStatus)load(context, "vkGetFenceStatus"); + vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)load(context, "vkGetImageMemoryRequirements"); + vkGetImageSparseMemoryRequirements = (PFN_vkGetImageSparseMemoryRequirements)load(context, "vkGetImageSparseMemoryRequirements"); + vkGetImageSubresourceLayout = (PFN_vkGetImageSubresourceLayout)load(context, "vkGetImageSubresourceLayout"); + vkGetPipelineCacheData = (PFN_vkGetPipelineCacheData)load(context, "vkGetPipelineCacheData"); + vkGetQueryPoolResults = (PFN_vkGetQueryPoolResults)load(context, "vkGetQueryPoolResults"); + vkGetRenderAreaGranularity = (PFN_vkGetRenderAreaGranularity)load(context, "vkGetRenderAreaGranularity"); + vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)load(context, "vkInvalidateMappedMemoryRanges"); + vkMapMemory = (PFN_vkMapMemory)load(context, "vkMapMemory"); + vkMergePipelineCaches = (PFN_vkMergePipelineCaches)load(context, "vkMergePipelineCaches"); + vkQueueBindSparse = (PFN_vkQueueBindSparse)load(context, "vkQueueBindSparse"); + vkQueueSubmit = (PFN_vkQueueSubmit)load(context, "vkQueueSubmit"); + vkQueueWaitIdle = (PFN_vkQueueWaitIdle)load(context, "vkQueueWaitIdle"); + vkResetCommandBuffer = (PFN_vkResetCommandBuffer)load(context, "vkResetCommandBuffer"); + vkResetCommandPool = (PFN_vkResetCommandPool)load(context, "vkResetCommandPool"); + vkResetDescriptorPool = (PFN_vkResetDescriptorPool)load(context, "vkResetDescriptorPool"); + vkResetEvent = (PFN_vkResetEvent)load(context, "vkResetEvent"); + vkResetFences = (PFN_vkResetFences)load(context, "vkResetFences"); + vkSetEvent = (PFN_vkSetEvent)load(context, "vkSetEvent"); + vkUnmapMemory = (PFN_vkUnmapMemory)load(context, "vkUnmapMemory"); + vkUpdateDescriptorSets = (PFN_vkUpdateDescriptorSets)load(context, "vkUpdateDescriptorSets"); + vkWaitForFences = (PFN_vkWaitForFences)load(context, "vkWaitForFences"); +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) + vkBindBufferMemory2 = (PFN_vkBindBufferMemory2)load(context, "vkBindBufferMemory2"); + vkBindImageMemory2 = (PFN_vkBindImageMemory2)load(context, "vkBindImageMemory2"); + vkCmdDispatchBase = (PFN_vkCmdDispatchBase)load(context, "vkCmdDispatchBase"); + vkCmdSetDeviceMask = (PFN_vkCmdSetDeviceMask)load(context, "vkCmdSetDeviceMask"); + vkCreateDescriptorUpdateTemplate = (PFN_vkCreateDescriptorUpdateTemplate)load(context, "vkCreateDescriptorUpdateTemplate"); + vkCreateSamplerYcbcrConversion = (PFN_vkCreateSamplerYcbcrConversion)load(context, "vkCreateSamplerYcbcrConversion"); + vkDestroyDescriptorUpdateTemplate = (PFN_vkDestroyDescriptorUpdateTemplate)load(context, "vkDestroyDescriptorUpdateTemplate"); + vkDestroySamplerYcbcrConversion = (PFN_vkDestroySamplerYcbcrConversion)load(context, "vkDestroySamplerYcbcrConversion"); + vkGetBufferMemoryRequirements2 = (PFN_vkGetBufferMemoryRequirements2)load(context, "vkGetBufferMemoryRequirements2"); + vkGetDescriptorSetLayoutSupport = (PFN_vkGetDescriptorSetLayoutSupport)load(context, "vkGetDescriptorSetLayoutSupport"); + vkGetDeviceGroupPeerMemoryFeatures = (PFN_vkGetDeviceGroupPeerMemoryFeatures)load(context, "vkGetDeviceGroupPeerMemoryFeatures"); + vkGetDeviceQueue2 = (PFN_vkGetDeviceQueue2)load(context, "vkGetDeviceQueue2"); + vkGetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2)load(context, "vkGetImageMemoryRequirements2"); + vkGetImageSparseMemoryRequirements2 = (PFN_vkGetImageSparseMemoryRequirements2)load(context, "vkGetImageSparseMemoryRequirements2"); + vkTrimCommandPool = (PFN_vkTrimCommandPool)load(context, "vkTrimCommandPool"); + vkUpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate)load(context, "vkUpdateDescriptorSetWithTemplate"); +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) + vkCmdBeginRenderPass2 = (PFN_vkCmdBeginRenderPass2)load(context, "vkCmdBeginRenderPass2"); + vkCmdDrawIndexedIndirectCount = (PFN_vkCmdDrawIndexedIndirectCount)load(context, "vkCmdDrawIndexedIndirectCount"); + vkCmdDrawIndirectCount = (PFN_vkCmdDrawIndirectCount)load(context, "vkCmdDrawIndirectCount"); + vkCmdEndRenderPass2 = (PFN_vkCmdEndRenderPass2)load(context, "vkCmdEndRenderPass2"); + vkCmdNextSubpass2 = (PFN_vkCmdNextSubpass2)load(context, "vkCmdNextSubpass2"); + vkCreateRenderPass2 = (PFN_vkCreateRenderPass2)load(context, "vkCreateRenderPass2"); + vkGetBufferDeviceAddress = (PFN_vkGetBufferDeviceAddress)load(context, "vkGetBufferDeviceAddress"); + vkGetBufferOpaqueCaptureAddress = (PFN_vkGetBufferOpaqueCaptureAddress)load(context, "vkGetBufferOpaqueCaptureAddress"); + vkGetDeviceMemoryOpaqueCaptureAddress = (PFN_vkGetDeviceMemoryOpaqueCaptureAddress)load(context, "vkGetDeviceMemoryOpaqueCaptureAddress"); + vkGetSemaphoreCounterValue = (PFN_vkGetSemaphoreCounterValue)load(context, "vkGetSemaphoreCounterValue"); + vkResetQueryPool = (PFN_vkResetQueryPool)load(context, "vkResetQueryPool"); + vkSignalSemaphore = (PFN_vkSignalSemaphore)load(context, "vkSignalSemaphore"); + vkWaitSemaphores = (PFN_vkWaitSemaphores)load(context, "vkWaitSemaphores"); +#endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) + vkCmdBeginRendering = (PFN_vkCmdBeginRendering)load(context, "vkCmdBeginRendering"); + vkCmdBindVertexBuffers2 = (PFN_vkCmdBindVertexBuffers2)load(context, "vkCmdBindVertexBuffers2"); + vkCmdBlitImage2 = (PFN_vkCmdBlitImage2)load(context, "vkCmdBlitImage2"); + vkCmdCopyBuffer2 = (PFN_vkCmdCopyBuffer2)load(context, "vkCmdCopyBuffer2"); + vkCmdCopyBufferToImage2 = (PFN_vkCmdCopyBufferToImage2)load(context, "vkCmdCopyBufferToImage2"); + vkCmdCopyImage2 = (PFN_vkCmdCopyImage2)load(context, "vkCmdCopyImage2"); + vkCmdCopyImageToBuffer2 = (PFN_vkCmdCopyImageToBuffer2)load(context, "vkCmdCopyImageToBuffer2"); + vkCmdEndRendering = (PFN_vkCmdEndRendering)load(context, "vkCmdEndRendering"); + vkCmdPipelineBarrier2 = (PFN_vkCmdPipelineBarrier2)load(context, "vkCmdPipelineBarrier2"); + vkCmdResetEvent2 = (PFN_vkCmdResetEvent2)load(context, "vkCmdResetEvent2"); + vkCmdResolveImage2 = (PFN_vkCmdResolveImage2)load(context, "vkCmdResolveImage2"); + vkCmdSetCullMode = (PFN_vkCmdSetCullMode)load(context, "vkCmdSetCullMode"); + vkCmdSetDepthBiasEnable = (PFN_vkCmdSetDepthBiasEnable)load(context, "vkCmdSetDepthBiasEnable"); + vkCmdSetDepthBoundsTestEnable = (PFN_vkCmdSetDepthBoundsTestEnable)load(context, "vkCmdSetDepthBoundsTestEnable"); + vkCmdSetDepthCompareOp = (PFN_vkCmdSetDepthCompareOp)load(context, "vkCmdSetDepthCompareOp"); + vkCmdSetDepthTestEnable = (PFN_vkCmdSetDepthTestEnable)load(context, "vkCmdSetDepthTestEnable"); + vkCmdSetDepthWriteEnable = (PFN_vkCmdSetDepthWriteEnable)load(context, "vkCmdSetDepthWriteEnable"); + vkCmdSetEvent2 = (PFN_vkCmdSetEvent2)load(context, "vkCmdSetEvent2"); + vkCmdSetFrontFace = (PFN_vkCmdSetFrontFace)load(context, "vkCmdSetFrontFace"); + vkCmdSetPrimitiveRestartEnable = (PFN_vkCmdSetPrimitiveRestartEnable)load(context, "vkCmdSetPrimitiveRestartEnable"); + vkCmdSetPrimitiveTopology = (PFN_vkCmdSetPrimitiveTopology)load(context, "vkCmdSetPrimitiveTopology"); + vkCmdSetRasterizerDiscardEnable = (PFN_vkCmdSetRasterizerDiscardEnable)load(context, "vkCmdSetRasterizerDiscardEnable"); + vkCmdSetScissorWithCount = (PFN_vkCmdSetScissorWithCount)load(context, "vkCmdSetScissorWithCount"); + vkCmdSetStencilOp = (PFN_vkCmdSetStencilOp)load(context, "vkCmdSetStencilOp"); + vkCmdSetStencilTestEnable = (PFN_vkCmdSetStencilTestEnable)load(context, "vkCmdSetStencilTestEnable"); + vkCmdSetViewportWithCount = (PFN_vkCmdSetViewportWithCount)load(context, "vkCmdSetViewportWithCount"); + vkCmdWaitEvents2 = (PFN_vkCmdWaitEvents2)load(context, "vkCmdWaitEvents2"); + vkCmdWriteTimestamp2 = (PFN_vkCmdWriteTimestamp2)load(context, "vkCmdWriteTimestamp2"); + vkCreatePrivateDataSlot = (PFN_vkCreatePrivateDataSlot)load(context, "vkCreatePrivateDataSlot"); + vkDestroyPrivateDataSlot = (PFN_vkDestroyPrivateDataSlot)load(context, "vkDestroyPrivateDataSlot"); + vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)load(context, "vkGetDeviceBufferMemoryRequirements"); + vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)load(context, "vkGetDeviceImageMemoryRequirements"); + vkGetDeviceImageSparseMemoryRequirements = (PFN_vkGetDeviceImageSparseMemoryRequirements)load(context, "vkGetDeviceImageSparseMemoryRequirements"); + vkGetPrivateData = (PFN_vkGetPrivateData)load(context, "vkGetPrivateData"); + vkQueueSubmit2 = (PFN_vkQueueSubmit2)load(context, "vkQueueSubmit2"); + vkSetPrivateData = (PFN_vkSetPrivateData)load(context, "vkSetPrivateData"); +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) + vkCmdBindDescriptorSets2 = (PFN_vkCmdBindDescriptorSets2)load(context, "vkCmdBindDescriptorSets2"); + vkCmdBindIndexBuffer2 = (PFN_vkCmdBindIndexBuffer2)load(context, "vkCmdBindIndexBuffer2"); + vkCmdPushConstants2 = (PFN_vkCmdPushConstants2)load(context, "vkCmdPushConstants2"); + vkCmdPushDescriptorSet = (PFN_vkCmdPushDescriptorSet)load(context, "vkCmdPushDescriptorSet"); + vkCmdPushDescriptorSet2 = (PFN_vkCmdPushDescriptorSet2)load(context, "vkCmdPushDescriptorSet2"); + vkCmdPushDescriptorSetWithTemplate = (PFN_vkCmdPushDescriptorSetWithTemplate)load(context, "vkCmdPushDescriptorSetWithTemplate"); + vkCmdPushDescriptorSetWithTemplate2 = (PFN_vkCmdPushDescriptorSetWithTemplate2)load(context, "vkCmdPushDescriptorSetWithTemplate2"); + vkCmdSetLineStipple = (PFN_vkCmdSetLineStipple)load(context, "vkCmdSetLineStipple"); + vkCmdSetRenderingAttachmentLocations = (PFN_vkCmdSetRenderingAttachmentLocations)load(context, "vkCmdSetRenderingAttachmentLocations"); + vkCmdSetRenderingInputAttachmentIndices = (PFN_vkCmdSetRenderingInputAttachmentIndices)load(context, "vkCmdSetRenderingInputAttachmentIndices"); + vkCopyImageToImage = (PFN_vkCopyImageToImage)load(context, "vkCopyImageToImage"); + vkCopyImageToMemory = (PFN_vkCopyImageToMemory)load(context, "vkCopyImageToMemory"); + vkCopyMemoryToImage = (PFN_vkCopyMemoryToImage)load(context, "vkCopyMemoryToImage"); + vkGetDeviceImageSubresourceLayout = (PFN_vkGetDeviceImageSubresourceLayout)load(context, "vkGetDeviceImageSubresourceLayout"); + vkGetImageSubresourceLayout2 = (PFN_vkGetImageSubresourceLayout2)load(context, "vkGetImageSubresourceLayout2"); + vkGetRenderingAreaGranularity = (PFN_vkGetRenderingAreaGranularity)load(context, "vkGetRenderingAreaGranularity"); + vkMapMemory2 = (PFN_vkMapMemory2)load(context, "vkMapMemory2"); + vkTransitionImageLayout = (PFN_vkTransitionImageLayout)load(context, "vkTransitionImageLayout"); + vkUnmapMemory2 = (PFN_vkUnmapMemory2)load(context, "vkUnmapMemory2"); +#endif /* defined(VK_VERSION_1_4) */ +#if defined(VK_AMDX_shader_enqueue) + vkCmdDispatchGraphAMDX = (PFN_vkCmdDispatchGraphAMDX)load(context, "vkCmdDispatchGraphAMDX"); + vkCmdDispatchGraphIndirectAMDX = (PFN_vkCmdDispatchGraphIndirectAMDX)load(context, "vkCmdDispatchGraphIndirectAMDX"); + vkCmdDispatchGraphIndirectCountAMDX = (PFN_vkCmdDispatchGraphIndirectCountAMDX)load(context, "vkCmdDispatchGraphIndirectCountAMDX"); + vkCmdInitializeGraphScratchMemoryAMDX = (PFN_vkCmdInitializeGraphScratchMemoryAMDX)load(context, "vkCmdInitializeGraphScratchMemoryAMDX"); + vkCreateExecutionGraphPipelinesAMDX = (PFN_vkCreateExecutionGraphPipelinesAMDX)load(context, "vkCreateExecutionGraphPipelinesAMDX"); + vkGetExecutionGraphPipelineNodeIndexAMDX = (PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)load(context, "vkGetExecutionGraphPipelineNodeIndexAMDX"); + vkGetExecutionGraphPipelineScratchSizeAMDX = (PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)load(context, "vkGetExecutionGraphPipelineScratchSizeAMDX"); +#endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) + vkAntiLagUpdateAMD = (PFN_vkAntiLagUpdateAMD)load(context, "vkAntiLagUpdateAMD"); +#endif /* defined(VK_AMD_anti_lag) */ +#if defined(VK_AMD_buffer_marker) + vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD"); +#endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + vkCmdWriteBufferMarker2AMD = (PFN_vkCmdWriteBufferMarker2AMD)load(context, "vkCmdWriteBufferMarker2AMD"); +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_AMD_display_native_hdr) + vkSetLocalDimmingAMD = (PFN_vkSetLocalDimmingAMD)load(context, "vkSetLocalDimmingAMD"); +#endif /* defined(VK_AMD_display_native_hdr) */ +#if defined(VK_AMD_draw_indirect_count) + vkCmdDrawIndexedIndirectCountAMD = (PFN_vkCmdDrawIndexedIndirectCountAMD)load(context, "vkCmdDrawIndexedIndirectCountAMD"); + vkCmdDrawIndirectCountAMD = (PFN_vkCmdDrawIndirectCountAMD)load(context, "vkCmdDrawIndirectCountAMD"); +#endif /* defined(VK_AMD_draw_indirect_count) */ +#if defined(VK_AMD_gpa_interface) + vkCmdBeginGpaSampleAMD = (PFN_vkCmdBeginGpaSampleAMD)load(context, "vkCmdBeginGpaSampleAMD"); + vkCmdBeginGpaSessionAMD = (PFN_vkCmdBeginGpaSessionAMD)load(context, "vkCmdBeginGpaSessionAMD"); + vkCmdCopyGpaSessionResultsAMD = (PFN_vkCmdCopyGpaSessionResultsAMD)load(context, "vkCmdCopyGpaSessionResultsAMD"); + vkCmdEndGpaSampleAMD = (PFN_vkCmdEndGpaSampleAMD)load(context, "vkCmdEndGpaSampleAMD"); + vkCmdEndGpaSessionAMD = (PFN_vkCmdEndGpaSessionAMD)load(context, "vkCmdEndGpaSessionAMD"); + vkCreateGpaSessionAMD = (PFN_vkCreateGpaSessionAMD)load(context, "vkCreateGpaSessionAMD"); + vkDestroyGpaSessionAMD = (PFN_vkDestroyGpaSessionAMD)load(context, "vkDestroyGpaSessionAMD"); + vkGetGpaDeviceClockInfoAMD = (PFN_vkGetGpaDeviceClockInfoAMD)load(context, "vkGetGpaDeviceClockInfoAMD"); + vkGetGpaSessionResultsAMD = (PFN_vkGetGpaSessionResultsAMD)load(context, "vkGetGpaSessionResultsAMD"); + vkGetGpaSessionStatusAMD = (PFN_vkGetGpaSessionStatusAMD)load(context, "vkGetGpaSessionStatusAMD"); + vkResetGpaSessionAMD = (PFN_vkResetGpaSessionAMD)load(context, "vkResetGpaSessionAMD"); + vkSetGpaDeviceClockModeAMD = (PFN_vkSetGpaDeviceClockModeAMD)load(context, "vkSetGpaDeviceClockModeAMD"); +#endif /* defined(VK_AMD_gpa_interface) */ +#if defined(VK_AMD_shader_info) + vkGetShaderInfoAMD = (PFN_vkGetShaderInfoAMD)load(context, "vkGetShaderInfoAMD"); +#endif /* defined(VK_AMD_shader_info) */ +#if defined(VK_ANDROID_external_memory_android_hardware_buffer) + vkGetAndroidHardwareBufferPropertiesANDROID = (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)load(context, "vkGetAndroidHardwareBufferPropertiesANDROID"); + vkGetMemoryAndroidHardwareBufferANDROID = (PFN_vkGetMemoryAndroidHardwareBufferANDROID)load(context, "vkGetMemoryAndroidHardwareBufferANDROID"); +#endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_ARM_data_graph) + vkBindDataGraphPipelineSessionMemoryARM = (PFN_vkBindDataGraphPipelineSessionMemoryARM)load(context, "vkBindDataGraphPipelineSessionMemoryARM"); + vkCmdDispatchDataGraphARM = (PFN_vkCmdDispatchDataGraphARM)load(context, "vkCmdDispatchDataGraphARM"); + vkCreateDataGraphPipelineSessionARM = (PFN_vkCreateDataGraphPipelineSessionARM)load(context, "vkCreateDataGraphPipelineSessionARM"); + vkCreateDataGraphPipelinesARM = (PFN_vkCreateDataGraphPipelinesARM)load(context, "vkCreateDataGraphPipelinesARM"); + vkDestroyDataGraphPipelineSessionARM = (PFN_vkDestroyDataGraphPipelineSessionARM)load(context, "vkDestroyDataGraphPipelineSessionARM"); + vkGetDataGraphPipelineAvailablePropertiesARM = (PFN_vkGetDataGraphPipelineAvailablePropertiesARM)load(context, "vkGetDataGraphPipelineAvailablePropertiesARM"); + vkGetDataGraphPipelinePropertiesARM = (PFN_vkGetDataGraphPipelinePropertiesARM)load(context, "vkGetDataGraphPipelinePropertiesARM"); + vkGetDataGraphPipelineSessionBindPointRequirementsARM = (PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM)load(context, "vkGetDataGraphPipelineSessionBindPointRequirementsARM"); + vkGetDataGraphPipelineSessionMemoryRequirementsARM = (PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM)load(context, "vkGetDataGraphPipelineSessionMemoryRequirementsARM"); +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 + vkCmdSetDispatchParametersARM = (PFN_vkCmdSetDispatchParametersARM)load(context, "vkCmdSetDispatchParametersARM"); +#endif /* defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 */ +#if defined(VK_ARM_shader_instrumentation) + vkClearShaderInstrumentationMetricsARM = (PFN_vkClearShaderInstrumentationMetricsARM)load(context, "vkClearShaderInstrumentationMetricsARM"); + vkCmdBeginShaderInstrumentationARM = (PFN_vkCmdBeginShaderInstrumentationARM)load(context, "vkCmdBeginShaderInstrumentationARM"); + vkCmdEndShaderInstrumentationARM = (PFN_vkCmdEndShaderInstrumentationARM)load(context, "vkCmdEndShaderInstrumentationARM"); + vkCreateShaderInstrumentationARM = (PFN_vkCreateShaderInstrumentationARM)load(context, "vkCreateShaderInstrumentationARM"); + vkDestroyShaderInstrumentationARM = (PFN_vkDestroyShaderInstrumentationARM)load(context, "vkDestroyShaderInstrumentationARM"); + vkGetShaderInstrumentationValuesARM = (PFN_vkGetShaderInstrumentationValuesARM)load(context, "vkGetShaderInstrumentationValuesARM"); +#endif /* defined(VK_ARM_shader_instrumentation) */ +#if defined(VK_ARM_tensors) + vkBindTensorMemoryARM = (PFN_vkBindTensorMemoryARM)load(context, "vkBindTensorMemoryARM"); + vkCmdCopyTensorARM = (PFN_vkCmdCopyTensorARM)load(context, "vkCmdCopyTensorARM"); + vkCreateTensorARM = (PFN_vkCreateTensorARM)load(context, "vkCreateTensorARM"); + vkCreateTensorViewARM = (PFN_vkCreateTensorViewARM)load(context, "vkCreateTensorViewARM"); + vkDestroyTensorARM = (PFN_vkDestroyTensorARM)load(context, "vkDestroyTensorARM"); + vkDestroyTensorViewARM = (PFN_vkDestroyTensorViewARM)load(context, "vkDestroyTensorViewARM"); + vkGetDeviceTensorMemoryRequirementsARM = (PFN_vkGetDeviceTensorMemoryRequirementsARM)load(context, "vkGetDeviceTensorMemoryRequirementsARM"); + vkGetTensorMemoryRequirementsARM = (PFN_vkGetTensorMemoryRequirementsARM)load(context, "vkGetTensorMemoryRequirementsARM"); +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) + vkGetTensorOpaqueCaptureDescriptorDataARM = (PFN_vkGetTensorOpaqueCaptureDescriptorDataARM)load(context, "vkGetTensorOpaqueCaptureDescriptorDataARM"); + vkGetTensorViewOpaqueCaptureDescriptorDataARM = (PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM)load(context, "vkGetTensorViewOpaqueCaptureDescriptorDataARM"); +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) + vkCmdSetAttachmentFeedbackLoopEnableEXT = (PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)load(context, "vkCmdSetAttachmentFeedbackLoopEnableEXT"); +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ +#if defined(VK_EXT_buffer_device_address) + vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)load(context, "vkGetBufferDeviceAddressEXT"); +#endif /* defined(VK_EXT_buffer_device_address) */ +#if defined(VK_EXT_calibrated_timestamps) + vkGetCalibratedTimestampsEXT = (PFN_vkGetCalibratedTimestampsEXT)load(context, "vkGetCalibratedTimestampsEXT"); +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) + vkCmdSetColorWriteEnableEXT = (PFN_vkCmdSetColorWriteEnableEXT)load(context, "vkCmdSetColorWriteEnableEXT"); +#endif /* defined(VK_EXT_color_write_enable) */ +#if defined(VK_EXT_conditional_rendering) + vkCmdBeginConditionalRenderingEXT = (PFN_vkCmdBeginConditionalRenderingEXT)load(context, "vkCmdBeginConditionalRenderingEXT"); + vkCmdEndConditionalRenderingEXT = (PFN_vkCmdEndConditionalRenderingEXT)load(context, "vkCmdEndConditionalRenderingEXT"); +#endif /* defined(VK_EXT_conditional_rendering) */ +#if defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) + vkCmdBeginCustomResolveEXT = (PFN_vkCmdBeginCustomResolveEXT)load(context, "vkCmdBeginCustomResolveEXT"); +#endif /* defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) */ +#if defined(VK_EXT_debug_marker) + vkCmdDebugMarkerBeginEXT = (PFN_vkCmdDebugMarkerBeginEXT)load(context, "vkCmdDebugMarkerBeginEXT"); + vkCmdDebugMarkerEndEXT = (PFN_vkCmdDebugMarkerEndEXT)load(context, "vkCmdDebugMarkerEndEXT"); + vkCmdDebugMarkerInsertEXT = (PFN_vkCmdDebugMarkerInsertEXT)load(context, "vkCmdDebugMarkerInsertEXT"); + vkDebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)load(context, "vkDebugMarkerSetObjectNameEXT"); + vkDebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT)load(context, "vkDebugMarkerSetObjectTagEXT"); +#endif /* defined(VK_EXT_debug_marker) */ +#if defined(VK_EXT_depth_bias_control) + vkCmdSetDepthBias2EXT = (PFN_vkCmdSetDepthBias2EXT)load(context, "vkCmdSetDepthBias2EXT"); +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) + vkCmdBindDescriptorBufferEmbeddedSamplersEXT = (PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT)load(context, "vkCmdBindDescriptorBufferEmbeddedSamplersEXT"); + vkCmdBindDescriptorBuffersEXT = (PFN_vkCmdBindDescriptorBuffersEXT)load(context, "vkCmdBindDescriptorBuffersEXT"); + vkCmdSetDescriptorBufferOffsetsEXT = (PFN_vkCmdSetDescriptorBufferOffsetsEXT)load(context, "vkCmdSetDescriptorBufferOffsetsEXT"); + vkGetBufferOpaqueCaptureDescriptorDataEXT = (PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT)load(context, "vkGetBufferOpaqueCaptureDescriptorDataEXT"); + vkGetDescriptorEXT = (PFN_vkGetDescriptorEXT)load(context, "vkGetDescriptorEXT"); + vkGetDescriptorSetLayoutBindingOffsetEXT = (PFN_vkGetDescriptorSetLayoutBindingOffsetEXT)load(context, "vkGetDescriptorSetLayoutBindingOffsetEXT"); + vkGetDescriptorSetLayoutSizeEXT = (PFN_vkGetDescriptorSetLayoutSizeEXT)load(context, "vkGetDescriptorSetLayoutSizeEXT"); + vkGetImageOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageOpaqueCaptureDescriptorDataEXT"); + vkGetImageViewOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageViewOpaqueCaptureDescriptorDataEXT"); + vkGetSamplerOpaqueCaptureDescriptorDataEXT = (PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT)load(context, "vkGetSamplerOpaqueCaptureDescriptorDataEXT"); +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) + vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT = (PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT)load(context, "vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT"); +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_descriptor_heap) + vkCmdBindResourceHeapEXT = (PFN_vkCmdBindResourceHeapEXT)load(context, "vkCmdBindResourceHeapEXT"); + vkCmdBindSamplerHeapEXT = (PFN_vkCmdBindSamplerHeapEXT)load(context, "vkCmdBindSamplerHeapEXT"); + vkCmdPushDataEXT = (PFN_vkCmdPushDataEXT)load(context, "vkCmdPushDataEXT"); + vkGetImageOpaqueCaptureDataEXT = (PFN_vkGetImageOpaqueCaptureDataEXT)load(context, "vkGetImageOpaqueCaptureDataEXT"); + vkWriteResourceDescriptorsEXT = (PFN_vkWriteResourceDescriptorsEXT)load(context, "vkWriteResourceDescriptorsEXT"); + vkWriteSamplerDescriptorsEXT = (PFN_vkWriteSamplerDescriptorsEXT)load(context, "vkWriteSamplerDescriptorsEXT"); +#endif /* defined(VK_EXT_descriptor_heap) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) + vkRegisterCustomBorderColorEXT = (PFN_vkRegisterCustomBorderColorEXT)load(context, "vkRegisterCustomBorderColorEXT"); + vkUnregisterCustomBorderColorEXT = (PFN_vkUnregisterCustomBorderColorEXT)load(context, "vkUnregisterCustomBorderColorEXT"); +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) + vkGetTensorOpaqueCaptureDataARM = (PFN_vkGetTensorOpaqueCaptureDataARM)load(context, "vkGetTensorOpaqueCaptureDataARM"); +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) */ +#if defined(VK_EXT_device_fault) + vkGetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)load(context, "vkGetDeviceFaultInfoEXT"); +#endif /* defined(VK_EXT_device_fault) */ +#if defined(VK_EXT_device_generated_commands) + vkCmdExecuteGeneratedCommandsEXT = (PFN_vkCmdExecuteGeneratedCommandsEXT)load(context, "vkCmdExecuteGeneratedCommandsEXT"); + vkCmdPreprocessGeneratedCommandsEXT = (PFN_vkCmdPreprocessGeneratedCommandsEXT)load(context, "vkCmdPreprocessGeneratedCommandsEXT"); + vkCreateIndirectCommandsLayoutEXT = (PFN_vkCreateIndirectCommandsLayoutEXT)load(context, "vkCreateIndirectCommandsLayoutEXT"); + vkCreateIndirectExecutionSetEXT = (PFN_vkCreateIndirectExecutionSetEXT)load(context, "vkCreateIndirectExecutionSetEXT"); + vkDestroyIndirectCommandsLayoutEXT = (PFN_vkDestroyIndirectCommandsLayoutEXT)load(context, "vkDestroyIndirectCommandsLayoutEXT"); + vkDestroyIndirectExecutionSetEXT = (PFN_vkDestroyIndirectExecutionSetEXT)load(context, "vkDestroyIndirectExecutionSetEXT"); + vkGetGeneratedCommandsMemoryRequirementsEXT = (PFN_vkGetGeneratedCommandsMemoryRequirementsEXT)load(context, "vkGetGeneratedCommandsMemoryRequirementsEXT"); + vkUpdateIndirectExecutionSetPipelineEXT = (PFN_vkUpdateIndirectExecutionSetPipelineEXT)load(context, "vkUpdateIndirectExecutionSetPipelineEXT"); + vkUpdateIndirectExecutionSetShaderEXT = (PFN_vkUpdateIndirectExecutionSetShaderEXT)load(context, "vkUpdateIndirectExecutionSetShaderEXT"); +#endif /* defined(VK_EXT_device_generated_commands) */ +#if defined(VK_EXT_discard_rectangles) + vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); +#endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 + vkCmdSetDiscardRectangleEnableEXT = (PFN_vkCmdSetDiscardRectangleEnableEXT)load(context, "vkCmdSetDiscardRectangleEnableEXT"); + vkCmdSetDiscardRectangleModeEXT = (PFN_vkCmdSetDiscardRectangleModeEXT)load(context, "vkCmdSetDiscardRectangleModeEXT"); +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ +#if defined(VK_EXT_display_control) + vkDisplayPowerControlEXT = (PFN_vkDisplayPowerControlEXT)load(context, "vkDisplayPowerControlEXT"); + vkGetSwapchainCounterEXT = (PFN_vkGetSwapchainCounterEXT)load(context, "vkGetSwapchainCounterEXT"); + vkRegisterDeviceEventEXT = (PFN_vkRegisterDeviceEventEXT)load(context, "vkRegisterDeviceEventEXT"); + vkRegisterDisplayEventEXT = (PFN_vkRegisterDisplayEventEXT)load(context, "vkRegisterDisplayEventEXT"); +#endif /* defined(VK_EXT_display_control) */ +#if defined(VK_EXT_external_memory_host) + vkGetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)load(context, "vkGetMemoryHostPointerPropertiesEXT"); +#endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) + vkGetMemoryMetalHandleEXT = (PFN_vkGetMemoryMetalHandleEXT)load(context, "vkGetMemoryMetalHandleEXT"); + vkGetMemoryMetalHandlePropertiesEXT = (PFN_vkGetMemoryMetalHandlePropertiesEXT)load(context, "vkGetMemoryMetalHandlePropertiesEXT"); +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) + vkCmdEndRendering2EXT = (PFN_vkCmdEndRendering2EXT)load(context, "vkCmdEndRendering2EXT"); +#endif /* defined(VK_EXT_fragment_density_map_offset) */ +#if defined(VK_EXT_full_screen_exclusive) + vkAcquireFullScreenExclusiveModeEXT = (PFN_vkAcquireFullScreenExclusiveModeEXT)load(context, "vkAcquireFullScreenExclusiveModeEXT"); + vkReleaseFullScreenExclusiveModeEXT = (PFN_vkReleaseFullScreenExclusiveModeEXT)load(context, "vkReleaseFullScreenExclusiveModeEXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) + vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ +#if defined(VK_EXT_hdr_metadata) + vkSetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)load(context, "vkSetHdrMetadataEXT"); +#endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_image_copy) + vkCopyImageToImageEXT = (PFN_vkCopyImageToImageEXT)load(context, "vkCopyImageToImageEXT"); + vkCopyImageToMemoryEXT = (PFN_vkCopyImageToMemoryEXT)load(context, "vkCopyImageToMemoryEXT"); + vkCopyMemoryToImageEXT = (PFN_vkCopyMemoryToImageEXT)load(context, "vkCopyMemoryToImageEXT"); + vkTransitionImageLayoutEXT = (PFN_vkTransitionImageLayoutEXT)load(context, "vkTransitionImageLayoutEXT"); +#endif /* defined(VK_EXT_host_image_copy) */ +#if defined(VK_EXT_host_query_reset) + vkResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)load(context, "vkResetQueryPoolEXT"); +#endif /* defined(VK_EXT_host_query_reset) */ +#if defined(VK_EXT_image_drm_format_modifier) + vkGetImageDrmFormatModifierPropertiesEXT = (PFN_vkGetImageDrmFormatModifierPropertiesEXT)load(context, "vkGetImageDrmFormatModifierPropertiesEXT"); +#endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) + vkCmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)load(context, "vkCmdSetLineStippleEXT"); +#endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_memory_decompression) + vkCmdDecompressMemoryEXT = (PFN_vkCmdDecompressMemoryEXT)load(context, "vkCmdDecompressMemoryEXT"); + vkCmdDecompressMemoryIndirectCountEXT = (PFN_vkCmdDecompressMemoryIndirectCountEXT)load(context, "vkCmdDecompressMemoryIndirectCountEXT"); +#endif /* defined(VK_EXT_memory_decompression) */ +#if defined(VK_EXT_mesh_shader) + vkCmdDrawMeshTasksEXT = (PFN_vkCmdDrawMeshTasksEXT)load(context, "vkCmdDrawMeshTasksEXT"); + vkCmdDrawMeshTasksIndirectEXT = (PFN_vkCmdDrawMeshTasksIndirectEXT)load(context, "vkCmdDrawMeshTasksIndirectEXT"); +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + vkCmdDrawMeshTasksIndirectCountEXT = (PFN_vkCmdDrawMeshTasksIndirectCountEXT)load(context, "vkCmdDrawMeshTasksIndirectCountEXT"); +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_EXT_metal_objects) + vkExportMetalObjectsEXT = (PFN_vkExportMetalObjectsEXT)load(context, "vkExportMetalObjectsEXT"); +#endif /* defined(VK_EXT_metal_objects) */ +#if defined(VK_EXT_multi_draw) + vkCmdDrawMultiEXT = (PFN_vkCmdDrawMultiEXT)load(context, "vkCmdDrawMultiEXT"); + vkCmdDrawMultiIndexedEXT = (PFN_vkCmdDrawMultiIndexedEXT)load(context, "vkCmdDrawMultiIndexedEXT"); +#endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) + vkBuildMicromapsEXT = (PFN_vkBuildMicromapsEXT)load(context, "vkBuildMicromapsEXT"); + vkCmdBuildMicromapsEXT = (PFN_vkCmdBuildMicromapsEXT)load(context, "vkCmdBuildMicromapsEXT"); + vkCmdCopyMemoryToMicromapEXT = (PFN_vkCmdCopyMemoryToMicromapEXT)load(context, "vkCmdCopyMemoryToMicromapEXT"); + vkCmdCopyMicromapEXT = (PFN_vkCmdCopyMicromapEXT)load(context, "vkCmdCopyMicromapEXT"); + vkCmdCopyMicromapToMemoryEXT = (PFN_vkCmdCopyMicromapToMemoryEXT)load(context, "vkCmdCopyMicromapToMemoryEXT"); + vkCmdWriteMicromapsPropertiesEXT = (PFN_vkCmdWriteMicromapsPropertiesEXT)load(context, "vkCmdWriteMicromapsPropertiesEXT"); + vkCopyMemoryToMicromapEXT = (PFN_vkCopyMemoryToMicromapEXT)load(context, "vkCopyMemoryToMicromapEXT"); + vkCopyMicromapEXT = (PFN_vkCopyMicromapEXT)load(context, "vkCopyMicromapEXT"); + vkCopyMicromapToMemoryEXT = (PFN_vkCopyMicromapToMemoryEXT)load(context, "vkCopyMicromapToMemoryEXT"); + vkCreateMicromapEXT = (PFN_vkCreateMicromapEXT)load(context, "vkCreateMicromapEXT"); + vkDestroyMicromapEXT = (PFN_vkDestroyMicromapEXT)load(context, "vkDestroyMicromapEXT"); + vkGetDeviceMicromapCompatibilityEXT = (PFN_vkGetDeviceMicromapCompatibilityEXT)load(context, "vkGetDeviceMicromapCompatibilityEXT"); + vkGetMicromapBuildSizesEXT = (PFN_vkGetMicromapBuildSizesEXT)load(context, "vkGetMicromapBuildSizesEXT"); + vkWriteMicromapsPropertiesEXT = (PFN_vkWriteMicromapsPropertiesEXT)load(context, "vkWriteMicromapsPropertiesEXT"); +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) + vkSetDeviceMemoryPriorityEXT = (PFN_vkSetDeviceMemoryPriorityEXT)load(context, "vkSetDeviceMemoryPriorityEXT"); +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) + vkGetPipelinePropertiesEXT = (PFN_vkGetPipelinePropertiesEXT)load(context, "vkGetPipelinePropertiesEXT"); +#endif /* defined(VK_EXT_pipeline_properties) */ +#if defined(VK_EXT_present_timing) + vkGetPastPresentationTimingEXT = (PFN_vkGetPastPresentationTimingEXT)load(context, "vkGetPastPresentationTimingEXT"); + vkGetSwapchainTimeDomainPropertiesEXT = (PFN_vkGetSwapchainTimeDomainPropertiesEXT)load(context, "vkGetSwapchainTimeDomainPropertiesEXT"); + vkGetSwapchainTimingPropertiesEXT = (PFN_vkGetSwapchainTimingPropertiesEXT)load(context, "vkGetSwapchainTimingPropertiesEXT"); + vkSetSwapchainPresentTimingQueueSizeEXT = (PFN_vkSetSwapchainPresentTimingQueueSizeEXT)load(context, "vkSetSwapchainPresentTimingQueueSizeEXT"); +#endif /* defined(VK_EXT_present_timing) */ +#if defined(VK_EXT_primitive_restart_index) + vkCmdSetPrimitiveRestartIndexEXT = (PFN_vkCmdSetPrimitiveRestartIndexEXT)load(context, "vkCmdSetPrimitiveRestartIndexEXT"); +#endif /* defined(VK_EXT_primitive_restart_index) */ +#if defined(VK_EXT_private_data) + vkCreatePrivateDataSlotEXT = (PFN_vkCreatePrivateDataSlotEXT)load(context, "vkCreatePrivateDataSlotEXT"); + vkDestroyPrivateDataSlotEXT = (PFN_vkDestroyPrivateDataSlotEXT)load(context, "vkDestroyPrivateDataSlotEXT"); + vkGetPrivateDataEXT = (PFN_vkGetPrivateDataEXT)load(context, "vkGetPrivateDataEXT"); + vkSetPrivateDataEXT = (PFN_vkSetPrivateDataEXT)load(context, "vkSetPrivateDataEXT"); +#endif /* defined(VK_EXT_private_data) */ +#if defined(VK_EXT_sample_locations) + vkCmdSetSampleLocationsEXT = (PFN_vkCmdSetSampleLocationsEXT)load(context, "vkCmdSetSampleLocationsEXT"); +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) + vkGetShaderModuleCreateInfoIdentifierEXT = (PFN_vkGetShaderModuleCreateInfoIdentifierEXT)load(context, "vkGetShaderModuleCreateInfoIdentifierEXT"); + vkGetShaderModuleIdentifierEXT = (PFN_vkGetShaderModuleIdentifierEXT)load(context, "vkGetShaderModuleIdentifierEXT"); +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) + vkCmdBindShadersEXT = (PFN_vkCmdBindShadersEXT)load(context, "vkCmdBindShadersEXT"); + vkCreateShadersEXT = (PFN_vkCreateShadersEXT)load(context, "vkCreateShadersEXT"); + vkDestroyShaderEXT = (PFN_vkDestroyShaderEXT)load(context, "vkDestroyShaderEXT"); + vkGetShaderBinaryDataEXT = (PFN_vkGetShaderBinaryDataEXT)load(context, "vkGetShaderBinaryDataEXT"); +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) + vkReleaseSwapchainImagesEXT = (PFN_vkReleaseSwapchainImagesEXT)load(context, "vkReleaseSwapchainImagesEXT"); +#endif /* defined(VK_EXT_swapchain_maintenance1) */ +#if defined(VK_EXT_transform_feedback) + vkCmdBeginQueryIndexedEXT = (PFN_vkCmdBeginQueryIndexedEXT)load(context, "vkCmdBeginQueryIndexedEXT"); + vkCmdBeginTransformFeedbackEXT = (PFN_vkCmdBeginTransformFeedbackEXT)load(context, "vkCmdBeginTransformFeedbackEXT"); + vkCmdBindTransformFeedbackBuffersEXT = (PFN_vkCmdBindTransformFeedbackBuffersEXT)load(context, "vkCmdBindTransformFeedbackBuffersEXT"); + vkCmdDrawIndirectByteCountEXT = (PFN_vkCmdDrawIndirectByteCountEXT)load(context, "vkCmdDrawIndirectByteCountEXT"); + vkCmdEndQueryIndexedEXT = (PFN_vkCmdEndQueryIndexedEXT)load(context, "vkCmdEndQueryIndexedEXT"); + vkCmdEndTransformFeedbackEXT = (PFN_vkCmdEndTransformFeedbackEXT)load(context, "vkCmdEndTransformFeedbackEXT"); +#endif /* defined(VK_EXT_transform_feedback) */ +#if defined(VK_EXT_validation_cache) + vkCreateValidationCacheEXT = (PFN_vkCreateValidationCacheEXT)load(context, "vkCreateValidationCacheEXT"); + vkDestroyValidationCacheEXT = (PFN_vkDestroyValidationCacheEXT)load(context, "vkDestroyValidationCacheEXT"); + vkGetValidationCacheDataEXT = (PFN_vkGetValidationCacheDataEXT)load(context, "vkGetValidationCacheDataEXT"); + vkMergeValidationCachesEXT = (PFN_vkMergeValidationCachesEXT)load(context, "vkMergeValidationCachesEXT"); +#endif /* defined(VK_EXT_validation_cache) */ +#if defined(VK_FUCHSIA_buffer_collection) + vkCreateBufferCollectionFUCHSIA = (PFN_vkCreateBufferCollectionFUCHSIA)load(context, "vkCreateBufferCollectionFUCHSIA"); + vkDestroyBufferCollectionFUCHSIA = (PFN_vkDestroyBufferCollectionFUCHSIA)load(context, "vkDestroyBufferCollectionFUCHSIA"); + vkGetBufferCollectionPropertiesFUCHSIA = (PFN_vkGetBufferCollectionPropertiesFUCHSIA)load(context, "vkGetBufferCollectionPropertiesFUCHSIA"); + vkSetBufferCollectionBufferConstraintsFUCHSIA = (PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)load(context, "vkSetBufferCollectionBufferConstraintsFUCHSIA"); + vkSetBufferCollectionImageConstraintsFUCHSIA = (PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)load(context, "vkSetBufferCollectionImageConstraintsFUCHSIA"); +#endif /* defined(VK_FUCHSIA_buffer_collection) */ +#if defined(VK_FUCHSIA_external_memory) + vkGetMemoryZirconHandleFUCHSIA = (PFN_vkGetMemoryZirconHandleFUCHSIA)load(context, "vkGetMemoryZirconHandleFUCHSIA"); + vkGetMemoryZirconHandlePropertiesFUCHSIA = (PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)load(context, "vkGetMemoryZirconHandlePropertiesFUCHSIA"); +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) + vkGetSemaphoreZirconHandleFUCHSIA = (PFN_vkGetSemaphoreZirconHandleFUCHSIA)load(context, "vkGetSemaphoreZirconHandleFUCHSIA"); + vkImportSemaphoreZirconHandleFUCHSIA = (PFN_vkImportSemaphoreZirconHandleFUCHSIA)load(context, "vkImportSemaphoreZirconHandleFUCHSIA"); +#endif /* defined(VK_FUCHSIA_external_semaphore) */ +#if defined(VK_GOOGLE_display_timing) + vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)load(context, "vkGetPastPresentationTimingGOOGLE"); + vkGetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)load(context, "vkGetRefreshCycleDurationGOOGLE"); +#endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) + vkCmdDrawClusterHUAWEI = (PFN_vkCmdDrawClusterHUAWEI)load(context, "vkCmdDrawClusterHUAWEI"); + vkCmdDrawClusterIndirectHUAWEI = (PFN_vkCmdDrawClusterIndirectHUAWEI)load(context, "vkCmdDrawClusterIndirectHUAWEI"); +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ +#if defined(VK_HUAWEI_invocation_mask) + vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 + vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = (PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)load(context, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI"); +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ +#if defined(VK_HUAWEI_subpass_shading) + vkCmdSubpassShadingHUAWEI = (PFN_vkCmdSubpassShadingHUAWEI)load(context, "vkCmdSubpassShadingHUAWEI"); +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) + vkAcquirePerformanceConfigurationINTEL = (PFN_vkAcquirePerformanceConfigurationINTEL)load(context, "vkAcquirePerformanceConfigurationINTEL"); + vkCmdSetPerformanceMarkerINTEL = (PFN_vkCmdSetPerformanceMarkerINTEL)load(context, "vkCmdSetPerformanceMarkerINTEL"); + vkCmdSetPerformanceOverrideINTEL = (PFN_vkCmdSetPerformanceOverrideINTEL)load(context, "vkCmdSetPerformanceOverrideINTEL"); + vkCmdSetPerformanceStreamMarkerINTEL = (PFN_vkCmdSetPerformanceStreamMarkerINTEL)load(context, "vkCmdSetPerformanceStreamMarkerINTEL"); + vkGetPerformanceParameterINTEL = (PFN_vkGetPerformanceParameterINTEL)load(context, "vkGetPerformanceParameterINTEL"); + vkInitializePerformanceApiINTEL = (PFN_vkInitializePerformanceApiINTEL)load(context, "vkInitializePerformanceApiINTEL"); + vkQueueSetPerformanceConfigurationINTEL = (PFN_vkQueueSetPerformanceConfigurationINTEL)load(context, "vkQueueSetPerformanceConfigurationINTEL"); + vkReleasePerformanceConfigurationINTEL = (PFN_vkReleasePerformanceConfigurationINTEL)load(context, "vkReleasePerformanceConfigurationINTEL"); + vkUninitializePerformanceApiINTEL = (PFN_vkUninitializePerformanceApiINTEL)load(context, "vkUninitializePerformanceApiINTEL"); +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) + vkBuildAccelerationStructuresKHR = (PFN_vkBuildAccelerationStructuresKHR)load(context, "vkBuildAccelerationStructuresKHR"); + vkCmdBuildAccelerationStructuresIndirectKHR = (PFN_vkCmdBuildAccelerationStructuresIndirectKHR)load(context, "vkCmdBuildAccelerationStructuresIndirectKHR"); + vkCmdBuildAccelerationStructuresKHR = (PFN_vkCmdBuildAccelerationStructuresKHR)load(context, "vkCmdBuildAccelerationStructuresKHR"); + vkCmdCopyAccelerationStructureKHR = (PFN_vkCmdCopyAccelerationStructureKHR)load(context, "vkCmdCopyAccelerationStructureKHR"); + vkCmdCopyAccelerationStructureToMemoryKHR = (PFN_vkCmdCopyAccelerationStructureToMemoryKHR)load(context, "vkCmdCopyAccelerationStructureToMemoryKHR"); + vkCmdCopyMemoryToAccelerationStructureKHR = (PFN_vkCmdCopyMemoryToAccelerationStructureKHR)load(context, "vkCmdCopyMemoryToAccelerationStructureKHR"); + vkCmdWriteAccelerationStructuresPropertiesKHR = (PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)load(context, "vkCmdWriteAccelerationStructuresPropertiesKHR"); + vkCopyAccelerationStructureKHR = (PFN_vkCopyAccelerationStructureKHR)load(context, "vkCopyAccelerationStructureKHR"); + vkCopyAccelerationStructureToMemoryKHR = (PFN_vkCopyAccelerationStructureToMemoryKHR)load(context, "vkCopyAccelerationStructureToMemoryKHR"); + vkCopyMemoryToAccelerationStructureKHR = (PFN_vkCopyMemoryToAccelerationStructureKHR)load(context, "vkCopyMemoryToAccelerationStructureKHR"); + vkCreateAccelerationStructureKHR = (PFN_vkCreateAccelerationStructureKHR)load(context, "vkCreateAccelerationStructureKHR"); + vkDestroyAccelerationStructureKHR = (PFN_vkDestroyAccelerationStructureKHR)load(context, "vkDestroyAccelerationStructureKHR"); + vkGetAccelerationStructureBuildSizesKHR = (PFN_vkGetAccelerationStructureBuildSizesKHR)load(context, "vkGetAccelerationStructureBuildSizesKHR"); + vkGetAccelerationStructureDeviceAddressKHR = (PFN_vkGetAccelerationStructureDeviceAddressKHR)load(context, "vkGetAccelerationStructureDeviceAddressKHR"); + vkGetDeviceAccelerationStructureCompatibilityKHR = (PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)load(context, "vkGetDeviceAccelerationStructureCompatibilityKHR"); + vkWriteAccelerationStructuresPropertiesKHR = (PFN_vkWriteAccelerationStructuresPropertiesKHR)load(context, "vkWriteAccelerationStructuresPropertiesKHR"); +#endif /* defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_bind_memory2) + vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2KHR)load(context, "vkBindBufferMemory2KHR"); + vkBindImageMemory2KHR = (PFN_vkBindImageMemory2KHR)load(context, "vkBindImageMemory2KHR"); +#endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) + vkGetBufferDeviceAddressKHR = (PFN_vkGetBufferDeviceAddressKHR)load(context, "vkGetBufferDeviceAddressKHR"); + vkGetBufferOpaqueCaptureAddressKHR = (PFN_vkGetBufferOpaqueCaptureAddressKHR)load(context, "vkGetBufferOpaqueCaptureAddressKHR"); + vkGetDeviceMemoryOpaqueCaptureAddressKHR = (PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)load(context, "vkGetDeviceMemoryOpaqueCaptureAddressKHR"); +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_calibrated_timestamps) + vkGetCalibratedTimestampsKHR = (PFN_vkGetCalibratedTimestampsKHR)load(context, "vkGetCalibratedTimestampsKHR"); +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_copy_commands2) + vkCmdBlitImage2KHR = (PFN_vkCmdBlitImage2KHR)load(context, "vkCmdBlitImage2KHR"); + vkCmdCopyBuffer2KHR = (PFN_vkCmdCopyBuffer2KHR)load(context, "vkCmdCopyBuffer2KHR"); + vkCmdCopyBufferToImage2KHR = (PFN_vkCmdCopyBufferToImage2KHR)load(context, "vkCmdCopyBufferToImage2KHR"); + vkCmdCopyImage2KHR = (PFN_vkCmdCopyImage2KHR)load(context, "vkCmdCopyImage2KHR"); + vkCmdCopyImageToBuffer2KHR = (PFN_vkCmdCopyImageToBuffer2KHR)load(context, "vkCmdCopyImageToBuffer2KHR"); + vkCmdResolveImage2KHR = (PFN_vkCmdResolveImage2KHR)load(context, "vkCmdResolveImage2KHR"); +#endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) + vkCmdCopyMemoryIndirectKHR = (PFN_vkCmdCopyMemoryIndirectKHR)load(context, "vkCmdCopyMemoryIndirectKHR"); + vkCmdCopyMemoryToImageIndirectKHR = (PFN_vkCmdCopyMemoryToImageIndirectKHR)load(context, "vkCmdCopyMemoryToImageIndirectKHR"); +#endif /* defined(VK_KHR_copy_memory_indirect) */ +#if defined(VK_KHR_create_renderpass2) + vkCmdBeginRenderPass2KHR = (PFN_vkCmdBeginRenderPass2KHR)load(context, "vkCmdBeginRenderPass2KHR"); + vkCmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)load(context, "vkCmdEndRenderPass2KHR"); + vkCmdNextSubpass2KHR = (PFN_vkCmdNextSubpass2KHR)load(context, "vkCmdNextSubpass2KHR"); + vkCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)load(context, "vkCreateRenderPass2KHR"); +#endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) + vkCreateDeferredOperationKHR = (PFN_vkCreateDeferredOperationKHR)load(context, "vkCreateDeferredOperationKHR"); + vkDeferredOperationJoinKHR = (PFN_vkDeferredOperationJoinKHR)load(context, "vkDeferredOperationJoinKHR"); + vkDestroyDeferredOperationKHR = (PFN_vkDestroyDeferredOperationKHR)load(context, "vkDestroyDeferredOperationKHR"); + vkGetDeferredOperationMaxConcurrencyKHR = (PFN_vkGetDeferredOperationMaxConcurrencyKHR)load(context, "vkGetDeferredOperationMaxConcurrencyKHR"); + vkGetDeferredOperationResultKHR = (PFN_vkGetDeferredOperationResultKHR)load(context, "vkGetDeferredOperationResultKHR"); +#endif /* defined(VK_KHR_deferred_host_operations) */ +#if defined(VK_KHR_descriptor_update_template) + vkCreateDescriptorUpdateTemplateKHR = (PFN_vkCreateDescriptorUpdateTemplateKHR)load(context, "vkCreateDescriptorUpdateTemplateKHR"); + vkDestroyDescriptorUpdateTemplateKHR = (PFN_vkDestroyDescriptorUpdateTemplateKHR)load(context, "vkDestroyDescriptorUpdateTemplateKHR"); + vkUpdateDescriptorSetWithTemplateKHR = (PFN_vkUpdateDescriptorSetWithTemplateKHR)load(context, "vkUpdateDescriptorSetWithTemplateKHR"); +#endif /* defined(VK_KHR_descriptor_update_template) */ +#if defined(VK_KHR_device_address_commands) + vkCmdBindIndexBuffer3KHR = (PFN_vkCmdBindIndexBuffer3KHR)load(context, "vkCmdBindIndexBuffer3KHR"); + vkCmdBindVertexBuffers3KHR = (PFN_vkCmdBindVertexBuffers3KHR)load(context, "vkCmdBindVertexBuffers3KHR"); + vkCmdCopyImageToMemoryKHR = (PFN_vkCmdCopyImageToMemoryKHR)load(context, "vkCmdCopyImageToMemoryKHR"); + vkCmdCopyMemoryKHR = (PFN_vkCmdCopyMemoryKHR)load(context, "vkCmdCopyMemoryKHR"); + vkCmdCopyMemoryToImageKHR = (PFN_vkCmdCopyMemoryToImageKHR)load(context, "vkCmdCopyMemoryToImageKHR"); + vkCmdCopyQueryPoolResultsToMemoryKHR = (PFN_vkCmdCopyQueryPoolResultsToMemoryKHR)load(context, "vkCmdCopyQueryPoolResultsToMemoryKHR"); + vkCmdDispatchIndirect2KHR = (PFN_vkCmdDispatchIndirect2KHR)load(context, "vkCmdDispatchIndirect2KHR"); + vkCmdDrawIndexedIndirect2KHR = (PFN_vkCmdDrawIndexedIndirect2KHR)load(context, "vkCmdDrawIndexedIndirect2KHR"); + vkCmdDrawIndirect2KHR = (PFN_vkCmdDrawIndirect2KHR)load(context, "vkCmdDrawIndirect2KHR"); + vkCmdFillMemoryKHR = (PFN_vkCmdFillMemoryKHR)load(context, "vkCmdFillMemoryKHR"); + vkCmdUpdateMemoryKHR = (PFN_vkCmdUpdateMemoryKHR)load(context, "vkCmdUpdateMemoryKHR"); +#endif /* defined(VK_KHR_device_address_commands) */ +#if defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) + vkCmdDrawIndexedIndirectCount2KHR = (PFN_vkCmdDrawIndexedIndirectCount2KHR)load(context, "vkCmdDrawIndexedIndirectCount2KHR"); + vkCmdDrawIndirectCount2KHR = (PFN_vkCmdDrawIndirectCount2KHR)load(context, "vkCmdDrawIndirectCount2KHR"); +#endif /* defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) + vkCmdBeginConditionalRendering2EXT = (PFN_vkCmdBeginConditionalRendering2EXT)load(context, "vkCmdBeginConditionalRendering2EXT"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) + vkCmdBeginTransformFeedback2EXT = (PFN_vkCmdBeginTransformFeedback2EXT)load(context, "vkCmdBeginTransformFeedback2EXT"); + vkCmdBindTransformFeedbackBuffers2EXT = (PFN_vkCmdBindTransformFeedbackBuffers2EXT)load(context, "vkCmdBindTransformFeedbackBuffers2EXT"); + vkCmdDrawIndirectByteCount2EXT = (PFN_vkCmdDrawIndirectByteCount2EXT)load(context, "vkCmdDrawIndirectByteCount2EXT"); + vkCmdEndTransformFeedback2EXT = (PFN_vkCmdEndTransformFeedback2EXT)load(context, "vkCmdEndTransformFeedback2EXT"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) + vkCmdDrawMeshTasksIndirect2EXT = (PFN_vkCmdDrawMeshTasksIndirect2EXT)load(context, "vkCmdDrawMeshTasksIndirect2EXT"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) */ +#if defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) + vkCmdDrawMeshTasksIndirectCount2EXT = (PFN_vkCmdDrawMeshTasksIndirectCount2EXT)load(context, "vkCmdDrawMeshTasksIndirectCount2EXT"); +#endif /* defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) + vkCmdWriteMarkerToMemoryAMD = (PFN_vkCmdWriteMarkerToMemoryAMD)load(context, "vkCmdWriteMarkerToMemoryAMD"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) + vkCreateAccelerationStructure2KHR = (PFN_vkCreateAccelerationStructure2KHR)load(context, "vkCreateAccelerationStructure2KHR"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_device_fault) + vkGetDeviceFaultDebugInfoKHR = (PFN_vkGetDeviceFaultDebugInfoKHR)load(context, "vkGetDeviceFaultDebugInfoKHR"); + vkGetDeviceFaultReportsKHR = (PFN_vkGetDeviceFaultReportsKHR)load(context, "vkGetDeviceFaultReportsKHR"); +#endif /* defined(VK_KHR_device_fault) */ +#if defined(VK_KHR_device_group) + vkCmdDispatchBaseKHR = (PFN_vkCmdDispatchBaseKHR)load(context, "vkCmdDispatchBaseKHR"); + vkCmdSetDeviceMaskKHR = (PFN_vkCmdSetDeviceMaskKHR)load(context, "vkCmdSetDeviceMaskKHR"); + vkGetDeviceGroupPeerMemoryFeaturesKHR = (PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)load(context, "vkGetDeviceGroupPeerMemoryFeaturesKHR"); +#endif /* defined(VK_KHR_device_group) */ +#if defined(VK_KHR_display_swapchain) + vkCreateSharedSwapchainsKHR = (PFN_vkCreateSharedSwapchainsKHR)load(context, "vkCreateSharedSwapchainsKHR"); +#endif /* defined(VK_KHR_display_swapchain) */ +#if defined(VK_KHR_draw_indirect_count) + vkCmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)load(context, "vkCmdDrawIndexedIndirectCountKHR"); + vkCmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)load(context, "vkCmdDrawIndirectCountKHR"); +#endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) + vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR)load(context, "vkCmdBeginRenderingKHR"); + vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR)load(context, "vkCmdEndRenderingKHR"); +#endif /* defined(VK_KHR_dynamic_rendering) */ +#if defined(VK_KHR_dynamic_rendering_local_read) + vkCmdSetRenderingAttachmentLocationsKHR = (PFN_vkCmdSetRenderingAttachmentLocationsKHR)load(context, "vkCmdSetRenderingAttachmentLocationsKHR"); + vkCmdSetRenderingInputAttachmentIndicesKHR = (PFN_vkCmdSetRenderingInputAttachmentIndicesKHR)load(context, "vkCmdSetRenderingInputAttachmentIndicesKHR"); +#endif /* defined(VK_KHR_dynamic_rendering_local_read) */ +#if defined(VK_KHR_external_fence_fd) + vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)load(context, "vkGetFenceFdKHR"); + vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)load(context, "vkImportFenceFdKHR"); +#endif /* defined(VK_KHR_external_fence_fd) */ +#if defined(VK_KHR_external_fence_win32) + vkGetFenceWin32HandleKHR = (PFN_vkGetFenceWin32HandleKHR)load(context, "vkGetFenceWin32HandleKHR"); + vkImportFenceWin32HandleKHR = (PFN_vkImportFenceWin32HandleKHR)load(context, "vkImportFenceWin32HandleKHR"); +#endif /* defined(VK_KHR_external_fence_win32) */ +#if defined(VK_KHR_external_memory_fd) + vkGetMemoryFdKHR = (PFN_vkGetMemoryFdKHR)load(context, "vkGetMemoryFdKHR"); + vkGetMemoryFdPropertiesKHR = (PFN_vkGetMemoryFdPropertiesKHR)load(context, "vkGetMemoryFdPropertiesKHR"); +#endif /* defined(VK_KHR_external_memory_fd) */ +#if defined(VK_KHR_external_memory_win32) + vkGetMemoryWin32HandleKHR = (PFN_vkGetMemoryWin32HandleKHR)load(context, "vkGetMemoryWin32HandleKHR"); + vkGetMemoryWin32HandlePropertiesKHR = (PFN_vkGetMemoryWin32HandlePropertiesKHR)load(context, "vkGetMemoryWin32HandlePropertiesKHR"); +#endif /* defined(VK_KHR_external_memory_win32) */ +#if defined(VK_KHR_external_semaphore_fd) + vkGetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR)load(context, "vkGetSemaphoreFdKHR"); + vkImportSemaphoreFdKHR = (PFN_vkImportSemaphoreFdKHR)load(context, "vkImportSemaphoreFdKHR"); +#endif /* defined(VK_KHR_external_semaphore_fd) */ +#if defined(VK_KHR_external_semaphore_win32) + vkGetSemaphoreWin32HandleKHR = (PFN_vkGetSemaphoreWin32HandleKHR)load(context, "vkGetSemaphoreWin32HandleKHR"); + vkImportSemaphoreWin32HandleKHR = (PFN_vkImportSemaphoreWin32HandleKHR)load(context, "vkImportSemaphoreWin32HandleKHR"); +#endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) + vkCmdSetFragmentShadingRateKHR = (PFN_vkCmdSetFragmentShadingRateKHR)load(context, "vkCmdSetFragmentShadingRateKHR"); +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_memory_requirements2) + vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2KHR)load(context, "vkGetBufferMemoryRequirements2KHR"); + vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2KHR)load(context, "vkGetImageMemoryRequirements2KHR"); + vkGetImageSparseMemoryRequirements2KHR = (PFN_vkGetImageSparseMemoryRequirements2KHR)load(context, "vkGetImageSparseMemoryRequirements2KHR"); +#endif /* defined(VK_KHR_get_memory_requirements2) */ +#if defined(VK_KHR_line_rasterization) + vkCmdSetLineStippleKHR = (PFN_vkCmdSetLineStippleKHR)load(context, "vkCmdSetLineStippleKHR"); +#endif /* defined(VK_KHR_line_rasterization) */ +#if defined(VK_KHR_maintenance1) + vkTrimCommandPoolKHR = (PFN_vkTrimCommandPoolKHR)load(context, "vkTrimCommandPoolKHR"); +#endif /* defined(VK_KHR_maintenance1) */ +#if defined(VK_KHR_maintenance10) + vkCmdEndRendering2KHR = (PFN_vkCmdEndRendering2KHR)load(context, "vkCmdEndRendering2KHR"); +#endif /* defined(VK_KHR_maintenance10) */ +#if defined(VK_KHR_maintenance3) + vkGetDescriptorSetLayoutSupportKHR = (PFN_vkGetDescriptorSetLayoutSupportKHR)load(context, "vkGetDescriptorSetLayoutSupportKHR"); +#endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) + vkGetDeviceBufferMemoryRequirementsKHR = (PFN_vkGetDeviceBufferMemoryRequirementsKHR)load(context, "vkGetDeviceBufferMemoryRequirementsKHR"); + vkGetDeviceImageMemoryRequirementsKHR = (PFN_vkGetDeviceImageMemoryRequirementsKHR)load(context, "vkGetDeviceImageMemoryRequirementsKHR"); + vkGetDeviceImageSparseMemoryRequirementsKHR = (PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)load(context, "vkGetDeviceImageSparseMemoryRequirementsKHR"); +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) + vkCmdBindIndexBuffer2KHR = (PFN_vkCmdBindIndexBuffer2KHR)load(context, "vkCmdBindIndexBuffer2KHR"); + vkGetDeviceImageSubresourceLayoutKHR = (PFN_vkGetDeviceImageSubresourceLayoutKHR)load(context, "vkGetDeviceImageSubresourceLayoutKHR"); + vkGetImageSubresourceLayout2KHR = (PFN_vkGetImageSubresourceLayout2KHR)load(context, "vkGetImageSubresourceLayout2KHR"); + vkGetRenderingAreaGranularityKHR = (PFN_vkGetRenderingAreaGranularityKHR)load(context, "vkGetRenderingAreaGranularityKHR"); +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_maintenance6) + vkCmdBindDescriptorSets2KHR = (PFN_vkCmdBindDescriptorSets2KHR)load(context, "vkCmdBindDescriptorSets2KHR"); + vkCmdPushConstants2KHR = (PFN_vkCmdPushConstants2KHR)load(context, "vkCmdPushConstants2KHR"); +#endif /* defined(VK_KHR_maintenance6) */ +#if defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) + vkCmdPushDescriptorSet2KHR = (PFN_vkCmdPushDescriptorSet2KHR)load(context, "vkCmdPushDescriptorSet2KHR"); + vkCmdPushDescriptorSetWithTemplate2KHR = (PFN_vkCmdPushDescriptorSetWithTemplate2KHR)load(context, "vkCmdPushDescriptorSetWithTemplate2KHR"); +#endif /* defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) + vkCmdBindDescriptorBufferEmbeddedSamplers2EXT = (PFN_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT)load(context, "vkCmdBindDescriptorBufferEmbeddedSamplers2EXT"); + vkCmdSetDescriptorBufferOffsets2EXT = (PFN_vkCmdSetDescriptorBufferOffsets2EXT)load(context, "vkCmdSetDescriptorBufferOffsets2EXT"); +#endif /* defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_KHR_map_memory2) + vkMapMemory2KHR = (PFN_vkMapMemory2KHR)load(context, "vkMapMemory2KHR"); + vkUnmapMemory2KHR = (PFN_vkUnmapMemory2KHR)load(context, "vkUnmapMemory2KHR"); +#endif /* defined(VK_KHR_map_memory2) */ +#if defined(VK_KHR_performance_query) + vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); + vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) + vkCreatePipelineBinariesKHR = (PFN_vkCreatePipelineBinariesKHR)load(context, "vkCreatePipelineBinariesKHR"); + vkDestroyPipelineBinaryKHR = (PFN_vkDestroyPipelineBinaryKHR)load(context, "vkDestroyPipelineBinaryKHR"); + vkGetPipelineBinaryDataKHR = (PFN_vkGetPipelineBinaryDataKHR)load(context, "vkGetPipelineBinaryDataKHR"); + vkGetPipelineKeyKHR = (PFN_vkGetPipelineKeyKHR)load(context, "vkGetPipelineKeyKHR"); + vkReleaseCapturedPipelineDataKHR = (PFN_vkReleaseCapturedPipelineDataKHR)load(context, "vkReleaseCapturedPipelineDataKHR"); +#endif /* defined(VK_KHR_pipeline_binary) */ +#if defined(VK_KHR_pipeline_executable_properties) + vkGetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)load(context, "vkGetPipelineExecutableInternalRepresentationsKHR"); + vkGetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)load(context, "vkGetPipelineExecutablePropertiesKHR"); + vkGetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR)load(context, "vkGetPipelineExecutableStatisticsKHR"); +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) + vkWaitForPresentKHR = (PFN_vkWaitForPresentKHR)load(context, "vkWaitForPresentKHR"); +#endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) + vkWaitForPresent2KHR = (PFN_vkWaitForPresent2KHR)load(context, "vkWaitForPresent2KHR"); +#endif /* defined(VK_KHR_present_wait2) */ +#if defined(VK_KHR_push_descriptor) + vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)load(context, "vkCmdPushDescriptorSetKHR"); +#endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) + vkCmdTraceRaysIndirect2KHR = (PFN_vkCmdTraceRaysIndirect2KHR)load(context, "vkCmdTraceRaysIndirect2KHR"); +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_ray_tracing_pipeline) + vkCmdSetRayTracingPipelineStackSizeKHR = (PFN_vkCmdSetRayTracingPipelineStackSizeKHR)load(context, "vkCmdSetRayTracingPipelineStackSizeKHR"); + vkCmdTraceRaysIndirectKHR = (PFN_vkCmdTraceRaysIndirectKHR)load(context, "vkCmdTraceRaysIndirectKHR"); + vkCmdTraceRaysKHR = (PFN_vkCmdTraceRaysKHR)load(context, "vkCmdTraceRaysKHR"); + vkCreateRayTracingPipelinesKHR = (PFN_vkCreateRayTracingPipelinesKHR)load(context, "vkCreateRayTracingPipelinesKHR"); + vkGetRayTracingCaptureReplayShaderGroupHandlesKHR = (PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)load(context, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR"); + vkGetRayTracingShaderGroupHandlesKHR = (PFN_vkGetRayTracingShaderGroupHandlesKHR)load(context, "vkGetRayTracingShaderGroupHandlesKHR"); + vkGetRayTracingShaderGroupStackSizeKHR = (PFN_vkGetRayTracingShaderGroupStackSizeKHR)load(context, "vkGetRayTracingShaderGroupStackSizeKHR"); +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_sampler_ycbcr_conversion) + vkCreateSamplerYcbcrConversionKHR = (PFN_vkCreateSamplerYcbcrConversionKHR)load(context, "vkCreateSamplerYcbcrConversionKHR"); + vkDestroySamplerYcbcrConversionKHR = (PFN_vkDestroySamplerYcbcrConversionKHR)load(context, "vkDestroySamplerYcbcrConversionKHR"); +#endif /* defined(VK_KHR_sampler_ycbcr_conversion) */ +#if defined(VK_KHR_shared_presentable_image) + vkGetSwapchainStatusKHR = (PFN_vkGetSwapchainStatusKHR)load(context, "vkGetSwapchainStatusKHR"); +#endif /* defined(VK_KHR_shared_presentable_image) */ +#if defined(VK_KHR_swapchain) + vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)load(context, "vkAcquireNextImageKHR"); + vkCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)load(context, "vkCreateSwapchainKHR"); + vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)load(context, "vkDestroySwapchainKHR"); + vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)load(context, "vkGetSwapchainImagesKHR"); + vkQueuePresentKHR = (PFN_vkQueuePresentKHR)load(context, "vkQueuePresentKHR"); +#endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) + vkReleaseSwapchainImagesKHR = (PFN_vkReleaseSwapchainImagesKHR)load(context, "vkReleaseSwapchainImagesKHR"); +#endif /* defined(VK_KHR_swapchain_maintenance1) */ +#if defined(VK_KHR_synchronization2) + vkCmdPipelineBarrier2KHR = (PFN_vkCmdPipelineBarrier2KHR)load(context, "vkCmdPipelineBarrier2KHR"); + vkCmdResetEvent2KHR = (PFN_vkCmdResetEvent2KHR)load(context, "vkCmdResetEvent2KHR"); + vkCmdSetEvent2KHR = (PFN_vkCmdSetEvent2KHR)load(context, "vkCmdSetEvent2KHR"); + vkCmdWaitEvents2KHR = (PFN_vkCmdWaitEvents2KHR)load(context, "vkCmdWaitEvents2KHR"); + vkCmdWriteTimestamp2KHR = (PFN_vkCmdWriteTimestamp2KHR)load(context, "vkCmdWriteTimestamp2KHR"); + vkQueueSubmit2KHR = (PFN_vkQueueSubmit2KHR)load(context, "vkQueueSubmit2KHR"); +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_timeline_semaphore) + vkGetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)load(context, "vkGetSemaphoreCounterValueKHR"); + vkSignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)load(context, "vkSignalSemaphoreKHR"); + vkWaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR)load(context, "vkWaitSemaphoresKHR"); +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) + vkCmdDecodeVideoKHR = (PFN_vkCmdDecodeVideoKHR)load(context, "vkCmdDecodeVideoKHR"); +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) + vkCmdEncodeVideoKHR = (PFN_vkCmdEncodeVideoKHR)load(context, "vkCmdEncodeVideoKHR"); + vkGetEncodedVideoSessionParametersKHR = (PFN_vkGetEncodedVideoSessionParametersKHR)load(context, "vkGetEncodedVideoSessionParametersKHR"); +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) + vkBindVideoSessionMemoryKHR = (PFN_vkBindVideoSessionMemoryKHR)load(context, "vkBindVideoSessionMemoryKHR"); + vkCmdBeginVideoCodingKHR = (PFN_vkCmdBeginVideoCodingKHR)load(context, "vkCmdBeginVideoCodingKHR"); + vkCmdControlVideoCodingKHR = (PFN_vkCmdControlVideoCodingKHR)load(context, "vkCmdControlVideoCodingKHR"); + vkCmdEndVideoCodingKHR = (PFN_vkCmdEndVideoCodingKHR)load(context, "vkCmdEndVideoCodingKHR"); + vkCreateVideoSessionKHR = (PFN_vkCreateVideoSessionKHR)load(context, "vkCreateVideoSessionKHR"); + vkCreateVideoSessionParametersKHR = (PFN_vkCreateVideoSessionParametersKHR)load(context, "vkCreateVideoSessionParametersKHR"); + vkDestroyVideoSessionKHR = (PFN_vkDestroyVideoSessionKHR)load(context, "vkDestroyVideoSessionKHR"); + vkDestroyVideoSessionParametersKHR = (PFN_vkDestroyVideoSessionParametersKHR)load(context, "vkDestroyVideoSessionParametersKHR"); + vkGetVideoSessionMemoryRequirementsKHR = (PFN_vkGetVideoSessionMemoryRequirementsKHR)load(context, "vkGetVideoSessionMemoryRequirementsKHR"); + vkUpdateVideoSessionParametersKHR = (PFN_vkUpdateVideoSessionParametersKHR)load(context, "vkUpdateVideoSessionParametersKHR"); +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_NVX_binary_import) + vkCmdCuLaunchKernelNVX = (PFN_vkCmdCuLaunchKernelNVX)load(context, "vkCmdCuLaunchKernelNVX"); + vkCreateCuFunctionNVX = (PFN_vkCreateCuFunctionNVX)load(context, "vkCreateCuFunctionNVX"); + vkCreateCuModuleNVX = (PFN_vkCreateCuModuleNVX)load(context, "vkCreateCuModuleNVX"); + vkDestroyCuFunctionNVX = (PFN_vkDestroyCuFunctionNVX)load(context, "vkDestroyCuFunctionNVX"); + vkDestroyCuModuleNVX = (PFN_vkDestroyCuModuleNVX)load(context, "vkDestroyCuModuleNVX"); +#endif /* defined(VK_NVX_binary_import) */ +#if defined(VK_NVX_image_view_handle) + vkGetImageViewHandleNVX = (PFN_vkGetImageViewHandleNVX)load(context, "vkGetImageViewHandleNVX"); +#endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 + vkGetImageViewHandle64NVX = (PFN_vkGetImageViewHandle64NVX)load(context, "vkGetImageViewHandle64NVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 + vkGetImageViewAddressNVX = (PFN_vkGetImageViewAddressNVX)load(context, "vkGetImageViewAddressNVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 + vkGetDeviceCombinedImageSamplerIndexNVX = (PFN_vkGetDeviceCombinedImageSamplerIndexNVX)load(context, "vkGetDeviceCombinedImageSamplerIndexNVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 */ +#if defined(VK_NV_clip_space_w_scaling) + vkCmdSetViewportWScalingNV = (PFN_vkCmdSetViewportWScalingNV)load(context, "vkCmdSetViewportWScalingNV"); +#endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_cluster_acceleration_structure) + vkCmdBuildClusterAccelerationStructureIndirectNV = (PFN_vkCmdBuildClusterAccelerationStructureIndirectNV)load(context, "vkCmdBuildClusterAccelerationStructureIndirectNV"); + vkGetClusterAccelerationStructureBuildSizesNV = (PFN_vkGetClusterAccelerationStructureBuildSizesNV)load(context, "vkGetClusterAccelerationStructureBuildSizesNV"); +#endif /* defined(VK_NV_cluster_acceleration_structure) */ +#if defined(VK_NV_compute_occupancy_priority) + vkCmdSetComputeOccupancyPriorityNV = (PFN_vkCmdSetComputeOccupancyPriorityNV)load(context, "vkCmdSetComputeOccupancyPriorityNV"); +#endif /* defined(VK_NV_compute_occupancy_priority) */ +#if defined(VK_NV_cooperative_vector) + vkCmdConvertCooperativeVectorMatrixNV = (PFN_vkCmdConvertCooperativeVectorMatrixNV)load(context, "vkCmdConvertCooperativeVectorMatrixNV"); + vkConvertCooperativeVectorMatrixNV = (PFN_vkConvertCooperativeVectorMatrixNV)load(context, "vkConvertCooperativeVectorMatrixNV"); +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_copy_memory_indirect) + vkCmdCopyMemoryIndirectNV = (PFN_vkCmdCopyMemoryIndirectNV)load(context, "vkCmdCopyMemoryIndirectNV"); + vkCmdCopyMemoryToImageIndirectNV = (PFN_vkCmdCopyMemoryToImageIndirectNV)load(context, "vkCmdCopyMemoryToImageIndirectNV"); +#endif /* defined(VK_NV_copy_memory_indirect) */ +#if defined(VK_NV_cuda_kernel_launch) + vkCmdCudaLaunchKernelNV = (PFN_vkCmdCudaLaunchKernelNV)load(context, "vkCmdCudaLaunchKernelNV"); + vkCreateCudaFunctionNV = (PFN_vkCreateCudaFunctionNV)load(context, "vkCreateCudaFunctionNV"); + vkCreateCudaModuleNV = (PFN_vkCreateCudaModuleNV)load(context, "vkCreateCudaModuleNV"); + vkDestroyCudaFunctionNV = (PFN_vkDestroyCudaFunctionNV)load(context, "vkDestroyCudaFunctionNV"); + vkDestroyCudaModuleNV = (PFN_vkDestroyCudaModuleNV)load(context, "vkDestroyCudaModuleNV"); + vkGetCudaModuleCacheNV = (PFN_vkGetCudaModuleCacheNV)load(context, "vkGetCudaModuleCacheNV"); +#endif /* defined(VK_NV_cuda_kernel_launch) */ +#if defined(VK_NV_device_diagnostic_checkpoints) + vkCmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)load(context, "vkCmdSetCheckpointNV"); + vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)load(context, "vkGetQueueCheckpointDataNV"); +#endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + vkGetQueueCheckpointData2NV = (PFN_vkGetQueueCheckpointData2NV)load(context, "vkGetQueueCheckpointData2NV"); +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_NV_device_generated_commands) + vkCmdBindPipelineShaderGroupNV = (PFN_vkCmdBindPipelineShaderGroupNV)load(context, "vkCmdBindPipelineShaderGroupNV"); + vkCmdExecuteGeneratedCommandsNV = (PFN_vkCmdExecuteGeneratedCommandsNV)load(context, "vkCmdExecuteGeneratedCommandsNV"); + vkCmdPreprocessGeneratedCommandsNV = (PFN_vkCmdPreprocessGeneratedCommandsNV)load(context, "vkCmdPreprocessGeneratedCommandsNV"); + vkCreateIndirectCommandsLayoutNV = (PFN_vkCreateIndirectCommandsLayoutNV)load(context, "vkCreateIndirectCommandsLayoutNV"); + vkDestroyIndirectCommandsLayoutNV = (PFN_vkDestroyIndirectCommandsLayoutNV)load(context, "vkDestroyIndirectCommandsLayoutNV"); + vkGetGeneratedCommandsMemoryRequirementsNV = (PFN_vkGetGeneratedCommandsMemoryRequirementsNV)load(context, "vkGetGeneratedCommandsMemoryRequirementsNV"); +#endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) + vkCmdUpdatePipelineIndirectBufferNV = (PFN_vkCmdUpdatePipelineIndirectBufferNV)load(context, "vkCmdUpdatePipelineIndirectBufferNV"); + vkGetPipelineIndirectDeviceAddressNV = (PFN_vkGetPipelineIndirectDeviceAddressNV)load(context, "vkGetPipelineIndirectDeviceAddressNV"); + vkGetPipelineIndirectMemoryRequirementsNV = (PFN_vkGetPipelineIndirectMemoryRequirementsNV)load(context, "vkGetPipelineIndirectMemoryRequirementsNV"); +#endif /* defined(VK_NV_device_generated_commands_compute) */ +#if defined(VK_NV_external_compute_queue) + vkCreateExternalComputeQueueNV = (PFN_vkCreateExternalComputeQueueNV)load(context, "vkCreateExternalComputeQueueNV"); + vkDestroyExternalComputeQueueNV = (PFN_vkDestroyExternalComputeQueueNV)load(context, "vkDestroyExternalComputeQueueNV"); + vkGetExternalComputeQueueDataNV = (PFN_vkGetExternalComputeQueueDataNV)load(context, "vkGetExternalComputeQueueDataNV"); +#endif /* defined(VK_NV_external_compute_queue) */ +#if defined(VK_NV_external_memory_rdma) + vkGetMemoryRemoteAddressNV = (PFN_vkGetMemoryRemoteAddressNV)load(context, "vkGetMemoryRemoteAddressNV"); +#endif /* defined(VK_NV_external_memory_rdma) */ +#if defined(VK_NV_external_memory_win32) + vkGetMemoryWin32HandleNV = (PFN_vkGetMemoryWin32HandleNV)load(context, "vkGetMemoryWin32HandleNV"); +#endif /* defined(VK_NV_external_memory_win32) */ +#if defined(VK_NV_fragment_shading_rate_enums) + vkCmdSetFragmentShadingRateEnumNV = (PFN_vkCmdSetFragmentShadingRateEnumNV)load(context, "vkCmdSetFragmentShadingRateEnumNV"); +#endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) + vkGetLatencyTimingsNV = (PFN_vkGetLatencyTimingsNV)load(context, "vkGetLatencyTimingsNV"); + vkLatencySleepNV = (PFN_vkLatencySleepNV)load(context, "vkLatencySleepNV"); + vkQueueNotifyOutOfBandNV = (PFN_vkQueueNotifyOutOfBandNV)load(context, "vkQueueNotifyOutOfBandNV"); + vkSetLatencyMarkerNV = (PFN_vkSetLatencyMarkerNV)load(context, "vkSetLatencyMarkerNV"); + vkSetLatencySleepModeNV = (PFN_vkSetLatencySleepModeNV)load(context, "vkSetLatencySleepModeNV"); +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) + vkCmdDecompressMemoryIndirectCountNV = (PFN_vkCmdDecompressMemoryIndirectCountNV)load(context, "vkCmdDecompressMemoryIndirectCountNV"); + vkCmdDecompressMemoryNV = (PFN_vkCmdDecompressMemoryNV)load(context, "vkCmdDecompressMemoryNV"); +#endif /* defined(VK_NV_memory_decompression) */ +#if defined(VK_NV_mesh_shader) + vkCmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)load(context, "vkCmdDrawMeshTasksIndirectNV"); + vkCmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV)load(context, "vkCmdDrawMeshTasksNV"); +#endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_NV_optical_flow) + vkBindOpticalFlowSessionImageNV = (PFN_vkBindOpticalFlowSessionImageNV)load(context, "vkBindOpticalFlowSessionImageNV"); + vkCmdOpticalFlowExecuteNV = (PFN_vkCmdOpticalFlowExecuteNV)load(context, "vkCmdOpticalFlowExecuteNV"); + vkCreateOpticalFlowSessionNV = (PFN_vkCreateOpticalFlowSessionNV)load(context, "vkCreateOpticalFlowSessionNV"); + vkDestroyOpticalFlowSessionNV = (PFN_vkDestroyOpticalFlowSessionNV)load(context, "vkDestroyOpticalFlowSessionNV"); +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) + vkCmdBuildPartitionedAccelerationStructuresNV = (PFN_vkCmdBuildPartitionedAccelerationStructuresNV)load(context, "vkCmdBuildPartitionedAccelerationStructuresNV"); + vkGetPartitionedAccelerationStructuresBuildSizesNV = (PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV)load(context, "vkGetPartitionedAccelerationStructuresBuildSizesNV"); +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ +#if defined(VK_NV_ray_tracing) + vkBindAccelerationStructureMemoryNV = (PFN_vkBindAccelerationStructureMemoryNV)load(context, "vkBindAccelerationStructureMemoryNV"); + vkCmdBuildAccelerationStructureNV = (PFN_vkCmdBuildAccelerationStructureNV)load(context, "vkCmdBuildAccelerationStructureNV"); + vkCmdCopyAccelerationStructureNV = (PFN_vkCmdCopyAccelerationStructureNV)load(context, "vkCmdCopyAccelerationStructureNV"); + vkCmdTraceRaysNV = (PFN_vkCmdTraceRaysNV)load(context, "vkCmdTraceRaysNV"); + vkCmdWriteAccelerationStructuresPropertiesNV = (PFN_vkCmdWriteAccelerationStructuresPropertiesNV)load(context, "vkCmdWriteAccelerationStructuresPropertiesNV"); + vkCompileDeferredNV = (PFN_vkCompileDeferredNV)load(context, "vkCompileDeferredNV"); + vkCreateAccelerationStructureNV = (PFN_vkCreateAccelerationStructureNV)load(context, "vkCreateAccelerationStructureNV"); + vkCreateRayTracingPipelinesNV = (PFN_vkCreateRayTracingPipelinesNV)load(context, "vkCreateRayTracingPipelinesNV"); + vkDestroyAccelerationStructureNV = (PFN_vkDestroyAccelerationStructureNV)load(context, "vkDestroyAccelerationStructureNV"); + vkGetAccelerationStructureHandleNV = (PFN_vkGetAccelerationStructureHandleNV)load(context, "vkGetAccelerationStructureHandleNV"); + vkGetAccelerationStructureMemoryRequirementsNV = (PFN_vkGetAccelerationStructureMemoryRequirementsNV)load(context, "vkGetAccelerationStructureMemoryRequirementsNV"); + vkGetRayTracingShaderGroupHandlesNV = (PFN_vkGetRayTracingShaderGroupHandlesNV)load(context, "vkGetRayTracingShaderGroupHandlesNV"); +#endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 + vkCmdSetExclusiveScissorEnableNV = (PFN_vkCmdSetExclusiveScissorEnableNV)load(context, "vkCmdSetExclusiveScissorEnableNV"); +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ +#if defined(VK_NV_scissor_exclusive) + vkCmdSetExclusiveScissorNV = (PFN_vkCmdSetExclusiveScissorNV)load(context, "vkCmdSetExclusiveScissorNV"); +#endif /* defined(VK_NV_scissor_exclusive) */ +#if defined(VK_NV_shading_rate_image) + vkCmdBindShadingRateImageNV = (PFN_vkCmdBindShadingRateImageNV)load(context, "vkCmdBindShadingRateImageNV"); + vkCmdSetCoarseSampleOrderNV = (PFN_vkCmdSetCoarseSampleOrderNV)load(context, "vkCmdSetCoarseSampleOrderNV"); + vkCmdSetViewportShadingRatePaletteNV = (PFN_vkCmdSetViewportShadingRatePaletteNV)load(context, "vkCmdSetViewportShadingRatePaletteNV"); +#endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_OHOS_external_memory) + vkGetMemoryNativeBufferOHOS = (PFN_vkGetMemoryNativeBufferOHOS)load(context, "vkGetMemoryNativeBufferOHOS"); + vkGetNativeBufferPropertiesOHOS = (PFN_vkGetNativeBufferPropertiesOHOS)load(context, "vkGetNativeBufferPropertiesOHOS"); +#endif /* defined(VK_OHOS_external_memory) */ +#if defined(VK_QCOM_queue_perf_hint) + vkQueueSetPerfHintQCOM = (PFN_vkQueueSetPerfHintQCOM)load(context, "vkQueueSetPerfHintQCOM"); +#endif /* defined(VK_QCOM_queue_perf_hint) */ +#if defined(VK_QCOM_tile_memory_heap) + vkCmdBindTileMemoryQCOM = (PFN_vkCmdBindTileMemoryQCOM)load(context, "vkCmdBindTileMemoryQCOM"); +#endif /* defined(VK_QCOM_tile_memory_heap) */ +#if defined(VK_QCOM_tile_properties) + vkGetDynamicRenderingTilePropertiesQCOM = (PFN_vkGetDynamicRenderingTilePropertiesQCOM)load(context, "vkGetDynamicRenderingTilePropertiesQCOM"); + vkGetFramebufferTilePropertiesQCOM = (PFN_vkGetFramebufferTilePropertiesQCOM)load(context, "vkGetFramebufferTilePropertiesQCOM"); +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) + vkCmdBeginPerTileExecutionQCOM = (PFN_vkCmdBeginPerTileExecutionQCOM)load(context, "vkCmdBeginPerTileExecutionQCOM"); + vkCmdDispatchTileQCOM = (PFN_vkCmdDispatchTileQCOM)load(context, "vkCmdDispatchTileQCOM"); + vkCmdEndPerTileExecutionQCOM = (PFN_vkCmdEndPerTileExecutionQCOM)load(context, "vkCmdEndPerTileExecutionQCOM"); +#endif /* defined(VK_QCOM_tile_shading) */ +#if defined(VK_QNX_external_memory_screen_buffer) + vkGetScreenBufferPropertiesQNX = (PFN_vkGetScreenBufferPropertiesQNX)load(context, "vkGetScreenBufferPropertiesQNX"); +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) + vkGetDescriptorSetHostMappingVALVE = (PFN_vkGetDescriptorSetHostMappingVALVE)load(context, "vkGetDescriptorSetHostMappingVALVE"); + vkGetDescriptorSetLayoutHostMappingInfoVALVE = (PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)load(context, "vkGetDescriptorSetLayoutHostMappingInfoVALVE"); +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) + vkCmdSetDepthClampRangeEXT = (PFN_vkCmdSetDepthClampRangeEXT)load(context, "vkCmdSetDepthClampRangeEXT"); +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) + vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); + vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); + vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); + vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); + vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); + vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); + vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); + vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); + vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); + vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); + vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); + vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) + vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); + vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); + vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); + vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); + vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) + vkCmdSetAlphaToCoverageEnableEXT = (PFN_vkCmdSetAlphaToCoverageEnableEXT)load(context, "vkCmdSetAlphaToCoverageEnableEXT"); + vkCmdSetAlphaToOneEnableEXT = (PFN_vkCmdSetAlphaToOneEnableEXT)load(context, "vkCmdSetAlphaToOneEnableEXT"); + vkCmdSetColorBlendEnableEXT = (PFN_vkCmdSetColorBlendEnableEXT)load(context, "vkCmdSetColorBlendEnableEXT"); + vkCmdSetColorBlendEquationEXT = (PFN_vkCmdSetColorBlendEquationEXT)load(context, "vkCmdSetColorBlendEquationEXT"); + vkCmdSetColorWriteMaskEXT = (PFN_vkCmdSetColorWriteMaskEXT)load(context, "vkCmdSetColorWriteMaskEXT"); + vkCmdSetDepthClampEnableEXT = (PFN_vkCmdSetDepthClampEnableEXT)load(context, "vkCmdSetDepthClampEnableEXT"); + vkCmdSetLogicOpEnableEXT = (PFN_vkCmdSetLogicOpEnableEXT)load(context, "vkCmdSetLogicOpEnableEXT"); + vkCmdSetPolygonModeEXT = (PFN_vkCmdSetPolygonModeEXT)load(context, "vkCmdSetPolygonModeEXT"); + vkCmdSetRasterizationSamplesEXT = (PFN_vkCmdSetRasterizationSamplesEXT)load(context, "vkCmdSetRasterizationSamplesEXT"); + vkCmdSetSampleMaskEXT = (PFN_vkCmdSetSampleMaskEXT)load(context, "vkCmdSetSampleMaskEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) + vkCmdSetTessellationDomainOriginEXT = (PFN_vkCmdSetTessellationDomainOriginEXT)load(context, "vkCmdSetTessellationDomainOriginEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) + vkCmdSetRasterizationStreamEXT = (PFN_vkCmdSetRasterizationStreamEXT)load(context, "vkCmdSetRasterizationStreamEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) + vkCmdSetConservativeRasterizationModeEXT = (PFN_vkCmdSetConservativeRasterizationModeEXT)load(context, "vkCmdSetConservativeRasterizationModeEXT"); + vkCmdSetExtraPrimitiveOverestimationSizeEXT = (PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)load(context, "vkCmdSetExtraPrimitiveOverestimationSizeEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) + vkCmdSetDepthClipEnableEXT = (PFN_vkCmdSetDepthClipEnableEXT)load(context, "vkCmdSetDepthClipEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) + vkCmdSetSampleLocationsEnableEXT = (PFN_vkCmdSetSampleLocationsEnableEXT)load(context, "vkCmdSetSampleLocationsEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) + vkCmdSetColorBlendAdvancedEXT = (PFN_vkCmdSetColorBlendAdvancedEXT)load(context, "vkCmdSetColorBlendAdvancedEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) + vkCmdSetProvokingVertexModeEXT = (PFN_vkCmdSetProvokingVertexModeEXT)load(context, "vkCmdSetProvokingVertexModeEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) + vkCmdSetLineRasterizationModeEXT = (PFN_vkCmdSetLineRasterizationModeEXT)load(context, "vkCmdSetLineRasterizationModeEXT"); + vkCmdSetLineStippleEnableEXT = (PFN_vkCmdSetLineStippleEnableEXT)load(context, "vkCmdSetLineStippleEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) + vkCmdSetDepthClipNegativeOneToOneEXT = (PFN_vkCmdSetDepthClipNegativeOneToOneEXT)load(context, "vkCmdSetDepthClipNegativeOneToOneEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) + vkCmdSetViewportWScalingEnableNV = (PFN_vkCmdSetViewportWScalingEnableNV)load(context, "vkCmdSetViewportWScalingEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) + vkCmdSetViewportSwizzleNV = (PFN_vkCmdSetViewportSwizzleNV)load(context, "vkCmdSetViewportSwizzleNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) + vkCmdSetCoverageToColorEnableNV = (PFN_vkCmdSetCoverageToColorEnableNV)load(context, "vkCmdSetCoverageToColorEnableNV"); + vkCmdSetCoverageToColorLocationNV = (PFN_vkCmdSetCoverageToColorLocationNV)load(context, "vkCmdSetCoverageToColorLocationNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) + vkCmdSetCoverageModulationModeNV = (PFN_vkCmdSetCoverageModulationModeNV)load(context, "vkCmdSetCoverageModulationModeNV"); + vkCmdSetCoverageModulationTableEnableNV = (PFN_vkCmdSetCoverageModulationTableEnableNV)load(context, "vkCmdSetCoverageModulationTableEnableNV"); + vkCmdSetCoverageModulationTableNV = (PFN_vkCmdSetCoverageModulationTableNV)load(context, "vkCmdSetCoverageModulationTableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) + vkCmdSetShadingRateImageEnableNV = (PFN_vkCmdSetShadingRateImageEnableNV)load(context, "vkCmdSetShadingRateImageEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) + vkCmdSetRepresentativeFragmentTestEnableNV = (PFN_vkCmdSetRepresentativeFragmentTestEnableNV)load(context, "vkCmdSetRepresentativeFragmentTestEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) + vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) + vkGetImageSubresourceLayout2EXT = (PFN_vkGetImageSubresourceLayout2EXT)load(context, "vkGetImageSubresourceLayout2EXT"); +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) + vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) + vkCmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)load(context, "vkCmdPushDescriptorSetWithTemplateKHR"); +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) + vkGetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR)load(context, "vkGetDeviceGroupPresentCapabilitiesKHR"); + vkGetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR)load(context, "vkGetDeviceGroupSurfacePresentModesKHR"); +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) + vkAcquireNextImage2KHR = (PFN_vkAcquireNextImage2KHR)load(context, "vkAcquireNextImage2KHR"); +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ + /* VOLK_GENERATE_LOAD_DEVICE */ +} + +static void volkGenLoadInstanceTable(struct VolkInstanceTable* table, void* context, PFN_vkVoidFunction (*load)(void*, const char*)) +{ + /* VOLK_GENERATE_LOAD_INSTANCE_TABLE */ +#if defined(VK_VERSION_1_0) + table->vkCreateDevice = (PFN_vkCreateDevice)load(context, "vkCreateDevice"); + table->vkDestroyInstance = (PFN_vkDestroyInstance)load(context, "vkDestroyInstance"); + table->vkEnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties)load(context, "vkEnumerateDeviceExtensionProperties"); + table->vkEnumerateDeviceLayerProperties = (PFN_vkEnumerateDeviceLayerProperties)load(context, "vkEnumerateDeviceLayerProperties"); + table->vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)load(context, "vkEnumeratePhysicalDevices"); + table->vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)load(context, "vkGetDeviceProcAddr"); + table->vkGetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures)load(context, "vkGetPhysicalDeviceFeatures"); + table->vkGetPhysicalDeviceFormatProperties = (PFN_vkGetPhysicalDeviceFormatProperties)load(context, "vkGetPhysicalDeviceFormatProperties"); + table->vkGetPhysicalDeviceImageFormatProperties = (PFN_vkGetPhysicalDeviceImageFormatProperties)load(context, "vkGetPhysicalDeviceImageFormatProperties"); + table->vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)load(context, "vkGetPhysicalDeviceMemoryProperties"); + table->vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)load(context, "vkGetPhysicalDeviceProperties"); + table->vkGetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties)load(context, "vkGetPhysicalDeviceQueueFamilyProperties"); + table->vkGetPhysicalDeviceSparseImageFormatProperties = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties)load(context, "vkGetPhysicalDeviceSparseImageFormatProperties"); +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) + table->vkEnumeratePhysicalDeviceGroups = (PFN_vkEnumeratePhysicalDeviceGroups)load(context, "vkEnumeratePhysicalDeviceGroups"); + table->vkGetPhysicalDeviceExternalBufferProperties = (PFN_vkGetPhysicalDeviceExternalBufferProperties)load(context, "vkGetPhysicalDeviceExternalBufferProperties"); + table->vkGetPhysicalDeviceExternalFenceProperties = (PFN_vkGetPhysicalDeviceExternalFenceProperties)load(context, "vkGetPhysicalDeviceExternalFenceProperties"); + table->vkGetPhysicalDeviceExternalSemaphoreProperties = (PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)load(context, "vkGetPhysicalDeviceExternalSemaphoreProperties"); + table->vkGetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2)load(context, "vkGetPhysicalDeviceFeatures2"); + table->vkGetPhysicalDeviceFormatProperties2 = (PFN_vkGetPhysicalDeviceFormatProperties2)load(context, "vkGetPhysicalDeviceFormatProperties2"); + table->vkGetPhysicalDeviceImageFormatProperties2 = (PFN_vkGetPhysicalDeviceImageFormatProperties2)load(context, "vkGetPhysicalDeviceImageFormatProperties2"); + table->vkGetPhysicalDeviceMemoryProperties2 = (PFN_vkGetPhysicalDeviceMemoryProperties2)load(context, "vkGetPhysicalDeviceMemoryProperties2"); + table->vkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2)load(context, "vkGetPhysicalDeviceProperties2"); + table->vkGetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2)load(context, "vkGetPhysicalDeviceQueueFamilyProperties2"); + table->vkGetPhysicalDeviceSparseImageFormatProperties2 = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)load(context, "vkGetPhysicalDeviceSparseImageFormatProperties2"); +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_3) + table->vkGetPhysicalDeviceToolProperties = (PFN_vkGetPhysicalDeviceToolProperties)load(context, "vkGetPhysicalDeviceToolProperties"); +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_ARM_data_graph) + table->vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM"); + table->vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM"); +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_data_graph_optical_flow) + table->vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM"); +#endif /* defined(VK_ARM_data_graph_optical_flow) */ +#if defined(VK_ARM_performance_counters_by_region) + table->vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM = (PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM)load(context, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM"); +#endif /* defined(VK_ARM_performance_counters_by_region) */ +#if defined(VK_ARM_shader_instrumentation) + table->vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM = (PFN_vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM)load(context, "vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM"); +#endif /* defined(VK_ARM_shader_instrumentation) */ +#if defined(VK_ARM_tensors) + table->vkGetPhysicalDeviceExternalTensorPropertiesARM = (PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM)load(context, "vkGetPhysicalDeviceExternalTensorPropertiesARM"); +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_EXT_acquire_drm_display) + table->vkAcquireDrmDisplayEXT = (PFN_vkAcquireDrmDisplayEXT)load(context, "vkAcquireDrmDisplayEXT"); + table->vkGetDrmDisplayEXT = (PFN_vkGetDrmDisplayEXT)load(context, "vkGetDrmDisplayEXT"); +#endif /* defined(VK_EXT_acquire_drm_display) */ +#if defined(VK_EXT_acquire_xlib_display) + table->vkAcquireXlibDisplayEXT = (PFN_vkAcquireXlibDisplayEXT)load(context, "vkAcquireXlibDisplayEXT"); + table->vkGetRandROutputDisplayEXT = (PFN_vkGetRandROutputDisplayEXT)load(context, "vkGetRandROutputDisplayEXT"); +#endif /* defined(VK_EXT_acquire_xlib_display) */ +#if defined(VK_EXT_calibrated_timestamps) + table->vkGetPhysicalDeviceCalibrateableTimeDomainsEXT = (PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)load(context, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT"); +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_debug_report) + table->vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)load(context, "vkCreateDebugReportCallbackEXT"); + table->vkDebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)load(context, "vkDebugReportMessageEXT"); + table->vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)load(context, "vkDestroyDebugReportCallbackEXT"); +#endif /* defined(VK_EXT_debug_report) */ +#if defined(VK_EXT_debug_utils) + table->vkCmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)load(context, "vkCmdBeginDebugUtilsLabelEXT"); + table->vkCmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)load(context, "vkCmdEndDebugUtilsLabelEXT"); + table->vkCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)load(context, "vkCmdInsertDebugUtilsLabelEXT"); + table->vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)load(context, "vkCreateDebugUtilsMessengerEXT"); + table->vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)load(context, "vkDestroyDebugUtilsMessengerEXT"); + table->vkQueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT)load(context, "vkQueueBeginDebugUtilsLabelEXT"); + table->vkQueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT)load(context, "vkQueueEndDebugUtilsLabelEXT"); + table->vkQueueInsertDebugUtilsLabelEXT = (PFN_vkQueueInsertDebugUtilsLabelEXT)load(context, "vkQueueInsertDebugUtilsLabelEXT"); + table->vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)load(context, "vkSetDebugUtilsObjectNameEXT"); + table->vkSetDebugUtilsObjectTagEXT = (PFN_vkSetDebugUtilsObjectTagEXT)load(context, "vkSetDebugUtilsObjectTagEXT"); + table->vkSubmitDebugUtilsMessageEXT = (PFN_vkSubmitDebugUtilsMessageEXT)load(context, "vkSubmitDebugUtilsMessageEXT"); +#endif /* defined(VK_EXT_debug_utils) */ +#if defined(VK_EXT_descriptor_heap) + table->vkGetPhysicalDeviceDescriptorSizeEXT = (PFN_vkGetPhysicalDeviceDescriptorSizeEXT)load(context, "vkGetPhysicalDeviceDescriptorSizeEXT"); +#endif /* defined(VK_EXT_descriptor_heap) */ +#if defined(VK_EXT_direct_mode_display) + table->vkReleaseDisplayEXT = (PFN_vkReleaseDisplayEXT)load(context, "vkReleaseDisplayEXT"); +#endif /* defined(VK_EXT_direct_mode_display) */ +#if defined(VK_EXT_directfb_surface) + table->vkCreateDirectFBSurfaceEXT = (PFN_vkCreateDirectFBSurfaceEXT)load(context, "vkCreateDirectFBSurfaceEXT"); + table->vkGetPhysicalDeviceDirectFBPresentationSupportEXT = (PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT)load(context, "vkGetPhysicalDeviceDirectFBPresentationSupportEXT"); +#endif /* defined(VK_EXT_directfb_surface) */ +#if defined(VK_EXT_display_surface_counter) + table->vkGetPhysicalDeviceSurfaceCapabilities2EXT = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)load(context, "vkGetPhysicalDeviceSurfaceCapabilities2EXT"); +#endif /* defined(VK_EXT_display_surface_counter) */ +#if defined(VK_EXT_full_screen_exclusive) + table->vkGetPhysicalDeviceSurfacePresentModes2EXT = (PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)load(context, "vkGetPhysicalDeviceSurfacePresentModes2EXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_headless_surface) + table->vkCreateHeadlessSurfaceEXT = (PFN_vkCreateHeadlessSurfaceEXT)load(context, "vkCreateHeadlessSurfaceEXT"); +#endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_metal_surface) + table->vkCreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT)load(context, "vkCreateMetalSurfaceEXT"); +#endif /* defined(VK_EXT_metal_surface) */ +#if defined(VK_EXT_sample_locations) + table->vkGetPhysicalDeviceMultisamplePropertiesEXT = (PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)load(context, "vkGetPhysicalDeviceMultisamplePropertiesEXT"); +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_tooling_info) + table->vkGetPhysicalDeviceToolPropertiesEXT = (PFN_vkGetPhysicalDeviceToolPropertiesEXT)load(context, "vkGetPhysicalDeviceToolPropertiesEXT"); +#endif /* defined(VK_EXT_tooling_info) */ +#if defined(VK_FUCHSIA_imagepipe_surface) + table->vkCreateImagePipeSurfaceFUCHSIA = (PFN_vkCreateImagePipeSurfaceFUCHSIA)load(context, "vkCreateImagePipeSurfaceFUCHSIA"); +#endif /* defined(VK_FUCHSIA_imagepipe_surface) */ +#if defined(VK_GGP_stream_descriptor_surface) + table->vkCreateStreamDescriptorSurfaceGGP = (PFN_vkCreateStreamDescriptorSurfaceGGP)load(context, "vkCreateStreamDescriptorSurfaceGGP"); +#endif /* defined(VK_GGP_stream_descriptor_surface) */ +#if defined(VK_KHR_android_surface) + table->vkCreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)load(context, "vkCreateAndroidSurfaceKHR"); +#endif /* defined(VK_KHR_android_surface) */ +#if defined(VK_KHR_calibrated_timestamps) + table->vkGetPhysicalDeviceCalibrateableTimeDomainsKHR = (PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR)load(context, "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR"); +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_cooperative_matrix) + table->vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR = (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR)load(context, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR"); +#endif /* defined(VK_KHR_cooperative_matrix) */ +#if defined(VK_KHR_device_group_creation) + table->vkEnumeratePhysicalDeviceGroupsKHR = (PFN_vkEnumeratePhysicalDeviceGroupsKHR)load(context, "vkEnumeratePhysicalDeviceGroupsKHR"); +#endif /* defined(VK_KHR_device_group_creation) */ +#if defined(VK_KHR_display) + table->vkCreateDisplayModeKHR = (PFN_vkCreateDisplayModeKHR)load(context, "vkCreateDisplayModeKHR"); + table->vkCreateDisplayPlaneSurfaceKHR = (PFN_vkCreateDisplayPlaneSurfaceKHR)load(context, "vkCreateDisplayPlaneSurfaceKHR"); + table->vkGetDisplayModePropertiesKHR = (PFN_vkGetDisplayModePropertiesKHR)load(context, "vkGetDisplayModePropertiesKHR"); + table->vkGetDisplayPlaneCapabilitiesKHR = (PFN_vkGetDisplayPlaneCapabilitiesKHR)load(context, "vkGetDisplayPlaneCapabilitiesKHR"); + table->vkGetDisplayPlaneSupportedDisplaysKHR = (PFN_vkGetDisplayPlaneSupportedDisplaysKHR)load(context, "vkGetDisplayPlaneSupportedDisplaysKHR"); + table->vkGetPhysicalDeviceDisplayPlanePropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)load(context, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"); + table->vkGetPhysicalDeviceDisplayPropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)load(context, "vkGetPhysicalDeviceDisplayPropertiesKHR"); +#endif /* defined(VK_KHR_display) */ +#if defined(VK_KHR_external_fence_capabilities) + table->vkGetPhysicalDeviceExternalFencePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)load(context, "vkGetPhysicalDeviceExternalFencePropertiesKHR"); +#endif /* defined(VK_KHR_external_fence_capabilities) */ +#if defined(VK_KHR_external_memory_capabilities) + table->vkGetPhysicalDeviceExternalBufferPropertiesKHR = (PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)load(context, "vkGetPhysicalDeviceExternalBufferPropertiesKHR"); +#endif /* defined(VK_KHR_external_memory_capabilities) */ +#if defined(VK_KHR_external_semaphore_capabilities) + table->vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)load(context, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"); +#endif /* defined(VK_KHR_external_semaphore_capabilities) */ +#if defined(VK_KHR_fragment_shading_rate) + table->vkGetPhysicalDeviceFragmentShadingRatesKHR = (PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)load(context, "vkGetPhysicalDeviceFragmentShadingRatesKHR"); +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_display_properties2) + table->vkGetDisplayModeProperties2KHR = (PFN_vkGetDisplayModeProperties2KHR)load(context, "vkGetDisplayModeProperties2KHR"); + table->vkGetDisplayPlaneCapabilities2KHR = (PFN_vkGetDisplayPlaneCapabilities2KHR)load(context, "vkGetDisplayPlaneCapabilities2KHR"); + table->vkGetPhysicalDeviceDisplayPlaneProperties2KHR = (PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)load(context, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR"); + table->vkGetPhysicalDeviceDisplayProperties2KHR = (PFN_vkGetPhysicalDeviceDisplayProperties2KHR)load(context, "vkGetPhysicalDeviceDisplayProperties2KHR"); +#endif /* defined(VK_KHR_get_display_properties2) */ +#if defined(VK_KHR_get_physical_device_properties2) + table->vkGetPhysicalDeviceFeatures2KHR = (PFN_vkGetPhysicalDeviceFeatures2KHR)load(context, "vkGetPhysicalDeviceFeatures2KHR"); + table->vkGetPhysicalDeviceFormatProperties2KHR = (PFN_vkGetPhysicalDeviceFormatProperties2KHR)load(context, "vkGetPhysicalDeviceFormatProperties2KHR"); + table->vkGetPhysicalDeviceImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)load(context, "vkGetPhysicalDeviceImageFormatProperties2KHR"); + table->vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)load(context, "vkGetPhysicalDeviceMemoryProperties2KHR"); + table->vkGetPhysicalDeviceProperties2KHR = (PFN_vkGetPhysicalDeviceProperties2KHR)load(context, "vkGetPhysicalDeviceProperties2KHR"); + table->vkGetPhysicalDeviceQueueFamilyProperties2KHR = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)load(context, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"); + table->vkGetPhysicalDeviceSparseImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)load(context, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"); +#endif /* defined(VK_KHR_get_physical_device_properties2) */ +#if defined(VK_KHR_get_surface_capabilities2) + table->vkGetPhysicalDeviceSurfaceCapabilities2KHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)load(context, "vkGetPhysicalDeviceSurfaceCapabilities2KHR"); + table->vkGetPhysicalDeviceSurfaceFormats2KHR = (PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)load(context, "vkGetPhysicalDeviceSurfaceFormats2KHR"); +#endif /* defined(VK_KHR_get_surface_capabilities2) */ +#if defined(VK_KHR_performance_query) + table->vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = (PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)load(context, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR"); + table->vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = (PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)load(context, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR"); +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_surface) + table->vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)load(context, "vkDestroySurfaceKHR"); + table->vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)load(context, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); + table->vkGetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)load(context, "vkGetPhysicalDeviceSurfaceFormatsKHR"); + table->vkGetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)load(context, "vkGetPhysicalDeviceSurfacePresentModesKHR"); + table->vkGetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)load(context, "vkGetPhysicalDeviceSurfaceSupportKHR"); +#endif /* defined(VK_KHR_surface) */ +#if defined(VK_KHR_video_encode_queue) + table->vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR = (PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR)load(context, "vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR"); +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) + table->vkGetPhysicalDeviceVideoCapabilitiesKHR = (PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)load(context, "vkGetPhysicalDeviceVideoCapabilitiesKHR"); + table->vkGetPhysicalDeviceVideoFormatPropertiesKHR = (PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)load(context, "vkGetPhysicalDeviceVideoFormatPropertiesKHR"); +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_KHR_wayland_surface) + table->vkCreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)load(context, "vkCreateWaylandSurfaceKHR"); + table->vkGetPhysicalDeviceWaylandPresentationSupportKHR = (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)load(context, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"); +#endif /* defined(VK_KHR_wayland_surface) */ +#if defined(VK_KHR_win32_surface) + table->vkCreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)load(context, "vkCreateWin32SurfaceKHR"); + table->vkGetPhysicalDeviceWin32PresentationSupportKHR = (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)load(context, "vkGetPhysicalDeviceWin32PresentationSupportKHR"); +#endif /* defined(VK_KHR_win32_surface) */ +#if defined(VK_KHR_xcb_surface) + table->vkCreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)load(context, "vkCreateXcbSurfaceKHR"); + table->vkGetPhysicalDeviceXcbPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)load(context, "vkGetPhysicalDeviceXcbPresentationSupportKHR"); +#endif /* defined(VK_KHR_xcb_surface) */ +#if defined(VK_KHR_xlib_surface) + table->vkCreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)load(context, "vkCreateXlibSurfaceKHR"); + table->vkGetPhysicalDeviceXlibPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)load(context, "vkGetPhysicalDeviceXlibPresentationSupportKHR"); +#endif /* defined(VK_KHR_xlib_surface) */ +#if defined(VK_MVK_ios_surface) + table->vkCreateIOSSurfaceMVK = (PFN_vkCreateIOSSurfaceMVK)load(context, "vkCreateIOSSurfaceMVK"); +#endif /* defined(VK_MVK_ios_surface) */ +#if defined(VK_MVK_macos_surface) + table->vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)load(context, "vkCreateMacOSSurfaceMVK"); +#endif /* defined(VK_MVK_macos_surface) */ +#if defined(VK_NN_vi_surface) + table->vkCreateViSurfaceNN = (PFN_vkCreateViSurfaceNN)load(context, "vkCreateViSurfaceNN"); +#endif /* defined(VK_NN_vi_surface) */ +#if defined(VK_NV_acquire_winrt_display) + table->vkAcquireWinrtDisplayNV = (PFN_vkAcquireWinrtDisplayNV)load(context, "vkAcquireWinrtDisplayNV"); + table->vkGetWinrtDisplayNV = (PFN_vkGetWinrtDisplayNV)load(context, "vkGetWinrtDisplayNV"); +#endif /* defined(VK_NV_acquire_winrt_display) */ +#if defined(VK_NV_cooperative_matrix) + table->vkGetPhysicalDeviceCooperativeMatrixPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV"); +#endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_cooperative_matrix2) + table->vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV"); +#endif /* defined(VK_NV_cooperative_matrix2) */ +#if defined(VK_NV_cooperative_vector) + table->vkGetPhysicalDeviceCooperativeVectorPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeVectorPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeVectorPropertiesNV"); +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_coverage_reduction_mode) + table->vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = (PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)load(context, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV"); +#endif /* defined(VK_NV_coverage_reduction_mode) */ +#if defined(VK_NV_external_memory_capabilities) + table->vkGetPhysicalDeviceExternalImageFormatPropertiesNV = (PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)load(context, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV"); +#endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_optical_flow) + table->vkGetPhysicalDeviceOpticalFlowImageFormatsNV = (PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV)load(context, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV"); +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_OHOS_surface) + table->vkCreateSurfaceOHOS = (PFN_vkCreateSurfaceOHOS)load(context, "vkCreateSurfaceOHOS"); +#endif /* defined(VK_OHOS_surface) */ +#if defined(VK_QNX_screen_surface) + table->vkCreateScreenSurfaceQNX = (PFN_vkCreateScreenSurfaceQNX)load(context, "vkCreateScreenSurfaceQNX"); + table->vkGetPhysicalDeviceScreenPresentationSupportQNX = (PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX)load(context, "vkGetPhysicalDeviceScreenPresentationSupportQNX"); +#endif /* defined(VK_QNX_screen_surface) */ +#if defined(VK_SEC_ubm_surface) + table->vkCreateUbmSurfaceSEC = (PFN_vkCreateUbmSurfaceSEC)load(context, "vkCreateUbmSurfaceSEC"); + table->vkGetPhysicalDeviceUbmPresentationSupportSEC = (PFN_vkGetPhysicalDeviceUbmPresentationSupportSEC)load(context, "vkGetPhysicalDeviceUbmPresentationSupportSEC"); +#endif /* defined(VK_SEC_ubm_surface) */ +#if (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) + table->vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM = (PFN_vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM)load(context, "vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM"); +#endif /* (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) + table->vkGetPhysicalDevicePresentRectanglesKHR = (PFN_vkGetPhysicalDevicePresentRectanglesKHR)load(context, "vkGetPhysicalDevicePresentRectanglesKHR"); +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ + /* VOLK_GENERATE_LOAD_INSTANCE_TABLE */ +} + +static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, PFN_vkVoidFunction (*load)(void*, const char*)) +{ + /* VOLK_GENERATE_LOAD_DEVICE_TABLE */ +#if defined(VK_VERSION_1_0) + table->vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)load(context, "vkAllocateCommandBuffers"); + table->vkAllocateDescriptorSets = (PFN_vkAllocateDescriptorSets)load(context, "vkAllocateDescriptorSets"); + table->vkAllocateMemory = (PFN_vkAllocateMemory)load(context, "vkAllocateMemory"); + table->vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer)load(context, "vkBeginCommandBuffer"); + table->vkBindBufferMemory = (PFN_vkBindBufferMemory)load(context, "vkBindBufferMemory"); + table->vkBindImageMemory = (PFN_vkBindImageMemory)load(context, "vkBindImageMemory"); + table->vkCmdBeginQuery = (PFN_vkCmdBeginQuery)load(context, "vkCmdBeginQuery"); + table->vkCmdBeginRenderPass = (PFN_vkCmdBeginRenderPass)load(context, "vkCmdBeginRenderPass"); + table->vkCmdBindDescriptorSets = (PFN_vkCmdBindDescriptorSets)load(context, "vkCmdBindDescriptorSets"); + table->vkCmdBindIndexBuffer = (PFN_vkCmdBindIndexBuffer)load(context, "vkCmdBindIndexBuffer"); + table->vkCmdBindPipeline = (PFN_vkCmdBindPipeline)load(context, "vkCmdBindPipeline"); + table->vkCmdBindVertexBuffers = (PFN_vkCmdBindVertexBuffers)load(context, "vkCmdBindVertexBuffers"); + table->vkCmdBlitImage = (PFN_vkCmdBlitImage)load(context, "vkCmdBlitImage"); + table->vkCmdClearAttachments = (PFN_vkCmdClearAttachments)load(context, "vkCmdClearAttachments"); + table->vkCmdClearColorImage = (PFN_vkCmdClearColorImage)load(context, "vkCmdClearColorImage"); + table->vkCmdClearDepthStencilImage = (PFN_vkCmdClearDepthStencilImage)load(context, "vkCmdClearDepthStencilImage"); + table->vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)load(context, "vkCmdCopyBuffer"); + table->vkCmdCopyBufferToImage = (PFN_vkCmdCopyBufferToImage)load(context, "vkCmdCopyBufferToImage"); + table->vkCmdCopyImage = (PFN_vkCmdCopyImage)load(context, "vkCmdCopyImage"); + table->vkCmdCopyImageToBuffer = (PFN_vkCmdCopyImageToBuffer)load(context, "vkCmdCopyImageToBuffer"); + table->vkCmdCopyQueryPoolResults = (PFN_vkCmdCopyQueryPoolResults)load(context, "vkCmdCopyQueryPoolResults"); + table->vkCmdDispatch = (PFN_vkCmdDispatch)load(context, "vkCmdDispatch"); + table->vkCmdDispatchIndirect = (PFN_vkCmdDispatchIndirect)load(context, "vkCmdDispatchIndirect"); + table->vkCmdDraw = (PFN_vkCmdDraw)load(context, "vkCmdDraw"); + table->vkCmdDrawIndexed = (PFN_vkCmdDrawIndexed)load(context, "vkCmdDrawIndexed"); + table->vkCmdDrawIndexedIndirect = (PFN_vkCmdDrawIndexedIndirect)load(context, "vkCmdDrawIndexedIndirect"); + table->vkCmdDrawIndirect = (PFN_vkCmdDrawIndirect)load(context, "vkCmdDrawIndirect"); + table->vkCmdEndQuery = (PFN_vkCmdEndQuery)load(context, "vkCmdEndQuery"); + table->vkCmdEndRenderPass = (PFN_vkCmdEndRenderPass)load(context, "vkCmdEndRenderPass"); + table->vkCmdExecuteCommands = (PFN_vkCmdExecuteCommands)load(context, "vkCmdExecuteCommands"); + table->vkCmdFillBuffer = (PFN_vkCmdFillBuffer)load(context, "vkCmdFillBuffer"); + table->vkCmdNextSubpass = (PFN_vkCmdNextSubpass)load(context, "vkCmdNextSubpass"); + table->vkCmdPipelineBarrier = (PFN_vkCmdPipelineBarrier)load(context, "vkCmdPipelineBarrier"); + table->vkCmdPushConstants = (PFN_vkCmdPushConstants)load(context, "vkCmdPushConstants"); + table->vkCmdResetEvent = (PFN_vkCmdResetEvent)load(context, "vkCmdResetEvent"); + table->vkCmdResetQueryPool = (PFN_vkCmdResetQueryPool)load(context, "vkCmdResetQueryPool"); + table->vkCmdResolveImage = (PFN_vkCmdResolveImage)load(context, "vkCmdResolveImage"); + table->vkCmdSetBlendConstants = (PFN_vkCmdSetBlendConstants)load(context, "vkCmdSetBlendConstants"); + table->vkCmdSetDepthBias = (PFN_vkCmdSetDepthBias)load(context, "vkCmdSetDepthBias"); + table->vkCmdSetDepthBounds = (PFN_vkCmdSetDepthBounds)load(context, "vkCmdSetDepthBounds"); + table->vkCmdSetEvent = (PFN_vkCmdSetEvent)load(context, "vkCmdSetEvent"); + table->vkCmdSetLineWidth = (PFN_vkCmdSetLineWidth)load(context, "vkCmdSetLineWidth"); + table->vkCmdSetScissor = (PFN_vkCmdSetScissor)load(context, "vkCmdSetScissor"); + table->vkCmdSetStencilCompareMask = (PFN_vkCmdSetStencilCompareMask)load(context, "vkCmdSetStencilCompareMask"); + table->vkCmdSetStencilReference = (PFN_vkCmdSetStencilReference)load(context, "vkCmdSetStencilReference"); + table->vkCmdSetStencilWriteMask = (PFN_vkCmdSetStencilWriteMask)load(context, "vkCmdSetStencilWriteMask"); + table->vkCmdSetViewport = (PFN_vkCmdSetViewport)load(context, "vkCmdSetViewport"); + table->vkCmdUpdateBuffer = (PFN_vkCmdUpdateBuffer)load(context, "vkCmdUpdateBuffer"); + table->vkCmdWaitEvents = (PFN_vkCmdWaitEvents)load(context, "vkCmdWaitEvents"); + table->vkCmdWriteTimestamp = (PFN_vkCmdWriteTimestamp)load(context, "vkCmdWriteTimestamp"); + table->vkCreateBuffer = (PFN_vkCreateBuffer)load(context, "vkCreateBuffer"); + table->vkCreateBufferView = (PFN_vkCreateBufferView)load(context, "vkCreateBufferView"); + table->vkCreateCommandPool = (PFN_vkCreateCommandPool)load(context, "vkCreateCommandPool"); + table->vkCreateComputePipelines = (PFN_vkCreateComputePipelines)load(context, "vkCreateComputePipelines"); + table->vkCreateDescriptorPool = (PFN_vkCreateDescriptorPool)load(context, "vkCreateDescriptorPool"); + table->vkCreateDescriptorSetLayout = (PFN_vkCreateDescriptorSetLayout)load(context, "vkCreateDescriptorSetLayout"); + table->vkCreateEvent = (PFN_vkCreateEvent)load(context, "vkCreateEvent"); + table->vkCreateFence = (PFN_vkCreateFence)load(context, "vkCreateFence"); + table->vkCreateFramebuffer = (PFN_vkCreateFramebuffer)load(context, "vkCreateFramebuffer"); + table->vkCreateGraphicsPipelines = (PFN_vkCreateGraphicsPipelines)load(context, "vkCreateGraphicsPipelines"); + table->vkCreateImage = (PFN_vkCreateImage)load(context, "vkCreateImage"); + table->vkCreateImageView = (PFN_vkCreateImageView)load(context, "vkCreateImageView"); + table->vkCreatePipelineCache = (PFN_vkCreatePipelineCache)load(context, "vkCreatePipelineCache"); + table->vkCreatePipelineLayout = (PFN_vkCreatePipelineLayout)load(context, "vkCreatePipelineLayout"); + table->vkCreateQueryPool = (PFN_vkCreateQueryPool)load(context, "vkCreateQueryPool"); + table->vkCreateRenderPass = (PFN_vkCreateRenderPass)load(context, "vkCreateRenderPass"); + table->vkCreateSampler = (PFN_vkCreateSampler)load(context, "vkCreateSampler"); + table->vkCreateSemaphore = (PFN_vkCreateSemaphore)load(context, "vkCreateSemaphore"); + table->vkCreateShaderModule = (PFN_vkCreateShaderModule)load(context, "vkCreateShaderModule"); + table->vkDestroyBuffer = (PFN_vkDestroyBuffer)load(context, "vkDestroyBuffer"); + table->vkDestroyBufferView = (PFN_vkDestroyBufferView)load(context, "vkDestroyBufferView"); + table->vkDestroyCommandPool = (PFN_vkDestroyCommandPool)load(context, "vkDestroyCommandPool"); + table->vkDestroyDescriptorPool = (PFN_vkDestroyDescriptorPool)load(context, "vkDestroyDescriptorPool"); + table->vkDestroyDescriptorSetLayout = (PFN_vkDestroyDescriptorSetLayout)load(context, "vkDestroyDescriptorSetLayout"); + table->vkDestroyDevice = (PFN_vkDestroyDevice)load(context, "vkDestroyDevice"); + table->vkDestroyEvent = (PFN_vkDestroyEvent)load(context, "vkDestroyEvent"); + table->vkDestroyFence = (PFN_vkDestroyFence)load(context, "vkDestroyFence"); + table->vkDestroyFramebuffer = (PFN_vkDestroyFramebuffer)load(context, "vkDestroyFramebuffer"); + table->vkDestroyImage = (PFN_vkDestroyImage)load(context, "vkDestroyImage"); + table->vkDestroyImageView = (PFN_vkDestroyImageView)load(context, "vkDestroyImageView"); + table->vkDestroyPipeline = (PFN_vkDestroyPipeline)load(context, "vkDestroyPipeline"); + table->vkDestroyPipelineCache = (PFN_vkDestroyPipelineCache)load(context, "vkDestroyPipelineCache"); + table->vkDestroyPipelineLayout = (PFN_vkDestroyPipelineLayout)load(context, "vkDestroyPipelineLayout"); + table->vkDestroyQueryPool = (PFN_vkDestroyQueryPool)load(context, "vkDestroyQueryPool"); + table->vkDestroyRenderPass = (PFN_vkDestroyRenderPass)load(context, "vkDestroyRenderPass"); + table->vkDestroySampler = (PFN_vkDestroySampler)load(context, "vkDestroySampler"); + table->vkDestroySemaphore = (PFN_vkDestroySemaphore)load(context, "vkDestroySemaphore"); + table->vkDestroyShaderModule = (PFN_vkDestroyShaderModule)load(context, "vkDestroyShaderModule"); + table->vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle)load(context, "vkDeviceWaitIdle"); + table->vkEndCommandBuffer = (PFN_vkEndCommandBuffer)load(context, "vkEndCommandBuffer"); + table->vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)load(context, "vkFlushMappedMemoryRanges"); + table->vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers)load(context, "vkFreeCommandBuffers"); + table->vkFreeDescriptorSets = (PFN_vkFreeDescriptorSets)load(context, "vkFreeDescriptorSets"); + table->vkFreeMemory = (PFN_vkFreeMemory)load(context, "vkFreeMemory"); + table->vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)load(context, "vkGetBufferMemoryRequirements"); + table->vkGetDeviceMemoryCommitment = (PFN_vkGetDeviceMemoryCommitment)load(context, "vkGetDeviceMemoryCommitment"); + table->vkGetDeviceQueue = (PFN_vkGetDeviceQueue)load(context, "vkGetDeviceQueue"); + table->vkGetEventStatus = (PFN_vkGetEventStatus)load(context, "vkGetEventStatus"); + table->vkGetFenceStatus = (PFN_vkGetFenceStatus)load(context, "vkGetFenceStatus"); + table->vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)load(context, "vkGetImageMemoryRequirements"); + table->vkGetImageSparseMemoryRequirements = (PFN_vkGetImageSparseMemoryRequirements)load(context, "vkGetImageSparseMemoryRequirements"); + table->vkGetImageSubresourceLayout = (PFN_vkGetImageSubresourceLayout)load(context, "vkGetImageSubresourceLayout"); + table->vkGetPipelineCacheData = (PFN_vkGetPipelineCacheData)load(context, "vkGetPipelineCacheData"); + table->vkGetQueryPoolResults = (PFN_vkGetQueryPoolResults)load(context, "vkGetQueryPoolResults"); + table->vkGetRenderAreaGranularity = (PFN_vkGetRenderAreaGranularity)load(context, "vkGetRenderAreaGranularity"); + table->vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)load(context, "vkInvalidateMappedMemoryRanges"); + table->vkMapMemory = (PFN_vkMapMemory)load(context, "vkMapMemory"); + table->vkMergePipelineCaches = (PFN_vkMergePipelineCaches)load(context, "vkMergePipelineCaches"); + table->vkQueueBindSparse = (PFN_vkQueueBindSparse)load(context, "vkQueueBindSparse"); + table->vkQueueSubmit = (PFN_vkQueueSubmit)load(context, "vkQueueSubmit"); + table->vkQueueWaitIdle = (PFN_vkQueueWaitIdle)load(context, "vkQueueWaitIdle"); + table->vkResetCommandBuffer = (PFN_vkResetCommandBuffer)load(context, "vkResetCommandBuffer"); + table->vkResetCommandPool = (PFN_vkResetCommandPool)load(context, "vkResetCommandPool"); + table->vkResetDescriptorPool = (PFN_vkResetDescriptorPool)load(context, "vkResetDescriptorPool"); + table->vkResetEvent = (PFN_vkResetEvent)load(context, "vkResetEvent"); + table->vkResetFences = (PFN_vkResetFences)load(context, "vkResetFences"); + table->vkSetEvent = (PFN_vkSetEvent)load(context, "vkSetEvent"); + table->vkUnmapMemory = (PFN_vkUnmapMemory)load(context, "vkUnmapMemory"); + table->vkUpdateDescriptorSets = (PFN_vkUpdateDescriptorSets)load(context, "vkUpdateDescriptorSets"); + table->vkWaitForFences = (PFN_vkWaitForFences)load(context, "vkWaitForFences"); +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) + table->vkBindBufferMemory2 = (PFN_vkBindBufferMemory2)load(context, "vkBindBufferMemory2"); + table->vkBindImageMemory2 = (PFN_vkBindImageMemory2)load(context, "vkBindImageMemory2"); + table->vkCmdDispatchBase = (PFN_vkCmdDispatchBase)load(context, "vkCmdDispatchBase"); + table->vkCmdSetDeviceMask = (PFN_vkCmdSetDeviceMask)load(context, "vkCmdSetDeviceMask"); + table->vkCreateDescriptorUpdateTemplate = (PFN_vkCreateDescriptorUpdateTemplate)load(context, "vkCreateDescriptorUpdateTemplate"); + table->vkCreateSamplerYcbcrConversion = (PFN_vkCreateSamplerYcbcrConversion)load(context, "vkCreateSamplerYcbcrConversion"); + table->vkDestroyDescriptorUpdateTemplate = (PFN_vkDestroyDescriptorUpdateTemplate)load(context, "vkDestroyDescriptorUpdateTemplate"); + table->vkDestroySamplerYcbcrConversion = (PFN_vkDestroySamplerYcbcrConversion)load(context, "vkDestroySamplerYcbcrConversion"); + table->vkGetBufferMemoryRequirements2 = (PFN_vkGetBufferMemoryRequirements2)load(context, "vkGetBufferMemoryRequirements2"); + table->vkGetDescriptorSetLayoutSupport = (PFN_vkGetDescriptorSetLayoutSupport)load(context, "vkGetDescriptorSetLayoutSupport"); + table->vkGetDeviceGroupPeerMemoryFeatures = (PFN_vkGetDeviceGroupPeerMemoryFeatures)load(context, "vkGetDeviceGroupPeerMemoryFeatures"); + table->vkGetDeviceQueue2 = (PFN_vkGetDeviceQueue2)load(context, "vkGetDeviceQueue2"); + table->vkGetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2)load(context, "vkGetImageMemoryRequirements2"); + table->vkGetImageSparseMemoryRequirements2 = (PFN_vkGetImageSparseMemoryRequirements2)load(context, "vkGetImageSparseMemoryRequirements2"); + table->vkTrimCommandPool = (PFN_vkTrimCommandPool)load(context, "vkTrimCommandPool"); + table->vkUpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate)load(context, "vkUpdateDescriptorSetWithTemplate"); +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) + table->vkCmdBeginRenderPass2 = (PFN_vkCmdBeginRenderPass2)load(context, "vkCmdBeginRenderPass2"); + table->vkCmdDrawIndexedIndirectCount = (PFN_vkCmdDrawIndexedIndirectCount)load(context, "vkCmdDrawIndexedIndirectCount"); + table->vkCmdDrawIndirectCount = (PFN_vkCmdDrawIndirectCount)load(context, "vkCmdDrawIndirectCount"); + table->vkCmdEndRenderPass2 = (PFN_vkCmdEndRenderPass2)load(context, "vkCmdEndRenderPass2"); + table->vkCmdNextSubpass2 = (PFN_vkCmdNextSubpass2)load(context, "vkCmdNextSubpass2"); + table->vkCreateRenderPass2 = (PFN_vkCreateRenderPass2)load(context, "vkCreateRenderPass2"); + table->vkGetBufferDeviceAddress = (PFN_vkGetBufferDeviceAddress)load(context, "vkGetBufferDeviceAddress"); + table->vkGetBufferOpaqueCaptureAddress = (PFN_vkGetBufferOpaqueCaptureAddress)load(context, "vkGetBufferOpaqueCaptureAddress"); + table->vkGetDeviceMemoryOpaqueCaptureAddress = (PFN_vkGetDeviceMemoryOpaqueCaptureAddress)load(context, "vkGetDeviceMemoryOpaqueCaptureAddress"); + table->vkGetSemaphoreCounterValue = (PFN_vkGetSemaphoreCounterValue)load(context, "vkGetSemaphoreCounterValue"); + table->vkResetQueryPool = (PFN_vkResetQueryPool)load(context, "vkResetQueryPool"); + table->vkSignalSemaphore = (PFN_vkSignalSemaphore)load(context, "vkSignalSemaphore"); + table->vkWaitSemaphores = (PFN_vkWaitSemaphores)load(context, "vkWaitSemaphores"); +#endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) + table->vkCmdBeginRendering = (PFN_vkCmdBeginRendering)load(context, "vkCmdBeginRendering"); + table->vkCmdBindVertexBuffers2 = (PFN_vkCmdBindVertexBuffers2)load(context, "vkCmdBindVertexBuffers2"); + table->vkCmdBlitImage2 = (PFN_vkCmdBlitImage2)load(context, "vkCmdBlitImage2"); + table->vkCmdCopyBuffer2 = (PFN_vkCmdCopyBuffer2)load(context, "vkCmdCopyBuffer2"); + table->vkCmdCopyBufferToImage2 = (PFN_vkCmdCopyBufferToImage2)load(context, "vkCmdCopyBufferToImage2"); + table->vkCmdCopyImage2 = (PFN_vkCmdCopyImage2)load(context, "vkCmdCopyImage2"); + table->vkCmdCopyImageToBuffer2 = (PFN_vkCmdCopyImageToBuffer2)load(context, "vkCmdCopyImageToBuffer2"); + table->vkCmdEndRendering = (PFN_vkCmdEndRendering)load(context, "vkCmdEndRendering"); + table->vkCmdPipelineBarrier2 = (PFN_vkCmdPipelineBarrier2)load(context, "vkCmdPipelineBarrier2"); + table->vkCmdResetEvent2 = (PFN_vkCmdResetEvent2)load(context, "vkCmdResetEvent2"); + table->vkCmdResolveImage2 = (PFN_vkCmdResolveImage2)load(context, "vkCmdResolveImage2"); + table->vkCmdSetCullMode = (PFN_vkCmdSetCullMode)load(context, "vkCmdSetCullMode"); + table->vkCmdSetDepthBiasEnable = (PFN_vkCmdSetDepthBiasEnable)load(context, "vkCmdSetDepthBiasEnable"); + table->vkCmdSetDepthBoundsTestEnable = (PFN_vkCmdSetDepthBoundsTestEnable)load(context, "vkCmdSetDepthBoundsTestEnable"); + table->vkCmdSetDepthCompareOp = (PFN_vkCmdSetDepthCompareOp)load(context, "vkCmdSetDepthCompareOp"); + table->vkCmdSetDepthTestEnable = (PFN_vkCmdSetDepthTestEnable)load(context, "vkCmdSetDepthTestEnable"); + table->vkCmdSetDepthWriteEnable = (PFN_vkCmdSetDepthWriteEnable)load(context, "vkCmdSetDepthWriteEnable"); + table->vkCmdSetEvent2 = (PFN_vkCmdSetEvent2)load(context, "vkCmdSetEvent2"); + table->vkCmdSetFrontFace = (PFN_vkCmdSetFrontFace)load(context, "vkCmdSetFrontFace"); + table->vkCmdSetPrimitiveRestartEnable = (PFN_vkCmdSetPrimitiveRestartEnable)load(context, "vkCmdSetPrimitiveRestartEnable"); + table->vkCmdSetPrimitiveTopology = (PFN_vkCmdSetPrimitiveTopology)load(context, "vkCmdSetPrimitiveTopology"); + table->vkCmdSetRasterizerDiscardEnable = (PFN_vkCmdSetRasterizerDiscardEnable)load(context, "vkCmdSetRasterizerDiscardEnable"); + table->vkCmdSetScissorWithCount = (PFN_vkCmdSetScissorWithCount)load(context, "vkCmdSetScissorWithCount"); + table->vkCmdSetStencilOp = (PFN_vkCmdSetStencilOp)load(context, "vkCmdSetStencilOp"); + table->vkCmdSetStencilTestEnable = (PFN_vkCmdSetStencilTestEnable)load(context, "vkCmdSetStencilTestEnable"); + table->vkCmdSetViewportWithCount = (PFN_vkCmdSetViewportWithCount)load(context, "vkCmdSetViewportWithCount"); + table->vkCmdWaitEvents2 = (PFN_vkCmdWaitEvents2)load(context, "vkCmdWaitEvents2"); + table->vkCmdWriteTimestamp2 = (PFN_vkCmdWriteTimestamp2)load(context, "vkCmdWriteTimestamp2"); + table->vkCreatePrivateDataSlot = (PFN_vkCreatePrivateDataSlot)load(context, "vkCreatePrivateDataSlot"); + table->vkDestroyPrivateDataSlot = (PFN_vkDestroyPrivateDataSlot)load(context, "vkDestroyPrivateDataSlot"); + table->vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)load(context, "vkGetDeviceBufferMemoryRequirements"); + table->vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)load(context, "vkGetDeviceImageMemoryRequirements"); + table->vkGetDeviceImageSparseMemoryRequirements = (PFN_vkGetDeviceImageSparseMemoryRequirements)load(context, "vkGetDeviceImageSparseMemoryRequirements"); + table->vkGetPrivateData = (PFN_vkGetPrivateData)load(context, "vkGetPrivateData"); + table->vkQueueSubmit2 = (PFN_vkQueueSubmit2)load(context, "vkQueueSubmit2"); + table->vkSetPrivateData = (PFN_vkSetPrivateData)load(context, "vkSetPrivateData"); +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) + table->vkCmdBindDescriptorSets2 = (PFN_vkCmdBindDescriptorSets2)load(context, "vkCmdBindDescriptorSets2"); + table->vkCmdBindIndexBuffer2 = (PFN_vkCmdBindIndexBuffer2)load(context, "vkCmdBindIndexBuffer2"); + table->vkCmdPushConstants2 = (PFN_vkCmdPushConstants2)load(context, "vkCmdPushConstants2"); + table->vkCmdPushDescriptorSet = (PFN_vkCmdPushDescriptorSet)load(context, "vkCmdPushDescriptorSet"); + table->vkCmdPushDescriptorSet2 = (PFN_vkCmdPushDescriptorSet2)load(context, "vkCmdPushDescriptorSet2"); + table->vkCmdPushDescriptorSetWithTemplate = (PFN_vkCmdPushDescriptorSetWithTemplate)load(context, "vkCmdPushDescriptorSetWithTemplate"); + table->vkCmdPushDescriptorSetWithTemplate2 = (PFN_vkCmdPushDescriptorSetWithTemplate2)load(context, "vkCmdPushDescriptorSetWithTemplate2"); + table->vkCmdSetLineStipple = (PFN_vkCmdSetLineStipple)load(context, "vkCmdSetLineStipple"); + table->vkCmdSetRenderingAttachmentLocations = (PFN_vkCmdSetRenderingAttachmentLocations)load(context, "vkCmdSetRenderingAttachmentLocations"); + table->vkCmdSetRenderingInputAttachmentIndices = (PFN_vkCmdSetRenderingInputAttachmentIndices)load(context, "vkCmdSetRenderingInputAttachmentIndices"); + table->vkCopyImageToImage = (PFN_vkCopyImageToImage)load(context, "vkCopyImageToImage"); + table->vkCopyImageToMemory = (PFN_vkCopyImageToMemory)load(context, "vkCopyImageToMemory"); + table->vkCopyMemoryToImage = (PFN_vkCopyMemoryToImage)load(context, "vkCopyMemoryToImage"); + table->vkGetDeviceImageSubresourceLayout = (PFN_vkGetDeviceImageSubresourceLayout)load(context, "vkGetDeviceImageSubresourceLayout"); + table->vkGetImageSubresourceLayout2 = (PFN_vkGetImageSubresourceLayout2)load(context, "vkGetImageSubresourceLayout2"); + table->vkGetRenderingAreaGranularity = (PFN_vkGetRenderingAreaGranularity)load(context, "vkGetRenderingAreaGranularity"); + table->vkMapMemory2 = (PFN_vkMapMemory2)load(context, "vkMapMemory2"); + table->vkTransitionImageLayout = (PFN_vkTransitionImageLayout)load(context, "vkTransitionImageLayout"); + table->vkUnmapMemory2 = (PFN_vkUnmapMemory2)load(context, "vkUnmapMemory2"); +#endif /* defined(VK_VERSION_1_4) */ +#if defined(VK_AMDX_shader_enqueue) + table->vkCmdDispatchGraphAMDX = (PFN_vkCmdDispatchGraphAMDX)load(context, "vkCmdDispatchGraphAMDX"); + table->vkCmdDispatchGraphIndirectAMDX = (PFN_vkCmdDispatchGraphIndirectAMDX)load(context, "vkCmdDispatchGraphIndirectAMDX"); + table->vkCmdDispatchGraphIndirectCountAMDX = (PFN_vkCmdDispatchGraphIndirectCountAMDX)load(context, "vkCmdDispatchGraphIndirectCountAMDX"); + table->vkCmdInitializeGraphScratchMemoryAMDX = (PFN_vkCmdInitializeGraphScratchMemoryAMDX)load(context, "vkCmdInitializeGraphScratchMemoryAMDX"); + table->vkCreateExecutionGraphPipelinesAMDX = (PFN_vkCreateExecutionGraphPipelinesAMDX)load(context, "vkCreateExecutionGraphPipelinesAMDX"); + table->vkGetExecutionGraphPipelineNodeIndexAMDX = (PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)load(context, "vkGetExecutionGraphPipelineNodeIndexAMDX"); + table->vkGetExecutionGraphPipelineScratchSizeAMDX = (PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)load(context, "vkGetExecutionGraphPipelineScratchSizeAMDX"); +#endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) + table->vkAntiLagUpdateAMD = (PFN_vkAntiLagUpdateAMD)load(context, "vkAntiLagUpdateAMD"); +#endif /* defined(VK_AMD_anti_lag) */ +#if defined(VK_AMD_buffer_marker) + table->vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD"); +#endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + table->vkCmdWriteBufferMarker2AMD = (PFN_vkCmdWriteBufferMarker2AMD)load(context, "vkCmdWriteBufferMarker2AMD"); +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_AMD_display_native_hdr) + table->vkSetLocalDimmingAMD = (PFN_vkSetLocalDimmingAMD)load(context, "vkSetLocalDimmingAMD"); +#endif /* defined(VK_AMD_display_native_hdr) */ +#if defined(VK_AMD_draw_indirect_count) + table->vkCmdDrawIndexedIndirectCountAMD = (PFN_vkCmdDrawIndexedIndirectCountAMD)load(context, "vkCmdDrawIndexedIndirectCountAMD"); + table->vkCmdDrawIndirectCountAMD = (PFN_vkCmdDrawIndirectCountAMD)load(context, "vkCmdDrawIndirectCountAMD"); +#endif /* defined(VK_AMD_draw_indirect_count) */ +#if defined(VK_AMD_gpa_interface) + table->vkCmdBeginGpaSampleAMD = (PFN_vkCmdBeginGpaSampleAMD)load(context, "vkCmdBeginGpaSampleAMD"); + table->vkCmdBeginGpaSessionAMD = (PFN_vkCmdBeginGpaSessionAMD)load(context, "vkCmdBeginGpaSessionAMD"); + table->vkCmdCopyGpaSessionResultsAMD = (PFN_vkCmdCopyGpaSessionResultsAMD)load(context, "vkCmdCopyGpaSessionResultsAMD"); + table->vkCmdEndGpaSampleAMD = (PFN_vkCmdEndGpaSampleAMD)load(context, "vkCmdEndGpaSampleAMD"); + table->vkCmdEndGpaSessionAMD = (PFN_vkCmdEndGpaSessionAMD)load(context, "vkCmdEndGpaSessionAMD"); + table->vkCreateGpaSessionAMD = (PFN_vkCreateGpaSessionAMD)load(context, "vkCreateGpaSessionAMD"); + table->vkDestroyGpaSessionAMD = (PFN_vkDestroyGpaSessionAMD)load(context, "vkDestroyGpaSessionAMD"); + table->vkGetGpaDeviceClockInfoAMD = (PFN_vkGetGpaDeviceClockInfoAMD)load(context, "vkGetGpaDeviceClockInfoAMD"); + table->vkGetGpaSessionResultsAMD = (PFN_vkGetGpaSessionResultsAMD)load(context, "vkGetGpaSessionResultsAMD"); + table->vkGetGpaSessionStatusAMD = (PFN_vkGetGpaSessionStatusAMD)load(context, "vkGetGpaSessionStatusAMD"); + table->vkResetGpaSessionAMD = (PFN_vkResetGpaSessionAMD)load(context, "vkResetGpaSessionAMD"); + table->vkSetGpaDeviceClockModeAMD = (PFN_vkSetGpaDeviceClockModeAMD)load(context, "vkSetGpaDeviceClockModeAMD"); +#endif /* defined(VK_AMD_gpa_interface) */ +#if defined(VK_AMD_shader_info) + table->vkGetShaderInfoAMD = (PFN_vkGetShaderInfoAMD)load(context, "vkGetShaderInfoAMD"); +#endif /* defined(VK_AMD_shader_info) */ +#if defined(VK_ANDROID_external_memory_android_hardware_buffer) + table->vkGetAndroidHardwareBufferPropertiesANDROID = (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)load(context, "vkGetAndroidHardwareBufferPropertiesANDROID"); + table->vkGetMemoryAndroidHardwareBufferANDROID = (PFN_vkGetMemoryAndroidHardwareBufferANDROID)load(context, "vkGetMemoryAndroidHardwareBufferANDROID"); +#endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_ARM_data_graph) + table->vkBindDataGraphPipelineSessionMemoryARM = (PFN_vkBindDataGraphPipelineSessionMemoryARM)load(context, "vkBindDataGraphPipelineSessionMemoryARM"); + table->vkCmdDispatchDataGraphARM = (PFN_vkCmdDispatchDataGraphARM)load(context, "vkCmdDispatchDataGraphARM"); + table->vkCreateDataGraphPipelineSessionARM = (PFN_vkCreateDataGraphPipelineSessionARM)load(context, "vkCreateDataGraphPipelineSessionARM"); + table->vkCreateDataGraphPipelinesARM = (PFN_vkCreateDataGraphPipelinesARM)load(context, "vkCreateDataGraphPipelinesARM"); + table->vkDestroyDataGraphPipelineSessionARM = (PFN_vkDestroyDataGraphPipelineSessionARM)load(context, "vkDestroyDataGraphPipelineSessionARM"); + table->vkGetDataGraphPipelineAvailablePropertiesARM = (PFN_vkGetDataGraphPipelineAvailablePropertiesARM)load(context, "vkGetDataGraphPipelineAvailablePropertiesARM"); + table->vkGetDataGraphPipelinePropertiesARM = (PFN_vkGetDataGraphPipelinePropertiesARM)load(context, "vkGetDataGraphPipelinePropertiesARM"); + table->vkGetDataGraphPipelineSessionBindPointRequirementsARM = (PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM)load(context, "vkGetDataGraphPipelineSessionBindPointRequirementsARM"); + table->vkGetDataGraphPipelineSessionMemoryRequirementsARM = (PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM)load(context, "vkGetDataGraphPipelineSessionMemoryRequirementsARM"); +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 + table->vkCmdSetDispatchParametersARM = (PFN_vkCmdSetDispatchParametersARM)load(context, "vkCmdSetDispatchParametersARM"); +#endif /* defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 */ +#if defined(VK_ARM_shader_instrumentation) + table->vkClearShaderInstrumentationMetricsARM = (PFN_vkClearShaderInstrumentationMetricsARM)load(context, "vkClearShaderInstrumentationMetricsARM"); + table->vkCmdBeginShaderInstrumentationARM = (PFN_vkCmdBeginShaderInstrumentationARM)load(context, "vkCmdBeginShaderInstrumentationARM"); + table->vkCmdEndShaderInstrumentationARM = (PFN_vkCmdEndShaderInstrumentationARM)load(context, "vkCmdEndShaderInstrumentationARM"); + table->vkCreateShaderInstrumentationARM = (PFN_vkCreateShaderInstrumentationARM)load(context, "vkCreateShaderInstrumentationARM"); + table->vkDestroyShaderInstrumentationARM = (PFN_vkDestroyShaderInstrumentationARM)load(context, "vkDestroyShaderInstrumentationARM"); + table->vkGetShaderInstrumentationValuesARM = (PFN_vkGetShaderInstrumentationValuesARM)load(context, "vkGetShaderInstrumentationValuesARM"); +#endif /* defined(VK_ARM_shader_instrumentation) */ +#if defined(VK_ARM_tensors) + table->vkBindTensorMemoryARM = (PFN_vkBindTensorMemoryARM)load(context, "vkBindTensorMemoryARM"); + table->vkCmdCopyTensorARM = (PFN_vkCmdCopyTensorARM)load(context, "vkCmdCopyTensorARM"); + table->vkCreateTensorARM = (PFN_vkCreateTensorARM)load(context, "vkCreateTensorARM"); + table->vkCreateTensorViewARM = (PFN_vkCreateTensorViewARM)load(context, "vkCreateTensorViewARM"); + table->vkDestroyTensorARM = (PFN_vkDestroyTensorARM)load(context, "vkDestroyTensorARM"); + table->vkDestroyTensorViewARM = (PFN_vkDestroyTensorViewARM)load(context, "vkDestroyTensorViewARM"); + table->vkGetDeviceTensorMemoryRequirementsARM = (PFN_vkGetDeviceTensorMemoryRequirementsARM)load(context, "vkGetDeviceTensorMemoryRequirementsARM"); + table->vkGetTensorMemoryRequirementsARM = (PFN_vkGetTensorMemoryRequirementsARM)load(context, "vkGetTensorMemoryRequirementsARM"); +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) + table->vkGetTensorOpaqueCaptureDescriptorDataARM = (PFN_vkGetTensorOpaqueCaptureDescriptorDataARM)load(context, "vkGetTensorOpaqueCaptureDescriptorDataARM"); + table->vkGetTensorViewOpaqueCaptureDescriptorDataARM = (PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM)load(context, "vkGetTensorViewOpaqueCaptureDescriptorDataARM"); +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) + table->vkCmdSetAttachmentFeedbackLoopEnableEXT = (PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)load(context, "vkCmdSetAttachmentFeedbackLoopEnableEXT"); +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ +#if defined(VK_EXT_buffer_device_address) + table->vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)load(context, "vkGetBufferDeviceAddressEXT"); +#endif /* defined(VK_EXT_buffer_device_address) */ +#if defined(VK_EXT_calibrated_timestamps) + table->vkGetCalibratedTimestampsEXT = (PFN_vkGetCalibratedTimestampsEXT)load(context, "vkGetCalibratedTimestampsEXT"); +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) + table->vkCmdSetColorWriteEnableEXT = (PFN_vkCmdSetColorWriteEnableEXT)load(context, "vkCmdSetColorWriteEnableEXT"); +#endif /* defined(VK_EXT_color_write_enable) */ +#if defined(VK_EXT_conditional_rendering) + table->vkCmdBeginConditionalRenderingEXT = (PFN_vkCmdBeginConditionalRenderingEXT)load(context, "vkCmdBeginConditionalRenderingEXT"); + table->vkCmdEndConditionalRenderingEXT = (PFN_vkCmdEndConditionalRenderingEXT)load(context, "vkCmdEndConditionalRenderingEXT"); +#endif /* defined(VK_EXT_conditional_rendering) */ +#if defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) + table->vkCmdBeginCustomResolveEXT = (PFN_vkCmdBeginCustomResolveEXT)load(context, "vkCmdBeginCustomResolveEXT"); +#endif /* defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) */ +#if defined(VK_EXT_debug_marker) + table->vkCmdDebugMarkerBeginEXT = (PFN_vkCmdDebugMarkerBeginEXT)load(context, "vkCmdDebugMarkerBeginEXT"); + table->vkCmdDebugMarkerEndEXT = (PFN_vkCmdDebugMarkerEndEXT)load(context, "vkCmdDebugMarkerEndEXT"); + table->vkCmdDebugMarkerInsertEXT = (PFN_vkCmdDebugMarkerInsertEXT)load(context, "vkCmdDebugMarkerInsertEXT"); + table->vkDebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)load(context, "vkDebugMarkerSetObjectNameEXT"); + table->vkDebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT)load(context, "vkDebugMarkerSetObjectTagEXT"); +#endif /* defined(VK_EXT_debug_marker) */ +#if defined(VK_EXT_depth_bias_control) + table->vkCmdSetDepthBias2EXT = (PFN_vkCmdSetDepthBias2EXT)load(context, "vkCmdSetDepthBias2EXT"); +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) + table->vkCmdBindDescriptorBufferEmbeddedSamplersEXT = (PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT)load(context, "vkCmdBindDescriptorBufferEmbeddedSamplersEXT"); + table->vkCmdBindDescriptorBuffersEXT = (PFN_vkCmdBindDescriptorBuffersEXT)load(context, "vkCmdBindDescriptorBuffersEXT"); + table->vkCmdSetDescriptorBufferOffsetsEXT = (PFN_vkCmdSetDescriptorBufferOffsetsEXT)load(context, "vkCmdSetDescriptorBufferOffsetsEXT"); + table->vkGetBufferOpaqueCaptureDescriptorDataEXT = (PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT)load(context, "vkGetBufferOpaqueCaptureDescriptorDataEXT"); + table->vkGetDescriptorEXT = (PFN_vkGetDescriptorEXT)load(context, "vkGetDescriptorEXT"); + table->vkGetDescriptorSetLayoutBindingOffsetEXT = (PFN_vkGetDescriptorSetLayoutBindingOffsetEXT)load(context, "vkGetDescriptorSetLayoutBindingOffsetEXT"); + table->vkGetDescriptorSetLayoutSizeEXT = (PFN_vkGetDescriptorSetLayoutSizeEXT)load(context, "vkGetDescriptorSetLayoutSizeEXT"); + table->vkGetImageOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageOpaqueCaptureDescriptorDataEXT"); + table->vkGetImageViewOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageViewOpaqueCaptureDescriptorDataEXT"); + table->vkGetSamplerOpaqueCaptureDescriptorDataEXT = (PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT)load(context, "vkGetSamplerOpaqueCaptureDescriptorDataEXT"); +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) + table->vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT = (PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT)load(context, "vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT"); +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_descriptor_heap) + table->vkCmdBindResourceHeapEXT = (PFN_vkCmdBindResourceHeapEXT)load(context, "vkCmdBindResourceHeapEXT"); + table->vkCmdBindSamplerHeapEXT = (PFN_vkCmdBindSamplerHeapEXT)load(context, "vkCmdBindSamplerHeapEXT"); + table->vkCmdPushDataEXT = (PFN_vkCmdPushDataEXT)load(context, "vkCmdPushDataEXT"); + table->vkGetImageOpaqueCaptureDataEXT = (PFN_vkGetImageOpaqueCaptureDataEXT)load(context, "vkGetImageOpaqueCaptureDataEXT"); + table->vkWriteResourceDescriptorsEXT = (PFN_vkWriteResourceDescriptorsEXT)load(context, "vkWriteResourceDescriptorsEXT"); + table->vkWriteSamplerDescriptorsEXT = (PFN_vkWriteSamplerDescriptorsEXT)load(context, "vkWriteSamplerDescriptorsEXT"); +#endif /* defined(VK_EXT_descriptor_heap) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) + table->vkRegisterCustomBorderColorEXT = (PFN_vkRegisterCustomBorderColorEXT)load(context, "vkRegisterCustomBorderColorEXT"); + table->vkUnregisterCustomBorderColorEXT = (PFN_vkUnregisterCustomBorderColorEXT)load(context, "vkUnregisterCustomBorderColorEXT"); +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) + table->vkGetTensorOpaqueCaptureDataARM = (PFN_vkGetTensorOpaqueCaptureDataARM)load(context, "vkGetTensorOpaqueCaptureDataARM"); +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) */ +#if defined(VK_EXT_device_fault) + table->vkGetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)load(context, "vkGetDeviceFaultInfoEXT"); +#endif /* defined(VK_EXT_device_fault) */ +#if defined(VK_EXT_device_generated_commands) + table->vkCmdExecuteGeneratedCommandsEXT = (PFN_vkCmdExecuteGeneratedCommandsEXT)load(context, "vkCmdExecuteGeneratedCommandsEXT"); + table->vkCmdPreprocessGeneratedCommandsEXT = (PFN_vkCmdPreprocessGeneratedCommandsEXT)load(context, "vkCmdPreprocessGeneratedCommandsEXT"); + table->vkCreateIndirectCommandsLayoutEXT = (PFN_vkCreateIndirectCommandsLayoutEXT)load(context, "vkCreateIndirectCommandsLayoutEXT"); + table->vkCreateIndirectExecutionSetEXT = (PFN_vkCreateIndirectExecutionSetEXT)load(context, "vkCreateIndirectExecutionSetEXT"); + table->vkDestroyIndirectCommandsLayoutEXT = (PFN_vkDestroyIndirectCommandsLayoutEXT)load(context, "vkDestroyIndirectCommandsLayoutEXT"); + table->vkDestroyIndirectExecutionSetEXT = (PFN_vkDestroyIndirectExecutionSetEXT)load(context, "vkDestroyIndirectExecutionSetEXT"); + table->vkGetGeneratedCommandsMemoryRequirementsEXT = (PFN_vkGetGeneratedCommandsMemoryRequirementsEXT)load(context, "vkGetGeneratedCommandsMemoryRequirementsEXT"); + table->vkUpdateIndirectExecutionSetPipelineEXT = (PFN_vkUpdateIndirectExecutionSetPipelineEXT)load(context, "vkUpdateIndirectExecutionSetPipelineEXT"); + table->vkUpdateIndirectExecutionSetShaderEXT = (PFN_vkUpdateIndirectExecutionSetShaderEXT)load(context, "vkUpdateIndirectExecutionSetShaderEXT"); +#endif /* defined(VK_EXT_device_generated_commands) */ +#if defined(VK_EXT_discard_rectangles) + table->vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); +#endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 + table->vkCmdSetDiscardRectangleEnableEXT = (PFN_vkCmdSetDiscardRectangleEnableEXT)load(context, "vkCmdSetDiscardRectangleEnableEXT"); + table->vkCmdSetDiscardRectangleModeEXT = (PFN_vkCmdSetDiscardRectangleModeEXT)load(context, "vkCmdSetDiscardRectangleModeEXT"); +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ +#if defined(VK_EXT_display_control) + table->vkDisplayPowerControlEXT = (PFN_vkDisplayPowerControlEXT)load(context, "vkDisplayPowerControlEXT"); + table->vkGetSwapchainCounterEXT = (PFN_vkGetSwapchainCounterEXT)load(context, "vkGetSwapchainCounterEXT"); + table->vkRegisterDeviceEventEXT = (PFN_vkRegisterDeviceEventEXT)load(context, "vkRegisterDeviceEventEXT"); + table->vkRegisterDisplayEventEXT = (PFN_vkRegisterDisplayEventEXT)load(context, "vkRegisterDisplayEventEXT"); +#endif /* defined(VK_EXT_display_control) */ +#if defined(VK_EXT_external_memory_host) + table->vkGetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)load(context, "vkGetMemoryHostPointerPropertiesEXT"); +#endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) + table->vkGetMemoryMetalHandleEXT = (PFN_vkGetMemoryMetalHandleEXT)load(context, "vkGetMemoryMetalHandleEXT"); + table->vkGetMemoryMetalHandlePropertiesEXT = (PFN_vkGetMemoryMetalHandlePropertiesEXT)load(context, "vkGetMemoryMetalHandlePropertiesEXT"); +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) + table->vkCmdEndRendering2EXT = (PFN_vkCmdEndRendering2EXT)load(context, "vkCmdEndRendering2EXT"); +#endif /* defined(VK_EXT_fragment_density_map_offset) */ +#if defined(VK_EXT_full_screen_exclusive) + table->vkAcquireFullScreenExclusiveModeEXT = (PFN_vkAcquireFullScreenExclusiveModeEXT)load(context, "vkAcquireFullScreenExclusiveModeEXT"); + table->vkReleaseFullScreenExclusiveModeEXT = (PFN_vkReleaseFullScreenExclusiveModeEXT)load(context, "vkReleaseFullScreenExclusiveModeEXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) + table->vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ +#if defined(VK_EXT_hdr_metadata) + table->vkSetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)load(context, "vkSetHdrMetadataEXT"); +#endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_image_copy) + table->vkCopyImageToImageEXT = (PFN_vkCopyImageToImageEXT)load(context, "vkCopyImageToImageEXT"); + table->vkCopyImageToMemoryEXT = (PFN_vkCopyImageToMemoryEXT)load(context, "vkCopyImageToMemoryEXT"); + table->vkCopyMemoryToImageEXT = (PFN_vkCopyMemoryToImageEXT)load(context, "vkCopyMemoryToImageEXT"); + table->vkTransitionImageLayoutEXT = (PFN_vkTransitionImageLayoutEXT)load(context, "vkTransitionImageLayoutEXT"); +#endif /* defined(VK_EXT_host_image_copy) */ +#if defined(VK_EXT_host_query_reset) + table->vkResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)load(context, "vkResetQueryPoolEXT"); +#endif /* defined(VK_EXT_host_query_reset) */ +#if defined(VK_EXT_image_drm_format_modifier) + table->vkGetImageDrmFormatModifierPropertiesEXT = (PFN_vkGetImageDrmFormatModifierPropertiesEXT)load(context, "vkGetImageDrmFormatModifierPropertiesEXT"); +#endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) + table->vkCmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)load(context, "vkCmdSetLineStippleEXT"); +#endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_memory_decompression) + table->vkCmdDecompressMemoryEXT = (PFN_vkCmdDecompressMemoryEXT)load(context, "vkCmdDecompressMemoryEXT"); + table->vkCmdDecompressMemoryIndirectCountEXT = (PFN_vkCmdDecompressMemoryIndirectCountEXT)load(context, "vkCmdDecompressMemoryIndirectCountEXT"); +#endif /* defined(VK_EXT_memory_decompression) */ +#if defined(VK_EXT_mesh_shader) + table->vkCmdDrawMeshTasksEXT = (PFN_vkCmdDrawMeshTasksEXT)load(context, "vkCmdDrawMeshTasksEXT"); + table->vkCmdDrawMeshTasksIndirectEXT = (PFN_vkCmdDrawMeshTasksIndirectEXT)load(context, "vkCmdDrawMeshTasksIndirectEXT"); +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + table->vkCmdDrawMeshTasksIndirectCountEXT = (PFN_vkCmdDrawMeshTasksIndirectCountEXT)load(context, "vkCmdDrawMeshTasksIndirectCountEXT"); +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_EXT_metal_objects) + table->vkExportMetalObjectsEXT = (PFN_vkExportMetalObjectsEXT)load(context, "vkExportMetalObjectsEXT"); +#endif /* defined(VK_EXT_metal_objects) */ +#if defined(VK_EXT_multi_draw) + table->vkCmdDrawMultiEXT = (PFN_vkCmdDrawMultiEXT)load(context, "vkCmdDrawMultiEXT"); + table->vkCmdDrawMultiIndexedEXT = (PFN_vkCmdDrawMultiIndexedEXT)load(context, "vkCmdDrawMultiIndexedEXT"); +#endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) + table->vkBuildMicromapsEXT = (PFN_vkBuildMicromapsEXT)load(context, "vkBuildMicromapsEXT"); + table->vkCmdBuildMicromapsEXT = (PFN_vkCmdBuildMicromapsEXT)load(context, "vkCmdBuildMicromapsEXT"); + table->vkCmdCopyMemoryToMicromapEXT = (PFN_vkCmdCopyMemoryToMicromapEXT)load(context, "vkCmdCopyMemoryToMicromapEXT"); + table->vkCmdCopyMicromapEXT = (PFN_vkCmdCopyMicromapEXT)load(context, "vkCmdCopyMicromapEXT"); + table->vkCmdCopyMicromapToMemoryEXT = (PFN_vkCmdCopyMicromapToMemoryEXT)load(context, "vkCmdCopyMicromapToMemoryEXT"); + table->vkCmdWriteMicromapsPropertiesEXT = (PFN_vkCmdWriteMicromapsPropertiesEXT)load(context, "vkCmdWriteMicromapsPropertiesEXT"); + table->vkCopyMemoryToMicromapEXT = (PFN_vkCopyMemoryToMicromapEXT)load(context, "vkCopyMemoryToMicromapEXT"); + table->vkCopyMicromapEXT = (PFN_vkCopyMicromapEXT)load(context, "vkCopyMicromapEXT"); + table->vkCopyMicromapToMemoryEXT = (PFN_vkCopyMicromapToMemoryEXT)load(context, "vkCopyMicromapToMemoryEXT"); + table->vkCreateMicromapEXT = (PFN_vkCreateMicromapEXT)load(context, "vkCreateMicromapEXT"); + table->vkDestroyMicromapEXT = (PFN_vkDestroyMicromapEXT)load(context, "vkDestroyMicromapEXT"); + table->vkGetDeviceMicromapCompatibilityEXT = (PFN_vkGetDeviceMicromapCompatibilityEXT)load(context, "vkGetDeviceMicromapCompatibilityEXT"); + table->vkGetMicromapBuildSizesEXT = (PFN_vkGetMicromapBuildSizesEXT)load(context, "vkGetMicromapBuildSizesEXT"); + table->vkWriteMicromapsPropertiesEXT = (PFN_vkWriteMicromapsPropertiesEXT)load(context, "vkWriteMicromapsPropertiesEXT"); +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) + table->vkSetDeviceMemoryPriorityEXT = (PFN_vkSetDeviceMemoryPriorityEXT)load(context, "vkSetDeviceMemoryPriorityEXT"); +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) + table->vkGetPipelinePropertiesEXT = (PFN_vkGetPipelinePropertiesEXT)load(context, "vkGetPipelinePropertiesEXT"); +#endif /* defined(VK_EXT_pipeline_properties) */ +#if defined(VK_EXT_present_timing) + table->vkGetPastPresentationTimingEXT = (PFN_vkGetPastPresentationTimingEXT)load(context, "vkGetPastPresentationTimingEXT"); + table->vkGetSwapchainTimeDomainPropertiesEXT = (PFN_vkGetSwapchainTimeDomainPropertiesEXT)load(context, "vkGetSwapchainTimeDomainPropertiesEXT"); + table->vkGetSwapchainTimingPropertiesEXT = (PFN_vkGetSwapchainTimingPropertiesEXT)load(context, "vkGetSwapchainTimingPropertiesEXT"); + table->vkSetSwapchainPresentTimingQueueSizeEXT = (PFN_vkSetSwapchainPresentTimingQueueSizeEXT)load(context, "vkSetSwapchainPresentTimingQueueSizeEXT"); +#endif /* defined(VK_EXT_present_timing) */ +#if defined(VK_EXT_primitive_restart_index) + table->vkCmdSetPrimitiveRestartIndexEXT = (PFN_vkCmdSetPrimitiveRestartIndexEXT)load(context, "vkCmdSetPrimitiveRestartIndexEXT"); +#endif /* defined(VK_EXT_primitive_restart_index) */ +#if defined(VK_EXT_private_data) + table->vkCreatePrivateDataSlotEXT = (PFN_vkCreatePrivateDataSlotEXT)load(context, "vkCreatePrivateDataSlotEXT"); + table->vkDestroyPrivateDataSlotEXT = (PFN_vkDestroyPrivateDataSlotEXT)load(context, "vkDestroyPrivateDataSlotEXT"); + table->vkGetPrivateDataEXT = (PFN_vkGetPrivateDataEXT)load(context, "vkGetPrivateDataEXT"); + table->vkSetPrivateDataEXT = (PFN_vkSetPrivateDataEXT)load(context, "vkSetPrivateDataEXT"); +#endif /* defined(VK_EXT_private_data) */ +#if defined(VK_EXT_sample_locations) + table->vkCmdSetSampleLocationsEXT = (PFN_vkCmdSetSampleLocationsEXT)load(context, "vkCmdSetSampleLocationsEXT"); +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) + table->vkGetShaderModuleCreateInfoIdentifierEXT = (PFN_vkGetShaderModuleCreateInfoIdentifierEXT)load(context, "vkGetShaderModuleCreateInfoIdentifierEXT"); + table->vkGetShaderModuleIdentifierEXT = (PFN_vkGetShaderModuleIdentifierEXT)load(context, "vkGetShaderModuleIdentifierEXT"); +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) + table->vkCmdBindShadersEXT = (PFN_vkCmdBindShadersEXT)load(context, "vkCmdBindShadersEXT"); + table->vkCreateShadersEXT = (PFN_vkCreateShadersEXT)load(context, "vkCreateShadersEXT"); + table->vkDestroyShaderEXT = (PFN_vkDestroyShaderEXT)load(context, "vkDestroyShaderEXT"); + table->vkGetShaderBinaryDataEXT = (PFN_vkGetShaderBinaryDataEXT)load(context, "vkGetShaderBinaryDataEXT"); +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) + table->vkReleaseSwapchainImagesEXT = (PFN_vkReleaseSwapchainImagesEXT)load(context, "vkReleaseSwapchainImagesEXT"); +#endif /* defined(VK_EXT_swapchain_maintenance1) */ +#if defined(VK_EXT_transform_feedback) + table->vkCmdBeginQueryIndexedEXT = (PFN_vkCmdBeginQueryIndexedEXT)load(context, "vkCmdBeginQueryIndexedEXT"); + table->vkCmdBeginTransformFeedbackEXT = (PFN_vkCmdBeginTransformFeedbackEXT)load(context, "vkCmdBeginTransformFeedbackEXT"); + table->vkCmdBindTransformFeedbackBuffersEXT = (PFN_vkCmdBindTransformFeedbackBuffersEXT)load(context, "vkCmdBindTransformFeedbackBuffersEXT"); + table->vkCmdDrawIndirectByteCountEXT = (PFN_vkCmdDrawIndirectByteCountEXT)load(context, "vkCmdDrawIndirectByteCountEXT"); + table->vkCmdEndQueryIndexedEXT = (PFN_vkCmdEndQueryIndexedEXT)load(context, "vkCmdEndQueryIndexedEXT"); + table->vkCmdEndTransformFeedbackEXT = (PFN_vkCmdEndTransformFeedbackEXT)load(context, "vkCmdEndTransformFeedbackEXT"); +#endif /* defined(VK_EXT_transform_feedback) */ +#if defined(VK_EXT_validation_cache) + table->vkCreateValidationCacheEXT = (PFN_vkCreateValidationCacheEXT)load(context, "vkCreateValidationCacheEXT"); + table->vkDestroyValidationCacheEXT = (PFN_vkDestroyValidationCacheEXT)load(context, "vkDestroyValidationCacheEXT"); + table->vkGetValidationCacheDataEXT = (PFN_vkGetValidationCacheDataEXT)load(context, "vkGetValidationCacheDataEXT"); + table->vkMergeValidationCachesEXT = (PFN_vkMergeValidationCachesEXT)load(context, "vkMergeValidationCachesEXT"); +#endif /* defined(VK_EXT_validation_cache) */ +#if defined(VK_FUCHSIA_buffer_collection) + table->vkCreateBufferCollectionFUCHSIA = (PFN_vkCreateBufferCollectionFUCHSIA)load(context, "vkCreateBufferCollectionFUCHSIA"); + table->vkDestroyBufferCollectionFUCHSIA = (PFN_vkDestroyBufferCollectionFUCHSIA)load(context, "vkDestroyBufferCollectionFUCHSIA"); + table->vkGetBufferCollectionPropertiesFUCHSIA = (PFN_vkGetBufferCollectionPropertiesFUCHSIA)load(context, "vkGetBufferCollectionPropertiesFUCHSIA"); + table->vkSetBufferCollectionBufferConstraintsFUCHSIA = (PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)load(context, "vkSetBufferCollectionBufferConstraintsFUCHSIA"); + table->vkSetBufferCollectionImageConstraintsFUCHSIA = (PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)load(context, "vkSetBufferCollectionImageConstraintsFUCHSIA"); +#endif /* defined(VK_FUCHSIA_buffer_collection) */ +#if defined(VK_FUCHSIA_external_memory) + table->vkGetMemoryZirconHandleFUCHSIA = (PFN_vkGetMemoryZirconHandleFUCHSIA)load(context, "vkGetMemoryZirconHandleFUCHSIA"); + table->vkGetMemoryZirconHandlePropertiesFUCHSIA = (PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)load(context, "vkGetMemoryZirconHandlePropertiesFUCHSIA"); +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) + table->vkGetSemaphoreZirconHandleFUCHSIA = (PFN_vkGetSemaphoreZirconHandleFUCHSIA)load(context, "vkGetSemaphoreZirconHandleFUCHSIA"); + table->vkImportSemaphoreZirconHandleFUCHSIA = (PFN_vkImportSemaphoreZirconHandleFUCHSIA)load(context, "vkImportSemaphoreZirconHandleFUCHSIA"); +#endif /* defined(VK_FUCHSIA_external_semaphore) */ +#if defined(VK_GOOGLE_display_timing) + table->vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)load(context, "vkGetPastPresentationTimingGOOGLE"); + table->vkGetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)load(context, "vkGetRefreshCycleDurationGOOGLE"); +#endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) + table->vkCmdDrawClusterHUAWEI = (PFN_vkCmdDrawClusterHUAWEI)load(context, "vkCmdDrawClusterHUAWEI"); + table->vkCmdDrawClusterIndirectHUAWEI = (PFN_vkCmdDrawClusterIndirectHUAWEI)load(context, "vkCmdDrawClusterIndirectHUAWEI"); +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ +#if defined(VK_HUAWEI_invocation_mask) + table->vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 + table->vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = (PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)load(context, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI"); +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ +#if defined(VK_HUAWEI_subpass_shading) + table->vkCmdSubpassShadingHUAWEI = (PFN_vkCmdSubpassShadingHUAWEI)load(context, "vkCmdSubpassShadingHUAWEI"); +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) + table->vkAcquirePerformanceConfigurationINTEL = (PFN_vkAcquirePerformanceConfigurationINTEL)load(context, "vkAcquirePerformanceConfigurationINTEL"); + table->vkCmdSetPerformanceMarkerINTEL = (PFN_vkCmdSetPerformanceMarkerINTEL)load(context, "vkCmdSetPerformanceMarkerINTEL"); + table->vkCmdSetPerformanceOverrideINTEL = (PFN_vkCmdSetPerformanceOverrideINTEL)load(context, "vkCmdSetPerformanceOverrideINTEL"); + table->vkCmdSetPerformanceStreamMarkerINTEL = (PFN_vkCmdSetPerformanceStreamMarkerINTEL)load(context, "vkCmdSetPerformanceStreamMarkerINTEL"); + table->vkGetPerformanceParameterINTEL = (PFN_vkGetPerformanceParameterINTEL)load(context, "vkGetPerformanceParameterINTEL"); + table->vkInitializePerformanceApiINTEL = (PFN_vkInitializePerformanceApiINTEL)load(context, "vkInitializePerformanceApiINTEL"); + table->vkQueueSetPerformanceConfigurationINTEL = (PFN_vkQueueSetPerformanceConfigurationINTEL)load(context, "vkQueueSetPerformanceConfigurationINTEL"); + table->vkReleasePerformanceConfigurationINTEL = (PFN_vkReleasePerformanceConfigurationINTEL)load(context, "vkReleasePerformanceConfigurationINTEL"); + table->vkUninitializePerformanceApiINTEL = (PFN_vkUninitializePerformanceApiINTEL)load(context, "vkUninitializePerformanceApiINTEL"); +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) + table->vkBuildAccelerationStructuresKHR = (PFN_vkBuildAccelerationStructuresKHR)load(context, "vkBuildAccelerationStructuresKHR"); + table->vkCmdBuildAccelerationStructuresIndirectKHR = (PFN_vkCmdBuildAccelerationStructuresIndirectKHR)load(context, "vkCmdBuildAccelerationStructuresIndirectKHR"); + table->vkCmdBuildAccelerationStructuresKHR = (PFN_vkCmdBuildAccelerationStructuresKHR)load(context, "vkCmdBuildAccelerationStructuresKHR"); + table->vkCmdCopyAccelerationStructureKHR = (PFN_vkCmdCopyAccelerationStructureKHR)load(context, "vkCmdCopyAccelerationStructureKHR"); + table->vkCmdCopyAccelerationStructureToMemoryKHR = (PFN_vkCmdCopyAccelerationStructureToMemoryKHR)load(context, "vkCmdCopyAccelerationStructureToMemoryKHR"); + table->vkCmdCopyMemoryToAccelerationStructureKHR = (PFN_vkCmdCopyMemoryToAccelerationStructureKHR)load(context, "vkCmdCopyMemoryToAccelerationStructureKHR"); + table->vkCmdWriteAccelerationStructuresPropertiesKHR = (PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)load(context, "vkCmdWriteAccelerationStructuresPropertiesKHR"); + table->vkCopyAccelerationStructureKHR = (PFN_vkCopyAccelerationStructureKHR)load(context, "vkCopyAccelerationStructureKHR"); + table->vkCopyAccelerationStructureToMemoryKHR = (PFN_vkCopyAccelerationStructureToMemoryKHR)load(context, "vkCopyAccelerationStructureToMemoryKHR"); + table->vkCopyMemoryToAccelerationStructureKHR = (PFN_vkCopyMemoryToAccelerationStructureKHR)load(context, "vkCopyMemoryToAccelerationStructureKHR"); + table->vkCreateAccelerationStructureKHR = (PFN_vkCreateAccelerationStructureKHR)load(context, "vkCreateAccelerationStructureKHR"); + table->vkDestroyAccelerationStructureKHR = (PFN_vkDestroyAccelerationStructureKHR)load(context, "vkDestroyAccelerationStructureKHR"); + table->vkGetAccelerationStructureBuildSizesKHR = (PFN_vkGetAccelerationStructureBuildSizesKHR)load(context, "vkGetAccelerationStructureBuildSizesKHR"); + table->vkGetAccelerationStructureDeviceAddressKHR = (PFN_vkGetAccelerationStructureDeviceAddressKHR)load(context, "vkGetAccelerationStructureDeviceAddressKHR"); + table->vkGetDeviceAccelerationStructureCompatibilityKHR = (PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)load(context, "vkGetDeviceAccelerationStructureCompatibilityKHR"); + table->vkWriteAccelerationStructuresPropertiesKHR = (PFN_vkWriteAccelerationStructuresPropertiesKHR)load(context, "vkWriteAccelerationStructuresPropertiesKHR"); +#endif /* defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_bind_memory2) + table->vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2KHR)load(context, "vkBindBufferMemory2KHR"); + table->vkBindImageMemory2KHR = (PFN_vkBindImageMemory2KHR)load(context, "vkBindImageMemory2KHR"); +#endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) + table->vkGetBufferDeviceAddressKHR = (PFN_vkGetBufferDeviceAddressKHR)load(context, "vkGetBufferDeviceAddressKHR"); + table->vkGetBufferOpaqueCaptureAddressKHR = (PFN_vkGetBufferOpaqueCaptureAddressKHR)load(context, "vkGetBufferOpaqueCaptureAddressKHR"); + table->vkGetDeviceMemoryOpaqueCaptureAddressKHR = (PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)load(context, "vkGetDeviceMemoryOpaqueCaptureAddressKHR"); +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_calibrated_timestamps) + table->vkGetCalibratedTimestampsKHR = (PFN_vkGetCalibratedTimestampsKHR)load(context, "vkGetCalibratedTimestampsKHR"); +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_copy_commands2) + table->vkCmdBlitImage2KHR = (PFN_vkCmdBlitImage2KHR)load(context, "vkCmdBlitImage2KHR"); + table->vkCmdCopyBuffer2KHR = (PFN_vkCmdCopyBuffer2KHR)load(context, "vkCmdCopyBuffer2KHR"); + table->vkCmdCopyBufferToImage2KHR = (PFN_vkCmdCopyBufferToImage2KHR)load(context, "vkCmdCopyBufferToImage2KHR"); + table->vkCmdCopyImage2KHR = (PFN_vkCmdCopyImage2KHR)load(context, "vkCmdCopyImage2KHR"); + table->vkCmdCopyImageToBuffer2KHR = (PFN_vkCmdCopyImageToBuffer2KHR)load(context, "vkCmdCopyImageToBuffer2KHR"); + table->vkCmdResolveImage2KHR = (PFN_vkCmdResolveImage2KHR)load(context, "vkCmdResolveImage2KHR"); +#endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) + table->vkCmdCopyMemoryIndirectKHR = (PFN_vkCmdCopyMemoryIndirectKHR)load(context, "vkCmdCopyMemoryIndirectKHR"); + table->vkCmdCopyMemoryToImageIndirectKHR = (PFN_vkCmdCopyMemoryToImageIndirectKHR)load(context, "vkCmdCopyMemoryToImageIndirectKHR"); +#endif /* defined(VK_KHR_copy_memory_indirect) */ +#if defined(VK_KHR_create_renderpass2) + table->vkCmdBeginRenderPass2KHR = (PFN_vkCmdBeginRenderPass2KHR)load(context, "vkCmdBeginRenderPass2KHR"); + table->vkCmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)load(context, "vkCmdEndRenderPass2KHR"); + table->vkCmdNextSubpass2KHR = (PFN_vkCmdNextSubpass2KHR)load(context, "vkCmdNextSubpass2KHR"); + table->vkCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)load(context, "vkCreateRenderPass2KHR"); +#endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) + table->vkCreateDeferredOperationKHR = (PFN_vkCreateDeferredOperationKHR)load(context, "vkCreateDeferredOperationKHR"); + table->vkDeferredOperationJoinKHR = (PFN_vkDeferredOperationJoinKHR)load(context, "vkDeferredOperationJoinKHR"); + table->vkDestroyDeferredOperationKHR = (PFN_vkDestroyDeferredOperationKHR)load(context, "vkDestroyDeferredOperationKHR"); + table->vkGetDeferredOperationMaxConcurrencyKHR = (PFN_vkGetDeferredOperationMaxConcurrencyKHR)load(context, "vkGetDeferredOperationMaxConcurrencyKHR"); + table->vkGetDeferredOperationResultKHR = (PFN_vkGetDeferredOperationResultKHR)load(context, "vkGetDeferredOperationResultKHR"); +#endif /* defined(VK_KHR_deferred_host_operations) */ +#if defined(VK_KHR_descriptor_update_template) + table->vkCreateDescriptorUpdateTemplateKHR = (PFN_vkCreateDescriptorUpdateTemplateKHR)load(context, "vkCreateDescriptorUpdateTemplateKHR"); + table->vkDestroyDescriptorUpdateTemplateKHR = (PFN_vkDestroyDescriptorUpdateTemplateKHR)load(context, "vkDestroyDescriptorUpdateTemplateKHR"); + table->vkUpdateDescriptorSetWithTemplateKHR = (PFN_vkUpdateDescriptorSetWithTemplateKHR)load(context, "vkUpdateDescriptorSetWithTemplateKHR"); +#endif /* defined(VK_KHR_descriptor_update_template) */ +#if defined(VK_KHR_device_address_commands) + table->vkCmdBindIndexBuffer3KHR = (PFN_vkCmdBindIndexBuffer3KHR)load(context, "vkCmdBindIndexBuffer3KHR"); + table->vkCmdBindVertexBuffers3KHR = (PFN_vkCmdBindVertexBuffers3KHR)load(context, "vkCmdBindVertexBuffers3KHR"); + table->vkCmdCopyImageToMemoryKHR = (PFN_vkCmdCopyImageToMemoryKHR)load(context, "vkCmdCopyImageToMemoryKHR"); + table->vkCmdCopyMemoryKHR = (PFN_vkCmdCopyMemoryKHR)load(context, "vkCmdCopyMemoryKHR"); + table->vkCmdCopyMemoryToImageKHR = (PFN_vkCmdCopyMemoryToImageKHR)load(context, "vkCmdCopyMemoryToImageKHR"); + table->vkCmdCopyQueryPoolResultsToMemoryKHR = (PFN_vkCmdCopyQueryPoolResultsToMemoryKHR)load(context, "vkCmdCopyQueryPoolResultsToMemoryKHR"); + table->vkCmdDispatchIndirect2KHR = (PFN_vkCmdDispatchIndirect2KHR)load(context, "vkCmdDispatchIndirect2KHR"); + table->vkCmdDrawIndexedIndirect2KHR = (PFN_vkCmdDrawIndexedIndirect2KHR)load(context, "vkCmdDrawIndexedIndirect2KHR"); + table->vkCmdDrawIndirect2KHR = (PFN_vkCmdDrawIndirect2KHR)load(context, "vkCmdDrawIndirect2KHR"); + table->vkCmdFillMemoryKHR = (PFN_vkCmdFillMemoryKHR)load(context, "vkCmdFillMemoryKHR"); + table->vkCmdUpdateMemoryKHR = (PFN_vkCmdUpdateMemoryKHR)load(context, "vkCmdUpdateMemoryKHR"); +#endif /* defined(VK_KHR_device_address_commands) */ +#if defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) + table->vkCmdDrawIndexedIndirectCount2KHR = (PFN_vkCmdDrawIndexedIndirectCount2KHR)load(context, "vkCmdDrawIndexedIndirectCount2KHR"); + table->vkCmdDrawIndirectCount2KHR = (PFN_vkCmdDrawIndirectCount2KHR)load(context, "vkCmdDrawIndirectCount2KHR"); +#endif /* defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) + table->vkCmdBeginConditionalRendering2EXT = (PFN_vkCmdBeginConditionalRendering2EXT)load(context, "vkCmdBeginConditionalRendering2EXT"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) + table->vkCmdBeginTransformFeedback2EXT = (PFN_vkCmdBeginTransformFeedback2EXT)load(context, "vkCmdBeginTransformFeedback2EXT"); + table->vkCmdBindTransformFeedbackBuffers2EXT = (PFN_vkCmdBindTransformFeedbackBuffers2EXT)load(context, "vkCmdBindTransformFeedbackBuffers2EXT"); + table->vkCmdDrawIndirectByteCount2EXT = (PFN_vkCmdDrawIndirectByteCount2EXT)load(context, "vkCmdDrawIndirectByteCount2EXT"); + table->vkCmdEndTransformFeedback2EXT = (PFN_vkCmdEndTransformFeedback2EXT)load(context, "vkCmdEndTransformFeedback2EXT"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) + table->vkCmdDrawMeshTasksIndirect2EXT = (PFN_vkCmdDrawMeshTasksIndirect2EXT)load(context, "vkCmdDrawMeshTasksIndirect2EXT"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) */ +#if defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) + table->vkCmdDrawMeshTasksIndirectCount2EXT = (PFN_vkCmdDrawMeshTasksIndirectCount2EXT)load(context, "vkCmdDrawMeshTasksIndirectCount2EXT"); +#endif /* defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) + table->vkCmdWriteMarkerToMemoryAMD = (PFN_vkCmdWriteMarkerToMemoryAMD)load(context, "vkCmdWriteMarkerToMemoryAMD"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) + table->vkCreateAccelerationStructure2KHR = (PFN_vkCreateAccelerationStructure2KHR)load(context, "vkCreateAccelerationStructure2KHR"); +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_device_fault) + table->vkGetDeviceFaultDebugInfoKHR = (PFN_vkGetDeviceFaultDebugInfoKHR)load(context, "vkGetDeviceFaultDebugInfoKHR"); + table->vkGetDeviceFaultReportsKHR = (PFN_vkGetDeviceFaultReportsKHR)load(context, "vkGetDeviceFaultReportsKHR"); +#endif /* defined(VK_KHR_device_fault) */ +#if defined(VK_KHR_device_group) + table->vkCmdDispatchBaseKHR = (PFN_vkCmdDispatchBaseKHR)load(context, "vkCmdDispatchBaseKHR"); + table->vkCmdSetDeviceMaskKHR = (PFN_vkCmdSetDeviceMaskKHR)load(context, "vkCmdSetDeviceMaskKHR"); + table->vkGetDeviceGroupPeerMemoryFeaturesKHR = (PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)load(context, "vkGetDeviceGroupPeerMemoryFeaturesKHR"); +#endif /* defined(VK_KHR_device_group) */ +#if defined(VK_KHR_display_swapchain) + table->vkCreateSharedSwapchainsKHR = (PFN_vkCreateSharedSwapchainsKHR)load(context, "vkCreateSharedSwapchainsKHR"); +#endif /* defined(VK_KHR_display_swapchain) */ +#if defined(VK_KHR_draw_indirect_count) + table->vkCmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)load(context, "vkCmdDrawIndexedIndirectCountKHR"); + table->vkCmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)load(context, "vkCmdDrawIndirectCountKHR"); +#endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) + table->vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR)load(context, "vkCmdBeginRenderingKHR"); + table->vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR)load(context, "vkCmdEndRenderingKHR"); +#endif /* defined(VK_KHR_dynamic_rendering) */ +#if defined(VK_KHR_dynamic_rendering_local_read) + table->vkCmdSetRenderingAttachmentLocationsKHR = (PFN_vkCmdSetRenderingAttachmentLocationsKHR)load(context, "vkCmdSetRenderingAttachmentLocationsKHR"); + table->vkCmdSetRenderingInputAttachmentIndicesKHR = (PFN_vkCmdSetRenderingInputAttachmentIndicesKHR)load(context, "vkCmdSetRenderingInputAttachmentIndicesKHR"); +#endif /* defined(VK_KHR_dynamic_rendering_local_read) */ +#if defined(VK_KHR_external_fence_fd) + table->vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)load(context, "vkGetFenceFdKHR"); + table->vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)load(context, "vkImportFenceFdKHR"); +#endif /* defined(VK_KHR_external_fence_fd) */ +#if defined(VK_KHR_external_fence_win32) + table->vkGetFenceWin32HandleKHR = (PFN_vkGetFenceWin32HandleKHR)load(context, "vkGetFenceWin32HandleKHR"); + table->vkImportFenceWin32HandleKHR = (PFN_vkImportFenceWin32HandleKHR)load(context, "vkImportFenceWin32HandleKHR"); +#endif /* defined(VK_KHR_external_fence_win32) */ +#if defined(VK_KHR_external_memory_fd) + table->vkGetMemoryFdKHR = (PFN_vkGetMemoryFdKHR)load(context, "vkGetMemoryFdKHR"); + table->vkGetMemoryFdPropertiesKHR = (PFN_vkGetMemoryFdPropertiesKHR)load(context, "vkGetMemoryFdPropertiesKHR"); +#endif /* defined(VK_KHR_external_memory_fd) */ +#if defined(VK_KHR_external_memory_win32) + table->vkGetMemoryWin32HandleKHR = (PFN_vkGetMemoryWin32HandleKHR)load(context, "vkGetMemoryWin32HandleKHR"); + table->vkGetMemoryWin32HandlePropertiesKHR = (PFN_vkGetMemoryWin32HandlePropertiesKHR)load(context, "vkGetMemoryWin32HandlePropertiesKHR"); +#endif /* defined(VK_KHR_external_memory_win32) */ +#if defined(VK_KHR_external_semaphore_fd) + table->vkGetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR)load(context, "vkGetSemaphoreFdKHR"); + table->vkImportSemaphoreFdKHR = (PFN_vkImportSemaphoreFdKHR)load(context, "vkImportSemaphoreFdKHR"); +#endif /* defined(VK_KHR_external_semaphore_fd) */ +#if defined(VK_KHR_external_semaphore_win32) + table->vkGetSemaphoreWin32HandleKHR = (PFN_vkGetSemaphoreWin32HandleKHR)load(context, "vkGetSemaphoreWin32HandleKHR"); + table->vkImportSemaphoreWin32HandleKHR = (PFN_vkImportSemaphoreWin32HandleKHR)load(context, "vkImportSemaphoreWin32HandleKHR"); +#endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) + table->vkCmdSetFragmentShadingRateKHR = (PFN_vkCmdSetFragmentShadingRateKHR)load(context, "vkCmdSetFragmentShadingRateKHR"); +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_memory_requirements2) + table->vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2KHR)load(context, "vkGetBufferMemoryRequirements2KHR"); + table->vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2KHR)load(context, "vkGetImageMemoryRequirements2KHR"); + table->vkGetImageSparseMemoryRequirements2KHR = (PFN_vkGetImageSparseMemoryRequirements2KHR)load(context, "vkGetImageSparseMemoryRequirements2KHR"); +#endif /* defined(VK_KHR_get_memory_requirements2) */ +#if defined(VK_KHR_line_rasterization) + table->vkCmdSetLineStippleKHR = (PFN_vkCmdSetLineStippleKHR)load(context, "vkCmdSetLineStippleKHR"); +#endif /* defined(VK_KHR_line_rasterization) */ +#if defined(VK_KHR_maintenance1) + table->vkTrimCommandPoolKHR = (PFN_vkTrimCommandPoolKHR)load(context, "vkTrimCommandPoolKHR"); +#endif /* defined(VK_KHR_maintenance1) */ +#if defined(VK_KHR_maintenance10) + table->vkCmdEndRendering2KHR = (PFN_vkCmdEndRendering2KHR)load(context, "vkCmdEndRendering2KHR"); +#endif /* defined(VK_KHR_maintenance10) */ +#if defined(VK_KHR_maintenance3) + table->vkGetDescriptorSetLayoutSupportKHR = (PFN_vkGetDescriptorSetLayoutSupportKHR)load(context, "vkGetDescriptorSetLayoutSupportKHR"); +#endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) + table->vkGetDeviceBufferMemoryRequirementsKHR = (PFN_vkGetDeviceBufferMemoryRequirementsKHR)load(context, "vkGetDeviceBufferMemoryRequirementsKHR"); + table->vkGetDeviceImageMemoryRequirementsKHR = (PFN_vkGetDeviceImageMemoryRequirementsKHR)load(context, "vkGetDeviceImageMemoryRequirementsKHR"); + table->vkGetDeviceImageSparseMemoryRequirementsKHR = (PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)load(context, "vkGetDeviceImageSparseMemoryRequirementsKHR"); +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) + table->vkCmdBindIndexBuffer2KHR = (PFN_vkCmdBindIndexBuffer2KHR)load(context, "vkCmdBindIndexBuffer2KHR"); + table->vkGetDeviceImageSubresourceLayoutKHR = (PFN_vkGetDeviceImageSubresourceLayoutKHR)load(context, "vkGetDeviceImageSubresourceLayoutKHR"); + table->vkGetImageSubresourceLayout2KHR = (PFN_vkGetImageSubresourceLayout2KHR)load(context, "vkGetImageSubresourceLayout2KHR"); + table->vkGetRenderingAreaGranularityKHR = (PFN_vkGetRenderingAreaGranularityKHR)load(context, "vkGetRenderingAreaGranularityKHR"); +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_maintenance6) + table->vkCmdBindDescriptorSets2KHR = (PFN_vkCmdBindDescriptorSets2KHR)load(context, "vkCmdBindDescriptorSets2KHR"); + table->vkCmdPushConstants2KHR = (PFN_vkCmdPushConstants2KHR)load(context, "vkCmdPushConstants2KHR"); +#endif /* defined(VK_KHR_maintenance6) */ +#if defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) + table->vkCmdPushDescriptorSet2KHR = (PFN_vkCmdPushDescriptorSet2KHR)load(context, "vkCmdPushDescriptorSet2KHR"); + table->vkCmdPushDescriptorSetWithTemplate2KHR = (PFN_vkCmdPushDescriptorSetWithTemplate2KHR)load(context, "vkCmdPushDescriptorSetWithTemplate2KHR"); +#endif /* defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) + table->vkCmdBindDescriptorBufferEmbeddedSamplers2EXT = (PFN_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT)load(context, "vkCmdBindDescriptorBufferEmbeddedSamplers2EXT"); + table->vkCmdSetDescriptorBufferOffsets2EXT = (PFN_vkCmdSetDescriptorBufferOffsets2EXT)load(context, "vkCmdSetDescriptorBufferOffsets2EXT"); +#endif /* defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_KHR_map_memory2) + table->vkMapMemory2KHR = (PFN_vkMapMemory2KHR)load(context, "vkMapMemory2KHR"); + table->vkUnmapMemory2KHR = (PFN_vkUnmapMemory2KHR)load(context, "vkUnmapMemory2KHR"); +#endif /* defined(VK_KHR_map_memory2) */ +#if defined(VK_KHR_performance_query) + table->vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); + table->vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) + table->vkCreatePipelineBinariesKHR = (PFN_vkCreatePipelineBinariesKHR)load(context, "vkCreatePipelineBinariesKHR"); + table->vkDestroyPipelineBinaryKHR = (PFN_vkDestroyPipelineBinaryKHR)load(context, "vkDestroyPipelineBinaryKHR"); + table->vkGetPipelineBinaryDataKHR = (PFN_vkGetPipelineBinaryDataKHR)load(context, "vkGetPipelineBinaryDataKHR"); + table->vkGetPipelineKeyKHR = (PFN_vkGetPipelineKeyKHR)load(context, "vkGetPipelineKeyKHR"); + table->vkReleaseCapturedPipelineDataKHR = (PFN_vkReleaseCapturedPipelineDataKHR)load(context, "vkReleaseCapturedPipelineDataKHR"); +#endif /* defined(VK_KHR_pipeline_binary) */ +#if defined(VK_KHR_pipeline_executable_properties) + table->vkGetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)load(context, "vkGetPipelineExecutableInternalRepresentationsKHR"); + table->vkGetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)load(context, "vkGetPipelineExecutablePropertiesKHR"); + table->vkGetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR)load(context, "vkGetPipelineExecutableStatisticsKHR"); +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) + table->vkWaitForPresentKHR = (PFN_vkWaitForPresentKHR)load(context, "vkWaitForPresentKHR"); +#endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) + table->vkWaitForPresent2KHR = (PFN_vkWaitForPresent2KHR)load(context, "vkWaitForPresent2KHR"); +#endif /* defined(VK_KHR_present_wait2) */ +#if defined(VK_KHR_push_descriptor) + table->vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)load(context, "vkCmdPushDescriptorSetKHR"); +#endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) + table->vkCmdTraceRaysIndirect2KHR = (PFN_vkCmdTraceRaysIndirect2KHR)load(context, "vkCmdTraceRaysIndirect2KHR"); +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_ray_tracing_pipeline) + table->vkCmdSetRayTracingPipelineStackSizeKHR = (PFN_vkCmdSetRayTracingPipelineStackSizeKHR)load(context, "vkCmdSetRayTracingPipelineStackSizeKHR"); + table->vkCmdTraceRaysIndirectKHR = (PFN_vkCmdTraceRaysIndirectKHR)load(context, "vkCmdTraceRaysIndirectKHR"); + table->vkCmdTraceRaysKHR = (PFN_vkCmdTraceRaysKHR)load(context, "vkCmdTraceRaysKHR"); + table->vkCreateRayTracingPipelinesKHR = (PFN_vkCreateRayTracingPipelinesKHR)load(context, "vkCreateRayTracingPipelinesKHR"); + table->vkGetRayTracingCaptureReplayShaderGroupHandlesKHR = (PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)load(context, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR"); + table->vkGetRayTracingShaderGroupHandlesKHR = (PFN_vkGetRayTracingShaderGroupHandlesKHR)load(context, "vkGetRayTracingShaderGroupHandlesKHR"); + table->vkGetRayTracingShaderGroupStackSizeKHR = (PFN_vkGetRayTracingShaderGroupStackSizeKHR)load(context, "vkGetRayTracingShaderGroupStackSizeKHR"); +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_sampler_ycbcr_conversion) + table->vkCreateSamplerYcbcrConversionKHR = (PFN_vkCreateSamplerYcbcrConversionKHR)load(context, "vkCreateSamplerYcbcrConversionKHR"); + table->vkDestroySamplerYcbcrConversionKHR = (PFN_vkDestroySamplerYcbcrConversionKHR)load(context, "vkDestroySamplerYcbcrConversionKHR"); +#endif /* defined(VK_KHR_sampler_ycbcr_conversion) */ +#if defined(VK_KHR_shared_presentable_image) + table->vkGetSwapchainStatusKHR = (PFN_vkGetSwapchainStatusKHR)load(context, "vkGetSwapchainStatusKHR"); +#endif /* defined(VK_KHR_shared_presentable_image) */ +#if defined(VK_KHR_swapchain) + table->vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)load(context, "vkAcquireNextImageKHR"); + table->vkCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)load(context, "vkCreateSwapchainKHR"); + table->vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)load(context, "vkDestroySwapchainKHR"); + table->vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)load(context, "vkGetSwapchainImagesKHR"); + table->vkQueuePresentKHR = (PFN_vkQueuePresentKHR)load(context, "vkQueuePresentKHR"); +#endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) + table->vkReleaseSwapchainImagesKHR = (PFN_vkReleaseSwapchainImagesKHR)load(context, "vkReleaseSwapchainImagesKHR"); +#endif /* defined(VK_KHR_swapchain_maintenance1) */ +#if defined(VK_KHR_synchronization2) + table->vkCmdPipelineBarrier2KHR = (PFN_vkCmdPipelineBarrier2KHR)load(context, "vkCmdPipelineBarrier2KHR"); + table->vkCmdResetEvent2KHR = (PFN_vkCmdResetEvent2KHR)load(context, "vkCmdResetEvent2KHR"); + table->vkCmdSetEvent2KHR = (PFN_vkCmdSetEvent2KHR)load(context, "vkCmdSetEvent2KHR"); + table->vkCmdWaitEvents2KHR = (PFN_vkCmdWaitEvents2KHR)load(context, "vkCmdWaitEvents2KHR"); + table->vkCmdWriteTimestamp2KHR = (PFN_vkCmdWriteTimestamp2KHR)load(context, "vkCmdWriteTimestamp2KHR"); + table->vkQueueSubmit2KHR = (PFN_vkQueueSubmit2KHR)load(context, "vkQueueSubmit2KHR"); +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_timeline_semaphore) + table->vkGetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)load(context, "vkGetSemaphoreCounterValueKHR"); + table->vkSignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)load(context, "vkSignalSemaphoreKHR"); + table->vkWaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR)load(context, "vkWaitSemaphoresKHR"); +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) + table->vkCmdDecodeVideoKHR = (PFN_vkCmdDecodeVideoKHR)load(context, "vkCmdDecodeVideoKHR"); +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) + table->vkCmdEncodeVideoKHR = (PFN_vkCmdEncodeVideoKHR)load(context, "vkCmdEncodeVideoKHR"); + table->vkGetEncodedVideoSessionParametersKHR = (PFN_vkGetEncodedVideoSessionParametersKHR)load(context, "vkGetEncodedVideoSessionParametersKHR"); +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) + table->vkBindVideoSessionMemoryKHR = (PFN_vkBindVideoSessionMemoryKHR)load(context, "vkBindVideoSessionMemoryKHR"); + table->vkCmdBeginVideoCodingKHR = (PFN_vkCmdBeginVideoCodingKHR)load(context, "vkCmdBeginVideoCodingKHR"); + table->vkCmdControlVideoCodingKHR = (PFN_vkCmdControlVideoCodingKHR)load(context, "vkCmdControlVideoCodingKHR"); + table->vkCmdEndVideoCodingKHR = (PFN_vkCmdEndVideoCodingKHR)load(context, "vkCmdEndVideoCodingKHR"); + table->vkCreateVideoSessionKHR = (PFN_vkCreateVideoSessionKHR)load(context, "vkCreateVideoSessionKHR"); + table->vkCreateVideoSessionParametersKHR = (PFN_vkCreateVideoSessionParametersKHR)load(context, "vkCreateVideoSessionParametersKHR"); + table->vkDestroyVideoSessionKHR = (PFN_vkDestroyVideoSessionKHR)load(context, "vkDestroyVideoSessionKHR"); + table->vkDestroyVideoSessionParametersKHR = (PFN_vkDestroyVideoSessionParametersKHR)load(context, "vkDestroyVideoSessionParametersKHR"); + table->vkGetVideoSessionMemoryRequirementsKHR = (PFN_vkGetVideoSessionMemoryRequirementsKHR)load(context, "vkGetVideoSessionMemoryRequirementsKHR"); + table->vkUpdateVideoSessionParametersKHR = (PFN_vkUpdateVideoSessionParametersKHR)load(context, "vkUpdateVideoSessionParametersKHR"); +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_NVX_binary_import) + table->vkCmdCuLaunchKernelNVX = (PFN_vkCmdCuLaunchKernelNVX)load(context, "vkCmdCuLaunchKernelNVX"); + table->vkCreateCuFunctionNVX = (PFN_vkCreateCuFunctionNVX)load(context, "vkCreateCuFunctionNVX"); + table->vkCreateCuModuleNVX = (PFN_vkCreateCuModuleNVX)load(context, "vkCreateCuModuleNVX"); + table->vkDestroyCuFunctionNVX = (PFN_vkDestroyCuFunctionNVX)load(context, "vkDestroyCuFunctionNVX"); + table->vkDestroyCuModuleNVX = (PFN_vkDestroyCuModuleNVX)load(context, "vkDestroyCuModuleNVX"); +#endif /* defined(VK_NVX_binary_import) */ +#if defined(VK_NVX_image_view_handle) + table->vkGetImageViewHandleNVX = (PFN_vkGetImageViewHandleNVX)load(context, "vkGetImageViewHandleNVX"); +#endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 + table->vkGetImageViewHandle64NVX = (PFN_vkGetImageViewHandle64NVX)load(context, "vkGetImageViewHandle64NVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 + table->vkGetImageViewAddressNVX = (PFN_vkGetImageViewAddressNVX)load(context, "vkGetImageViewAddressNVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 + table->vkGetDeviceCombinedImageSamplerIndexNVX = (PFN_vkGetDeviceCombinedImageSamplerIndexNVX)load(context, "vkGetDeviceCombinedImageSamplerIndexNVX"); +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 */ +#if defined(VK_NV_clip_space_w_scaling) + table->vkCmdSetViewportWScalingNV = (PFN_vkCmdSetViewportWScalingNV)load(context, "vkCmdSetViewportWScalingNV"); +#endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_cluster_acceleration_structure) + table->vkCmdBuildClusterAccelerationStructureIndirectNV = (PFN_vkCmdBuildClusterAccelerationStructureIndirectNV)load(context, "vkCmdBuildClusterAccelerationStructureIndirectNV"); + table->vkGetClusterAccelerationStructureBuildSizesNV = (PFN_vkGetClusterAccelerationStructureBuildSizesNV)load(context, "vkGetClusterAccelerationStructureBuildSizesNV"); +#endif /* defined(VK_NV_cluster_acceleration_structure) */ +#if defined(VK_NV_compute_occupancy_priority) + table->vkCmdSetComputeOccupancyPriorityNV = (PFN_vkCmdSetComputeOccupancyPriorityNV)load(context, "vkCmdSetComputeOccupancyPriorityNV"); +#endif /* defined(VK_NV_compute_occupancy_priority) */ +#if defined(VK_NV_cooperative_vector) + table->vkCmdConvertCooperativeVectorMatrixNV = (PFN_vkCmdConvertCooperativeVectorMatrixNV)load(context, "vkCmdConvertCooperativeVectorMatrixNV"); + table->vkConvertCooperativeVectorMatrixNV = (PFN_vkConvertCooperativeVectorMatrixNV)load(context, "vkConvertCooperativeVectorMatrixNV"); +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_copy_memory_indirect) + table->vkCmdCopyMemoryIndirectNV = (PFN_vkCmdCopyMemoryIndirectNV)load(context, "vkCmdCopyMemoryIndirectNV"); + table->vkCmdCopyMemoryToImageIndirectNV = (PFN_vkCmdCopyMemoryToImageIndirectNV)load(context, "vkCmdCopyMemoryToImageIndirectNV"); +#endif /* defined(VK_NV_copy_memory_indirect) */ +#if defined(VK_NV_cuda_kernel_launch) + table->vkCmdCudaLaunchKernelNV = (PFN_vkCmdCudaLaunchKernelNV)load(context, "vkCmdCudaLaunchKernelNV"); + table->vkCreateCudaFunctionNV = (PFN_vkCreateCudaFunctionNV)load(context, "vkCreateCudaFunctionNV"); + table->vkCreateCudaModuleNV = (PFN_vkCreateCudaModuleNV)load(context, "vkCreateCudaModuleNV"); + table->vkDestroyCudaFunctionNV = (PFN_vkDestroyCudaFunctionNV)load(context, "vkDestroyCudaFunctionNV"); + table->vkDestroyCudaModuleNV = (PFN_vkDestroyCudaModuleNV)load(context, "vkDestroyCudaModuleNV"); + table->vkGetCudaModuleCacheNV = (PFN_vkGetCudaModuleCacheNV)load(context, "vkGetCudaModuleCacheNV"); +#endif /* defined(VK_NV_cuda_kernel_launch) */ +#if defined(VK_NV_device_diagnostic_checkpoints) + table->vkCmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)load(context, "vkCmdSetCheckpointNV"); + table->vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)load(context, "vkGetQueueCheckpointDataNV"); +#endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + table->vkGetQueueCheckpointData2NV = (PFN_vkGetQueueCheckpointData2NV)load(context, "vkGetQueueCheckpointData2NV"); +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_NV_device_generated_commands) + table->vkCmdBindPipelineShaderGroupNV = (PFN_vkCmdBindPipelineShaderGroupNV)load(context, "vkCmdBindPipelineShaderGroupNV"); + table->vkCmdExecuteGeneratedCommandsNV = (PFN_vkCmdExecuteGeneratedCommandsNV)load(context, "vkCmdExecuteGeneratedCommandsNV"); + table->vkCmdPreprocessGeneratedCommandsNV = (PFN_vkCmdPreprocessGeneratedCommandsNV)load(context, "vkCmdPreprocessGeneratedCommandsNV"); + table->vkCreateIndirectCommandsLayoutNV = (PFN_vkCreateIndirectCommandsLayoutNV)load(context, "vkCreateIndirectCommandsLayoutNV"); + table->vkDestroyIndirectCommandsLayoutNV = (PFN_vkDestroyIndirectCommandsLayoutNV)load(context, "vkDestroyIndirectCommandsLayoutNV"); + table->vkGetGeneratedCommandsMemoryRequirementsNV = (PFN_vkGetGeneratedCommandsMemoryRequirementsNV)load(context, "vkGetGeneratedCommandsMemoryRequirementsNV"); +#endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) + table->vkCmdUpdatePipelineIndirectBufferNV = (PFN_vkCmdUpdatePipelineIndirectBufferNV)load(context, "vkCmdUpdatePipelineIndirectBufferNV"); + table->vkGetPipelineIndirectDeviceAddressNV = (PFN_vkGetPipelineIndirectDeviceAddressNV)load(context, "vkGetPipelineIndirectDeviceAddressNV"); + table->vkGetPipelineIndirectMemoryRequirementsNV = (PFN_vkGetPipelineIndirectMemoryRequirementsNV)load(context, "vkGetPipelineIndirectMemoryRequirementsNV"); +#endif /* defined(VK_NV_device_generated_commands_compute) */ +#if defined(VK_NV_external_compute_queue) + table->vkCreateExternalComputeQueueNV = (PFN_vkCreateExternalComputeQueueNV)load(context, "vkCreateExternalComputeQueueNV"); + table->vkDestroyExternalComputeQueueNV = (PFN_vkDestroyExternalComputeQueueNV)load(context, "vkDestroyExternalComputeQueueNV"); + table->vkGetExternalComputeQueueDataNV = (PFN_vkGetExternalComputeQueueDataNV)load(context, "vkGetExternalComputeQueueDataNV"); +#endif /* defined(VK_NV_external_compute_queue) */ +#if defined(VK_NV_external_memory_rdma) + table->vkGetMemoryRemoteAddressNV = (PFN_vkGetMemoryRemoteAddressNV)load(context, "vkGetMemoryRemoteAddressNV"); +#endif /* defined(VK_NV_external_memory_rdma) */ +#if defined(VK_NV_external_memory_win32) + table->vkGetMemoryWin32HandleNV = (PFN_vkGetMemoryWin32HandleNV)load(context, "vkGetMemoryWin32HandleNV"); +#endif /* defined(VK_NV_external_memory_win32) */ +#if defined(VK_NV_fragment_shading_rate_enums) + table->vkCmdSetFragmentShadingRateEnumNV = (PFN_vkCmdSetFragmentShadingRateEnumNV)load(context, "vkCmdSetFragmentShadingRateEnumNV"); +#endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) + table->vkGetLatencyTimingsNV = (PFN_vkGetLatencyTimingsNV)load(context, "vkGetLatencyTimingsNV"); + table->vkLatencySleepNV = (PFN_vkLatencySleepNV)load(context, "vkLatencySleepNV"); + table->vkQueueNotifyOutOfBandNV = (PFN_vkQueueNotifyOutOfBandNV)load(context, "vkQueueNotifyOutOfBandNV"); + table->vkSetLatencyMarkerNV = (PFN_vkSetLatencyMarkerNV)load(context, "vkSetLatencyMarkerNV"); + table->vkSetLatencySleepModeNV = (PFN_vkSetLatencySleepModeNV)load(context, "vkSetLatencySleepModeNV"); +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) + table->vkCmdDecompressMemoryIndirectCountNV = (PFN_vkCmdDecompressMemoryIndirectCountNV)load(context, "vkCmdDecompressMemoryIndirectCountNV"); + table->vkCmdDecompressMemoryNV = (PFN_vkCmdDecompressMemoryNV)load(context, "vkCmdDecompressMemoryNV"); +#endif /* defined(VK_NV_memory_decompression) */ +#if defined(VK_NV_mesh_shader) + table->vkCmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)load(context, "vkCmdDrawMeshTasksIndirectNV"); + table->vkCmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV)load(context, "vkCmdDrawMeshTasksNV"); +#endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + table->vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_NV_optical_flow) + table->vkBindOpticalFlowSessionImageNV = (PFN_vkBindOpticalFlowSessionImageNV)load(context, "vkBindOpticalFlowSessionImageNV"); + table->vkCmdOpticalFlowExecuteNV = (PFN_vkCmdOpticalFlowExecuteNV)load(context, "vkCmdOpticalFlowExecuteNV"); + table->vkCreateOpticalFlowSessionNV = (PFN_vkCreateOpticalFlowSessionNV)load(context, "vkCreateOpticalFlowSessionNV"); + table->vkDestroyOpticalFlowSessionNV = (PFN_vkDestroyOpticalFlowSessionNV)load(context, "vkDestroyOpticalFlowSessionNV"); +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) + table->vkCmdBuildPartitionedAccelerationStructuresNV = (PFN_vkCmdBuildPartitionedAccelerationStructuresNV)load(context, "vkCmdBuildPartitionedAccelerationStructuresNV"); + table->vkGetPartitionedAccelerationStructuresBuildSizesNV = (PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV)load(context, "vkGetPartitionedAccelerationStructuresBuildSizesNV"); +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ +#if defined(VK_NV_ray_tracing) + table->vkBindAccelerationStructureMemoryNV = (PFN_vkBindAccelerationStructureMemoryNV)load(context, "vkBindAccelerationStructureMemoryNV"); + table->vkCmdBuildAccelerationStructureNV = (PFN_vkCmdBuildAccelerationStructureNV)load(context, "vkCmdBuildAccelerationStructureNV"); + table->vkCmdCopyAccelerationStructureNV = (PFN_vkCmdCopyAccelerationStructureNV)load(context, "vkCmdCopyAccelerationStructureNV"); + table->vkCmdTraceRaysNV = (PFN_vkCmdTraceRaysNV)load(context, "vkCmdTraceRaysNV"); + table->vkCmdWriteAccelerationStructuresPropertiesNV = (PFN_vkCmdWriteAccelerationStructuresPropertiesNV)load(context, "vkCmdWriteAccelerationStructuresPropertiesNV"); + table->vkCompileDeferredNV = (PFN_vkCompileDeferredNV)load(context, "vkCompileDeferredNV"); + table->vkCreateAccelerationStructureNV = (PFN_vkCreateAccelerationStructureNV)load(context, "vkCreateAccelerationStructureNV"); + table->vkCreateRayTracingPipelinesNV = (PFN_vkCreateRayTracingPipelinesNV)load(context, "vkCreateRayTracingPipelinesNV"); + table->vkDestroyAccelerationStructureNV = (PFN_vkDestroyAccelerationStructureNV)load(context, "vkDestroyAccelerationStructureNV"); + table->vkGetAccelerationStructureHandleNV = (PFN_vkGetAccelerationStructureHandleNV)load(context, "vkGetAccelerationStructureHandleNV"); + table->vkGetAccelerationStructureMemoryRequirementsNV = (PFN_vkGetAccelerationStructureMemoryRequirementsNV)load(context, "vkGetAccelerationStructureMemoryRequirementsNV"); + table->vkGetRayTracingShaderGroupHandlesNV = (PFN_vkGetRayTracingShaderGroupHandlesNV)load(context, "vkGetRayTracingShaderGroupHandlesNV"); +#endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 + table->vkCmdSetExclusiveScissorEnableNV = (PFN_vkCmdSetExclusiveScissorEnableNV)load(context, "vkCmdSetExclusiveScissorEnableNV"); +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ +#if defined(VK_NV_scissor_exclusive) + table->vkCmdSetExclusiveScissorNV = (PFN_vkCmdSetExclusiveScissorNV)load(context, "vkCmdSetExclusiveScissorNV"); +#endif /* defined(VK_NV_scissor_exclusive) */ +#if defined(VK_NV_shading_rate_image) + table->vkCmdBindShadingRateImageNV = (PFN_vkCmdBindShadingRateImageNV)load(context, "vkCmdBindShadingRateImageNV"); + table->vkCmdSetCoarseSampleOrderNV = (PFN_vkCmdSetCoarseSampleOrderNV)load(context, "vkCmdSetCoarseSampleOrderNV"); + table->vkCmdSetViewportShadingRatePaletteNV = (PFN_vkCmdSetViewportShadingRatePaletteNV)load(context, "vkCmdSetViewportShadingRatePaletteNV"); +#endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_OHOS_external_memory) + table->vkGetMemoryNativeBufferOHOS = (PFN_vkGetMemoryNativeBufferOHOS)load(context, "vkGetMemoryNativeBufferOHOS"); + table->vkGetNativeBufferPropertiesOHOS = (PFN_vkGetNativeBufferPropertiesOHOS)load(context, "vkGetNativeBufferPropertiesOHOS"); +#endif /* defined(VK_OHOS_external_memory) */ +#if defined(VK_QCOM_queue_perf_hint) + table->vkQueueSetPerfHintQCOM = (PFN_vkQueueSetPerfHintQCOM)load(context, "vkQueueSetPerfHintQCOM"); +#endif /* defined(VK_QCOM_queue_perf_hint) */ +#if defined(VK_QCOM_tile_memory_heap) + table->vkCmdBindTileMemoryQCOM = (PFN_vkCmdBindTileMemoryQCOM)load(context, "vkCmdBindTileMemoryQCOM"); +#endif /* defined(VK_QCOM_tile_memory_heap) */ +#if defined(VK_QCOM_tile_properties) + table->vkGetDynamicRenderingTilePropertiesQCOM = (PFN_vkGetDynamicRenderingTilePropertiesQCOM)load(context, "vkGetDynamicRenderingTilePropertiesQCOM"); + table->vkGetFramebufferTilePropertiesQCOM = (PFN_vkGetFramebufferTilePropertiesQCOM)load(context, "vkGetFramebufferTilePropertiesQCOM"); +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) + table->vkCmdBeginPerTileExecutionQCOM = (PFN_vkCmdBeginPerTileExecutionQCOM)load(context, "vkCmdBeginPerTileExecutionQCOM"); + table->vkCmdDispatchTileQCOM = (PFN_vkCmdDispatchTileQCOM)load(context, "vkCmdDispatchTileQCOM"); + table->vkCmdEndPerTileExecutionQCOM = (PFN_vkCmdEndPerTileExecutionQCOM)load(context, "vkCmdEndPerTileExecutionQCOM"); +#endif /* defined(VK_QCOM_tile_shading) */ +#if defined(VK_QNX_external_memory_screen_buffer) + table->vkGetScreenBufferPropertiesQNX = (PFN_vkGetScreenBufferPropertiesQNX)load(context, "vkGetScreenBufferPropertiesQNX"); +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) + table->vkGetDescriptorSetHostMappingVALVE = (PFN_vkGetDescriptorSetHostMappingVALVE)load(context, "vkGetDescriptorSetHostMappingVALVE"); + table->vkGetDescriptorSetLayoutHostMappingInfoVALVE = (PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)load(context, "vkGetDescriptorSetLayoutHostMappingInfoVALVE"); +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) + table->vkCmdSetDepthClampRangeEXT = (PFN_vkCmdSetDepthClampRangeEXT)load(context, "vkCmdSetDepthClampRangeEXT"); +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) + table->vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); + table->vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); + table->vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); + table->vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); + table->vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); + table->vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); + table->vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); + table->vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); + table->vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); + table->vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); + table->vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); + table->vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) + table->vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); + table->vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); + table->vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); + table->vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); + table->vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) + table->vkCmdSetAlphaToCoverageEnableEXT = (PFN_vkCmdSetAlphaToCoverageEnableEXT)load(context, "vkCmdSetAlphaToCoverageEnableEXT"); + table->vkCmdSetAlphaToOneEnableEXT = (PFN_vkCmdSetAlphaToOneEnableEXT)load(context, "vkCmdSetAlphaToOneEnableEXT"); + table->vkCmdSetColorBlendEnableEXT = (PFN_vkCmdSetColorBlendEnableEXT)load(context, "vkCmdSetColorBlendEnableEXT"); + table->vkCmdSetColorBlendEquationEXT = (PFN_vkCmdSetColorBlendEquationEXT)load(context, "vkCmdSetColorBlendEquationEXT"); + table->vkCmdSetColorWriteMaskEXT = (PFN_vkCmdSetColorWriteMaskEXT)load(context, "vkCmdSetColorWriteMaskEXT"); + table->vkCmdSetDepthClampEnableEXT = (PFN_vkCmdSetDepthClampEnableEXT)load(context, "vkCmdSetDepthClampEnableEXT"); + table->vkCmdSetLogicOpEnableEXT = (PFN_vkCmdSetLogicOpEnableEXT)load(context, "vkCmdSetLogicOpEnableEXT"); + table->vkCmdSetPolygonModeEXT = (PFN_vkCmdSetPolygonModeEXT)load(context, "vkCmdSetPolygonModeEXT"); + table->vkCmdSetRasterizationSamplesEXT = (PFN_vkCmdSetRasterizationSamplesEXT)load(context, "vkCmdSetRasterizationSamplesEXT"); + table->vkCmdSetSampleMaskEXT = (PFN_vkCmdSetSampleMaskEXT)load(context, "vkCmdSetSampleMaskEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) + table->vkCmdSetTessellationDomainOriginEXT = (PFN_vkCmdSetTessellationDomainOriginEXT)load(context, "vkCmdSetTessellationDomainOriginEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) + table->vkCmdSetRasterizationStreamEXT = (PFN_vkCmdSetRasterizationStreamEXT)load(context, "vkCmdSetRasterizationStreamEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) + table->vkCmdSetConservativeRasterizationModeEXT = (PFN_vkCmdSetConservativeRasterizationModeEXT)load(context, "vkCmdSetConservativeRasterizationModeEXT"); + table->vkCmdSetExtraPrimitiveOverestimationSizeEXT = (PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)load(context, "vkCmdSetExtraPrimitiveOverestimationSizeEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) + table->vkCmdSetDepthClipEnableEXT = (PFN_vkCmdSetDepthClipEnableEXT)load(context, "vkCmdSetDepthClipEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) + table->vkCmdSetSampleLocationsEnableEXT = (PFN_vkCmdSetSampleLocationsEnableEXT)load(context, "vkCmdSetSampleLocationsEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) + table->vkCmdSetColorBlendAdvancedEXT = (PFN_vkCmdSetColorBlendAdvancedEXT)load(context, "vkCmdSetColorBlendAdvancedEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) + table->vkCmdSetProvokingVertexModeEXT = (PFN_vkCmdSetProvokingVertexModeEXT)load(context, "vkCmdSetProvokingVertexModeEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) + table->vkCmdSetLineRasterizationModeEXT = (PFN_vkCmdSetLineRasterizationModeEXT)load(context, "vkCmdSetLineRasterizationModeEXT"); + table->vkCmdSetLineStippleEnableEXT = (PFN_vkCmdSetLineStippleEnableEXT)load(context, "vkCmdSetLineStippleEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) + table->vkCmdSetDepthClipNegativeOneToOneEXT = (PFN_vkCmdSetDepthClipNegativeOneToOneEXT)load(context, "vkCmdSetDepthClipNegativeOneToOneEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) + table->vkCmdSetViewportWScalingEnableNV = (PFN_vkCmdSetViewportWScalingEnableNV)load(context, "vkCmdSetViewportWScalingEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) + table->vkCmdSetViewportSwizzleNV = (PFN_vkCmdSetViewportSwizzleNV)load(context, "vkCmdSetViewportSwizzleNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) + table->vkCmdSetCoverageToColorEnableNV = (PFN_vkCmdSetCoverageToColorEnableNV)load(context, "vkCmdSetCoverageToColorEnableNV"); + table->vkCmdSetCoverageToColorLocationNV = (PFN_vkCmdSetCoverageToColorLocationNV)load(context, "vkCmdSetCoverageToColorLocationNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) + table->vkCmdSetCoverageModulationModeNV = (PFN_vkCmdSetCoverageModulationModeNV)load(context, "vkCmdSetCoverageModulationModeNV"); + table->vkCmdSetCoverageModulationTableEnableNV = (PFN_vkCmdSetCoverageModulationTableEnableNV)load(context, "vkCmdSetCoverageModulationTableEnableNV"); + table->vkCmdSetCoverageModulationTableNV = (PFN_vkCmdSetCoverageModulationTableNV)load(context, "vkCmdSetCoverageModulationTableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) + table->vkCmdSetShadingRateImageEnableNV = (PFN_vkCmdSetShadingRateImageEnableNV)load(context, "vkCmdSetShadingRateImageEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) + table->vkCmdSetRepresentativeFragmentTestEnableNV = (PFN_vkCmdSetRepresentativeFragmentTestEnableNV)load(context, "vkCmdSetRepresentativeFragmentTestEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) + table->vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) + table->vkGetImageSubresourceLayout2EXT = (PFN_vkGetImageSubresourceLayout2EXT)load(context, "vkGetImageSubresourceLayout2EXT"); +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) + table->vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) + table->vkCmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)load(context, "vkCmdPushDescriptorSetWithTemplateKHR"); +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) + table->vkGetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR)load(context, "vkGetDeviceGroupPresentCapabilitiesKHR"); + table->vkGetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR)load(context, "vkGetDeviceGroupSurfacePresentModesKHR"); +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) + table->vkAcquireNextImage2KHR = (PFN_vkAcquireNextImage2KHR)load(context, "vkAcquireNextImage2KHR"); +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ + /* VOLK_GENERATE_LOAD_DEVICE_TABLE */ +} + +#ifdef __GNUC__ +#ifdef VOLK_DEFAULT_VISIBILITY +# pragma GCC visibility push(default) +#else +# pragma GCC visibility push(hidden) +#endif +#endif + +/* VOLK_GENERATE_PROTOTYPES_C */ +#if defined(VK_VERSION_1_0) +PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; +PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets; +PFN_vkAllocateMemory vkAllocateMemory; +PFN_vkBeginCommandBuffer vkBeginCommandBuffer; +PFN_vkBindBufferMemory vkBindBufferMemory; +PFN_vkBindImageMemory vkBindImageMemory; +PFN_vkCmdBeginQuery vkCmdBeginQuery; +PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; +PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets; +PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; +PFN_vkCmdBindPipeline vkCmdBindPipeline; +PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; +PFN_vkCmdBlitImage vkCmdBlitImage; +PFN_vkCmdClearAttachments vkCmdClearAttachments; +PFN_vkCmdClearColorImage vkCmdClearColorImage; +PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage; +PFN_vkCmdCopyBuffer vkCmdCopyBuffer; +PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; +PFN_vkCmdCopyImage vkCmdCopyImage; +PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer; +PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults; +PFN_vkCmdDispatch vkCmdDispatch; +PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect; +PFN_vkCmdDraw vkCmdDraw; +PFN_vkCmdDrawIndexed vkCmdDrawIndexed; +PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect; +PFN_vkCmdDrawIndirect vkCmdDrawIndirect; +PFN_vkCmdEndQuery vkCmdEndQuery; +PFN_vkCmdEndRenderPass vkCmdEndRenderPass; +PFN_vkCmdExecuteCommands vkCmdExecuteCommands; +PFN_vkCmdFillBuffer vkCmdFillBuffer; +PFN_vkCmdNextSubpass vkCmdNextSubpass; +PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; +PFN_vkCmdPushConstants vkCmdPushConstants; +PFN_vkCmdResetEvent vkCmdResetEvent; +PFN_vkCmdResetQueryPool vkCmdResetQueryPool; +PFN_vkCmdResolveImage vkCmdResolveImage; +PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants; +PFN_vkCmdSetDepthBias vkCmdSetDepthBias; +PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds; +PFN_vkCmdSetEvent vkCmdSetEvent; +PFN_vkCmdSetLineWidth vkCmdSetLineWidth; +PFN_vkCmdSetScissor vkCmdSetScissor; +PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask; +PFN_vkCmdSetStencilReference vkCmdSetStencilReference; +PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask; +PFN_vkCmdSetViewport vkCmdSetViewport; +PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer; +PFN_vkCmdWaitEvents vkCmdWaitEvents; +PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp; +PFN_vkCreateBuffer vkCreateBuffer; +PFN_vkCreateBufferView vkCreateBufferView; +PFN_vkCreateCommandPool vkCreateCommandPool; +PFN_vkCreateComputePipelines vkCreateComputePipelines; +PFN_vkCreateDescriptorPool vkCreateDescriptorPool; +PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout; +PFN_vkCreateDevice vkCreateDevice; +PFN_vkCreateEvent vkCreateEvent; +PFN_vkCreateFence vkCreateFence; +PFN_vkCreateFramebuffer vkCreateFramebuffer; +PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines; +PFN_vkCreateImage vkCreateImage; +PFN_vkCreateImageView vkCreateImageView; +PFN_vkCreateInstance vkCreateInstance; +PFN_vkCreatePipelineCache vkCreatePipelineCache; +PFN_vkCreatePipelineLayout vkCreatePipelineLayout; +PFN_vkCreateQueryPool vkCreateQueryPool; +PFN_vkCreateRenderPass vkCreateRenderPass; +PFN_vkCreateSampler vkCreateSampler; +PFN_vkCreateSemaphore vkCreateSemaphore; +PFN_vkCreateShaderModule vkCreateShaderModule; +PFN_vkDestroyBuffer vkDestroyBuffer; +PFN_vkDestroyBufferView vkDestroyBufferView; +PFN_vkDestroyCommandPool vkDestroyCommandPool; +PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool; +PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout; +PFN_vkDestroyDevice vkDestroyDevice; +PFN_vkDestroyEvent vkDestroyEvent; +PFN_vkDestroyFence vkDestroyFence; +PFN_vkDestroyFramebuffer vkDestroyFramebuffer; +PFN_vkDestroyImage vkDestroyImage; +PFN_vkDestroyImageView vkDestroyImageView; +PFN_vkDestroyInstance vkDestroyInstance; +PFN_vkDestroyPipeline vkDestroyPipeline; +PFN_vkDestroyPipelineCache vkDestroyPipelineCache; +PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout; +PFN_vkDestroyQueryPool vkDestroyQueryPool; +PFN_vkDestroyRenderPass vkDestroyRenderPass; +PFN_vkDestroySampler vkDestroySampler; +PFN_vkDestroySemaphore vkDestroySemaphore; +PFN_vkDestroyShaderModule vkDestroyShaderModule; +PFN_vkDeviceWaitIdle vkDeviceWaitIdle; +PFN_vkEndCommandBuffer vkEndCommandBuffer; +PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; +PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; +PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; +PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; +PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; +PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; +PFN_vkFreeCommandBuffers vkFreeCommandBuffers; +PFN_vkFreeDescriptorSets vkFreeDescriptorSets; +PFN_vkFreeMemory vkFreeMemory; +PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; +PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment; +PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; +PFN_vkGetDeviceQueue vkGetDeviceQueue; +PFN_vkGetEventStatus vkGetEventStatus; +PFN_vkGetFenceStatus vkGetFenceStatus; +PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; +PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements; +PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout; +PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; +PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; +PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties; +PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties; +PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; +PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; +PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; +PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties; +PFN_vkGetPipelineCacheData vkGetPipelineCacheData; +PFN_vkGetQueryPoolResults vkGetQueryPoolResults; +PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity; +PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; +PFN_vkMapMemory vkMapMemory; +PFN_vkMergePipelineCaches vkMergePipelineCaches; +PFN_vkQueueBindSparse vkQueueBindSparse; +PFN_vkQueueSubmit vkQueueSubmit; +PFN_vkQueueWaitIdle vkQueueWaitIdle; +PFN_vkResetCommandBuffer vkResetCommandBuffer; +PFN_vkResetCommandPool vkResetCommandPool; +PFN_vkResetDescriptorPool vkResetDescriptorPool; +PFN_vkResetEvent vkResetEvent; +PFN_vkResetFences vkResetFences; +PFN_vkSetEvent vkSetEvent; +PFN_vkUnmapMemory vkUnmapMemory; +PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets; +PFN_vkWaitForFences vkWaitForFences; +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) +PFN_vkBindBufferMemory2 vkBindBufferMemory2; +PFN_vkBindImageMemory2 vkBindImageMemory2; +PFN_vkCmdDispatchBase vkCmdDispatchBase; +PFN_vkCmdSetDeviceMask vkCmdSetDeviceMask; +PFN_vkCreateDescriptorUpdateTemplate vkCreateDescriptorUpdateTemplate; +PFN_vkCreateSamplerYcbcrConversion vkCreateSamplerYcbcrConversion; +PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate; +PFN_vkDestroySamplerYcbcrConversion vkDestroySamplerYcbcrConversion; +PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; +PFN_vkEnumeratePhysicalDeviceGroups vkEnumeratePhysicalDeviceGroups; +PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2; +PFN_vkGetDescriptorSetLayoutSupport vkGetDescriptorSetLayoutSupport; +PFN_vkGetDeviceGroupPeerMemoryFeatures vkGetDeviceGroupPeerMemoryFeatures; +PFN_vkGetDeviceQueue2 vkGetDeviceQueue2; +PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2; +PFN_vkGetImageSparseMemoryRequirements2 vkGetImageSparseMemoryRequirements2; +PFN_vkGetPhysicalDeviceExternalBufferProperties vkGetPhysicalDeviceExternalBufferProperties; +PFN_vkGetPhysicalDeviceExternalFenceProperties vkGetPhysicalDeviceExternalFenceProperties; +PFN_vkGetPhysicalDeviceExternalSemaphoreProperties vkGetPhysicalDeviceExternalSemaphoreProperties; +PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2; +PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2; +PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2; +PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2; +PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2; +PFN_vkGetPhysicalDeviceQueueFamilyProperties2 vkGetPhysicalDeviceQueueFamilyProperties2; +PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 vkGetPhysicalDeviceSparseImageFormatProperties2; +PFN_vkTrimCommandPool vkTrimCommandPool; +PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate; +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) +PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2; +PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount; +PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount; +PFN_vkCmdEndRenderPass2 vkCmdEndRenderPass2; +PFN_vkCmdNextSubpass2 vkCmdNextSubpass2; +PFN_vkCreateRenderPass2 vkCreateRenderPass2; +PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress; +PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress; +PFN_vkGetDeviceMemoryOpaqueCaptureAddress vkGetDeviceMemoryOpaqueCaptureAddress; +PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue; +PFN_vkResetQueryPool vkResetQueryPool; +PFN_vkSignalSemaphore vkSignalSemaphore; +PFN_vkWaitSemaphores vkWaitSemaphores; +#endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) +PFN_vkCmdBeginRendering vkCmdBeginRendering; +PFN_vkCmdBindVertexBuffers2 vkCmdBindVertexBuffers2; +PFN_vkCmdBlitImage2 vkCmdBlitImage2; +PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2; +PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2; +PFN_vkCmdCopyImage2 vkCmdCopyImage2; +PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2; +PFN_vkCmdEndRendering vkCmdEndRendering; +PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2; +PFN_vkCmdResetEvent2 vkCmdResetEvent2; +PFN_vkCmdResolveImage2 vkCmdResolveImage2; +PFN_vkCmdSetCullMode vkCmdSetCullMode; +PFN_vkCmdSetDepthBiasEnable vkCmdSetDepthBiasEnable; +PFN_vkCmdSetDepthBoundsTestEnable vkCmdSetDepthBoundsTestEnable; +PFN_vkCmdSetDepthCompareOp vkCmdSetDepthCompareOp; +PFN_vkCmdSetDepthTestEnable vkCmdSetDepthTestEnable; +PFN_vkCmdSetDepthWriteEnable vkCmdSetDepthWriteEnable; +PFN_vkCmdSetEvent2 vkCmdSetEvent2; +PFN_vkCmdSetFrontFace vkCmdSetFrontFace; +PFN_vkCmdSetPrimitiveRestartEnable vkCmdSetPrimitiveRestartEnable; +PFN_vkCmdSetPrimitiveTopology vkCmdSetPrimitiveTopology; +PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnable; +PFN_vkCmdSetScissorWithCount vkCmdSetScissorWithCount; +PFN_vkCmdSetStencilOp vkCmdSetStencilOp; +PFN_vkCmdSetStencilTestEnable vkCmdSetStencilTestEnable; +PFN_vkCmdSetViewportWithCount vkCmdSetViewportWithCount; +PFN_vkCmdWaitEvents2 vkCmdWaitEvents2; +PFN_vkCmdWriteTimestamp2 vkCmdWriteTimestamp2; +PFN_vkCreatePrivateDataSlot vkCreatePrivateDataSlot; +PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot; +PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements; +PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements; +PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements; +PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties; +PFN_vkGetPrivateData vkGetPrivateData; +PFN_vkQueueSubmit2 vkQueueSubmit2; +PFN_vkSetPrivateData vkSetPrivateData; +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) +PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2; +PFN_vkCmdBindIndexBuffer2 vkCmdBindIndexBuffer2; +PFN_vkCmdPushConstants2 vkCmdPushConstants2; +PFN_vkCmdPushDescriptorSet vkCmdPushDescriptorSet; +PFN_vkCmdPushDescriptorSet2 vkCmdPushDescriptorSet2; +PFN_vkCmdPushDescriptorSetWithTemplate vkCmdPushDescriptorSetWithTemplate; +PFN_vkCmdPushDescriptorSetWithTemplate2 vkCmdPushDescriptorSetWithTemplate2; +PFN_vkCmdSetLineStipple vkCmdSetLineStipple; +PFN_vkCmdSetRenderingAttachmentLocations vkCmdSetRenderingAttachmentLocations; +PFN_vkCmdSetRenderingInputAttachmentIndices vkCmdSetRenderingInputAttachmentIndices; +PFN_vkCopyImageToImage vkCopyImageToImage; +PFN_vkCopyImageToMemory vkCopyImageToMemory; +PFN_vkCopyMemoryToImage vkCopyMemoryToImage; +PFN_vkGetDeviceImageSubresourceLayout vkGetDeviceImageSubresourceLayout; +PFN_vkGetImageSubresourceLayout2 vkGetImageSubresourceLayout2; +PFN_vkGetRenderingAreaGranularity vkGetRenderingAreaGranularity; +PFN_vkMapMemory2 vkMapMemory2; +PFN_vkTransitionImageLayout vkTransitionImageLayout; +PFN_vkUnmapMemory2 vkUnmapMemory2; +#endif /* defined(VK_VERSION_1_4) */ +#if defined(VK_AMDX_shader_enqueue) +PFN_vkCmdDispatchGraphAMDX vkCmdDispatchGraphAMDX; +PFN_vkCmdDispatchGraphIndirectAMDX vkCmdDispatchGraphIndirectAMDX; +PFN_vkCmdDispatchGraphIndirectCountAMDX vkCmdDispatchGraphIndirectCountAMDX; +PFN_vkCmdInitializeGraphScratchMemoryAMDX vkCmdInitializeGraphScratchMemoryAMDX; +PFN_vkCreateExecutionGraphPipelinesAMDX vkCreateExecutionGraphPipelinesAMDX; +PFN_vkGetExecutionGraphPipelineNodeIndexAMDX vkGetExecutionGraphPipelineNodeIndexAMDX; +PFN_vkGetExecutionGraphPipelineScratchSizeAMDX vkGetExecutionGraphPipelineScratchSizeAMDX; +#endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) +PFN_vkAntiLagUpdateAMD vkAntiLagUpdateAMD; +#endif /* defined(VK_AMD_anti_lag) */ +#if defined(VK_AMD_buffer_marker) +PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; +#endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) +PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_AMD_display_native_hdr) +PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD; +#endif /* defined(VK_AMD_display_native_hdr) */ +#if defined(VK_AMD_draw_indirect_count) +PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD; +PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD; +#endif /* defined(VK_AMD_draw_indirect_count) */ +#if defined(VK_AMD_gpa_interface) +PFN_vkCmdBeginGpaSampleAMD vkCmdBeginGpaSampleAMD; +PFN_vkCmdBeginGpaSessionAMD vkCmdBeginGpaSessionAMD; +PFN_vkCmdCopyGpaSessionResultsAMD vkCmdCopyGpaSessionResultsAMD; +PFN_vkCmdEndGpaSampleAMD vkCmdEndGpaSampleAMD; +PFN_vkCmdEndGpaSessionAMD vkCmdEndGpaSessionAMD; +PFN_vkCreateGpaSessionAMD vkCreateGpaSessionAMD; +PFN_vkDestroyGpaSessionAMD vkDestroyGpaSessionAMD; +PFN_vkGetGpaDeviceClockInfoAMD vkGetGpaDeviceClockInfoAMD; +PFN_vkGetGpaSessionResultsAMD vkGetGpaSessionResultsAMD; +PFN_vkGetGpaSessionStatusAMD vkGetGpaSessionStatusAMD; +PFN_vkResetGpaSessionAMD vkResetGpaSessionAMD; +PFN_vkSetGpaDeviceClockModeAMD vkSetGpaDeviceClockModeAMD; +#endif /* defined(VK_AMD_gpa_interface) */ +#if defined(VK_AMD_shader_info) +PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD; +#endif /* defined(VK_AMD_shader_info) */ +#if defined(VK_ANDROID_external_memory_android_hardware_buffer) +PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; +PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; +#endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_ARM_data_graph) +PFN_vkBindDataGraphPipelineSessionMemoryARM vkBindDataGraphPipelineSessionMemoryARM; +PFN_vkCmdDispatchDataGraphARM vkCmdDispatchDataGraphARM; +PFN_vkCreateDataGraphPipelineSessionARM vkCreateDataGraphPipelineSessionARM; +PFN_vkCreateDataGraphPipelinesARM vkCreateDataGraphPipelinesARM; +PFN_vkDestroyDataGraphPipelineSessionARM vkDestroyDataGraphPipelineSessionARM; +PFN_vkGetDataGraphPipelineAvailablePropertiesARM vkGetDataGraphPipelineAvailablePropertiesARM; +PFN_vkGetDataGraphPipelinePropertiesARM vkGetDataGraphPipelinePropertiesARM; +PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM vkGetDataGraphPipelineSessionBindPointRequirementsARM; +PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM vkGetDataGraphPipelineSessionMemoryRequirementsARM; +PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM; +PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM; +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_data_graph_optical_flow) +PFN_vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM; +#endif /* defined(VK_ARM_data_graph_optical_flow) */ +#if defined(VK_ARM_performance_counters_by_region) +PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM; +#endif /* defined(VK_ARM_performance_counters_by_region) */ +#if defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 +PFN_vkCmdSetDispatchParametersARM vkCmdSetDispatchParametersARM; +#endif /* defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 */ +#if defined(VK_ARM_shader_instrumentation) +PFN_vkClearShaderInstrumentationMetricsARM vkClearShaderInstrumentationMetricsARM; +PFN_vkCmdBeginShaderInstrumentationARM vkCmdBeginShaderInstrumentationARM; +PFN_vkCmdEndShaderInstrumentationARM vkCmdEndShaderInstrumentationARM; +PFN_vkCreateShaderInstrumentationARM vkCreateShaderInstrumentationARM; +PFN_vkDestroyShaderInstrumentationARM vkDestroyShaderInstrumentationARM; +PFN_vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM; +PFN_vkGetShaderInstrumentationValuesARM vkGetShaderInstrumentationValuesARM; +#endif /* defined(VK_ARM_shader_instrumentation) */ +#if defined(VK_ARM_tensors) +PFN_vkBindTensorMemoryARM vkBindTensorMemoryARM; +PFN_vkCmdCopyTensorARM vkCmdCopyTensorARM; +PFN_vkCreateTensorARM vkCreateTensorARM; +PFN_vkCreateTensorViewARM vkCreateTensorViewARM; +PFN_vkDestroyTensorARM vkDestroyTensorARM; +PFN_vkDestroyTensorViewARM vkDestroyTensorViewARM; +PFN_vkGetDeviceTensorMemoryRequirementsARM vkGetDeviceTensorMemoryRequirementsARM; +PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM vkGetPhysicalDeviceExternalTensorPropertiesARM; +PFN_vkGetTensorMemoryRequirementsARM vkGetTensorMemoryRequirementsARM; +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) +PFN_vkGetTensorOpaqueCaptureDescriptorDataARM vkGetTensorOpaqueCaptureDescriptorDataARM; +PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM vkGetTensorViewOpaqueCaptureDescriptorDataARM; +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_acquire_drm_display) +PFN_vkAcquireDrmDisplayEXT vkAcquireDrmDisplayEXT; +PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; +#endif /* defined(VK_EXT_acquire_drm_display) */ +#if defined(VK_EXT_acquire_xlib_display) +PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT; +PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT; +#endif /* defined(VK_EXT_acquire_xlib_display) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) +PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT vkCmdSetAttachmentFeedbackLoopEnableEXT; +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ +#if defined(VK_EXT_buffer_device_address) +PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; +#endif /* defined(VK_EXT_buffer_device_address) */ +#if defined(VK_EXT_calibrated_timestamps) +PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT; +PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT; +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) +PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT; +#endif /* defined(VK_EXT_color_write_enable) */ +#if defined(VK_EXT_conditional_rendering) +PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT; +PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT; +#endif /* defined(VK_EXT_conditional_rendering) */ +#if defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) +PFN_vkCmdBeginCustomResolveEXT vkCmdBeginCustomResolveEXT; +#endif /* defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) */ +#if defined(VK_EXT_debug_marker) +PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBeginEXT; +PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEndEXT; +PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsertEXT; +PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT; +PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT; +#endif /* defined(VK_EXT_debug_marker) */ +#if defined(VK_EXT_debug_report) +PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; +PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT; +PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; +#endif /* defined(VK_EXT_debug_report) */ +#if defined(VK_EXT_debug_utils) +PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT; +PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT; +PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT; +PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT; +PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT; +PFN_vkQueueBeginDebugUtilsLabelEXT vkQueueBeginDebugUtilsLabelEXT; +PFN_vkQueueEndDebugUtilsLabelEXT vkQueueEndDebugUtilsLabelEXT; +PFN_vkQueueInsertDebugUtilsLabelEXT vkQueueInsertDebugUtilsLabelEXT; +PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT; +PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT; +PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT; +#endif /* defined(VK_EXT_debug_utils) */ +#if defined(VK_EXT_depth_bias_control) +PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT; +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) +PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT vkCmdBindDescriptorBufferEmbeddedSamplersEXT; +PFN_vkCmdBindDescriptorBuffersEXT vkCmdBindDescriptorBuffersEXT; +PFN_vkCmdSetDescriptorBufferOffsetsEXT vkCmdSetDescriptorBufferOffsetsEXT; +PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT vkGetBufferOpaqueCaptureDescriptorDataEXT; +PFN_vkGetDescriptorEXT vkGetDescriptorEXT; +PFN_vkGetDescriptorSetLayoutBindingOffsetEXT vkGetDescriptorSetLayoutBindingOffsetEXT; +PFN_vkGetDescriptorSetLayoutSizeEXT vkGetDescriptorSetLayoutSizeEXT; +PFN_vkGetImageOpaqueCaptureDescriptorDataEXT vkGetImageOpaqueCaptureDescriptorDataEXT; +PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; +PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) +PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_descriptor_heap) +PFN_vkCmdBindResourceHeapEXT vkCmdBindResourceHeapEXT; +PFN_vkCmdBindSamplerHeapEXT vkCmdBindSamplerHeapEXT; +PFN_vkCmdPushDataEXT vkCmdPushDataEXT; +PFN_vkGetImageOpaqueCaptureDataEXT vkGetImageOpaqueCaptureDataEXT; +PFN_vkGetPhysicalDeviceDescriptorSizeEXT vkGetPhysicalDeviceDescriptorSizeEXT; +PFN_vkWriteResourceDescriptorsEXT vkWriteResourceDescriptorsEXT; +PFN_vkWriteSamplerDescriptorsEXT vkWriteSamplerDescriptorsEXT; +#endif /* defined(VK_EXT_descriptor_heap) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) +PFN_vkRegisterCustomBorderColorEXT vkRegisterCustomBorderColorEXT; +PFN_vkUnregisterCustomBorderColorEXT vkUnregisterCustomBorderColorEXT; +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) +PFN_vkGetTensorOpaqueCaptureDataARM vkGetTensorOpaqueCaptureDataARM; +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) */ +#if defined(VK_EXT_device_fault) +PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; +#endif /* defined(VK_EXT_device_fault) */ +#if defined(VK_EXT_device_generated_commands) +PFN_vkCmdExecuteGeneratedCommandsEXT vkCmdExecuteGeneratedCommandsEXT; +PFN_vkCmdPreprocessGeneratedCommandsEXT vkCmdPreprocessGeneratedCommandsEXT; +PFN_vkCreateIndirectCommandsLayoutEXT vkCreateIndirectCommandsLayoutEXT; +PFN_vkCreateIndirectExecutionSetEXT vkCreateIndirectExecutionSetEXT; +PFN_vkDestroyIndirectCommandsLayoutEXT vkDestroyIndirectCommandsLayoutEXT; +PFN_vkDestroyIndirectExecutionSetEXT vkDestroyIndirectExecutionSetEXT; +PFN_vkGetGeneratedCommandsMemoryRequirementsEXT vkGetGeneratedCommandsMemoryRequirementsEXT; +PFN_vkUpdateIndirectExecutionSetPipelineEXT vkUpdateIndirectExecutionSetPipelineEXT; +PFN_vkUpdateIndirectExecutionSetShaderEXT vkUpdateIndirectExecutionSetShaderEXT; +#endif /* defined(VK_EXT_device_generated_commands) */ +#if defined(VK_EXT_direct_mode_display) +PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; +#endif /* defined(VK_EXT_direct_mode_display) */ +#if defined(VK_EXT_directfb_surface) +PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT; +PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectFBPresentationSupportEXT; +#endif /* defined(VK_EXT_directfb_surface) */ +#if defined(VK_EXT_discard_rectangles) +PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; +#endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 +PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; +PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ +#if defined(VK_EXT_display_control) +PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; +PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; +PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT; +PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; +#endif /* defined(VK_EXT_display_control) */ +#if defined(VK_EXT_display_surface_counter) +PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; +#endif /* defined(VK_EXT_display_surface_counter) */ +#if defined(VK_EXT_external_memory_host) +PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; +#endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) +PFN_vkGetMemoryMetalHandleEXT vkGetMemoryMetalHandleEXT; +PFN_vkGetMemoryMetalHandlePropertiesEXT vkGetMemoryMetalHandlePropertiesEXT; +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) +PFN_vkCmdEndRendering2EXT vkCmdEndRendering2EXT; +#endif /* defined(VK_EXT_fragment_density_map_offset) */ +#if defined(VK_EXT_full_screen_exclusive) +PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT; +PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT; +PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT; +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) +PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ +#if defined(VK_EXT_hdr_metadata) +PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; +#endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_headless_surface) +PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT; +#endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_host_image_copy) +PFN_vkCopyImageToImageEXT vkCopyImageToImageEXT; +PFN_vkCopyImageToMemoryEXT vkCopyImageToMemoryEXT; +PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT; +PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT; +#endif /* defined(VK_EXT_host_image_copy) */ +#if defined(VK_EXT_host_query_reset) +PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; +#endif /* defined(VK_EXT_host_query_reset) */ +#if defined(VK_EXT_image_drm_format_modifier) +PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT; +#endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) +PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; +#endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_memory_decompression) +PFN_vkCmdDecompressMemoryEXT vkCmdDecompressMemoryEXT; +PFN_vkCmdDecompressMemoryIndirectCountEXT vkCmdDecompressMemoryIndirectCountEXT; +#endif /* defined(VK_EXT_memory_decompression) */ +#if defined(VK_EXT_mesh_shader) +PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT; +PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT; +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) +PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_EXT_metal_objects) +PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT; +#endif /* defined(VK_EXT_metal_objects) */ +#if defined(VK_EXT_metal_surface) +PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; +#endif /* defined(VK_EXT_metal_surface) */ +#if defined(VK_EXT_multi_draw) +PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; +PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; +#endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) +PFN_vkBuildMicromapsEXT vkBuildMicromapsEXT; +PFN_vkCmdBuildMicromapsEXT vkCmdBuildMicromapsEXT; +PFN_vkCmdCopyMemoryToMicromapEXT vkCmdCopyMemoryToMicromapEXT; +PFN_vkCmdCopyMicromapEXT vkCmdCopyMicromapEXT; +PFN_vkCmdCopyMicromapToMemoryEXT vkCmdCopyMicromapToMemoryEXT; +PFN_vkCmdWriteMicromapsPropertiesEXT vkCmdWriteMicromapsPropertiesEXT; +PFN_vkCopyMemoryToMicromapEXT vkCopyMemoryToMicromapEXT; +PFN_vkCopyMicromapEXT vkCopyMicromapEXT; +PFN_vkCopyMicromapToMemoryEXT vkCopyMicromapToMemoryEXT; +PFN_vkCreateMicromapEXT vkCreateMicromapEXT; +PFN_vkDestroyMicromapEXT vkDestroyMicromapEXT; +PFN_vkGetDeviceMicromapCompatibilityEXT vkGetDeviceMicromapCompatibilityEXT; +PFN_vkGetMicromapBuildSizesEXT vkGetMicromapBuildSizesEXT; +PFN_vkWriteMicromapsPropertiesEXT vkWriteMicromapsPropertiesEXT; +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) +PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT; +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) +PFN_vkGetPipelinePropertiesEXT vkGetPipelinePropertiesEXT; +#endif /* defined(VK_EXT_pipeline_properties) */ +#if defined(VK_EXT_present_timing) +PFN_vkGetPastPresentationTimingEXT vkGetPastPresentationTimingEXT; +PFN_vkGetSwapchainTimeDomainPropertiesEXT vkGetSwapchainTimeDomainPropertiesEXT; +PFN_vkGetSwapchainTimingPropertiesEXT vkGetSwapchainTimingPropertiesEXT; +PFN_vkSetSwapchainPresentTimingQueueSizeEXT vkSetSwapchainPresentTimingQueueSizeEXT; +#endif /* defined(VK_EXT_present_timing) */ +#if defined(VK_EXT_primitive_restart_index) +PFN_vkCmdSetPrimitiveRestartIndexEXT vkCmdSetPrimitiveRestartIndexEXT; +#endif /* defined(VK_EXT_primitive_restart_index) */ +#if defined(VK_EXT_private_data) +PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; +PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; +PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT; +PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; +#endif /* defined(VK_EXT_private_data) */ +#if defined(VK_EXT_sample_locations) +PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; +PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT; +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) +PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; +PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) +PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; +PFN_vkCreateShadersEXT vkCreateShadersEXT; +PFN_vkDestroyShaderEXT vkDestroyShaderEXT; +PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) +PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; +#endif /* defined(VK_EXT_swapchain_maintenance1) */ +#if defined(VK_EXT_tooling_info) +PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT; +#endif /* defined(VK_EXT_tooling_info) */ +#if defined(VK_EXT_transform_feedback) +PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT; +PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT; +PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT; +PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT; +PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT; +PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT; +#endif /* defined(VK_EXT_transform_feedback) */ +#if defined(VK_EXT_validation_cache) +PFN_vkCreateValidationCacheEXT vkCreateValidationCacheEXT; +PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT; +PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; +PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; +#endif /* defined(VK_EXT_validation_cache) */ +#if defined(VK_FUCHSIA_buffer_collection) +PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; +PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA; +PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA; +PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA; +PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA; +#endif /* defined(VK_FUCHSIA_buffer_collection) */ +#if defined(VK_FUCHSIA_external_memory) +PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; +PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) +PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA; +PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_semaphore) */ +#if defined(VK_FUCHSIA_imagepipe_surface) +PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA; +#endif /* defined(VK_FUCHSIA_imagepipe_surface) */ +#if defined(VK_GGP_stream_descriptor_surface) +PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; +#endif /* defined(VK_GGP_stream_descriptor_surface) */ +#if defined(VK_GOOGLE_display_timing) +PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; +PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; +#endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) +PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; +PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ +#if defined(VK_HUAWEI_invocation_mask) +PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 +PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ +#if defined(VK_HUAWEI_subpass_shading) +PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI; +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) +PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL; +PFN_vkCmdSetPerformanceMarkerINTEL vkCmdSetPerformanceMarkerINTEL; +PFN_vkCmdSetPerformanceOverrideINTEL vkCmdSetPerformanceOverrideINTEL; +PFN_vkCmdSetPerformanceStreamMarkerINTEL vkCmdSetPerformanceStreamMarkerINTEL; +PFN_vkGetPerformanceParameterINTEL vkGetPerformanceParameterINTEL; +PFN_vkInitializePerformanceApiINTEL vkInitializePerformanceApiINTEL; +PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL; +PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL; +PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL; +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) +PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR; +PFN_vkCmdBuildAccelerationStructuresIndirectKHR vkCmdBuildAccelerationStructuresIndirectKHR; +PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; +PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR; +PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR; +PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR; +PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR; +PFN_vkCopyAccelerationStructureKHR vkCopyAccelerationStructureKHR; +PFN_vkCopyAccelerationStructureToMemoryKHR vkCopyAccelerationStructureToMemoryKHR; +PFN_vkCopyMemoryToAccelerationStructureKHR vkCopyMemoryToAccelerationStructureKHR; +PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR; +PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR; +PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR; +PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; +PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR; +PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR; +#endif /* defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_android_surface) +PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; +#endif /* defined(VK_KHR_android_surface) */ +#if defined(VK_KHR_bind_memory2) +PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; +PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; +#endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) +PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; +PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR; +PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR; +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_calibrated_timestamps) +PFN_vkGetCalibratedTimestampsKHR vkGetCalibratedTimestampsKHR; +PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR vkGetPhysicalDeviceCalibrateableTimeDomainsKHR; +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_cooperative_matrix) +PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR; +#endif /* defined(VK_KHR_cooperative_matrix) */ +#if defined(VK_KHR_copy_commands2) +PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; +PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR; +PFN_vkCmdCopyBufferToImage2KHR vkCmdCopyBufferToImage2KHR; +PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR; +PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR; +PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR; +#endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) +PFN_vkCmdCopyMemoryIndirectKHR vkCmdCopyMemoryIndirectKHR; +PFN_vkCmdCopyMemoryToImageIndirectKHR vkCmdCopyMemoryToImageIndirectKHR; +#endif /* defined(VK_KHR_copy_memory_indirect) */ +#if defined(VK_KHR_create_renderpass2) +PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR; +PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR; +PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR; +PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR; +#endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) +PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR; +PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR; +PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR; +PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR; +PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR; +#endif /* defined(VK_KHR_deferred_host_operations) */ +#if defined(VK_KHR_descriptor_update_template) +PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR; +PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR; +PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR; +#endif /* defined(VK_KHR_descriptor_update_template) */ +#if defined(VK_KHR_device_address_commands) +PFN_vkCmdBindIndexBuffer3KHR vkCmdBindIndexBuffer3KHR; +PFN_vkCmdBindVertexBuffers3KHR vkCmdBindVertexBuffers3KHR; +PFN_vkCmdCopyImageToMemoryKHR vkCmdCopyImageToMemoryKHR; +PFN_vkCmdCopyMemoryKHR vkCmdCopyMemoryKHR; +PFN_vkCmdCopyMemoryToImageKHR vkCmdCopyMemoryToImageKHR; +PFN_vkCmdCopyQueryPoolResultsToMemoryKHR vkCmdCopyQueryPoolResultsToMemoryKHR; +PFN_vkCmdDispatchIndirect2KHR vkCmdDispatchIndirect2KHR; +PFN_vkCmdDrawIndexedIndirect2KHR vkCmdDrawIndexedIndirect2KHR; +PFN_vkCmdDrawIndirect2KHR vkCmdDrawIndirect2KHR; +PFN_vkCmdFillMemoryKHR vkCmdFillMemoryKHR; +PFN_vkCmdUpdateMemoryKHR vkCmdUpdateMemoryKHR; +#endif /* defined(VK_KHR_device_address_commands) */ +#if defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) +PFN_vkCmdDrawIndexedIndirectCount2KHR vkCmdDrawIndexedIndirectCount2KHR; +PFN_vkCmdDrawIndirectCount2KHR vkCmdDrawIndirectCount2KHR; +#endif /* defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) +PFN_vkCmdBeginConditionalRendering2EXT vkCmdBeginConditionalRendering2EXT; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) +PFN_vkCmdBeginTransformFeedback2EXT vkCmdBeginTransformFeedback2EXT; +PFN_vkCmdBindTransformFeedbackBuffers2EXT vkCmdBindTransformFeedbackBuffers2EXT; +PFN_vkCmdDrawIndirectByteCount2EXT vkCmdDrawIndirectByteCount2EXT; +PFN_vkCmdEndTransformFeedback2EXT vkCmdEndTransformFeedback2EXT; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) +PFN_vkCmdDrawMeshTasksIndirect2EXT vkCmdDrawMeshTasksIndirect2EXT; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) */ +#if defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) +PFN_vkCmdDrawMeshTasksIndirectCount2EXT vkCmdDrawMeshTasksIndirectCount2EXT; +#endif /* defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) +PFN_vkCmdWriteMarkerToMemoryAMD vkCmdWriteMarkerToMemoryAMD; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) +PFN_vkCreateAccelerationStructure2KHR vkCreateAccelerationStructure2KHR; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_device_fault) +PFN_vkGetDeviceFaultDebugInfoKHR vkGetDeviceFaultDebugInfoKHR; +PFN_vkGetDeviceFaultReportsKHR vkGetDeviceFaultReportsKHR; +#endif /* defined(VK_KHR_device_fault) */ +#if defined(VK_KHR_device_group) +PFN_vkCmdDispatchBaseKHR vkCmdDispatchBaseKHR; +PFN_vkCmdSetDeviceMaskKHR vkCmdSetDeviceMaskKHR; +PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR vkGetDeviceGroupPeerMemoryFeaturesKHR; +#endif /* defined(VK_KHR_device_group) */ +#if defined(VK_KHR_device_group_creation) +PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR; +#endif /* defined(VK_KHR_device_group_creation) */ +#if defined(VK_KHR_display) +PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR; +PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR; +PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR; +PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR; +PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR; +PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR; +PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR; +#endif /* defined(VK_KHR_display) */ +#if defined(VK_KHR_display_swapchain) +PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; +#endif /* defined(VK_KHR_display_swapchain) */ +#if defined(VK_KHR_draw_indirect_count) +PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; +PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; +#endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) +PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; +PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#endif /* defined(VK_KHR_dynamic_rendering) */ +#if defined(VK_KHR_dynamic_rendering_local_read) +PFN_vkCmdSetRenderingAttachmentLocationsKHR vkCmdSetRenderingAttachmentLocationsKHR; +PFN_vkCmdSetRenderingInputAttachmentIndicesKHR vkCmdSetRenderingInputAttachmentIndicesKHR; +#endif /* defined(VK_KHR_dynamic_rendering_local_read) */ +#if defined(VK_KHR_external_fence_capabilities) +PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; +#endif /* defined(VK_KHR_external_fence_capabilities) */ +#if defined(VK_KHR_external_fence_fd) +PFN_vkGetFenceFdKHR vkGetFenceFdKHR; +PFN_vkImportFenceFdKHR vkImportFenceFdKHR; +#endif /* defined(VK_KHR_external_fence_fd) */ +#if defined(VK_KHR_external_fence_win32) +PFN_vkGetFenceWin32HandleKHR vkGetFenceWin32HandleKHR; +PFN_vkImportFenceWin32HandleKHR vkImportFenceWin32HandleKHR; +#endif /* defined(VK_KHR_external_fence_win32) */ +#if defined(VK_KHR_external_memory_capabilities) +PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR vkGetPhysicalDeviceExternalBufferPropertiesKHR; +#endif /* defined(VK_KHR_external_memory_capabilities) */ +#if defined(VK_KHR_external_memory_fd) +PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR; +PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR; +#endif /* defined(VK_KHR_external_memory_fd) */ +#if defined(VK_KHR_external_memory_win32) +PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR; +PFN_vkGetMemoryWin32HandlePropertiesKHR vkGetMemoryWin32HandlePropertiesKHR; +#endif /* defined(VK_KHR_external_memory_win32) */ +#if defined(VK_KHR_external_semaphore_capabilities) +PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR vkGetPhysicalDeviceExternalSemaphorePropertiesKHR; +#endif /* defined(VK_KHR_external_semaphore_capabilities) */ +#if defined(VK_KHR_external_semaphore_fd) +PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR; +PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; +#endif /* defined(VK_KHR_external_semaphore_fd) */ +#if defined(VK_KHR_external_semaphore_win32) +PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR; +PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR; +#endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) +PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR; +PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR; +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_display_properties2) +PFN_vkGetDisplayModeProperties2KHR vkGetDisplayModeProperties2KHR; +PFN_vkGetDisplayPlaneCapabilities2KHR vkGetDisplayPlaneCapabilities2KHR; +PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR vkGetPhysicalDeviceDisplayPlaneProperties2KHR; +PFN_vkGetPhysicalDeviceDisplayProperties2KHR vkGetPhysicalDeviceDisplayProperties2KHR; +#endif /* defined(VK_KHR_get_display_properties2) */ +#if defined(VK_KHR_get_memory_requirements2) +PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; +PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; +PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR; +#endif /* defined(VK_KHR_get_memory_requirements2) */ +#if defined(VK_KHR_get_physical_device_properties2) +PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; +PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR; +PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2KHR; +PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR; +PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; +PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR; +PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR vkGetPhysicalDeviceSparseImageFormatProperties2KHR; +#endif /* defined(VK_KHR_get_physical_device_properties2) */ +#if defined(VK_KHR_get_surface_capabilities2) +PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR; +PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR; +#endif /* defined(VK_KHR_get_surface_capabilities2) */ +#if defined(VK_KHR_line_rasterization) +PFN_vkCmdSetLineStippleKHR vkCmdSetLineStippleKHR; +#endif /* defined(VK_KHR_line_rasterization) */ +#if defined(VK_KHR_maintenance1) +PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR; +#endif /* defined(VK_KHR_maintenance1) */ +#if defined(VK_KHR_maintenance10) +PFN_vkCmdEndRendering2KHR vkCmdEndRendering2KHR; +#endif /* defined(VK_KHR_maintenance10) */ +#if defined(VK_KHR_maintenance3) +PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; +#endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) +PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR; +PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; +PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) +PFN_vkCmdBindIndexBuffer2KHR vkCmdBindIndexBuffer2KHR; +PFN_vkGetDeviceImageSubresourceLayoutKHR vkGetDeviceImageSubresourceLayoutKHR; +PFN_vkGetImageSubresourceLayout2KHR vkGetImageSubresourceLayout2KHR; +PFN_vkGetRenderingAreaGranularityKHR vkGetRenderingAreaGranularityKHR; +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_maintenance6) +PFN_vkCmdBindDescriptorSets2KHR vkCmdBindDescriptorSets2KHR; +PFN_vkCmdPushConstants2KHR vkCmdPushConstants2KHR; +#endif /* defined(VK_KHR_maintenance6) */ +#if defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) +PFN_vkCmdPushDescriptorSet2KHR vkCmdPushDescriptorSet2KHR; +PFN_vkCmdPushDescriptorSetWithTemplate2KHR vkCmdPushDescriptorSetWithTemplate2KHR; +#endif /* defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) +PFN_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT vkCmdBindDescriptorBufferEmbeddedSamplers2EXT; +PFN_vkCmdSetDescriptorBufferOffsets2EXT vkCmdSetDescriptorBufferOffsets2EXT; +#endif /* defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_KHR_map_memory2) +PFN_vkMapMemory2KHR vkMapMemory2KHR; +PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#endif /* defined(VK_KHR_map_memory2) */ +#if defined(VK_KHR_performance_query) +PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; +PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; +PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR; +PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) +PFN_vkCreatePipelineBinariesKHR vkCreatePipelineBinariesKHR; +PFN_vkDestroyPipelineBinaryKHR vkDestroyPipelineBinaryKHR; +PFN_vkGetPipelineBinaryDataKHR vkGetPipelineBinaryDataKHR; +PFN_vkGetPipelineKeyKHR vkGetPipelineKeyKHR; +PFN_vkReleaseCapturedPipelineDataKHR vkReleaseCapturedPipelineDataKHR; +#endif /* defined(VK_KHR_pipeline_binary) */ +#if defined(VK_KHR_pipeline_executable_properties) +PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR; +PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR; +PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR; +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) +PFN_vkWaitForPresentKHR vkWaitForPresentKHR; +#endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) +PFN_vkWaitForPresent2KHR vkWaitForPresent2KHR; +#endif /* defined(VK_KHR_present_wait2) */ +#if defined(VK_KHR_push_descriptor) +PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; +#endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) +PFN_vkCmdTraceRaysIndirect2KHR vkCmdTraceRaysIndirect2KHR; +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_ray_tracing_pipeline) +PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; +PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR; +PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR; +PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR; +PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR; +PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR; +PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR; +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_sampler_ycbcr_conversion) +PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; +PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; +#endif /* defined(VK_KHR_sampler_ycbcr_conversion) */ +#if defined(VK_KHR_shared_presentable_image) +PFN_vkGetSwapchainStatusKHR vkGetSwapchainStatusKHR; +#endif /* defined(VK_KHR_shared_presentable_image) */ +#if defined(VK_KHR_surface) +PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; +PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; +PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; +PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; +PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; +#endif /* defined(VK_KHR_surface) */ +#if defined(VK_KHR_swapchain) +PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; +PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; +PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; +PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; +PFN_vkQueuePresentKHR vkQueuePresentKHR; +#endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) +PFN_vkReleaseSwapchainImagesKHR vkReleaseSwapchainImagesKHR; +#endif /* defined(VK_KHR_swapchain_maintenance1) */ +#if defined(VK_KHR_synchronization2) +PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; +PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR; +PFN_vkCmdSetEvent2KHR vkCmdSetEvent2KHR; +PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR; +PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; +PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_timeline_semaphore) +PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR; +PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR; +PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR; +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) +PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) +PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; +PFN_vkGetEncodedVideoSessionParametersKHR vkGetEncodedVideoSessionParametersKHR; +PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR; +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) +PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; +PFN_vkCmdBeginVideoCodingKHR vkCmdBeginVideoCodingKHR; +PFN_vkCmdControlVideoCodingKHR vkCmdControlVideoCodingKHR; +PFN_vkCmdEndVideoCodingKHR vkCmdEndVideoCodingKHR; +PFN_vkCreateVideoSessionKHR vkCreateVideoSessionKHR; +PFN_vkCreateVideoSessionParametersKHR vkCreateVideoSessionParametersKHR; +PFN_vkDestroyVideoSessionKHR vkDestroyVideoSessionKHR; +PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR; +PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR vkGetPhysicalDeviceVideoCapabilitiesKHR; +PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR vkGetPhysicalDeviceVideoFormatPropertiesKHR; +PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR; +PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR; +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_KHR_wayland_surface) +PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; +PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR; +#endif /* defined(VK_KHR_wayland_surface) */ +#if defined(VK_KHR_win32_surface) +PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; +PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR; +#endif /* defined(VK_KHR_win32_surface) */ +#if defined(VK_KHR_xcb_surface) +PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; +PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR; +#endif /* defined(VK_KHR_xcb_surface) */ +#if defined(VK_KHR_xlib_surface) +PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; +PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR; +#endif /* defined(VK_KHR_xlib_surface) */ +#if defined(VK_MVK_ios_surface) +PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK; +#endif /* defined(VK_MVK_ios_surface) */ +#if defined(VK_MVK_macos_surface) +PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; +#endif /* defined(VK_MVK_macos_surface) */ +#if defined(VK_NN_vi_surface) +PFN_vkCreateViSurfaceNN vkCreateViSurfaceNN; +#endif /* defined(VK_NN_vi_surface) */ +#if defined(VK_NVX_binary_import) +PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX; +PFN_vkCreateCuFunctionNVX vkCreateCuFunctionNVX; +PFN_vkCreateCuModuleNVX vkCreateCuModuleNVX; +PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX; +PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX; +#endif /* defined(VK_NVX_binary_import) */ +#if defined(VK_NVX_image_view_handle) +PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX; +#endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 +PFN_vkGetImageViewHandle64NVX vkGetImageViewHandle64NVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 +PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 +PFN_vkGetDeviceCombinedImageSamplerIndexNVX vkGetDeviceCombinedImageSamplerIndexNVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 */ +#if defined(VK_NV_acquire_winrt_display) +PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV; +PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV; +#endif /* defined(VK_NV_acquire_winrt_display) */ +#if defined(VK_NV_clip_space_w_scaling) +PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; +#endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_cluster_acceleration_structure) +PFN_vkCmdBuildClusterAccelerationStructureIndirectNV vkCmdBuildClusterAccelerationStructureIndirectNV; +PFN_vkGetClusterAccelerationStructureBuildSizesNV vkGetClusterAccelerationStructureBuildSizesNV; +#endif /* defined(VK_NV_cluster_acceleration_structure) */ +#if defined(VK_NV_compute_occupancy_priority) +PFN_vkCmdSetComputeOccupancyPriorityNV vkCmdSetComputeOccupancyPriorityNV; +#endif /* defined(VK_NV_compute_occupancy_priority) */ +#if defined(VK_NV_cooperative_matrix) +PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; +#endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_cooperative_matrix2) +PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV; +#endif /* defined(VK_NV_cooperative_matrix2) */ +#if defined(VK_NV_cooperative_vector) +PFN_vkCmdConvertCooperativeVectorMatrixNV vkCmdConvertCooperativeVectorMatrixNV; +PFN_vkConvertCooperativeVectorMatrixNV vkConvertCooperativeVectorMatrixNV; +PFN_vkGetPhysicalDeviceCooperativeVectorPropertiesNV vkGetPhysicalDeviceCooperativeVectorPropertiesNV; +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_copy_memory_indirect) +PFN_vkCmdCopyMemoryIndirectNV vkCmdCopyMemoryIndirectNV; +PFN_vkCmdCopyMemoryToImageIndirectNV vkCmdCopyMemoryToImageIndirectNV; +#endif /* defined(VK_NV_copy_memory_indirect) */ +#if defined(VK_NV_coverage_reduction_mode) +PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV; +#endif /* defined(VK_NV_coverage_reduction_mode) */ +#if defined(VK_NV_cuda_kernel_launch) +PFN_vkCmdCudaLaunchKernelNV vkCmdCudaLaunchKernelNV; +PFN_vkCreateCudaFunctionNV vkCreateCudaFunctionNV; +PFN_vkCreateCudaModuleNV vkCreateCudaModuleNV; +PFN_vkDestroyCudaFunctionNV vkDestroyCudaFunctionNV; +PFN_vkDestroyCudaModuleNV vkDestroyCudaModuleNV; +PFN_vkGetCudaModuleCacheNV vkGetCudaModuleCacheNV; +#endif /* defined(VK_NV_cuda_kernel_launch) */ +#if defined(VK_NV_device_diagnostic_checkpoints) +PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; +PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; +#endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) +PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_NV_device_generated_commands) +PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV; +PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV; +PFN_vkCmdPreprocessGeneratedCommandsNV vkCmdPreprocessGeneratedCommandsNV; +PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV; +PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; +PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) +PFN_vkCmdUpdatePipelineIndirectBufferNV vkCmdUpdatePipelineIndirectBufferNV; +PFN_vkGetPipelineIndirectDeviceAddressNV vkGetPipelineIndirectDeviceAddressNV; +PFN_vkGetPipelineIndirectMemoryRequirementsNV vkGetPipelineIndirectMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands_compute) */ +#if defined(VK_NV_external_compute_queue) +PFN_vkCreateExternalComputeQueueNV vkCreateExternalComputeQueueNV; +PFN_vkDestroyExternalComputeQueueNV vkDestroyExternalComputeQueueNV; +PFN_vkGetExternalComputeQueueDataNV vkGetExternalComputeQueueDataNV; +#endif /* defined(VK_NV_external_compute_queue) */ +#if defined(VK_NV_external_memory_capabilities) +PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; +#endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_external_memory_rdma) +PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV; +#endif /* defined(VK_NV_external_memory_rdma) */ +#if defined(VK_NV_external_memory_win32) +PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; +#endif /* defined(VK_NV_external_memory_win32) */ +#if defined(VK_NV_fragment_shading_rate_enums) +PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; +#endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) +PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; +PFN_vkLatencySleepNV vkLatencySleepNV; +PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; +PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; +PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) +PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; +PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; +#endif /* defined(VK_NV_memory_decompression) */ +#if defined(VK_NV_mesh_shader) +PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; +PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV; +#endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) +PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_NV_optical_flow) +PFN_vkBindOpticalFlowSessionImageNV vkBindOpticalFlowSessionImageNV; +PFN_vkCmdOpticalFlowExecuteNV vkCmdOpticalFlowExecuteNV; +PFN_vkCreateOpticalFlowSessionNV vkCreateOpticalFlowSessionNV; +PFN_vkDestroyOpticalFlowSessionNV vkDestroyOpticalFlowSessionNV; +PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV vkGetPhysicalDeviceOpticalFlowImageFormatsNV; +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) +PFN_vkCmdBuildPartitionedAccelerationStructuresNV vkCmdBuildPartitionedAccelerationStructuresNV; +PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV vkGetPartitionedAccelerationStructuresBuildSizesNV; +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ +#if defined(VK_NV_ray_tracing) +PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV; +PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV; +PFN_vkCmdCopyAccelerationStructureNV vkCmdCopyAccelerationStructureNV; +PFN_vkCmdTraceRaysNV vkCmdTraceRaysNV; +PFN_vkCmdWriteAccelerationStructuresPropertiesNV vkCmdWriteAccelerationStructuresPropertiesNV; +PFN_vkCompileDeferredNV vkCompileDeferredNV; +PFN_vkCreateAccelerationStructureNV vkCreateAccelerationStructureNV; +PFN_vkCreateRayTracingPipelinesNV vkCreateRayTracingPipelinesNV; +PFN_vkDestroyAccelerationStructureNV vkDestroyAccelerationStructureNV; +PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV; +PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; +PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; +#endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 +PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ +#if defined(VK_NV_scissor_exclusive) +PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; +#endif /* defined(VK_NV_scissor_exclusive) */ +#if defined(VK_NV_shading_rate_image) +PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; +PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; +PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; +#endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_OHOS_external_memory) +PFN_vkGetMemoryNativeBufferOHOS vkGetMemoryNativeBufferOHOS; +PFN_vkGetNativeBufferPropertiesOHOS vkGetNativeBufferPropertiesOHOS; +#endif /* defined(VK_OHOS_external_memory) */ +#if defined(VK_OHOS_surface) +PFN_vkCreateSurfaceOHOS vkCreateSurfaceOHOS; +#endif /* defined(VK_OHOS_surface) */ +#if defined(VK_QCOM_queue_perf_hint) +PFN_vkQueueSetPerfHintQCOM vkQueueSetPerfHintQCOM; +#endif /* defined(VK_QCOM_queue_perf_hint) */ +#if defined(VK_QCOM_tile_memory_heap) +PFN_vkCmdBindTileMemoryQCOM vkCmdBindTileMemoryQCOM; +#endif /* defined(VK_QCOM_tile_memory_heap) */ +#if defined(VK_QCOM_tile_properties) +PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM; +PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM; +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) +PFN_vkCmdBeginPerTileExecutionQCOM vkCmdBeginPerTileExecutionQCOM; +PFN_vkCmdDispatchTileQCOM vkCmdDispatchTileQCOM; +PFN_vkCmdEndPerTileExecutionQCOM vkCmdEndPerTileExecutionQCOM; +#endif /* defined(VK_QCOM_tile_shading) */ +#if defined(VK_QNX_external_memory_screen_buffer) +PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX; +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ +#if defined(VK_QNX_screen_surface) +PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX; +PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX; +#endif /* defined(VK_QNX_screen_surface) */ +#if defined(VK_SEC_ubm_surface) +PFN_vkCreateUbmSurfaceSEC vkCreateUbmSurfaceSEC; +PFN_vkGetPhysicalDeviceUbmPresentationSupportSEC vkGetPhysicalDeviceUbmPresentationSupportSEC; +#endif /* defined(VK_SEC_ubm_surface) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) +PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; +PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) +PFN_vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM; +#endif /* (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) +PFN_vkCmdSetDepthClampRangeEXT vkCmdSetDepthClampRangeEXT; +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) +PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; +PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; +PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; +PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; +PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; +PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; +PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; +PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; +PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; +PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; +PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; +PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) +PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; +PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; +PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; +PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; +PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) +PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; +PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; +PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; +PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; +PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; +PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; +PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; +PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; +PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; +PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) +PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) +PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) +PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; +PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) +PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) +PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) +PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) +PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) +PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; +PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) +PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) +PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) +PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) +PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; +PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) +PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; +PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; +PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) +PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) +PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) +PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) +PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT; +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) +PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) +PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) +PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR; +PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR; +PFN_vkGetPhysicalDevicePresentRectanglesKHR vkGetPhysicalDevicePresentRectanglesKHR; +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) +PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ +/* VOLK_GENERATE_PROTOTYPES_C */ + +#ifdef __GNUC__ +# pragma GCC visibility pop +#endif + +#ifdef __cplusplus +} // extern "C" / namespace volk +#endif +/* clang-format on */ diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/volk.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/volk.h new file mode 100644 index 00000000..4cfa79fa --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/volk/volk.h @@ -0,0 +1,3465 @@ +/** + * volk + * + * Copyright (C) 2018-2026, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at https://github.com/zeux/volk + * + * This library is distributed under the MIT License. See notice at the end of this file. + */ +/* clang-format off */ +#ifndef VOLK_H_ +#define VOLK_H_ + +#if defined(VOLK_NAMESPACE) && !defined(__cplusplus) +#error VOLK_NAMESPACE is only supported in C++ +#endif + +#if defined(VULKAN_H_) && !defined(VK_NO_PROTOTYPES) +# error To use volk, you need to define VK_NO_PROTOTYPES before including vulkan.h +#endif + +/* VOLK_GENERATE_VERSION_DEFINE */ +#define VOLK_HEADER_VERSION 352 +/* VOLK_GENERATE_VERSION_DEFINE */ + +#ifndef VK_NO_PROTOTYPES +# define VK_NO_PROTOTYPES +#endif + +#ifndef VULKAN_H_ +# ifdef VOLK_VULKAN_H_PATH +# include VOLK_VULKAN_H_PATH +# else /* Platform headers included below */ +# include +# include +# endif +#endif + +#ifdef __cplusplus +#ifdef VOLK_NAMESPACE +namespace volk { +#else +extern "C" { +#endif +#endif + +struct VolkInstanceTable; +struct VolkDeviceTable; + +/** + * Initialize library by loading Vulkan loader; call this function before creating the Vulkan instance. + * + * Returns VK_SUCCESS on success and VK_ERROR_INITIALIZATION_FAILED otherwise. + */ +VkResult volkInitialize(void); + +/** + * Initialize library by providing a custom handler to load global symbols. + * + * This function can be used instead of volkInitialize. + * The handler function pointer will be asked to load global Vulkan symbols which require no instance + * (such as vkCreateInstance, vkEnumerateInstance* and vkEnumerateInstanceVersion if available). + */ +void volkInitializeCustom(PFN_vkGetInstanceProcAddr handler); + +/** + * Finalize library by unloading Vulkan loader and resetting global symbols to NULL. + * + * This function does not need to be called on process exit (as loader will be unloaded automatically) or if volkInitialize failed. + * In general this function is optional to call but may be useful in rare cases eg if volk needs to be reinitialized multiple times. + */ +void volkFinalize(void); + +/** + * Get Vulkan instance version supported by the Vulkan loader, or 0 if Vulkan isn't supported + * + * Returns 0 if volkInitialize wasn't called or failed. + */ +uint32_t volkGetInstanceVersion(void); + +/** + * Load global function pointers using application-created VkInstance; call this function after creating the Vulkan instance. + */ +void volkLoadInstance(VkInstance instance); + +/** + * Load global function pointers using application-created VkInstance; call this function after creating the Vulkan instance. + * Skips loading device-based function pointers, requires usage of volkLoadDevice afterwards. + */ +void volkLoadInstanceOnly(VkInstance instance); + +/** + * Load global function pointers using application-created VkDevice; call this function after creating the Vulkan device. + * + * Note: this is not suitable for applications that want to use multiple VkDevice objects concurrently. + */ +void volkLoadDevice(VkDevice device); + +/** + * Return last VkInstance for which global function pointers have been loaded via volkLoadInstance(), + * or VK_NULL_HANDLE if volkLoadInstance() has not been called. + */ +VkInstance volkGetLoadedInstance(void); + +/** + * Return last VkDevice for which global function pointers have been loaded via volkLoadDevice(), + * or VK_NULL_HANDLE if volkLoadDevice() has not been called. + */ +VkDevice volkGetLoadedDevice(void); + +/** + * Load function pointers using application-created VkInstance into a table. + * Application should use function pointers from that table instead of using global function pointers. + */ +void volkLoadInstanceTable(struct VolkInstanceTable* table, VkInstance instance); + +/** + * Load function pointers using application-created VkDevice into a table. + * Application should use function pointers from that table instead of using global function pointers. + */ +void volkLoadDeviceTable(struct VolkDeviceTable* table, VkDevice device); + +#ifdef __cplusplus +} // extern "C" / namespace volk +#endif + +/* Instead of directly including vulkan.h, we include platform-specific parts of the SDK manually + * This is necessary to avoid including platform headers in some cases (which vulkan.h does unconditionally) + * and replace them with forward declarations, which makes build times faster and avoids macro conflicts. + * + * Note that we only replace platform-specific headers when the headers are known to be problematic: very large + * or slow to compile (Windows), or introducing unprefixed macros which can cause conflicts (Windows, Xlib). + */ +#if !defined(VULKAN_H_) && !defined(VOLK_VULKAN_H_PATH) + +#ifdef VK_USE_PLATFORM_ANDROID_KHR +#include +#endif + +#ifdef VK_USE_PLATFORM_FUCHSIA +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_IOS_MVK +#include +#endif + +#ifdef VK_USE_PLATFORM_MACOS_MVK +#include +#endif + +#ifdef VK_USE_PLATFORM_METAL_EXT +#include +#endif + +#ifdef VK_USE_PLATFORM_VI_NN +#include +#endif + +#ifdef VK_USE_PLATFORM_WAYLAND_KHR +#include +#endif + +#ifdef VK_USE_PLATFORM_WIN32_KHR +typedef unsigned long DWORD; +typedef const wchar_t* LPCWSTR; +typedef void* HANDLE; +typedef struct HINSTANCE__* HINSTANCE; +typedef struct HWND__* HWND; +typedef struct HMONITOR__* HMONITOR; +typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES; +#include +#endif + +#ifdef VK_USE_PLATFORM_XCB_KHR +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_XLIB_KHR +typedef struct _XDisplay Display; +typedef unsigned long Window; +typedef unsigned long VisualID; +#include +#endif + +#ifdef VK_USE_PLATFORM_DIRECTFB_EXT +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT +typedef struct _XDisplay Display; +typedef unsigned long RROutput; +#include +#endif + +#ifdef VK_USE_PLATFORM_GGP +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_SCREEN_QNX +#include +#include +#endif + +#ifdef VK_USE_PLATFORM_SCI +#include +#include +#include +#endif + +#ifdef VK_ENABLE_BETA_EXTENSIONS +#include +#endif + +#ifdef VK_USE_PLATFORM_OHOS +#include +#endif + +#endif + +#ifdef __cplusplus +#ifdef VOLK_NAMESPACE +namespace volk { +#else +extern "C" { +#endif +#endif + +/** + * Instance-specific function pointer table + */ +struct VolkInstanceTable +{ + /* VOLK_GENERATE_INSTANCE_TABLE */ +#if defined(VK_VERSION_1_0) + PFN_vkCreateDevice vkCreateDevice; + PFN_vkDestroyInstance vkDestroyInstance; + PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; + PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; + PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; + PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; + PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties; + PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties; + PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; + PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; + PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties; +#else + PFN_vkVoidFunction padding_f34b07f4[13]; +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) + PFN_vkEnumeratePhysicalDeviceGroups vkEnumeratePhysicalDeviceGroups; + PFN_vkGetPhysicalDeviceExternalBufferProperties vkGetPhysicalDeviceExternalBufferProperties; + PFN_vkGetPhysicalDeviceExternalFenceProperties vkGetPhysicalDeviceExternalFenceProperties; + PFN_vkGetPhysicalDeviceExternalSemaphoreProperties vkGetPhysicalDeviceExternalSemaphoreProperties; + PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2; + PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2; + PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2; + PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2; + PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2; + PFN_vkGetPhysicalDeviceQueueFamilyProperties2 vkGetPhysicalDeviceQueueFamilyProperties2; + PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 vkGetPhysicalDeviceSparseImageFormatProperties2; +#else + PFN_vkVoidFunction padding_73de037b[11]; +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_3) + PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties; +#else + PFN_vkVoidFunction padding_60958868[1]; +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_ARM_data_graph) + PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM; + PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM; +#else + PFN_vkVoidFunction padding_15920a35[2]; +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_data_graph_optical_flow) + PFN_vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM; +#else + PFN_vkVoidFunction padding_4da6b74b[1]; +#endif /* defined(VK_ARM_data_graph_optical_flow) */ +#if defined(VK_ARM_performance_counters_by_region) + PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM; +#else + PFN_vkVoidFunction padding_4fd09193[1]; +#endif /* defined(VK_ARM_performance_counters_by_region) */ +#if defined(VK_ARM_shader_instrumentation) + PFN_vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM; +#else + PFN_vkVoidFunction padding_faae0311[1]; +#endif /* defined(VK_ARM_shader_instrumentation) */ +#if defined(VK_ARM_tensors) + PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM vkGetPhysicalDeviceExternalTensorPropertiesARM; +#else + PFN_vkVoidFunction padding_4622403f[1]; +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_EXT_acquire_drm_display) + PFN_vkAcquireDrmDisplayEXT vkAcquireDrmDisplayEXT; + PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; +#else + PFN_vkVoidFunction padding_8e427d62[2]; +#endif /* defined(VK_EXT_acquire_drm_display) */ +#if defined(VK_EXT_acquire_xlib_display) + PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT; + PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT; +#else + PFN_vkVoidFunction padding_6e6f0a05[2]; +#endif /* defined(VK_EXT_acquire_xlib_display) */ +#if defined(VK_EXT_calibrated_timestamps) + PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT; +#else + PFN_vkVoidFunction padding_61710136[1]; +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_debug_report) + PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; + PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT; + PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; +#else + PFN_vkVoidFunction padding_250c28de[3]; +#endif /* defined(VK_EXT_debug_report) */ +#if defined(VK_EXT_debug_utils) + PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT; + PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT; + PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT; + PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT; + PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT; + PFN_vkQueueBeginDebugUtilsLabelEXT vkQueueBeginDebugUtilsLabelEXT; + PFN_vkQueueEndDebugUtilsLabelEXT vkQueueEndDebugUtilsLabelEXT; + PFN_vkQueueInsertDebugUtilsLabelEXT vkQueueInsertDebugUtilsLabelEXT; + PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT; + PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT; + PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT; +#else + PFN_vkVoidFunction padding_3e2e81f7[11]; +#endif /* defined(VK_EXT_debug_utils) */ +#if defined(VK_EXT_descriptor_heap) + PFN_vkGetPhysicalDeviceDescriptorSizeEXT vkGetPhysicalDeviceDescriptorSizeEXT; +#else + PFN_vkVoidFunction padding_ce9bfed[1]; +#endif /* defined(VK_EXT_descriptor_heap) */ +#if defined(VK_EXT_direct_mode_display) + PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; +#else + PFN_vkVoidFunction padding_899830c3[1]; +#endif /* defined(VK_EXT_direct_mode_display) */ +#if defined(VK_EXT_directfb_surface) + PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT; + PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectFBPresentationSupportEXT; +#else + PFN_vkVoidFunction padding_f7e0f7b1[2]; +#endif /* defined(VK_EXT_directfb_surface) */ +#if defined(VK_EXT_display_surface_counter) + PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; +#else + PFN_vkVoidFunction padding_8bff43f7[1]; +#endif /* defined(VK_EXT_display_surface_counter) */ +#if defined(VK_EXT_full_screen_exclusive) + PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT; +#else + PFN_vkVoidFunction padding_ff6b086[1]; +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_headless_surface) + PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT; +#else + PFN_vkVoidFunction padding_f8cab9e0[1]; +#endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_metal_surface) + PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; +#else + PFN_vkVoidFunction padding_1c6d079a[1]; +#endif /* defined(VK_EXT_metal_surface) */ +#if defined(VK_EXT_sample_locations) + PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT; +#else + PFN_vkVoidFunction padding_fd7ffce7[1]; +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_tooling_info) + PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT; +#else + PFN_vkVoidFunction padding_99aa5ee9[1]; +#endif /* defined(VK_EXT_tooling_info) */ +#if defined(VK_FUCHSIA_imagepipe_surface) + PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA; +#else + PFN_vkVoidFunction padding_6db35e8f[1]; +#endif /* defined(VK_FUCHSIA_imagepipe_surface) */ +#if defined(VK_GGP_stream_descriptor_surface) + PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; +#else + PFN_vkVoidFunction padding_cc96d0ec[1]; +#endif /* defined(VK_GGP_stream_descriptor_surface) */ +#if defined(VK_KHR_android_surface) + PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; +#else + PFN_vkVoidFunction padding_ab4fe82c[1]; +#endif /* defined(VK_KHR_android_surface) */ +#if defined(VK_KHR_calibrated_timestamps) + PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR vkGetPhysicalDeviceCalibrateableTimeDomainsKHR; +#else + PFN_vkVoidFunction padding_663b2fa0[1]; +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_cooperative_matrix) + PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR; +#else + PFN_vkVoidFunction padding_59e376cc[1]; +#endif /* defined(VK_KHR_cooperative_matrix) */ +#if defined(VK_KHR_device_group_creation) + PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR; +#else + PFN_vkVoidFunction padding_6db81211[1]; +#endif /* defined(VK_KHR_device_group_creation) */ +#if defined(VK_KHR_display) + PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR; + PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR; + PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR; + PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR; + PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR; + PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR; + PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR; +#else + PFN_vkVoidFunction padding_cce37eaf[7]; +#endif /* defined(VK_KHR_display) */ +#if defined(VK_KHR_external_fence_capabilities) + PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; +#else + PFN_vkVoidFunction padding_b2076412[1]; +#endif /* defined(VK_KHR_external_fence_capabilities) */ +#if defined(VK_KHR_external_memory_capabilities) + PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR vkGetPhysicalDeviceExternalBufferPropertiesKHR; +#else + PFN_vkVoidFunction padding_f167e378[1]; +#endif /* defined(VK_KHR_external_memory_capabilities) */ +#if defined(VK_KHR_external_semaphore_capabilities) + PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR vkGetPhysicalDeviceExternalSemaphorePropertiesKHR; +#else + PFN_vkVoidFunction padding_acdaf099[1]; +#endif /* defined(VK_KHR_external_semaphore_capabilities) */ +#if defined(VK_KHR_fragment_shading_rate) + PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR; +#else + PFN_vkVoidFunction padding_d59cae82[1]; +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_display_properties2) + PFN_vkGetDisplayModeProperties2KHR vkGetDisplayModeProperties2KHR; + PFN_vkGetDisplayPlaneCapabilities2KHR vkGetDisplayPlaneCapabilities2KHR; + PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR vkGetPhysicalDeviceDisplayPlaneProperties2KHR; + PFN_vkGetPhysicalDeviceDisplayProperties2KHR vkGetPhysicalDeviceDisplayProperties2KHR; +#else + PFN_vkVoidFunction padding_46c0938b[4]; +#endif /* defined(VK_KHR_get_display_properties2) */ +#if defined(VK_KHR_get_physical_device_properties2) + PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; + PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR; + PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2KHR; + PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR; + PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; + PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR; + PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR vkGetPhysicalDeviceSparseImageFormatProperties2KHR; +#else + PFN_vkVoidFunction padding_5fac460e[7]; +#endif /* defined(VK_KHR_get_physical_device_properties2) */ +#if defined(VK_KHR_get_surface_capabilities2) + PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR; + PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR; +#else + PFN_vkVoidFunction padding_3baff606[2]; +#endif /* defined(VK_KHR_get_surface_capabilities2) */ +#if defined(VK_KHR_performance_query) + PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; + PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR; +#else + PFN_vkVoidFunction padding_1b45ef8f[2]; +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_surface) + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; +#else + PFN_vkVoidFunction padding_8f1ea665[5]; +#endif /* defined(VK_KHR_surface) */ +#if defined(VK_KHR_video_encode_queue) + PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR; +#else + PFN_vkVoidFunction padding_f0a3114[1]; +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) + PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR vkGetPhysicalDeviceVideoCapabilitiesKHR; + PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR vkGetPhysicalDeviceVideoFormatPropertiesKHR; +#else + PFN_vkVoidFunction padding_12d937aa[2]; +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_KHR_wayland_surface) + PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; + PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR; +#else + PFN_vkVoidFunction padding_92436324[2]; +#endif /* defined(VK_KHR_wayland_surface) */ +#if defined(VK_KHR_win32_surface) + PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; + PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR; +#else + PFN_vkVoidFunction padding_b8dcaf56[2]; +#endif /* defined(VK_KHR_win32_surface) */ +#if defined(VK_KHR_xcb_surface) + PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; + PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR; +#else + PFN_vkVoidFunction padding_b6b79326[2]; +#endif /* defined(VK_KHR_xcb_surface) */ +#if defined(VK_KHR_xlib_surface) + PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; + PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR; +#else + PFN_vkVoidFunction padding_c5e2b5db[2]; +#endif /* defined(VK_KHR_xlib_surface) */ +#if defined(VK_MVK_ios_surface) + PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK; +#else + PFN_vkVoidFunction padding_52f99096[1]; +#endif /* defined(VK_MVK_ios_surface) */ +#if defined(VK_MVK_macos_surface) + PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; +#else + PFN_vkVoidFunction padding_1d7ced9a[1]; +#endif /* defined(VK_MVK_macos_surface) */ +#if defined(VK_NN_vi_surface) + PFN_vkCreateViSurfaceNN vkCreateViSurfaceNN; +#else + PFN_vkVoidFunction padding_d9ec3901[1]; +#endif /* defined(VK_NN_vi_surface) */ +#if defined(VK_NV_acquire_winrt_display) + PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV; + PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV; +#else + PFN_vkVoidFunction padding_41c66e6[2]; +#endif /* defined(VK_NV_acquire_winrt_display) */ +#if defined(VK_NV_cooperative_matrix) + PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; +#else + PFN_vkVoidFunction padding_ee7fcfc8[1]; +#endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_cooperative_matrix2) + PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV; +#else + PFN_vkVoidFunction padding_2ec091f4[1]; +#endif /* defined(VK_NV_cooperative_matrix2) */ +#if defined(VK_NV_cooperative_vector) + PFN_vkGetPhysicalDeviceCooperativeVectorPropertiesNV vkGetPhysicalDeviceCooperativeVectorPropertiesNV; +#else + PFN_vkVoidFunction padding_50d51145[1]; +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_coverage_reduction_mode) + PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV; +#else + PFN_vkVoidFunction padding_9a9f15ac[1]; +#endif /* defined(VK_NV_coverage_reduction_mode) */ +#if defined(VK_NV_external_memory_capabilities) + PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; +#else + PFN_vkVoidFunction padding_988145[1]; +#endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_optical_flow) + PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV vkGetPhysicalDeviceOpticalFlowImageFormatsNV; +#else + PFN_vkVoidFunction padding_46a4b95[1]; +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_OHOS_surface) + PFN_vkCreateSurfaceOHOS vkCreateSurfaceOHOS; +#else + PFN_vkVoidFunction padding_b94570ee[1]; +#endif /* defined(VK_OHOS_surface) */ +#if defined(VK_QNX_screen_surface) + PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX; + PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX; +#else + PFN_vkVoidFunction padding_9b43b57c[2]; +#endif /* defined(VK_QNX_screen_surface) */ +#if defined(VK_SEC_ubm_surface) + PFN_vkCreateUbmSurfaceSEC vkCreateUbmSurfaceSEC; + PFN_vkGetPhysicalDeviceUbmPresentationSupportSEC vkGetPhysicalDeviceUbmPresentationSupportSEC; +#else + PFN_vkVoidFunction padding_bdcf11f9[2]; +#endif /* defined(VK_SEC_ubm_surface) */ +#if (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) + PFN_vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM; +#else + PFN_vkVoidFunction padding_d3dcb1f3[1]; +#endif /* (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) + PFN_vkGetPhysicalDevicePresentRectanglesKHR vkGetPhysicalDevicePresentRectanglesKHR; +#else + PFN_vkVoidFunction padding_a8092b55[1]; +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ + /* VOLK_GENERATE_INSTANCE_TABLE */ +}; + +/** + * Device-specific function pointer table + */ +struct VolkDeviceTable +{ + /* VOLK_GENERATE_DEVICE_TABLE */ +#if defined(VK_VERSION_1_0) + PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; + PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets; + PFN_vkAllocateMemory vkAllocateMemory; + PFN_vkBeginCommandBuffer vkBeginCommandBuffer; + PFN_vkBindBufferMemory vkBindBufferMemory; + PFN_vkBindImageMemory vkBindImageMemory; + PFN_vkCmdBeginQuery vkCmdBeginQuery; + PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; + PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets; + PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; + PFN_vkCmdBindPipeline vkCmdBindPipeline; + PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; + PFN_vkCmdBlitImage vkCmdBlitImage; + PFN_vkCmdClearAttachments vkCmdClearAttachments; + PFN_vkCmdClearColorImage vkCmdClearColorImage; + PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage; + PFN_vkCmdCopyBuffer vkCmdCopyBuffer; + PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; + PFN_vkCmdCopyImage vkCmdCopyImage; + PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer; + PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults; + PFN_vkCmdDispatch vkCmdDispatch; + PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect; + PFN_vkCmdDraw vkCmdDraw; + PFN_vkCmdDrawIndexed vkCmdDrawIndexed; + PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect; + PFN_vkCmdDrawIndirect vkCmdDrawIndirect; + PFN_vkCmdEndQuery vkCmdEndQuery; + PFN_vkCmdEndRenderPass vkCmdEndRenderPass; + PFN_vkCmdExecuteCommands vkCmdExecuteCommands; + PFN_vkCmdFillBuffer vkCmdFillBuffer; + PFN_vkCmdNextSubpass vkCmdNextSubpass; + PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; + PFN_vkCmdPushConstants vkCmdPushConstants; + PFN_vkCmdResetEvent vkCmdResetEvent; + PFN_vkCmdResetQueryPool vkCmdResetQueryPool; + PFN_vkCmdResolveImage vkCmdResolveImage; + PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants; + PFN_vkCmdSetDepthBias vkCmdSetDepthBias; + PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds; + PFN_vkCmdSetEvent vkCmdSetEvent; + PFN_vkCmdSetLineWidth vkCmdSetLineWidth; + PFN_vkCmdSetScissor vkCmdSetScissor; + PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask; + PFN_vkCmdSetStencilReference vkCmdSetStencilReference; + PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask; + PFN_vkCmdSetViewport vkCmdSetViewport; + PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer; + PFN_vkCmdWaitEvents vkCmdWaitEvents; + PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp; + PFN_vkCreateBuffer vkCreateBuffer; + PFN_vkCreateBufferView vkCreateBufferView; + PFN_vkCreateCommandPool vkCreateCommandPool; + PFN_vkCreateComputePipelines vkCreateComputePipelines; + PFN_vkCreateDescriptorPool vkCreateDescriptorPool; + PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout; + PFN_vkCreateEvent vkCreateEvent; + PFN_vkCreateFence vkCreateFence; + PFN_vkCreateFramebuffer vkCreateFramebuffer; + PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines; + PFN_vkCreateImage vkCreateImage; + PFN_vkCreateImageView vkCreateImageView; + PFN_vkCreatePipelineCache vkCreatePipelineCache; + PFN_vkCreatePipelineLayout vkCreatePipelineLayout; + PFN_vkCreateQueryPool vkCreateQueryPool; + PFN_vkCreateRenderPass vkCreateRenderPass; + PFN_vkCreateSampler vkCreateSampler; + PFN_vkCreateSemaphore vkCreateSemaphore; + PFN_vkCreateShaderModule vkCreateShaderModule; + PFN_vkDestroyBuffer vkDestroyBuffer; + PFN_vkDestroyBufferView vkDestroyBufferView; + PFN_vkDestroyCommandPool vkDestroyCommandPool; + PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool; + PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout; + PFN_vkDestroyDevice vkDestroyDevice; + PFN_vkDestroyEvent vkDestroyEvent; + PFN_vkDestroyFence vkDestroyFence; + PFN_vkDestroyFramebuffer vkDestroyFramebuffer; + PFN_vkDestroyImage vkDestroyImage; + PFN_vkDestroyImageView vkDestroyImageView; + PFN_vkDestroyPipeline vkDestroyPipeline; + PFN_vkDestroyPipelineCache vkDestroyPipelineCache; + PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout; + PFN_vkDestroyQueryPool vkDestroyQueryPool; + PFN_vkDestroyRenderPass vkDestroyRenderPass; + PFN_vkDestroySampler vkDestroySampler; + PFN_vkDestroySemaphore vkDestroySemaphore; + PFN_vkDestroyShaderModule vkDestroyShaderModule; + PFN_vkDeviceWaitIdle vkDeviceWaitIdle; + PFN_vkEndCommandBuffer vkEndCommandBuffer; + PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; + PFN_vkFreeCommandBuffers vkFreeCommandBuffers; + PFN_vkFreeDescriptorSets vkFreeDescriptorSets; + PFN_vkFreeMemory vkFreeMemory; + PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; + PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment; + PFN_vkGetDeviceQueue vkGetDeviceQueue; + PFN_vkGetEventStatus vkGetEventStatus; + PFN_vkGetFenceStatus vkGetFenceStatus; + PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; + PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements; + PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout; + PFN_vkGetPipelineCacheData vkGetPipelineCacheData; + PFN_vkGetQueryPoolResults vkGetQueryPoolResults; + PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity; + PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; + PFN_vkMapMemory vkMapMemory; + PFN_vkMergePipelineCaches vkMergePipelineCaches; + PFN_vkQueueBindSparse vkQueueBindSparse; + PFN_vkQueueSubmit vkQueueSubmit; + PFN_vkQueueWaitIdle vkQueueWaitIdle; + PFN_vkResetCommandBuffer vkResetCommandBuffer; + PFN_vkResetCommandPool vkResetCommandPool; + PFN_vkResetDescriptorPool vkResetDescriptorPool; + PFN_vkResetEvent vkResetEvent; + PFN_vkResetFences vkResetFences; + PFN_vkSetEvent vkSetEvent; + PFN_vkUnmapMemory vkUnmapMemory; + PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets; + PFN_vkWaitForFences vkWaitForFences; +#else + PFN_vkVoidFunction padding_6ce80d51[120]; +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) + PFN_vkBindBufferMemory2 vkBindBufferMemory2; + PFN_vkBindImageMemory2 vkBindImageMemory2; + PFN_vkCmdDispatchBase vkCmdDispatchBase; + PFN_vkCmdSetDeviceMask vkCmdSetDeviceMask; + PFN_vkCreateDescriptorUpdateTemplate vkCreateDescriptorUpdateTemplate; + PFN_vkCreateSamplerYcbcrConversion vkCreateSamplerYcbcrConversion; + PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate; + PFN_vkDestroySamplerYcbcrConversion vkDestroySamplerYcbcrConversion; + PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2; + PFN_vkGetDescriptorSetLayoutSupport vkGetDescriptorSetLayoutSupport; + PFN_vkGetDeviceGroupPeerMemoryFeatures vkGetDeviceGroupPeerMemoryFeatures; + PFN_vkGetDeviceQueue2 vkGetDeviceQueue2; + PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2; + PFN_vkGetImageSparseMemoryRequirements2 vkGetImageSparseMemoryRequirements2; + PFN_vkTrimCommandPool vkTrimCommandPool; + PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate; +#else + PFN_vkVoidFunction padding_1ec56847[16]; +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) + PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2; + PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount; + PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount; + PFN_vkCmdEndRenderPass2 vkCmdEndRenderPass2; + PFN_vkCmdNextSubpass2 vkCmdNextSubpass2; + PFN_vkCreateRenderPass2 vkCreateRenderPass2; + PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress; + PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress; + PFN_vkGetDeviceMemoryOpaqueCaptureAddress vkGetDeviceMemoryOpaqueCaptureAddress; + PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue; + PFN_vkResetQueryPool vkResetQueryPool; + PFN_vkSignalSemaphore vkSignalSemaphore; + PFN_vkWaitSemaphores vkWaitSemaphores; +#else + PFN_vkVoidFunction padding_a3e00662[13]; +#endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) + PFN_vkCmdBeginRendering vkCmdBeginRendering; + PFN_vkCmdBindVertexBuffers2 vkCmdBindVertexBuffers2; + PFN_vkCmdBlitImage2 vkCmdBlitImage2; + PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2; + PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2; + PFN_vkCmdCopyImage2 vkCmdCopyImage2; + PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2; + PFN_vkCmdEndRendering vkCmdEndRendering; + PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2; + PFN_vkCmdResetEvent2 vkCmdResetEvent2; + PFN_vkCmdResolveImage2 vkCmdResolveImage2; + PFN_vkCmdSetCullMode vkCmdSetCullMode; + PFN_vkCmdSetDepthBiasEnable vkCmdSetDepthBiasEnable; + PFN_vkCmdSetDepthBoundsTestEnable vkCmdSetDepthBoundsTestEnable; + PFN_vkCmdSetDepthCompareOp vkCmdSetDepthCompareOp; + PFN_vkCmdSetDepthTestEnable vkCmdSetDepthTestEnable; + PFN_vkCmdSetDepthWriteEnable vkCmdSetDepthWriteEnable; + PFN_vkCmdSetEvent2 vkCmdSetEvent2; + PFN_vkCmdSetFrontFace vkCmdSetFrontFace; + PFN_vkCmdSetPrimitiveRestartEnable vkCmdSetPrimitiveRestartEnable; + PFN_vkCmdSetPrimitiveTopology vkCmdSetPrimitiveTopology; + PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnable; + PFN_vkCmdSetScissorWithCount vkCmdSetScissorWithCount; + PFN_vkCmdSetStencilOp vkCmdSetStencilOp; + PFN_vkCmdSetStencilTestEnable vkCmdSetStencilTestEnable; + PFN_vkCmdSetViewportWithCount vkCmdSetViewportWithCount; + PFN_vkCmdWaitEvents2 vkCmdWaitEvents2; + PFN_vkCmdWriteTimestamp2 vkCmdWriteTimestamp2; + PFN_vkCreatePrivateDataSlot vkCreatePrivateDataSlot; + PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot; + PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements; + PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements; + PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements; + PFN_vkGetPrivateData vkGetPrivateData; + PFN_vkQueueSubmit2 vkQueueSubmit2; + PFN_vkSetPrivateData vkSetPrivateData; +#else + PFN_vkVoidFunction padding_ee798a88[36]; +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) + PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2; + PFN_vkCmdBindIndexBuffer2 vkCmdBindIndexBuffer2; + PFN_vkCmdPushConstants2 vkCmdPushConstants2; + PFN_vkCmdPushDescriptorSet vkCmdPushDescriptorSet; + PFN_vkCmdPushDescriptorSet2 vkCmdPushDescriptorSet2; + PFN_vkCmdPushDescriptorSetWithTemplate vkCmdPushDescriptorSetWithTemplate; + PFN_vkCmdPushDescriptorSetWithTemplate2 vkCmdPushDescriptorSetWithTemplate2; + PFN_vkCmdSetLineStipple vkCmdSetLineStipple; + PFN_vkCmdSetRenderingAttachmentLocations vkCmdSetRenderingAttachmentLocations; + PFN_vkCmdSetRenderingInputAttachmentIndices vkCmdSetRenderingInputAttachmentIndices; + PFN_vkCopyImageToImage vkCopyImageToImage; + PFN_vkCopyImageToMemory vkCopyImageToMemory; + PFN_vkCopyMemoryToImage vkCopyMemoryToImage; + PFN_vkGetDeviceImageSubresourceLayout vkGetDeviceImageSubresourceLayout; + PFN_vkGetImageSubresourceLayout2 vkGetImageSubresourceLayout2; + PFN_vkGetRenderingAreaGranularity vkGetRenderingAreaGranularity; + PFN_vkMapMemory2 vkMapMemory2; + PFN_vkTransitionImageLayout vkTransitionImageLayout; + PFN_vkUnmapMemory2 vkUnmapMemory2; +#else + PFN_vkVoidFunction padding_82585fa3[19]; +#endif /* defined(VK_VERSION_1_4) */ +#if defined(VK_AMDX_shader_enqueue) + PFN_vkCmdDispatchGraphAMDX vkCmdDispatchGraphAMDX; + PFN_vkCmdDispatchGraphIndirectAMDX vkCmdDispatchGraphIndirectAMDX; + PFN_vkCmdDispatchGraphIndirectCountAMDX vkCmdDispatchGraphIndirectCountAMDX; + PFN_vkCmdInitializeGraphScratchMemoryAMDX vkCmdInitializeGraphScratchMemoryAMDX; + PFN_vkCreateExecutionGraphPipelinesAMDX vkCreateExecutionGraphPipelinesAMDX; + PFN_vkGetExecutionGraphPipelineNodeIndexAMDX vkGetExecutionGraphPipelineNodeIndexAMDX; + PFN_vkGetExecutionGraphPipelineScratchSizeAMDX vkGetExecutionGraphPipelineScratchSizeAMDX; +#else + PFN_vkVoidFunction padding_9d3e2bba[7]; +#endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) + PFN_vkAntiLagUpdateAMD vkAntiLagUpdateAMD; +#else + PFN_vkVoidFunction padding_cf792fb4[1]; +#endif /* defined(VK_AMD_anti_lag) */ +#if defined(VK_AMD_buffer_marker) + PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; +#else + PFN_vkVoidFunction padding_7836e92f[1]; +#endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; +#else + PFN_vkVoidFunction padding_bbf9b7bb[1]; +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_AMD_display_native_hdr) + PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD; +#else + PFN_vkVoidFunction padding_6b81b2fb[1]; +#endif /* defined(VK_AMD_display_native_hdr) */ +#if defined(VK_AMD_draw_indirect_count) + PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD; + PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD; +#else + PFN_vkVoidFunction padding_fbfa9964[2]; +#endif /* defined(VK_AMD_draw_indirect_count) */ +#if defined(VK_AMD_gpa_interface) + PFN_vkCmdBeginGpaSampleAMD vkCmdBeginGpaSampleAMD; + PFN_vkCmdBeginGpaSessionAMD vkCmdBeginGpaSessionAMD; + PFN_vkCmdCopyGpaSessionResultsAMD vkCmdCopyGpaSessionResultsAMD; + PFN_vkCmdEndGpaSampleAMD vkCmdEndGpaSampleAMD; + PFN_vkCmdEndGpaSessionAMD vkCmdEndGpaSessionAMD; + PFN_vkCreateGpaSessionAMD vkCreateGpaSessionAMD; + PFN_vkDestroyGpaSessionAMD vkDestroyGpaSessionAMD; + PFN_vkGetGpaDeviceClockInfoAMD vkGetGpaDeviceClockInfoAMD; + PFN_vkGetGpaSessionResultsAMD vkGetGpaSessionResultsAMD; + PFN_vkGetGpaSessionStatusAMD vkGetGpaSessionStatusAMD; + PFN_vkResetGpaSessionAMD vkResetGpaSessionAMD; + PFN_vkSetGpaDeviceClockModeAMD vkSetGpaDeviceClockModeAMD; +#else + PFN_vkVoidFunction padding_56ca082d[12]; +#endif /* defined(VK_AMD_gpa_interface) */ +#if defined(VK_AMD_shader_info) + PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD; +#else + PFN_vkVoidFunction padding_bfb754b[1]; +#endif /* defined(VK_AMD_shader_info) */ +#if defined(VK_ANDROID_external_memory_android_hardware_buffer) + PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; + PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; +#else + PFN_vkVoidFunction padding_c67b1beb[2]; +#endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_ARM_data_graph) + PFN_vkBindDataGraphPipelineSessionMemoryARM vkBindDataGraphPipelineSessionMemoryARM; + PFN_vkCmdDispatchDataGraphARM vkCmdDispatchDataGraphARM; + PFN_vkCreateDataGraphPipelineSessionARM vkCreateDataGraphPipelineSessionARM; + PFN_vkCreateDataGraphPipelinesARM vkCreateDataGraphPipelinesARM; + PFN_vkDestroyDataGraphPipelineSessionARM vkDestroyDataGraphPipelineSessionARM; + PFN_vkGetDataGraphPipelineAvailablePropertiesARM vkGetDataGraphPipelineAvailablePropertiesARM; + PFN_vkGetDataGraphPipelinePropertiesARM vkGetDataGraphPipelinePropertiesARM; + PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM vkGetDataGraphPipelineSessionBindPointRequirementsARM; + PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM vkGetDataGraphPipelineSessionMemoryRequirementsARM; +#else + PFN_vkVoidFunction padding_894d85d8[9]; +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 + PFN_vkCmdSetDispatchParametersARM vkCmdSetDispatchParametersARM; +#else + PFN_vkVoidFunction padding_4702b278[1]; +#endif /* defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 */ +#if defined(VK_ARM_shader_instrumentation) + PFN_vkClearShaderInstrumentationMetricsARM vkClearShaderInstrumentationMetricsARM; + PFN_vkCmdBeginShaderInstrumentationARM vkCmdBeginShaderInstrumentationARM; + PFN_vkCmdEndShaderInstrumentationARM vkCmdEndShaderInstrumentationARM; + PFN_vkCreateShaderInstrumentationARM vkCreateShaderInstrumentationARM; + PFN_vkDestroyShaderInstrumentationARM vkDestroyShaderInstrumentationARM; + PFN_vkGetShaderInstrumentationValuesARM vkGetShaderInstrumentationValuesARM; +#else + PFN_vkVoidFunction padding_dcecc311[6]; +#endif /* defined(VK_ARM_shader_instrumentation) */ +#if defined(VK_ARM_tensors) + PFN_vkBindTensorMemoryARM vkBindTensorMemoryARM; + PFN_vkCmdCopyTensorARM vkCmdCopyTensorARM; + PFN_vkCreateTensorARM vkCreateTensorARM; + PFN_vkCreateTensorViewARM vkCreateTensorViewARM; + PFN_vkDestroyTensorARM vkDestroyTensorARM; + PFN_vkDestroyTensorViewARM vkDestroyTensorViewARM; + PFN_vkGetDeviceTensorMemoryRequirementsARM vkGetDeviceTensorMemoryRequirementsARM; + PFN_vkGetTensorMemoryRequirementsARM vkGetTensorMemoryRequirementsARM; +#else + PFN_vkVoidFunction padding_df67a729[8]; +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) + PFN_vkGetTensorOpaqueCaptureDescriptorDataARM vkGetTensorOpaqueCaptureDescriptorDataARM; + PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM vkGetTensorViewOpaqueCaptureDescriptorDataARM; +#else + PFN_vkVoidFunction padding_9483bf7e[2]; +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) + PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT vkCmdSetAttachmentFeedbackLoopEnableEXT; +#else + PFN_vkVoidFunction padding_760a41f5[1]; +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ +#if defined(VK_EXT_buffer_device_address) + PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; +#else + PFN_vkVoidFunction padding_3b69d885[1]; +#endif /* defined(VK_EXT_buffer_device_address) */ +#if defined(VK_EXT_calibrated_timestamps) + PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT; +#else + PFN_vkVoidFunction padding_d0981c89[1]; +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) + PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT; +#else + PFN_vkVoidFunction padding_d301ecc3[1]; +#endif /* defined(VK_EXT_color_write_enable) */ +#if defined(VK_EXT_conditional_rendering) + PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT; + PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT; +#else + PFN_vkVoidFunction padding_ab532c18[2]; +#endif /* defined(VK_EXT_conditional_rendering) */ +#if defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) + PFN_vkCmdBeginCustomResolveEXT vkCmdBeginCustomResolveEXT; +#else + PFN_vkVoidFunction padding_962e418a[1]; +#endif /* defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) */ +#if defined(VK_EXT_debug_marker) + PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBeginEXT; + PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEndEXT; + PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsertEXT; + PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT; + PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT; +#else + PFN_vkVoidFunction padding_89986968[5]; +#endif /* defined(VK_EXT_debug_marker) */ +#if defined(VK_EXT_depth_bias_control) + PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT; +#else + PFN_vkVoidFunction padding_bcddab4d[1]; +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) + PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT vkCmdBindDescriptorBufferEmbeddedSamplersEXT; + PFN_vkCmdBindDescriptorBuffersEXT vkCmdBindDescriptorBuffersEXT; + PFN_vkCmdSetDescriptorBufferOffsetsEXT vkCmdSetDescriptorBufferOffsetsEXT; + PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT vkGetBufferOpaqueCaptureDescriptorDataEXT; + PFN_vkGetDescriptorEXT vkGetDescriptorEXT; + PFN_vkGetDescriptorSetLayoutBindingOffsetEXT vkGetDescriptorSetLayoutBindingOffsetEXT; + PFN_vkGetDescriptorSetLayoutSizeEXT vkGetDescriptorSetLayoutSizeEXT; + PFN_vkGetImageOpaqueCaptureDescriptorDataEXT vkGetImageOpaqueCaptureDescriptorDataEXT; + PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; + PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; +#else + PFN_vkVoidFunction padding_80aa973c[10]; +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) + PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; +#else + PFN_vkVoidFunction padding_98d0fb33[1]; +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_descriptor_heap) + PFN_vkCmdBindResourceHeapEXT vkCmdBindResourceHeapEXT; + PFN_vkCmdBindSamplerHeapEXT vkCmdBindSamplerHeapEXT; + PFN_vkCmdPushDataEXT vkCmdPushDataEXT; + PFN_vkGetImageOpaqueCaptureDataEXT vkGetImageOpaqueCaptureDataEXT; + PFN_vkWriteResourceDescriptorsEXT vkWriteResourceDescriptorsEXT; + PFN_vkWriteSamplerDescriptorsEXT vkWriteSamplerDescriptorsEXT; +#else + PFN_vkVoidFunction padding_a061cda9[6]; +#endif /* defined(VK_EXT_descriptor_heap) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) + PFN_vkRegisterCustomBorderColorEXT vkRegisterCustomBorderColorEXT; + PFN_vkUnregisterCustomBorderColorEXT vkUnregisterCustomBorderColorEXT; +#else + PFN_vkVoidFunction padding_7b7ddcfe[2]; +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) + PFN_vkGetTensorOpaqueCaptureDataARM vkGetTensorOpaqueCaptureDataARM; +#else + PFN_vkVoidFunction padding_533712c5[1]; +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) */ +#if defined(VK_EXT_device_fault) + PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; +#else + PFN_vkVoidFunction padding_55095419[1]; +#endif /* defined(VK_EXT_device_fault) */ +#if defined(VK_EXT_device_generated_commands) + PFN_vkCmdExecuteGeneratedCommandsEXT vkCmdExecuteGeneratedCommandsEXT; + PFN_vkCmdPreprocessGeneratedCommandsEXT vkCmdPreprocessGeneratedCommandsEXT; + PFN_vkCreateIndirectCommandsLayoutEXT vkCreateIndirectCommandsLayoutEXT; + PFN_vkCreateIndirectExecutionSetEXT vkCreateIndirectExecutionSetEXT; + PFN_vkDestroyIndirectCommandsLayoutEXT vkDestroyIndirectCommandsLayoutEXT; + PFN_vkDestroyIndirectExecutionSetEXT vkDestroyIndirectExecutionSetEXT; + PFN_vkGetGeneratedCommandsMemoryRequirementsEXT vkGetGeneratedCommandsMemoryRequirementsEXT; + PFN_vkUpdateIndirectExecutionSetPipelineEXT vkUpdateIndirectExecutionSetPipelineEXT; + PFN_vkUpdateIndirectExecutionSetShaderEXT vkUpdateIndirectExecutionSetShaderEXT; +#else + PFN_vkVoidFunction padding_7ba7ebaa[9]; +#endif /* defined(VK_EXT_device_generated_commands) */ +#if defined(VK_EXT_discard_rectangles) + PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; +#else + PFN_vkVoidFunction padding_d6355c2[1]; +#endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 + PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; + PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#else + PFN_vkVoidFunction padding_7bb44f77[2]; +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ +#if defined(VK_EXT_display_control) + PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; + PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; + PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT; + PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; +#else + PFN_vkVoidFunction padding_d30dfaaf[4]; +#endif /* defined(VK_EXT_display_control) */ +#if defined(VK_EXT_external_memory_host) + PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; +#else + PFN_vkVoidFunction padding_357656e9[1]; +#endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) + PFN_vkGetMemoryMetalHandleEXT vkGetMemoryMetalHandleEXT; + PFN_vkGetMemoryMetalHandlePropertiesEXT vkGetMemoryMetalHandlePropertiesEXT; +#else + PFN_vkVoidFunction padding_37d43fb[2]; +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) + PFN_vkCmdEndRendering2EXT vkCmdEndRendering2EXT; +#else + PFN_vkVoidFunction padding_9c90cf11[1]; +#endif /* defined(VK_EXT_fragment_density_map_offset) */ +#if defined(VK_EXT_full_screen_exclusive) + PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT; + PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT; +#else + PFN_vkVoidFunction padding_3859df46[2]; +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) + PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; +#else + PFN_vkVoidFunction padding_e5b48b5b[1]; +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ +#if defined(VK_EXT_hdr_metadata) + PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; +#else + PFN_vkVoidFunction padding_ca6d733c[1]; +#endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_image_copy) + PFN_vkCopyImageToImageEXT vkCopyImageToImageEXT; + PFN_vkCopyImageToMemoryEXT vkCopyImageToMemoryEXT; + PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT; + PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT; +#else + PFN_vkVoidFunction padding_dd6d9b61[4]; +#endif /* defined(VK_EXT_host_image_copy) */ +#if defined(VK_EXT_host_query_reset) + PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; +#else + PFN_vkVoidFunction padding_34e58bd3[1]; +#endif /* defined(VK_EXT_host_query_reset) */ +#if defined(VK_EXT_image_drm_format_modifier) + PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT; +#else + PFN_vkVoidFunction padding_eb50dc14[1]; +#endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) + PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; +#else + PFN_vkVoidFunction padding_8a212c37[1]; +#endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_memory_decompression) + PFN_vkCmdDecompressMemoryEXT vkCmdDecompressMemoryEXT; + PFN_vkCmdDecompressMemoryIndirectCountEXT vkCmdDecompressMemoryIndirectCountEXT; +#else + PFN_vkVoidFunction padding_c3b649ee[2]; +#endif /* defined(VK_EXT_memory_decompression) */ +#if defined(VK_EXT_mesh_shader) + PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT; + PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT; +#else + PFN_vkVoidFunction padding_f65e838[2]; +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; +#else + PFN_vkVoidFunction padding_dcbaac2f[1]; +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_EXT_metal_objects) + PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT; +#else + PFN_vkVoidFunction padding_df21f735[1]; +#endif /* defined(VK_EXT_metal_objects) */ +#if defined(VK_EXT_multi_draw) + PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; + PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; +#else + PFN_vkVoidFunction padding_ce8b93b6[2]; +#endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) + PFN_vkBuildMicromapsEXT vkBuildMicromapsEXT; + PFN_vkCmdBuildMicromapsEXT vkCmdBuildMicromapsEXT; + PFN_vkCmdCopyMemoryToMicromapEXT vkCmdCopyMemoryToMicromapEXT; + PFN_vkCmdCopyMicromapEXT vkCmdCopyMicromapEXT; + PFN_vkCmdCopyMicromapToMemoryEXT vkCmdCopyMicromapToMemoryEXT; + PFN_vkCmdWriteMicromapsPropertiesEXT vkCmdWriteMicromapsPropertiesEXT; + PFN_vkCopyMemoryToMicromapEXT vkCopyMemoryToMicromapEXT; + PFN_vkCopyMicromapEXT vkCopyMicromapEXT; + PFN_vkCopyMicromapToMemoryEXT vkCopyMicromapToMemoryEXT; + PFN_vkCreateMicromapEXT vkCreateMicromapEXT; + PFN_vkDestroyMicromapEXT vkDestroyMicromapEXT; + PFN_vkGetDeviceMicromapCompatibilityEXT vkGetDeviceMicromapCompatibilityEXT; + PFN_vkGetMicromapBuildSizesEXT vkGetMicromapBuildSizesEXT; + PFN_vkWriteMicromapsPropertiesEXT vkWriteMicromapsPropertiesEXT; +#else + PFN_vkVoidFunction padding_fa41e53c[14]; +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) + PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT; +#else + PFN_vkVoidFunction padding_b2d2c2d7[1]; +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) + PFN_vkGetPipelinePropertiesEXT vkGetPipelinePropertiesEXT; +#else + PFN_vkVoidFunction padding_11313020[1]; +#endif /* defined(VK_EXT_pipeline_properties) */ +#if defined(VK_EXT_present_timing) + PFN_vkGetPastPresentationTimingEXT vkGetPastPresentationTimingEXT; + PFN_vkGetSwapchainTimeDomainPropertiesEXT vkGetSwapchainTimeDomainPropertiesEXT; + PFN_vkGetSwapchainTimingPropertiesEXT vkGetSwapchainTimingPropertiesEXT; + PFN_vkSetSwapchainPresentTimingQueueSizeEXT vkSetSwapchainPresentTimingQueueSizeEXT; +#else + PFN_vkVoidFunction padding_8751feb5[4]; +#endif /* defined(VK_EXT_present_timing) */ +#if defined(VK_EXT_primitive_restart_index) + PFN_vkCmdSetPrimitiveRestartIndexEXT vkCmdSetPrimitiveRestartIndexEXT; +#else + PFN_vkVoidFunction padding_a1770b32[1]; +#endif /* defined(VK_EXT_primitive_restart_index) */ +#if defined(VK_EXT_private_data) + PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; + PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; + PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT; + PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; +#else + PFN_vkVoidFunction padding_108010f[4]; +#endif /* defined(VK_EXT_private_data) */ +#if defined(VK_EXT_sample_locations) + PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; +#else + PFN_vkVoidFunction padding_26f9079f[1]; +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) + PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; + PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; +#else + PFN_vkVoidFunction padding_e10c8f86[2]; +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) + PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; + PFN_vkCreateShadersEXT vkCreateShadersEXT; + PFN_vkDestroyShaderEXT vkDestroyShaderEXT; + PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#else + PFN_vkVoidFunction padding_374f3e18[4]; +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) + PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; +#else + PFN_vkVoidFunction padding_ea55bf74[1]; +#endif /* defined(VK_EXT_swapchain_maintenance1) */ +#if defined(VK_EXT_transform_feedback) + PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT; + PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT; + PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT; + PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT; + PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT; + PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT; +#else + PFN_vkVoidFunction padding_36980658[6]; +#endif /* defined(VK_EXT_transform_feedback) */ +#if defined(VK_EXT_validation_cache) + PFN_vkCreateValidationCacheEXT vkCreateValidationCacheEXT; + PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT; + PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; + PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; +#else + PFN_vkVoidFunction padding_b4f2df29[4]; +#endif /* defined(VK_EXT_validation_cache) */ +#if defined(VK_FUCHSIA_buffer_collection) + PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; + PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA; + PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA; + PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA; + PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA; +#else + PFN_vkVoidFunction padding_8eaa27bc[5]; +#endif /* defined(VK_FUCHSIA_buffer_collection) */ +#if defined(VK_FUCHSIA_external_memory) + PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; + PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; +#else + PFN_vkVoidFunction padding_e3cb8a67[2]; +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) + PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA; + PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA; +#else + PFN_vkVoidFunction padding_3df6f656[2]; +#endif /* defined(VK_FUCHSIA_external_semaphore) */ +#if defined(VK_GOOGLE_display_timing) + PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; + PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; +#else + PFN_vkVoidFunction padding_2a6f50cd[2]; +#endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) + PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; + PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#else + PFN_vkVoidFunction padding_75b97be6[2]; +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ +#if defined(VK_HUAWEI_invocation_mask) + PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; +#else + PFN_vkVoidFunction padding_c3a4569f[1]; +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 + PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#else + PFN_vkVoidFunction padding_2e923f32[1]; +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ +#if defined(VK_HUAWEI_subpass_shading) + PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI; +#else + PFN_vkVoidFunction padding_f766fdf5[1]; +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) + PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL; + PFN_vkCmdSetPerformanceMarkerINTEL vkCmdSetPerformanceMarkerINTEL; + PFN_vkCmdSetPerformanceOverrideINTEL vkCmdSetPerformanceOverrideINTEL; + PFN_vkCmdSetPerformanceStreamMarkerINTEL vkCmdSetPerformanceStreamMarkerINTEL; + PFN_vkGetPerformanceParameterINTEL vkGetPerformanceParameterINTEL; + PFN_vkInitializePerformanceApiINTEL vkInitializePerformanceApiINTEL; + PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL; + PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL; + PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL; +#else + PFN_vkVoidFunction padding_495a0a0b[9]; +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) + PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR; + PFN_vkCmdBuildAccelerationStructuresIndirectKHR vkCmdBuildAccelerationStructuresIndirectKHR; + PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; + PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR; + PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR; + PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR; + PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR; + PFN_vkCopyAccelerationStructureKHR vkCopyAccelerationStructureKHR; + PFN_vkCopyAccelerationStructureToMemoryKHR vkCopyAccelerationStructureToMemoryKHR; + PFN_vkCopyMemoryToAccelerationStructureKHR vkCopyMemoryToAccelerationStructureKHR; + PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR; + PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR; + PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR; + PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; + PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR; + PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR; +#else + PFN_vkVoidFunction padding_5a999b78[16]; +#endif /* defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_bind_memory2) + PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; + PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; +#else + PFN_vkVoidFunction padding_ed8481f5[2]; +#endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) + PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; + PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR; + PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR; +#else + PFN_vkVoidFunction padding_178fdf81[3]; +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_calibrated_timestamps) + PFN_vkGetCalibratedTimestampsKHR vkGetCalibratedTimestampsKHR; +#else + PFN_vkVoidFunction padding_8fd6f40d[1]; +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_copy_commands2) + PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; + PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR; + PFN_vkCmdCopyBufferToImage2KHR vkCmdCopyBufferToImage2KHR; + PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR; + PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR; + PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR; +#else + PFN_vkVoidFunction padding_4c841ff2[6]; +#endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) + PFN_vkCmdCopyMemoryIndirectKHR vkCmdCopyMemoryIndirectKHR; + PFN_vkCmdCopyMemoryToImageIndirectKHR vkCmdCopyMemoryToImageIndirectKHR; +#else + PFN_vkVoidFunction padding_95995957[2]; +#endif /* defined(VK_KHR_copy_memory_indirect) */ +#if defined(VK_KHR_create_renderpass2) + PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR; + PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR; + PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR; + PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR; +#else + PFN_vkVoidFunction padding_2a0a8727[4]; +#endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) + PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR; + PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR; + PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR; + PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR; + PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR; +#else + PFN_vkVoidFunction padding_346287bb[5]; +#endif /* defined(VK_KHR_deferred_host_operations) */ +#if defined(VK_KHR_descriptor_update_template) + PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR; + PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR; + PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR; +#else + PFN_vkVoidFunction padding_3d63aec0[3]; +#endif /* defined(VK_KHR_descriptor_update_template) */ +#if defined(VK_KHR_device_address_commands) + PFN_vkCmdBindIndexBuffer3KHR vkCmdBindIndexBuffer3KHR; + PFN_vkCmdBindVertexBuffers3KHR vkCmdBindVertexBuffers3KHR; + PFN_vkCmdCopyImageToMemoryKHR vkCmdCopyImageToMemoryKHR; + PFN_vkCmdCopyMemoryKHR vkCmdCopyMemoryKHR; + PFN_vkCmdCopyMemoryToImageKHR vkCmdCopyMemoryToImageKHR; + PFN_vkCmdCopyQueryPoolResultsToMemoryKHR vkCmdCopyQueryPoolResultsToMemoryKHR; + PFN_vkCmdDispatchIndirect2KHR vkCmdDispatchIndirect2KHR; + PFN_vkCmdDrawIndexedIndirect2KHR vkCmdDrawIndexedIndirect2KHR; + PFN_vkCmdDrawIndirect2KHR vkCmdDrawIndirect2KHR; + PFN_vkCmdFillMemoryKHR vkCmdFillMemoryKHR; + PFN_vkCmdUpdateMemoryKHR vkCmdUpdateMemoryKHR; +#else + PFN_vkVoidFunction padding_2b90e4ce[11]; +#endif /* defined(VK_KHR_device_address_commands) */ +#if defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) + PFN_vkCmdDrawIndexedIndirectCount2KHR vkCmdDrawIndexedIndirectCount2KHR; + PFN_vkCmdDrawIndirectCount2KHR vkCmdDrawIndirectCount2KHR; +#else + PFN_vkVoidFunction padding_7a492754[2]; +#endif /* defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) + PFN_vkCmdBeginConditionalRendering2EXT vkCmdBeginConditionalRendering2EXT; +#else + PFN_vkVoidFunction padding_f9bf440[1]; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) + PFN_vkCmdBeginTransformFeedback2EXT vkCmdBeginTransformFeedback2EXT; + PFN_vkCmdBindTransformFeedbackBuffers2EXT vkCmdBindTransformFeedbackBuffers2EXT; + PFN_vkCmdDrawIndirectByteCount2EXT vkCmdDrawIndirectByteCount2EXT; + PFN_vkCmdEndTransformFeedback2EXT vkCmdEndTransformFeedback2EXT; +#else + PFN_vkVoidFunction padding_2d72d440[4]; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) + PFN_vkCmdDrawMeshTasksIndirect2EXT vkCmdDrawMeshTasksIndirect2EXT; +#else + PFN_vkVoidFunction padding_4e6fc3d1[1]; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) */ +#if defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) + PFN_vkCmdDrawMeshTasksIndirectCount2EXT vkCmdDrawMeshTasksIndirectCount2EXT; +#else + PFN_vkVoidFunction padding_5dc290cb[1]; +#endif /* defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) + PFN_vkCmdWriteMarkerToMemoryAMD vkCmdWriteMarkerToMemoryAMD; +#else + PFN_vkVoidFunction padding_140dbb45[1]; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) + PFN_vkCreateAccelerationStructure2KHR vkCreateAccelerationStructure2KHR; +#else + PFN_vkVoidFunction padding_2564889a[1]; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_device_fault) + PFN_vkGetDeviceFaultDebugInfoKHR vkGetDeviceFaultDebugInfoKHR; + PFN_vkGetDeviceFaultReportsKHR vkGetDeviceFaultReportsKHR; +#else + PFN_vkVoidFunction padding_d83e9289[2]; +#endif /* defined(VK_KHR_device_fault) */ +#if defined(VK_KHR_device_group) + PFN_vkCmdDispatchBaseKHR vkCmdDispatchBaseKHR; + PFN_vkCmdSetDeviceMaskKHR vkCmdSetDeviceMaskKHR; + PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR vkGetDeviceGroupPeerMemoryFeaturesKHR; +#else + PFN_vkVoidFunction padding_5ebe16bd[3]; +#endif /* defined(VK_KHR_device_group) */ +#if defined(VK_KHR_display_swapchain) + PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; +#else + PFN_vkVoidFunction padding_12099367[1]; +#endif /* defined(VK_KHR_display_swapchain) */ +#if defined(VK_KHR_draw_indirect_count) + PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; + PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; +#else + PFN_vkVoidFunction padding_7b5bc4c1[2]; +#endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) + PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; + PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#else + PFN_vkVoidFunction padding_b80f75a5[2]; +#endif /* defined(VK_KHR_dynamic_rendering) */ +#if defined(VK_KHR_dynamic_rendering_local_read) + PFN_vkCmdSetRenderingAttachmentLocationsKHR vkCmdSetRenderingAttachmentLocationsKHR; + PFN_vkCmdSetRenderingInputAttachmentIndicesKHR vkCmdSetRenderingInputAttachmentIndicesKHR; +#else + PFN_vkVoidFunction padding_b1510532[2]; +#endif /* defined(VK_KHR_dynamic_rendering_local_read) */ +#if defined(VK_KHR_external_fence_fd) + PFN_vkGetFenceFdKHR vkGetFenceFdKHR; + PFN_vkImportFenceFdKHR vkImportFenceFdKHR; +#else + PFN_vkVoidFunction padding_a2c787d5[2]; +#endif /* defined(VK_KHR_external_fence_fd) */ +#if defined(VK_KHR_external_fence_win32) + PFN_vkGetFenceWin32HandleKHR vkGetFenceWin32HandleKHR; + PFN_vkImportFenceWin32HandleKHR vkImportFenceWin32HandleKHR; +#else + PFN_vkVoidFunction padding_55d8e6a9[2]; +#endif /* defined(VK_KHR_external_fence_win32) */ +#if defined(VK_KHR_external_memory_fd) + PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR; + PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR; +#else + PFN_vkVoidFunction padding_982d9e19[2]; +#endif /* defined(VK_KHR_external_memory_fd) */ +#if defined(VK_KHR_external_memory_win32) + PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR; + PFN_vkGetMemoryWin32HandlePropertiesKHR vkGetMemoryWin32HandlePropertiesKHR; +#else + PFN_vkVoidFunction padding_4af9e25a[2]; +#endif /* defined(VK_KHR_external_memory_win32) */ +#if defined(VK_KHR_external_semaphore_fd) + PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR; + PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; +#else + PFN_vkVoidFunction padding_2237b7cf[2]; +#endif /* defined(VK_KHR_external_semaphore_fd) */ +#if defined(VK_KHR_external_semaphore_win32) + PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR; + PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR; +#else + PFN_vkVoidFunction padding_c18dea52[2]; +#endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) + PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR; +#else + PFN_vkVoidFunction padding_f91b0a90[1]; +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_memory_requirements2) + PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; + PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; + PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR; +#else + PFN_vkVoidFunction padding_79d9c5c4[3]; +#endif /* defined(VK_KHR_get_memory_requirements2) */ +#if defined(VK_KHR_line_rasterization) + PFN_vkCmdSetLineStippleKHR vkCmdSetLineStippleKHR; +#else + PFN_vkVoidFunction padding_83c2939[1]; +#endif /* defined(VK_KHR_line_rasterization) */ +#if defined(VK_KHR_maintenance1) + PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR; +#else + PFN_vkVoidFunction padding_4b372c56[1]; +#endif /* defined(VK_KHR_maintenance1) */ +#if defined(VK_KHR_maintenance10) + PFN_vkCmdEndRendering2KHR vkCmdEndRendering2KHR; +#else + PFN_vkVoidFunction padding_c866e6ce[1]; +#endif /* defined(VK_KHR_maintenance10) */ +#if defined(VK_KHR_maintenance3) + PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; +#else + PFN_vkVoidFunction padding_5ea7858d[1]; +#endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) + PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR; + PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; + PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; +#else + PFN_vkVoidFunction padding_8e2d4198[3]; +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) + PFN_vkCmdBindIndexBuffer2KHR vkCmdBindIndexBuffer2KHR; + PFN_vkGetDeviceImageSubresourceLayoutKHR vkGetDeviceImageSubresourceLayoutKHR; + PFN_vkGetImageSubresourceLayout2KHR vkGetImageSubresourceLayout2KHR; + PFN_vkGetRenderingAreaGranularityKHR vkGetRenderingAreaGranularityKHR; +#else + PFN_vkVoidFunction padding_37040339[4]; +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_maintenance6) + PFN_vkCmdBindDescriptorSets2KHR vkCmdBindDescriptorSets2KHR; + PFN_vkCmdPushConstants2KHR vkCmdPushConstants2KHR; +#else + PFN_vkVoidFunction padding_442955d8[2]; +#endif /* defined(VK_KHR_maintenance6) */ +#if defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) + PFN_vkCmdPushDescriptorSet2KHR vkCmdPushDescriptorSet2KHR; + PFN_vkCmdPushDescriptorSetWithTemplate2KHR vkCmdPushDescriptorSetWithTemplate2KHR; +#else + PFN_vkVoidFunction padding_80e8513f[2]; +#endif /* defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) + PFN_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT vkCmdBindDescriptorBufferEmbeddedSamplers2EXT; + PFN_vkCmdSetDescriptorBufferOffsets2EXT vkCmdSetDescriptorBufferOffsets2EXT; +#else + PFN_vkVoidFunction padding_2816b9cd[2]; +#endif /* defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_KHR_map_memory2) + PFN_vkMapMemory2KHR vkMapMemory2KHR; + PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#else + PFN_vkVoidFunction padding_5a6d8986[2]; +#endif /* defined(VK_KHR_map_memory2) */ +#if defined(VK_KHR_performance_query) + PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; + PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; +#else + PFN_vkVoidFunction padding_76f2673b[2]; +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) + PFN_vkCreatePipelineBinariesKHR vkCreatePipelineBinariesKHR; + PFN_vkDestroyPipelineBinaryKHR vkDestroyPipelineBinaryKHR; + PFN_vkGetPipelineBinaryDataKHR vkGetPipelineBinaryDataKHR; + PFN_vkGetPipelineKeyKHR vkGetPipelineKeyKHR; + PFN_vkReleaseCapturedPipelineDataKHR vkReleaseCapturedPipelineDataKHR; +#else + PFN_vkVoidFunction padding_65232810[5]; +#endif /* defined(VK_KHR_pipeline_binary) */ +#if defined(VK_KHR_pipeline_executable_properties) + PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR; + PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR; + PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR; +#else + PFN_vkVoidFunction padding_f7629b1e[3]; +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) + PFN_vkWaitForPresentKHR vkWaitForPresentKHR; +#else + PFN_vkVoidFunction padding_b16cbe03[1]; +#endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) + PFN_vkWaitForPresent2KHR vkWaitForPresent2KHR; +#else + PFN_vkVoidFunction padding_7401483a[1]; +#endif /* defined(VK_KHR_present_wait2) */ +#if defined(VK_KHR_push_descriptor) + PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; +#else + PFN_vkVoidFunction padding_8f7712ad[1]; +#endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) + PFN_vkCmdTraceRaysIndirect2KHR vkCmdTraceRaysIndirect2KHR; +#else + PFN_vkVoidFunction padding_dd5f9b4a[1]; +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_ray_tracing_pipeline) + PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; + PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR; + PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR; + PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR; + PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR; + PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR; + PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR; +#else + PFN_vkVoidFunction padding_af99aedc[7]; +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_sampler_ycbcr_conversion) + PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; + PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; +#else + PFN_vkVoidFunction padding_88e61b30[2]; +#endif /* defined(VK_KHR_sampler_ycbcr_conversion) */ +#if defined(VK_KHR_shared_presentable_image) + PFN_vkGetSwapchainStatusKHR vkGetSwapchainStatusKHR; +#else + PFN_vkVoidFunction padding_1ff3379[1]; +#endif /* defined(VK_KHR_shared_presentable_image) */ +#if defined(VK_KHR_swapchain) + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; + PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; + PFN_vkQueuePresentKHR vkQueuePresentKHR; +#else + PFN_vkVoidFunction padding_a1de893b[5]; +#endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) + PFN_vkReleaseSwapchainImagesKHR vkReleaseSwapchainImagesKHR; +#else + PFN_vkVoidFunction padding_e032d5c4[1]; +#endif /* defined(VK_KHR_swapchain_maintenance1) */ +#if defined(VK_KHR_synchronization2) + PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; + PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR; + PFN_vkCmdSetEvent2KHR vkCmdSetEvent2KHR; + PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR; + PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; + PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; +#else + PFN_vkVoidFunction padding_e85bf128[6]; +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_timeline_semaphore) + PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR; + PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR; + PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR; +#else + PFN_vkVoidFunction padding_c799d931[3]; +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) + PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; +#else + PFN_vkVoidFunction padding_7a7cc7ad[1]; +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) + PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; + PFN_vkGetEncodedVideoSessionParametersKHR vkGetEncodedVideoSessionParametersKHR; +#else + PFN_vkVoidFunction padding_f2997fb4[2]; +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) + PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; + PFN_vkCmdBeginVideoCodingKHR vkCmdBeginVideoCodingKHR; + PFN_vkCmdControlVideoCodingKHR vkCmdControlVideoCodingKHR; + PFN_vkCmdEndVideoCodingKHR vkCmdEndVideoCodingKHR; + PFN_vkCreateVideoSessionKHR vkCreateVideoSessionKHR; + PFN_vkCreateVideoSessionParametersKHR vkCreateVideoSessionParametersKHR; + PFN_vkDestroyVideoSessionKHR vkDestroyVideoSessionKHR; + PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR; + PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR; + PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR; +#else + PFN_vkVoidFunction padding_98fb7016[10]; +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_NVX_binary_import) + PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX; + PFN_vkCreateCuFunctionNVX vkCreateCuFunctionNVX; + PFN_vkCreateCuModuleNVX vkCreateCuModuleNVX; + PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX; + PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX; +#else + PFN_vkVoidFunction padding_eb54309b[5]; +#endif /* defined(VK_NVX_binary_import) */ +#if defined(VK_NVX_image_view_handle) + PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX; +#else + PFN_vkVoidFunction padding_887f6736[1]; +#endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 + PFN_vkGetImageViewHandle64NVX vkGetImageViewHandle64NVX; +#else + PFN_vkVoidFunction padding_64ad40e2[1]; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 + PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; +#else + PFN_vkVoidFunction padding_d290479a[1]; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 + PFN_vkGetDeviceCombinedImageSamplerIndexNVX vkGetDeviceCombinedImageSamplerIndexNVX; +#else + PFN_vkVoidFunction padding_a980205b[1]; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 */ +#if defined(VK_NV_clip_space_w_scaling) + PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; +#else + PFN_vkVoidFunction padding_88d7eb2e[1]; +#endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_cluster_acceleration_structure) + PFN_vkCmdBuildClusterAccelerationStructureIndirectNV vkCmdBuildClusterAccelerationStructureIndirectNV; + PFN_vkGetClusterAccelerationStructureBuildSizesNV vkGetClusterAccelerationStructureBuildSizesNV; +#else + PFN_vkVoidFunction padding_60e35395[2]; +#endif /* defined(VK_NV_cluster_acceleration_structure) */ +#if defined(VK_NV_compute_occupancy_priority) + PFN_vkCmdSetComputeOccupancyPriorityNV vkCmdSetComputeOccupancyPriorityNV; +#else + PFN_vkVoidFunction padding_488584ea[1]; +#endif /* defined(VK_NV_compute_occupancy_priority) */ +#if defined(VK_NV_cooperative_vector) + PFN_vkCmdConvertCooperativeVectorMatrixNV vkCmdConvertCooperativeVectorMatrixNV; + PFN_vkConvertCooperativeVectorMatrixNV vkConvertCooperativeVectorMatrixNV; +#else + PFN_vkVoidFunction padding_f4a887d0[2]; +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_copy_memory_indirect) + PFN_vkCmdCopyMemoryIndirectNV vkCmdCopyMemoryIndirectNV; + PFN_vkCmdCopyMemoryToImageIndirectNV vkCmdCopyMemoryToImageIndirectNV; +#else + PFN_vkVoidFunction padding_9536230e[2]; +#endif /* defined(VK_NV_copy_memory_indirect) */ +#if defined(VK_NV_cuda_kernel_launch) + PFN_vkCmdCudaLaunchKernelNV vkCmdCudaLaunchKernelNV; + PFN_vkCreateCudaFunctionNV vkCreateCudaFunctionNV; + PFN_vkCreateCudaModuleNV vkCreateCudaModuleNV; + PFN_vkDestroyCudaFunctionNV vkDestroyCudaFunctionNV; + PFN_vkDestroyCudaModuleNV vkDestroyCudaModuleNV; + PFN_vkGetCudaModuleCacheNV vkGetCudaModuleCacheNV; +#else + PFN_vkVoidFunction padding_2eabdf3b[6]; +#endif /* defined(VK_NV_cuda_kernel_launch) */ +#if defined(VK_NV_device_diagnostic_checkpoints) + PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; + PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; +#else + PFN_vkVoidFunction padding_adaa5a21[2]; +#endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) + PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; +#else + PFN_vkVoidFunction padding_c776633d[1]; +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_NV_device_generated_commands) + PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV; + PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV; + PFN_vkCmdPreprocessGeneratedCommandsNV vkCmdPreprocessGeneratedCommandsNV; + PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV; + PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; + PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; +#else + PFN_vkVoidFunction padding_4c7e4395[6]; +#endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) + PFN_vkCmdUpdatePipelineIndirectBufferNV vkCmdUpdatePipelineIndirectBufferNV; + PFN_vkGetPipelineIndirectDeviceAddressNV vkGetPipelineIndirectDeviceAddressNV; + PFN_vkGetPipelineIndirectMemoryRequirementsNV vkGetPipelineIndirectMemoryRequirementsNV; +#else + PFN_vkVoidFunction padding_5195094c[3]; +#endif /* defined(VK_NV_device_generated_commands_compute) */ +#if defined(VK_NV_external_compute_queue) + PFN_vkCreateExternalComputeQueueNV vkCreateExternalComputeQueueNV; + PFN_vkDestroyExternalComputeQueueNV vkDestroyExternalComputeQueueNV; + PFN_vkGetExternalComputeQueueDataNV vkGetExternalComputeQueueDataNV; +#else + PFN_vkVoidFunction padding_4f947e0b[3]; +#endif /* defined(VK_NV_external_compute_queue) */ +#if defined(VK_NV_external_memory_rdma) + PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV; +#else + PFN_vkVoidFunction padding_920e405[1]; +#endif /* defined(VK_NV_external_memory_rdma) */ +#if defined(VK_NV_external_memory_win32) + PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; +#else + PFN_vkVoidFunction padding_c13d6f3a[1]; +#endif /* defined(VK_NV_external_memory_win32) */ +#if defined(VK_NV_fragment_shading_rate_enums) + PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; +#else + PFN_vkVoidFunction padding_4979ca14[1]; +#endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) + PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; + PFN_vkLatencySleepNV vkLatencySleepNV; + PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; + PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; + PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#else + PFN_vkVoidFunction padding_fabf8b19[5]; +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) + PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; + PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; +#else + PFN_vkVoidFunction padding_706009[2]; +#endif /* defined(VK_NV_memory_decompression) */ +#if defined(VK_NV_mesh_shader) + PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; + PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV; +#else + PFN_vkVoidFunction padding_ac232758[2]; +#endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) + PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; +#else + PFN_vkVoidFunction padding_53495be7[1]; +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_NV_optical_flow) + PFN_vkBindOpticalFlowSessionImageNV vkBindOpticalFlowSessionImageNV; + PFN_vkCmdOpticalFlowExecuteNV vkCmdOpticalFlowExecuteNV; + PFN_vkCreateOpticalFlowSessionNV vkCreateOpticalFlowSessionNV; + PFN_vkDestroyOpticalFlowSessionNV vkDestroyOpticalFlowSessionNV; +#else + PFN_vkVoidFunction padding_f67571eb[4]; +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) + PFN_vkCmdBuildPartitionedAccelerationStructuresNV vkCmdBuildPartitionedAccelerationStructuresNV; + PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV vkGetPartitionedAccelerationStructuresBuildSizesNV; +#else + PFN_vkVoidFunction padding_d27c8c6d[2]; +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ +#if defined(VK_NV_ray_tracing) + PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV; + PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV; + PFN_vkCmdCopyAccelerationStructureNV vkCmdCopyAccelerationStructureNV; + PFN_vkCmdTraceRaysNV vkCmdTraceRaysNV; + PFN_vkCmdWriteAccelerationStructuresPropertiesNV vkCmdWriteAccelerationStructuresPropertiesNV; + PFN_vkCompileDeferredNV vkCompileDeferredNV; + PFN_vkCreateAccelerationStructureNV vkCreateAccelerationStructureNV; + PFN_vkCreateRayTracingPipelinesNV vkCreateRayTracingPipelinesNV; + PFN_vkDestroyAccelerationStructureNV vkDestroyAccelerationStructureNV; + PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV; + PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; + PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; +#else + PFN_vkVoidFunction padding_feefbeac[12]; +#endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 + PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#else + PFN_vkVoidFunction padding_e3c24f80[1]; +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ +#if defined(VK_NV_scissor_exclusive) + PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; +#else + PFN_vkVoidFunction padding_8e88d86c[1]; +#endif /* defined(VK_NV_scissor_exclusive) */ +#if defined(VK_NV_shading_rate_image) + PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; + PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; + PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; +#else + PFN_vkVoidFunction padding_92a0767f[3]; +#endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_OHOS_external_memory) + PFN_vkGetMemoryNativeBufferOHOS vkGetMemoryNativeBufferOHOS; + PFN_vkGetNativeBufferPropertiesOHOS vkGetNativeBufferPropertiesOHOS; +#else + PFN_vkVoidFunction padding_9c703846[2]; +#endif /* defined(VK_OHOS_external_memory) */ +#if defined(VK_QCOM_queue_perf_hint) + PFN_vkQueueSetPerfHintQCOM vkQueueSetPerfHintQCOM; +#else + PFN_vkVoidFunction padding_98b80534[1]; +#endif /* defined(VK_QCOM_queue_perf_hint) */ +#if defined(VK_QCOM_tile_memory_heap) + PFN_vkCmdBindTileMemoryQCOM vkCmdBindTileMemoryQCOM; +#else + PFN_vkVoidFunction padding_e2d55d04[1]; +#endif /* defined(VK_QCOM_tile_memory_heap) */ +#if defined(VK_QCOM_tile_properties) + PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM; + PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM; +#else + PFN_vkVoidFunction padding_be12e32[2]; +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) + PFN_vkCmdBeginPerTileExecutionQCOM vkCmdBeginPerTileExecutionQCOM; + PFN_vkCmdDispatchTileQCOM vkCmdDispatchTileQCOM; + PFN_vkCmdEndPerTileExecutionQCOM vkCmdEndPerTileExecutionQCOM; +#else + PFN_vkVoidFunction padding_fcd9e1df[3]; +#endif /* defined(VK_QCOM_tile_shading) */ +#if defined(VK_QNX_external_memory_screen_buffer) + PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX; +#else + PFN_vkVoidFunction padding_1c27735d[1]; +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) + PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; + PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; +#else + PFN_vkVoidFunction padding_fd71e4c6[2]; +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) + PFN_vkCmdSetDepthClampRangeEXT vkCmdSetDepthClampRangeEXT; +#else + PFN_vkVoidFunction padding_faa18a61[1]; +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) + PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; + PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; + PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; + PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; + PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; + PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; + PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; + PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; + PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; + PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; + PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; + PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#else + PFN_vkVoidFunction padding_3e8c720f[12]; +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) + PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; + PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; + PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; + PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; + PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#else + PFN_vkVoidFunction padding_b93e02a6[5]; +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) + PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; + PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; + PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; + PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; + PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; + PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; + PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; + PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; + PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; + PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; +#else + PFN_vkVoidFunction padding_ab566e7e[10]; +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) + PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; +#else + PFN_vkVoidFunction padding_6730ed0c[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) + PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; +#else + PFN_vkVoidFunction padding_d3ebb335[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) + PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; + PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; +#else + PFN_vkVoidFunction padding_a21758f4[2]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) + PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; +#else + PFN_vkVoidFunction padding_a498a838[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) + PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; +#else + PFN_vkVoidFunction padding_67db38de[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) + PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; +#else + PFN_vkVoidFunction padding_fbea7481[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) + PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; +#else + PFN_vkVoidFunction padding_3a8ec90e[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) + PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; + PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; +#else + PFN_vkVoidFunction padding_29cdb756[2]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) + PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; +#else + PFN_vkVoidFunction padding_815a7240[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) + PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#else + PFN_vkVoidFunction padding_d1f00511[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) + PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; +#else + PFN_vkVoidFunction padding_7a73d553[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) + PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; + PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; +#else + PFN_vkVoidFunction padding_6045fb8c[2]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) + PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; + PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; + PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; +#else + PFN_vkVoidFunction padding_bdc35c80[3]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) + PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; +#else + PFN_vkVoidFunction padding_9a5cd6e8[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) + PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; +#else + PFN_vkVoidFunction padding_3ee17e96[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) + PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; +#else + PFN_vkVoidFunction padding_263d525a[1]; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) + PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT; +#else + PFN_vkVoidFunction padding_ecddace1[1]; +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) + PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#else + PFN_vkVoidFunction padding_d83e1de1[1]; +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) + PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; +#else + PFN_vkVoidFunction padding_60f8358a[1]; +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) + PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR; + PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR; +#else + PFN_vkVoidFunction padding_460290c6[2]; +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) + PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; +#else + PFN_vkVoidFunction padding_cffc198[1]; +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ + /* VOLK_GENERATE_DEVICE_TABLE */ +}; + +/* VOLK_GENERATE_PROTOTYPES_H */ +#if defined(VK_VERSION_1_0) +extern PFN_vkCreateDevice vkCreateDevice; +extern PFN_vkCreateInstance vkCreateInstance; +extern PFN_vkDestroyInstance vkDestroyInstance; +extern PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; +extern PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; +extern PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; +extern PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; +extern PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; +extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; +extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; +extern PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; +extern PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties; +extern PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties; +extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; +extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; +extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; +extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties; +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) +extern PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; +extern PFN_vkEnumeratePhysicalDeviceGroups vkEnumeratePhysicalDeviceGroups; +extern PFN_vkGetPhysicalDeviceExternalBufferProperties vkGetPhysicalDeviceExternalBufferProperties; +extern PFN_vkGetPhysicalDeviceExternalFenceProperties vkGetPhysicalDeviceExternalFenceProperties; +extern PFN_vkGetPhysicalDeviceExternalSemaphoreProperties vkGetPhysicalDeviceExternalSemaphoreProperties; +extern PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2; +extern PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2; +extern PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2; +extern PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2; +extern PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2; +extern PFN_vkGetPhysicalDeviceQueueFamilyProperties2 vkGetPhysicalDeviceQueueFamilyProperties2; +extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 vkGetPhysicalDeviceSparseImageFormatProperties2; +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_3) +extern PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties; +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_ARM_data_graph) +extern PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM; +extern PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM; +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_data_graph_optical_flow) +extern PFN_vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM; +#endif /* defined(VK_ARM_data_graph_optical_flow) */ +#if defined(VK_ARM_performance_counters_by_region) +extern PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM; +#endif /* defined(VK_ARM_performance_counters_by_region) */ +#if defined(VK_ARM_shader_instrumentation) +extern PFN_vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM; +#endif /* defined(VK_ARM_shader_instrumentation) */ +#if defined(VK_ARM_tensors) +extern PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM vkGetPhysicalDeviceExternalTensorPropertiesARM; +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_EXT_acquire_drm_display) +extern PFN_vkAcquireDrmDisplayEXT vkAcquireDrmDisplayEXT; +extern PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; +#endif /* defined(VK_EXT_acquire_drm_display) */ +#if defined(VK_EXT_acquire_xlib_display) +extern PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT; +extern PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT; +#endif /* defined(VK_EXT_acquire_xlib_display) */ +#if defined(VK_EXT_calibrated_timestamps) +extern PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT; +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_debug_report) +extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; +extern PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT; +extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; +#endif /* defined(VK_EXT_debug_report) */ +#if defined(VK_EXT_debug_utils) +extern PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT; +extern PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT; +extern PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT; +extern PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT; +extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT; +extern PFN_vkQueueBeginDebugUtilsLabelEXT vkQueueBeginDebugUtilsLabelEXT; +extern PFN_vkQueueEndDebugUtilsLabelEXT vkQueueEndDebugUtilsLabelEXT; +extern PFN_vkQueueInsertDebugUtilsLabelEXT vkQueueInsertDebugUtilsLabelEXT; +extern PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT; +extern PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT; +extern PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT; +#endif /* defined(VK_EXT_debug_utils) */ +#if defined(VK_EXT_descriptor_heap) +extern PFN_vkGetPhysicalDeviceDescriptorSizeEXT vkGetPhysicalDeviceDescriptorSizeEXT; +#endif /* defined(VK_EXT_descriptor_heap) */ +#if defined(VK_EXT_direct_mode_display) +extern PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; +#endif /* defined(VK_EXT_direct_mode_display) */ +#if defined(VK_EXT_directfb_surface) +extern PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT; +extern PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectFBPresentationSupportEXT; +#endif /* defined(VK_EXT_directfb_surface) */ +#if defined(VK_EXT_display_surface_counter) +extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; +#endif /* defined(VK_EXT_display_surface_counter) */ +#if defined(VK_EXT_full_screen_exclusive) +extern PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT; +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_headless_surface) +extern PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT; +#endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_metal_surface) +extern PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; +#endif /* defined(VK_EXT_metal_surface) */ +#if defined(VK_EXT_sample_locations) +extern PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT; +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_tooling_info) +extern PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT; +#endif /* defined(VK_EXT_tooling_info) */ +#if defined(VK_FUCHSIA_imagepipe_surface) +extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA; +#endif /* defined(VK_FUCHSIA_imagepipe_surface) */ +#if defined(VK_GGP_stream_descriptor_surface) +extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; +#endif /* defined(VK_GGP_stream_descriptor_surface) */ +#if defined(VK_KHR_android_surface) +extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; +#endif /* defined(VK_KHR_android_surface) */ +#if defined(VK_KHR_calibrated_timestamps) +extern PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR vkGetPhysicalDeviceCalibrateableTimeDomainsKHR; +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_cooperative_matrix) +extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR; +#endif /* defined(VK_KHR_cooperative_matrix) */ +#if defined(VK_KHR_device_group_creation) +extern PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR; +#endif /* defined(VK_KHR_device_group_creation) */ +#if defined(VK_KHR_display) +extern PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR; +extern PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR; +extern PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR; +extern PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR; +extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR; +extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR; +extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR; +#endif /* defined(VK_KHR_display) */ +#if defined(VK_KHR_external_fence_capabilities) +extern PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; +#endif /* defined(VK_KHR_external_fence_capabilities) */ +#if defined(VK_KHR_external_memory_capabilities) +extern PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR vkGetPhysicalDeviceExternalBufferPropertiesKHR; +#endif /* defined(VK_KHR_external_memory_capabilities) */ +#if defined(VK_KHR_external_semaphore_capabilities) +extern PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR vkGetPhysicalDeviceExternalSemaphorePropertiesKHR; +#endif /* defined(VK_KHR_external_semaphore_capabilities) */ +#if defined(VK_KHR_fragment_shading_rate) +extern PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR; +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_display_properties2) +extern PFN_vkGetDisplayModeProperties2KHR vkGetDisplayModeProperties2KHR; +extern PFN_vkGetDisplayPlaneCapabilities2KHR vkGetDisplayPlaneCapabilities2KHR; +extern PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR vkGetPhysicalDeviceDisplayPlaneProperties2KHR; +extern PFN_vkGetPhysicalDeviceDisplayProperties2KHR vkGetPhysicalDeviceDisplayProperties2KHR; +#endif /* defined(VK_KHR_get_display_properties2) */ +#if defined(VK_KHR_get_physical_device_properties2) +extern PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; +extern PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR; +extern PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2KHR; +extern PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR; +extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; +extern PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR; +extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR vkGetPhysicalDeviceSparseImageFormatProperties2KHR; +#endif /* defined(VK_KHR_get_physical_device_properties2) */ +#if defined(VK_KHR_get_surface_capabilities2) +extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR; +extern PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR; +#endif /* defined(VK_KHR_get_surface_capabilities2) */ +#if defined(VK_KHR_performance_query) +extern PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; +extern PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR; +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_surface) +extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; +extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; +extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; +extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; +extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; +#endif /* defined(VK_KHR_surface) */ +#if defined(VK_KHR_video_encode_queue) +extern PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR; +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) +extern PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR vkGetPhysicalDeviceVideoCapabilitiesKHR; +extern PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR vkGetPhysicalDeviceVideoFormatPropertiesKHR; +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_KHR_wayland_surface) +extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; +extern PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR; +#endif /* defined(VK_KHR_wayland_surface) */ +#if defined(VK_KHR_win32_surface) +extern PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; +extern PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR; +#endif /* defined(VK_KHR_win32_surface) */ +#if defined(VK_KHR_xcb_surface) +extern PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; +extern PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR; +#endif /* defined(VK_KHR_xcb_surface) */ +#if defined(VK_KHR_xlib_surface) +extern PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; +extern PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR; +#endif /* defined(VK_KHR_xlib_surface) */ +#if defined(VK_MVK_ios_surface) +extern PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK; +#endif /* defined(VK_MVK_ios_surface) */ +#if defined(VK_MVK_macos_surface) +extern PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; +#endif /* defined(VK_MVK_macos_surface) */ +#if defined(VK_NN_vi_surface) +extern PFN_vkCreateViSurfaceNN vkCreateViSurfaceNN; +#endif /* defined(VK_NN_vi_surface) */ +#if defined(VK_NV_acquire_winrt_display) +extern PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV; +extern PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV; +#endif /* defined(VK_NV_acquire_winrt_display) */ +#if defined(VK_NV_cooperative_matrix) +extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; +#endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_cooperative_matrix2) +extern PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV; +#endif /* defined(VK_NV_cooperative_matrix2) */ +#if defined(VK_NV_cooperative_vector) +extern PFN_vkGetPhysicalDeviceCooperativeVectorPropertiesNV vkGetPhysicalDeviceCooperativeVectorPropertiesNV; +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_coverage_reduction_mode) +extern PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV; +#endif /* defined(VK_NV_coverage_reduction_mode) */ +#if defined(VK_NV_external_memory_capabilities) +extern PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; +#endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_optical_flow) +extern PFN_vkGetPhysicalDeviceOpticalFlowImageFormatsNV vkGetPhysicalDeviceOpticalFlowImageFormatsNV; +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_OHOS_surface) +extern PFN_vkCreateSurfaceOHOS vkCreateSurfaceOHOS; +#endif /* defined(VK_OHOS_surface) */ +#if defined(VK_QNX_screen_surface) +extern PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX; +extern PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX; +#endif /* defined(VK_QNX_screen_surface) */ +#if defined(VK_SEC_ubm_surface) +extern PFN_vkCreateUbmSurfaceSEC vkCreateUbmSurfaceSEC; +extern PFN_vkGetPhysicalDeviceUbmPresentationSupportSEC vkGetPhysicalDeviceUbmPresentationSupportSEC; +#endif /* defined(VK_SEC_ubm_surface) */ +#if (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) +extern PFN_vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM; +#endif /* (defined(VK_ARM_data_graph_instruction_set_tosa)) || (defined(VK_ARM_data_graph_optical_flow)) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) +extern PFN_vkGetPhysicalDevicePresentRectanglesKHR vkGetPhysicalDevicePresentRectanglesKHR; +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ +/* VOLK_GENERATE_PROTOTYPES_H */ + +#ifndef VOLK_NO_DEVICE_PROTOTYPES +/* VOLK_GENERATE_PROTOTYPES_H_DEVICE */ +#if defined(VK_VERSION_1_0) +extern PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; +extern PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets; +extern PFN_vkAllocateMemory vkAllocateMemory; +extern PFN_vkBeginCommandBuffer vkBeginCommandBuffer; +extern PFN_vkBindBufferMemory vkBindBufferMemory; +extern PFN_vkBindImageMemory vkBindImageMemory; +extern PFN_vkCmdBeginQuery vkCmdBeginQuery; +extern PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; +extern PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets; +extern PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; +extern PFN_vkCmdBindPipeline vkCmdBindPipeline; +extern PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; +extern PFN_vkCmdBlitImage vkCmdBlitImage; +extern PFN_vkCmdClearAttachments vkCmdClearAttachments; +extern PFN_vkCmdClearColorImage vkCmdClearColorImage; +extern PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage; +extern PFN_vkCmdCopyBuffer vkCmdCopyBuffer; +extern PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; +extern PFN_vkCmdCopyImage vkCmdCopyImage; +extern PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer; +extern PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults; +extern PFN_vkCmdDispatch vkCmdDispatch; +extern PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect; +extern PFN_vkCmdDraw vkCmdDraw; +extern PFN_vkCmdDrawIndexed vkCmdDrawIndexed; +extern PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect; +extern PFN_vkCmdDrawIndirect vkCmdDrawIndirect; +extern PFN_vkCmdEndQuery vkCmdEndQuery; +extern PFN_vkCmdEndRenderPass vkCmdEndRenderPass; +extern PFN_vkCmdExecuteCommands vkCmdExecuteCommands; +extern PFN_vkCmdFillBuffer vkCmdFillBuffer; +extern PFN_vkCmdNextSubpass vkCmdNextSubpass; +extern PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; +extern PFN_vkCmdPushConstants vkCmdPushConstants; +extern PFN_vkCmdResetEvent vkCmdResetEvent; +extern PFN_vkCmdResetQueryPool vkCmdResetQueryPool; +extern PFN_vkCmdResolveImage vkCmdResolveImage; +extern PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants; +extern PFN_vkCmdSetDepthBias vkCmdSetDepthBias; +extern PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds; +extern PFN_vkCmdSetEvent vkCmdSetEvent; +extern PFN_vkCmdSetLineWidth vkCmdSetLineWidth; +extern PFN_vkCmdSetScissor vkCmdSetScissor; +extern PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask; +extern PFN_vkCmdSetStencilReference vkCmdSetStencilReference; +extern PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask; +extern PFN_vkCmdSetViewport vkCmdSetViewport; +extern PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer; +extern PFN_vkCmdWaitEvents vkCmdWaitEvents; +extern PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp; +extern PFN_vkCreateBuffer vkCreateBuffer; +extern PFN_vkCreateBufferView vkCreateBufferView; +extern PFN_vkCreateCommandPool vkCreateCommandPool; +extern PFN_vkCreateComputePipelines vkCreateComputePipelines; +extern PFN_vkCreateDescriptorPool vkCreateDescriptorPool; +extern PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout; +extern PFN_vkCreateEvent vkCreateEvent; +extern PFN_vkCreateFence vkCreateFence; +extern PFN_vkCreateFramebuffer vkCreateFramebuffer; +extern PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines; +extern PFN_vkCreateImage vkCreateImage; +extern PFN_vkCreateImageView vkCreateImageView; +extern PFN_vkCreatePipelineCache vkCreatePipelineCache; +extern PFN_vkCreatePipelineLayout vkCreatePipelineLayout; +extern PFN_vkCreateQueryPool vkCreateQueryPool; +extern PFN_vkCreateRenderPass vkCreateRenderPass; +extern PFN_vkCreateSampler vkCreateSampler; +extern PFN_vkCreateSemaphore vkCreateSemaphore; +extern PFN_vkCreateShaderModule vkCreateShaderModule; +extern PFN_vkDestroyBuffer vkDestroyBuffer; +extern PFN_vkDestroyBufferView vkDestroyBufferView; +extern PFN_vkDestroyCommandPool vkDestroyCommandPool; +extern PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool; +extern PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout; +extern PFN_vkDestroyDevice vkDestroyDevice; +extern PFN_vkDestroyEvent vkDestroyEvent; +extern PFN_vkDestroyFence vkDestroyFence; +extern PFN_vkDestroyFramebuffer vkDestroyFramebuffer; +extern PFN_vkDestroyImage vkDestroyImage; +extern PFN_vkDestroyImageView vkDestroyImageView; +extern PFN_vkDestroyPipeline vkDestroyPipeline; +extern PFN_vkDestroyPipelineCache vkDestroyPipelineCache; +extern PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout; +extern PFN_vkDestroyQueryPool vkDestroyQueryPool; +extern PFN_vkDestroyRenderPass vkDestroyRenderPass; +extern PFN_vkDestroySampler vkDestroySampler; +extern PFN_vkDestroySemaphore vkDestroySemaphore; +extern PFN_vkDestroyShaderModule vkDestroyShaderModule; +extern PFN_vkDeviceWaitIdle vkDeviceWaitIdle; +extern PFN_vkEndCommandBuffer vkEndCommandBuffer; +extern PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; +extern PFN_vkFreeCommandBuffers vkFreeCommandBuffers; +extern PFN_vkFreeDescriptorSets vkFreeDescriptorSets; +extern PFN_vkFreeMemory vkFreeMemory; +extern PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; +extern PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment; +extern PFN_vkGetDeviceQueue vkGetDeviceQueue; +extern PFN_vkGetEventStatus vkGetEventStatus; +extern PFN_vkGetFenceStatus vkGetFenceStatus; +extern PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; +extern PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements; +extern PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout; +extern PFN_vkGetPipelineCacheData vkGetPipelineCacheData; +extern PFN_vkGetQueryPoolResults vkGetQueryPoolResults; +extern PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity; +extern PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; +extern PFN_vkMapMemory vkMapMemory; +extern PFN_vkMergePipelineCaches vkMergePipelineCaches; +extern PFN_vkQueueBindSparse vkQueueBindSparse; +extern PFN_vkQueueSubmit vkQueueSubmit; +extern PFN_vkQueueWaitIdle vkQueueWaitIdle; +extern PFN_vkResetCommandBuffer vkResetCommandBuffer; +extern PFN_vkResetCommandPool vkResetCommandPool; +extern PFN_vkResetDescriptorPool vkResetDescriptorPool; +extern PFN_vkResetEvent vkResetEvent; +extern PFN_vkResetFences vkResetFences; +extern PFN_vkSetEvent vkSetEvent; +extern PFN_vkUnmapMemory vkUnmapMemory; +extern PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets; +extern PFN_vkWaitForFences vkWaitForFences; +#endif /* defined(VK_VERSION_1_0) */ +#if defined(VK_VERSION_1_1) +extern PFN_vkBindBufferMemory2 vkBindBufferMemory2; +extern PFN_vkBindImageMemory2 vkBindImageMemory2; +extern PFN_vkCmdDispatchBase vkCmdDispatchBase; +extern PFN_vkCmdSetDeviceMask vkCmdSetDeviceMask; +extern PFN_vkCreateDescriptorUpdateTemplate vkCreateDescriptorUpdateTemplate; +extern PFN_vkCreateSamplerYcbcrConversion vkCreateSamplerYcbcrConversion; +extern PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate; +extern PFN_vkDestroySamplerYcbcrConversion vkDestroySamplerYcbcrConversion; +extern PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2; +extern PFN_vkGetDescriptorSetLayoutSupport vkGetDescriptorSetLayoutSupport; +extern PFN_vkGetDeviceGroupPeerMemoryFeatures vkGetDeviceGroupPeerMemoryFeatures; +extern PFN_vkGetDeviceQueue2 vkGetDeviceQueue2; +extern PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2; +extern PFN_vkGetImageSparseMemoryRequirements2 vkGetImageSparseMemoryRequirements2; +extern PFN_vkTrimCommandPool vkTrimCommandPool; +extern PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate; +#endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) +extern PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2; +extern PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount; +extern PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount; +extern PFN_vkCmdEndRenderPass2 vkCmdEndRenderPass2; +extern PFN_vkCmdNextSubpass2 vkCmdNextSubpass2; +extern PFN_vkCreateRenderPass2 vkCreateRenderPass2; +extern PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress; +extern PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress; +extern PFN_vkGetDeviceMemoryOpaqueCaptureAddress vkGetDeviceMemoryOpaqueCaptureAddress; +extern PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue; +extern PFN_vkResetQueryPool vkResetQueryPool; +extern PFN_vkSignalSemaphore vkSignalSemaphore; +extern PFN_vkWaitSemaphores vkWaitSemaphores; +#endif /* defined(VK_VERSION_1_2) */ +#if defined(VK_VERSION_1_3) +extern PFN_vkCmdBeginRendering vkCmdBeginRendering; +extern PFN_vkCmdBindVertexBuffers2 vkCmdBindVertexBuffers2; +extern PFN_vkCmdBlitImage2 vkCmdBlitImage2; +extern PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2; +extern PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2; +extern PFN_vkCmdCopyImage2 vkCmdCopyImage2; +extern PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2; +extern PFN_vkCmdEndRendering vkCmdEndRendering; +extern PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2; +extern PFN_vkCmdResetEvent2 vkCmdResetEvent2; +extern PFN_vkCmdResolveImage2 vkCmdResolveImage2; +extern PFN_vkCmdSetCullMode vkCmdSetCullMode; +extern PFN_vkCmdSetDepthBiasEnable vkCmdSetDepthBiasEnable; +extern PFN_vkCmdSetDepthBoundsTestEnable vkCmdSetDepthBoundsTestEnable; +extern PFN_vkCmdSetDepthCompareOp vkCmdSetDepthCompareOp; +extern PFN_vkCmdSetDepthTestEnable vkCmdSetDepthTestEnable; +extern PFN_vkCmdSetDepthWriteEnable vkCmdSetDepthWriteEnable; +extern PFN_vkCmdSetEvent2 vkCmdSetEvent2; +extern PFN_vkCmdSetFrontFace vkCmdSetFrontFace; +extern PFN_vkCmdSetPrimitiveRestartEnable vkCmdSetPrimitiveRestartEnable; +extern PFN_vkCmdSetPrimitiveTopology vkCmdSetPrimitiveTopology; +extern PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnable; +extern PFN_vkCmdSetScissorWithCount vkCmdSetScissorWithCount; +extern PFN_vkCmdSetStencilOp vkCmdSetStencilOp; +extern PFN_vkCmdSetStencilTestEnable vkCmdSetStencilTestEnable; +extern PFN_vkCmdSetViewportWithCount vkCmdSetViewportWithCount; +extern PFN_vkCmdWaitEvents2 vkCmdWaitEvents2; +extern PFN_vkCmdWriteTimestamp2 vkCmdWriteTimestamp2; +extern PFN_vkCreatePrivateDataSlot vkCreatePrivateDataSlot; +extern PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot; +extern PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements; +extern PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements; +extern PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements; +extern PFN_vkGetPrivateData vkGetPrivateData; +extern PFN_vkQueueSubmit2 vkQueueSubmit2; +extern PFN_vkSetPrivateData vkSetPrivateData; +#endif /* defined(VK_VERSION_1_3) */ +#if defined(VK_VERSION_1_4) +extern PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2; +extern PFN_vkCmdBindIndexBuffer2 vkCmdBindIndexBuffer2; +extern PFN_vkCmdPushConstants2 vkCmdPushConstants2; +extern PFN_vkCmdPushDescriptorSet vkCmdPushDescriptorSet; +extern PFN_vkCmdPushDescriptorSet2 vkCmdPushDescriptorSet2; +extern PFN_vkCmdPushDescriptorSetWithTemplate vkCmdPushDescriptorSetWithTemplate; +extern PFN_vkCmdPushDescriptorSetWithTemplate2 vkCmdPushDescriptorSetWithTemplate2; +extern PFN_vkCmdSetLineStipple vkCmdSetLineStipple; +extern PFN_vkCmdSetRenderingAttachmentLocations vkCmdSetRenderingAttachmentLocations; +extern PFN_vkCmdSetRenderingInputAttachmentIndices vkCmdSetRenderingInputAttachmentIndices; +extern PFN_vkCopyImageToImage vkCopyImageToImage; +extern PFN_vkCopyImageToMemory vkCopyImageToMemory; +extern PFN_vkCopyMemoryToImage vkCopyMemoryToImage; +extern PFN_vkGetDeviceImageSubresourceLayout vkGetDeviceImageSubresourceLayout; +extern PFN_vkGetImageSubresourceLayout2 vkGetImageSubresourceLayout2; +extern PFN_vkGetRenderingAreaGranularity vkGetRenderingAreaGranularity; +extern PFN_vkMapMemory2 vkMapMemory2; +extern PFN_vkTransitionImageLayout vkTransitionImageLayout; +extern PFN_vkUnmapMemory2 vkUnmapMemory2; +#endif /* defined(VK_VERSION_1_4) */ +#if defined(VK_AMDX_shader_enqueue) +extern PFN_vkCmdDispatchGraphAMDX vkCmdDispatchGraphAMDX; +extern PFN_vkCmdDispatchGraphIndirectAMDX vkCmdDispatchGraphIndirectAMDX; +extern PFN_vkCmdDispatchGraphIndirectCountAMDX vkCmdDispatchGraphIndirectCountAMDX; +extern PFN_vkCmdInitializeGraphScratchMemoryAMDX vkCmdInitializeGraphScratchMemoryAMDX; +extern PFN_vkCreateExecutionGraphPipelinesAMDX vkCreateExecutionGraphPipelinesAMDX; +extern PFN_vkGetExecutionGraphPipelineNodeIndexAMDX vkGetExecutionGraphPipelineNodeIndexAMDX; +extern PFN_vkGetExecutionGraphPipelineScratchSizeAMDX vkGetExecutionGraphPipelineScratchSizeAMDX; +#endif /* defined(VK_AMDX_shader_enqueue) */ +#if defined(VK_AMD_anti_lag) +extern PFN_vkAntiLagUpdateAMD vkAntiLagUpdateAMD; +#endif /* defined(VK_AMD_anti_lag) */ +#if defined(VK_AMD_buffer_marker) +extern PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; +#endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) +extern PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; +#endif /* defined(VK_AMD_buffer_marker) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_AMD_display_native_hdr) +extern PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD; +#endif /* defined(VK_AMD_display_native_hdr) */ +#if defined(VK_AMD_draw_indirect_count) +extern PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD; +extern PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD; +#endif /* defined(VK_AMD_draw_indirect_count) */ +#if defined(VK_AMD_gpa_interface) +extern PFN_vkCmdBeginGpaSampleAMD vkCmdBeginGpaSampleAMD; +extern PFN_vkCmdBeginGpaSessionAMD vkCmdBeginGpaSessionAMD; +extern PFN_vkCmdCopyGpaSessionResultsAMD vkCmdCopyGpaSessionResultsAMD; +extern PFN_vkCmdEndGpaSampleAMD vkCmdEndGpaSampleAMD; +extern PFN_vkCmdEndGpaSessionAMD vkCmdEndGpaSessionAMD; +extern PFN_vkCreateGpaSessionAMD vkCreateGpaSessionAMD; +extern PFN_vkDestroyGpaSessionAMD vkDestroyGpaSessionAMD; +extern PFN_vkGetGpaDeviceClockInfoAMD vkGetGpaDeviceClockInfoAMD; +extern PFN_vkGetGpaSessionResultsAMD vkGetGpaSessionResultsAMD; +extern PFN_vkGetGpaSessionStatusAMD vkGetGpaSessionStatusAMD; +extern PFN_vkResetGpaSessionAMD vkResetGpaSessionAMD; +extern PFN_vkSetGpaDeviceClockModeAMD vkSetGpaDeviceClockModeAMD; +#endif /* defined(VK_AMD_gpa_interface) */ +#if defined(VK_AMD_shader_info) +extern PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD; +#endif /* defined(VK_AMD_shader_info) */ +#if defined(VK_ANDROID_external_memory_android_hardware_buffer) +extern PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; +extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; +#endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_ARM_data_graph) +extern PFN_vkBindDataGraphPipelineSessionMemoryARM vkBindDataGraphPipelineSessionMemoryARM; +extern PFN_vkCmdDispatchDataGraphARM vkCmdDispatchDataGraphARM; +extern PFN_vkCreateDataGraphPipelineSessionARM vkCreateDataGraphPipelineSessionARM; +extern PFN_vkCreateDataGraphPipelinesARM vkCreateDataGraphPipelinesARM; +extern PFN_vkDestroyDataGraphPipelineSessionARM vkDestroyDataGraphPipelineSessionARM; +extern PFN_vkGetDataGraphPipelineAvailablePropertiesARM vkGetDataGraphPipelineAvailablePropertiesARM; +extern PFN_vkGetDataGraphPipelinePropertiesARM vkGetDataGraphPipelinePropertiesARM; +extern PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM vkGetDataGraphPipelineSessionBindPointRequirementsARM; +extern PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM vkGetDataGraphPipelineSessionMemoryRequirementsARM; +#endif /* defined(VK_ARM_data_graph) */ +#if defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 +extern PFN_vkCmdSetDispatchParametersARM vkCmdSetDispatchParametersARM; +#endif /* defined(VK_ARM_scheduling_controls) && VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION >= 2 */ +#if defined(VK_ARM_shader_instrumentation) +extern PFN_vkClearShaderInstrumentationMetricsARM vkClearShaderInstrumentationMetricsARM; +extern PFN_vkCmdBeginShaderInstrumentationARM vkCmdBeginShaderInstrumentationARM; +extern PFN_vkCmdEndShaderInstrumentationARM vkCmdEndShaderInstrumentationARM; +extern PFN_vkCreateShaderInstrumentationARM vkCreateShaderInstrumentationARM; +extern PFN_vkDestroyShaderInstrumentationARM vkDestroyShaderInstrumentationARM; +extern PFN_vkGetShaderInstrumentationValuesARM vkGetShaderInstrumentationValuesARM; +#endif /* defined(VK_ARM_shader_instrumentation) */ +#if defined(VK_ARM_tensors) +extern PFN_vkBindTensorMemoryARM vkBindTensorMemoryARM; +extern PFN_vkCmdCopyTensorARM vkCmdCopyTensorARM; +extern PFN_vkCreateTensorARM vkCreateTensorARM; +extern PFN_vkCreateTensorViewARM vkCreateTensorViewARM; +extern PFN_vkDestroyTensorARM vkDestroyTensorARM; +extern PFN_vkDestroyTensorViewARM vkDestroyTensorViewARM; +extern PFN_vkGetDeviceTensorMemoryRequirementsARM vkGetDeviceTensorMemoryRequirementsARM; +extern PFN_vkGetTensorMemoryRequirementsARM vkGetTensorMemoryRequirementsARM; +#endif /* defined(VK_ARM_tensors) */ +#if defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) +extern PFN_vkGetTensorOpaqueCaptureDescriptorDataARM vkGetTensorOpaqueCaptureDescriptorDataARM; +extern PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM vkGetTensorViewOpaqueCaptureDescriptorDataARM; +#endif /* defined(VK_ARM_tensors) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_attachment_feedback_loop_dynamic_state) +extern PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT vkCmdSetAttachmentFeedbackLoopEnableEXT; +#endif /* defined(VK_EXT_attachment_feedback_loop_dynamic_state) */ +#if defined(VK_EXT_buffer_device_address) +extern PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; +#endif /* defined(VK_EXT_buffer_device_address) */ +#if defined(VK_EXT_calibrated_timestamps) +extern PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT; +#endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) +extern PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT; +#endif /* defined(VK_EXT_color_write_enable) */ +#if defined(VK_EXT_conditional_rendering) +extern PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT; +extern PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT; +#endif /* defined(VK_EXT_conditional_rendering) */ +#if defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) +extern PFN_vkCmdBeginCustomResolveEXT vkCmdBeginCustomResolveEXT; +#endif /* defined(VK_EXT_custom_resolve) && (defined(VK_KHR_dynamic_rendering) || defined(VK_VERSION_1_3)) */ +#if defined(VK_EXT_debug_marker) +extern PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBeginEXT; +extern PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEndEXT; +extern PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsertEXT; +extern PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT; +extern PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT; +#endif /* defined(VK_EXT_debug_marker) */ +#if defined(VK_EXT_depth_bias_control) +extern PFN_vkCmdSetDepthBias2EXT vkCmdSetDepthBias2EXT; +#endif /* defined(VK_EXT_depth_bias_control) */ +#if defined(VK_EXT_descriptor_buffer) +extern PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT vkCmdBindDescriptorBufferEmbeddedSamplersEXT; +extern PFN_vkCmdBindDescriptorBuffersEXT vkCmdBindDescriptorBuffersEXT; +extern PFN_vkCmdSetDescriptorBufferOffsetsEXT vkCmdSetDescriptorBufferOffsetsEXT; +extern PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT vkGetBufferOpaqueCaptureDescriptorDataEXT; +extern PFN_vkGetDescriptorEXT vkGetDescriptorEXT; +extern PFN_vkGetDescriptorSetLayoutBindingOffsetEXT vkGetDescriptorSetLayoutBindingOffsetEXT; +extern PFN_vkGetDescriptorSetLayoutSizeEXT vkGetDescriptorSetLayoutSizeEXT; +extern PFN_vkGetImageOpaqueCaptureDescriptorDataEXT vkGetImageOpaqueCaptureDescriptorDataEXT; +extern PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; +extern PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) +extern PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ +#if defined(VK_EXT_descriptor_heap) +extern PFN_vkCmdBindResourceHeapEXT vkCmdBindResourceHeapEXT; +extern PFN_vkCmdBindSamplerHeapEXT vkCmdBindSamplerHeapEXT; +extern PFN_vkCmdPushDataEXT vkCmdPushDataEXT; +extern PFN_vkGetImageOpaqueCaptureDataEXT vkGetImageOpaqueCaptureDataEXT; +extern PFN_vkWriteResourceDescriptorsEXT vkWriteResourceDescriptorsEXT; +extern PFN_vkWriteSamplerDescriptorsEXT vkWriteSamplerDescriptorsEXT; +#endif /* defined(VK_EXT_descriptor_heap) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) +extern PFN_vkRegisterCustomBorderColorEXT vkRegisterCustomBorderColorEXT; +extern PFN_vkUnregisterCustomBorderColorEXT vkUnregisterCustomBorderColorEXT; +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_EXT_custom_border_color) */ +#if defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) +extern PFN_vkGetTensorOpaqueCaptureDataARM vkGetTensorOpaqueCaptureDataARM; +#endif /* defined(VK_EXT_descriptor_heap) && defined(VK_ARM_tensors) */ +#if defined(VK_EXT_device_fault) +extern PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; +#endif /* defined(VK_EXT_device_fault) */ +#if defined(VK_EXT_device_generated_commands) +extern PFN_vkCmdExecuteGeneratedCommandsEXT vkCmdExecuteGeneratedCommandsEXT; +extern PFN_vkCmdPreprocessGeneratedCommandsEXT vkCmdPreprocessGeneratedCommandsEXT; +extern PFN_vkCreateIndirectCommandsLayoutEXT vkCreateIndirectCommandsLayoutEXT; +extern PFN_vkCreateIndirectExecutionSetEXT vkCreateIndirectExecutionSetEXT; +extern PFN_vkDestroyIndirectCommandsLayoutEXT vkDestroyIndirectCommandsLayoutEXT; +extern PFN_vkDestroyIndirectExecutionSetEXT vkDestroyIndirectExecutionSetEXT; +extern PFN_vkGetGeneratedCommandsMemoryRequirementsEXT vkGetGeneratedCommandsMemoryRequirementsEXT; +extern PFN_vkUpdateIndirectExecutionSetPipelineEXT vkUpdateIndirectExecutionSetPipelineEXT; +extern PFN_vkUpdateIndirectExecutionSetShaderEXT vkUpdateIndirectExecutionSetShaderEXT; +#endif /* defined(VK_EXT_device_generated_commands) */ +#if defined(VK_EXT_discard_rectangles) +extern PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; +#endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 +extern PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; +extern PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ +#if defined(VK_EXT_display_control) +extern PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; +extern PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; +extern PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT; +extern PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; +#endif /* defined(VK_EXT_display_control) */ +#if defined(VK_EXT_external_memory_host) +extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; +#endif /* defined(VK_EXT_external_memory_host) */ +#if defined(VK_EXT_external_memory_metal) +extern PFN_vkGetMemoryMetalHandleEXT vkGetMemoryMetalHandleEXT; +extern PFN_vkGetMemoryMetalHandlePropertiesEXT vkGetMemoryMetalHandlePropertiesEXT; +#endif /* defined(VK_EXT_external_memory_metal) */ +#if defined(VK_EXT_fragment_density_map_offset) +extern PFN_vkCmdEndRendering2EXT vkCmdEndRendering2EXT; +#endif /* defined(VK_EXT_fragment_density_map_offset) */ +#if defined(VK_EXT_full_screen_exclusive) +extern PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT; +extern PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT; +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) +extern PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; +#endif /* defined(VK_EXT_full_screen_exclusive) && (defined(VK_KHR_device_group) || defined(VK_VERSION_1_1)) */ +#if defined(VK_EXT_hdr_metadata) +extern PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; +#endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_image_copy) +extern PFN_vkCopyImageToImageEXT vkCopyImageToImageEXT; +extern PFN_vkCopyImageToMemoryEXT vkCopyImageToMemoryEXT; +extern PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT; +extern PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT; +#endif /* defined(VK_EXT_host_image_copy) */ +#if defined(VK_EXT_host_query_reset) +extern PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; +#endif /* defined(VK_EXT_host_query_reset) */ +#if defined(VK_EXT_image_drm_format_modifier) +extern PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT; +#endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) +extern PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; +#endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_memory_decompression) +extern PFN_vkCmdDecompressMemoryEXT vkCmdDecompressMemoryEXT; +extern PFN_vkCmdDecompressMemoryIndirectCountEXT vkCmdDecompressMemoryIndirectCountEXT; +#endif /* defined(VK_EXT_memory_decompression) */ +#if defined(VK_EXT_mesh_shader) +extern PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT; +extern PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT; +#endif /* defined(VK_EXT_mesh_shader) */ +#if defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) +extern PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT; +#endif /* defined(VK_EXT_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_EXT_metal_objects) +extern PFN_vkExportMetalObjectsEXT vkExportMetalObjectsEXT; +#endif /* defined(VK_EXT_metal_objects) */ +#if defined(VK_EXT_multi_draw) +extern PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; +extern PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; +#endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_opacity_micromap) +extern PFN_vkBuildMicromapsEXT vkBuildMicromapsEXT; +extern PFN_vkCmdBuildMicromapsEXT vkCmdBuildMicromapsEXT; +extern PFN_vkCmdCopyMemoryToMicromapEXT vkCmdCopyMemoryToMicromapEXT; +extern PFN_vkCmdCopyMicromapEXT vkCmdCopyMicromapEXT; +extern PFN_vkCmdCopyMicromapToMemoryEXT vkCmdCopyMicromapToMemoryEXT; +extern PFN_vkCmdWriteMicromapsPropertiesEXT vkCmdWriteMicromapsPropertiesEXT; +extern PFN_vkCopyMemoryToMicromapEXT vkCopyMemoryToMicromapEXT; +extern PFN_vkCopyMicromapEXT vkCopyMicromapEXT; +extern PFN_vkCopyMicromapToMemoryEXT vkCopyMicromapToMemoryEXT; +extern PFN_vkCreateMicromapEXT vkCreateMicromapEXT; +extern PFN_vkDestroyMicromapEXT vkDestroyMicromapEXT; +extern PFN_vkGetDeviceMicromapCompatibilityEXT vkGetDeviceMicromapCompatibilityEXT; +extern PFN_vkGetMicromapBuildSizesEXT vkGetMicromapBuildSizesEXT; +extern PFN_vkWriteMicromapsPropertiesEXT vkWriteMicromapsPropertiesEXT; +#endif /* defined(VK_EXT_opacity_micromap) */ +#if defined(VK_EXT_pageable_device_local_memory) +extern PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT; +#endif /* defined(VK_EXT_pageable_device_local_memory) */ +#if defined(VK_EXT_pipeline_properties) +extern PFN_vkGetPipelinePropertiesEXT vkGetPipelinePropertiesEXT; +#endif /* defined(VK_EXT_pipeline_properties) */ +#if defined(VK_EXT_present_timing) +extern PFN_vkGetPastPresentationTimingEXT vkGetPastPresentationTimingEXT; +extern PFN_vkGetSwapchainTimeDomainPropertiesEXT vkGetSwapchainTimeDomainPropertiesEXT; +extern PFN_vkGetSwapchainTimingPropertiesEXT vkGetSwapchainTimingPropertiesEXT; +extern PFN_vkSetSwapchainPresentTimingQueueSizeEXT vkSetSwapchainPresentTimingQueueSizeEXT; +#endif /* defined(VK_EXT_present_timing) */ +#if defined(VK_EXT_primitive_restart_index) +extern PFN_vkCmdSetPrimitiveRestartIndexEXT vkCmdSetPrimitiveRestartIndexEXT; +#endif /* defined(VK_EXT_primitive_restart_index) */ +#if defined(VK_EXT_private_data) +extern PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; +extern PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; +extern PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT; +extern PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; +#endif /* defined(VK_EXT_private_data) */ +#if defined(VK_EXT_sample_locations) +extern PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; +#endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_shader_module_identifier) +extern PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; +extern PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; +#endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) +extern PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; +extern PFN_vkCreateShadersEXT vkCreateShadersEXT; +extern PFN_vkDestroyShaderEXT vkDestroyShaderEXT; +extern PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#endif /* defined(VK_EXT_shader_object) */ +#if defined(VK_EXT_swapchain_maintenance1) +extern PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; +#endif /* defined(VK_EXT_swapchain_maintenance1) */ +#if defined(VK_EXT_transform_feedback) +extern PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT; +extern PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT; +extern PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT; +extern PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT; +extern PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT; +extern PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT; +#endif /* defined(VK_EXT_transform_feedback) */ +#if defined(VK_EXT_validation_cache) +extern PFN_vkCreateValidationCacheEXT vkCreateValidationCacheEXT; +extern PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT; +extern PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; +extern PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; +#endif /* defined(VK_EXT_validation_cache) */ +#if defined(VK_FUCHSIA_buffer_collection) +extern PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; +extern PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA; +extern PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA; +extern PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA; +extern PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA; +#endif /* defined(VK_FUCHSIA_buffer_collection) */ +#if defined(VK_FUCHSIA_external_memory) +extern PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; +extern PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) +extern PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA; +extern PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_semaphore) */ +#if defined(VK_GOOGLE_display_timing) +extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; +extern PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; +#endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) +extern PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; +extern PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ +#if defined(VK_HUAWEI_invocation_mask) +extern PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 +extern PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#endif /* defined(VK_HUAWEI_subpass_shading) && VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION >= 2 */ +#if defined(VK_HUAWEI_subpass_shading) +extern PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI; +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) +extern PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL; +extern PFN_vkCmdSetPerformanceMarkerINTEL vkCmdSetPerformanceMarkerINTEL; +extern PFN_vkCmdSetPerformanceOverrideINTEL vkCmdSetPerformanceOverrideINTEL; +extern PFN_vkCmdSetPerformanceStreamMarkerINTEL vkCmdSetPerformanceStreamMarkerINTEL; +extern PFN_vkGetPerformanceParameterINTEL vkGetPerformanceParameterINTEL; +extern PFN_vkInitializePerformanceApiINTEL vkInitializePerformanceApiINTEL; +extern PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL; +extern PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL; +extern PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL; +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) +extern PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR; +extern PFN_vkCmdBuildAccelerationStructuresIndirectKHR vkCmdBuildAccelerationStructuresIndirectKHR; +extern PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; +extern PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR; +extern PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR; +extern PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR; +extern PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR; +extern PFN_vkCopyAccelerationStructureKHR vkCopyAccelerationStructureKHR; +extern PFN_vkCopyAccelerationStructureToMemoryKHR vkCopyAccelerationStructureToMemoryKHR; +extern PFN_vkCopyMemoryToAccelerationStructureKHR vkCopyMemoryToAccelerationStructureKHR; +extern PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR; +extern PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR; +extern PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR; +extern PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; +extern PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR; +extern PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR; +#endif /* defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_bind_memory2) +extern PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; +extern PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; +#endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) +extern PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; +extern PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR; +extern PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR; +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_calibrated_timestamps) +extern PFN_vkGetCalibratedTimestampsKHR vkGetCalibratedTimestampsKHR; +#endif /* defined(VK_KHR_calibrated_timestamps) */ +#if defined(VK_KHR_copy_commands2) +extern PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; +extern PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR; +extern PFN_vkCmdCopyBufferToImage2KHR vkCmdCopyBufferToImage2KHR; +extern PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR; +extern PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR; +extern PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR; +#endif /* defined(VK_KHR_copy_commands2) */ +#if defined(VK_KHR_copy_memory_indirect) +extern PFN_vkCmdCopyMemoryIndirectKHR vkCmdCopyMemoryIndirectKHR; +extern PFN_vkCmdCopyMemoryToImageIndirectKHR vkCmdCopyMemoryToImageIndirectKHR; +#endif /* defined(VK_KHR_copy_memory_indirect) */ +#if defined(VK_KHR_create_renderpass2) +extern PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR; +extern PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR; +extern PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR; +extern PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR; +#endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) +extern PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR; +extern PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR; +extern PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR; +extern PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR; +extern PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR; +#endif /* defined(VK_KHR_deferred_host_operations) */ +#if defined(VK_KHR_descriptor_update_template) +extern PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR; +extern PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR; +extern PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR; +#endif /* defined(VK_KHR_descriptor_update_template) */ +#if defined(VK_KHR_device_address_commands) +extern PFN_vkCmdBindIndexBuffer3KHR vkCmdBindIndexBuffer3KHR; +extern PFN_vkCmdBindVertexBuffers3KHR vkCmdBindVertexBuffers3KHR; +extern PFN_vkCmdCopyImageToMemoryKHR vkCmdCopyImageToMemoryKHR; +extern PFN_vkCmdCopyMemoryKHR vkCmdCopyMemoryKHR; +extern PFN_vkCmdCopyMemoryToImageKHR vkCmdCopyMemoryToImageKHR; +extern PFN_vkCmdCopyQueryPoolResultsToMemoryKHR vkCmdCopyQueryPoolResultsToMemoryKHR; +extern PFN_vkCmdDispatchIndirect2KHR vkCmdDispatchIndirect2KHR; +extern PFN_vkCmdDrawIndexedIndirect2KHR vkCmdDrawIndexedIndirect2KHR; +extern PFN_vkCmdDrawIndirect2KHR vkCmdDrawIndirect2KHR; +extern PFN_vkCmdFillMemoryKHR vkCmdFillMemoryKHR; +extern PFN_vkCmdUpdateMemoryKHR vkCmdUpdateMemoryKHR; +#endif /* defined(VK_KHR_device_address_commands) */ +#if defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) +extern PFN_vkCmdDrawIndexedIndirectCount2KHR vkCmdDrawIndexedIndirectCount2KHR; +extern PFN_vkCmdDrawIndirectCount2KHR vkCmdDrawIndirectCount2KHR; +#endif /* defined(VK_KHR_device_address_commands) && (defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) +extern PFN_vkCmdBeginConditionalRendering2EXT vkCmdBeginConditionalRendering2EXT; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_conditional_rendering) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) +extern PFN_vkCmdBeginTransformFeedback2EXT vkCmdBeginTransformFeedback2EXT; +extern PFN_vkCmdBindTransformFeedbackBuffers2EXT vkCmdBindTransformFeedbackBuffers2EXT; +extern PFN_vkCmdDrawIndirectByteCount2EXT vkCmdDrawIndirectByteCount2EXT; +extern PFN_vkCmdEndTransformFeedback2EXT vkCmdEndTransformFeedback2EXT; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_transform_feedback) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) +extern PFN_vkCmdDrawMeshTasksIndirect2EXT vkCmdDrawMeshTasksIndirect2EXT; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_EXT_mesh_shader) */ +#if defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) +extern PFN_vkCmdDrawMeshTasksIndirectCount2EXT vkCmdDrawMeshTasksIndirectCount2EXT; +#endif /* defined(VK_KHR_device_address_commands) && ((defined(VK_KHR_draw_indirect_count) || defined(VK_VERSION_1_2)) && defined(VK_EXT_mesh_shader)) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) +extern PFN_vkCmdWriteMarkerToMemoryAMD vkCmdWriteMarkerToMemoryAMD; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) +extern PFN_vkCreateAccelerationStructure2KHR vkCreateAccelerationStructure2KHR; +#endif /* defined(VK_KHR_device_address_commands) && defined(VK_KHR_acceleration_structure) */ +#if defined(VK_KHR_device_fault) +extern PFN_vkGetDeviceFaultDebugInfoKHR vkGetDeviceFaultDebugInfoKHR; +extern PFN_vkGetDeviceFaultReportsKHR vkGetDeviceFaultReportsKHR; +#endif /* defined(VK_KHR_device_fault) */ +#if defined(VK_KHR_device_group) +extern PFN_vkCmdDispatchBaseKHR vkCmdDispatchBaseKHR; +extern PFN_vkCmdSetDeviceMaskKHR vkCmdSetDeviceMaskKHR; +extern PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR vkGetDeviceGroupPeerMemoryFeaturesKHR; +#endif /* defined(VK_KHR_device_group) */ +#if defined(VK_KHR_display_swapchain) +extern PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; +#endif /* defined(VK_KHR_display_swapchain) */ +#if defined(VK_KHR_draw_indirect_count) +extern PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR; +extern PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR; +#endif /* defined(VK_KHR_draw_indirect_count) */ +#if defined(VK_KHR_dynamic_rendering) +extern PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR; +extern PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR; +#endif /* defined(VK_KHR_dynamic_rendering) */ +#if defined(VK_KHR_dynamic_rendering_local_read) +extern PFN_vkCmdSetRenderingAttachmentLocationsKHR vkCmdSetRenderingAttachmentLocationsKHR; +extern PFN_vkCmdSetRenderingInputAttachmentIndicesKHR vkCmdSetRenderingInputAttachmentIndicesKHR; +#endif /* defined(VK_KHR_dynamic_rendering_local_read) */ +#if defined(VK_KHR_external_fence_fd) +extern PFN_vkGetFenceFdKHR vkGetFenceFdKHR; +extern PFN_vkImportFenceFdKHR vkImportFenceFdKHR; +#endif /* defined(VK_KHR_external_fence_fd) */ +#if defined(VK_KHR_external_fence_win32) +extern PFN_vkGetFenceWin32HandleKHR vkGetFenceWin32HandleKHR; +extern PFN_vkImportFenceWin32HandleKHR vkImportFenceWin32HandleKHR; +#endif /* defined(VK_KHR_external_fence_win32) */ +#if defined(VK_KHR_external_memory_fd) +extern PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR; +extern PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR; +#endif /* defined(VK_KHR_external_memory_fd) */ +#if defined(VK_KHR_external_memory_win32) +extern PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR; +extern PFN_vkGetMemoryWin32HandlePropertiesKHR vkGetMemoryWin32HandlePropertiesKHR; +#endif /* defined(VK_KHR_external_memory_win32) */ +#if defined(VK_KHR_external_semaphore_fd) +extern PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR; +extern PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; +#endif /* defined(VK_KHR_external_semaphore_fd) */ +#if defined(VK_KHR_external_semaphore_win32) +extern PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR; +extern PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR; +#endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) +extern PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR; +#endif /* defined(VK_KHR_fragment_shading_rate) */ +#if defined(VK_KHR_get_memory_requirements2) +extern PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; +extern PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; +extern PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR; +#endif /* defined(VK_KHR_get_memory_requirements2) */ +#if defined(VK_KHR_line_rasterization) +extern PFN_vkCmdSetLineStippleKHR vkCmdSetLineStippleKHR; +#endif /* defined(VK_KHR_line_rasterization) */ +#if defined(VK_KHR_maintenance1) +extern PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR; +#endif /* defined(VK_KHR_maintenance1) */ +#if defined(VK_KHR_maintenance10) +extern PFN_vkCmdEndRendering2KHR vkCmdEndRendering2KHR; +#endif /* defined(VK_KHR_maintenance10) */ +#if defined(VK_KHR_maintenance3) +extern PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; +#endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_maintenance4) +extern PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR; +extern PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; +extern PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; +#endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_maintenance5) +extern PFN_vkCmdBindIndexBuffer2KHR vkCmdBindIndexBuffer2KHR; +extern PFN_vkGetDeviceImageSubresourceLayoutKHR vkGetDeviceImageSubresourceLayoutKHR; +extern PFN_vkGetImageSubresourceLayout2KHR vkGetImageSubresourceLayout2KHR; +extern PFN_vkGetRenderingAreaGranularityKHR vkGetRenderingAreaGranularityKHR; +#endif /* defined(VK_KHR_maintenance5) */ +#if defined(VK_KHR_maintenance6) +extern PFN_vkCmdBindDescriptorSets2KHR vkCmdBindDescriptorSets2KHR; +extern PFN_vkCmdPushConstants2KHR vkCmdPushConstants2KHR; +#endif /* defined(VK_KHR_maintenance6) */ +#if defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) +extern PFN_vkCmdPushDescriptorSet2KHR vkCmdPushDescriptorSet2KHR; +extern PFN_vkCmdPushDescriptorSetWithTemplate2KHR vkCmdPushDescriptorSetWithTemplate2KHR; +#endif /* defined(VK_KHR_maintenance6) && defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) +extern PFN_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT vkCmdBindDescriptorBufferEmbeddedSamplers2EXT; +extern PFN_vkCmdSetDescriptorBufferOffsets2EXT vkCmdSetDescriptorBufferOffsets2EXT; +#endif /* defined(VK_KHR_maintenance6) && defined(VK_EXT_descriptor_buffer) */ +#if defined(VK_KHR_map_memory2) +extern PFN_vkMapMemory2KHR vkMapMemory2KHR; +extern PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#endif /* defined(VK_KHR_map_memory2) */ +#if defined(VK_KHR_performance_query) +extern PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; +extern PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_binary) +extern PFN_vkCreatePipelineBinariesKHR vkCreatePipelineBinariesKHR; +extern PFN_vkDestroyPipelineBinaryKHR vkDestroyPipelineBinaryKHR; +extern PFN_vkGetPipelineBinaryDataKHR vkGetPipelineBinaryDataKHR; +extern PFN_vkGetPipelineKeyKHR vkGetPipelineKeyKHR; +extern PFN_vkReleaseCapturedPipelineDataKHR vkReleaseCapturedPipelineDataKHR; +#endif /* defined(VK_KHR_pipeline_binary) */ +#if defined(VK_KHR_pipeline_executable_properties) +extern PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR; +extern PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR; +extern PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR; +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) +extern PFN_vkWaitForPresentKHR vkWaitForPresentKHR; +#endif /* defined(VK_KHR_present_wait) */ +#if defined(VK_KHR_present_wait2) +extern PFN_vkWaitForPresent2KHR vkWaitForPresent2KHR; +#endif /* defined(VK_KHR_present_wait2) */ +#if defined(VK_KHR_push_descriptor) +extern PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; +#endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) +extern PFN_vkCmdTraceRaysIndirect2KHR vkCmdTraceRaysIndirect2KHR; +#endif /* defined(VK_KHR_ray_tracing_maintenance1) && defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_ray_tracing_pipeline) +extern PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; +extern PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR; +extern PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR; +extern PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR; +extern PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR; +extern PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR; +extern PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR; +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ +#if defined(VK_KHR_sampler_ycbcr_conversion) +extern PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; +extern PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; +#endif /* defined(VK_KHR_sampler_ycbcr_conversion) */ +#if defined(VK_KHR_shared_presentable_image) +extern PFN_vkGetSwapchainStatusKHR vkGetSwapchainStatusKHR; +#endif /* defined(VK_KHR_shared_presentable_image) */ +#if defined(VK_KHR_swapchain) +extern PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; +extern PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; +extern PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; +extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; +extern PFN_vkQueuePresentKHR vkQueuePresentKHR; +#endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_swapchain_maintenance1) +extern PFN_vkReleaseSwapchainImagesKHR vkReleaseSwapchainImagesKHR; +#endif /* defined(VK_KHR_swapchain_maintenance1) */ +#if defined(VK_KHR_synchronization2) +extern PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; +extern PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR; +extern PFN_vkCmdSetEvent2KHR vkCmdSetEvent2KHR; +extern PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR; +extern PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; +extern PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_timeline_semaphore) +extern PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR; +extern PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR; +extern PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR; +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) +extern PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) +extern PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; +extern PFN_vkGetEncodedVideoSessionParametersKHR vkGetEncodedVideoSessionParametersKHR; +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) +extern PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; +extern PFN_vkCmdBeginVideoCodingKHR vkCmdBeginVideoCodingKHR; +extern PFN_vkCmdControlVideoCodingKHR vkCmdControlVideoCodingKHR; +extern PFN_vkCmdEndVideoCodingKHR vkCmdEndVideoCodingKHR; +extern PFN_vkCreateVideoSessionKHR vkCreateVideoSessionKHR; +extern PFN_vkCreateVideoSessionParametersKHR vkCreateVideoSessionParametersKHR; +extern PFN_vkDestroyVideoSessionKHR vkDestroyVideoSessionKHR; +extern PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR; +extern PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR; +extern PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR; +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_NVX_binary_import) +extern PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX; +extern PFN_vkCreateCuFunctionNVX vkCreateCuFunctionNVX; +extern PFN_vkCreateCuModuleNVX vkCreateCuModuleNVX; +extern PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX; +extern PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX; +#endif /* defined(VK_NVX_binary_import) */ +#if defined(VK_NVX_image_view_handle) +extern PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX; +#endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 +extern PFN_vkGetImageViewHandle64NVX vkGetImageViewHandle64NVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 3 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 +extern PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 2 */ +#if defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 +extern PFN_vkGetDeviceCombinedImageSamplerIndexNVX vkGetDeviceCombinedImageSamplerIndexNVX; +#endif /* defined(VK_NVX_image_view_handle) && VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION >= 4 */ +#if defined(VK_NV_clip_space_w_scaling) +extern PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; +#endif /* defined(VK_NV_clip_space_w_scaling) */ +#if defined(VK_NV_cluster_acceleration_structure) +extern PFN_vkCmdBuildClusterAccelerationStructureIndirectNV vkCmdBuildClusterAccelerationStructureIndirectNV; +extern PFN_vkGetClusterAccelerationStructureBuildSizesNV vkGetClusterAccelerationStructureBuildSizesNV; +#endif /* defined(VK_NV_cluster_acceleration_structure) */ +#if defined(VK_NV_compute_occupancy_priority) +extern PFN_vkCmdSetComputeOccupancyPriorityNV vkCmdSetComputeOccupancyPriorityNV; +#endif /* defined(VK_NV_compute_occupancy_priority) */ +#if defined(VK_NV_cooperative_vector) +extern PFN_vkCmdConvertCooperativeVectorMatrixNV vkCmdConvertCooperativeVectorMatrixNV; +extern PFN_vkConvertCooperativeVectorMatrixNV vkConvertCooperativeVectorMatrixNV; +#endif /* defined(VK_NV_cooperative_vector) */ +#if defined(VK_NV_copy_memory_indirect) +extern PFN_vkCmdCopyMemoryIndirectNV vkCmdCopyMemoryIndirectNV; +extern PFN_vkCmdCopyMemoryToImageIndirectNV vkCmdCopyMemoryToImageIndirectNV; +#endif /* defined(VK_NV_copy_memory_indirect) */ +#if defined(VK_NV_cuda_kernel_launch) +extern PFN_vkCmdCudaLaunchKernelNV vkCmdCudaLaunchKernelNV; +extern PFN_vkCreateCudaFunctionNV vkCreateCudaFunctionNV; +extern PFN_vkCreateCudaModuleNV vkCreateCudaModuleNV; +extern PFN_vkDestroyCudaFunctionNV vkDestroyCudaFunctionNV; +extern PFN_vkDestroyCudaModuleNV vkDestroyCudaModuleNV; +extern PFN_vkGetCudaModuleCacheNV vkGetCudaModuleCacheNV; +#endif /* defined(VK_NV_cuda_kernel_launch) */ +#if defined(VK_NV_device_diagnostic_checkpoints) +extern PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; +extern PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; +#endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) +extern PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; +#endif /* defined(VK_NV_device_diagnostic_checkpoints) && (defined(VK_VERSION_1_3) || defined(VK_KHR_synchronization2)) */ +#if defined(VK_NV_device_generated_commands) +extern PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV; +extern PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV; +extern PFN_vkCmdPreprocessGeneratedCommandsNV vkCmdPreprocessGeneratedCommandsNV; +extern PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV; +extern PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; +extern PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_device_generated_commands_compute) +extern PFN_vkCmdUpdatePipelineIndirectBufferNV vkCmdUpdatePipelineIndirectBufferNV; +extern PFN_vkGetPipelineIndirectDeviceAddressNV vkGetPipelineIndirectDeviceAddressNV; +extern PFN_vkGetPipelineIndirectMemoryRequirementsNV vkGetPipelineIndirectMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands_compute) */ +#if defined(VK_NV_external_compute_queue) +extern PFN_vkCreateExternalComputeQueueNV vkCreateExternalComputeQueueNV; +extern PFN_vkDestroyExternalComputeQueueNV vkDestroyExternalComputeQueueNV; +extern PFN_vkGetExternalComputeQueueDataNV vkGetExternalComputeQueueDataNV; +#endif /* defined(VK_NV_external_compute_queue) */ +#if defined(VK_NV_external_memory_rdma) +extern PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV; +#endif /* defined(VK_NV_external_memory_rdma) */ +#if defined(VK_NV_external_memory_win32) +extern PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; +#endif /* defined(VK_NV_external_memory_win32) */ +#if defined(VK_NV_fragment_shading_rate_enums) +extern PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; +#endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) +extern PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; +extern PFN_vkLatencySleepNV vkLatencySleepNV; +extern PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; +extern PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; +extern PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#endif /* defined(VK_NV_low_latency2) */ +#if defined(VK_NV_memory_decompression) +extern PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; +extern PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; +#endif /* defined(VK_NV_memory_decompression) */ +#if defined(VK_NV_mesh_shader) +extern PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; +extern PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV; +#endif /* defined(VK_NV_mesh_shader) */ +#if defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) +extern PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; +#endif /* defined(VK_NV_mesh_shader) && (defined(VK_VERSION_1_2) || defined(VK_KHR_draw_indirect_count) || defined(VK_AMD_draw_indirect_count)) */ +#if defined(VK_NV_optical_flow) +extern PFN_vkBindOpticalFlowSessionImageNV vkBindOpticalFlowSessionImageNV; +extern PFN_vkCmdOpticalFlowExecuteNV vkCmdOpticalFlowExecuteNV; +extern PFN_vkCreateOpticalFlowSessionNV vkCreateOpticalFlowSessionNV; +extern PFN_vkDestroyOpticalFlowSessionNV vkDestroyOpticalFlowSessionNV; +#endif /* defined(VK_NV_optical_flow) */ +#if defined(VK_NV_partitioned_acceleration_structure) +extern PFN_vkCmdBuildPartitionedAccelerationStructuresNV vkCmdBuildPartitionedAccelerationStructuresNV; +extern PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV vkGetPartitionedAccelerationStructuresBuildSizesNV; +#endif /* defined(VK_NV_partitioned_acceleration_structure) */ +#if defined(VK_NV_ray_tracing) +extern PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV; +extern PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV; +extern PFN_vkCmdCopyAccelerationStructureNV vkCmdCopyAccelerationStructureNV; +extern PFN_vkCmdTraceRaysNV vkCmdTraceRaysNV; +extern PFN_vkCmdWriteAccelerationStructuresPropertiesNV vkCmdWriteAccelerationStructuresPropertiesNV; +extern PFN_vkCompileDeferredNV vkCompileDeferredNV; +extern PFN_vkCreateAccelerationStructureNV vkCreateAccelerationStructureNV; +extern PFN_vkCreateRayTracingPipelinesNV vkCreateRayTracingPipelinesNV; +extern PFN_vkDestroyAccelerationStructureNV vkDestroyAccelerationStructureNV; +extern PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV; +extern PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; +extern PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; +#endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 +extern PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ +#if defined(VK_NV_scissor_exclusive) +extern PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; +#endif /* defined(VK_NV_scissor_exclusive) */ +#if defined(VK_NV_shading_rate_image) +extern PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; +extern PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; +extern PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; +#endif /* defined(VK_NV_shading_rate_image) */ +#if defined(VK_OHOS_external_memory) +extern PFN_vkGetMemoryNativeBufferOHOS vkGetMemoryNativeBufferOHOS; +extern PFN_vkGetNativeBufferPropertiesOHOS vkGetNativeBufferPropertiesOHOS; +#endif /* defined(VK_OHOS_external_memory) */ +#if defined(VK_QCOM_queue_perf_hint) +extern PFN_vkQueueSetPerfHintQCOM vkQueueSetPerfHintQCOM; +#endif /* defined(VK_QCOM_queue_perf_hint) */ +#if defined(VK_QCOM_tile_memory_heap) +extern PFN_vkCmdBindTileMemoryQCOM vkCmdBindTileMemoryQCOM; +#endif /* defined(VK_QCOM_tile_memory_heap) */ +#if defined(VK_QCOM_tile_properties) +extern PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM; +extern PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM; +#endif /* defined(VK_QCOM_tile_properties) */ +#if defined(VK_QCOM_tile_shading) +extern PFN_vkCmdBeginPerTileExecutionQCOM vkCmdBeginPerTileExecutionQCOM; +extern PFN_vkCmdDispatchTileQCOM vkCmdDispatchTileQCOM; +extern PFN_vkCmdEndPerTileExecutionQCOM vkCmdEndPerTileExecutionQCOM; +#endif /* defined(VK_QCOM_tile_shading) */ +#if defined(VK_QNX_external_memory_screen_buffer) +extern PFN_vkGetScreenBufferPropertiesQNX vkGetScreenBufferPropertiesQNX; +#endif /* defined(VK_QNX_external_memory_screen_buffer) */ +#if defined(VK_VALVE_descriptor_set_host_mapping) +extern PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; +extern PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; +#endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) +extern PFN_vkCmdSetDepthClampRangeEXT vkCmdSetDepthClampRangeEXT; +#endif /* (defined(VK_EXT_depth_clamp_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clamp_control)) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; +extern PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; +extern PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; +extern PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; +extern PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; +extern PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; +extern PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; +extern PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; +extern PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; +extern PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; +extern PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; +extern PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; +extern PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; +extern PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; +extern PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; +extern PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; +extern PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; +extern PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; +extern PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; +extern PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; +extern PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; +extern PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; +extern PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; +extern PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; +extern PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && (defined(VK_KHR_maintenance2) || defined(VK_VERSION_1_1))) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) +extern PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_transform_feedback)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_transform_feedback)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) +extern PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; +extern PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_conservative_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_conservative_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) +extern PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_enable)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_enable)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) +extern PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_sample_locations)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_sample_locations)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) +extern PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_blend_operation_advanced)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_blend_operation_advanced)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) +extern PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_provoking_vertex)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_provoking_vertex)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) +extern PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; +extern PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_line_rasterization)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_line_rasterization)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) +extern PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_EXT_depth_clip_control)) || (defined(VK_EXT_shader_object) && defined(VK_EXT_depth_clip_control)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) +extern PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_clip_space_w_scaling)) || (defined(VK_EXT_shader_object) && defined(VK_NV_clip_space_w_scaling)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) +extern PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_viewport_swizzle)) || (defined(VK_EXT_shader_object) && defined(VK_NV_viewport_swizzle)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) +extern PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; +extern PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_fragment_coverage_to_color)) || (defined(VK_EXT_shader_object) && defined(VK_NV_fragment_coverage_to_color)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) +extern PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; +extern PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; +extern PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_framebuffer_mixed_samples)) || (defined(VK_EXT_shader_object) && defined(VK_NV_framebuffer_mixed_samples)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) +extern PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_shading_rate_image)) || (defined(VK_EXT_shader_object) && defined(VK_NV_shading_rate_image)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) +extern PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_representative_fragment_test)) || (defined(VK_EXT_shader_object) && defined(VK_NV_representative_fragment_test)) */ +#if (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) +extern PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3) && defined(VK_NV_coverage_reduction_mode)) || (defined(VK_EXT_shader_object) && defined(VK_NV_coverage_reduction_mode)) */ +#if (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) +extern PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT; +#endif /* (defined(VK_EXT_host_image_copy)) || (defined(VK_EXT_image_compression_control)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) +extern PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ +#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) +extern PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; +#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && (defined(VK_VERSION_1_1) || defined(VK_KHR_descriptor_update_template))) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) +extern PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR; +extern PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR; +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) +extern PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; +#endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_swapchain)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ +/* VOLK_GENERATE_PROTOTYPES_H_DEVICE */ +#endif + +#ifdef __cplusplus +} // extern "C" / namespace volk +#endif + +#ifdef VOLK_NAMESPACE +using namespace volk; +#endif + +#endif // VOLK_H + +#ifdef VOLK_IMPLEMENTATION +#undef VOLK_IMPLEMENTATION +/* Prevent tools like dependency checkers from detecting a cyclic dependency */ +#define VOLK_SOURCE "volk.c" +#include VOLK_SOURCE +#endif + +/** + * Copyright (c) 2018-2026 Arseny Kapoulkine + * + * 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. +*/ +/* clang-format on */ diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/CMakeLists.txt new file mode 100644 index 00000000..d95ea648 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/CMakeLists.txt @@ -0,0 +1,7 @@ +add_granite_internal_lib(granite-threading + thread_group.cpp thread_group.hpp + thread_latch.cpp thread_latch.hpp + task_composer.cpp task_composer.hpp) + +target_include_directories(granite-threading PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-threading PUBLIC granite-util granite-application-global) \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/task_composer.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/task_composer.cpp new file mode 100644 index 00000000..79b32c6a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/task_composer.cpp @@ -0,0 +1,91 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "task_composer.hpp" + +namespace Granite +{ +TaskComposer::TaskComposer(ThreadGroup &group_) + : group(group_) +{ +} + +void TaskComposer::set_incoming_task(TaskGroupHandle group_) +{ + current = std::move(group_); +} + +TaskGroup &TaskComposer::begin_pipeline_stage() +{ + auto new_group = group.create_task(); + auto new_deps = group.create_task(); + if (current) + group.add_dependency(*new_deps, *current); + if (next_stage_deps) + group.add_dependency(*new_deps, *next_stage_deps); + next_stage_deps.reset(); + group.add_dependency(*new_group, *new_deps); + + current = std::move(new_group); + incoming_deps = std::move(new_deps); + return *current; +} + +TaskGroup &TaskComposer::get_group() +{ + if (!current) + return begin_pipeline_stage(); + else + return *current; +} + +TaskGroupHandle TaskComposer::get_outgoing_task() +{ + begin_pipeline_stage(); + auto ret = std::move(incoming_deps); + incoming_deps = {}; + current = {}; + return ret; +} + +TaskGroupHandle TaskComposer::get_pipeline_stage_dependency() +{ + return incoming_deps; +} + +TaskGroupHandle TaskComposer::get_deferred_enqueue_handle() +{ + if (!next_stage_deps) + next_stage_deps = group.create_task(); + return next_stage_deps; +} + +ThreadGroup &TaskComposer::get_thread_group() +{ + return group; +} + +void TaskComposer::add_outgoing_dependency(TaskGroup &task) +{ + group.add_dependency(task, *get_outgoing_task()); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/task_composer.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/task_composer.hpp new file mode 100644 index 00000000..f08e0f44 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/task_composer.hpp @@ -0,0 +1,59 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "thread_group.hpp" + +// Designed to compose a series of pipelined tasks. + +namespace Granite +{ +class TaskComposer +{ +public: + explicit TaskComposer(ThreadGroup &group); + void set_incoming_task(TaskGroupHandle group); + TaskGroup &begin_pipeline_stage(); + TaskGroup &get_group(); + + // Returns a waitable handle that can be waited on. + TaskGroupHandle get_outgoing_task(); + TaskGroupHandle get_pipeline_stage_dependency(); + ThreadGroup &get_thread_group(); + + // If this is called, the next pipeline stage will implicitly depend + // on the task returned. This is useful if a pipeline stage will spawn tasks on its own, + // which can only be known at the time of task execution. + // As long as the enqueue handle is kept alive in child tasks, + // the next pipeline stage will not begin. + TaskGroupHandle get_deferred_enqueue_handle(); + + void add_outgoing_dependency(TaskGroup &task); + +private: + ThreadGroup &group; + TaskGroupHandle current; + TaskGroupHandle incoming_deps; + TaskGroupHandle next_stage_deps; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_group.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_group.cpp new file mode 100644 index 00000000..6285eb83 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_group.cpp @@ -0,0 +1,447 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "thread_group.hpp" +#include +#include +#include +#include "logging.hpp" +#include "thread_id.hpp" +#include "thread_priority.hpp" +#include "string_helpers.hpp" +#include "timeline_trace_file.hpp" +#include "thread_name.hpp" +#include "environment.hpp" + +namespace Granite +{ +namespace Internal +{ +void TaskDeps::notify_dependees() +{ + if (signal) + signal->signal_increment(); + + for (auto &dep : pending) + dep->dependency_satisfied(); + pending.clear(); + + { + std::lock_guard holder{cond_lock}; + done = true; + cond.notify_all(); + } +} + +void TaskDeps::task_completed() +{ + auto old_tasks = count.fetch_sub(1, std::memory_order_acq_rel); + assert(old_tasks > 0); + if (old_tasks == 1) + notify_dependees(); +} + +void TaskDeps::dependency_satisfied() +{ + auto old_deps = dependency_count.fetch_sub(1, std::memory_order_acq_rel); + assert(old_deps > 0); + + if (old_deps == 1) + { + if (pending_tasks.empty()) + notify_dependees(); + else + { + group->move_to_ready_tasks(pending_tasks); + pending_tasks.clear(); + } + } +} +} + +TaskGroup::TaskGroup(ThreadGroup *group_) + : group(group_) +{ +} + +void TaskGroup::flush() +{ + if (flushed) + throw std::logic_error("Cannot flush more than once."); + + flushed = true; + deps->dependency_satisfied(); +} + +void TaskGroup::wait() +{ + if (!flushed) + flush(); + + std::unique_lock holder{deps->cond_lock}; + deps->cond.wait(holder, [this]() { + return deps->done; + }); +} + +bool TaskGroup::poll() +{ + if (!flushed) + flush(); + return deps->count.load(std::memory_order_acquire) == 0; +} + +TaskGroup::~TaskGroup() +{ + if (!flushed) + flush(); +} + +void ThreadGroup::set_async_main_thread() +{ + Util::set_current_thread_name("MainAsyncThread"); + Util::TimelineTraceFile::set_tid("main-async"); + // Seems reasonable to make sure main thread is making forward progress when it has something useful to do. + Util::set_current_thread_priority(Util::ThreadPriority::High); +} + +static void set_main_thread_name() +{ + Util::set_current_thread_name("MainThread"); + Util::TimelineTraceFile::set_tid("main"); + // Seems reasonable to make sure main thread is making forward progress when it has something useful to do. + Util::set_current_thread_priority(Util::ThreadPriority::High); +} + +static void set_worker_thread_name_and_prio(unsigned index, TaskClass task_class) +{ + auto name = Util::join(task_class == TaskClass::Foreground ? "FG-" : "BG-", index); + Util::set_current_thread_name(name.c_str()); + Util::TimelineTraceFile::set_tid(name.c_str()); + Util::set_current_thread_priority(task_class == TaskClass::Foreground ? + Util::ThreadPriority::Default : Util::ThreadPriority::Low); +} + +void ThreadGroup::refresh_global_timeline_trace_file() +{ + Util::TimelineTraceFile::set_per_thread(timeline_trace_file.get()); +} + +void ThreadGroup::set_thread_context() +{ + refresh_global_timeline_trace_file(); +} + +Util::TimelineTraceFile *ThreadGroup::get_timeline_trace_file() +{ + return timeline_trace_file.get(); +} + +void ThreadGroup::start(unsigned num_threads_foreground, + unsigned num_threads_background, + const std::function &on_thread_begin) +{ + if (active) + throw std::logic_error("Cannot start a thread group which has already started."); + + dead = false; + active = true; + + fg.thread_group.resize(num_threads_foreground); + bg.thread_group.resize(num_threads_background); + +#ifndef GRANITE_SHIPPING + std::string path; + if (Util::get_environment("GRANITE_TIMELINE_TRACE", path)) + { + LOGI("Enabling JSON timeline tracing to %s.\n", path.c_str()); + timeline_trace_file = std::make_unique(path); + } +#endif + + refresh_global_timeline_trace_file(); + set_main_thread_name(); + + unsigned self_index = 1; + for (auto &t : fg.thread_group) + { + t = std::make_unique([this, on_thread_begin, self_index]() { + refresh_global_timeline_trace_file(); + set_worker_thread_name_and_prio(self_index - 1, TaskClass::Foreground); + if (on_thread_begin) + on_thread_begin(); + thread_looper(self_index, TaskClass::Foreground); + }); + self_index++; + } + + for (auto &t : bg.thread_group) + { + t = std::make_unique([this, on_thread_begin, self_index]() { + refresh_global_timeline_trace_file(); + set_worker_thread_name_and_prio(self_index - 1, TaskClass::Background); + if (on_thread_begin) + on_thread_begin(); + thread_looper(self_index, TaskClass::Background); + }); + self_index++; + } +} + +void ThreadGroup::submit(TaskGroupHandle &group) +{ + group->flush(); + group.reset(); +} + +void ThreadGroup::add_dependency(TaskGroup &dependee, TaskGroup &dependency) +{ + if (dependency.flushed) + throw std::logic_error("Cannot wait for task group which has been flushed."); + if (dependee.flushed) + throw std::logic_error("Cannot add dependency to task group which has been flushed."); + + dependency.deps->pending.push_back(dependee.deps); + dependee.deps->dependency_count.fetch_add(1, std::memory_order_relaxed); +} + +void ThreadGroup::move_to_ready_tasks(const Util::SmallVector &list) +{ + unsigned fg_task_count = 0; + unsigned bg_task_count = 0; + for (auto *t : list) + { + if (t->deps->task_class == TaskClass::Foreground) + fg_task_count++; + else + bg_task_count++; + } + + total_tasks.fetch_add(list.size(), std::memory_order_relaxed); + + if (fg_task_count) + { + std::lock_guard holder{fg.cond_lock}; + + for (auto &t : list) + fg.ready_tasks.push(t); + + if (fg_task_count >= fg.thread_group.size()) + fg.cond.notify_all(); + else + { + for (unsigned i = 0; i < fg_task_count; i++) + fg.cond.notify_one(); + } + } + + if (bg_task_count) + { + std::lock_guard holder{bg.cond_lock}; + + for (auto &t : list) + bg.ready_tasks.push(t); + + if (bg_task_count >= bg.thread_group.size()) + bg.cond.notify_all(); + else + { + for (unsigned i = 0; i < bg_task_count; i++) + bg.cond.notify_one(); + } + } +} + +void Internal::TaskGroupDeleter::operator()(TaskGroup *group) +{ + group->group->free_task_group(group); +} + +void Internal::TaskDepsDeleter::operator()(Internal::TaskDeps *deps) +{ + deps->group->free_task_deps(deps); +} + +void ThreadGroup::free_task_group(TaskGroup *group) +{ + task_group_pool.free(group); +} + +void ThreadGroup::free_task_deps(Internal::TaskDeps *deps) +{ + task_deps_pool.free(deps); +} + +void TaskSignal::signal_increment() +{ + std::lock_guard holder{lock}; + counter++; + cond.notify_all(); +} + +void TaskSignal::wait_until_at_least(uint64_t count) +{ + std::unique_lock holder{lock}; + cond.wait(holder, [&]() -> bool { + return counter >= count; + }); +} + +uint64_t TaskSignal::get_count() +{ + std::lock_guard holder{lock}; + return counter; +} + +TaskGroupHandle ThreadGroup::create_task() +{ + TaskGroupHandle group(task_group_pool.allocate(this)); + group->deps = Internal::TaskDepsHandle(task_deps_pool.allocate(this)); + group->deps->count.store(0, std::memory_order_relaxed); + return group; +} + +void TaskGroup::set_fence_counter_signal(TaskSignal *signal) +{ + deps->signal = signal; +} + +ThreadGroup *TaskGroup::get_thread_group() const +{ + return group; +} + +void TaskGroup::set_desc(const char *desc) +{ + snprintf(deps->desc, sizeof(deps->desc), "%s", desc); +} + +void TaskGroup::set_task_class(TaskClass task_class) +{ + deps->task_class = task_class; +} + +void ThreadGroup::wait_idle() +{ + std::unique_lock holder{wait_cond_lock}; + wait_cond.wait(holder, [&]() { + return total_tasks.load(std::memory_order_relaxed) == completed_tasks.load(std::memory_order_relaxed); + }); +} + +bool ThreadGroup::is_idle() +{ + return total_tasks.load(std::memory_order_acquire) == completed_tasks.load(std::memory_order_acquire); +} + +void ThreadGroup::thread_looper(unsigned index, TaskClass task_class) +{ + Util::register_thread_index(index); + auto &ctx = task_class == TaskClass::Foreground ? fg : bg; + + for (;;) + { + Internal::Task *task = nullptr; + + { + std::unique_lock holder{ctx.cond_lock}; + ctx.cond.wait(holder, [&]() { + return dead || !ctx.ready_tasks.empty(); + }); + + if (dead && ctx.ready_tasks.empty()) + break; + + task = ctx.ready_tasks.front(); + ctx.ready_tasks.pop(); + } + + if (task->callable) + { + GRANITE_SCOPED_TIMELINE_EVENT_FILE(timeline_trace_file.get(), task->deps->desc); + task->callable.call(); + } + + task->deps->task_completed(); + task_pool.free(task); + + { + auto completed = completed_tasks.fetch_add(1, std::memory_order_relaxed) + 1; + //LOGI("Task completed (%u / %u)!\n", completed, total_tasks.load(memory_order_relaxed)); + + if (completed == total_tasks.load(std::memory_order_relaxed)) + { + std::lock_guard holder{wait_cond_lock}; + wait_cond.notify_all(); + } + } + } +} + +ThreadGroup::ThreadGroup() +{ + total_tasks.store(0); + completed_tasks.store(0); +} + +ThreadGroup::~ThreadGroup() +{ + stop(); +} + +void ThreadGroup::stop() +{ + if (!active) + return; + + wait_idle(); + + { + std::lock_guard holder_fg{fg.cond_lock}; + std::lock_guard holder_bg{bg.cond_lock}; + dead = true; + fg.cond.notify_all(); + bg.cond.notify_all(); + } + + for (auto &t : fg.thread_group) + { + if (t && t->joinable()) + { + t->join(); + t.reset(); + } + } + + for (auto &t : bg.thread_group) + { + if (t && t->joinable()) + { + t->join(); + t.reset(); + } + } + + active = false; + dead = false; +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_group.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_group.hpp new file mode 100644 index 00000000..b6a1c62c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_group.hpp @@ -0,0 +1,244 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "object_pool.hpp" +#include "variant.hpp" +#include "intrusive.hpp" +#include "timeline_trace_file.hpp" +#include "global_managers.hpp" +#include "small_vector.hpp" +#include "small_callable.hpp" + +namespace Granite +{ +class ThreadGroup; + +struct TaskSignal +{ + std::condition_variable cond; + std::mutex lock; + uint64_t counter = 0; + + void signal_increment(); + void wait_until_at_least(uint64_t count); + uint64_t get_count(); +}; + +enum class TaskClass : uint8_t +{ + Foreground, + Background +}; + +struct TaskGroup; +namespace Internal +{ +struct TaskDeps; +struct Task; + +struct TaskDepsDeleter +{ + void operator()(TaskDeps *deps); +}; + +struct TaskGroupDeleter +{ + void operator()(TaskGroup *group); +}; + +struct TaskDeps : Util::IntrusivePtrEnabled +{ + explicit TaskDeps(ThreadGroup *group_) + : group(group_) + { + count.store(0, std::memory_order_relaxed); + // One implicit dependency is the flush() happening. + dependency_count.store(1, std::memory_order_relaxed); + desc[0] = '\0'; + } + + ThreadGroup *group; + Util::SmallVector> pending; + std::atomic_uint count; + + Util::SmallVector pending_tasks; + TaskSignal *signal = nullptr; + std::atomic_uint dependency_count; + + void task_completed(); + void dependency_satisfied(); + void notify_dependees(); + + std::condition_variable cond; + std::mutex cond_lock; + bool done = false; + TaskClass task_class = TaskClass::Foreground; + + char desc[64]; +}; +using TaskDepsHandle = Util::IntrusivePtr; + +struct Task +{ + template + Task(TaskDepsHandle deps_, Func&& func) + : callable(std::forward(func)), deps(std::move(deps_)) + { + } + + Task() = default; + + Util::SmallCallable callable; + TaskDepsHandle deps; +}; + +static_assert(sizeof(Task) == 64, "sizeof(Task) is unexpected."); +} + +struct TaskGroup : Util::IntrusivePtrEnabled +{ + explicit TaskGroup(ThreadGroup *group); + ~TaskGroup(); + void flush(); + void wait(); + bool poll(); + + ThreadGroup *group; + Internal::TaskDepsHandle deps; + + template + void enqueue_task(Func&& func); + + void set_fence_counter_signal(TaskSignal *signal); + ThreadGroup *get_thread_group() const; + + void set_desc(const char *desc); + void set_task_class(TaskClass task_class); + + unsigned id = 0; + bool flushed = false; +}; + +using TaskGroupHandle = Util::IntrusivePtr; + +class ThreadGroup final : public ThreadGroupInterface +{ +public: + ThreadGroup(); + ~ThreadGroup(); + ThreadGroup(ThreadGroup &&) = delete; + void operator=(ThreadGroup &&) = delete; + + void start(unsigned num_threads_foreground, + unsigned num_threads_background, + const std::function &on_thread_begin) override; + + unsigned get_num_threads() const + { + return unsigned(fg.thread_group.size() + bg.thread_group.size()); + } + + void stop(); + + template + void enqueue_task(TaskGroup &group, Func&& func); + template + TaskGroupHandle create_task(Func&& func); + TaskGroupHandle create_task(); + + void move_to_ready_tasks(const Util::SmallVector &list); + + void add_dependency(TaskGroup &dependee, TaskGroup &dependency); + + void free_task_group(TaskGroup *group); + void free_task_deps(Internal::TaskDeps *deps); + + void submit(TaskGroupHandle &group); + void wait_idle(); + bool is_idle(); + + Util::TimelineTraceFile *get_timeline_trace_file(); + void refresh_global_timeline_trace_file(); + + static void set_async_main_thread(); + +private: + Util::ThreadSafeObjectPool task_pool; + Util::ThreadSafeObjectPool task_group_pool; + Util::ThreadSafeObjectPool task_deps_pool; + + struct + { + std::vector> thread_group; + std::queue ready_tasks; + std::mutex cond_lock; + std::condition_variable cond; + } fg, bg; + + void thread_looper(unsigned self_index, TaskClass task_class); + + bool active = false; + bool dead = false; + + std::condition_variable wait_cond; + std::mutex wait_cond_lock; + std::atomic_uint total_tasks; + std::atomic_uint completed_tasks; + + std::unique_ptr timeline_trace_file; + void set_thread_context() override; +}; + +template +TaskGroupHandle ThreadGroup::create_task(Func&& func) +{ + TaskGroupHandle group(task_group_pool.allocate(this)); + group->deps = Internal::TaskDepsHandle(task_deps_pool.allocate(this)); + group->deps->pending_tasks.push_back(task_pool.allocate(group->deps, std::forward(func))); + group->deps->count.store(1, std::memory_order_relaxed); + return group; +} + +template +void ThreadGroup::enqueue_task(TaskGroup &group, Func&& func) +{ + if (group.flushed) + throw std::logic_error("Cannot enqueue work to a flushed task group."); + group.deps->pending_tasks.push_back(task_pool.allocate(group.deps, std::forward(func))); + group.deps->count.fetch_add(1, std::memory_order_relaxed); +} + +template +void TaskGroup::enqueue_task(Func&& func) +{ + group->enqueue_task(*this, std::forward(func)); +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_latch.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_latch.cpp new file mode 100644 index 00000000..dc371798 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_latch.cpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "thread_latch.hpp" +#include + +namespace Granite +{ +void ThreadLatch::set_latch() +{ + std::lock_guard holder{lock}; + assert(!latch); + latch = true; + cond.notify_one(); +} + +void ThreadLatch::clear_latch() +{ + std::lock_guard holder{lock}; + assert(latch); + latch = false; + cond.notify_one(); +} + +bool ThreadLatch::wait_latch_set() +{ + std::unique_lock holder{lock}; + cond.wait(holder, [this]() { + return latch || dead; + }); + return !dead; +} + +bool ThreadLatch::wait_latch_cleared() +{ + std::unique_lock holder{lock}; + cond.wait(holder, [this]() { + return !latch || dead; + }); + return !dead; +} + +void ThreadLatch::kill_latch() +{ + std::lock_guard holder{lock}; + dead = true; + cond.notify_one(); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_latch.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_latch.hpp new file mode 100644 index 00000000..965634c4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/threading/thread_latch.hpp @@ -0,0 +1,46 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include + +namespace Granite +{ +class ThreadLatch +{ +public: + void set_latch(); + void clear_latch(); + bool wait_latch_cleared(); + bool wait_latch_set(); + void kill_latch(); + +private: + std::condition_variable cond; + std::mutex lock; + bool latch = false; + bool dead = false; +}; + +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/toolchains/aarch64.cmake b/crates/pyrowave-sys/vendor/pyrowave/Granite/toolchains/aarch64.cmake new file mode 100644 index 00000000..f4a1dfa4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/toolchains/aarch64.cmake @@ -0,0 +1,4 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm64) +set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/toolchains/armhf.cmake b/crates/pyrowave-sys/vendor/pyrowave/Granite/toolchains/armhf.cmake new file mode 100644 index 00000000..a812ff06 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/toolchains/armhf.cmake @@ -0,0 +1,4 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm) +set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) +set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++) diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/CMakeLists.txt new file mode 100644 index 00000000..c5c0a24f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/CMakeLists.txt @@ -0,0 +1,52 @@ +add_granite_internal_lib(granite-util + logging.hpp logging.cpp + aligned_alloc.cpp aligned_alloc.hpp + bitops.hpp + array_view.hpp + variant.hpp + enum_cast.hpp + hash.hpp + intrusive.hpp + intrusive_list.hpp + object_pool.hpp + stack_allocator.hpp + temporary_hashmap.hpp + read_write_lock.hpp + async_object_sink.hpp + unstable_remove_if.hpp + intrusive_hash_map.hpp + timer.hpp timer.cpp + small_vector.hpp + thread_id.hpp thread_id.cpp + string_helpers.hpp string_helpers.cpp + timeline_trace_file.hpp timeline_trace_file.cpp + thread_name.hpp thread_name.cpp + thread_priority.hpp thread_priority.cpp + cli_parser.cpp cli_parser.hpp + dynamic_library.cpp dynamic_library.hpp + generational_handle.hpp + atomic_append_buffer.hpp + lru_cache.hpp + unordered_array.hpp + message_queue.hpp message_queue.cpp + small_callable.hpp radix_sorter.hpp + dynamic_array.hpp + arena_allocator.hpp arena_allocator.cpp + environment.hpp environment.cpp + slab_allocator.hpp slab_allocator.cpp + no_init_pod.hpp) +target_include_directories(granite-util PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-util PUBLIC granite-application-global-interface) + +if (NOT WIN32) + target_link_libraries(granite-util PUBLIC dl) + find_library(LIBRT_LIBRARY rt) + if (EXISTS ${LIBRT_LIBRARY}) + target_link_libraries(granite-util PUBLIC rt) + endif() +endif() + +if (GRANITE_SHIPPING) + target_compile_definitions(granite-util PUBLIC GRANITE_SHIPPING) +endif() + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/aligned_alloc.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/aligned_alloc.cpp new file mode 100644 index 00000000..8660fc25 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/aligned_alloc.cpp @@ -0,0 +1,83 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "aligned_alloc.hpp" +#include +#include +#include +#ifdef _WIN32 +#include +#endif + +namespace Util +{ +void *memalign_alloc(size_t boundary, size_t size) +{ +#if defined(_WIN32) + return _aligned_malloc(size, boundary); +#elif defined(_ISOC11_SOURCE) + return aligned_alloc(boundary, (size + boundary - 1) & ~(boundary - 1)); +#elif (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600) + void *ptr = nullptr; + if (posix_memalign(&ptr, boundary, size) < 0) + return nullptr; + return ptr; +#else + // Align stuff ourselves. Kinda ugly, but will work anywhere. + void **place; + uintptr_t addr = 0; + void *ptr = malloc(boundary + size + sizeof(uintptr_t)); + + if (ptr == nullptr) + return nullptr; + + addr = ((uintptr_t)ptr + sizeof(uintptr_t) + boundary) & ~(boundary - 1); + place = (void **) addr; + place[-1] = ptr; + + return (void *) addr; +#endif +} + +void *memalign_calloc(size_t boundary, size_t size) +{ + void *ret = memalign_alloc(boundary, size); + if (ret) + memset(ret, 0, size); + return ret; +} + +void memalign_free(void *ptr) +{ +#if defined(_WIN32) + _aligned_free(ptr); +#elif !defined(_ISOC11_SOURCE) && !((_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600)) + if (ptr != nullptr) + { + void **p = (void **) ptr; + free(p[-1]); + } +#else + free(ptr); +#endif +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/aligned_alloc.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/aligned_alloc.hpp new file mode 100644 index 00000000..35f236d4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/aligned_alloc.hpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include + +namespace Util +{ +void *memalign_alloc(size_t boundary, size_t size); +void *memalign_calloc(size_t boundary, size_t size); +void memalign_free(void *ptr); + +struct AlignedDeleter { void operator()(void *ptr) { memalign_free(ptr); }}; + +template +struct AlignedAllocation +{ + static void *operator new(size_t size) + { + void *ret = ::Util::memalign_alloc(alignof(T), size); +#ifdef __EXCEPTIONS + if (!ret) throw std::bad_alloc(); +#endif + return ret; + } + + static void *operator new[](size_t size) + { + void *ret = ::Util::memalign_alloc(alignof(T), size); +#ifdef __EXCEPTIONS + if (!ret) throw std::bad_alloc(); +#endif + return ret; + } + + static void operator delete(void *ptr) + { + return ::Util::memalign_free(ptr); + } + + static void operator delete[](void *ptr) + { + return ::Util::memalign_free(ptr); + } +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/arena_allocator.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/arena_allocator.cpp new file mode 100644 index 00000000..5ee57066 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/arena_allocator.cpp @@ -0,0 +1,197 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen +* +* 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. +*/ + +#include "arena_allocator.hpp" +#include "bitops.hpp" +#include + +namespace Util +{ +void LegionAllocator::allocate(uint32_t num_blocks, uint32_t &out_mask, uint32_t &out_offset) +{ + assert(NumSubBlocks >= num_blocks); + assert(num_blocks != 0); + + uint32_t block_mask; + if (num_blocks == NumSubBlocks) + block_mask = ~0u; + else + block_mask = ((1u << num_blocks) - 1u); + + uint32_t mask = free_blocks[num_blocks - 1]; + uint32_t b = trailing_zeroes(mask); + + assert(((free_blocks[0] >> b) & block_mask) == block_mask); + + uint32_t sb = block_mask << b; + free_blocks[0] &= ~sb; + update_longest_run(); + + out_mask = sb; + out_offset = b; +} + +void LegionAllocator::free(uint32_t mask) +{ + assert((free_blocks[0] & mask) == 0); + free_blocks[0] |= mask; + update_longest_run(); +} + +void LegionAllocator::update_longest_run() +{ + uint32_t f = free_blocks[0]; + longest_run = 0; + + while (f) + { + free_blocks[longest_run++] = f; + f &= f >> 1; + } +} + +bool SliceSubAllocator::allocate_backing_heap(AllocatedSlice *allocation) +{ + uint32_t count = sub_block_size * Util::LegionAllocator::NumSubBlocks; + + if (parent) + { + return parent->allocate(count, allocation); + } + else if (global_allocator) + { + uint32_t index = global_allocator->allocate(count); + if (index == UINT32_MAX) + return false; + + *allocation = {}; + allocation->count = count; + allocation->buffer_index = index; + return true; + } + else + { + return false; + } +} + +void SliceSubAllocator::free_backing_heap(AllocatedSlice *allocation) const +{ + if (parent) + parent->free(allocation->heap, allocation->mask); + else if (global_allocator) + global_allocator->free(allocation->buffer_index); +} + +void SliceSubAllocator::prepare_allocation(AllocatedSlice *allocation, Util::IntrusiveList::Iterator heap, + const Util::SuballocationResult &suballoc) +{ + allocation->buffer_index = heap->allocation.buffer_index; + allocation->offset = heap->allocation.offset + suballoc.offset; + allocation->count = suballoc.size; + allocation->mask = suballoc.mask; + allocation->heap = heap; + allocation->alloc = this; +} + +void SliceAllocator::init(uint32_t sub_block_size, uint32_t num_sub_blocks_in_arena_log2, + Util::SliceBackingAllocator *alloc) +{ + global_allocator = alloc; + assert(num_sub_blocks_in_arena_log2 < SliceAllocatorCount * 5 && num_sub_blocks_in_arena_log2 >= 5); + unsigned num_hierarchies = (num_sub_blocks_in_arena_log2 + 4) / 5; + assert(num_hierarchies <= SliceAllocatorCount); + + for (unsigned i = 0; i < num_hierarchies - 1; i++) + allocators[i].parent = &allocators[i + 1]; + allocators[num_hierarchies - 1].global_allocator = alloc; + + unsigned shamt[SliceAllocatorCount] = {}; + shamt[num_hierarchies - 1] = num_sub_blocks_in_arena_log2 - Util::floor_log2(Util::LegionAllocator::NumSubBlocks); + + // Spread out the multiplier if possible. + for (unsigned i = num_hierarchies - 1; i > 1; i--) + { + shamt[i - 1] = shamt[i] - shamt[i] / (i); + assert(shamt[i] - shamt[i - 1] <= Util::floor_log2(Util::LegionAllocator::NumSubBlocks)); + } + + for (unsigned i = 0; i < num_hierarchies; i++) + { + allocators[i].set_sub_block_size(sub_block_size << shamt[i]); + allocators[i].set_object_pool(&object_pool); + } +} + +void SliceAllocator::free(const Util::AllocatedSlice &slice) +{ + if (slice.alloc) + slice.alloc->free(slice.heap, slice.mask); + else if (slice.buffer_index != UINT32_MAX) + global_allocator->free(slice.buffer_index); +} + +void SliceAllocator::prime(const void *opaque_meta) +{ + for (auto &alloc : allocators) + { + if (alloc.global_allocator) + { + alloc.global_allocator->prime(alloc.get_sub_block_size() * Util::LegionAllocator::NumSubBlocks, opaque_meta); + break; + } + } +} + +bool SliceAllocator::allocate(uint32_t count, Util::AllocatedSlice *slice) +{ + for (auto &alloc : allocators) + { + uint32_t max_alloc_size = alloc.get_max_allocation_size(); + if (count <= max_alloc_size) + return alloc.allocate(count, slice); + } + + LOGE("Allocation of %u elements is too large for SliceAllocator.\n", count); + return false; +} + +void SliceBackingAllocatorVA::free(uint32_t) +{ + allocated = false; +} + +uint32_t SliceBackingAllocatorVA::allocate(uint32_t) +{ + if (allocated) + return UINT32_MAX; + else + { + allocated = true; + return 0; + } +} + +void SliceBackingAllocatorVA::prime(uint32_t, const void *) +{ +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/arena_allocator.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/arena_allocator.hpp new file mode 100644 index 00000000..31cb0d75 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/arena_allocator.hpp @@ -0,0 +1,336 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen +* +* 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. +*/ + +#pragma once + +#include +#include +#include "intrusive_list.hpp" +#include "logging.hpp" +#include "object_pool.hpp" +#include "bitops.hpp" + +namespace Util +{ +// Expands the buddy allocator to consider 32 "buddies". +// The allocator is logical and works in terms of units, not bytes. +class LegionAllocator +{ +public: + enum + { + NumSubBlocks = 32u, + AllFree = ~0u + }; + + LegionAllocator(const LegionAllocator &) = delete; + void operator=(const LegionAllocator &) = delete; + + LegionAllocator() + { + for (auto &v : free_blocks) + v = AllFree; + longest_run = 32; + } + + ~LegionAllocator() + { + if (free_blocks[0] != AllFree) + LOGE("Memory leak in block detected.\n"); + } + + inline bool full() const + { + return free_blocks[0] == 0; + } + + inline bool empty() const + { + return free_blocks[0] == AllFree; + } + + inline uint32_t get_longest_run() const + { + return longest_run; + } + + void allocate(uint32_t num_blocks, uint32_t &mask, uint32_t &offset); + void free(uint32_t mask); + +private: + uint32_t free_blocks[NumSubBlocks]; + uint32_t longest_run = 0; + void update_longest_run(); +}; + +// Represents that a legion heap is backed by some kind of allocation. +template +struct LegionHeap : Util::IntrusiveListEnabled> +{ + BackingAllocation allocation; + Util::LegionAllocator heap; +}; + +template +struct AllocationArena +{ + Util::IntrusiveList> heaps[Util::LegionAllocator::NumSubBlocks]; + Util::IntrusiveList> full_heaps; + uint32_t heap_availability_mask = 0; +}; + +struct SuballocationResult +{ + uint32_t offset; + uint32_t size; + uint32_t mask; +}; + +template +class ArenaAllocator +{ +public: + using MiniHeap = LegionHeap; + + ~ArenaAllocator() + { + bool error = false; + + if (heap_arena.full_heaps.begin()) + error = true; + + for (auto &h : heap_arena.heaps) + if (h.begin()) + error = true; + + if (error) + LOGE("Memory leaked in class allocator!\n"); + } + + inline void set_sub_block_size(uint32_t size) + { + assert(Util::is_pow2(size)); + sub_block_size_log2 = Util::floor_log2(size); + sub_block_size = size; + } + + inline uint32_t get_max_allocation_size() const + { + return sub_block_size * Util::LegionAllocator::NumSubBlocks; + } + + inline uint32_t get_sub_block_size() const + { + return sub_block_size; + } + + inline uint32_t get_block_alignment() const + { + return get_sub_block_size(); + } + + inline bool allocate(uint32_t size, BackingAllocation *alloc) + { + unsigned num_blocks = (size + sub_block_size - 1) >> sub_block_size_log2; + uint32_t size_mask = (1u << (num_blocks - 1)) - 1; + uint32_t index = trailing_zeroes(heap_arena.heap_availability_mask & ~size_mask); + + if (index < LegionAllocator::NumSubBlocks) + { + auto itr = heap_arena.heaps[index].begin(); + assert(itr); + assert(index >= (num_blocks - 1)); + + auto &heap = *itr; + static_cast(this)->prepare_allocation(alloc, itr, suballocate(num_blocks, heap)); + + unsigned new_index = heap.heap.get_longest_run() - 1; + + if (heap.heap.full()) + { + heap_arena.full_heaps.move_to_front(heap_arena.heaps[index], itr); + if (!heap_arena.heaps[index].begin()) + heap_arena.heap_availability_mask &= ~(1u << index); + } + else if (new_index != index) + { + auto &new_heap = heap_arena.heaps[new_index]; + new_heap.move_to_front(heap_arena.heaps[index], itr); + heap_arena.heap_availability_mask |= 1u << new_index; + if (!heap_arena.heaps[index].begin()) + heap_arena.heap_availability_mask &= ~(1u << index); + } + + return true; + } + + // We didn't find a vacant heap, make a new one. + auto *node = object_pool->allocate(); + if (!node) + return false; + + auto &heap = *node; + + if (!static_cast(this)->allocate_backing_heap(&heap.allocation)) + { + object_pool->free(node); + return false; + } + + // This cannot fail. + static_cast(this)->prepare_allocation(alloc, node, suballocate(num_blocks, heap)); + + if (heap.heap.full()) + { + heap_arena.full_heaps.insert_front(node); + } + else + { + unsigned new_index = heap.heap.get_longest_run() - 1; + heap_arena.heaps[new_index].insert_front(node); + heap_arena.heap_availability_mask |= 1u << new_index; + } + + return true; + } + + inline void free(typename IntrusiveList::Iterator itr, uint32_t mask) + { + auto *heap = itr.get(); + auto &block = heap->heap; + bool was_full = block.full(); + + unsigned index = block.get_longest_run() - 1; + block.free(mask); + unsigned new_index = block.get_longest_run() - 1; + + if (block.empty()) + { + static_cast(this)->free_backing_heap(&heap->allocation); + + if (was_full) + heap_arena.full_heaps.erase(heap); + else + { + heap_arena.heaps[index].erase(heap); + if (!heap_arena.heaps[index].begin()) + heap_arena.heap_availability_mask &= ~(1u << index); + } + + object_pool->free(heap); + } + else if (was_full) + { + heap_arena.heaps[new_index].move_to_front(heap_arena.full_heaps, heap); + heap_arena.heap_availability_mask |= 1u << new_index; + } + else if (index != new_index) + { + heap_arena.heaps[new_index].move_to_front(heap_arena.heaps[index], heap); + heap_arena.heap_availability_mask |= 1u << new_index; + if (!heap_arena.heaps[index].begin()) + heap_arena.heap_availability_mask &= ~(1u << index); + } + } + + inline void set_object_pool(ObjectPool *object_pool_) + { + object_pool = object_pool_; + } + +protected: + AllocationArena heap_arena; + ObjectPool> *object_pool = nullptr; + + uint32_t sub_block_size = 1; + uint32_t sub_block_size_log2 = 0; + +private: + inline SuballocationResult suballocate(uint32_t num_blocks, MiniHeap &heap) + { + SuballocationResult res = {}; + res.size = num_blocks << sub_block_size_log2; + heap.heap.allocate(num_blocks, res.mask, res.offset); + res.offset <<= sub_block_size_log2; + return res; + } +}; + +struct SliceSubAllocator; + +struct AllocatedSlice +{ + uint32_t buffer_index = UINT32_MAX; + uint32_t offset = 0; + uint32_t count = 0; + uint32_t mask = 0; + + SliceSubAllocator *alloc = nullptr; + Util::IntrusiveList>::Iterator heap = {}; +}; + +struct SliceBackingAllocator +{ + virtual ~SliceBackingAllocator() = default; + virtual uint32_t allocate(uint32_t count) = 0; + virtual void free(uint32_t index) = 0; + virtual void prime(uint32_t count, const void *opaque_meta) = 0; +}; + +struct SliceBackingAllocatorVA : SliceBackingAllocator +{ + uint32_t allocate(uint32_t count) override; + void free(uint32_t index) override; + void prime(uint32_t count, const void *opaque_meta) override; + bool allocated = false; +}; + +struct SliceSubAllocator : Util::ArenaAllocator +{ + SliceSubAllocator *parent = nullptr; + SliceBackingAllocator *global_allocator = nullptr; + + // Implements curious recurring template pattern calls. + bool allocate_backing_heap(AllocatedSlice *allocation); + void free_backing_heap(AllocatedSlice *allocation) const; + void prepare_allocation(AllocatedSlice *allocation, Util::IntrusiveList::Iterator heap, + const Util::SuballocationResult &suballoc); +}; + +class SliceAllocator +{ +public: + bool allocate(uint32_t count, Util::AllocatedSlice *slice); + void free(const Util::AllocatedSlice &slice); + void prime(const void *opaque_meta); + +protected: + SliceAllocator() = default; + void init(uint32_t sub_block_size, uint32_t num_sub_blocks_in_arena_log2, SliceBackingAllocator *alloc); + +private: + Util::ObjectPool> object_pool; + SliceBackingAllocator *global_allocator = nullptr; + enum { SliceAllocatorCount = 5 }; + Util::SliceSubAllocator allocators[SliceAllocatorCount]; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/array_view.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/array_view.hpp new file mode 100644 index 00000000..a02f1385 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/array_view.hpp @@ -0,0 +1,109 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include + +namespace Util +{ +template +class ArrayView +{ +public: + using ConstT = const typename std::remove_const::type; + + ArrayView(T *t, size_t size) + : ptr(t), array_size(size) + { + } + + template + ArrayView(U &u) + : ptr(u.data()), array_size(u.size()) + { + } + + ArrayView() = default; + + T *begin() + { + return ptr; + } + + T *end() + { + return ptr + array_size; + } + + ConstT *begin() const + { + return ptr; + } + + ConstT *end() const + { + return ptr + array_size; + } + + T &operator[](size_t n) + { + return ptr[n]; + } + + ConstT &operator[](size_t n) const + { + return ptr[n]; + } + + size_t size() const + { + return array_size; + } + + T *data() + { + return ptr; + } + + ConstT *data() const + { + return ptr; + } + + bool empty() const + { + return array_size == 0; + } + + void reset() + { + ptr = nullptr; + array_size = 0; + } + +private: + T *ptr = nullptr; + size_t array_size = 0; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/async_object_sink.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/async_object_sink.hpp new file mode 100644 index 00000000..3fa4ca94 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/async_object_sink.hpp @@ -0,0 +1,108 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include "read_write_lock.hpp" + +namespace Util +{ +template +class AsyncObjectSink +{ +public: + AsyncObjectSink() + { + has_object.store(false); + } + + auto get_nowait() + { + return raw_object.load(std::memory_order_acquire); + } + + auto get() + { + if (has_object.load(std::memory_order_acquire)) + { + return get_nowait(); + } + else + { + { + std::unique_lock holder{lock}; + cond.wait(holder, [&]() + { + return async_object_exists; + }); + } + return get_nowait(); + } + } + + T write_object(T new_object) + { + auto *raw_ptr = new_object.get(); + spin.lock_write(); + std::swap(object, new_object); + + // Need to release here since the content inside the pointer needs to be made visible + // before the pointer itself. + // The pointer needs to be written before has_object. + raw_object.store(raw_ptr, std::memory_order_release); + + if (!has_object.exchange(true, std::memory_order_acq_rel)) + { + std::lock_guard holder{lock}; + async_object_exists = true; + cond.notify_all(); + } + + spin.unlock_write(); + return new_object; + } + + void reset() + { + spin.lock_write(); + std::lock_guard holder{lock}; + async_object_exists = false; + has_object.store(false); + object = {}; + spin.unlock_write(); + } + +private: + T object; + using RawT = decltype(object.get()); + + std::atomic raw_object; + std::condition_variable cond; + std::mutex lock; + Util::RWSpinLock spin; + std::atomic_bool has_object; + bool async_object_exists = false; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/atomic_append_buffer.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/atomic_append_buffer.hpp new file mode 100644 index 00000000..8bcce28c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/atomic_append_buffer.hpp @@ -0,0 +1,157 @@ +/* Copyright (c) 2021-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include "aligned_alloc.hpp" +#include "bitops.hpp" +#include +#include +#include + +namespace Util +{ +template +class AtomicAppendBuffer +{ +public: + static_assert(std::is_trivially_destructible::value, "T is not trivially destructible."); + + AtomicAppendBuffer() + { + count.store(0, std::memory_order_relaxed); + for (auto &l : lists) + l.store(nullptr, std::memory_order_relaxed); + + assert(count.is_lock_free()); + assert(lists[0].is_lock_free()); + } + + ~AtomicAppendBuffer() + { + for (auto &l : lists) + { + auto *ptr = l.load(std::memory_order_relaxed); + Util::memalign_free(ptr); + } + } + + AtomicAppendBuffer(const AtomicAppendBuffer &) = delete; + void operator=(const AtomicAppendBuffer &) = delete; + + void clear() + { + count.store(0, std::memory_order_relaxed); + } + + // Only thing that is thread-safe. + template + void push(U &&u) + { + uint32_t offset = count.fetch_add(1, std::memory_order_relaxed); + auto w = reserve_write(offset); + w.first[w.second] = std::forward(u); + } + + uint32_t size() const + { + return count.load(std::memory_order_relaxed); + } + + template + void for_each_ranged(Func &&func) + { + uint32_t offset = count.load(std::memory_order_relaxed); + if (!offset) + return; + offset--; + int msb = 31 - int(leading_zeroes(offset)); + msb = std::max(msb, MinimumMSB); + int list_index = msb - MinimumMSB; + + // Iterate over the complete lists. + for (int index = 0; index < list_index; index++) + { + uint32_t num_elements = num_elements_per_list_index(index); + auto *t = lists[index].load(std::memory_order_relaxed); + for (uint32_t i = 0; i < num_elements; i += 1u << MinimumMSB) + func(&t[i], 1u << MinimumMSB); + } + + // Iterate over the final list. + if (list_index != 0) + offset -= 1u << msb; + uint32_t num_elements = offset + 1; + auto *t = lists[list_index].load(std::memory_order_relaxed); + for (uint32_t i = 0; i < num_elements; i += 1u << MinimumMSB) + func(&t[i], std::min(num_elements - i, 1u << MinimumMSB)); + } + +private: + static_assert(MinimumMSB < 32, "MinimumMSB must be < 32."); + std::atomic lists[32 - MinimumMSB]; + std::atomic_uint32_t count; + + static uint32_t num_elements_per_list_index(unsigned index) + { + return 1u << (index + MinimumMSB + unsigned(index == 0)); + } + + std::pair reserve_write(uint32_t required_offset) + { + int msb = 31 - int(leading_zeroes(uint32_t(required_offset))); + if (msb < MinimumMSB) + msb = MinimumMSB; + int list_index = msb - MinimumMSB; + + uint32_t offset = required_offset; + if (list_index != 0) + offset -= 1u << msb; + + // If we can observe the pointer, we're good. + if (auto *new_t = lists[list_index].load(std::memory_order_relaxed)) + return { new_t, offset }; + + uint32_t required_count = num_elements_per_list_index(list_index); + size_t required_size = size_t(required_count) * sizeof(T); + auto *new_t = static_cast(Util::memalign_alloc(std::max(64, alignof(T)), required_size)); + T *expected_t = nullptr; + + // Relaxed order is fine. We will not read anything from this buffer until we have synchronized, and + // thus memory order is moot. + if (!lists[list_index].compare_exchange_strong(expected_t, new_t, + std::memory_order_relaxed, + std::memory_order_relaxed)) + { + // Another thread allocated early, free. + Util::memalign_free(new_t); + new_t = expected_t; + } + + return { new_t, offset }; + } +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/bitops.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/bitops.hpp new file mode 100644 index 00000000..4bceaeb3 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/bitops.hpp @@ -0,0 +1,199 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#ifdef _MSC_VER +#include +#endif + +namespace Util +{ +#ifdef __GNUC__ +#define leading_zeroes_(x) ((x) == 0 ? 32 : __builtin_clz(x)) +#define trailing_zeroes_(x) ((x) == 0 ? 32 : __builtin_ctz(x)) +#define trailing_ones_(x) __builtin_ctz(~uint32_t(x)) +#define leading_zeroes64_(x) ((x) == 0 ? 64 : __builtin_clzll(x)) +#define trailing_zeroes64_(x) ((x) == 0 ? 64 : __builtin_ctzll(x)) +#define trailing_ones64_(x) __builtin_ctzll(~uint64_t(x)) +#define popcount32_(x) __builtin_popcount(x) +#define popcount64_(x) __builtin_popcountll(x) + +static inline uint32_t leading_zeroes(uint32_t x) { return leading_zeroes_(x); } +static inline uint32_t trailing_zeroes(uint32_t x) { return trailing_zeroes_(x); } +static inline uint32_t trailing_ones(uint32_t x) { return trailing_ones_(x); } +static inline uint32_t leading_zeroes64(uint64_t x) { return leading_zeroes64_(x); } +static inline uint32_t trailing_zeroes64(uint64_t x) { return trailing_zeroes64_(x); } +static inline uint32_t trailing_ones64(uint64_t x) { return trailing_ones64_(x); } +static inline uint32_t popcount32(uint32_t x) { return popcount32_(x); } +static inline uint32_t popcount64(uint64_t x) { return popcount64_(x); } + +#elif defined(_MSC_VER) +namespace Internal +{ +static inline uint32_t popcount32(uint32_t x) +{ + return __popcnt(x); +} + +static inline uint32_t popcount64(uint64_t x) +{ +#ifdef _WIN64 + return __popcnt64(x); +#else + return popcount32(uint32_t(x)) + popcount32(uint32_t(x >> 32)); +#endif +} + +static inline uint32_t clz(uint32_t x) +{ + unsigned long result; + if (_BitScanReverse(&result, x)) + return 31 - result; + else + return 32; +} + +static inline uint32_t ctz(uint32_t x) +{ + unsigned long result; + if (_BitScanForward(&result, x)) + return result; + else + return 32; +} + +static inline uint32_t clz64(uint64_t x) +{ +#ifdef _WIN64 + unsigned long result; + if (_BitScanReverse64(&result, x)) + return 63 - result; + else + return 64; +#else + if (x > UINT32_MAX) + return clz(uint32_t(x >> 32)); + else + return clz(uint32_t(x)) + 32; +#endif +} + +static inline uint32_t ctz64(uint64_t x) +{ +#ifdef _WIN64 + unsigned long result; + if (_BitScanForward64(&result, x)) + return result; + else + return 64; +#else + if ((x & UINT32_MAX) != 0) + return ctz(uint32_t(x)); + else + return ctz(uint32_t(x >> 32)) + 32; +#endif +} +} + +static inline uint32_t leading_zeroes(uint32_t x) { return Internal::clz(x); } +static inline uint32_t trailing_zeroes(uint32_t x) { return Internal::ctz(x); } +static inline uint32_t trailing_ones(uint32_t x) { return Internal::ctz(~x); } +static inline uint32_t leading_zeroes64(uint64_t x) { return Internal::clz64(x); } +static inline uint32_t trailing_zeroes64(uint64_t x) { return Internal::ctz64(x); } +static inline uint32_t trailing_ones64(uint64_t x) { return Internal::ctz64(~x); } +static inline uint32_t popcount32(uint32_t x) { return Internal::popcount32(x); } +static inline uint32_t popcount64(uint64_t x) { return Internal::popcount64(x); } +#else +#error "Implement me." +#endif + +template +inline void for_each_bit64(uint64_t value, const T &func) +{ + while (value) + { + uint32_t bit = trailing_zeroes64(value); + func(bit); + value &= ~(1ull << bit); + } +} + +template +inline void for_each_bit(uint32_t value, const T &func) +{ + while (value) + { + uint32_t bit = trailing_zeroes(value); + func(bit); + value &= ~(1u << bit); + } +} + +template +inline void for_each_bit_range(uint32_t value, const T &func) +{ + if (value == ~0u) + { + func(0, 32); + return; + } + + uint32_t bit_offset = 0; + while (value) + { + uint32_t bit = trailing_zeroes(value); + bit_offset += bit; + value >>= bit; + uint32_t range = trailing_ones(value); + func(bit_offset, range); + value &= ~((1u << range) - 1); + } +} + +template +inline bool is_pow2(T value) +{ + return (value & (value - T(1))) == T(0); +} + +inline uint32_t next_pow2(uint32_t v) +{ + v--; + v |= v >> 16; + v |= v >> 8; + v |= v >> 4; + v |= v >> 2; + v |= v >> 1; + return v + 1; +} + +inline uint32_t prev_pow2(uint32_t v) +{ + return next_pow2(v + 1) >> 1; +} + +inline uint32_t floor_log2(uint32_t v) +{ + return 31 - leading_zeroes(v); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/cli_parser.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/cli_parser.cpp new file mode 100644 index 00000000..77933a5d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/cli_parser.cpp @@ -0,0 +1,189 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "cli_parser.hpp" +#include "logging.hpp" +#include +#include +#include + +namespace Util +{ +CLIParser::CLIParser(CLICallbacks cbs_, int argc_, char *argv_[]) + : cbs(std::move(cbs_)), argc(argc_), argv(argv_) +{ +} + +bool CLIParser::parse() +{ +#if defined(__EXCEPTIONS) || defined(__HAS_EXCEPTIONS) + try +#endif + { + while (argc && !ended_state) + { + const char *next = *argv++; + argc--; + + if (*next != '-' && cbs.default_handler) + { + cbs.default_handler(next); + } + else + { + auto itr = cbs.callbacks.find(next); + if (itr == std::end(cbs.callbacks)) + { + if (unknown_argument_is_default) + cbs.default_handler(next); +#if defined(__EXCEPTIONS) || defined(__HAS_EXCEPTIONS) + else + throw std::invalid_argument("Invalid argument"); +#else + else + return false; +#endif + } + else + itr->second(*this); + } + } + + return true; + } +#if defined(__EXCEPTIONS) || defined(__HAS_EXCEPTIONS) + catch (const std::exception &e) + { + LOGE("Failed to parse arguments: %s\n", e.what()); + if (cbs.error_handler) + { + cbs.error_handler(); + } + return false; + } +#endif +} + +void CLIParser::end() +{ + ended_state = true; +} + +unsigned CLIParser::next_uint() +{ + if (!argc) + { +#ifdef __EXCEPTIONS + throw std::invalid_argument("Tried to parse uint, but nothing left in arguments"); +#else + return 0; +#endif + } + + auto val = std::stoul(*argv); + if (val > std::numeric_limits::max()) + { +#ifdef __EXCEPTIONS + throw std::invalid_argument("next_uint() out of range"); +#else + return 0; +#endif + } + + argc--; + argv++; + + return unsigned(val); +} + +double CLIParser::next_double() +{ + if (!argc) + { +#ifdef __EXCEPTIONS + throw std::invalid_argument("Tried to parse double, but nothing left in arguments"); +#else + return 0; +#endif + } + + double val = std::stod(*argv); + + argc--; + argv++; + + return val; +} + +const char *CLIParser::next_string() +{ + if (!argc) + { +#ifdef __EXCEPTIONS + throw std::invalid_argument("Tried to parse string, but nothing left in arguments"); +#else + return nullptr; +#endif + } + + const char *ret = *argv; + argc--; + argv++; + return ret; +} + +bool parse_cli_filtered(CLICallbacks cbs, int &argc, char *argv[], int &exit_code) +{ + if (argc == 0) + { + exit_code = 1; + return false; + } + + exit_code = 0; + std::vector filtered; + filtered.reserve(argc + 1); + filtered.push_back(argv[0]); + + cbs.default_handler = [&](const char *arg) { filtered.push_back(const_cast(arg)); }; + + CLIParser parser(std::move(cbs), argc - 1, argv + 1); + parser.ignore_unknown_arguments(); + + if (!parser.parse()) + { + exit_code = 1; + return false; + } + else if (parser.is_ended_state()) + { + exit_code = 0; + return false; + } + + argc = int(filtered.size()); + std::copy(filtered.begin(), filtered.end(), argv); + argv[argc] = nullptr; + return true; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/cli_parser.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/cli_parser.hpp new file mode 100644 index 00000000..741c5246 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/cli_parser.hpp @@ -0,0 +1,82 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include + +namespace Util +{ +class CLIParser; + +struct CLICallbacks +{ + void add(const char *cli, const std::function &func) + { + callbacks[cli] = func; + } + + std::unordered_map> callbacks; + std::function error_handler; + std::function default_handler; +}; + +class CLIParser +{ +public: + // Don't pass in argv[0], which is the application name. + // Pass in argc - 1, argv + 1. + CLIParser(CLICallbacks cbs_, int argc_, char *argv_[]); + + bool parse(); + void end(); + + unsigned next_uint(); + double next_double(); + const char *next_string(); + + bool is_ended_state() const + { + return ended_state; + } + + void ignore_unknown_arguments() + { + unknown_argument_is_default = true; + } + +private: + CLICallbacks cbs; + int argc; + char **argv; + bool ended_state = false; + bool unknown_argument_is_default = false; +}; + +// Returns false is parsing requires an exit, either because of error, or by request. +// In that case, exit_code should be returned from main(). +// argc / argv must contain the full argc, argv, where argv[0] holds program name. +bool parse_cli_filtered(CLICallbacks cbs, int &argc, char *argv[], int &exit_code); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/compile_time_hash.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/compile_time_hash.hpp new file mode 100644 index 00000000..f4a5c621 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/compile_time_hash.hpp @@ -0,0 +1,86 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Util +{ +#ifdef _MSC_VER +// MSVC generates bogus warnings here. +#pragma warning(disable: 4307) +#endif + +constexpr uint64_t fnv_iterate(uint64_t hash, uint8_t c) +{ + return (hash * 0x100000001b3ull) ^ c; +} + +template +constexpr uint64_t compile_time_fnv1_inner(uint64_t hash, const char *str) +{ + return compile_time_fnv1_inner(fnv_iterate(hash, uint8_t(str[index])), str); +} + +template<> +constexpr uint64_t compile_time_fnv1_inner(uint64_t hash, const char *) +{ + return hash; +} + +template +constexpr uint64_t compile_time_fnv1(const char (&str)[len]) +{ + return compile_time_fnv1_inner(0xcbf29ce484222325ull, str); +} + +constexpr uint64_t compile_time_fnv1_merge(uint64_t a, uint64_t b) +{ + return fnv_iterate( + fnv_iterate( + fnv_iterate( + fnv_iterate( + fnv_iterate( + fnv_iterate( + fnv_iterate( + fnv_iterate(a, uint8_t(b >> 0)), + uint8_t(b >> 8)), + uint8_t(b >> 16)), + uint8_t(b >> 24)), + uint8_t(b >> 32)), + uint8_t(b >> 40)), + uint8_t(b >> 48)), + uint8_t(b >> 56)); +} + +constexpr uint64_t compile_time_fnv1_merged(uint64_t hash) +{ + return hash; +} + +template +constexpr uint64_t compile_time_fnv1_merged(T hash, T hash2, Ts... hashes) +{ + return compile_time_fnv1_merged(compile_time_fnv1_merge(hash, hash2), hashes...); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/dynamic_array.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/dynamic_array.hpp new file mode 100644 index 00000000..0ed7fd40 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/dynamic_array.hpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "aligned_alloc.hpp" +#include +#include +#include +#include + +namespace Util +{ +template +class DynamicArray +{ +public: + // Only POD-like types work here since we don't invoke placement new or delete. + static_assert(std::is_trivially_default_constructible::value, "T must be trivially constructible."); + static_assert(std::is_trivially_destructible::value, "T must be trivially destructible."); + + void reserve(size_t n) + { + if (n > N) + { + n = std::max(n, N * 3 / 2); + + auto *new_ptr = static_cast( + memalign_alloc(std::max(64, alignof(T)), n * sizeof(T))); + + if (buffer) + memcpy(new_ptr, buffer.get(), N * sizeof(T)); + + buffer.reset(new_ptr); + N = n; + } + } + + T &operator[](size_t index) { return buffer.get()[index]; } + const T &operator[](size_t index) const { return buffer.get()[index]; } + T *data() { return buffer.get(); } + const T *data() const { return buffer.get(); } + size_t get_capacity() const { return N; } + +private: + std::unique_ptr buffer; + size_t N = 0; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/dynamic_library.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/dynamic_library.cpp new file mode 100644 index 00000000..c36f7d75 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/dynamic_library.cpp @@ -0,0 +1,99 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "dynamic_library.hpp" +#include "logging.hpp" +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#else +#include +#endif + +namespace Util +{ +DynamicLibrary::DynamicLibrary(const char *path) +{ +#ifdef _WIN32 + module = LoadLibraryA(path); + if (!module) + LOGE("Failed to load dynamic library.\n"); +#else + dylib = dlopen(path, RTLD_NOW); + if (!dylib) + LOGE("Failed to load dynamic library.\n"); +#endif +} + +DynamicLibrary::DynamicLibrary(Util::DynamicLibrary &&other) noexcept +{ + *this = std::move(other); +} + +DynamicLibrary &DynamicLibrary::operator=(Util::DynamicLibrary &&other) noexcept +{ + close(); +#ifdef _WIN32 + module = other.module; + other.module = nullptr; +#else + dylib = other.dylib; + other.dylib = nullptr; +#endif + return *this; +} + +void DynamicLibrary::close() +{ +#ifdef _WIN32 + if (module) + FreeLibrary(module); + module = nullptr; +#else + if (dylib) + dlclose(dylib); + dylib = nullptr; +#endif +} + +DynamicLibrary::~DynamicLibrary() +{ + close(); +} + +void *DynamicLibrary::get_symbol_internal(const char *symbol) +{ +#ifdef _WIN32 + if (module) + return (void*)GetProcAddress(module, symbol); + else + return nullptr; +#else + if (dylib) + return dlsym(dylib, symbol); + else + return nullptr; +#endif +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/dynamic_library.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/dynamic_library.hpp new file mode 100644 index 00000000..69266b82 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/dynamic_library.hpp @@ -0,0 +1,67 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +namespace Util +{ +class DynamicLibrary +{ +public: + DynamicLibrary() = default; + explicit DynamicLibrary(const char *path); + ~DynamicLibrary(); + + DynamicLibrary(DynamicLibrary &&other) noexcept; + DynamicLibrary &operator=(DynamicLibrary &&other) noexcept; + + template + Func get_symbol(const char *symbol) + { + return reinterpret_cast(get_symbol_internal(symbol)); + } + + explicit operator bool() const + { +#if _WIN32 + return module != nullptr; +#else + return dylib != nullptr; +#endif + } + +private: +#if _WIN32 + HMODULE module = nullptr; +#else + void *dylib = nullptr; +#endif + + void *get_symbol_internal(const char *symbol); + void close(); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/enum_cast.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/enum_cast.hpp new file mode 100644 index 00000000..a6787270 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/enum_cast.hpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Util +{ +template +constexpr typename std::underlying_type::type ecast(T x) +{ + return static_cast::type>(x); +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/environment.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/environment.cpp new file mode 100644 index 00000000..5405f0cb --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/environment.cpp @@ -0,0 +1,96 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include "environment.hpp" +#include +#include + +namespace Util +{ +bool get_environment(const char *env, std::string &str) +{ +#ifdef _WIN32 + char buf[4096]; + DWORD count = GetEnvironmentVariableA(env, buf, sizeof(buf)); + if (count) + { + str = { buf, buf + count }; + return true; + } + else + return false; +#else + if (const char *v = getenv(env)) + { + str = v; + return true; + } + else + return false; +#endif +} + +void set_environment(const char *env, const char *value) +{ +#ifdef _WIN32 + SetEnvironmentVariableA(env, value); +#else + setenv(env, value, 1); +#endif +} + +std::string get_environment_string(const char *env, const char *default_value) +{ + std::string v; + if (!get_environment(env, v)) + v = default_value; + return v; +} + +unsigned get_environment_uint(const char *env, unsigned default_value) +{ + unsigned value = default_value; + std::string v; + if (get_environment(env, v)) + value = unsigned(std::stoul(v)); + return value; +} + +int get_environment_int(const char *env, int default_value) +{ + int value = default_value; + std::string v; + if (get_environment(env, v)) + value = int(std::stol(v)); + return value; +} + +bool get_environment_bool(const char *env, bool default_value) +{ + return get_environment_int(env, int(default_value)) != 0; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/environment.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/environment.hpp new file mode 100644 index 00000000..8ee10659 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/environment.hpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Util +{ +bool get_environment(const char *env, std::string &str); +std::string get_environment_string(const char *env, const char *default_value); +unsigned get_environment_uint(const char *env, unsigned default_value); +int get_environment_int(const char *env, int default_value); +bool get_environment_bool(const char *env, bool default_value); +void set_environment(const char *env, const char *value); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/generational_handle.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/generational_handle.hpp new file mode 100644 index 00000000..86a495b9 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/generational_handle.hpp @@ -0,0 +1,175 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include "object_pool.hpp" +#include + +namespace Util +{ +using GenerationalHandleID = uint32_t; +template +class GenerationalHandlePool +{ +public: + using ID = GenerationalHandleID; + + GenerationalHandlePool() + { + elements.resize(16); + generation.resize(16); + for (unsigned i = 0; i < 16; i++) + vacant_indices.push(i); + } + + ~GenerationalHandlePool() + { + for (auto &elem : elements) + if (elem) + pool.free(elem); + } + + GenerationalHandlePool(const GenerationalHandlePool &) = delete; + void operator=(const GenerationalHandlePool &) = delete; + + template + ID emplace(P&&... p) + { + auto index = get_vacant_index(); + auto generation_index = uint8_t(++generation[index]); + + // Reserve generation index 0 for sentinel purposes. + if (!generation_index) + generation_index = ++generation[index]; + + elements[index] = pool.allocate(std::forward

(p)...); + return make_id(index, generation_index); + } + + void remove(ID id) + { + auto index = memory_index(id); + auto gen_index = generation_index(id); + + if (index >= elements.size()) + return; + if (gen_index != generation[index]) + return; + if (!elements[index]) + return; + + pool.free(elements[index]); + elements[index] = nullptr; + vacant_indices.push(index); + } + + T *maybe_get(ID id) const + { + auto index = memory_index(id); + auto gen_index = generation_index(id); + + if (index >= elements.size()) + return nullptr; + if (gen_index != generation[index]) + return nullptr; + + return elements[index]; + } + + T &get(ID id) const + { + auto index = memory_index(id); + auto gen_index = generation_index(id); + + if (index >= elements.size()) + throw std::logic_error("Invalid ID."); + if (gen_index != generation[index]) + throw std::logic_error("Invalid ID."); + if (!elements[index]) + throw std::logic_error("Invalid ID."); + + return *elements[index]; + } + + void clear() + { + for (size_t i = 0; i < elements.size(); i++) + { + if (elements[i]) + { + pool.free(elements[i]); + vacant_indices.push(i); + elements[i] = nullptr; + } + } + } + +private: + Util::ObjectPool pool; + std::vector elements; + std::vector generation; + std::stack vacant_indices; + + uint32_t get_vacant_index() + { + if (vacant_indices.empty()) + { + size_t current_size = elements.size(); + + // If this is ever a problem, we can bump to 64-bit IDs. + if (current_size >= (size_t(1) << 24u)) + throw std::bad_alloc(); + + elements.resize(current_size * 2); + generation.resize(current_size * 2); + for (size_t index = current_size; index < 2 * current_size; index++) + vacant_indices.push(index); + } + + auto ret = vacant_indices.top(); + vacant_indices.pop(); + return ret; + } + + static ID make_id(uint32_t index, uint32_t generation_index) + { + assert(index <= 0x00ffffffu); + assert(generation_index <= 0xffu); + return (generation_index << 24u) | index; + } + + static uint32_t generation_index(ID id) + { + return (id >> 24u) & 0xffu; + } + + static uint32_t memory_index(ID id) + { + return id & 0xffffffu; + } +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/hash.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/hash.hpp new file mode 100644 index 00000000..5c16caf5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/hash.hpp @@ -0,0 +1,105 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include +#include + +namespace Util +{ +using Hash = uint64_t; + +class Hasher +{ +public: + explicit Hasher(Hash h_) + : h(h_) + { + } + + Hasher() = default; + + template + inline void data(const T *data_, size_t size) + { + size /= sizeof(*data_); + for (size_t i = 0; i < size; i++) + h = (h * 0x100000001b3ull) ^ data_[i]; + } + + inline void u32(uint32_t value) + { + h = (h * 0x100000001b3ull) ^ value; + } + + inline void s32(int32_t value) + { + u32(uint32_t(value)); + } + + inline void f32(float value) + { + union + { + float f32; + uint32_t u32; + } u; + u.f32 = value; + u32(u.u32); + } + + inline void u64(uint64_t value) + { + u32(value & 0xffffffffu); + u32(value >> 32); + } + + template + inline void pointer(T *ptr) + { + u64(reinterpret_cast(ptr)); + } + + inline void string(const char *str) + { + char c; + u32(0xff); + while ((c = *str++) != '\0') + u32(uint8_t(c)); + } + + inline void string(const std::string &str) + { + u32(0xff); + for (auto &c : str) + u32(uint8_t(c)); + } + + inline Hash get() const + { + return h; + } + +private: + Hash h = 0xcbf29ce484222325ull; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/hashmap.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/hashmap.hpp new file mode 100644 index 00000000..f3e0c780 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/hashmap.hpp @@ -0,0 +1,40 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include "hash.hpp" + +namespace Util +{ +struct UnityHasher +{ + inline size_t operator()(uint64_t hash) const + { + return hash; + } +}; + +template +using HashMap = std::unordered_map; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/intrusive.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/intrusive.hpp new file mode 100644 index 00000000..b299f765 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/intrusive.hpp @@ -0,0 +1,310 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Util +{ +class SingleThreadCounter +{ +public: + inline void add_ref() + { + count++; + } + + inline bool release() + { + return --count == 0; + } + +private: + uint32_t count = 1; +}; + +class MultiThreadCounter +{ +public: + MultiThreadCounter() + { + count.store(1, std::memory_order_relaxed); + } + + inline void add_ref() + { + count.fetch_add(1, std::memory_order_relaxed); + } + + inline bool release() + { + auto result = count.fetch_sub(1, std::memory_order_acq_rel); + return result == 1; + } + +private: + std::atomic_uint32_t count; +}; + +template +class IntrusivePtr; + +template , typename ReferenceOps = SingleThreadCounter> +class IntrusivePtrEnabled +{ +public: + using IntrusivePtrType = IntrusivePtr; + using EnabledBase = T; + using EnabledDeleter = Deleter; + using EnabledReferenceOp = ReferenceOps; + + void release_reference() + { + if (reference_count.release()) + Deleter()(static_cast(this)); + } + + void add_reference() + { + reference_count.add_ref(); + } + + IntrusivePtrEnabled() = default; + + IntrusivePtrEnabled(const IntrusivePtrEnabled &) = delete; + + void operator=(const IntrusivePtrEnabled &) = delete; + +protected: + Util::IntrusivePtr reference_from_this(); + +private: + ReferenceOps reference_count; +}; + +template +class IntrusivePtr +{ +public: + template + friend class IntrusivePtr; + + IntrusivePtr() = default; + + explicit IntrusivePtr(T *handle) + : data(handle) + { + } + + T &operator*() + { + return *data; + } + + const T &operator*() const + { + return *data; + } + + T *operator->() + { + return data; + } + + const T *operator->() const + { + return data; + } + + explicit operator bool() const + { + return data != nullptr; + } + + bool operator==(const IntrusivePtr &other) const + { + return data == other.data; + } + + bool operator!=(const IntrusivePtr &other) const + { + return data != other.data; + } + + T *get() + { + return data; + } + + const T *get() const + { + return data; + } + + void reset() + { + using ReferenceBase = IntrusivePtrEnabled< + typename T::EnabledBase, + typename T::EnabledDeleter, + typename T::EnabledReferenceOp>; + + // Static up-cast here to avoid potential issues with multiple intrusive inheritance. + // Also makes sure that the pointer type actually inherits from this type. + if (data) + static_cast(data)->release_reference(); + data = nullptr; + } + + template + IntrusivePtr &operator=(const IntrusivePtr &other) + { + static_assert(std::is_base_of::value, + "Cannot safely assign downcasted intrusive pointers."); + + using ReferenceBase = IntrusivePtrEnabled< + typename T::EnabledBase, + typename T::EnabledDeleter, + typename T::EnabledReferenceOp>; + + reset(); + data = static_cast(other.data); + + // Static up-cast here to avoid potential issues with multiple intrusive inheritance. + // Also makes sure that the pointer type actually inherits from this type. + if (data) + static_cast(data)->add_reference(); + return *this; + } + + IntrusivePtr &operator=(const IntrusivePtr &other) + { + using ReferenceBase = IntrusivePtrEnabled< + typename T::EnabledBase, + typename T::EnabledDeleter, + typename T::EnabledReferenceOp>; + + if (this != &other) + { + reset(); + data = other.data; + if (data) + static_cast(data)->add_reference(); + } + return *this; + } + + template + IntrusivePtr(const IntrusivePtr &other) + { + *this = other; + } + + IntrusivePtr(const IntrusivePtr &other) + { + *this = other; + } + + ~IntrusivePtr() + { + reset(); + } + + template + IntrusivePtr &operator=(IntrusivePtr &&other) noexcept + { + reset(); + data = other.data; + other.data = nullptr; + return *this; + } + + IntrusivePtr &operator=(IntrusivePtr &&other) noexcept + { + if (this != &other) + { + reset(); + data = other.data; + other.data = nullptr; + } + return *this; + } + + template + IntrusivePtr(IntrusivePtr &&other) noexcept + { + *this = std::move(other); + } + + template + IntrusivePtr(IntrusivePtr &&other) noexcept + { + *this = std::move(other); + } + + T *release() & + { + T *ret = data; + data = nullptr; + return ret; + } + + T *release() && + { + T *ret = data; + data = nullptr; + return ret; + } + +private: + T *data = nullptr; +}; + +template +IntrusivePtr IntrusivePtrEnabled::reference_from_this() +{ + add_reference(); + return IntrusivePtr(static_cast(this)); +} + +template +using DerivedIntrusivePtrType = IntrusivePtr; + +template +DerivedIntrusivePtrType make_handle(P &&... p) +{ + return DerivedIntrusivePtrType(new T(std::forward

(p)...)); +} + +template +typename Base::IntrusivePtrType make_derived_handle(P &&... p) +{ + return typename Base::IntrusivePtrType(new Derived(std::forward

(p)...)); +} + +template +using ThreadSafeIntrusivePtrEnabled = IntrusivePtrEnabled, MultiThreadCounter>; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/intrusive_hash_map.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/intrusive_hash_map.hpp new file mode 100644 index 00000000..d2f4752c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/intrusive_hash_map.hpp @@ -0,0 +1,695 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "hash.hpp" +#include "intrusive_list.hpp" +#include "object_pool.hpp" +#include "read_write_lock.hpp" +#include +#include + +namespace Util +{ +template +class IntrusiveHashMapEnabled : public IntrusiveListEnabled +{ +public: + IntrusiveHashMapEnabled() = default; + IntrusiveHashMapEnabled(Util::Hash hash) + : intrusive_hashmap_key(hash) + { + } + + void set_hash(Util::Hash hash) + { + intrusive_hashmap_key = hash; + } + + Util::Hash get_hash() const + { + return intrusive_hashmap_key; + } + +private: + Hash intrusive_hashmap_key = 0; +}; + +template +struct IntrusivePODWrapper : public IntrusiveHashMapEnabled> +{ + template + explicit IntrusivePODWrapper(U&& value_) + : value(std::forward(value_)) + { + } + + IntrusivePODWrapper() = default; + + T& get() + { + return value; + } + + const T& get() const + { + return value; + } + + T value = {}; +}; + +// This HashMap is non-owning. It just arranges a list of pointers. +// It's kind of special purpose container used by the Vulkan backend. +// Dealing with memory ownership is done through composition by a different class. +// T must inherit from IntrusiveHashMapEnabled. +// Each instance of T can only be part of one hashmap. + +template +class IntrusiveHashMapHolder +{ +public: + enum { InitialSize = 16, InitialLoadCount = 3 }; + + T *find(Hash hash) const + { + if (values.empty()) + return nullptr; + + Hash hash_mask = values.size() - 1; + auto masked = hash & hash_mask; + for (unsigned i = 0; i < load_count; i++) + { + if (values[masked] && get_hash(values[masked]) == hash) + return values[masked]; + masked = (masked + 1) & hash_mask; + } + + return nullptr; + } + + template + bool find_and_consume_pod(Hash hash, P &p) const + { + T *t = find(hash); + if (t) + { + p = t->get(); + return true; + } + else + return false; + } + + // Inserts, if value already exists, insertion does not happen. + // Return value is the data which is not part of the hashmap. + // It should be deleted or similar. + // Returns nullptr if nothing was in the hashmap for this key. + T *insert_yield(T *&value) + { + if (values.empty()) + grow(); + + Hash hash_mask = values.size() - 1; + auto hash = get_hash(value); + auto masked = hash & hash_mask; + + for (unsigned i = 0; i < load_count; i++) + { + if (values[masked] && get_hash(values[masked]) == hash) + { + T *ret = value; + value = values[masked]; + return ret; + } + else if (!values[masked]) + { + values[masked] = value; + list.insert_front(value); + return nullptr; + } + masked = (masked + 1) & hash_mask; + } + + grow(); + return insert_yield(value); + } + + T *insert_replace(T *value) + { + if (values.empty()) + grow(); + + Hash hash_mask = values.size() - 1; + auto hash = get_hash(value); + auto masked = hash & hash_mask; + + for (unsigned i = 0; i < load_count; i++) + { + if (values[masked] && get_hash(values[masked]) == hash) + { + std::swap(values[masked], value); + list.erase(value); + list.insert_front(values[masked]); + return value; + } + else if (!values[masked]) + { + assert(!values[masked]); + values[masked] = value; + list.insert_front(value); + return nullptr; + } + masked = (masked + 1) & hash_mask; + } + + grow(); + return insert_replace(value); + } + + T *erase(Hash hash) + { + Hash hash_mask = values.size() - 1; + auto masked = hash & hash_mask; + + for (unsigned i = 0; i < load_count; i++) + { + if (values[masked] && get_hash(values[masked]) == hash) + { + auto *value = values[masked]; + list.erase(value); + values[masked] = nullptr; + return value; + } + masked = (masked + 1) & hash_mask; + } + return nullptr; + } + + void erase(T *value) + { + erase(get_hash(value)); + } + + void clear() + { + list.clear(); + values.clear(); + load_count = 0; + } + + typename IntrusiveList::Iterator begin() const + { + return list.begin(); + } + + typename IntrusiveList::Iterator end() const + { + return list.end(); + } + + IntrusiveList &inner_list() + { + return list; + } + + const IntrusiveList &inner_list() const + { + return list; + } + +private: + + inline bool compare_key(Hash masked, Hash hash) const + { + return get_key_for_index(masked) == hash; + } + + inline Hash get_hash(const T *value) const + { + return static_cast *>(value)->get_hash(); + } + + inline Hash get_key_for_index(Hash masked) const + { + return get_hash(values[masked]); + } + + bool insert_inner(T *value) + { + Hash hash_mask = values.size() - 1; + auto hash = get_hash(value); + auto masked = hash & hash_mask; + + for (unsigned i = 0; i < load_count; i++) + { + if (!values[masked]) + { + values[masked] = value; + return true; + } + masked = (masked + 1) & hash_mask; + } + return false; + } + + void grow() + { + bool success; + do + { + for (auto &v : values) + v = nullptr; + + if (values.empty()) + { + values.resize(InitialSize); + load_count = InitialLoadCount; + //LOGI("Growing hashmap to %u elements.\n", InitialSize); + } + else + { + values.resize(values.size() * 2); + //LOGI("Growing hashmap to %u elements.\n", unsigned(values.size())); + load_count++; + } + + // Re-insert. + success = true; + for (auto &t : list) + { + if (!insert_inner(&t)) + { + success = false; + break; + } + } + } while (!success); + } + + std::vector values; + IntrusiveList list; + unsigned load_count = 0; +}; + +template +class IntrusiveHashMap +{ +public: + ~IntrusiveHashMap() + { + clear(); + } + + IntrusiveHashMap() = default; + IntrusiveHashMap(const IntrusiveHashMap &) = delete; + void operator=(const IntrusiveHashMap &) = delete; + + void clear() + { + auto &list = hashmap.inner_list(); + auto itr = list.begin(); + while (itr != list.end()) + { + auto *to_free = itr.get(); + itr = list.erase(itr); + pool.free(to_free); + } + + hashmap.clear(); + } + + T *find(Hash hash) const + { + return hashmap.find(hash); + } + + T &operator[](Hash hash) + { + auto *t = find(hash); + if (!t) + t = emplace_yield(hash); + return *t; + } + + template + bool find_and_consume_pod(Hash hash, P &p) const + { + return hashmap.find_and_consume_pod(hash, p); + } + + void erase(T *value) + { + hashmap.erase(value); + pool.free(value); + } + + void erase(Hash hash) + { + auto *value = hashmap.erase(hash); + if (value) + pool.free(value); + } + + template + T *emplace_replace(Hash hash, P&&... p) + { + T *t = allocate(std::forward

(p)...); + return insert_replace(hash, t); + } + + template + T *emplace_yield(Hash hash, P&&... p) + { + T *t = allocate(std::forward

(p)...); + return insert_yield(hash, t); + } + + template + T *allocate(P&&... p) + { + return pool.allocate(std::forward

(p)...); + } + + void free(T *value) + { + pool.free(value); + } + + T *insert_replace(Hash hash, T *value) + { + static_cast *>(value)->set_hash(hash); + T *to_delete = hashmap.insert_replace(value); + if (to_delete) + pool.free(to_delete); + return value; + } + + T *insert_yield(Hash hash, T *value) + { + static_cast *>(value)->set_hash(hash); + T *to_delete = hashmap.insert_yield(value); + if (to_delete) + pool.free(to_delete); + return value; + } + + typename IntrusiveList::Iterator begin() const + { + return hashmap.begin(); + } + + typename IntrusiveList::Iterator end() const + { + return hashmap.end(); + } + + IntrusiveHashMap &get_thread_unsafe() + { + return *this; + } + + const IntrusiveHashMap &get_thread_unsafe() const + { + return *this; + } + +private: + IntrusiveHashMapHolder hashmap; + ObjectPool pool; +}; + +template +using IntrusiveHashMapWrapper = IntrusiveHashMap>; + +template +class ThreadSafeIntrusiveHashMap +{ +public: + T *find(Hash hash) const + { + lock.lock_read(); + T *t = hashmap.find(hash); + lock.unlock_read(); + + // We can race with the intrusive list internal pointers, + // but that's an internal detail which should never be touched outside the hashmap. + return t; + } + + template + bool find_and_consume_pod(Hash hash, P &p) const + { + lock.lock_read(); + bool ret = hashmap.find_and_consume_pod(hash, p); + lock.unlock_read(); + return ret; + } + + void clear() + { + lock.lock_write(); + hashmap.clear(); + lock.unlock_write(); + } + + // Assumption is that readers will not be erased while in use by any other thread. + void erase(T *value) + { + lock.lock_write(); + hashmap.erase(value); + lock.unlock_write(); + } + + void erase(Hash hash) + { + lock.lock_write(); + hashmap.erase(hash); + lock.unlock_write(); + } + + template + T *allocate(P&&... p) + { + lock.lock_write(); + T *t = hashmap.allocate(std::forward

(p)...); + lock.unlock_write(); + return t; + } + + void free(T *value) + { + lock.lock_write(); + hashmap.free(value); + lock.unlock_write(); + } + + T *insert_replace(Hash hash, T *value) + { + lock.lock_write(); + value = hashmap.insert_replace(hash, value); + lock.unlock_write(); + return value; + } + + T *insert_yield(Hash hash, T *value) + { + lock.lock_write(); + value = hashmap.insert_yield(hash, value); + lock.unlock_write(); + return value; + } + + // This one is very sketchy, since callers need to make sure there are no readers of this hash. + template + T *emplace_replace(Hash hash, P&&... p) + { + lock.lock_write(); + T *t = hashmap.emplace_replace(hash, std::forward

(p)...); + lock.unlock_write(); + return t; + } + + template + T *emplace_yield(Hash hash, P&&... p) + { + lock.lock_write(); + T *t = hashmap.emplace_yield(hash, std::forward

(p)...); + lock.unlock_write(); + return t; + } + + // Not supposed to be called in racy conditions, + // we could have a global read lock and unlock while iterating if necessary. + typename IntrusiveList::Iterator begin() + { + return hashmap.begin(); + } + + typename IntrusiveList::Iterator end() + { + return hashmap.end(); + } + + IntrusiveHashMap &get_thread_unsafe() + { + return hashmap; + } + + const IntrusiveHashMap &get_thread_unsafe() const + { + return hashmap; + } + +private: + IntrusiveHashMap hashmap; + mutable RWSpinLock lock; +}; + +// A special purpose hashmap which is split into a read-only, immutable portion and a plain thread-safe one. +// User can move read-write thread-safe portion to read-only portion when user knows it's safe to do so. +template +class ThreadSafeIntrusiveHashMapReadCached +{ +public: + ~ThreadSafeIntrusiveHashMapReadCached() + { + clear(); + } + + T *find(Hash hash) const + { + T *t = read_only.find(hash); + if (t) + return t; + + lock.lock_read(); + t = read_write.find(hash); + lock.unlock_read(); + return t; + } + + void move_to_read_only() + { + auto &list = read_write.inner_list(); + auto itr = list.begin(); + while (itr != list.end()) + { + auto *to_move = itr.get(); + read_write.erase(to_move); + T *to_delete = read_only.insert_yield(to_move); + if (to_delete) + object_pool.free(to_delete); + itr = list.begin(); + } + } + + template + bool find_and_consume_pod(Hash hash, P &p) const + { + if (read_only.find_and_consume_pod(hash, p)) + return true; + + lock.lock_read(); + bool ret = read_write.find_and_consume_pod(hash, p); + lock.unlock_read(); + return ret; + } + + void clear() + { + lock.lock_write(); + clear_list(read_only.inner_list()); + clear_list(read_write.inner_list()); + read_only.clear(); + read_write.clear(); + lock.unlock_write(); + } + + template + T *allocate(P&&... p) + { + lock.lock_write(); + T *t = object_pool.allocate(std::forward

(p)...); + lock.unlock_write(); + return t; + } + + void free(T *ptr) + { + lock.lock_write(); + object_pool.free(ptr); + lock.unlock_write(); + } + + T *insert_yield(Hash hash, T *value) + { + static_cast *>(value)->set_hash(hash); + lock.lock_write(); + T *to_delete = read_write.insert_yield(value); + if (to_delete) + object_pool.free(to_delete); + lock.unlock_write(); + return value; + } + + template + T *emplace_yield(Hash hash, P&&... p) + { + T *t = allocate(std::forward

(p)...); + return insert_yield(hash, t); + } + + IntrusiveHashMapHolder &get_read_only() + { + return read_only; + } + + const IntrusiveHashMapHolder &get_read_only() const + { + return read_only; + } + + IntrusiveHashMapHolder &get_read_write() + { + return read_write; + } + +private: + IntrusiveHashMapHolder read_only; + IntrusiveHashMapHolder read_write; + ObjectPool object_pool; + mutable RWSpinLock lock; + + void clear_list(IntrusiveList &list) + { + auto itr = list.begin(); + while (itr != list.end()) + { + auto *to_free = itr.get(); + itr = list.erase(itr); + object_pool.free(to_free); + } + } +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/intrusive_list.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/intrusive_list.hpp new file mode 100644 index 00000000..241f0ba0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/intrusive_list.hpp @@ -0,0 +1,197 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +namespace Util +{ +template +struct IntrusiveListEnabled +{ + IntrusiveListEnabled *prev = nullptr; + IntrusiveListEnabled *next = nullptr; +}; + +template +class IntrusiveList +{ +public: + void clear() + { + head = nullptr; + tail = nullptr; + } + + class Iterator + { + public: + friend class IntrusiveList; + Iterator(IntrusiveListEnabled *node_) + : node(node_) + { + } + + Iterator() = default; + + explicit operator bool() const + { + return node != nullptr; + } + + bool operator==(const Iterator &other) const + { + return node == other.node; + } + + bool operator!=(const Iterator &other) const + { + return node != other.node; + } + + T &operator*() + { + return *static_cast(node); + } + + const T &operator*() const + { + return *static_cast(node); + } + + T *get() + { + return static_cast(node); + } + + const T *get() const + { + return static_cast(node); + } + + T *operator->() + { + return static_cast(node); + } + + const T *operator->() const + { + return static_cast(node); + } + + Iterator &operator++() + { + node = node->next; + return *this; + } + + Iterator &operator--() + { + node = node->prev; + return *this; + } + + private: + IntrusiveListEnabled *node = nullptr; + }; + + Iterator begin() const + { + return Iterator(head); + } + + Iterator rbegin() const + { + return Iterator(tail); + } + + Iterator end() const + { + return Iterator(); + } + + Iterator erase(Iterator itr) + { + auto *node = itr.get(); + auto *next = node->next; + auto *prev = node->prev; + + if (prev) + prev->next = next; + else + head = next; + + if (next) + next->prev = prev; + else + tail = prev; + + return next; + } + + void insert_front(Iterator itr) + { + auto *node = itr.get(); + if (head) + head->prev = node; + else + tail = node; + + node->next = head; + node->prev = nullptr; + head = node; + } + + void insert_back(Iterator itr) + { + auto *node = itr.get(); + if (tail) + tail->next = node; + else + head = node; + + node->prev = tail; + node->next = nullptr; + tail = node; + } + + void move_to_front(IntrusiveList &other, Iterator itr) + { + other.erase(itr); + insert_front(itr); + } + + void move_to_back(IntrusiveList &other, Iterator itr) + { + other.erase(itr); + insert_back(itr); + } + + bool empty() const + { + return head == nullptr; + } + +private: + IntrusiveListEnabled *head = nullptr; + IntrusiveListEnabled *tail = nullptr; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/logging.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/logging.cpp new file mode 100644 index 00000000..ce9ba374 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/logging.cpp @@ -0,0 +1,72 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "logging.hpp" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +namespace Util +{ +static thread_local LoggingInterface *logging_iface; + +bool interface_log(const char *tag, const char *fmt, ...) +{ + if (!logging_iface) + return false; + + va_list va; + va_start(va, fmt); + bool ret = logging_iface->log(tag, fmt, va); + va_end(va); + return ret; +} + +void set_thread_logging_interface(LoggingInterface *iface) +{ + logging_iface = iface; +} + +#ifdef _WIN32 +void debug_output_log(const char *tag, const char *fmt, ...) +{ + if (!IsDebuggerPresent()) + return; + + va_list va; + va_start(va, fmt); + auto len = vsnprintf(nullptr, 0, fmt, va); + if (len > 0) + { + size_t tag_len = strlen(tag); + char *buf = new char[len + tag_len + 1]; + memcpy(buf, tag, tag_len); + vsnprintf(buf + tag_len, len + 1, fmt, va); + OutputDebugStringA(buf); + delete[] buf; + } + va_end(va); +} +#endif +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/logging.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/logging.hpp new file mode 100644 index 00000000..6e26d7fb --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/logging.hpp @@ -0,0 +1,162 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include + +namespace Util +{ +class LoggingInterface +{ +public: + virtual ~LoggingInterface() = default; + virtual bool log(const char *tag, const char *fmt, va_list va) = 0; +}; + +bool interface_log(const char *tag, const char *fmt, ...); +void set_thread_logging_interface(LoggingInterface *iface); +} + +#if defined(_WIN32) +namespace Util +{ +void debug_output_log(const char *tag, const char *fmt, ...); +} + +#define LOGE_FALLBACK(...) do { \ + fprintf(stderr, "[ERROR]: " __VA_ARGS__); \ + fflush(stderr); \ + ::Util::debug_output_log("[ERROR]: ", __VA_ARGS__); \ +} while(false) + +#define LOGW_FALLBACK(...) do { \ + fprintf(stderr, "[WARN]: " __VA_ARGS__); \ + fflush(stderr); \ + ::Util::debug_output_log("[WARN]: ", __VA_ARGS__); \ +} while(false) + +#define LOGI_FALLBACK(...) do { \ + fprintf(stderr, "[INFO]: " __VA_ARGS__); \ + fflush(stderr); \ + ::Util::debug_output_log("[INFO]: ", __VA_ARGS__); \ +} while(false) +#elif defined(ANDROID) +#include +#define LOGE_FALLBACK(...) do { __android_log_print(ANDROID_LOG_ERROR, "Granite", __VA_ARGS__); } while(0) +#define LOGW_FALLBACK(...) do { __android_log_print(ANDROID_LOG_WARN, "Granite", __VA_ARGS__); } while(0) +#define LOGI_FALLBACK(...) do { __android_log_print(ANDROID_LOG_INFO, "Granite", __VA_ARGS__); } while(0) +#else +#define LOGE_FALLBACK(...) \ + do \ + { \ + fprintf(stderr, "[ERROR]: " __VA_ARGS__); \ + fflush(stderr); \ + } while (false) + +#define LOGW_FALLBACK(...) \ + do \ + { \ + fprintf(stderr, "[WARN]: " __VA_ARGS__); \ + fflush(stderr); \ + } while (false) + +#define LOGI_FALLBACK(...) \ + do \ + { \ + fprintf(stderr, "[INFO]: " __VA_ARGS__); \ + fflush(stderr); \ + } while (false) +#endif + +#ifndef _MSC_VER +#include + +namespace Internal +{ +// Stole idea from RenderDoc. +struct IsDebugged +{ + IsDebugged() + { + FILE *f = ::fopen("/proc/self/status", "r"); + if (!f) + return; + + while (!feof(f)) + { + constexpr int size = 512; + char line[size]; + line[size - 1] = '\0'; + if (!fgets(line, sizeof(line) - 1, f)) + break; + + int pid = 0; + if (sscanf(line, "TracerPid: %d", &pid) == 1 && pid != 0) + { + state = true; + break; + } + } + + ::fclose(f); + } + + bool state = false; +}; + +static inline bool is_debugged() +{ + static IsDebugged is_debugged; + return is_debugged.state; +} +} +#else +#define NOMINMAX +#include +#include +#endif + +static inline void debug_break() +{ +#ifdef _MSC_VER + if (IsDebuggerPresent()) + __debugbreak(); +#else +#if defined(__GNUC__) && defined(__linux__) && (defined(__i386__) || defined(__x86_64__)) + // __builtin_trap on GCC is SIGILL, not SIGTRAP. + // Stole idea from RenderDoc. + if (Internal::is_debugged()) + __asm__ volatile("int $0x03;"); +#elif defined(__clang__) + if (Internal::is_debugged()) + __builtin_debugtrap(); +#endif +#endif +} + +#define LOGE(...) do { if (!::Util::interface_log("[ERROR]: ", __VA_ARGS__)) { LOGE_FALLBACK(__VA_ARGS__); } debug_break(); } while(0) +#define LOGW(...) do { if (!::Util::interface_log("[WARN]: ", __VA_ARGS__)) { LOGW_FALLBACK(__VA_ARGS__); }} while(0) +#define LOGI(...) do { if (!::Util::interface_log("[INFO]: ", __VA_ARGS__)) { LOGI_FALLBACK(__VA_ARGS__); }} while(0) + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/lru_cache.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/lru_cache.hpp new file mode 100644 index 00000000..e7b38f61 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/lru_cache.hpp @@ -0,0 +1,163 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "object_pool.hpp" +#include "intrusive_list.hpp" +#include "intrusive_hash_map.hpp" + +namespace Util +{ +template +class LRUCache +{ +public: + void set_total_cost(uint64_t cost) + { + total_cost_limit = cost; + } + + uint64_t get_current_cost() const + { + return total_cost; + } + + T *find_and_mark_as_recent(uint64_t cookie) + { + auto *entry = hashmap.find(get_hash(cookie)); + if (entry) + { + lru.move_to_front(lru, entry->get()); + return &entry->get()->t; + } + else + return nullptr; + } + + T *allocate(uint64_t cookie, uint64_t cost) + { + Hash hash = get_hash(cookie); + auto *hash_entry = hashmap.find(hash); + if (hash_entry) + { + total_cost += cost - hash_entry->get()->cost; + hash_entry->get()->cost = cost; + lru.move_to_front(lru, hash_entry->get()); + return &hash_entry->get()->t; + } + + total_cost += cost; + + auto *entry = pool.allocate(); + entry->cost = cost; + entry->hash = hash; + + lru.insert_front(entry); + hashmap.emplace_replace(get_hash(cookie), lru.begin()); + return &entry->t; + } + + uint64_t prune() + { + uint64_t total_pruned = 0; + while (total_cost > total_cost_limit) + { + auto itr = lru.rbegin(); + total_cost -= itr->cost; + total_pruned += itr->cost; + lru.erase(itr); + hashmap.erase(itr->hash); + pool.free(itr.get()); + } + return total_pruned; + } + + bool evict(uint64_t cookie) + { + auto *entry = hashmap.find(get_hash(cookie)); + if (entry) + { + lru.move_to_back(lru, entry->get()); + return true; + } + else + return false; + } + + bool erase(uint64_t cookie) + { + auto *entry = hashmap.find(get_hash(cookie)); + if (entry) + { + hashmap.erase(entry); + lru.erase(entry->get()); + pool.free(entry->get().get()); + return true; + } + else + return false; + } + + ~LRUCache() + { + while (!lru.empty()) + { + auto itr = lru.begin(); + lru.erase(itr); + pool.free(itr.get()); + } + } + + struct CacheEntry : IntrusiveListEnabled + { + uint64_t cost; + Hash hash; + T t; + }; + + typename IntrusiveList::Iterator begin() + { + return lru.begin(); + } + + typename IntrusiveList::Iterator end() + { + return lru.end(); + } + +private: + uint64_t total_cost = 0; + uint64_t total_cost_limit = 0; + + ObjectPool pool; + IntrusiveList lru; + IntrusiveHashMap::Iterator>> hashmap; + + static Hash get_hash(uint64_t cookie) + { + Hasher h; + h.u64(cookie); + return h.get(); + } +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/message_queue.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/message_queue.cpp new file mode 100644 index 00000000..57a04ed0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/message_queue.cpp @@ -0,0 +1,182 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "message_queue.hpp" +#include "aligned_alloc.hpp" +#include "logging.hpp" +#include +#include + +namespace Util +{ +void MessageQueuePayloadDeleter::operator()(void *ptr) +{ + memalign_free(ptr); +} + +LockFreeMessageQueue::LockFreeMessageQueue() +{ + for (unsigned i = 0; i < 8; i++) + payload_capacity[i] = 256u << i; + for (unsigned i = 0; i < 8; i++) + write_ring[i].reset((16u * 1024u) >> i); + read_ring.reset(32 * 1024); + + // Pre-fill the rings. + for (unsigned i = 0; i < 8; i++) + { + unsigned count = 512u >> i; + for (unsigned j = 0; j < count; j++) + { + MessageQueuePayload payload; + payload.set_payload_data(memalign_calloc(64, payload_capacity[i]), payload_capacity[i]); + recycle_payload(std::move(payload)); + } + } +} + +size_t LockFreeMessageQueue::available_read_messages() const noexcept +{ + return read_ring.read_avail(); +} + +MessageQueuePayload LockFreeMessageQueue::read_message() noexcept +{ + MessageQueuePayload payload; + read_ring.read_and_move(payload); + return payload; +} + +bool LockFreeMessageQueue::push_written_payload(MessageQueuePayload payload) noexcept +{ + return read_ring.write_and_move(std::move(payload)); +} + +void LockFreeMessageQueue::recycle_payload(MessageQueuePayload payload) noexcept +{ + for (unsigned i = 0; i < 8; i++) + { + if (payload.get_capacity() == payload_capacity[i]) + { + write_ring[i].write_and_move(std::move(payload)); + return; + } + } +} + +MessageQueuePayload LockFreeMessageQueue::allocate_write_payload(size_t size) noexcept +{ + MessageQueuePayload payload; + for (unsigned i = 0; i < 8; i++) + { + if (size <= payload_capacity[i]) + { + if (!write_ring[i].read_and_move(payload)) + payload.set_payload_data(memalign_calloc(64, payload_capacity[i]), payload_capacity[i]); + return payload; + } + } + + payload.set_payload_data(memalign_calloc(64, size), size); + return payload; +} + +MessageQueue::MessageQueue() +{ + corked.store(true); +} + +void MessageQueue::cork() +{ + corked.store(true, std::memory_order_relaxed); +} + +void MessageQueue::uncork() +{ + corked.store(false, std::memory_order_relaxed); +} + +bool MessageQueue::is_uncorked() const +{ + return !corked.load(std::memory_order_relaxed); +} + +MessageQueuePayload MessageQueue::allocate_write_payload(size_t size) noexcept +{ + if (corked.load(std::memory_order_relaxed)) + return {}; + std::lock_guard holder{lock}; + return LockFreeMessageQueue::allocate_write_payload(size); +} + +bool MessageQueue::push_written_payload(MessageQueuePayload payload) noexcept +{ + std::lock_guard holder{lock}; + return LockFreeMessageQueue::push_written_payload(std::move(payload)); +} + +size_t MessageQueue::available_read_messages() const noexcept +{ + std::lock_guard holder{lock}; + return LockFreeMessageQueue::available_read_messages(); +} + +MessageQueuePayload MessageQueue::read_message() noexcept +{ + std::lock_guard holder{lock}; + return LockFreeMessageQueue::read_message(); +} + +void MessageQueue::recycle_payload(MessageQueuePayload payload) noexcept +{ + std::lock_guard holder{lock}; + return LockFreeMessageQueue::recycle_payload(std::move(payload)); +} + +bool MessageQueue::log(const char *tag, const char *fmt, va_list va) +{ + if (!is_uncorked()) + return false; + char message_buffer[16 * 1024]; + memcpy(message_buffer, tag, strlen(tag)); + + vsnprintf(message_buffer + strlen(tag), sizeof(message_buffer) - strlen(tag), fmt, va); + va_end(va); + + size_t message_size = strlen(message_buffer) + 1; + + while (message_size >= 2 && message_buffer[message_size - 2] == '\n') + { + message_buffer[message_size - 2] = '\0'; + message_size--; + } + + auto message_payload = allocate_write_payload(message_size); + if (message_payload) + { + memcpy(static_cast(message_payload.get_payload_data()), message_buffer, message_size); + push_written_payload(std::move(message_payload)); + } + + return true; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/message_queue.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/message_queue.hpp new file mode 100644 index 00000000..c16eeab7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/message_queue.hpp @@ -0,0 +1,241 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include "global_managers_interface.hpp" +#include "logging.hpp" + +namespace Util +{ +// There can only be one concurrent reader, and one concurrent writer. +// This is useful for lock-less messaging between two threads, e.g. a worker thread and master thread. +template +class LockFreeRingBuffer +{ +public: + LockFreeRingBuffer() + { + reset(1); + assert(read_count.is_lock_free()); + assert(write_count.is_lock_free()); + } + + void reset(size_t count) + { + //assert((count & (count - 1)) == 0); + ring.resize(count); + read_count.store(0); + write_count.store(0); + } + + size_t read_avail() const noexcept + { + return write_count.load(std::memory_order_acquire) - + read_count.load(std::memory_order_relaxed); + } + + size_t write_avail() const noexcept + { + return ring.size() - + (write_count.load(std::memory_order_relaxed) - + read_count.load(std::memory_order_acquire)); + } + + bool write_and_move(T *values, size_t count) noexcept + { + size_t current_written = read_count.load(std::memory_order_relaxed); + size_t current_read = write_count.load(std::memory_order_acquire); + if (count > ring.size() - (current_written - current_read)) + return false; + + size_t can_write_first = std::min(ring.size() - write_offset, count); + size_t can_write_second = count - can_write_first; + std::move(values, values + can_write_first, ring.data() + write_offset); + + write_offset += can_write_first; + values += can_write_first; + if (write_offset >= ring.size()) + write_offset -= ring.size(); + + std::move(values, values + can_write_second, ring.data()); + write_offset += can_write_second; + + // Need release ordering so the reads here can't be ordered after the store. + write_count.store(write_count.load(std::memory_order_relaxed) + count, std::memory_order_release); + return true; + } + + bool read_and_move(T *values, size_t count) noexcept + { + size_t current_read = read_count.load(std::memory_order_relaxed); + size_t current_written = write_count.load(std::memory_order_acquire); + if (count > current_written - current_read) + return false; + + size_t can_read_first = std::min(ring.size() - read_offset, count); + size_t can_read_second = count - can_read_first; + std::move(ring.data() + read_offset, ring.data() + read_offset + can_read_first, values); + + read_offset += can_read_first; + values += can_read_first; + if (read_offset >= ring.size()) + read_offset -= ring.size(); + + std::move(ring.data(), ring.data() + can_read_second, values); + read_offset += can_read_second; + + // Need release ordering so the reads here can't be ordered after the store. + read_count.store(read_count.load(std::memory_order_relaxed) + count, std::memory_order_release); + return true; + } + + bool write_and_move(T value) noexcept + { + return write_and_move(&value, 1); + } + + bool read_and_move(T &value) noexcept + { + return read_and_move(&value, 1); + } + +private: + std::atomic_size_t read_count; + std::atomic_size_t write_count; + size_t read_offset = 0; + size_t write_offset = 0; + std::vector ring; +}; + +struct MessageQueuePayloadDeleter +{ + void operator()(void *ptr); +}; + +class MessageQueuePayload +{ +public: + template + T &as() + { + assert(handle); + return *static_cast(handle); + } + + // The handle might be slightly different from payload if we allocated + // with multiple-inheritance and the base class we care about is not the first one in the inheritance list. + template + void set_payload_handle(T *t) + { + handle = t; + } + + explicit operator bool() const + { + return bool(payload); + } + + size_t get_size() const + { + return payload_size; + } + + void set_size(size_t size) + { + assert(size <= payload_capacity); + payload_size = size; + } + + void set_payload_data(void *ptr, size_t size) + { + payload.reset(ptr); + payload_capacity = size; + } + + void *get_payload_data() const + { + return payload.get(); + } + + size_t get_capacity() const + { + return payload_capacity; + } + +private: + std::unique_ptr payload; + void *handle = nullptr; + size_t payload_size = 0; + size_t payload_capacity = 0; +}; + +class LockFreeMessageQueue +{ +public: + LockFreeMessageQueue(); + + MessageQueuePayload allocate_write_payload(size_t size) noexcept; + bool push_written_payload(MessageQueuePayload payload) noexcept; + + size_t available_read_messages() const noexcept; + MessageQueuePayload read_message() noexcept; + void recycle_payload(MessageQueuePayload payload) noexcept; + +private: + LockFreeRingBuffer read_ring; + LockFreeRingBuffer write_ring[8]; + size_t payload_capacity[8] = {}; +}; + +class MessageQueue final : private LockFreeMessageQueue, public MessageQueueInterface +{ +public: + MessageQueue(); + void cork(); + void uncork(); + + bool is_uncorked() const; + + MessageQueuePayload allocate_write_payload(size_t size) noexcept; + bool push_written_payload(MessageQueuePayload payload) noexcept; + + size_t available_read_messages() const noexcept; + MessageQueuePayload read_message() noexcept; + void recycle_payload(MessageQueuePayload payload) noexcept; + +private: + mutable std::mutex lock; + mutable std::condition_variable cond; + std::atomic_bool corked; + + bool log(const char *tag, const char *fmt, va_list va) override; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/no_init_pod.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/no_init_pod.hpp new file mode 100644 index 00000000..54d3f3d8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/no_init_pod.hpp @@ -0,0 +1,42 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Util +{ +template +struct NoInitPOD +{ + T value; + + NoInitPOD() + { + static_assert(sizeof(NoInitPOD) == sizeof(T), "Sizes do not match."); + static_assert(alignof(NoInitPOD) == alignof(T), "Alignments do not match."); + } + + static_assert(std::is_pod::value, "Type is not POD."); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/object_pool.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/object_pool.hpp new file mode 100644 index 00000000..12ee8451 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/object_pool.hpp @@ -0,0 +1,132 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "aligned_alloc.hpp" + +//#define OBJECT_POOL_DEBUG + +namespace Util +{ +template +class ObjectPool +{ +public: + template + T *allocate(P &&... p) + { +#ifndef OBJECT_POOL_DEBUG + if (vacants.empty()) + { + unsigned num_objects = 64u << memory.size(); + T *ptr = static_cast(memalign_alloc(std::max(64, alignof(T)), + num_objects * sizeof(T))); + if (!ptr) + return nullptr; + + for (unsigned i = 0; i < num_objects; i++) + vacants.push_back(&ptr[i]); + + memory.emplace_back(ptr); + } + + T *ptr = vacants.back(); + vacants.pop_back(); + new(ptr) T(std::forward

(p)...); + return ptr; +#else + return new T(std::forward

(p)...); +#endif + } + + void free(T *ptr) + { +#ifndef OBJECT_POOL_DEBUG + ptr->~T(); + vacants.push_back(ptr); +#else + delete ptr; +#endif + } + + void clear() + { +#ifndef OBJECT_POOL_DEBUG + vacants.clear(); + memory.clear(); +#endif + } + +protected: +#ifndef OBJECT_POOL_DEBUG + std::vector vacants; + + struct MallocDeleter + { + void operator()(T *ptr) + { + memalign_free(ptr); + } + }; + + std::vector> memory; +#endif +}; + +template +class ThreadSafeObjectPool : private ObjectPool +{ +public: + template + T *allocate(P &&... p) + { + std::lock_guard holder{lock}; + return ObjectPool::allocate(std::forward

(p)...); + } + + void free(T *ptr) + { +#ifndef OBJECT_POOL_DEBUG + ptr->~T(); + std::lock_guard holder{lock}; + this->vacants.push_back(ptr); +#else + delete ptr; +#endif + } + + void clear() + { + std::lock_guard holder{lock}; + ObjectPool::clear(); + } + +private: + std::mutex lock; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/radix_sorter.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/radix_sorter.hpp new file mode 100644 index 00000000..35670573 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/radix_sorter.hpp @@ -0,0 +1,149 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include "dynamic_array.hpp" +#include + +namespace Util +{ +template +static inline void radix_sort_pass(ValueT * __restrict outputs, const ValueT * __restrict inputs, + IndexT * __restrict output_indices, + const IndexT * __restrict input_indices, + IndexT * __restrict scratch_indices, + size_t count) +{ + constexpr int num_values = 1 << bits; + IndexT per_value_counts[num_values] = {}; + for (size_t i = 0; i < count; i++) + { + ValueT c = (inputs[i] >> offset) & ((ValueT(1) << bits) - ValueT(1)); + scratch_indices[i] = per_value_counts[c]++; + } + + IndexT per_value_counts_prefix[num_values]; + IndexT prefix_sum = 0; + for (int i = 0; i < num_values; i++) + { + per_value_counts_prefix[i] = prefix_sum; + prefix_sum += per_value_counts[i]; + } + + for (size_t i = 0; i < count; i++) + { + ValueT inp = inputs[i]; + ValueT c = (inp >> offset) & ((ValueT(1) << bits) - ValueT(1)); + IndexT effective_index = scratch_indices[i] + per_value_counts_prefix[c]; + IndexT input_index = input_indices ? input_indices[i] : i; + + output_indices[effective_index] = input_index; + outputs[effective_index] = inp; + } +} + +template +class RadixSorter +{ +public: + static_assert(sizeof...(pattern) % 2 == 0, "Need even number of radix passes."); + static_assert(sizeof...(pattern) > 0, "Need at least one radix pass."); + + void resize(size_t count) + { + codes.reserve(count * 2); + indices.reserve(count * 3); + N = count; + } + + void sort() + { + sort_inner_first(); + } + + size_t size() const + { + return N; + } + + CodeT *code_data() + { + return codes.data(); + } + + const CodeT *code_data() const + { + return codes.data(); + } + + const uint32_t *indices_data() const + { + return indices.data(); + } + +private: + DynamicArray codes; + DynamicArray indices; + size_t N = 0; + + template + void sort_inner(CodeT *, CodeT *, uint32_t *, uint32_t *, uint32_t *) + { + } + + template + void sort_inner(CodeT *output_values, CodeT *input_values, + uint32_t *output_indices, uint32_t *input_indices, + uint32_t *scratch_indices) + { + radix_sort_pass(output_values, input_values, + output_indices, input_indices, + scratch_indices, N); + + sort_inner(input_values, output_values, + input_indices, output_indices, + scratch_indices); + } + + template + void sort_inner_first() + { + auto *output_values = codes.data(); + auto *input_values = codes.data() + N; + + auto *output_indices = indices.data(); + auto *input_indices = indices.data() + 1 * N; + auto *scratch_indices = indices.data() + 2 * N; + + radix_sort_pass<0, count>(input_values, output_values, + input_indices, static_cast(nullptr), + scratch_indices, N); + + sort_inner(output_values, input_values, + output_indices, input_indices, + scratch_indices); + } +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/read_write_lock.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/read_write_lock.hpp new file mode 100644 index 00000000..b9efcc09 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/read_write_lock.hpp @@ -0,0 +1,149 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +#ifdef __SSE2__ +#include +#endif + +namespace Util +{ +class RWSpinLock +{ +public: + enum { Reader = 2, Writer = 1 }; + RWSpinLock() + { + counter.store(0); + } + + inline void lock_read() + { + unsigned v = counter.fetch_add(Reader, std::memory_order_acquire); + while ((v & Writer) != 0) + { +#ifdef __SSE2__ + _mm_pause(); +#endif + v = counter.load(std::memory_order_acquire); + } + } + + inline bool try_lock_read() + { + unsigned v = counter.fetch_add(Reader, std::memory_order_acquire); + if ((v & Writer) != 0) + { + unlock_read(); + return false; + } + + return true; + } + + inline void unlock_read() + { + counter.fetch_sub(Reader, std::memory_order_release); + } + + inline void lock_write() + { + uint32_t expected = 0; + while (!counter.compare_exchange_weak(expected, Writer, + std::memory_order_acquire, + std::memory_order_relaxed)) + { +#ifdef __SSE2__ + _mm_pause(); +#endif + expected = 0; + } + } + + inline bool try_lock_write() + { + uint32_t expected = 0; + return counter.compare_exchange_strong(expected, Writer, + std::memory_order_acquire, + std::memory_order_relaxed); + } + + inline void unlock_write() + { + counter.fetch_and(~Writer, std::memory_order_release); + } + + inline void promote_reader_to_writer() + { + uint32_t expected = Reader; + if (!counter.compare_exchange_strong(expected, Writer, + std::memory_order_acquire, + std::memory_order_relaxed)) + { + unlock_read(); + lock_write(); + } + } + +private: + std::atomic_uint32_t counter; +}; + +class RWSpinLockReadHolder +{ +public: + explicit RWSpinLockReadHolder(RWSpinLock &lock_) + : lock(lock_) + { + lock.lock_read(); + } + + ~RWSpinLockReadHolder() + { + lock.unlock_read(); + } + +private: + RWSpinLock &lock; +}; + +class RWSpinLockWriteHolder +{ +public: + explicit RWSpinLockWriteHolder(RWSpinLock &lock_) + : lock(lock_) + { + lock.lock_write(); + } + + ~RWSpinLockWriteHolder() + { + lock.unlock_write(); + } + +private: + RWSpinLock &lock; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/slab_allocator.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/slab_allocator.cpp new file mode 100644 index 00000000..ddd6e997 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/slab_allocator.cpp @@ -0,0 +1,58 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "slab_allocator.hpp" + +namespace Util +{ +SlabAllocator::SlabAllocator(size_t object_size_) + : object_size(object_size_) +{ +} + +uint8_t *SlabAllocator::allocate() +{ + if (vacants.empty()) + { + size_t count = size_t(64) << memory.size(); + memory.emplace_back(static_cast(memalign_alloc(64, count * object_size))); + auto *ptr = memory.back().get(); + vacants.reserve(vacants.size() + count); + for (size_t i = 0; i < count; i++, ptr += object_size) + vacants.push_back(ptr); + } + + auto *v = vacants.back(); + vacants.pop_back(); + return v; +} + +void SlabAllocator::free(uint8_t *ptr) +{ + vacants.push_back(ptr); +} + +void ThreadSafeSlabAllocator::init(size_t object_size) +{ + slab = SlabAllocator(object_size); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/slab_allocator.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/slab_allocator.hpp new file mode 100644 index 00000000..932bc498 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/slab_allocator.hpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include +#include +#include +#include +#include +#include "aligned_alloc.hpp" + +namespace Util +{ +class SlabAllocator +{ +public: + SlabAllocator() = default; + explicit SlabAllocator(size_t object_size); + uint8_t *allocate(); + void free(uint8_t *ptr); + +private: + struct MallocDeleter + { + void operator()(uint8_t *ptr) + { + memalign_free(ptr); + } + }; + + std::vector vacants; + std::vector> memory; + size_t object_size = 0; +}; + +class ThreadSafeSlabAllocator +{ +public: + ThreadSafeSlabAllocator() = default; + void init(size_t object_size); + + inline uint8_t *allocate() { std::lock_guard holder{lock}; return slab.allocate(); } + inline void free(uint8_t *ptr) { std::lock_guard holder{lock}; slab.free(ptr); } + +private: + SlabAllocator slab; + std::mutex lock; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/small_callable.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/small_callable.hpp new file mode 100644 index 00000000..7785c577 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/small_callable.hpp @@ -0,0 +1,141 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include + +namespace Util +{ +template +class SmallCallable; + +template +class SmallCallable +{ +public: + inline R call(Params... params) + { + return get_invokable().call(std::forward(params)...); + } + + inline explicit operator bool() const + { + return get_invokable().active(); + } + + ~SmallCallable() + { + get_invokable().~Invokable(); + } + + template + inline explicit SmallCallable(Func&& fn) + { + using PlainFunc = std::remove_cv_t>; + // Avoid mistaken double-wrap. + static_assert(!std::is_same, PlainFunc>::value, "std::function not supported."); + static_assert(sizeof(CapturedInvokable) <= sizeof(payload), "Callback payload is too large."); + new(payload) CapturedInvokable(std::forward(fn)); + } + + inline explicit SmallCallable(R (*fn)(Params...)) + { + static_assert(sizeof(CapturedPlain) <= sizeof(payload), "Callback payload is too large."); + new(payload) CapturedPlain(fn); + } + + template + inline SmallCallable(T *ptr, R (T::*memb)(Params...)) + { + using MemberFunc = CapturedMemberFunc; + static_assert(sizeof(MemberFunc) <= sizeof(payload), "Callback payload is too large."); + new(payload) MemberFunc(ptr, memb); + } + + inline SmallCallable() + { + new(payload) NullInvoker(); + } + + SmallCallable(const SmallCallable &) = delete; + SmallCallable(SmallCallable &&) = delete; + void operator=(const SmallCallable &) = delete; + void operator=(SmallCallable &&) = delete; + +private: + struct Invokable + { + virtual ~Invokable() = default; + virtual R call(Params...) = 0; + virtual bool active() const = 0; + }; + + template + struct CapturedInvokable final : Invokable + { + explicit CapturedInvokable(I&& holder_) : holder(std::move(holder_)) {} + R call(Params... params) override { return holder(std::forward(params)...); }; + bool active() const override { return true; } + I holder; + }; + + struct NullInvoker final : Invokable + { + R call(Params...) override { return R(); } + bool active() const override { return false; } + }; + + struct CapturedPlain final : Invokable + { + explicit CapturedPlain(R (*func_)(Params...)) : func(func_) {} + R call(Params... params) override { return func(std::forward(params)...); } + bool active() const override { return func != nullptr; } + R (*func)(Params...); + }; + + template + struct CapturedMemberFunc final : Invokable + { + explicit CapturedMemberFunc(T *ptr_, R (T::*func_)(Params...)) : ptr(ptr_), func(func_) {} + R call(Params... params) override { return (ptr->*func)(std::forward(params)...); } + bool active() const override { return ptr != nullptr && func != nullptr; } + T *ptr; + R (T::*func)(Params...); + }; + + Invokable &get_invokable() + { + return *reinterpret_cast(&payload[0]); + } + + const Invokable &get_invokable() const + { + return *reinterpret_cast(&payload[0]); + } + + alignas(Align) char payload[PayloadSize]; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/small_vector.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/small_vector.hpp new file mode 100644 index 00000000..28ac913b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/small_vector.hpp @@ -0,0 +1,456 @@ +/* Copyright (c) 2019-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Util +{ +// std::aligned_storage does not support size == 0, so roll our own. +template +class AlignedBuffer +{ +public: + T *data() + { + return reinterpret_cast(aligned_char); + } + +private: + alignas(T) char aligned_char[sizeof(T) * N]; +}; + +template +class AlignedBuffer +{ +public: + T *data() + { + return nullptr; + } +}; + +// An immutable version of SmallVector which erases type information about storage. +template +class VectorView +{ +public: + T &operator[](size_t i) + { + return ptr[i]; + } + + const T &operator[](size_t i) const + { + return ptr[i]; + } + + bool empty() const + { + return buffer_size == 0; + } + + size_t size() const + { + return buffer_size; + } + + T *data() + { + return ptr; + } + + const T *data() const + { + return ptr; + } + + T *begin() + { + return ptr; + } + + T *end() + { + return ptr + buffer_size; + } + + const T *begin() const + { + return ptr; + } + + const T *end() const + { + return ptr + buffer_size; + } + + T &front() + { + return ptr[0]; + } + + const T &front() const + { + return ptr[0]; + } + + T &back() + { + return ptr[buffer_size - 1]; + } + + const T &back() const + { + return ptr[buffer_size - 1]; + } + + // Avoid sliced copies. Base class should only be read as a reference. + VectorView(const VectorView &) = delete; + void operator=(const VectorView &) = delete; + +protected: + VectorView() = default; + T *ptr = nullptr; + size_t buffer_size = 0; +}; + +// Simple vector which supports up to N elements inline, without malloc/free. +// We use a lot of throwaway vectors all over the place which triggers allocations. +// This class only implements the subset of std::vector we need in SPIRV-Cross. +// It is *NOT* a drop-in replacement in general projects. +template +class SmallVector : public VectorView +{ +public: + SmallVector() + { + this->ptr = stack_storage.data(); + buffer_capacity = N; + } + + SmallVector(const T *arg_list_begin, const T *arg_list_end) + : SmallVector() + { + auto count = size_t(arg_list_end - arg_list_begin); + reserve(count); + for (size_t i = 0; i < count; i++, arg_list_begin++) + new (&this->ptr[i]) T(*arg_list_begin); + this->buffer_size = count; + } + + SmallVector(SmallVector &&other) noexcept : SmallVector() + { + *this = std::move(other); + } + + SmallVector(const std::initializer_list &init_list) : SmallVector() + { + insert(this->end(), init_list.begin(), init_list.end()); + } + + SmallVector &operator=(SmallVector &&other) noexcept + { + clear(); + if (other.ptr != other.stack_storage.data()) + { + // Pilfer allocated pointer. + if (this->ptr != stack_storage.data()) + free(this->ptr); + this->ptr = other.ptr; + this->buffer_size = other.buffer_size; + buffer_capacity = other.buffer_capacity; + other.ptr = nullptr; + other.buffer_size = 0; + other.buffer_capacity = 0; + } + else + { + // Need to move the stack contents individually. + reserve(other.buffer_size); + for (size_t i = 0; i < other.buffer_size; i++) + { + new (&this->ptr[i]) T(std::move(other.ptr[i])); + other.ptr[i].~T(); + } + this->buffer_size = other.buffer_size; + other.buffer_size = 0; + } + return *this; + } + + SmallVector(const SmallVector &other) + : SmallVector() + { + *this = other; + } + + SmallVector &operator=(const SmallVector &other) + { + clear(); + reserve(other.buffer_size); + for (size_t i = 0; i < other.buffer_size; i++) + new (&this->ptr[i]) T(other.ptr[i]); + this->buffer_size = other.buffer_size; + return *this; + } + + explicit SmallVector(size_t count) + : SmallVector() + { + resize(count); + } + + ~SmallVector() + { + clear(); + if (this->ptr != stack_storage.data()) + free(this->ptr); + } + + void clear() + { + for (size_t i = 0; i < this->buffer_size; i++) + this->ptr[i].~T(); + this->buffer_size = 0; + } + + void push_back(const T &t) + { + reserve(this->buffer_size + 1); + new (&this->ptr[this->buffer_size]) T(t); + this->buffer_size++; + } + + void push_back(T &&t) + { + reserve(this->buffer_size + 1); + new (&this->ptr[this->buffer_size]) T(std::move(t)); + this->buffer_size++; + } + + void pop_back() + { + // Work around false positive warning on GCC 8.3. + // Calling pop_back on empty vector is undefined. + if (!this->empty()) + resize(this->buffer_size - 1); + } + + template + void emplace_back(Ts &&... ts) + { + reserve(this->buffer_size + 1); + new (&this->ptr[this->buffer_size]) T(std::forward(ts)...); + this->buffer_size++; + } + + void reserve(size_t count) + { + if (count > buffer_capacity) + { + size_t target_capacity = buffer_capacity; + if (target_capacity == 0) + target_capacity = 1; + if (target_capacity < N) + target_capacity = N; + + while (target_capacity < count) + target_capacity <<= 1u; + + T *new_buffer = + target_capacity > N ? static_cast(malloc(target_capacity * sizeof(T))) : stack_storage.data(); + + if (!new_buffer) + std::terminate(); + + // In case for some reason two allocations both come from same stack. + if (new_buffer != this->ptr) + { + // We don't deal with types which can throw in move constructor. + for (size_t i = 0; i < this->buffer_size; i++) + { + new (&new_buffer[i]) T(std::move(this->ptr[i])); + this->ptr[i].~T(); + } + } + + if (this->ptr != stack_storage.data()) + free(this->ptr); + this->ptr = new_buffer; + buffer_capacity = target_capacity; + } + } + + void insert(T *itr, const T *insert_begin, const T *insert_end) + { + auto count = size_t(insert_end - insert_begin); + if (itr == this->end()) + { + reserve(this->buffer_size + count); + for (size_t i = 0; i < count; i++, insert_begin++) + new (&this->ptr[this->buffer_size + i]) T(*insert_begin); + this->buffer_size += count; + } + else + { + if (this->buffer_size + count > buffer_capacity) + { + auto target_capacity = this->buffer_size + count; + if (target_capacity == 0) + target_capacity = 1; + if (target_capacity < N) + target_capacity = N; + + while (target_capacity < count) + target_capacity <<= 1u; + + // Need to allocate new buffer. Move everything to a new buffer. + T *new_buffer = + target_capacity > N ? static_cast(malloc(target_capacity * sizeof(T))) : stack_storage.data(); + if (!new_buffer) + std::terminate(); + + // First, move elements from source buffer to new buffer. + // We don't deal with types which can throw in move constructor. + auto *target_itr = new_buffer; + auto *original_source_itr = this->begin(); + + if (new_buffer != this->ptr) + { + while (original_source_itr != itr) + { + new (target_itr) T(std::move(*original_source_itr)); + original_source_itr->~T(); + ++original_source_itr; + ++target_itr; + } + } + + // Copy-construct new elements. + for (auto *source_itr = insert_begin; source_itr != insert_end; ++source_itr, ++target_itr) + new (target_itr) T(*source_itr); + + // Move over the other half. + if (new_buffer != this->ptr || insert_begin != insert_end) + { + while (original_source_itr != this->end()) + { + new (target_itr) T(std::move(*original_source_itr)); + original_source_itr->~T(); + ++original_source_itr; + ++target_itr; + } + } + + if (this->ptr != stack_storage.data()) + free(this->ptr); + this->ptr = new_buffer; + buffer_capacity = target_capacity; + } + else + { + // Move in place, need to be a bit careful about which elements are constructed and which are not. + // Move the end and construct the new elements. + auto *target_itr = this->end() + count; + auto *source_itr = this->end(); + while (target_itr != this->end() && source_itr != itr) + { + --target_itr; + --source_itr; + new (target_itr) T(std::move(*source_itr)); + } + + // For already constructed elements we can move-assign. + std::move_backward(itr, source_itr, target_itr); + + // For the inserts which go to already constructed elements, we can do a plain copy. + while (itr != this->end() && insert_begin != insert_end) + *itr++ = *insert_begin++; + + // For inserts into newly allocated memory, we must copy-construct instead. + while (insert_begin != insert_end) + { + new (itr) T(*insert_begin); + ++itr; + ++insert_begin; + } + } + + this->buffer_size += count; + } + } + + void insert(T *itr, const T &value) + { + insert(itr, &value, &value + 1); + } + + T *erase(T *itr) + { + std::move(itr + 1, this->end(), itr); + this->ptr[--this->buffer_size].~T(); + return itr; + } + + void erase(T *start_erase, T *end_erase) + { + if (end_erase == this->end()) + { + resize(size_t(start_erase - this->begin())); + } + else + { + auto new_size = this->buffer_size - (end_erase - start_erase); + std::move(end_erase, this->end(), start_erase); + resize(new_size); + } + } + + void resize(size_t new_size) + { + if (new_size < this->buffer_size) + { + for (size_t i = new_size; i < this->buffer_size; i++) + this->ptr[i].~T(); + } + else if (new_size > this->buffer_size) + { + reserve(new_size); + for (size_t i = this->buffer_size; i < new_size; i++) + new (&this->ptr[i]) T(); + } + + this->buffer_size = new_size; + } + +private: + size_t buffer_capacity = 0; + AlignedBuffer stack_storage; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/stack_allocator.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/stack_allocator.hpp new file mode 100644 index 00000000..f9a0b398 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/stack_allocator.hpp @@ -0,0 +1,62 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Util +{ +template +class StackAllocator +{ +public: + T *allocate(size_t count) + { + if (count == 0) + return nullptr; + if (offset + count > N) + return nullptr; + + T *ret = buffer + offset; + offset += count; + return ret; + } + + T *allocate_cleared(size_t count) + { + T *ret = allocate(count); + if (ret) + std::fill(ret, ret + count, T()); + return ret; + } + + void reset() + { + offset = 0; + } + +private: + T buffer[N]; + size_t offset = 0; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/string_helpers.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/string_helpers.cpp new file mode 100644 index 00000000..237f52a0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/string_helpers.cpp @@ -0,0 +1,73 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "string_helpers.hpp" + +namespace Util +{ +static std::vector split(const std::string &str, const char *delim, bool allow_empty) +{ + if (str.empty()) + return {}; + std::vector ret; + + size_t start_index = 0; + size_t index = 0; + while ((index = str.find_first_of(delim, start_index)) != std::string::npos) + { + if (allow_empty || index > start_index) + ret.push_back(str.substr(start_index, index - start_index)); + start_index = index + 1; + + if (allow_empty && (index == str.size() - 1)) + ret.emplace_back(); + } + + if (start_index < str.size()) + ret.push_back(str.substr(start_index)); + return ret; +} + +std::vector split(const std::string &str, const char *delim) +{ + return split(str, delim, true); +} + +std::vector split_no_empty(const std::string &str, const char *delim) +{ + return split(str, delim, false); +} + +std::string strip_whitespace(const std::string &str) +{ + std::string ret; + auto index = str.find_first_not_of(" \t"); + if (index == std::string::npos) + return ""; + ret = str.substr(index, std::string::npos); + index = ret.find_last_not_of(" \t"); + if (index != std::string::npos) + return ret.substr(0, index + 1); + else + return ret; +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/string_helpers.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/string_helpers.hpp new file mode 100644 index 00000000..54a9271c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/string_helpers.hpp @@ -0,0 +1,59 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include + +namespace inner +{ +template +void join_helper(std::ostringstream &stream, T &&t) +{ + stream << std::forward(t); +} + +template +void join_helper(std::ostringstream &stream, T &&t, Ts &&... ts) +{ + stream << std::forward(t); + join_helper(stream, std::forward(ts)...); +} +} + +namespace Util +{ +template +inline std::string join(Ts &&... ts) +{ + std::ostringstream stream; + inner::join_helper(stream, std::forward(ts)...); + return stream.str(); +} + +std::vector split(const std::string &str, const char *delim); +std::vector split_no_empty(const std::string &str, const char *delim); +std::string strip_whitespace(const std::string &str); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/temporary_hashmap.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/temporary_hashmap.hpp new file mode 100644 index 00000000..f8d9a90e --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/temporary_hashmap.hpp @@ -0,0 +1,177 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "hash.hpp" +#include "object_pool.hpp" +#include "intrusive_list.hpp" +#include "intrusive_hash_map.hpp" +#include + +namespace Util +{ +template +class TemporaryHashmapEnabled +{ +public: + void set_hash(Hash hash_) + { + hash = hash_; + } + + void set_index(unsigned index_) + { + index = index_; + } + + Hash get_hash() + { + return hash; + } + + unsigned get_index() const + { + return index; + } + +private: + Hash hash = 0; + unsigned index = 0; +}; + +template +class TemporaryHashmap +{ +public: + ~TemporaryHashmap() + { + clear(); + } + + void clear() + { + for (auto &ring : rings) + { + while (!ring.empty()) + { + auto itr = ring.begin(); + ring.erase(itr); + auto &node = *itr; + object_pool.free(static_cast(&node)); + } + } + hashmap.clear(); + + for (auto &vacant : vacants) + object_pool.free(static_cast(&*vacant)); + vacants.clear(); + object_pool.clear(); + } + + void begin_frame() + { + index = (index + 1) & (RingSize - 1); + auto &ring = rings[index]; + + while (!ring.empty()) + { + auto itr = ring.begin(); + ring.erase(itr); + auto &node = *itr; + hashmap.erase(node.get_hash()); + free_object(&node, ReuseTag()); + } + } + + T *request(Hash hash) + { + auto *v = hashmap.find(hash); + if (v) + { + auto node = v->get(); + if (node->get_index() != index) + { + rings[index].move_to_front(rings[node->get_index()], node); + node->set_index(index); + } + + return &*node; + } + else + return nullptr; + } + + template + void make_vacant(P &&... p) + { + vacants.push_back(object_pool.allocate(std::forward

(p)...)); + } + + T *request_vacant(Hash hash) + { + if (vacants.empty()) + return nullptr; + + auto top = vacants.back(); + vacants.pop_back(); + top->set_index(index); + top->set_hash(hash); + hashmap.emplace_replace(hash, top); + rings[index].insert_front(top); + return &*top; + } + + template + T *emplace(Hash hash, P &&... p) + { + auto *node = object_pool.allocate(std::forward

(p)...); + node->set_index(index); + node->set_hash(hash); + hashmap.emplace_replace(hash, node); + rings[index].insert_front(node); + return node; + } + +private: + IntrusiveList rings[RingSize]; + ObjectPool object_pool; + unsigned index = 0; + IntrusiveHashMap::Iterator>> hashmap; + std::vector::Iterator> vacants; + + template + struct ReuseTag + { + }; + + void free_object(T *object, const ReuseTag &) + { + object_pool.free(object); + } + + void free_object(T *object, const ReuseTag &) + { + vacants.push_back(object); + } +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_id.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_id.cpp new file mode 100644 index 00000000..c685fedd --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_id.cpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "thread_id.hpp" +#include "logging.hpp" + +namespace Util +{ +static thread_local unsigned thread_id_to_index = ~0u; + +unsigned get_current_thread_index() +{ + auto ret = thread_id_to_index; + if (ret == ~0u) + { + LOGE("Thread does not exist in thread manager or is not the main thread.\n"); + return 0; + } + return ret; +} + +void register_thread_index(unsigned index) +{ + thread_id_to_index = index; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_id.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_id.hpp new file mode 100644 index 00000000..45c15e34 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_id.hpp @@ -0,0 +1,29 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +namespace Util +{ +unsigned get_current_thread_index(); +void register_thread_index(unsigned thread_index); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_name.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_name.cpp new file mode 100644 index 00000000..e9681786 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_name.cpp @@ -0,0 +1,59 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "thread_name.hpp" + +#if !defined(_WIN32) +#include +#else +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + +namespace Util +{ +void set_current_thread_name(const char *name) +{ +#if defined(__linux__) + pthread_setname_np(pthread_self(), name); +#elif defined(__APPLE__) + pthread_setname_np(name); +#elif defined(_WIN32) + using PFN_SetThreadDescription = HRESULT (WINAPI *)(HANDLE, PCWSTR); + auto module = GetModuleHandleA("kernel32.dll"); + PFN_SetThreadDescription SetThreadDescription = module ? reinterpret_cast( + (void *)GetProcAddress(module, "SetThreadDescription")) : nullptr; + + if (SetThreadDescription) + { + std::wstring wname; + while (*name != '\0') + { + wname.push_back(*name); + name++; + } + SetThreadDescription(GetCurrentThread(), wname.c_str()); + } +#endif +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_name.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_name.hpp new file mode 100644 index 00000000..45f2dae6 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_name.hpp @@ -0,0 +1,28 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +namespace Util +{ +void set_current_thread_name(const char *name); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_priority.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_priority.cpp new file mode 100644 index 00000000..227cb545 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_priority.cpp @@ -0,0 +1,67 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "thread_priority.hpp" +#include "logging.hpp" + +#if defined(__linux__) +#include +#elif defined(_WIN32) +#include +#endif + +namespace Util +{ +void set_current_thread_priority(ThreadPriority priority) +{ +#if defined(__linux__) + if (priority == ThreadPriority::Low) + { + struct sched_param param = {}; + int policy = 0; + param.sched_priority = sched_get_priority_min(SCHED_BATCH); + policy = SCHED_BATCH; + if (pthread_setschedparam(pthread_self(), policy, ¶m) != 0) + LOGE("Failed to set thread priority.\n"); + } +#elif defined(_WIN32) + if (priority == ThreadPriority::Low) + { + if (!SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN)) + LOGE("Failed to set background thread priority.\n"); + } + else if (priority == ThreadPriority::Default) + { + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL)) + LOGE("Failed to set normal thread priority.\n"); + } + else if (priority == ThreadPriority::High) + { + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) + LOGE("Failed to set high thread priority.\n"); + } +#else +#warning "Unimplemented set_current_thread_priority." + (void)priority; +#endif +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_priority.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_priority.hpp new file mode 100644 index 00000000..0d4582b0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/thread_priority.hpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +namespace Util +{ +enum class ThreadPriority +{ + High, + Default, + Low +}; + +void set_current_thread_priority(ThreadPriority priority); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timeline_trace_file.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timeline_trace_file.cpp new file mode 100644 index 00000000..4aa08cad --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timeline_trace_file.cpp @@ -0,0 +1,185 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "logging.hpp" +#include "timeline_trace_file.hpp" +#include "thread_name.hpp" +#include "timer.hpp" +#include +#include + +namespace Util +{ +static thread_local char trace_tid[32]; +static thread_local TimelineTraceFile *trace_file; + +void TimelineTraceFile::set_tid(const char *tid) +{ + snprintf(trace_tid, sizeof(trace_tid), "%s", tid); +} + +void TimelineTraceFile::set_per_thread(TimelineTraceFile *file) +{ + trace_file = file; +} + +TimelineTraceFile *TimelineTraceFile::get_per_thread() +{ + return trace_file; +} + +void TimelineTraceFile::Event::set_desc(const char *desc_) +{ + snprintf(desc, sizeof(desc), "%s", desc_); +} + +void TimelineTraceFile::Event::set_tid(const char *tid_) +{ + snprintf(tid, sizeof(tid), "%s", tid_); +} + +TimelineTraceFile::Event *TimelineTraceFile::begin_event(const char *desc, uint32_t pid) +{ + auto *e = event_pool.allocate(); + e->pid = pid; + e->set_tid(trace_tid); + e->set_desc(desc); + e->start_ns = get_current_time_nsecs(); + return e; +} + +TimelineTraceFile::Event *TimelineTraceFile::allocate_event() +{ + auto *e = event_pool.allocate(); + e->desc[0] = '\0'; + e->tid[0] = '\0'; + e->pid = 0; + e->start_ns = 0; + e->end_ns = 0; + return e; +} + +void TimelineTraceFile::submit_event(Event *e) +{ + std::lock_guard holder{lock}; + queued_events.push(e); + cond.notify_one(); +} + +void TimelineTraceFile::end_event(Event *e) +{ + e->end_ns = get_current_time_nsecs(); + submit_event(e); +} + +TimelineTraceFile::TimelineTraceFile(const std::string &path) +{ + thr = std::thread(&TimelineTraceFile::looper, this, path); +} + +void TimelineTraceFile::looper(std::string path) +{ + set_current_thread_name("json-trace-io"); + + FILE *file = fopen(path.c_str(), "w"); + if (!file) + LOGE("Failed to open file: %s.\n", path.c_str()); + + if (file) + fputs("[\n", file); + + uint64_t base_ts = get_current_time_nsecs(); + + for (;;) + { + Event *e; + { + std::unique_lock holder{lock}; + cond.wait(holder, [this]() { + return !queued_events.empty(); + }); + e = queued_events.front(); + queued_events.pop(); + } + + if (!e) + break; + + auto start_us = int64_t(e->start_ns - base_ts) * 1e-3; + auto end_us = int64_t(e->end_ns - base_ts) * 1e-3; + + if (file && start_us <= end_us) + { + fprintf(file, "{ \"name\": \"%s\", \"ph\": \"B\", \"tid\": \"%s\", \"pid\": \"%u\", \"ts\": %f },\n", + e->desc, e->tid, e->pid, start_us); + fprintf(file, "{ \"name\": \"%s\", \"ph\": \"E\", \"tid\": \"%s\", \"pid\": \"%u\", \"ts\": %f },\n", + e->desc, e->tid, e->pid, end_us); + } + + event_pool.free(e); + } + + // Intentionally truncate the JSON so that we can emit "," after the last element. + if (file) + fclose(file); +} + +TimelineTraceFile::~TimelineTraceFile() +{ + submit_event(nullptr); + if (thr.joinable()) + thr.join(); +} + +TimelineTraceFile::ScopedEvent::ScopedEvent(TimelineTraceFile *file_, const char *tag, uint32_t pid) + : file(file_) +{ + if (file && tag && *tag != '\0') + event = file->begin_event(tag, pid); +} + +TimelineTraceFile::ScopedEvent::~ScopedEvent() +{ + if (event) + file->end_event(event); +} + +TimelineTraceFile::ScopedEvent & +TimelineTraceFile::ScopedEvent::operator=(TimelineTraceFile::ScopedEvent &&other) noexcept +{ + if (this != &other) + { + if (event) + file->end_event(event); + event = other.event; + file = other.file; + other.event = nullptr; + other.file = nullptr; + } + return *this; +} + +TimelineTraceFile::ScopedEvent::ScopedEvent(TimelineTraceFile::ScopedEvent &&other) noexcept +{ + *this = std::move(other); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timeline_trace_file.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timeline_trace_file.hpp new file mode 100644 index 00000000..9c4c968c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timeline_trace_file.hpp @@ -0,0 +1,96 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "object_pool.hpp" + +namespace Util +{ +class TimelineTraceFile +{ +public: + explicit TimelineTraceFile(const std::string &path); + ~TimelineTraceFile(); + + static void set_tid(const char *tid); + static TimelineTraceFile *get_per_thread(); + static void set_per_thread(TimelineTraceFile *file); + + struct Event + { + char desc[256]; + char tid[32]; + uint32_t pid; + uint64_t start_ns, end_ns; + + void set_desc(const char *desc); + void set_tid(const char *tid); + }; + Event *begin_event(const char *desc, uint32_t pid = 0); + void end_event(Event *e); + + Event *allocate_event(); + void submit_event(Event *e); + + struct ScopedEvent + { + ScopedEvent(TimelineTraceFile *file, const char *tag, uint32_t pid = 0); + ScopedEvent() = default; + ~ScopedEvent(); + void operator=(const ScopedEvent &) = delete; + ScopedEvent(const ScopedEvent &) = delete; + ScopedEvent(ScopedEvent &&other) noexcept; + ScopedEvent &operator=(ScopedEvent &&other) noexcept; + TimelineTraceFile *file = nullptr; + Event *event = nullptr; + }; + +private: + void looper(std::string path); + std::thread thr; + std::mutex lock; + std::condition_variable cond; + + ThreadSafeObjectPool event_pool; + std::queue queued_events; +}; + +#ifndef GRANITE_SHIPPING + +#define GRANITE_MACRO_CONCAT_IMPL(a, b) a##b +#define GRANITE_MACRO_CONCAT(a, b) GRANITE_MACRO_CONCAT_IMPL(a, b) +#define GRANITE_SCOPED_TIMELINE_EVENT(str) \ + ::Util::TimelineTraceFile::ScopedEvent GRANITE_MACRO_CONCAT(_timeline_scoped_count_, __COUNTER__){GRANITE_THREAD_GROUP() ? GRANITE_THREAD_GROUP()->get_timeline_trace_file() : nullptr, str} +#define GRANITE_SCOPED_TIMELINE_EVENT_FILE(file, str) \ + ::Util::TimelineTraceFile::ScopedEvent GRANITE_MACRO_CONCAT(_timeline_scoped_count_, __COUNTER__){file, str} +#else +#define GRANITE_SCOPED_TIMELINE_EVENT(...) ((void)0) +#define GRANITE_SCOPED_TIMELINE_EVENT_FILE(...) ((void)0) +#endif +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timer.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timer.cpp new file mode 100644 index 00000000..a1408352 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timer.cpp @@ -0,0 +1,162 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "timer.hpp" +#include "logging.hpp" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#include +#endif + +#ifdef __SSE2__ +#include +#endif + +namespace Util +{ +FrameTimer::FrameTimer() +{ + reset(); +} + +void FrameTimer::reset() +{ + start = get_time(); + last = start; + last_period = 0; +} + +void FrameTimer::enter_idle() +{ + idle_start = get_time(); +} + +void FrameTimer::leave_idle() +{ + auto idle_end = get_time(); + idle_time += idle_end - idle_start; +} + +double FrameTimer::get_frame_time() const +{ + return double(last_period) * 1e-9; +} + +double FrameTimer::frame() +{ + auto new_time = get_time() - idle_time; + last_period = new_time - last; + last = new_time; + return double(last_period) * 1e-9; +} + +double FrameTimer::frame(double frame_time) +{ + last_period = int64_t(frame_time * 1e9); + last += last_period; + return frame_time; +} + +double FrameTimer::get_elapsed() const +{ + return double(last - start) * 1e-9; +} + +int64_t FrameTimer::get_time() +{ + return get_current_time_nsecs(); +} + +#ifdef _WIN32 +struct QPCFreq +{ + QPCFreq() + { + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + inv_freq = 1e9 / double(freq.QuadPart); + } + + double inv_freq; +} static static_qpc_freq; +#endif + +int64_t get_current_time_nsecs() +{ +#ifdef _WIN32 + LARGE_INTEGER li; + if (!QueryPerformanceCounter(&li)) + return 0; + return int64_t(double(li.QuadPart) * static_qpc_freq.inv_freq); +#else + struct timespec ts = {}; + constexpr auto timebase = CLOCK_MONOTONIC; + if (clock_gettime(timebase, &ts) < 0) + return 0; + return ts.tv_sec * 1000000000ll + ts.tv_nsec; +#endif +} + +void sleep_until_nsecs(int64_t timepoint) +{ +#ifdef _WIN32 + // Somewhat naive path. Improve this later. + int64_t d = get_current_time_nsecs() - timepoint; + if (d <= 0) + return; + + // Assumes timer resolution has been set. + Sleep(d / 1000000); + + // Spin the rest of the way. + while (get_current_time_nsecs() < timepoint) + { +#ifdef __SSE2__ + _mm_pause(); +#endif + } +#else + constexpr auto timebase = CLOCK_MONOTONIC; + struct timespec ts = {}; + ts.tv_sec = timepoint / 1000000000ll; + ts.tv_nsec = timepoint % 1000000000ll; + // Linux does not support clock_nanosleep with MONOTONIC_RAW :( + int ret; + while ((ret = clock_nanosleep(timebase, TIMER_ABSTIME, &ts, nullptr)) == EINTR) {} +#endif +} + +void Timer::start() +{ + t = get_current_time_nsecs(); +} + +double Timer::end() +{ + auto nt = get_current_time_nsecs(); + return double(nt - t) * 1e-9; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timer.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timer.hpp new file mode 100644 index 00000000..0a8287c0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/timer.hpp @@ -0,0 +1,64 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Util +{ +class FrameTimer +{ +public: + FrameTimer(); + + void reset(); + double frame(); + double frame(double frame_time); + double get_elapsed() const; + double get_frame_time() const; + + void enter_idle(); + void leave_idle(); + +private: + int64_t start; + int64_t last; + int64_t last_period; + int64_t idle_start; + int64_t idle_time = 0; + int64_t get_time(); +}; + +class Timer +{ +public: + void start(); + double end(); + +private: + int64_t t = 0; +}; + +int64_t get_current_time_nsecs(); +void sleep_until_nsecs(int64_t timepoint); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/unordered_array.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/unordered_array.hpp new file mode 100644 index 00000000..bc31a383 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/unordered_array.hpp @@ -0,0 +1,115 @@ +/* Copyright (c) 2021-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Util +{ +struct IntrusiveUnorderedArrayEnabled +{ + size_t unordered_array_offset; +}; + +// A special kind of vector where we only care about contiguous storage, not relative order between elements. +// This allows for O(1) removal. The stored type needs to store its own array offset. +template +class IntrusiveUnorderedArray +{ +public: + static_assert(std::is_base_of::value, + "T is not derived from IntrusiveUnorderedArrayEnabled."); + + void add(T *t) + { + t->unordered_array_offset = ts.size(); + ts.push_back(t); + } + + void erase(T *t) + { + erase_offset(t->unordered_array_offset); + } + + typename std::vector::const_iterator begin() const + { + return ts.begin(); + } + + typename std::vector::const_iterator end() const + { + return ts.end(); + } + + size_t size() const + { + return ts.size(); + } + + void clear() + { + ts.clear(); + } + + // If functor returns true, the pointer can be freed in the callback. + // Implementation must not dereference the pointer if true is returned. + template + void garbage_collect_if(const Func &func) + { + auto begin_itr = begin(); + auto end_itr = end(); + while (begin_itr != end_itr) + { + size_t offset = (*begin_itr)->unordered_array_offset; + if (func(*begin_itr)) + { + --end_itr; + erase_offset(offset); + } + else + { + ++begin_itr; + } + } + } + +private: + std::vector ts; + + void erase_offset(size_t offset) + { + assert(offset < ts.size()); + auto ¤t = ts[offset]; + if (¤t != &ts.back()) + { + std::swap(current, ts.back()); + current->unordered_array_offset = offset; + } + ts.pop_back(); + } +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/unstable_remove_if.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/unstable_remove_if.hpp new file mode 100644 index 00000000..4e48a58d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/unstable_remove_if.hpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Util +{ +template +BidirectionalItr unstable_remove_if(BidirectionalItr first, BidirectionalItr last, UnaryPredicate &&p) +{ + while (first != last) + { + if (p(*first)) + { + --last; + std::swap(*first, *last); + } + else + ++first; + } + + return first; +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/util/variant.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/variant.hpp new file mode 100644 index 00000000..9ef29f03 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/util/variant.hpp @@ -0,0 +1,77 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Granite +{ +class Variant +{ +public: + Variant() = default; + + template + explicit Variant(T &&t) + { + set(std::forward(t)); + } + + template + void set(T &&t) + { + value = std::make_shared>(std::forward(t)); + } + + template + T &get() + { + return static_cast *>(value.get())->value; + } + + template + const T &get() const + { + return static_cast *>(value.get())->value; + } + +private: + struct Holder + { + virtual ~Holder() = default; + }; + + template + struct HolderValue : Holder + { + template + HolderValue(P &&p) + : value(std::forward

(p)) + { + } + + U value; + }; + std::shared_ptr value; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/CMakeLists.txt new file mode 100644 index 00000000..1b108d34 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/CMakeLists.txt @@ -0,0 +1,126 @@ +add_granite_internal_lib(granite-vulkan + context.cpp context.hpp + vulkan_headers.hpp vulkan_prerotate.hpp + device.cpp device.hpp + wsi.cpp wsi.hpp + wsi_pacer.cpp wsi_pacer.hpp + buffer_pool.cpp buffer_pool.hpp + image.cpp image.hpp + cookie.cpp cookie.hpp + sampler.cpp sampler.hpp + command_pool.cpp command_pool.hpp + fence_manager.cpp fence_manager.hpp + descriptor_set.cpp descriptor_set.hpp + semaphore_manager.cpp semaphore_manager.hpp + command_buffer.cpp command_buffer.hpp + shader.cpp shader.hpp + render_pass.cpp render_pass.hpp + buffer.cpp buffer.hpp + rtas.cpp rtas.hpp + indirect_layout.cpp indirect_layout.hpp + pipeline_cache.cpp pipeline_cache.hpp + semaphore.cpp semaphore.hpp + memory_allocator.cpp memory_allocator.hpp + fence.hpp fence.cpp + format.hpp + limits.hpp + type_to_string.hpp + quirks.hpp + vulkan_common.hpp + event_manager.cpp event_manager.hpp + breadcrumbs.cpp breadcrumbs.hpp + pipeline_event.cpp pipeline_event.hpp + query_pool.cpp query_pool.hpp + texture/texture_format.cpp texture/texture_format.hpp) + +if (WIN32 AND GRANITE_VULKAN_DXGI_INTEROP) + target_sources(granite-vulkan PRIVATE wsi_dxgi.cpp wsi_dxgi.hpp) + target_compile_definitions(granite-vulkan PUBLIC HAVE_WSI_DXGI_INTEROP) +endif() + +target_include_directories(granite-vulkan PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +if (GRANITE_RENDERDOC_CAPTURE) + target_link_libraries(granite-vulkan PRIVATE granite-renderdoc-app) + target_sources(granite-vulkan PRIVATE renderdoc_capture.cpp) + if (NOT WIN32) + target_link_libraries(granite-vulkan PRIVATE dl) + endif() +endif() + +if (GRANITE_VULKAN_SYSTEM_HANDLES) + if (GRANITE_VULKAN_FOSSILIZE) + target_compile_definitions(granite-vulkan PUBLIC GRANITE_VULKAN_FOSSILIZE) + target_sources(granite-vulkan PRIVATE device_fossilize.cpp device_fossilize.hpp) + target_link_libraries(granite-vulkan PUBLIC fossilize) + endif() + + target_compile_definitions(granite-vulkan PUBLIC GRANITE_VULKAN_SYSTEM_HANDLES) + target_sources(granite-vulkan PRIVATE + managers/shader_manager.cpp + managers/shader_manager.hpp + managers/resource_manager.cpp + managers/resource_manager.hpp) + + target_sources(granite-vulkan PRIVATE + texture/memory_mapped_texture.cpp texture/memory_mapped_texture.hpp + mesh/meshlet.hpp mesh/meshlet.cpp + texture/texture_files.cpp texture/texture_files.hpp + texture/texture_decoder.cpp texture/texture_decoder.hpp) + + target_link_libraries(granite-vulkan + PUBLIC granite-filesystem + PRIVATE granite-threading granite-rapidjson granite-stb granite-math) + + target_include_directories(granite-vulkan PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/managers + ${CMAKE_CURRENT_SOURCE_DIR}/texture + ${CMAKE_CURRENT_SOURCE_DIR}/mesh) + + if (GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER) + target_compile_definitions(granite-vulkan PUBLIC GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER=1) + target_link_libraries(granite-vulkan PRIVATE granite-compiler) + endif() +endif() + +if (${CMAKE_BUILD_TYPE} MATCHES "Debug") + target_compile_definitions(granite-vulkan PUBLIC VULKAN_DEBUG) +endif() + +target_link_libraries(granite-vulkan + PRIVATE granite-volk + PUBLIC granite-util granite-volk-headers) + +if (GRANITE_VULKAN_SPIRV_CROSS) + target_link_libraries(granite-vulkan PRIVATE spirv-cross-core) + target_compile_definitions(granite-vulkan PRIVATE GRANITE_VULKAN_SPIRV_CROSS=1) +endif() + +if (ANDROID AND GRANITE_ANDROID_SWAPPY) + find_package(games-frame-pacing REQUIRED CONFIG) + target_link_libraries(granite-vulkan PRIVATE games-frame-pacing::swappy) + target_compile_definitions(granite-vulkan PRIVATE HAVE_SWAPPY) +endif() + +if (GRANITE_SHIPPING) + target_compile_definitions(granite-vulkan PUBLIC GRANITE_SHIPPING) +endif() + +if (GRANITE_FFMPEG_VULKAN) + target_compile_definitions(granite-vulkan PRIVATE HAVE_FFMPEG_VULKAN) +endif() + +if (GRANITE_VULKAN_PROFILES) + # Must be defined by caller as an INTERFACE library before including Granite. + if (NOT TARGET granite-vulkan-profiles) + message(FATAL_ERROR "granite-vulkan-profiles is not a target. This must be defined by caller before add_subdirectory(Granite).") + endif() + target_link_libraries(granite-vulkan PRIVATE granite-vulkan-profiles) + target_compile_definitions(granite-vulkan PRIVATE GRANITE_VULKAN_PROFILES) +endif() + +if (GRANITE_VULKAN_POST_MORTEM) + add_subdirectory(post-mortem) + target_link_libraries(granite-vulkan PRIVATE granite-vulkan-post-mortem) + target_compile_definitions(granite-vulkan PUBLIC HAVE_GRANITE_VULKAN_POST_MORTEM) +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/breadcrumbs.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/breadcrumbs.cpp new file mode 100644 index 00000000..c6999819 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/breadcrumbs.cpp @@ -0,0 +1,568 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "breadcrumbs.hpp" +#include "shader.hpp" +#include "device.hpp" +#include "timer.hpp" +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +namespace Vulkan +{ +void CheckpointString::report(FILE *file) +{ + fprintf(file, "%s\n", str.c_str()); +} + +void CheckpointDispatch::report(FILE *file) +{ + fprintf(file, "Dispatch (%u, %u, %u)\n", x, y, z); +} + +void CheckpointDraw::report(FILE *file) +{ + fprintf(file, "Draw (%u, %u, %d, %u)\n", + vertex_count, instance_count, vertex_offset, instance_offset); +} + +void CheckpointDrawIndexed::report(FILE *file) +{ + fprintf(file, "DrawIndexed (%u, %u, %u, %d, %u)\n", + index_count, instance_count, first_index, vertex_offset, instance_offset); +} + +void CheckpointMeshDispatch::report(FILE *file) +{ + fprintf(file, "MeshTasks (%u, %u, %u)\n", x, y, z); +} + +void CheckpointIndirectBase::report(FILE *file) +{ + fprintf(file, "%s (#%016llx)\n", tag, static_cast(va)); +} + +void CheckpointMultiIndirectBase::report(FILE *file) +{ + fprintf(file, "%s (#%016llx), count %u, stride %u\n", + tag, + static_cast(va), + count, stride); +} + +void CheckpointShader::report(FILE *file) +{ + fprintf(file, "Shader (#%016llx)\n", static_cast(shader->get_hash())); +} + +static void *nv_encode_checkpoint(uint32_t index, uint32_t counter) +{ + return reinterpret_cast(uintptr_t(index) + uintptr_t(counter) * BreadcrumbsTracker::MaxCommandBuffers); +} + +static uint32_t nv_decode_context(void *opaque) +{ + return reinterpret_cast(opaque) % BreadcrumbsTracker::MaxCommandBuffers; +} + +static uint32_t nv_decode_counter(void *opaque) +{ + return reinterpret_cast(opaque) / BreadcrumbsTracker::MaxCommandBuffers; +} + +void BreadcrumbsTracker::init(Device *device_) +{ + device = device_; + if (!device->get_device_features().supports_post_mortem) + return; + + active = true; + + command_buffers.resize(MaxCommandBuffers); + vacant_command_buffers.reserve(MaxCommandBuffers); + for (uint32_t i = MaxCommandBuffers; i; i--) + vacant_command_buffers.push_back(i - 1); + + if (device->get_device_features().supports_amd_buffer_marker) + { + BufferCreateInfo info = {}; + info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + info.domain = BufferDomain::DebugReadback; + info.size = MaxCommandBuffers * sizeof(uint32_t) * 2; + info.misc = BUFFER_MISC_ZERO_INITIALIZE_BIT; + amd_marker_buffer = device->create_buffer(info).release(); + } + + blocks.init(CheckpointObjectSize); +} + +void BreadcrumbsTracker::deinit() +{ + for (auto &cmd : command_buffers) + reset_command_buffer(cmd); + if (amd_marker_buffer) + amd_marker_buffer->release_reference(); +} + +BufferMarkerHandle BreadcrumbsTracker::allocate_command_buffer(VkCommandBuffer cmd) +{ + if (!active) + return {}; + + std::lock_guard holder{lock}; + + if (vacant_command_buffers.empty()) + return {}; + + BufferMarkerHandle ret = { vacant_command_buffers.back() }; + vacant_command_buffers.pop_back(); + command_buffers[ret.index].cmd = cmd; + return ret; +} + +void BreadcrumbsTracker::free_command_buffer(BufferMarkerHandle handle) +{ + if (handle.index == BufferMarkerHandle::Invalid) + return; + + std::lock_guard holder{lock}; + assert(handle.index < MaxCommandBuffers); + vacant_command_buffers.push_back(handle.index); + reset_command_buffer(command_buffers[handle.index]); +} + +void BreadcrumbsTracker::reset_command_buffer(CommandBuffer &cmd) +{ + for (auto &check : cmd.checkpoints) + { + if (check.iface) + { + check.iface->~CheckpointReportInterface(); + blocks.free(reinterpret_cast(check.iface)); + } + } + + // Free the memory too to avoid extreme bloat. + cmd = {}; +} + +void BreadcrumbsTracker::begin(BufferMarkerHandle handle) +{ + if (handle.index == BufferMarkerHandle::Invalid) + return; + + auto &cmd = command_buffers[handle.index]; + + cmd.counter++; + cmd.checkpoints.push_back({ nullptr, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, cmd.counter }); + + if (device->get_device_features().supports_nv_checkpoints) + { + cmd.checkpoints.push_back({ nullptr, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, cmd.counter }); + // A checkpoint is implicitly a top and a bottom marker. + device->get_device_table().vkCmdSetCheckpointNV(cmd.cmd, nv_encode_checkpoint(handle.index, cmd.counter)); + } + else if (device->get_device_features().supports_amd_buffer_marker) + { + device->get_device_table().vkCmdWriteBufferMarkerAMD(cmd.cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + amd_marker_buffer->get_buffer(), + (2 * handle.index + 0) * sizeof(uint32_t), cmd.counter); + } +} + +void BreadcrumbsTracker::signal(BufferMarkerHandle handle) +{ + if (handle.index == BufferMarkerHandle::Invalid) + return; + + auto &cmd = command_buffers[handle.index]; + + if (device->get_device_features().supports_nv_checkpoints) + { + cmd.counter++; + cmd.checkpoints.push_back({ nullptr, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, cmd.counter }); + cmd.checkpoints.push_back({ nullptr, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, cmd.counter }); + device->get_device_table().vkCmdSetCheckpointNV(cmd.cmd, nv_encode_checkpoint(handle.index, cmd.counter)); + } + else if (device->get_device_features().supports_amd_buffer_marker) + { + cmd.checkpoints.push_back({ nullptr, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, cmd.counter }); + device->get_device_table().vkCmdWriteBufferMarkerAMD(cmd.cmd, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + amd_marker_buffer->get_buffer(), + (2 * handle.index + 1) * sizeof(uint32_t), cmd.counter); + + cmd.counter++; + cmd.checkpoints.push_back({ nullptr, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, cmd.counter }); + device->get_device_table().vkCmdWriteBufferMarkerAMD(cmd.cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + amd_marker_buffer->get_buffer(), + (2 * handle.index + 0) * sizeof(uint32_t), cmd.counter); + } +} + +void BreadcrumbsTracker::end(BufferMarkerHandle handle) +{ + if (handle.index == BufferMarkerHandle::Invalid) + return; + + auto &cmd = command_buffers[handle.index]; + cmd.counter = UINT32_MAX; + + if (device->get_device_features().supports_nv_checkpoints) + { + device->get_device_table().vkCmdSetCheckpointNV(cmd.cmd, nv_encode_checkpoint(handle.index, cmd.counter)); + } + else if (device->get_device_features().supports_amd_buffer_marker) + { + device->get_device_table().vkCmdWriteBufferMarkerAMD(cmd.cmd, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + amd_marker_buffer->get_buffer(), + (2 * handle.index + 0) * sizeof(uint32_t), cmd.counter); + + device->get_device_table().vkCmdWriteBufferMarkerAMD(cmd.cmd, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + amd_marker_buffer->get_buffer(), + (2 * handle.index + 1) * sizeof(uint32_t), cmd.counter); + } + + cmd.checkpoints.push_back({ nullptr, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, cmd.counter }); + cmd.checkpoints.push_back({ nullptr, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, cmd.counter }); + + // Avoid breadcrumbs spilling between command buffers. + VkDependencyInfo dep = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO }; + VkMemoryBarrier2 bar = { VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 }; + dep.memoryBarrierCount = 1; + dep.pMemoryBarriers = &bar; + bar.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; + bar.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT; + bar.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; + bar.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT; + device->get_device_table().vkCmdPipelineBarrier2(cmd.cmd, &dep); +} + +void BreadcrumbsTracker::report_command_list(FILE *file, CommandBuffer &cmd, uint32_t top_marker, uint32_t bottom_marker) +{ + bool observed_begin_cmd = false; + bool observed_end_cmd = false; + + fprintf(file, "\n=== Command Buffer ===\n"); + + if (bottom_marker == 0) + { + fprintf(file, "=== Crash region BEGIN ===\n"); + observed_begin_cmd = true; + } + + for (auto &check : cmd.checkpoints) + { + if (!observed_end_cmd && check.stages == VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT && check.counter > top_marker) + { + // The command processor did not reach this checkpoint. Any command after this point cannot be the culprit. + fprintf(file, "=== Crash region END ===\n"); + observed_end_cmd = true; + } + + if (check.iface) + check.iface->report(file); + + if (!observed_begin_cmd && check.stages == VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT && check.counter == bottom_marker) + { + // The GPU completed all commands up to this point and is the last counter that was completed. + // Crash must be after this point. + fprintf(file, "=== Crash region BEGIN ===\n"); + observed_begin_cmd = true; + } + } + + if (top_marker == UINT32_MAX) + fprintf(file, "=== Crash region END ===\n"); + + fprintf(file, "====================\n"); +} + +void BreadcrumbsTracker::report_command_list_amd(FILE *file, uint32_t index) +{ + auto &cmd = command_buffers[index]; + + // Unused, cannot be the culprit. + if (cmd.counter == 0) + return; + + auto *ptr = static_cast(device->map_host_buffer(*amd_marker_buffer, MEMORY_ACCESS_READ_BIT, 2 * sizeof(uint32_t) * index, sizeof(uint32_t) * 2)); + uint32_t top_marker = ptr[0]; + uint32_t bottom_marker = ptr[1]; + + // The command buffer is done executing. + if (top_marker == UINT32_MAX && bottom_marker == UINT32_MAX) + return; + + // Never started executing properly. Cannot be a culprit. + if (top_marker == 0 && bottom_marker == 0) + return; + + // Edge case where we crashed before the first command of a recycled command buffer completed. + if (top_marker > 0 && bottom_marker == UINT32_MAX) + bottom_marker = 0; + + fprintf(file, "Reporting for command index %u, top marker %u, bottom marker %u\n", index, top_marker, bottom_marker); + report_command_list(file, cmd, top_marker, bottom_marker); + reported = true; +} + +void BreadcrumbsTracker::notify_device_hung() +{ + if (!active) + return; + + std::lock_guard holder{lock}; + if (reported) + return; + + char path[256]; + std::time_t t = std::time(nullptr); + std::tm gmt; + + // Date-time in C was always a great time :') +#ifdef _WIN32 + gmtime_s(&gmt, &t); +#else + gmtime_r(&t, &gmt); +#endif + + // Windows does not like colons in path names, so %T breaks. + strftime(path, sizeof(path), "granite-post-mortem-%Y-%m-%d-%H-%M-%S.txt", &gmt); + + LOGE("Device hung ... Attempting to grab post-mortem data to: %s\n", path); + + auto start_time = Util::get_current_time_nsecs(); + auto end_time = start_time + 5ll * 1000 * 1000 * 1000; + + // Try to observe device lost properly. + VkResult vr = VK_SUCCESS; + while (vr != VK_ERROR_DEVICE_LOST && Util::get_current_time_nsecs() < end_time) + vr = device->get_device_table().vkDeviceWaitIdle(device->get_device()); + + if (vr == VK_ERROR_DEVICE_LOST) + LOGE("Observed device lost after %.3f seconds of blocking.\n", 1e-9 * (Util::get_current_time_nsecs() - start_time)); + + FILE *file = fopen(path, "w"); + if (!file) + { + LOGE("Failed to open \"%s\", dumping to stderr instead.\n", path); + file = stderr; + } + + if (vr != VK_ERROR_DEVICE_LOST) + { + if (file != stderr) + LOGE("Cannot observe device lost state, report may be incomplete ...\n"); + fprintf(file, "Cannot observe device lost state, report may be incomplete ...\n"); + } + + fprintf(file, "Post-mortem analysis ...\n"); + + if (device->get_device_features().supports_nv_checkpoints) + { + auto &queues = device->get_queue_info().queues; + for (uint32_t i = 0; i < QUEUE_INDEX_COUNT; i++) + { + if (queues[i] == VK_NULL_HANDLE || std::find(queues, queues + i, queues[i]) != queues + i) + continue; + + auto &table = device->get_device_table(); + uint32_t count; + table.vkGetQueueCheckpointDataNV(queues[i], &count, nullptr); + + if (count == 0) + continue; + + std::vector checkpoints(count); + for (auto &check : checkpoints) + check.sType = VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV; + table.vkGetQueueCheckpointDataNV(queues[i], &count, checkpoints.data()); + + uint32_t top_marker = 0; + uint32_t bottom_marker = 0; + uint32_t top_context = BufferMarkerHandle::Invalid; + uint32_t bottom_context = BufferMarkerHandle::Invalid; + + for (auto &check : checkpoints) + { + uint32_t context = nv_decode_context(check.pCheckpointMarker); + uint32_t counter = nv_decode_counter(check.pCheckpointMarker); + + if (check.stage == VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT) + { + top_marker = counter; + top_context = context; + } + else if (check.stage == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT) + { + bottom_marker = counter; + bottom_context = context; + } + } + + if (top_context == BufferMarkerHandle::Invalid) + fprintf(file, "Missing context, this should not happen.\n"); + else if (top_context != bottom_context || top_context == BufferMarkerHandle::Invalid) + fprintf(file, "Mismatching contexts, this should not happen.\n"); + else + { + report_command_list(file, command_buffers[top_context], top_marker, bottom_marker); + reported = true; + } + } + } + else if (device->get_device_features().supports_amd_buffer_marker) + { + for (uint32_t i = 0; i < MaxCommandBuffers; i++) + report_command_list_amd(file, i); + } + + // Need to observe the device lost properly first before we can query fault information. + auto &table = device->get_device_table(); + + const auto addr_type_to_str = [](VkDeviceFaultAddressTypeKHR type) + { + switch (type) + { + case VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_KHR: return "None"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_KHR: return "ReadInvalid"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_KHR: return "WriteInvalid"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_KHR: return "ExecuteInvalid"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_KHR: return "IPUnknown"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_KHR: return "IPInvalid"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_KHR: return "IPFault"; + default: return "???"; + } + }; + + const auto report_address = [&](const char *tag, const VkDeviceFaultAddressInfoKHR &info) + { + fprintf(file, " %s fault: %s\n", tag, addr_type_to_str(info.addressType)); + fprintf(file, " %s address: #%016llx\n", tag, + static_cast(info.reportedAddress)); + fprintf(file, " %s precision: #%016llx\n", tag, + static_cast(info.addressPrecision)); + }; + + const auto report_vendor = [&](const VkDeviceFaultVendorInfoKHR &info) + { + fprintf(file, " Vendor desc: %s\n", info.description); + fprintf(file, " Vendor fault code: %llu\n", + static_cast(info.vendorFaultCode)); + fprintf(file, " Vendor fault data: %llu\n", + static_cast(info.vendorFaultData)); + }; + + if (device->get_device_features().fault_features_khr.deviceFault) + { + std::vector faults; + uint32_t count; + + if (table.vkGetDeviceFaultReportsKHR(device->get_device(), UINT64_MAX, &count, nullptr) != VK_SUCCESS) + { + fprintf(file, "Failed to get fault reports.\n"); + return; + } + + faults.resize(count); + for (auto &fault : faults) + fault.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_KHR; + + if (table.vkGetDeviceFaultReportsKHR(device->get_device(), UINT64_MAX, &count, faults.data()) != VK_SUCCESS) + { + fprintf(file, "Failed to get fault reports.\n"); + return; + } + + for (auto &fault : faults) + { + fprintf(file, "=== Fault ===\n"); + fprintf(file, " Desc: %s\n", fault.description); + fprintf(file, " groupID: %llu\n", static_cast(fault.groupId)); + + if (fault.flags & VK_DEVICE_FAULT_FLAG_DEVICE_LOST_KHR) + fprintf(file, " Fault caused DEVICE_LOST\n"); + if (fault.flags & VK_DEVICE_FAULT_FLAG_WATCHDOG_TIMEOUT_KHR) + fprintf(file, " GPU Timeout\n"); + if (fault.flags & VK_DEVICE_FAULT_FLAG_OVERFLOW_KHR) + fprintf(file, " Fault buffer overflowed\n"); + + if (fault.flags & VK_DEVICE_FAULT_FLAG_VENDOR_KHR) + report_vendor(fault.vendorInfo); + if (fault.flags & VK_DEVICE_FAULT_FLAG_MEMORY_ADDRESS_KHR) + report_address("Memory", fault.faultAddressInfo); + if (fault.flags & VK_DEVICE_FAULT_FLAG_INSTRUCTION_ADDRESS_KHR) + report_address("Instruction ", fault.instructionAddressInfo); + } + } + else + { + VkDeviceFaultCountsEXT counts = { VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT }; + VkDeviceFaultInfoEXT fault = { VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT }; + + if (table.vkGetDeviceFaultInfoEXT(device->get_device(), &counts, nullptr) != VK_SUCCESS) + { + fprintf(file, "Failed to get fault reports.\n"); + return; + } + + std::vector addresses(counts.addressInfoCount); + std::vector vendor_infos(counts.vendorInfoCount); + uint8_t *vendor_data = counts.vendorBinarySize ? new uint8_t[counts.vendorBinarySize] : nullptr; + + fault.pAddressInfos = addresses.data(); + fault.pVendorInfos = vendor_infos.data(); + fault.pVendorBinaryData = vendor_data; + + if (table.vkGetDeviceFaultInfoEXT(device->get_device(), &counts, &fault) != VK_SUCCESS) + { + fprintf(file, "Failed to get fault reports.\n"); + return; + } + + for (uint32_t i = 0; i < counts.addressInfoCount; i++) + report_address("Memory", addresses[i]); + for (uint32_t i = 0; i < counts.vendorInfoCount; i++) + report_vendor(vendor_infos[i]); + + delete[] vendor_data; + } + + fprintf(file, "... DONE\n"); + + if (file != stderr) + fclose(file); + + LOGE("Completed post-mortem analysis, will crash now.\n"); +#ifdef _WIN32 + char msg[512]; + snprintf(msg, sizeof(msg), "GPU crashed, see post-mortem log in %s. Application will now terminate.", path); + MessageBoxA(nullptr, msg, "Granite Post Mortem", MB_OK); + TerminateProcess(GetCurrentProcess(), 1); +#endif + std::terminate(); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/breadcrumbs.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/breadcrumbs.hpp new file mode 100644 index 00000000..51b1b5b7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/breadcrumbs.hpp @@ -0,0 +1,222 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "slab_allocator.hpp" +#include "vulkan_headers.hpp" +#include "vulkan_common.hpp" +#include +#include +#include + +namespace Vulkan +{ +class Device; +class Buffer; +class Shader; + +struct CheckpointReportInterface +{ + virtual void report(FILE *file) = 0; + virtual ~CheckpointReportInterface() = default; +}; + +struct CheckpointString : CheckpointReportInterface +{ + CheckpointString(std::string str_) : str(std::move(str_)) {} + void report(FILE *file) override; + std::string str; +}; + +struct CheckpointDispatch : CheckpointReportInterface +{ + CheckpointDispatch(uint32_t x_, uint32_t y_, uint32_t z_) + : x(x_), y(y_), z(z_) {} + void report(FILE *file) override; + uint32_t x, y, z; +}; + +struct CheckpointDraw : CheckpointReportInterface +{ + CheckpointDraw(uint32_t vertex_count_, uint32_t instance_count_, int32_t vertex_offset_, uint32_t instance_offset_) + : vertex_count(vertex_count_), instance_count(instance_count_) + , vertex_offset(vertex_offset_), instance_offset(instance_offset_) {} + + void report(FILE *file) override; + uint32_t vertex_count; + uint32_t instance_count; + int32_t vertex_offset; + uint32_t instance_offset; +}; + +struct CheckpointDrawIndexed : CheckpointReportInterface +{ + CheckpointDrawIndexed(uint32_t index_count_, uint32_t instance_count_, uint32_t first_index_, int32_t vertex_offset_, uint32_t instance_offset_) + : index_count(index_count_), instance_count(instance_count_), first_index(first_index_) + , vertex_offset(vertex_offset_), instance_offset(instance_offset_) {} + + void report(FILE *file) override; + uint32_t index_count; + uint32_t instance_count; + uint32_t first_index; + int32_t vertex_offset; + uint32_t instance_offset; +}; + +struct CheckpointMeshDispatch : CheckpointReportInterface +{ + CheckpointMeshDispatch(uint32_t x_, uint32_t y_, uint32_t z_) + : x(x_), y(y_), z(z_) {} + void report(FILE *file) override; + uint32_t x, y, z; +}; + +struct CheckpointIndirectBase : CheckpointReportInterface +{ + CheckpointIndirectBase(const char *tag_, VkDeviceAddress va_) : tag(tag_), va(va_) {} + + void report(FILE *file) override; + + const char *tag; + VkDeviceAddress va; +}; + +struct CheckpointMultiIndirectBase : CheckpointReportInterface +{ + CheckpointMultiIndirectBase(const char *tag_, VkDeviceAddress va_, + uint32_t count_, uint32_t stride_) + : tag(tag_), va(va_), count(count_), stride(stride_) {} + + void report(FILE *file) override; + + const char *tag; + VkDeviceAddress va; + uint32_t count; + uint32_t stride; +}; + +struct CheckpointMultiIndirectCountBase : CheckpointReportInterface +{ + CheckpointMultiIndirectCountBase(const char *tag_, VkDeviceAddress va_, VkDeviceAddress count_va_, + uint32_t count_, uint32_t stride_) + : tag(tag_), va(va_), count_va(count_va_), count(count_), stride(stride_) {} + + void report(FILE *file) override + { + fprintf(file, "%s (#%016llx), countVA (#%016llx), count %u, stride %u\n", + tag, + static_cast(va), + static_cast(count_va), + count, stride); + } + + const char *tag; + VkDeviceAddress va; + VkDeviceAddress count_va; + uint32_t count; + uint32_t stride; +}; + +struct CheckpointShader : CheckpointReportInterface +{ + CheckpointShader(const Shader *shader_) : shader(shader_) {} + void report(FILE *file) override; + const Shader *shader; +}; + +// 1 second. +// It seems like if we have too long timeout, NV driver on Windows is broken +// and loses checkpoint information (?!?!). +// It seems like we have to call it before we start getting vkQueueSubmit() device losts, +// then it's too late. +static constexpr uint64_t PostMortemTimeout = 1ull * 1000 * 1000 * 1000; + +class BreadcrumbsTracker +{ +public: + enum { CheckpointObjectSize = 64, MaxCommandBuffers = 8 * 1024 }; + void init(Device *device); + void deinit(); + BufferMarkerHandle allocate_command_buffer(VkCommandBuffer cmd); + void free_command_buffer(BufferMarkerHandle handle); + + void begin(BufferMarkerHandle handle); + + template + void checkpoint(BufferMarkerHandle handle, Ts &&... ts) + { + if (!active) + return; + + static_assert(sizeof(T) <= CheckpointObjectSize, "Object size is too large."); + auto *raw = reinterpret_cast(blocks.allocate()); + new (raw) T(std::forward(ts)...); + + Checkpoint checkpoint = {}; + checkpoint.iface = raw; + assert(handle.index < command_buffers.size()); + command_buffers[handle.index].checkpoints.push_back(checkpoint); + } + + template + void checkpoint_with_signal(BufferMarkerHandle handle, Ts &&... ts) + { + checkpoint(handle, std::forward(ts)...); + signal(handle); + } + + void signal(BufferMarkerHandle handle); + void end(BufferMarkerHandle handle); + + void notify_device_hung(); + +private: + Device *device = nullptr; + bool active = false; + Buffer *amd_marker_buffer = nullptr; + std::mutex lock; + bool reported = false; + + struct Checkpoint + { + CheckpointReportInterface *iface; + VkPipelineStageFlags2 stages; + uint32_t counter; + }; + + struct CommandBuffer + { + std::vector checkpoints; + uint32_t counter = 0; + VkCommandBuffer cmd; + }; + + std::vector command_buffers; + std::vector vacant_command_buffers; + Util::ThreadSafeSlabAllocator blocks; + + void reset_command_buffer(CommandBuffer &cmd); + void report_command_list_amd(FILE *file, uint32_t index); + void report_command_list(FILE *file, CommandBuffer &cmd, uint32_t top_marker, uint32_t bottom_marker); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer.cpp new file mode 100644 index 00000000..d3229cb8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer.cpp @@ -0,0 +1,89 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "buffer.hpp" +#include "device.hpp" + +namespace Vulkan +{ +Buffer::Buffer(Device *device_, VkBuffer buffer_, const DeviceAllocation &alloc_, const BufferCreateInfo &info_, + VkDeviceAddress bda_) + : Cookie(device_) + , device(device_) + , buffer(buffer_) + , alloc(alloc_) + , info(info_) + , bda(bda_) +{ +} + +ExternalHandle Buffer::export_handle() +{ + return alloc.export_handle(*device); +} + +Buffer::~Buffer() +{ + if (owns_buffer) + { + if (internal_sync) + { + device->destroy_buffer_nolock(buffer); + device->free_memory_nolock(alloc); + } + else + { + device->destroy_buffer(buffer); + device->free_memory(alloc); + } + } +} + +void BufferDeleter::operator()(Buffer *buffer) +{ + buffer->device->handle_pool.buffers.free(buffer); +} + +BufferView::BufferView(Device *device_, + const CachedBufferView &view_, + const BufferViewCreateInfo &create_info_) + : Cookie(device_) + , device(device_) + , view(view_) + , info(create_info_) +{ +} + +BufferView::~BufferView() +{ + if (internal_sync) + device->destroy_buffer_view_nolock(view); + else + device->destroy_buffer_view(view); +} + +void BufferViewDeleter::operator()(BufferView *view) +{ + view->device->handle_pool.buffer_views.free(view); +} + +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer.hpp new file mode 100644 index 00000000..75535ed4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer.hpp @@ -0,0 +1,183 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "cookie.hpp" +#include "vulkan_common.hpp" +#include "memory_allocator.hpp" + +namespace Vulkan +{ +class Device; + +enum class BufferDomain +{ + Device, // Device local. Probably not visible from CPU. + LinkedDeviceHost, // On desktop, directly mapped VRAM over PCI. + LinkedDeviceHostPreferDevice, // Prefer device local of host visible. + Host, // Host-only, needs to be synced to GPU. Might be device local as well on iGPUs. + CachedHost, + CachedCoherentHostPreferCoherent, // Aim for both cached and coherent, but prefer COHERENT + CachedCoherentHostPreferCached, // Aim for both cached and coherent, but prefer CACHED + UMACachedCoherentPreferDevice, // Aim for DEVICE | CACHED | COHERENT, but fallback to plain DEVICE if not supported. + DebugReadback // DEVICE_COHERENT + HOST_COHERENT. For AMD_buffer_marker and other breadcrumbs. +}; + +enum BufferMiscFlagBits +{ + BUFFER_MISC_ZERO_INITIALIZE_BIT = 1 << 0, + BUFFER_MISC_EXTERNAL_MEMORY_BIT = 1 << 1 +}; + +using BufferMiscFlags = uint32_t; + +struct BufferCreateInfo +{ + BufferDomain domain = BufferDomain::Device; + VkDeviceSize size = 0; + VkBufferUsageFlags2 usage = 0; + BufferMiscFlags misc = 0; + VkMemoryRequirements allocation_requirements = {}; + ExternalHandle external; + void *pnext = nullptr; +}; + +class Buffer; +struct BufferDeleter +{ + void operator()(Buffer *buffer); +}; + +class BufferView; +struct BufferViewDeleter +{ + void operator()(BufferView *view); +}; + +class Buffer : public Util::IntrusivePtrEnabled, + public Cookie, public InternalSyncEnabled +{ +public: + friend struct BufferDeleter; + ~Buffer(); + + VkBuffer get_buffer() const + { + return buffer; + } + + const BufferCreateInfo &get_create_info() const + { + return info; + } + + DeviceAllocation &get_allocation() + { + return alloc; + } + + const DeviceAllocation &get_allocation() const + { + return alloc; + } + + ExternalHandle export_handle(); + + VkDeviceAddress get_device_address() const + { + VK_ASSERT(bda); + return bda; + } + + void disown_buffer() + { + owns_buffer = false; + } + +private: + friend class Util::ObjectPool; + Buffer(Device *device, VkBuffer buffer, const DeviceAllocation &alloc, const BufferCreateInfo &info, + VkDeviceAddress bda); + + Device *device; + VkBuffer buffer; + DeviceAllocation alloc; + BufferCreateInfo info; + VkDeviceAddress bda; + bool owns_buffer = true; +}; +using BufferHandle = Util::IntrusivePtr; + +struct BufferViewCreateInfo +{ + const Buffer *buffer; + VkFormat format; + VkDeviceSize offset; + VkDeviceSize range; +}; + +class BufferView : public Util::IntrusivePtrEnabled, + public Cookie, public InternalSyncEnabled +{ +public: + friend struct BufferViewDeleter; + ~BufferView(); + + VkBufferView get_view() const + { + VK_ASSERT(view.view); + return view.view; + } + + const CachedDescriptorPayload &get_uniform_payload() const + { + VK_ASSERT(view.uniform.ptr && view.uniform.type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + return view.uniform; + } + + const CachedDescriptorPayload &get_storage_payload() const + { + VK_ASSERT(view.storage.ptr && view.storage.type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); + return view.storage; + } + + const BufferViewCreateInfo &get_create_info() + { + return info; + } + + const Buffer &get_buffer() const + { + return *info.buffer; + } + +private: + friend class Util::ObjectPool; + BufferView(Device *device, const CachedBufferView &view, const BufferViewCreateInfo &info); + + Device *device; + CachedBufferView view; + BufferViewCreateInfo info; +}; +using BufferViewHandle = Util::IntrusivePtr; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer_pool.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer_pool.cpp new file mode 100644 index 00000000..9b487b17 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer_pool.cpp @@ -0,0 +1,128 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "buffer_pool.hpp" +#include "device.hpp" +#include + +namespace Vulkan +{ +void BufferPool::init(Device *device_, VkDeviceSize block_size_, + VkDeviceSize alignment_, VkBufferUsageFlags usage_) +{ + device = device_; + block_size = block_size_; + alignment = alignment_; + usage = usage_; +} + +void BufferPool::set_max_retained_blocks(size_t max_blocks) +{ + max_retained_blocks = max_blocks; +} + +BufferBlock::~BufferBlock() +{ +} + +void BufferPool::reset() +{ + blocks.clear(); +} + +BufferBlock BufferPool::allocate_block(VkDeviceSize size) +{ + BufferDomain ideal_domain = ((usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT) != 0) ? + BufferDomain::Host : BufferDomain::LinkedDeviceHost; + + BufferBlock block; + + BufferCreateInfo info; + info.domain = ideal_domain; + info.size = size; + info.usage = usage; + + block.buffer = device->create_buffer(info, nullptr); + device->set_name(*block.buffer, "chain-allocated-block"); + block.buffer->set_internal_sync_object(); + + // Try to map it, will fail unless the memory is host visible. + block.mapped = static_cast(device->map_host_buffer(*block.buffer, MEMORY_ACCESS_WRITE_BIT)); + + block.offset = 0; + block.alignment = alignment; + block.size = size; + return block; +} + +BufferBlock BufferPool::request_block(VkDeviceSize minimum_size) +{ + if ((minimum_size > block_size) || blocks.empty()) + { + return allocate_block(std::max(block_size, minimum_size)); + } + else + { + auto back = std::move(blocks.back()); + blocks.pop_back(); + + back.mapped = static_cast(device->map_host_buffer(*back.buffer, MEMORY_ACCESS_WRITE_BIT)); + back.offset = 0; + return back; + } +} + +void BufferPool::recycle_block(BufferBlock &block) +{ + VK_ASSERT(block.size == block_size); + + if (blocks.size() < max_retained_blocks) + blocks.push_back(std::move(block)); + else + block = {}; +} + +BufferPool::~BufferPool() +{ + VK_ASSERT(blocks.empty()); +} + +BufferBlockAllocation BufferBlock::allocate(VkDeviceSize allocate_size) +{ + auto aligned_offset = (offset + alignment - 1) & ~(alignment - 1); + if (aligned_offset + allocate_size <= size) + { + auto *ret = mapped + aligned_offset; + offset = aligned_offset + allocate_size; + return { ret, buffer, aligned_offset, allocate_size }; + } + else + return { nullptr, {}, 0, 0 }; +} + +void BufferBlock::unmap(Device &device) +{ + device.unmap_host_buffer(*buffer, MEMORY_ACCESS_WRITE_BIT); + mapped = nullptr; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer_pool.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer_pool.hpp new file mode 100644 index 00000000..e4076e93 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/buffer_pool.hpp @@ -0,0 +1,91 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include "intrusive.hpp" +#include +#include + +namespace Vulkan +{ +class Device; +class Buffer; + +struct BufferBlockAllocation +{ + uint8_t *host; + Util::IntrusivePtr buffer; + VkDeviceSize offset; + VkDeviceSize padded_size; +}; + +class BufferBlock +{ +public: + ~BufferBlock(); + + BufferBlockAllocation allocate(VkDeviceSize allocate_size); + bool is_mapped() const { return mapped != nullptr; } + const Buffer &get_buffer() const { return *buffer; } + void unmap(Device &device); + + VkDeviceSize get_offset() const { return offset; } + VkDeviceSize get_size() const { return size; } + +private: + friend class BufferPool; + Util::IntrusivePtr buffer; + VkDeviceSize offset = 0; + VkDeviceSize alignment = 0; + VkDeviceSize size = 0; + uint8_t *mapped = nullptr; +}; + +class BufferPool +{ +public: + ~BufferPool(); + void init(Device *device, VkDeviceSize block_size, VkDeviceSize alignment, VkBufferUsageFlags usage); + void reset(); + + void set_max_retained_blocks(size_t max_blocks); + + VkDeviceSize get_block_size() const + { + return block_size; + } + + BufferBlock request_block(VkDeviceSize minimum_size); + void recycle_block(BufferBlock &block); + +private: + Device *device = nullptr; + VkDeviceSize block_size = 0; + VkDeviceSize alignment = 0; + VkBufferUsageFlags usage = 0; + size_t max_retained_blocks = 0; + std::vector blocks; + BufferBlock allocate_block(VkDeviceSize size); +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_buffer.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_buffer.cpp new file mode 100644 index 00000000..15e822eb --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_buffer.cpp @@ -0,0 +1,4639 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "command_buffer.hpp" +#include "device.hpp" +#include "format.hpp" +#include "thread_id.hpp" +#include "vulkan_prerotate.hpp" +#include "indirect_layout.hpp" +#include "timer.hpp" +#include "breadcrumbs.hpp" +#include + +using namespace Util; + +namespace Vulkan +{ +template +void CommandBuffer::checkpoint(Ts &&... ts) +{ + device->managers.breadcrumbs.checkpoint(breadcrumbs, std::forward(ts)...); +} + +template +void CommandBuffer::checkpoint_with_signal(Ts &&... ts) +{ + device->managers.breadcrumbs.checkpoint_with_signal(breadcrumbs, std::forward(ts)...); +} + +void CommandBuffer::checkpoint(const char *tag) +{ + checkpoint(tag); +} + +static inline uint32_t get_combined_spec_constant_mask(const DeferredPipelineCompile &compile) +{ + return compile.potential_static_state.spec_constant_mask | + (compile.potential_static_state.internal_spec_constant_mask << VULKAN_NUM_USER_SPEC_CONSTANTS); +} + +CommandBuffer::CommandBuffer(Device *device_, VkCommandBuffer cmd_, VkPipelineCache cache, Type type_, bool secondary) + : device(device_) + , table(device_->get_device_table()) + , cmd(cmd_) + , type(type_) + , is_secondary(secondary) +{ + pipeline_state.cache = cache; + begin_compute(); + set_opaque_state(); + memset(&pipeline_state.static_state, 0, sizeof(pipeline_state.static_state)); + memset(&bindings, 0, sizeof(bindings)); + + // Set up extra state which PSO creation depends on implicitly. + // This needs to affect hashing to make Fossilize path behave as expected. + auto &features = device->get_device_features(); + pipeline_state.subgroup_size_tag = + (features.vk13_props.minSubgroupSize << 0) | + (features.vk13_props.maxSubgroupSize << 8); + + device->lock.read_only_cache.lock_read(); + + if (type == Type::Generic || type == Type::AsyncCompute) + { + if (device->get_device_features().descriptor_heap_features.descriptorHeap) + { + if (!secondary) + { + VkBindHeapInfoEXT bind_heap = { VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT }; + + auto heap = device->managers.descriptor_buffer.get_resource_heap(); + bind_heap.heapRange.address = heap.va; + bind_heap.heapRange.size = heap.size; + bind_heap.reservedRangeOffset = heap.reserved_offset; + bind_heap.reservedRangeSize = heap.size - heap.reserved_offset; + table.vkCmdBindResourceHeapEXT(cmd, &bind_heap); + + heap = device->managers.descriptor_buffer.get_sampler_heap(); + bind_heap.heapRange.address = heap.va; + bind_heap.heapRange.size = heap.size; + bind_heap.reservedRangeOffset = heap.reserved_offset; + bind_heap.reservedRangeSize = heap.size - heap.reserved_offset; + table.vkCmdBindSamplerHeapEXT(cmd, &bind_heap); + } + + desc_heap_enable = true; + } + else if (device->get_device_features().supports_descriptor_buffer) + { + VkDescriptorBufferBindingInfoEXT buf_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT }; + buf_info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT | + VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT; + buf_info.address = device->managers.descriptor_buffer.get_resource_heap().va; + table.vkCmdBindDescriptorBuffersEXT(cmd, 1, &buf_info); + desc_buffer_enable = true; + } + } +} + +CommandBuffer::~CommandBuffer() +{ + VK_ASSERT(!vbo_block.is_mapped()); + VK_ASSERT(!ibo_block.is_mapped()); + VK_ASSERT(!ubo_block.is_mapped()); + VK_ASSERT(!staging_block.is_mapped()); + device->lock.read_only_cache.unlock_read(); +} + +void CommandBuffer::fill_buffer(const Buffer &dst, uint32_t value) +{ + fill_buffer(dst, value, 0, VK_WHOLE_SIZE); +} + +void CommandBuffer::fill_buffer(const Buffer &dst, uint32_t value, VkDeviceSize offset, VkDeviceSize size) +{ + table.vkCmdFillBuffer(cmd, dst.get_buffer(), offset, size, value); + checkpoint("fill-buffer"); +} + +void CommandBuffer::copy_buffer(const Buffer &dst, VkDeviceSize dst_offset, const Buffer &src, VkDeviceSize src_offset, + VkDeviceSize size) +{ + const VkBufferCopy region = { + src_offset, dst_offset, size, + }; + table.vkCmdCopyBuffer(cmd, src.get_buffer(), dst.get_buffer(), 1, ®ion); + checkpoint_with_signal("copy-buffer"); +} + +void CommandBuffer::copy_buffer(const Buffer &dst, const Buffer &src) +{ + VK_ASSERT(dst.get_create_info().size == src.get_create_info().size); + copy_buffer(dst, 0, src, 0, dst.get_create_info().size); +} + +void CommandBuffer::copy_buffer(const Buffer &dst, const Buffer &src, const VkBufferCopy *copies, size_t count) +{ + table.vkCmdCopyBuffer(cmd, src.get_buffer(), dst.get_buffer(), count, copies); + checkpoint_with_signal("copy-buffer"); +} + +void CommandBuffer::copy_image(const Vulkan::Image &dst, const Vulkan::Image &src, const VkOffset3D &dst_offset, + const VkOffset3D &src_offset, const VkExtent3D &extent, + const VkImageSubresourceLayers &dst_subresource, + const VkImageSubresourceLayers &src_subresource) +{ + VkImageCopy region = {}; + region.dstOffset = dst_offset; + region.srcOffset = src_offset; + region.extent = extent; + region.srcSubresource = src_subresource; + region.dstSubresource = dst_subresource; + + table.vkCmdCopyImage(cmd, src.get_image(), src.get_layout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), + dst.get_image(), dst.get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + 1, ®ion); + checkpoint_with_signal("copy-image"); +} + +void CommandBuffer::copy_image(const Image &dst, const Image &src) +{ + uint32_t levels = src.get_create_info().levels; + VK_ASSERT(src.get_create_info().levels == dst.get_create_info().levels); + VK_ASSERT(src.get_create_info().width == dst.get_create_info().width); + VK_ASSERT(src.get_create_info().height == dst.get_create_info().height); + VK_ASSERT(src.get_create_info().depth == dst.get_create_info().depth); + VK_ASSERT(src.get_create_info().type == dst.get_create_info().type); + VK_ASSERT(src.get_create_info().layers == dst.get_create_info().layers); + VK_ASSERT(src.get_create_info().levels == dst.get_create_info().levels); + + VkImageCopy regions[32] = {}; + + for (uint32_t i = 0; i < levels; i++) + { + auto ®ion = regions[i]; + region.extent.width = src.get_create_info().width; + region.extent.height = src.get_create_info().height; + region.extent.depth = src.get_create_info().depth; + region.srcSubresource.aspectMask = format_to_aspect_mask(src.get_format()); + region.srcSubresource.layerCount = src.get_create_info().layers; + region.dstSubresource.aspectMask = format_to_aspect_mask(dst.get_format()); + region.dstSubresource.layerCount = dst.get_create_info().layers; + region.srcSubresource.mipLevel = i; + region.dstSubresource.mipLevel = i; + VK_ASSERT(region.srcSubresource.aspectMask == region.dstSubresource.aspectMask); + } + + table.vkCmdCopyImage(cmd, src.get_image(), src.get_layout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), + dst.get_image(), dst.get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + levels, regions); + checkpoint_with_signal("copy-image"); +} + +void CommandBuffer::copy_buffer_to_image(const Image &image, const Buffer &buffer, unsigned num_blits, + const VkBufferImageCopy *blits) +{ + table.vkCmdCopyBufferToImage(cmd, buffer.get_buffer(), + image.get_image(), image.get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), num_blits, blits); + checkpoint_with_signal("copy-buffer-to-image"); +} + +void CommandBuffer::copy_image_to_buffer(const Buffer &buffer, const Image &image, unsigned num_blits, + const VkBufferImageCopy *blits) +{ + table.vkCmdCopyImageToBuffer(cmd, image.get_image(), image.get_layout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), + buffer.get_buffer(), num_blits, blits); + checkpoint_with_signal("copy-image-to-buffer"); +} + +void CommandBuffer::copy_buffer_to_image(const Image &image, const Buffer &src, VkDeviceSize buffer_offset, + const VkOffset3D &offset, const VkExtent3D &extent, unsigned row_length, + unsigned slice_height, const VkImageSubresourceLayers &subresource) +{ + const VkBufferImageCopy region = { + buffer_offset, + row_length, slice_height, + subresource, offset, extent, + }; + table.vkCmdCopyBufferToImage(cmd, src.get_buffer(), image.get_image(), image.get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + 1, ®ion); + checkpoint_with_signal("copy-buffer-to-image"); +} + +void CommandBuffer::copy_image_to_buffer(const Buffer &buffer, const Image &image, VkDeviceSize buffer_offset, + const VkOffset3D &offset, const VkExtent3D &extent, unsigned row_length, + unsigned slice_height, const VkImageSubresourceLayers &subresource) +{ + const VkBufferImageCopy region = { + buffer_offset, + row_length, slice_height, + subresource, offset, extent, + }; + table.vkCmdCopyImageToBuffer(cmd, image.get_image(), image.get_layout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), + buffer.get_buffer(), 1, ®ion); + checkpoint_with_signal("copy-image-to-buffer"); +} + +void CommandBuffer::clear_image(const Image &image, const VkClearValue &value) +{ + auto aspect = format_to_aspect_mask(image.get_format()); + clear_image(image, value, aspect); +} + +void CommandBuffer::clear_image(const Image &image, const VkClearValue &value, VkImageAspectFlags aspect) +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(!actual_render_pass); + + VkImageSubresourceRange range = {}; + range.aspectMask = aspect; + range.baseArrayLayer = 0; + range.baseMipLevel = 0; + range.levelCount = image.get_create_info().levels; + range.layerCount = image.get_create_info().layers; + if (aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) + { + table.vkCmdClearDepthStencilImage(cmd, image.get_image(), image.get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + &value.depthStencil, 1, &range); + } + else + { + table.vkCmdClearColorImage(cmd, image.get_image(), image.get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + &value.color, 1, &range); + } +} + +void CommandBuffer::clear_quad(unsigned attachment, const VkClearRect &rect, const VkClearValue &value, + VkImageAspectFlags aspect) +{ + VK_ASSERT(framebuffer); + VK_ASSERT(actual_render_pass); + VkClearAttachment att = {}; + att.clearValue = value; + att.colorAttachment = attachment; + att.aspectMask = aspect; + + auto tmp_rect = rect; + rect2d_transform_xy(tmp_rect.rect, current_framebuffer_surface_transform, + framebuffer->get_width(), framebuffer->get_height()); + table.vkCmdClearAttachments(cmd, 1, &att, 1, &tmp_rect); +} + +void CommandBuffer::clear_quad(const VkClearRect &rect, const VkClearAttachment *attachments, unsigned num_attachments) +{ + VK_ASSERT(framebuffer); + VK_ASSERT(actual_render_pass); + auto tmp_rect = rect; + rect2d_transform_xy(tmp_rect.rect, current_framebuffer_surface_transform, + framebuffer->get_width(), framebuffer->get_height()); + table.vkCmdClearAttachments(cmd, num_attachments, attachments, 1, &tmp_rect); +} + +void CommandBuffer::begin_barrier_batch() +{ + VK_ASSERT(!barrier_batch.active); + barrier_batch.active = true; +} + +void CommandBuffer::end_barrier_batch() +{ + VK_ASSERT(barrier_batch.active); + barrier_batch.active = false; + + VkDependencyInfo dep = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO }; + dep.pMemoryBarriers = barrier_batch.memory_barriers.data(); + dep.memoryBarrierCount = barrier_batch.memory_barriers.size(); + dep.pBufferMemoryBarriers = barrier_batch.buffer_barriers.data(); + dep.bufferMemoryBarrierCount = barrier_batch.buffer_barriers.size(); + dep.pImageMemoryBarriers = barrier_batch.image_barriers.data(); + dep.imageMemoryBarrierCount = barrier_batch.image_barriers.size(); + + barrier(dep); + + barrier_batch.memory_barriers.clear(); + barrier_batch.buffer_barriers.clear(); + barrier_batch.image_barriers.clear(); +} + +void CommandBuffer::full_barrier() +{ + VK_ASSERT(!actual_render_pass); + VK_ASSERT(!framebuffer); + barrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_ACCESS_MEMORY_WRITE_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT); +} + +void CommandBuffer::pixel_barrier() +{ + VK_ASSERT(actual_render_pass); + VK_ASSERT(framebuffer); + VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER }; + barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + table.vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_DEPENDENCY_BY_REGION_BIT, 1, &barrier, 0, nullptr, 0, nullptr); +} + +void CommandBuffer::barrier(VkPipelineStageFlags2 src_stages, VkAccessFlags2 src_access, + VkPipelineStageFlags2 dst_stages, VkAccessFlags2 dst_access) +{ + VkDependencyInfo dep = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO }; + VkMemoryBarrier2 b = { VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 }; + dep.memoryBarrierCount = 1; + dep.pMemoryBarriers = &b; + b.srcStageMask = src_stages; + b.dstStageMask = dst_stages; + b.srcAccessMask = src_access; + b.dstAccessMask = dst_access; + barrier(dep); +} + +static inline bool is_legacy_layout(VkImageLayout layout) +{ + switch (layout) + { + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return true; + + default: + return false; + } +} + +void CommandBuffer::barrier(const VkDependencyInfo &dep) +{ + VK_ASSERT(!actual_render_pass); + VK_ASSERT(!framebuffer); + + if (barrier_batch.active) + { + if (dep.memoryBarrierCount) + { + barrier_batch.memory_barriers.insert( + barrier_batch.memory_barriers.end(), + dep.pMemoryBarriers, + dep.pMemoryBarriers + dep.memoryBarrierCount); + } + + if (dep.bufferMemoryBarrierCount) + { + barrier_batch.buffer_barriers.insert( + barrier_batch.buffer_barriers.end(), + dep.pBufferMemoryBarriers, + dep.pBufferMemoryBarriers + dep.bufferMemoryBarrierCount); + } + + if (dep.imageMemoryBarrierCount) + { + barrier_batch.image_barriers.insert( + barrier_batch.image_barriers.end(), + dep.pImageMemoryBarriers, + dep.pImageMemoryBarriers + dep.imageMemoryBarrierCount); + } + + return; + } + +#ifdef VULKAN_DEBUG + VkPipelineStageFlags2 stages = 0; + VkAccessFlags2 access = 0; + + for (uint32_t i = 0; i < dep.memoryBarrierCount; i++) + { + auto &b = dep.pMemoryBarriers[i]; + stages |= b.srcStageMask | b.dstStageMask; + access |= b.srcAccessMask | b.dstAccessMask; + } + + for (uint32_t i = 0; i < dep.bufferMemoryBarrierCount; i++) + { + auto &b = dep.pBufferMemoryBarriers[i]; + stages |= b.srcStageMask | b.dstStageMask; + access |= b.srcAccessMask | b.dstAccessMask; + } + + for (uint32_t i = 0; i < dep.imageMemoryBarrierCount; i++) + { + auto &b = dep.pImageMemoryBarriers[i]; + stages |= b.srcStageMask | b.dstStageMask; + access |= b.srcAccessMask | b.dstAccessMask; + } + + if (stages & VK_PIPELINE_STAGE_TRANSFER_BIT) + LOGW("Using deprecated TRANSFER stage.\n"); + if (stages & VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT) + LOGW("Using deprecated BOTTOM_OF_PIPE stage.\n"); + if (stages & VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT) + LOGW("Using deprecated TOP_OF_PIPE stage.\n"); + + if (access & VK_ACCESS_SHADER_READ_BIT) + LOGW("Using deprecated SHADER_READ access.\n"); + if (stages & VK_ACCESS_SHADER_WRITE_BIT) + LOGW("Using deprecated SHADER_WRITE access.\n"); + + for (uint32_t i = 0; i < dep.imageMemoryBarrierCount; i++) + { + VK_ASSERT(!is_legacy_layout(dep.pImageMemoryBarriers[i].oldLayout) && + !is_legacy_layout(dep.pImageMemoryBarriers[i].newLayout)); + } +#endif + + table.vkCmdPipelineBarrier2(cmd, &dep); + checkpoint_with_signal("barrier"); +} + +void CommandBuffer::buffer_barrier(const Buffer &buffer, + VkPipelineStageFlags2 src_stages, VkAccessFlags2 src_access, + VkPipelineStageFlags2 dst_stages, VkAccessFlags2 dst_access) +{ + VkBufferMemoryBarrier2 b = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 }; + VkDependencyInfo dep = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO }; + + b.srcAccessMask = src_access; + b.dstAccessMask = dst_access; + b.buffer = buffer.get_buffer(); + b.offset = 0; + b.size = VK_WHOLE_SIZE; + b.srcStageMask = src_stages; + b.dstStageMask = dst_stages; + b.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + b.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + + dep.bufferMemoryBarrierCount = 1; + dep.pBufferMemoryBarriers = &b; + + barrier(dep); +} + +// Buffers are always CONCURRENT. +static uint32_t deduce_acquire_release_family_index(Device &device) +{ + uint32_t family = VK_QUEUE_FAMILY_IGNORED; + auto &queue_info = device.get_queue_info(); + for (auto &i : queue_info.family_indices) + { + if (i != VK_QUEUE_FAMILY_IGNORED) + { + if (family == VK_QUEUE_FAMILY_IGNORED) + family = i; + else if (i != family) + return VK_QUEUE_FAMILY_IGNORED; + } + } + + return family; +} + +static uint32_t deduce_acquire_release_family_index(Device &device, const Image &image, uint32_t family_index) +{ + uint32_t family = family_index; + auto &queue_info = device.get_queue_info(); + + if (image.get_create_info().misc & IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT) + if (queue_info.family_indices[QUEUE_INDEX_GRAPHICS] != family) + return VK_QUEUE_FAMILY_IGNORED; + + if (image.get_create_info().misc & IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT) + { + if (queue_info.family_indices[QUEUE_INDEX_COMPUTE] != family) + return VK_QUEUE_FAMILY_IGNORED; + } + + if (image.get_create_info().misc & IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT) + if (queue_info.family_indices[QUEUE_INDEX_COMPUTE] != family) + return VK_QUEUE_FAMILY_IGNORED; + + return family; +} + +void CommandBuffer::release_image_barrier( + const Image &image, + VkImageLayout old_layout, VkImageLayout new_layout, + VkPipelineStageFlags2 src_stage, VkAccessFlags2 src_access, + uint32_t dst_queue_family) +{ + VkImageMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 }; + uint32_t family_index = device->get_queue_info().family_indices[device->get_physical_queue_type(type)]; + + barrier.image = image.get_image(); + barrier.subresourceRange = { + format_to_aspect_mask(image.get_format()), + 0, VK_REMAINING_MIP_LEVELS, + 0, VK_REMAINING_ARRAY_LAYERS + }; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + + barrier.srcQueueFamilyIndex = deduce_acquire_release_family_index(*device, image, family_index); + barrier.dstQueueFamilyIndex = dst_queue_family; + + barrier.srcAccessMask = src_access; + barrier.srcStageMask = src_stage; + + image_barriers(1, &barrier); +} + +void CommandBuffer::acquire_image_barrier( + const Image &image, + VkImageLayout old_layout, VkImageLayout new_layout, + VkPipelineStageFlags2 dst_stage, VkAccessFlags2 dst_access, + uint32_t src_queue_family) +{ + VkImageMemoryBarrier2 b = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 }; + uint32_t family_index = device->get_queue_info().family_indices[device->get_physical_queue_type(type)]; + + b.image = image.get_image(); + b.subresourceRange = { + format_to_aspect_mask(image.get_format()), + 0, VK_REMAINING_MIP_LEVELS, + 0, VK_REMAINING_ARRAY_LAYERS + }; + b.oldLayout = old_layout; + b.newLayout = new_layout; + b.srcQueueFamilyIndex = src_queue_family; + b.dstQueueFamilyIndex = deduce_acquire_release_family_index(*device, image, family_index); + + b.dstStageMask = dst_stage; + b.dstAccessMask = dst_access; + + image_barriers(1, &b); +} + +void CommandBuffer::release_buffer_barrier( + const Buffer &buffer, + VkPipelineStageFlags2 src_stage, VkAccessFlags2 src_access, + uint32_t dst_queue_family) +{ + VkBufferMemoryBarrier2 b = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 }; + b.buffer = buffer.get_buffer(); + b.size = buffer.get_create_info().size; + b.srcQueueFamilyIndex = deduce_acquire_release_family_index(*device); + b.dstQueueFamilyIndex = dst_queue_family; + b.srcStageMask = src_stage; + b.srcAccessMask = src_access; + buffer_barriers(1, &b); +} + +void CommandBuffer::acquire_buffer_barrier( + const Buffer &buffer, + VkPipelineStageFlags2 dst_stage, VkAccessFlags2 dst_access, + uint32_t src_queue_family) +{ + VkBufferMemoryBarrier2 b = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 }; + b.buffer = buffer.get_buffer(); + b.size = buffer.get_create_info().size; + b.srcQueueFamilyIndex = src_queue_family; + b.dstQueueFamilyIndex = deduce_acquire_release_family_index(*device); + b.dstStageMask = dst_stage; + b.dstAccessMask = dst_access; + buffer_barriers(1, &b); +} + +void CommandBuffer::image_barrier(const Image &image, + VkImageLayout old_layout, VkImageLayout new_layout, + VkPipelineStageFlags2 src_stages, VkAccessFlags2 src_access, + VkPipelineStageFlags2 dst_stages, VkAccessFlags2 dst_access) +{ + VK_ASSERT(!actual_render_pass); + VK_ASSERT(!framebuffer); + VK_ASSERT(image.get_create_info().domain != ImageDomain::Transient); + VK_ASSERT(!is_legacy_layout(old_layout) && !is_legacy_layout(new_layout)); + + VkImageMemoryBarrier2 b = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 }; + b.srcAccessMask = src_access; + b.dstAccessMask = dst_access; + b.oldLayout = old_layout; + b.newLayout = new_layout; + b.image = image.get_image(); + b.subresourceRange.aspectMask = format_to_aspect_mask(image.get_create_info().format); + b.subresourceRange.levelCount = image.get_create_info().levels; + b.subresourceRange.layerCount = image.get_create_info().layers; + b.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + b.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + b.srcStageMask = src_stages; + b.dstStageMask = dst_stages; + + image_barriers(1, &b); +} + +void CommandBuffer::buffer_barriers(uint32_t buffer_barriers, const VkBufferMemoryBarrier2 *buffers) +{ + VkDependencyInfo dep = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO }; + dep.bufferMemoryBarrierCount = buffer_barriers; + dep.pBufferMemoryBarriers = buffers; + barrier(dep); +} + +void CommandBuffer::image_barriers(uint32_t image_barriers, const VkImageMemoryBarrier2 *images) +{ + VkDependencyInfo dep = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO }; + dep.imageMemoryBarrierCount = image_barriers; + dep.pImageMemoryBarriers = images; + barrier(dep); +} + +void CommandBuffer::barrier_prepare_generate_mipmap(const Image &image, VkImageLayout base_level_layout, + VkPipelineStageFlags2 src_stage, VkAccessFlags2 src_access, + bool need_top_level_barrier) +{ + auto &create_info = image.get_create_info(); + VkImageMemoryBarrier2 barriers[2] = {}; + VK_ASSERT(create_info.levels > 1); + (void)create_info; + + for (unsigned i = 0; i < 2; i++) + { + barriers[i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; + barriers[i].image = image.get_image(); + barriers[i].subresourceRange.aspectMask = format_to_aspect_mask(image.get_format()); + barriers[i].subresourceRange.layerCount = image.get_create_info().layers; + barriers[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[i].srcStageMask = src_stage; + barriers[i].dstStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; + + if (i == 0) + { + barriers[i].oldLayout = base_level_layout; + barriers[i].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barriers[i].srcAccessMask = src_access; + barriers[i].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barriers[i].subresourceRange.baseMipLevel = 0; + barriers[i].subresourceRange.levelCount = 1; + } + else + { + barriers[i].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + barriers[i].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barriers[i].srcAccessMask = 0; + barriers[i].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barriers[i].subresourceRange.baseMipLevel = 1; + barriers[i].subresourceRange.levelCount = image.get_create_info().levels - 1; + } + } + + image_barriers(need_top_level_barrier ? 2 : 1, need_top_level_barrier ? barriers : barriers + 1); +} + +void CommandBuffer::generate_mipmap(const Image &image) +{ + auto &create_info = image.get_create_info(); + VkOffset3D size = { int(create_info.width), int(create_info.height), int(create_info.depth) }; + const VkOffset3D origin = { 0, 0, 0 }; + + VK_ASSERT(image.get_layout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + VkImageMemoryBarrier2 b = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 }; + b.image = image.get_image(); + b.subresourceRange.levelCount = 1; + b.subresourceRange.layerCount = image.get_create_info().layers; + b.subresourceRange.aspectMask = format_to_aspect_mask(image.get_format()); + b.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + b.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + b.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + b.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + b.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + b.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + b.srcStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; + b.dstStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; + + for (unsigned i = 1; i < create_info.levels; i++) + { + VkOffset3D src_size = size; + size.x = std::max(size.x >> 1, 1); + size.y = std::max(size.y >> 1, 1); + size.z = std::max(size.z >> 1, 1); + + blit_image(image, image, + origin, size, origin, src_size, i, i - 1, 0, 0, create_info.layers, VK_FILTER_LINEAR); + + b.subresourceRange.baseMipLevel = i; + image_barriers(1, &b); + } +} + +void CommandBuffer::blit_image(const Image &dst, const Image &src, + const VkOffset3D &dst_offset, + const VkOffset3D &dst_extent, const VkOffset3D &src_offset, const VkOffset3D &src_extent, + unsigned dst_level, unsigned src_level, unsigned dst_base_layer, unsigned src_base_layer, + unsigned num_layers, VkFilter filter) +{ + const auto add_offset = [](const VkOffset3D &a, const VkOffset3D &b) -> VkOffset3D { + return { a.x + b.x, a.y + b.y, a.z + b.z }; + }; + + const VkImageBlit blit = { + { format_to_aspect_mask(src.get_create_info().format), src_level, src_base_layer, num_layers }, + { src_offset, add_offset(src_offset, src_extent) }, + { format_to_aspect_mask(dst.get_create_info().format), dst_level, dst_base_layer, num_layers }, + { dst_offset, add_offset(dst_offset, dst_extent) }, + }; + + table.vkCmdBlitImage(cmd, + src.get_image(), src.get_layout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), + dst.get_image(), dst.get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + 1, &blit, filter); +} + +void CommandBuffer::begin_context() +{ + dirty = ~0u; + dirty_sets_realloc = ~0u; + dirty_vbos = ~0u; + current_pipeline = {}; + current_pipeline_layout = VK_NULL_HANDLE; + pipeline_state.layout = nullptr; + pipeline_state.program = nullptr; + pipeline_state.potential_static_state.spec_constant_mask = 0; + pipeline_state.potential_static_state.internal_spec_constant_mask = 0; + memset(bindings.cookies, 0, sizeof(bindings.cookies)); + memset(bindings.secondary_cookies, 0, sizeof(bindings.secondary_cookies)); + memset(&index_state, 0, sizeof(index_state)); + memset(vbo.buffers, 0, sizeof(vbo.buffers)); + + if (debug_channel_buffer) + set_storage_buffer(VULKAN_NUM_DESCRIPTOR_SETS - 1, VULKAN_NUM_BINDINGS - 1, *debug_channel_buffer); + + VK_ASSERT(!barrier_batch.active); +} + +void CommandBuffer::begin_compute() +{ + is_compute = true; + begin_context(); +} + +void CommandBuffer::begin_graphics() +{ + is_compute = false; + begin_context(); + + // Vertex shaders which support prerotate are expected to include inc/prerotate.h and + // call prerotate_fixup_clip_xy(). + if (current_framebuffer_surface_transform != VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) + set_surface_transform_specialization_constants(); +} + +void CommandBuffer::init_viewport_scissor(const RenderPassInfo &info, const Framebuffer *fb) +{ + VkRect2D rect = info.render_area; + + uint32_t fb_width = fb->get_width(); + uint32_t fb_height = fb->get_height(); + + // Convert fb_width / fb_height to logical width / height if need be. + if (surface_transform_swaps_xy(current_framebuffer_surface_transform)) + std::swap(fb_width, fb_height); + + rect.offset.x = std::min(int32_t(fb_width), rect.offset.x); + rect.offset.y = std::min(int32_t(fb_height), rect.offset.y); + rect.extent.width = std::min(fb_width - rect.offset.x, rect.extent.width); + rect.extent.height = std::min(fb_height - rect.offset.y, rect.extent.height); + + viewport = { + float(rect.offset.x), float(rect.offset.y), + float(rect.extent.width), float(rect.extent.height), + 0.0f, 1.0f + }; + scissor = rect; +} + +CommandBufferHandle CommandBuffer::request_secondary_command_buffer(Device &device, const RenderPassInfo &info, + unsigned thread_index, unsigned subpass) +{ + auto *fb = &device.request_framebuffer(info); + auto cmd = device.request_secondary_command_buffer_for_thread(thread_index, fb, subpass); + cmd->init_surface_transform(info); + cmd->begin_graphics(); + + cmd->framebuffer = fb; + cmd->pipeline_state.compatible_render_pass = &fb->get_compatible_render_pass(); + cmd->actual_render_pass = &device.request_render_pass(info, false); + + unsigned i; + for (i = 0; i < info.num_color_attachments; i++) + cmd->framebuffer_attachments[i] = info.color_attachments[i]; + if (info.depth_stencil) + cmd->framebuffer_attachments[i++] = info.depth_stencil; + + cmd->init_viewport_scissor(info, fb); + cmd->pipeline_state.subpass_index = subpass; + cmd->current_contents = VK_SUBPASS_CONTENTS_INLINE; + + return cmd; +} + +CommandBufferHandle CommandBuffer::request_secondary_command_buffer(unsigned thread_index_, unsigned subpass_) +{ + VK_ASSERT(framebuffer); + VK_ASSERT(!is_secondary); + + auto secondary_cmd = device->request_secondary_command_buffer_for_thread(thread_index_, framebuffer, subpass_); + secondary_cmd->begin_graphics(); + + secondary_cmd->framebuffer = framebuffer; + secondary_cmd->pipeline_state.compatible_render_pass = pipeline_state.compatible_render_pass; + secondary_cmd->actual_render_pass = actual_render_pass; + memcpy(secondary_cmd->framebuffer_attachments, framebuffer_attachments, sizeof(framebuffer_attachments)); + + secondary_cmd->pipeline_state.subpass_index = subpass_; + secondary_cmd->viewport = viewport; + secondary_cmd->scissor = scissor; + secondary_cmd->current_contents = VK_SUBPASS_CONTENTS_INLINE; + + return secondary_cmd; +} + +void CommandBuffer::submit_secondary(CommandBufferHandle secondary) +{ + VK_ASSERT(!is_secondary); + VK_ASSERT(secondary->is_secondary); + VK_ASSERT(pipeline_state.subpass_index == secondary->pipeline_state.subpass_index); + VK_ASSERT(current_contents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); + + device->submit_secondary(*this, *secondary); +} + +void CommandBuffer::next_subpass(VkSubpassContents contents) +{ + VK_ASSERT(framebuffer); + VK_ASSERT(pipeline_state.compatible_render_pass); + VK_ASSERT(actual_render_pass); + pipeline_state.subpass_index++; + VK_ASSERT(pipeline_state.subpass_index < actual_render_pass->get_num_subpasses()); + table.vkCmdNextSubpass(cmd, contents); + current_contents = contents; + begin_graphics(); +} + +void CommandBuffer::set_surface_transform_specialization_constants() +{ + float transform[4]; + pipeline_state.potential_static_state.internal_spec_constant_mask = 0xf; + build_prerotate_matrix_2x2(current_framebuffer_surface_transform, transform); + for (unsigned i = 0; i < 4; i++) + { + memcpy(pipeline_state.potential_static_state.spec_constants + VULKAN_NUM_USER_SPEC_CONSTANTS, + transform, sizeof(transform)); + } +} + +void CommandBuffer::init_surface_transform(const RenderPassInfo &info) +{ + // Validate that all prerotate state matches, unless the attachments are transient, since we don't really care, + // and it gets messy to forward rotation state to them. + VkSurfaceTransformFlagBitsKHR prerorate = VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR; + for (unsigned i = 0; i < info.num_color_attachments; i++) + { + auto usage = info.color_attachments[i]->get_image().get_create_info().usage; + if ((usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) == 0) + { + auto image_prerotate = info.color_attachments[i]->get_image().get_surface_transform(); + if (prerorate == VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR) + { + prerorate = image_prerotate; + } + else if (prerorate != image_prerotate) + { + LOGE("Mismatch in prerotate state for color attachment %u! (%u != %u)\n", + i, unsigned(prerorate), unsigned(image_prerotate)); + } + } + } + + if (prerorate != VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR && info.depth_stencil) + { + auto usage = info.depth_stencil->get_image().get_create_info().usage; + if ((usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) == 0) + { + auto image_prerotate = info.depth_stencil->get_image().get_surface_transform(); + if (prerorate != image_prerotate) + LOGE("Mismatch in prerotate state for depth-stencil! (%u != %u)\n", unsigned(prerorate), unsigned(image_prerotate)); + } + } + + if (prerorate == VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR) + prerorate = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + current_framebuffer_surface_transform = prerorate; +} + +void CommandBuffer::begin_render_pass(const RenderPassInfo &info, VkSubpassContents contents) +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(!pipeline_state.compatible_render_pass); + VK_ASSERT(!actual_render_pass); + + framebuffer = &device->request_framebuffer(info); + init_surface_transform(info); + pipeline_state.compatible_render_pass = &framebuffer->get_compatible_render_pass(); + actual_render_pass = &device->request_render_pass(info, false); + pipeline_state.subpass_index = 0; + framebuffer_is_multiview = info.num_layers > 1; + + memset(framebuffer_attachments, 0, sizeof(framebuffer_attachments)); + unsigned att; + for (att = 0; att < info.num_color_attachments; att++) + framebuffer_attachments[att] = info.color_attachments[att]; + if (info.depth_stencil) + framebuffer_attachments[att++] = info.depth_stencil; + + init_viewport_scissor(info, framebuffer); + + VkClearValue clear_values[VULKAN_NUM_ATTACHMENTS + 1]; + unsigned num_clear_values = 0; + + for (unsigned i = 0; i < info.num_color_attachments; i++) + { + VK_ASSERT(info.color_attachments[i]); + if (info.clear_attachments & (1u << i)) + { + clear_values[i].color = info.clear_color[i]; + num_clear_values = i + 1; + } + + if (info.color_attachments[i]->get_image().is_swapchain_image()) + swapchain_touch_in_stages(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + } + + if (info.depth_stencil && (info.op_flags & RENDER_PASS_OP_CLEAR_DEPTH_STENCIL_BIT) != 0) + { + clear_values[info.num_color_attachments].depthStencil = info.clear_depth_stencil; + num_clear_values = info.num_color_attachments + 1; + } + + VkRenderPassBeginInfo begin_info = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO }; + begin_info.renderPass = actual_render_pass->get_render_pass(); + begin_info.framebuffer = framebuffer->get_framebuffer(); + begin_info.renderArea = scissor; + begin_info.clearValueCount = num_clear_values; + begin_info.pClearValues = clear_values; + + // In the render pass interface, we pretend we are rendering with normal + // un-rotated coordinates. + rect2d_transform_xy(begin_info.renderArea, current_framebuffer_surface_transform, + framebuffer->get_width(), framebuffer->get_height()); + + table.vkCmdBeginRenderPass(cmd, &begin_info, contents); + + current_contents = contents; + begin_graphics(); +} + +void CommandBuffer::end_render_pass() +{ + VK_ASSERT(framebuffer); + VK_ASSERT(actual_render_pass); + VK_ASSERT(pipeline_state.compatible_render_pass); + + table.vkCmdEndRenderPass(cmd); + + framebuffer = nullptr; + actual_render_pass = nullptr; + pipeline_state.compatible_render_pass = nullptr; + begin_compute(); +} + +static void log_compile_time(const char *tag, Hash hash, + int64_t time_ns, VkResult result, + CommandBuffer::CompileMode mode) +{ + bool stall = time_ns >= 5 * 1000 * 1000 && mode != CommandBuffer::CompileMode::AsyncThread; +#ifndef VULKAN_DEBUG + // If a compile takes more than 5 ms and it's not happening on an async thread, + // we consider it a stall. + if (stall) +#endif + { + double time_us = 1e-3 * double(time_ns); + const char *mode_str; + + switch (mode) + { + case CommandBuffer::CompileMode::Sync: + mode_str = "sync"; + break; + + case CommandBuffer::CompileMode::FailOnCompileRequired: + mode_str = "fail-on-compile-required"; + break; + + default: + mode_str = "async-thread"; + break; + } + +#ifdef VULKAN_DEBUG + if (!stall) + { + LOGI("Compile (%s, %016llx): thread %u - %.3f us (mode: %s, success: %s).\n", + tag, static_cast(hash), + get_current_thread_index(), + time_us, mode_str, result == VK_SUCCESS ? "yes" : "no"); + } + else +#endif + { + LOGW("Stalled compile (%s, %016llx): thread %u - %.3f us (mode: %s, success: %s).\n", + tag, static_cast(hash), + get_current_thread_index(), + time_us, mode_str, result == VK_SUCCESS ? "yes" : "no"); + } + } +} + +Pipeline CommandBuffer::build_compute_pipeline(Device *device, const DeferredPipelineCompile &compile, + CompileMode mode) +{ + // This can be called from outside a CommandBuffer content, so need to hold lock. + Util::RWSpinLockReadHolder holder{device->lock.read_only_cache}; + + // If we don't have pipeline creation cache control feature, + // we must assume compilation can be synchronous. + if (mode == CompileMode::FailOnCompileRequired && + (device->get_workarounds().broken_pipeline_cache_control || + !device->get_device_features().vk13_features.pipelineCreationCacheControl)) + { + return {}; + } + + auto &shader = *compile.program->get_shader(ShaderStage::Compute); + VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; + info.layout = compile.layout->get_layout(); + info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + info.stage.module = shader.get_module(); + info.stage.pName = "main"; + info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; + + VkSpecializationInfo spec_info = {}; + VkSpecializationMapEntry spec_entries[VULKAN_NUM_TOTAL_SPEC_CONSTANTS]; + auto mask = compile.layout->get_resource_layout().combined_spec_constant_mask & + get_combined_spec_constant_mask(compile); + + uint32_t spec_constants[VULKAN_NUM_TOTAL_SPEC_CONSTANTS]; + + if (mask) + { + info.stage.pSpecializationInfo = &spec_info; + spec_info.pData = spec_constants; + spec_info.pMapEntries = spec_entries; + + for_each_bit(mask, [&](uint32_t bit) { + auto &entry = spec_entries[spec_info.mapEntryCount]; + entry.offset = sizeof(uint32_t) * spec_info.mapEntryCount; + entry.size = sizeof(uint32_t); + entry.constantID = bit; + + spec_constants[spec_info.mapEntryCount] = compile.potential_static_state.spec_constants[bit]; + spec_info.mapEntryCount++; + }); + spec_info.dataSize = spec_info.mapEntryCount * sizeof(uint32_t); + } + + VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_size_info; + + if (compile.static_state.state.subgroup_control_size) + { + if (!setup_subgroup_size_control(*device, info.stage, subgroup_size_info, + VK_SHADER_STAGE_COMPUTE_BIT, + compile.static_state.state.subgroup_full_group, + compile.static_state.state.subgroup_minimum_size_log2, + compile.static_state.state.subgroup_maximum_size_log2)) + { + LOGE("Subgroup size configuration not supported.\n"); + return {}; + } + } + + VkPipelineCreateFlags2CreateInfoKHR flags2 = { VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR }; + auto heap = device->get_device_features().descriptor_heap_features.descriptorHeap; + + if (compile.static_state.state.indirect_bindable || heap) + { + flags2.pNext = info.pNext; + info.pNext = &flags2; + } + + if (compile.static_state.state.indirect_bindable) + { + flags2.flags |= VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT; + + auto supported_stages = device->get_device_features(). + device_generated_commands_properties.supportedIndirectCommandsShaderStagesPipelineBinding; + (void)supported_stages; + VK_ASSERT((supported_stages & VK_SHADER_STAGE_COMPUTE_BIT) != 0); + } + + VkPipeline compute_pipeline = VK_NULL_HANDLE; +#ifdef GRANITE_VULKAN_FOSSILIZE + device->register_compute_pipeline(compile.hash, info); +#endif + + auto &table = device->get_device_table(); + + if (mode == CompileMode::FailOnCompileRequired) + { + info.flags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; + flags2.flags |= VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; + } + + if (device->get_device_features().supports_descriptor_buffer) + { + info.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + flags2.flags |= VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT; + } + + // Setup mapping structures after Fossilize capture since we want a normalized capture. + VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = + { VK_STRUCTURE_TYPE_SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT }; + + if (heap) + { + flags2.flags |= VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT; + + auto &mappings = compile.layout->get_heap_mappings(); + mapping_info.mappingCount = uint32_t(mappings.size()); + mapping_info.pMappings = mappings.data(); + mapping_info.pNext = info.stage.pNext; + info.stage.pNext = &mapping_info; + } + + auto start_ts = Util::get_current_time_nsecs(); + VkResult vr = device->pipeline_binary_cache.create_pipeline(&info, compile.cache, &compute_pipeline); + auto end_ts = Util::get_current_time_nsecs(); + log_compile_time("compute", compile.hash, end_ts - start_ts, vr, mode); + + if (vr != VK_SUCCESS || compute_pipeline == VK_NULL_HANDLE) + { + if (vr < 0) + LOGE("Failed to create compute pipeline!\n"); + return {}; + } + + auto returned_pipeline = compile.program->add_pipeline(compile.hash, { compute_pipeline, 0 }); + if (returned_pipeline.pipeline != compute_pipeline) + table.vkDestroyPipeline(device->get_device(), compute_pipeline, nullptr); + return returned_pipeline; +} + +void CommandBuffer::extract_pipeline_state(DeferredPipelineCompile &compile) const +{ + compile = pipeline_state; + + if (!compile.program) + { + LOGE("Attempting to extract pipeline state when no program is bound.\n"); + return; + } + + if (is_compute) + update_hash_compute_pipeline(compile); + else + update_hash_graphics_pipeline(compile, nullptr); +} + +bool CommandBuffer::setup_subgroup_size_control( + Vulkan::Device &device, VkPipelineShaderStageCreateInfo &stage_info, + VkPipelineShaderStageRequiredSubgroupSizeCreateInfo &required_info, + VkShaderStageFlagBits stage, bool full_group, + unsigned min_size_log2, unsigned max_size_log2) +{ + if (!device.supports_subgroup_size_log2(full_group, min_size_log2, max_size_log2, stage)) + return false; + + auto &features = device.get_device_features(); + + if (full_group) + stage_info.flags |= VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT; + + // If subgroup size control is only enabled, we want varying subgroup size, whatever it is. + uint32_t min_subgroups = 1u << min_size_log2; + uint32_t max_subgroups = 1u << max_size_log2; + if ((min_size_log2 == 0 && max_size_log2 == 0) || + ((min_subgroups <= features.vk13_props.minSubgroupSize && + max_subgroups >= features.vk13_props.maxSubgroupSize))) + { + stage_info.flags |= VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT; + } + else + { + required_info = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO }; + + // Pick a fixed subgroup size. Prefer smallest subgroup size. + if (min_subgroups < features.vk13_props.minSubgroupSize) + required_info.requiredSubgroupSize = features.vk13_props.minSubgroupSize; + else + required_info.requiredSubgroupSize = min_subgroups; + + required_info.pNext = const_cast(stage_info.pNext); + stage_info.pNext = &required_info; + } + + return true; +} + +Pipeline CommandBuffer::build_graphics_pipeline(Device *device, const DeferredPipelineCompile &compile, + CompileMode mode) +{ + // This can be called from outside a CommandBuffer content, so need to hold lock. + Util::RWSpinLockReadHolder holder{device->lock.read_only_cache}; + + // If we don't have pipeline creation cache control feature, + // we must assume compilation can be synchronous. + if (mode == CompileMode::FailOnCompileRequired && + (device->get_workarounds().broken_pipeline_cache_control || + !device->get_device_features().vk13_features.pipelineCreationCacheControl)) + { + return {}; + } + + // Viewport state + VkPipelineViewportStateCreateInfo vp = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; + vp.viewportCount = 1; + vp.scissorCount = 1; + + // Dynamic state + VkPipelineDynamicStateCreateInfo dyn = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; + dyn.dynamicStateCount = 2; + VkDynamicState states[7] = { + VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_VIEWPORT, + }; + dyn.pDynamicStates = states; + + uint32_t dynamic_mask = COMMAND_BUFFER_DIRTY_VIEWPORT_BIT | COMMAND_BUFFER_DIRTY_SCISSOR_BIT; + + if (compile.static_state.state.depth_bias_enable) + { + states[dyn.dynamicStateCount++] = VK_DYNAMIC_STATE_DEPTH_BIAS; + dynamic_mask |= COMMAND_BUFFER_DIRTY_DEPTH_BIAS_BIT; + } + + if (compile.static_state.state.stencil_test) + { + states[dyn.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK; + states[dyn.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE; + states[dyn.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK; + dynamic_mask |= COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT; + } + + // Blend state + VkPipelineColorBlendAttachmentState blend_attachments[VULKAN_NUM_ATTACHMENTS]; + VkPipelineColorBlendStateCreateInfo blend = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; + blend.attachmentCount = compile.compatible_render_pass->get_num_color_attachments(compile.subpass_index); + blend.pAttachments = blend_attachments; + for (unsigned i = 0; i < blend.attachmentCount; i++) + { + auto &att = blend_attachments[i]; + att = {}; + + if (compile.compatible_render_pass->get_color_attachment(compile.subpass_index, i).attachment != VK_ATTACHMENT_UNUSED && + (compile.layout->get_resource_layout().render_target_mask & (1u << i))) + { + att.colorWriteMask = (compile.static_state.state.write_mask >> (4 * i)) & 0xf; + att.blendEnable = compile.static_state.state.blend_enable; + if (att.blendEnable) + { + att.alphaBlendOp = static_cast(compile.static_state.state.alpha_blend_op); + att.colorBlendOp = static_cast(compile.static_state.state.color_blend_op); + att.dstAlphaBlendFactor = static_cast(compile.static_state.state.dst_alpha_blend); + att.srcAlphaBlendFactor = static_cast(compile.static_state.state.src_alpha_blend); + att.dstColorBlendFactor = static_cast(compile.static_state.state.dst_color_blend); + att.srcColorBlendFactor = static_cast(compile.static_state.state.src_color_blend); + } + } + } + memcpy(blend.blendConstants, compile.potential_static_state.blend_constants, sizeof(blend.blendConstants)); + + // Depth state + VkPipelineDepthStencilStateCreateInfo ds = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; + ds.stencilTestEnable = compile.compatible_render_pass->has_stencil(compile.subpass_index) && compile.static_state.state.stencil_test != 0; + ds.depthTestEnable = compile.compatible_render_pass->has_depth(compile.subpass_index) && compile.static_state.state.depth_test != 0; + ds.depthWriteEnable = compile.compatible_render_pass->has_depth(compile.subpass_index) && compile.static_state.state.depth_write != 0; + + if (ds.depthTestEnable) + ds.depthCompareOp = static_cast(compile.static_state.state.depth_compare); + + if (ds.stencilTestEnable) + { + ds.front.compareOp = static_cast(compile.static_state.state.stencil_front_compare_op); + ds.front.passOp = static_cast(compile.static_state.state.stencil_front_pass); + ds.front.failOp = static_cast(compile.static_state.state.stencil_front_fail); + ds.front.depthFailOp = static_cast(compile.static_state.state.stencil_front_depth_fail); + ds.back.compareOp = static_cast(compile.static_state.state.stencil_back_compare_op); + ds.back.passOp = static_cast(compile.static_state.state.stencil_back_pass); + ds.back.failOp = static_cast(compile.static_state.state.stencil_back_fail); + ds.back.depthFailOp = static_cast(compile.static_state.state.stencil_back_depth_fail); + } + + // Vertex input + VkPipelineVertexInputStateCreateInfo vi = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; + VkVertexInputAttributeDescription vi_attribs[VULKAN_NUM_VERTEX_ATTRIBS]; + VkVertexInputBindingDescription vi_bindings[VULKAN_NUM_VERTEX_BUFFERS]; + + if (compile.program->get_shader(ShaderStage::Vertex)) + { + vi.pVertexAttributeDescriptions = vi_attribs; + uint32_t attr_mask = compile.layout->get_resource_layout().attribute_mask; + uint32_t binding_mask = 0; + for_each_bit(attr_mask, [&](uint32_t bit) { + auto &attr = vi_attribs[vi.vertexAttributeDescriptionCount++]; + attr.location = bit; + attr.binding = compile.attribs[bit].binding; + attr.format = compile.attribs[bit].format; + attr.offset = compile.attribs[bit].offset; + binding_mask |= 1u << attr.binding; + }); + + vi.pVertexBindingDescriptions = vi_bindings; + for_each_bit(binding_mask, [&](uint32_t bit) { + auto &bind = vi_bindings[vi.vertexBindingDescriptionCount++]; + bind.binding = bit; + bind.inputRate = compile.input_rates[bit]; + bind.stride = compile.strides[bit]; + }); + } + + // Input assembly + VkPipelineInputAssemblyStateCreateInfo ia = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; + ia.primitiveRestartEnable = compile.static_state.state.primitive_restart; + ia.topology = static_cast(compile.static_state.state.topology); + + // Multisample + VkPipelineMultisampleStateCreateInfo ms = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; + ms.rasterizationSamples = static_cast(compile.compatible_render_pass->get_sample_count(compile.subpass_index)); + + if (compile.compatible_render_pass->get_sample_count(compile.subpass_index) > 1) + { + ms.alphaToCoverageEnable = compile.static_state.state.alpha_to_coverage; + ms.alphaToOneEnable = compile.static_state.state.alpha_to_one; + ms.sampleShadingEnable = compile.static_state.state.sample_shading; + ms.minSampleShading = 1.0f; + } + + // Raster + VkPipelineRasterizationStateCreateInfo raster = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; + raster.cullMode = static_cast(compile.static_state.state.cull_mode); + raster.frontFace = static_cast(compile.static_state.state.front_face); + raster.lineWidth = 1.0f; + raster.polygonMode = compile.static_state.state.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL; + raster.depthBiasEnable = compile.static_state.state.depth_bias_enable != 0; + + VkPipelineRasterizationConservativeStateCreateInfoEXT conservative_raster = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT + }; + if (compile.static_state.state.conservative_raster) + { + if (device->get_device_features().supports_conservative_rasterization) + { + raster.pNext = &conservative_raster; + conservative_raster.conservativeRasterizationMode = VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT; + } + else + { + LOGE("Conservative rasterization is not supported on this device.\n"); + return {}; + } + } + + // Stages + VkPipelineShaderStageCreateInfo stages[Util::ecast(ShaderStage::Count)]; + unsigned num_stages = 0; + + VkSpecializationInfo spec_info[ecast(ShaderStage::Count)] = {}; + VkSpecializationMapEntry spec_entries[ecast(ShaderStage::Count)][VULKAN_NUM_TOTAL_SPEC_CONSTANTS]; + uint32_t spec_constants[Util::ecast(ShaderStage::Count)][VULKAN_NUM_TOTAL_SPEC_CONSTANTS]; + + VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_size_info_task; + VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_size_info_mesh; + + for (int i = 0; i < Util::ecast(ShaderStage::Count); i++) + { + auto mask = compile.layout->get_resource_layout().spec_constant_mask[i] & + get_combined_spec_constant_mask(compile); + + if (mask) + { + spec_info[i].pData = spec_constants[i]; + spec_info[i].pMapEntries = spec_entries[i]; + + for_each_bit(mask, [&](uint32_t bit) + { + auto &entry = spec_entries[i][spec_info[i].mapEntryCount]; + entry.offset = sizeof(uint32_t) * spec_info[i].mapEntryCount; + entry.size = sizeof(uint32_t); + entry.constantID = bit; + spec_constants[i][spec_info[i].mapEntryCount] = compile.potential_static_state.spec_constants[bit]; + spec_info[i].mapEntryCount++; + }); + spec_info[i].dataSize = spec_info[i].mapEntryCount * sizeof(uint32_t); + } + } + + for (int i = 0; i < Util::ecast(ShaderStage::Count); i++) + { + auto stage = static_cast(i); + if (compile.program->get_shader(stage)) + { + auto &s = stages[num_stages++]; + s = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }; + s.module = compile.program->get_shader(stage)->get_module(); + s.pName = "main"; + s.stage = static_cast(1u << i); + if (spec_info[i].mapEntryCount) + s.pSpecializationInfo = &spec_info[i]; + + if (stage == ShaderStage::Mesh || stage == ShaderStage::Task) + { + VkPipelineShaderStageRequiredSubgroupSizeCreateInfo *required_info; + unsigned min_size_log2, max_size_log2; + bool size_enabled, full_group; + + if (stage == ShaderStage::Mesh) + { + size_enabled = compile.static_state.state.subgroup_control_size; + full_group = compile.static_state.state.subgroup_full_group; + min_size_log2 = compile.static_state.state.subgroup_minimum_size_log2; + max_size_log2 = compile.static_state.state.subgroup_maximum_size_log2; + required_info = &subgroup_size_info_mesh; + } + else + { + size_enabled = compile.static_state.state.subgroup_control_size_task; + full_group = compile.static_state.state.subgroup_full_group_task; + min_size_log2 = compile.static_state.state.subgroup_minimum_size_log2_task; + max_size_log2 = compile.static_state.state.subgroup_maximum_size_log2_task; + required_info = &subgroup_size_info_task; + } + + if (size_enabled) + { + if (!setup_subgroup_size_control( + *device, s, *required_info, s.stage, + full_group, min_size_log2, max_size_log2)) + { + LOGE("Subgroup size configuration not supported.\n"); + return {}; + } + } + } + } + } + + VkGraphicsPipelineCreateInfo pipe = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; + pipe.layout = compile.layout->get_layout(); + pipe.renderPass = compile.compatible_render_pass->get_render_pass(); + pipe.subpass = compile.subpass_index; + + pipe.pViewportState = &vp; + pipe.pDynamicState = &dyn; + pipe.pColorBlendState = &blend; + pipe.pDepthStencilState = &ds; + if (compile.program->get_shader(ShaderStage::Vertex)) + { + pipe.pVertexInputState = &vi; + pipe.pInputAssemblyState = &ia; + } + pipe.pMultisampleState = &ms; + pipe.pRasterizationState = &raster; + pipe.pStages = stages; + pipe.stageCount = num_stages; + + VkPipelineCreateFlags2CreateInfoKHR flags2 = { VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR }; + auto heap = device->get_device_features().descriptor_heap_features.descriptorHeap; + + if (compile.static_state.state.indirect_bindable || heap) + { + flags2.pNext = pipe.pNext; + pipe.pNext = &flags2; + } + + if (compile.static_state.state.indirect_bindable) + { + flags2.flags |= VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT; + + auto supported_stages = device->get_device_features(). + device_generated_commands_properties.supportedIndirectCommandsShaderStagesPipelineBinding; + (void)supported_stages; + VK_ASSERT(!compile.program->get_shader(ShaderStage::Vertex) || (supported_stages & VK_SHADER_STAGE_VERTEX_BIT) != 0); + VK_ASSERT(!compile.program->get_shader(ShaderStage::Fragment) || (supported_stages & VK_SHADER_STAGE_FRAGMENT_BIT) != 0); + VK_ASSERT(!compile.program->get_shader(ShaderStage::Mesh) || (supported_stages & VK_SHADER_STAGE_MESH_BIT_EXT) != 0); + VK_ASSERT(!compile.program->get_shader(ShaderStage::Task) || (supported_stages & VK_SHADER_STAGE_TASK_BIT_EXT) != 0); + VK_ASSERT(!compile.program->get_shader(ShaderStage::Compute) || (supported_stages & VK_SHADER_STAGE_COMPUTE_BIT) != 0); + } + + VkPipeline pipeline = VK_NULL_HANDLE; +#ifdef GRANITE_VULKAN_FOSSILIZE + device->register_graphics_pipeline(compile.hash, pipe); +#endif + + // Patch in mapping structs late since we don't want to capture it in Fossilize. + // It is somewhat device dependent. + VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info[3]; + + if (heap) + { + flags2.flags |= VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT; + auto &mappings = compile.layout->get_heap_mappings(); + VK_ASSERT(pipe.stageCount <= 3); + + for (uint32_t i = 0; i < pipe.stageCount; i++) + { + mapping_info[i] = { VK_STRUCTURE_TYPE_SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT }; + mapping_info[i].mappingCount = uint32_t(mappings.size()); + mapping_info[i].pMappings = mappings.data(); + mapping_info[i].pNext = stages[i].pNext; + stages[i].pNext = &mapping_info[i]; + } + } + + auto &table = device->get_device_table(); + + if (mode == CompileMode::FailOnCompileRequired) + { + pipe.flags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; + flags2.flags |= VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; + } + + if (device->get_device_features().supports_descriptor_buffer) + { + pipe.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + flags2.flags |= VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT; + } + + auto start_ts = Util::get_current_time_nsecs(); + VkResult res = device->pipeline_binary_cache.create_pipeline(&pipe, compile.cache, &pipeline); + auto end_ts = Util::get_current_time_nsecs(); + log_compile_time("graphics", compile.hash, end_ts - start_ts, res, mode); + + if (res != VK_SUCCESS || pipeline == VK_NULL_HANDLE) + { + if (res < 0) + LOGE("Failed to create graphics pipeline!\n"); + return {}; + } + + auto returned_pipeline = compile.program->add_pipeline(compile.hash, { pipeline, dynamic_mask }); + if (returned_pipeline.pipeline != pipeline) + table.vkDestroyPipeline(device->get_device(), pipeline, nullptr); + return returned_pipeline; +} + +bool CommandBuffer::flush_compute_pipeline(bool synchronous) +{ + update_hash_compute_pipeline(pipeline_state); + current_pipeline = pipeline_state.program->get_pipeline(pipeline_state.hash); + if (current_pipeline.pipeline == VK_NULL_HANDLE) + { + current_pipeline = build_compute_pipeline( + device, pipeline_state, + synchronous ? CompileMode::Sync : CompileMode::FailOnCompileRequired); + } + return current_pipeline.pipeline != VK_NULL_HANDLE; +} + +void CommandBuffer::update_hash_compute_pipeline(DeferredPipelineCompile &compile) +{ + Hasher h; + h.u64(compile.program->get_hash()); + h.u64(compile.layout->get_hash()); + + // Spec constants. + auto &layout = compile.layout->get_resource_layout(); + uint32_t combined_spec_constant = layout.combined_spec_constant_mask; + combined_spec_constant &= get_combined_spec_constant_mask(compile); + h.u32(combined_spec_constant); + for_each_bit(combined_spec_constant, [&](uint32_t bit) { + h.u32(compile.potential_static_state.spec_constants[bit]); + }); + + if (compile.static_state.state.subgroup_control_size) + { + h.s32(1); + h.u32(compile.static_state.state.subgroup_minimum_size_log2); + h.u32(compile.static_state.state.subgroup_maximum_size_log2); + h.u32(compile.static_state.state.subgroup_full_group); + // Required for Fossilize since we don't know exactly how to lower these requirements to a PSO + // without knowing some device state. + h.u32(compile.subgroup_size_tag); + } + else + h.s32(0); + + compile.hash = h.get(); +} + +void CommandBuffer::update_hash_graphics_pipeline(DeferredPipelineCompile &compile, uint32_t *out_active_vbos) +{ + Hasher h; + uint32_t active_vbos = 0; + auto &layout = compile.layout->get_resource_layout(); + for_each_bit(layout.attribute_mask, [&](uint32_t bit) { + h.u32(bit); + active_vbos |= 1u << compile.attribs[bit].binding; + h.u32(compile.attribs[bit].binding); + h.u32(compile.attribs[bit].format); + h.u32(compile.attribs[bit].offset); + }); + + for_each_bit(active_vbos, [&](uint32_t bit) { + h.u32(compile.input_rates[bit]); + h.u32(compile.strides[bit]); + }); + + if (out_active_vbos) + *out_active_vbos = active_vbos; + + h.u64(compile.compatible_render_pass->get_hash()); + h.u32(compile.subpass_index); + h.u64(compile.program->get_hash()); + h.u64(compile.layout->get_hash()); + h.data(compile.static_state.words, sizeof(compile.static_state.words)); + + if (compile.static_state.state.blend_enable) + { + const auto needs_blend_constant = [](VkBlendFactor factor) { + return factor == VK_BLEND_FACTOR_CONSTANT_COLOR || factor == VK_BLEND_FACTOR_CONSTANT_ALPHA; + }; + bool b0 = needs_blend_constant(static_cast(compile.static_state.state.src_color_blend)); + bool b1 = needs_blend_constant(static_cast(compile.static_state.state.src_alpha_blend)); + bool b2 = needs_blend_constant(static_cast(compile.static_state.state.dst_color_blend)); + bool b3 = needs_blend_constant(static_cast(compile.static_state.state.dst_alpha_blend)); + if (b0 || b1 || b2 || b3) + h.data(reinterpret_cast(compile.potential_static_state.blend_constants), + sizeof(compile.potential_static_state.blend_constants)); + } + + // Spec constants. + uint32_t combined_spec_constant = layout.combined_spec_constant_mask; + combined_spec_constant &= get_combined_spec_constant_mask(compile); + h.u32(combined_spec_constant); + for_each_bit(combined_spec_constant, [&](uint32_t bit) { + h.u32(compile.potential_static_state.spec_constants[bit]); + }); + + if (compile.program->get_shader(ShaderStage::Task)) + { + if (compile.static_state.state.subgroup_control_size_task) + { + h.s32(1); + h.u32(compile.static_state.state.subgroup_minimum_size_log2_task); + h.u32(compile.static_state.state.subgroup_maximum_size_log2_task); + h.u32(compile.static_state.state.subgroup_full_group_task); + // Required for Fossilize since we don't know exactly how to lower these requirements to a PSO + // without knowing some device state. + h.u32(compile.subgroup_size_tag); + } + else + h.s32(0); + } + + if (compile.program->get_shader(ShaderStage::Mesh)) + { + if (compile.static_state.state.subgroup_control_size) + { + h.s32(1); + h.u32(compile.static_state.state.subgroup_minimum_size_log2); + h.u32(compile.static_state.state.subgroup_maximum_size_log2); + h.u32(compile.static_state.state.subgroup_full_group); + // Required for Fossilize since we don't know exactly how to lower these requirements to a PSO + // without knowing some device state. + h.u32(compile.subgroup_size_tag); + } + else + h.s32(0); + } + + compile.hash = h.get(); +} + +bool CommandBuffer::flush_graphics_pipeline(bool synchronous) +{ + auto mode = synchronous ? CompileMode::Sync : CompileMode::FailOnCompileRequired; + update_hash_graphics_pipeline(pipeline_state, &active_vbos); + current_pipeline = pipeline_state.program->get_pipeline(pipeline_state.hash); + if (current_pipeline.pipeline == VK_NULL_HANDLE) + current_pipeline = build_graphics_pipeline(device, pipeline_state, mode); + return current_pipeline.pipeline != VK_NULL_HANDLE; +} + +void CommandBuffer::bind_pipeline(VkPipelineBindPoint bind_point, VkPipeline pipeline, uint32_t active_dynamic_state) +{ + table.vkCmdBindPipeline(cmd, bind_point, pipeline); + + // If some dynamic state is static in the pipeline it clobbers the dynamic state. + // As a performance optimization don't clobber everything. + uint32_t static_state_clobber = ~active_dynamic_state & COMMAND_BUFFER_DYNAMIC_BITS; + set_dirty(static_state_clobber); +} + +VkPipeline CommandBuffer::flush_compute_state(bool synchronous) +{ + VK_ASSERT(!barrier_batch.active); + if (!pipeline_state.program) + return VK_NULL_HANDLE; + VK_ASSERT(pipeline_state.layout); + + if (current_pipeline.pipeline == VK_NULL_HANDLE) + set_dirty(COMMAND_BUFFER_DIRTY_PIPELINE_BIT); + + if (get_and_clear(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT | COMMAND_BUFFER_DIRTY_PIPELINE_BIT)) + { + VkPipeline old_pipe = current_pipeline.pipeline; + if (!flush_compute_pipeline(synchronous)) + return VK_NULL_HANDLE; + + if (old_pipe != current_pipeline.pipeline) + bind_pipeline(VK_PIPELINE_BIND_POINT_COMPUTE, current_pipeline.pipeline, current_pipeline.dynamic_mask); + } + + if (current_pipeline.pipeline == VK_NULL_HANDLE) + return VK_NULL_HANDLE; + + flush_descriptor_sets(); + + if (get_and_clear(COMMAND_BUFFER_DIRTY_PUSH_CONSTANTS_BIT)) + { + auto &range = pipeline_state.layout->get_resource_layout().push_constant_range; + + if (desc_heap_enable) + { + if (range.size) + { + VkPushDataInfoEXT info = { VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT }; + info.data.size = range.size; + info.data.address = bindings.push_constant_data; + table.vkCmdPushDataEXT(cmd, &info); + } + } + else + { + if (range.stageFlags != 0) + { + VK_ASSERT(range.offset == 0); + table.vkCmdPushConstants(cmd, current_pipeline_layout, range.stageFlags, + 0, range.size, + bindings.push_constant_data); + } + } + } + + return current_pipeline.pipeline; +} + +VkPipeline CommandBuffer::flush_render_state(bool synchronous) +{ + VK_ASSERT(!barrier_batch.active); + if (!pipeline_state.program) + return VK_NULL_HANDLE; + VK_ASSERT(pipeline_state.layout); + + if (current_pipeline.pipeline == VK_NULL_HANDLE) + set_dirty(COMMAND_BUFFER_DIRTY_PIPELINE_BIT); + + // We've invalidated pipeline state, update the VkPipeline. + if (get_and_clear(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT | COMMAND_BUFFER_DIRTY_PIPELINE_BIT | + COMMAND_BUFFER_DIRTY_STATIC_VERTEX_BIT)) + { + VkPipeline old_pipe = current_pipeline.pipeline; + if (!flush_graphics_pipeline(synchronous)) + return VK_NULL_HANDLE; + + if (old_pipe != current_pipeline.pipeline) + bind_pipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, current_pipeline.pipeline, current_pipeline.dynamic_mask); + +#ifdef VULKAN_DEBUG + if (current_framebuffer_surface_transform != VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) + { + // Make sure that if we're using prerotate, our vertex shaders have prerotate. + auto spec_constant_mask = pipeline_state.layout->get_resource_layout().combined_spec_constant_mask; + constexpr uint32_t expected_mask = 0xfu << VULKAN_NUM_USER_SPEC_CONSTANTS; + VK_ASSERT((spec_constant_mask & expected_mask) == expected_mask); + } +#endif + } + + if (current_pipeline.pipeline == VK_NULL_HANDLE) + return VK_NULL_HANDLE; + + flush_descriptor_sets(); + + if (get_and_clear(COMMAND_BUFFER_DIRTY_PUSH_CONSTANTS_BIT)) + { + auto &range = pipeline_state.layout->get_resource_layout().push_constant_range; + + if (desc_heap_enable) + { + if (range.size) + { + VkPushDataInfoEXT info = { VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT }; + info.data.size = range.size; + info.data.address = bindings.push_constant_data; + table.vkCmdPushDataEXT(cmd, &info); + } + } + else + { + if (range.stageFlags != 0) + { + VK_ASSERT(range.offset == 0); + table.vkCmdPushConstants(cmd, current_pipeline_layout, range.stageFlags, + 0, range.size, + bindings.push_constant_data); + } + } + } + + if (get_and_clear(COMMAND_BUFFER_DIRTY_VIEWPORT_BIT)) + { + if (current_framebuffer_surface_transform != VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) + { + auto tmp_viewport = viewport; + viewport_transform_xy(tmp_viewport, current_framebuffer_surface_transform, + framebuffer->get_width(), framebuffer->get_height()); + table.vkCmdSetViewport(cmd, 0, 1, &tmp_viewport); + } + else + table.vkCmdSetViewport(cmd, 0, 1, &viewport); + } + + if (get_and_clear(COMMAND_BUFFER_DIRTY_SCISSOR_BIT)) + { + auto tmp_scissor = scissor; + rect2d_transform_xy(tmp_scissor, current_framebuffer_surface_transform, + framebuffer->get_width(), framebuffer->get_height()); + rect2d_clip(tmp_scissor); + table.vkCmdSetScissor(cmd, 0, 1, &tmp_scissor); + } + + if (pipeline_state.static_state.state.depth_bias_enable && get_and_clear(COMMAND_BUFFER_DIRTY_DEPTH_BIAS_BIT)) + table.vkCmdSetDepthBias(cmd, dynamic_state.depth_bias_constant, 0.0f, dynamic_state.depth_bias_slope); + if (pipeline_state.static_state.state.stencil_test && get_and_clear(COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT)) + { + table.vkCmdSetStencilCompareMask(cmd, VK_STENCIL_FACE_FRONT_BIT, dynamic_state.front_compare_mask); + table.vkCmdSetStencilReference(cmd, VK_STENCIL_FACE_FRONT_BIT, dynamic_state.front_reference); + table.vkCmdSetStencilWriteMask(cmd, VK_STENCIL_FACE_FRONT_BIT, dynamic_state.front_write_mask); + table.vkCmdSetStencilCompareMask(cmd, VK_STENCIL_FACE_BACK_BIT, dynamic_state.back_compare_mask); + table.vkCmdSetStencilReference(cmd, VK_STENCIL_FACE_BACK_BIT, dynamic_state.back_reference); + table.vkCmdSetStencilWriteMask(cmd, VK_STENCIL_FACE_BACK_BIT, dynamic_state.back_write_mask); + } + + uint32_t update_vbo_mask = dirty_vbos & active_vbos; + for_each_bit_range(update_vbo_mask, [&](uint32_t binding, uint32_t binding_count) { +#ifdef VULKAN_DEBUG + for (unsigned i = binding; i < binding + binding_count; i++) + VK_ASSERT(vbo.buffers[i] != VK_NULL_HANDLE); +#endif + table.vkCmdBindVertexBuffers(cmd, binding, binding_count, vbo.buffers + binding, vbo.offsets + binding); + }); + dirty_vbos &= ~update_vbo_mask; + + return current_pipeline.pipeline; +} + +bool CommandBuffer::flush_pipeline_state_without_blocking() +{ + if (is_compute) + return flush_compute_state(false) != VK_NULL_HANDLE; + else + return flush_render_state(false) != VK_NULL_HANDLE; +} + +VkPipeline CommandBuffer::get_current_compute_pipeline() +{ + return flush_compute_state(true); +} + +VkPipeline CommandBuffer::get_current_graphics_pipeline() +{ + return flush_render_state(true); +} + +void CommandBuffer::wait_events(uint32_t count, const PipelineEvent *events, const VkDependencyInfo *deps) +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(!actual_render_pass); + + Util::SmallVector vk_events; + vk_events.reserve(count); + for (uint32_t i = 0; i < count; i++) + vk_events.push_back(events[i]->get_event()); + + if (device->get_workarounds().emulate_event_as_pipeline_barrier) + { + for (uint32_t i = 0; i < count; i++) + barrier(deps[i]); + } + else + { + table.vkCmdWaitEvents2(cmd, count, vk_events.data(), deps); + } +} + +PipelineEvent CommandBuffer::signal_event(const VkDependencyInfo &dep) +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(!actual_render_pass); + auto event = device->begin_signal_event(); + + if (!device->get_workarounds().emulate_event_as_pipeline_barrier) + table.vkCmdSetEvent2(cmd, event->get_event(), &dep); + return event; +} + +void CommandBuffer::set_vertex_attrib(uint32_t attrib, uint32_t binding, VkFormat format, VkDeviceSize offset) +{ + VK_ASSERT(attrib < VULKAN_NUM_VERTEX_ATTRIBS); + VK_ASSERT(framebuffer); + + auto &attr = pipeline_state.attribs[attrib]; + + if (attr.binding != binding || attr.format != format || attr.offset != offset) + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_VERTEX_BIT); + + VK_ASSERT(binding < VULKAN_NUM_VERTEX_BUFFERS); + + attr.binding = binding; + attr.format = format; + attr.offset = offset; +} + +void CommandBuffer::set_index_buffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType index_type) +{ + if (index_state.buffer == buffer.get_buffer() && + index_state.offset == offset && + index_state.index_type == index_type) + { + return; + } + + index_state.buffer = buffer.get_buffer(); + index_state.offset = offset; + index_state.index_type = index_type; + table.vkCmdBindIndexBuffer(cmd, buffer.get_buffer(), offset, index_type); +} + +void CommandBuffer::set_vertex_binding(uint32_t binding, const Buffer &buffer, VkDeviceSize offset, VkDeviceSize stride, + VkVertexInputRate step_rate) +{ + VK_ASSERT(binding < VULKAN_NUM_VERTEX_BUFFERS); + VK_ASSERT(framebuffer); + + VkBuffer vkbuffer = buffer.get_buffer(); + if (vbo.buffers[binding] != vkbuffer || vbo.offsets[binding] != offset) + dirty_vbos |= 1u << binding; + if (pipeline_state.strides[binding] != stride || pipeline_state.input_rates[binding] != step_rate) + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_VERTEX_BIT); + + vbo.buffers[binding] = vkbuffer; + vbo.offsets[binding] = offset; + pipeline_state.strides[binding] = stride; + pipeline_state.input_rates[binding] = step_rate; +} + +void CommandBuffer::set_viewport(const VkViewport &viewport_) +{ + VK_ASSERT(framebuffer); + viewport = viewport_; + set_dirty(COMMAND_BUFFER_DIRTY_VIEWPORT_BIT); +} + +const VkViewport &CommandBuffer::get_viewport() const +{ + return viewport; +} + +void CommandBuffer::set_scissor(const VkRect2D &rect) +{ + VK_ASSERT(framebuffer); + VK_ASSERT(rect.offset.x >= 0); + VK_ASSERT(rect.offset.y >= 0); + scissor = rect; + set_dirty(COMMAND_BUFFER_DIRTY_SCISSOR_BIT); +} + +void CommandBuffer::push_constants(const void *data, VkDeviceSize offset, VkDeviceSize range) +{ + VK_ASSERT(offset + range <= VULKAN_PUSH_CONSTANT_SIZE); + memcpy(bindings.push_constant_data + offset, data, range); + set_dirty(COMMAND_BUFFER_DIRTY_PUSH_CONSTANTS_BIT); +} + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES +void CommandBuffer::set_program(const std::string &compute, const std::vector> &defines) +{ + auto *p = device->get_shader_manager().register_compute(compute); + if (p) + { + auto *variant = p->register_variant(defines); + set_program(variant->get_program()); + } + else + set_program(nullptr); +} + +void CommandBuffer::set_program(const std::string &vertex, const std::string &fragment, + const std::vector> &defines) +{ + auto *p = device->get_shader_manager().register_graphics(vertex, fragment); + if (p) + { + auto *variant = p->register_variant(defines); + set_program(variant->get_program()); + } + else + set_program(nullptr); +} + +void CommandBuffer::set_program(const std::string &task, const std::string &mesh, const std::string &fragment, + const std::vector> &defines) +{ + auto *p = device->get_shader_manager().register_graphics(task, mesh, fragment); + if (p) + { + auto *variant = p->register_variant(defines); + set_program(variant->get_program()); + } + else + set_program(nullptr); +} +#endif + +VkIndirectExecutionSetEXT +CommandBuffer::bake_and_set_program_group(Program *const *programs, unsigned num_programs, + const ExecutionSetSpecializationConstants *spec_constants, + const PipelineLayout *layout) +{ + current_pipeline = {}; + pipeline_state.program = nullptr; + set_dirty(COMMAND_BUFFER_DIRTY_PIPELINE_BIT); + + VK_ASSERT(device->get_device_features().device_generated_commands_features.deviceGeneratedCommands); + + if (!num_programs) + return VK_NULL_HANDLE; + +#ifdef VULKAN_DEBUG + for (unsigned i = 0; i < num_programs; i++) + { + VK_ASSERT((framebuffer && programs[i]->get_shader(ShaderStage::Fragment)) || + (!framebuffer && programs[i]->get_shader(ShaderStage::Compute))); + } +#endif + + if (!layout && pipeline_state.program) + { + CombinedResourceLayout combined_layout = programs[0]->get_pipeline_layout()->get_resource_layout(); + for (unsigned i = 1; i < num_programs; i++) + device->merge_combined_resource_layout(combined_layout, *programs[i]); + layout = device->request_pipeline_layout(combined_layout, nullptr); + } + + set_program_layout(layout); + + bool is_compute_pso = programs[0]->get_shader(ShaderStage::Compute); + + VkIndirectExecutionSetPipelineInfoEXT pipeline_info = { VK_STRUCTURE_TYPE_INDIRECT_EXECUTION_SET_PIPELINE_INFO_EXT }; + VkIndirectExecutionSetCreateInfoEXT info = { VK_STRUCTURE_TYPE_INDIRECT_EXECUTION_SET_CREATE_INFO_EXT }; + info.type = VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXT; + info.info.pPipelineInfo = &pipeline_info; + pipeline_info.maxPipelineCount = num_programs; + + VkIndirectExecutionSetEXT execution_set = VK_NULL_HANDLE; + + for (unsigned i = 0; i < num_programs; i++) + { + pipeline_state.program = programs[i]; + pipeline_state.static_state.state.indirect_bindable = 1; + set_dirty(COMMAND_BUFFER_DIRTY_PIPELINE_BIT | COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); + + if (spec_constants) + { + set_specialization_constant_mask(spec_constants[i].mask); + for_each_bit(spec_constants[i].mask, [&](uint32_t bit) { + set_specialization_constant(bit, spec_constants[i].constants[bit]); + }); + } + + if (is_compute_pso) + { + if (!flush_compute_pipeline(true)) + { + LOGE("Failed to flush compute pipeline state for indirect execution set.\n"); + return VK_NULL_HANDLE; + } + } + else + { + if (!flush_graphics_pipeline(true)) + { + LOGE("Failed to flush graphics pipeline state for indirect execution set.\n"); + return VK_NULL_HANDLE; + } + } + + // If creating these is expensive, we may want to consider a hash'n'cache approach or explicit ownership. + // There really shouldn't be many of these per frame though. + if (i == 0) + { + // Index 0 is implicitly written on creation. + pipeline_info.initialPipeline = current_pipeline.pipeline; + if (table.vkCreateIndirectExecutionSetEXT(device->get_device(), &info, nullptr, &execution_set) != VK_SUCCESS) + { + LOGE("Failed to create indirect execution set.\n"); + return VK_NULL_HANDLE; + } + + device->destroy_indirect_execution_set(execution_set); + } + else + { + VkWriteIndirectExecutionSetPipelineEXT write = { VK_STRUCTURE_TYPE_WRITE_INDIRECT_EXECUTION_SET_PIPELINE_EXT }; + write.index = i; + write.pipeline = current_pipeline.pipeline; + table.vkUpdateIndirectExecutionSetPipelineEXT(device->get_device(), execution_set, 1, &write); + } + } + + // The initial pipeline must be bound when preprocessing and executing. + table.vkCmdBindPipeline(cmd, is_compute_pso ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeline_info.initialPipeline); + + return execution_set; +} + +void CommandBuffer::set_program(Program *program) +{ + if (pipeline_state.program == program) + return; + + pipeline_state.program = program; + pipeline_state.static_state.state.indirect_bindable = 0; + current_pipeline = {}; + + set_dirty(COMMAND_BUFFER_DIRTY_PIPELINE_BIT); + if (!program) + return; + + VK_ASSERT((framebuffer && pipeline_state.program->get_shader(ShaderStage::Fragment)) || + (!framebuffer && pipeline_state.program->get_shader(ShaderStage::Compute))); + + set_program_layout(program->get_pipeline_layout()); + + if (program && device->get_device_features().supports_post_mortem) + { + static const ShaderStage stages[] = { + ShaderStage::Vertex, + ShaderStage::Fragment, + ShaderStage::Compute, + ShaderStage::Task, + ShaderStage::Mesh, + }; + + for (auto stage : stages) + if (auto *shader = program->get_shader(stage)) + checkpoint(shader); + } +} + +void CommandBuffer::set_program_layout(const PipelineLayout *layout) +{ + VK_ASSERT(layout); + if (!pipeline_state.layout) + { + dirty_sets_realloc = ~0u; + set_dirty(COMMAND_BUFFER_DIRTY_PUSH_CONSTANTS_BIT); + } + else if (layout->get_hash() != pipeline_state.layout->get_hash()) + { + auto &new_layout = layout->get_resource_layout(); + auto &old_layout = pipeline_state.layout->get_resource_layout(); + + uint32_t first_invalidated_set_index = VULKAN_NUM_DESCRIPTOR_SETS; + uint32_t new_push_set = layout->get_push_set_index(); + uint32_t old_push_set = pipeline_state.layout->get_push_set_index(); + if (new_push_set == old_push_set) + { + new_push_set = UINT32_MAX; + old_push_set = UINT32_MAX; + } + + // If the push constant layout changes, all descriptor sets + // are invalidated. + if (new_layout.push_constant_layout_hash != old_layout.push_constant_layout_hash) + { + first_invalidated_set_index = 0; + set_dirty(COMMAND_BUFFER_DIRTY_PUSH_CONSTANTS_BIT); + } + else + { + // Find the first set whose descriptor set layout differs. + for (unsigned set = 0; set < VULKAN_NUM_DESCRIPTOR_SETS; set++) + { + if (layout->get_allocator(set) != pipeline_state.layout->get_allocator(set) || + set == new_push_set || set == old_push_set) + { + first_invalidated_set_index = set; + break; + } + } + } + + if (first_invalidated_set_index < VULKAN_NUM_DESCRIPTOR_SETS) + { + dirty_sets_rebind |= ~((1u << first_invalidated_set_index) - 1u); + + for (unsigned set = first_invalidated_set_index; set < VULKAN_NUM_DESCRIPTOR_SETS; set++) + { + if (layout->get_allocator(set) != pipeline_state.layout->get_allocator(set) || + set == new_push_set || set == old_push_set) + { + dirty_sets_realloc |= 1u << set; + } + } + } + } + + pipeline_state.layout = layout; + current_pipeline_layout = pipeline_state.layout->get_layout(); +} + +void *CommandBuffer::allocate_constant_data(unsigned set, unsigned binding, VkDeviceSize size) +{ + VK_ASSERT(size <= VULKAN_MAX_UBO_SIZE); + auto data = ubo_block.allocate(size); + if (!data.host) + { + device->request_uniform_block(ubo_block, size); + data = ubo_block.allocate(size); + } + set_uniform_buffer(set, binding, *data.buffer, data.offset, data.padded_size); + return data.host; +} + +void *CommandBuffer::allocate_index_data(VkDeviceSize size, VkIndexType index_type) +{ + auto data = ibo_block.allocate(size); + if (!data.host) + { + device->request_index_block(ibo_block, size); + data = ibo_block.allocate(size); + } + set_index_buffer(*data.buffer, data.offset, index_type); + return data.host; +} + +BufferBlockAllocation CommandBuffer::request_scratch_buffer_memory(VkDeviceSize size) +{ + if (size == 0) + return {}; + + auto data = staging_block.allocate(size); + if (!data.host) + { + device->request_staging_block(staging_block, size); + data = staging_block.allocate(size); + } + + return data; +} + +void *CommandBuffer::update_buffer(const Buffer &buffer, VkDeviceSize offset, VkDeviceSize size) +{ + auto data = request_scratch_buffer_memory(size); + if (data.host) + copy_buffer(buffer, offset, *data.buffer, data.offset, size); + return data.host; +} + +void CommandBuffer::update_buffer_inline(const Buffer &buffer, VkDeviceSize offset, VkDeviceSize size, const void *data) +{ + VK_ASSERT(size <= 64 * 1024); + table.vkCmdUpdateBuffer(cmd, buffer.get_buffer(), offset, size, data); +} + +void *CommandBuffer::update_image(const Image &image, const VkOffset3D &offset, const VkExtent3D &extent, + uint32_t row_length, uint32_t image_height, + const VkImageSubresourceLayers &subresource) +{ + auto &create_info = image.get_create_info(); + uint32_t width = image.get_width(subresource.mipLevel); + uint32_t height = image.get_height(subresource.mipLevel); + uint32_t depth = image.get_depth(subresource.mipLevel); + + if ((subresource.aspectMask & (VK_IMAGE_ASPECT_PLANE_0_BIT | + VK_IMAGE_ASPECT_PLANE_1_BIT | + VK_IMAGE_ASPECT_PLANE_2_BIT)) != 0) + { + format_ycbcr_downsample_dimensions(create_info.format, subresource.aspectMask, width, height); + } + + if (!row_length) + row_length = width; + + if (!image_height) + image_height = height; + + uint32_t blocks_x = row_length; + uint32_t blocks_y = image_height; + format_num_blocks(create_info.format, blocks_x, blocks_y); + + VkDeviceSize size = + TextureFormatLayout::format_block_size(create_info.format, subresource.aspectMask) * subresource.layerCount * depth * blocks_x * blocks_y; + + auto data = staging_block.allocate(size); + if (!data.host) + { + device->request_staging_block(staging_block, size); + data = staging_block.allocate(size); + } + + copy_buffer_to_image(image, *data.buffer, data.offset, offset, extent, row_length, image_height, subresource); + return data.host; +} + +void *CommandBuffer::update_image(const Image &image, uint32_t row_length, uint32_t image_height) +{ + const VkImageSubresourceLayers subresource = { + format_to_aspect_mask(image.get_format()), 0, 0, 1, + }; + return update_image(image, { 0, 0, 0 }, { image.get_width(), image.get_height(), image.get_depth() }, row_length, + image_height, subresource); +} + +void *CommandBuffer::allocate_vertex_data(unsigned binding, VkDeviceSize size, VkDeviceSize stride, + VkVertexInputRate step_rate) +{ + auto data = vbo_block.allocate(size); + if (!data.host) + { + device->request_vertex_block(vbo_block, size); + data = vbo_block.allocate(size); + } + + set_vertex_binding(binding, *data.buffer, data.offset, stride, step_rate); + return data.host; +} + +void CommandBuffer::set_uniform_buffer(unsigned set, unsigned binding, const Buffer &buffer, VkDeviceSize offset, + VkDeviceSize range) +{ + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + VK_ASSERT(buffer.get_create_info().usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + auto &b = bindings.bindings[set][binding]; + + if (desc_heap_enable) + { + if (range == VK_WHOLE_SIZE) + range = buffer.get_create_info().size - offset; + + if (buffer.get_cookie() == bindings.cookies[set][binding] && + b.buffer_addr_heap.address == buffer.get_device_address() + offset && + b.buffer_addr_heap.size == range) + { + return; + } + + b.buffer_addr_heap.address = buffer.get_device_address() + offset; + b.buffer_addr_heap.size = range; + } + else if (desc_buffer_enable) + { + if (range == VK_WHOLE_SIZE) + range = buffer.get_create_info().size - offset; + + if (buffer.get_cookie() == bindings.cookies[set][binding] && + b.buffer_addr_buffer.address == buffer.get_device_address() + offset && + b.buffer_addr_buffer.range == range) + { + return; + } + + b.buffer_addr_buffer.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT; + b.buffer_addr_buffer.pNext = nullptr; + b.buffer_addr_buffer.address = buffer.get_device_address() + offset; + b.buffer_addr_buffer.range = range; + b.buffer_addr_buffer.format = VK_FORMAT_UNDEFINED; + } + else if (buffer.get_cookie() != bindings.cookies[set][binding] || + b.buffer.range != range || b.buffer.offset != offset) + { + b.buffer = { buffer.get_buffer(), offset, range }; + } + + bindings.cookies[set][binding] = buffer.get_cookie(); + bindings.secondary_cookies[set][binding] = 0; + dirty_sets_realloc |= 1u << set; +} + +void CommandBuffer::set_storage_buffer(unsigned set, unsigned binding, const Buffer &buffer, VkDeviceSize offset, + VkDeviceSize range) +{ + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + VK_ASSERT(buffer.get_create_info().usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + auto &b = bindings.bindings[set][binding]; + + if (desc_heap_enable) + { + if (range == VK_WHOLE_SIZE) + range = buffer.get_create_info().size - offset; + + if (buffer.get_cookie() == bindings.cookies[set][binding] && + b.buffer_addr_heap.address == buffer.get_device_address() + offset && + b.buffer_addr_heap.size == range) + { + return; + } + + b.buffer_addr_heap.address = buffer.get_device_address() + offset; + b.buffer_addr_heap.size = range; + } + else if (desc_buffer_enable) + { + if (range == VK_WHOLE_SIZE) + range = buffer.get_create_info().size - offset; + + if (buffer.get_cookie() == bindings.cookies[set][binding] && + b.buffer_addr_buffer.address == buffer.get_device_address() + offset && + b.buffer_addr_buffer.range == range) + { + return; + } + + b.buffer_addr_buffer.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT; + b.buffer_addr_buffer.pNext = nullptr; + b.buffer_addr_buffer.address = buffer.get_device_address() + offset; + b.buffer_addr_buffer.range = range; + b.buffer_addr_buffer.format = VK_FORMAT_UNDEFINED; + } + else if (buffer.get_cookie() != bindings.cookies[set][binding] || + b.buffer.offset != offset || b.buffer.range != range) + { + b.buffer = { buffer.get_buffer(), offset, range }; + } + + bindings.cookies[set][binding] = buffer.get_cookie(); + bindings.secondary_cookies[set][binding] = 0; + dirty_sets_realloc |= 1u << set; +} + +void CommandBuffer::set_uniform_buffer(unsigned set, unsigned binding, const Buffer &buffer) +{ + set_uniform_buffer(set, binding, buffer, 0, buffer.get_create_info().size); +} + +void CommandBuffer::set_storage_buffer(unsigned set, unsigned binding, const Buffer &buffer) +{ + set_storage_buffer(set, binding, buffer, 0, buffer.get_create_info().size); +} + +void CommandBuffer::set_rtas(unsigned set, unsigned binding, const RTAS &rtas) +{ + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + VK_ASSERT(rtas.get_type() == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR); + auto &b = bindings.bindings[set][binding]; + + if (rtas.get_cookie() == bindings.cookies[set][binding]) + return; + bindings.cookies[set][binding] = rtas.get_cookie(); + + if (desc_heap_enable) + { + b.buffer_addr_heap.address = rtas.get_device_address(); + b.buffer_addr_heap.size = 0; + } + else if (desc_buffer_enable) + b.buffer_addr_buffer.address = rtas.get_device_address(); + else + b.rtas = rtas.get_rtas(); +} + +void CommandBuffer::set_sampler(unsigned set, unsigned binding, const Sampler &sampler) +{ + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + if (sampler.get_cookie() == bindings.secondary_cookies[set][binding]) + return; + + auto &b = bindings.bindings[set][binding]; + b.image.fp.sampler = sampler.get_sampler(); + b.image.integer.sampler = sampler.get_sampler(); + if (desc_heap_enable) + { + VK_ASSERT(((uint64_t)sampler.get_sampler()) >> 63); + b.image.sampler_ptr = nullptr; + b.image.fp_heap_index.sampler_heap_index = uint32_t((uint64_t)sampler.get_sampler()); + b.image.integer_heap_index.sampler_heap_index = uint32_t((uint64_t)sampler.get_sampler()); + } + else if (desc_buffer_enable) + { + auto &p = sampler.get_descriptor_payload(); + b.image.sampler_ptr = p.ptr; + b.image.fp_heap_index.sampler_heap_index = p.heap_index; + b.image.integer_heap_index.sampler_heap_index = p.heap_index; + } + dirty_sets_realloc |= 1u << set; + bindings.secondary_cookies[set][binding] = sampler.get_cookie(); +} + +void CommandBuffer::set_buffer_view_common(unsigned set, unsigned binding, const BufferView &view, + VkDescriptorType desc_type) +{ + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + auto cookie = view.get_cookie() + (desc_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + if (cookie == bindings.cookies[set][binding]) + return; + auto &b = bindings.bindings[set][binding]; + + if (desc_buffer_enable || desc_heap_enable) + { + if (desc_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) + { + b.buffer_view.buffer.ptr = view.get_uniform_payload().ptr; + b.buffer_view.buffer.heap_index = view.get_uniform_payload().heap_index; + } + else + { + b.buffer_view.buffer.ptr = view.get_storage_payload().ptr; + b.buffer_view.buffer.heap_index = view.get_storage_payload().heap_index; + } + } + else + b.buffer_view.handle = view.get_view(); + + bindings.cookies[set][binding] = cookie; + bindings.secondary_cookies[set][binding] = 0; + dirty_sets_realloc |= 1u << set; +} + +void CommandBuffer::set_buffer_view(unsigned set, unsigned binding, const BufferView &view) +{ + VK_ASSERT(view.get_buffer().get_create_info().usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT); + set_buffer_view_common(set, binding, view, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); +} + +void CommandBuffer::set_storage_buffer_view(unsigned set, unsigned binding, const BufferView &view) +{ + VK_ASSERT(view.get_buffer().get_create_info().usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT); + set_buffer_view_common(set, binding, view, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); +} + +void CommandBuffer::set_input_attachments(unsigned set, unsigned start_binding) +{ + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(start_binding + actual_render_pass->get_num_input_attachments(pipeline_state.subpass_index) <= VULKAN_NUM_BINDINGS); + unsigned num_input_attachments = actual_render_pass->get_num_input_attachments(pipeline_state.subpass_index); + for (unsigned i = 0; i < num_input_attachments; i++) + { + auto &ref = actual_render_pass->get_input_attachment(pipeline_state.subpass_index, i); + if (ref.attachment == VK_ATTACHMENT_UNUSED) + continue; + + const ImageView *view = framebuffer_attachments[ref.attachment]; + VK_ASSERT(view); + VK_ASSERT(view->get_image().get_create_info().usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); + + if (view->get_cookie() == bindings.cookies[set][start_binding + i] && + bindings.bindings[set][start_binding + i].image.fp.imageLayout == ref.layout) + { + continue; + } + + auto &b = bindings.bindings[set][start_binding + i]; + b.image.fp.imageLayout = ref.layout; + b.image.integer.imageLayout = ref.layout; + b.image.fp.imageView = view->get_float_view().view; + b.image.integer.imageView = view->get_integer_view().view; + + if (desc_buffer_enable || desc_heap_enable) + { + if (ref.layout == VK_IMAGE_LAYOUT_GENERAL) + { + b.image.fp_ptr = view->get_float_view().input_attachment_feedback.ptr; + b.image.integer_ptr = view->get_integer_view().input_attachment_feedback.ptr; + b.image.fp_heap_index.image_heap_index = + view->get_float_view().input_attachment_feedback.heap_index; + b.image.integer_heap_index.image_heap_index = + view->get_integer_view().input_attachment_feedback.heap_index; + } + else + { + b.image.fp_ptr = view->get_float_view().input_attachment.ptr; + b.image.integer_ptr = view->get_integer_view().input_attachment.ptr; + b.image.fp_heap_index.image_heap_index = + view->get_float_view().input_attachment.heap_index; + b.image.integer_heap_index.image_heap_index = + view->get_integer_view().input_attachment.heap_index; + } + } + + bindings.cookies[set][start_binding + i] = view->get_cookie(); + dirty_sets_realloc |= 1u << set; + } +} + +void CommandBuffer::set_texture(unsigned set, unsigned binding, + VkImageView float_view, VkImageView integer_view, VkImageLayout layout, + const CachedDescriptorPayload &float_payload, + const CachedDescriptorPayload &integer_payload, + uint64_t cookie) +{ + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + if (cookie == bindings.cookies[set][binding] && bindings.bindings[set][binding].image.fp.imageLayout == layout) + return; + + auto &b = bindings.bindings[set][binding]; + b.image.fp.imageLayout = layout; + b.image.fp.imageView = float_view; + b.image.integer.imageLayout = layout; + b.image.integer.imageView = integer_view; + if (desc_buffer_enable || desc_heap_enable) + { + b.image.fp_ptr = float_payload.ptr; + b.image.integer_ptr = integer_payload.ptr; + b.image.fp_heap_index.image_heap_index = float_payload.heap_index; + b.image.integer_heap_index.image_heap_index = integer_payload.heap_index; + } + bindings.cookies[set][binding] = cookie; + dirty_sets_realloc |= 1u << set; +} + +void CommandBuffer::set_bindless(unsigned set, const BindlessDescriptorSet &handle) +{ + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(handle.valid); + if (desc_buffer_enable || desc_heap_enable) + desc_buffer_heap_cached_offsets[set] = handle.handle.offset; + else + bindless_sets[set] = handle.handle.set; + dirty_sets_realloc |= 1u << set; +} + +void CommandBuffer::set_texture(unsigned set, unsigned binding, const ImageView &view) +{ + VK_ASSERT(view.get_image().get_create_info().usage & VK_IMAGE_USAGE_SAMPLED_BIT); + auto &fp = view.get_float_view(); + auto &integer = view.get_integer_view(); + set_texture(set, binding, fp.view, integer.view, view.get_image().get_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL), + fp.sampled, integer.sampled, + view.get_cookie()); +} + +enum CookieBits +{ + COOKIE_BIT_UNORM = 1 << 0, + COOKIE_BIT_SRGB = 1 << 1, + COOKIE_BIT_PER_MIP = 1 << 4 +}; + +void CommandBuffer::set_unorm_texture(unsigned set, unsigned binding, const ImageView &view) +{ + VK_ASSERT(view.get_image().get_create_info().usage & VK_IMAGE_USAGE_SAMPLED_BIT); + auto &unorm_view = view.get_unorm_view(); + VK_ASSERT(unorm_view.view != VK_NULL_HANDLE); + set_texture(set, binding, + unorm_view.view, unorm_view.view, view.get_image().get_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL), + unorm_view.sampled, unorm_view.sampled, + view.get_cookie() | COOKIE_BIT_UNORM); +} + +void CommandBuffer::set_srgb_texture(unsigned set, unsigned binding, const ImageView &view) +{ + VK_ASSERT(view.get_image().get_create_info().usage & VK_IMAGE_USAGE_SAMPLED_BIT); + auto &srgb_view = view.get_srgb_view(); + VK_ASSERT(srgb_view.view != VK_NULL_HANDLE); + set_texture(set, binding, + srgb_view.view, srgb_view.view, view.get_image().get_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL), + srgb_view.sampled, srgb_view.sampled, + view.get_cookie() | COOKIE_BIT_SRGB); +} + +void CommandBuffer::set_texture(unsigned set, unsigned binding, const ImageView &view, const Sampler &sampler) +{ + set_sampler(set, binding, sampler); + set_texture(set, binding, view); +} + +void CommandBuffer::set_texture(unsigned set, unsigned binding, const ImageView &view, StockSampler stock) +{ + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + VK_ASSERT(view.get_image().get_create_info().usage & VK_IMAGE_USAGE_SAMPLED_BIT); + const auto &sampler = device->get_stock_sampler(stock); + set_texture(set, binding, view, sampler); +} + +void CommandBuffer::set_sampler(unsigned set, unsigned binding, StockSampler stock) +{ + const auto &sampler = device->get_stock_sampler(stock); + set_sampler(set, binding, sampler); +} + +void CommandBuffer::set_storage_texture(unsigned set, unsigned binding, const ImageView &view) +{ + VK_ASSERT(view.get_image().get_create_info().usage & VK_IMAGE_USAGE_STORAGE_BIT); + auto &fp = view.get_float_view(); + set_texture(set, binding, fp.view, fp.view, view.get_image().get_layout(VK_IMAGE_LAYOUT_GENERAL), + fp.storage, fp.storage, + view.get_cookie()); +} + +void CommandBuffer::set_storage_texture_level(unsigned set, unsigned binding, + const Vulkan::ImageView &view, unsigned level) +{ + VK_ASSERT(view.get_image().get_create_info().usage & VK_IMAGE_USAGE_STORAGE_BIT); + auto &mip_view = view.get_mip_view(level); + set_texture(set, binding, mip_view.view, mip_view.view, + view.get_image().get_layout(VK_IMAGE_LAYOUT_GENERAL), + mip_view.storage, mip_view.storage, + view.get_cookie() | COOKIE_BIT_PER_MIP | level); +} + +void CommandBuffer::set_unorm_storage_texture(unsigned set, unsigned binding, const ImageView &view) +{ + VK_ASSERT(view.get_image().get_create_info().usage & VK_IMAGE_USAGE_STORAGE_BIT); + auto &unorm_view = view.get_unorm_view(); + VK_ASSERT(unorm_view.view != VK_NULL_HANDLE); + set_texture(set, binding, unorm_view.view, unorm_view.view, view.get_image().get_layout(VK_IMAGE_LAYOUT_GENERAL), + unorm_view.storage, unorm_view.storage, + view.get_cookie() | COOKIE_BIT_UNORM); +} + +void CommandBuffer::flush_descriptor_offsets(uint32_t &first_set, uint32_t &set_count) +{ + if (!set_count) + return; + + // We only have one global descriptor buffer. + static uint32_t indices[VULKAN_NUM_DESCRIPTOR_SETS]; + + table.vkCmdSetDescriptorBufferOffsetsEXT( + cmd, actual_render_pass ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE, + current_pipeline_layout, first_set, set_count, indices, desc_buffer_heap_cached_offsets + first_set); + + set_count = 0; +} + +void CommandBuffer::flush_descriptor_binds(const VkDescriptorSet *sets, + uint32_t &first_set, uint32_t &set_count) +{ + if (!set_count) + return; + + table.vkCmdBindDescriptorSets( + cmd, actual_render_pass ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE, + current_pipeline_layout, first_set, set_count, sets, 0, nullptr); + + set_count = 0; +} + +void CommandBuffer::rebind_descriptor_set(uint32_t set, VkDescriptorSet *sets, uint32_t &first_set, uint32_t &set_count) +{ + if (set_count == 0) + { + first_set = set; + } + else if (first_set + set_count != set) + { + flush_descriptor_binds(sets, first_set, set_count); + first_set = set; + } + + auto &layout = pipeline_state.layout->get_resource_layout(); + if (layout.bindless_descriptor_set_mask & (1u << set)) + { + VK_ASSERT(bindless_sets[set]); + sets[set_count++] = bindless_sets[set]; + } + else + sets[set_count++] = allocated_sets[set]; +} + +void CommandBuffer::rebind_descriptor_offset(uint32_t set, uint32_t &first_set, uint32_t &set_count) +{ + if (set_count == 0) + { + first_set = set; + } + else if (first_set + set_count != set) + { + flush_descriptor_offsets(first_set, set_count); + first_set = set; + } + + set_count++; +} + +void CommandBuffer::validate_descriptor_binds(uint32_t set) +{ +#ifdef VULKAN_DEBUG + auto &layout = pipeline_state.layout->get_resource_layout(); + auto &set_layout = layout.sets[set]; + + for_each_bit(set_layout.uniform_buffer_mask, + [&](uint32_t binding) + { + unsigned array_size = set_layout.meta[binding].array_size; + for (unsigned i = 0; i < array_size; i++) + VK_ASSERT(bindings.bindings[set][binding + i].buffer.buffer != VK_NULL_HANDLE); + }); + + // SSBOs + for_each_bit(set_layout.storage_buffer_mask, + [&](uint32_t binding) + { + unsigned array_size = set_layout.meta[binding].array_size; + for (unsigned i = 0; i < array_size; i++) + VK_ASSERT(bindings.bindings[set][binding + i].buffer.buffer != VK_NULL_HANDLE); + }); + + // RTAS + for_each_bit(set_layout.rtas_mask, + [&](uint32_t binding) + { + unsigned array_size = set_layout.meta[binding].array_size; + for (unsigned i = 0; i < array_size; i++) + VK_ASSERT(bindings.bindings[set][binding + i].rtas != VK_NULL_HANDLE); + }); + + // Texel buffers + for_each_bit(set_layout.sampled_texel_buffer_mask | set_layout.storage_texel_buffer_mask, + [&](uint32_t binding) + { + unsigned array_size = set_layout.meta[binding].array_size; + for (unsigned i = 0; i < array_size; i++) + VK_ASSERT(bindings.bindings[set][binding + i].buffer_view.handle != VK_NULL_HANDLE); + }); + + // Sampled images + for_each_bit(set_layout.sampled_image_mask, + [&](uint32_t binding) + { + unsigned array_size = set_layout.meta[binding].array_size; + for (unsigned i = 0; i < array_size; i++) + { + if ((set_layout.immutable_sampler_mask & (1u << (binding + i))) == 0) + VK_ASSERT(bindings.bindings[set][binding + i].image.fp.sampler != VK_NULL_HANDLE); + VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE); + } + }); + + // Separate images + for_each_bit(set_layout.separate_image_mask, + [&](uint32_t binding) + { + unsigned array_size = set_layout.meta[binding].array_size; + for (unsigned i = 0; i < array_size; i++) + VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE); + }); + + // Separate samplers + for_each_bit(set_layout.sampler_mask & ~set_layout.immutable_sampler_mask, + [&](uint32_t binding) + { + unsigned array_size = set_layout.meta[binding].array_size; + for (unsigned i = 0; i < array_size; i++) + VK_ASSERT(bindings.bindings[set][binding + i].image.fp.sampler != VK_NULL_HANDLE); + }); + + // Storage images + for_each_bit(set_layout.storage_image_mask, + [&](uint32_t binding) + { + unsigned array_size = set_layout.meta[binding].array_size; + for (unsigned i = 0; i < array_size; i++) + VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE); + }); + + // Input attachments + for_each_bit(set_layout.input_attachment_mask, + [&](uint32_t binding) + { + unsigned array_size = set_layout.meta[binding].array_size; + for (unsigned i = 0; i < array_size; i++) + VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE); + }); +#else + (void)set; +#endif +} + +void CommandBuffer::push_descriptor_set(uint32_t set) +{ +#ifdef VULKAN_DEBUG + validate_descriptor_binds(set); +#endif + + VkDescriptorUpdateTemplate update_template = pipeline_state.layout->get_update_template(set); + VK_ASSERT(update_template); + table.vkCmdPushDescriptorSetWithTemplate( + cmd, update_template, + pipeline_state.layout->get_layout(), set, bindings.bindings[set]); +} + +CommandBuffer::DescriptorSlice CommandBuffer::allocate_descriptor_slice(VkDeviceSize size, VkDeviceSize align) +{ + DescriptorSlice slice = {}; + + desc_buffer_alloc_offset = (desc_buffer_alloc_offset + align - 1) & ~(align - 1); + + if (desc_buffer_alloc_offset + size > desc_buffer.get_size()) + { + // Page in a new block. + if (desc_buffer.get_size()) + device->free_descriptor_buffer_allocation(desc_buffer); + + // The descriptor heap is precious, don't be too wasteful. + VkDeviceSize padded_size = std::max(size, desc_heap_enable ? 4 * 1024 : 16 * 1024); + desc_buffer = device->managers.descriptor_buffer.allocate(padded_size); + desc_buffer_alloc_offset = 0; + } + + slice.offset = desc_buffer.get_offset() + desc_buffer_alloc_offset; + slice.mapped = device->managers.descriptor_buffer.get_resource_heap().mapped + slice.offset; + desc_buffer_alloc_offset += size; + return slice; +} + +void CommandBuffer::allocate_descriptor_heap_set(uint32_t set) +{ + auto &layout = *pipeline_state.layout; + auto *push_words = bindings.inline_descriptors[set].push_data_words; + auto *push_ptrs = bindings.inline_descriptors[set].push_data_addr; + + auto heap_slice_size = layout.get_heap_slice_size(set); + auto heap_table_size = layout.get_heap_table_size(set); + uint8_t *mapped_table = nullptr; + uint8_t *mapped_heap = nullptr; + + auto &ext = device->get_device_features(); + + DescriptorSlice slice = {}; + + if (heap_slice_size) + { + auto align = ext.resource_heap_resource_desc_size; + slice = allocate_descriptor_slice(heap_slice_size, align); + + uint32_t push_offset; + if (layout.get_heap_buffer_descriptor_strategy(set) == PipelineLayout::DescriptorStrategy::HeapSlice) + push_offset = layout.get_descriptor_set_push_buffer_offset(set); + else if (layout.get_heap_image_descriptor_strategy(set) == PipelineLayout::DescriptorStrategy::HeapSlice) + push_offset = layout.get_descriptor_set_push_image_offset(set); + else + { + VK_ASSERT(0 && "Need heap slice in at least one path.\n"); + return; + } + + uint32_t offset = uint32_t(slice.offset) >> ext.resource_heap_resource_desc_size_log2; + desc_buffer_heap_cached_offsets[set] = offset; + mapped_heap = slice.mapped; + + VkPushDataInfoEXT info = { VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT }; + info.offset = push_offset; + info.data.address = &offset; + info.data.size = sizeof(uint32_t); + table.vkCmdPushDataEXT(cmd, &info); + } + + if (heap_table_size) + { + // INDIRECT tables are effectively UBOs. + auto data = ubo_block.allocate(heap_table_size); + if (!data.host) + { + device->request_uniform_block(ubo_block, heap_table_size); + data = ubo_block.allocate(heap_table_size); + } + + auto va = data.buffer->get_device_address() + data.offset; + + uint32_t push_offset; + if (layout.get_heap_buffer_descriptor_strategy(set) == PipelineLayout::DescriptorStrategy::IndirectTable) + push_offset = layout.get_descriptor_set_push_buffer_offset(set); + else if (layout.get_heap_image_descriptor_strategy(set) == PipelineLayout::DescriptorStrategy::IndirectTable) + push_offset = layout.get_descriptor_set_push_image_offset(set); + else + { + VK_ASSERT(0 && "Need heap table in at least one path.\n"); + return; + } + + desc_heap_cached_table[set] = va; + mapped_table = data.host; + + VkPushDataInfoEXT info = { VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT }; + info.offset = push_offset; + info.data.address = &va; + info.data.size = sizeof(VkDeviceAddress); + table.vkCmdPushDataEXT(cmd, &info); + } + + auto &set_layout = layout.get_resource_layout().sets[set]; + auto &binds = bindings.bindings[set]; + + VkResourceDescriptorInfoEXT resource_desc[VULKAN_NUM_BINDINGS]; + VkHostAddressRangeEXT host_ranges[VULKAN_NUM_BINDINGS]; + uint32_t resource_desc_count = 0; + + switch (layout.get_heap_buffer_descriptor_strategy(set)) + { + case PipelineLayout::DescriptorStrategy::Inline: + Util::for_each_bit(set_layout.uniform_buffer_mask | + set_layout.storage_buffer_mask | + set_layout.rtas_mask, [&](unsigned bit) + { + push_ptrs[layout.get_descriptor_offset(set, bit) / sizeof(VkDeviceAddress)] = + binds[bit].buffer_addr_heap.address; + }); + break; + + case PipelineLayout::DescriptorStrategy::HeapSlice: + Util::for_each_bit(set_layout.uniform_buffer_mask, [&](unsigned bit) + { + for (uint32_t i = 0; i < set_layout.meta[bit].array_size; i++) + { + VK_ASSERT(resource_desc_count < VULKAN_NUM_BINDINGS); + host_ranges[resource_desc_count].address = mapped_heap + layout.get_descriptor_offset(set, bit + i); + host_ranges[resource_desc_count].size = ext.descriptor_heap_properties.bufferDescriptorSize; + resource_desc[resource_desc_count] = { VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT }; + resource_desc[resource_desc_count].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource_desc[resource_desc_count].data.pAddressRange = &binds[bit + i].buffer_addr_heap; + resource_desc_count++; + } + }); + + Util::for_each_bit(set_layout.storage_buffer_mask, [&](unsigned bit) + { + for (uint32_t i = 0; i < set_layout.meta[bit].array_size; i++) + { + VK_ASSERT(resource_desc_count < VULKAN_NUM_BINDINGS); + host_ranges[resource_desc_count].address = mapped_heap + layout.get_descriptor_offset(set, bit + i); + host_ranges[resource_desc_count].size = ext.descriptor_heap_properties.bufferDescriptorSize; + resource_desc[resource_desc_count] = { VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT }; + resource_desc[resource_desc_count].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + resource_desc[resource_desc_count].data.pAddressRange = &binds[bit + i].buffer_addr_heap; + resource_desc_count++; + } + }); + + Util::for_each_bit(set_layout.rtas_mask, [&](unsigned bit) + { + for (uint32_t i = 0; i < set_layout.meta[bit].array_size; i++) + { + VK_ASSERT(resource_desc_count < VULKAN_NUM_BINDINGS); + host_ranges[resource_desc_count].address = mapped_heap + layout.get_descriptor_offset(set, bit + i); + host_ranges[resource_desc_count].size = ext.descriptor_heap_properties.bufferDescriptorSize; + resource_desc[resource_desc_count] = { VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT }; + resource_desc[resource_desc_count].type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + resource_desc[resource_desc_count].data.pAddressRange = &binds[bit + i].buffer_addr_heap; + resource_desc_count++; + } + }); + break; + + case PipelineLayout::DescriptorStrategy::IndirectTable: + Util::for_each_bit(set_layout.uniform_buffer_mask | + set_layout.storage_buffer_mask | + set_layout.rtas_mask, [&](unsigned bit) + { + memcpy(mapped_table + layout.get_descriptor_offset(set, bit), + &binds[bit].buffer_addr_heap.address, sizeof(VkDeviceAddress)); + }); + break; + } + + if (resource_desc_count) + table.vkWriteResourceDescriptorsEXT(device->get_device(), resource_desc_count, resource_desc, host_ranges); + + auto simple_image_mask = set_layout.separate_image_mask | set_layout.storage_image_mask | + set_layout.input_attachment_mask; + auto texel_buffer_mask = set_layout.storage_texel_buffer_mask | set_layout.sampled_texel_buffer_mask; + + switch (layout.get_heap_image_descriptor_strategy(set)) + { + case PipelineLayout::DescriptorStrategy::Inline: + Util::for_each_bit(simple_image_mask, [&](unsigned bit) + { + push_words[layout.get_descriptor_offset(set, bit) / sizeof(uint32_t)] = + binds[bit].image.integer_heap_index.image_heap_index; + }); + + Util::for_each_bit(texel_buffer_mask, [&](unsigned bit) + { + push_words[layout.get_descriptor_offset(set, bit) / sizeof(uint32_t)] = + binds[bit].buffer_view.buffer.heap_index; + }); + + Util::for_each_bit(set_layout.sampler_mask, [&](unsigned bit) + { + push_words[layout.get_descriptor_offset(set, bit) / sizeof(uint32_t)] = + binds[bit].image.integer_heap_index.sampler_heap_index; + }); + + Util::for_each_bit(set_layout.sampled_image_mask, [&](unsigned bit) + { + push_words[layout.get_descriptor_offset(set, bit) / sizeof(uint32_t)] = + binds[bit].image.integer_heap_index.word; + }); + break; + + case PipelineLayout::DescriptorStrategy::HeapSlice: + Util::for_each_bit(set_layout.separate_image_mask, [&](unsigned bit) + { + for (unsigned i = 0; i < set_layout.meta[bit].array_size; i++) + { + auto *ptr = (set_layout.fp_mask & (1u << bit)) != 0 + ? binds[bit + i].image.fp_ptr + : binds[bit + i].image.integer_ptr; + + VK_ASSERT(ptr); + device->managers.descriptor_buffer.copy_sampled_image( + mapped_heap + layout.get_descriptor_offset(set, bit + i), ptr); + } + }); + + Util::for_each_bit(set_layout.storage_image_mask, [&](unsigned bit) + { + for (unsigned i = 0; i < set_layout.meta[bit].array_size; i++) + { + auto *ptr = (set_layout.fp_mask & (1u << bit)) != 0 + ? binds[bit + i].image.fp_ptr + : binds[bit + i].image.integer_ptr; + + VK_ASSERT(ptr); + device->managers.descriptor_buffer.copy_storage_image( + mapped_heap + layout.get_descriptor_offset(set, bit + i), ptr); + } + }); + + Util::for_each_bit(set_layout.input_attachment_mask, [&](unsigned bit) + { + for (unsigned i = 0; i < set_layout.meta[bit].array_size; i++) + { + auto *ptr = (set_layout.fp_mask & (1u << bit)) != 0 + ? binds[bit + i].image.fp_ptr + : binds[bit + i].image.integer_ptr; + + VK_ASSERT(ptr); + device->managers.descriptor_buffer.copy_input_attachment( + mapped_heap + layout.get_descriptor_offset(set, bit + i), ptr); + } + }); + + Util::for_each_bit(set_layout.sampled_texel_buffer_mask, [&](unsigned bit) + { + for (unsigned i = 0; i < set_layout.meta[bit].array_size; i++) + { + auto *ptr = binds[bit + i].buffer_view.buffer.ptr; + VK_ASSERT(ptr); + device->managers.descriptor_buffer.copy_uniform_texel( + mapped_heap + layout.get_descriptor_offset(set, bit + i), ptr); + } + }); + + Util::for_each_bit(set_layout.storage_texel_buffer_mask, [&](unsigned bit) + { + for (unsigned i = 0; i < set_layout.meta[bit].array_size; i++) + { + auto *ptr = binds[bit + i].buffer_view.buffer.ptr; + VK_ASSERT(ptr); + device->managers.descriptor_buffer.copy_storage_texel( + mapped_heap + layout.get_descriptor_offset(set, bit + i), ptr); + } + }); + break; + + case PipelineLayout::DescriptorStrategy::IndirectTable: + Util::for_each_bit(simple_image_mask, [&](unsigned bit) + { + for (unsigned i = 0; i < set_layout.meta[bit].array_size; i++) + { + auto *ptr = mapped_table + layout.get_descriptor_offset(set, bit + i); + uint32_t index = binds[bit + i].image.integer_heap_index.image_heap_index; + memcpy(ptr, &index, sizeof(uint32_t)); + } + }); + + Util::for_each_bit(texel_buffer_mask, [&](unsigned bit) + { + for (unsigned i = 0; i < set_layout.meta[bit].array_size; i++) + { + auto *ptr = mapped_table + layout.get_descriptor_offset(set, bit + i); + const uint32_t &index = binds[bit + i].buffer_view.buffer.heap_index; + memcpy(ptr, &index, sizeof(uint32_t)); + } + }); + + Util::for_each_bit(set_layout.sampler_mask, [&](unsigned bit) + { + for (unsigned i = 0; i < set_layout.meta[bit].array_size; i++) + { + auto *ptr = mapped_table + layout.get_descriptor_offset(set, bit + i); + uint32_t index = binds[bit + i].image.integer_heap_index.sampler_heap_index; + memcpy(ptr, &index, sizeof(uint32_t)); + } + }); + + Util::for_each_bit(set_layout.sampled_image_mask, [&](unsigned bit) + { + for (unsigned i = 0; i < set_layout.meta[bit].array_size; i++) + { + auto *ptr = mapped_table + layout.get_descriptor_offset(set, bit + i); + uint32_t index = binds[bit + i].image.integer_heap_index.word; + memcpy(ptr, &index, sizeof(uint32_t)); + } + }); + break; + } + + if (uint32_t inline_size = layout.get_descriptor_set_inline_size(set)) + { + VkPushDataInfoEXT info = { VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT }; + info.offset = layout.get_descriptor_set_inline_offsets(set); + info.data.address = push_words; + info.data.size = inline_size; + table.vkCmdPushDataEXT(cmd, &info); + } +} + +void CommandBuffer::allocate_descriptor_offset(uint32_t set, uint32_t &first_set, uint32_t &set_count) +{ + if (set_count == 0) + { + first_set = set; + } + else if (first_set + set_count != set) + { + flush_descriptor_offsets(first_set, set_count); + first_set = set; + } + + auto &layout = pipeline_state.layout->get_resource_layout(); + if (layout.bindless_descriptor_set_mask & (1u << set)) + { + set_count++; + return; + } + + auto &set_layout = layout.sets[set]; + auto *set_allocator = pipeline_state.layout->get_allocator(set); + auto size = set_allocator->get_resource_heap_size(); + + auto slice = allocate_descriptor_slice(size, device->get_device_features().resource_heap_offset_alignment); + desc_buffer_heap_cached_offsets[set] = slice.offset; + auto *mapped = slice.mapped; + + VkDescriptorGetInfoEXT info = { VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT }; + + Util::for_each_bit(set_layout.sampled_image_mask, [&](unsigned binding) { + // TODO: Figure out something smarter for combined image samplers. + // Most likely we can cache the combined variant for normal stock samplers. + info.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + if (set_layout.fp_mask & (1u << binding)) + info.data.pSampledImage = &bindings.bindings[set][binding + i].image.fp; + else + info.data.pSampledImage = &bindings.bindings[set][binding + i].image.integer; + + VK_ASSERT(info.data.pSampledImage->imageView && info.data.pSampledImage->sampler); + + table.vkGetDescriptorEXT( + device->get_device(), &info, + device->get_device_features().descriptor_buffer_properties.combinedImageSamplerDescriptorSize, + mapped + set_allocator->get_binding_offset(binding + i)); + } + }); + + Util::for_each_bit(set_layout.separate_image_mask, [&](unsigned binding) { + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + auto *ptr = (set_layout.fp_mask & (1u << binding)) != 0 ? + bindings.bindings[set][binding + i].image.fp_ptr : + bindings.bindings[set][binding + i].image.integer_ptr; + VK_ASSERT(ptr); + device->managers.descriptor_buffer.copy_sampled_image( + mapped + set_allocator->get_binding_offset(binding + i), ptr); + } + }); + + Util::for_each_bit(set_layout.input_attachment_mask, [&](unsigned binding) { + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + auto *ptr = (set_layout.fp_mask & (1u << binding)) != 0 ? + bindings.bindings[set][binding + i].image.fp_ptr : + bindings.bindings[set][binding + i].image.integer_ptr; + VK_ASSERT(ptr); + device->managers.descriptor_buffer.copy_input_attachment( + mapped + set_allocator->get_binding_offset(binding + i), ptr); + } + }); + + Util::for_each_bit(set_layout.storage_image_mask, [&](unsigned binding) { + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + auto *ptr = bindings.bindings[set][binding + i].image.fp_ptr; + VK_ASSERT(ptr); + device->managers.descriptor_buffer.copy_storage_image( + mapped + set_allocator->get_binding_offset(binding + i), ptr); + } + }); + + Util::for_each_bit(set_layout.sampler_mask, [&](unsigned binding) { + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + auto *ptr = bindings.bindings[set][binding + i].image.sampler_ptr; + VK_ASSERT(ptr); + device->managers.descriptor_buffer.copy_sampler(mapped + set_allocator->get_binding_offset(binding + i), ptr); + } + }); + + auto ubo_size = device->managers.descriptor_buffer.get_descriptor_size_for_type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + auto ssbo_size = device->managers.descriptor_buffer.get_descriptor_size_for_type(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + auto rtas_size = device->managers.descriptor_buffer.get_descriptor_size_for_type(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR); + + // UBOs and SSBOs cannot really be cached since there is no view and they are expected to get suballocated anyway. + Util::for_each_bit(set_layout.uniform_buffer_mask, [&](unsigned binding) { + info.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + info.data.pUniformBuffer = &bindings.bindings[set][binding + i].buffer_addr_buffer; + VK_ASSERT(info.data.pUniformBuffer->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT && + info.data.pUniformBuffer->address); + table.vkGetDescriptorEXT( + device->get_device(), &info, + ubo_size, mapped + set_allocator->get_binding_offset(binding + i)); + } + }); + + Util::for_each_bit(set_layout.storage_buffer_mask, [&](unsigned binding) { + info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + info.data.pStorageBuffer = &bindings.bindings[set][binding + i].buffer_addr_buffer; + VK_ASSERT(info.data.pStorageBuffer->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT && + info.data.pStorageBuffer->address); + table.vkGetDescriptorEXT( + device->get_device(), &info, + ssbo_size, mapped + set_allocator->get_binding_offset(binding + i)); + } + }); + + Util::for_each_bit(set_layout.rtas_mask, [&](unsigned binding) { + info.type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + info.data.accelerationStructure = bindings.bindings[set][binding + i].buffer_addr_buffer.address; + VK_ASSERT(info.data.accelerationStructure != 0); + table.vkGetDescriptorEXT( + device->get_device(), &info, + rtas_size, mapped + set_allocator->get_binding_offset(binding + i)); + } + }); + + Util::for_each_bit(set_layout.sampled_texel_buffer_mask, [&](unsigned binding) { + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + VK_ASSERT(bindings.bindings[set][binding + i].buffer_view.buffer.ptr); + device->managers.descriptor_buffer.copy_uniform_texel( + mapped + set_allocator->get_binding_offset(binding + i), + bindings.bindings[set][binding + i].buffer_view.buffer.ptr); + } + }); + + Util::for_each_bit(set_layout.storage_texel_buffer_mask, [&](unsigned binding) { + for (unsigned i = 0; i < set_layout.meta[binding].array_size; i++) + { + VK_ASSERT(bindings.bindings[set][binding + i].buffer_view.buffer.ptr); + device->managers.descriptor_buffer.copy_storage_texel( + mapped + set_allocator->get_binding_offset(binding + i), + bindings.bindings[set][binding + i].buffer_view.buffer.ptr); + } + }); + + set_count++; +} + +void CommandBuffer::flush_descriptor_set(uint32_t set, VkDescriptorSet *sets, + uint32_t &first_set, uint32_t &set_count) +{ + if (set_count == 0) + { + first_set = set; + } + else if (first_set + set_count != set) + { + flush_descriptor_binds(sets, first_set, set_count); + first_set = set; + } + + auto &layout = pipeline_state.layout->get_resource_layout(); + if (layout.bindless_descriptor_set_mask & (1u << set)) + { + VK_ASSERT(bindless_sets[set]); + sets[set_count++] = bindless_sets[set]; + return; + } + +#ifdef VULKAN_DEBUG + validate_descriptor_binds(set); +#endif + + auto vk_set = pipeline_state.layout->get_allocator(set)->request_descriptor_set(thread_index, device->frame_context_index); + + VkDescriptorUpdateTemplate update_template = pipeline_state.layout->get_update_template(set); + VK_ASSERT(update_template); + table.vkUpdateDescriptorSetWithTemplate(device->get_device(), vk_set, update_template, bindings.bindings[set]); + sets[set_count++] = vk_set; + allocated_sets[set] = vk_set; +} + +void CommandBuffer::rebind_descriptor_heap_set(uint32_t set) +{ + VkPushDataInfoEXT info = { VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT }; + + if (uint32_t inline_size = pipeline_state.layout->get_descriptor_set_inline_size(set)) + { + info.offset = pipeline_state.layout->get_descriptor_set_inline_offsets(set); + info.data.address = bindings.inline_descriptors[set].push_data_words; + info.data.size = inline_size; + table.vkCmdPushDataEXT(cmd, &info); + } + + bool push_slice = false; + + if (pipeline_state.layout->get_heap_buffer_descriptor_strategy(set) == + PipelineLayout::DescriptorStrategy::HeapSlice) + { + info.offset = pipeline_state.layout->get_descriptor_set_push_buffer_offset(set); + push_slice = true; + } + else if (pipeline_state.layout->get_heap_image_descriptor_strategy(set) == + PipelineLayout::DescriptorStrategy::HeapSlice) + { + info.offset = pipeline_state.layout->get_descriptor_set_push_image_offset(set); + push_slice = true; + } + + if (push_slice) + { + auto offset = uint32_t(desc_buffer_heap_cached_offsets[set]); + info.data.address = &offset; + info.data.size = sizeof(offset); + table.vkCmdPushDataEXT(cmd, &info); + } + + bool push_table = false; + + if (pipeline_state.layout->get_heap_buffer_descriptor_strategy(set) == + PipelineLayout::DescriptorStrategy::IndirectTable) + { + info.offset = pipeline_state.layout->get_descriptor_set_push_buffer_offset(set); + push_table = true; + } + else if (pipeline_state.layout->get_heap_image_descriptor_strategy(set) == + PipelineLayout::DescriptorStrategy::IndirectTable) + { + info.offset = pipeline_state.layout->get_descriptor_set_push_image_offset(set); + push_table = true; + } + + if (push_table) + { + info.data.address = &desc_heap_cached_table[set]; + info.data.size = sizeof(VkDeviceAddress); + table.vkCmdPushDataEXT(cmd, &info); + } +} + +void CommandBuffer::flush_descriptor_sets() +{ + auto &layout = pipeline_state.layout->get_resource_layout(); + + uint32_t first_set = 0; + uint32_t set_count = 0; + + dirty_sets_rebind |= dirty_sets_realloc; + uint32_t set_update_mask = layout.descriptor_set_mask & dirty_sets_rebind; + + if (desc_heap_enable) + { + auto &ext = device->get_device_features(); + + for_each_bit(set_update_mask & dirty_sets_rebind & ~layout.bindless_descriptor_set_mask, [&](uint32_t set) + { + if (set_update_mask & dirty_sets_realloc) + allocate_descriptor_heap_set(set); + else + rebind_descriptor_heap_set(set); + }); + + for_each_bit(set_update_mask & layout.bindless_descriptor_set_mask, [&](uint32_t set) + { + uint32_t offset = uint32_t(desc_buffer_heap_cached_offsets[set]) >> ext.resource_heap_resource_desc_size_log2; + VkPushDataInfoEXT info = { VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT }; + info.data.address = &offset; + info.data.size = sizeof(offset); + info.offset = pipeline_state.layout->get_descriptor_set_push_image_offset(set); + table.vkCmdPushDataEXT(cmd, &info); + }); + } + else if (desc_buffer_enable) + { + for_each_bit(set_update_mask, [&](uint32_t set) + { + if ((dirty_sets_realloc & (1u << set)) != 0) + allocate_descriptor_offset(set, first_set, set_count); + else + rebind_descriptor_offset(set, first_set, set_count); + }); + + flush_descriptor_offsets(first_set, set_count); + } + else + { + VkDescriptorSet sets[VULKAN_NUM_DESCRIPTOR_SETS]; + + uint32_t push_set_index = pipeline_state.layout->get_push_set_index(); + if (push_set_index != UINT32_MAX && (dirty_sets_rebind & (1u << push_set_index)) != 0) + { + push_descriptor_set(push_set_index); + set_update_mask &= ~(1u << push_set_index); + } + + for_each_bit(set_update_mask, [&](uint32_t set) + { + if ((dirty_sets_realloc & (1u << set)) != 0) + flush_descriptor_set(set, sets, first_set, set_count); + else + rebind_descriptor_set(set, sets, first_set, set_count); + }); + + flush_descriptor_binds(sets, first_set, set_count); + } + + dirty_sets_realloc = 0; + dirty_sets_rebind = 0; +} + +void CommandBuffer::draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance) +{ + VK_ASSERT(!is_compute); + if (flush_render_state(true) != VK_NULL_HANDLE) + { + VK_ASSERT(pipeline_state.program->get_shader(ShaderStage::Vertex) != nullptr); + table.vkCmdDraw(cmd, vertex_count, instance_count, first_vertex, first_instance); + checkpoint_with_signal(vertex_count, instance_count, first_vertex, first_instance); + } + else + LOGE("Failed to flush render state, draw call will be dropped.\n"); +} + +void CommandBuffer::draw_indexed(uint32_t index_count, uint32_t instance_count, uint32_t first_index, + int32_t vertex_offset, uint32_t first_instance) +{ + VK_ASSERT(!is_compute); + VK_ASSERT(index_state.buffer != VK_NULL_HANDLE); + if (flush_render_state(true) != VK_NULL_HANDLE) + { + VK_ASSERT(pipeline_state.program->get_shader(ShaderStage::Vertex) != nullptr); + table.vkCmdDrawIndexed(cmd, index_count, instance_count, first_index, vertex_offset, first_instance); + checkpoint_with_signal(index_count, instance_count, first_index, vertex_offset, first_instance); + } + else + LOGE("Failed to flush render state, draw call will be dropped.\n"); +} + +void CommandBuffer::draw_mesh_tasks(uint32_t tasks_x, uint32_t tasks_y, uint32_t tasks_z) +{ + VK_ASSERT(!is_compute); + + if (framebuffer_is_multiview && !get_device().get_device_features().mesh_shader_features.multiviewMeshShader) + { + LOGE("meshShader not supported in multiview, dropping draw call.\n"); + return; + } + + if (flush_render_state(true) != VK_NULL_HANDLE) + { + VK_ASSERT(pipeline_state.program->get_shader(ShaderStage::Mesh) != nullptr); + table.vkCmdDrawMeshTasksEXT(cmd, tasks_x, tasks_y, tasks_z); + checkpoint_with_signal(tasks_x, tasks_y, tasks_z); + } + else + LOGE("Failed to flush render state, draw call will be dropped.\n"); +} + +void CommandBuffer::draw_mesh_tasks_indirect(const Buffer &buffer, VkDeviceSize offset, + uint32_t draw_count, uint32_t stride) +{ + VK_ASSERT(!is_compute); + + if (framebuffer_is_multiview && !get_device().get_device_features().mesh_shader_features.multiviewMeshShader) + { + LOGE("meshShader not supported in multiview, dropping draw call.\n"); + return; + } + + if (flush_render_state(true) != VK_NULL_HANDLE) + { + VK_ASSERT(pipeline_state.program->get_shader(ShaderStage::Mesh) != nullptr); + table.vkCmdDrawMeshTasksIndirectEXT(cmd, buffer.get_buffer(), offset, draw_count, stride); + checkpoint_with_signal("MeshMDI", buffer.get_device_address() + offset, draw_count, stride); + } + else + LOGE("Failed to flush render state, draw call will be dropped.\n"); +} + +void CommandBuffer::draw_mesh_tasks_multi_indirect(const Buffer &buffer, VkDeviceSize offset, + uint32_t draw_count, uint32_t stride, + const Buffer &count, VkDeviceSize count_offset) +{ + VK_ASSERT(!is_compute); + + if (framebuffer_is_multiview && !get_device().get_device_features().mesh_shader_features.multiviewMeshShader) + { + LOGE("meshShader not supported in multiview, dropping draw call.\n"); + return; + } + + if (flush_render_state(true) != VK_NULL_HANDLE) + { + VK_ASSERT(pipeline_state.program->get_shader(ShaderStage::Mesh) != nullptr); + table.vkCmdDrawMeshTasksIndirectCountEXT(cmd, buffer.get_buffer(), offset, + count.get_buffer(), count_offset, + draw_count, stride); + + checkpoint_with_signal("MeshMDI", buffer.get_device_address() + offset, + count.get_device_address() + count_offset, + draw_count, stride); + } + else + LOGE("Failed to flush render state, draw call will be dropped.\n"); +} + +void CommandBuffer::draw_indirect(const Vulkan::Buffer &buffer, + VkDeviceSize offset, uint32_t draw_count, uint32_t stride) +{ + VK_ASSERT(!is_compute); + if (flush_render_state(true) != VK_NULL_HANDLE) + { + VK_ASSERT(pipeline_state.program->get_shader(ShaderStage::Vertex) != nullptr); + table.vkCmdDrawIndirect(cmd, buffer.get_buffer(), offset, draw_count, stride); + checkpoint_with_signal("DrawMDI", buffer.get_device_address() + offset, draw_count, stride); + } + else + LOGE("Failed to flush render state, draw call will be dropped.\n"); +} + +void CommandBuffer::draw_multi_indirect(const Buffer &buffer, VkDeviceSize offset, uint32_t draw_count, uint32_t stride, + const Buffer &count, VkDeviceSize count_offset) +{ + VK_ASSERT(!is_compute); + if (!get_device().get_device_features().vk12_features.drawIndirectCount) + { + LOGE("VK_KHR_draw_indirect_count not supported, dropping draw call.\n"); + return; + } + + if (flush_render_state(true) != VK_NULL_HANDLE) + { + VK_ASSERT(pipeline_state.program->get_shader(ShaderStage::Vertex) != nullptr); + table.vkCmdDrawIndirectCount(cmd, buffer.get_buffer(), offset, + count.get_buffer(), count_offset, + draw_count, stride); + checkpoint_with_signal("DrawMDI", buffer.get_device_address() + offset, + count.get_device_address() + count_offset, + draw_count, stride); + } + else + LOGE("Failed to flush render state, draw call will be dropped.\n"); +} + +void CommandBuffer::draw_indexed_multi_indirect(const Buffer &buffer, VkDeviceSize offset, uint32_t draw_count, uint32_t stride, + const Buffer &count, VkDeviceSize count_offset) +{ + VK_ASSERT(!is_compute); + if (!get_device().get_device_features().vk12_features.drawIndirectCount) + { + LOGE("VK_KHR_draw_indirect_count not supported, dropping draw call.\n"); + return; + } + + if (flush_render_state(true) != VK_NULL_HANDLE) + { + VK_ASSERT(pipeline_state.program->get_shader(ShaderStage::Vertex) != nullptr); + table.vkCmdDrawIndexedIndirectCount(cmd, buffer.get_buffer(), offset, + count.get_buffer(), count_offset, + draw_count, stride); + checkpoint_with_signal("DrawIndexedMDI", buffer.get_device_address() + offset, + count.get_device_address() + count_offset, + draw_count, stride); + } + else + LOGE("Failed to flush render state, draw call will be dropped.\n"); +} + +void CommandBuffer::draw_indexed_indirect(const Vulkan::Buffer &buffer, + VkDeviceSize offset, uint32_t draw_count, uint32_t stride) +{ + VK_ASSERT(!is_compute); + if (flush_render_state(true) != VK_NULL_HANDLE) + { + VK_ASSERT(pipeline_state.program->get_shader(ShaderStage::Vertex) != nullptr); + table.vkCmdDrawIndexedIndirect(cmd, buffer.get_buffer(), offset, draw_count, stride); + checkpoint_with_signal("DrawIndexedIndirect", buffer.get_device_address() + offset, draw_count, stride); + } + else + LOGE("Failed to flush render state, draw call will be dropped.\n"); +} + +void CommandBuffer::dispatch_indirect(const Buffer &buffer, VkDeviceSize offset) +{ + VK_ASSERT(is_compute); + if (flush_compute_state(true) != VK_NULL_HANDLE) + { + table.vkCmdDispatchIndirect(cmd, buffer.get_buffer(), offset); + checkpoint_with_signal("DispatchIndirect", buffer.get_device_address() + offset); + } + else + LOGE("Failed to flush render state, dispatch will be dropped.\n"); +} + +void CommandBuffer::execute_indirect_commands( + VkIndirectExecutionSetEXT execution_set, + const IndirectLayout *indirect_layout, uint32_t sequences, + const Vulkan::Buffer &indirect, VkDeviceSize offset, + const Vulkan::Buffer *count, size_t count_offset, + CommandBuffer &preprocess) +{ + VK_ASSERT((is_compute && (indirect_layout->get_shader_stages() & VK_SHADER_STAGE_COMPUTE_BIT) != 0) || + (!is_compute && (indirect_layout->get_shader_stages() & VK_SHADER_STAGE_COMPUTE_BIT) == 0)); + VK_ASSERT(device->get_device_features().device_generated_commands_features.deviceGeneratedCommands); + + if (is_compute) + { + if (flush_compute_state(true) == VK_NULL_HANDLE) + { + LOGE("Failed to flush compute state, dispatch will be dropped.\n"); + return; + } + } + else + { + if (flush_render_state(true) == VK_NULL_HANDLE) + { + LOGE("Failed to flush render state, draw call will be dropped.\n"); + return; + } + } + + // TODO: Linearly allocate these, but big indirect commands like these + // should only be done a few times per render pass anyways. + VkGeneratedCommandsMemoryRequirementsInfoEXT generated = + { VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_EXT }; + VkGeneratedCommandsPipelineInfoEXT pipeline = + { VK_STRUCTURE_TYPE_GENERATED_COMMANDS_PIPELINE_INFO_EXT }; + VkMemoryRequirements2 reqs = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 }; + + generated.indirectCommandsLayout = indirect_layout->get_layout(); + generated.maxSequenceCount = sequences; + generated.indirectExecutionSet = execution_set; + + if (execution_set == VK_NULL_HANDLE) + { + generated.pNext = &pipeline; + pipeline.pipeline = current_pipeline.pipeline; + } + + table.vkGetGeneratedCommandsMemoryRequirementsEXT(device->get_device(), &generated, &reqs); + + BufferHandle preprocess_buffer; + + if (reqs.memoryRequirements.size) + { + BufferCreateInfo bufinfo = {}; + bufinfo.size = reqs.memoryRequirements.size; + bufinfo.domain = BufferDomain::Device; + bufinfo.allocation_requirements = reqs.memoryRequirements; + bufinfo.usage = VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR | VK_BUFFER_USAGE_2_PREPROCESS_BUFFER_BIT_EXT; + preprocess_buffer = device->create_buffer(bufinfo); + } + + VkGeneratedCommandsInfoEXT exec_info = { VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_EXT }; + exec_info.indirectCommandsLayout = indirect_layout->get_layout(); + exec_info.shaderStages = indirect_layout->get_shader_stages(); + exec_info.indirectAddress = indirect.get_device_address() + offset; + exec_info.indirectAddressSize = indirect.get_create_info().size - offset; + exec_info.preprocessSize = reqs.memoryRequirements.size; + exec_info.preprocessAddress = preprocess_buffer ? preprocess_buffer->get_device_address() : 0; + exec_info.maxSequenceCount = sequences; + exec_info.indirectExecutionSet = execution_set; + + if (execution_set == VK_NULL_HANDLE) + exec_info.pNext = &pipeline; + + if (count) + exec_info.sequenceCountAddress = count->get_device_address() + count_offset; + + VK_ASSERT(preprocess.cmd != cmd); + table.vkCmdPreprocessGeneratedCommandsEXT(preprocess.cmd, &exec_info, cmd); + preprocess.checkpoint_with_signal("preprocess-dgc"); + table.vkCmdExecuteGeneratedCommandsEXT(cmd, VK_TRUE, &exec_info); + checkpoint_with_signal("execute-dgc"); + + // Everything is nuked after execute generated commands. + set_dirty(COMMAND_BUFFER_DYNAMIC_BITS | + COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT | + COMMAND_BUFFER_DIRTY_PIPELINE_BIT); + +} + +void CommandBuffer::dispatch(uint32_t groups_x, uint32_t groups_y, uint32_t groups_z) +{ + VK_ASSERT(is_compute); + if (flush_compute_state(true) != VK_NULL_HANDLE) + { + table.vkCmdDispatch(cmd, groups_x, groups_y, groups_z); + checkpoint_with_signal(groups_x, groups_y, groups_z); + } + else + LOGE("Failed to flush render state, dispatch will be dropped.\n"); +} + +void CommandBuffer::begin_rtas_batch() +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(!rtas_batch.in_batch); + rtas_batch.in_batch = true; +} + +void CommandBuffer::emit_scratch_barrier() +{ + // If we're reusing the scratch buffer, we have to synchronize it. + barrier(VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, + VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | + VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR); +} + +void CommandBuffer::setup_batch(VkAccelerationStructureTypeKHR rtas_type) +{ + rtas_batch.geom_info.resize(rtas_batch.ranges.size()); + rtas_batch.range_info_ptrs.resize(rtas_batch.ranges.size()); + + if (rtas_type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) + { + rtas_batch.range_infos.resize(rtas_batch.geometries.size()); + rtas_batch.geometries_conv.resize(rtas_batch.geometries.size()); + } + else + { + rtas_batch.range_infos.resize(rtas_batch.ranges.size()); + rtas_batch.geometries_conv.resize(rtas_batch.ranges.size()); + } + + VkDeviceSize total_scratch = 0; + VkDeviceSize scratch_align = + device->get_device_features().rtas_properties.minAccelerationStructureScratchOffsetAlignment; + scratch_align -= 1; + + for (size_t i = 0, n = rtas_batch.ranges.size(); i < n; i++) + { + auto &geom_info = rtas_batch.geom_info[i]; + geom_info = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; + geom_info.mode = rtas_batch.build_modes[i] == BuildMode::Build ? + VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR : + VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR; + geom_info.type = rtas_type; + + if (rtas_type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) + { + switch (rtas_batch.blas_modes[i]) + { + case BLASMode::Static: + geom_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR; + break; + + case BLASMode::Skinned: + geom_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR | + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR; + break; + } + + rtas_batch.range_info_ptrs[i] = rtas_batch.range_infos.data() + rtas_batch.ranges[i].start; + geom_info.pGeometries = rtas_batch.geometries_conv.data() + rtas_batch.ranges[i].start; + geom_info.geometryCount = rtas_batch.ranges[i].count; + } + else + { + geom_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR; + + rtas_batch.range_info_ptrs[i] = rtas_batch.range_infos.data() + i; + geom_info.pGeometries = rtas_batch.geometries_conv.data() + i; + geom_info.geometryCount = 1; + } + + geom_info.dstAccelerationStructure = rtas_batch.ranges[i].dst; + geom_info.srcAccelerationStructure = rtas_batch.ranges[i].src; + + total_scratch = (total_scratch + scratch_align) & ~scratch_align; + total_scratch += rtas_batch.ranges[i].scratch; + } + + // Safety net in case the implementation doesn't require scratch somehow. + total_scratch = std::max(total_scratch, 16); + + if (!rtas_batch.scratch || total_scratch > rtas_batch.scratch->get_create_info().size) + { + BufferCreateInfo scratch_info = {}; + scratch_info.domain = BufferDomain::Device; + // Let the size grow a bit to avoid too much realloc explosion. + scratch_info.size = !rtas_batch.scratch ? total_scratch : (total_scratch * 3 / 2); + scratch_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + + // Scratch buffers have higher VkBuffer alignment. + scratch_info.allocation_requirements.size = scratch_info.size; + scratch_info.allocation_requirements.memoryTypeBits = UINT32_MAX; + scratch_info.allocation_requirements.alignment = scratch_align + 1; + + rtas_batch.scratch = device->create_buffer(scratch_info); + } + else + { + // Reusing memory, need barrier. + emit_scratch_barrier(); + } + + total_scratch = 0; + for (size_t i = 0, n = rtas_batch.ranges.size(); i < n; i++) + { + auto &geom_info = rtas_batch.geom_info[i]; + total_scratch = (total_scratch + scratch_align) & ~scratch_align; + geom_info.scratchData.deviceAddress = rtas_batch.scratch->get_device_address() + total_scratch; + total_scratch += rtas_batch.ranges[i].scratch; + } +} + +void CommandBuffer::build_blas_batch() +{ + setup_batch(VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); + + for (size_t i = 0, n = rtas_batch.geometries.size(); i < n; i++) + { + auto &geom = rtas_batch.geometries_conv[i]; + auto &input = rtas_batch.geometries[i]; + auto &range = rtas_batch.range_infos[i]; + geom.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + geom.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + + auto &tri = geom.geometry.triangles; + tri.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + + tri.vertexFormat = input.format; + tri.vertexData.deviceAddress = input.vbo; + tri.maxVertex = input.num_vertices - 1; + tri.vertexStride = input.stride; + + tri.indexData.deviceAddress = input.ibo; + tri.indexType = input.index_type; + VK_ASSERT(input.ibo || input.index_type == VK_INDEX_TYPE_NONE_KHR); + + tri.transformData.deviceAddress = input.transform; + + // Rest is 0. + range.primitiveCount = input.num_primitives; + } + + table.vkCmdBuildAccelerationStructuresKHR( + cmd, rtas_batch.ranges.size(), rtas_batch.geom_info.data(), rtas_batch.range_info_ptrs.data()); + + checkpoint_with_signal("build-blas"); +} + +void CommandBuffer::build_tlas_batch() +{ + setup_batch(VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR); + + // We have array-of-pointer situation since we don't guarantee linear addressing of instances. + // Ensure that all instances are backed by device addresses. + + VkDeviceSize required_scratch_storage = 0; + for (auto &instance : rtas_batch.instances) + { + if (instance.bda == 0) + { + VK_ASSERT(instance.instance); + required_scratch_storage += sizeof(*instance.instance); + } + } + + required_scratch_storage += rtas_batch.instances.size() * sizeof(VkDeviceAddress); + + // Could add scratch for this, but we shouldn't be building more than one TLAS per frame or something ... + BufferCreateInfo scratch_info = {}; + scratch_info.size = required_scratch_storage; + scratch_info.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR; + scratch_info.domain = BufferDomain::LinkedDeviceHost; + auto instance_storage_scratch = device->create_buffer(scratch_info); + VkDeviceAddress va = instance_storage_scratch->get_device_address(); + + auto *upload_instances = static_cast( + device->map_host_buffer(*instance_storage_scratch, MEMORY_ACCESS_WRITE_BIT)); + + for (auto &instance : rtas_batch.instances) + { + if (instance.bda == 0) + { + *upload_instances++ = *instance.instance; + instance.bda = va; + va += sizeof(*instance.instance); + } + } + + auto *addrs = reinterpret_cast(upload_instances); + for (auto &instance : rtas_batch.instances) + { + VK_ASSERT(instance.bda); + *addrs++ = instance.bda; + } + + device->unmap_host_buffer(*instance_storage_scratch, MEMORY_ACCESS_WRITE_BIT); + + for (size_t i = 0, n = rtas_batch.ranges.size(); i < n; i++) + { + auto &geom = rtas_batch.geometries_conv[i]; + auto &range = rtas_batch.range_infos[i]; + geom.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + geom.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + + auto &inst = geom.geometry.instances; + inst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + inst.arrayOfPointers = VK_TRUE; + inst.data.deviceAddress = va + rtas_batch.ranges[i].start * sizeof(VkDeviceAddress); + + // Rest is 0. + range.primitiveCount = rtas_batch.ranges[i].count; + } + + table.vkCmdBuildAccelerationStructuresKHR( + cmd, rtas_batch.ranges.size(), rtas_batch.geom_info.data(), rtas_batch.range_info_ptrs.data()); + + checkpoint_with_signal("build-tlas"); +} + +void CommandBuffer::end_rtas_batch() +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(rtas_batch.in_batch); + rtas_batch.in_batch = false; + + if (!rtas_batch.ranges.empty()) + { + if (!rtas_batch.geometries.empty()) + build_blas_batch(); + else + build_tlas_batch(); + + if (!rtas_batch.queries.empty()) + { + // Unlike most queries, these have to be synchronized. + barrier(VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, + // COPY is maintenance1 and we don't need to rely on that. + VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR); + } + } + + for (auto &query : rtas_batch.queries) + { + table.vkCmdWriteAccelerationStructuresPropertiesKHR( + cmd, 1, &query.rtas, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, + query.pool, query.index); + + checkpoint_with_signal("write-rtas-properties"); + } + + rtas_batch.geometries.clear(); + rtas_batch.instances.clear(); + rtas_batch.ranges.clear(); + rtas_batch.build_modes.clear(); + rtas_batch.blas_modes.clear(); + rtas_batch.queries.clear(); +} + +void CommandBuffer::compact_rtas(const Vulkan::RTAS &dst, const Vulkan::RTAS &src) +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(!rtas_batch.in_batch); + + VkCopyAccelerationStructureInfoKHR info = { VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR }; + info.src = src.get_rtas(); + info.dst = dst.get_rtas(); + info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR; + table.vkCmdCopyAccelerationStructureKHR(cmd, &info); + checkpoint_with_signal("compact-rtas"); +} + +void CommandBuffer::write_compacted_rtas_size(const RTAS &rtas, const QueryPoolResult &query) +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(rtas_batch.in_batch); + rtas_batch.queries.push_back({ rtas.get_rtas(), query.get_query_pool(), query.get_query_pool_index() }); +} + +void CommandBuffer::build_rtas(BuildMode mode, const RTAS &rtas, const TopRTASCreateInfo &info) +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(rtas_batch.in_batch); + + VK_ASSERT(rtas_batch.ranges.size() == rtas_batch.instances.size()); + RTASBatch::Range new_range = { rtas.get_rtas(), mode == BuildMode::Update ? rtas.get_rtas() : VK_NULL_HANDLE, + rtas.get_scratch_size(mode), + rtas_batch.instances.size(), info.count }; + rtas_batch.instances.insert(rtas_batch.instances.end(), info.instances, info.instances + info.count); + rtas_batch.ranges.push_back(new_range); + rtas_batch.build_modes.push_back(mode); +} + +void CommandBuffer::build_rtas(BuildMode mode, const RTAS &rtas, const BottomRTASCreateInfo &info) +{ + VK_ASSERT(!framebuffer); + VK_ASSERT(rtas_batch.in_batch); + VK_ASSERT(mode == BuildMode::Build || info.mode == BLASMode::Skinned); + + VK_ASSERT(rtas_batch.ranges.size() == rtas_batch.blas_modes.size()); + RTASBatch::Range new_range = { rtas.get_rtas(), mode == BuildMode::Update ? rtas.get_rtas() : VK_NULL_HANDLE, + rtas.get_scratch_size(mode), + rtas_batch.geometries.size(), info.count }; + rtas_batch.ranges.push_back(new_range); + rtas_batch.geometries.insert(rtas_batch.geometries.end(), info.geometries, info.geometries + info.count); + rtas_batch.build_modes.push_back(mode); + rtas_batch.blas_modes.push_back(info.mode); +} + +void CommandBuffer::clear_render_state() +{ + // Preserve spec constant mask. + auto &state = pipeline_state.static_state.state; + memset(&state, 0, sizeof(state)); +} + +void CommandBuffer::set_opaque_state() +{ + clear_render_state(); + auto &state = pipeline_state.static_state.state; + state.front_face = VK_FRONT_FACE_COUNTER_CLOCKWISE; + state.cull_mode = VK_CULL_MODE_BACK_BIT; + state.blend_enable = false; + state.depth_test = true; + state.depth_compare = VK_COMPARE_OP_GREATER_OR_EQUAL; + state.depth_write = true; + state.depth_bias_enable = false; + state.primitive_restart = false; + state.stencil_test = false; + state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + state.write_mask = ~0u; + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); +} + +void CommandBuffer::set_quad_state() +{ + clear_render_state(); + auto &state = pipeline_state.static_state.state; + state.front_face = VK_FRONT_FACE_COUNTER_CLOCKWISE; + state.cull_mode = VK_CULL_MODE_NONE; + state.blend_enable = false; + state.depth_test = false; + state.depth_write = false; + state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + state.write_mask = ~0u; + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); +} + +void CommandBuffer::set_opaque_sprite_state() +{ + clear_render_state(); + auto &state = pipeline_state.static_state.state; + state.front_face = VK_FRONT_FACE_COUNTER_CLOCKWISE; + state.cull_mode = VK_CULL_MODE_NONE; + state.blend_enable = false; + state.depth_compare = VK_COMPARE_OP_GREATER; + state.depth_test = true; + state.depth_write = true; + state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + state.write_mask = ~0u; + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); +} + +void CommandBuffer::set_transparent_sprite_state() +{ + clear_render_state(); + auto &state = pipeline_state.static_state.state; + state.front_face = VK_FRONT_FACE_COUNTER_CLOCKWISE; + state.cull_mode = VK_CULL_MODE_NONE; + state.blend_enable = true; + state.depth_test = true; + state.depth_compare = VK_COMPARE_OP_GREATER; + state.depth_write = false; + state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + state.write_mask = ~0u; + + // The alpha layer should start at 1 (fully transparent). + // As layers are blended in, the transparency is multiplied with other transparencies (1 - alpha). + set_blend_factors(VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ZERO, + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA); + set_blend_op(VK_BLEND_OP_ADD); + + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); +} + +void CommandBuffer::restore_state(const CommandBufferSavedState &state) +{ + auto &static_state = pipeline_state.static_state; + auto &potential_static_state = pipeline_state.potential_static_state; + + for (unsigned i = 0; i < VULKAN_NUM_DESCRIPTOR_SETS; i++) + { + if (state.flags & (COMMAND_BUFFER_SAVED_BINDINGS_0_BIT << i)) + { + if (memcmp(state.bindings.bindings[i], bindings.bindings[i], sizeof(bindings.bindings[i]))) + { + memcpy(bindings.bindings[i], state.bindings.bindings[i], sizeof(bindings.bindings[i])); + memcpy(bindings.cookies[i], state.bindings.cookies[i], sizeof(bindings.cookies[i])); + memcpy(bindings.secondary_cookies[i], state.bindings.secondary_cookies[i], sizeof(bindings.secondary_cookies[i])); + dirty_sets_realloc |= 1u << i; + } + } + } + + if (state.flags & COMMAND_BUFFER_SAVED_PUSH_CONSTANT_BIT) + { + if (memcmp(state.bindings.push_constant_data, bindings.push_constant_data, sizeof(bindings.push_constant_data)) != 0) + { + memcpy(bindings.push_constant_data, state.bindings.push_constant_data, sizeof(bindings.push_constant_data)); + set_dirty(COMMAND_BUFFER_DIRTY_PUSH_CONSTANTS_BIT); + } + } + + if ((state.flags & COMMAND_BUFFER_SAVED_VIEWPORT_BIT) && memcmp(&state.viewport, &viewport, sizeof(viewport)) != 0) + { + viewport = state.viewport; + set_dirty(COMMAND_BUFFER_DIRTY_VIEWPORT_BIT); + } + + if ((state.flags & COMMAND_BUFFER_SAVED_SCISSOR_BIT) && memcmp(&state.scissor, &scissor, sizeof(scissor)) != 0) + { + scissor = state.scissor; + set_dirty(COMMAND_BUFFER_DIRTY_SCISSOR_BIT); + } + + if (state.flags & COMMAND_BUFFER_SAVED_RENDER_STATE_BIT) + { + if (memcmp(&state.static_state, &static_state, sizeof(static_state)) != 0) + { + memcpy(&static_state, &state.static_state, sizeof(static_state)); + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); + } + + if (memcmp(&state.potential_static_state, &potential_static_state, sizeof(potential_static_state)) != 0) + { + memcpy(&potential_static_state, &state.potential_static_state, sizeof(potential_static_state)); + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); + } + + if (memcmp(&state.dynamic_state, &dynamic_state, sizeof(dynamic_state)) != 0) + { + memcpy(&dynamic_state, &state.dynamic_state, sizeof(dynamic_state)); + set_dirty(COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT | COMMAND_BUFFER_DIRTY_DEPTH_BIAS_BIT); + } + } +} + +void CommandBuffer::save_state(CommandBufferSaveStateFlags flags, CommandBufferSavedState &state) +{ + for (unsigned i = 0; i < VULKAN_NUM_DESCRIPTOR_SETS; i++) + { + if (flags & (COMMAND_BUFFER_SAVED_BINDINGS_0_BIT << i)) + { + memcpy(state.bindings.bindings[i], bindings.bindings[i], sizeof(bindings.bindings[i])); + memcpy(state.bindings.cookies[i], bindings.cookies[i], sizeof(bindings.cookies[i])); + memcpy(state.bindings.secondary_cookies[i], bindings.secondary_cookies[i], + sizeof(bindings.secondary_cookies[i])); + } + } + + if (flags & COMMAND_BUFFER_SAVED_VIEWPORT_BIT) + state.viewport = viewport; + if (flags & COMMAND_BUFFER_SAVED_SCISSOR_BIT) + state.scissor = scissor; + + if (flags & COMMAND_BUFFER_SAVED_RENDER_STATE_BIT) + { + memcpy(&state.static_state, &pipeline_state.static_state, sizeof(pipeline_state.static_state)); + state.potential_static_state = pipeline_state.potential_static_state; + state.dynamic_state = dynamic_state; + } + + if (flags & COMMAND_BUFFER_SAVED_PUSH_CONSTANT_BIT) + memcpy(state.bindings.push_constant_data, bindings.push_constant_data, sizeof(bindings.push_constant_data)); + + state.flags = flags; +} + +QueryPoolHandle CommandBuffer::write_timestamp(VkPipelineStageFlags2 stage) +{ + return device->write_timestamp(cmd, stage); +} + +void CommandBuffer::end_threaded_recording() +{ + VK_ASSERT(!debug_channel_buffer); + + if (is_ended || borrowed) + return; + + is_ended = true; + + // We must end a command buffer on the same thread index we started it on. + VK_ASSERT(get_current_thread_index() == thread_index); + + if (has_profiling()) + { + auto &query_pool = device->get_performance_query_pool(device->get_physical_queue_type(type)); + query_pool.end_command_buffer(cmd); + } + + device->managers.breadcrumbs.end(breadcrumbs); + + if (table.vkEndCommandBuffer(cmd) != VK_SUCCESS) + LOGE("Failed to end command buffer.\n"); +} + +void CommandBuffer::end() +{ + VK_ASSERT(!barrier_batch.active); + VK_ASSERT(!rtas_batch.in_batch); + + // When called, we're holding a device submission lock. + end_threaded_recording(); + + if (vbo_block.is_mapped()) + device->request_vertex_block_nolock(vbo_block, 0); + if (ibo_block.is_mapped()) + device->request_index_block_nolock(ibo_block, 0); + if (ubo_block.is_mapped()) + device->request_uniform_block_nolock(ubo_block, 0); + if (staging_block.is_mapped()) + device->request_staging_block_nolock(staging_block, 0); + if (desc_buffer.get_size()) + device->free_descriptor_buffer_allocation_nolock(desc_buffer); + + if (rtas_batch.scratch) + { + rtas_batch.scratch->set_internal_sync_object(); + rtas_batch.scratch.reset(); + } +} + +void CommandBuffer::insert_label(const char *name, const float *color) +{ + if (!device->ext.supports_debug_utils || !vkCmdInsertDebugUtilsLabelEXT) + return; + + VkDebugUtilsLabelEXT info = { VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; + if (color) + { + for (unsigned i = 0; i < 4; i++) + info.color[i] = color[i]; + } + else + { + for (unsigned i = 0; i < 4; i++) + info.color[i] = 1.0f; + } + + info.pLabelName = name; + vkCmdInsertDebugUtilsLabelEXT(cmd, &info); +} + +void CommandBuffer::begin_region(const char *name, const float *color) +{ + if (!device->ext.supports_debug_utils || !vkCmdBeginDebugUtilsLabelEXT) + return; + + VkDebugUtilsLabelEXT info = { VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; + if (color) + { + for (unsigned i = 0; i < 4; i++) + info.color[i] = color[i]; + } + else + { + for (unsigned i = 0; i < 4; i++) + info.color[i] = 1.0f; + } + + info.pLabelName = name; + vkCmdBeginDebugUtilsLabelEXT(cmd, &info); +} + +void CommandBuffer::end_region() +{ + if (device->ext.supports_debug_utils && vkCmdEndDebugUtilsLabelEXT) + vkCmdEndDebugUtilsLabelEXT(cmd); +} + +void CommandBuffer::enable_profiling() +{ + profiling = true; +} + +bool CommandBuffer::has_profiling() const +{ + return profiling; +} + +void CommandBuffer::begin_debug_channel(DebugChannelInterface *iface, const char *tag, VkDeviceSize size) +{ + if (debug_channel_buffer) + end_debug_channel(); + + debug_channel_tag = tag; + debug_channel_interface = iface; + + BufferCreateInfo info = {}; + info.size = size; + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + info.domain = BufferDomain::Device; + debug_channel_buffer = device->create_buffer(info); + + fill_buffer(*debug_channel_buffer, 0); + buffer_barrier(*debug_channel_buffer, + VK_PIPELINE_STAGE_2_CLEAR_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT); + + set_storage_buffer(VULKAN_NUM_DESCRIPTOR_SETS - 1, VULKAN_NUM_BINDINGS - 1, *debug_channel_buffer); +} + +void CommandBuffer::end_debug_channel() +{ + if (!debug_channel_buffer) + return; + + BufferCreateInfo info = {}; + info.size = debug_channel_buffer->get_create_info().size; + info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + info.domain = BufferDomain::CachedHost; + auto debug_channel_readback = device->create_buffer(info); + barrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_ACCESS_SHADER_WRITE_BIT, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_READ_BIT); + copy_buffer(*debug_channel_readback, *debug_channel_buffer); + barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_HOST_BIT, VK_ACCESS_HOST_READ_BIT); + + debug_channel_buffer.reset(); + device->add_debug_channel_buffer(debug_channel_interface, std::move(debug_channel_tag), std::move(debug_channel_readback)); + debug_channel_readback = {}; + debug_channel_tag = {}; + debug_channel_interface = nullptr; +} + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES +void CommandBufferUtil::set_quad_vertex_state(CommandBuffer &cmd) +{ +#ifdef __APPLE__ + // For *some* reason, Metal does not support tightly packed R8G8 ... + // Have to use RGBA8 <_<. + auto *data = static_cast(cmd.allocate_vertex_data(0, 16, 4)); + *data++ = -127; + *data++ = +127; + *data++ = 0; + *data++ = +127; + *data++ = +127; + *data++ = +127; + *data++ = 0; + *data++ = +127; + *data++ = -127; + *data++ = -127; + *data++ = 0; + *data++ = +127; + *data++ = +127; + *data++ = -127; + *data++ = 0; + *data++ = +127; + + cmd.set_vertex_attrib(0, 0, VK_FORMAT_R8G8B8A8_SNORM, 0); +#else + auto *data = static_cast(cmd.allocate_vertex_data(0, 8, 2)); + *data++ = -127; + *data++ = +127; + *data++ = +127; + *data++ = +127; + *data++ = -127; + *data++ = -127; + *data++ = +127; + *data++ = -127; + + cmd.set_vertex_attrib(0, 0, VK_FORMAT_R8G8_SNORM, 0); +#endif +} + +void CommandBufferUtil::set_fullscreen_quad_vertex_state(CommandBuffer &cmd) +{ + auto *data = static_cast(cmd.allocate_vertex_data(0, 6 * sizeof(float), 2 * sizeof(float))); + *data++ = -1.0f; + *data++ = -3.0f; + *data++ = -1.0f; + *data++ = +1.0f; + *data++ = +3.0f; + *data++ = +1.0f; + + cmd.set_vertex_attrib(0, 0, VK_FORMAT_R32G32_SFLOAT, 0); +} + +void CommandBufferUtil::draw_fullscreen_quad(CommandBuffer &cmd, unsigned instances) +{ + cmd.set_primitive_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + cmd.draw(3, instances); +} + +void CommandBufferUtil::draw_quad(CommandBuffer &cmd, unsigned instances) +{ + cmd.set_primitive_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); + cmd.draw(4, instances); +} + +void CommandBufferUtil::draw_fullscreen_quad(CommandBuffer &cmd, const std::string &vertex, const std::string &fragment, + const std::vector> &defines) +{ + draw_fullscreen_quad_depth(cmd, vertex, fragment, false, false, VK_COMPARE_OP_ALWAYS, defines); +} + +void CommandBufferUtil::draw_fullscreen_quad_depth(CommandBuffer &cmd, const std::string &vertex, + const std::string &fragment, + bool depth_test, bool depth_write, VkCompareOp depth_compare, + const std::vector> &defines) +{ + setup_fullscreen_quad(cmd, vertex, fragment, defines, depth_test, depth_write, depth_compare); + draw_fullscreen_quad(cmd); +} + +void CommandBufferUtil::setup_fullscreen_quad(Vulkan::CommandBuffer &cmd, const std::string &vertex, + const std::string &fragment, + const std::vector> &defines, bool depth_test, + bool depth_write, VkCompareOp depth_compare) +{ + cmd.set_program(vertex, fragment, defines); + cmd.set_quad_state(); + set_fullscreen_quad_vertex_state(cmd); + cmd.set_depth_test(depth_test, depth_write); + cmd.set_depth_compare(depth_compare); + cmd.set_primitive_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); +} +#endif + +void CommandBufferDeleter::operator()(Vulkan::CommandBuffer *cmd) +{ + cmd->device->handle_pool.command_buffers.free(cmd); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_buffer.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_buffer.hpp new file mode 100644 index 00000000..7e39ed0d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_buffer.hpp @@ -0,0 +1,1055 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "buffer.hpp" +#include "rtas.hpp" +#include "buffer_pool.hpp" +#include "vulkan_headers.hpp" +#include "image.hpp" +#include "pipeline_event.hpp" +#include "query_pool.hpp" +#include "render_pass.hpp" +#include "sampler.hpp" +#include "shader.hpp" +#include "vulkan_common.hpp" +#include + +namespace Vulkan +{ +class DebugChannelInterface; +class IndirectLayout; + +static inline VkPipelineStageFlags convert_vk_stage2(VkPipelineStageFlags2 stages) +{ + constexpr VkPipelineStageFlags2 transfer_mask = + VK_PIPELINE_STAGE_2_COPY_BIT | + VK_PIPELINE_STAGE_2_BLIT_BIT | + VK_PIPELINE_STAGE_2_RESOLVE_BIT | + VK_PIPELINE_STAGE_2_CLEAR_BIT | + VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR; + + constexpr VkPipelineStageFlags2 preraster_mask = + VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT; + + if ((stages & transfer_mask) != 0) + { + stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; + stages &= ~transfer_mask; + } + + if ((stages & preraster_mask) != 0) + { + // TODO: Augment if we add mesh shader support eventually. + stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; + stages &= ~preraster_mask; + } + + return VkPipelineStageFlags(stages); +} + +static inline VkPipelineStageFlags convert_vk_src_stage2(VkPipelineStageFlags2 stages) +{ + stages = convert_vk_stage2(stages); + if (stages == VK_PIPELINE_STAGE_NONE) + stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + return VkPipelineStageFlags(stages); +} + +static inline VkPipelineStageFlags convert_vk_dst_stage2(VkPipelineStageFlags2 stages) +{ + stages = convert_vk_stage2(stages); + if (stages == VK_PIPELINE_STAGE_NONE) + stages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + return VkPipelineStageFlags(stages); +} + +static inline VkAccessFlags convert_vk_access_flags2(VkAccessFlags2 access) +{ + constexpr VkAccessFlags2 sampled_mask = + VK_ACCESS_2_SHADER_SAMPLED_READ_BIT | + VK_ACCESS_2_SHADER_STORAGE_READ_BIT | + VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR; + + constexpr VkAccessFlags2 storage_mask = + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT; + + if ((access & sampled_mask) != 0) + { + access |= VK_ACCESS_SHADER_READ_BIT; + access &= ~sampled_mask; + } + + if ((access & storage_mask) != 0) + { + access |= VK_ACCESS_SHADER_WRITE_BIT; + access &= ~storage_mask; + } + + return VkAccessFlags(access); +} + +enum CommandBufferDirtyBits +{ + COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT = 1 << 0, + COMMAND_BUFFER_DIRTY_PIPELINE_BIT = 1 << 1, + + COMMAND_BUFFER_DIRTY_VIEWPORT_BIT = 1 << 2, + COMMAND_BUFFER_DIRTY_SCISSOR_BIT = 1 << 3, + COMMAND_BUFFER_DIRTY_DEPTH_BIAS_BIT = 1 << 4, + COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT = 1 << 5, + + COMMAND_BUFFER_DIRTY_STATIC_VERTEX_BIT = 1 << 6, + + COMMAND_BUFFER_DIRTY_PUSH_CONSTANTS_BIT = 1 << 7, + + COMMAND_BUFFER_DYNAMIC_BITS = COMMAND_BUFFER_DIRTY_VIEWPORT_BIT | COMMAND_BUFFER_DIRTY_SCISSOR_BIT | + COMMAND_BUFFER_DIRTY_DEPTH_BIAS_BIT | + COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT +}; +using CommandBufferDirtyFlags = uint32_t; + +#define COMPARE_OP_BITS 3 +#define STENCIL_OP_BITS 3 +#define BLEND_FACTOR_BITS 5 +#define BLEND_OP_BITS 3 +#define CULL_MODE_BITS 2 +#define FRONT_FACE_BITS 1 +#define TOPOLOGY_BITS 4 +union PipelineState { + struct + { + // Word 0, tightly packed. + uint32_t depth_write : 1; + uint32_t depth_test : 1; + uint32_t blend_enable : 1; + uint32_t cull_mode : CULL_MODE_BITS; + uint32_t front_face : FRONT_FACE_BITS; + uint32_t depth_compare : COMPARE_OP_BITS; + uint32_t depth_bias_enable : 1; + uint32_t stencil_test : 1; + uint32_t stencil_front_fail : STENCIL_OP_BITS; + uint32_t stencil_front_pass : STENCIL_OP_BITS; + uint32_t stencil_front_depth_fail : STENCIL_OP_BITS; + uint32_t stencil_front_compare_op : COMPARE_OP_BITS; + uint32_t stencil_back_fail : STENCIL_OP_BITS; + uint32_t stencil_back_pass : STENCIL_OP_BITS; + uint32_t stencil_back_depth_fail : STENCIL_OP_BITS; + + // Word 1, tightly packed. + uint32_t stencil_back_compare_op : COMPARE_OP_BITS; + uint32_t alpha_to_coverage : 1; + uint32_t alpha_to_one : 1; + uint32_t sample_shading : 1; + uint32_t src_color_blend : BLEND_FACTOR_BITS; + uint32_t dst_color_blend : BLEND_FACTOR_BITS; + uint32_t color_blend_op : BLEND_OP_BITS; + uint32_t src_alpha_blend : BLEND_FACTOR_BITS; + uint32_t dst_alpha_blend : BLEND_FACTOR_BITS; + uint32_t alpha_blend_op : BLEND_OP_BITS; + + // Word 2, tightly packed. + uint32_t primitive_restart : 1; + uint32_t topology : TOPOLOGY_BITS; + uint32_t wireframe : 1; + uint32_t subgroup_control_size : 1; + uint32_t subgroup_full_group : 1; + uint32_t subgroup_minimum_size_log2 : 3; + uint32_t subgroup_maximum_size_log2 : 3; + uint32_t subgroup_control_size_task : 1; + uint32_t subgroup_full_group_task : 1; + uint32_t subgroup_minimum_size_log2_task : 3; + uint32_t subgroup_maximum_size_log2_task : 3; + uint32_t conservative_raster : 1; + uint32_t indirect_bindable : 1; + uint32_t padding : 8; + + // Word 3 + uint32_t write_mask; + } state; + uint32_t words[4]; +}; + +struct PotentialState +{ + float blend_constants[4]; + uint32_t spec_constants[VULKAN_NUM_TOTAL_SPEC_CONSTANTS]; + uint8_t spec_constant_mask; + uint8_t internal_spec_constant_mask; +}; + +struct DynamicState +{ + float depth_bias_constant = 0.0f; + float depth_bias_slope = 0.0f; + uint8_t front_compare_mask = 0; + uint8_t front_write_mask = 0; + uint8_t front_reference = 0; + uint8_t back_compare_mask = 0; + uint8_t back_write_mask = 0; + uint8_t back_reference = 0; +}; + +struct VertexAttribState +{ + uint32_t binding; + VkFormat format; + uint32_t offset; +}; + +struct IndexState +{ + VkBuffer buffer; + VkDeviceSize offset; + VkIndexType index_type; +}; + +struct VertexBindingState +{ + VkBuffer buffers[VULKAN_NUM_VERTEX_BUFFERS]; + VkDeviceSize offsets[VULKAN_NUM_VERTEX_BUFFERS]; +}; + +enum CommandBufferSavedStateBits +{ + COMMAND_BUFFER_SAVED_BINDINGS_0_BIT = 1u << 0, + COMMAND_BUFFER_SAVED_BINDINGS_1_BIT = 1u << 1, + COMMAND_BUFFER_SAVED_BINDINGS_2_BIT = 1u << 2, + COMMAND_BUFFER_SAVED_BINDINGS_3_BIT = 1u << 3, + COMMAND_BUFFER_SAVED_VIEWPORT_BIT = 1u << 4, + COMMAND_BUFFER_SAVED_SCISSOR_BIT = 1u << 5, + COMMAND_BUFFER_SAVED_RENDER_STATE_BIT = 1u << 6, + COMMAND_BUFFER_SAVED_PUSH_CONSTANT_BIT = 1u << 7 +}; +static_assert(VULKAN_NUM_DESCRIPTOR_SETS == 4, "Number of descriptor sets != 4."); +using CommandBufferSaveStateFlags = uint32_t; + +struct CommandBufferSavedState +{ + CommandBufferSaveStateFlags flags; + ResourceBindings bindings; + VkViewport viewport; + VkRect2D scissor; + + PipelineState static_state; + PotentialState potential_static_state; + DynamicState dynamic_state; +}; + +struct DeferredPipelineCompile +{ + Program *program; + const PipelineLayout *layout; + + const RenderPass *compatible_render_pass; + PipelineState static_state; + PotentialState potential_static_state; + VertexAttribState attribs[VULKAN_NUM_VERTEX_ATTRIBS]; + VkDeviceSize strides[VULKAN_NUM_VERTEX_BUFFERS]; + VkVertexInputRate input_rates[VULKAN_NUM_VERTEX_BUFFERS]; + + unsigned subpass_index; + Util::Hash hash; + VkPipelineCache cache; + uint32_t subgroup_size_tag; +}; + +class CommandBuffer; +struct CommandBufferDeleter +{ + void operator()(CommandBuffer *cmd); +}; + +class Device; +class CommandBuffer : public Util::IntrusivePtrEnabled +{ +public: + friend struct CommandBufferDeleter; + enum class Type + { + Generic = QUEUE_INDEX_GRAPHICS, + AsyncCompute = QUEUE_INDEX_COMPUTE, + AsyncTransfer = QUEUE_INDEX_TRANSFER, + VideoDecode = QUEUE_INDEX_VIDEO_DECODE, + VideoEncode = QUEUE_INDEX_VIDEO_ENCODE, + Count + }; + + ~CommandBuffer(); + VkCommandBuffer get_command_buffer() const + { + return cmd; + } + + void begin_region(const char *name, const float *color = nullptr); + void insert_label(const char *name, const float *color = nullptr); + void end_region(); + void checkpoint(const char *tag); + + Device &get_device() + { + return *device; + } + + VkPipelineStageFlags2 swapchain_touched_in_stages() const + { + return uses_swapchain_in_stages; + } + + // Only used when using swapchain in non-obvious ways, like compute or transfer. + void swapchain_touch_in_stages(VkPipelineStageFlags2 stages) + { + uses_swapchain_in_stages |= stages; + } + + void set_thread_index(unsigned index_) + { + thread_index = index_; + } + + void set_borrowed() + { + borrowed = true; + } + + bool is_borrowed() const + { + return borrowed; + } + + unsigned get_thread_index() const + { + return thread_index; + } + + bool get_is_secondary() const + { + return is_secondary; + } + + void set_breadcrumbs_handle(BufferMarkerHandle handle) + { + breadcrumbs = handle; + } + + void clear_image(const Image &image, const VkClearValue &value); + void clear_image(const Image &image, const VkClearValue &value, VkImageAspectFlags aspect); + void clear_quad(unsigned attachment, const VkClearRect &rect, const VkClearValue &value, + VkImageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT); + void clear_quad(const VkClearRect &rect, const VkClearAttachment *attachments, unsigned num_attachments); + + void fill_buffer(const Buffer &dst, uint32_t value); + void fill_buffer(const Buffer &dst, uint32_t value, VkDeviceSize offset, VkDeviceSize size); + void copy_buffer(const Buffer &dst, VkDeviceSize dst_offset, const Buffer &src, VkDeviceSize src_offset, + VkDeviceSize size); + void copy_buffer(const Buffer &dst, const Buffer &src); + void copy_buffer(const Buffer &dst, const Buffer &src, const VkBufferCopy *copies, size_t count); + void copy_image(const Image &dst, const Image &src); + void copy_image(const Image &dst, const Image &src, + const VkOffset3D &dst_offset, const VkOffset3D &src_offset, + const VkExtent3D &extent, + const VkImageSubresourceLayers &dst_subresource, + const VkImageSubresourceLayers &src_subresource); + + void copy_buffer_to_image(const Image &image, const Buffer &buffer, VkDeviceSize buffer_offset, + const VkOffset3D &offset, const VkExtent3D &extent, unsigned row_length, + unsigned slice_height, const VkImageSubresourceLayers &subresrouce); + void copy_buffer_to_image(const Image &image, const Buffer &buffer, unsigned num_blits, const VkBufferImageCopy *blits); + + void copy_image_to_buffer(const Buffer &buffer, const Image &image, unsigned num_blits, const VkBufferImageCopy *blits); + void copy_image_to_buffer(const Buffer &dst, const Image &src, VkDeviceSize buffer_offset, const VkOffset3D &offset, + const VkExtent3D &extent, unsigned row_length, unsigned slice_height, + const VkImageSubresourceLayers &subresrouce); + + void begin_barrier_batch(); + void end_barrier_batch(); + + void full_barrier(); + void pixel_barrier(); + + // Simplified global memory barrier. + void barrier(VkPipelineStageFlags2 src_stage, VkAccessFlags2 src_access, + VkPipelineStageFlags2 dst_stage, VkAccessFlags2 dst_access); + + PipelineEvent signal_event(const VkDependencyInfo &dep); + void wait_events(uint32_t num_events, const PipelineEvent *events, const VkDependencyInfo *deps); + + // Full expressive barrier. + void barrier(const VkDependencyInfo &dep); + + void buffer_barrier(const Buffer &buffer, + VkPipelineStageFlags2 src_stage, VkAccessFlags2 src_access, + VkPipelineStageFlags2 dst_stage, VkAccessFlags2 dst_access); + + void image_barrier(const Image &image, + VkImageLayout old_layout, VkImageLayout new_layout, + VkPipelineStageFlags2 src_stage, VkAccessFlags2 src_access, + VkPipelineStageFlags2 dst_stage, VkAccessFlags2 dst_access); + + void buffer_barriers(uint32_t buffer_barriers, const VkBufferMemoryBarrier2 *buffers); + void image_barriers(uint32_t image_barriers, const VkImageMemoryBarrier2 *images); + + void release_buffer_barrier(const Buffer &buffer, VkPipelineStageFlags2 src_stage, VkAccessFlags2 src_access, + uint32_t dst_queue_family = VK_QUEUE_FAMILY_EXTERNAL); + void acquire_buffer_barrier(const Buffer &buffer, VkPipelineStageFlags2 dst_stage, VkAccessFlags2 dst_access, + uint32_t src_queue_family = VK_QUEUE_FAMILY_EXTERNAL); + void release_image_barrier(const Image &image, + VkImageLayout old_layout, VkImageLayout new_layout, + VkPipelineStageFlags2 src_stage, VkAccessFlags2 src_access, + uint32_t dst_queue_family = VK_QUEUE_FAMILY_EXTERNAL); + void acquire_image_barrier(const Image &image, VkImageLayout old_layout, VkImageLayout new_layout, + VkPipelineStageFlags2 dst_stage, VkAccessFlags2 dst_access, + uint32_t src_queue_family = VK_QUEUE_FAMILY_EXTERNAL); + + void blit_image(const Image &dst, + const Image &src, + const VkOffset3D &dst_offset0, const VkOffset3D &dst_extent, + const VkOffset3D &src_offset0, const VkOffset3D &src_extent, unsigned dst_level, unsigned src_level, + unsigned dst_base_layer = 0, uint32_t src_base_layer = 0, unsigned num_layers = 1, + VkFilter filter = VK_FILTER_LINEAR); + + // Prepares an image to have its mipmap generated. + // Puts the top-level into TRANSFER_SRC_OPTIMAL, and all other levels are invalidated with an UNDEFINED -> TRANSFER_DST_OPTIMAL. + void barrier_prepare_generate_mipmap(const Image &image, VkImageLayout base_level_layout, + VkPipelineStageFlags2 src_stage, VkAccessFlags2 src_access, + bool need_top_level_barrier = true); + + // The image must have been transitioned with barrier_prepare_generate_mipmap before calling this function. + // After calling this function, the image will be entirely in TRANSFER_SRC_OPTIMAL layout. + // Wait for TRANSFER stage to drain before transitioning away from TRANSFER_SRC_OPTIMAL. + void generate_mipmap(const Image &image); + + void begin_render_pass(const RenderPassInfo &info, VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE); + void next_subpass(VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE); + void end_render_pass(); + void submit_secondary(Util::IntrusivePtr secondary); + inline unsigned get_current_subpass() const + { + return pipeline_state.subpass_index; + } + Util::IntrusivePtr request_secondary_command_buffer(unsigned thread_index, unsigned subpass); + static Util::IntrusivePtr request_secondary_command_buffer(Device &device, + const RenderPassInfo &rp, unsigned thread_index, unsigned subpass); + + void set_program(Program *program); + + // Pipeline state must not change between calling this and dispatching. + // Ideally it's called right before execute indirect commands. + // The execution set handle is only valid as long as the creating command buffer is alive. + + struct ExecutionSetSpecializationConstants + { + uint32_t mask; + uint32_t constants[VULKAN_NUM_USER_SPEC_CONSTANTS]; + }; + + VkIndirectExecutionSetEXT bake_and_set_program_group( + Program * const *programs, unsigned num_programs, + const ExecutionSetSpecializationConstants *spec_constants, + const PipelineLayout *layout); + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + // Convenience functions for one-off shader binds. + void set_program(const std::string &task, const std::string &mesh, const std::string &fragment, + const std::vector> &defines = {}); + void set_program(const std::string &vertex, const std::string &fragment, + const std::vector> &defines = {}); + void set_program(const std::string &compute, + const std::vector> &defines = {}); +#endif + + void set_buffer_view(unsigned set, unsigned binding, const BufferView &view); + void set_storage_buffer_view(unsigned set, unsigned binding, const BufferView &view); + void set_input_attachments(unsigned set, unsigned start_binding); + void set_texture(unsigned set, unsigned binding, const ImageView &view); + void set_unorm_texture(unsigned set, unsigned binding, const ImageView &view); + void set_srgb_texture(unsigned set, unsigned binding, const ImageView &view); + void set_texture(unsigned set, unsigned binding, const ImageView &view, const Sampler &sampler); + void set_texture(unsigned set, unsigned binding, const ImageView &view, StockSampler sampler); + void set_storage_texture(unsigned set, unsigned binding, const ImageView &view); + void set_storage_texture_level(unsigned set, unsigned binding, const ImageView &view, unsigned level); + void set_unorm_storage_texture(unsigned set, unsigned binding, const ImageView &view); + void set_sampler(unsigned set, unsigned binding, const Sampler &sampler); + void set_sampler(unsigned set, unsigned binding, StockSampler sampler); + void set_uniform_buffer(unsigned set, unsigned binding, const Buffer &buffer); + void set_uniform_buffer(unsigned set, unsigned binding, const Buffer &buffer, VkDeviceSize offset, + VkDeviceSize range); + void set_storage_buffer(unsigned set, unsigned binding, const Buffer &buffer); + void set_storage_buffer(unsigned set, unsigned binding, const Buffer &buffer, VkDeviceSize offset, + VkDeviceSize range); + void set_rtas(unsigned set, unsigned binding, const RTAS &rtas); + + void set_bindless(unsigned set, const BindlessDescriptorSet &handle); + + void push_constants(const void *data, VkDeviceSize offset, VkDeviceSize range); + + void *allocate_constant_data(unsigned set, unsigned binding, VkDeviceSize size); + + template + T *allocate_typed_constant_data(unsigned set, unsigned binding, unsigned count) + { + return static_cast(allocate_constant_data(set, binding, count * sizeof(T))); + } + + void *allocate_vertex_data(unsigned binding, VkDeviceSize size, VkDeviceSize stride, + VkVertexInputRate step_rate = VK_VERTEX_INPUT_RATE_VERTEX); + void *allocate_index_data(VkDeviceSize size, VkIndexType index_type); + + void *update_buffer(const Buffer &buffer, VkDeviceSize offset, VkDeviceSize size); + void update_buffer_inline(const Buffer &buffer, VkDeviceSize offset, VkDeviceSize size, + const void *data); + void *update_image(const Image &image, const VkOffset3D &offset, const VkExtent3D &extent, uint32_t row_length, + uint32_t image_height, const VkImageSubresourceLayers &subresource); + void *update_image(const Image &image, uint32_t row_length = 0, uint32_t image_height = 0); + BufferBlockAllocation request_scratch_buffer_memory(VkDeviceSize size); + + void set_viewport(const VkViewport &viewport); + const VkViewport &get_viewport() const; + void set_scissor(const VkRect2D &rect); + + void set_vertex_attrib(uint32_t attrib, uint32_t binding, VkFormat format, VkDeviceSize offset); + void set_vertex_binding(uint32_t binding, const Buffer &buffer, VkDeviceSize offset, VkDeviceSize stride, + VkVertexInputRate step_rate = VK_VERTEX_INPUT_RATE_VERTEX); + void set_index_buffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType index_type); + + void draw(uint32_t vertex_count, uint32_t instance_count = 1, uint32_t first_vertex = 0, + uint32_t first_instance = 0); + void draw_indexed(uint32_t index_count, uint32_t instance_count = 1, uint32_t first_index = 0, + int32_t vertex_offset = 0, uint32_t first_instance = 0); + void draw_mesh_tasks(uint32_t tasks_x, uint32_t tasks_y, uint32_t tasks_z); + + void dispatch(uint32_t groups_x, uint32_t groups_y, uint32_t groups_z); + + void draw_indirect(const Buffer &buffer, VkDeviceSize offset, uint32_t draw_count, uint32_t stride); + void draw_indexed_indirect(const Buffer &buffer, VkDeviceSize offset, uint32_t draw_count, uint32_t stride); + void draw_multi_indirect(const Buffer &buffer, VkDeviceSize offset, uint32_t draw_count, uint32_t stride, + const Buffer &count, VkDeviceSize count_offset); + void draw_indexed_multi_indirect(const Buffer &buffer, VkDeviceSize offset, uint32_t draw_count, uint32_t stride, + const Buffer &count, VkDeviceSize count_offset); + void dispatch_indirect(const Buffer &buffer, VkDeviceSize offset); + void draw_mesh_tasks_indirect(const Buffer &buffer, VkDeviceSize offset, uint32_t draw_count, uint32_t stride); + void draw_mesh_tasks_multi_indirect(const Buffer &buffer, VkDeviceSize offset, uint32_t draw_count, uint32_t stride, + const Buffer &count, VkDeviceSize count_offset); + void execute_indirect_commands(VkIndirectExecutionSetEXT execution_set, + const IndirectLayout *indirect_layout, + uint32_t sequences, + const Buffer &indirect, VkDeviceSize offset, + const Buffer *count, size_t count_offset, + CommandBuffer &preprocess); + + void begin_rtas_batch(); + void build_rtas(BuildMode mode, const RTAS &rtas, const BottomRTASCreateInfo &info); + void build_rtas(BuildMode mode, const RTAS &rtas, const TopRTASCreateInfo &info); + void write_compacted_rtas_size(const RTAS &rtas, const QueryPoolResult &query); + void compact_rtas(const RTAS &dst, const RTAS &src); + void end_rtas_batch(); + + void set_opaque_state(); + void set_quad_state(); + void set_opaque_sprite_state(); + void set_transparent_sprite_state(); + + void save_state(CommandBufferSaveStateFlags flags, CommandBufferSavedState &state); + void restore_state(const CommandBufferSavedState &state); + +#define SET_STATIC_STATE(value) \ + do \ + { \ + if (pipeline_state.static_state.state.value != value) \ + { \ + pipeline_state.static_state.state.value = value; \ + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); \ + } \ + } while (0) + +#define SET_POTENTIALLY_STATIC_STATE(value) \ + do \ + { \ + if (pipeline_state.potential_static_state.value != value) \ + { \ + pipeline_state.potential_static_state.value = value; \ + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); \ + } \ + } while (0) + + inline void set_depth_test(bool depth_test, bool depth_write) + { + SET_STATIC_STATE(depth_test); + SET_STATIC_STATE(depth_write); + } + + inline void set_wireframe(bool wireframe) + { + SET_STATIC_STATE(wireframe); + } + + inline void set_depth_compare(VkCompareOp depth_compare) + { + SET_STATIC_STATE(depth_compare); + } + + inline void set_blend_enable(bool blend_enable) + { + SET_STATIC_STATE(blend_enable); + } + + inline void set_blend_factors(VkBlendFactor src_color_blend, VkBlendFactor src_alpha_blend, + VkBlendFactor dst_color_blend, VkBlendFactor dst_alpha_blend) + { + SET_STATIC_STATE(src_color_blend); + SET_STATIC_STATE(dst_color_blend); + SET_STATIC_STATE(src_alpha_blend); + SET_STATIC_STATE(dst_alpha_blend); + } + + inline void set_blend_factors(VkBlendFactor src_blend, VkBlendFactor dst_blend) + { + set_blend_factors(src_blend, src_blend, dst_blend, dst_blend); + } + + inline void set_blend_op(VkBlendOp color_blend_op, VkBlendOp alpha_blend_op) + { + SET_STATIC_STATE(color_blend_op); + SET_STATIC_STATE(alpha_blend_op); + } + + inline void set_blend_op(VkBlendOp blend_op) + { + set_blend_op(blend_op, blend_op); + } + + inline void set_depth_bias(bool depth_bias_enable) + { + SET_STATIC_STATE(depth_bias_enable); + } + + inline void set_color_write_mask(uint32_t write_mask) + { + SET_STATIC_STATE(write_mask); + } + + inline void set_stencil_test(bool stencil_test) + { + SET_STATIC_STATE(stencil_test); + } + + inline void set_stencil_front_ops(VkCompareOp stencil_front_compare_op, VkStencilOp stencil_front_pass, + VkStencilOp stencil_front_fail, VkStencilOp stencil_front_depth_fail) + { + SET_STATIC_STATE(stencil_front_compare_op); + SET_STATIC_STATE(stencil_front_pass); + SET_STATIC_STATE(stencil_front_fail); + SET_STATIC_STATE(stencil_front_depth_fail); + } + + inline void set_stencil_back_ops(VkCompareOp stencil_back_compare_op, VkStencilOp stencil_back_pass, + VkStencilOp stencil_back_fail, VkStencilOp stencil_back_depth_fail) + { + SET_STATIC_STATE(stencil_back_compare_op); + SET_STATIC_STATE(stencil_back_pass); + SET_STATIC_STATE(stencil_back_fail); + SET_STATIC_STATE(stencil_back_depth_fail); + } + + inline void set_stencil_ops(VkCompareOp stencil_compare_op, VkStencilOp stencil_pass, VkStencilOp stencil_fail, + VkStencilOp stencil_depth_fail) + { + set_stencil_front_ops(stencil_compare_op, stencil_pass, stencil_fail, stencil_depth_fail); + set_stencil_back_ops(stencil_compare_op, stencil_pass, stencil_fail, stencil_depth_fail); + } + + inline void set_primitive_topology(VkPrimitiveTopology topology) + { + SET_STATIC_STATE(topology); + } + + inline void set_primitive_restart(bool primitive_restart) + { + SET_STATIC_STATE(primitive_restart); + } + + inline void set_multisample_state(bool alpha_to_coverage, bool alpha_to_one = false, bool sample_shading = false) + { + SET_STATIC_STATE(alpha_to_coverage); + SET_STATIC_STATE(alpha_to_one); + SET_STATIC_STATE(sample_shading); + } + + inline void set_front_face(VkFrontFace front_face) + { + SET_STATIC_STATE(front_face); + } + + inline void set_cull_mode(VkCullModeFlags cull_mode) + { + SET_STATIC_STATE(cull_mode); + } + + inline void set_blend_constants(const float blend_constants[4]) + { + SET_POTENTIALLY_STATIC_STATE(blend_constants[0]); + SET_POTENTIALLY_STATIC_STATE(blend_constants[1]); + SET_POTENTIALLY_STATIC_STATE(blend_constants[2]); + SET_POTENTIALLY_STATIC_STATE(blend_constants[3]); + } + + inline void set_specialization_constant_mask(uint32_t spec_constant_mask) + { + VK_ASSERT((spec_constant_mask & ~((1u << VULKAN_NUM_USER_SPEC_CONSTANTS) - 1u)) == 0u); + SET_POTENTIALLY_STATIC_STATE(spec_constant_mask); + } + + template + inline void set_specialization_constant(unsigned index, const T &value) + { + VK_ASSERT(index < VULKAN_NUM_USER_SPEC_CONSTANTS); + static_assert(sizeof(value) == sizeof(uint32_t), "Spec constant data must be 32-bit."); + if (memcmp(&pipeline_state.potential_static_state.spec_constants[index], &value, sizeof(value))) + { + memcpy(&pipeline_state.potential_static_state.spec_constants[index], &value, sizeof(value)); + if (pipeline_state.potential_static_state.spec_constant_mask & (1u << index)) + set_dirty(COMMAND_BUFFER_DIRTY_STATIC_STATE_BIT); + } + } + + inline void set_specialization_constant(unsigned index, bool value) + { + set_specialization_constant(index, uint32_t(value)); + } + + inline void enable_subgroup_size_control(bool subgroup_control_size, + VkShaderStageFlagBits stage = VK_SHADER_STAGE_COMPUTE_BIT) + { + VK_ASSERT(stage == VK_SHADER_STAGE_TASK_BIT_EXT || + stage == VK_SHADER_STAGE_MESH_BIT_EXT || + stage == VK_SHADER_STAGE_COMPUTE_BIT); + + if (stage != VK_SHADER_STAGE_TASK_BIT_EXT) + { + SET_STATIC_STATE(subgroup_control_size); + } + else + { + auto subgroup_control_size_task = subgroup_control_size; + SET_STATIC_STATE(subgroup_control_size_task); + } + } + + inline void set_subgroup_size_log2(bool subgroup_full_group, + uint8_t subgroup_minimum_size_log2, + uint8_t subgroup_maximum_size_log2, + VkShaderStageFlagBits stage = VK_SHADER_STAGE_COMPUTE_BIT) + { + VK_ASSERT(stage == VK_SHADER_STAGE_TASK_BIT_EXT || + stage == VK_SHADER_STAGE_MESH_BIT_EXT || + stage == VK_SHADER_STAGE_COMPUTE_BIT); + + VK_ASSERT(subgroup_minimum_size_log2 < 8); + VK_ASSERT(subgroup_maximum_size_log2 < 8); + + if (stage != VK_SHADER_STAGE_TASK_BIT_EXT) + { + SET_STATIC_STATE(subgroup_full_group); + SET_STATIC_STATE(subgroup_minimum_size_log2); + SET_STATIC_STATE(subgroup_maximum_size_log2); + } + else + { + auto subgroup_full_group_task = subgroup_full_group; + auto subgroup_minimum_size_log2_task = subgroup_minimum_size_log2; + auto subgroup_maximum_size_log2_task = subgroup_maximum_size_log2; + SET_STATIC_STATE(subgroup_full_group_task); + SET_STATIC_STATE(subgroup_minimum_size_log2_task); + SET_STATIC_STATE(subgroup_maximum_size_log2_task); + } + } + + inline void set_conservative_rasterization(bool conservative_raster) + { + SET_STATIC_STATE(conservative_raster); + } + +#define SET_DYNAMIC_STATE(state, flags) \ + do \ + { \ + if (dynamic_state.state != state) \ + { \ + dynamic_state.state = state; \ + set_dirty(flags); \ + } \ + } while (0) + + inline void set_depth_bias(float depth_bias_constant, float depth_bias_slope) + { + SET_DYNAMIC_STATE(depth_bias_constant, COMMAND_BUFFER_DIRTY_DEPTH_BIAS_BIT); + SET_DYNAMIC_STATE(depth_bias_slope, COMMAND_BUFFER_DIRTY_DEPTH_BIAS_BIT); + } + + inline void set_stencil_front_reference(uint8_t front_compare_mask, uint8_t front_write_mask, + uint8_t front_reference) + { + SET_DYNAMIC_STATE(front_compare_mask, COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT); + SET_DYNAMIC_STATE(front_write_mask, COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT); + SET_DYNAMIC_STATE(front_reference, COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT); + } + + inline void set_stencil_back_reference(uint8_t back_compare_mask, uint8_t back_write_mask, uint8_t back_reference) + { + SET_DYNAMIC_STATE(back_compare_mask, COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT); + SET_DYNAMIC_STATE(back_write_mask, COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT); + SET_DYNAMIC_STATE(back_reference, COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT); + } + + inline void set_stencil_reference(uint8_t compare_mask, uint8_t write_mask, uint8_t reference) + { + set_stencil_front_reference(compare_mask, write_mask, reference); + set_stencil_back_reference(compare_mask, write_mask, reference); + } + + inline Type get_command_buffer_type() const + { + return type; + } + + QueryPoolHandle write_timestamp(VkPipelineStageFlags2 stage); + + // Used when recording command buffers in a thread, and submitting them in a different thread. + // Need to make sure that no further commands on the VkCommandBuffer happen. + void end_threaded_recording(); + // End is called automatically by Device in submission. Should not be called by application. + void end(); + void enable_profiling(); + bool has_profiling() const; + + void begin_debug_channel(DebugChannelInterface *iface, const char *tag, VkDeviceSize size); + void end_debug_channel(); + + void extract_pipeline_state(DeferredPipelineCompile &compile) const; + + enum class CompileMode + { + Sync, + FailOnCompileRequired, + AsyncThread + }; + static Pipeline build_graphics_pipeline(Device *device, const DeferredPipelineCompile &compile, CompileMode mode); + static Pipeline build_compute_pipeline(Device *device, const DeferredPipelineCompile &compile, CompileMode mode); + bool flush_pipeline_state_without_blocking(); + + VkPipeline get_current_compute_pipeline(); + VkPipeline get_current_graphics_pipeline(); + +private: + friend class Util::ObjectPool; + CommandBuffer(Device *device, VkCommandBuffer cmd, VkPipelineCache cache, Type type, bool secondary); + + Device *device; + const VolkDeviceTable &table; + VkCommandBuffer cmd; + Type type; + BufferMarkerHandle breadcrumbs; + + const Framebuffer *framebuffer = nullptr; + const RenderPass *actual_render_pass = nullptr; + const Vulkan::ImageView *framebuffer_attachments[VULKAN_NUM_ATTACHMENTS + 1] = {}; + + IndexState index_state = {}; + VertexBindingState vbo = {}; + ResourceBindings bindings; + VkDescriptorSet bindless_sets[VULKAN_NUM_DESCRIPTOR_SETS] = {}; + VkDescriptorSet allocated_sets[VULKAN_NUM_DESCRIPTOR_SETS] = {}; + + Pipeline current_pipeline = {}; + VkPipelineLayout current_pipeline_layout = VK_NULL_HANDLE; + VkSubpassContents current_contents = VK_SUBPASS_CONTENTS_INLINE; + unsigned thread_index = 0; + bool borrowed = false; + + VkViewport viewport = {}; + VkRect2D scissor = {}; + + CommandBufferDirtyFlags dirty = ~0u; + uint32_t dirty_sets_realloc = 0; + uint32_t dirty_sets_rebind = 0; + uint32_t dirty_vbos = 0; + uint32_t active_vbos = 0; + VkPipelineStageFlags2 uses_swapchain_in_stages = 0; + bool is_compute = true; + bool is_secondary = false; + bool is_ended = false; + bool framebuffer_is_multiview = false; + + void set_dirty(CommandBufferDirtyFlags flags) + { + dirty |= flags; + } + + CommandBufferDirtyFlags get_and_clear(CommandBufferDirtyFlags flags) + { + auto mask = dirty & flags; + dirty &= ~flags; + return mask; + } + + DeferredPipelineCompile pipeline_state = {}; + DynamicState dynamic_state = {}; +#ifndef _MSC_VER + static_assert(sizeof(pipeline_state.static_state.words) >= sizeof(pipeline_state.static_state.state), + "Hashable pipeline state is not large enough!"); +#endif + + VkPipeline flush_render_state(bool synchronous); + VkPipeline flush_compute_state(bool synchronous); + void clear_render_state(); + + bool flush_graphics_pipeline(bool synchronous); + bool flush_compute_pipeline(bool synchronous); + void flush_descriptor_sets(); + void begin_graphics(); + void flush_descriptor_set( + uint32_t set, VkDescriptorSet *sets, + uint32_t &first_set, uint32_t &set_count); + void push_descriptor_set(uint32_t set); + void rebind_descriptor_set( + uint32_t set, VkDescriptorSet *sets, + uint32_t &first_set, uint32_t &set_count); + void flush_descriptor_binds(const VkDescriptorSet *sets, + uint32_t &first_set, uint32_t &set_count); + void rebind_descriptor_offset(uint32_t set, uint32_t &first_set, uint32_t &set_count); + void allocate_descriptor_offset(uint32_t set, uint32_t &first_set, uint32_t &set_count); + void flush_descriptor_offsets(uint32_t &first_set, uint32_t &set_count); + void validate_descriptor_binds(uint32_t set); + void allocate_descriptor_heap_set(uint32_t set); + void rebind_descriptor_heap_set(uint32_t set); + + struct DescriptorSlice + { + uint8_t *mapped; + VkDeviceSize offset; + }; + DescriptorSlice allocate_descriptor_slice(VkDeviceSize size, VkDeviceSize alignment); + + void begin_compute(); + void begin_context(); + + BufferBlock vbo_block; + BufferBlock ibo_block; + BufferBlock ubo_block; + BufferBlock staging_block; + + DescriptorBufferAllocation desc_buffer = {}; + VkDeviceSize desc_buffer_alloc_offset = 0; + VkDeviceSize desc_buffer_heap_cached_offsets[VULKAN_NUM_DESCRIPTOR_SETS]; + VkDeviceAddress desc_heap_cached_table[VULKAN_NUM_DESCRIPTOR_SETS]; + bool desc_buffer_enable = false; + bool desc_heap_enable = false; + + void set_texture(unsigned set, unsigned binding, + VkImageView float_view, VkImageView integer_view, VkImageLayout layout, + const CachedDescriptorPayload &float_payload, const CachedDescriptorPayload &integer_payload, + uint64_t cookie); + void set_buffer_view_common(unsigned set, unsigned binding, const BufferView &view, VkDescriptorType type); + + void init_viewport_scissor(const RenderPassInfo &info, const Framebuffer *framebuffer); + void init_surface_transform(const RenderPassInfo &info); + VkSurfaceTransformFlagBitsKHR current_framebuffer_surface_transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + + bool profiling = false; + std::string debug_channel_tag; + Vulkan::BufferHandle debug_channel_buffer; + DebugChannelInterface *debug_channel_interface = nullptr; + + void bind_pipeline(VkPipelineBindPoint bind_point, VkPipeline pipeline, uint32_t active_dynamic_state); + + static void update_hash_graphics_pipeline(DeferredPipelineCompile &compile, uint32_t *active_vbos); + static void update_hash_compute_pipeline(DeferredPipelineCompile &compile); + void set_surface_transform_specialization_constants(); + + void set_program_layout(const PipelineLayout *layout); + + static bool setup_subgroup_size_control(Device &device, VkPipelineShaderStageCreateInfo &stage_info, + VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT &required_info, + VkShaderStageFlagBits stage, + bool full_group, unsigned min_size_log2, unsigned max_size_log2); + + struct + { + Util::SmallVector memory_barriers; + Util::SmallVector buffer_barriers; + Util::SmallVector image_barriers; + bool active = false; + } barrier_batch; + + struct RTASBatch + { + struct Range { VkAccelerationStructureKHR dst, src; VkDeviceSize scratch; size_t start, count; }; + struct Query { VkAccelerationStructureKHR rtas; VkQueryPool pool; uint32_t index; }; + + Util::SmallVector geometries_conv; + Util::SmallVector geom_info; + Util::SmallVector range_infos; + Util::SmallVector range_info_ptrs; + + Util::SmallVector geometries; // BLAS + Util::SmallVector instances; // TLAS + Util::SmallVector ranges; + Util::SmallVector build_modes; + Util::SmallVector blas_modes; + Util::SmallVector queries; + + BufferHandle scratch; + bool in_batch = false; + } rtas_batch; + + void build_blas_batch(); + void build_tlas_batch(); + void setup_batch(VkAccelerationStructureTypeKHR rtas_type); + void emit_scratch_barrier(); + + template void checkpoint(Ts &&... ts); + template void checkpoint_with_signal(Ts &&... ts); +}; + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES +struct CommandBufferUtil +{ + static void draw_fullscreen_quad(CommandBuffer &cmd, const std::string &vertex, const std::string &fragment, + const std::vector> &defines = {}); + static void draw_fullscreen_quad_depth(CommandBuffer &cmd, const std::string &vertex, const std::string &fragment, + bool depth_test, bool depth_write, VkCompareOp depth_compare, + const std::vector> &defines = {}); + static void set_fullscreen_quad_vertex_state(CommandBuffer &cmd); + static void set_quad_vertex_state(CommandBuffer &cmd); + + static void setup_fullscreen_quad(CommandBuffer &cmd, const std::string &vertex, const std::string &fragment, + const std::vector> &defines = {}, + bool depth_test = false, bool depth_write = false, + VkCompareOp depth_compare = VK_COMPARE_OP_ALWAYS); + + static void draw_fullscreen_quad(CommandBuffer &cmd, unsigned instances = 1); + static void draw_quad(CommandBuffer &cmd, unsigned instances = 1); +}; +#endif + +using CommandBufferHandle = Util::IntrusivePtr; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_pool.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_pool.cpp new file mode 100644 index 00000000..e7e60737 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_pool.cpp @@ -0,0 +1,180 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "command_pool.hpp" +#include "device.hpp" + +namespace Vulkan +{ +CommandPool::CommandPool(Device *device_, uint32_t queue_family_index) + : device(device_), table(&device_->get_device_table()) +{ + VkCommandPoolCreateInfo info = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; + info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; + info.queueFamilyIndex = queue_family_index; + if (queue_family_index != VK_QUEUE_FAMILY_IGNORED) + table->vkCreateCommandPool(device->get_device(), &info, nullptr, &pool); +} + +CommandPool::CommandPool(CommandPool &&other) noexcept +{ + *this = std::move(other); +} + +CommandPool &CommandPool::operator=(CommandPool &&other) noexcept +{ + if (this != &other) + { + device = other.device; + table = other.table; + if (!buffers.empty()) + table->vkFreeCommandBuffers(device->get_device(), pool, buffers.size(), buffers.data()); + if (pool != VK_NULL_HANDLE) + table->vkDestroyCommandPool(device->get_device(), pool, nullptr); + + pool = VK_NULL_HANDLE; + buffers.clear(); + std::swap(pool, other.pool); + std::swap(buffers, other.buffers); + index = other.index; + other.index = 0; +#ifdef VULKAN_DEBUG + in_flight.clear(); + std::swap(in_flight, other.in_flight); +#endif + } + return *this; +} + +CommandPool::~CommandPool() +{ + if (!buffers.empty()) + table->vkFreeCommandBuffers(device->get_device(), pool, buffers.size(), buffers.data()); + if (!secondary_buffers.empty()) + table->vkFreeCommandBuffers(device->get_device(), pool, secondary_buffers.size(), secondary_buffers.data()); + if (pool != VK_NULL_HANDLE) + table->vkDestroyCommandPool(device->get_device(), pool, nullptr); +} + +void CommandPool::signal_submitted(VkCommandBuffer cmd) +{ +#ifdef VULKAN_DEBUG + VK_ASSERT(in_flight.find(cmd) != end(in_flight)); + in_flight.erase(cmd); +#else + (void)cmd; +#endif +} + +VkCommandBuffer CommandPool::request_secondary_command_buffer() +{ + VK_ASSERT(pool != VK_NULL_HANDLE); + + if (secondary_index < secondary_buffers.size()) + { + auto ret = secondary_buffers[secondary_index++]; +#ifdef VULKAN_DEBUG + VK_ASSERT(in_flight.find(ret) == end(in_flight)); + in_flight.insert(ret); +#endif + return ret; + } + else + { + VkCommandBuffer cmd; + VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; + info.commandPool = pool; + info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; + info.commandBufferCount = 1; + + table->vkAllocateCommandBuffers(device->get_device(), &info, &cmd); +#ifdef VULKAN_DEBUG + VK_ASSERT(in_flight.find(cmd) == end(in_flight)); + in_flight.insert(cmd); +#endif + secondary_buffers.push_back(cmd); + secondary_index++; + return cmd; + } +} + +VkCommandBuffer CommandPool::request_command_buffer() +{ + VK_ASSERT(pool != VK_NULL_HANDLE); + + if (index < buffers.size()) + { + auto ret = buffers[index++]; +#ifdef VULKAN_DEBUG + VK_ASSERT(in_flight.find(ret) == end(in_flight)); + in_flight.insert(ret); +#endif + return ret; + } + else + { + VkCommandBuffer cmd; + VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; + info.commandPool = pool; + info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + info.commandBufferCount = 1; + + table->vkAllocateCommandBuffers(device->get_device(), &info, &cmd); +#ifdef VULKAN_DEBUG + VK_ASSERT(in_flight.find(cmd) == end(in_flight)); + in_flight.insert(cmd); +#endif + buffers.push_back(cmd); + index++; + return cmd; + } +} + +void CommandPool::begin() +{ + if (pool == VK_NULL_HANDLE) + return; + +#ifdef VULKAN_DEBUG + VK_ASSERT(in_flight.empty()); +#endif + if (index > 0 || secondary_index > 0) + table->vkResetCommandPool(device->get_device(), pool, 0); + index = 0; + secondary_index = 0; +} + +void CommandPool::trim() +{ + if (pool == VK_NULL_HANDLE) + return; + + table->vkResetCommandPool(device->get_device(), pool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); + if (!buffers.empty()) + table->vkFreeCommandBuffers(device->get_device(), pool, buffers.size(), buffers.data()); + if (!secondary_buffers.empty()) + table->vkFreeCommandBuffers(device->get_device(), pool, secondary_buffers.size(), secondary_buffers.data()); + buffers.clear(); + secondary_buffers.clear(); + table->vkTrimCommandPool(device->get_device(), pool, 0); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_pool.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_pool.hpp new file mode 100644 index 00000000..8f67fcfb --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/command_pool.hpp @@ -0,0 +1,61 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include +#include + +namespace Vulkan +{ +class Device; +class CommandPool +{ +public: + CommandPool(Device *device, uint32_t queue_family_index); + ~CommandPool(); + + CommandPool(CommandPool &&) noexcept; + CommandPool &operator=(CommandPool &&) noexcept; + CommandPool(const CommandPool &) = delete; + void operator=(const CommandPool &) = delete; + + void begin(); + void trim(); + VkCommandBuffer request_command_buffer(); + VkCommandBuffer request_secondary_command_buffer(); + void signal_submitted(VkCommandBuffer cmd); + +private: + Device *device; + const VolkDeviceTable *table; + VkCommandPool pool = VK_NULL_HANDLE; + std::vector buffers; + std::vector secondary_buffers; +#ifdef VULKAN_DEBUG + std::unordered_set in_flight; +#endif + unsigned index = 0; + unsigned secondary_index = 0; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/context.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/context.cpp new file mode 100644 index 00000000..5257fc33 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/context.cpp @@ -0,0 +1,2323 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "context.hpp" +#include "limits.hpp" +#include "small_vector.hpp" +#include "environment.hpp" +#include "bitops.hpp" +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#elif defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#if defined(ANDROID) && defined(HAVE_SWAPPY) +#include "swappy/swappyVk.h" +#endif + +#ifdef HAVE_GRANITE_VULKAN_POST_MORTEM +#include "post_mortem.hpp" +#endif + +//#undef VULKAN_DEBUG + +#ifdef GRANITE_VULKAN_PROFILES +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +// We need to make sure profiles implementation sees volk symbols, not loader. +#include "vulkan/vulkan_profiles.cpp" +// Ideally there would be a vpQueryProfile which returns a const pointer to static VpProfileProperties, +// so we wouldn't have to do this. +struct ProfileHolder +{ + explicit ProfileHolder(const std::string &name) + { + if (name.empty()) + return; + + uint32_t count; + vpGetProfiles(&count, nullptr); + props.resize(count); + vpGetProfiles(&count, props.data()); + + for (auto &prop : props) + if (name == prop.profileName) + profile = ∝ + } + Util::SmallVector props; + const VpProfileProperties *profile = nullptr; +}; + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif +#endif + +#define NV_DRIVER_VERSION_MAJOR(v) (uint32_t(v) >> 22) + +namespace Vulkan +{ +static constexpr ContextCreationFlags video_context_flags = + CONTEXT_CREATION_ENABLE_VIDEO_DECODE_BIT | + CONTEXT_CREATION_ENABLE_VIDEO_ENCODE_BIT | + CONTEXT_CREATION_ENABLE_VIDEO_FEATURE_ONLY_BIT; + +void Context::set_instance_factory(InstanceFactory *factory) +{ + instance_factory = factory; +} + +void Context::set_device_factory(DeviceFactory *factory) +{ + device_factory = factory; +} + +void Context::set_application_info(const VkApplicationInfo *app_info) +{ + user_application_info.copy_assign(app_info); + VK_ASSERT(!app_info || app_info->apiVersion >= VK_API_VERSION_1_1); +} + +CopiedApplicationInfo::CopiedApplicationInfo() +{ + set_default_app(); +} + +void CopiedApplicationInfo::set_default_app() +{ + engine.clear(); + application.clear(); + app = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, + "Granite", 0, "Granite", 0, + VK_API_VERSION_1_1, + }; +} + +void CopiedApplicationInfo::copy_assign(const VkApplicationInfo *info) +{ + if (info) + { + app = *info; + + if (info->pApplicationName) + { + application = info->pApplicationName; + app.pApplicationName = application.c_str(); + } + else + application.clear(); + + if (info->pEngineName) + { + engine = info->pEngineName; + app.pEngineName = engine.c_str(); + } + else + engine.clear(); + } + else + { + set_default_app(); + } +} + +const VkApplicationInfo &CopiedApplicationInfo::get_application_info() const +{ + return app; +} + +bool Context::init_instance(const char * const *instance_ext, uint32_t instance_ext_count, ContextCreationFlags flags) +{ + destroy_device(); + destroy_instance(); + + owned_instance = !instance_factory || !instance_factory->factory_owns_created_instance(); + if (!create_instance(instance_ext, instance_ext_count, flags)) + { + destroy_instance(); + LOGE("Failed to create Vulkan instance.\n"); + return false; + } + + return true; +} + +bool Context::init_device(VkPhysicalDevice gpu_, VkSurfaceKHR surface_compat, const char *const *device_ext, + uint32_t device_ext_count, ContextCreationFlags flags) +{ + owned_device = !device_factory || !device_factory->factory_owns_created_device(); + VkPhysicalDeviceFeatures features = {}; + if (!create_device(gpu_, surface_compat, device_ext, device_ext_count, &features, flags)) + { + destroy_device(); + LOGE("Failed to create Vulkan device.\n"); + return false; + } + + return true; +} + +bool Context::init_instance_and_device(const char * const *instance_ext, uint32_t instance_ext_count, + const char * const *device_ext, uint32_t device_ext_count, + ContextCreationFlags flags) +{ + if (!init_instance(instance_ext, instance_ext_count, flags)) + return false; + if (!init_device(VK_NULL_HANDLE, VK_NULL_HANDLE, device_ext, device_ext_count, flags)) + return false; + return true; +} + +static std::mutex loader_init_lock; +static bool loader_init_once; +static PFN_vkGetInstanceProcAddr instance_proc_addr; + +PFN_vkGetInstanceProcAddr Context::get_instance_proc_addr() +{ + return instance_proc_addr; +} + +bool Context::init_loader(PFN_vkGetInstanceProcAddr addr, bool force_reload) +{ + std::lock_guard holder(loader_init_lock); + if (loader_init_once && !force_reload && !addr) + return true; + + if (!addr) + { +#ifndef _WIN32 + static void *module; + if (!module) + { + auto vulkan_path = Util::get_environment_string("GRANITE_VULKAN_LIBRARY", ""); + if (!vulkan_path.empty()) + module = dlopen(vulkan_path.c_str(), RTLD_LOCAL | RTLD_LAZY); +#ifdef __APPLE__ + if (!module) + module = dlopen("libvulkan.1.dylib", RTLD_LOCAL | RTLD_LAZY); + if (!module) + module = dlopen("libMoltenVK.dylib", RTLD_LOCAL | RTLD_LAZY); +#else + if (!module) + module = dlopen("libvulkan.so.1", RTLD_LOCAL | RTLD_LAZY); + if (!module) + module = dlopen("libvulkan.so", RTLD_LOCAL | RTLD_LAZY); +#endif + if (!module) + return false; + } + + addr = reinterpret_cast(dlsym(module, "vkGetInstanceProcAddr")); + if (!addr) + return false; +#else + static HMODULE module; + if (!module) + { + module = LoadLibraryA("vulkan-1.dll"); + if (!module) + return false; + } + + // Ugly pointer warning workaround. + auto ptr = GetProcAddress(module, "vkGetInstanceProcAddr"); + static_assert(sizeof(ptr) == sizeof(addr), "Mismatch pointer type."); + memcpy(&addr, &ptr, sizeof(ptr)); + + if (!addr) + return false; +#endif + } + + instance_proc_addr = addr; + volkInitializeCustom(addr); + loader_init_once = true; + return true; +} + +bool Context::init_device_from_instance(VkInstance instance_, VkPhysicalDevice gpu_, VkSurfaceKHR surface, + const char **required_device_extensions, unsigned num_required_device_extensions, + const VkPhysicalDeviceFeatures *required_features, + ContextCreationFlags flags) +{ + destroy_device(); + destroy_instance(); + + instance = instance_; + owned_instance = false; + owned_device = true; + + if (!create_instance(nullptr, 0, flags)) + return false; + + if (!create_device(gpu_, surface, required_device_extensions, num_required_device_extensions, required_features, flags)) + { + destroy_device(); + LOGE("Failed to create Vulkan device.\n"); + return false; + } + + return true; +} + +void Context::destroy_device() +{ + if (device != VK_NULL_HANDLE) + device_table.vkDeviceWaitIdle(device); + +#if defined(ANDROID) && defined(HAVE_SWAPPY) + if (device != VK_NULL_HANDLE) + SwappyVk_destroyDevice(device); +#endif + +#ifdef HAVE_GRANITE_VULKAN_POST_MORTEM + PostMortem::deinit(); +#endif + + if (owned_device && device != VK_NULL_HANDLE) + { + device_table.vkDestroyDevice(device, nullptr); + device = VK_NULL_HANDLE; + owned_device = false; + } +} + +void Context::destroy_instance() +{ +#ifdef VULKAN_DEBUG + if (debug_messenger) + vkDestroyDebugUtilsMessengerEXT(instance, debug_messenger, nullptr); + debug_messenger = VK_NULL_HANDLE; +#endif + + if (owned_instance && instance != VK_NULL_HANDLE) + { + vkDestroyInstance(instance, nullptr); + instance = VK_NULL_HANDLE; + owned_instance = false; + } +} + +Context::Context() +{ +} + +Context::~Context() +{ + destroy_device(); + destroy_instance(); +} + +const VkApplicationInfo &Context::get_application_info() const +{ + return user_application_info.get_application_info(); +} + +void Context::notify_validation_error(const char *msg) +{ + if (message_callback) + message_callback(msg); +} + +void Context::set_notification_callback(std::function func) +{ + message_callback = std::move(func); +} + +#ifdef VULKAN_DEBUG +static VKAPI_ATTR VkBool32 VKAPI_CALL vulkan_messenger_cb( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void *pUserData) +{ + auto *context = static_cast(pUserData); + + switch (messageSeverity) + { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + if (messageType == VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) + { + LOGE("[Vulkan]: Validation Error: %s - %s\n", pCallbackData->pMessageIdName, pCallbackData->pMessage); + context->notify_validation_error(pCallbackData->pMessage); + } + else + LOGE("[Vulkan]: Other Error: %s\n", pCallbackData->pMessage); + break; + + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + if (messageType == VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) + LOGW("[Vulkan]: Validation Warning: %s - %s\n", pCallbackData->pMessageIdName, pCallbackData->pMessage); + else + LOGW("[Vulkan]: Other Warning: %s\n", pCallbackData->pMessage); + break; + +#if 0 + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + if (messageType == VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) + LOGI("[Vulkan]: Validation Info: %s\n", pCallbackData->pMessage); + else + LOGI("[Vulkan]: Other Info: %s\n", pCallbackData->pMessage); + break; +#endif + + default: + return VK_FALSE; + } + + bool log_object_names = false; + for (uint32_t i = 0; i < pCallbackData->objectCount; i++) + { + auto *name = pCallbackData->pObjects[i].pObjectName; + if (name) + { + log_object_names = true; + break; + } + } + + if (log_object_names) + { + for (uint32_t i = 0; i < pCallbackData->objectCount; i++) + { + auto *name = pCallbackData->pObjects[i].pObjectName; + LOGI(" Object #%u: %s\n", i, name ? name : "N/A"); + } + } + + return VK_FALSE; +} +#endif + +void Context::set_required_profile(const char *profile, bool strict) +{ + if (profile) + required_profile = profile; + else + required_profile.clear(); + required_profile_strict = strict; +} + +bool Context::init_profile() +{ +#ifdef GRANITE_VULKAN_PROFILES + if (required_profile.empty()) + { + if (Util::get_environment("GRANITE_VULKAN_PROFILE", required_profile)) + LOGI("Overriding profile: %s\n", required_profile.c_str()); + + required_profile_strict = Util::get_environment_bool("GRANITE_VULKAN_PROFILE_STRICT", false); + if (required_profile_strict) + LOGI("Using profile strictness.\n"); + } + + if (required_profile.empty()) + return true; + + ProfileHolder profile{required_profile}; + + if (!profile.profile) + { + LOGW("No profile matches %s.\n", required_profile.c_str()); + return false; + } + + VkBool32 supported = VK_FALSE; + if (vpGetInstanceProfileSupport(nullptr, profile.profile, &supported) != VK_SUCCESS || !supported) + { + LOGE("Profile %s is not supported.\n", required_profile.c_str()); + return false; + } +#endif + + return true; +} + +VkResult Context::create_instance_from_profile(const VkInstanceCreateInfo &info, VkInstance *pInstance) +{ +#ifdef GRANITE_VULKAN_PROFILES + ProfileHolder holder{required_profile}; + if (!holder.profile) + return VK_ERROR_INITIALIZATION_FAILED; + + if (instance_factory) + { + // Can override vkGetInstanceProcAddr (macro define) and override vkCreateInstance + // to a TLS magic trampoline if we really have to. + LOGE("Instance factory currently not supported with profiles.\n"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + VpInstanceCreateInfo vp_info = {}; + vp_info.pCreateInfo = &info; + vp_info.pProfile = holder.profile; + // Any extra extensions we add for instances are essential, like WSI stuff. + vp_info.flags = VP_INSTANCE_CREATE_MERGE_EXTENSIONS_BIT; + + VkResult result; + if ((result = vpCreateInstance(&vp_info, nullptr, pInstance)) != VK_SUCCESS) + LOGE("Failed to create instance from profile.\n"); + + return result; +#else + (void)info; + (void)pInstance; + return VK_ERROR_INITIALIZATION_FAILED; +#endif +} + +VkResult Context::create_device_from_profile(const VkDeviceCreateInfo &info, VkDevice *pDevice) +{ +#ifdef GRANITE_VULKAN_PROFILES + ProfileHolder holder{required_profile}; + if (!holder.profile) + return VK_ERROR_INITIALIZATION_FAILED; + + if (device_factory) + { + // Need TLS hackery like instance. + LOGE("Device factory currently not supported with profiles.\n"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + auto tmp_info = info; + + VpDeviceCreateInfo vp_info = {}; + vp_info.pProfile = holder.profile; + vp_info.pCreateInfo = &tmp_info; + vp_info.flags |= VP_DEVICE_CREATE_DISABLE_ROBUST_ACCESS; + + if (required_profile_strict) + { + tmp_info.enabledExtensionCount = 0; + tmp_info.ppEnabledExtensionNames = nullptr; + tmp_info.pNext = nullptr; + tmp_info.pEnabledFeatures = nullptr; + } + else + { + vp_info.flags = VP_DEVICE_CREATE_MERGE_EXTENSIONS_BIT | VP_DEVICE_CREATE_OVERRIDE_FEATURES_BIT; + } + + VkResult result; + if ((result = vpCreateDevice(gpu, &vp_info, nullptr, pDevice)) != VK_SUCCESS) + LOGE("Failed to create device from profile.\n"); + return result; +#else + (void)info; + (void)pDevice; + return VK_ERROR_INITIALIZATION_FAILED; +#endif +} + +VkApplicationInfo Context::get_promoted_application_info() const +{ + auto *inherit_info = instance_factory ? instance_factory->get_existing_create_info() : nullptr; + auto app_info = get_application_info(); + + VK_ASSERT(!inherit_info || inherit_info->pApplicationInfo); + uint32_t supported_instance_version = + inherit_info ? inherit_info->pApplicationInfo->apiVersion : volkGetInstanceVersion(); + + // Granite min-req is 1.1. + app_info.apiVersion = std::max(VK_API_VERSION_1_1, app_info.apiVersion); + + // Target Vulkan 1.4 if available, + // but the tooling ecosystem isn't quite ready for this yet, so stick to 1.3 for the time being. + app_info.apiVersion = std::max(app_info.apiVersion, std::min(VK_API_VERSION_1_4, supported_instance_version)); + + return app_info; +} + +bool Context::create_instance(const char * const *instance_ext, uint32_t instance_ext_count, ContextCreationFlags flags) +{ + VkInstanceCreateInfo info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; + auto app_info = get_promoted_application_info(); + auto *inherit_info = instance_factory ? instance_factory->get_existing_create_info() : nullptr; + uint32_t supported_instance_version = + inherit_info ? inherit_info->pApplicationInfo->apiVersion : volkGetInstanceVersion(); + + if (supported_instance_version < app_info.apiVersion) + { + LOGE("Vulkan loader does not support required Vulkan version.\n"); + return false; + } + + if (inherit_info) + { + instance_ext = inherit_info->ppEnabledExtensionNames; + instance_ext_count = inherit_info->enabledExtensionCount; + } + + info.pApplicationInfo = &app_info; + + std::vector instance_exts; + std::vector instance_layers; + for (uint32_t i = 0; i < instance_ext_count; i++) + instance_exts.push_back(instance_ext[i]); + + uint32_t ext_count = 0; + if (!inherit_info) + vkEnumerateInstanceExtensionProperties(nullptr, &ext_count, nullptr); + std::vector queried_extensions(ext_count); + if (ext_count && !inherit_info) + vkEnumerateInstanceExtensionProperties(nullptr, &ext_count, queried_extensions.data()); + + uint32_t layer_count = 0; + if (!inherit_info) + vkEnumerateInstanceLayerProperties(&layer_count, nullptr); + std::vector queried_layers(layer_count); + if (layer_count && !inherit_info) + vkEnumerateInstanceLayerProperties(&layer_count, queried_layers.data()); + + if (!inherit_info) + { + LOGI("Layer count: %u\n", layer_count); + for (auto &layer: queried_layers) + LOGI("Found layer: %s.\n", layer.layerName); + } + + const auto has_extension = [&](const char *name) -> bool { + if (inherit_info) + { + for (uint32_t i = 0; i < inherit_info->enabledExtensionCount; i++) + if (strcmp(inherit_info->ppEnabledExtensionNames[i], name) == 0) + return true; + return false; + } + + auto itr = find_if(begin(queried_extensions), end(queried_extensions), [name](const VkExtensionProperties &e) -> bool { + return strcmp(e.extensionName, name) == 0; + }); + return itr != end(queried_extensions); + }; + + if (!inherit_info) + for (uint32_t i = 0; i < instance_ext_count; i++) + if (!has_extension(instance_ext[i])) + return false; + + if (has_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) + { + instance_exts.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + ext.supports_debug_utils = true; + } + + auto itr = std::find_if(instance_ext, instance_ext + instance_ext_count, [](const char *name) { + return strcmp(name, VK_KHR_SURFACE_EXTENSION_NAME) == 0; + }); + bool has_surface_extension = itr != (instance_ext + instance_ext_count); + + if (has_surface_extension && has_extension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME)) + { + instance_exts.push_back(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME); + ext.supports_surface_capabilities2 = true; + } + + if ((flags & CONTEXT_CREATION_ENABLE_ADVANCED_WSI_BIT) != 0 && + has_surface_extension && + has_extension(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME)) + { + instance_exts.push_back(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME); + ext.supports_swapchain_colorspace = true; + } + +#ifdef VULKAN_DEBUG + const auto has_layer = [&](const char *name) -> bool { + if (inherit_info) + { + for (uint32_t i = 0; i < inherit_info->enabledLayerCount; i++) + if (strcmp(inherit_info->ppEnabledLayerNames[i], name) == 0) + return true; + return false; + } + + auto layer_itr = find_if(begin(queried_layers), end(queried_layers), [name](const VkLayerProperties &e) -> bool { + return strcmp(e.layerName, name) == 0; + }); + return layer_itr != end(queried_layers); + }; + + force_no_validation = Util::get_environment_bool("GRANITE_VULKAN_NO_VALIDATION", false); + VkValidationFeaturesEXT validation_features = { VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT }; + + if (!force_no_validation && has_layer("VK_LAYER_KHRONOS_validation")) + { + instance_layers.push_back("VK_LAYER_KHRONOS_validation"); + LOGI("Enabling VK_LAYER_KHRONOS_validation.\n"); + + uint32_t layer_ext_count = 0; + vkEnumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation", &layer_ext_count, nullptr); + std::vector layer_exts(layer_ext_count); + vkEnumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation", &layer_ext_count, layer_exts.data()); + + if (Util::get_environment_bool("GRANITE_VULKAN_SYNC_VALIDATION", false)) + { + // Tons of false positives around timeline semaphores atm, so don't bother. + if (find_if(begin(layer_exts), end(layer_exts), [](const VkExtensionProperties &e) + { + return strcmp(e.extensionName, VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME) == 0; + }) != end(layer_exts)) + { + instance_exts.push_back(VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME); + static const VkValidationFeatureEnableEXT validation_sync_features[1] = { + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT, + }; + LOGI("Enabling VK_EXT_validation_features for synchronization validation.\n"); + validation_features.enabledValidationFeatureCount = 1; + validation_features.pEnabledValidationFeatures = validation_sync_features; + info.pNext = &validation_features; + } + } + + if (!ext.supports_debug_utils && + find_if(begin(layer_exts), end(layer_exts), [](const VkExtensionProperties &e) { + return strcmp(e.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0; + }) != end(layer_exts)) + { + instance_exts.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + ext.supports_debug_utils = true; + } + } +#endif + + if (ext.supports_surface_capabilities2) + { + bool supports_khr = has_extension(VK_KHR_SURFACE_MAINTENANCE_1_EXTENSION_NAME); + bool supports_ext = has_extension(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME); + + if (supports_khr || supports_ext) + { + instance_exts.push_back( + supports_khr ? VK_KHR_SURFACE_MAINTENANCE_1_EXTENSION_NAME + : VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME); + ext.supports_surface_maintenance1 = true; + } + } + + if (has_extension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) + { + // Permit MoltenVK (and other portability drivers) when enumerating drivers via the Vulkan loader. + info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + instance_exts.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + + // To use drivers which support VK_KHR_portability_subset, we have to enable the portability_subset + // extension as well, but since that's a provisional extension, it's not safe to ship that. + // Just ignore this requirement, since only VVL is likely to complain here. + } + + if (inherit_info) + { + info.enabledExtensionCount = inherit_info->enabledExtensionCount; + info.ppEnabledExtensionNames = inherit_info->ppEnabledExtensionNames; + info.enabledLayerCount = inherit_info->enabledLayerCount; + info.ppEnabledLayerNames = inherit_info->ppEnabledLayerNames; + } + else + { + info.enabledExtensionCount = instance_exts.size(); + info.ppEnabledExtensionNames = instance_exts.empty() ? nullptr : instance_exts.data(); + info.enabledLayerCount = instance_layers.size(); + info.ppEnabledLayerNames = instance_layers.empty() ? nullptr : instance_layers.data(); + } + + for (uint32_t i = 0; i < info.enabledExtensionCount; i++) + LOGI("Enabling instance extension: %s.\n", info.ppEnabledExtensionNames[i]); + +#ifdef GRANITE_VULKAN_PROFILES + if (!init_profile()) + { + LOGE("Profile is not supported.\n"); + return false; + } + + if (instance == VK_NULL_HANDLE && !required_profile.empty()) + if (create_instance_from_profile(info, &instance) != VK_SUCCESS) + return false; +#endif + + // instance != VK_NULL_HANDLE here is deprecated and somewhat broken. + // For libretro Vulkan context negotiation v1. + if (instance == VK_NULL_HANDLE) + { + if (instance_factory) + { + instance = instance_factory->create_instance(&info); + if (instance == VK_NULL_HANDLE) + return false; + } + else if (vkCreateInstance(&info, nullptr, &instance) != VK_SUCCESS) + return false; + + // If we have a pre-existing instance, we can only assume Vulkan 1.1 in legacy interface. + ext.instance_api_core_version = app_info.apiVersion; + } + + if (inherit_info) + { + ext.instance_extensions = inherit_info->ppEnabledExtensionNames; + ext.num_instance_extensions = inherit_info->enabledExtensionCount; + } + else + { + enabled_instance_extensions = std::move(instance_exts); + ext.instance_extensions = enabled_instance_extensions.data(); + ext.num_instance_extensions = uint32_t(enabled_instance_extensions.size()); + } + + volkLoadInstance(instance); + +#if defined(VULKAN_DEBUG) + if (ext.supports_debug_utils) + { + VkDebugUtilsMessengerCreateInfoEXT debug_info = { VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT }; + debug_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + debug_info.pfnUserCallback = vulkan_messenger_cb; + debug_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT; + debug_info.pUserData = this; + + // For some reason, this segfaults Android, sigh ... We get relevant output in logcat anyways. + if (vkCreateDebugUtilsMessengerEXT) + vkCreateDebugUtilsMessengerEXT(instance, &debug_info, nullptr, &debug_messenger); + } +#endif + + return true; +} + +static unsigned device_score(VkPhysicalDevice &gpu) +{ + VkPhysicalDeviceProperties props = {}; + vkGetPhysicalDeviceProperties(gpu, &props); + + if (props.apiVersion < VK_API_VERSION_1_1) + return 0; + + switch (props.deviceType) + { + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: + return 3; + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: + return 2; + case VK_PHYSICAL_DEVICE_TYPE_CPU: + return 1; + default: + return 0; + } +} + +QueueInfo::QueueInfo() +{ + for (auto &index : family_indices) + index = VK_QUEUE_FAMILY_IGNORED; +} + +bool Context::physical_device_supports_surface_and_profile(VkPhysicalDevice candidate_gpu, VkSurfaceKHR surface) const +{ +#ifdef GRANITE_VULKAN_PROFILES + if (!required_profile.empty()) + { + ProfileHolder holder{required_profile}; + if (!holder.profile) + return false; + + VkBool32 supported = VK_FALSE; + if (vpGetPhysicalDeviceProfileSupport(instance, candidate_gpu, holder.profile, &supported) != VK_SUCCESS || + !supported) + { + return false; + } + } +#endif + + if (surface == VK_NULL_HANDLE) + return true; + + VkPhysicalDeviceProperties dev_props; + vkGetPhysicalDeviceProperties(candidate_gpu, &dev_props); + if (dev_props.limits.maxUniformBufferRange < VULKAN_MAX_UBO_SIZE) + { + LOGW("Device does not support 64 KiB UBOs. Must be *ancient* mobile driver.\n"); + return false; + } + + if (dev_props.apiVersion < VK_API_VERSION_1_1) + { + LOGW("Device does not support Vulkan 1.1. Skipping.\n"); + return false; + } + + uint32_t family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(candidate_gpu, &family_count, nullptr); + Util::SmallVector props(family_count); + vkGetPhysicalDeviceQueueFamilyProperties(candidate_gpu, &family_count, props.data()); + + for (uint32_t i = 0; i < family_count; i++) + { + // A graphics queue candidate must support present for us to select it. + if ((props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) + { + VkBool32 supported = VK_FALSE; + if (vkGetPhysicalDeviceSurfaceSupportKHR(candidate_gpu, i, surface, &supported) == VK_SUCCESS && supported) + return true; + } + } + + return false; +} + +bool Context::create_device(VkPhysicalDevice gpu_, VkSurfaceKHR surface, + const char * const *required_device_extensions, uint32_t num_required_device_extensions, + const VkPhysicalDeviceFeatures *required_features, + ContextCreationFlags flags) +{ + gpu = gpu_; + if (gpu == VK_NULL_HANDLE) + { + uint32_t gpu_count = 0; + if (vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr) != VK_SUCCESS) + return false; + + if (gpu_count == 0) + return false; + + std::vector gpus(gpu_count); + if (vkEnumeratePhysicalDevices(instance, &gpu_count, gpus.data()) != VK_SUCCESS) + return false; + + for (auto &g : gpus) + { + VkPhysicalDeviceProperties props; + vkGetPhysicalDeviceProperties(g, &props); + LOGI("Found Vulkan GPU: %s\n", props.deviceName); + LOGI(" API: %u.%u.%u\n", + VK_VERSION_MAJOR(props.apiVersion), + VK_VERSION_MINOR(props.apiVersion), + VK_VERSION_PATCH(props.apiVersion)); + LOGI(" Driver: %u.%u.%u\n", + VK_VERSION_MAJOR(props.driverVersion), + VK_VERSION_MINOR(props.driverVersion), + VK_VERSION_PATCH(props.driverVersion)); + } + + int gpu_index = Util::get_environment_int("GRANITE_VULKAN_DEVICE_INDEX", -1); + if (gpu_index >= 0 && gpu_index < int(gpu_count)) + gpu = gpus[gpu_index]; + + if (gpu != VK_NULL_HANDLE) + { + if (!physical_device_supports_surface_and_profile(gpu, surface)) + { + LOGE("Selected physical device which does not support surface.\n"); + gpu = VK_NULL_HANDLE; + } + } + + if (gpu == VK_NULL_HANDLE) + { + unsigned max_score = 0; + // Prefer earlier entries in list. + for (size_t i = gpus.size(); i; i--) + { + unsigned score = device_score(gpus[i - 1]); + if (score >= max_score && physical_device_supports_surface_and_profile(gpus[i - 1], surface)) + { + max_score = score; + gpu = gpus[i - 1]; + } + } + } + + if (gpu == VK_NULL_HANDLE) + { + LOGE("Found not GPU which supports surface.\n"); + return false; + } + } + else if (!physical_device_supports_surface_and_profile(gpu, surface)) + { + LOGE("Selected physical device does not support surface.\n"); + return false; + } + + auto *inherit_info = device_factory ? device_factory->get_existing_create_info() : nullptr; + std::vector queried_extensions; + + if (inherit_info) + { + required_device_extensions = inherit_info->ppEnabledExtensionNames; + num_required_device_extensions = inherit_info->enabledExtensionCount; + } + +#ifdef GRANITE_VULKAN_PROFILES + // Only allow extensions that profile declares. + ProfileHolder profile{required_profile}; + if (profile.profile && required_profile_strict) + { + uint32_t ext_count = 0; + vpGetProfileDeviceExtensionProperties(profile.profile, &ext_count, nullptr); + queried_extensions.resize(ext_count); + if (ext_count) + vpGetProfileDeviceExtensionProperties(profile.profile, &ext_count, queried_extensions.data()); + } + else +#endif + { + uint32_t ext_count = 0; + if (!inherit_info) + vkEnumerateDeviceExtensionProperties(gpu, nullptr, &ext_count, nullptr); + queried_extensions.resize(ext_count); + if (ext_count && !inherit_info) + vkEnumerateDeviceExtensionProperties(gpu, nullptr, &ext_count, queried_extensions.data()); + } + + const auto has_extension = [&](const char *name) -> bool { + if (inherit_info) + { + for (uint32_t i = 0; i < inherit_info->enabledExtensionCount; i++) + if (strcmp(inherit_info->ppEnabledExtensionNames[i], name) == 0) + return true; + return false; + } + + auto itr = find_if(begin(queried_extensions), end(queried_extensions), [name](const VkExtensionProperties &e) -> bool { + return strcmp(e.extensionName, name) == 0; + }); + return itr != end(queried_extensions); + }; + + if (!inherit_info) + for (uint32_t i = 0; i < num_required_device_extensions; i++) + if (!has_extension(required_device_extensions[i])) + return false; + + vkGetPhysicalDeviceProperties(gpu, &gpu_props); + // We can use core device functionality if enabled VkInstance apiVersion and physical device supports it. + ext.device_api_core_version = std::min(ext.instance_api_core_version, gpu_props.apiVersion); + + LOGI("Using Vulkan GPU: %s\n", gpu_props.deviceName); + + // FFmpeg integration requires Vulkan 1.3 core for physical device. + uint32_t minimum_api_version = (flags & video_context_flags) ? VK_API_VERSION_1_3 : VK_API_VERSION_1_1; + if (ext.device_api_core_version < minimum_api_version && (flags & video_context_flags) != 0) + { + LOGW("Requested FFmpeg-enabled context, but Vulkan 1.3 was not supported. Falling back to 1.1 without support.\n"); + minimum_api_version = VK_API_VERSION_1_1; + flags &= ~video_context_flags; + } + + if (ext.device_api_core_version < minimum_api_version) + { + LOGE("Found no Vulkan GPU which supports Vulkan 1.%u.\n", + VK_API_VERSION_MINOR(minimum_api_version)); + return false; + } + + vkGetPhysicalDeviceMemoryProperties(gpu, &mem_props); + + uint32_t queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties2(gpu, &queue_family_count, nullptr); + Util::SmallVector queue_props(queue_family_count); + Util::SmallVector video_queue_props2(queue_family_count); + + if ((flags & video_context_flags) != 0 && has_extension(VK_KHR_VIDEO_QUEUE_EXTENSION_NAME)) + ext.supports_video_queue = true; + + for (uint32_t i = 0; i < queue_family_count; i++) + { + queue_props[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; + if (ext.supports_video_queue) + { + queue_props[i].pNext = &video_queue_props2[i]; + video_queue_props2[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR; + } + } + + Util::SmallVector queue_offsets(queue_family_count); + Util::SmallVector> queue_priorities(queue_family_count); + vkGetPhysicalDeviceQueueFamilyProperties2(gpu, &queue_family_count, queue_props.data()); + + if (inherit_info) + { + for (uint32_t i = 0; i < queue_family_count; i++) + { + auto itr = std::find_if(inherit_info->pQueueCreateInfos, + inherit_info->pQueueCreateInfos + inherit_info->queueCreateInfoCount, + [&](const VkDeviceQueueCreateInfo &queue) { return queue.queueFamilyIndex == i; }); + + if (itr != inherit_info->pQueueCreateInfos + inherit_info->queueCreateInfoCount) + queue_props[i].queueFamilyProperties.queueCount = itr->queueCount; + else + queue_props[i].queueFamilyProperties.queueCount = 0; + } + } + + queue_info = {}; + uint32_t queue_indices[QUEUE_INDEX_COUNT] = {}; + + const auto find_vacant_queue = [&](uint32_t &family, uint32_t &index, + VkQueueFlags required, VkQueueFlags ignore_flags, + float priority) -> bool { + for (unsigned family_index = 0; family_index < queue_family_count; family_index++) + { + if ((queue_props[family_index].queueFamilyProperties.queueFlags & ignore_flags) != 0) + continue; + + // A graphics queue candidate must support present for us to select it. + if ((required & VK_QUEUE_GRAPHICS_BIT) != 0 && surface != VK_NULL_HANDLE) + { + VkBool32 supported = VK_FALSE; + if (vkGetPhysicalDeviceSurfaceSupportKHR(gpu, family_index, surface, &supported) != VK_SUCCESS || !supported) + continue; + } + + if (queue_props[family_index].queueFamilyProperties.queueCount && + (queue_props[family_index].queueFamilyProperties.queueFlags & required) == required) + { + family = family_index; + queue_props[family_index].queueFamilyProperties.queueCount--; + index = queue_offsets[family_index]++; + queue_priorities[family_index].push_back(priority); + return true; + } + } + + return false; + }; + + if (!find_vacant_queue(queue_info.family_indices[QUEUE_INDEX_GRAPHICS], + queue_indices[QUEUE_INDEX_GRAPHICS], + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 0, 0.5f)) + { + LOGE("Could not find suitable graphics queue.\n"); + return false; + } + + // XXX: This assumes timestamp valid bits is the same for all queue types. + queue_info.timestamp_valid_bits = + queue_props[queue_info.family_indices[QUEUE_INDEX_GRAPHICS]].queueFamilyProperties.timestampValidBits; + + // Prefer standalone compute queue. If not, fall back to another graphics queue. + if (!find_vacant_queue(queue_info.family_indices[QUEUE_INDEX_COMPUTE], queue_indices[QUEUE_INDEX_COMPUTE], + VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT, 0.5f) && + !find_vacant_queue(queue_info.family_indices[QUEUE_INDEX_COMPUTE], queue_indices[QUEUE_INDEX_COMPUTE], + VK_QUEUE_COMPUTE_BIT, 0, 0.5f)) + { + // Fallback to the graphics queue if we must. + queue_info.family_indices[QUEUE_INDEX_COMPUTE] = queue_info.family_indices[QUEUE_INDEX_GRAPHICS]; + queue_indices[QUEUE_INDEX_COMPUTE] = queue_indices[QUEUE_INDEX_GRAPHICS]; + } + + // For transfer, try to find a queue which only supports transfer, e.g. DMA queue. + // If not, fallback to a dedicated compute queue. + // Finally, fallback to same queue as compute. + if (!find_vacant_queue(queue_info.family_indices[QUEUE_INDEX_TRANSFER], queue_indices[QUEUE_INDEX_TRANSFER], + VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 0.5f) && + !find_vacant_queue(queue_info.family_indices[QUEUE_INDEX_TRANSFER], queue_indices[QUEUE_INDEX_TRANSFER], + VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT, 0.5f)) + { + queue_info.family_indices[QUEUE_INDEX_TRANSFER] = queue_info.family_indices[QUEUE_INDEX_COMPUTE]; + queue_indices[QUEUE_INDEX_TRANSFER] = queue_indices[QUEUE_INDEX_COMPUTE]; + } + + if (ext.supports_video_queue) + { + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_DECODE_BIT) != 0) + { + if (!find_vacant_queue(queue_info.family_indices[QUEUE_INDEX_VIDEO_DECODE], + queue_indices[QUEUE_INDEX_VIDEO_DECODE], + VK_QUEUE_VIDEO_DECODE_BIT_KHR, 0, 0.5f)) + { + queue_info.family_indices[QUEUE_INDEX_VIDEO_DECODE] = VK_QUEUE_FAMILY_IGNORED; + queue_indices[QUEUE_INDEX_VIDEO_DECODE] = UINT32_MAX; + } + } + + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_ENCODE_BIT) != 0) + { + if (!find_vacant_queue(queue_info.family_indices[QUEUE_INDEX_VIDEO_ENCODE], + queue_indices[QUEUE_INDEX_VIDEO_ENCODE], + VK_QUEUE_VIDEO_ENCODE_BIT_KHR, 0, 0.5f)) + { + queue_info.family_indices[QUEUE_INDEX_VIDEO_ENCODE] = VK_QUEUE_FAMILY_IGNORED; + queue_indices[QUEUE_INDEX_VIDEO_ENCODE] = UINT32_MAX; + } + } + } + + VkDeviceCreateInfo device_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + + Util::SmallVector queue_infos; + for (uint32_t family_index = 0; family_index < queue_family_count; family_index++) + { + if (queue_offsets[family_index] == 0) + continue; + + VkDeviceQueueCreateInfo info = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; + info.queueFamilyIndex = family_index; + info.queueCount = queue_offsets[family_index]; + info.pQueuePriorities = queue_priorities[family_index].data(); + queue_infos.push_back(info); + } + + if (inherit_info) + { + device_info.pQueueCreateInfos = inherit_info->pQueueCreateInfos; + device_info.queueCreateInfoCount = inherit_info->queueCreateInfoCount; + } + else + { + device_info.pQueueCreateInfos = queue_infos.data(); + device_info.queueCreateInfoCount = uint32_t(queue_infos.size()); + } + + std::vector enabled_extensions; + + bool requires_swapchain = false; + for (uint32_t i = 0; i < num_required_device_extensions; i++) + { + enabled_extensions.push_back(required_device_extensions[i]); + if (strcmp(required_device_extensions[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) + requires_swapchain = true; + else if (strcmp(required_device_extensions[i], VK_KHR_PRESENT_ID_EXTENSION_NAME) == 0 || + strcmp(required_device_extensions[i], VK_KHR_PRESENT_ID_2_EXTENSION_NAME) == 0 || + strcmp(required_device_extensions[i], VK_KHR_PRESENT_WAIT_EXTENSION_NAME) == 0 || + strcmp(required_device_extensions[i], VK_KHR_PRESENT_WAIT_2_EXTENSION_NAME) == 0 || + strcmp(required_device_extensions[i], VK_EXT_HDR_METADATA_EXTENSION_NAME) == 0 || + strcmp(required_device_extensions[i], VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME) == 0 || + strcmp(required_device_extensions[i], VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME) == 0) + { + flags |= CONTEXT_CREATION_ENABLE_ADVANCED_WSI_BIT; + } + } + +#if defined(ANDROID) && defined(HAVE_SWAPPY) + // Enable additional extensions required by SwappyVk. + std::unique_ptr swappy_str_buffer; + if (requires_swapchain) + { + uint32_t required_swappy_extension_count = 0; + + // I'm really not sure why the API just didn't return static const char * strings here, + // but oh well. + SwappyVk_determineDeviceExtensions(gpu, uint32_t(queried_extensions.size()), + queried_extensions.data(), + &required_swappy_extension_count, + nullptr); + swappy_str_buffer.reset(new char[required_swappy_extension_count * (VK_MAX_EXTENSION_NAME_SIZE + 1)]); + + std::vector extension_buffer; + extension_buffer.reserve(required_swappy_extension_count); + for (uint32_t i = 0; i < required_swappy_extension_count; i++) + extension_buffer.push_back(swappy_str_buffer.get() + i * (VK_MAX_EXTENSION_NAME_SIZE + 1)); + SwappyVk_determineDeviceExtensions(gpu, uint32_t(queried_extensions.size()), + queried_extensions.data(), + &required_swappy_extension_count, + extension_buffer.data()); + + for (auto *required_ext : extension_buffer) + enabled_extensions.push_back(required_ext); + } +#endif + +#ifdef _WIN32 + if (ext.supports_surface_capabilities2 && has_extension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME)) + { + ext.supports_full_screen_exclusive = true; + enabled_extensions.push_back(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME); + } +#endif + + if ( +#ifdef _WIN32 + has_extension(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME) && + has_extension(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME) +#else + has_extension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME) && + has_extension(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME) +#endif + ) + { + ext.supports_external = true; +#ifdef _WIN32 + enabled_extensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME); + enabled_extensions.push_back(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME); +#else + enabled_extensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME); + enabled_extensions.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); +#endif + } + else + ext.supports_external = false; + + if (ext.supports_external) + { + if (has_extension(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) + enabled_extensions.push_back(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME); + + if (has_extension(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME); + ext.supports_drm_modifiers = true; + } + } + + if (has_extension(VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME)) + { + ext.supports_calibrated_timestamps = true; + enabled_extensions.push_back(VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME); + } + + if (has_extension(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME); + ext.supports_conservative_rasterization = true; + } + + if (ext.device_api_core_version < VK_API_VERSION_1_2) + { + if (!has_extension(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) + { + LOGE("VK_KHR_create_renderpass2 is not supported.\n"); + return false; + } + + enabled_extensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); + + if (has_extension(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME)) + { + ext.supports_image_format_list = true; + enabled_extensions.push_back(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME); + } + } + else + ext.supports_image_format_list = true; + + // Physical device functionality. + ext.supports_format_feature_flags2 = ext.device_api_core_version >= VK_API_VERSION_1_3 || + has_extension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME); + + if (has_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME)) + ext.supports_tooling_info = true; + + if (ext.supports_video_queue) + { + enabled_extensions.push_back(VK_KHR_VIDEO_QUEUE_EXTENSION_NAME); + + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_DECODE_BIT) != 0 && + has_extension(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME); + ext.supports_video_decode_queue = true; + + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_H264_BIT) != 0 && + has_extension(VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME); + + if (queue_info.family_indices[QUEUE_INDEX_VIDEO_DECODE] != VK_QUEUE_FAMILY_IGNORED) + { + ext.supports_video_decode_h264 = + (video_queue_props2[queue_info.family_indices[QUEUE_INDEX_VIDEO_DECODE]].videoCodecOperations & + VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) != 0; + } + } + + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_H265_BIT) != 0 && + has_extension(VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME); + + if (queue_info.family_indices[QUEUE_INDEX_VIDEO_DECODE] != VK_QUEUE_FAMILY_IGNORED) + { + ext.supports_video_decode_h265 = + (video_queue_props2[queue_info.family_indices[QUEUE_INDEX_VIDEO_DECODE]].videoCodecOperations & + VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) != 0; + } + } + + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_AV1_BIT) != 0 && + has_extension(VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME); + + if (queue_info.family_indices[QUEUE_INDEX_VIDEO_DECODE] != VK_QUEUE_FAMILY_IGNORED) + { + ext.supports_video_decode_av1 = + (video_queue_props2[queue_info.family_indices[QUEUE_INDEX_VIDEO_DECODE]].videoCodecOperations & + VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) != 0; + } + } + } + else if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_FEATURE_ONLY_BIT) != 0 && + has_extension(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME); + } + + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_ENCODE_BIT) != 0 && + has_extension(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME); + ext.supports_video_encode_queue = true; + + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_H264_BIT) != 0 && + has_extension(VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME); + + if (queue_info.family_indices[QUEUE_INDEX_VIDEO_ENCODE] != VK_QUEUE_FAMILY_IGNORED) + { + ext.supports_video_encode_h264 = + (video_queue_props2[queue_info.family_indices[QUEUE_INDEX_VIDEO_ENCODE]].videoCodecOperations & + VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR) != 0; + } + } + + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_H265_BIT) != 0 && + has_extension(VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME); + + if (queue_info.family_indices[QUEUE_INDEX_VIDEO_ENCODE] != VK_QUEUE_FAMILY_IGNORED) + { + ext.supports_video_encode_h265 = + (video_queue_props2[queue_info.family_indices[QUEUE_INDEX_VIDEO_ENCODE]].videoCodecOperations & + VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR) != 0; + } + } + + if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_AV1_BIT) != 0 && + has_extension(VK_KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME); + + if (queue_info.family_indices[QUEUE_INDEX_VIDEO_ENCODE] != VK_QUEUE_FAMILY_IGNORED) + { + ext.supports_video_encode_av1 = + (video_queue_props2[queue_info.family_indices[QUEUE_INDEX_VIDEO_ENCODE]].videoCodecOperations & + VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR) != 0; + } + } + } + else if ((flags & CONTEXT_CREATION_ENABLE_VIDEO_FEATURE_ONLY_BIT) != 0 && + has_extension(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME); + } + } + + pdf2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; + auto **ppNext = reinterpret_cast(&pdf2.pNext); + + const auto add_chain = [&](void *pnext, size_t size, + VkStructureType type, const VkDeviceCreateInfo *device_create_info) { + auto *sout = static_cast(pnext); + memset(sout, 0, size); + sout->sType = type; + + if (device_create_info) + { + auto *existing = find_pnext(device_create_info->pNext, type); + if (existing) + memcpy(sout + 1, existing + 1, size - sizeof(*sout)); + } + + *ppNext = sout; + ppNext = &sout->pNext; + }; + +#define ADD_CHAIN(s, type) add_chain(&(s), sizeof(s), VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ ## type, inherit_info) + + if (ext.supports_video_encode_av1) + ADD_CHAIN(ext.av1_features, VIDEO_ENCODE_AV1_FEATURES_KHR); + + if (ext.device_api_core_version >= VK_API_VERSION_1_2) + { + ADD_CHAIN(ext.vk11_features, VULKAN_1_1_FEATURES); + ADD_CHAIN(ext.vk12_features, VULKAN_1_2_FEATURES); + } + else + { + if (has_extension(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME)) + { + ADD_CHAIN(ext.host_query_reset_features, HOST_QUERY_RESET_FEATURES); + enabled_extensions.push_back(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME); + } + + if (has_extension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) + { + ADD_CHAIN(ext.float16_int8_features, FLOAT16_INT8_FEATURES_KHR); + enabled_extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); + } + + if (has_extension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME)) + { + ADD_CHAIN(ext.storage_16bit_features, 16BIT_STORAGE_FEATURES_KHR); + enabled_extensions.push_back(VK_KHR_16BIT_STORAGE_EXTENSION_NAME); + } + + if (has_extension(VK_KHR_8BIT_STORAGE_EXTENSION_NAME)) + { + ADD_CHAIN(ext.storage_8bit_features, 8BIT_STORAGE_FEATURES_KHR); + enabled_extensions.push_back(VK_KHR_8BIT_STORAGE_EXTENSION_NAME); + } + } + + if (ext.device_api_core_version >= VK_API_VERSION_1_3) + { + ADD_CHAIN(ext.vk13_features, VULKAN_1_3_FEATURES); + } + else + { + if (has_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME)) + { + ADD_CHAIN(ext.subgroup_size_control_features, SUBGROUP_SIZE_CONTROL_FEATURES_EXT); + enabled_extensions.push_back(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME); + } + + if (has_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME)) + { + ADD_CHAIN(ext.sync2_features, SYNCHRONIZATION_2_FEATURES_KHR); + enabled_extensions.push_back(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); + } + else + { + LOGE("KHR_synchronization2 is not supported. This is a hard requirement for Granite.\n"); + return false; + } + } + + bool supports_khr_push_descriptor = false; + + if (ext.device_api_core_version >= VK_API_VERSION_1_4) + { + ADD_CHAIN(ext.vk14_features, VULKAN_1_4_FEATURES); + } + else + { + if ((flags & CONTEXT_CREATION_ENABLE_PUSH_DESCRIPTOR_BIT) != 0 && has_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); + supports_khr_push_descriptor = true; + } + + if (has_extension(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME); + ADD_CHAIN(ext.index_type_uint8_features, INDEX_TYPE_UINT8_FEATURES_EXT); + } + + if (has_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); + ADD_CHAIN(ext.maintenance5_features, MAINTENANCE_5_FEATURES_KHR); + } + } + + if (has_extension(VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME); + ADD_CHAIN(ext.compute_shader_derivative_features, COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR); + } + + if (has_extension(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME); + ADD_CHAIN(ext.performance_query_features, PERFORMANCE_QUERY_FEATURES_KHR); + } + + if (has_extension(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME); + ADD_CHAIN(ext.memory_priority_features, MEMORY_PRIORITY_FEATURES_EXT); + } + + if (has_extension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); + ext.supports_memory_budget = true; + } + + if (has_extension(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME)) + { + ext.supports_astc_decode_mode = true; + enabled_extensions.push_back(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME); + ADD_CHAIN(ext.astc_decode_features, ASTC_DECODE_FEATURES_EXT); + } + + if (has_extension(VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME); + ADD_CHAIN(ext.pageable_device_local_memory_features, PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT); + } + + if (has_extension(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME); + ADD_CHAIN(ext.device_generated_commands_features, DEVICE_GENERATED_COMMANDS_FEATURES_EXT); + } + + if (has_extension(VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME); + ADD_CHAIN(ext.descriptor_pool_overallocation_features, DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV); + } + + if (has_extension(VK_EXT_MESH_SHADER_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_MESH_SHADER_EXTENSION_NAME); + ADD_CHAIN(ext.mesh_shader_features, MESH_SHADER_FEATURES_EXT); + } + + if (has_extension(VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME); + ADD_CHAIN(ext.rgba10x6_formats_features, RGBA10X6_FORMATS_FEATURES_EXT); + } + + if (has_extension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME)) + { + ext.supports_external_memory_host = true; + enabled_extensions.push_back(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); + } + + if (has_extension(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME); + ADD_CHAIN(ext.barycentric_features, FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR); + } + + if (ext.supports_video_queue && has_extension(VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME); + ADD_CHAIN(ext.video_maintenance1_features, VIDEO_MAINTENANCE_1_FEATURES_KHR); + } + + if (has_extension(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME); + ADD_CHAIN(ext.image_compression_control_features, IMAGE_COMPRESSION_CONTROL_FEATURES_EXT); + } + + if (has_extension(VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME); + ADD_CHAIN(ext.image_compression_control_swapchain_features, IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT); + } + + if (has_extension(VK_NV_LOW_LATENCY_2_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_NV_LOW_LATENCY_2_EXTENSION_NAME); + ext.supports_low_latency2_nv = true; + } + + if (has_extension(VK_AMD_ANTI_LAG_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_AMD_ANTI_LAG_EXTENSION_NAME); + ADD_CHAIN(ext.anti_lag_features, ANTI_LAG_FEATURES_AMD); + } + + if (has_extension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_RAY_QUERY_EXTENSION_NAME); + enabled_extensions.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); + enabled_extensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); + ADD_CHAIN(ext.ray_query_features, RAY_QUERY_FEATURES_KHR); + ADD_CHAIN(ext.rtas_features, ACCELERATION_STRUCTURE_FEATURES_KHR); + } + + if (ext.device_api_core_version >= VK_API_VERSION_1_3) + { + ext.supports_store_op_none = true; + } + else if (has_extension(VK_KHR_LOAD_STORE_OP_NONE_EXTENSION_NAME)) + { + ext.supports_store_op_none = true; + enabled_extensions.push_back(VK_KHR_LOAD_STORE_OP_NONE_EXTENSION_NAME); + } + else if (has_extension(VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME)) + { + ext.supports_store_op_none = true; + enabled_extensions.push_back(VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME); + } + + // Pipeline binaries are currently borked in VVL. + if ((flags & CONTEXT_CREATION_ENABLE_PIPELINE_BINARY_BIT) != 0 && + has_extension(VK_KHR_PIPELINE_BINARY_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_PIPELINE_BINARY_EXTENSION_NAME); + ADD_CHAIN(ext.pipeline_binary_features, PIPELINE_BINARY_FEATURES_KHR); + } + + if ((flags & CONTEXT_CREATION_ENABLE_ROBUSTNESS_2_BIT) != 0 && has_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); + ADD_CHAIN(ext.robustness2_features, ROBUSTNESS_2_FEATURES_EXT); + } + +#if !defined(VULKAN_DEBUG) + if ((flags & CONTEXT_CREATION_ENABLE_DESCRIPTOR_HEAP_BIT) != 0 && + has_extension(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME)) + { + ADD_CHAIN(ext.descriptor_heap_features, DESCRIPTOR_HEAP_FEATURES_EXT); + enabled_extensions.push_back(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME); + ADD_CHAIN(ext.untyped_pointers_features, SHADER_UNTYPED_POINTERS_FEATURES_KHR); + enabled_extensions.push_back(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME); + } + else if ((flags & CONTEXT_CREATION_ENABLE_DESCRIPTOR_BUFFER_BIT) != 0 && + has_extension(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME)) + { + ADD_CHAIN(ext.descriptor_buffer_features, DESCRIPTOR_BUFFER_FEATURES_EXT); + enabled_extensions.push_back(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); + } +#endif + + if ((flags & CONTEXT_CREATION_ENABLE_ADVANCED_WSI_BIT) != 0 && requires_swapchain) + { + if (has_extension(VK_KHR_PRESENT_ID_2_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_PRESENT_ID_2_EXTENSION_NAME); + ADD_CHAIN(ext.present_id2_features, PRESENT_ID_2_FEATURES_KHR); + } + else if (has_extension(VK_KHR_PRESENT_ID_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_PRESENT_ID_EXTENSION_NAME); + ADD_CHAIN(ext.present_id_features, PRESENT_ID_FEATURES_KHR); + } + + if (has_extension(VK_KHR_PRESENT_WAIT_2_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_PRESENT_WAIT_2_EXTENSION_NAME); + ADD_CHAIN(ext.present_wait2_features, PRESENT_WAIT_2_FEATURES_KHR); + } + else if (has_extension(VK_KHR_PRESENT_WAIT_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_PRESENT_WAIT_EXTENSION_NAME); + ADD_CHAIN(ext.present_wait_features, PRESENT_WAIT_FEATURES_KHR); + } + +#if !defined(ANDROID) || !defined(HAVE_SWAPPY) + // Assume that swappy takes care of all this on Android. + if (has_extension(VK_EXT_PRESENT_TIMING_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_PRESENT_TIMING_EXTENSION_NAME); + ADD_CHAIN(ext.present_timing_features, PRESENT_TIMING_FEATURES_EXT); + } +#endif + + if (ext.supports_surface_maintenance1) + { + if (has_extension(VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME); + ADD_CHAIN(ext.swapchain_maintenance1_features, SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR); + } + else if (has_extension(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME); + ADD_CHAIN(ext.swapchain_maintenance1_features, SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR); + } + } + + if (ext.supports_swapchain_colorspace && has_extension(VK_EXT_HDR_METADATA_EXTENSION_NAME)) + { + ext.supports_hdr_metadata = true; + enabled_extensions.push_back(VK_EXT_HDR_METADATA_EXTENSION_NAME); + } + } + + if ((flags & CONTEXT_CREATION_ENABLE_POST_MORTEM_BIT) || + Util::get_environment_bool("GRANITE_VULKAN_POST_MORTEM", false)) + { + if (has_extension(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME); + ADD_CHAIN(ext.coherent_memory_features, COHERENT_MEMORY_FEATURES_AMD); + } + + if (has_extension(VK_AMD_BUFFER_MARKER_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_AMD_BUFFER_MARKER_EXTENSION_NAME); + ext.supports_amd_buffer_marker = true; + } + + if (has_extension(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME); + ext.supports_nv_checkpoints = true; + } + + // The KHR is quite new and not all relevant drivers support the KHR yet. + if (has_extension(VK_KHR_DEVICE_FAULT_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_DEVICE_FAULT_EXTENSION_NAME); + ADD_CHAIN(ext.fault_features_khr, FAULT_FEATURES_KHR); + } + else if (has_extension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_EXT_DEVICE_FAULT_EXTENSION_NAME); + ADD_CHAIN(ext.fault_features_ext, FAULT_FEATURES_EXT); + } + + ext.supports_post_mortem = true; + } + + if (has_extension(VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME); + ADD_CHAIN(ext.cooperative_matrix_features, COOPERATIVE_MATRIX_FEATURES_KHR); + } + + if (has_extension(VK_VALVE_SHADER_MIXED_FLOAT_DOT_PRODUCT_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_VALVE_SHADER_MIXED_FLOAT_DOT_PRODUCT_EXTENSION_NAME); + ADD_CHAIN(ext.shader_mixed_float_dot_product_features, SHADER_MIXED_FLOAT_DOT_PRODUCT_FEATURES_VALVE); + } + +#ifdef GRANITE_VULKAN_PROFILES + // Override any features in the profile in strict mode. + if (profile.profile && required_profile_strict) + { + vpGetProfileFeatures(profile.profile, &pdf2); + } + else +#endif + { + if (!inherit_info) + { + vkGetPhysicalDeviceFeatures2(gpu, &pdf2); + } + else if (inherit_info->pNext) + { + auto *features = find_pnext(inherit_info->pNext, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2); + pdf2.features = features->features; + } + else if (inherit_info->pEnabledFeatures) + { + pdf2.features = *inherit_info->pEnabledFeatures; + } + } + + // Promote fallback features to core structs. + if (ext.host_query_reset_features.hostQueryReset) + ext.vk12_features.hostQueryReset = VK_TRUE; + + if (ext.storage_16bit_features.storageBuffer16BitAccess) + ext.vk11_features.storageBuffer16BitAccess = VK_TRUE; + if (ext.storage_16bit_features.storageInputOutput16) + ext.vk11_features.storageInputOutput16 = VK_TRUE; + if (ext.storage_16bit_features.storagePushConstant16) + ext.vk11_features.storagePushConstant16 = VK_TRUE; + if (ext.storage_16bit_features.uniformAndStorageBuffer16BitAccess) + ext.vk11_features.uniformAndStorageBuffer16BitAccess = VK_TRUE; + + if (ext.storage_8bit_features.storageBuffer8BitAccess) + ext.vk12_features.storageBuffer8BitAccess = VK_TRUE; + if (ext.storage_8bit_features.storagePushConstant8) + ext.vk12_features.storagePushConstant8 = VK_TRUE; + if (ext.storage_8bit_features.uniformAndStorageBuffer8BitAccess) + ext.vk12_features.uniformAndStorageBuffer8BitAccess = VK_TRUE; + + if (ext.float16_int8_features.shaderFloat16) + ext.vk12_features.shaderFloat16 = VK_TRUE; + if (ext.float16_int8_features.shaderInt8) + ext.vk12_features.shaderInt8 = VK_TRUE; + + if (ext.subgroup_size_control_features.computeFullSubgroups) + ext.vk13_features.computeFullSubgroups = VK_TRUE; + if (ext.subgroup_size_control_features.subgroupSizeControl) + ext.vk13_features.subgroupSizeControl = VK_TRUE; + + if (ext.sync2_features.synchronization2) + ext.vk13_features.synchronization2 = VK_TRUE; + + if (ext.maintenance5_features.maintenance5) + ext.vk14_features.maintenance5 = VK_TRUE; + if (supports_khr_push_descriptor) + ext.vk14_features.pushDescriptor = VK_TRUE; + if (ext.index_type_uint8_features.indexTypeUint8) + ext.vk14_features.indexTypeUint8 = VK_TRUE; + /// + + ext.vk11_features.multiviewGeometryShader = VK_FALSE; + ext.vk11_features.multiviewTessellationShader = VK_FALSE; + ext.vk11_features.protectedMemory = VK_FALSE; + ext.vk11_features.variablePointers = VK_FALSE; + ext.vk11_features.variablePointersStorageBuffer = VK_FALSE; + + ext.vk12_features.bufferDeviceAddressCaptureReplay = VK_FALSE; + ext.vk12_features.bufferDeviceAddressMultiDevice = VK_FALSE; + ext.vk12_features.imagelessFramebuffer = VK_FALSE; + + ext.vk13_features.descriptorBindingInlineUniformBlockUpdateAfterBind = VK_FALSE; + ext.vk13_features.inlineUniformBlock = VK_FALSE; + ext.vk13_features.privateData = VK_FALSE; + + // Might be relevant when we move fully to 1.4. + ext.vk14_features.dynamicRenderingLocalRead = VK_FALSE; + ext.vk14_features.globalPriorityQuery = VK_FALSE; + ext.vk14_features.pipelineProtectedAccess = VK_FALSE; + ext.vk14_features.pipelineRobustness = VK_FALSE; + ext.vk14_features.vertexAttributeInstanceRateDivisor = VK_FALSE; + ext.vk14_features.vertexAttributeInstanceRateZeroDivisor = VK_FALSE; + ext.vk14_features.stippledBresenhamLines = VK_FALSE; + ext.vk14_features.stippledRectangularLines = VK_FALSE; + ext.vk14_features.stippledSmoothLines = VK_FALSE; + ext.vk14_features.rectangularLines = VK_FALSE; + ext.vk14_features.smoothLines = VK_FALSE; + ext.vk14_features.bresenhamLines = VK_FALSE; + if ((flags & CONTEXT_CREATION_ENABLE_PUSH_DESCRIPTOR_BIT) == 0) + ext.vk14_features.pushDescriptor = VK_FALSE; + + ext.mesh_shader_features.primitiveFragmentShadingRateMeshShader = VK_FALSE; + ext.mesh_shader_features.meshShaderQueries = VK_FALSE; + ext.mesh_shader_features.multiviewMeshShader = VK_FALSE; + + ext.descriptor_buffer_features.descriptorBufferCaptureReplay = VK_FALSE; + ext.descriptor_buffer_features.descriptorBufferImageLayoutIgnored = VK_FALSE; + ext.descriptor_buffer_features.descriptorBufferPushDescriptors = VK_FALSE; + + ext.descriptor_heap_features.descriptorHeapCaptureReplay = VK_FALSE; + + // Enable device features we might care about. + { + VkPhysicalDeviceFeatures enabled_features = *required_features; + if (pdf2.features.robustBufferAccess && (flags & CONTEXT_CREATION_ENABLE_ROBUSTNESS_2_BIT) != 0) + enabled_features.robustBufferAccess = VK_TRUE; + if (pdf2.features.textureCompressionETC2) + enabled_features.textureCompressionETC2 = VK_TRUE; + if (pdf2.features.textureCompressionBC) + enabled_features.textureCompressionBC = VK_TRUE; + if (pdf2.features.textureCompressionASTC_LDR) + enabled_features.textureCompressionASTC_LDR = VK_TRUE; + if (pdf2.features.fullDrawIndexUint32) + enabled_features.fullDrawIndexUint32 = VK_TRUE; + if (pdf2.features.imageCubeArray) + enabled_features.imageCubeArray = VK_TRUE; + if (pdf2.features.fillModeNonSolid) + enabled_features.fillModeNonSolid = VK_TRUE; + if (pdf2.features.independentBlend) + enabled_features.independentBlend = VK_TRUE; + if (pdf2.features.sampleRateShading) + enabled_features.sampleRateShading = VK_TRUE; + if (pdf2.features.vertexPipelineStoresAndAtomics) + enabled_features.vertexPipelineStoresAndAtomics = VK_TRUE; + if (pdf2.features.fragmentStoresAndAtomics) + enabled_features.fragmentStoresAndAtomics = VK_TRUE; + if (pdf2.features.shaderStorageImageExtendedFormats) + enabled_features.shaderStorageImageExtendedFormats = VK_TRUE; + if (pdf2.features.shaderStorageImageMultisample) + enabled_features.shaderStorageImageMultisample = VK_TRUE; + if (pdf2.features.largePoints) + enabled_features.largePoints = VK_TRUE; + if (pdf2.features.shaderInt16) + enabled_features.shaderInt16 = VK_TRUE; + if (pdf2.features.shaderInt64) + enabled_features.shaderInt64 = VK_TRUE; + if (pdf2.features.shaderStorageImageWriteWithoutFormat) + enabled_features.shaderStorageImageWriteWithoutFormat = VK_TRUE; + if (pdf2.features.shaderStorageImageReadWithoutFormat) + enabled_features.shaderStorageImageReadWithoutFormat = VK_TRUE; + if (pdf2.features.multiDrawIndirect) + enabled_features.multiDrawIndirect = VK_TRUE; + + if (pdf2.features.shaderSampledImageArrayDynamicIndexing) + enabled_features.shaderSampledImageArrayDynamicIndexing = VK_TRUE; + if (pdf2.features.shaderUniformBufferArrayDynamicIndexing) + enabled_features.shaderUniformBufferArrayDynamicIndexing = VK_TRUE; + if (pdf2.features.shaderStorageBufferArrayDynamicIndexing) + enabled_features.shaderStorageBufferArrayDynamicIndexing = VK_TRUE; + if (pdf2.features.shaderStorageImageArrayDynamicIndexing) + enabled_features.shaderStorageImageArrayDynamicIndexing = VK_TRUE; + if (pdf2.features.shaderImageGatherExtended) + enabled_features.shaderImageGatherExtended = VK_TRUE; + + if (pdf2.features.samplerAnisotropy) + enabled_features.samplerAnisotropy = VK_TRUE; + + pdf2.features = enabled_features; + ext.enabled_features = enabled_features; + } + + device_info.pNext = inherit_info ? inherit_info->pNext : &pdf2; + +#ifdef HAVE_GRANITE_VULKAN_POST_MORTEM + VkPhysicalDeviceDiagnosticsConfigFeaturesNV diagnostic_config_nv; + VkDeviceDiagnosticsConfigCreateInfoNV diagnostic_config_create_nv; + if (has_extension(VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME)) + { + enabled_extensions.push_back(VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME); + diagnostic_config_nv = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV }; + diagnostic_config_create_nv = { VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV }; + diagnostic_config_nv.diagnosticsConfig = VK_TRUE; + diagnostic_config_create_nv.flags = VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV | + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV | + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV | + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV; + diagnostic_config_nv.pNext = &diagnostic_config_create_nv; + diagnostic_config_create_nv.pNext = device_info.pNext; + device_info.pNext = &diagnostic_config_nv; + PostMortem::init_nv_aftermath(); + } +#endif + + // Only need GetPhysicalDeviceProperties2 for Vulkan 1.1-only code, so don't bother getting KHR variant. + VkPhysicalDeviceProperties2 props = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 }; + // Fallback, query some important Vulkan 1.1 structs if we cannot use core 1.2 method. + VkPhysicalDeviceDriverProperties driver_properties = {}; + VkPhysicalDeviceIDProperties id_properties = {}; + VkPhysicalDeviceSubgroupProperties subgroup_properties = {}; + VkPhysicalDeviceSubgroupSizeControlProperties size_control_props = {}; + +#undef ADD_CHAIN +#define ADD_CHAIN(s, type) add_chain(&(s), sizeof(s), VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ ## type, nullptr) + ppNext = reinterpret_cast(&props.pNext); + + if (ext.device_api_core_version >= VK_API_VERSION_1_2) + { + ADD_CHAIN(ext.vk11_props, VULKAN_1_1_PROPERTIES); + ADD_CHAIN(ext.vk12_props, VULKAN_1_2_PROPERTIES); + } + else + { + if (has_extension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) + ADD_CHAIN(driver_properties, DRIVER_PROPERTIES); + ADD_CHAIN(id_properties, ID_PROPERTIES); + ADD_CHAIN(subgroup_properties, SUBGROUP_PROPERTIES); + } + + if (ext.device_api_core_version >= VK_API_VERSION_1_3) + ADD_CHAIN(ext.vk13_props, VULKAN_1_3_PROPERTIES); + else if (has_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME)) + ADD_CHAIN(size_control_props, SUBGROUP_SIZE_CONTROL_PROPERTIES); + + if (ext.device_api_core_version >= VK_API_VERSION_1_4) + ADD_CHAIN(ext.vk14_props, VULKAN_1_4_PROPERTIES); + + if (ext.supports_external_memory_host) + ADD_CHAIN(ext.host_memory_properties, EXTERNAL_MEMORY_HOST_PROPERTIES_EXT); + + if (has_extension(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME)) + ADD_CHAIN(ext.device_generated_commands_properties, DEVICE_GENERATED_COMMANDS_PROPERTIES_EXT); + + if (ext.supports_conservative_rasterization) + ADD_CHAIN(ext.conservative_rasterization_properties, CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT); + + if (has_extension(VK_EXT_MESH_SHADER_EXTENSION_NAME)) + ADD_CHAIN(ext.mesh_shader_properties, MESH_SHADER_PROPERTIES_EXT); + + if ((flags & CONTEXT_CREATION_ENABLE_DESCRIPTOR_HEAP_BIT) != 0 && + has_extension(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME)) + { + ADD_CHAIN(ext.descriptor_heap_properties, DESCRIPTOR_HEAP_PROPERTIES_EXT); + } + else if ((flags & CONTEXT_CREATION_ENABLE_DESCRIPTOR_BUFFER_BIT) != 0 && + has_extension(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME)) + { + ADD_CHAIN(ext.descriptor_buffer_properties, DESCRIPTOR_BUFFER_PROPERTIES_EXT); + } + + if (has_extension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + ADD_CHAIN(ext.rtas_properties, ACCELERATION_STRUCTURE_PROPERTIES_KHR); + +#ifndef HAVE_GRANITE_VULKAN_POST_MORTEM + if ((flags & CONTEXT_CREATION_ENABLE_PIPELINE_BINARY_BIT) != 0 && + has_extension(VK_KHR_PIPELINE_BINARY_EXTENSION_NAME)) + ADD_CHAIN(ext.pipeline_binary_properties, PIPELINE_BINARY_PROPERTIES_KHR); +#endif + + vkGetPhysicalDeviceProperties2(gpu, &props); + + // If a layer or driver doesn't tell us that internal cache is preferred, + // go ahead and take full control over the cache. + if (!ext.pipeline_binary_properties.pipelineBinaryPrefersInternalCache && + ext.pipeline_binary_features.pipelineBinaries && + ext.pipeline_binary_properties.pipelineBinaryInternalCacheControl) + { + ext.pipeline_binary_internal_cache_control.sType = + VK_STRUCTURE_TYPE_DEVICE_PIPELINE_BINARY_INTERNAL_CACHE_CONTROL_KHR; + ext.pipeline_binary_internal_cache_control.disableInternalCache = VK_TRUE; + ext.pipeline_binary_internal_cache_control.pNext = device_info.pNext; + device_info.pNext = &ext.pipeline_binary_internal_cache_control; + } + + if (ext.device_api_core_version < VK_API_VERSION_1_2) + { + ext.driver_id = driver_properties.driverID; + ext.supports_driver_properties = has_extension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME); + ext.vk12_props.driverID = ext.driver_id; + memcpy(ext.vk11_props.deviceUUID, id_properties.deviceUUID, sizeof(id_properties.deviceUUID)); + memcpy(ext.vk11_props.driverUUID, id_properties.driverUUID, sizeof(id_properties.driverUUID)); + memcpy(ext.vk11_props.deviceLUID, id_properties.deviceLUID, sizeof(id_properties.deviceLUID)); + ext.vk11_props.deviceNodeMask = id_properties.deviceNodeMask; + ext.vk11_props.deviceLUIDValid = id_properties.deviceLUIDValid; + ext.vk11_props.subgroupQuadOperationsInAllStages = subgroup_properties.quadOperationsInAllStages; + ext.vk11_props.subgroupSupportedOperations = subgroup_properties.supportedOperations; + ext.vk11_props.subgroupSupportedStages = subgroup_properties.supportedStages; + ext.vk11_props.subgroupSize = subgroup_properties.subgroupSize; + } + else + { + ext.driver_id = ext.vk12_props.driverID; + ext.supports_driver_properties = true; + } + + if (ext.device_api_core_version < VK_API_VERSION_1_3) + { + ext.vk13_props.minSubgroupSize = size_control_props.minSubgroupSize; + ext.vk13_props.maxSubgroupSize = size_control_props.maxSubgroupSize; + ext.vk13_props.requiredSubgroupSizeStages = size_control_props.requiredSubgroupSizeStages; + ext.vk13_props.maxComputeWorkgroupSubgroups = size_control_props.maxComputeWorkgroupSubgroups; + } + +#ifdef GRANITE_VULKAN_PROFILES + // Override any properties in the profile in strict mode. + if (profile.profile && required_profile_strict) + vpGetProfileProperties(profile.profile, &props); +#endif + + if (inherit_info) + { + device_info.enabledExtensionCount = inherit_info->enabledExtensionCount; + device_info.ppEnabledExtensionNames = inherit_info->ppEnabledExtensionNames; + } + else + { + device_info.enabledExtensionCount = enabled_extensions.size(); + device_info.ppEnabledExtensionNames = enabled_extensions.empty() ? nullptr : enabled_extensions.data(); + } + + for (uint32_t i = 0; i < device_info.enabledExtensionCount; i++) + LOGI("Enabling device extension: %s.\n", device_info.ppEnabledExtensionNames[i]); + +#ifdef GRANITE_VULKAN_PROFILES + if (!required_profile.empty()) + { + if (create_device_from_profile(device_info, &device) != VK_SUCCESS) + return false; + } + else +#endif + { + if (device_factory) + { + device = device_factory->create_device(gpu, &device_info); + if (device == VK_NULL_HANDLE) + return false; + } + else if (vkCreateDevice(gpu, &device_info, nullptr, &device) != VK_SUCCESS) + return false; + } + + if (inherit_info) + { + ext.device_extensions = inherit_info->ppEnabledExtensionNames; + ext.num_device_extensions = inherit_info->enabledExtensionCount; + + if (inherit_info->pNext) + { + ext.pdf2 = static_cast(inherit_info->pNext); + VK_ASSERT(ext.pdf2->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2); + } + else + { + ext.pdf2 = &pdf2; + } + } + else + { + enabled_device_extensions = std::move(enabled_extensions); + ext.device_extensions = enabled_device_extensions.data(); + ext.num_device_extensions = uint32_t(enabled_device_extensions.size()); + ext.pdf2 = &pdf2; + } + +#ifdef GRANITE_VULKAN_FOSSILIZE + feature_filter.init(ext.device_api_core_version, + const_cast(device_info.ppEnabledExtensionNames), + device_info.enabledExtensionCount, + &pdf2, &props); + feature_filter.set_device_query_interface(this); +#endif + + volkLoadDeviceTable(&device_table, device); + +#define PROMOTE_CALL(n, e) if (!device_table.vk##n) device_table.vk##n = device_table.vk##n##e + PROMOTE_CALL(CreateRenderPass2, KHR); + PROMOTE_CALL(QueueSubmit2, KHR); + PROMOTE_CALL(CmdPipelineBarrier2, KHR); + PROMOTE_CALL(CmdWriteTimestamp2, KHR); + PROMOTE_CALL(CmdSetEvent2, KHR); + PROMOTE_CALL(CmdResetEvent2, KHR); + PROMOTE_CALL(CmdWaitEvents2, KHR); + PROMOTE_CALL(ResetQueryPool, EXT); + PROMOTE_CALL(CmdPushDescriptorSetWithTemplate, KHR); +#undef PROMOTE_CALL + + for (int i = 0; i < QUEUE_INDEX_COUNT; i++) + { + if (queue_info.family_indices[i] != VK_QUEUE_FAMILY_IGNORED) + { + queue_info.queues[i] = device_factory ? + device_factory->get_queue(queue_info.family_indices[i], queue_indices[i]) : VK_NULL_HANDLE; + + if (!queue_info.queues[i]) + { + device_table.vkGetDeviceQueue(device, queue_info.family_indices[i], queue_indices[i], + &queue_info.queues[i]); + } + + queue_info.counts[i] = queue_offsets[queue_info.family_indices[i]]; + +#if defined(ANDROID) && defined(HAVE_SWAPPY) + SwappyVk_setQueueFamilyIndex(device, queue_info.queues[i], queue_info.family_indices[i]); +#endif + } + else + { + queue_info.queues[i] = VK_NULL_HANDLE; + } + } + +#ifdef VULKAN_DEBUG + static const char *family_names[QUEUE_INDEX_COUNT] = { "Graphics", "Compute", "Transfer", "Video decode", "Video encode" }; + for (int i = 0; i < QUEUE_INDEX_COUNT; i++) + if (queue_info.family_indices[i] != VK_QUEUE_FAMILY_IGNORED) + LOGI("%s queue: family %u, index %u.\n", family_names[i], queue_info.family_indices[i], queue_indices[i]); +#endif + + if (ext.descriptor_buffer_features.descriptorBuffer) + { + auto max_heap_size = std::min( + ext.descriptor_buffer_properties.maxSamplerDescriptorBufferRange, + ext.descriptor_buffer_properties.maxResourceDescriptorBufferRange); + + // Only expose this if we can easily linearly allocate samplers and combined image samplers. + // Cba to deal with planar arrays of combined image samplers either. + ext.supports_descriptor_buffer = + ext.descriptor_buffer_properties.samplerDescriptorSize * 512ull * 1024ull <= max_heap_size && + ext.descriptor_buffer_properties.sampledImageDescriptorSize * 512ull * 1024ull <= max_heap_size && + ext.descriptor_buffer_properties.combinedImageSamplerDescriptorSingleArray; + } + + ext.supports_descriptor_buffer_or_heap = + ext.supports_descriptor_buffer || ext.descriptor_heap_features.descriptorHeap; + + if (ext.descriptor_heap_features.descriptorHeap) + { + ext.resource_heap_offset_alignment = std::max( + ext.descriptor_heap_properties.bufferDescriptorAlignment, + ext.descriptor_heap_properties.imageDescriptorAlignment); + + ext.resource_heap_resource_desc_size = std::max( + ext.descriptor_heap_properties.bufferDescriptorSize, + ext.resource_heap_resource_desc_size); + + ext.resource_heap_resource_desc_size = std::max( + ext.descriptor_heap_properties.imageDescriptorSize, + ext.resource_heap_resource_desc_size); + + ext.resource_heap_resource_desc_size = Util::next_pow2(ext.resource_heap_resource_desc_size); + ext.resource_heap_resource_desc_size_log2 = Util::floor_log2(ext.resource_heap_resource_desc_size); + } + else + { + ext.resource_heap_offset_alignment = ext.descriptor_buffer_properties.descriptorBufferOffsetAlignment; + } + + return true; +} + +const VkDeviceCreateInfo *DeviceFactory::get_existing_create_info() +{ + return nullptr; +} + +bool DeviceFactory::factory_owns_created_device() +{ + return false; +} + +VkQueue DeviceFactory::get_queue(uint32_t, uint32_t) +{ + return VK_NULL_HANDLE; +} + +const VkInstanceCreateInfo *InstanceFactory::get_existing_create_info() +{ + return nullptr; +} + +bool InstanceFactory::factory_owns_created_instance() +{ + return false; +} + +#ifdef GRANITE_VULKAN_FOSSILIZE +bool Context::format_is_supported(VkFormat format, VkFormatFeatureFlags features) +{ + if (gpu == VK_NULL_HANDLE) + return false; + + VkFormatProperties props; + vkGetPhysicalDeviceFormatProperties(gpu, format, &props); + auto supported = props.bufferFeatures | props.linearTilingFeatures | props.optimalTilingFeatures; + return (supported & features) == features; +} + +bool Context::descriptor_set_layout_is_supported(const VkDescriptorSetLayoutCreateInfo *set_layout) +{ + if (device == VK_NULL_HANDLE) + return false; + + VkDescriptorSetLayoutSupport support = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT }; + vkGetDescriptorSetLayoutSupport(device, set_layout, &support); + return support.supported == VK_TRUE; +} + +void Context::physical_device_feature_query(VkPhysicalDeviceFeatures2 *pdf2_) +{ + if (gpu && vkGetPhysicalDeviceFeatures2) + vkGetPhysicalDeviceFeatures2(gpu, pdf2_); +} +#endif +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/context.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/context.hpp new file mode 100644 index 00000000..6dc77e3b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/context.hpp @@ -0,0 +1,458 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include "logging.hpp" +#include "vulkan_common.hpp" +#include +#include + +#ifdef GRANITE_VULKAN_FOSSILIZE +#include "cli/fossilize_feature_filter.hpp" +#endif + +namespace Util +{ +class TimelineTraceFile; +} + +namespace Granite +{ +class Filesystem; +class ThreadGroup; +class AssetManager; +} + +namespace Vulkan +{ +struct DeviceFeatures +{ + bool supports_debug_utils = false; + bool supports_external_memory_host = false; + bool supports_surface_capabilities2 = false; + bool supports_full_screen_exclusive = false; + bool supports_conservative_rasterization = false; + bool supports_calibrated_timestamps = false; + bool supports_memory_budget = false; + bool supports_video_queue = false; + bool supports_driver_properties = false; + bool supports_video_decode_queue = false; + bool supports_video_decode_h264 = false; + bool supports_video_decode_h265 = false; + bool supports_video_decode_av1 = false; + bool supports_astc_decode_mode = false; + bool supports_image_format_list = false; + bool supports_format_feature_flags2 = false; + bool supports_video_encode_queue = false; + bool supports_video_encode_h264 = false; + bool supports_video_encode_h265 = false; + bool supports_video_encode_av1 = false; + bool supports_external = false; + bool supports_tooling_info = false; + bool supports_hdr_metadata = false; + bool supports_swapchain_colorspace = false; + bool supports_surface_maintenance1 = false; + bool supports_store_op_none = false; + bool supports_low_latency2_nv = false; + bool supports_drm_modifiers = false; + bool supports_descriptor_buffer = false; + bool supports_amd_buffer_marker = false; + bool supports_nv_checkpoints = false; + bool supports_post_mortem = false; + + bool supports_descriptor_buffer_or_heap = false; + uint32_t resource_heap_offset_alignment = 0; + uint32_t resource_heap_resource_desc_size = 0; + uint32_t resource_heap_resource_desc_size_log2 = 0; + + VkPhysicalDeviceFeatures enabled_features = {}; + + VkPhysicalDeviceVulkan11Features vk11_features = {}; + VkPhysicalDeviceVulkan12Features vk12_features = {}; + VkPhysicalDeviceVulkan13Features vk13_features = {}; + VkPhysicalDeviceVulkan14Features vk14_features = {}; + VkPhysicalDeviceVulkan11Properties vk11_props = {}; + VkPhysicalDeviceVulkan12Properties vk12_props = {}; + VkPhysicalDeviceVulkan13Properties vk13_props = {}; + VkPhysicalDeviceVulkan14Properties vk14_props = {}; + + // KHR + VkPhysicalDeviceComputeShaderDerivativesFeaturesKHR compute_shader_derivative_features = {}; + VkPhysicalDevicePerformanceQueryFeaturesKHR performance_query_features = {}; + VkPhysicalDevicePresentIdFeaturesKHR present_id_features = {}; + VkPhysicalDevicePresentId2FeaturesKHR present_id2_features = {}; + VkPhysicalDevicePresentWaitFeaturesKHR present_wait_features = {}; + VkPhysicalDevicePresentWait2FeaturesKHR present_wait2_features = {}; + VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR barycentric_features = {}; + VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maintenance1_features = {}; + VkPhysicalDevicePipelineBinaryFeaturesKHR pipeline_binary_features = {}; + VkPhysicalDevicePipelineBinaryPropertiesKHR pipeline_binary_properties = {}; + VkDevicePipelineBinaryInternalCacheControlKHR pipeline_binary_internal_cache_control = {}; + VkPhysicalDeviceMaintenance5FeaturesKHR maintenance5_features = {}; + VkPhysicalDeviceVideoEncodeAV1FeaturesKHR av1_features = {}; + VkPhysicalDeviceAccelerationStructureFeaturesKHR rtas_features = {}; + VkPhysicalDeviceAccelerationStructurePropertiesKHR rtas_properties = {}; + VkPhysicalDeviceRayQueryFeaturesKHR ray_query_features = {}; + VkPhysicalDeviceShaderUntypedPointersFeaturesKHR untyped_pointers_features = {}; + VkPhysicalDeviceFaultFeaturesKHR fault_features_khr = {}; + VkPhysicalDeviceCooperativeMatrixFeaturesKHR cooperative_matrix_features = {}; + + // EXT + VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_memory_properties = {}; + VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_rasterization_properties = {}; + VkPhysicalDeviceMemoryPriorityFeaturesEXT memory_priority_features = {}; + VkPhysicalDeviceASTCDecodeFeaturesEXT astc_decode_features = {}; + VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR swapchain_maintenance1_features = {}; + VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT pageable_device_local_memory_features = {}; + VkPhysicalDeviceMeshShaderFeaturesEXT mesh_shader_features = {}; + VkPhysicalDeviceMeshShaderPropertiesEXT mesh_shader_properties = {}; + VkPhysicalDeviceIndexTypeUint8FeaturesEXT index_type_uint8_features = {}; + VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT rgba10x6_formats_features = {}; + VkPhysicalDeviceImageCompressionControlFeaturesEXT image_compression_control_features = {}; + VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT image_compression_control_swapchain_features = {}; + VkPhysicalDeviceDeviceGeneratedCommandsFeaturesEXT device_generated_commands_features = {}; + VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT device_generated_commands_properties = {}; + VkPhysicalDeviceRobustness2FeaturesEXT robustness2_features = {}; + VkPhysicalDeviceDescriptorBufferFeaturesEXT descriptor_buffer_features = {}; + VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_buffer_properties = {}; + VkPhysicalDevicePresentTimingFeaturesEXT present_timing_features = {}; + VkPhysicalDeviceDescriptorHeapFeaturesEXT descriptor_heap_features = {}; + VkPhysicalDeviceDescriptorHeapPropertiesEXT descriptor_heap_properties = {}; + VkPhysicalDeviceFaultFeaturesEXT fault_features_ext = {}; + + // Vendor + VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV descriptor_pool_overallocation_features = {}; + VkPhysicalDeviceAntiLagFeaturesAMD anti_lag_features = {}; + VkPhysicalDeviceCoherentMemoryFeaturesAMD coherent_memory_features = {}; + VkPhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE shader_mixed_float_dot_product_features = {}; + + // Fallback feature structs (Vulkan 1.1) + VkPhysicalDeviceHostQueryResetFeatures host_query_reset_features = {}; + VkPhysicalDevice16BitStorageFeaturesKHR storage_16bit_features = {}; + // Fallback feature structs (Vulkan 1.2) + VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8_features = {}; + VkPhysicalDevice8BitStorageFeaturesKHR storage_8bit_features = {}; + // Fallback feature structs (Vulkan 1.3) + VkPhysicalDeviceSubgroupSizeControlFeatures subgroup_size_control_features = {}; + VkPhysicalDeviceSynchronization2Features sync2_features = {}; + + VkDriverId driver_id = {}; + + // References Vulkan::Context. + const VkPhysicalDeviceFeatures2 *pdf2 = nullptr; + const char * const * instance_extensions = nullptr; + uint32_t num_instance_extensions = 0; + const char * const * device_extensions = nullptr; + uint32_t num_device_extensions = 0; + + uint32_t instance_api_core_version = VK_API_VERSION_1_1; + uint32_t device_api_core_version = VK_API_VERSION_1_1; +}; + +enum VendorID +{ + VENDOR_ID_AMD = 0x1002, + VENDOR_ID_NVIDIA = 0x10de, + VENDOR_ID_INTEL = 0x8086, + VENDOR_ID_ARM = 0x13b5, + VENDOR_ID_QCOM = 0x5143 +}; + +enum ContextCreationFlagBits +{ + CONTEXT_CREATION_ENABLE_ADVANCED_WSI_BIT = 1 << 0, + CONTEXT_CREATION_ENABLE_VIDEO_DECODE_BIT = 1 << 1, + CONTEXT_CREATION_ENABLE_VIDEO_ENCODE_BIT = 1 << 2, + CONTEXT_CREATION_ENABLE_VIDEO_H264_BIT = 1 << 3, + CONTEXT_CREATION_ENABLE_VIDEO_H265_BIT = 1 << 4, + CONTEXT_CREATION_ENABLE_PIPELINE_BINARY_BIT = 1 << 5, + CONTEXT_CREATION_ENABLE_PUSH_DESCRIPTOR_BIT = 1 << 6, + CONTEXT_CREATION_ENABLE_ROBUSTNESS_2_BIT = 1 << 7, + CONTEXT_CREATION_ENABLE_VIDEO_AV1_BIT = 1 << 8, + CONTEXT_CREATION_ENABLE_DESCRIPTOR_BUFFER_BIT = 1 << 9, + CONTEXT_CREATION_ENABLE_DESCRIPTOR_HEAP_BIT = 1 << 10, + CONTEXT_CREATION_ENABLE_POST_MORTEM_BIT = 1 << 11, + CONTEXT_CREATION_ENABLE_VIDEO_FEATURE_ONLY_BIT = 1 << 12, +}; +using ContextCreationFlags = uint32_t; + +struct QueueInfo +{ + QueueInfo(); + VkQueue queues[QUEUE_INDEX_COUNT] = {}; + uint32_t family_indices[QUEUE_INDEX_COUNT]; + uint32_t counts[QUEUE_INDEX_COUNT] = {}; + uint32_t timestamp_valid_bits = 0; +}; + +struct InstanceFactory +{ + virtual ~InstanceFactory() = default; + virtual VkInstance create_instance(const VkInstanceCreateInfo *info) = 0; + + // Lifetime of any data in create info must remain as long as Context is alive. + virtual const VkInstanceCreateInfo *get_existing_create_info(); + virtual bool factory_owns_created_instance(); +}; + +struct DeviceFactory +{ + virtual ~DeviceFactory() = default; + virtual VkDevice create_device(VkPhysicalDevice gpu, const VkDeviceCreateInfo *info) = 0; + + // Lifetime of any data in create info must remain as long as Context is alive. + // If pNext is not NULL, the first link in the pNext chain must be VkPhysicalDeviceFeatures2. + virtual const VkDeviceCreateInfo *get_existing_create_info(); + virtual bool factory_owns_created_device(); + virtual VkQueue get_queue(uint32_t family_index, uint32_t index); +}; + +class CopiedApplicationInfo +{ +public: + CopiedApplicationInfo(); + const VkApplicationInfo &get_application_info() const; + void copy_assign(const VkApplicationInfo *info); + +private: + std::string application; + std::string engine; + VkApplicationInfo app = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, "Granite", 0, "Granite", 0, VK_API_VERSION_1_1, + }; + + void set_default_app(); +}; + +class Context + : public Util::IntrusivePtrEnabled, HandleCounter> +#ifdef GRANITE_VULKAN_FOSSILIZE + , public Fossilize::DeviceQueryInterface +#endif +{ +public: + // If these interface are set, factory->create() calls are used instead of global vkCreateInstance and vkCreateDevice. + // For deeper API interop scenarios. + void set_instance_factory(InstanceFactory *factory); + void set_device_factory(DeviceFactory *factory); + + // Only takes effect if profiles are enabled in build. (GRANITE_VULKAN_PROFILES) + // If profile is non-null, forces a specific profile. + // If not supported, initialization fails. + // If not set, ignore profiles. + // If strict is false, the profile should be seen as a baseline and Granite will augment features on top. + // If true, the profile is a strict limit for device functionality. For validation purposes. + void set_required_profile(const char *profile, bool strict); + + // Call before initializing instances. app_info may be freed after returning. + // API_VERSION must be at least 1.1. + // By default, a Vulkan 1.1 to 1.4 instance is created depending on support. + void set_application_info(const VkApplicationInfo *app_info); + + // Recommended interface. + // InstanceFactory can be used to override enabled instance layers and extensions. + // For simple WSI use, it is enough to just enable VK_KHR_surface and the platform. + bool init_instance(const char * const *instance_ext, uint32_t instance_ext_count, + ContextCreationFlags flags = 0); + // DeviceFactory can be used to override enabled device extensions. + // For simple WSI use, it is enough to just enable VK_KHR_swapchain. + bool init_device(VkPhysicalDevice gpu, VkSurfaceKHR surface_compat, + const char * const *device_ext, uint32_t device_ext_count, + ContextCreationFlags flags = 0); + + // Simplified initialization which calls init_instance and init_device in succession with NULL GPU and surface. + // Provided for compat with older code. + bool init_instance_and_device(const char * const *instance_ext, uint32_t instance_ext_count, + const char * const *device_ext, uint32_t device_ext_count, + ContextCreationFlags flags = 0); + + // Deprecated. For libretro Vulkan context negotiation v1. + // Use InstanceFactory and DeviceFactory for more advanced scenarios in v2. + bool init_device_from_instance(VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface, + const char **required_device_extensions, + unsigned num_required_device_extensions, + const VkPhysicalDeviceFeatures *required_features, + ContextCreationFlags flags = 0); + + Context(); + Context(const Context &) = delete; + void operator=(const Context &) = delete; + static bool init_loader(PFN_vkGetInstanceProcAddr addr, bool force_reload = false); + static PFN_vkGetInstanceProcAddr get_instance_proc_addr(); + + ~Context(); + + VkInstance get_instance() const + { + return instance; + } + + VkPhysicalDevice get_gpu() const + { + return gpu; + } + + VkDevice get_device() const + { + return device; + } + + const QueueInfo &get_queue_info() const + { + return queue_info; + } + + const VkPhysicalDeviceProperties &get_gpu_props() const + { + return gpu_props; + } + + const VkPhysicalDeviceMemoryProperties &get_mem_props() const + { + return mem_props; + } + + void release_instance() + { + owned_instance = false; + } + + void release_device() + { + owned_device = false; + } + + const DeviceFeatures &get_enabled_device_features() const + { + return ext; + } + + const VkApplicationInfo &get_application_info() const; + + void notify_validation_error(const char *msg); + void set_notification_callback(std::function func); + + void set_num_thread_indices(unsigned indices) + { + num_thread_indices = indices; + } + + unsigned get_num_thread_indices() const + { + return num_thread_indices; + } + + const VolkDeviceTable &get_device_table() const + { + return device_table; + } + + struct SystemHandles + { + Util::TimelineTraceFile *timeline_trace_file = nullptr; + Granite::Filesystem *filesystem = nullptr; + Granite::ThreadGroup *thread_group = nullptr; + Granite::AssetManager *asset_manager = nullptr; + }; + + void set_system_handles(const SystemHandles &handles_) + { + handles = handles_; + } + + const SystemHandles &get_system_handles() const + { + return handles; + } + +#ifdef GRANITE_VULKAN_FOSSILIZE + const Fossilize::FeatureFilter &get_feature_filter() const + { + return feature_filter; + } +#endif + + const VkPhysicalDeviceFeatures2 &get_physical_device_features() const + { + return pdf2; + } + +private: + InstanceFactory *instance_factory = nullptr; + DeviceFactory *device_factory = nullptr; + VkDevice device = VK_NULL_HANDLE; + VkInstance instance = VK_NULL_HANDLE; + VkPhysicalDevice gpu = VK_NULL_HANDLE; + VolkDeviceTable device_table = {}; + SystemHandles handles; + VkPhysicalDeviceProperties gpu_props = {}; + VkPhysicalDeviceMemoryProperties mem_props = {}; + + CopiedApplicationInfo user_application_info; + + QueueInfo queue_info; + unsigned num_thread_indices = 1; + + bool create_instance(const char * const *instance_ext, uint32_t instance_ext_count, ContextCreationFlags flags); + bool create_device(VkPhysicalDevice gpu, VkSurfaceKHR surface, + const char * const *required_device_extensions, uint32_t num_required_device_extensions, + const VkPhysicalDeviceFeatures *required_features, ContextCreationFlags flags); + + bool owned_instance = false; + bool owned_device = false; + DeviceFeatures ext; + VkPhysicalDeviceFeatures2 pdf2; + std::vector enabled_device_extensions; + std::vector enabled_instance_extensions; + + std::string required_profile; + bool required_profile_strict = false; + +#ifdef VULKAN_DEBUG + VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE; + bool force_no_validation = false; +#endif + std::function message_callback; + + void destroy_instance(); + void destroy_device(); + + bool physical_device_supports_surface_and_profile(VkPhysicalDevice candidate_gpu, VkSurfaceKHR surface) const; + +#ifdef GRANITE_VULKAN_FOSSILIZE + Fossilize::FeatureFilter feature_filter; + bool format_is_supported(VkFormat format, VkFormatFeatureFlags features) override; + bool descriptor_set_layout_is_supported(const VkDescriptorSetLayoutCreateInfo *set_layout) override; + void physical_device_feature_query(VkPhysicalDeviceFeatures2 *pdf2) override; +#endif + + bool init_profile(); + VkResult create_instance_from_profile(const VkInstanceCreateInfo &info, VkInstance *pInstance); + VkResult create_device_from_profile(const VkDeviceCreateInfo &info, VkDevice *pDevice); + + VkApplicationInfo get_promoted_application_info() const; +}; + +using ContextHandle = Util::IntrusivePtr; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/cookie.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/cookie.cpp new file mode 100644 index 00000000..1eb9286f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/cookie.cpp @@ -0,0 +1,32 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "cookie.hpp" +#include "device.hpp" + +namespace Vulkan +{ +Cookie::Cookie(Device *device) + : cookie(device->allocate_cookie()) +{ +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/cookie.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/cookie.hpp new file mode 100644 index 00000000..91eb2db0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/cookie.hpp @@ -0,0 +1,61 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include "hash.hpp" +#include "intrusive_hash_map.hpp" + +namespace Vulkan +{ +class Device; + +class Cookie +{ +public: + Cookie(Device *device); + + uint64_t get_cookie() const + { + return cookie; + } + +private: + uint64_t cookie; +}; + +template +using HashedObject = Util::IntrusiveHashMapEnabled; + +class InternalSyncEnabled +{ +public: + void set_internal_sync_object() + { + internal_sync = true; + } + +protected: + bool internal_sync = false; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/descriptor_set.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/descriptor_set.cpp new file mode 100644 index 00000000..e1d8b093 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/descriptor_set.cpp @@ -0,0 +1,672 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "descriptor_set.hpp" +#include "device.hpp" +#include + +using namespace Util; + +namespace Vulkan +{ +DescriptorSetAllocator::DescriptorSetAllocator(Hash hash, Device *device_, const DescriptorSetLayout &layout, + const uint32_t *stages_for_binds, + const ImmutableSampler * const *immutable_samplers) + : IntrusiveHashMapEnabled(hash) + , device(device_) + , table(device_->get_device_table()) +{ + bindless = layout.meta[0].array_size == DescriptorSetLayout::UNSIZED_ARRAY; + + if (!bindless) + { + unsigned count = device_->num_thread_indices * device_->per_frame.size(); + per_thread_and_frame.resize(count); + } + + if (bindless && !device->get_device_features().vk12_features.descriptorIndexing) + { + LOGE("Cannot support descriptor indexing on this device.\n"); + return; + } + + VkDescriptorSetLayoutCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; + VkDescriptorSetLayoutBindingFlagsCreateInfoEXT flags = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT }; + VkSampler vk_immutable_samplers[VULKAN_NUM_BINDINGS] = {}; + std::vector bindings; + VkDescriptorBindingFlagsEXT binding_flags = 0; + + if (bindless) + { + if (!device->ext.supports_descriptor_buffer) + info.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; + info.pNext = &flags; + + flags.bindingCount = 1; + flags.pBindingFlags = &binding_flags; + + binding_flags = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT; + if (!device->ext.supports_descriptor_buffer) + { + // These flags are implied when using descriptor buffer. + binding_flags |= VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; + } + } + + if (device->ext.supports_descriptor_buffer) + info.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + + for (unsigned i = 0; i < VULKAN_NUM_BINDINGS; i++) + { + auto stages = stages_for_binds[i]; + if (stages == 0) + continue; + + unsigned array_size = layout.meta[i].array_size; + unsigned pool_array_size; + if (array_size == DescriptorSetLayout::UNSIZED_ARRAY) + { + array_size = VULKAN_NUM_BINDINGS_BINDLESS_VARYING; + pool_array_size = array_size; + } + else + pool_array_size = array_size * VULKAN_NUM_SETS_PER_POOL; + + unsigned types = 0; + if (layout.sampled_image_mask & (1u << i)) + { + if ((layout.immutable_sampler_mask & (1u << i)) && immutable_samplers && immutable_samplers[i]) + vk_immutable_samplers[i] = immutable_samplers[i]->get_sampler().get_sampler(); + + bindings.push_back({ i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, array_size, stages, + vk_immutable_samplers[i] != VK_NULL_HANDLE ? &vk_immutable_samplers[i] : nullptr }); + pool_size.push_back({ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, pool_array_size }); + types++; + } + + if (layout.sampled_texel_buffer_mask & (1u << i)) + { + bindings.push_back({ i, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, array_size, stages, nullptr }); + pool_size.push_back({ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, pool_array_size }); + types++; + } + + if (layout.storage_texel_buffer_mask & (1u << i)) + { + bindings.push_back({ i, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, array_size, stages, nullptr }); + pool_size.push_back({ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, pool_array_size }); + types++; + } + + if (layout.storage_image_mask & (1u << i)) + { + bindings.push_back({ i, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, array_size, stages, nullptr }); + pool_size.push_back({ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, pool_array_size }); + types++; + } + + if (layout.uniform_buffer_mask & (1u << i)) + { + auto type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + bindings.push_back({ i, type, array_size, stages, nullptr }); + pool_size.push_back({ type, pool_array_size }); + types++; + } + + if (layout.storage_buffer_mask & (1u << i)) + { + bindings.push_back({ i, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, array_size, stages, nullptr }); + pool_size.push_back({ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, pool_array_size }); + types++; + } + + if (layout.rtas_mask & (1u << i)) + { + bindings.push_back({ i, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, array_size, stages, nullptr }); + pool_size.push_back({ VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, pool_array_size }); + types++; + } + + if (layout.input_attachment_mask & (1u << i)) + { + bindings.push_back({ i, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, array_size, stages, nullptr }); + pool_size.push_back({ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, pool_array_size }); + types++; + } + + if (layout.separate_image_mask & (1u << i)) + { + bindings.push_back({ i, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, array_size, stages, nullptr }); + pool_size.push_back({ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, pool_array_size }); + types++; + } + + if (layout.sampler_mask & (1u << i)) + { + if ((layout.immutable_sampler_mask & (1u << i)) && immutable_samplers && immutable_samplers[i]) + { + if (!device->get_device_features().supports_descriptor_buffer) + vk_immutable_samplers[i] = immutable_samplers[i]->get_sampler().get_sampler(); + else + LOGE("Cannot use immutable samplers with descriptor buffer. Ignoring.\n"); + } + + bindings.push_back({ i, VK_DESCRIPTOR_TYPE_SAMPLER, array_size, stages, + vk_immutable_samplers[i] != VK_NULL_HANDLE ? &vk_immutable_samplers[i] : nullptr }); + pool_size.push_back({ VK_DESCRIPTOR_TYPE_SAMPLER, pool_array_size }); + types++; + } + + (void)types; + VK_ASSERT(types <= 1 && "Descriptor set aliasing!"); + } + + if (!bindings.empty()) + { + info.bindingCount = bindings.size(); + info.pBindings = bindings.data(); + + if (bindless && bindings.size() != 1) + { + LOGE("Using bindless but have bindingCount != 1.\n"); + return; + } + } + + bool heap = device->get_device_features().descriptor_heap_features.descriptorHeap == VK_TRUE; + + if (!heap) + { +#ifdef VULKAN_DEBUG + LOGI("Creating descriptor set layout.\n"); +#endif + if (table.vkCreateDescriptorSetLayout(device->get_device(), &info, nullptr, &set_layout_pool) != VK_SUCCESS) + LOGE("Failed to create descriptor set layout."); + } + + if (device->ext.supports_descriptor_buffer && !heap) + { + // Query the memory layout. + table.vkGetDescriptorSetLayoutSizeEXT(device->get_device(), set_layout_pool, &desc_set_size); + + if (bindless) + { + table.vkGetDescriptorSetLayoutBindingOffsetEXT( + device->get_device(), set_layout_pool, 0, &desc_set_variable_offset); + } + else + { + for (auto &bind : bindings) + { + VkDeviceSize offset = 0; + VkDeviceSize stride = device->managers.descriptor_buffer.get_descriptor_size_for_type(bind.descriptorType); + + table.vkGetDescriptorSetLayoutBindingOffsetEXT( + device->get_device(), set_layout_pool, bind.binding, &offset); + + for (uint32_t i = 0; i < bind.descriptorCount; i++) + desc_offsets[bind.binding + i] = offset + i * stride; + } + } + } + +#ifdef GRANITE_VULKAN_FOSSILIZE + if (device->ext.supports_descriptor_buffer && !heap) + { + // Normalize the recorded flags. + if (bindless) + { + info.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; + binding_flags |= VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; + } + + info.flags &= ~VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + } + + if (set_layout_pool) + device->register_descriptor_set_layout(set_layout_pool, get_hash(), info); +#endif + + // Push descriptors is not used with descriptor buffer. + if (!bindless && device->get_device_features().vk14_features.pushDescriptor && + !heap && !device->get_device_features().descriptor_buffer_features.descriptorBuffer) + { + info.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT; + if (table.vkCreateDescriptorSetLayout(device->get_device(), &info, nullptr, &set_layout_push) != VK_SUCCESS) + LOGE("Failed to create descriptor set layout."); +#ifdef GRANITE_VULKAN_FOSSILIZE + if (set_layout_push) + device->register_descriptor_set_layout(set_layout_push, get_hash(), info); +#endif + } +} + +void DescriptorSetAllocator::reset_bindless_pool(VkDescriptorPool pool) +{ + table.vkResetDescriptorPool(device->get_device(), pool, 0); +} + +BindlessDescriptorSet DescriptorSetAllocator::allocate_bindless_set(VkDescriptorPool pool, unsigned num_descriptors) +{ + if (!pool || !bindless) + return {}; + + VkDescriptorSetAllocateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; + info.descriptorPool = pool; + info.descriptorSetCount = 1; + info.pSetLayouts = &set_layout_pool; + + VkDescriptorSetVariableDescriptorCountAllocateInfoEXT count_info = + { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT }; + + uint32_t num_desc = num_descriptors; + count_info.descriptorSetCount = 1; + count_info.pDescriptorCounts = &num_desc; + info.pNext = &count_info; + + BindlessDescriptorSet desc_set; + if (table.vkAllocateDescriptorSets(device->get_device(), &info, &desc_set.handle.set) != VK_SUCCESS) + return {}; + + desc_set.valid = true; + return desc_set; +} + +DescriptorBufferAllocation DescriptorSetAllocator::allocate_bindless_buffer(unsigned num_sets, unsigned num_descriptors) +{ + if (!bindless) + return {}; + + VkDeviceSize size = get_variable_offset() * num_sets + + device->managers.descriptor_buffer.get_descriptor_size_for_type(pool_size[0].type) * + num_descriptors; + + size += (std::max(num_sets, 1u) - 1u) * + std::max( + device->get_device_features().resource_heap_offset_alignment, + device->get_device_features().resource_heap_resource_desc_size); + + return device->managers.descriptor_buffer.allocate(size); +} + +VkDeviceSize DescriptorSetAllocator::get_variable_size(unsigned count) const +{ + return get_variable_offset() + + device->managers.descriptor_buffer.get_descriptor_size_for_type(pool_size[0].type) * + count; +} + +VkDescriptorPool DescriptorSetAllocator::allocate_bindless_pool(unsigned num_sets, unsigned num_descriptors) +{ + if (!bindless) + return VK_NULL_HANDLE; + + VkDescriptorPool pool = VK_NULL_HANDLE; + VkDescriptorPoolCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + info.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT; + info.maxSets = num_sets; + info.poolSizeCount = 1; + + VkDescriptorPoolSize size = pool_size[0]; + size.descriptorCount = num_descriptors; + info.pPoolSizes = &size; + + if (table.vkCreateDescriptorPool(device->get_device(), &info, nullptr, &pool) != VK_SUCCESS) + { + LOGE("Failed to create descriptor pool.\n"); + return VK_NULL_HANDLE; + } + + return pool; +} + +void DescriptorSetAllocator::begin_frame() +{ + if (!bindless) + { + // This can only be called in a situation where no command buffers are alive, + // so we don't need to consider any locks here. + if (device->per_frame.size() * device->num_thread_indices != per_thread_and_frame.size()) + per_thread_and_frame.resize(device->per_frame.size() * device->num_thread_indices); + + // It would be safe to set all offsets to 0 here, but that's a little wasteful. + for (uint32_t i = 0; i < device->num_thread_indices; i++) + per_thread_and_frame[i * device->per_frame.size() + device->frame_context_index].offset = 0; + } +} + +VkDescriptorSet DescriptorSetAllocator::request_descriptor_set(unsigned thread_index, unsigned frame_index) +{ + VK_ASSERT(!bindless); + + size_t flattened_index = thread_index * device->per_frame.size() + frame_index; + + auto &state = per_thread_and_frame[flattened_index]; + + unsigned pool_index = state.offset / VULKAN_NUM_SETS_PER_POOL; + unsigned pool_offset = state.offset % VULKAN_NUM_SETS_PER_POOL; + + if (pool_index >= state.pools.size()) + { + Pool *pool = state.object_pool.allocate(); + + VkDescriptorPoolCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + info.maxSets = VULKAN_NUM_SETS_PER_POOL; + if (!pool_size.empty()) + { + info.poolSizeCount = pool_size.size(); + info.pPoolSizes = pool_size.data(); + } + + bool overallocation = + device->get_device_features().descriptor_pool_overallocation_features.descriptorPoolOverallocation == + VK_TRUE; + + if (overallocation) + { + // No point in allocating new pools if we can keep using the existing one. + info.flags |= VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV | + VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV; + } + + bool need_alloc = !overallocation || state.pools.empty(); + + pool->pool = VK_NULL_HANDLE; + if (need_alloc && table.vkCreateDescriptorPool(device->get_device(), &info, nullptr, &pool->pool) != VK_SUCCESS) + { + LOGE("Failed to create descriptor pool.\n"); + state.object_pool.free(pool); + return VK_NULL_HANDLE; + } + + VkDescriptorSetLayout layouts[VULKAN_NUM_SETS_PER_POOL]; + std::fill(std::begin(layouts), std::end(layouts), set_layout_pool); + + VkDescriptorSetAllocateInfo alloc = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; + alloc.descriptorPool = pool->pool != VK_NULL_HANDLE ? pool->pool : state.pools.front()->pool; + alloc.descriptorSetCount = VULKAN_NUM_SETS_PER_POOL; + alloc.pSetLayouts = layouts; + + if (table.vkAllocateDescriptorSets(device->get_device(), &alloc, pool->sets) != VK_SUCCESS) + LOGE("Failed to allocate descriptor sets.\n"); + state.pools.push_back(pool); + } + + VkDescriptorSet vk_set = state.pools[pool_index]->sets[pool_offset]; + state.offset++; + return vk_set; +} + +void DescriptorSetAllocator::clear() +{ + for (auto &state : per_thread_and_frame) + { + for (auto *obj : state.pools) + { + table.vkDestroyDescriptorPool(device->get_device(), obj->pool, nullptr); + state.object_pool.free(obj); + } + state.pools.clear(); + state.offset = 0; + state.object_pool = {}; + } +} + +DescriptorSetAllocator::~DescriptorSetAllocator() +{ + table.vkDestroyDescriptorSetLayout(device->get_device(), set_layout_pool, nullptr); + table.vkDestroyDescriptorSetLayout(device->get_device(), set_layout_push, nullptr); + clear(); +} + +BindlessDescriptorPool::BindlessDescriptorPool(Device *device_, DescriptorSetAllocator *allocator_, + VkDescriptorPool pool, uint32_t num_sets, uint32_t num_desc) + : device(device_), allocator(allocator_), desc_pool(pool), total_sets(num_sets), total_descriptors(num_desc) +{ + if (!desc_pool) + bindless_buffer = allocator->allocate_bindless_buffer(num_sets, num_desc); +} + +BindlessDescriptorPool::~BindlessDescriptorPool() +{ + if (desc_pool) + { + if (internal_sync) + device->destroy_descriptor_pool_nolock(desc_pool); + else + device->destroy_descriptor_pool(desc_pool); + } + + if (bindless_buffer.get_size() != 0) + { + if (internal_sync) + device->free_descriptor_buffer_allocation_nolock(bindless_buffer); + else + device->free_descriptor_buffer_allocation(bindless_buffer); + } +} + +BindlessDescriptorSet BindlessDescriptorPool::get_descriptor_set() const +{ + return desc_set; +} + +void BindlessDescriptorPool::reset() +{ + if (desc_pool != VK_NULL_HANDLE) + allocator->reset_bindless_pool(desc_pool); + desc_set = {}; + allocated_descriptor_count = 0; + allocated_sets = 0; + bindless_buffer_offset = 0; +} + +bool BindlessDescriptorPool::allocate_descriptors(unsigned count) +{ + if (device->get_device_features().supports_descriptor_buffer_or_heap) + { + auto alignment = std::max( + device->get_device_features().resource_heap_offset_alignment, + device->get_device_features().resource_heap_resource_desc_size); + + bindless_buffer_offset = (bindless_buffer_offset + alignment - 1) & ~(alignment - 1); + VkDeviceSize size = allocator->get_variable_size(count); + + desc_set = {}; + if (bindless_buffer_offset + size <= bindless_buffer.get_size()) + { + desc_set.handle.offset = bindless_buffer_offset + bindless_buffer.get_offset(); + desc_set.valid = true; + bindless_buffer_offset += size; + + allocated_descriptor_count += count; + allocated_sets++; + } + + info_ptrs.reserve(count); + } + else + { + // Not all drivers will exhaust the pool for us, so make sure we don't allocate more than expected. + if (allocated_sets == total_sets) + return false; + if (allocated_descriptor_count + count > total_descriptors) + return false; + + allocated_descriptor_count += count; + allocated_sets++; + + desc_set = allocator->allocate_bindless_set(desc_pool, count); + infos.reserve(count); + } + + write_count = 0; + return bool(desc_set); +} + +void BindlessDescriptorPool::push_texture(const ImageView &view) +{ + // TODO: Deal with integer view for depth-stencil images? + if (!desc_pool) + push_texture(view.get_float_view().sampled.ptr); + else + push_texture(view.get_float_view().view, view.get_image().get_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL)); +} + +void BindlessDescriptorPool::push_texture_unorm(const ImageView &view) +{ + if (!desc_pool) + push_texture(view.get_unorm_view().sampled.ptr); + else + push_texture(view.get_unorm_view().view, view.get_image().get_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL)); +} + +void BindlessDescriptorPool::push_texture_srgb(const ImageView &view) +{ + if (!desc_pool) + push_texture(view.get_srgb_view().sampled.ptr); + else + push_texture(view.get_srgb_view().view, view.get_image().get_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL)); +} + +void BindlessDescriptorPool::push_texture(VkImageView view, VkImageLayout layout) +{ + VK_ASSERT(write_count < infos.get_capacity()); + auto &image_info = infos[write_count]; + image_info = { VK_NULL_HANDLE, view, layout }; + write_count++; +} + +void BindlessDescriptorPool::push_texture(const uint8_t *ptr) +{ + VK_ASSERT(write_count < info_ptrs.get_capacity()); + info_ptrs[write_count++] = ptr; +} + +void BindlessDescriptorPool::update() +{ + if (device->get_device_features().supports_descriptor_buffer_or_heap) + { + device->managers.descriptor_buffer.copy_sampled_image_n( + device->managers.descriptor_buffer.get_resource_heap().mapped + + desc_set.handle.offset + allocator->get_variable_offset(), + info_ptrs.data(), write_count); + } + else + { + VkWriteDescriptorSet desc = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + desc.descriptorCount = write_count; + desc.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + desc.dstSet = desc_set.handle.set; + + desc.pImageInfo = infos.data(); + desc.pBufferInfo = nullptr; + desc.pTexelBufferView = nullptr; + + if (write_count) + { + auto &table = device->get_device_table(); + table.vkUpdateDescriptorSets(device->get_device(), 1, &desc, 0, nullptr); + } + } +} + +void BindlessDescriptorPoolDeleter::operator()(BindlessDescriptorPool *pool) +{ + pool->device->handle_pool.bindless_descriptor_pool.free(pool); +} + +unsigned BindlessAllocator::push(const ImageView &view) +{ + auto ret = unsigned(views.size()); + views.push_back(&view); + if (views.size() > VULKAN_NUM_BINDINGS_BINDLESS_VARYING) + { + LOGE("Exceeding maximum number of bindless resources per set (%u >= %u).\n", + unsigned(views.size()), VULKAN_NUM_BINDINGS_BINDLESS_VARYING); + } + return ret; +} + +void BindlessAllocator::begin() +{ + views.clear(); +} + +void BindlessAllocator::reset() +{ + descriptor_pool.reset(); +} + +unsigned BindlessAllocator::get_next_offset() const +{ + return unsigned(views.size()); +} + +void BindlessAllocator::reserve_max_resources_per_pool(unsigned set_count, unsigned descriptor_count) +{ + max_sets_per_pool = std::max(max_sets_per_pool, set_count); + max_descriptors_per_pool = std::max(max_descriptors_per_pool, descriptor_count); + views.reserve(max_descriptors_per_pool); +} + +void BindlessAllocator::set_bindless_resource_type(BindlessResourceType type) +{ + resource_type = type; +} + +BindlessDescriptorSet BindlessAllocator::commit(Device &device) +{ + max_sets_per_pool = std::max(1u, max_sets_per_pool); + max_descriptors_per_pool = std::max(views.size(), max_descriptors_per_pool); + max_descriptors_per_pool = std::max(1u, max_descriptors_per_pool); + max_descriptors_per_pool = std::min(max_descriptors_per_pool, VULKAN_NUM_BINDINGS_BINDLESS_VARYING); + unsigned to_allocate = std::max(views.size(), 1u); + + if (!descriptor_pool) + { + descriptor_pool = device.create_bindless_descriptor_pool( + resource_type, max_sets_per_pool, max_descriptors_per_pool); + } + + if (!descriptor_pool->allocate_descriptors(to_allocate)) + { + descriptor_pool = device.create_bindless_descriptor_pool( + resource_type, max_sets_per_pool, max_descriptors_per_pool); + + if (!descriptor_pool->allocate_descriptors(to_allocate)) + { + LOGE("Failed to allocate descriptors on a fresh descriptor pool!\n"); + return {}; + } + } + + for (size_t i = 0, n = views.size(); i < n; i++) + descriptor_pool->push_texture(*views[i]); + descriptor_pool->update(); + + return descriptor_pool->get_descriptor_set(); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/descriptor_set.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/descriptor_set.hpp new file mode 100644 index 00000000..2d7e6f9f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/descriptor_set.hpp @@ -0,0 +1,243 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "hash.hpp" +#include "object_pool.hpp" +#include "temporary_hashmap.hpp" +#include "vulkan_headers.hpp" +#include "sampler.hpp" +#include "limits.hpp" +#include "dynamic_array.hpp" +#include +#include +#include "cookie.hpp" +#include "memory_allocator.hpp" + +namespace Vulkan +{ +class Device; +struct ArraySizeAccessMeta +{ + uint8_t array_size : 7; + uint8_t requires_descriptor_size : 1; +}; +static_assert(sizeof(ArraySizeAccessMeta) == sizeof(uint8_t), "Unexpected bitfield padding."); + +struct DescriptorSetLayout +{ + uint32_t sampled_image_mask = 0; + uint32_t storage_image_mask = 0; + uint32_t uniform_buffer_mask = 0; + uint32_t storage_buffer_mask = 0; + uint32_t rtas_mask = 0; + uint32_t sampled_texel_buffer_mask = 0; + uint32_t storage_texel_buffer_mask = 0; + uint32_t input_attachment_mask = 0; + uint32_t sampler_mask = 0; + uint32_t separate_image_mask = 0; + uint32_t fp_mask = 0; + uint32_t immutable_sampler_mask = 0; + ArraySizeAccessMeta meta[VULKAN_NUM_BINDINGS] = {}; + enum { UNSIZED_ARRAY = 0x7f }; +}; + +// Avoid -Wclass-memaccess warnings since we hash DescriptorSetLayout. + +static const unsigned VULKAN_NUM_SETS_PER_POOL = 64; +static const unsigned VULKAN_DESCRIPTOR_RING_SIZE = 16; + +class DescriptorSetAllocator; +class BindlessDescriptorPool; +class ImageView; + +struct BindlessDescriptorPoolDeleter +{ + void operator()(BindlessDescriptorPool *pool); +}; + +struct BindlessDescriptorSet +{ + union Handle + { + VkDescriptorSet set; + VkDeviceSize offset; + } handle = {}; + bool valid = false; + explicit operator bool() const { return valid; } +}; + +class BindlessDescriptorPool : public Util::IntrusivePtrEnabled, + public InternalSyncEnabled +{ +public: + friend struct BindlessDescriptorPoolDeleter; + explicit BindlessDescriptorPool(Device *device, DescriptorSetAllocator *allocator, VkDescriptorPool pool, + uint32_t total_sets, uint32_t total_descriptors); + ~BindlessDescriptorPool(); + void operator=(const BindlessDescriptorPool &) = delete; + BindlessDescriptorPool(const BindlessDescriptorPool &) = delete; + + void reset(); + bool allocate_descriptors(unsigned count); + BindlessDescriptorSet get_descriptor_set() const; + + void push_texture(const ImageView &view); + void push_texture_unorm(const ImageView &view); + void push_texture_srgb(const ImageView &view); + void update(); + +private: + Device *device; + DescriptorSetAllocator *allocator; + + VkDescriptorPool desc_pool; + DescriptorBufferAllocation bindless_buffer; + VkDeviceSize bindless_buffer_offset = 0; + + BindlessDescriptorSet desc_set; + + uint32_t allocated_sets = 0; + uint32_t total_sets = 0; + uint32_t allocated_descriptor_count = 0; + uint32_t total_descriptors = 0; + + void push_texture(VkImageView view, VkImageLayout layout); + void push_texture(const uint8_t *ptr); + Util::DynamicArray infos; + Util::DynamicArray info_ptrs; + uint32_t write_count = 0; +}; +using BindlessDescriptorPoolHandle = Util::IntrusivePtr; + +enum class BindlessResourceType +{ + Image +}; + +class DescriptorSetAllocator : public HashedObject +{ +public: + DescriptorSetAllocator(Util::Hash hash, Device *device, const DescriptorSetLayout &layout, + const uint32_t *stages_for_bindings, + const ImmutableSampler * const *immutable_samplers); + ~DescriptorSetAllocator(); + void operator=(const DescriptorSetAllocator &) = delete; + DescriptorSetAllocator(const DescriptorSetAllocator &) = delete; + + void begin_frame(); + VkDescriptorSet request_descriptor_set(unsigned thread_index, unsigned frame_context); + + VkDescriptorSetLayout get_layout_for_pool() const + { + return set_layout_pool; + } + + VkDescriptorSetLayout get_layout_for_push() const + { + return set_layout_push; + } + + void clear(); + + bool is_bindless() const + { + return bindless; + } + + // Legacy descriptors. + VkDescriptorPool allocate_bindless_pool(unsigned num_sets, unsigned num_descriptors); + BindlessDescriptorSet allocate_bindless_set(VkDescriptorPool pool, unsigned num_descriptors); + void reset_bindless_pool(VkDescriptorPool pool); + + // Descriptor buffer integration. + DescriptorBufferAllocation allocate_bindless_buffer(unsigned num_sets, unsigned num_descriptors); + + VkDeviceSize get_resource_heap_size() const + { + return desc_set_size; + } + + VkDeviceSize get_variable_offset() const + { + return desc_set_variable_offset; + } + + VkDeviceSize get_variable_size(unsigned count) const; + + uint32_t get_binding_offset(uint32_t binding) const + { + return desc_offsets[binding]; + } + +private: + Device *device; + const VolkDeviceTable &table; + VkDescriptorSetLayout set_layout_pool = VK_NULL_HANDLE; + VkDescriptorSetLayout set_layout_push = VK_NULL_HANDLE; + + VkDeviceSize desc_set_size = 0; + VkDeviceSize desc_set_variable_offset = 0; + uint32_t desc_offsets[VULKAN_NUM_BINDINGS] = {}; + + struct Pool + { + VkDescriptorPool pool; + VkDescriptorSet sets[VULKAN_NUM_SETS_PER_POOL]; + }; + + struct PerThreadAndFrame + { + std::vector pools; + Util::ObjectPool object_pool; + uint32_t offset = 0; + }; + + std::vector per_thread_and_frame; + std::vector pool_size; + bool bindless = false; +}; + +class BindlessAllocator +{ +public: + void reserve_max_resources_per_pool(unsigned set_count, unsigned descriptor_count); + void set_bindless_resource_type(BindlessResourceType type); + + void begin(); + unsigned push(const ImageView &view); + + BindlessDescriptorSet commit(Device &device); + + unsigned get_next_offset() const; + + void reset(); + +private: + BindlessDescriptorPoolHandle descriptor_pool; + unsigned max_sets_per_pool = 0; + unsigned max_descriptors_per_pool = 0; + BindlessResourceType resource_type = BindlessResourceType::Image; + std::vector views; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device.cpp new file mode 100644 index 00000000..8b5bdb64 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device.cpp @@ -0,0 +1,5925 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "device.hpp" +#ifdef GRANITE_VULKAN_FOSSILIZE +#include "device_fossilize.hpp" +#endif +#include "format.hpp" +#include "timeline_trace_file.hpp" +#include "type_to_string.hpp" +#include "quirks.hpp" +#include "timer.hpp" +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES +#include "string_helpers.hpp" +#endif + +#include "thread_id.hpp" +static unsigned get_thread_index() +{ + return Util::get_current_thread_index(); +} +#define LOCK() std::lock_guard _holder_##__COUNTER__{lock.lock} +#define LOCK_MEMORY() std::lock_guard _holder_##__COUNTER__{lock.memory_lock} +#define LOCK_CACHE() ::Util::RWSpinLockReadHolder _holder_##__COUNTER__{lock.read_only_cache} +#define DRAIN_FRAME_LOCK() \ + std::unique_lock _holder{lock.lock}; \ + lock.cond.wait(_holder, [&]() { \ + return lock.counter == 0; \ + }) + +using namespace Util; + +namespace Vulkan +{ +static constexpr VkImageUsageFlags image_usage_video_flags = + VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR; + +static const QueueIndices queue_flush_order[] = { + QUEUE_INDEX_TRANSFER, + QUEUE_INDEX_VIDEO_DECODE, + QUEUE_INDEX_VIDEO_ENCODE, + QUEUE_INDEX_GRAPHICS, + QUEUE_INDEX_COMPUTE, +}; + +Device::Device() + : framebuffer_allocator(this) + , transient_allocator(this) + , pipeline_binary_cache(this) +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + , shader_manager(this) + , resource_manager(this) +#endif +{ + cookie.store(0); +} + +Semaphore Device::request_semaphore(VkSemaphoreType type, VkSemaphore vk_semaphore, bool transfer_ownership) +{ + if (type == VK_SEMAPHORE_TYPE_TIMELINE && !ext.vk12_features.timelineSemaphore) + { + LOGE("Timeline semaphores not supported.\n"); + return Semaphore{}; + } + + if (vk_semaphore == VK_NULL_HANDLE) + { + if (type == VK_SEMAPHORE_TYPE_BINARY) + { + LOCK(); + vk_semaphore = managers.semaphore.request_cleared_semaphore(); + } + else + { + VkSemaphoreTypeCreateInfo type_info = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO }; + VkSemaphoreCreateInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; + info.pNext = &type_info; + type_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; + type_info.initialValue = 0; + if (table->vkCreateSemaphore(device, &info, nullptr, &vk_semaphore) != VK_SUCCESS) + { + LOGE("Failed to create semaphore.\n"); + return Semaphore{}; + } + } + transfer_ownership = true; + } + + if (type == VK_SEMAPHORE_TYPE_BINARY) + { + Semaphore ptr(handle_pool.semaphores.allocate(this, vk_semaphore, false, transfer_ownership)); + return ptr; + } + else + { + Semaphore ptr(handle_pool.semaphores.allocate(this, 0, vk_semaphore, transfer_ownership)); + ptr->set_proxy_timeline(); + return ptr; + } +} + +Semaphore Device::request_timeline_semaphore_as_binary(const SemaphoreHolder &holder, uint64_t value) +{ + VK_ASSERT(holder.get_semaphore_type() == VK_SEMAPHORE_TYPE_TIMELINE); + VK_ASSERT(holder.is_proxy_timeline()); + Semaphore ptr(handle_pool.semaphores.allocate(this, value, holder.get_semaphore(), false)); + return ptr; +} + +Semaphore Device::request_semaphore_external(VkSemaphoreType type, + VkExternalSemaphoreHandleTypeFlagBits handle_type) +{ + if (type == VK_SEMAPHORE_TYPE_TIMELINE && !ext.vk12_features.timelineSemaphore) + { + LOGE("Timeline semaphores not supported.\n"); + return Semaphore{}; + } + + if (!ext.supports_external) + { + LOGE("External semaphores not supported.\n"); + return Semaphore{}; + } + + VkSemaphoreTypeCreateInfo type_info = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO }; + type_info.semaphoreType = type; + VkExternalSemaphoreFeatureFlags features; + + { + VkExternalSemaphoreProperties props = { VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES }; + VkPhysicalDeviceExternalSemaphoreInfo info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO }; + info.handleType = handle_type; + + // Workaround AMD Windows bug where it reports TIMELINE as not supported. + // D3D12_FENCE used to be BINARY type before timelines were introduced to Vulkan. + if (type != VK_SEMAPHORE_TYPE_BINARY && handle_type != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT) + info.pNext = &type_info; + vkGetPhysicalDeviceExternalSemaphoreProperties(gpu, &info, &props); + + features = props.externalSemaphoreFeatures; + + if (!features) + { + LOGE("External semaphore handle type #%x is not supported.\n", handle_type); + return Semaphore{}; + } + } + + VkSemaphoreCreateInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; + VkExportSemaphoreCreateInfo export_info = { VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO }; + + if ((features & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) != 0) + { + export_info.handleTypes = handle_type; + export_info.pNext = info.pNext; + info.pNext = &export_info; + } + + if (type != VK_SEMAPHORE_TYPE_BINARY) + { + type_info.pNext = info.pNext; + info.pNext = &type_info; + } + + VkSemaphore semaphore; + if (table->vkCreateSemaphore(device, &info, nullptr, &semaphore) != VK_SUCCESS) + { + LOGE("Failed to create external semaphore.\n"); + return Semaphore{}; + } + + if (type == VK_SEMAPHORE_TYPE_TIMELINE) + { + Semaphore ptr(handle_pool.semaphores.allocate(this, 0, semaphore, true)); + ptr->set_external_object_compatible(handle_type, features); + ptr->set_proxy_timeline(); + return ptr; + } + else + { + Semaphore ptr(handle_pool.semaphores.allocate(this, semaphore, false, true)); + ptr->set_external_object_compatible(handle_type, features); + return ptr; + } +} + +Semaphore Device::request_proxy_semaphore() +{ + Semaphore ptr(handle_pool.semaphores.allocate(this)); + return ptr; +} + +void Device::add_wait_semaphore(CommandBuffer::Type type, Semaphore semaphore, VkPipelineStageFlags2 stages, bool flush) +{ + VK_ASSERT(!semaphore->is_proxy_timeline()); + + LOCK(); + add_wait_semaphore_nolock(get_physical_queue_type(type), std::move(semaphore), stages, flush); +} + +void Device::add_wait_semaphore_nolock(QueueIndices physical_type, Semaphore semaphore, + VkPipelineStageFlags2 stages, bool flush) +{ + if (flush) + flush_frame_nolock(physical_type); + auto &data = queue_data[physical_type]; + +#ifdef VULKAN_DEBUG + for (auto &sem : data.wait_semaphores) + VK_ASSERT(sem.get() != semaphore.get()); +#endif + + semaphore->set_pending_wait(); + data.wait_semaphores.push_back(semaphore); + data.wait_stages.push_back(stages); + data.need_fence = true; + + // Sanity check. + VK_ASSERT(data.wait_semaphores.size() < 16 * 1024); +} + +LinearHostImageHandle Device::create_linear_host_image(const LinearHostImageCreateInfo &info) +{ + if ((info.usage & ~VK_IMAGE_USAGE_SAMPLED_BIT) != 0) + return LinearHostImageHandle(nullptr); + + ImageCreateInfo create_info; + create_info.width = info.width; + create_info.height = info.height; + create_info.domain = + (info.flags & LINEAR_HOST_IMAGE_HOST_CACHED_BIT) != 0 ? + ImageDomain::LinearHostCached : + ImageDomain::LinearHost; + create_info.levels = 1; + create_info.layers = 1; + create_info.initial_layout = VK_IMAGE_LAYOUT_GENERAL; + create_info.format = info.format; + create_info.samples = VK_SAMPLE_COUNT_1_BIT; + create_info.usage = info.usage; + create_info.type = VK_IMAGE_TYPE_2D; + create_info.layout = ImageLayout::General; + + if ((info.flags & LINEAR_HOST_IMAGE_REQUIRE_LINEAR_FILTER_BIT) != 0) + create_info.misc |= IMAGE_MISC_VERIFY_FORMAT_FEATURE_SAMPLED_LINEAR_FILTER_BIT; + if ((info.flags & LINEAR_HOST_IMAGE_IGNORE_DEVICE_LOCAL_BIT) != 0) + create_info.misc |= IMAGE_MISC_LINEAR_IMAGE_IGNORE_DEVICE_LOCAL_BIT; + + BufferHandle cpu_image; + auto gpu_image = create_image(create_info); + if (!gpu_image) + { + // Fall-back to staging buffer. + create_info.domain = ImageDomain::Physical; + create_info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + create_info.misc = IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT | IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT; + create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + gpu_image = create_image(create_info); + if (!gpu_image) + return LinearHostImageHandle(nullptr); + + BufferCreateInfo buffer; + buffer.domain = + (info.flags & LINEAR_HOST_IMAGE_HOST_CACHED_BIT) != 0 ? + BufferDomain::CachedHost : + BufferDomain::Host; + buffer.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer.size = info.width * info.height * TextureFormatLayout::format_block_size(info.format, format_to_aspect_mask(info.format)); + cpu_image = create_buffer(buffer); + if (!cpu_image) + return LinearHostImageHandle(nullptr); + } + + return LinearHostImageHandle(handle_pool.linear_images.allocate(this, std::move(gpu_image), std::move(cpu_image), info.stages)); +} + +void *Device::map_linear_host_image(const LinearHostImage &image, MemoryAccessFlags access) +{ + void *host = managers.memory.map_memory(image.get_host_visible_allocation(), access, + 0, image.get_host_visible_allocation().get_size()); + return host; +} + +void Device::unmap_linear_host_image_and_sync(const LinearHostImage &image, MemoryAccessFlags access) +{ + managers.memory.unmap_memory(image.get_host_visible_allocation(), access, + 0, image.get_host_visible_allocation().get_size()); + if (image.need_staging_copy()) + { + // Kinda icky fallback, shouldn't really be used on discrete cards. + auto cmd = request_command_buffer(CommandBuffer::Type::AsyncTransfer); + cmd->image_barrier(image.get_image(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_NONE, 0, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT); + cmd->copy_buffer_to_image(image.get_image(), image.get_host_visible_buffer(), + 0, {}, + { image.get_image().get_width(), image.get_image().get_height(), 1 }, + 0, 0, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }); + + // Don't care about dstAccessMask, semaphore takes care of everything. + cmd->image_barrier(image.get_image(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_NONE, 0); + + Semaphore sem; + submit(cmd, nullptr, 1, &sem); + + // The queue type is an assumption. Should add some parameter for that. + add_wait_semaphore(CommandBuffer::Type::Generic, sem, image.get_used_pipeline_stages(), true); + } +} + +void *Device::map_host_buffer(const Buffer &buffer, MemoryAccessFlags access) +{ + void *host = managers.memory.map_memory(buffer.get_allocation(), access, 0, buffer.get_create_info().size); + return host; +} + +void Device::unmap_host_buffer(const Buffer &buffer, MemoryAccessFlags access) +{ + managers.memory.unmap_memory(buffer.get_allocation(), access, 0, buffer.get_create_info().size); +} + +void *Device::map_host_buffer(const Buffer &buffer, MemoryAccessFlags access, VkDeviceSize offset, VkDeviceSize length) +{ + VK_ASSERT(offset + length <= buffer.get_create_info().size); + void *host = managers.memory.map_memory(buffer.get_allocation(), access, offset, length); + return host; +} + +void Device::unmap_host_buffer(const Buffer &buffer, MemoryAccessFlags access, VkDeviceSize offset, VkDeviceSize length) +{ + VK_ASSERT(offset + length <= buffer.get_create_info().size); + managers.memory.unmap_memory(buffer.get_allocation(), access, offset, length); +} + +Shader *Device::request_shader(const uint32_t *data, size_t size, const ResourceLayout *layout) +{ + auto hash = Shader::hash(data, size); + LOCK_CACHE(); + auto *ret = shaders.find(hash); + if (!ret) + ret = shaders.emplace_yield(hash, hash, this, data, size, layout); + return ret; +} + +Shader *Device::request_shader_by_hash(Hash hash) +{ + LOCK_CACHE(); + return shaders.find(hash); +} + +Program *Device::request_program(Vulkan::Shader *compute_shader, const ImmutableSamplerBank *sampler_bank) +{ + if (!compute_shader) + return nullptr; + + Util::Hasher hasher; + hasher.u64(compute_shader->get_hash()); + ImmutableSamplerBank::hash(hasher, sampler_bank); + + LOCK_CACHE(); + auto hash = hasher.get(); + auto *ret = programs.find(hash); + if (!ret) + ret = programs.emplace_yield(hash, this, compute_shader, sampler_bank); + return ret; +} + +Program *Device::request_program(const uint32_t *compute_data, size_t compute_size, const ResourceLayout *layout) +{ + if (!compute_size) + return nullptr; + + auto *compute_shader = request_shader(compute_data, compute_size, layout); + return request_program(compute_shader); +} + +Program *Device::request_program(Shader *vertex, Shader *fragment, const ImmutableSamplerBank *sampler_bank) +{ + if (!vertex || !fragment) + return nullptr; + + Util::Hasher hasher; + hasher.u64(vertex->get_hash()); + hasher.u64(fragment->get_hash()); + ImmutableSamplerBank::hash(hasher, sampler_bank); + + auto hash = hasher.get(); + LOCK_CACHE(); + auto *ret = programs.find(hash); + + if (!ret) + ret = programs.emplace_yield(hash, this, vertex, fragment, sampler_bank); + return ret; +} + +Program *Device::request_program(Shader *task, Shader *mesh, Shader *fragment, const ImmutableSamplerBank *sampler_bank) +{ + if (!mesh || !fragment) + return nullptr; + + if (!get_device_features().mesh_shader_features.meshShader) + { + LOGE("meshShader not supported.\n"); + return nullptr; + } + + if (task && !get_device_features().mesh_shader_features.taskShader) + { + LOGE("taskShader not supported.\n"); + return nullptr; + } + + Util::Hasher hasher; + hasher.u64(task ? task->get_hash() : 0); + hasher.u64(mesh->get_hash()); + hasher.u64(fragment->get_hash()); + ImmutableSamplerBank::hash(hasher, sampler_bank); + + auto hash = hasher.get(); + LOCK_CACHE(); + auto *ret = programs.find(hash); + + if (!ret) + ret = programs.emplace_yield(hash, this, task, mesh, fragment, sampler_bank); + return ret; +} + +Program *Device::request_program(const uint32_t *vertex_data, size_t vertex_size, + const uint32_t *fragment_data, size_t fragment_size, + const ResourceLayout *vertex_layout, + const ResourceLayout *fragment_layout) +{ + if (!vertex_size || !fragment_size) + return nullptr; + + auto *vertex = request_shader(vertex_data, vertex_size, vertex_layout); + auto *fragment = request_shader(fragment_data, fragment_size, fragment_layout); + return request_program(vertex, fragment); +} + +Program *Device::request_program(const uint32_t *task_data, size_t task_size, + const uint32_t *mesh_data, size_t mesh_size, + const uint32_t *fragment_data, size_t fragment_size, + const ResourceLayout *task_layout, + const ResourceLayout *mesh_layout, + const ResourceLayout *fragment_layout) +{ + if (!mesh_size || !fragment_size) + return nullptr; + + Shader *task = nullptr; + if (task_size) + task = request_shader(task_data, task_size, task_layout); + auto *mesh = request_shader(mesh_data, mesh_size, mesh_layout); + auto *fragment = request_shader(fragment_data, fragment_size, fragment_layout); + return request_program(task, mesh, fragment); +} + +const PipelineLayout *Device::request_pipeline_layout(const CombinedResourceLayout &layout, + const ImmutableSamplerBank *sampler_bank) +{ + Hasher h; + h.data(reinterpret_cast(layout.sets), sizeof(layout.sets)); + h.data(&layout.stages_for_bindings[0][0], sizeof(layout.stages_for_bindings)); + h.u32(layout.push_constant_range.stageFlags); + h.u32(layout.push_constant_range.size); + h.data(layout.spec_constant_mask, sizeof(layout.spec_constant_mask)); + h.u32(layout.attribute_mask); + h.u32(layout.render_target_mask); + for (unsigned set = 0; set < VULKAN_NUM_DESCRIPTOR_SETS; set++) + { + Util::for_each_bit(layout.sets[set].immutable_sampler_mask, [&](unsigned bit) { + VK_ASSERT(sampler_bank && sampler_bank->samplers[set][bit]); + h.u64(sampler_bank->samplers[set][bit]->get_hash()); + }); + } + + auto hash = h.get(); + auto *ret = pipeline_layouts.find(hash); + if (!ret) + ret = pipeline_layouts.emplace_yield(hash, hash, this, layout, sampler_bank); + return ret; +} + +DescriptorSetAllocator *Device::request_descriptor_set_allocator(const DescriptorSetLayout &layout, const uint32_t *stages_for_bindings, + const ImmutableSampler * const *immutable_samplers_) +{ + Hasher h; + h.data(reinterpret_cast(&layout), sizeof(layout)); + h.data(stages_for_bindings, sizeof(uint32_t) * VULKAN_NUM_BINDINGS); + Util::for_each_bit(layout.immutable_sampler_mask, [&](unsigned bit) { + VK_ASSERT(immutable_samplers_ && immutable_samplers_[bit]); + h.u64(immutable_samplers_[bit]->get_hash()); + }); + auto hash = h.get(); + + LOCK_CACHE(); + auto *ret = descriptor_set_allocators.find(hash); + if (!ret) + ret = descriptor_set_allocators.emplace_yield(hash, hash, this, layout, stages_for_bindings, immutable_samplers_); + return ret; +} + +const IndirectLayout *Device::request_indirect_layout( + const PipelineLayout *layout, const Vulkan::IndirectLayoutToken *tokens, + uint32_t num_tokens, uint32_t stride) +{ + Hasher h; + + h.u64(layout ? layout->get_hash() : 0); + + for (uint32_t i = 0; i < num_tokens; i++) + h.u32(Util::ecast(tokens[i].type)); + + for (uint32_t i = 0; i < num_tokens; i++) + { + if (tokens[i].type != IndirectLayoutToken::Type::SequenceCount) + h.u32(tokens[i].offset); + + if (tokens[i].type == IndirectLayoutToken::Type::PushConstant || + tokens[i].type == IndirectLayoutToken::Type::SequenceCount) + { + h.u32(tokens[i].data.push.offset); + h.u32(tokens[i].data.push.range); + } + else if (tokens[i].type == IndirectLayoutToken::Type::VBO) + { + h.u32(tokens[i].data.vbo.binding); + } + } + + h.u32(stride); + auto hash = h.get(); + + LOCK_CACHE(); + auto *ret = indirect_layouts.find(hash); + if (!ret) + ret = indirect_layouts.emplace_yield(hash, this, layout, tokens, num_tokens, stride); + return ret; +} + +void Device::merge_combined_resource_layout(CombinedResourceLayout &layout, const Program &program) +{ + if (program.get_shader(ShaderStage::Vertex)) + layout.attribute_mask |= program.get_shader(ShaderStage::Vertex)->get_layout().input_mask; + if (program.get_shader(ShaderStage::Fragment)) + layout.render_target_mask |= program.get_shader(ShaderStage::Fragment)->get_layout().output_mask; + + for (unsigned i = 0; i < static_cast(ShaderStage::Count); i++) + { + auto *shader = program.get_shader(static_cast(i)); + if (!shader) + continue; + + uint32_t stage_mask = 1u << i; + + auto &shader_layout = shader->get_layout(); + + for (unsigned set = 0; set < VULKAN_NUM_DESCRIPTOR_SETS; set++) + { + layout.sets[set].sampled_image_mask |= shader_layout.sets[set].sampled_image_mask; + layout.sets[set].storage_image_mask |= shader_layout.sets[set].storage_image_mask; + layout.sets[set].uniform_buffer_mask |= shader_layout.sets[set].uniform_buffer_mask; + layout.sets[set].storage_buffer_mask |= shader_layout.sets[set].storage_buffer_mask; + layout.sets[set].rtas_mask |= shader_layout.sets[set].rtas_mask; + layout.sets[set].sampled_texel_buffer_mask |= shader_layout.sets[set].sampled_texel_buffer_mask; + layout.sets[set].storage_texel_buffer_mask |= shader_layout.sets[set].storage_texel_buffer_mask; + layout.sets[set].input_attachment_mask |= shader_layout.sets[set].input_attachment_mask; + layout.sets[set].sampler_mask |= shader_layout.sets[set].sampler_mask; + layout.sets[set].separate_image_mask |= shader_layout.sets[set].separate_image_mask; + layout.sets[set].fp_mask |= shader_layout.sets[set].fp_mask; + + uint32_t active_binds = + shader_layout.sets[set].sampled_image_mask | + shader_layout.sets[set].storage_image_mask | + shader_layout.sets[set].uniform_buffer_mask| + shader_layout.sets[set].storage_buffer_mask | + shader_layout.sets[set].rtas_mask | + shader_layout.sets[set].sampled_texel_buffer_mask | + shader_layout.sets[set].storage_texel_buffer_mask | + shader_layout.sets[set].input_attachment_mask | + shader_layout.sets[set].sampler_mask | + shader_layout.sets[set].separate_image_mask; + + if (active_binds) + layout.stages_for_sets[set] |= stage_mask; + + for_each_bit(active_binds, [&](uint32_t bit) { + layout.stages_for_bindings[set][bit] |= stage_mask; + + auto &combined_meta = layout.sets[set].meta[bit]; + auto &shader_meta = shader_layout.sets[set].meta[bit]; + if (combined_meta.array_size && combined_meta.array_size != shader_meta.array_size) + LOGE("Mismatch between array sizes in different shaders.\n"); + else + combined_meta.array_size = shader_meta.array_size; + + combined_meta.requires_descriptor_size |= shader_meta.requires_descriptor_size; + }); + } + + // Merge push constant ranges into one range. + // Do not try to split into multiple ranges as it just complicates things for no obvious gain. + if (shader_layout.push_constant_size != 0) + { + layout.push_constant_range.stageFlags |= 1u << i; + layout.push_constant_range.size = + std::max(layout.push_constant_range.size, shader_layout.push_constant_size); + } + + layout.spec_constant_mask[i] = shader_layout.spec_constant_mask; + layout.combined_spec_constant_mask |= shader_layout.spec_constant_mask; + layout.bindless_descriptor_set_mask |= shader_layout.bindless_set_mask; + } + + for (unsigned set = 0; set < VULKAN_NUM_DESCRIPTOR_SETS; set++) + { + if (layout.stages_for_sets[set] == 0) + continue; + + layout.descriptor_set_mask |= 1u << set; + + for (unsigned binding = 0; binding < VULKAN_NUM_BINDINGS; binding++) + { + auto &meta = layout.sets[set].meta[binding]; + if (meta.array_size == DescriptorSetLayout::UNSIZED_ARRAY) + { + for (unsigned i = 1; i < VULKAN_NUM_BINDINGS; i++) + { + if (layout.stages_for_bindings[set][i] != 0) + LOGE("Using bindless for set = %u, but binding = %u has a descriptor attached to it.\n", set, i); + } + + // Allows us to have one unified descriptor set layout for bindless. + layout.stages_for_bindings[set][binding] = VK_SHADER_STAGE_ALL; + } + else if (meta.array_size == 0) + { + meta.array_size = 1; + } + else + { + for (unsigned i = 1; i < meta.array_size; i++) + { + if (layout.stages_for_bindings[set][binding + i] != 0) + { + LOGE("Detected binding aliasing for (%u, %u). Binding array with %u elements starting at (%u, %u) overlaps.\n", + set, binding + i, meta.array_size, set, binding); + } + } + } + } + } + + Hasher h; + h.u32(layout.push_constant_range.stageFlags); + h.u32(layout.push_constant_range.size); + layout.push_constant_layout_hash = h.get(); +} + +void Device::bake_program(Program &program, const ImmutableSamplerBank *sampler_bank) +{ + CombinedResourceLayout layout; + ImmutableSamplerBank ext_immutable_samplers = {}; + + merge_combined_resource_layout(layout, program); + + if (sampler_bank) + { + for (unsigned set = 0; set < VULKAN_NUM_DESCRIPTOR_SETS; set++) + { + for_each_bit(layout.sets[set].sampler_mask | layout.sets[set].sampled_image_mask, [&](uint32_t binding) + { + if (sampler_bank->samplers[set][binding]) + { + ext_immutable_samplers.samplers[set][binding] = sampler_bank->samplers[set][binding]; + layout.sets[set].immutable_sampler_mask |= 1u << binding; + } + }); + } + } + + program.set_pipeline_layout(request_pipeline_layout(layout, &ext_immutable_samplers)); +} + +bool Device::init_pipeline_cache(const uint8_t *data, size_t size, bool persistent_mapping) +{ + if (ext.pipeline_binary_features.pipelineBinaries) + return pipeline_binary_cache.init_from_payload(data, size, persistent_mapping); + + static const auto uuid_size = sizeof(gpu_props.pipelineCacheUUID); + static const auto hash_size = sizeof(Util::Hash); + + VkPipelineCacheCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; + if (!data || size < uuid_size + hash_size) + { + LOGI("Creating a fresh pipeline cache.\n"); + } + else if (memcmp(data, gpu_props.pipelineCacheUUID, uuid_size) != 0) + { + LOGI("Pipeline cache UUID changed.\n"); + } + else + { + Util::Hash reference_hash; + memcpy(&reference_hash, data + uuid_size, sizeof(reference_hash)); + + info.initialDataSize = size - uuid_size - hash_size; + data += uuid_size + hash_size; + info.pInitialData = data; + + Util::Hasher h; + h.data(data, info.initialDataSize); + + if (h.get() == reference_hash) + LOGI("Initializing pipeline cache.\n"); + else + { + LOGW("Pipeline cache is corrupt, creating a fresh cache.\n"); + info.pInitialData = nullptr; + info.initialDataSize = 0; + } + } + + if (legacy_pipeline_cache != VK_NULL_HANDLE) + table->vkDestroyPipelineCache(device, legacy_pipeline_cache, nullptr); + legacy_pipeline_cache = VK_NULL_HANDLE; + return table->vkCreatePipelineCache(device, &info, nullptr, &legacy_pipeline_cache) == VK_SUCCESS; +} + +void Device::init_pipeline_cache() +{ +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + if (!system_handles.filesystem) + return; + auto file = system_handles.filesystem->open_readonly_mapping("cache://pipeline_cache.bin"); + if (file) + { + if (ext.pipeline_binary_features.pipelineBinaries) + persistent_pipeline_cache = file; + + auto size = file->get_size(); + auto *mapped = file->data(); + if (mapped && !init_pipeline_cache(mapped, size, bool(persistent_pipeline_cache))) + { + LOGE("Failed to initialize pipeline cache.\n"); + persistent_pipeline_cache.reset(); + } + } + else if (!init_pipeline_cache(nullptr, 0)) + LOGE("Failed to initialize pipeline cache.\n"); +#endif +} + +size_t Device::get_pipeline_cache_size() +{ + if (legacy_pipeline_cache == VK_NULL_HANDLE) + return pipeline_binary_cache.get_serialized_size(); + + static const auto uuid_size = sizeof(gpu_props.pipelineCacheUUID); + static const auto hash_size = sizeof(Util::Hash); + size_t size = 0; + if (table->vkGetPipelineCacheData(device, legacy_pipeline_cache, &size, nullptr) != VK_SUCCESS) + { + LOGE("Failed to get pipeline cache data.\n"); + return 0; + } + + return size + uuid_size + hash_size; +} + +bool Device::get_pipeline_cache_data(uint8_t *data, size_t size) +{ + if (legacy_pipeline_cache == VK_NULL_HANDLE) + return pipeline_binary_cache.serialize(data, size); + + static const auto uuid_size = sizeof(gpu_props.pipelineCacheUUID); + static const auto hash_size = sizeof(Util::Hash); + if (size < uuid_size + hash_size) + return false; + + auto *hash_data = data + uuid_size; + + size -= uuid_size + hash_size; + memcpy(data, gpu_props.pipelineCacheUUID, uuid_size); + data = hash_data + hash_size; + + if (table->vkGetPipelineCacheData(device, legacy_pipeline_cache, &size, data) != VK_SUCCESS) + { + LOGE("Failed to get pipeline cache data.\n"); + return false; + } + + Util::Hasher h; + h.data(data, size); + auto blob_hash = h.get(); + memcpy(hash_data, &blob_hash, sizeof(blob_hash)); + + return true; +} + +void Device::flush_pipeline_cache() +{ +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + if (!system_handles.filesystem) + return; + + if (ext.pipeline_binary_features.pipelineBinaries && + !pipeline_binary_cache.has_new_binary_entries() && + persistent_pipeline_cache) + { + LOGI("No new pipelines have been observed, skipping serialize.\n"); + return; + } + + size_t size = get_pipeline_cache_size(); + if (!size) + { + LOGE("Failed to get pipeline cache size.\n"); + return; + } + + auto file = system_handles.filesystem->open_transactional_mapping( + "cache://pipeline_cache.bin", size); + + if (!file) + { + LOGE("Failed to get pipeline cache data.\n"); + return; + } + + if (!get_pipeline_cache_data(file->mutable_data(), size)) + { + LOGE("Failed to get pipeline cache data.\n"); + return; + } + + persistent_pipeline_cache.reset(); +#endif +} + +void Device::init_workarounds() +{ + workarounds = {}; + +#ifdef __APPLE__ + // Events are not supported in MoltenVK. + // TODO: Use VK_KHR_portability_subset to determine this. + workarounds.emulate_event_as_pipeline_barrier = true; + LOGW("Emulating events as pipeline barriers on Metal emulation.\n"); + LOGW("Disabling push descriptors on Metal emulation.\n"); +#else + if (gpu_props.vendorID == VENDOR_ID_ARM) + { + LOGW("Workaround applied: Emulating events as pipeline barriers.\n"); + workarounds.emulate_event_as_pipeline_barrier = true; + } + + // For whatever ridiculous reason, pipeline cache control causes GPU hangs on Pascal cards in parallel-rdp. + // Use mesh shaders as the sentinel to check for that. + if (ext.driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY && + (VK_VERSION_MAJOR(gpu_props.driverVersion) < 535 || + !ext.mesh_shader_features.meshShader)) + { + LOGW("Disabling pipeline cache control.\n"); + workarounds.broken_pipeline_cache_control = true; + } + else if (ext.driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR) + { + // Seems broken on this driver too. Compilation stutter galore ... + LOGW("Disabling pipeline cache control.\n"); + workarounds.broken_pipeline_cache_control = true; + } + + if (ext.driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY) + workarounds.broken_present_fence = true; +#endif + + if (ext.supports_tooling_info && vkGetPhysicalDeviceToolPropertiesEXT) + { + uint32_t count = 0; + vkGetPhysicalDeviceToolPropertiesEXT(gpu, &count, nullptr); + Util::SmallVector tool_props(count); + for (auto &t : tool_props) + t = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT }; + vkGetPhysicalDeviceToolPropertiesEXT(gpu, &count, tool_props.data()); + for (auto &t : tool_props) + { + LOGI(" Detected attached tool:\n"); + LOGI(" Name: %s\n", t.name); + LOGI(" Description: %s\n", t.description); + LOGI(" Version: %s\n", t.version); + if ((t.purposes & VK_TOOL_PURPOSE_TRACING_BIT_EXT) != 0 && + (t.purposes & VK_TOOL_PURPOSE_PROFILING_BIT) == 0) + { + // Workaround a now-fixed RenderDoc where using ReBAR memory + // causes horrible performance. + if (strcmp(t.name, "RenderDoc") == 0) + { + unsigned major = 0, minor = 0; + int tokens = sscanf(t.version, "v%d.%d", &major, &minor); + if (tokens == 2 && major * 1000 + minor < 1042) + { + LOGI("Detected non-profiling tracing tool, forcing host cached memory types for performance.\n"); + workarounds.force_host_cached = true; + } + } + } + + if (!debug_marker_sensitive && (t.purposes & VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT) != 0) + { + LOGI("Detected tool which cares about debug markers.\n"); + debug_marker_sensitive = true; + } + } + } +} + +void Device::set_context(const Context &context) +{ + ctx = &context; + table = &context.get_device_table(); + + register_thread_index(0); + instance = context.get_instance(); + gpu = context.get_gpu(); + device = context.get_device(); + num_thread_indices = context.get_num_thread_indices(); + + queue_info = context.get_queue_info(); + + mem_props = context.get_mem_props(); + gpu_props = context.get_gpu_props(); + ext = context.get_enabled_device_features(); + system_handles = context.get_system_handles(); + + init_workarounds(); + init_pipeline_cache(); + init_timeline_semaphores(); + init_frame_contexts(2); // By default, regular double buffer between CPU and GPU. + + managers.memory.init(this); + managers.semaphore.init(this); + managers.fence.init(this); + managers.event.init(this); + managers.vbo.init(this, 4 * 1024, 16, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + managers.ibo.init(this, 4 * 1024, 16, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + managers.ubo.init(this, 256 * 1024, std::max(16u, gpu_props.limits.minUniformBufferOffsetAlignment), + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + managers.staging.init(this, 64 * 1024, + std::max(gpu_props.limits.minStorageBufferOffsetAlignment, + std::max(16u, gpu_props.limits.optimalBufferCopyOffsetAlignment)), + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + + managers.vbo.set_max_retained_blocks(256); + managers.ibo.set_max_retained_blocks(256); + managers.ubo.set_max_retained_blocks(64); + managers.staging.set_max_retained_blocks(32); + managers.descriptor_buffer.init(this); + managers.breadcrumbs.init(this); + + init_stock_samplers(); + + for (int i = 0; i < QUEUE_INDEX_COUNT; i++) + { + if (queue_info.family_indices[i] == VK_QUEUE_FAMILY_IGNORED) + continue; + + bool alias_pool = false; + for (int j = 0; j < i; j++) + { + if (queue_info.family_indices[i] == queue_info.family_indices[j]) + { + alias_pool = true; + break; + } + } + + if (!alias_pool) + queue_data[i].performance_query_pool.init_device(this, queue_info.family_indices[i]); + } + + init_calibrated_timestamps(); + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + resource_manager.init(); +#endif +} + +void Device::begin_shader_caches() +{ + if (!ctx) + { + LOGE("No context. Forgot Device::set_context()?\n"); + return; + } + +#ifdef GRANITE_VULKAN_FOSSILIZE + init_pipeline_state(ctx->get_feature_filter(), ctx->get_physical_device_features(), + ctx->get_application_info()); +#elif defined(GRANITE_VULKAN_SYSTEM_HANDLES) + // Fossilize init will deal with init_shader_manager_cache() + init_shader_manager_cache(nullptr); +#endif +} + +#ifndef GRANITE_VULKAN_FOSSILIZE +unsigned Device::query_initialization_progress(InitializationStage) const +{ + // If we don't have Fossilize, everything is considered done up front. + return 100; +} + +void Device::wait_shader_caches() +{ +} +#endif + +void Device::init_timeline_semaphores() +{ + if (!ext.vk12_features.timelineSemaphore) + return; + + VkSemaphoreTypeCreateInfo type_info = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO }; + VkSemaphoreCreateInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; + info.pNext = &type_info; + type_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; + type_info.initialValue = 0; + + for (int i = 0; i < QUEUE_INDEX_COUNT; i++) + if (table->vkCreateSemaphore(device, &info, nullptr, &queue_data[i].timeline_semaphore) != VK_SUCCESS) + LOGE("Failed to create timeline semaphore.\n"); +} + +void Device::configure_default_geometry_samplers(float max_aniso, float lod_bias) +{ + init_stock_sampler(StockSampler::DefaultGeometryFilterClamp, max_aniso, lod_bias); + init_stock_sampler(StockSampler::DefaultGeometryFilterWrap, max_aniso, lod_bias); +} + +void Device::init_stock_sampler(StockSampler mode, float max_aniso, float lod_bias) +{ + SamplerCreateInfo info = {}; + info.max_lod = VK_LOD_CLAMP_NONE; + info.max_anisotropy = 1.0f; + + switch (mode) + { + case StockSampler::NearestShadow: + case StockSampler::LinearShadow: + info.compare_enable = true; + info.compare_op = VK_COMPARE_OP_GREATER_OR_EQUAL; + break; + + default: + info.compare_enable = false; + break; + } + + switch (mode) + { + case StockSampler::TrilinearClamp: + case StockSampler::TrilinearWrap: + case StockSampler::DefaultGeometryFilterWrap: + case StockSampler::DefaultGeometryFilterClamp: + info.mipmap_mode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + break; + + default: + info.mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + break; + } + + switch (mode) + { + case StockSampler::DefaultGeometryFilterClamp: + case StockSampler::DefaultGeometryFilterWrap: + case StockSampler::LinearClamp: + case StockSampler::LinearWrap: + case StockSampler::TrilinearClamp: + case StockSampler::TrilinearWrap: + case StockSampler::LinearShadow: + info.mag_filter = VK_FILTER_LINEAR; + info.min_filter = VK_FILTER_LINEAR; + break; + + default: + info.mag_filter = VK_FILTER_NEAREST; + info.min_filter = VK_FILTER_NEAREST; + break; + } + + switch (mode) + { + default: + case StockSampler::DefaultGeometryFilterWrap: + case StockSampler::LinearWrap: + case StockSampler::NearestWrap: + case StockSampler::TrilinearWrap: + info.address_mode_u = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.address_mode_v = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.address_mode_w = VK_SAMPLER_ADDRESS_MODE_REPEAT; + break; + + case StockSampler::DefaultGeometryFilterClamp: + case StockSampler::LinearClamp: + case StockSampler::NearestClamp: + case StockSampler::TrilinearClamp: + case StockSampler::NearestShadow: + case StockSampler::LinearShadow: + info.address_mode_u = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.address_mode_v = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.address_mode_w = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + break; + } + + switch (mode) + { + case StockSampler::DefaultGeometryFilterWrap: + case StockSampler::DefaultGeometryFilterClamp: + if (get_device_features().enabled_features.samplerAnisotropy) + { + info.anisotropy_enable = true; + info.max_anisotropy = std::min(max_aniso, get_gpu_properties().limits.maxSamplerAnisotropy); + } + info.mip_lod_bias = lod_bias; + break; + + default: + break; + } + + samplers[unsigned(mode)] = request_immutable_sampler(info, nullptr); +} + +void Device::init_stock_samplers() +{ + for (unsigned i = 0; i < static_cast(StockSampler::Count); i++) + { + auto mode = static_cast(i); + init_stock_sampler(mode, 8.0f, 0.0f); + } +} + +static void request_block(Device &device, BufferBlock &block, VkDeviceSize size, + BufferPool &pool, std::vector &recycle) +{ + if (block.is_mapped()) + block.unmap(device); + + if (block.get_offset() == 0) + { + if (block.get_size() == pool.get_block_size()) + pool.recycle_block(block); + } + else + { + if (block.get_size() == pool.get_block_size()) + recycle.push_back(block); + } + + if (size) + block = pool.request_block(size); + else + block = {}; +} + +void Device::request_vertex_block(BufferBlock &block, VkDeviceSize size) +{ + LOCK(); + request_vertex_block_nolock(block, size); +} + +void Device::request_vertex_block_nolock(BufferBlock &block, VkDeviceSize size) +{ + request_block(*this, block, size, managers.vbo, frame().vbo_blocks); +} + +void Device::request_index_block(BufferBlock &block, VkDeviceSize size) +{ + LOCK(); + request_index_block_nolock(block, size); +} + +void Device::request_index_block_nolock(BufferBlock &block, VkDeviceSize size) +{ + request_block(*this, block, size, managers.ibo, frame().ibo_blocks); +} + +void Device::request_uniform_block(BufferBlock &block, VkDeviceSize size) +{ + LOCK(); + request_uniform_block_nolock(block, size); +} + +void Device::request_uniform_block_nolock(BufferBlock &block, VkDeviceSize size) +{ + request_block(*this, block, size, managers.ubo, frame().ubo_blocks); +} + +void Device::request_staging_block(BufferBlock &block, VkDeviceSize size) +{ + LOCK(); + request_staging_block_nolock(block, size); +} + +void Device::request_staging_block_nolock(BufferBlock &block, VkDeviceSize size) +{ + request_block(*this, block, size, managers.staging, frame().staging_blocks); +} + +void Device::submit(CommandBufferHandle &cmd, Fence *fence, unsigned semaphore_count, Semaphore *semaphores) +{ + cmd->end_debug_channel(); + + LOCK(); + submit_nolock(std::move(cmd), fence, semaphore_count, semaphores); +} + +void Device::submit_and_sync_to_queues(CommandBufferHandle &cmd, uint32_t sync_to_queues) +{ + LOCK(); + + auto type = cmd->get_command_buffer_type(); + auto physical_type = get_physical_queue_type(type); + auto &data = queue_data[physical_type]; + + // Resolve obvious cycles. + uint32_t cycle_queues = queue_data[physical_type].has_incoming_queue_dependencies & sync_to_queues; + Util::for_each_bit(cycle_queues, [&](unsigned bit) { + flush_frame_nolock(QueueIndices(bit)); + }); + + submit_nolock(std::move(cmd), nullptr, 0, nullptr); + + // Avoid self-sync which causes a loop. + sync_to_queues &= ~(1u << physical_type); + data.implicit_sync_to_queues |= sync_to_queues; + Util::for_each_bit(sync_to_queues, [&](unsigned bit) { + queue_data[QueueIndices(bit)].has_incoming_queue_dependencies |= 1u << physical_type; + }); + + // This is only used internally, and we should never introduce cycles on our own. + // Verify that there is a flush path for the dependees which does not cause cycles. + + // Disable checks for now, it has bugs. +#if defined(VULKAN_DEBUG) && 0 + uint32_t executing_queues = sync_to_queues; + uint32_t new_executing_queues = executing_queues; + + while (new_executing_queues != 0) + { + auto tmp_queues = new_executing_queues; + new_executing_queues = 0; + Util::for_each_bit(tmp_queues, [&](unsigned i) { + if ((executing_queues & queue_data[i].has_incoming_queue_dependencies) != 0) + { + LOGE("Found cycle in internal staging commands.\n"); + abort(); + } + else + { + new_executing_queues |= queue_data[i].has_incoming_queue_dependencies; + } + }); + + executing_queues |= new_executing_queues; + } +#endif +} + +void Device::submit_discard_nolock(CommandBufferHandle &cmd) +{ + bool borrowed = cmd->is_borrowed(); + +#ifdef VULKAN_DEBUG + if (!borrowed) + { + auto type = cmd->get_command_buffer_type(); + auto &pool = frame().cmd_pools[get_physical_queue_type(type)][cmd->get_thread_index()]; + pool.signal_submitted(cmd->get_command_buffer()); + } +#endif + + cmd->end(); + + cmd.reset(); + + if (!borrowed) + decrement_frame_counter_nolock(); +} + +void Device::submit_discard(CommandBufferHandle &cmd) +{ + LOCK(); + submit_discard_nolock(cmd); +} + +QueueIndices Device::get_physical_queue_type(CommandBuffer::Type queue_type) const +{ + // Enums match. + return QueueIndices(queue_type); +} + +void Device::submit_nolock(CommandBufferHandle cmd, Fence *fence, unsigned semaphore_count, Semaphore *semaphores) +{ + auto type = cmd->get_command_buffer_type(); + auto physical_type = get_physical_queue_type(type); + auto &submissions = frame().submissions[physical_type]; +#ifdef VULKAN_DEBUG + auto &pool = frame().cmd_pools[physical_type][cmd->get_thread_index()]; + pool.signal_submitted(cmd->get_command_buffer()); +#endif + + bool profiled_submit = cmd->has_profiling(); + + if (profiled_submit) + { + LOGI("Submitting profiled command buffer, draining GPU.\n"); + Fence drain_fence; + submit_empty_nolock(physical_type, &drain_fence, nullptr, -1); + drain_fence->wait(); + drain_fence->set_internal_sync_object(); + } + + cmd->end(); + submissions.push_back(std::move(cmd)); + + InternalFence signalled_fence; + + if (fence || semaphore_count) + { + submit_queue(physical_type, fence ? &signalled_fence : nullptr, + nullptr, + semaphore_count, semaphores, + profiled_submit ? 0 : -1); + } + + if (fence) + { + VK_ASSERT(!*fence); + if (signalled_fence.value) + *fence = Fence(handle_pool.fences.allocate(this, signalled_fence.value, signalled_fence.timeline)); + else + *fence = Fence(handle_pool.fences.allocate(this, signalled_fence.fence)); + } + + if (profiled_submit) + { + // Drain queue again and report results. + LOGI("Submitted profiled command buffer, draining GPU and report ...\n"); + auto &query_pool = get_performance_query_pool(physical_type); + Fence drain_fence; + submit_empty_nolock(physical_type, &drain_fence, nullptr, fence || semaphore_count ? -1 : 0); + drain_fence->wait(); + drain_fence->set_internal_sync_object(); + query_pool.report(); + } + + decrement_frame_counter_nolock(); +} + +void Device::submit_external(CommandBuffer::Type type) +{ + LOCK(); + auto &data = queue_data[get_physical_queue_type(type)]; + data.need_fence = true; +} + +void Device::submit_empty(CommandBuffer::Type type, Fence *fence, SemaphoreHolder *semaphore) +{ + VK_ASSERT(!semaphore || !semaphore->is_proxy_timeline()); + LOCK(); + submit_empty_nolock(get_physical_queue_type(type), fence, semaphore, -1); +} + +void Device::submit_empty_nolock(QueueIndices physical_type, Fence *fence, + SemaphoreHolder *semaphore, int profiling_iteration) +{ + InternalFence signalled_fence = {}; + + submit_queue(physical_type, fence ? &signalled_fence : nullptr, semaphore, + 0, nullptr, profiling_iteration); + + if (fence) + { + if (signalled_fence.value) + *fence = Fence(handle_pool.fences.allocate(this, signalled_fence.value, signalled_fence.timeline)); + else + *fence = Fence(handle_pool.fences.allocate(this, signalled_fence.fence)); + } +} + +void Device::submit_empty_inner(QueueIndices physical_type, InternalFence *fence, + SemaphoreHolder *external_semaphore, + unsigned semaphore_count, Semaphore *semaphores) +{ + auto &data = queue_data[physical_type]; + VkSemaphore timeline_semaphore = data.timeline_semaphore; + uint64_t timeline_value = ++data.current_timeline; + VkQueue queue = queue_info.queues[physical_type]; + frame().timeline_fences[physical_type] = data.current_timeline; + + // Add external wait semaphores. + Helper::WaitSemaphores wait_semaphores; + Helper::BatchComposer composer(get_device_features().supports_low_latency2_nv ? wsi.low_latency.present_id : 0); + collect_wait_semaphores(data, wait_semaphores); + composer.add_wait_submissions(wait_semaphores); + + for (auto consume : frame().consumed_semaphores) + { + composer.add_wait_semaphore(consume, VK_PIPELINE_STAGE_NONE); + frame().recycled_semaphores.push_back(consume); + } + frame().consumed_semaphores.clear(); + + emit_queue_signals(composer, external_semaphore, + timeline_semaphore, timeline_value, + fence, semaphore_count, semaphores); + + VkFence cleared_fence = fence && !ext.vk12_features.timelineSemaphore ? + managers.fence.request_cleared_fence() : + VK_NULL_HANDLE; + if (fence) + fence->fence = cleared_fence; + + auto start_ts = write_calibrated_timestamp_nolock(); + auto result = submit_batches(composer, queue, cleared_fence); + auto end_ts = write_calibrated_timestamp_nolock(); + register_time_interval_nolock("CPU", std::move(start_ts), std::move(end_ts), "submit"); + + emit_implicit_sync_to_queues(physical_type); + + if (result != VK_SUCCESS) + LOGE("vkQueueSubmit2 failed (code: %d).\n", int(result)); + + if (result == VK_ERROR_DEVICE_LOST) + managers.breadcrumbs.notify_device_hung(); + + if (!ext.vk12_features.timelineSemaphore) + data.need_fence = true; +} + +Fence Device::request_legacy_fence() +{ + VkFence fence = managers.fence.request_cleared_fence(); + return Fence(handle_pool.fences.allocate(this, fence)); +} + +void Device::collect_wait_semaphores(QueueData &data, Helper::WaitSemaphores &sem) +{ + VkSemaphoreSubmitInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO }; + + for (size_t i = 0, n = data.wait_semaphores.size(); i < n; i++) + { + auto &semaphore = data.wait_semaphores[i]; + bool is_owned = semaphore->is_owned(); + auto vk_semaphore = semaphore->consume(); + if (semaphore->get_semaphore_type() == VK_SEMAPHORE_TYPE_TIMELINE) + { + info.semaphore = vk_semaphore; + info.stageMask = data.wait_stages[i]; + info.value = semaphore->get_timeline_value(); + + auto itr = std::find_if( + sem.timeline_waits.begin(), sem.timeline_waits.end(), [&](const VkSemaphoreSubmitInfo &old_info) + { return old_info.semaphore == info.semaphore && old_info.stageMask == info.stageMask; }); + + if (itr != sem.timeline_waits.end()) + { + auto &old_info = *itr; + old_info.value = std::max(old_info.value, info.value); + } + else + { + sem.timeline_waits.push_back(info); + } + } + else + { + if (is_owned) + { + if (semaphore->is_external_object_compatible()) + frame().destroyed_semaphores.push_back(vk_semaphore); + else + frame().recycled_semaphores.push_back(vk_semaphore); + } + + info.semaphore = vk_semaphore; + info.stageMask = data.wait_stages[i]; + info.value = 0; + sem.binary_waits.push_back(info); + } + } + + data.wait_stages.clear(); + data.wait_semaphores.clear(); +} + +Helper::BatchComposer::BatchComposer(uint64_t present_id_nv_) + : present_id_nv(present_id_nv_) +{ + submits.emplace_back(); +} + +void Helper::BatchComposer::begin_batch() +{ + if (!waits[submit_index].empty() || !cmds[submit_index].empty() || !signals[submit_index].empty()) + { + submit_index = submits.size(); + submits.emplace_back(); + VK_ASSERT(submits.size() <= MaxSubmissions); + } +} + +void Helper::BatchComposer::add_wait_submissions(WaitSemaphores &sem) +{ + auto &w = waits[submit_index]; + + if (!sem.binary_waits.empty()) + w.insert(w.end(), sem.binary_waits.begin(), sem.binary_waits.end()); + + if (!sem.timeline_waits.empty()) + w.insert(w.end(), sem.timeline_waits.begin(), sem.timeline_waits.end()); +} + +SmallVector & +Helper::BatchComposer::bake(int profiling_iteration) +{ + if (present_id_nv) + present_ids_nv.resize(submits.size()); + + for (size_t i = 0, n = submits.size(); i < n; i++) + { + auto &submit = submits[i]; + + submit = { VK_STRUCTURE_TYPE_SUBMIT_INFO_2 }; + submit.commandBufferInfoCount = uint32_t(cmds[i].size()); + submit.pCommandBufferInfos = cmds[i].data(); + submit.signalSemaphoreInfoCount = uint32_t(signals[i].size()); + submit.pSignalSemaphoreInfos = signals[i].data(); + submit.waitSemaphoreInfoCount = uint32_t(waits[i].size()); + submit.pWaitSemaphoreInfos = waits[i].data(); + + if (present_id_nv) + { + present_ids_nv[i].sType = VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV; + present_ids_nv[i].presentID = present_id_nv; + present_ids_nv[i].pNext = submit.pNext; + submit.pNext = &present_ids_nv[i]; + } + + if (profiling_iteration >= 0) + { + profiling_infos[i] = { VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR }; + profiling_infos[i].counterPassIndex = uint32_t(profiling_iteration); + profiling_infos[i].pNext = submit.pNext; + submit.pNext = &profiling_infos[i]; + } + } + + // Compact the submission array to avoid empty submissions. + size_t submit_count = 0; + for (size_t i = 0, n = submits.size(); i < n; i++) + { + if (submits[i].waitSemaphoreInfoCount || submits[i].signalSemaphoreInfoCount || submits[i].commandBufferInfoCount) + { + if (i != submit_count) + submits[submit_count] = submits[i]; + submit_count++; + } + } + + submits.resize(submit_count); + return submits; +} + +void Helper::BatchComposer::add_command_buffer(VkCommandBuffer cmd) +{ + if (!signals[submit_index].empty()) + begin_batch(); + + VkCommandBufferSubmitInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO }; + info.commandBuffer = cmd; + cmds[submit_index].push_back(info); +} + +void Helper::BatchComposer::add_signal_semaphore(VkSemaphore sem, VkPipelineStageFlags2 stages, uint64_t timeline) +{ + VkSemaphoreSubmitInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO }; + info.semaphore = sem; + info.stageMask = stages; + info.value = timeline; + signals[submit_index].push_back(info); +} + +void Helper::BatchComposer::add_wait_semaphore(SemaphoreHolder &sem, VkPipelineStageFlags2 stage) +{ + if (!cmds[submit_index].empty() || !signals[submit_index].empty()) + begin_batch(); + + bool is_timeline = sem.get_semaphore_type() == VK_SEMAPHORE_TYPE_TIMELINE; + + VkSemaphoreSubmitInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO }; + info.semaphore = sem.get_semaphore(); + info.stageMask = stage; + info.value = is_timeline ? sem.get_timeline_value() : 0; + waits[submit_index].push_back(info); +} + +void Helper::BatchComposer::add_wait_semaphore(VkSemaphore sem, VkPipelineStageFlags2 stage) +{ + if (!cmds[submit_index].empty() || !signals[submit_index].empty()) + begin_batch(); + + VkSemaphoreSubmitInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO }; + info.semaphore = sem; + info.stageMask = stage; + info.value = 0; + waits[submit_index].push_back(info); +} + +void Device::emit_implicit_sync_to_queues(QueueIndices physical_type) +{ + auto &data = queue_data[physical_type]; + auto sync_to_queues = data.implicit_sync_to_queues; + // Clear this early to avoid infinite recursion. + data.implicit_sync_to_queues = 0; + + if (ext.vk12_features.timelineSemaphore) + { + Util::for_each_bit(sync_to_queues, [&](unsigned bit) + { + auto queue_index = QueueIndices(bit); + auto sem = Semaphore( + handle_pool.semaphores.allocate(this, data.current_timeline, data.timeline_semaphore, false)); + sem->signal_external(); + + // Ensure that all pending command buffers observe the wait since we have deferred adding the signal. + auto &dependee = queue_data[queue_index]; + dependee.wait_semaphores.push_back(std::move(sem)); + dependee.wait_stages.push_back(VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT); + dependee.has_incoming_queue_dependencies &= ~(1u << physical_type); + }); + } + else + { + Util::for_each_bit(sync_to_queues, [&](unsigned bit) + { + auto sem = request_legacy_semaphore(); + submit_empty_inner(physical_type, nullptr, sem.get(), 0, nullptr); + + auto queue_index = QueueIndices(bit); + + // Ensure that all pending command buffers observe the wait since we have deferred adding the signal. + queue_data[queue_index].wait_semaphores.push_back(std::move(sem)); + queue_data[queue_index].wait_stages.push_back(VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT); + queue_data[queue_index].has_incoming_queue_dependencies &= ~(1u << physical_type); + }); + } +} + +void Device::emit_queue_signals(Helper::BatchComposer &composer, + SemaphoreHolder *external_semaphore, + VkSemaphore sem, uint64_t timeline, InternalFence *fence, + unsigned semaphore_count, Semaphore *semaphores) +{ + if (external_semaphore) + { + VK_ASSERT(!external_semaphore->is_signalled()); + VK_ASSERT(!external_semaphore->is_proxy_timeline()); + VK_ASSERT(external_semaphore->get_semaphore()); + external_semaphore->signal_external(); + composer.add_signal_semaphore(external_semaphore->get_semaphore(), + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + external_semaphore->get_semaphore_type() == VK_SEMAPHORE_TYPE_TIMELINE ? + external_semaphore->get_timeline_value() : 0); + + // Make sure we observe that the external semaphore is signalled before fences are signalled. + composer.begin_batch(); + } + + // Add external signal semaphores. + if (ext.vk12_features.timelineSemaphore) + { + // Signal once and distribute the timeline value to all. + composer.add_signal_semaphore(sem, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, timeline); + + if (fence) + { + fence->timeline = sem; + fence->value = timeline; + fence->fence = VK_NULL_HANDLE; + } + + for (unsigned i = 0; i < semaphore_count; i++) + { + VK_ASSERT(!semaphores[i]); + semaphores[i] = Semaphore(handle_pool.semaphores.allocate(this, timeline, sem, false)); + semaphores[i]->signal_external(); + } + } + else + { + if (fence) + { + fence->timeline = VK_NULL_HANDLE; + fence->value = 0; + } + + for (unsigned i = 0; i < semaphore_count; i++) + { + VkSemaphore cleared_semaphore = managers.semaphore.request_cleared_semaphore(); + composer.add_signal_semaphore(cleared_semaphore, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0); + VK_ASSERT(!semaphores[i]); + semaphores[i] = Semaphore(handle_pool.semaphores.allocate(this, cleared_semaphore, true, true)); + } + } +} + +VkResult Device::queue_submit(VkQueue queue, uint32_t count, const VkSubmitInfo2 *submits, VkFence fence) +{ + return table->vkQueueSubmit2(queue, count, submits, fence); +} + +VkResult Device::submit_batches(Helper::BatchComposer &composer, VkQueue queue, VkFence fence, int profiling_iteration) +{ + auto &submits = composer.bake(profiling_iteration); + if (queue_lock_callback) + queue_lock_callback(); + + VkResult result = queue_submit(queue, uint32_t(submits.size()), submits.data(), fence); + + if (ImplementationQuirks::get().queue_wait_on_submission) + table->vkQueueWaitIdle(queue); + if (queue_unlock_callback) + queue_unlock_callback(); + + return result; +} + +void Device::submit_queue(QueueIndices physical_type, InternalFence *fence, + SemaphoreHolder *external_semaphore, + unsigned semaphore_count, Semaphore *semaphores, int profiling_iteration) +{ + auto &data = queue_data[physical_type]; + Util::for_each_bit(data.has_incoming_queue_dependencies, [&](unsigned bits) { + VK_ASSERT(physical_type != bits); + submit_queue(QueueIndices(bits), nullptr); + }); + VK_ASSERT(data.has_incoming_queue_dependencies == 0); + + auto &submissions = frame().submissions[physical_type]; + + if (submissions.empty()) + { + if (fence || semaphore_count || external_semaphore || data.implicit_sync_to_queues || !data.wait_semaphores.empty()) + submit_empty_inner(physical_type, fence, external_semaphore, semaphore_count, semaphores); + return; + } + + if (get_device_features().supports_low_latency2_nv && + wsi.low_latency.need_submit_begin_marker && + wsi.low_latency.present_id && + wsi.low_latency.swapchain) + { + VkSetLatencyMarkerInfoNV marker_info = { VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV }; + marker_info.presentID = wsi.low_latency.present_id; + table->vkSetLatencyMarkerNV(device, wsi.low_latency.swapchain, &marker_info); + wsi.low_latency.need_submit_begin_marker = false; + } + + VkSemaphore timeline_semaphore = data.timeline_semaphore; + uint64_t timeline_value = ++data.current_timeline; + + VkQueue queue = queue_info.queues[physical_type]; + frame().timeline_fences[physical_type] = data.current_timeline; + + Helper::BatchComposer composer(get_device_features().supports_low_latency2_nv ? wsi.low_latency.present_id : 0); + Helper::WaitSemaphores wait_semaphores; + collect_wait_semaphores(data, wait_semaphores); + + composer.add_wait_submissions(wait_semaphores); + + // Find first command buffer which uses WSI, we'll need to emit WSI acquire wait before the first command buffer + // that uses WSI image. + + for (size_t i = 0, submissions_size = submissions.size(); i < submissions_size; i++) + { + auto &cmd = submissions[i]; + VkPipelineStageFlags2 wsi_stages = cmd->swapchain_touched_in_stages(); + + if (wsi_stages != 0 && !wsi.consumed) + { + if (!can_touch_swapchain_in_command_buffer(physical_type)) + LOGE("Touched swapchain in unsupported command buffer type %u.\n", unsigned(physical_type)); + + if (wsi.acquire && wsi.acquire->get_semaphore() != VK_NULL_HANDLE) + { + VK_ASSERT(wsi.acquire->is_signalled()); + composer.add_wait_semaphore(*wsi.acquire, wsi_stages); + if (wsi.acquire->get_semaphore_type() == VK_SEMAPHORE_TYPE_BINARY) + { + if (wsi.acquire->is_external_object_compatible()) + frame().destroyed_semaphores.push_back(wsi.acquire->get_semaphore()); + else + frame().recycled_semaphores.push_back(wsi.acquire->get_semaphore()); + } + wsi.acquire->consume(); + wsi.acquire.reset(); + } + + composer.add_command_buffer(cmd->get_command_buffer()); + + VkSemaphore release = managers.semaphore.request_cleared_semaphore(); + wsi.release = Semaphore(handle_pool.semaphores.allocate(this, release, true, true)); + wsi.release->set_internal_sync_object(); + composer.add_signal_semaphore(release, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0); + wsi.present_queue = queue; + wsi.present_queue_type = cmd->get_command_buffer_type(); + wsi.consumed = true; + } + else + { + // After we have consumed WSI, we cannot keep using it, since we + // already signalled the semaphore. + VK_ASSERT(wsi_stages == 0); + composer.add_command_buffer(cmd->get_command_buffer()); + } + } + + VkFence cleared_fence = fence && !ext.vk12_features.timelineSemaphore ? + managers.fence.request_cleared_fence() : + VK_NULL_HANDLE; + + if (fence) + fence->fence = cleared_fence; + + for (auto consume : frame().consumed_semaphores) + { + composer.add_wait_semaphore(consume, VK_PIPELINE_STAGE_NONE); + frame().recycled_semaphores.push_back(consume); + } + frame().consumed_semaphores.clear(); + + emit_queue_signals(composer, external_semaphore, timeline_semaphore, timeline_value, + fence, semaphore_count, semaphores); + + auto start_ts = write_calibrated_timestamp_nolock(); + auto result = submit_batches(composer, queue, cleared_fence, profiling_iteration); + auto end_ts = write_calibrated_timestamp_nolock(); + register_time_interval_nolock("CPU", std::move(start_ts), std::move(end_ts), "submit"); + + if (result != VK_SUCCESS) + LOGE("vkQueueSubmit2 failed (code: %d).\n", int(result)); + + if (result == VK_ERROR_DEVICE_LOST) + managers.breadcrumbs.notify_device_hung(); + + submissions.clear(); + + emit_implicit_sync_to_queues(physical_type); + + if (!ext.vk12_features.timelineSemaphore) + data.need_fence = true; +} + +void Device::flush_frame_nolock(QueueIndices physical_type) +{ + if (queue_info.queues[physical_type] != VK_NULL_HANDLE) + submit_queue(physical_type, nullptr); +} + +void Device::end_frame_context() +{ + DRAIN_FRAME_LOCK(); + end_frame_nolock(); +} + +void Device::end_frame_nolock() +{ + // Flushing one queue may require flushes on other queues. + // Make sure everything is resolved before we check for fences. + // This is mostly unnecessary with timeline semaphores. + flush_frame_nolock(); + + // Make sure we have a fence which covers all submissions in the frame. + for (auto &i : queue_flush_order) + { + if (queue_data[i].need_fence || + !frame().submissions[i].empty() || + !frame().consumed_semaphores.empty()) + { + InternalFence fence = {}; + submit_queue(i, &fence); + if (fence.fence != VK_NULL_HANDLE) + frame().wait_and_recycle_fences.push_back(fence.fence); + queue_data[i].need_fence = false; + + VK_ASSERT(queue_data[i].wait_semaphores.empty()); + } + } +} + +void Device::flush_frame() +{ + LOCK(); + flush_frame_nolock(); +} + +void Device::flush_frame_nolock() +{ + for (auto &i : queue_flush_order) + flush_frame_nolock(i); +} + +PerformanceQueryPool &Device::get_performance_query_pool(QueueIndices physical_index) +{ + for (int i = 0; i < physical_index; i++) + if (queue_info.family_indices[i] == queue_info.family_indices[physical_index]) + return queue_data[i].performance_query_pool; + return queue_data[physical_index].performance_query_pool; +} + +CommandBufferHandle Device::request_command_buffer(CommandBuffer::Type type) +{ + return request_command_buffer_for_thread(get_thread_index(), type); +} + +CommandBufferHandle Device::request_command_buffer_for_thread(unsigned thread_index, CommandBuffer::Type type) +{ + LOCK(); + return request_command_buffer_nolock(thread_index, type, false); +} + +CommandBufferHandle Device::request_borrowed_command_buffer(VkCommandBuffer cmd) +{ + LOCK(); + CommandBufferHandle handle(handle_pool.command_buffers.allocate(this, cmd, legacy_pipeline_cache, + Vulkan::CommandBuffer::Type::Generic /* somewhat irrelevant */, false)); + handle->set_thread_index(get_thread_index()); + handle->set_borrowed(); + return handle; +} + +CommandBufferHandle Device::request_profiled_command_buffer(CommandBuffer::Type type) +{ + return request_profiled_command_buffer_for_thread(get_thread_index(), type); +} + +CommandBufferHandle Device::request_profiled_command_buffer_for_thread(unsigned thread_index, + CommandBuffer::Type type) +{ + LOCK(); + return request_command_buffer_nolock(thread_index, type, true); +} + +CommandBufferHandle Device::request_command_buffer_nolock(unsigned thread_index, CommandBuffer::Type type, bool profiled) +{ + auto physical_type = get_physical_queue_type(type); + auto &pool = frame().cmd_pools[physical_type][thread_index]; + auto cmd = pool.request_command_buffer(); + + if (profiled && !ext.performance_query_features.performanceCounterQueryPools) + { + LOGW("Profiling is not supported on this device.\n"); + profiled = false; + } + + VkCommandBufferBeginInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + table->vkBeginCommandBuffer(cmd, &info); + add_frame_counter_nolock(); + CommandBufferHandle handle(handle_pool.command_buffers.allocate(this, cmd, legacy_pipeline_cache, type, false)); + handle->set_thread_index(thread_index); + + auto breadcrumbs = managers.breadcrumbs.allocate_command_buffer(cmd); + if (breadcrumbs.index != BufferMarkerHandle::Invalid) + { + handle->set_breadcrumbs_handle(breadcrumbs); + managers.breadcrumbs.begin(breadcrumbs); + frame().breadcrumbs.push_back(breadcrumbs); + } + + if (profiled) + { + auto &query_pool = get_performance_query_pool(physical_type); + handle->enable_profiling(); + query_pool.begin_command_buffer(handle->get_command_buffer()); + } + + return handle; +} + +void Device::submit_secondary(CommandBuffer &primary, CommandBuffer &secondary) +{ + { + LOCK(); + secondary.end(); + decrement_frame_counter_nolock(); + +#ifdef VULKAN_DEBUG + auto &pool = frame().cmd_pools[get_physical_queue_type(secondary.get_command_buffer_type())][secondary.get_thread_index()]; + pool.signal_submitted(secondary.get_command_buffer()); +#endif + } + + VkCommandBuffer secondary_cmd = secondary.get_command_buffer(); + table->vkCmdExecuteCommands(primary.get_command_buffer(), 1, &secondary_cmd); +} + +CommandBufferHandle Device::request_secondary_command_buffer_for_thread(unsigned thread_index, + const Framebuffer *framebuffer, + unsigned subpass, + CommandBuffer::Type type) +{ + LOCK(); + + auto &pool = frame().cmd_pools[get_physical_queue_type(type)][thread_index]; + auto cmd = pool.request_secondary_command_buffer(); + VkCommandBufferBeginInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO }; + + inherit.framebuffer = VK_NULL_HANDLE; + inherit.renderPass = framebuffer->get_compatible_render_pass().get_render_pass(); + inherit.subpass = subpass; + info.pInheritanceInfo = &inherit; + info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; + + VkBindHeapInfoEXT resource_heap = { VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT }; + VkBindHeapInfoEXT sampler_heap = { VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT }; + VkCommandBufferInheritanceDescriptorHeapInfoEXT inheritance_heap = + { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_DESCRIPTOR_HEAP_INFO_EXT }; + inheritance_heap.pResourceHeapBindInfo = &resource_heap; + inheritance_heap.pSamplerHeapBindInfo = &sampler_heap; + + if (ext.descriptor_heap_features.descriptorHeap) + { + auto heap = managers.descriptor_buffer.get_resource_heap(); + resource_heap.heapRange.address = heap.va; + resource_heap.heapRange.size = heap.size; + resource_heap.reservedRangeOffset = heap.reserved_offset; + resource_heap.reservedRangeSize = heap.size - heap.reserved_offset; + + heap = managers.descriptor_buffer.get_sampler_heap(); + sampler_heap.heapRange.address = heap.va; + sampler_heap.heapRange.size = heap.size; + sampler_heap.reservedRangeOffset = heap.reserved_offset; + sampler_heap.reservedRangeSize = heap.size - heap.reserved_offset; + + inherit.pNext = &inheritance_heap; + } + + // Don't add breadcrumb stuff to secondaries for now. Need some extra thought on how that is supposed to work. + + table->vkBeginCommandBuffer(cmd, &info); + add_frame_counter_nolock(); + CommandBufferHandle handle(handle_pool.command_buffers.allocate(this, cmd, legacy_pipeline_cache, type, true)); + handle->set_thread_index(thread_index); + return handle; +} + +void Device::set_acquire_semaphore(unsigned index, Semaphore acquire) +{ + wsi.acquire = std::move(acquire); + wsi.index = index; + wsi.consumed = false; + + if (wsi.acquire) + { + wsi.acquire->set_internal_sync_object(); + VK_ASSERT(wsi.acquire->is_signalled()); + } +} + +void Device::set_present_id(VkSwapchainKHR swapchain, uint64_t present_id) +{ + if (wsi.low_latency.present_id != present_id) + wsi.low_latency.need_submit_begin_marker = true; + wsi.low_latency.swapchain = swapchain; + wsi.low_latency.present_id = present_id; +} + +Semaphore Device::consume_release_semaphore() +{ + auto ret = std::move(wsi.release); + wsi.release.reset(); + return ret; +} + +VkQueue Device::get_current_present_queue() const +{ + VK_ASSERT(wsi.present_queue); + return wsi.present_queue; +} + +CommandBuffer::Type Device::get_current_present_queue_type() const +{ + VK_ASSERT(wsi.present_queue); + return wsi.present_queue_type; +} + +const Sampler &Device::get_stock_sampler(StockSampler sampler) const +{ + return samplers[static_cast(sampler)]->get_sampler(); +} + +bool Device::swapchain_touched() const +{ + return wsi.consumed; +} + +Device::~Device() +{ + wsi.acquire.reset(); + wsi.release.reset(); + wsi.swapchain.clear(); + managers.descriptor_buffer.teardown(); + managers.breadcrumbs.deinit(); + + wait_idle(); + + managers.timestamps.log_simple(); + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + flush_shader_manager_cache(); +#endif + +#ifdef GRANITE_VULKAN_FOSSILIZE + flush_pipeline_state(); +#endif + + if (legacy_pipeline_cache != VK_NULL_HANDLE || ext.pipeline_binary_features.pipelineBinaries) + flush_pipeline_cache(); + + if (table) + table->vkDestroyPipelineCache(device, legacy_pipeline_cache, nullptr); + + framebuffer_allocator.clear(); + transient_allocator.clear(); + + deinit_timeline_semaphores(); +} + +void Device::deinit_timeline_semaphores() +{ + for (auto &data : queue_data) + { + if (data.timeline_semaphore != VK_NULL_HANDLE) + table->vkDestroySemaphore(device, data.timeline_semaphore, nullptr); + data.timeline_semaphore = VK_NULL_HANDLE; + } + + // Make sure we don't accidentally try to wait for these after we destroy the semaphores. + for (auto &frame : per_frame) + { + for (auto &fence : frame->timeline_fences) + fence = 0; + for (auto &timeline : frame->timeline_semaphores) + timeline = VK_NULL_HANDLE; + } +} + +void Device::init_frame_contexts(unsigned count) +{ + DRAIN_FRAME_LOCK(); + wait_idle_nolock(); + + // Clear out caches which might contain stale data from now on. + framebuffer_allocator.clear(); + transient_allocator.clear(); + per_frame.clear(); + + for (unsigned i = 0; i < count; i++) + { + auto frame = std::unique_ptr(new PerFrame(this, i)); + per_frame.emplace_back(std::move(frame)); + } +} + +void Device::init_external_swapchain(const std::vector &swapchain_images) +{ + DRAIN_FRAME_LOCK(); + wsi.swapchain.clear(); + wait_idle_nolock(); + + wsi.index = 0; + wsi.consumed = false; + for (auto &image : swapchain_images) + { + wsi.swapchain.push_back(image); + if (image) + { + wsi.swapchain.back()->set_internal_sync_object(); + wsi.swapchain.back()->get_view().set_internal_sync_object(); + } + } +} + +bool Device::can_touch_swapchain_in_command_buffer(QueueIndices physical_type) const +{ + // If 0, we have virtual swap chain, so anything goes. + if (!wsi.queue_family_support_mask) + return true; + + return (wsi.queue_family_support_mask & (1u << queue_info.family_indices[physical_type])) != 0; +} + +bool Device::can_touch_swapchain_in_command_buffer(CommandBuffer::Type type) const +{ + return can_touch_swapchain_in_command_buffer(get_physical_queue_type(type)); +} + +void Device::set_swapchain_queue_family_support(uint32_t queue_family_support) +{ + wsi.queue_family_support_mask = queue_family_support; +} + +BufferHandle Device::wrap_buffer(const BufferCreateInfo &info, VkBuffer buffer, bool supports_bda) +{ + VkDeviceAddress bda = 0; + + if (supports_bda && get_device_features().vk12_features.bufferDeviceAddress) + { + VkBufferDeviceAddressInfo bda_info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO }; + bda_info.buffer = buffer; + bda = table->vkGetBufferDeviceAddress(device, &bda_info); + } + + BufferHandle handle(handle_pool.buffers.allocate(this, buffer, DeviceAllocation{}, info, bda)); + handle->disown_buffer(); + return handle; +} + +ImageHandle Device::wrap_image(const ImageCreateInfo &info, VkImage image) +{ + auto img = ImageHandle(handle_pool.images.allocate( + this, image, CachedImageView{}, + DeviceAllocation{}, info, VK_IMAGE_VIEW_TYPE_MAX_ENUM)); + img->disown_image(); + return img; +} + +void Device::init_swapchain(const std::vector &swapchain_images, unsigned width, unsigned height, VkFormat format, + VkSurfaceTransformFlagBitsKHR transform, VkImageUsageFlags usage, VkImageLayout layout) +{ + DRAIN_FRAME_LOCK(); + wsi.swapchain.clear(); + + auto info = ImageCreateInfo::render_target(width, height, format); + info.usage = usage; + + wsi.index = 0; + wsi.consumed = false; + for (auto &image : swapchain_images) + { + VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + view_info.image = image; + view_info.format = format; + view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.subresourceRange.aspectMask = format_to_aspect_mask(format); + view_info.subresourceRange.baseMipLevel = 0; + view_info.subresourceRange.baseArrayLayer = 0; + view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.layerCount = 1; + view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + + CachedImageView view = {}; + if (!managers.descriptor_buffer.create_image_view(view_info, usage, ImageLayout::Optimal, view)) + LOGE("Failed to create view for backbuffer."); + + auto backbuffer = ImageHandle(handle_pool.images.allocate(this, image, view, DeviceAllocation{}, info, VK_IMAGE_VIEW_TYPE_2D)); + backbuffer->set_internal_sync_object(); + backbuffer->disown_image(); + backbuffer->get_view().set_internal_sync_object(); + backbuffer->set_surface_transform(transform); + wsi.swapchain.push_back(backbuffer); + set_name(*backbuffer, "backbuffer"); + backbuffer->set_swapchain_layout(layout); + } +} + +Device::PerFrame::PerFrame(Device *device_, unsigned frame_index_) + : device(*device_) + , frame_index(frame_index_) + , table(device_->get_device_table()) + , managers(device_->managers) + , query_pool_ts(device_, VK_QUERY_TYPE_TIMESTAMP) + , query_pool_rtas(device_, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR) +{ + unsigned count = device_->num_thread_indices; + for (int i = 0; i < QUEUE_INDEX_COUNT; i++) + { + timeline_semaphores[i] = device.queue_data[i].timeline_semaphore; + cmd_pools[i].reserve(count); + for (unsigned j = 0; j < count; j++) + cmd_pools[i].emplace_back(device_, device_->queue_info.family_indices[i]); + } +} + +void Device::free_memory_nolock(const DeviceAllocation &alloc) +{ + frame().allocations.push_back(alloc); +} + +#ifdef VULKAN_DEBUG + +template +static inline bool exists(const T &container, const U &value) +{ + return find(begin(container), end(container), value) != end(container); +} + +#endif + +void Device::reset_fence(VkFence fence, bool observed_wait) +{ + LOCK(); + reset_fence_nolock(fence, observed_wait); +} + +void Device::destroy_buffer(VkBuffer buffer) +{ + LOCK(); + destroy_buffer_nolock(buffer); +} + +void Device::destroy_rtas(VkAccelerationStructureKHR rtas) +{ + LOCK(); + destroy_rtas_nolock(rtas); +} + +void Device::destroy_indirect_execution_set(VkIndirectExecutionSetEXT exec_set) +{ + LOCK(); + destroy_indirect_execution_set_nolock(exec_set); +} + +void Device::destroy_descriptor_pool(VkDescriptorPool desc_pool) +{ + LOCK(); + destroy_descriptor_pool_nolock(desc_pool); +} + +void Device::destroy_buffer_view(const CachedBufferView &view) +{ + LOCK(); + destroy_buffer_view_nolock(view); +} + +void Device::destroy_event(VkEvent event) +{ + LOCK(); + destroy_event_nolock(event); +} + +void Device::destroy_framebuffer(VkFramebuffer framebuffer) +{ + LOCK(); + destroy_framebuffer_nolock(framebuffer); +} + +void Device::destroy_image(VkImage image) +{ + LOCK(); + destroy_image_nolock(image); +} + +void Device::destroy_semaphore(VkSemaphore semaphore) +{ + LOCK(); + destroy_semaphore_nolock(semaphore); +} + +void Device::consume_semaphore(VkSemaphore semaphore) +{ + LOCK(); + consume_semaphore_nolock(semaphore); +} + +void Device::recycle_semaphore(VkSemaphore semaphore) +{ + LOCK(); + recycle_semaphore_nolock(semaphore); +} + +void Device::free_memory(const DeviceAllocation &alloc) +{ + LOCK(); + free_memory_nolock(alloc); +} + +void Device::destroy_sampler(VkSampler sampler) +{ + LOCK(); + destroy_sampler_nolock(sampler); +} + +void Device::destroy_image_view(const CachedImageView &view) +{ + LOCK(); + destroy_image_view_nolock(view); +} + +void Device::free_descriptor_buffer_allocation(const DescriptorBufferAllocation &alloc) +{ + LOCK(); + free_descriptor_buffer_allocation_nolock(alloc); +} + +void Device::free_cached_descriptor_payload(const CachedDescriptorPayload &payload) +{ + LOCK(); + free_cached_descriptor_payload_nolock(payload); +} + +void Device::destroy_image_view_nolock(const CachedImageView &view) +{ + frame().destroyed_image_views.push_back(view); +} + +void Device::destroy_buffer_view_nolock(const CachedBufferView &view) +{ + frame().destroyed_buffer_views.push_back(view); +} + +void Device::destroy_semaphore_nolock(VkSemaphore semaphore) +{ + VK_ASSERT(!exists(frame().destroyed_semaphores, semaphore)); + frame().destroyed_semaphores.push_back(semaphore); +} + +void Device::consume_semaphore_nolock(VkSemaphore semaphore) +{ + VK_ASSERT(!exists(frame().consumed_semaphores, semaphore)); + frame().consumed_semaphores.push_back(semaphore); +} + +void Device::recycle_semaphore_nolock(VkSemaphore semaphore) +{ + VK_ASSERT(!exists(frame().recycled_semaphores, semaphore)); + frame().recycled_semaphores.push_back(semaphore); +} + +void Device::destroy_event_nolock(VkEvent event) +{ + VK_ASSERT(!exists(frame().recycled_events, event)); + frame().recycled_events.push_back(event); +} + +void Device::reset_fence_nolock(VkFence fence, bool observed_wait) +{ + if (observed_wait) + { + table->vkResetFences(device, 1, &fence); + managers.fence.recycle_fence(fence); + } + else + frame().wait_and_recycle_fences.push_back(fence); +} + +void Device::free_descriptor_buffer_allocation_nolock(const DescriptorBufferAllocation &alloc) +{ + frame().descriptor_buffer_allocs.push_back(alloc); +} + +void Device::free_cached_descriptor_payload_nolock(const CachedDescriptorPayload &payload) +{ + frame().cached_descriptor_payloads.push_back(payload); +} + +PipelineEvent Device::request_pipeline_event() +{ + return PipelineEvent(handle_pool.events.allocate(this, managers.event.request_cleared_event())); +} + +void Device::destroy_image_nolock(VkImage image) +{ + VK_ASSERT(!exists(frame().destroyed_images, image)); + frame().destroyed_images.push_back(image); +} + +void Device::destroy_buffer_nolock(VkBuffer buffer) +{ + VK_ASSERT(!exists(frame().destroyed_buffers, buffer)); + frame().destroyed_buffers.push_back(buffer); +} + +void Device::destroy_rtas_nolock(VkAccelerationStructureKHR rtas) +{ + VK_ASSERT(!exists(frame().destroyed_rtas, rtas)); + frame().destroyed_rtas.push_back(rtas); +} + +void Device::destroy_indirect_execution_set_nolock(VkIndirectExecutionSetEXT exec_set) +{ + VK_ASSERT(!exists(frame().destroyed_execution_sets, exec_set)); + frame().destroyed_execution_sets.push_back(exec_set); +} + +void Device::destroy_descriptor_pool_nolock(VkDescriptorPool desc_pool) +{ + VK_ASSERT(!exists(frame().destroyed_descriptor_pools, desc_pool)); + frame().destroyed_descriptor_pools.push_back(desc_pool); +} + +void Device::destroy_sampler_nolock(VkSampler sampler) +{ + VK_ASSERT(!exists(frame().destroyed_samplers, sampler)); + frame().destroyed_samplers.push_back(sampler); +} + +void Device::destroy_framebuffer_nolock(VkFramebuffer framebuffer) +{ + VK_ASSERT(!exists(frame().destroyed_framebuffers, framebuffer)); + frame().destroyed_framebuffers.push_back(framebuffer); +} + +void Device::wait_idle() +{ + DRAIN_FRAME_LOCK(); + wait_idle_nolock(); +} + +void Device::wait_idle_nolock() +{ + if (!per_frame.empty()) + end_frame_nolock(); + + if (device != VK_NULL_HANDLE) + { + if (queue_lock_callback) + queue_lock_callback(); + auto result = table->vkDeviceWaitIdle(device); + if (result != VK_SUCCESS) + LOGE("vkDeviceWaitIdle failed with code: %d\n", result); + if (queue_unlock_callback) + queue_unlock_callback(); + } + + // Free memory for buffer pools. + managers.vbo.reset(); + managers.ubo.reset(); + managers.ibo.reset(); + managers.staging.reset(); + for (auto &frame : per_frame) + { + frame->vbo_blocks.clear(); + frame->ibo_blocks.clear(); + frame->ubo_blocks.clear(); + frame->staging_blocks.clear(); + } + + framebuffer_allocator.clear(); + transient_allocator.clear(); + + if (!ext.supports_descriptor_buffer_or_heap) + { + for (auto &allocator: descriptor_set_allocators.get_read_only()) + allocator.clear(); + for (auto &allocator: descriptor_set_allocators.get_read_write()) + allocator.clear(); + } + + for (auto &frame : per_frame) + { + frame->begin(); + frame->trim_command_pools(); + } + + { + LOCK_MEMORY(); + managers.memory.garbage_collect(); + } +} + +void Device::promote_read_write_caches_to_read_only() +{ + // Components which could potentially call into these must hold global reader locks. + // - A CommandBuffer holds a read lock for its lifetime. + // - Fossilize replay in the background also holds lock. + if (lock.read_only_cache.try_lock_write()) + { + pipeline_layouts.move_to_read_only(); + descriptor_set_allocators.move_to_read_only(); + shaders.move_to_read_only(); + programs.move_to_read_only(); + for (auto &program : programs.get_read_only()) + program.promote_read_write_to_read_only(); + render_passes.move_to_read_only(); + immutable_samplers.move_to_read_only(); + immutable_ycbcr_conversions.move_to_read_only(); +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + shader_manager.promote_read_write_caches_to_read_only(); +#endif + lock.read_only_cache.unlock_write(); + } +} + +void Device::set_enable_async_thread_frame_context(bool enable) +{ + LOCK(); + lock.async_frame_context = enable; +} + +void Device::next_frame_context_in_async_thread() +{ + bool do_next_frame_context; + { + LOCK(); + do_next_frame_context = lock.async_frame_context; + } + + if (do_next_frame_context) + next_frame_context(); +} + +bool Device::next_frame_context_is_non_blocking() +{ + DRAIN_FRAME_LOCK(); + + uint32_t next_context = frame_context_index + 1; + if (next_context >= per_frame.size()) + next_context = 0; + + return per_frame[next_context]->wait(0); +} + +void Device::next_frame_context() +{ + DRAIN_FRAME_LOCK(); + + if (frame_context_begin_ts) + { + auto frame_context_end_ts = write_calibrated_timestamp_nolock(); + register_time_interval_nolock("CPU", std::move(frame_context_begin_ts), std::move(frame_context_end_ts), "command submissions"); + frame_context_begin_ts = {}; + } + + // Flush the frame here as we might have pending staging command buffers from init stage. + end_frame_nolock(); + + framebuffer_allocator.begin_frame(); + transient_allocator.begin_frame(); + + if (!ext.supports_descriptor_buffer_or_heap) + { + for (auto &allocator: descriptor_set_allocators.get_read_only()) + allocator.begin_frame(); + for (auto &allocator: descriptor_set_allocators.get_read_write()) + allocator.begin_frame(); + } + + VK_ASSERT(!per_frame.empty()); + frame_context_index++; + if (frame_context_index >= per_frame.size()) + frame_context_index = 0; + + promote_read_write_caches_to_read_only(); + + frame().begin(); + recalibrate_timestamps(); + frame_context_begin_ts = write_calibrated_timestamp_nolock(); +} + +QueryPoolHandle Device::write_timestamp(VkCommandBuffer cmd, VkPipelineStageFlags2 stage) +{ + LOCK(); + return write_timestamp_nolock(cmd, stage); +} + +QueryPoolHandle Device::write_timestamp_nolock(VkCommandBuffer cmd, VkPipelineStageFlags2 stage) +{ + return frame().query_pool_ts.write_timestamp(cmd, stage); +} + +QueryPoolHandle Device::write_calibrated_timestamp() +{ + LOCK(); + return write_calibrated_timestamp_nolock(); +} + +QueryPoolHandle Device::write_calibrated_timestamp_nolock() +{ + if (!system_handles.timeline_trace_file) + return {}; + + auto handle = QueryPoolHandle(handle_pool.query.allocate( + this, false, VK_QUERY_TYPE_TIMESTAMP, VK_NULL_HANDLE, 0)); + handle->signal_value(get_current_time_nsecs()); + return handle; +} + +void Device::init_calibrated_timestamps() +{ + calibrated_time_domain = VK_TIME_DOMAIN_DEVICE_KHR; + if (!get_device_features().supports_calibrated_timestamps) + return; + + uint32_t count; + vkGetPhysicalDeviceCalibrateableTimeDomainsKHR(gpu, &count, nullptr); + std::vector domains(count); + if (vkGetPhysicalDeviceCalibrateableTimeDomainsKHR(gpu, &count, domains.data()) != VK_SUCCESS) + return; + + bool supports_device_domain = false; + for (auto &domain : domains) + { + if (domain == VK_TIME_DOMAIN_DEVICE_KHR) + { + supports_device_domain = true; + break; + } + } + + if (!supports_device_domain) + return; + + for (auto &domain : domains) + { +#ifdef _WIN32 + const auto supported_domain = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR; +#else + const auto supported_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR; +#endif + if (domain == supported_domain) + { + calibrated_time_domain = domain; + break; + } + } + + if (calibrated_time_domain == VK_TIME_DOMAIN_DEVICE_KHR) + { + LOGE("Could not find a suitable time domain for calibrated timestamps.\n"); + return; + } + + if (!resample_calibrated_timestamps()) + { + LOGE("Failed to get calibrated timestamps.\n"); + calibrated_time_domain = VK_TIME_DOMAIN_DEVICE_KHR; + return; + } +} + +bool Device::resample_calibrated_timestamps() +{ + VkCalibratedTimestampInfoKHR infos[2] = {}; + infos[0].sType = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_KHR; + infos[1].sType = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_KHR; + infos[0].timeDomain = calibrated_time_domain; + infos[1].timeDomain = VK_TIME_DOMAIN_DEVICE_KHR; + uint64_t timestamps[2] = {}; + uint64_t max_deviation; + + if (table->vkGetCalibratedTimestampsKHR(device, 2, infos, timestamps, &max_deviation) != VK_SUCCESS) + { + LOGE("Failed to get calibrated timestamps.\n"); + calibrated_time_domain = VK_TIME_DOMAIN_DEVICE_KHR; + return false; + } + + calibrated_timestamp_host = timestamps[0]; + calibrated_timestamp_device = timestamps[1]; + calibrated_timestamp_device_accum = calibrated_timestamp_device; + +#ifdef _WIN32 + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + calibrated_timestamp_host = int64_t(1e9 * calibrated_timestamp_host / double(freq.QuadPart)); +#endif + return true; +} + +void Device::recalibrate_timestamps() +{ + if (calibrated_time_domain == VK_TIME_DOMAIN_DEVICE_KHR) + return; + + // Recalibrate every once in a while ... + timestamp_calibration_counter++; + if (timestamp_calibration_counter < 64) + return; + timestamp_calibration_counter = 0; + resample_calibrated_timestamps(); +} + +void Device::register_time_interval(std::string tid, QueryPoolHandle start_ts, QueryPoolHandle end_ts, + const std::string &tag) +{ + LOCK(); + register_time_interval_nolock(std::move(tid), std::move(start_ts), std::move(end_ts), tag); +} + +void Device::register_time_interval_nolock(std::string tid, QueryPoolHandle start_ts, QueryPoolHandle end_ts, + const std::string &tag) +{ + if (start_ts && end_ts) + { + TimestampInterval *timestamp_tag = managers.timestamps.get_timestamp_tag(tag.c_str()); +#ifdef VULKAN_DEBUG + if (start_ts->is_signalled() && end_ts->is_signalled()) + VK_ASSERT(end_ts->get_timestamp_ticks() >= start_ts->get_timestamp_ticks()); +#endif + frame().timestamp_intervals.push_back({ std::move(tid), std::move(start_ts), std::move(end_ts), timestamp_tag }); + } +} + +void Device::add_frame_counter_nolock() +{ + lock.counter++; +} + +void Device::decrement_frame_counter_nolock() +{ + VK_ASSERT(lock.counter > 0); + lock.counter--; + lock.cond.notify_all(); +} + +void Device::PerFrame::trim_command_pools() +{ + for (auto &cmd_pool : cmd_pools) + for (auto &pool : cmd_pool) + pool.trim(); +} + +bool Device::PerFrame::wait(uint64_t timeout) +{ + VkDevice vkdevice = device.get_device(); + bool has_timeline = true; + + for (auto &sem : timeline_semaphores) + { + if (sem == VK_NULL_HANDLE) + { + has_timeline = false; + break; + } + } + + if (device.get_device_features().vk12_features.timelineSemaphore && has_timeline) + { + VkSemaphoreWaitInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO }; + VkSemaphore sems[QUEUE_INDEX_COUNT]; + uint64_t values[QUEUE_INDEX_COUNT]; + for (int i = 0; i < QUEUE_INDEX_COUNT; i++) + { + if (timeline_fences[i]) + { + sems[info.semaphoreCount] = timeline_semaphores[i]; + values[info.semaphoreCount] = timeline_fences[i]; + info.semaphoreCount++; + } + } + + if (info.semaphoreCount) + { + info.pSemaphores = sems; + info.pValues = values; + + if (device.ext.supports_post_mortem && timeout == UINT64_MAX) + { + // Some GPUs just timeout here rather than return device lost in finite time. + VkResult vr = table.vkWaitSemaphores(vkdevice, &info, PostMortemTimeout); + + // Maybe we can read the latched device lost state now. + if (vr == VK_TIMEOUT) + vr = table.vkWaitSemaphores(vkdevice, &info, 0); + + // If GPU doesn't complete in 2 seconds, something has gone very wrong. + if (vr != VK_SUCCESS) + { + managers.breadcrumbs.notify_device_hung(); + return false; + } + } + else + { + if (table.vkWaitSemaphores(vkdevice, &info, timeout) != VK_SUCCESS) + return false; + } + } + } + + // If we're using timeline semaphores, these paths should never be hit (or only for swapchain maintenance1). + if (!wait_and_recycle_fences.empty()) + { + if (device.ext.supports_post_mortem && timeout == UINT64_MAX) + { + // Some GPUs just timeout here rather than return device lost in finite time. + VkResult vr = table.vkWaitForFences(vkdevice, wait_and_recycle_fences.size(), wait_and_recycle_fences.data(), VK_TRUE, PostMortemTimeout); + + // Maybe we can read the latched device lost state now. + if (vr == VK_TIMEOUT) + vr = table.vkWaitForFences(vkdevice, wait_and_recycle_fences.size(), wait_and_recycle_fences.data(), VK_TRUE, 0); + + // If GPU doesn't complete in 2 seconds, something has gone very wrong. + if (vr != VK_SUCCESS) + { + managers.breadcrumbs.notify_device_hung(); + return false; + } + } + + if (table.vkWaitForFences(vkdevice, wait_and_recycle_fences.size(), wait_and_recycle_fences.data(), VK_TRUE, timeout) != VK_SUCCESS) + return false; + table.vkResetFences(vkdevice, wait_and_recycle_fences.size(), wait_and_recycle_fences.data()); + for (auto &fence : wait_and_recycle_fences) + managers.fence.recycle_fence(fence); + wait_and_recycle_fences.clear(); + } + + return true; +} + +void Device::PerFrame::begin() +{ + VkDevice vkdevice = device.get_device(); + + Vulkan::QueryPoolHandle wait_fence_ts; + if (!in_destructor) + wait_fence_ts = device.write_calibrated_timestamp_nolock(); + + wait(UINT64_MAX); + + for (auto &cmd_pool : cmd_pools) + for (auto &pool : cmd_pool) + pool.begin(); + + query_pool_ts.begin(); + query_pool_rtas.begin(); + + for (auto &channel : debug_channels) + device.parse_debug_channel(channel); + + // Free the debug channel buffers here, and they will immediately be recycled by the destroyed_buffers right below. + debug_channels.clear(); + + for (auto &block : vbo_blocks) + managers.vbo.recycle_block(block); + for (auto &block : ibo_blocks) + managers.ibo.recycle_block(block); + for (auto &block : ubo_blocks) + managers.ubo.recycle_block(block); + for (auto &block : staging_blocks) + managers.staging.recycle_block(block); + vbo_blocks.clear(); + ibo_blocks.clear(); + ubo_blocks.clear(); + staging_blocks.clear(); + + for (auto &framebuffer : destroyed_framebuffers) + table.vkDestroyFramebuffer(vkdevice, framebuffer, nullptr); + for (auto &sampler : destroyed_samplers) + managers.descriptor_buffer.destroy_sampler(sampler); + for (auto &view : destroyed_image_views) + managers.descriptor_buffer.free_image_view(view); + for (auto &view : destroyed_buffer_views) + managers.descriptor_buffer.free_buffer_view(view); + for (auto &image : destroyed_images) + table.vkDestroyImage(vkdevice, image, nullptr); + for (auto &rtas : destroyed_rtas) + table.vkDestroyAccelerationStructureKHR(vkdevice, rtas, nullptr); + for (auto &buffer : destroyed_buffers) + table.vkDestroyBuffer(vkdevice, buffer, nullptr); + for (auto &semaphore : destroyed_semaphores) + table.vkDestroySemaphore(vkdevice, semaphore, nullptr); + for (auto &pool : destroyed_descriptor_pools) + table.vkDestroyDescriptorPool(vkdevice, pool, nullptr); + for (auto &exec_set : destroyed_execution_sets) + table.vkDestroyIndirectExecutionSetEXT(vkdevice, exec_set, nullptr); + for (auto &semaphore : recycled_semaphores) + managers.semaphore.recycle(semaphore); + for (auto &event : recycled_events) + managers.event.recycle(event); + managers.descriptor_buffer.free(descriptor_buffer_allocs.data(), descriptor_buffer_allocs.size()); + managers.descriptor_buffer.free_cached_descriptors( + cached_descriptor_payloads.data(), cached_descriptor_payloads.size()); + for (auto &crumb : breadcrumbs) + managers.breadcrumbs.free_command_buffer(crumb); + VK_ASSERT(consumed_semaphores.empty()); + + if (!allocations.empty()) + { + std::lock_guard holder{device.lock.memory_lock}; + for (auto &alloc : allocations) + alloc.free_immediate(managers.memory); + } + + destroyed_framebuffers.clear(); + destroyed_samplers.clear(); + destroyed_image_views.clear(); + destroyed_buffer_views.clear(); + destroyed_images.clear(); + destroyed_buffers.clear(); + destroyed_rtas.clear(); + destroyed_execution_sets.clear(); + destroyed_semaphores.clear(); + destroyed_descriptor_pools.clear(); + recycled_semaphores.clear(); + recycled_events.clear(); + allocations.clear(); + descriptor_buffer_allocs.clear(); + cached_descriptor_payloads.clear(); + breadcrumbs.clear(); + + if (!in_destructor) + device.register_time_interval_nolock("CPU", std::move(wait_fence_ts), device.write_calibrated_timestamp_nolock(), "fence + recycle"); + + int64_t min_timestamp_us = std::numeric_limits::max(); + int64_t max_timestamp_us = 0; + + for (auto &ts : timestamp_intervals) + { + if (ts.end_ts->is_signalled() && ts.start_ts->is_signalled()) + { + VK_ASSERT(ts.start_ts->is_device_timebase() == ts.end_ts->is_device_timebase()); + + int64_t start_ts = ts.start_ts->get_timestamp_ticks(); + int64_t end_ts = ts.end_ts->get_timestamp_ticks(); + if (ts.start_ts->is_device_timebase()) + ts.timestamp_tag->accumulate_time(device.convert_device_timestamp_delta(start_ts, end_ts)); + else + ts.timestamp_tag->accumulate_time(1e-9 * double(end_ts - start_ts)); + + if (device.system_handles.timeline_trace_file) + { + start_ts = device.convert_timestamp_to_absolute_nsec(*ts.start_ts); + end_ts = device.convert_timestamp_to_absolute_nsec(*ts.end_ts); + min_timestamp_us = (std::min)(min_timestamp_us, start_ts); + max_timestamp_us = (std::max)(max_timestamp_us, end_ts); + + auto *e = device.system_handles.timeline_trace_file->allocate_event(); + e->set_desc(ts.timestamp_tag->get_tag().c_str()); + e->set_tid(ts.tid.c_str()); + e->pid = frame_index + 1; + e->start_ns = start_ts; + e->end_ns = end_ts; + device.system_handles.timeline_trace_file->submit_event(e); + } + } + } + + if (device.system_handles.timeline_trace_file && min_timestamp_us <= max_timestamp_us) + { + auto *e = device.system_handles.timeline_trace_file->allocate_event(); + e->set_desc("CPU + GPU full frame"); + e->set_tid("Frame context"); + e->pid = frame_index + 1; + e->start_ns = min_timestamp_us; + e->end_ns = max_timestamp_us; + device.system_handles.timeline_trace_file->submit_event(e); + } + + managers.timestamps.mark_end_of_frame_context(); + timestamp_intervals.clear(); +} + +Device::PerFrame::~PerFrame() +{ + in_destructor = true; + begin(); +} + +uint32_t Device::find_memory_type(uint32_t required, uint32_t mask) const +{ + uint32_t valid_device_local_mask = 0; + uint32_t valid_mask = 0; + + for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) + { + if (((1u << i) & mask) != 0) + { + uint32_t flags = mem_props.memoryTypes[i].propertyFlags; + if ((flags & required) == required) + { + valid_mask |= 1u << i; + if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) + valid_device_local_mask |= 1u << i; + } + } + } + + // If we don't request device local, try to avoid it. + // Avoids a quirk of NVK where we end up allocating device memory instead since DEVICE | COHERENT + // appears before COHERENT | CACHED. + if ((required & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0 && valid_mask != valid_device_local_mask) + valid_mask &= ~valid_device_local_mask; + + if (valid_mask != 0) + return Util::trailing_zeroes(valid_mask); + else + return UINT32_MAX; +} + +uint32_t Device::find_memory_type(BufferDomain domain, uint32_t mask) const +{ + uint32_t prio[3] = {}; + + // Optimize for tracing apps by not allocating host memory that is uncached. + if (workarounds.force_host_cached) + { + switch (domain) + { + case BufferDomain::LinkedDeviceHostPreferDevice: + domain = BufferDomain::Device; + break; + + case BufferDomain::LinkedDeviceHost: + case BufferDomain::Host: + case BufferDomain::CachedCoherentHostPreferCoherent: + domain = BufferDomain::CachedCoherentHostPreferCached; + break; + + default: + break; + } + } + + switch (domain) + { + case BufferDomain::Device: + prio[0] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + break; + + case BufferDomain::LinkedDeviceHost: + prio[0] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + prio[1] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + prio[2] = prio[1]; + break; + + case BufferDomain::LinkedDeviceHostPreferDevice: + prio[0] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + prio[1] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + prio[2] = prio[1]; + break; + + case BufferDomain::Host: + prio[0] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + prio[1] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + prio[2] = prio[1]; + break; + + case BufferDomain::CachedHost: + prio[0] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + prio[1] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + prio[2] = prio[1]; + break; + + case BufferDomain::CachedCoherentHostPreferCached: + prio[0] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + prio[1] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + prio[2] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + break; + + case BufferDomain::CachedCoherentHostPreferCoherent: + prio[0] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + prio[1] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + prio[2] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + break; + + case BufferDomain::UMACachedCoherentPreferDevice: + prio[0] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_CACHED_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + prio[1] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + + // On iGPU, we expect to find a UMA type, but RADV tends to report split heaps on iGPU for app compat reasons. + // If the device type is integrated we just assume that host visible memory isn't meaningfully slower than + // "device local" memory. + if (gpu_props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) + prio[2] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + else + prio[2] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + + break; + + case BufferDomain::DebugReadback: + if (!ext.supports_amd_buffer_marker) + return UINT32_MAX; + + prio[1] = VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD | VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD | + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + prio[0] = prio[0] | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + prio[2] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + break; + } + + for (auto &p : prio) + { + uint32_t index = find_memory_type(p, mask); + if (index != UINT32_MAX) + return index; + } + + return UINT32_MAX; +} + +uint32_t Device::find_memory_type(ImageDomain domain, uint32_t mask) const +{ + uint32_t desired = 0, fallback = 0; + switch (domain) + { + case ImageDomain::Physical: + desired = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + fallback = 0; + break; + + case ImageDomain::Transient: + desired = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; + fallback = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + break; + + case ImageDomain::LinearHostCached: + desired = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + fallback = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + break; + + case ImageDomain::LinearHost: + desired = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + fallback = 0; + break; + + case ImageDomain::LinearDevice: + desired = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + fallback = 0; + break; + + case ImageDomain::HostCopy: + desired = 0; + fallback = 0; + break; + } + + uint32_t index = find_memory_type(desired, mask); + if (index != UINT32_MAX) + return index; + + index = find_memory_type(fallback, mask); + if (index != UINT32_MAX) + return index; + + return UINT32_MAX; +} + +static inline VkImageViewType get_image_view_type(const ImageCreateInfo &create_info, const ImageViewCreateInfo *view) +{ + unsigned layers = view ? view->layers : create_info.layers; + unsigned base_layer = view ? view->base_layer : 0; + + if (layers == VK_REMAINING_ARRAY_LAYERS) + layers = create_info.layers - base_layer; + + bool force_array = + view ? (view->misc & IMAGE_VIEW_MISC_FORCE_ARRAY_BIT) : (create_info.misc & IMAGE_MISC_FORCE_ARRAY_BIT); + + switch (create_info.type) + { + case VK_IMAGE_TYPE_1D: + VK_ASSERT(create_info.width >= 1); + VK_ASSERT(create_info.height == 1); + VK_ASSERT(create_info.depth == 1); + VK_ASSERT(create_info.samples == VK_SAMPLE_COUNT_1_BIT); + + if (layers > 1 || force_array) + return VK_IMAGE_VIEW_TYPE_1D_ARRAY; + else + return VK_IMAGE_VIEW_TYPE_1D; + + case VK_IMAGE_TYPE_2D: + VK_ASSERT(create_info.width >= 1); + VK_ASSERT(create_info.height >= 1); + VK_ASSERT(create_info.depth == 1); + + if ((create_info.flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && (layers % 6) == 0) + { + VK_ASSERT(create_info.width == create_info.height); + + if (layers > 6 || force_array) + return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; + else + return VK_IMAGE_VIEW_TYPE_CUBE; + } + else + { + if (layers > 1 || force_array) + return VK_IMAGE_VIEW_TYPE_2D_ARRAY; + else + return VK_IMAGE_VIEW_TYPE_2D; + } + + case VK_IMAGE_TYPE_3D: + VK_ASSERT(create_info.width >= 1); + VK_ASSERT(create_info.height >= 1); + VK_ASSERT(create_info.depth >= 1); + return VK_IMAGE_VIEW_TYPE_3D; + + default: + VK_ASSERT(0 && "bogus"); + return VK_IMAGE_VIEW_TYPE_MAX_ENUM; + } +} + +BufferViewHandle Device::create_buffer_view(const BufferViewCreateInfo &view_info) +{ + CachedBufferView view; + if (!managers.descriptor_buffer.create_buffer_view(view_info, view)) + return BufferViewHandle(nullptr); + return BufferViewHandle(handle_pool.buffer_views.allocate(this, view, view_info)); +} + +class ImageResourceHolder +{ +public: + explicit ImageResourceHolder(Device *device_) + : device(device_) + , table(device_->get_device_table()) + { + } + + ~ImageResourceHolder() + { + if (owned) + cleanup(); + } + + Device *device; + const VolkDeviceTable &table; + + VkImage image = VK_NULL_HANDLE; + VkDeviceMemory memory = VK_NULL_HANDLE; + CachedImageView image_view = {}; + CachedImageView depth_view = {}; + CachedImageView stencil_view = {}; + CachedImageView unorm_view = {}; + CachedImageView srgb_view = {}; + VkImageViewType default_view_type = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + std::vector rt_views; + std::vector mip_views; + DeviceAllocation allocation; + DeviceAllocator *allocator = nullptr; + bool owned = true; + + VkImageViewType get_default_view_type() const + { + return default_view_type; + } + + bool setup_conversion_info(VkImageViewCreateInfo &create_info, + VkSamplerYcbcrConversionInfo &conversion, + const ImmutableYcbcrConversion *ycbcr_conversion) const + { + if (ycbcr_conversion) + { + if (!device->get_device_features().vk11_features.samplerYcbcrConversion) + return false; + conversion = { VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO }; + conversion.conversion = ycbcr_conversion->get_conversion(); + conversion.pNext = create_info.pNext; + create_info.pNext = &conversion; + } + + return true; + } + + bool setup_view_usage_info(VkImageViewCreateInfo &create_info, VkImageUsageFlags usage, + VkImageUsageFlags &view_usage) const + { + view_usage = usage; + view_usage &= VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | + image_usage_video_flags; + + if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) + { + VkFormatProperties3 props3 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 }; + device->get_format_properties(create_info.format, &props3); + if ((props3.optimalTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT) == 0) + view_usage &= ~VK_IMAGE_USAGE_STORAGE_BIT; + } + + return true; + } + + bool setup_astc_decode_mode_info(VkImageViewCreateInfo &create_info, VkImageViewASTCDecodeModeEXT &astc_info) const + { + if (!device->get_device_features().supports_astc_decode_mode) + return true; + + auto type = format_compression_type(create_info.format); + if (type != FormatCompressionType::ASTC) + return true; + + if (format_is_srgb(create_info.format)) + return true; + + if (format_is_compressed_hdr(create_info.format)) + { + if (device->get_device_features().astc_decode_features.decodeModeSharedExponent) + astc_info.decodeMode = VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; + else + astc_info.decodeMode = VK_FORMAT_R16G16B16A16_SFLOAT; + } + else + { + astc_info.decodeMode = VK_FORMAT_R8G8B8A8_UNORM; + } + + astc_info.pNext = create_info.pNext; + create_info.pNext = &astc_info; + return true; + } + + bool create_default_views(const ImageCreateInfo &create_info, const VkImageViewCreateInfo *view_info, + const ImmutableYcbcrConversion *ycbcr_conversion, + bool create_unorm_srgb_views = false, bool create_mip_level_views = false, + const VkFormat *view_formats = nullptr) + { + if ((create_info.usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | + image_usage_video_flags)) == 0) + { + LOGE("Cannot create image view unless certain usage flags are present.\n"); + return false; + } + + VkImageViewCreateInfo default_view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + VkSamplerYcbcrConversionInfo conversion_info = { VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO }; + VkImageViewASTCDecodeModeEXT astc_decode_mode_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT }; + VkImageUsageFlags view_usage = 0; + + if (!view_info) + { + default_view_info.image = image; + default_view_info.format = create_info.format; + default_view_info.components = create_info.swizzle; + default_view_info.subresourceRange.aspectMask = format_to_aspect_mask(default_view_info.format); + default_view_info.viewType = get_image_view_type(create_info, nullptr); + default_view_info.subresourceRange.baseMipLevel = 0; + default_view_info.subresourceRange.baseArrayLayer = 0; + default_view_info.subresourceRange.levelCount = create_info.levels; + default_view_info.subresourceRange.layerCount = create_info.layers; + + default_view_type = default_view_info.viewType; + } + else + default_view_info = *view_info; + + view_info = &default_view_info; + if (!setup_conversion_info(default_view_info, conversion_info, ycbcr_conversion)) + return false; + + if (!setup_view_usage_info(default_view_info, create_info.usage, view_usage)) + return false; + + if (!setup_astc_decode_mode_info(default_view_info, astc_decode_mode_info)) + return false; + + if (!create_alt_views(*view_info, create_info.layout, view_usage)) + return false; + + if (!create_render_target_views(*view_info, create_info.layout, view_usage)) + return false; + + if (!create_default_view(*view_info, create_info.layout, view_usage)) + return false; + + if (create_unorm_srgb_views) + { + auto info = *view_info; + auto srgb_unorm_usage = view_usage; + + if (create_info.usage & VK_IMAGE_USAGE_STORAGE_BIT) + srgb_unorm_usage |= VK_IMAGE_USAGE_STORAGE_BIT; + info.format = view_formats[0]; + if (!device->managers.descriptor_buffer.create_image_view(info, srgb_unorm_usage, create_info.layout, unorm_view)) + return false; + + srgb_unorm_usage &= ~VK_IMAGE_USAGE_STORAGE_BIT; + info.format = view_formats[1]; + if (!device->managers.descriptor_buffer.create_image_view(info, srgb_unorm_usage, create_info.layout, srgb_view)) + return false; + } + + if (create_mip_level_views && !create_mip_views(*view_info, create_info.layout, view_usage)) + return false; + + return true; + } + +private: + bool create_render_target_views(const VkImageViewCreateInfo &info, ImageLayout layout, VkImageUsageFlags view_usage) + { + if (info.viewType == VK_IMAGE_VIEW_TYPE_3D) + return true; + + constexpr VkImageUsageFlags render_target_usage = + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + // If we have a render target, and non-trivial case (layers = 1, levels = 1), + // create an array of render targets which correspond to each layer (mip 0). + if ((view_usage & render_target_usage) != 0 && + ((info.subresourceRange.levelCount > 1) || (info.subresourceRange.layerCount > 1))) + { + rt_views.reserve(info.subresourceRange.layerCount); + view_usage &= render_target_usage; + + auto view_info = info; + view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_info.subresourceRange.baseMipLevel = info.subresourceRange.baseMipLevel; + for (uint32_t layer = 0; layer < info.subresourceRange.layerCount; layer++) + { + view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.layerCount = 1; + view_info.subresourceRange.baseArrayLayer = layer + info.subresourceRange.baseArrayLayer; + + CachedImageView rt_view = {}; + if (!device->managers.descriptor_buffer.create_image_view(view_info, view_usage, layout, rt_view)) + return false; + rt_views.push_back(rt_view); + } + } + + return true; + } + + bool create_mip_views(const VkImageViewCreateInfo &info, ImageLayout layout, VkImageUsageFlags view_usage) + { + VK_ASSERT(info.subresourceRange.levelCount != VK_REMAINING_MIP_LEVELS); + if (info.subresourceRange.levelCount <= 1) + return true; + mip_views.reserve(info.subresourceRange.levelCount); + + view_usage &= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT; + auto view_info = info; + + for (unsigned level = 0; level < info.subresourceRange.levelCount; level++) + { + view_info.subresourceRange.baseMipLevel = level; + view_info.subresourceRange.levelCount = 1; + + CachedImageView mip_view = {}; + if (!device->managers.descriptor_buffer.create_image_view(view_info, view_usage, layout, mip_view)) + return false; + mip_views.push_back(mip_view); + } + + return true; + } + + bool create_alt_views(const VkImageViewCreateInfo &info, ImageLayout layout, VkImageUsageFlags view_usage) + { + if (info.viewType == VK_IMAGE_VIEW_TYPE_CUBE || + info.viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY || + info.viewType == VK_IMAGE_VIEW_TYPE_3D) + { + return true; + } + + constexpr VkImageUsageFlags sampled_usage = + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + + if (info.subresourceRange.aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) && + (view_usage & sampled_usage) != 0) + { + auto view_info = info; + view_usage &= sampled_usage; + + // We need this to be able to sample the texture, or otherwise use it as a non-pure DS attachment. + view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (!device->managers.descriptor_buffer.create_image_view(view_info, view_usage, layout, depth_view)) + return false; + + view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + if (!device->managers.descriptor_buffer.create_image_view(view_info, view_usage, layout, stencil_view)) + return false; + } + + return true; + } + + bool create_default_view(const VkImageViewCreateInfo &info, ImageLayout layout, VkImageUsageFlags usage) + { + // Create the normal image view. This one contains every subresource. + return device->managers.descriptor_buffer.create_image_view(info, usage, layout, image_view); + } + + void cleanup() + { + auto &m = device->managers.descriptor_buffer; + m.free_image_view(image_view); + m.free_image_view(depth_view); + m.free_image_view(stencil_view); + m.free_image_view(unorm_view); + m.free_image_view(srgb_view); + for (auto &view : rt_views) + m.free_image_view(view); + for (auto &view : mip_views) + m.free_image_view(view); + + VkDevice vkdevice = device->get_device(); + + if (image) + table.vkDestroyImage(vkdevice, image, nullptr); + if (memory) + table.vkFreeMemory(vkdevice, memory, nullptr); + if (allocator) + allocation.free_immediate(*allocator); + } +}; + +ImageViewHandle Device::create_image_view(const ImageViewCreateInfo &create_info) +{ + ImageResourceHolder holder(this); + auto &image_create_info = create_info.image->get_create_info(); + + VkFormat format = create_info.format != VK_FORMAT_UNDEFINED ? create_info.format : image_create_info.format; + + VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + view_info.image = create_info.image->get_image(); + view_info.format = format; + view_info.components = create_info.swizzle; + view_info.subresourceRange.aspectMask = + create_info.aspect ? create_info.aspect : format_to_aspect_mask(format); + view_info.subresourceRange.baseMipLevel = create_info.base_level; + view_info.subresourceRange.baseArrayLayer = create_info.base_layer; + view_info.subresourceRange.levelCount = create_info.levels; + view_info.subresourceRange.layerCount = create_info.layers; + + if (create_info.view_type == VK_IMAGE_VIEW_TYPE_MAX_ENUM) + view_info.viewType = get_image_view_type(image_create_info, &create_info); + else + view_info.viewType = create_info.view_type; + + unsigned num_levels; + if (view_info.subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS) + num_levels = create_info.image->get_create_info().levels - view_info.subresourceRange.baseMipLevel; + else + num_levels = view_info.subresourceRange.levelCount; + + unsigned num_layers; + if (view_info.subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS) + num_layers = create_info.image->get_create_info().layers - view_info.subresourceRange.baseArrayLayer; + else + num_layers = view_info.subresourceRange.layerCount; + + view_info.subresourceRange.levelCount = num_levels; + view_info.subresourceRange.layerCount = num_layers; + + if (!holder.create_default_views(image_create_info, &view_info, + create_info.ycbcr_conversion)) + { + return ImageViewHandle(nullptr); + } + + ImageViewCreateInfo tmp = create_info; + tmp.format = format; + ImageViewHandle ret(handle_pool.image_views.allocate(this, holder.image_view, tmp)); + if (ret) + { + holder.owned = false; + ret->set_separate_depth_stencil_views(holder.depth_view, holder.stencil_view); + ret->set_render_target_views(std::move(holder.rt_views)); + ret->set_mip_views(std::move(holder.mip_views)); + return ret; + } + else + return ImageViewHandle(nullptr); +} + +InitialImageBuffer Device::create_image_staging_buffer(const TextureFormatLayout &layout) +{ + InitialImageBuffer result = {}; + result.host = { layout.data(), layout.get_required_size() }; + layout.build_buffer_image_copies(result.blits); + return result; +} + +InitialImageBuffer Device::create_image_staging_buffer(const ImageCreateInfo &info, const ImageInitialData *initial) +{ + // This method is very annoying to deal with and requires shuffling a lot of data around. + // Plumbing this through to host image copy is a hot mess and is avoided. + + InitialImageBuffer result = {}; + + bool generate_mips = (info.misc & IMAGE_MISC_GENERATE_MIPS_BIT) != 0; + TextureFormatLayout layout; + + unsigned copy_levels; + if (generate_mips) + copy_levels = 1; + else if (info.levels == 0) + copy_levels = TextureFormatLayout::num_miplevels(info.width, info.height, info.depth); + else + copy_levels = info.levels; + + switch (info.type) + { + case VK_IMAGE_TYPE_1D: + layout.set_1d(info.format, info.width, info.layers, copy_levels); + break; + case VK_IMAGE_TYPE_2D: + layout.set_2d(info.format, info.width, info.height, info.layers, copy_levels); + break; + case VK_IMAGE_TYPE_3D: + layout.set_3d(info.format, info.width, info.height, info.depth, copy_levels); + break; + default: + return {}; + } + + if (copy_levels == 1 && info.layers == 1) + { + result.host = { initial[0].data, layout.get_required_size() }; + layout.build_buffer_image_copies(result.blits); + auto &blit = result.blits.front(); + const auto &mip_info = layout.get_mip_info(0); + + // Adjust the blit in case it's not tightly packed. + uint32_t src_row_length = + initial[0].row_length ? initial[0].row_length : mip_info.row_length; + uint32_t src_array_height = + initial[0].image_height ? initial[0].image_height : mip_info.image_height; + + result.host.size = format_get_layer_size( + info.format, blit.imageSubresource.aspectMask, src_row_length, src_array_height, info.depth); + + blit.bufferOffset = 0; + blit.bufferRowLength = src_row_length; + blit.bufferImageHeight = src_array_height; + return result; + } + + BufferCreateInfo buffer_info = {}; + buffer_info.domain = BufferDomain::Host; + buffer_info.size = layout.get_required_size(); + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + { + GRANITE_SCOPED_TIMELINE_EVENT_FILE(system_handles.timeline_trace_file, "allocate-image-staging-buffer"); + result.buffer = create_buffer(buffer_info, nullptr); + } + set_name(*result.buffer, "image-upload-staging-buffer"); + + // And now, do the actual copy. + auto *mapped = static_cast(map_host_buffer(*result.buffer, MEMORY_ACCESS_WRITE_BIT)); + unsigned index = 0; + + layout.set_buffer(mapped, layout.get_required_size()); + + GRANITE_SCOPED_TIMELINE_EVENT_FILE(system_handles.timeline_trace_file, "copy-image-staging-buffer"); + for (unsigned level = 0; level < copy_levels; level++) + { + const auto &mip_info = layout.get_mip_info(level); + uint32_t dst_height_stride = layout.get_layer_size(level); + size_t row_size = layout.get_row_size(level); + + for (unsigned layer = 0; layer < info.layers; layer++, index++) + { + uint32_t src_row_length = + initial[index].row_length ? initial[index].row_length : mip_info.row_length; + uint32_t src_array_height = + initial[index].image_height ? initial[index].image_height : mip_info.image_height; + + uint32_t src_row_stride = layout.row_byte_stride(src_row_length); + uint32_t src_height_stride = layout.layer_byte_stride(src_array_height, src_row_stride); + + auto *dst = static_cast(layout.data(layer, level)); + const auto *src = static_cast(initial[index].data); + + for (uint32_t z = 0; z < mip_info.depth; z++) + for (uint32_t y = 0; y < mip_info.block_image_height; y++) + memcpy(dst + z * dst_height_stride + y * row_size, src + z * src_height_stride + y * src_row_stride, row_size); + } + } + + unmap_host_buffer(*result.buffer, MEMORY_ACCESS_WRITE_BIT); + layout.build_buffer_image_copies(result.blits); + return result; +} + +DeviceAllocationOwnerHandle Device::take_device_allocation_ownership(Image &image) +{ + if ((image.get_create_info().misc & IMAGE_MISC_FORCE_NO_DEDICATED_BIT) == 0) + { + LOGE("Must use FORCE_NO_DEDICATED_BIT to take ownership of memory.\n"); + return DeviceAllocationOwnerHandle{}; + } + + if (!image.get_allocation().alloc || !image.get_allocation().base) + return DeviceAllocationOwnerHandle{}; + + return DeviceAllocationOwnerHandle(handle_pool.allocations.allocate(this, image.take_allocation_ownership())); +} + +DeviceAllocationOwnerHandle Device::allocate_memory(const MemoryAllocateInfo &info) +{ + uint32_t index = find_memory_type(info.required_properties, info.requirements.memoryTypeBits); + if (index == UINT32_MAX) + return {}; + + DeviceAllocation alloc = {}; + { + LOCK_MEMORY(); + if (!managers.memory.allocate_generic_memory(info.requirements.size, info.requirements.alignment, info.mode, + index, &alloc)) + { + return {}; + } + } + return DeviceAllocationOwnerHandle(handle_pool.allocations.allocate(this, alloc)); +} + +void Device::get_memory_budget(HeapBudget *budget) +{ + LOCK_MEMORY(); + managers.memory.get_memory_budget(budget); +} + +ImageHandle Device::create_image(const ImageCreateInfo &create_info, const ImageInitialData *initial) +{ + if (initial) + { + auto staging_buffer = create_image_staging_buffer(create_info, initial); + return create_image_from_staging_buffer(create_info, &staging_buffer); + } + else + return create_image_from_staging_buffer(create_info, nullptr); +} + +bool Device::allocate_image_memory(DeviceAllocation *allocation, const ImageCreateInfo &info, + VkImage image, VkImageTiling tiling, VkImageUsageFlags usage) +{ + if ((info.flags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0 && info.num_memory_aliases == 0) + { + LOGE("Must use memory aliases when creating a DISJOINT planar image.\n"); + return false; + } + + bool use_external = (info.misc & IMAGE_MISC_EXTERNAL_MEMORY_BIT) != 0; + if (use_external && info.num_memory_aliases != 0) + { + LOGE("Cannot use external and memory aliases at the same time.\n"); + return false; + } + + if (use_external && tiling == VK_IMAGE_TILING_LINEAR) + { + LOGE("Cannot use linear tiling with external memory.\n"); + return false; + } + + if (info.num_memory_aliases != 0) + { + *allocation = {}; + + unsigned num_planes = format_ycbcr_num_planes(info.format); + if (info.num_memory_aliases < num_planes) + return false; + + if (num_planes == 1) + { + VkMemoryRequirements reqs; + table->vkGetImageMemoryRequirements(device, image, &reqs); + auto &alias = *info.memory_aliases[0]; + + // Verify we can actually use this aliased allocation. + if ((reqs.memoryTypeBits & (1u << alias.memory_type)) == 0) + return false; + if (reqs.size > alias.size) + return false; + if (((alias.offset + reqs.alignment - 1) & ~(reqs.alignment - 1)) != alias.offset) + return false; + + if (table->vkBindImageMemory(device, image, alias.get_memory(), alias.get_offset()) != VK_SUCCESS) + return false; + } + else + { + VkBindImageMemoryInfo bind_infos[3]; + VkBindImagePlaneMemoryInfo bind_plane_infos[3]; + VK_ASSERT(num_planes <= 3); + + for (unsigned plane = 0; plane < num_planes; plane++) + { + VkMemoryRequirements2 memory_req = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 }; + VkImageMemoryRequirementsInfo2 image_info = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 }; + image_info.image = image; + + VkImagePlaneMemoryRequirementsInfo plane_info = { VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO }; + plane_info.planeAspect = static_cast(VK_IMAGE_ASPECT_PLANE_0_BIT << plane); + image_info.pNext = &plane_info; + + table->vkGetImageMemoryRequirements2(device, &image_info, &memory_req); + auto &reqs = memory_req.memoryRequirements; + auto &alias = *info.memory_aliases[plane]; + + // Verify we can actually use this aliased allocation. + if ((reqs.memoryTypeBits & (1u << alias.memory_type)) == 0) + return false; + if (reqs.size > alias.size) + return false; + if (((alias.offset + reqs.alignment - 1) & ~(reqs.alignment - 1)) != alias.offset) + return false; + + bind_infos[plane] = { VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO }; + bind_infos[plane].image = image; + bind_infos[plane].memory = alias.base; + bind_infos[plane].memoryOffset = alias.offset; + bind_infos[plane].pNext = &bind_plane_infos[plane]; + + bind_plane_infos[plane] = { VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO }; + bind_plane_infos[plane].planeAspect = static_cast(VK_IMAGE_ASPECT_PLANE_0_BIT << plane); + } + + if (table->vkBindImageMemory2(device, num_planes, bind_infos) != VK_SUCCESS) + return false; + } + } + else + { + VkMemoryRequirements reqs; + table->vkGetImageMemoryRequirements(device, image, &reqs); + + // If we intend to alias with other images bump the alignment to something very high. + // This is kind of crude, but should be high enough to allow YCbCr disjoint aliasing on any implementation. + if (info.flags & VK_IMAGE_CREATE_ALIAS_BIT) + if (reqs.alignment < 64 * 1024) + reqs.alignment = 64 * 1024; + + auto domain = (usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT) != 0 ? ImageDomain::HostCopy : info.domain; + uint32_t memory_type = find_memory_type(domain, reqs.memoryTypeBits); + if (memory_type == UINT32_MAX) + { + LOGE("Failed to find memory type.\n"); + return false; + } + + if (tiling == VK_IMAGE_TILING_LINEAR && + (info.misc & IMAGE_MISC_LINEAR_IMAGE_IGNORE_DEVICE_LOCAL_BIT) == 0) + { + // Is it also device local? + if ((mem_props.memoryTypes[memory_type].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) + return false; + } + + ExternalHandle external = info.external; + + AllocationMode mode; + if (use_external) + { + mode = AllocationMode::External; + } + else if (tiling == VK_IMAGE_TILING_OPTIMAL && + (info.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT)) != 0) + { + mode = AllocationMode::OptimalRenderTarget; + } + else + { + mode = tiling == VK_IMAGE_TILING_OPTIMAL || info.domain == ImageDomain::LinearDevice ? + AllocationMode::OptimalResource : AllocationMode::LinearHostMappable; + } + + { + LOCK_MEMORY(); + if (!managers.memory.allocate_image_memory(reqs.size, reqs.alignment, mode, memory_type, image, + (info.misc & IMAGE_MISC_FORCE_NO_DEDICATED_BIT) != 0, allocation, + use_external ? &external : nullptr)) + { + LOGE("Failed to allocate image memory (type %u, size: %u).\n", + unsigned(memory_type), unsigned(reqs.size)); + return false; + } + } + + if (table->vkBindImageMemory(device, image, allocation->get_memory(), + allocation->get_offset()) != VK_SUCCESS) + { + LOGE("Failed to bind image memory.\n"); + return false; + } + } + + return true; +} + +static void add_unique_family(uint32_t *sharing_indices, uint32_t &count, uint32_t family) +{ + if (family == VK_QUEUE_FAMILY_IGNORED) + return; + + for (uint32_t i = 0; i < count; i++) + if (sharing_indices[i] == family) + return; + sharing_indices[count++] = family; +} + +ImageHandle Device::create_image_from_staging_buffer(const ImageCreateInfo &create_info, + const InitialImageBuffer *staging_buffer) +{ + ImageResourceHolder holder(this); + + VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + info.format = create_info.format; + info.extent.width = create_info.width; + info.extent.height = create_info.height; + info.extent.depth = create_info.depth; + info.imageType = create_info.type; + info.mipLevels = create_info.levels; + info.arrayLayers = create_info.layers; + info.samples = create_info.samples; + info.pNext = create_info.pnext; + + if (create_info.domain == ImageDomain::LinearHostCached || + create_info.domain == ImageDomain::LinearHost || + create_info.domain == ImageDomain::LinearDevice) + { + info.tiling = VK_IMAGE_TILING_LINEAR; + info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + } + else + { + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + if ((create_info.misc & IMAGE_MISC_EXTERNAL_MEMORY_BIT) != 0) + { + if (info.initialLayout != VK_IMAGE_LAYOUT_UNDEFINED) + { + LOGE("Cannot use non-undefined initial layout for external memory.\n"); + return {}; + } + + if (create_info.external.memory_handle_type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) + info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; + } + + info.usage = create_info.usage; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + if (create_info.domain == ImageDomain::Transient) + info.usage |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; + + info.flags = create_info.flags; + + if (info.mipLevels == 0) + info.mipLevels = image_num_miplevels(info.extent); + + VkImageFormatListCreateInfo format_info = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO }; + VkFormat view_formats[2]; + format_info.pViewFormats = view_formats; + format_info.viewFormatCount = 2; + bool create_unorm_srgb_views = false; + + if (create_info.misc & IMAGE_MISC_MUTABLE_SRGB_BIT) + { + format_info.viewFormatCount = ImageCreateInfo::compute_view_formats(create_info, view_formats); + if (format_info.viewFormatCount != 0) + { + create_unorm_srgb_views = true; + + const auto *input_format_list = static_cast(info.pNext); + while (input_format_list && input_format_list->sType != VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO) + input_format_list = static_cast(input_format_list->pNext); + + if (ext.supports_image_format_list && !input_format_list) + { + format_info.pNext = info.pNext; + info.pNext = &format_info; + } + } + } + + if ((create_info.misc & IMAGE_MISC_MUTABLE_SRGB_BIT) != 0) + info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + + uint32_t sharing_indices[QUEUE_INDEX_COUNT]; + + uint32_t queue_flags = create_info.misc & (IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT | + IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT | + IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT | + IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_DUPLEX); + bool concurrent_queue = queue_flags != 0 || + staging_buffer != nullptr || + create_info.initial_layout != VK_IMAGE_LAYOUT_UNDEFINED; + + if (concurrent_queue) + { + info.sharingMode = VK_SHARING_MODE_CONCURRENT; + + // If we didn't specify queue usage, + // just enable every queue since we need to use transfer queue for initial upload. + if (staging_buffer && queue_flags == 0) + { + // We never imply video here. + constexpr ImageMiscFlags implicit_queues_all = + IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT | + IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT | + IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT; + + queue_flags |= implicit_queues_all; + } + else if (staging_buffer) + { + // Make sure that these queues are included. + queue_flags |= IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT; + if (create_info.misc & IMAGE_MISC_GENERATE_MIPS_BIT) + queue_flags |= IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT; + } + + struct + { + uint32_t flags; + QueueIndices index; + } static const mappings[] = { + { IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT, QUEUE_INDEX_GRAPHICS }, + { IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT, QUEUE_INDEX_COMPUTE }, + { IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT, QUEUE_INDEX_TRANSFER }, + { IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_DECODE_BIT, QUEUE_INDEX_VIDEO_DECODE }, + { IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_ENCODE_BIT, QUEUE_INDEX_VIDEO_ENCODE }, + }; + + for (auto &m : mappings) + if ((queue_flags & m.flags) != 0) + add_unique_family(sharing_indices, info.queueFamilyIndexCount, queue_info.family_indices[m.index]); + + if (info.queueFamilyIndexCount > 1) + info.pQueueFamilyIndices = sharing_indices; + else + { + info.pQueueFamilyIndices = nullptr; + info.queueFamilyIndexCount = 0; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + } + } + + if (queue_flags == 0) + queue_flags |= IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT; + + VkFormatFeatureFlags check_extra_features = 0; + if ((create_info.misc & IMAGE_MISC_VERIFY_FORMAT_FEATURE_SAMPLED_LINEAR_FILTER_BIT) != 0) + check_extra_features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; + + if (info.tiling == VK_IMAGE_TILING_LINEAR) + { + if (staging_buffer) + return ImageHandle(nullptr); + + // Do some more stringent checks. + if (info.mipLevels > 1) + return ImageHandle(nullptr); + if (info.arrayLayers > 1) + return ImageHandle(nullptr); + if (info.imageType != VK_IMAGE_TYPE_2D) + return ImageHandle(nullptr); + if (info.samples != VK_SAMPLE_COUNT_1_BIT) + return ImageHandle(nullptr); + + VkImageFormatProperties2 props = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 }; + if (!get_image_format_properties(info.format, info.imageType, info.tiling, info.usage, info.flags, info.pNext, &props)) + return ImageHandle(nullptr); + + if (!props.imageFormatProperties.maxArrayLayers || + !props.imageFormatProperties.maxMipLevels || + (info.extent.width > props.imageFormatProperties.maxExtent.width) || + (info.extent.height > props.imageFormatProperties.maxExtent.height) || + (info.extent.depth > props.imageFormatProperties.maxExtent.depth)) + { + return ImageHandle(nullptr); + } + } + + if ((create_info.flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) == 0 && + (!image_format_is_supported(create_info.format, image_usage_to_features(info.usage) | check_extra_features, info.tiling))) + { + LOGE("Format %u is not supported for usage flags!\n", unsigned(create_info.format)); + return ImageHandle(nullptr); + } + + bool use_external = (create_info.misc & IMAGE_MISC_EXTERNAL_MEMORY_BIT) != 0; + if (use_external && create_info.domain != ImageDomain::Physical) + { + LOGE("Must use physical image domain for external memory images.\n"); + return ImageHandle(nullptr); + } + + if (use_external && !ext.supports_external) + { + LOGE("External memory not supported.\n"); + return ImageHandle(nullptr); + } + + VkExternalMemoryImageCreateInfo external_info = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO }; + if (ext.supports_external && use_external) + { + // Ensure that the handle type is supported. + VkImageFormatProperties2 props2 = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 }; + VkExternalImageFormatProperties external_props = + { VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES }; + VkPhysicalDeviceExternalImageFormatInfo external_format_info = + { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO }; + external_format_info.handleType = create_info.external.memory_handle_type; + + VkPhysicalDeviceImageDrmFormatModifierInfoEXT modifier_info = + { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT }; + + VkImageFormatListCreateInfo format_list = {}; + if (const auto *list_info = find_pnext( + info.pNext, VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO)) + { + format_list = *list_info; + format_list.pNext = nullptr; + external_format_info.pNext = &format_list; + } + + if (info.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) + { + modifier_info.pNext = external_format_info.pNext; + external_format_info.pNext = &modifier_info; + + // If we're exporting, we have a list of formats instead. + if (auto *list_info = find_pnext( + info.pNext, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT)) + { + VK_ASSERT(list_info->drmFormatModifierCount != 0); + modifier_info.drmFormatModifier = list_info->pDrmFormatModifiers[0]; + } + else if (auto *drm_info = find_pnext( + info.pNext, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT)) + { + modifier_info.drmFormatModifier = drm_info->drmFormatModifier; + } + else + { + LOGE("Trying to create DRM modifier image without explicit info.\n"); + return ImageHandle(nullptr); + } + + modifier_info.sharingMode = info.sharingMode; + modifier_info.queueFamilyIndexCount = info.queueFamilyIndexCount; + modifier_info.pQueueFamilyIndices = info.pQueueFamilyIndices; + } + + props2.pNext = &external_props; + if (!get_image_format_properties(info.format, info.imageType, info.tiling, + info.usage, info.flags, + &external_format_info, &props2)) + { + LOGE("Image format is not supported for external memory type #%x.\n", + external_format_info.handleType); + return ImageHandle(nullptr); + } + + bool supports_import = (external_props.externalMemoryProperties.externalMemoryFeatures & + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0; + bool supports_export = (external_props.externalMemoryProperties.externalMemoryFeatures & + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0; + + if (!supports_import && create_info.external) + { + LOGE("Attempting to import with handle type #%x, but it is not supported.\n", + create_info.external.memory_handle_type); + return ImageHandle(nullptr); + } + else if (!supports_export && !create_info.external) + { + LOGE("Attempting to export with handle type #%x, but it is not supported.\n", + create_info.external.memory_handle_type); + return ImageHandle(nullptr); + } + + external_info.handleTypes = create_info.external.memory_handle_type; + external_info.pNext = info.pNext; + info.pNext = &external_info; + } + + // FIXME: Is there a more intelligent way to detect if we should be using host image copy? + if (ext.vk14_features.hostImageCopy && staging_buffer && staging_buffer->host.size && + (gpu_props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU || + gpu_props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)) + { + VkHostImageCopyDevicePerformanceQuery query = + { VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY }; + VkImageFormatProperties2 props2 = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 }; + props2.pNext = &query; + + if (get_image_format_properties(info.format, info.imageType, info.tiling, + info.usage | VK_IMAGE_USAGE_HOST_TRANSFER_BIT, + info.flags, info.pNext, &props2)) + { + // If we don't lose compression, go ahead. + if (query.optimalDeviceAccess) + info.usage |= VK_IMAGE_USAGE_HOST_TRANSFER_BIT; + } + } + + bool generate_mips = (create_info.misc & IMAGE_MISC_GENERATE_MIPS_BIT) != 0; + if (staging_buffer && (generate_mips || (info.usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT) == 0)) + info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + + if (table->vkCreateImage(device, &info, nullptr, &holder.image) != VK_SUCCESS) + { + LOGE("Failed to create image in vkCreateImage.\n"); + return ImageHandle(nullptr); + } + + if (!allocate_image_memory(&holder.allocation, create_info, holder.image, info.tiling, info.usage)) + { + LOGE("Failed to allocate memory for image.\n"); + return ImageHandle(nullptr); + } + + auto tmpinfo = create_info; + tmpinfo.usage = info.usage; + tmpinfo.flags = info.flags; + tmpinfo.levels = info.mipLevels; + + if ((info.usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT) != 0) + { + tmpinfo.layout = ImageLayout::General; + if (tmpinfo.initial_layout != VK_IMAGE_LAYOUT_UNDEFINED) + tmpinfo.initial_layout = VK_IMAGE_LAYOUT_GENERAL; + } + + bool has_view = (info.usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | + image_usage_video_flags)) != 0 && + (create_info.misc & IMAGE_MISC_NO_DEFAULT_VIEWS_BIT) == 0; + bool create_mip_views = info.mipLevels > 1 && (create_info.misc & IMAGE_MISC_CREATE_PER_MIP_LEVEL_VIEWS_BIT) != 0; + + VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + if (has_view) + { + if (!holder.create_default_views(tmpinfo, nullptr, create_info.ycbcr_conversion, + create_unorm_srgb_views, create_mip_views, view_formats)) + { + LOCK_MEMORY(); + holder.allocation.free_immediate(managers.memory); + return ImageHandle(nullptr); + } + + view_type = holder.get_default_view_type(); + } + + ImageHandle handle(handle_pool.images.allocate(this, holder.image, holder.image_view, holder.allocation, tmpinfo, view_type)); + if (handle) + { + holder.owned = false; + if (has_view) + { + handle->get_view().set_separate_depth_stencil_views(holder.depth_view, holder.stencil_view); + handle->get_view().set_render_target_views(holder.rt_views); + handle->get_view().set_mip_views(holder.mip_views); + handle->get_view().set_unorm_view(holder.unorm_view); + handle->get_view().set_srgb_view(holder.srgb_view); + } + } + + CommandBufferHandle transition_cmd; + + // Copy initial data to texture. + if (staging_buffer) + { + auto *buffer = staging_buffer->buffer.get(); + + // TODO: If we have host image copy, we can bypass this whole thing. + BufferHandle scratch_buffer; + if (!buffer && (info.usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT) == 0) + { + if (staging_buffer->host.size == 0) + { + LOGE("Must specifiy either host scratch or buffer.\n"); + return ImageHandle(nullptr); + } + + BufferCreateInfo scratch_info = {}; + scratch_info.domain = BufferDomain::Host; + scratch_info.size = staging_buffer->host.size; + scratch_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + scratch_buffer = create_buffer(scratch_info, staging_buffer->host.data); + buffer = scratch_buffer.get(); + } + + VK_ASSERT(create_info.domain != ImageDomain::Transient); + VK_ASSERT(create_info.initial_layout != VK_IMAGE_LAYOUT_UNDEFINED); + + // Now we've used the TRANSFER queue to copy data over to the GPU. + // For mipmapping, we're now moving over to graphics, + // the transfer queue is designed for CPU <-> GPU and that's it. + // For concurrent queue mode, we just need to inject a semaphore. + + CommandBufferHandle transfer_cmd; + + if ((info.usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT) == 0) + { + transfer_cmd = request_command_buffer(CommandBuffer::Type::AsyncTransfer); + + transfer_cmd->image_barrier(*handle, VK_IMAGE_LAYOUT_UNDEFINED, + handle->get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_NONE, 0, VK_PIPELINE_STAGE_2_COPY_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + + transfer_cmd->begin_region("copy-image-to-gpu"); + transfer_cmd->copy_buffer_to_image(*handle, *buffer, + staging_buffer->blits.size(), staging_buffer->blits.data()); + transfer_cmd->end_region(); + } + else + { + VkHostImageLayoutTransitionInfo transition = { VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO }; + transition.image = holder.image; + transition.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + transition.newLayout = VK_IMAGE_LAYOUT_GENERAL; + transition.subresourceRange = { + format_to_aspect_mask(info.format), + 0, VK_REMAINING_MIP_LEVELS, + 0, VK_REMAINING_ARRAY_LAYERS, + }; + table->vkTransitionImageLayout(device, 1, &transition); + + VkCopyMemoryToImageInfo copy = { VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO }; + copy.dstImage = handle->get_image(); + copy.dstImageLayout = VK_IMAGE_LAYOUT_GENERAL; + copy.regionCount = staging_buffer->blits.size(); + SmallVector copies(copy.regionCount); + copy.pRegions = copies.data(); + + for (uint32_t i = 0; i < copy.regionCount; i++) + { + auto &dst = copies[i]; + auto &src = staging_buffer->blits[i]; + dst.sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY; + dst.pHostPointer = static_cast(staging_buffer->host.data) + src.bufferOffset; + dst.imageSubresource = src.imageSubresource; + dst.imageOffset = src.imageOffset; + dst.imageExtent = src.imageExtent; + dst.memoryRowLength = src.bufferRowLength; + dst.memoryImageHeight = src.bufferImageHeight; + } + + // Bang the memory straight into the image without a staging copy. + table->vkCopyMemoryToImage(device, ©); + } + + if (generate_mips) + { + auto graphics_cmd = request_command_buffer(CommandBuffer::Type::Generic); + Semaphore sem; + + if (transfer_cmd) + submit_and_sync_to_queues(transfer_cmd, 1u << QUEUE_INDEX_GRAPHICS); + + auto src_layout = + (info.usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT) != 0 ? + VK_IMAGE_LAYOUT_GENERAL : handle->get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + graphics_cmd->begin_region("mipgen"); + graphics_cmd->barrier_prepare_generate_mipmap(*handle, src_layout, VK_PIPELINE_STAGE_NONE, 0, true); + graphics_cmd->generate_mipmap(*handle); + graphics_cmd->end_region(); + + bool sync_with_graphics = (queue_flags & IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT) != 0; + + graphics_cmd->image_barrier( + *handle, handle->get_layout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), + tmpinfo.initial_layout, + VK_PIPELINE_STAGE_2_BLIT_BIT, 0, + sync_with_graphics ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : VK_PIPELINE_STAGE_NONE, + sync_with_graphics ? VK_ACCESS_MEMORY_READ_BIT : VK_ACCESS_NONE); + + transition_cmd = std::move(graphics_cmd); + } + else if (transfer_cmd) + { + bool sync_with_transfer = (create_info.misc & IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT) != 0; + + transfer_cmd->image_barrier( + *handle, handle->get_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + tmpinfo.initial_layout, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + sync_with_transfer ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : VK_PIPELINE_STAGE_NONE, + sync_with_transfer ? VK_ACCESS_MEMORY_READ_BIT : VK_ACCESS_NONE); + + transition_cmd = std::move(transfer_cmd); + } + } + else if (create_info.initial_layout != VK_IMAGE_LAYOUT_UNDEFINED) + { + VK_ASSERT(create_info.domain != ImageDomain::Transient); + + // Need to perform the barrier in some command buffer, pick an appropriate one based on supported queues. + // Pick the most lenient queue first in case we need to transition to a weird layout. + CommandBuffer::Type type = CommandBuffer::Type::Count; + if (queue_flags & IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT) + type = CommandBuffer::Type::Generic; + else if (queue_flags & IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT) + type = CommandBuffer::Type::AsyncCompute; + else if (queue_flags & IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT) + type = CommandBuffer::Type::AsyncTransfer; + else if (queue_flags & IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_DECODE_BIT) + type = CommandBuffer::Type::VideoDecode; + else if (queue_flags & IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_ENCODE_BIT) + type = CommandBuffer::Type::VideoEncode; + VK_ASSERT(type != CommandBuffer::Type::Count); + + auto cmd = request_command_buffer(type); + cmd->image_barrier(*handle, info.initialLayout, create_info.initial_layout, + VK_PIPELINE_STAGE_NONE, 0, + VK_PIPELINE_STAGE_NONE, 0); + transition_cmd = std::move(cmd); + } + + // For concurrent queue, make sure that compute, transfer or video decode can see the final image as well. + if (transition_cmd) + { + uint32_t sync_queues = 0; + + // These are implied by default. + if (queue_flags & IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT) + sync_queues |= 1u << QUEUE_INDEX_GRAPHICS; + if (queue_flags & IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT) + sync_queues |= 1u << QUEUE_INDEX_COMPUTE; + + // Do not synchronize transfer/video queues here unless we explicitly asked for it. + if (create_info.misc & IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT) + { + // Avoid transfer -> graphics -> transfer cycle, have to flush transfer queue before we introduce dependency. + if (generate_mips) + { + LOCK(); + flush_frame_nolock(QUEUE_INDEX_TRANSFER); + } + sync_queues |= 1u << QUEUE_INDEX_TRANSFER; + } + if (create_info.misc & IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_DECODE_BIT) + sync_queues |= 1u << QUEUE_INDEX_VIDEO_DECODE; + if (create_info.misc & IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_ENCODE_BIT) + sync_queues |= 1u << QUEUE_INDEX_VIDEO_ENCODE; + + submit_and_sync_to_queues(transition_cmd, sync_queues); + } + + return handle; +} + +const ImmutableSampler *Device::request_immutable_sampler(const SamplerCreateInfo &sampler_info, + const ImmutableYcbcrConversion *ycbcr) +{ + auto info = Sampler::fill_vk_sampler_info(sampler_info); + Util::Hasher h; + + h.u32(info.flags); + h.u32(info.addressModeU); + h.u32(info.addressModeV); + h.u32(info.addressModeW); + h.u32(info.minFilter); + h.u32(info.magFilter); + h.u32(info.mipmapMode); + h.f32(info.minLod); + h.f32(info.maxLod); + h.f32(info.mipLodBias); + h.u32(info.compareEnable); + h.u32(info.compareOp); + h.u32(info.anisotropyEnable); + h.f32(info.maxAnisotropy); + h.u32(info.borderColor); + h.u32(info.unnormalizedCoordinates); + if (ycbcr) + h.u64(ycbcr->get_hash()); + else + h.u32(0); + + LOCK_CACHE(); + auto *sampler = immutable_samplers.find(h.get()); + if (!sampler) + sampler = immutable_samplers.emplace_yield(h.get(), h.get(), this, sampler_info, ycbcr); + + return sampler; +} + +const ImmutableYcbcrConversion *Device::request_immutable_ycbcr_conversion( + const VkSamplerYcbcrConversionCreateInfo &info) +{ + Util::Hasher h; + h.u32(info.forceExplicitReconstruction); + h.u32(info.format); + h.u32(info.chromaFilter); + h.u32(info.components.r); + h.u32(info.components.g); + h.u32(info.components.b); + h.u32(info.components.a); + h.u32(info.xChromaOffset); + h.u32(info.yChromaOffset); + h.u32(info.ycbcrModel); + h.u32(info.ycbcrRange); + + LOCK_CACHE(); + auto *sampler = immutable_ycbcr_conversions.find(h.get()); + if (!sampler) + sampler = immutable_ycbcr_conversions.emplace_yield(h.get(), h.get(), this, info); + return sampler; +} + +SamplerHandle Device::create_sampler(const SamplerCreateInfo &sampler_info) +{ + auto info = Sampler::fill_vk_sampler_info(sampler_info); + + VkSampler sampler = managers.descriptor_buffer.create_sampler(&info); + if (sampler == VK_NULL_HANDLE) + return SamplerHandle(nullptr); + return SamplerHandle(handle_pool.samplers.allocate(this, sampler, sampler_info, false)); +} + +BindlessDescriptorPoolHandle Device::create_bindless_descriptor_pool(BindlessResourceType type, + unsigned num_sets, unsigned num_descriptors) +{ + if (!ext.vk12_features.descriptorIndexing) + return BindlessDescriptorPoolHandle{nullptr}; + + DescriptorSetLayout layout; + const uint32_t stages_for_sets[VULKAN_NUM_BINDINGS] = { VK_SHADER_STAGE_ALL }; + layout.meta[0].array_size = DescriptorSetLayout::UNSIZED_ARRAY; + for (unsigned i = 1; i < VULKAN_NUM_BINDINGS; i++) + layout.meta[i].array_size = 1; + + switch (type) + { + case BindlessResourceType::Image: + layout.separate_image_mask = 1; + break; + + default: + return BindlessDescriptorPoolHandle{nullptr}; + } + + auto *allocator = request_descriptor_set_allocator(layout, stages_for_sets, nullptr); + + VkDescriptorPool pool = VK_NULL_HANDLE; + + if (!ext.supports_descriptor_buffer_or_heap) + { + if (allocator) + pool = allocator->allocate_bindless_pool(num_sets, num_descriptors); + + if (!pool) + { + LOGE("Failed to allocate bindless pool.\n"); + return BindlessDescriptorPoolHandle{nullptr}; + } + } + + auto *handle = handle_pool.bindless_descriptor_pool.allocate(this, allocator, pool, + num_sets, num_descriptors); + return BindlessDescriptorPoolHandle{handle}; +} + +void Device::fill_buffer_sharing_indices(VkBufferCreateInfo &info, uint32_t *sharing_indices) +{ + for (auto &i : queue_info.family_indices) + add_unique_family(sharing_indices, info.queueFamilyIndexCount, i); + + if (info.queueFamilyIndexCount > 1) + { + info.sharingMode = VK_SHARING_MODE_CONCURRENT; + info.pQueueFamilyIndices = sharing_indices; + } + else + { + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.queueFamilyIndexCount = 0; + info.pQueueFamilyIndices = nullptr; + } +} + +BufferHandle Device::create_imported_host_buffer(const BufferCreateInfo &create_info, VkExternalMemoryHandleTypeFlagBits type, void *host_buffer) +{ + if (create_info.domain != BufferDomain::Host && + create_info.domain != BufferDomain::CachedHost && + create_info.domain != BufferDomain::CachedCoherentHostPreferCached && + create_info.domain != BufferDomain::CachedCoherentHostPreferCoherent) + { + return BufferHandle{}; + } + + if (!ext.supports_external_memory_host) + return BufferHandle{}; + + if ((reinterpret_cast(host_buffer) & (ext.host_memory_properties.minImportedHostPointerAlignment - 1)) != 0) + { + LOGE("Host buffer is not aligned appropriately.\n"); + return BufferHandle{}; + } + + VkExternalMemoryBufferCreateInfo external_info = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO }; + external_info.handleTypes = type; + + VkMemoryHostPointerPropertiesEXT host_pointer_props = { VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT }; + if (table->vkGetMemoryHostPointerPropertiesEXT(device, type, host_buffer, &host_pointer_props) != VK_SUCCESS) + { + LOGE("Host pointer is not importable.\n"); + return BufferHandle{}; + } + + VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + VkBufferUsageFlags2CreateInfo usage2 = { VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO }; + info.size = create_info.size; + usage2.usage = create_info.usage; + if (get_device_features().vk12_features.bufferDeviceAddress) + usage2.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.pNext = &external_info; + + external_info.pNext = create_info.pnext; + + uint32_t sharing_indices[QUEUE_INDEX_COUNT]; + fill_buffer_sharing_indices(info, sharing_indices); + + if (ext.vk14_features.maintenance5) + { + usage2.pNext = info.pNext; + info.pNext = &usage2; + } + else + info.usage = VkBufferUsageFlags(usage2.usage); + + VkBuffer buffer; + VkMemoryRequirements reqs; + if (table->vkCreateBuffer(device, &info, nullptr, &buffer) != VK_SUCCESS) + return BufferHandle{}; + + table->vkGetBufferMemoryRequirements(device, buffer, &reqs); + + reqs.alignment = std::max(reqs.alignment, gpu_props.limits.nonCoherentAtomSize); + // For BDA purposes + reqs.alignment = std::max(reqs.alignment, 16u); + + // Weird workaround for latest AMD Windows drivers which sets memoryTypeBits to 0 when using the external handle type. + if (!reqs.memoryTypeBits) + reqs.memoryTypeBits = ~0u; + + auto plain_reqs = reqs; + reqs.memoryTypeBits &= host_pointer_props.memoryTypeBits; + + if (reqs.memoryTypeBits == 0) + { + LOGE("No compatible host pointer types are available.\n"); + table->vkDestroyBuffer(device, buffer, nullptr); + return BufferHandle{}; + } + + uint32_t memory_type = find_memory_type(create_info.domain, reqs.memoryTypeBits); + + if (memory_type == UINT32_MAX) + { + // Weird workaround for Intel Windows where the only memory type is DEVICE_LOCAL + // with no HOST_VISIBLE (!?!?!). + // However, it appears to work just fine to allocate with other memory types as well ... + // Oh well. + + // Ignore host_pointer_props. + reqs = plain_reqs; + memory_type = find_memory_type(create_info.domain, reqs.memoryTypeBits); + } + + if (memory_type == UINT32_MAX) + { + LOGE("Failed to find memory type.\n"); + table->vkDestroyBuffer(device, buffer, nullptr); + return BufferHandle{}; + } + + VkMemoryAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + alloc_info.allocationSize = (create_info.size + ext.host_memory_properties.minImportedHostPointerAlignment - 1) & + ~(ext.host_memory_properties.minImportedHostPointerAlignment - 1); + alloc_info.memoryTypeIndex = memory_type; + + VkMemoryAllocateFlagsInfo flags_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO }; + if (get_device_features().vk12_features.bufferDeviceAddress) + { + alloc_info.pNext = &flags_info; + flags_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; + } + + VkImportMemoryHostPointerInfoEXT import = { VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT }; + import.handleType = type; + import.pHostPointer = host_buffer; + import.pNext = alloc_info.pNext; + alloc_info.pNext = &import; + + VkDeviceMemory memory; + if (table->vkAllocateMemory(device, &alloc_info, nullptr, &memory) != VK_SUCCESS) + { + table->vkDestroyBuffer(device, buffer, nullptr); + return BufferHandle{}; + } + + auto allocation = DeviceAllocation::make_imported_allocation(memory, info.size, memory_type); + if (table->vkMapMemory(device, memory, 0, VK_WHOLE_SIZE, 0, reinterpret_cast(&allocation.host_base)) != VK_SUCCESS) + { + { + LOCK_MEMORY(); + allocation.free_immediate(managers.memory); + } + table->vkDestroyBuffer(device, buffer, nullptr); + return BufferHandle{}; + } + + if (table->vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS) + { + { + LOCK_MEMORY(); + allocation.free_immediate(managers.memory); + } + table->vkDestroyBuffer(device, buffer, nullptr); + return BufferHandle{}; + } + + VkDeviceAddress bda = 0; + if (get_device_features().vk12_features.bufferDeviceAddress) + { + VkBufferDeviceAddressInfo bda_info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO }; + bda_info.buffer = buffer; + bda = table->vkGetBufferDeviceAddress(device, &bda_info); + } + + BufferHandle handle(handle_pool.buffers.allocate(this, buffer, allocation, create_info, bda)); + return handle; +} + +RTASHandle Device::create_rtas(VkAccelerationStructureTypeKHR type, BufferHandle buffer, + VkDeviceSize offset, VkDeviceSize size) +{ + if (!ext.rtas_features.accelerationStructure) + { + LOGE("RTAS not supported on this driver.\n"); + return {}; + } + + VK_ASSERT(buffer->get_create_info().usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR); + VK_ASSERT(offset + size <= buffer->get_create_info().size); + + VkAccelerationStructureCreateInfoKHR rtas_info = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR }; + rtas_info.buffer = buffer->get_buffer(); + rtas_info.offset = offset; + rtas_info.size = size; + rtas_info.type = type; + + VkAccelerationStructureKHR rtas; + if (table->vkCreateAccelerationStructureKHR(device, &rtas_info, nullptr, &rtas) != VK_SUCCESS) + { + LOGE("Failed to create RTAS.\n"); + return {}; + } + + RTASHandle handle(handle_pool.rtas.allocate(this, rtas, rtas_info.type, std::move(buffer))); + return handle; +} + +RTASHandle Device::create_rtas(VkAccelerationStructureTypeKHR type, VkDeviceSize size) +{ + if (!ext.rtas_features.accelerationStructure) + { + LOGE("RTAS not supported on this driver.\n"); + return {}; + } + + BufferHandle buffer; + BufferCreateInfo buffer_info = {}; + buffer_info.size = size; + buffer_info.domain = BufferDomain::Device; + buffer_info.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; + buffer = create_buffer(buffer_info); + + return create_rtas(type, std::move(buffer), 0, size); +} + +RTASHandle Device::create_rtas(const TopRTASCreateInfo &info, CommandBuffer *cmd) +{ + if (!ext.rtas_features.accelerationStructure) + { + LOGE("RTAS not supported on this driver.\n"); + return {}; + } + VkAccelerationStructureBuildGeometryInfoKHR geom_info = + { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; + VkAccelerationStructureBuildSizesInfoKHR size_info = + { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; + + geom_info.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + geom_info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + geom_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR; + + uint32_t primitive_count = info.count; + + VkAccelerationStructureGeometryKHR geom = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR }; + geom.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + auto &inst = geom.geometry.instances; + inst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + inst.arrayOfPointers = VK_TRUE; + geom_info.geometryCount = 1; + geom_info.pGeometries = &geom; + + table->vkGetAccelerationStructureBuildSizesKHR( + device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, + &geom_info, &primitive_count, &size_info); + + auto handle = create_rtas(geom_info.type, size_info.accelerationStructureSize); + handle->set_scratch_size(size_info.buildScratchSize, size_info.updateScratchSize); + + if (cmd) + cmd->build_rtas(BuildMode::Build, *handle, info); + + return handle; +} + +RTASHandle Device::create_rtas(const BottomRTASCreateInfo &info, CommandBuffer *cmd, QueryPoolHandle *compacted_size) +{ + if (!ext.rtas_features.accelerationStructure) + { + LOGE("RTAS not supported on this driver.\n"); + return {}; + } + + if (compacted_size && !cmd) + { + LOGE("If specifying compacted size, must have a command buffer.\n"); + return {}; + } + + if (compacted_size && info.mode != BLASMode::Static) + { + LOGE("Only Static mode supports compaction.\n"); + return {}; + } + + VkAccelerationStructureBuildGeometryInfoKHR geom_info = + { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; + VkAccelerationStructureBuildSizesInfoKHR size_info = + { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; + + geom_info.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + geom_info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + + switch (info.mode) + { + case BLASMode::Static: + geom_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR; + break; + + case BLASMode::Skinned: + geom_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR | + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR; + break; + } + + Util::SmallVector geometries; + Util::SmallVector primitive_counts; + + geometries.reserve(info.count); + primitive_counts.reserve(info.count); + + for (size_t i = 0; i < info.count; i++) + { + auto &input = info.geometries[i]; + VkAccelerationStructureGeometryKHR geom = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR }; + geom.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + auto &tri = geom.geometry.triangles; + tri.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + + tri.vertexFormat = input.format; + tri.vertexData.deviceAddress = input.vbo; + tri.maxVertex = input.num_vertices - 1; + tri.vertexStride = input.stride; + + tri.indexData.deviceAddress = input.ibo; + tri.indexType = input.index_type; + VK_ASSERT(input.ibo || input.index_type == VK_INDEX_TYPE_NONE_KHR); + + tri.transformData.deviceAddress = input.transform; + + geometries.push_back(geom); + primitive_counts.push_back(input.num_primitives); + } + + geom_info.geometryCount = info.count; + geom_info.pGeometries = geometries.data(); + + table->vkGetAccelerationStructureBuildSizesKHR( + device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, + &geom_info, primitive_counts.data(), &size_info); + + auto handle = create_rtas(geom_info.type, size_info.accelerationStructureSize); + handle->set_scratch_size(size_info.buildScratchSize, size_info.updateScratchSize); + + if (cmd) + { + cmd->build_rtas(BuildMode::Build, *handle, info); + + if (compacted_size) + { + auto query = frame().query_pool_rtas.allocate_query(cmd->get_command_buffer()); + cmd->write_compacted_rtas_size(*handle, *query); + *compacted_size = std::move(query); + } + } + + return handle; +} + +BufferHandle Device::create_buffer(const BufferCreateInfo &create_info, const void *initial) +{ + DeviceAllocation allocation; + VkBuffer buffer; + + bool zero_initialize = (create_info.misc & BUFFER_MISC_ZERO_INITIALIZE_BIT) != 0; + bool use_external = (create_info.misc & BUFFER_MISC_EXTERNAL_MEMORY_BIT) != 0; + if (initial && zero_initialize) + { + LOGE("Cannot initialize buffer with data and clear.\n"); + return BufferHandle{}; + } + + if (use_external && create_info.domain != BufferDomain::Device) + { + LOGE("When using external memory, must be Device domain.\n"); + return BufferHandle{}; + } + + VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + VkBufferUsageFlags2CreateInfo usage2 = { VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO }; + info.size = create_info.size; + usage2.usage = create_info.usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + if (get_device_features().vk12_features.bufferDeviceAddress) + usage2.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.pNext = create_info.pnext; + + uint32_t sharing_indices[QUEUE_INDEX_COUNT]; + fill_buffer_sharing_indices(info, sharing_indices); + + if (use_external && !ext.supports_external) + { + LOGE("External memory not supported.\n"); + return BufferHandle{}; + } + + VkExternalMemoryBufferCreateInfo external_info = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO }; + if (ext.supports_external && use_external) + { + // Ensure that the handle type is supported. + VkPhysicalDeviceExternalBufferInfo external_buffer_props_info = + { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO }; + VkExternalBufferProperties external_buffer_props = { VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES }; + external_buffer_props_info.handleType = create_info.external.memory_handle_type; + external_buffer_props_info.usage = VkBufferUsageFlags(usage2.usage); + external_buffer_props_info.flags = info.flags; + vkGetPhysicalDeviceExternalBufferProperties(gpu, &external_buffer_props_info, &external_buffer_props); + + bool supports_import = (external_buffer_props.externalMemoryProperties.externalMemoryFeatures & + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0; + bool supports_export = (external_buffer_props.externalMemoryProperties.externalMemoryFeatures & + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0; + + if (!supports_import && !create_info.external) + { + LOGE("Attempting to import with handle type #%x, but it is not supported.\n", + create_info.external.memory_handle_type); + return BufferHandle{}; + } + else if (!supports_export && create_info.external) + { + LOGE("Attempting to export with handle type #%x, but it is not supported.\n", + create_info.external.memory_handle_type); + return BufferHandle{}; + } + + external_info.handleTypes = create_info.external.memory_handle_type; + external_info.pNext = info.pNext; + info.pNext = &external_info; + } + + if (ext.vk14_features.maintenance5) + { + usage2.pNext = info.pNext; + info.pNext = &usage2; + } + else + info.usage = VkBufferUsageFlags(usage2.usage); + + if (table->vkCreateBuffer(device, &info, nullptr, &buffer) != VK_SUCCESS) + return BufferHandle(nullptr); + + VkMemoryRequirements2 reqs = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 }; + VkBufferMemoryRequirementsInfo2 req_info = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 }; + req_info.buffer = buffer; + table->vkGetBufferMemoryRequirements2(device, &req_info, &reqs); + + reqs.memoryRequirements.alignment = std::max(reqs.memoryRequirements.alignment, gpu_props.limits.nonCoherentAtomSize); + // For BDA purposes + reqs.memoryRequirements.alignment = std::max(reqs.memoryRequirements.alignment, 16u); + + if (create_info.allocation_requirements.size) + { + reqs.memoryRequirements.memoryTypeBits &= + create_info.allocation_requirements.memoryTypeBits; + reqs.memoryRequirements.size = + std::max(reqs.memoryRequirements.size, create_info.allocation_requirements.size); + reqs.memoryRequirements.alignment = + std::max(reqs.memoryRequirements.alignment, create_info.allocation_requirements.alignment); + } + + uint32_t memory_type = find_memory_type(create_info.domain, reqs.memoryRequirements.memoryTypeBits); + if (memory_type == UINT32_MAX) + { + LOGE("Failed to find memory type.\n"); + table->vkDestroyBuffer(device, buffer, nullptr); + return BufferHandle(nullptr); + } + + AllocationMode mode; + if ((create_info.misc & BUFFER_MISC_EXTERNAL_MEMORY_BIT) != 0) + mode = AllocationMode::External; + else if (create_info.domain == BufferDomain::Device && + (create_info.usage & (VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) != 0) + mode = AllocationMode::LinearDeviceHighPriority; + else if (create_info.domain == BufferDomain::Device || + create_info.domain == BufferDomain::LinkedDeviceHostPreferDevice) + mode = AllocationMode::LinearDevice; + else + mode = AllocationMode::LinearHostMappable; + + auto external = create_info.external; + + { + LOCK_MEMORY(); + if (!managers.memory.allocate_buffer_memory(reqs.memoryRequirements.size, reqs.memoryRequirements.alignment, + mode, memory_type, buffer, &allocation, + use_external ? &external : nullptr)) + { + if (use_external) + { + LOGE("Failed to export / import buffer memory.\n"); + table->vkDestroyBuffer(device, buffer, nullptr); + return BufferHandle(nullptr); + } + + auto fallback_domain = create_info.domain; + + // This memory type is rather scarce, so fallback to Host type if we've exhausted this memory. + if (create_info.domain == BufferDomain::LinkedDeviceHost) + { + LOGW("Exhausted LinkedDeviceHost memory, falling back to host.\n"); + fallback_domain = BufferDomain::Host; + } + else if (create_info.domain == BufferDomain::LinkedDeviceHostPreferDevice) + { + LOGW("Exhausted LinkedDeviceHostPreferDevice memory, falling back to device.\n"); + fallback_domain = BufferDomain::Device; + } + + memory_type = find_memory_type(fallback_domain, reqs.memoryRequirements.memoryTypeBits); + + if (memory_type == UINT32_MAX || fallback_domain == create_info.domain || + !managers.memory.allocate_buffer_memory(reqs.memoryRequirements.size, reqs.memoryRequirements.alignment, + mode, memory_type, buffer, &allocation, nullptr)) + { + LOGE("Failed to allocate fallback memory.\n"); + table->vkDestroyBuffer(device, buffer, nullptr); + return BufferHandle(nullptr); + } + } + } + + if (table->vkBindBufferMemory(device, buffer, allocation.get_memory(), allocation.get_offset()) != VK_SUCCESS) + { + { + LOCK_MEMORY(); + allocation.free_immediate(managers.memory); + } + + table->vkDestroyBuffer(device, buffer, nullptr); + return BufferHandle(nullptr); + } + + auto tmpinfo = create_info; + tmpinfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + + VkDeviceAddress bda = 0; + if (get_device_features().vk12_features.bufferDeviceAddress) + { + VkBufferDeviceAddressInfo bda_info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO }; + bda_info.buffer = buffer; + bda = table->vkGetBufferDeviceAddress(device, &bda_info); + } + + BufferHandle handle(handle_pool.buffers.allocate(this, buffer, allocation, tmpinfo, bda)); + + bool need_init = initial || zero_initialize; + void *ptr = nullptr; + if (need_init && memory_type_is_host_visible(memory_type)) + ptr = managers.memory.map_memory(allocation, MEMORY_ACCESS_WRITE_BIT, 0, allocation.get_size()); + + if (need_init && !ptr) + { + auto cmd = request_command_buffer(CommandBuffer::Type::AsyncTransfer); + if (initial) + { + auto staging_info = create_info; + staging_info.domain = BufferDomain::Host; + auto staging_buffer = create_buffer(staging_info, initial); + set_name(*staging_buffer, "buffer-upload-staging-buffer"); + + cmd->begin_region("copy-buffer-staging"); + cmd->copy_buffer(*handle, *staging_buffer); + cmd->end_region(); + } + else + { + cmd->begin_region("fill-buffer-staging"); + cmd->fill_buffer(*handle, 0); + cmd->end_region(); + } + + uint32_t queue_indices = (1u << QUEUE_INDEX_GRAPHICS) | (1u << QUEUE_INDEX_COMPUTE); + if (ext.supports_video_decode_queue) + queue_indices |= 1u << QUEUE_INDEX_VIDEO_DECODE; + if (ext.supports_video_encode_queue) + queue_indices |= 1u << QUEUE_INDEX_VIDEO_ENCODE; + submit_and_sync_to_queues(cmd, queue_indices); + } + else if (need_init) + { + if (initial) + memcpy(ptr, initial, create_info.size); + else + memset(ptr, 0, create_info.size); + managers.memory.unmap_memory(allocation, MEMORY_ACCESS_WRITE_BIT, 0, allocation.get_size()); + } + return handle; +} + +bool Device::memory_type_is_device_optimal(uint32_t type) const +{ + return (mem_props.memoryTypes[type].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0; +} + +bool Device::memory_type_is_host_visible(uint32_t type) const +{ + return (mem_props.memoryTypes[type].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0; +} + +static VkFormatFeatureFlags2 promote_storage_usage(const DeviceFeatures &features, VkFormat format, + VkFormatFeatureFlags2 supported) +{ + if ((supported & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT) != 0 && + format_supports_storage_image_read_write_without_format(format)) + { + if (features.enabled_features.shaderStorageImageReadWithoutFormat) + supported |= VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT; + if (features.enabled_features.shaderStorageImageWriteWithoutFormat) + supported |= VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT; + } + + return supported; +} + +void Device::get_format_properties(VkFormat format, VkFormatProperties3 *properties3) const +{ + VkFormatProperties2 properties2 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 }; + VK_ASSERT(properties3->sType == VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3); + + if (ext.supports_format_feature_flags2) + { + properties2.pNext = properties3; + vkGetPhysicalDeviceFormatProperties2(gpu, format, &properties2); + } + else + { + // Skip properties3 and synthesize the results instead. + properties2.pNext = properties3->pNext; + vkGetPhysicalDeviceFormatProperties2(gpu, format, &properties2); + + properties3->optimalTilingFeatures = properties2.formatProperties.optimalTilingFeatures; + properties3->linearTilingFeatures = properties2.formatProperties.linearTilingFeatures; + properties3->bufferFeatures = properties2.formatProperties.bufferFeatures; + + // Automatically promote for supported formats. + properties3->optimalTilingFeatures = + promote_storage_usage(ext, format, properties3->optimalTilingFeatures); + properties3->linearTilingFeatures = + promote_storage_usage(ext, format, properties3->linearTilingFeatures); + } +} + +bool Device::get_image_format_properties(VkFormat format, VkImageType type, VkImageTiling tiling, + VkImageUsageFlags usage, VkImageCreateFlags flags, + const void *pNext, + VkImageFormatProperties2 *properties2) const +{ + VK_ASSERT(properties2->sType == VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2); + VkPhysicalDeviceImageFormatInfo2 info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 }; + info.pNext = pNext; + info.format = format; + info.type = type; + info.tiling = tiling; + info.usage = usage; + info.flags = flags; + + VkResult res = vkGetPhysicalDeviceImageFormatProperties2(gpu, &info, properties2); + return res == VK_SUCCESS; +} + +bool Device::image_format_is_supported(VkFormat format, VkFormatFeatureFlags2 required, VkImageTiling tiling) const +{ + VkFormatProperties3 props3 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 }; + get_format_properties(format, &props3); + auto flags = tiling == VK_IMAGE_TILING_OPTIMAL ? props3.optimalTilingFeatures : props3.linearTilingFeatures; + return (flags & required) == required; +} + +VkFormat Device::get_default_depth_stencil_format() const +{ + if (image_format_is_supported(VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL)) + return VK_FORMAT_D32_SFLOAT_S8_UINT; + if (image_format_is_supported(VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL)) + return VK_FORMAT_D24_UNORM_S8_UINT; + + return VK_FORMAT_UNDEFINED; +} + +VkFormat Device::get_default_depth_format() const +{ + if (image_format_is_supported(VK_FORMAT_D32_SFLOAT, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL)) + return VK_FORMAT_D32_SFLOAT; + if (image_format_is_supported(VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL)) + return VK_FORMAT_X8_D24_UNORM_PACK32; + if (image_format_is_supported(VK_FORMAT_D16_UNORM, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL)) + return VK_FORMAT_D16_UNORM; + + return VK_FORMAT_UNDEFINED; +} + +uint64_t Device::allocate_cookie() +{ + // Reserve lower bits for "special purposes". + return cookie.fetch_add(32, std::memory_order_relaxed) + 32; +} + +const RenderPass &Device::request_render_pass(const RenderPassInfo &info, bool compatible) +{ + Hasher h; + VkFormat formats[VULKAN_NUM_ATTACHMENTS]; + VkFormat depth_stencil; + uint32_t lazy = 0; + uint32_t optimal = 0; + + for (unsigned i = 0; i < info.num_color_attachments; i++) + { + VK_ASSERT(info.color_attachments[i]); + formats[i] = info.color_attachments[i]->get_format(); + if (info.color_attachments[i]->get_image().get_create_info().domain == ImageDomain::Transient) + lazy |= 1u << i; + if (info.color_attachments[i]->get_image().get_create_info().layout == ImageLayout::Optimal) + optimal |= 1u << i; + + // This can change external subpass dependencies, so it must always be hashed. + h.u32(info.color_attachments[i]->get_image().get_swapchain_layout()); + } + + if (info.depth_stencil) + { + if (info.depth_stencil->get_image().get_create_info().domain == ImageDomain::Transient) + lazy |= 1u << info.num_color_attachments; + if (info.depth_stencil->get_image().get_create_info().layout == ImageLayout::Optimal) + optimal |= 1u << info.num_color_attachments; + } + + // For multiview, base layer is encoded into the view mask. + if (info.num_layers > 1) + { + h.u32(info.base_layer); + h.u32(info.num_layers); + } + else + { + h.u32(0); + h.u32(info.num_layers); + } + + h.u32(info.num_subpasses); + for (unsigned i = 0; i < info.num_subpasses; i++) + { + h.u32(info.subpasses[i].num_color_attachments); + h.u32(info.subpasses[i].num_input_attachments); + h.u32(info.subpasses[i].num_resolve_attachments); + h.u32(static_cast(info.subpasses[i].depth_stencil_mode)); + for (unsigned j = 0; j < info.subpasses[i].num_color_attachments; j++) + h.u32(info.subpasses[i].color_attachments[j]); + for (unsigned j = 0; j < info.subpasses[i].num_input_attachments; j++) + h.u32(info.subpasses[i].input_attachments[j]); + for (unsigned j = 0; j < info.subpasses[i].num_resolve_attachments; j++) + h.u32(info.subpasses[i].resolve_attachments[j]); + } + + depth_stencil = info.depth_stencil ? info.depth_stencil->get_format() : VK_FORMAT_UNDEFINED; + h.data(formats, info.num_color_attachments * sizeof(VkFormat)); + h.u32(info.num_color_attachments); + h.u32(depth_stencil); + + // Compatible render passes do not care about load/store, or image layouts. + if (!compatible) + { + h.u32(info.op_flags); + h.u32(info.clear_attachments); + h.u32(info.load_attachments); + h.u32(info.store_attachments); + h.u32(optimal); + } + + // Lazy flag can change external subpass dependencies, which is not compatible. + h.u32(lazy); + + // Marked for v2 render passes. + h.u32(2); + + auto hash = h.get(); + + auto *ret = render_passes.find(hash); + if (!ret) + ret = render_passes.emplace_yield(hash, hash, this, info); + return *ret; +} + +const Framebuffer &Device::request_framebuffer(const RenderPassInfo &info) +{ + return framebuffer_allocator.request_framebuffer(info); +} + +ImageHandle Device::get_transient_attachment(unsigned width, unsigned height, VkFormat format, + unsigned index, unsigned samples, unsigned layers) +{ + return transient_allocator.request_attachment(width, height, format, index, samples, layers); +} + +ImageView &Device::get_swapchain_view() +{ + VK_ASSERT(wsi.index < wsi.swapchain.size()); + return wsi.swapchain[wsi.index]->get_view(); +} + +ImageView &Device::get_swapchain_view(unsigned index) +{ + VK_ASSERT(index < wsi.swapchain.size()); + return wsi.swapchain[index]->get_view(); +} + +unsigned Device::get_num_frame_contexts() const +{ + return unsigned(per_frame.size()); +} + +unsigned Device::get_num_swapchain_images() const +{ + return unsigned(wsi.swapchain.size()); +} + +unsigned Device::get_swapchain_index() const +{ + return wsi.index; +} + +unsigned Device::get_current_frame_context() const +{ + return frame_context_index; +} + +RenderPassInfo Device::get_swapchain_render_pass(SwapchainRenderPass style) +{ + RenderPassInfo info; + info.num_color_attachments = 1; + info.color_attachments[0] = &get_swapchain_view(); + info.clear_attachments = ~0u; + info.store_attachments = 1u << 0; + + switch (style) + { + case SwapchainRenderPass::Depth: + { + info.op_flags |= RENDER_PASS_OP_CLEAR_DEPTH_STENCIL_BIT; + auto att = get_transient_attachment(wsi.swapchain[wsi.index]->get_create_info().width, + wsi.swapchain[wsi.index]->get_create_info().height, + get_default_depth_format()); + info.depth_stencil = &att->get_view(); + break; + } + + case SwapchainRenderPass::DepthStencil: + { + info.op_flags |= RENDER_PASS_OP_CLEAR_DEPTH_STENCIL_BIT; + auto att = get_transient_attachment(wsi.swapchain[wsi.index]->get_create_info().width, + wsi.swapchain[wsi.index]->get_create_info().height, + get_default_depth_stencil_format()); + info.depth_stencil = &att->get_view(); + break; + } + + default: + break; + } + return info; +} + +void Device::external_queue_lock() +{ + lock.lock.lock(); + if (queue_lock_callback) + queue_lock_callback(); +} + +void Device::external_queue_unlock() +{ + lock.lock.unlock(); + if (queue_unlock_callback) + queue_unlock_callback(); +} + +void Device::set_queue_lock(std::function lock_callback, std::function unlock_callback) +{ + queue_lock_callback = std::move(lock_callback); + queue_unlock_callback = std::move(unlock_callback); +} + +void Device::set_name(uint64_t object, VkObjectType type, const char *name) +{ + if (ext.supports_debug_utils) + { + VkDebugUtilsObjectNameInfoEXT info = { VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT }; + info.objectType = type; + info.objectHandle = object; + info.pObjectName = name; + // Be defensive against broken loaders (Android have been weird here in the past). + if (vkSetDebugUtilsObjectNameEXT) + vkSetDebugUtilsObjectNameEXT(device, &info); + } +} + +void Device::set_name(const Buffer &buffer, const char *name) +{ + set_name((uint64_t)buffer.get_buffer(), VK_OBJECT_TYPE_BUFFER, name); +} + +void Device::set_name(const Image &image, const char *name) +{ + set_name((uint64_t)image.get_image(), VK_OBJECT_TYPE_IMAGE, name); +} + +void Device::set_name(const CommandBuffer &cmd, const char *name) +{ + set_name((uint64_t)cmd.get_command_buffer(), VK_OBJECT_TYPE_COMMAND_BUFFER, name); +} + +void Device::query_available_performance_counters(CommandBuffer::Type type, uint32_t *count, + const VkPerformanceCounterKHR **counters, + const VkPerformanceCounterDescriptionKHR **desc) +{ + auto &query_pool = get_performance_query_pool(get_physical_queue_type(type)); + *count = query_pool.get_num_counters(); + *counters = query_pool.get_available_counters(); + *desc = query_pool.get_available_counter_descs(); +} + +bool Device::init_performance_counters(CommandBuffer::Type type, const std::vector &names) +{ + return queue_data[get_physical_queue_type(type)].performance_query_pool.init_counters(names); +} + +void Device::release_profiling() +{ + table->vkReleaseProfilingLockKHR(device); +} + +bool Device::acquire_profiling() +{ + if (!ext.performance_query_features.performanceCounterQueryPools) + return false; + + VkAcquireProfilingLockInfoKHR info = { VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR }; + info.timeout = UINT64_MAX; + if (table->vkAcquireProfilingLockKHR(device, &info) != VK_SUCCESS) + { + LOGE("Failed to acquire profiling lock.\n"); + return false; + } + + return true; +} + +void Device::add_debug_channel_buffer(DebugChannelInterface *iface, std::string tag, Vulkan::BufferHandle buffer) +{ + buffer->set_internal_sync_object(); + LOCK(); + frame().debug_channels.push_back({ iface, std::move(tag), std::move(buffer) }); +} + +void Device::parse_debug_channel(const PerFrame::DebugChannel &channel) +{ + if (!channel.iface) + return; + + auto *words = static_cast(map_host_buffer(*channel.buffer, MEMORY_ACCESS_READ_BIT)); + + size_t size = channel.buffer->get_create_info().size; + if (size <= sizeof(uint32_t)) + { + LOGE("Debug channel buffer is too small.\n"); + return; + } + + // Format for the debug channel. + // Word 0: Atomic counter used by shader. + // Word 1-*: [total message length, code, x, y, z, args] + + size -= sizeof(uint32_t); + size /= sizeof(uint32_t); + + if (words[0].u32 > size) + { + LOGW("Debug channel overflowed and messaged were dropped. Consider increasing debug channel size to at least %u bytes.\n", + unsigned((words[0].u32 + 1) * sizeof(uint32_t))); + } + + words++; + + while (size != 0 && words[0].u32 >= 5 && words[0].u32 <= size) + { + channel.iface->message(channel.tag, words[1].u32, + words[2].u32, words[3].u32, words[4].u32, + words[0].u32 - 5, &words[5]); + size -= words[0].u32; + words += words[0].u32; + } + + unmap_host_buffer(*channel.buffer, MEMORY_ACCESS_READ_BIT); +} + +static int64_t convert_to_signed_delta(uint64_t start_ticks, uint64_t end_ticks, unsigned valid_bits) +{ + unsigned shamt = 64 - valid_bits; + start_ticks <<= shamt; + end_ticks <<= shamt; + auto ticks_delta = int64_t(end_ticks - start_ticks); + ticks_delta >>= shamt; + return ticks_delta; +} + +double Device::convert_device_timestamp_delta(uint64_t start_ticks, uint64_t end_ticks) const +{ + int64_t ticks_delta = convert_to_signed_delta(start_ticks, end_ticks, queue_info.timestamp_valid_bits); + return double(int64_t(ticks_delta)) * gpu_props.limits.timestampPeriod * 1e-9; +} + +uint64_t Device::update_wrapped_device_timestamp(uint64_t ts) +{ + calibrated_timestamp_device_accum += + convert_to_signed_delta(calibrated_timestamp_device_accum, + ts, + queue_info.timestamp_valid_bits); + return calibrated_timestamp_device_accum; +} + +int64_t Device::convert_timestamp_to_absolute_nsec(const QueryPoolResult &handle) +{ + auto ts = int64_t(handle.get_timestamp_ticks()); + if (handle.is_device_timebase()) + { + if (calibrated_time_domain == VK_TIME_DOMAIN_DEVICE_KHR) + LOGW("Attempting to convert device timestamp to calibrated domain, but calibrated timestamps are not supported."); + + // Ensure that we deal with timestamp wraparound correctly. + // On some hardware, we have < 64 valid bits and the timestamp counters will wrap around at some interval. + // As long as timestamps come in at a reasonably steady pace, we can deal with wraparound cleanly. + ts = update_wrapped_device_timestamp(ts); + ts = calibrated_timestamp_host + int64_t(double(ts - calibrated_timestamp_device) * gpu_props.limits.timestampPeriod); + } + return ts; +} + +PipelineEvent Device::begin_signal_event() +{ + return request_pipeline_event(); +} + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES +ResourceManager &Device::get_resource_manager() +{ + return resource_manager; +} + +ShaderManager &Device::get_shader_manager() +{ +#ifdef GRANITE_VULKAN_FOSSILIZE + if (query_initialization_progress(InitializationStage::ShaderModules) < 100) + { + LOGW("Querying shader manager before completion of module initialization.\n" + "Application should not hit this case.\n" + "Blocking until completion ... Try using DeviceShaderModuleReadyEvent or PipelineReadyEvent instead.\n"); + block_until_shader_module_ready(); + } +#endif + return shader_manager; +} +#endif + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES +void Device::init_shader_manager_cache(Granite::TaskGroup *shader_compilation_group) +{ + if (!shader_manager.load_shader_cache("assets://shader_cache.json", shader_compilation_group)) + shader_manager.load_shader_cache("cache://shader_cache.json", shader_compilation_group); +} + +void Device::flush_shader_manager_cache() +{ + shader_manager.save_shader_cache("cache://shader_cache.json"); +} +#endif + +const VolkDeviceTable &Device::get_device_table() const +{ + return *table; +} + +#ifndef GRANITE_RENDERDOC_CAPTURE +bool Device::init_renderdoc_capture() +{ + LOGE("RenderDoc API capture is not enabled in this build.\n"); + return false; +} + +void Device::begin_renderdoc_capture() +{ +} + +void Device::end_renderdoc_capture() +{ +} +#endif + +bool Device::supports_subgroup_size_log2(bool subgroup_full_group, uint8_t subgroup_minimum_size_log2, + uint8_t subgroup_maximum_size_log2, VkShaderStageFlagBits stage) const +{ + if (ImplementationQuirks::get().force_no_subgroup_size_control) + return false; + + if (stage != VK_SHADER_STAGE_COMPUTE_BIT && + stage != VK_SHADER_STAGE_MESH_BIT_EXT && + stage != VK_SHADER_STAGE_TASK_BIT_EXT) + { + return false; + } + + if (!ext.vk13_features.subgroupSizeControl) + return false; + if (subgroup_full_group && !ext.vk13_features.computeFullSubgroups) + return false; + + // VARIABLE_SIZE is always supported. + // 0/0 is degenerate case. + if (subgroup_minimum_size_log2 == 0 && subgroup_maximum_size_log2 == 0) + return true; + + uint32_t min_subgroups = 1u << subgroup_minimum_size_log2; + uint32_t max_subgroups = 1u << subgroup_maximum_size_log2; + + bool full_range = min_subgroups <= ext.vk13_props.minSubgroupSize && + max_subgroups >= ext.vk13_props.maxSubgroupSize; + + // We can use VARYING size. + if (full_range) + return true; + + if (min_subgroups > ext.vk13_props.maxSubgroupSize || + max_subgroups < ext.vk13_props.minSubgroupSize) + { + // No overlap in requested subgroup size and available subgroup size. + return false; + } + + // We need requiredSubgroupSizeStages support here. + return (ext.vk13_props.requiredSubgroupSizeStages & stage) != 0; +} + +const QueueInfo &Device::get_queue_info() const +{ + return queue_info; +} + +void Device::timestamp_log_reset() +{ + managers.timestamps.reset(); +} + +void Device::timestamp_log(const TimestampIntervalReportCallback &cb) const +{ + managers.timestamps.log_simple(cb); +} + +CommandBufferHandle request_command_buffer_with_ownership_transfer( + Device &device, + const Vulkan::Image &image, + const OwnershipTransferInfo &info, + const Vulkan::Semaphore &semaphore) +{ + auto &queue_info = device.get_queue_info(); + unsigned old_family = queue_info.family_indices[device.get_physical_queue_type(info.old_queue)]; + unsigned new_family = queue_info.family_indices[device.get_physical_queue_type(info.new_queue)]; + bool image_is_concurrent = (image.get_create_info().misc & + (Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT | + Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT | + Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT | + Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_DUPLEX)) != 0; + bool need_ownership_transfer = old_family != new_family && !image_is_concurrent; + + VkImageMemoryBarrier2 ownership = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 }; + ownership.image = image.get_image(); + ownership.subresourceRange.aspectMask = format_to_aspect_mask(image.get_format()); + ownership.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ownership.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + ownership.oldLayout = info.old_image_layout; + ownership.newLayout = info.new_image_layout; + ownership.srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + + if (need_ownership_transfer) + { + ownership.srcQueueFamilyIndex = old_family; + ownership.dstQueueFamilyIndex = new_family; + + if (semaphore) + device.add_wait_semaphore(info.old_queue, semaphore, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, true); + auto release_cmd = device.request_command_buffer(info.old_queue); + + release_cmd->image_barriers(1, &ownership); + + Semaphore sem; + device.submit(release_cmd, nullptr, 1, &sem); + device.add_wait_semaphore(info.new_queue, sem, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, true); + } + else + { + ownership.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + ownership.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + if (semaphore) + device.add_wait_semaphore(info.new_queue, semaphore, info.dst_pipeline_stage, true); + } + + // Ownership transfers may perform writes, so make those operations visible. + // If we require neither layout transition nor ownership transfer, + // visibility is ensured by semaphores. + bool need_dst_barrier = need_ownership_transfer || info.old_image_layout != info.new_image_layout; + + auto acquire_cmd = device.request_command_buffer(info.new_queue); + if (need_dst_barrier) + { + if (!need_ownership_transfer) + ownership.srcStageMask = info.dst_pipeline_stage; + ownership.dstAccessMask = info.dst_access; + ownership.dstStageMask = info.dst_pipeline_stage; + acquire_cmd->image_barriers(1, &ownership); + } + + return acquire_cmd; +} + +static ImplementationQuirks implementation_quirks; +ImplementationQuirks &ImplementationQuirks::get() +{ + return implementation_quirks; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device.hpp new file mode 100644 index 00000000..ce080407 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device.hpp @@ -0,0 +1,973 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "buffer.hpp" +#include "command_buffer.hpp" +#include "command_pool.hpp" +#include "fence.hpp" +#include "fence_manager.hpp" +#include "image.hpp" +#include "memory_allocator.hpp" +#include "render_pass.hpp" +#include "sampler.hpp" +#include "semaphore.hpp" +#include "semaphore_manager.hpp" +#include "event_manager.hpp" +#include "shader.hpp" +#include "context.hpp" +#include "query_pool.hpp" +#include "buffer_pool.hpp" +#include "indirect_layout.hpp" +#include "pipeline_cache.hpp" +#include "breadcrumbs.hpp" +#include +#include +#include +#include +#include + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES +#include "shader_manager.hpp" +#include "resource_manager.hpp" +#endif + +#include +#include +#include + +#ifdef GRANITE_VULKAN_FOSSILIZE +#include "fossilize.hpp" +#endif + +#include "quirks.hpp" +#include "small_vector.hpp" + +namespace Util +{ +class TimelineTraceFile; +} + +namespace Granite +{ +struct TaskGroup; +} + +namespace Vulkan +{ +enum class SwapchainRenderPass +{ + ColorOnly, + Depth, + DepthStencil +}; + +struct HostReference +{ + const void *data; + size_t size; +}; + +struct InitialImageBuffer +{ + // Either buffer or host is used. Ideally host is used so that host image copy can be used for uploads. + BufferHandle buffer; + HostReference host; + Util::SmallVector blits; +}; + +struct HandlePool +{ + VulkanObjectPool buffers; + VulkanObjectPool rtas; + VulkanObjectPool images; + VulkanObjectPool linear_images; + VulkanObjectPool image_views; + VulkanObjectPool buffer_views; + VulkanObjectPool samplers; + VulkanObjectPool fences; + VulkanObjectPool semaphores; + VulkanObjectPool events; + VulkanObjectPool query; + VulkanObjectPool command_buffers; + VulkanObjectPool bindless_descriptor_pool; + VulkanObjectPool allocations; +}; + +class DebugChannelInterface +{ +public: + union Word + { + uint32_t u32; + int32_t s32; + float f32; + }; + virtual void message(const std::string &tag, uint32_t code, uint32_t x, uint32_t y, uint32_t z, + uint32_t word_count, const Word *words) = 0; +}; + +namespace Helper +{ +struct WaitSemaphores +{ + Util::SmallVector binary_waits; + Util::SmallVector timeline_waits; +}; + +class BatchComposer +{ +public: + enum { MaxSubmissions = 8 }; + + explicit BatchComposer(uint64_t present_id_nv); + void add_wait_submissions(WaitSemaphores &sem); + void add_wait_semaphore(SemaphoreHolder &sem, VkPipelineStageFlags2 stage); + void add_wait_semaphore(VkSemaphore sem, VkPipelineStageFlags2 stage); + void add_signal_semaphore(VkSemaphore sem, VkPipelineStageFlags2 stage, uint64_t count); + void add_command_buffer(VkCommandBuffer cmd); + + void begin_batch(); + Util::SmallVector &bake(int profiling_iteration = -1); + +private: + Util::SmallVector submits; + VkPerformanceQuerySubmitInfoKHR profiling_infos[Helper::BatchComposer::MaxSubmissions]; + + Util::SmallVector present_ids_nv; + Util::SmallVector waits[MaxSubmissions]; + Util::SmallVector signals[MaxSubmissions]; + Util::SmallVector cmds[MaxSubmissions]; + + uint64_t present_id_nv = 0; + unsigned submit_index = 0; +}; +} + +class Device + : public Util::IntrusivePtrEnabled, HandleCounter> +#ifdef GRANITE_VULKAN_FOSSILIZE + , public Fossilize::StateCreatorInterface +#endif +{ +public: + // Device-based objects which need to poke at internal data structures when their lifetimes end. + // Don't want to expose a lot of internal guts to make this work. + friend class QueryPool; + friend struct QueryPoolResultDeleter; + friend class EventHolder; + friend struct EventHolderDeleter; + friend class SemaphoreHolder; + friend struct SemaphoreHolderDeleter; + friend class FenceHolder; + friend struct FenceHolderDeleter; + friend class Sampler; + friend struct SamplerDeleter; + friend class ImmutableSampler; + friend class ImmutableYcbcrConversion; + friend class Buffer; + friend struct BufferDeleter; + friend class RTAS; + friend struct RTASDeleter; + friend class BufferView; + friend struct BufferViewDeleter; + friend class ImageView; + friend struct ImageViewDeleter; + friend class Image; + friend struct ImageDeleter; + friend struct LinearHostImageDeleter; + friend class CommandBuffer; + friend struct CommandBufferDeleter; + friend class BindlessDescriptorPool; + friend struct BindlessDescriptorPoolDeleter; + friend class Program; + friend class WSI; + friend class Cookie; + friend class Framebuffer; + friend class PipelineLayout; + friend class FramebufferAllocator; + friend class RenderPass; + friend class Texture; + friend class DescriptorSetAllocator; + friend class Shader; + friend class ImageResourceHolder; + friend class DeviceAllocationOwner; + friend struct DeviceAllocationDeleter; + + Device(); + ~Device(); + + // No move-copy. + void operator=(Device &&) = delete; + Device(Device &&) = delete; + + // Only called by main thread, during setup phase. + void set_context(const Context &context); + + // This is asynchronous in nature. See query_initialization_progress(). + // Kicks off Fossilize and shader manager caching. + void begin_shader_caches(); + // For debug or trivial applications, blocks until all shader cache work is done. + void wait_shader_caches(); + + void init_swapchain(const std::vector &swapchain_images, unsigned width, unsigned height, VkFormat format, + VkSurfaceTransformFlagBitsKHR transform, VkImageUsageFlags usage, VkImageLayout layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + void set_swapchain_queue_family_support(uint32_t queue_family_support); + bool can_touch_swapchain_in_command_buffer(CommandBuffer::Type type) const; + void init_external_swapchain(const std::vector &swapchain_images); + void init_frame_contexts(unsigned count); + const VolkDeviceTable &get_device_table() const; + + // Profiling + bool init_performance_counters(CommandBuffer::Type type, const std::vector &names); + bool acquire_profiling(); + void release_profiling(); + void query_available_performance_counters(CommandBuffer::Type type, + uint32_t *count, + const VkPerformanceCounterKHR **counters, + const VkPerformanceCounterDescriptionKHR **desc); + + ImageView &get_swapchain_view(); + ImageView &get_swapchain_view(unsigned index); + unsigned get_num_swapchain_images() const; + unsigned get_num_frame_contexts() const; + unsigned get_swapchain_index() const; + unsigned get_current_frame_context() const; + + size_t get_pipeline_cache_size(); + bool get_pipeline_cache_data(uint8_t *data, size_t size); + // If persistent_mapping is true, the data pointer lifetime is live as long as the device is. + // Useful for read-only file mmap. + bool init_pipeline_cache(const uint8_t *data, size_t size, bool persistent_mapping = false); + + // Frame-pushing interface. + void next_frame_context(); + bool next_frame_context_is_non_blocking(); + + // Normally, the main thread ensures forward progress of the frame context + // so that async tasks don't have to care about it, + // but in the case where async threads are continuously pumping Vulkan work + // in the background, they need to reclaim memory if WSI goes to sleep for a long period of time. + void next_frame_context_in_async_thread(); + void set_enable_async_thread_frame_context(bool enable); + + void wait_idle(); + void end_frame_context(); + + // RenderDoc integration API for app-guided captures. + static bool init_renderdoc_capture(); + // Calls next_frame_context() and begins a renderdoc capture. + void begin_renderdoc_capture(); + // Calls next_frame_context() and ends the renderdoc capture. + void end_renderdoc_capture(); + + // Set names for objects for debuggers and profilers. + void set_name(const Buffer &buffer, const char *name); + void set_name(const Image &image, const char *name); + void set_name(const CommandBuffer &cmd, const char *name); + // Generic version. + void set_name(uint64_t object, VkObjectType type, const char *name); + + // Submission interface, may be called from any thread at any time. + void flush_frame(); + CommandBufferHandle request_command_buffer(CommandBuffer::Type type = CommandBuffer::Type::Generic); + CommandBufferHandle request_command_buffer_for_thread(unsigned thread_index, CommandBuffer::Type type = CommandBuffer::Type::Generic); + // Must be given back with submit_discard(). + CommandBufferHandle request_borrowed_command_buffer(VkCommandBuffer cmd); + + CommandBufferHandle request_profiled_command_buffer(CommandBuffer::Type type = CommandBuffer::Type::Generic); + CommandBufferHandle request_profiled_command_buffer_for_thread(unsigned thread_index, CommandBuffer::Type type = CommandBuffer::Type::Generic); + + void submit(CommandBufferHandle &cmd, Fence *fence = nullptr, + unsigned semaphore_count = 0, Semaphore *semaphore = nullptr); + + void submit_empty(CommandBuffer::Type type, + Fence *fence = nullptr, + SemaphoreHolder *semaphore = nullptr); + // Mark that there have been work submitted in this frame context outside our control + // that accesses resources Vulkan::Device owns. + void submit_external(CommandBuffer::Type type); + void submit_discard(CommandBufferHandle &cmd); + QueueIndices get_physical_queue_type(CommandBuffer::Type queue_type) const; + void register_time_interval(std::string tid, QueryPoolHandle start_ts, QueryPoolHandle end_ts, + const std::string &tag); + + // Request shaders and programs. These objects are owned by the Device. + Shader *request_shader(const uint32_t *code, size_t size, const ResourceLayout *layout = nullptr); + Shader *request_shader_by_hash(Util::Hash hash); + Program *request_program(const uint32_t *task_data, size_t task_size, + const uint32_t *mesh_data, size_t mesh_size, + const uint32_t *fragment_data, size_t fragment_size, + const ResourceLayout *task_layout = nullptr, + const ResourceLayout *mesh_layout = nullptr, + const ResourceLayout *fragment_layout = nullptr); + Program *request_program(const uint32_t *vertex_data, size_t vertex_size, + const uint32_t *fragment_data, size_t fragment_size, + const ResourceLayout *vertex_layout = nullptr, + const ResourceLayout *fragment_layout = nullptr); + Program *request_program(const uint32_t *compute_data, size_t compute_size, + const ResourceLayout *layout = nullptr); + Program *request_program(Shader *task, Shader *mesh, Shader *fragment, const ImmutableSamplerBank *sampler_bank = nullptr); + Program *request_program(Shader *vertex, Shader *fragment, const ImmutableSamplerBank *sampler_bank = nullptr); + Program *request_program(Shader *compute, const ImmutableSamplerBank *sampler_bank = nullptr); + const IndirectLayout *request_indirect_layout(const PipelineLayout *layout, const IndirectLayoutToken *tokens, + uint32_t num_tokens, uint32_t stride); + + const ImmutableYcbcrConversion *request_immutable_ycbcr_conversion(const VkSamplerYcbcrConversionCreateInfo &info); + const ImmutableSampler *request_immutable_sampler(const SamplerCreateInfo &info, const ImmutableYcbcrConversion *ycbcr); + + // Map and unmap buffer objects. + void *map_host_buffer(const Buffer &buffer, MemoryAccessFlags access); + void unmap_host_buffer(const Buffer &buffer, MemoryAccessFlags access); + void *map_host_buffer(const Buffer &buffer, MemoryAccessFlags access, VkDeviceSize offset, VkDeviceSize length); + void unmap_host_buffer(const Buffer &buffer, MemoryAccessFlags access, VkDeviceSize offset, VkDeviceSize length); + + void *map_linear_host_image(const LinearHostImage &image, MemoryAccessFlags access); + void unmap_linear_host_image_and_sync(const LinearHostImage &image, MemoryAccessFlags access); + + // Create buffers and images. + BufferHandle create_buffer(const BufferCreateInfo &info, const void *initial = nullptr); + BufferHandle create_imported_host_buffer(const BufferCreateInfo &info, VkExternalMemoryHandleTypeFlagBits type, void *host_buffer); + ImageHandle create_image(const ImageCreateInfo &info, const ImageInitialData *initial = nullptr); + ImageHandle create_image_from_staging_buffer(const ImageCreateInfo &info, const InitialImageBuffer *buffer); + LinearHostImageHandle create_linear_host_image(const LinearHostImageCreateInfo &info); + BufferHandle wrap_buffer(const BufferCreateInfo &info, VkBuffer buffer, bool supports_bda = true); + // Does not create any default image views. Only wraps the VkImage + // as a non-owned handle for purposes of API interop. + ImageHandle wrap_image(const ImageCreateInfo &info, VkImage img); + DeviceAllocationOwnerHandle take_device_allocation_ownership(Image &image); + DeviceAllocationOwnerHandle allocate_memory(const MemoryAllocateInfo &info); + + // If cmd is not null, the RTAS is immediately built. + // If compacted_size is not null, a compacted size query will be made. info.mode must be compatible with compaction. + RTASHandle create_rtas(const BottomRTASCreateInfo &info, CommandBuffer *cmd, QueryPoolHandle *compacted_size); + RTASHandle create_rtas(const TopRTASCreateInfo &info, CommandBuffer *cmd); + // Generic creation methods. + RTASHandle create_rtas(VkAccelerationStructureTypeKHR type, VkDeviceSize size); + RTASHandle create_rtas(VkAccelerationStructureTypeKHR type, BufferHandle buffer, VkDeviceSize offset, VkDeviceSize size); + + // Create staging buffers for images. + + // This is deprecated and considered slow path. + // If number of subresources is 1, the fast path can be taken. + InitialImageBuffer create_image_staging_buffer(const ImageCreateInfo &info, const ImageInitialData *initial); + + // Only takes a reference to the layout. + // Ideal path when uploading resources since it's compatible with host image copy, etc. + InitialImageBuffer create_image_staging_buffer(const TextureFormatLayout &layout); + + // Create image view, buffer views and samplers. + ImageViewHandle create_image_view(const ImageViewCreateInfo &view_info); + BufferViewHandle create_buffer_view(const BufferViewCreateInfo &view_info); + SamplerHandle create_sampler(const SamplerCreateInfo &info); + + BindlessDescriptorPoolHandle create_bindless_descriptor_pool(BindlessResourceType type, + unsigned num_sets, unsigned num_descriptors); + + // Render pass helpers. + bool image_format_is_supported(VkFormat format, VkFormatFeatureFlags2KHR required, VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL) const; + void get_format_properties(VkFormat format, VkFormatProperties3KHR *properties) const; + bool get_image_format_properties(VkFormat format, VkImageType type, VkImageTiling tiling, + VkImageUsageFlags usage, VkImageCreateFlags flags, + const void *pNext, + VkImageFormatProperties2 *properties2) const; + + VkFormat get_default_depth_stencil_format() const; + VkFormat get_default_depth_format() const; + ImageHandle get_transient_attachment(unsigned width, unsigned height, VkFormat format, + unsigned index = 0, unsigned samples = 1, unsigned layers = 1); + RenderPassInfo get_swapchain_render_pass(SwapchainRenderPass style); + + // Semaphore API: + // Semaphores in Granite are abstracted to support both binary and timeline semaphores + // internally. + // In practice this means that semaphores behave like single-use binary semaphores, + // with one signal and one wait. + // A single semaphore handle is not reused for multiple submissions, and they must be recycled through + // the device. The intended use is device.submit(&sem), device.add_wait_semaphore(sem); dispose(sem); + // For timeline semaphores, the semaphore is just a proxy object which + // holds the internally owned VkSemaphore + timeline value and is otherwise lightweight. + // + // However, there are various use cases where we explicitly need semaphore objects: + // - Interoperate with other code that only accepts VkSemaphore. + // - Interoperate with external objects. We need to know whether to use binary or timeline. + // For timelines, we need to know which handle type to use (OPAQUE or ID3D12Fence). + // Binary external semaphore is always opaque with TEMPORARY semantics. + + void add_wait_semaphore(CommandBuffer::Type type, Semaphore semaphore, VkPipelineStageFlags2 stages, bool flush); + + // If transfer_ownership is set, Semaphore owns the VkSemaphore. Otherwise, application must + // free the semaphore when GPU usage of it is complete. + Semaphore request_semaphore(VkSemaphoreTypeKHR type, VkSemaphore handle = VK_NULL_HANDLE, bool transfer_ownership = false); + + // Requests a binary or timeline semaphore that can be used to import/export. + // These semaphores cannot be used directly by add_wait_semaphore() and submit_empty(). + // See request_timeline_semaphore_as_binary() for how to use timelines. + Semaphore request_semaphore_external(VkSemaphoreTypeKHR type, + VkExternalSemaphoreHandleTypeFlagBits handle_type); + + // The created semaphore does not hold ownership of the VkSemaphore object. + // This is used when we want to wait on or signal an external timeline semaphore at a specific timeline value. + // We must collapse the timeline to a "binary" semaphore before we can call submit_empty or add_wait_semaphore(). + Semaphore request_timeline_semaphore_as_binary(const SemaphoreHolder &holder, uint64_t value); + + // A proxy semaphore which lets us grab a semaphore handle before we signal it. + // Move assignment can be used to move a payload. + // Mostly useful to deal better with render graph implementation. + // For time being however, we'll support moving the payload over to the proxy object. + Semaphore request_proxy_semaphore(); + + // For compat with existing code that uses this entry point. + inline Semaphore request_legacy_semaphore() { return request_semaphore(VK_SEMAPHORE_TYPE_BINARY_KHR); } + + inline VkDevice get_device() const + { + return device; + } + + inline VkPhysicalDevice get_physical_device() const + { + return gpu; + } + + inline VkInstance get_instance() const + { + return instance; + } + + inline const VkPhysicalDeviceMemoryProperties &get_memory_properties() const + { + return mem_props; + } + + inline const VkPhysicalDeviceProperties &get_gpu_properties() const + { + return gpu_props; + } + + void get_memory_budget(HeapBudget *budget); + + const Sampler &get_stock_sampler(StockSampler sampler) const; + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + // To obtain ShaderManager, ShaderModules must be observed to be complete + // in query_initialization_progress(). + ShaderManager &get_shader_manager(); + ResourceManager &get_resource_manager(); + Granite::FileMappingHandle persistent_pipeline_cache; +#endif + + // Useful for loading screens or otherwise figuring out + // when we can start rendering in a stable state. + enum class InitializationStage + { + CacheMaintenance, + // When this is done, shader modules and the shader manager have been populated. + // At this stage it is safe to use shaders in a configuration where we + // don't have SPIRV-Cross and/or shaderc to do on the fly compilation. + // For shipping configurations. We can still compile pipelines, but it may stutter. + ShaderModules, + // When this is done, pipelines should never stutter if Fossilize knows about the pipeline. + Pipelines + }; + + // 0 -> not started + // [1, 99] rough percentage of completion + // >= 100 done + unsigned query_initialization_progress(InitializationStage status) const; + + // For some platforms, the device and queue might be shared, possibly across threads, so need some mechanism to + // lock the global device and queue. + void set_queue_lock(std::function lock_callback, + std::function unlock_callback); + + // Alternative form, when we have to provide lock callbacks to external APIs. + void external_queue_lock(); + void external_queue_unlock(); + + const ImplementationWorkarounds &get_workarounds() const + { + return workarounds; + } + + const DeviceFeatures &get_device_features() const + { + return ext; + } + + bool consumes_debug_markers() const + { + return debug_marker_sensitive; + } + + bool swapchain_touched() const; + + double convert_device_timestamp_delta(uint64_t start_ticks, uint64_t end_ticks) const; + int64_t convert_timestamp_to_absolute_nsec(const QueryPoolResult &handle); + // Writes a timestamp on host side, which is calibrated to the GPU timebase. + QueryPoolHandle write_calibrated_timestamp(); + + // A split version of VkEvent handling which lets us record a wait command before signal is recorded. + PipelineEvent begin_signal_event(); + + const Context::SystemHandles &get_system_handles() const + { + return system_handles; + } + + void configure_default_geometry_samplers(float max_aniso, float lod_bias); + + bool supports_subgroup_size_log2(bool subgroup_full_group, + uint8_t subgroup_minimum_size_log2, + uint8_t subgroup_maximum_size_log2, + VkShaderStageFlagBits stage = VK_SHADER_STAGE_COMPUTE_BIT) const; + + const QueueInfo &get_queue_info() const; + + void timestamp_log_reset(); + void timestamp_log(const TimestampIntervalReportCallback &cb) const; + +private: + VkInstance instance = VK_NULL_HANDLE; + VkPhysicalDevice gpu = VK_NULL_HANDLE; + VkDevice device = VK_NULL_HANDLE; + const VolkDeviceTable *table = nullptr; + const Context *ctx = nullptr; + QueueInfo queue_info; + unsigned num_thread_indices = 1; + + std::atomic_uint64_t cookie; + + uint64_t allocate_cookie(); + void bake_program(Program &program, const ImmutableSamplerBank *sampler_bank); + void merge_combined_resource_layout(CombinedResourceLayout &layout, const Program &program); + + void request_vertex_block(BufferBlock &block, VkDeviceSize size); + void request_index_block(BufferBlock &block, VkDeviceSize size); + void request_uniform_block(BufferBlock &block, VkDeviceSize size); + void request_staging_block(BufferBlock &block, VkDeviceSize size); + + QueryPoolHandle write_timestamp(VkCommandBuffer cmd, VkPipelineStageFlags2 stage); + + void set_acquire_semaphore(unsigned index, Semaphore acquire); + void set_present_id(VkSwapchainKHR low_latency_swapchain, uint64_t present_id); + Semaphore consume_release_semaphore(); + VkQueue get_current_present_queue() const; + CommandBuffer::Type get_current_present_queue_type() const; + + const PipelineLayout *request_pipeline_layout(const CombinedResourceLayout &layout, + const ImmutableSamplerBank *immutable_samplers); + DescriptorSetAllocator *request_descriptor_set_allocator(const DescriptorSetLayout &layout, + const uint32_t *stages_for_sets, + const ImmutableSampler * const *immutable_samplers); + const Framebuffer &request_framebuffer(const RenderPassInfo &info); + const RenderPass &request_render_pass(const RenderPassInfo &info, bool compatible); + + VkPhysicalDeviceMemoryProperties mem_props; + VkPhysicalDeviceProperties gpu_props; + + DeviceFeatures ext; + bool debug_marker_sensitive = false; + void init_stock_samplers(); + void init_stock_sampler(StockSampler sampler, float max_aniso, float lod_bias); + void init_timeline_semaphores(); + void deinit_timeline_semaphores(); + + uint64_t update_wrapped_device_timestamp(uint64_t ts); + Context::SystemHandles system_handles; + + QueryPoolHandle write_timestamp_nolock(VkCommandBuffer cmd, VkPipelineStageFlags2 stage); + QueryPoolHandle write_calibrated_timestamp_nolock(); + void register_time_interval_nolock(std::string tid, QueryPoolHandle start_ts, QueryPoolHandle end_ts, + const std::string &tag); + + // Make sure this is deleted last. + HandlePool handle_pool; + + // Calibrated timestamps. + void init_calibrated_timestamps(); + void recalibrate_timestamps(); + bool resample_calibrated_timestamps(); + VkTimeDomainEXT calibrated_time_domain = VK_TIME_DOMAIN_DEVICE_EXT; + int64_t calibrated_timestamp_device = 0; + int64_t calibrated_timestamp_host = 0; + int64_t calibrated_timestamp_device_accum = 0; + unsigned timestamp_calibration_counter = 0; + Vulkan::QueryPoolHandle frame_context_begin_ts; + + struct Managers + { + DeviceAllocator memory; + FenceManager fence; + SemaphoreManager semaphore; + EventManager event; + BufferPool vbo, ibo, ubo, staging; + TimestampIntervalManager timestamps; + DescriptorBufferAllocator descriptor_buffer; + BreadcrumbsTracker breadcrumbs; + }; + Managers managers; + + struct + { + std::mutex memory_lock; + std::mutex lock; + std::condition_variable cond; + Util::RWSpinLock read_only_cache; + unsigned counter = 0; + bool async_frame_context = false; + } lock; + + struct PerFrame + { + PerFrame(Device *device, unsigned index); + ~PerFrame(); + void operator=(const PerFrame &) = delete; + PerFrame(const PerFrame &) = delete; + + bool wait(uint64_t timeout); + void begin(); + void trim_command_pools(); + + Device &device; + unsigned frame_index; + const VolkDeviceTable &table; + Managers &managers; + + std::vector cmd_pools[QUEUE_INDEX_COUNT]; + VkSemaphore timeline_semaphores[QUEUE_INDEX_COUNT] = {}; + uint64_t timeline_fences[QUEUE_INDEX_COUNT] = {}; + + QueryPool query_pool_ts, query_pool_rtas; + + std::vector vbo_blocks; + std::vector ibo_blocks; + std::vector ubo_blocks; + std::vector staging_blocks; + + std::vector wait_and_recycle_fences; + + std::vector allocations; + std::vector destroyed_framebuffers; + std::vector destroyed_samplers; + std::vector destroyed_image_views; + std::vector destroyed_buffer_views; + std::vector destroyed_images; + std::vector destroyed_buffers; + std::vector destroyed_rtas; + std::vector destroyed_descriptor_pools; + Util::SmallVector submissions[QUEUE_INDEX_COUNT]; + std::vector recycled_semaphores; + std::vector recycled_events; + std::vector destroyed_semaphores; + std::vector consumed_semaphores; + std::vector destroyed_execution_sets; + std::vector descriptor_buffer_allocs; + std::vector cached_descriptor_payloads; + std::vector breadcrumbs; + + struct DebugChannel + { + DebugChannelInterface *iface; + std::string tag; + BufferHandle buffer; + }; + std::vector debug_channels; + + struct TimestampIntervalHandles + { + std::string tid; + QueryPoolHandle start_ts; + QueryPoolHandle end_ts; + TimestampInterval *timestamp_tag; + }; + std::vector timestamp_intervals; + + bool in_destructor = false; + }; + // The per frame structure must be destroyed after + // the hashmap data structures below, so it must be declared before. + std::vector> per_frame; + + struct + { + Semaphore acquire; + Semaphore release; + std::vector swapchain; + VkQueue present_queue = VK_NULL_HANDLE; + Vulkan::CommandBuffer::Type present_queue_type = {}; + uint32_t queue_family_support_mask = 0; + unsigned index = 0; + bool consumed = false; + + struct + { + uint64_t present_id; + bool need_submit_begin_marker; + VkSwapchainKHR swapchain; + } low_latency = {}; + } wsi; + bool can_touch_swapchain_in_command_buffer(QueueIndices physical_type) const; + + struct QueueData + { + Util::SmallVector wait_semaphores; + Util::SmallVector wait_stages; + bool need_fence = false; + + VkSemaphore timeline_semaphore = VK_NULL_HANDLE; + uint64_t current_timeline = 0; + PerformanceQueryPool performance_query_pool; + uint32_t implicit_sync_to_queues = 0; + uint32_t has_incoming_queue_dependencies = 0; + } queue_data[QUEUE_INDEX_COUNT]; + + struct InternalFence + { + VkFence fence; + VkSemaphore timeline; + uint64_t value; + }; + + void submit_queue(QueueIndices physical_type, InternalFence *fence, + SemaphoreHolder *external_semaphore = nullptr, + unsigned semaphore_count = 0, + Semaphore *semaphore = nullptr, + int profiled_iteration = -1); + + PerFrame &frame() + { + VK_ASSERT(frame_context_index < per_frame.size()); + VK_ASSERT(per_frame[frame_context_index]); + return *per_frame[frame_context_index]; + } + + const PerFrame &frame() const + { + VK_ASSERT(frame_context_index < per_frame.size()); + VK_ASSERT(per_frame[frame_context_index]); + return *per_frame[frame_context_index]; + } + + unsigned frame_context_index = 0; + + uint32_t find_memory_type(BufferDomain domain, uint32_t mask) const; + uint32_t find_memory_type(ImageDomain domain, uint32_t mask) const; + uint32_t find_memory_type(uint32_t required, uint32_t mask) const; + bool memory_type_is_device_optimal(uint32_t type) const; + bool memory_type_is_host_visible(uint32_t type) const; + + const ImmutableSampler *samplers[static_cast(StockSampler::Count)] = {}; + + VulkanCache pipeline_layouts; + VulkanCache descriptor_set_allocators; + VulkanCache render_passes; + VulkanCache shaders; + VulkanCache programs; + VulkanCache immutable_samplers; + VulkanCache immutable_ycbcr_conversions; + VulkanCache indirect_layouts; + + FramebufferAllocator framebuffer_allocator; + TransientAttachmentAllocator transient_allocator; + VkPipelineCache legacy_pipeline_cache = VK_NULL_HANDLE; + PipelineCache pipeline_binary_cache; + + void init_pipeline_cache(); + void flush_pipeline_cache(); + + PerformanceQueryPool &get_performance_query_pool(QueueIndices physical_type); + PipelineEvent request_pipeline_event(); + + std::function queue_lock_callback; + std::function queue_unlock_callback; + void flush_frame_nolock(QueueIndices physical_type); + void submit_empty_inner(QueueIndices type, InternalFence *fence, + SemaphoreHolder *external_semaphore, + unsigned semaphore_count, + Semaphore *semaphore); + + void collect_wait_semaphores(QueueData &data, Helper::WaitSemaphores &semaphores); + void emit_queue_signals(Helper::BatchComposer &composer, + SemaphoreHolder *external_semaphore, + VkSemaphore sem, uint64_t timeline, InternalFence *fence, + unsigned semaphore_count, Semaphore *semaphores); + void emit_implicit_sync_to_queues(QueueIndices physical_type); + VkResult submit_batches(Helper::BatchComposer &composer, VkQueue queue, VkFence fence, + int profiling_iteration = -1); + VkResult queue_submit(VkQueue queue, uint32_t count, const VkSubmitInfo2 *submits, VkFence fence); + + void destroy_buffer(VkBuffer buffer); + void destroy_rtas(VkAccelerationStructureKHR rtas); + void destroy_image(VkImage image); + void destroy_image_view(const CachedImageView &view); + void destroy_buffer_view(const CachedBufferView &view); + void destroy_sampler(VkSampler sampler); + void destroy_framebuffer(VkFramebuffer framebuffer); + void destroy_semaphore(VkSemaphore semaphore); + void consume_semaphore(VkSemaphore semaphore); + void recycle_semaphore(VkSemaphore semaphore); + void destroy_event(VkEvent event); + void free_memory(const DeviceAllocation &alloc); + void reset_fence(VkFence fence, bool observed_wait); + void destroy_descriptor_pool(VkDescriptorPool desc_pool); + void destroy_indirect_execution_set(VkIndirectExecutionSetEXT exec_set); + void free_descriptor_buffer_allocation(const DescriptorBufferAllocation &alloc); + void free_cached_descriptor_payload(const CachedDescriptorPayload &payload); + + void destroy_buffer_nolock(VkBuffer buffer); + void destroy_rtas_nolock(VkAccelerationStructureKHR rtas); + void destroy_image_nolock(VkImage image); + void destroy_image_view_nolock(const CachedImageView &view); + void destroy_buffer_view_nolock(const CachedBufferView &view); + void destroy_sampler_nolock(VkSampler sampler); + void destroy_framebuffer_nolock(VkFramebuffer framebuffer); + void destroy_semaphore_nolock(VkSemaphore semaphore); + void consume_semaphore_nolock(VkSemaphore semaphore); + void recycle_semaphore_nolock(VkSemaphore semaphore); + void destroy_event_nolock(VkEvent event); + void free_memory_nolock(const DeviceAllocation &alloc); + void destroy_descriptor_pool_nolock(VkDescriptorPool desc_pool); + void reset_fence_nolock(VkFence fence, bool observed_wait); + void destroy_indirect_execution_set_nolock(VkIndirectExecutionSetEXT exec_set); + void free_descriptor_buffer_allocation_nolock(const DescriptorBufferAllocation &alloc); + void free_cached_descriptor_payload_nolock(const CachedDescriptorPayload &payload); + + void flush_frame_nolock(); + CommandBufferHandle request_command_buffer_nolock(unsigned thread_index, CommandBuffer::Type type, bool profiled); + void submit_discard_nolock(CommandBufferHandle &cmd); + void submit_and_sync_to_queues(CommandBufferHandle &cmd, uint32_t sync_to_queues); + void submit_nolock(CommandBufferHandle cmd, Fence *fence, + unsigned semaphore_count, Semaphore *semaphore); + void submit_empty_nolock(QueueIndices physical_type, Fence *fence, + SemaphoreHolder *semaphore, int profiling_iteration); + void add_wait_semaphore_nolock(QueueIndices type, Semaphore semaphore, + VkPipelineStageFlags2 stages, bool flush); + + void request_vertex_block_nolock(BufferBlock &block, VkDeviceSize size); + void request_index_block_nolock(BufferBlock &block, VkDeviceSize size); + void request_uniform_block_nolock(BufferBlock &block, VkDeviceSize size); + void request_staging_block_nolock(BufferBlock &block, VkDeviceSize size); + + CommandBufferHandle request_secondary_command_buffer_for_thread(unsigned thread_index, + const Framebuffer *framebuffer, + unsigned subpass, + CommandBuffer::Type type = CommandBuffer::Type::Generic); + void add_frame_counter_nolock(); + void decrement_frame_counter_nolock(); + void submit_secondary(CommandBuffer &primary, CommandBuffer &secondary); + void wait_idle_nolock(); + void end_frame_nolock(); + + void add_debug_channel_buffer(DebugChannelInterface *iface, std::string tag, BufferHandle buffer); + void parse_debug_channel(const PerFrame::DebugChannel &channel); + + Fence request_legacy_fence(); + +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + ShaderManager shader_manager; + ResourceManager resource_manager; + void init_shader_manager_cache(Granite::TaskGroup *shader_compilation_group); + void flush_shader_manager_cache(); +#endif + +#ifdef GRANITE_VULKAN_FOSSILIZE + bool enqueue_create_sampler(Fossilize::Hash hash, const VkSamplerCreateInfo *create_info, VkSampler *sampler) override; + bool enqueue_create_descriptor_set_layout(Fossilize::Hash hash, const VkDescriptorSetLayoutCreateInfo *create_info, VkDescriptorSetLayout *layout) override; + bool enqueue_create_pipeline_layout(Fossilize::Hash hash, const VkPipelineLayoutCreateInfo *create_info, VkPipelineLayout *layout) override; + bool enqueue_create_shader_module(Fossilize::Hash hash, const VkShaderModuleCreateInfo *create_info, VkShaderModule *module) override; + bool enqueue_create_render_pass(Fossilize::Hash hash, const VkRenderPassCreateInfo *create_info, VkRenderPass *render_pass) override; + bool enqueue_create_render_pass2(Fossilize::Hash hash, const VkRenderPassCreateInfo2 *create_info, VkRenderPass *render_pass) override; + bool enqueue_create_compute_pipeline(Fossilize::Hash hash, const VkComputePipelineCreateInfo *create_info, VkPipeline *pipeline) override; + bool enqueue_create_graphics_pipeline(Fossilize::Hash hash, const VkGraphicsPipelineCreateInfo *create_info, VkPipeline *pipeline) override; + bool enqueue_create_raytracing_pipeline(Fossilize::Hash hash, const VkRayTracingPipelineCreateInfoKHR *create_info, VkPipeline *pipeline) override; + bool fossilize_replay_graphics_pipeline(Fossilize::Hash hash, VkGraphicsPipelineCreateInfo &info); + bool fossilize_replay_compute_pipeline(Fossilize::Hash hash, VkComputePipelineCreateInfo &info); + + void replay_tag_simple(Fossilize::ResourceTag tag); + + void register_graphics_pipeline(Fossilize::Hash hash, const VkGraphicsPipelineCreateInfo &info); + void register_compute_pipeline(Fossilize::Hash hash, const VkComputePipelineCreateInfo &info); + void register_render_pass(VkRenderPass render_pass, Fossilize::Hash hash, const VkRenderPassCreateInfo2KHR &info); + void register_descriptor_set_layout(VkDescriptorSetLayout layout, Fossilize::Hash hash, const VkDescriptorSetLayoutCreateInfo &info); + void register_pipeline_layout(VkPipelineLayout layout, Fossilize::Hash hash, const VkPipelineLayoutCreateInfo &info); + void register_shader_module(VkShaderModule module, Fossilize::Hash hash, const VkShaderModuleCreateInfo &info); + void register_sampler(VkSampler sampler, Fossilize::Hash hash, const VkSamplerCreateInfo &info); + void register_sampler_ycbcr_conversion(VkSamplerYcbcrConversion ycbcr, const VkSamplerYcbcrConversionCreateInfo &info); + + struct RecorderState; + std::unique_ptr recorder_state; + + struct ReplayerState; + std::unique_ptr replayer_state; + + void promote_write_cache_to_readonly() const; + void promote_readonly_db_from_assets() const; + + void init_pipeline_state(const Fossilize::FeatureFilter &filter, + const VkPhysicalDeviceFeatures2 &pdf2, + const VkApplicationInfo &application_info); + void flush_pipeline_state(); + void block_until_shader_module_ready(); + void block_until_pipeline_ready(); +#endif + + ImplementationWorkarounds workarounds; + void init_workarounds(); + + void fill_buffer_sharing_indices(VkBufferCreateInfo &create_info, uint32_t *sharing_indices); + + bool allocate_image_memory(DeviceAllocation *allocation, const ImageCreateInfo &info, + VkImage image, VkImageTiling tiling, VkImageUsageFlags usage); + + void promote_read_write_caches_to_read_only(); +}; + +// A fairly complex helper used for async queue readbacks. +// Typically used for things like headless backend which emulates WSI through readbacks + encode. +struct OwnershipTransferInfo +{ + CommandBuffer::Type old_queue; + CommandBuffer::Type new_queue; + VkImageLayout old_image_layout; + VkImageLayout new_image_layout; + VkPipelineStageFlags2 dst_pipeline_stage; + VkAccessFlags2 dst_access; +}; + +// For an image which was last accessed in old_queue, requests a command buffer +// for new_queue. Commands will be enqueued as necessary in new_queue to ensure that a complete ownership +// transfer has taken place. +// If queue family for old_queue differs from new_queue, a release barrier is enqueued in old_queue. +// In new_queue we perform either an acquire barrier or a simple pipeline barrier to change layout if required. +// If semaphore is a valid handle, it will be waited on in either old_queue to perform release barrier +// or new_queue depending on what is required. +// If the image uses CONCURRENT sharing mode, acquire/release barriers are skipped. +CommandBufferHandle request_command_buffer_with_ownership_transfer( + Device &device, + const Vulkan::Image &image, + const OwnershipTransferInfo &info, + const Vulkan::Semaphore &semaphore); + +using DeviceHandle = Util::IntrusivePtr; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device_fossilize.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device_fossilize.cpp new file mode 100644 index 00000000..df697381 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device_fossilize.cpp @@ -0,0 +1,1184 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "device_fossilize.hpp" +#include "timer.hpp" +#include "thread_group.hpp" +#include "fossilize_db.hpp" +#include "dynamic_array.hpp" + +namespace Vulkan +{ +Device::RecorderState::RecorderState() +{ + recorder_ready.store(false, std::memory_order_relaxed); +} + +Device::RecorderState::~RecorderState() +{ +} + +Device::ReplayerState::ReplayerState() +{ + progress.prepare.store(0, std::memory_order_relaxed); + progress.modules.store(0, std::memory_order_relaxed); + progress.pipelines.store(0, std::memory_order_relaxed); +} + +Device::ReplayerState::~ReplayerState() +{ +} + +void Device::register_sampler(VkSampler sampler, Fossilize::Hash hash, const VkSamplerCreateInfo &info) +{ + if (!recorder_state) + return; + + if (!recorder_state->recorder_ready.load(std::memory_order_acquire)) + { + LOGW("Attempting to register sampler before recorder is ready.\n"); + return; + } + + if (!recorder_state->recorder.record_sampler(sampler, info, hash)) + LOGW("Failed to register sampler.\n"); +} + +void Device::register_sampler_ycbcr_conversion( + VkSamplerYcbcrConversion ycbcr, const VkSamplerYcbcrConversionCreateInfo &info) +{ + if (!recorder_state) + return; + + if (!recorder_state->recorder_ready.load(std::memory_order_acquire)) + { + LOGW("Attempting to register sampler YCbCr conversion before recorder is ready.\n"); + return; + } + + if (!recorder_state->recorder.record_ycbcr_conversion(ycbcr, info)) + LOGW("Failed to register YCbCr conversion.\n"); +} + +void Device::register_descriptor_set_layout(VkDescriptorSetLayout layout, Fossilize::Hash hash, const VkDescriptorSetLayoutCreateInfo &info) +{ + if (!recorder_state) + return; + + if (!recorder_state->recorder_ready.load(std::memory_order_acquire)) + { + LOGW("Attempting to register descriptor set layout before recorder is ready.\n"); + return; + } + + if (!recorder_state->recorder.record_descriptor_set_layout(layout, info, hash)) + LOGW("Failed to register descriptor set layout.\n"); +} + +void Device::register_pipeline_layout(VkPipelineLayout layout, Fossilize::Hash hash, const VkPipelineLayoutCreateInfo &info) +{ + if (!recorder_state) + return; + + if (!recorder_state->recorder_ready.load(std::memory_order_acquire)) + { + LOGW("Attempting to register pipeline layout before recorder is ready.\n"); + return; + } + + if (!recorder_state->recorder.record_pipeline_layout(layout, info, hash)) + LOGW("Failed to register pipeline layout.\n"); +} + +void Device::register_shader_module(VkShaderModule module, Fossilize::Hash hash, const VkShaderModuleCreateInfo &info) +{ + if (!recorder_state) + return; + + if (!recorder_state->recorder_ready.load(std::memory_order_acquire)) + { + LOGW("Attempting to register shader module before recorder is ready.\n"); + return; + } + + replayer_state->feature_filter->register_shader_module_info(module, &info); + + if (!recorder_state->recorder.record_shader_module(module, info, hash)) + LOGW("Failed to register shader module.\n"); +} + +void Device::register_compute_pipeline(Fossilize::Hash hash, const VkComputePipelineCreateInfo &info) +{ + if (!recorder_state) + return; + + if (!recorder_state->recorder_ready.load(std::memory_order_acquire)) + { + LOGW("Attempting to register compute pipeline before recorder is ready.\n"); + return; + } + + // Normalize the creation for both non-DB and DB. + auto tmp = info; + + if (const auto *flags = find_pnext( + info.pNext, VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO)) + { + const_cast(flags)->flags &= + ~(VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT | VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT); + } + else + { + tmp.flags &= ~VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + } + + if (!recorder_state->recorder.record_compute_pipeline(VK_NULL_HANDLE, tmp, nullptr, 0, hash)) + LOGW("Failed to register compute pipeline.\n"); +} + +void Device::register_graphics_pipeline(Fossilize::Hash hash, const VkGraphicsPipelineCreateInfo &info) +{ + if (!recorder_state) + return; + + if (!recorder_state->recorder_ready.load(std::memory_order_acquire)) + { + LOGW("Attempting to register graphics pipeline before recorder is ready.\n"); + return; + } + + // Normalize the creation for both non-DB and DB. + auto tmp = info; + + if (const auto *flags = find_pnext( + info.pNext, VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO)) + { + const_cast(flags)->flags &= + ~(VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT | VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT); + } + else + { + tmp.flags &= ~VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + } + + if (!recorder_state->recorder.record_graphics_pipeline(VK_NULL_HANDLE, tmp, nullptr, 0, hash)) + LOGW("Failed to register graphics pipeline.\n"); +} + +void Device::register_render_pass(VkRenderPass render_pass, Fossilize::Hash hash, const VkRenderPassCreateInfo2KHR &info) +{ + if (!recorder_state) + return; + + if (!recorder_state->recorder_ready.load(std::memory_order_acquire)) + { + LOGW("Attempting to register render pass before recorder is ready.\n"); + return; + } + + if (!recorder_state->recorder.record_render_pass2(render_pass, info, hash)) + LOGW("Failed to register render pass.\n"); +} + +bool Device::enqueue_create_shader_module(Fossilize::Hash hash, const VkShaderModuleCreateInfo *create_info, VkShaderModule *module) +{ + if (!replayer_state->feature_filter->shader_module_is_supported(create_info)) + { + *module = VK_NULL_HANDLE; + replayer_state->progress.modules.fetch_add(1, std::memory_order_release); + return true; + } + + ResourceLayout layout; + + // If we know the resource layout already, just reuse that. Avoids spinning up SPIRV-Cross reflection + // and allows us to not even build it for release builds. + if (shader_manager.get_resource_layout_by_shader_hash(hash, layout)) + shaders.emplace_yield(hash, hash, this, create_info->pCode, create_info->codeSize, &layout); + else + shaders.emplace_yield(hash, hash, this, create_info->pCode, create_info->codeSize); + + // Resolve the handles later. + *module = (VkShaderModule)hash; + replayer_state->progress.modules.fetch_add(1, std::memory_order_release); + return true; +} + +static void remove_pnext(void *chain_, VkStructureType sType) +{ + auto *chain = static_cast(chain_); + while (chain && chain->pNext) + { + auto *next = chain->pNext; + if (next->sType == sType) + { + chain->pNext = next->pNext; + return; + } + + chain = next; + } +} + +bool Device::fossilize_replay_graphics_pipeline(Fossilize::Hash hash, VkGraphicsPipelineCreateInfo &info) +{ + int vert_index = -1; + int task_index = -1; + int mesh_index = -1; + int frag_index = -1; + + for (uint32_t i = 0; i < info.stageCount; i++) + { + switch (info.pStages[i].stage) + { + case VK_SHADER_STAGE_VERTEX_BIT: + vert_index = int(i); + break; + + case VK_SHADER_STAGE_TASK_BIT_EXT: + task_index = int(i); + break; + + case VK_SHADER_STAGE_MESH_BIT_EXT: + mesh_index = int(i); + break; + + case VK_SHADER_STAGE_FRAGMENT_BIT: + frag_index = int(i); + break; + + default: + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return false; + } + } + + if (frag_index < 0 || (mesh_index < 0 && vert_index < 0) || + (mesh_index >= 0 && vert_index >= 0)) + { + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return false; + } + + auto *vert_shader = vert_index >= 0 ? shaders.find((Fossilize::Hash)info.pStages[vert_index].module) : nullptr; + auto *task_shader = task_index >= 0 ? shaders.find((Fossilize::Hash)info.pStages[task_index].module) : nullptr; + auto *mesh_shader = mesh_index >= 0 ? shaders.find((Fossilize::Hash)info.pStages[mesh_index].module) : nullptr; + auto *frag_shader = shaders.find((Fossilize::Hash)info.pStages[frag_index].module); + + if ((!vert_shader && !mesh_shader) || !frag_shader) + { + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return false; + } + + Program *ret; + if (mesh_shader) + { + ret = request_program(task_shader, mesh_shader, frag_shader, + reinterpret_cast(info.layout)); + } + else + { + ret = request_program(vert_shader, frag_shader, + reinterpret_cast(info.layout)); + } + + if (ret) + { + // The layout is dummy, resolve it here. + info.layout = ret->get_pipeline_layout()->get_layout(); + + // Resolve shader modules. + if (vert_index >= 0) + const_cast(info.pStages)[vert_index].module = vert_shader->get_module(); + if (task_index >= 0) + const_cast(info.pStages)[task_index].module = task_shader->get_module(); + if (mesh_index >= 0) + const_cast(info.pStages)[mesh_index].module = mesh_shader->get_module(); + const_cast(info.pStages)[frag_index].module = frag_shader->get_module(); + } + + // Patch in heap information late. + VkPipelineCreateFlags2CreateInfo flags2 = { VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO }; + VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info[3]; + + if (ret && ext.descriptor_heap_features.descriptorHeap) + { + if (!find_pnext(info.pNext, flags2.sType)) + { + flags2.flags = info.flags | VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT; + flags2.pNext = info.pNext; + info.pNext = &flags2; + } + + auto &mappings = ret->get_pipeline_layout()->get_heap_mappings(); + for (uint32_t i = 0; i < info.stageCount; i++) + { + mapping_info[i] = { VK_STRUCTURE_TYPE_SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT }; + mapping_info[i].pNext = info.pStages[i].pNext; + mapping_info[i].mappingCount = uint32_t(mappings.size()); + mapping_info[i].pMappings = mappings.data(); + const_cast(info.pStages[i]).pNext = &mapping_info[i]; + } + } + + auto *f2 = find_pnext(info.pNext, flags2.sType); + // No need to use flags2, demote to stay more compatible with legacy drivers. + if (f2 && (f2->flags >> 32) == 0) + remove_pnext(&info, VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO); + + if (!ret || !replayer_state->feature_filter->graphics_pipeline_is_supported(&info)) + { + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return true; + } + +#ifdef VULKAN_DEBUG + LOGI("Replaying graphics pipeline.\n"); +#endif + + uint32_t dynamic_state = 0; + if (info.pDynamicState) + { + for (uint32_t i = 0; i < info.pDynamicState->dynamicStateCount; i++) + { + switch (info.pDynamicState->pDynamicStates[i]) + { + case VK_DYNAMIC_STATE_VIEWPORT: + dynamic_state |= COMMAND_BUFFER_DIRTY_VIEWPORT_BIT; + break; + + case VK_DYNAMIC_STATE_SCISSOR: + dynamic_state |= COMMAND_BUFFER_DIRTY_SCISSOR_BIT; + break; + + case VK_DYNAMIC_STATE_DEPTH_BIAS: + dynamic_state |= COMMAND_BUFFER_DIRTY_DEPTH_BIAS_BIT; + break; + + case VK_DYNAMIC_STATE_STENCIL_REFERENCE: + case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: + case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: + dynamic_state |= COMMAND_BUFFER_DIRTY_STENCIL_REFERENCE_BIT; + break; + + default: + break; + } + } + } + + VkPipeline pipeline = VK_NULL_HANDLE; + VkResult res = pipeline_binary_cache.create_pipeline(&info, legacy_pipeline_cache, &pipeline); + if (res != VK_SUCCESS) + { + LOGE("Failed to create graphics pipeline!\n"); + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return false; + } + + auto actual_pipe = ret->add_pipeline(hash, { pipeline, dynamic_state }).pipeline; + if (actual_pipe != pipeline) + table->vkDestroyPipeline(device, pipeline, nullptr); + + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return actual_pipe != VK_NULL_HANDLE; +} + +bool Device::fossilize_replay_compute_pipeline(Fossilize::Hash hash, VkComputePipelineCreateInfo &info) +{ + // Find the Shader* associated with this VkShaderModule and just use that. + auto *shader = shaders.find((Fossilize::Hash)info.stage.module); + if (!shader) + { + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return false; + } + + auto *ret = request_program(shader, reinterpret_cast(info.layout)); + + if (ret) + { + // The layout is dummy, resolve it here. + info.layout = ret->get_pipeline_layout()->get_layout(); + + // Resolve shader module. + info.stage.module = shader->get_module(); + } + + // Patch in heap information late. + VkPipelineCreateFlags2CreateInfo flags2 = { VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO }; + VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = + { VK_STRUCTURE_TYPE_SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT }; + + if (ret && ext.descriptor_heap_features.descriptorHeap) + { + if (!find_pnext(info.pNext, flags2.sType)) + { + flags2.flags = info.flags | VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT; + flags2.pNext = info.pNext; + info.pNext = &flags2; + } + + auto &mappings = ret->get_pipeline_layout()->get_heap_mappings(); + mapping_info = { VK_STRUCTURE_TYPE_SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT }; + mapping_info.pNext = info.stage.pNext; + mapping_info.mappingCount = uint32_t(mappings.size()); + mapping_info.pMappings = mappings.data(); + info.stage.pNext = &mapping_info; + } + + auto *f2 = find_pnext(info.pNext, flags2.sType); + // No need to use flags2, demote to stay more compatible with legacy drivers. + if (f2 && (f2->flags >> 32) == 0) + remove_pnext(&info, VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO); + + if (!ret || !replayer_state->feature_filter->compute_pipeline_is_supported(&info)) + { + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return true; + } + +#ifdef VULKAN_DEBUG + LOGI("Replaying compute pipeline.\n"); +#endif + VkPipeline pipeline = VK_NULL_HANDLE; + VkResult res = pipeline_binary_cache.create_pipeline(&info, legacy_pipeline_cache, &pipeline); + if (res != VK_SUCCESS) + { + LOGE("Failed to create compute pipeline!\n"); + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return false; + } + + auto actual_pipe = ret->add_pipeline(hash, { pipeline, 0 }).pipeline; + if (actual_pipe != pipeline) + table->vkDestroyPipeline(device, pipeline, nullptr); + + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return actual_pipe != VK_NULL_HANDLE; +} + +bool Device::enqueue_create_graphics_pipeline(Fossilize::Hash hash, + const VkGraphicsPipelineCreateInfo *create_info, + VkPipeline *pipeline) +{ + for (uint32_t i = 0; i < create_info->stageCount; i++) + { + if (create_info->pStages[i].module == VK_NULL_HANDLE) + { + *pipeline = VK_NULL_HANDLE; + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return true; + } + } + + if (create_info->renderPass == VK_NULL_HANDLE) + { + *pipeline = VK_NULL_HANDLE; + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return true; + } + + auto *flags2 = find_pnext( + create_info->pNext, VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO); + + // Re-introduce descriptor buffer flag if needed. + if (ext.supports_descriptor_buffer) + { + const_cast(create_info)->flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + if (flags2) + const_cast(flags2)->flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + } + + if (ext.descriptor_heap_features.descriptorHeap) + { + // Fix up missing flags2 later. + if (flags2) + const_cast(flags2)->flags |= VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT; + } + + // The lifetime of create_info is tied to the replayer itself. + replayer_state->graphics_pipelines.emplace_back(hash, const_cast(create_info)); + return true; +} + +bool Device::enqueue_create_compute_pipeline(Fossilize::Hash hash, + const VkComputePipelineCreateInfo *create_info, + VkPipeline *pipeline) +{ + if (create_info->stage.module == VK_NULL_HANDLE) + { + *pipeline = VK_NULL_HANDLE; + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + return true; + } + + auto *flags2 = find_pnext( + create_info->pNext, VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO); + + // Re-introduce descriptor buffer flag if needed. + if (ext.supports_descriptor_buffer) + { + const_cast(create_info)->flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + if (flags2) + const_cast(flags2)->flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + } + + if (ext.descriptor_heap_features.descriptorHeap) + { + // Fix up missing flags2 later. + if (flags2) + const_cast(flags2)->flags |= VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT; + } + + // The lifetime of create_info is tied to the replayer itself. + replayer_state->compute_pipelines.emplace_back(hash, const_cast(create_info)); + return true; +} + +bool Device::enqueue_create_render_pass(Fossilize::Hash, + const VkRenderPassCreateInfo *, + VkRenderPass *) +{ + return false; +} + +bool Device::enqueue_create_render_pass2(Fossilize::Hash hash, const VkRenderPassCreateInfo2 *create_info, VkRenderPass *render_pass) +{ + if (!replayer_state->feature_filter->render_pass2_is_supported(create_info)) + { + render_pass = VK_NULL_HANDLE; + return true; + } + + auto *pass = render_passes.emplace_yield(hash, hash, this, *create_info); + *render_pass = pass->get_render_pass(); + return true; +} + +bool Device::enqueue_create_raytracing_pipeline( + Fossilize::Hash, const VkRayTracingPipelineCreateInfoKHR *, VkPipeline *) +{ + return false; +} + +bool Device::enqueue_create_sampler(Fossilize::Hash hash, const VkSamplerCreateInfo *info, VkSampler *vk_sampler) +{ + if (!replayer_state->feature_filter->sampler_is_supported(info)) + { + *vk_sampler = VK_NULL_HANDLE; + return false; + } + + const ImmutableYcbcrConversion *ycbcr = nullptr; + + if (info->pNext) + { + // YCbCr conversion create infos are replayed inline in Fossilize. + const auto *ycbcr_info = static_cast(info->pNext); + if (ycbcr_info && ycbcr_info->sType == VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO) + ycbcr = request_immutable_ycbcr_conversion(*ycbcr_info); + } + + auto sampler_info = Sampler::fill_sampler_info(*info); + auto *samp = immutable_samplers.emplace_yield(hash, hash, this, sampler_info, ycbcr); + *vk_sampler = reinterpret_cast(samp); + return true; +} + +bool Device::enqueue_create_descriptor_set_layout(Fossilize::Hash, const VkDescriptorSetLayoutCreateInfo *info, VkDescriptorSetLayout *layout) +{ + if (!replayer_state->feature_filter->descriptor_set_layout_is_supported(info)) + { + *layout = VK_NULL_HANDLE; + return true; + } + + auto &alloc = replayer_state->base_replayer.get_allocator(); + auto *sampler_bank = alloc.allocate_n_cleared(VULKAN_NUM_BINDINGS); + + if (!ext.supports_descriptor_buffer) + { + // For now, we have no easy way of supporting immutable samplers with descriptor buffers. + // They are never really used anyway, so ... + for (uint32_t i = 0; i < info->bindingCount; i++) + if (info->pBindings[i].pImmutableSamplers && info->pBindings[i].pImmutableSamplers[0] != VK_NULL_HANDLE) + sampler_bank[i] = reinterpret_cast(info->pBindings[i].pImmutableSamplers[0]); + } + + *layout = reinterpret_cast(sampler_bank); + return true; +} + +bool Device::enqueue_create_pipeline_layout(Fossilize::Hash, const VkPipelineLayoutCreateInfo *info, VkPipelineLayout *layout) +{ + if (!replayer_state->feature_filter->pipeline_layout_is_supported(info)) + { + *layout = VK_NULL_HANDLE; + return true; + } + + auto &alloc = replayer_state->base_replayer.get_allocator(); + auto *sampler_bank = alloc.allocate_cleared(); + for (uint32_t i = 0; i < info->setLayoutCount; i++) + { + memcpy(sampler_bank->samplers[i], + reinterpret_cast(info->pSetLayouts[i]), + sizeof(sampler_bank->samplers[i])); + } + + *layout = reinterpret_cast(sampler_bank); + return true; +} + +void Device::promote_readonly_db_from_assets() const +{ + auto *fs = get_system_handles().filesystem; + + // We might want to be able to ship a Fossilize database so that we can prime all PSOs up front. + Granite::FileStat s_cache = {}; + Granite::FileStat s_assets = {}; + bool cache_exists = fs->stat("cache://fossilize/db.foz", s_cache) && s_cache.type == Granite::PathType::File; + bool assets_exists = fs->stat("assets://fossilize/db.foz", s_assets) && s_assets.type == Granite::PathType::File; + + bool overwrite = false; + if (assets_exists) + { + if (!cache_exists) + { + overwrite = true; + } + else + { + // If an application updates the assets Foz DB for shipping updates, throw the old one away. + std::string cache_iter, asset_iter; + if (!fs->read_file_to_string("cache://fossilize/iteration", cache_iter) || + !fs->read_file_to_string("assets://fossilize/iteration", asset_iter) || + cache_iter != asset_iter) + { + overwrite = true; + } + } + } + + if (overwrite) + { + // The Fossilize DB needs to work with a proper file system. The assets folder is highly virtual by nature. + auto ro = fs->open_readonly_mapping("assets://fossilize/db.foz"); + if (!ro) + { + LOGE("Failed to open readonly Fossilize archive.\n"); + return; + } + + if (!fs->write_buffer_to_file("cache://fossilize/db.foz", ro->data(), ro->get_size())) + { + LOGE("Failed to write to cache://fossilize/db.foz"); + return; + } + + std::string asset_iter; + if (fs->read_file_to_string("assets://fossilize/iteration", asset_iter)) + fs->write_string_to_file("cache://fossilize/iteration", asset_iter); + } +} + +void Device::replay_tag_simple(Fossilize::ResourceTag tag) +{ + size_t count = 0; + replayer_state->db->get_hash_list_for_resource_tag(tag, &count, nullptr); + std::vector hashes(count); + replayer_state->db->get_hash_list_for_resource_tag(tag, &count, hashes.data()); + + Util::DynamicArray buffer; + auto &db = *replayer_state->db; + size_t size = 0; + + for (auto hash : hashes) + { + if (!db.read_entry(tag, hash, &size, nullptr, 0)) + continue; + buffer.reserve(size); + if (!db.read_entry(tag, hash, &size, buffer.data(), 0)) + continue; + if (!replayer_state->base_replayer.parse(*this, &db, buffer.data(), size)) + LOGW("Failed to replay object.\n"); + } +} + +void Device::promote_write_cache_to_readonly() const +{ + auto *fs = get_system_handles().filesystem; + auto list = fs->list("cache://fossilize"); + std::vector merge_paths_str; + std::vector del_paths_str; + std::vector merge_paths; + merge_paths_str.reserve(list.size()); + merge_paths.reserve(list.size()); + bool have_read_only = false; + + for (auto &l : list) + { + if (l.type != Granite::PathType::File || l.path == "fossilize/iteration" || l.path == "fossilize/TOUCH") + continue; + else if (l.path == "fossilize/db.foz") + { + have_read_only = true; + LOGI("Fossilize: Found read-only cache.\n"); + continue; + } + else if (l.path == "fossilize/merge.foz") + { + del_paths_str.emplace_back("cache://fossilize/merge.foz"); + continue; + } + + auto p = "cache://" + l.path; + merge_paths_str.push_back(p); + del_paths_str.push_back(p); + LOGI("Fossilize: Found write cache: %s.\n", merge_paths_str.back().c_str()); + } + + if (!have_read_only && merge_paths_str.size() == 1) + { + LOGI("Fossilize: No read-cache and one write cache. Replacing directly.\n"); + if (fs->move_replace("cache://fossilize/db.foz", merge_paths_str.front())) + LOGI("Fossilize: Promoted write-only cache.\n"); + else + LOGW("Fossilize: Failed to promote write-only cache.\n"); + } + else if (!merge_paths_str.empty()) + { + auto append_path = fs->get_filesystem_path("cache://fossilize/merge.foz"); + bool should_merge; + + // Ensure that we have taken exclusive write access to this file. + // Only one process will be able to pass this test until the file is removed. + if (have_read_only) + { + LOGI("Fossilize: Attempting to merge caches.\n"); + should_merge = fs->move_yield("cache://fossilize/merge.foz", "cache://fossilize/db.foz"); + } + else + { + auto db = std::unique_ptr( + Fossilize::create_stream_archive_database(append_path.c_str(), Fossilize::DatabaseMode::ExclusiveOverWrite)); + should_merge = db && db->prepare(); + } + + if (should_merge) + { + for (auto &str : merge_paths_str) + { + str = fs->get_filesystem_path(str); + merge_paths.push_back(str.c_str()); + } + + if (Fossilize::merge_concurrent_databases(append_path.c_str(), merge_paths.data(), merge_paths.size())) + { + if (fs->move_replace("cache://fossilize/db.foz", "cache://fossilize/merge.foz")) + LOGI("Fossilize: Successfully merged caches.\n"); + else + LOGW("Fossilize: Failed to replace existing read-only database.\n"); + } + else + LOGW("Fossilize: Failed to merge databases.\n"); + } + else + LOGW("Fossilize: Skipping merge due to unexpected error.\n"); + } + else + LOGI("Fossilize: No write only files, nothing to do.\n"); + + // Cleanup any stale write-only files. + // This can easily race against concurrent processes, so the cache will likely be destroyed by accident, + // but that's ok. Running multiple Granite processes concurrently like this is questionable at best. + for (auto &str : del_paths_str) + fs->remove(str); +} + +void Device::init_pipeline_state(const Fossilize::FeatureFilter &filter, + const VkPhysicalDeviceFeatures2 &pdf2, + const VkApplicationInfo &application_info) +{ + if (!get_system_handles().filesystem) + { + LOGW("Filesystem system handle must be provided to use Fossilize.\n"); + return; + } + + if (!get_system_handles().thread_group) + { + LOGW("Thread group system handle must be provided to use Fossilize.\n"); + return; + } + + replayer_state.reset(new ReplayerState); + recorder_state.reset(new RecorderState); + + if (!recorder_state->recorder.record_application_info(application_info)) + LOGW("Failed to record application info.\n"); + if (!recorder_state->recorder.record_physical_device_features(&pdf2)) + LOGW("Failed to record PDF2.\n"); + + lock.read_only_cache.lock_read(); + + // Only non-const usage is to register modules, and that is atomic within the implementation. + replayer_state->feature_filter = const_cast(&filter); + + auto *group = get_system_handles().thread_group; + auto shader_compilation = group->create_task(); + + shader_compilation->set_desc("shaderc-compilation"); + + auto shader_manager_task = group->create_task([this, task = shader_compilation]() mutable { + init_shader_manager_cache(task.get()); + }); + shader_manager_task->set_desc("shader-manager-init"); + + auto cache_maintenance_task = group->create_task([this]() { + // Ensure we create the Fossilize cache folder. + // Also creates a timestamp. + get_system_handles().filesystem->open("cache://fossilize/TOUCH", Granite::FileMode::WriteOnly); + replayer_state->progress.prepare.fetch_add(20, std::memory_order_release); + promote_write_cache_to_readonly(); + replayer_state->progress.prepare.fetch_add(50, std::memory_order_release); + promote_readonly_db_from_assets(); + replayer_state->progress.prepare.fetch_add(20, std::memory_order_release); + }); + cache_maintenance_task->set_desc("foz-cache-maintenance"); + + auto recorder_kick_task = group->create_task([this]() { + // Kick off recorder thread. + auto write_real_path = get_system_handles().filesystem->get_filesystem_path("cache://fossilize/db"); + if (!write_real_path.empty()) + { + recorder_state->db.reset(Fossilize::create_concurrent_database( + write_real_path.c_str(), Fossilize::DatabaseMode::Append, nullptr, 0)); + recorder_state->recorder.set_database_enable_application_feature_links(false); + recorder_state->recorder.init_recording_thread(recorder_state->db.get()); + } + recorder_state->recorder_ready.store(true, std::memory_order_release); + replayer_state->progress.prepare.fetch_add(10, std::memory_order_release); + }); + recorder_kick_task->set_desc("foz-recorder-kick"); + + group->add_dependency(*recorder_kick_task, *cache_maintenance_task); + + auto prepare_task = group->create_task([this]() { + auto *fs = get_system_handles().filesystem; + auto read_real_path = fs->get_filesystem_path("cache://fossilize/db.foz"); + if (read_real_path.empty()) + { + replayer_state->progress.modules.store(~0u, std::memory_order_release); + replayer_state->progress.pipelines.store(~0u, std::memory_order_release); + return; + } + + replayer_state->db.reset( + Fossilize::create_stream_archive_database(read_real_path.c_str(), Fossilize::DatabaseMode::ReadOnly)); + + if (replayer_state->db && !replayer_state->db->prepare()) + { + LOGW("Failed to prepare read-only cache.\n"); + replayer_state->db.reset(); + } + + if (replayer_state->db) + { + replay_tag_simple(Fossilize::RESOURCE_SAMPLER); + replay_tag_simple(Fossilize::RESOURCE_DESCRIPTOR_SET_LAYOUT); + replay_tag_simple(Fossilize::RESOURCE_PIPELINE_LAYOUT); + replay_tag_simple(Fossilize::RESOURCE_RENDER_PASS); + + size_t count = 0; + + replayer_state->db->get_hash_list_for_resource_tag(Fossilize::RESOURCE_SHADER_MODULE, &count, nullptr); + replayer_state->module_hashes.resize(count); + replayer_state->db->get_hash_list_for_resource_tag(Fossilize::RESOURCE_SHADER_MODULE, &count, + replayer_state->module_hashes.data()); + + replayer_state->db->get_hash_list_for_resource_tag(Fossilize::RESOURCE_GRAPHICS_PIPELINE, &count, nullptr); + replayer_state->graphics_hashes.resize(count); + replayer_state->db->get_hash_list_for_resource_tag(Fossilize::RESOURCE_GRAPHICS_PIPELINE, &count, + replayer_state->graphics_hashes.data()); + + replayer_state->db->get_hash_list_for_resource_tag(Fossilize::RESOURCE_COMPUTE_PIPELINE, &count, nullptr); + replayer_state->compute_hashes.resize(count); + replayer_state->db->get_hash_list_for_resource_tag(Fossilize::RESOURCE_COMPUTE_PIPELINE, &count, + replayer_state->compute_hashes.data()); + + replayer_state->progress.num_modules = replayer_state->module_hashes.size(); + replayer_state->progress.num_pipelines = + replayer_state->graphics_hashes.size() + replayer_state->compute_hashes.size(); + } + + if (replayer_state->progress.num_modules == 0) + replayer_state->progress.modules.store(~0u, std::memory_order_release); + if (replayer_state->progress.num_pipelines == 0) + replayer_state->progress.pipelines.store(~0u, std::memory_order_release); + }); + prepare_task->set_desc("foz-prepare"); + + group->add_dependency(*prepare_task, *recorder_kick_task); + + auto parse_modules_task = group->create_task(); + parse_modules_task->set_desc("foz-parse-modules"); + group->add_dependency(*parse_modules_task, *prepare_task); + group->add_dependency(*parse_modules_task, *shader_manager_task); + + for (unsigned i = 0; i < NumTasks; i++) + { + parse_modules_task->enqueue_task([this, i]() { + if (!replayer_state->db) + return; + + Fossilize::StateReplayer module_replayer; + Util::DynamicArray buffer; + auto &db = *replayer_state->db; + + size_t start = (i * replayer_state->module_hashes.size()) / NumTasks; + size_t end = ((i + 1) * replayer_state->module_hashes.size()) / NumTasks; + size_t size = 0; + + for (; start < end; start++) + { + auto hash = replayer_state->module_hashes[start]; + if (!db.read_entry(Fossilize::RESOURCE_SHADER_MODULE, hash, &size, nullptr, Fossilize::PAYLOAD_READ_CONCURRENT_BIT)) + continue; + buffer.reserve(size); + if (!db.read_entry(Fossilize::RESOURCE_SHADER_MODULE, hash, &size, buffer.data(), Fossilize::PAYLOAD_READ_CONCURRENT_BIT)) + continue; + + if (!module_replayer.parse(*this, &db, buffer.data(), size)) + { + replayer_state->progress.modules.fetch_add(1, std::memory_order_release); + LOGW("Failed to parse module.\n"); + } + } + }); + } + + group->add_dependency(*shader_compilation, *parse_modules_task); + + auto parse_graphics_task = group->create_task([this]() { + if (!replayer_state->db) + return; + + auto &replayer = replayer_state->graphics_replayer; + replayer.copy_handle_references(replayer_state->base_replayer); + replayer.set_resolve_shader_module_handles(false); + + size_t size = 0; + auto &db = *replayer_state->db; + Util::DynamicArray buffer; + + for (auto hash : replayer_state->graphics_hashes) + { + if (!db.read_entry(Fossilize::RESOURCE_GRAPHICS_PIPELINE, hash, &size, nullptr, Fossilize::PAYLOAD_READ_CONCURRENT_BIT)) + continue; + buffer.reserve(size); + if (!db.read_entry(Fossilize::RESOURCE_GRAPHICS_PIPELINE, hash, &size, buffer.data(), Fossilize::PAYLOAD_READ_CONCURRENT_BIT)) + continue; + + if (!replayer.parse(*this, &db, buffer.data(), size)) + { + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + LOGW("Failed to parse graphics pipeline.\n"); + } + } + }); + parse_graphics_task->set_desc("foz-parse-graphics"); + group->add_dependency(*parse_graphics_task, *prepare_task); + + auto parse_compute_task = group->create_task([this]() { + if (!replayer_state->db) + return; + + auto &replayer = replayer_state->compute_replayer; + replayer.copy_handle_references(replayer_state->base_replayer); + replayer.set_resolve_shader_module_handles(false); + + size_t size = 0; + auto &db = *replayer_state->db; + Util::DynamicArray buffer; + for (auto hash : replayer_state->compute_hashes) + { + if (!db.read_entry(Fossilize::RESOURCE_COMPUTE_PIPELINE, hash, &size, nullptr, Fossilize::PAYLOAD_READ_CONCURRENT_BIT)) + continue; + buffer.reserve(size); + if (!db.read_entry(Fossilize::RESOURCE_COMPUTE_PIPELINE, hash, &size, buffer.data(), Fossilize::PAYLOAD_READ_CONCURRENT_BIT)) + continue; + + if (!replayer.parse(*this, &db, buffer.data(), size)) + { + replayer_state->progress.pipelines.fetch_add(1, std::memory_order_release); + LOGW("Failed to parse compute pipeline.\n"); + } + } + }); + parse_compute_task->set_desc("foz-parse-compute"); + group->add_dependency(*parse_compute_task, *prepare_task); + + auto compile_graphics_task = group->create_task(); + auto compile_compute_task = group->create_task(); + compile_graphics_task->set_desc("foz-compile-graphics"); + compile_compute_task->set_desc("foz-compile-compute"); + group->add_dependency(*compile_graphics_task, *parse_modules_task); + group->add_dependency(*compile_graphics_task, *parse_graphics_task); + group->add_dependency(*compile_compute_task, *parse_modules_task); + group->add_dependency(*compile_compute_task, *parse_compute_task); + for (unsigned i = 0; i < NumTasks; i++) + { + compile_graphics_task->enqueue_task([this, i]() { + size_t start = (i * replayer_state->graphics_pipelines.size()) / NumTasks; + size_t end = ((i + 1) * replayer_state->graphics_pipelines.size()) / NumTasks; + for (; start < end; start++) + { + auto &pipe = replayer_state->graphics_pipelines[start]; + fossilize_replay_graphics_pipeline(pipe.first, *pipe.second); + } + }); + + compile_compute_task->enqueue_task([this, i]() { + size_t start = (i * replayer_state->compute_pipelines.size()) / NumTasks; + size_t end = ((i + 1) * replayer_state->compute_pipelines.size()) / NumTasks; + for (; start < end; start++) + { + auto &pipe = replayer_state->compute_pipelines[start]; + fossilize_replay_compute_pipeline(pipe.first, *pipe.second); + } + }); + } + + replayer_state->complete = get_system_handles().thread_group->create_task([this]() { + LOGI("Fossilize replay completed!\n Modules: %zu\n Graphics: %zu\n Compute: %zu\n", + replayer_state->module_hashes.size(), + replayer_state->graphics_hashes.size(), + replayer_state->compute_hashes.size()); + lock.read_only_cache.unlock_read(); + const auto cleanup = [](Fossilize::StateReplayer &r) { + r.forget_handle_references(); + r.forget_pipeline_handle_references(); + r.get_allocator().reset(); + }; + cleanup(replayer_state->base_replayer); + cleanup(replayer_state->graphics_replayer); + cleanup(replayer_state->compute_replayer); + replayer_state->graphics_pipelines.clear(); + replayer_state->compute_pipelines.clear(); + replayer_state->module_hashes.clear(); + replayer_state->graphics_hashes.clear(); + replayer_state->compute_hashes.clear(); + replayer_state->db.reset(); + }); + replayer_state->complete->set_desc("foz-replay-complete"); + group->add_dependency(*replayer_state->complete, *compile_graphics_task); + group->add_dependency(*replayer_state->complete, *compile_compute_task); + group->add_dependency(*replayer_state->complete, *shader_compilation); + replayer_state->complete->flush(); + + replayer_state->module_ready = std::move(parse_modules_task); + replayer_state->module_ready->flush(); + + auto compile_task = group->create_task(); + group->add_dependency(*compile_task, *compile_graphics_task); + group->add_dependency(*compile_task, *compile_compute_task); + replayer_state->pipeline_ready = std::move(compile_task); + replayer_state->pipeline_ready->flush(); +} + +void Device::flush_pipeline_state() +{ + if (replayer_state) + { + if (replayer_state->complete) + replayer_state->complete->wait(); + replayer_state.reset(); + } + + if (recorder_state) + { + recorder_state->recorder.tear_down_recording_thread(); + recorder_state.reset(); + } +} + +unsigned Device::query_initialization_progress(InitializationStage status) const +{ + if (!replayer_state) + return 100; + + switch (status) + { + case InitializationStage::CacheMaintenance: + return replayer_state->progress.prepare.load(std::memory_order_acquire); + + case InitializationStage::ShaderModules: + { + unsigned done = replayer_state->progress.modules.load(std::memory_order_acquire); + // Avoid 0/0. + if (!done) + return 0; + else if (done == ~0u) + return 100; + return (100u * done) / replayer_state->progress.num_modules; + } + + case InitializationStage::Pipelines: + { + unsigned done = replayer_state->progress.pipelines.load(std::memory_order_acquire); + // Avoid 0/0. + if (!done) + return 0; + else if (done == ~0u) + return 100; + return (100u * done) / replayer_state->progress.num_pipelines; + } + + default: + break; + } + + return 0; +} + +void Device::block_until_shader_module_ready() +{ + if (!replayer_state || !replayer_state->module_ready) + return; + replayer_state->module_ready->wait(); +} + +void Device::block_until_pipeline_ready() +{ + if (!replayer_state || !replayer_state->pipeline_ready) + return; + replayer_state->pipeline_ready->wait(); +} + +void Device::wait_shader_caches() +{ + block_until_pipeline_ready(); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device_fossilize.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device_fossilize.hpp new file mode 100644 index 00000000..4dccda93 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/device_fossilize.hpp @@ -0,0 +1,70 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "device.hpp" +#include "thread_group.hpp" + +namespace Vulkan +{ +struct Device::RecorderState +{ + RecorderState(); + ~RecorderState(); + + std::unique_ptr db; + Fossilize::StateRecorder recorder; + std::atomic_bool recorder_ready; +}; + +static constexpr unsigned NumTasks = 4; +struct Device::ReplayerState +{ + ReplayerState(); + ~ReplayerState(); + + std::vector module_hashes; + std::vector graphics_hashes; + std::vector compute_hashes; + + Fossilize::StateReplayer base_replayer; + Fossilize::StateReplayer graphics_replayer; + Fossilize::StateReplayer compute_replayer; + Fossilize::FeatureFilter *feature_filter = nullptr; + std::unique_ptr db; + Granite::TaskGroupHandle complete; + Granite::TaskGroupHandle module_ready; + Granite::TaskGroupHandle pipeline_ready; + std::vector> graphics_pipelines; + std::vector> compute_pipelines; + + struct + { + std::atomic_uint32_t pipelines; + std::atomic_uint32_t modules; + std::atomic_uint32_t prepare; + uint32_t num_pipelines = 0; + uint32_t num_modules = 0; + } progress; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/event_manager.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/event_manager.cpp new file mode 100644 index 00000000..01b6120a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/event_manager.cpp @@ -0,0 +1,72 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "event_manager.hpp" +#include "device.hpp" + +namespace Vulkan +{ +EventManager::~EventManager() +{ + if (!workaround) + for (auto &event : events) + table->vkDestroyEvent(device->get_device(), event, nullptr); +} + +void EventManager::recycle(VkEvent event) +{ + if (!workaround && event != VK_NULL_HANDLE) + { + table->vkResetEvent(device->get_device(), event); + events.push_back(event); + } +} + +VkEvent EventManager::request_cleared_event() +{ + if (workaround) + { + // Can't use reinterpret_cast because of MSVC. + return (VkEvent) ++workaround_counter; + } + else if (events.empty()) + { + VkEvent event; + VkEventCreateInfo info = { VK_STRUCTURE_TYPE_EVENT_CREATE_INFO }; + table->vkCreateEvent(device->get_device(), &info, nullptr, &event); + return event; + } + else + { + auto event = events.back(); + events.pop_back(); + return event; + } +} + +void EventManager::init(Device *device_) +{ + device = device_; + table = &device->get_device_table(); + workaround = device_->get_workarounds().emulate_event_as_pipeline_barrier; +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/event_manager.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/event_manager.hpp new file mode 100644 index 00000000..ae297fea --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/event_manager.hpp @@ -0,0 +1,47 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include + +namespace Vulkan +{ +class Device; +class EventManager +{ +public: + void init(Device *device); + ~EventManager(); + + VkEvent request_cleared_event(); + void recycle(VkEvent event); + +private: + Device *device = nullptr; + const VolkDeviceTable *table = nullptr; + std::vector events; + uint64_t workaround_counter = 0; + bool workaround = false; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence.cpp new file mode 100644 index 00000000..b6900cf4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence.cpp @@ -0,0 +1,155 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "fence.hpp" +#include "device.hpp" + +namespace Vulkan +{ +FenceHolder::~FenceHolder() +{ + if (fence != VK_NULL_HANDLE) + { + if (internal_sync) + device->reset_fence_nolock(fence, observed_wait); + else + device->reset_fence(fence, observed_wait); + } +} + +const VkFence &FenceHolder::get_fence() const +{ + return fence; +} + +void FenceHolder::wait() +{ + auto &table = device->get_device_table(); + + // Waiting for the same VkFence in parallel is not allowed, and there seems to be some shenanigans on Intel + // when waiting for a timeline semaphore in parallel with same value as well. + std::lock_guard holder{lock}; + + if (observed_wait) + return; + + if (timeline_value != 0) + { + VK_ASSERT(timeline_semaphore); + VkSemaphoreWaitInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO }; + info.semaphoreCount = 1; + info.pSemaphores = &timeline_semaphore; + info.pValues = &timeline_value; + + if (device->get_device_features().supports_post_mortem) + { + VkResult vr = table.vkWaitSemaphores(device->get_device(), &info, PostMortemTimeout); + if (vr == VK_TIMEOUT) + vr = table.vkWaitSemaphores(device->get_device(), &info, 0); + if (vr != VK_SUCCESS) + { + device->managers.breadcrumbs.notify_device_hung(); + return; + } + } + + if (table.vkWaitSemaphores(device->get_device(), &info, UINT64_MAX) != VK_SUCCESS) + { + LOGE("Failed to wait for timeline semaphore!\n"); + device->managers.breadcrumbs.notify_device_hung(); + } + else + observed_wait = true; + } + else + { + if (device->get_device_features().supports_post_mortem) + { + VkResult vr = table.vkWaitForFences(device->get_device(), 1, &fence, VK_TRUE, PostMortemTimeout); + if (vr == VK_TIMEOUT) + vr = table.vkWaitForFences(device->get_device(), 1, &fence, VK_TRUE, 0); + if (vr != VK_SUCCESS) + { + device->managers.breadcrumbs.notify_device_hung(); + return; + } + } + + if (table.vkWaitForFences(device->get_device(), 1, &fence, VK_TRUE, UINT64_MAX) != VK_SUCCESS) + { + LOGE("Failed to wait for fence!\n"); + device->managers.breadcrumbs.notify_device_hung(); + } + else + observed_wait = true; + } +} + +bool FenceHolder::wait_timeout(uint64_t timeout) +{ + bool ret; + auto &table = device->get_device_table(); + + // Waiting for the same VkFence in parallel is not allowed, and there seems to be some shenanigans on Intel + // when waiting for a timeline semaphore in parallel with same value as well. + std::lock_guard holder{lock}; + + if (observed_wait) + return true; + + if (timeline_value != 0) + { + VK_ASSERT(timeline_semaphore); + + if (timeout == 0) + { + uint64_t current_value = 0; + ret = table.vkGetSemaphoreCounterValue(device->get_device(), timeline_semaphore, ¤t_value) == VK_SUCCESS && + current_value >= timeline_value; + } + else + { + VkSemaphoreWaitInfo info = {VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO}; + info.semaphoreCount = 1; + info.pSemaphores = &timeline_semaphore; + info.pValues = &timeline_value; + ret = table.vkWaitSemaphores(device->get_device(), &info, timeout) == VK_SUCCESS; + } + } + else + { + if (timeout == 0) + ret = table.vkGetFenceStatus(device->get_device(), fence) == VK_SUCCESS; + else + ret = table.vkWaitForFences(device->get_device(), 1, &fence, VK_TRUE, timeout) == VK_SUCCESS; + } + + if (ret) + observed_wait = true; + return ret; +} + +void FenceHolderDeleter::operator()(Vulkan::FenceHolder *fence) +{ + fence->device->handle_pool.fences.free(fence); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence.hpp new file mode 100644 index 00000000..5e45e6ec --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence.hpp @@ -0,0 +1,81 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_common.hpp" +#include "vulkan_headers.hpp" +#include "object_pool.hpp" +#include "cookie.hpp" +#include + +namespace Vulkan +{ +class Device; + +class FenceHolder; +struct FenceHolderDeleter +{ + void operator()(FenceHolder *fence); +}; + +class FenceHolder : public Util::IntrusivePtrEnabled, public InternalSyncEnabled +{ +public: + friend struct FenceHolderDeleter; + friend class WSI; + + ~FenceHolder(); + void wait(); + bool wait_timeout(uint64_t nsec); + +private: + friend class Util::ObjectPool; + FenceHolder(Device *device_, VkFence fence_) + : device(device_), + fence(fence_), + timeline_semaphore(VK_NULL_HANDLE), + timeline_value(0) + { + } + + FenceHolder(Device *device_, uint64_t value, VkSemaphore timeline_semaphore_) + : device(device_), + fence(VK_NULL_HANDLE), + timeline_semaphore(timeline_semaphore_), + timeline_value(value) + { + VK_ASSERT(value > 0); + } + + const VkFence &get_fence() const; + + Device *device; + VkFence fence; + VkSemaphore timeline_semaphore; + uint64_t timeline_value; + bool observed_wait = false; + std::mutex lock; +}; + +using Fence = Util::IntrusivePtr; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence_manager.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence_manager.cpp new file mode 100644 index 00000000..3c3a174d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence_manager.cpp @@ -0,0 +1,61 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "fence_manager.hpp" +#include "device.hpp" + +namespace Vulkan +{ +void FenceManager::init(Device *device_) +{ + device = device_; + table = &device->get_device_table(); +} + +VkFence FenceManager::request_cleared_fence() +{ + if (!fences.empty()) + { + auto ret = fences.back(); + fences.pop_back(); + return ret; + } + else + { + VkFence fence; + VkFenceCreateInfo info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; + table->vkCreateFence(device->get_device(), &info, nullptr, &fence); + return fence; + } +} + +void FenceManager::recycle_fence(VkFence fence) +{ + fences.push_back(fence); +} + +FenceManager::~FenceManager() +{ + for (auto &fence : fences) + table->vkDestroyFence(device->get_device(), fence, nullptr); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence_manager.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence_manager.hpp new file mode 100644 index 00000000..bbeda583 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/fence_manager.hpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include + +namespace Vulkan +{ +class Device; +class FenceManager +{ +public: + void init(Device *device); + ~FenceManager(); + + VkFence request_cleared_fence(); + void recycle_fence(VkFence fence); + +private: + Device *device = nullptr; + const VolkDeviceTable *table = nullptr; + std::vector fences; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/format.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/format.hpp new file mode 100644 index 00000000..518e6718 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/format.hpp @@ -0,0 +1,386 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include "texture/texture_format.hpp" + +namespace Vulkan +{ +enum class FormatCompressionType +{ + Uncompressed, + BC, + ETC, + ASTC +}; + +static inline FormatCompressionType format_compression_type(VkFormat format) +{ + switch (format) + { + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + case VK_FORMAT_BC2_SRGB_BLOCK: + case VK_FORMAT_BC2_UNORM_BLOCK: + case VK_FORMAT_BC3_SRGB_BLOCK: + case VK_FORMAT_BC3_UNORM_BLOCK: + case VK_FORMAT_BC4_UNORM_BLOCK: + case VK_FORMAT_BC4_SNORM_BLOCK: + case VK_FORMAT_BC5_UNORM_BLOCK: + case VK_FORMAT_BC5_SNORM_BLOCK: + case VK_FORMAT_BC6H_SFLOAT_BLOCK: + case VK_FORMAT_BC6H_UFLOAT_BLOCK: + case VK_FORMAT_BC7_SRGB_BLOCK: + case VK_FORMAT_BC7_UNORM_BLOCK: + return FormatCompressionType::BC; + + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: + case VK_FORMAT_EAC_R11_SNORM_BLOCK: + case VK_FORMAT_EAC_R11_UNORM_BLOCK: + return FormatCompressionType::ETC; + +#define astc_fmt(w, h) \ + case VK_FORMAT_ASTC_##w##x##h##_UNORM_BLOCK: \ + case VK_FORMAT_ASTC_##w##x##h##_SRGB_BLOCK: \ + case VK_FORMAT_ASTC_##w##x##h##_SFLOAT_BLOCK_EXT + astc_fmt(4, 4): + astc_fmt(5, 4): + astc_fmt(5, 5): + astc_fmt(6, 5): + astc_fmt(6, 6): + astc_fmt(8, 5): + astc_fmt(8, 6): + astc_fmt(8, 8): + astc_fmt(10, 5): + astc_fmt(10, 6): + astc_fmt(10, 8): + astc_fmt(10, 10): + astc_fmt(12, 10): + astc_fmt(12, 12): + return FormatCompressionType::ASTC; +#undef astc_fmt + + default: + return FormatCompressionType::Uncompressed; + } +} + +static inline bool format_is_compressed_hdr(VkFormat format) +{ + switch (format) + { +#define astc_fmt(w, h) case VK_FORMAT_ASTC_##w##x##h##_SFLOAT_BLOCK_EXT + astc_fmt(4, 4): + astc_fmt(5, 4): + astc_fmt(5, 5): + astc_fmt(6, 5): + astc_fmt(6, 6): + astc_fmt(8, 5): + astc_fmt(8, 6): + astc_fmt(8, 8): + astc_fmt(10, 5): + astc_fmt(10, 6): + astc_fmt(10, 8): + astc_fmt(10, 10): + astc_fmt(12, 10): + astc_fmt(12, 12): +#undef astc_fmt + return true; + + case VK_FORMAT_BC6H_SFLOAT_BLOCK: + case VK_FORMAT_BC6H_UFLOAT_BLOCK: + return true; + + default: + return false; + } +} + +static inline bool format_is_srgb(VkFormat format) +{ + switch (format) + { + case VK_FORMAT_A8B8G8R8_SRGB_PACK32: + case VK_FORMAT_R8G8B8A8_SRGB: + case VK_FORMAT_B8G8R8A8_SRGB: + case VK_FORMAT_R8_SRGB: + case VK_FORMAT_R8G8_SRGB: + case VK_FORMAT_R8G8B8_SRGB: + case VK_FORMAT_B8G8R8_SRGB: + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + case VK_FORMAT_BC2_SRGB_BLOCK: + case VK_FORMAT_BC3_SRGB_BLOCK: + case VK_FORMAT_BC7_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: + return true; + + default: + return false; + } +} + +static inline bool format_has_depth_aspect(VkFormat format) +{ + switch (format) + { + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_X8_D24_UNORM_PACK32: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return true; + + default: + return false; + } +} + +static inline bool format_has_stencil_aspect(VkFormat format) +{ + switch (format) + { + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + case VK_FORMAT_S8_UINT: + return true; + + default: + return false; + } +} + +static inline bool format_has_depth_or_stencil_aspect(VkFormat format) +{ + return format_has_depth_aspect(format) || format_has_stencil_aspect(format); +} + +static inline VkImageAspectFlags format_to_aspect_mask(VkFormat format) +{ + switch (format) + { + case VK_FORMAT_UNDEFINED: + return 0; + + case VK_FORMAT_S8_UINT: + return VK_IMAGE_ASPECT_STENCIL_BIT; + + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; + + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_X8_D24_UNORM_PACK32: + return VK_IMAGE_ASPECT_DEPTH_BIT; + + default: + return VK_IMAGE_ASPECT_COLOR_BIT; + } +} + +static inline void format_align_dim(VkFormat format, uint32_t &width, uint32_t &height) +{ + uint32_t align_width, align_height; + TextureFormatLayout::format_block_dim(format, align_width, align_height); + width = ((width + align_width - 1) / align_width) * align_width; + height = ((height + align_height - 1) / align_height) * align_height; +} + +static inline void format_num_blocks(VkFormat format, uint32_t &width, uint32_t &height) +{ + uint32_t align_width, align_height; + TextureFormatLayout::format_block_dim(format, align_width, align_height); + width = (width + align_width - 1) / align_width; + height = (height + align_height - 1) / align_height; +} + +static inline VkDeviceSize format_get_layer_size(VkFormat format, VkImageAspectFlags aspect, unsigned width, unsigned height, unsigned depth) +{ + uint32_t blocks_x = width; + uint32_t blocks_y = height; + format_num_blocks(format, blocks_x, blocks_y); + format_align_dim(format, width, height); + + VkDeviceSize size = VkDeviceSize(TextureFormatLayout::format_block_size(format, aspect)) * depth * blocks_x * blocks_y; + return size; +} + +static inline unsigned format_ycbcr_num_planes(VkFormat format) +{ + switch (format) + { + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: + return 3; + + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: + return 2; + + default: + return 1; + } +} + +static inline void format_ycbcr_downsample_dimensions(VkFormat format, VkImageAspectFlags aspect, uint32_t &width, uint32_t &height) +{ + if (aspect == VK_IMAGE_ASPECT_PLANE_0_BIT) + return; + + switch (format) + { +#define fmt(x, sub0, sub1) \ + case VK_FORMAT_##x: \ + width >>= sub0; \ + height >>= sub1; \ + break + + fmt(G8_B8_R8_3PLANE_420_UNORM, 1, 1); + fmt(G8_B8R8_2PLANE_420_UNORM, 1, 1); + fmt(G8_B8_R8_3PLANE_422_UNORM, 1, 0); + fmt(G8_B8R8_2PLANE_422_UNORM, 1, 0); + fmt(G8_B8_R8_3PLANE_444_UNORM, 0, 0); + + fmt(G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, 1, 1); + fmt(G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, 1, 0); + fmt(G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, 0, 0); + fmt(G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, 1, 1); + fmt(G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, 1, 0); + + fmt(G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, 1, 1); + fmt(G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, 1, 0); + fmt(G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, 0, 0); + fmt(G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, 1, 1); + fmt(G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, 1, 0); + + fmt(G16_B16_R16_3PLANE_420_UNORM, 1, 1); + fmt(G16_B16_R16_3PLANE_422_UNORM, 1, 0); + fmt(G16_B16_R16_3PLANE_444_UNORM, 0, 0); + fmt(G16_B16R16_2PLANE_420_UNORM, 1, 1); + fmt(G16_B16R16_2PLANE_422_UNORM, 1, 0); + + default: + break; + } +#undef fmt +} + +static inline bool format_supports_storage_image_read_write_without_format(VkFormat format) +{ + /* from https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#formats-without-shader-storage-format */ + static const VkFormat supported_formats[] = + { + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_SNORM, + VK_FORMAT_R8G8B8A8_UINT, + VK_FORMAT_R8G8B8A8_SINT, + VK_FORMAT_R32_UINT, + VK_FORMAT_R32_SINT, + VK_FORMAT_R32_SFLOAT, + VK_FORMAT_R32G32_UINT, + VK_FORMAT_R32G32_SINT, + VK_FORMAT_R32G32_SFLOAT, + VK_FORMAT_R32G32B32A32_UINT, + VK_FORMAT_R32G32B32A32_SINT, + VK_FORMAT_R32G32B32A32_SFLOAT, + VK_FORMAT_R16G16B16A16_UINT, + VK_FORMAT_R16G16B16A16_SINT, + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_FORMAT_R16G16_SFLOAT, + VK_FORMAT_B10G11R11_UFLOAT_PACK32, + VK_FORMAT_R16_SFLOAT, + VK_FORMAT_R16G16B16A16_UNORM, + VK_FORMAT_A2B10G10R10_UNORM_PACK32, + VK_FORMAT_R16G16_UNORM, + VK_FORMAT_R8G8_UNORM, + VK_FORMAT_R16_UNORM, + VK_FORMAT_R8_UNORM, + VK_FORMAT_R16G16B16A16_SNORM, + VK_FORMAT_R16G16_SNORM, + VK_FORMAT_R8G8_SNORM, + VK_FORMAT_R16_SNORM, + VK_FORMAT_R8_SNORM, + VK_FORMAT_R16G16_SINT, + VK_FORMAT_R8G8_SINT, + VK_FORMAT_R16_SINT, + VK_FORMAT_R8_SINT, + VK_FORMAT_A2B10G10R10_UINT_PACK32, + VK_FORMAT_R16G16_UINT, + VK_FORMAT_R8G8_UINT, + VK_FORMAT_R16_UINT, + VK_FORMAT_R8_UINT, + }; + + for (auto fmt : supported_formats) + if (fmt == format) + return true; + + return false; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/image.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/image.cpp new file mode 100644 index 00000000..132b5d5d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/image.cpp @@ -0,0 +1,260 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "image.hpp" +#include "device.hpp" +#include "buffer.hpp" + +namespace Vulkan +{ +ImageView::ImageView(Device *device_, const CachedImageView &view_, const ImageViewCreateInfo &info_) + : Cookie(device_) + , device(device_) + , view(view_) + , info(info_) +{ +} + +const CachedImageView &ImageView::get_render_target_view(unsigned layer) const +{ + // Transient images just have one layer. + if (info.image->get_create_info().domain == ImageDomain::Transient) + return view; + + VK_ASSERT(layer < get_create_info().layers); + + if (render_target_views.empty()) + return view; + else + { + VK_ASSERT(layer < render_target_views.size()); + return render_target_views[layer]; + } +} + +const CachedImageView &ImageView::get_mip_view(unsigned level) const +{ + VK_ASSERT(level < get_create_info().levels); + + if (mip_views.empty()) + return view; + else + { + VK_ASSERT(level < mip_views.size()); + return mip_views[level]; + } +} + +void ImageView::free_cached_view(CachedImageView &cached) +{ + if (internal_sync) + device->destroy_image_view_nolock(cached); + else + device->destroy_image_view(cached); +} + +ImageView::~ImageView() +{ + free_cached_view(view); + free_cached_view(depth_view); + free_cached_view(stencil_view); + free_cached_view(unorm_view); + free_cached_view(srgb_view); + for (auto &v : render_target_views) + free_cached_view(v); + for (auto &v : mip_views) + free_cached_view(v); +} + +unsigned ImageView::get_view_width() const +{ + unsigned width = info.image->get_width(info.base_level); + + if (info.aspect == VK_IMAGE_ASPECT_PLANE_1_BIT || info.aspect == VK_IMAGE_ASPECT_PLANE_2_BIT) + { + unsigned h = 0; + format_ycbcr_downsample_dimensions(info.image->get_format(), info.aspect, width, h); + } + + return width; +} + +unsigned ImageView::get_view_height() const +{ + unsigned height = info.image->get_height(info.base_level); + + if (info.aspect == VK_IMAGE_ASPECT_PLANE_1_BIT || info.aspect == VK_IMAGE_ASPECT_PLANE_2_BIT) + { + unsigned w = 0; + format_ycbcr_downsample_dimensions(info.image->get_format(), info.aspect, w, height); + } + + return height; +} + +unsigned ImageView::get_view_depth() const +{ + return info.image->get_depth(info.base_level); +} + +Image::Image(Device *device_, VkImage image_, const CachedImageView &default_view, const DeviceAllocation &alloc_, + const ImageCreateInfo &create_info_, VkImageViewType view_type) + : Cookie(device_) + , device(device_) + , image(image_) + , alloc(alloc_) + , create_info(create_info_) +{ + if (view_type != VK_IMAGE_VIEW_TYPE_MAX_ENUM) + { + ImageViewCreateInfo info; + info.image = this; + info.view_type = view_type; + info.format = create_info.format; + info.base_level = 0; + info.levels = create_info.levels; + info.base_layer = 0; + info.layers = create_info.layers; + view = ImageViewHandle(device->handle_pool.image_views.allocate(device, default_view, info)); + } +} + +DeviceAllocation Image::take_allocation_ownership() +{ + DeviceAllocation ret = {}; + std::swap(ret, alloc); + return ret; +} + +ExternalHandle Image::export_handle() +{ + return alloc.export_handle(*device); +} + +void Image::disown_image() +{ + owns_image = false; +} + +void Image::disown_memory_allocation() +{ + owns_memory_allocation = false; +} + +Image::~Image() +{ + if (owns_image) + { + if (internal_sync) + device->destroy_image_nolock(image); + else + device->destroy_image(image); + } + + if (alloc.get_memory() && owns_memory_allocation) + { + if (internal_sync) + device->free_memory_nolock(alloc); + else + device->free_memory(alloc); + } +} + +const Buffer &LinearHostImage::get_host_visible_buffer() const +{ + return *cpu_image; +} + +bool LinearHostImage::need_staging_copy() const +{ + return gpu_image->get_create_info().domain != ImageDomain::LinearHostCached && + gpu_image->get_create_info().domain != ImageDomain::LinearHost; +} + +const DeviceAllocation &LinearHostImage::get_host_visible_allocation() const +{ + return need_staging_copy() ? cpu_image->get_allocation() : gpu_image->get_allocation(); +} + +const ImageView &LinearHostImage::get_view() const +{ + return gpu_image->get_view(); +} + +const Image &LinearHostImage::get_image() const +{ + return *gpu_image; +} + +size_t LinearHostImage::get_offset() const +{ + return row_offset; +} + +size_t LinearHostImage::get_row_pitch_bytes() const +{ + return row_pitch; +} + +VkPipelineStageFlags2 LinearHostImage::get_used_pipeline_stages() const +{ + return stages; +} + +LinearHostImage::LinearHostImage(Device *device_, ImageHandle gpu_image_, BufferHandle cpu_image_, VkPipelineStageFlags2 stages_) + : device(device_), gpu_image(std::move(gpu_image_)), cpu_image(std::move(cpu_image_)), stages(stages_) +{ + if (gpu_image->get_create_info().domain == ImageDomain::LinearHostCached || + gpu_image->get_create_info().domain == ImageDomain::LinearHost) + { + VkImageSubresource sub = {}; + sub.aspectMask = format_to_aspect_mask(gpu_image->get_format()); + VkSubresourceLayout layout; + + auto &table = device_->get_device_table(); + table.vkGetImageSubresourceLayout(device->get_device(), gpu_image->get_image(), &sub, &layout); + row_pitch = layout.rowPitch; + row_offset = layout.offset; + } + else + { + row_pitch = gpu_image->get_width() * TextureFormatLayout::format_block_size(gpu_image->get_format(), + format_to_aspect_mask(gpu_image->get_format())); + row_offset = 0; + } +} + +void ImageViewDeleter::operator()(ImageView *view) +{ + view->device->handle_pool.image_views.free(view); +} + +void ImageDeleter::operator()(Image *image) +{ + image->device->handle_pool.images.free(image); +} + +void LinearHostImageDeleter::operator()(LinearHostImage *image) +{ + image->device->handle_pool.linear_images.free(image); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/image.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/image.hpp new file mode 100644 index 00000000..0b4c10c1 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/image.hpp @@ -0,0 +1,582 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "cookie.hpp" +#include "format.hpp" +#include "vulkan_common.hpp" +#include "memory_allocator.hpp" +#include "vulkan_headers.hpp" +#include + +namespace Vulkan +{ +class Device; + +static inline uint32_t image_num_miplevels(const VkExtent3D &extent) +{ + uint32_t size = std::max(std::max(extent.width, extent.height), extent.depth); + return Util::floor_log2(size) + 1; +} + +static inline VkFormatFeatureFlags image_usage_to_features(VkImageUsageFlags usage) +{ + VkFormatFeatureFlags flags = 0; + if (usage & VK_IMAGE_USAGE_SAMPLED_BIT) + flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; + if (usage & VK_IMAGE_USAGE_STORAGE_BIT) + flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT; + if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; + if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + + return flags; +} + +struct ImageInitialData +{ + const void *data; + unsigned row_length; + unsigned image_height; +}; + +enum ImageMiscFlagBits +{ + IMAGE_MISC_GENERATE_MIPS_BIT = 1 << 0, + IMAGE_MISC_FORCE_ARRAY_BIT = 1 << 1, + IMAGE_MISC_MUTABLE_SRGB_BIT = 1 << 2, + IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT = 1 << 3, + IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT = 1 << 4, + IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_TRANSFER_BIT = 1 << 6, + IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_DECODE_BIT = 1 << 7, + IMAGE_MISC_VERIFY_FORMAT_FEATURE_SAMPLED_LINEAR_FILTER_BIT = 1 << 8, + IMAGE_MISC_LINEAR_IMAGE_IGNORE_DEVICE_LOCAL_BIT = 1 << 9, + IMAGE_MISC_FORCE_NO_DEDICATED_BIT = 1 << 10, + IMAGE_MISC_NO_DEFAULT_VIEWS_BIT = 1 << 11, + IMAGE_MISC_EXTERNAL_MEMORY_BIT = 1 << 12, + IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_ENCODE_BIT = 1 << 13, + IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_DUPLEX = + IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_DECODE_BIT | + IMAGE_MISC_CONCURRENT_QUEUE_VIDEO_ENCODE_BIT, + IMAGE_MISC_CREATE_PER_MIP_LEVEL_VIEWS_BIT = 1 << 14 +}; +using ImageMiscFlags = uint32_t; + +enum ImageViewMiscFlagBits +{ + IMAGE_VIEW_MISC_FORCE_ARRAY_BIT = 1 << 0 +}; +using ImageViewMiscFlags = uint32_t; + +class Image; +class ImmutableYcbcrConversion; + +struct ImageViewCreateInfo +{ + const Image *image = nullptr; + VkFormat format = VK_FORMAT_UNDEFINED; + unsigned base_level = 0; + unsigned levels = VK_REMAINING_MIP_LEVELS; + unsigned base_layer = 0; + unsigned layers = VK_REMAINING_ARRAY_LAYERS; + VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + ImageViewMiscFlags misc = 0; + VkComponentMapping swizzle = { + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + }; + VkImageAspectFlags aspect = 0; + const ImmutableYcbcrConversion *ycbcr_conversion = nullptr; +}; + +class ImageView; + +struct ImageViewDeleter +{ + void operator()(ImageView *view); +}; + +class ImageView : public Util::IntrusivePtrEnabled, + public Cookie, public InternalSyncEnabled +{ +public: + friend struct ImageViewDeleter; + + ImageView(Device *device, const CachedImageView &view, const ImageViewCreateInfo &info); + + ~ImageView(); + + void set_separate_depth_stencil_views(const CachedImageView &depth, const CachedImageView &stencil) + { + VK_ASSERT(depth_view.view == VK_NULL_HANDLE); + VK_ASSERT(stencil_view.view == VK_NULL_HANDLE); + depth_view = depth; + stencil_view = stencil; + } + + void set_render_target_views(std::vector views) + { + VK_ASSERT(render_target_views.empty()); + render_target_views = std::move(views); + } + + void set_mip_views(std::vector views) + { + VK_ASSERT(mip_views.empty()); + mip_views = std::move(views); + } + + void set_unorm_view(const CachedImageView &view_) + { + VK_ASSERT(unorm_view.view == VK_NULL_HANDLE); + unorm_view = view_; + } + + void set_srgb_view(const CachedImageView &view_) + { + VK_ASSERT(srgb_view.view == VK_NULL_HANDLE); + srgb_view = view_; + } + + // By default, gets a combined view which includes all aspects in the image. + // This would be used mostly for render targets. + const CachedImageView &get_view() const + { + return view; + } + + const CachedImageView &get_render_target_view(unsigned layer) const; + const CachedImageView &get_mip_view(unsigned level) const; + + // Gets an image view which only includes floating point domains. + // Takes effect when we want to sample from an image which is Depth/Stencil, + // but we only want to sample depth. + const CachedImageView &get_float_view() const + { + return depth_view.view != VK_NULL_HANDLE ? depth_view : view; + } + + // Gets an image view which only includes integer domains. + // Takes effect when we want to sample from an image which is Depth/Stencil, + // but we only want to sample stencil. + const CachedImageView &get_integer_view() const + { + return stencil_view.view != VK_NULL_HANDLE ? stencil_view : view; + } + + const CachedImageView &get_unorm_view() const + { + return unorm_view.view != VK_NULL_HANDLE ? unorm_view : view; + } + + const CachedImageView &get_srgb_view() const + { + return srgb_view.view != VK_NULL_HANDLE ? srgb_view : view; + } + + VkFormat get_format() const + { + return info.format; + } + + const Image &get_image() const + { + return *info.image; + } + + const ImageViewCreateInfo &get_create_info() const + { + return info; + } + + unsigned get_view_width() const; + unsigned get_view_height() const; + unsigned get_view_depth() const; + +private: + Device *device; + CachedImageView view = {}; + std::vector render_target_views; + std::vector mip_views; + CachedImageView depth_view = {}; + CachedImageView stencil_view = {}; + CachedImageView unorm_view = {}; + CachedImageView srgb_view = {}; + ImageViewCreateInfo info; + + void free_cached_view(CachedImageView &cached); +}; + +using ImageViewHandle = Util::IntrusivePtr; + +enum class ImageDomain +{ + Physical, + Transient, + LinearHostCached, + LinearHost, + LinearDevice, + HostCopy +}; + +enum class ImageLayout +{ + Optimal, + General +}; + +struct ImageCreateInfo +{ + ImageDomain domain = ImageDomain::Physical; + unsigned width = 0; + unsigned height = 0; + unsigned depth = 1; + unsigned levels = 1; + VkFormat format = VK_FORMAT_UNDEFINED; + VkImageType type = VK_IMAGE_TYPE_2D; + unsigned layers = 1; + VkImageUsageFlags usage = 0; + VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; + VkImageCreateFlags flags = 0; + ImageMiscFlags misc = 0; + VkImageLayout initial_layout = VK_IMAGE_LAYOUT_GENERAL; + VkComponentMapping swizzle = { + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + }; + const DeviceAllocation **memory_aliases = nullptr; + unsigned num_memory_aliases = 0; + const ImmutableYcbcrConversion *ycbcr_conversion = nullptr; + void *pnext = nullptr; + ExternalHandle external; + ImageLayout layout = ImageLayout::Optimal; + + static ImageCreateInfo immutable_image(const TextureFormatLayout &layout) + { + Vulkan::ImageCreateInfo info; + info.width = layout.get_width(); + info.height = layout.get_height(); + info.type = layout.get_image_type(); + info.depth = layout.get_depth(); + info.format = layout.get_format(); + info.layers = layout.get_layers(); + info.levels = layout.get_levels(); + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.domain = ImageDomain::Physical; + return info; + } + + static ImageCreateInfo immutable_2d_image(unsigned width, unsigned height, VkFormat format, bool mipmapped = false) + { + ImageCreateInfo info; + info.width = width; + info.height = height; + info.depth = 1; + info.levels = mipmapped ? 0u : 1u; + info.format = format; + info.type = VK_IMAGE_TYPE_2D; + info.layers = 1; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.flags = 0; + info.misc = mipmapped ? unsigned(IMAGE_MISC_GENERATE_MIPS_BIT) : 0u; + info.initial_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + return info; + } + + static ImageCreateInfo + immutable_3d_image(unsigned width, unsigned height, unsigned depth, VkFormat format, bool mipmapped = false) + { + ImageCreateInfo info = immutable_2d_image(width, height, format, mipmapped); + info.depth = depth; + info.type = VK_IMAGE_TYPE_3D; + return info; + } + + static ImageCreateInfo render_target(unsigned width, unsigned height, VkFormat format) + { + ImageCreateInfo info; + info.width = width; + info.height = height; + info.depth = 1; + info.levels = 1; + info.format = format; + info.type = VK_IMAGE_TYPE_2D; + info.layers = 1; + info.usage = (format_has_depth_or_stencil_aspect(format) ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.flags = 0; + info.misc = 0; + info.initial_layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; + return info; + } + + static ImageCreateInfo transient_render_target(unsigned width, unsigned height, VkFormat format) + { + ImageCreateInfo info; + info.domain = ImageDomain::Transient; + info.width = width; + info.height = height; + info.depth = 1; + info.levels = 1; + info.format = format; + info.type = VK_IMAGE_TYPE_2D; + info.layers = 1; + info.usage = (format_has_depth_or_stencil_aspect(format) ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.flags = 0; + info.misc = 0; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + return info; + } + + static uint32_t compute_view_formats(const ImageCreateInfo &info, VkFormat *formats) + { + if ((info.misc & IMAGE_MISC_MUTABLE_SRGB_BIT) == 0) + return 0; + + switch (info.format) + { + case VK_FORMAT_R8G8B8A8_UNORM: + case VK_FORMAT_R8G8B8A8_SRGB: + formats[0] = VK_FORMAT_R8G8B8A8_UNORM; + formats[1] = VK_FORMAT_R8G8B8A8_SRGB; + return 2; + + case VK_FORMAT_B8G8R8A8_UNORM: + case VK_FORMAT_B8G8R8A8_SRGB: + formats[0] = VK_FORMAT_B8G8R8A8_UNORM; + formats[1] = VK_FORMAT_B8G8R8A8_SRGB; + return 2; + + case VK_FORMAT_A8B8G8R8_UNORM_PACK32: + case VK_FORMAT_A8B8G8R8_SRGB_PACK32: + formats[0] = VK_FORMAT_A8B8G8R8_UNORM_PACK32; + formats[1] = VK_FORMAT_A8B8G8R8_SRGB_PACK32; + return 2; + + default: + return 0; + } + } +}; + +class Image; + +struct ImageDeleter +{ + void operator()(Image *image); +}; + +class Image : public Util::IntrusivePtrEnabled, + public Cookie, public InternalSyncEnabled +{ +public: + friend struct ImageDeleter; + + ~Image(); + + Image(Image &&) = delete; + + Image &operator=(Image &&) = delete; + + const ImageView &get_view() const + { + VK_ASSERT(view); + return *view; + } + + ImageView &get_view() + { + VK_ASSERT(view); + return *view; + } + + VkImage get_image() const + { + return image; + } + + VkFormat get_format() const + { + return create_info.format; + } + + uint32_t get_width(uint32_t lod = 0) const + { + return std::max(1u, create_info.width >> lod); + } + + uint32_t get_height(uint32_t lod = 0) const + { + return std::max(1u, create_info.height >> lod); + } + + uint32_t get_depth(uint32_t lod = 0) const + { + return std::max(1u, create_info.depth >> lod); + } + + const ImageCreateInfo &get_create_info() const + { + return create_info; + } + + VkImageLayout get_layout(VkImageLayout optimal) const + { + return create_info.layout == ImageLayout::Optimal ? optimal : VK_IMAGE_LAYOUT_GENERAL; + } + + bool is_swapchain_image() const + { + return swapchain_layout != VK_IMAGE_LAYOUT_UNDEFINED; + } + + VkImageLayout get_swapchain_layout() const + { + return swapchain_layout; + } + + void set_swapchain_layout(VkImageLayout layout) + { + swapchain_layout = layout; + } + + const DeviceAllocation &get_allocation() const + { + return alloc; + } + + void disown_image(); + void disown_memory_allocation(); + DeviceAllocation take_allocation_ownership(); + + void set_surface_transform(VkSurfaceTransformFlagBitsKHR transform) + { + surface_transform = transform; + if (transform != VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) + { + const VkImageUsageFlags safe_usage_flags = + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + + if ((create_info.usage & ~safe_usage_flags) != 0) + { + LOGW("Using surface transform for non-pure render target image (usage: %u). This can lead to weird results.\n", + create_info.usage); + } + } + } + + VkSurfaceTransformFlagBitsKHR get_surface_transform() const + { + return surface_transform; + } + + ExternalHandle export_handle(); + +private: + friend class Util::ObjectPool; + + Image(Device *device, VkImage image, const CachedImageView &default_view, const DeviceAllocation &alloc, + const ImageCreateInfo &info, VkImageViewType view_type); + + Device *device; + VkImage image; + ImageViewHandle view; + DeviceAllocation alloc; + ImageCreateInfo create_info; + + VkImageLayout swapchain_layout = VK_IMAGE_LAYOUT_UNDEFINED; + VkSurfaceTransformFlagBitsKHR surface_transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + bool owns_image = true; + bool owns_memory_allocation = true; +}; + +using ImageHandle = Util::IntrusivePtr; + +class LinearHostImage; +struct LinearHostImageDeleter +{ + void operator()(LinearHostImage *image); +}; + +class Buffer; + +enum LinearHostImageCreateInfoFlagBits +{ + LINEAR_HOST_IMAGE_HOST_CACHED_BIT = 1 << 0, + LINEAR_HOST_IMAGE_REQUIRE_LINEAR_FILTER_BIT = 1 << 1, + LINEAR_HOST_IMAGE_IGNORE_DEVICE_LOCAL_BIT = 1 << 2 +}; +using LinearHostImageCreateInfoFlags = uint32_t; + +struct LinearHostImageCreateInfo +{ + unsigned width = 0; + unsigned height = 0; + VkFormat format = VK_FORMAT_UNDEFINED; + VkImageUsageFlags usage = 0; + VkPipelineStageFlags2 stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + LinearHostImageCreateInfoFlags flags = 0; +}; + +// Special image type which supports direct CPU mapping. +// Useful optimization for UMA implementations of Vulkan where we don't necessarily need +// to perform staging copies. It gracefully falls back to staging buffer as needed. +// Only usage flag SAMPLED_BIT is currently supported. +class LinearHostImage : public Util::IntrusivePtrEnabled +{ +public: + friend struct LinearHostImageDeleter; + + size_t get_row_pitch_bytes() const; + size_t get_offset() const; + const ImageView &get_view() const; + const Image &get_image() const; + const DeviceAllocation &get_host_visible_allocation() const; + const Buffer &get_host_visible_buffer() const; + bool need_staging_copy() const; + VkPipelineStageFlags2 get_used_pipeline_stages() const; + +private: + friend class Util::ObjectPool; + LinearHostImage(Device *device, ImageHandle gpu_image, Util::IntrusivePtr cpu_image, + VkPipelineStageFlags2 stages); + Device *device; + ImageHandle gpu_image; + Util::IntrusivePtr cpu_image; + VkPipelineStageFlags2 stages; + size_t row_pitch; + size_t row_offset; +}; +using LinearHostImageHandle = Util::IntrusivePtr; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/indirect_layout.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/indirect_layout.cpp new file mode 100644 index 00000000..79fd004b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/indirect_layout.cpp @@ -0,0 +1,146 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "indirect_layout.hpp" +#include "device.hpp" + +namespace Vulkan +{ +IndirectLayout::IndirectLayout(Device *device_, + const PipelineLayout *pipeline_layout, const IndirectLayoutToken *tokens, + uint32_t num_tokens, uint32_t stride) + : device(device_) +{ + VkIndirectCommandsLayoutCreateInfoEXT info = { VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_EXT }; + info.indirectStride = stride; + info.pipelineLayout = pipeline_layout ? pipeline_layout->get_layout() : VK_NULL_HANDLE; + info.flags = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_EXT | + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_EXT; + + Util::SmallVector ext_tokens; + Util::SmallVector vbo_tokens; + Util::SmallVector push_tokens; + VkIndirectCommandsIndexBufferTokenEXT ibo_token; + VkIndirectCommandsExecutionSetTokenEXT exec_token; + + ext_tokens.reserve(num_tokens); + vbo_tokens.reserve(num_tokens); + push_tokens.reserve(num_tokens); + bool heap = device->get_device_features().descriptor_heap_features.descriptorHeap == VK_TRUE; + + for (uint32_t i = 0; i < num_tokens; i++) + { + VkIndirectCommandsLayoutTokenEXT token = { VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_EXT }; + switch (tokens[i].type) + { + case IndirectLayoutToken::Type::VBO: + token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXT; + vbo_tokens.emplace_back(); + token.data.pVertexBuffer = &vbo_tokens.back(); + vbo_tokens.back().vertexBindingUnit = tokens[i].data.vbo.binding; + break; + + case IndirectLayoutToken::Type::IBO: + token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_EXT; + token.data.pIndexBuffer = &ibo_token; + ibo_token.mode = VK_INDIRECT_COMMANDS_INPUT_MODE_VULKAN_INDEX_BUFFER_EXT; + break; + + case IndirectLayoutToken::Type::PushConstant: + case IndirectLayoutToken::Type::SequenceCount: + { + auto push_token_type = heap ? + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_DATA_EXT : + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT; + + auto sequence_token_type = heap ? + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_DATA_SEQUENCE_INDEX_EXT : + VK_INDIRECT_COMMANDS_TOKEN_TYPE_SEQUENCE_INDEX_EXT; + + token.type = tokens[i].type == IndirectLayoutToken::Type::PushConstant ? + push_token_type : sequence_token_type; + + push_tokens.emplace_back(); + token.data.pPushConstant = &push_tokens.back(); + VK_ASSERT(pipeline_layout->get_layout()); + push_tokens.back().updateRange.size = tokens[i].data.push.range; + push_tokens.back().updateRange.offset = tokens[i].data.push.offset; + push_tokens.back().updateRange.stageFlags = + heap ? VkShaderStageFlags(VK_SHADER_STAGE_ALL) : + pipeline_layout->get_resource_layout().push_constant_range.stageFlags; + break; + } + + case IndirectLayoutToken::Type::Draw: + info.shaderStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; + token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT; + break; + + case IndirectLayoutToken::Type::DrawIndexed: + token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_EXT; + info.shaderStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; + break; + + case IndirectLayoutToken::Type::Shader: + token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT; + token.data.pExecutionSet = &exec_token; + break; + + case IndirectLayoutToken::Type::MeshTasks: + token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_EXT; + info.shaderStages |= VK_SHADER_STAGE_MESH_BIT_EXT | VK_SHADER_STAGE_TASK_BIT_EXT | + VK_SHADER_STAGE_FRAGMENT_BIT; + break; + + case IndirectLayoutToken::Type::Dispatch: + token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT; + info.shaderStages |= VK_SHADER_STAGE_COMPUTE_BIT; + break; + + default: + LOGE("Invalid token type.\n"); + break; + } + + token.offset = tokens[i].offset; + + ext_tokens.push_back(token); + } + + info.pTokens = ext_tokens.data(); + info.tokenCount = num_tokens; + exec_token.type = VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXT; + exec_token.shaderStages = info.shaderStages; + stages = info.shaderStages; + + auto &table = device->get_device_table(); + if (table.vkCreateIndirectCommandsLayoutEXT(device->get_device(), &info, nullptr, &layout) != VK_SUCCESS) + { + LOGE("Failed to create indirect layout.\n"); + } +} + +IndirectLayout::~IndirectLayout() +{ + device->get_device_table().vkDestroyIndirectCommandsLayoutEXT(device->get_device(), layout, nullptr); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/indirect_layout.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/indirect_layout.hpp new file mode 100644 index 00000000..89522d22 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/indirect_layout.hpp @@ -0,0 +1,93 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include "vulkan_common.hpp" +#include "cookie.hpp" +#include "small_vector.hpp" + +namespace Vulkan +{ +class Device; +class PipelineLayout; + +struct IndirectLayoutToken +{ + enum class Type + { + Invalid = 0, + Shader, + PushConstant, + SequenceCount, + VBO, + IBO, + Draw, + DrawIndexed, + MeshTasks, + Dispatch + }; + + Type type = Type::Invalid; + uint32_t offset = 0; + + union + { + struct + { + uint32_t offset; + uint32_t range; + } push; + + struct + { + uint32_t binding; + } vbo; + } data = {}; +}; + +class IndirectLayout : public HashedObject +{ +public: + IndirectLayout(Device *device, const PipelineLayout *layout, const IndirectLayoutToken *token, + uint32_t num_tokens, uint32_t stride); + ~IndirectLayout(); + + VkIndirectCommandsLayoutEXT get_layout() const + { + return layout; + } + + VkShaderStageFlags get_shader_stages() const + { + return stages; + } + +private: + friend class Device; + + Device *device; + VkIndirectCommandsLayoutEXT layout; + VkShaderStageFlags stages; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/limits.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/limits.hpp new file mode 100644 index 00000000..613aef6a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/limits.hpp @@ -0,0 +1,41 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +namespace Vulkan +{ +constexpr unsigned VULKAN_NUM_DESCRIPTOR_SETS = 4; +constexpr unsigned VULKAN_NUM_DYNAMIC_UBOS = 8; // Vulkan min-spec +constexpr unsigned VULKAN_NUM_BINDINGS = 32; +constexpr unsigned VULKAN_NUM_BINDINGS_BINDLESS_VARYING = 16 * 1024; +constexpr unsigned VULKAN_NUM_ATTACHMENTS = 8; +constexpr unsigned VULKAN_NUM_VERTEX_ATTRIBS = 16; +constexpr unsigned VULKAN_NUM_VERTEX_BUFFERS = 4; +constexpr unsigned VULKAN_PUSH_CONSTANT_SIZE = 128; +constexpr unsigned VULKAN_PUSH_DATA_SIZE = 256; +constexpr unsigned VULKAN_MAX_UBO_SIZE = 64 * 1024; +constexpr unsigned VULKAN_NUM_USER_SPEC_CONSTANTS = 8; +constexpr unsigned VULKAN_NUM_INTERNAL_SPEC_CONSTANTS = 4; +constexpr unsigned VULKAN_NUM_TOTAL_SPEC_CONSTANTS = + VULKAN_NUM_USER_SPEC_CONSTANTS + VULKAN_NUM_INTERNAL_SPEC_CONSTANTS; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/resource_manager.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/resource_manager.cpp new file mode 100644 index 00000000..7ee50057 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/resource_manager.cpp @@ -0,0 +1,922 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "resource_manager.hpp" +#include "device.hpp" +#include "memory_mapped_texture.hpp" +#include "texture_files.hpp" +#include "texture_decoder.hpp" +#include "string_helpers.hpp" +#include "thread_group.hpp" +#include "meshlet.hpp" +#include "aabb.hpp" +#include "environment.hpp" +#include + +namespace Vulkan +{ +ResourceManager::ResourceManager(Device *device_) + : device(device_) + , index_buffer_allocator(*device_, 256, 17) + , attribute_buffer_allocator(*device_, 256, 17) + , indirect_buffer_allocator(*device_, 32, 15) + , mesh_header_allocator(*device_, 32, 15) + , mesh_stream_allocator(*device_, 8, 17) + , mesh_payload_allocator(*device_, 32, 17) +{ + assets.reserve(Granite::AssetID::MaxIDs); +} + +ResourceManager::~ResourceManager() +{ + // Also works as a teardown mechanism to make sure there are no async threads in flight. + if (manager) + manager->set_asset_instantiator_interface(nullptr); + + // Ensure resource releases go through. + latch_handles(); +} + +void ResourceManager::set_id_bounds(uint32_t bound) +{ + // We must avoid reallocation here to avoid a ton of extra silly locking. + VK_ASSERT(bound <= Granite::AssetID::MaxIDs); + assets.resize(bound); +} + +void ResourceManager::set_asset_class(Granite::AssetID id, Granite::AssetClass asset_class) +{ + if (id) + { + assets[id.id].asset_class = asset_class; + if (asset_class != Granite::AssetClass::Mesh) + { + std::unique_lock holder{lock}; + views.resize(assets.size()); + + if (!views[id.id]) + views[id.id] = &get_fallback_image(asset_class)->get_view(); + } + } +} + +void ResourceManager::release_asset(Granite::AssetID id) +{ + if (id) + { + std::unique_lock holder{lock}; + VK_ASSERT(id.id < assets.size()); + auto &asset = assets[id.id]; + asset.latchable = false; + updates.push_back(id); + } +} + +uint64_t ResourceManager::estimate_cost_asset(Granite::AssetID id, Granite::File &file) +{ + if (assets[id.id].asset_class == Granite::AssetClass::Mesh) + { + // Compression factor of 2x is reasonable to assume. + if (mesh_encoding == MeshEncoding::VBOAndIBOMDI) + return file.get_size() * 2; + else + return file.get_size(); + } + else + { + // TODO: When we get compressed BC/ASTC, this will have to change. + return file.get_size(); + } +} + +void ResourceManager::init_mesh_assets() +{ + Internal::MeshGlobalAllocator::PrimeOpaque opaque = {}; + opaque.domain = BufferDomain::Device; + opaque.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + + if (device->get_device_features().mesh_shader_features.meshShader) + { + mesh_encoding = MeshEncoding::MeshletEncoded; + LOGI("Opting in to meshlet path.\n"); + } + else + { + mesh_encoding = MeshEncoding::VBOAndIBOMDI; + LOGI("Falling back to multi-draw-indirect path.\n"); + } + + std::string encoding; + if (Util::get_environment("GRANITE_MESH_ENCODING", encoding)) + { + if (encoding == "encoded") + mesh_encoding = MeshEncoding::MeshletEncoded; + else if (encoding == "decoded") + mesh_encoding = MeshEncoding::MeshletDecoded; + else if (encoding == "mdi") + mesh_encoding = MeshEncoding::VBOAndIBOMDI; + else if (encoding == "classic") + mesh_encoding = MeshEncoding::Classic; + else + LOGE("Unknown encoding: %s\n", encoding.c_str()); + } + + if (mesh_encoding != MeshEncoding::MeshletEncoded) + { + unsigned index_size; + + if (mesh_encoding == MeshEncoding::Classic) + index_size = sizeof(uint32_t); + else if (device->get_device_features().vk14_features.indexTypeUint8) + index_size = sizeof(uint8_t); + else + index_size = sizeof(uint16_t); + + index_buffer_allocator.set_element_size(0, 3 * index_size); // 8-bit or 32-bit indices. + attribute_buffer_allocator.set_soa_count(3); + attribute_buffer_allocator.set_element_size(0, sizeof(float) * 3); + attribute_buffer_allocator.set_element_size(1, sizeof(float) * 2 + sizeof(uint32_t) * 2); + attribute_buffer_allocator.set_element_size(2, sizeof(uint32_t) * 2); + + opaque.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + index_buffer_allocator.prime(&opaque); + opaque.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + attribute_buffer_allocator.prime(&opaque); + + if (mesh_encoding != MeshEncoding::Classic) + { + auto element_size = mesh_encoding == MeshEncoding::MeshletDecoded ? + sizeof(Meshlet::RuntimeHeaderDecoded) : sizeof(Meshlet::RuntimeHeaderDecodedMDI); + + indirect_buffer_allocator.set_soa_count(2); + indirect_buffer_allocator.set_element_size(0, Meshlet::ChunkFactor * element_size); + indirect_buffer_allocator.set_element_size(1, sizeof(Meshlet::Bound)); + + opaque.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT; + indirect_buffer_allocator.prime(&opaque); + } + } + else + { + mesh_header_allocator.set_element_size(0, sizeof(Meshlet::RuntimeHeaderEncoded)); + mesh_stream_allocator.set_element_size(0, sizeof(Meshlet::Stream)); + mesh_payload_allocator.set_element_size(0, sizeof(Meshlet::PayloadWord)); + + mesh_header_allocator.set_soa_count(2); + mesh_header_allocator.set_element_size(1, sizeof(Meshlet::Bound)); + + opaque.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + mesh_header_allocator.prime(&opaque); + mesh_stream_allocator.prime(&opaque); + mesh_payload_allocator.prime(&opaque); + } +} + +void ResourceManager::init() +{ + manager = device->get_system_handles().asset_manager; + + // Need to initialize these before setting the interface. + { + uint8_t buffer[4] = {0xff, 0x00, 0xff, 0xff}; + auto info = ImageCreateInfo::immutable_2d_image(1, 1, VK_FORMAT_R8G8B8A8_UNORM); + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + info.misc = IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT | + IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT; + ImageInitialData data = {buffer, 0, 0}; + fallback_color = device->create_image(info, &data); + buffer[0] = 0x80; + buffer[1] = 0x80; + buffer[2] = 0xff; + fallback_normal = device->create_image(info, &data); + buffer[0] = 0x00; + buffer[1] = 0x00; + fallback_pbr = device->create_image(info, &data); + memset(buffer, 0, sizeof(buffer)); + fallback_zero = device->create_image(info, &data); + } + + if (manager) + { + manager->set_asset_instantiator_interface(this); + + HeapBudget budget[VK_MAX_MEMORY_HEAPS] = {}; + device->get_memory_budget(budget); + + // Try to set aside 50% of budgetable VRAM for the resource manager. Seems reasonable. + VkDeviceSize size = 0; + for (uint32_t i = 0; i < device->get_memory_properties().memoryHeapCount; i++) + if ((device->get_memory_properties().memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0) + size = std::max(size, budget[i].budget_size / 2); + + if (size == 0) + { + LOGW("No DEVICE_LOCAL heap was found, assuming 2 GiB budget.\n"); + size = 2 * 1024 * 1024; + } + + LOGI("Using texture budget of %u MiB.\n", unsigned(size / (1024 * 1024))); + manager->set_asset_budget(size); + + // This is somewhat arbitrary. + manager->set_asset_budget_per_iteration(2 * 1000 * 1000); + } + + // Opt-in. Normal Granite applications shouldn't allocate up a ton of space up front. + if (manager && manager->get_wants_mesh_assets()) + init_mesh_assets(); +} + +ImageHandle ResourceManager::create_gtx(const MemoryMappedTexture &mapped_file, Granite::AssetID id) +{ + if (mapped_file.empty()) + return {}; + + auto &layout = mapped_file.get_layout(); + + VkComponentMapping swizzle = {}; + mapped_file.remap_swizzle(swizzle); + + ImageHandle image; + if (!device->image_format_is_supported(layout.get_format(), VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) && + format_compression_type(layout.get_format()) != FormatCompressionType::Uncompressed) + { + LOGI("Compressed format #%u is not supported, falling back to compute decode of compressed image.\n", + unsigned(layout.get_format())); + + GRANITE_SCOPED_TIMELINE_EVENT_FILE(device->get_system_handles().timeline_trace_file, "texture-load-submit-decompress"); + auto cmd = device->request_command_buffer(CommandBuffer::Type::AsyncCompute); + image = Granite::decode_compressed_image(*cmd, layout, VK_FORMAT_UNDEFINED, swizzle); + Semaphore sem; + device->submit(cmd, nullptr, 1, &sem); + device->add_wait_semaphore(CommandBuffer::Type::Generic, sem, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, true); + } + else + { + ImageCreateInfo info = ImageCreateInfo::immutable_image(layout); + info.swizzle = swizzle; + info.flags = (mapped_file.get_flags() & MEMORY_MAPPED_TEXTURE_CUBE_MAP_COMPATIBLE_BIT) ? + VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : + 0; + info.misc = IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT | + IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT; + + if (info.levels == 1 && + (mapped_file.get_flags() & MEMORY_MAPPED_TEXTURE_GENERATE_MIPMAP_ON_LOAD_BIT) != 0 && + device->image_format_is_supported(info.format, VK_FORMAT_FEATURE_BLIT_SRC_BIT) && + device->image_format_is_supported(info.format, VK_FORMAT_FEATURE_BLIT_DST_BIT)) + { + info.levels = 0; + info.misc |= IMAGE_MISC_GENERATE_MIPS_BIT; + } + + if (!device->image_format_is_supported(info.format, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) + { + LOGE("Format (%u) is not supported!\n", unsigned(info.format)); + return {}; + } + + InitialImageBuffer staging; + + { + GRANITE_SCOPED_TIMELINE_EVENT_FILE(device->get_system_handles().timeline_trace_file, + "texture-load-create-staging"); + staging = device->create_image_staging_buffer(layout); + } + + { + GRANITE_SCOPED_TIMELINE_EVENT_FILE(device->get_system_handles().timeline_trace_file, + "texture-load-allocate-image"); + image = device->create_image_from_staging_buffer(info, &staging); + } + } + + if (image) + { + auto name = Util::join("AssetID-", id.id); + device->set_name(*image, name.c_str()); + } + return image; +} + +ImageHandle ResourceManager::create_gtx(Granite::FileMappingHandle mapping, Granite::AssetID id) +{ + MemoryMappedTexture mapped_file; + if (!mapped_file.map_read(std::move(mapping))) + { + LOGE("Failed to read texture.\n"); + return {}; + } + + return create_gtx(mapped_file, id); +} + +ImageHandle ResourceManager::create_other(const Granite::FileMapping &mapping, Granite::AssetClass asset_class, + Granite::AssetID id) +{ + auto tex = load_texture_from_memory(mapping.data(), + mapping.get_size(), asset_class == Granite::AssetClass::ImageColor ? + ColorSpace::sRGB : ColorSpace::Linear); + return create_gtx(tex, id); +} + +const ImageView *ResourceManager::get_image_view_blocking(Granite::AssetID id) +{ + std::unique_lock holder{lock}; + + if (id.id >= assets.size()) + { + LOGE("ID %u is out of bounds.\n", id.id); + return nullptr; + } + + auto &asset = assets[id.id]; + + if (asset.image) + return &asset.image->get_view(); + + if (!manager->iterate_blocking(*device->get_system_handles().thread_group, id)) + { + LOGE("Failed to iterate.\n"); + return nullptr; + } + + cond.wait(holder, [&asset]() -> bool { + return bool(asset.latchable); + }); + + return &asset.image->get_view(); +} + +void ResourceManager::instantiate_asset(Granite::AssetManager &manager_, Granite::TaskGroup *task, + Granite::AssetID id, Granite::File &file) +{ + if (task) + { + task->enqueue_task([this, &manager_, &file, id]() { + instantiate_asset(manager_, id, file); + }); + } + else + { + instantiate_asset(manager_, id, file); + } +} + +void ResourceManager::instantiate_asset(Granite::AssetManager &manager_, + Granite::AssetID id, + Granite::File &file) +{ + auto &asset = assets[id.id]; + if (asset.asset_class == Granite::AssetClass::Mesh) + instantiate_asset_mesh(manager_, id, file); + else + instantiate_asset_image(manager_, id, file); +} + +bool ResourceManager::allocate_asset_mesh(Granite::AssetID id, const Meshlet::MeshView &view) +{ + if (!view.format_header) + return false; + + std::lock_guard holder{mesh_allocator_lock}; + auto &asset = assets[id.id]; + + bool ret = true; + + if (mesh_encoding == MeshEncoding::MeshletEncoded) + { + if (ret) + ret = mesh_header_allocator.allocate(view.num_bounds_256, &asset.mesh.indirect_or_header); + + if (ret) + { + ret = mesh_stream_allocator.allocate( + view.num_bounds_256 * Meshlet::ChunkFactor * view.format_header->stream_count, + &asset.mesh.attr_or_stream); + } + + if (ret) + ret = mesh_payload_allocator.allocate(view.format_header->payload_size_words, &asset.mesh.index_or_payload); + } + else + { + if (ret) + ret = index_buffer_allocator.allocate(view.total_primitives, &asset.mesh.index_or_payload); + if (ret) + ret = attribute_buffer_allocator.allocate(view.total_vertices, &asset.mesh.attr_or_stream); + + if (ret && mesh_encoding != MeshEncoding::Classic) + ret = indirect_buffer_allocator.allocate(view.num_bounds_256, &asset.mesh.indirect_or_header); + } + + if (mesh_encoding == MeshEncoding::Classic) + { + asset.mesh.draw.indexed = { + view.total_primitives * 3, 1, + asset.mesh.index_or_payload.offset, + int32_t(asset.mesh.attr_or_stream.offset), 0, + }; + } + else + { + asset.mesh.draw.meshlet = { + asset.mesh.indirect_or_header.offset, + view.num_bounds_256, + view.format_header->style, + }; + } + + if (!ret) + { + if (mesh_encoding == MeshEncoding::MeshletEncoded) + { + mesh_payload_allocator.free(asset.mesh.index_or_payload); + mesh_stream_allocator.free(asset.mesh.attr_or_stream); + mesh_header_allocator.free(asset.mesh.indirect_or_header); + } + else + { + index_buffer_allocator.free(asset.mesh.index_or_payload); + attribute_buffer_allocator.free(asset.mesh.attr_or_stream); + indirect_buffer_allocator.free(asset.mesh.indirect_or_header); + } + + asset.mesh = {}; + } + return ret; +} + +void ResourceManager::instantiate_asset_mesh(Granite::AssetManager &manager_, + Granite::AssetID id, + Granite::File &file) +{ + Granite::FileMappingHandle mapping; + if (file.get_size()) + mapping = file.map(); + + Meshlet::MeshView view = {}; + if (mapping) + view = Meshlet::create_mesh_view(*mapping); + bool ret = allocate_asset_mesh(id, view); + + // Decode the meshlet. Later, we'll have to do a lot of device specific stuff here to select optimal + // processing: + // - Native meshlets + // - Encoded attribute + // - Decoded attributes + // - Optimize for multi-draw-indirect or not? (8-bit indices). + + auto &asset = assets[id.id]; + + if (ret) + { + size_t total_streams = view.format_header->meshlet_count * view.format_header->stream_count; + size_t total_padded_streams = view.num_bounds_256 * Meshlet::ChunkFactor * view.format_header->stream_count; + + if (mesh_encoding == MeshEncoding::MeshletEncoded) + { + auto cmd = device->request_command_buffer(CommandBuffer::Type::AsyncTransfer); + + void *payload_data = cmd->update_buffer(*mesh_payload_allocator.get_buffer(0, 0), + asset.mesh.index_or_payload.offset * sizeof(Meshlet::PayloadWord), + view.format_header->payload_size_words * sizeof(Meshlet::PayloadWord)); + memcpy(payload_data, view.payload, view.format_header->payload_size_words * sizeof(Meshlet::PayloadWord)); + + auto *headers = static_cast( + cmd->update_buffer(*mesh_header_allocator.get_buffer(0, 0), + asset.mesh.indirect_or_header.offset * sizeof(Meshlet::RuntimeHeaderEncoded), + view.num_bounds_256 * sizeof(Meshlet::RuntimeHeaderEncoded))); + + for (uint32_t i = 0, n = view.num_bounds_256; i < n; i++) + { + headers[i].stream_offset = asset.mesh.attr_or_stream.offset + + i * Meshlet::ChunkFactor * view.format_header->stream_count; + } + + auto *bounds = static_cast( + cmd->update_buffer(*mesh_header_allocator.get_buffer(0, 1), + asset.mesh.indirect_or_header.offset * sizeof(Meshlet::Bound), + view.num_bounds_256 * sizeof(Meshlet::Bound))); + memcpy(bounds, view.bounds_256, view.num_bounds_256 * sizeof(Meshlet::Bound)); + + auto *streams = static_cast( + cmd->update_buffer(*mesh_stream_allocator.get_buffer(0, 0), + asset.mesh.attr_or_stream.offset * sizeof(Meshlet::Stream), + total_padded_streams * sizeof(Meshlet::Stream))); + + for (uint32_t i = 0; i < total_streams; i++) + { + auto in_stream = view.streams[i]; + in_stream.offset_in_words += asset.mesh.index_or_payload.offset; + streams[i] = in_stream; + } + + memset(streams + total_streams, 0, (total_padded_streams - total_streams) * sizeof(Meshlet::Stream)); + + Semaphore sem; + device->submit(cmd, nullptr, 1, &sem); + device->add_wait_semaphore(CommandBuffer::Type::Generic, std::move(sem), + VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT | + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, false); + } + else + { + auto cmd = device->request_command_buffer(CommandBuffer::Type::AsyncCompute); + + BufferCreateInfo buf = {}; + buf.domain = BufferDomain::Host; + buf.size = view.format_header->payload_size_words * sizeof(Meshlet::PayloadWord); + buf.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + auto payload = device->create_buffer(buf, view.payload); + + Meshlet::DecodeInfo info = {}; + info.target_style = view.format_header->style; + if (mesh_encoding == MeshEncoding::Classic) + info.flags |= Meshlet::DECODE_MODE_UNROLLED_MESH; + else if (!device->get_device_features().vk14_features.indexTypeUint8) + info.flags |= Meshlet::DECODE_MODE_INDEX_16; + info.ibo = index_buffer_allocator.get_buffer(0, 0); + + for (unsigned i = 0; i < 3; i++) + info.streams[i] = attribute_buffer_allocator.get_buffer(0, i); + + info.payload = payload.get(); + + info.push.primitive_offset = asset.mesh.index_or_payload.offset; + info.push.vertex_offset = asset.mesh.attr_or_stream.offset; + + info.runtime_style = mesh_encoding == MeshEncoding::MeshletDecoded ? + Meshlet::RuntimeStyle::Meshlet : Meshlet::RuntimeStyle::MDI; + + if (mesh_encoding != MeshEncoding::Classic) + { + auto *bounds = static_cast( + cmd->update_buffer(*indirect_buffer_allocator.get_buffer(0, 1), + asset.mesh.indirect_or_header.offset * sizeof(Meshlet::Bound), + view.num_bounds_256 * sizeof(Meshlet::Bound))); + memcpy(bounds, view.bounds_256, view.num_bounds_256 * sizeof(Meshlet::Bound)); + + info.indirect = indirect_buffer_allocator.get_buffer(0, 0); + info.indirect_offset = asset.mesh.indirect_or_header.offset; + } + + Meshlet::decode_mesh(*cmd, info, view); + + Semaphore sem; + device->submit(cmd, nullptr, 1, &sem); + device->add_wait_semaphore(CommandBuffer::Type::Generic, std::move(sem), + VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT | + VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT, false); + } + } + + uint64_t cost = 0; + if (ret) + { + if (mesh_encoding == MeshEncoding::MeshletEncoded) + { + cost += view.format_header->payload_size_words * mesh_payload_allocator.get_element_size(0); + cost += view.num_bounds_256 * mesh_header_allocator.get_element_size(0); + cost += view.num_bounds_256 * mesh_header_allocator.get_element_size(1); + cost += view.format_header->meshlet_count * view.format_header->stream_count * mesh_stream_allocator.get_element_size(0); + } + else + { + cost += view.total_primitives * index_buffer_allocator.get_element_size(0); + cost += view.total_vertices * attribute_buffer_allocator.get_element_size(0); + cost += view.total_vertices * attribute_buffer_allocator.get_element_size(1); + cost += view.total_vertices * attribute_buffer_allocator.get_element_size(2); + if (mesh_encoding != MeshEncoding::Classic) + { + cost += view.format_header->meshlet_count * indirect_buffer_allocator.get_element_size(0); + cost += view.format_header->meshlet_count * indirect_buffer_allocator.get_element_size(1); + } + } + } + + std::lock_guard holder{lock}; + updates.push_back(id); + manager_.update_cost(id, ret ? cost : 0); + asset.latchable = true; + cond.notify_all(); +} + +void ResourceManager::instantiate_asset_image(Granite::AssetManager &manager_, + Granite::AssetID id, + Granite::File &file) +{ + auto &asset = assets[id.id]; + + ImageHandle image; + if (file.get_size()) + { + auto mapping = file.map(); + if (mapping) + { + if (MemoryMappedTexture::is_header(mapping->data(), mapping->get_size())) + image = create_gtx(std::move(mapping), id); + else + image = create_other(*mapping, asset.asset_class, id); + } + else + LOGE("Failed to map file.\n"); + } + + // Have to signal something. + if (!image) + image = get_fallback_image(asset.asset_class); + + std::lock_guard holder{lock}; + updates.push_back(id); + asset.image = std::move(image); + asset.latchable = true; + manager_.update_cost(id, asset.image ? asset.image->get_allocation().get_size() : 0); + cond.notify_all(); +} + +const ImageHandle &ResourceManager::get_fallback_image(Granite::AssetClass asset_class) +{ + switch (asset_class) + { + default: + case Granite::AssetClass::ImageZeroable: + return fallback_zero; + case Granite::AssetClass::ImageColor: + return fallback_color; + case Granite::AssetClass::ImageNormal: + return fallback_normal; + case Granite::AssetClass::ImageMetallicRoughness: + return fallback_pbr; + } +} + +void ResourceManager::latch_handles() +{ + std::lock_guard holder{lock}; + + views.resize(assets.size()); + draws.resize(assets.size()); + + for (auto &update : updates) + { + if (update.id >= views.size()) + continue; + auto &asset = assets[update.id]; + + if (asset.asset_class == Granite::AssetClass::Mesh) + { + if (!asset.latchable) + { + { + std::lock_guard holder_alloc{mesh_allocator_lock}; + if (mesh_encoding == MeshEncoding::MeshletEncoded) + { + mesh_payload_allocator.free(asset.mesh.index_or_payload); + mesh_stream_allocator.free(asset.mesh.attr_or_stream); + mesh_header_allocator.free(asset.mesh.indirect_or_header); + } + else + { + index_buffer_allocator.free(asset.mesh.index_or_payload); + attribute_buffer_allocator.free(asset.mesh.attr_or_stream); + indirect_buffer_allocator.free(asset.mesh.indirect_or_header); + } + } + asset.mesh = {}; + } + + draws[update.id] = asset.mesh.draw; + } + else + { + const ImageView *view; + if (!asset.latchable) + asset.image.reset(); + + if (asset.image) + { + view = &asset.image->get_view(); + } + else + { + auto &img = get_fallback_image(asset.asset_class); + view = &img->get_view(); + } + + views[update.id] = view; + } + } + updates.clear(); +} + +const Buffer *ResourceManager::get_index_buffer() const +{ + return index_buffer_allocator.get_buffer(0, 0); +} + +const Buffer *ResourceManager::get_position_buffer() const +{ + return attribute_buffer_allocator.get_buffer(0, 0); +} + +const Buffer *ResourceManager::get_attribute_buffer() const +{ + return attribute_buffer_allocator.get_buffer(0, 1); +} + +const Buffer *ResourceManager::get_skinning_buffer() const +{ + return attribute_buffer_allocator.get_buffer(0, 2); +} + +const Buffer *ResourceManager::get_indirect_buffer() const +{ + return indirect_buffer_allocator.get_buffer(0, 0); +} + +const Buffer *ResourceManager::get_meshlet_payload_buffer() const +{ + return mesh_payload_allocator.get_buffer(0, 0); +} + +const Buffer *ResourceManager::get_meshlet_header_buffer() const +{ + return mesh_header_allocator.get_buffer(0, 0); +} + +const Buffer *ResourceManager::get_meshlet_stream_header_buffer() const +{ + return mesh_stream_allocator.get_buffer(0, 0); +} + +const Buffer *ResourceManager::get_cluster_bounds_buffer() const +{ + if (mesh_encoding == MeshEncoding::MeshletEncoded) + return mesh_header_allocator.get_buffer(0, 1); + else + return indirect_buffer_allocator.get_buffer(0, 1); +} + +bool ResourceManager::mesh_rendering_is_hierarchical_task() const +{ + return device->get_gpu_properties().vendorID == VENDOR_ID_AMD; +} + +bool ResourceManager::mesh_rendering_is_local_invocation_indexed() const +{ +#if 0 + bool local_invocation_indexed = + device->get_device_features().mesh_shader_properties.prefersLocalInvocationPrimitiveOutput || + device->get_device_features().mesh_shader_properties.prefersLocalInvocationVertexOutput; + + return local_invocation_indexed; +#else + return false; +#endif +} + +bool ResourceManager::mesh_rendering_is_wave_culled() const +{ + return device->supports_subgroup_size_log2(true, 5, 5, VK_SHADER_STAGE_MESH_BIT_EXT) && + device->get_device_features().vk13_props.minSubgroupSize == 32; +} + +MeshBufferAllocator::MeshBufferAllocator(Device &device, uint32_t sub_block_size, uint32_t num_sub_blocks_in_arena_log2) + : global_allocator(device) +{ + init(sub_block_size, num_sub_blocks_in_arena_log2, &global_allocator); +} + +void MeshBufferAllocator::set_soa_count(unsigned soa_count) +{ + VK_ASSERT(soa_count <= Internal::MeshGlobalAllocator::MaxSoACount); + global_allocator.soa_count = soa_count; +} + +void MeshBufferAllocator::set_element_size(unsigned soa_index, uint32_t element_size) +{ + VK_ASSERT(soa_index < global_allocator.soa_count); + global_allocator.element_size[soa_index] = element_size; +} + +uint32_t MeshBufferAllocator::get_element_size(unsigned soa_index) const +{ + VK_ASSERT(soa_index < global_allocator.soa_count); + return global_allocator.element_size[soa_index]; +} + +const Buffer *MeshBufferAllocator::get_buffer(unsigned index, unsigned soa_index) const +{ + VK_ASSERT(soa_index < global_allocator.soa_count); + index = index * global_allocator.soa_count + soa_index; + + // Avoid any race condition. + if (index < soa_index && global_allocator.preallocated_handles[soa_index]) + return global_allocator.preallocated_handles[soa_index]; + else if (index < global_allocator.global_buffers.size()) + return global_allocator.global_buffers[index].get(); + else + return nullptr; +} + +namespace Internal +{ +uint32_t MeshGlobalAllocator::allocate(uint32_t count) +{ + BufferCreateInfo info = {}; + + uint32_t target_index = UINT32_MAX; + uint32_t search_index = 0; + + for (uint32_t i = 0, n = global_buffers.size(); i < n; i += soa_count, search_index++) + { + if (!global_buffers[i]) + { + target_index = search_index; + break; + } + } + + if (target_index == UINT32_MAX) + { + if (!global_buffers.empty()) + return UINT32_MAX; + + target_index = search_index; + for (uint32_t i = 0; i < soa_count; i++) + global_buffers.emplace_back(); + } + + for (uint32_t soa_index = 0; soa_index < soa_count; soa_index++) + { + info.size = VkDeviceSize(count) * element_size[soa_index]; + info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; + info.domain = BufferDomain::Device; + + if (preallocated[soa_index] && preallocated[soa_index]->get_create_info().size >= info.size) + std::swap(preallocated[soa_index], global_buffers[target_index * soa_count + soa_index]); + else + global_buffers[target_index * soa_count + soa_index] = device.create_buffer(info); + } + + return target_index; +} + +void MeshGlobalAllocator::prime(uint32_t count, const void *opaque_meta) +{ + auto *opaque = static_cast(opaque_meta); + BufferCreateInfo info = {}; + for (uint32_t i = 0; i < soa_count; i++) + { + if (preallocated[i]) + continue; + + info.size = VkDeviceSize(count) * element_size[i]; + info.usage = opaque->usage; + info.domain = opaque->domain; + preallocated[i] = device.create_buffer(info); + preallocated_handles[i] = preallocated[i].get(); + } +} + +void MeshGlobalAllocator::free(uint32_t index) +{ + index *= soa_count; + VK_ASSERT(index < global_buffers.size()); + for (uint32_t i = 0; i < soa_count; i++) + { + std::swap(preallocated[i], global_buffers[index + i]); + global_buffers[index + i].reset(); + } +} + +MeshGlobalAllocator::MeshGlobalAllocator(Device &device_) + : device(device_) +{} +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/resource_manager.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/resource_manager.hpp new file mode 100644 index 00000000..8e5327cb --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/resource_manager.hpp @@ -0,0 +1,206 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "image.hpp" +#include "buffer.hpp" +#include "asset_manager.hpp" +#include "meshlet.hpp" +#include "arena_allocator.hpp" +#include "small_vector.hpp" +#include +#include + +namespace Vulkan +{ +class MemoryMappedTexture; + +namespace Internal +{ +struct MeshGlobalAllocator final : Util::SliceBackingAllocator +{ + explicit MeshGlobalAllocator(Device &device); + uint32_t allocate(uint32_t count) override; + void free(uint32_t index) override; + + struct PrimeOpaque + { + VkBufferUsageFlags usage; + BufferDomain domain; + }; + + void prime(uint32_t count, const void *opaque_meta) override; + + enum { MaxSoACount = 3 }; // Position, attribute, skinning. + + Device &device; + uint32_t element_size[MaxSoACount] = {}; + uint32_t soa_count = 1; + Util::SmallVector global_buffers; + BufferHandle preallocated[MaxSoACount]; + const Buffer *preallocated_handles[MaxSoACount] = {}; +}; +} + +class MeshBufferAllocator : public Util::SliceAllocator +{ +public: + MeshBufferAllocator(Device &device, uint32_t sub_block_size, uint32_t num_sub_blocks_in_arena_log2); + void set_soa_count(unsigned soa_count); + void set_element_size(unsigned soa_index, uint32_t element_size); + uint32_t get_element_size(unsigned soa_index) const; + const Buffer *get_buffer(unsigned index, unsigned soa_index) const; + +private: + Internal::MeshGlobalAllocator global_allocator; +}; + +class ResourceManager final : private Granite::AssetInstantiatorInterface +{ +public: + explicit ResourceManager(Device *device); + ~ResourceManager() override; + void init(); + + enum class MeshEncoding + { + MeshletEncoded, + MeshletDecoded, + VBOAndIBOMDI, + Classic + }; + + const Vulkan::ImageView *get_image_view(Granite::AssetID id) const + { + if (id.id < views.size()) + return views[id.id]; + else + return nullptr; + } + + const Vulkan::ImageView *get_image_view_blocking(Granite::AssetID id); + + struct DrawRange + { + uint32_t offset; + uint32_t count; + Meshlet::MeshStyle style; + }; + + union DrawCall + { + DrawRange meshlet; + VkDrawIndexedIndirectCommand indexed; + }; + + DrawCall get_mesh_draw_range(Granite::AssetID id) const + { + if (id.id < draws.size()) + return draws[id.id]; + else + return {}; + } + + MeshEncoding get_mesh_encoding() const + { + return mesh_encoding; + } + + const Buffer *get_index_buffer() const; + const Buffer *get_position_buffer() const; + const Buffer *get_attribute_buffer() const; + const Buffer *get_skinning_buffer() const; + const Buffer *get_indirect_buffer() const; + + const Buffer *get_meshlet_payload_buffer() const; + const Buffer *get_meshlet_header_buffer() const; + const Buffer *get_meshlet_stream_header_buffer() const; + + const Buffer *get_cluster_bounds_buffer() const; + + // Mesh shading requires some vendor specific tuning. + bool mesh_rendering_is_hierarchical_task() const; + bool mesh_rendering_is_local_invocation_indexed() const; + bool mesh_rendering_is_wave_culled() const; + +private: + Device *device; + Granite::AssetManager *manager = nullptr; + + void latch_handles() override; + uint64_t estimate_cost_asset(Granite::AssetID id, Granite::File &file) override; + void instantiate_asset(Granite::AssetManager &manager, Granite::TaskGroup *task, + Granite::AssetID id, Granite::File &file) override; + void release_asset(Granite::AssetID id) override; + void set_id_bounds(uint32_t bound) override; + void set_asset_class(Granite::AssetID id, Granite::AssetClass asset_class) override; + + struct Asset + { + ImageHandle image; + struct + { + Util::AllocatedSlice index_or_payload, attr_or_stream, indirect_or_header; + DrawCall draw; + } mesh; + Granite::AssetClass asset_class = Granite::AssetClass::ImageZeroable; + bool latchable = false; + }; + + std::mutex lock; + std::condition_variable cond; + + std::vector assets; + std::vector views; + std::vector draws; + std::vector updates; + + ImageHandle fallback_color; + ImageHandle fallback_normal; + ImageHandle fallback_zero; + ImageHandle fallback_pbr; + + ImageHandle create_gtx(Granite::FileMappingHandle mapping, Granite::AssetID id); + ImageHandle create_gtx(const MemoryMappedTexture &mapping, Granite::AssetID id); + ImageHandle create_other(const Granite::FileMapping &mapping, Granite::AssetClass asset_class, Granite::AssetID id); + const ImageHandle &get_fallback_image(Granite::AssetClass asset_class); + + void instantiate_asset(Granite::AssetManager &manager, Granite::AssetID id, Granite::File &file); + void instantiate_asset_image(Granite::AssetManager &manager, Granite::AssetID id, Granite::File &file); + void instantiate_asset_mesh(Granite::AssetManager &manager, Granite::AssetID id, Granite::File &file); + + std::mutex mesh_allocator_lock; + MeshBufferAllocator index_buffer_allocator; + MeshBufferAllocator attribute_buffer_allocator; + MeshBufferAllocator indirect_buffer_allocator; + MeshBufferAllocator mesh_header_allocator; + MeshBufferAllocator mesh_stream_allocator; + MeshBufferAllocator mesh_payload_allocator; + + MeshEncoding mesh_encoding = MeshEncoding::Classic; + + bool allocate_asset_mesh(Granite::AssetID id, const Meshlet::MeshView &view); + + void init_mesh_assets(); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/shader_manager.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/shader_manager.cpp new file mode 100644 index 00000000..9277e27a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/shader_manager.cpp @@ -0,0 +1,1039 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER +#include "compiler.hpp" +#endif +#include "shader_manager.hpp" +#include "path_utils.hpp" +#include "device.hpp" +#include "rapidjson_wrapper.hpp" +#include "timeline_trace_file.hpp" +#include "thread_group.hpp" +#include +#include + +using namespace Util; + +#define DEPENDENCY_LOCK() std::lock_guard holder{dependency_lock} + +namespace Vulkan +{ +ShaderTemplate::ShaderTemplate(Device *device_, + const std::string &shader_path, + ShaderStage force_stage_, + MetaCache &cache_, + Util::Hash path_hash_, + const std::vector &include_directories_) + : device(device_), path(shader_path), force_stage(force_stage_), cache(cache_), path_hash(path_hash_) +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + , include_directories(include_directories_) +#endif +{ + (void)include_directories_; +} + +ShaderTemplate::~ShaderTemplate() +{ +} + +bool ShaderTemplate::init() +{ + if (Granite::Path::ext(path) == "spv") + { + if (!device->get_system_handles().filesystem) + return false; + + auto precompiled_file = device->get_system_handles().filesystem->open_readonly_mapping(path); + const uint32_t *ptr; + + if (!precompiled_file || !(ptr = precompiled_file->data())) + { + LOGE("Failed to load shader: %s.\n", path.c_str()); + return false; + } + + static_shader = { ptr, ptr + precompiled_file->get_size() / sizeof(uint32_t) }; +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + source_hash = 0; +#endif + return true; + } + +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + if (!device->get_system_handles().filesystem) + return false; + + GRANITE_SCOPED_TIMELINE_EVENT_FILE(device->get_system_handles().timeline_trace_file, "glsl-preprocess"); + + compiler = std::make_unique(*device->get_system_handles().filesystem); + compiler->set_target(device->get_device_features().device_api_core_version >= VK_API_VERSION_1_3 ? + Granite::Target::Vulkan13 : Granite::Target::Vulkan11); + if (!compiler->set_source_from_file(path, Granite::Stage(force_stage))) + return false; + compiler->set_include_directories(&include_directories); + if (!compiler->preprocess()) + { + LOGE("Failed to pre-process shader: %s\n", path.c_str()); + compiler.reset(); + return false; + } + source_hash = compiler->get_source_hash(); +#endif + + return true; +} + +const ShaderTemplateVariant *ShaderTemplate::register_variant( + const std::vector> *defines, Shader *precompiled_shader) +{ + Hasher h; + if (defines) + { + // If we have a static shader, we cannot use defines since we won't be compiling anything. + VK_ASSERT(static_shader.empty() || defines->empty()); + + for (auto &define : *defines) + { + h.string(define.first); + h.s32(define.second); + } + } + + auto hash = h.get(); + h.u64(path_hash); + auto complete_hash = h.get(); + + auto *ret = variants.find(hash); + if (!ret) + { + auto *variant = variants.allocate(); + variant->hash = complete_hash; + + PrecomputedMeta *precompiled_spirv = nullptr; + if (!precompiled_shader) + { + precompiled_spirv = cache.variant_to_shader.find(complete_hash); + + if (precompiled_spirv) + { + if (!device->request_shader_by_hash(precompiled_spirv->shader_hash)) + { + LOGW("Got precompiled SPIR-V hash for variant (%016llx), but it does not exist, is Fossilize archive incomplete?\n", + static_cast(precompiled_spirv->shader_hash)); + precompiled_spirv = nullptr; + } +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + else if (source_hash != precompiled_spirv->source_hash) + { + LOGW("Source hash is invalidated for %s, recompiling.\n", path.c_str()); + precompiled_spirv = nullptr; + } +#endif + } + } + + if (precompiled_shader) + { + variant->precompiled_shader = precompiled_shader; + } + else if (!precompiled_spirv) + { + if (!static_shader.empty()) + { + variant->spirv = static_shader; +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + update_variant_cache(*variant); +#endif + } +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + else if (compiler) + { +#ifdef VULKAN_DEBUG + std::string hash_debug_str; + if (defines) + { + for (auto &def : *defines) + { + hash_debug_str += "\n"; + hash_debug_str += " "; + hash_debug_str += def.first; + hash_debug_str += " = "; + hash_debug_str += std::to_string(def.second); + } + hash_debug_str += "."; + } + LOGI("Compiling shader: %s%s\n", path.c_str(), hash_debug_str.c_str()); +#endif + + std::string error_message; + + { + GRANITE_SCOPED_TIMELINE_EVENT_FILE(device->get_system_handles().timeline_trace_file, + "glsl-compile"); + variant->spirv = compiler->compile(error_message, defines); + } + + if (variant->spirv.empty()) + { + LOGE("Shader error:\n%s\n", error_message.c_str()); + variants.free(variant); + return nullptr; + } + update_variant_cache(*variant); + } + else + return nullptr; +#else + LOGE("Could not find shader variant for %s in cache.\n", path.c_str()); + { + std::string str; + str += "["; + for (size_t i = 0, n = defines ? defines->size() : 0; i < n; i++) + { + str += "\n\t{ \"define\" : \"" + defines->operator[](i).first + "\", \"value\" : " + std::to_string(defines->operator[](i).second) + "}"; + if (i + 1 < n) + str += ","; + } + str += "\n]"; + LOGE("Slangmosh variant:\n%s\n", str.c_str()); + } + variants.free(variant); + return nullptr; +#endif + } + else + variant->spirv_hash = precompiled_spirv->shader_hash; + + variant->instance++; + if (defines) + variant->defines = *defines; + + ret = variants.insert_yield(hash, variant); + } + return ret; +} + +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER +#ifndef GRANITE_SHIPPING +void ShaderTemplate::recompile_variant(ShaderTemplateVariant &variant) +{ + std::string error_message; + auto newspirv = compiler->compile(error_message, &variant.defines); + if (newspirv.empty()) + { + LOGE("Failed to compile shader: %s\n%s\n", path.c_str(), error_message.c_str()); + for (auto &define : variant.defines) + LOGE(" Define: %s = %d\n", define.first.c_str(), define.second); + return; + } + + variant.spirv = std::move(newspirv); + variant.instance++; + update_variant_cache(variant); +} +#endif + +void ShaderTemplate::update_variant_cache(const ShaderTemplateVariant &variant) +{ + if (variant.spirv.empty()) + return; + + auto shader_hash = Shader::hash(variant.spirv.data(), + variant.spirv.size() * sizeof(uint32_t)); + + ResourceLayout layout; + Shader::reflect_resource_layout(layout, variant.spirv.data(), variant.spirv.size() * sizeof(uint32_t)); + +#ifndef GRANITE_SHIPPING + auto *var_to_shader = cache.variant_to_shader.find(variant.hash); + if (var_to_shader) + { + // This is only updated from inotify callbacks, so threading shouldn't really be a concern. + var_to_shader->source_hash = source_hash; + var_to_shader->shader_hash = shader_hash; + } + else +#endif + { + cache.variant_to_shader.emplace_yield(variant.hash, source_hash, shader_hash); + } + + cache.shader_to_layout.emplace_yield(shader_hash, layout); +} + +#ifndef GRANITE_SHIPPING +void ShaderTemplate::recompile() +{ + // Recompile all variants. + if (!device->get_system_handles().filesystem) + return; + auto newcompiler = std::make_unique(*device->get_system_handles().filesystem); + newcompiler->set_target(device->get_device_features().device_api_core_version >= VK_API_VERSION_1_3 ? + Granite::Target::Vulkan13 : Granite::Target::Vulkan11); + if (!newcompiler->set_source_from_file(path, Granite::Stage(force_stage))) + return; + newcompiler->set_include_directories(&include_directories); + if (!newcompiler->preprocess()) + { + LOGE("Failed to preprocess updated shader: %s\n", path.c_str()); + return; + } + compiler = std::move(newcompiler); + source_hash = compiler->get_source_hash(); + + for (auto &variant : variants.get_read_only()) + recompile_variant(variant); + for (auto &variant : variants.get_read_write()) + recompile_variant(variant); +} +#endif + +void ShaderTemplate::register_dependencies(ShaderManager &manager) +{ + if (compiler) + for (auto &dep : compiler->get_dependencies()) + manager.register_dependency_nolock(this, dep); +} +#endif + +void ShaderProgram::set_stage(Vulkan::ShaderStage stage, ShaderTemplate *shader) +{ + stages[static_cast(stage)] = shader; + VK_ASSERT(variant_cache.begin() == variant_cache.end()); +} + +ShaderProgramVariant::ShaderProgramVariant(Device *device_) + : device(device_) +{ +#ifndef GRANITE_SHIPPING + for (auto &inst : shader_instance) + inst.store(0, std::memory_order_relaxed); + program.store(nullptr, std::memory_order_relaxed); +#endif +} + +Vulkan::Shader *ShaderTemplateVariant::resolve(Vulkan::Device &device) const +{ + if (precompiled_shader) + return precompiled_shader; + else if (spirv.empty()) + return device.request_shader_by_hash(spirv_hash); + else + return device.request_shader(spirv.data(), spirv.size() * sizeof(uint32_t)); +} + +Vulkan::Program *ShaderProgramVariant::get_program_compute() +{ + Vulkan::Program *ret; + + auto *comp = stages[Util::ecast(Vulkan::ShaderStage::Compute)]; +#ifdef GRANITE_SHIPPING + ret = device->request_program(comp->resolve(*device), sampler_bank.get()); +#else + auto &comp_instance = shader_instance[Util::ecast(Vulkan::ShaderStage::Compute)]; + + // If we have observed all possible compilation instances, + // we can safely read program directly. + // comp->instance will only ever be incremented in the main thread on an inotify, so this is fine. + // If comp->instance changes in the interim, we are at least guaranteed to read a sensible value for program. + unsigned loaded_instance = comp_instance.load(std::memory_order_acquire); + if (loaded_instance == comp->instance) + return program.load(std::memory_order_relaxed); + + instance_lock.lock_write(); + if (comp_instance.load(std::memory_order_relaxed) != comp->instance) + { + ret = device->request_program(comp->resolve(*device), sampler_bank.get()); + program.store(ret, std::memory_order_relaxed); + comp_instance.store(comp->instance, std::memory_order_release); + } + else + { + ret = program.load(std::memory_order_relaxed); + } + instance_lock.unlock_write(); +#endif + + return ret; +} + +Vulkan::Program *ShaderProgramVariant::get_program_graphics() +{ + Vulkan::Program *ret; + auto *vert = stages[Util::ecast(Vulkan::ShaderStage::Vertex)]; + auto *mesh = stages[Util::ecast(Vulkan::ShaderStage::Mesh)]; + auto *task = stages[Util::ecast(Vulkan::ShaderStage::Task)]; + auto *frag = stages[Util::ecast(Vulkan::ShaderStage::Fragment)]; + +#ifdef GRANITE_SHIPPING + if (mesh && frag) + { + ret = device->request_program(task ? task->resolve(*device) : nullptr, + mesh->resolve(*device), + frag->resolve(*device), + sampler_bank.get()); + } + else if (vert && frag) + { + ret = device->request_program(vert->resolve(*device), + frag->resolve(*device), + sampler_bank.get()); + } + else + return nullptr; +#else + auto &vert_instance = shader_instance[Util::ecast(Vulkan::ShaderStage::Vertex)]; + auto &frag_instance = shader_instance[Util::ecast(Vulkan::ShaderStage::Fragment)]; + auto &mesh_instance = shader_instance[Util::ecast(Vulkan::ShaderStage::Mesh)]; + auto &task_instance = shader_instance[Util::ecast(Vulkan::ShaderStage::Task)]; + + unsigned loaded_vert_instance = vert_instance.load(std::memory_order_acquire); + unsigned loaded_mesh_instance = mesh_instance.load(std::memory_order_acquire); + unsigned loaded_task_instance = task_instance.load(std::memory_order_acquire); + unsigned loaded_frag_instance = frag_instance.load(std::memory_order_acquire); + + // If we have observed all possible compilation instances, + // we can safely read program directly. + // comp->instance will only ever be incremented in the main thread on an inotify, so this is fine. + // If comp->instance changes in the interim, we are at least guaranteed to read a sensible value for program. + if (mesh && frag) + { + if ((!task || (loaded_task_instance == task->instance)) && + loaded_mesh_instance == mesh->instance && + loaded_frag_instance == frag->instance) + { + return program.load(std::memory_order_relaxed); + } + } + else if (vert && frag) + { + if (loaded_vert_instance == vert->instance && loaded_frag_instance == frag->instance) + return program.load(std::memory_order_relaxed); + } + else + return nullptr; + + instance_lock.lock_write(); + + if (mesh) + { + if ((task && task_instance.load(std::memory_order_relaxed) != task->instance) || + mesh_instance.load(std::memory_order_relaxed) != mesh->instance || + frag_instance.load(std::memory_order_relaxed) != frag->instance) + { + ret = device->request_program(task ? task->resolve(*device) : nullptr, + mesh->resolve(*device), + frag->resolve(*device), + sampler_bank.get()); + program.store(ret, std::memory_order_relaxed); + if (task) + task_instance.store(task->instance, std::memory_order_release); + mesh_instance.store(mesh->instance, std::memory_order_release); + frag_instance.store(frag->instance, std::memory_order_release); + } + else + { + ret = program.load(std::memory_order_relaxed); + } + } + else + { + if (vert_instance.load(std::memory_order_relaxed) != vert->instance || + frag_instance.load(std::memory_order_relaxed) != frag->instance) + { + ret = device->request_program(vert->resolve(*device), + frag->resolve(*device), + sampler_bank.get()); + program.store(ret, std::memory_order_relaxed); + vert_instance.store(vert->instance, std::memory_order_release); + frag_instance.store(frag->instance, std::memory_order_release); + } + else + { + ret = program.load(std::memory_order_relaxed); + } + } + + instance_lock.unlock_write(); +#endif + + return ret; +} + +Vulkan::Program *ShaderProgramVariant::get_program() +{ + auto *frag = stages[static_cast(Vulkan::ShaderStage::Fragment)]; + auto *comp = stages[static_cast(Vulkan::ShaderStage::Compute)]; + + if (comp) + return get_program_compute(); + else if (frag) + return get_program_graphics(); + else + return nullptr; +} + +ShaderProgramVariant *ShaderProgram::register_variant(const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank) +{ + return register_variant(nullptr, defines, sampler_bank); +} + +ShaderProgramVariant *ShaderProgram::register_precompiled_variant(Shader *comp, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank) +{ + Shader *shaders[int(ShaderStage::Count)] = {}; + shaders[int(ShaderStage::Compute)] = comp; + return register_variant(shaders, defines, sampler_bank); +} + +ShaderProgramVariant *ShaderProgram::register_precompiled_variant(Shader *task, Shader *mesh, Shader *frag, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank) +{ + Shader *shaders[int(ShaderStage::Count)] = {}; + shaders[int(ShaderStage::Task)] = task; + shaders[int(ShaderStage::Mesh)] = mesh; + shaders[int(ShaderStage::Fragment)] = frag; + return register_variant(shaders, defines, sampler_bank); +} + +ShaderProgramVariant *ShaderProgram::register_precompiled_variant(Vulkan::Shader *vert, Vulkan::Shader *frag, + const std::vector> &defines, + const Vulkan::ImmutableSamplerBank *sampler_bank) +{ + Shader *shaders[int(ShaderStage::Count)] = {}; + shaders[int(ShaderStage::Vertex)] = vert; + shaders[int(ShaderStage::Fragment)] = frag; + return register_variant(shaders, defines, sampler_bank); +} + +ShaderProgramVariant *ShaderProgram::register_variant(Shader * const *precompiled_shaders, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank) +{ + Hasher h; + for (auto &define : defines) + { + h.string(define.first); + h.s32(define.second); + } + + ImmutableSamplerBank::hash(h, sampler_bank); + + auto hash = h.get(); + + if (auto *variant = variant_cache.find(hash)) + return variant; + + auto *new_variant = variant_cache.allocate(device); + if (sampler_bank) + new_variant->sampler_bank.reset(new ImmutableSamplerBank(*sampler_bank)); + + for (int i = 0; i < int(Vulkan::ShaderStage::Count); i++) + { + if (stages[i]) + { + new_variant->stages[i] = stages[i]->register_variant( + &defines, precompiled_shaders ? precompiled_shaders[i] : nullptr); + } + } + + // Make sure it's compiled correctly. + new_variant->get_program(); + + new_variant = variant_cache.insert_yield(hash, new_variant); + return new_variant; +} + +ShaderProgram *ShaderManager::register_compute(const std::string &compute) +{ + auto *tmpl = get_template(compute, ShaderStage::Compute); + if (!tmpl) + return nullptr; + + Util::Hasher h; + h.u64(tmpl->get_path_hash()); + auto hash = h.get(); + + auto *ret = programs.find(hash); + if (!ret) + ret = programs.emplace_yield(hash, device, tmpl); + return ret; +} + +ShaderTemplate *ShaderManager::get_template(const std::string &path, ShaderStage force_stage) +{ + Hasher hasher; + hasher.string(path); + auto hash = hasher.get(); + + auto *ret = shaders.find(hash); + if (!ret) + { + auto *shader = shaders.allocate(device, path, force_stage, + meta_cache, hasher.get(), include_directories); + if (!shader->init()) + { + shaders.free(shader); + return nullptr; + } + +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + { + DEPENDENCY_LOCK(); + register_dependency_nolock(shader, path); + shader->register_dependencies(*this); + } +#endif + ret = shaders.insert_yield(hash, shader); + } + return ret; +} + +ShaderProgram *ShaderManager::register_graphics(const std::string &vertex, const std::string &fragment) +{ + auto *vert_tmpl = get_template(vertex, ShaderStage::Vertex); + auto *frag_tmpl = get_template(fragment, ShaderStage::Fragment); + if (!vert_tmpl || !frag_tmpl) + return nullptr; + + Util::Hasher h; + h.u64(vert_tmpl->get_path_hash()); + h.u64(frag_tmpl->get_path_hash()); + auto hash = h.get(); + + auto *ret = programs.find(hash); + if (!ret) + ret = programs.emplace_yield(hash, device, vert_tmpl, frag_tmpl); + return ret; +} + +ShaderProgram *ShaderManager::register_graphics(const std::string &task, const std::string &mesh, const std::string &fragment) +{ + ShaderTemplate *task_tmpl = nullptr; + if (!task.empty()) + task_tmpl = get_template(task, ShaderStage::Task); + auto *mesh_tmpl = get_template(mesh, ShaderStage::Mesh); + auto *frag_tmpl = get_template(fragment, ShaderStage::Fragment); + if (!mesh_tmpl || !frag_tmpl) + return nullptr; + + Util::Hasher h; + h.u64(task_tmpl ? task_tmpl->get_path_hash() : 0); + h.u64(mesh_tmpl->get_path_hash()); + h.u64(frag_tmpl->get_path_hash()); + auto hash = h.get(); + + auto *ret = programs.find(hash); + if (!ret) + ret = programs.emplace_yield(hash, device, task_tmpl, mesh_tmpl, frag_tmpl); + return ret; +} + +ShaderManager::~ShaderManager() +{ +#if defined(GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER) && !defined(GRANITE_SHIPPING) + for (auto &dir : directory_watches) + if (dir.second.backend) + dir.second.backend->uninstall_notification(dir.second.handle); +#endif +} + +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER +void ShaderManager::register_dependency(ShaderTemplate *shader, const std::string &dependency) +{ + DEPENDENCY_LOCK(); + register_dependency_nolock(shader, dependency); +} + +void ShaderManager::register_dependency_nolock(ShaderTemplate *shader, const std::string &dependency) +{ + dependees[dependency].insert(shader); +#ifndef GRANITE_SHIPPING + add_directory_watch(dependency); +#endif +} + +#ifndef GRANITE_SHIPPING +void ShaderManager::recompile(const Granite::FileNotifyInfo &info) +{ + DEPENDENCY_LOCK(); + if (info.type == Granite::FileNotifyType::FileDeleted) + return; + + auto &deps = dependees[info.path]; + for (auto &dep : deps) + { + dep->recompile(); + dep->register_dependencies(*this); + } +} + +void ShaderManager::add_directory_watch(const std::string &source) +{ + if (!device->get_system_handles().filesystem) + return; + auto basedir = Granite::Path::basedir(source); + if (directory_watches.find(basedir) != end(directory_watches)) + return; + + auto paths = Granite::Path::protocol_split(basedir); + auto *backend = device->get_system_handles().filesystem->get_backend(paths.first); + if (!backend) + return; + + Granite::FileNotifyHandle handle = -1; + handle = backend->install_notification(paths.second, [this](const Granite::FileNotifyInfo &info) { + recompile(info); + }); + + if (handle >= 0) + directory_watches[basedir] = { backend, handle }; +} +#endif +#endif + +void ShaderManager::register_shader_from_variant_hash(Hash variant_hash, + Hash source_hash, + Hash shader_hash, + const ResourceLayout &layout) +{ + auto *var_to_shader = meta_cache.variant_to_shader.emplace_yield(variant_hash, source_hash, shader_hash); + if (var_to_shader->source_hash != source_hash || var_to_shader->shader_hash != shader_hash) + { + // Unsure if this function is even used, but I suppose we'll figure out ... + LOGW("Mismatch in register_shader_from_variant_hash.\n"); + } + meta_cache.shader_to_layout.emplace_yield(shader_hash, layout); +} + +bool ShaderManager::get_shader_hash_by_variant_hash(Hash variant_hash, Hash &shader_hash) const +{ + auto *shader = meta_cache.variant_to_shader.find(variant_hash); + if (shader) + { + shader_hash = shader->shader_hash; + return true; + } + else + return false; +} + +bool ShaderManager::get_resource_layout_by_shader_hash(Util::Hash shader_hash, ResourceLayout &layout) const +{ + auto *shader = meta_cache.shader_to_layout.find(shader_hash); + if (shader) + { + layout = shader->get(); + return true; + } + else + return false; +} + +void ShaderManager::add_include_directory(const std::string &path) +{ + if (find(begin(include_directories), end(include_directories), path) == end(include_directories)) + include_directories.push_back(path); +} + +void ShaderManager::promote_read_write_caches_to_read_only() +{ + shaders.move_to_read_only(); + programs.move_to_read_only(); + meta_cache.variant_to_shader.move_to_read_only(); + meta_cache.shader_to_layout.move_to_read_only(); +} + +static ResourceLayout parse_resource_layout(const rapidjson::Value &layout_obj) +{ + ResourceLayout layout; + + layout.bindless_set_mask = layout_obj["bindlessSetMask"].GetUint(); + layout.input_mask = layout_obj["inputMask"].GetUint(); + layout.output_mask = layout_obj["outputMask"].GetUint(); + layout.push_constant_size = layout_obj["pushConstantSize"].GetUint(); + layout.spec_constant_mask = layout_obj["specConstantMask"].GetUint(); + + for (unsigned i = 0; i < VULKAN_NUM_DESCRIPTOR_SETS; i++) + { + auto &set_obj = layout_obj["sets"][i]; + auto &set = layout.sets[i]; + set.uniform_buffer_mask = set_obj["uniformBufferMask"].GetUint(); + set.storage_buffer_mask = set_obj["storageBufferMask"].GetUint(); + if (set_obj.HasMember("rtasMask")) + set.rtas_mask = set_obj["rtasMask"].GetUint(); + set.sampled_texel_buffer_mask = set_obj["sampledTexelBufferMask"].GetUint(); + set.storage_texel_buffer_mask = set_obj["storageTexelBufferMask"].GetUint(); + set.sampled_image_mask = set_obj["sampledImageMask"].GetUint(); + set.storage_image_mask = set_obj["storageImageMask"].GetUint(); + set.separate_image_mask = set_obj["separateImageMask"].GetUint(); + set.sampler_mask = set_obj["samplerMask"].GetUint(); + set.input_attachment_mask = set_obj["inputAttachmentMask"].GetUint(); + set.fp_mask = set_obj["fpMask"].GetUint(); + auto &array_size = set_obj["arraySize"]; + auto &req_desc_size = set_obj["requiresDescriptorSize"]; + for (unsigned j = 0; j < VULKAN_NUM_BINDINGS; j++) + set.meta[j].array_size = array_size[j].GetUint(); + for (unsigned j = 0; j < VULKAN_NUM_BINDINGS; j++) + set.meta[j].requires_descriptor_size = req_desc_size[j].GetUint(); + } + + return layout; +} + +template +static rapidjson::Value serialize_resource_layout(const ResourceLayout &layout, Alloc &allocator) +{ + using namespace rapidjson; + + Value layout_obj(kObjectType); + layout_obj.AddMember("bindlessSetMask", layout.bindless_set_mask, allocator); + layout_obj.AddMember("inputMask", layout.input_mask, allocator); + layout_obj.AddMember("outputMask", layout.output_mask, allocator); + layout_obj.AddMember("pushConstantSize", layout.push_constant_size, allocator); + layout_obj.AddMember("specConstantMask", layout.spec_constant_mask, allocator); + Value desc_sets(kArrayType); + for (auto &set : layout.sets) + { + Value set_obj(kObjectType); + set_obj.AddMember("uniformBufferMask", set.uniform_buffer_mask, allocator); + set_obj.AddMember("storageBufferMask", set.storage_buffer_mask, allocator); + set_obj.AddMember("rtasMask", set.rtas_mask, allocator); + set_obj.AddMember("sampledTexelBufferMask", set.sampled_texel_buffer_mask, allocator); + set_obj.AddMember("storageTexelBufferMask", set.storage_texel_buffer_mask, allocator); + set_obj.AddMember("sampledImageMask", set.sampled_image_mask, allocator); + set_obj.AddMember("storageImageMask", set.storage_image_mask, allocator); + set_obj.AddMember("separateImageMask", set.separate_image_mask, allocator); + set_obj.AddMember("samplerMask", set.sampler_mask, allocator); + set_obj.AddMember("inputAttachmentMask", set.input_attachment_mask, allocator); + set_obj.AddMember("fpMask", set.fp_mask, allocator); + Value array_size(kArrayType); + Value req_desc_size(kArrayType); + for (auto &meta : set.meta) + { + array_size.PushBack(uint32_t(meta.array_size), allocator); + req_desc_size.PushBack(uint32_t(meta.requires_descriptor_size), allocator); + } + set_obj.AddMember("arraySize", array_size, allocator); + set_obj.AddMember("requiresDescriptorSize", req_desc_size, allocator); + desc_sets.PushBack(set_obj, allocator); + } + layout_obj.AddMember("sets", desc_sets, allocator); + return layout_obj; +} + +bool ShaderManager::load_shader_cache(const std::string &path, Granite::TaskGroup *shader_compilation_group) +{ + if (!device->get_system_handles().filesystem) + return false; + + using namespace rapidjson; + std::string json; + if (!device->get_system_handles().filesystem->read_file_to_string(path, json)) + return false; + + Document doc; + doc.Parse(json); + if (doc.HasParseError()) + { + LOGE("Failed to parse shader cache format!\n"); + return false; + } + + if (!doc.HasMember("shaderCacheVersion")) + { + LOGE("Member shaderCacheVersion does not exist.\n"); + return false; + } + + unsigned version = doc["shaderCacheVersion"].GetUint(); + if (version != ResourceLayout::Version) + { + LOGE("Incompatible shader cache version %u != %u.\n", version, ResourceLayout::Version); + return false; + } + + auto &maps = doc["maps"]; + for (auto itr = maps.Begin(); itr != maps.End(); ++itr) + { + auto &value = *itr; + + Util::Hash variant_hash = value["variant"].GetUint64(); + Util::Hash spirv_hash = value["spirvHash"].GetUint64(); + Util::Hash source_hash = value["sourceHash"].GetUint64(); + ResourceLayout layout = parse_resource_layout(value["layout"]); + meta_cache.variant_to_shader.emplace_yield(variant_hash, source_hash, spirv_hash); + meta_cache.shader_to_layout.emplace_yield(spirv_hash, layout); + } + + if (shader_compilation_group && doc.HasMember("shaders")) + { + auto &parsed_shaders = doc["shaders"]; + for (auto itr = parsed_shaders.Begin(); itr != parsed_shaders.End(); ++itr) + { + auto &shader = *itr; + + std::string shader_path = shader["path"].GetString(); + if (Granite::Path::ext(shader_path) == "spv") + continue; + + auto shader_stage = ShaderStage(shader["stage"].GetUint()); + + auto *thread_group = shader_compilation_group->get_thread_group(); + + // Workaround capture size. + auto shader_path_ptr = std::make_shared(shader_path); + + // Prime it alone to avoid racing hashmap inserts. + auto glsl_parse_task = thread_group->create_task([this, shader_path_ptr, shader_stage]() -> void + { + get_template(*shader_path_ptr, shader_stage); + }); + glsl_parse_task->set_desc("glsl-parse-task"); + + LOGI("Queueing shader variants for: %s\n", shader_path.c_str()); + + auto &variants = shader["variants"]; + for (auto variant_itr = variants.Begin(); variant_itr != variants.End(); ++variant_itr) + { + auto &variant = *variant_itr; + std::vector> defines; + for (auto define_itr = variant.Begin(); define_itr != variant.End(); ++define_itr) + defines.emplace_back((*define_itr)["define"].GetString(), (*define_itr)["value"].GetInt()); + + struct TaskPayload + { + std::string path; + ShaderStage stage; + std::vector> defines; + }; + + auto payload = std::make_unique(); + payload->path = shader_path; + payload->stage = shader_stage; + payload->defines = std::move(defines); + + shader_compilation_group->enqueue_task([this, payload = std::move(payload)]() + { + // This is fairly efficient on its own, no need to go wide, since it's mostly just IO. + auto *templ = get_template(payload->path, payload->stage); + if (templ) + templ->register_variant(&payload->defines, nullptr); + }); + + thread_group->add_dependency(*shader_compilation_group, *glsl_parse_task); + } + } + } + + LOGI("Loaded shader manager cache from %s.\n", path.c_str()); + return true; +} + +bool ShaderManager::save_shader_cache(const std::string &path) +{ + if (!device->get_system_handles().filesystem) + return false; + + using namespace rapidjson; + Document doc; + doc.SetObject(); + auto &allocator = doc.GetAllocator(); + doc.AddMember("shaderCacheVersion", uint32_t(ResourceLayout::Version), allocator); + + Value maps(kArrayType); + + meta_cache.variant_to_shader.move_to_read_only(); + auto &var_to_shader = meta_cache.variant_to_shader.get_read_only(); + + for (auto &entry : var_to_shader) + { + Value map_entry(kObjectType); + map_entry.AddMember("variant", entry.get_hash(), allocator); + map_entry.AddMember("spirvHash", entry.shader_hash, allocator); + map_entry.AddMember("sourceHash", entry.source_hash, allocator); + + ResourceLayout layout; + if (get_resource_layout_by_shader_hash(entry.shader_hash, layout)) + { + Value layout_obj = serialize_resource_layout(layout, allocator); + map_entry.AddMember("layout", layout_obj, allocator); + } + else + LOGE("Failed to lookup resource reflection result. This shouldn't happen ...\n"); + + maps.PushBack(map_entry, allocator); + } + + doc.AddMember("maps", maps, allocator); + + Value compiled_shaders(kArrayType); + + shaders.move_to_read_only(); + for (auto &entry : shaders.get_read_only()) + { + Value shader(kObjectType); + Value variants(kArrayType); + shader.AddMember("path", entry.get_path(), allocator); + shader.AddMember("stage", int(entry.get_stage()), allocator); + + entry.get_variants().move_to_read_only(); + for (auto &var : entry.get_variants().get_read_only()) + { + Value defines(kArrayType); + for (auto &def : var.defines) + { + Value define_value_pair(kObjectType); + define_value_pair.AddMember("define", def.first, allocator); + define_value_pair.AddMember("value", def.second, allocator); + defines.PushBack(define_value_pair, allocator); + } + + variants.PushBack(defines, allocator); + } + + shader.AddMember("variants", variants, allocator); + compiled_shaders.PushBack(shader, allocator); + } + + doc.AddMember("shaders", compiled_shaders, allocator); + + StringBuffer buffer; + Writer writer(buffer); + doc.Accept(writer); + + if (!device->get_system_handles().filesystem->write_buffer_to_file(path, buffer.GetString(), buffer.GetSize())) + { + LOGE("Failed to open %s for writing.\n", path.c_str()); + return false; + } + else + LOGI("Saved shader manager cache to %s.\n", path.c_str()); + + return true; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/shader_manager.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/shader_manager.hpp new file mode 100644 index 00000000..0810fc17 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/managers/shader_manager.hpp @@ -0,0 +1,277 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "shader.hpp" +#include "vulkan_common.hpp" +#include "filesystem.hpp" +#include +#include +#include +#include +#include +#include "hash.hpp" +#include "read_write_lock.hpp" + +namespace Granite +{ +class GLSLCompiler; +struct TaskGroup; +enum class Stage; +} + +namespace Vulkan +{ +struct ShaderTemplateVariant; +struct PrecomputedMeta : Util::IntrusiveHashMapEnabled +{ + PrecomputedMeta(Util::Hash source_hash_, Util::Hash shader_hash_) + : source_hash(source_hash_), shader_hash(shader_hash_) + { + } + Util::Hash source_hash; + Util::Hash shader_hash; +}; +using PrecomputedShaderCache = VulkanCache; +using ReflectionCache = VulkanCache>; + +struct MetaCache +{ + PrecomputedShaderCache variant_to_shader; + ReflectionCache shader_to_layout; +}; + +class ShaderManager; +class Device; + +struct ShaderTemplateVariant : public Util::IntrusiveHashMapEnabled +{ + Util::Hash hash = 0; + Util::Hash spirv_hash = 0; + std::vector spirv; + std::vector> defines; + Shader *precompiled_shader = nullptr; + unsigned instance = 0; + + Vulkan::Shader *resolve(Vulkan::Device &device) const; +}; + +class ShaderTemplate : public Util::IntrusiveHashMapEnabled +{ +public: + ShaderTemplate(Device *device, const std::string &shader_path, + ShaderStage force_stage, MetaCache &cache, + Util::Hash path_hash, const std::vector &include_directories); + ~ShaderTemplate(); + + bool init(); + + const ShaderTemplateVariant *register_variant(const std::vector> *defines, + Shader *precompiled_shader); + void register_dependencies(ShaderManager &manager); + + Util::Hash get_path_hash() const + { + return path_hash; + } + + const std::string &get_path() const + { + return path; + } + + ShaderStage get_stage() const + { + return force_stage; + } + + VulkanCache &get_variants() + { + return variants; + } + +#ifndef GRANITE_SHIPPING + // We'll never want to recompile shaders in runtime outside a dev environment. + void recompile(); +#endif + +private: + Device *device; + std::string path; + ShaderStage force_stage; + MetaCache &cache; + Util::Hash path_hash = 0; + std::vector static_shader; +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + std::unique_ptr compiler; + const std::vector &include_directories; + void update_variant_cache(const ShaderTemplateVariant &variant); + Util::Hash source_hash = 0; +#ifndef GRANITE_SHIPPING + // We'll never want to recompile shaders in runtime outside a dev environment. + void recompile_variant(ShaderTemplateVariant &variant); +#endif +#endif + VulkanCache variants; +}; + +class ShaderProgramVariant : public Util::IntrusiveHashMapEnabled +{ +public: + explicit ShaderProgramVariant(Device *device); + Vulkan::Program *get_program(); + +private: + friend class ShaderProgram; + Device *device; + const ShaderTemplateVariant *stages[static_cast(Vulkan::ShaderStage::Count)] = {}; + std::unique_ptr sampler_bank; + +#ifndef GRANITE_SHIPPING + // We'll never want to recompile shaders in runtime outside a dev environment. + std::atomic_uint shader_instance[static_cast(Vulkan::ShaderStage::Count)]; + std::atomic program; + Util::RWSpinLock instance_lock; +#endif + + Vulkan::Program *get_program_compute(); + Vulkan::Program *get_program_graphics(); +}; + +class ShaderProgram : public Util::IntrusiveHashMapEnabled +{ +public: + ShaderProgram(Device *device_, ShaderTemplate *compute) + : device(device_) + { + set_stage(Vulkan::ShaderStage::Compute, compute); + } + + ShaderProgram(Device *device_, ShaderTemplate *vert, ShaderTemplate *frag) + : device(device_) + { + set_stage(Vulkan::ShaderStage::Vertex, vert); + set_stage(Vulkan::ShaderStage::Fragment, frag); + } + + ShaderProgram(Device *device_, ShaderTemplate *task, ShaderTemplate *mesh, ShaderTemplate *frag) + : device(device_) + { + if (task) + set_stage(Vulkan::ShaderStage::Task, task); + set_stage(Vulkan::ShaderStage::Mesh, mesh); + set_stage(Vulkan::ShaderStage::Fragment, frag); + } + + void set_stage(Vulkan::ShaderStage stage, ShaderTemplate *shader); + ShaderProgramVariant *register_variant(const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank = nullptr); + + ShaderProgramVariant *register_precompiled_variant( + Shader *vert, Shader *frag, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank = nullptr); + + ShaderProgramVariant *register_precompiled_variant( + Shader *comp, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank = nullptr); + + ShaderProgramVariant *register_precompiled_variant( + Shader *task, Shader *mesh, Shader *frag, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank = nullptr); + +private: + Device *device; + ShaderTemplate *stages[static_cast(Vulkan::ShaderStage::Count)] = {}; + VulkanCacheReadWrite variant_cache; + + ShaderProgramVariant *register_variant(Shader * const *precompiled_shaders, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank); +}; + +class ShaderManager +{ +public: + explicit ShaderManager(Device *device_) + : device(device_) + { + } + + bool load_shader_cache(const std::string &path, Granite::TaskGroup *shader_compilation_group); + bool save_shader_cache(const std::string &path); + + void add_include_directory(const std::string &path); + + ~ShaderManager(); + ShaderProgram *register_graphics(const std::string &task, const std::string &mesh, const std::string &fragment); + ShaderProgram *register_graphics(const std::string &vertex, const std::string &fragment); + ShaderProgram *register_compute(const std::string &compute); + +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + void register_dependency(ShaderTemplate *shader, const std::string &dependency); + void register_dependency_nolock(ShaderTemplate *shader, const std::string &dependency); +#endif + + bool get_shader_hash_by_variant_hash(Util::Hash variant_hash, Util::Hash &shader_hash) const; + bool get_resource_layout_by_shader_hash(Util::Hash shader_hash, ResourceLayout &layout) const; + void register_shader_from_variant_hash(Util::Hash variant_hash, Util::Hash source_hash, + Util::Hash shader_hash, const ResourceLayout &layout); + + Device *get_device() + { + return device; + } + + void promote_read_write_caches_to_read_only(); + +private: + Device *device; + + MetaCache meta_cache; + VulkanCache shaders; + VulkanCache programs; + std::vector include_directories; + + ShaderTemplate *get_template(const std::string &source, ShaderStage force_stage); + +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER + std::unordered_map> dependees; + std::mutex dependency_lock; + +#ifndef GRANITE_SHIPPING + // We'll never want to recompile shaders in runtime outside a dev environment. + struct Notify + { + Granite::FilesystemBackend *backend; + Granite::FileNotifyHandle handle; + }; + std::unordered_map directory_watches; + void add_directory_watch(const std::string &source); + void recompile(const Granite::FileNotifyInfo &info); +#endif +#endif +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/memory_allocator.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/memory_allocator.cpp new file mode 100644 index 00000000..f33bdac3 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/memory_allocator.cpp @@ -0,0 +1,1602 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "memory_allocator.hpp" +#include "timeline_trace_file.hpp" +#include "device.hpp" +#include + +#ifndef _WIN32 +#include +#else +#define WIN32_LEAN_AND_MEAN +#include +#endif + +namespace Vulkan +{ +static bool allocation_mode_supports_bda(AllocationMode mode) +{ + switch (mode) + { + case AllocationMode::LinearDevice: + case AllocationMode::LinearHostMappable: + case AllocationMode::LinearDeviceHighPriority: + return true; + + default: + break; + } + + return false; +} + +void DeviceAllocation::free_immediate() +{ + if (!alloc) + return; + + alloc->free(heap, mask); + alloc = nullptr; + base = VK_NULL_HANDLE; + mask = 0; + offset = 0; +} + +ExternalHandle DeviceAllocation::export_handle(Device &device) +{ + ExternalHandle h; + + if (exportable_types == 0) + { + LOGE("Cannot export from this allocation.\n"); + return h; + } + + auto &table = device.get_device_table(); + +#ifdef _WIN32 + VkMemoryGetWin32HandleInfoKHR handle_info = { VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR }; + handle_info.handleType = static_cast(exportable_types); + handle_info.memory = base; + h.memory_handle_type = handle_info.handleType; + + if (table.vkGetMemoryWin32HandleKHR(device.get_device(), &handle_info, &h.handle) != VK_SUCCESS) + { + LOGE("Failed to export memory handle.\n"); + h.handle = nullptr; + } +#else + VkMemoryGetFdInfoKHR fd_info = { VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR }; + fd_info.handleType = static_cast(exportable_types); + fd_info.memory = base; + h.memory_handle_type = fd_info.handleType; + + if (table.vkGetMemoryFdKHR(device.get_device(), &fd_info, &h.handle) != VK_SUCCESS) + { + LOGE("Failed to export memory handle.\n"); + h.handle = -1; + } +#endif + + return h; +} + +void DeviceAllocation::free_immediate(DeviceAllocator &allocator) +{ + if (alloc) + free_immediate(); + else if (base) + { + allocator.internal_free_no_recycle(size, memory_type, base); + base = VK_NULL_HANDLE; + } +} + +void DeviceAllocation::free_global(DeviceAllocator &allocator, uint32_t size_, uint32_t memory_type_) +{ + if (base) + { + allocator.internal_free(size_, memory_type_, mode, base, host_base != nullptr); + base = VK_NULL_HANDLE; + mask = 0; + offset = 0; + } +} + +void ClassAllocator::prepare_allocation(DeviceAllocation *alloc, Util::IntrusiveList::Iterator heap_itr, + const Util::SuballocationResult &suballoc) +{ + auto &heap = *heap_itr; + alloc->heap = heap_itr; + alloc->base = heap.allocation.base; + alloc->offset = suballoc.offset + heap.allocation.offset; + alloc->mask = suballoc.mask; + alloc->size = suballoc.size; + + if (heap.allocation.host_base) + alloc->host_base = heap.allocation.host_base + suballoc.offset; + + VK_ASSERT(heap.allocation.mode == global_allocator_mode); + VK_ASSERT(heap.allocation.memory_type == memory_type); + + alloc->mode = global_allocator_mode; + alloc->memory_type = memory_type; + alloc->alloc = this; +} + +static inline bool mode_request_host_mapping(AllocationMode mode) +{ + // LinearHostMapping will always work. LinearDevice ones will speculatively work on UMA. + return mode == AllocationMode::LinearHostMappable || + mode == AllocationMode::LinearDevice || + mode == AllocationMode::LinearDeviceHighPriority; +} + +bool ClassAllocator::allocate_backing_heap(DeviceAllocation *alloc) +{ + uint32_t alloc_size = sub_block_size * Util::LegionAllocator::NumSubBlocks; + + if (parent) + { + return parent->allocate(alloc_size, alloc); + } + else + { + alloc->offset = 0; + alloc->host_base = nullptr; + alloc->mode = global_allocator_mode; + alloc->memory_type = memory_type; + + return global_allocator->internal_allocate( + alloc_size, memory_type, global_allocator_mode, &alloc->base, + mode_request_host_mapping(global_allocator_mode) ? &alloc->host_base : nullptr, + VK_OBJECT_TYPE_DEVICE, 0, nullptr); + } +} + +void ClassAllocator::free_backing_heap(DeviceAllocation *allocation) +{ + assert(allocation->mode == global_allocator_mode); + assert(allocation->memory_type == memory_type); + + // Our mini-heap is completely freed, free to higher level allocator. + if (parent) + allocation->free_immediate(); + else + allocation->free_global(*global_allocator, sub_block_size * Util::LegionAllocator::NumSubBlocks, memory_type); +} + +bool Allocator::allocate_global(uint32_t size, AllocationMode mode, DeviceAllocation *alloc) +{ + // Fall back to global allocation, do not recycle. + alloc->host_base = nullptr; + if (!global_allocator->internal_allocate( + size, memory_type, mode, &alloc->base, + mode_request_host_mapping(mode) ? &alloc->host_base : nullptr, + VK_OBJECT_TYPE_DEVICE, 0, nullptr)) + { + return false; + } + + alloc->mode = mode; + alloc->alloc = nullptr; + alloc->memory_type = memory_type; + alloc->size = size; + return true; +} + +bool Allocator::allocate_dedicated(uint32_t size, AllocationMode mode, DeviceAllocation *alloc, + VkObjectType type, uint64_t object, ExternalHandle *external) +{ + // Fall back to global allocation, do not recycle. + alloc->host_base = nullptr; + if (!global_allocator->internal_allocate( + size, memory_type, mode, &alloc->base, + mode_request_host_mapping(mode) ? &alloc->host_base : nullptr, + type, object, external)) + { + return false; + } + + alloc->mode = mode; + alloc->alloc = nullptr; + alloc->memory_type = memory_type; + alloc->size = size; + + // If we imported memory instead, do not allow handle export. + if (external && !(*external)) + alloc->exportable_types = external->memory_handle_type; + + return true; +} + +DeviceAllocation DeviceAllocation::make_imported_allocation(VkDeviceMemory memory, VkDeviceSize size, + uint32_t memory_type) +{ + DeviceAllocation alloc = {}; + alloc.base = memory; + alloc.offset = 0; + alloc.size = size; + alloc.memory_type = memory_type; + return alloc; +} + +bool Allocator::allocate(uint32_t size, uint32_t alignment, AllocationMode mode, DeviceAllocation *alloc) +{ + for (auto &c : classes) + { + auto &suballocator = c[unsigned(mode)]; + + // Find a suitable class to allocate from. + if (size <= suballocator.get_max_allocation_size()) + { + if (alignment > suballocator.get_block_alignment()) + { + size_t padded_size = size + (alignment - suballocator.get_block_alignment()); + if (padded_size <= suballocator.get_max_allocation_size()) + size = padded_size; + else + continue; + } + + bool ret = suballocator.allocate(size, alloc); + if (ret) + { + uint32_t aligned_offset = (alloc->offset + alignment - 1) & ~(alignment - 1); + if (alloc->host_base) + alloc->host_base += aligned_offset - alloc->offset; + alloc->offset = aligned_offset; + VK_ASSERT(alloc->mode == mode); + VK_ASSERT(alloc->memory_type == memory_type); + } + + return ret; + } + } + + if (!allocate_global(size, mode, alloc)) + return false; + + VK_ASSERT(alloc->mode == mode); + VK_ASSERT(alloc->memory_type == memory_type); + return true; +} + +Allocator::Allocator(Util::ObjectPool &object_pool) +{ + for (int i = 0; i < Util::ecast(MemoryClass::Count) - 1; i++) + for (int j = 0; j < Util::ecast(AllocationMode::Count); j++) + classes[i][j].set_parent(&classes[i + 1][j]); + + for (auto &c : classes) + for (auto &m : c) + m.set_object_pool(&object_pool); + + for (int j = 0; j < Util::ecast(AllocationMode::Count); j++) + { + auto mode = static_cast(j); + + // 128 chunk + get_class_allocator(MemoryClass::Small, mode).set_sub_block_size(128); + // 4k chunk + get_class_allocator(MemoryClass::Medium, mode).set_sub_block_size( + 128 * Util::LegionAllocator::NumSubBlocks); // 4K + // 128k chunk + get_class_allocator(MemoryClass::Large, mode).set_sub_block_size( + 128 * Util::LegionAllocator::NumSubBlocks * + Util::LegionAllocator::NumSubBlocks); + // 2M chunk + get_class_allocator(MemoryClass::Huge, mode).set_sub_block_size( + 64 * Util::LegionAllocator::NumSubBlocks * Util::LegionAllocator::NumSubBlocks * + Util::LegionAllocator::NumSubBlocks); + } +} + +void DeviceAllocator::init(Device *device_) +{ + device = device_; + table = &device->get_device_table(); + mem_props = device->get_memory_properties(); + const auto &props = device->get_gpu_properties(); + atom_alignment = props.limits.nonCoherentAtomSize; + + heaps.clear(); + allocators.clear(); + + heaps.resize(mem_props.memoryHeapCount); + allocators.reserve(mem_props.memoryTypeCount); + for (unsigned i = 0; i < mem_props.memoryTypeCount; i++) + { + allocators.emplace_back(new Allocator(object_pool)); + allocators.back()->set_global_allocator(this, i); + } + + HeapBudget budgets[VK_MAX_MEMORY_HEAPS]; + get_memory_budget(budgets); + + // Figure out if we have a PCI-e BAR heap. + // We need to be very careful with our budget (usually 128 MiB out of 256 MiB) on these heaps + // since they can lead to instability if overused. + VkMemoryPropertyFlags combined_allowed_flags[VK_MAX_MEMORY_HEAPS] = {}; + for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) + { + uint32_t heap_index = mem_props.memoryTypes[i].heapIndex; + combined_allowed_flags[heap_index] |= mem_props.memoryTypes[i].propertyFlags; + } + + bool has_host_only_heap = false; + bool has_device_only_heap = false; + VkDeviceSize host_heap_size = 0; + VkDeviceSize device_heap_size = 0; + const VkMemoryPropertyFlags pinned_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + for (uint32_t i = 0; i < mem_props.memoryHeapCount; i++) + { + if ((combined_allowed_flags[i] & pinned_flags) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + { + has_host_only_heap = true; + host_heap_size = (std::max)(host_heap_size, mem_props.memoryHeaps[i].size); + } + else if ((combined_allowed_flags[i] & pinned_flags) == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + { + has_device_only_heap = true; + device_heap_size = (std::max)(device_heap_size, mem_props.memoryHeaps[i].size); + } + } + + // If we have ReBAR enabled, we generally won't find DEVICE only and HOST only heaps. + // Budget criticalness should only be considered if we have the default small BAR heap (256 MiB). + if (has_host_only_heap && has_device_only_heap) + { + for (uint32_t i = 0; i < mem_props.memoryHeapCount; i++) + { + if ((combined_allowed_flags[i] & pinned_flags) == pinned_flags && + mem_props.memoryHeaps[i].size < host_heap_size && + mem_props.memoryHeaps[i].size < device_heap_size) + { + memory_heap_is_budget_critical[i] = true; + } + } + } +} + +bool DeviceAllocator::allocate_generic_memory(uint32_t size, uint32_t alignment, AllocationMode mode, + uint32_t memory_type, DeviceAllocation *alloc) +{ + return allocators[memory_type]->allocate(size, alignment, mode, alloc); +} + +bool DeviceAllocator::allocate_buffer_memory(uint32_t size, uint32_t alignment, AllocationMode mode, + uint32_t memory_type, VkBuffer buffer, + DeviceAllocation *alloc, ExternalHandle *external) +{ + if (mode == AllocationMode::External) + { + return allocators[memory_type]->allocate_dedicated( + size, mode, alloc, + VK_OBJECT_TYPE_BUFFER, (uint64_t)buffer, external); + } + else + { + return allocate_generic_memory(size, alignment, mode, memory_type, alloc); + } +} + +bool DeviceAllocator::allocate_image_memory(uint32_t size, uint32_t alignment, AllocationMode mode, uint32_t memory_type, + VkImage image, bool force_no_dedicated, DeviceAllocation *alloc, + ExternalHandle *external) +{ + if (force_no_dedicated) + { + VK_ASSERT(mode != AllocationMode::External && !external); + return allocate_generic_memory(size, alignment, mode, memory_type, alloc); + } + + VkImageMemoryRequirementsInfo2 info = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 }; + info.image = image; + + VkMemoryDedicatedRequirements dedicated_req = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS }; + VkMemoryRequirements2 mem_req = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 }; + mem_req.pNext = &dedicated_req; + table->vkGetImageMemoryRequirements2(device->get_device(), &info, &mem_req); + + if (dedicated_req.prefersDedicatedAllocation || + dedicated_req.requiresDedicatedAllocation || + mode == AllocationMode::External) + { + return allocators[memory_type]->allocate_dedicated( + size, mode, alloc, VK_OBJECT_TYPE_IMAGE, (uint64_t)image, external); + } + else + { + return allocate_generic_memory(size, alignment, mode, memory_type, alloc); + } +} + +void DeviceAllocator::Heap::garbage_collect(Device *device_) +{ + auto &table_ = device_->get_device_table(); + for (auto &block : blocks) + { + table_.vkFreeMemory(device_->get_device(), block.memory, nullptr); + size -= block.size; + } + blocks.clear(); +} + +DeviceAllocator::~DeviceAllocator() +{ + for (auto &heap : heaps) + heap.garbage_collect(device); +} + +void DeviceAllocator::internal_free(uint32_t size, uint32_t memory_type, AllocationMode mode, VkDeviceMemory memory, bool is_mapped) +{ + if (is_mapped) + table->vkUnmapMemory(device->get_device(), memory); + + auto &heap = heaps[mem_props.memoryTypes[memory_type].heapIndex]; + + VK_ASSERT(mode != AllocationMode::Count); + + heap.blocks.push_back({ memory, size, memory_type, mode }); + if (memory_heap_is_budget_critical[mem_props.memoryTypes[memory_type].heapIndex]) + heap.garbage_collect(device); +} + +void DeviceAllocator::internal_free_no_recycle(uint32_t size, uint32_t memory_type, VkDeviceMemory memory) +{ + auto &heap = heaps[mem_props.memoryTypes[memory_type].heapIndex]; + table->vkFreeMemory(device->get_device(), memory, nullptr); + heap.size -= size; +} + +void DeviceAllocator::garbage_collect() +{ + for (auto &heap : heaps) + heap.garbage_collect(device); +} + +void *DeviceAllocator::map_memory(const DeviceAllocation &alloc, MemoryAccessFlags flags, + VkDeviceSize offset, VkDeviceSize length) +{ + VkDeviceSize base_offset = offset; + + // This will only happen if the memory type is device local only, which we cannot possibly map. + if (!alloc.host_base) + return nullptr; + + if ((flags & MEMORY_ACCESS_READ_BIT) && + !(mem_props.memoryTypes[alloc.memory_type].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) + { + offset += alloc.offset; + VkDeviceSize end_offset = offset + length; + offset &= ~(atom_alignment - 1); + length = end_offset - offset; + VkDeviceSize size = (length + atom_alignment - 1) & ~(atom_alignment - 1); + + // Have to invalidate cache here. + const VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, nullptr, alloc.base, offset, size, + }; + table->vkInvalidateMappedMemoryRanges(device->get_device(), 1, &range); + } + + return alloc.host_base + base_offset; +} + +void DeviceAllocator::unmap_memory(const DeviceAllocation &alloc, MemoryAccessFlags flags, + VkDeviceSize offset, VkDeviceSize length) +{ + // This will only happen if the memory type is device local only, which we cannot possibly map. + if (!alloc.host_base) + return; + + if ((flags & MEMORY_ACCESS_WRITE_BIT) && + !(mem_props.memoryTypes[alloc.memory_type].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) + { + offset += alloc.offset; + VkDeviceSize end_offset = offset + length; + offset &= ~(atom_alignment - 1); + length = end_offset - offset; + VkDeviceSize size = (length + atom_alignment - 1) & ~(atom_alignment - 1); + + // Have to flush caches here. + const VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, nullptr, alloc.base, offset, size, + }; + table->vkFlushMappedMemoryRanges(device->get_device(), 1, &range); + } +} + +void DeviceAllocator::get_memory_budget_nolock(HeapBudget *heap_budgets) +{ + uint32_t num_heaps = mem_props.memoryHeapCount; + + if (device->get_device_features().supports_memory_budget) + { + VkPhysicalDeviceMemoryProperties2 props = + { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 }; + VkPhysicalDeviceMemoryBudgetPropertiesEXT budget_props = + { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT }; + + if (device->get_device_features().supports_memory_budget) + props.pNext = &budget_props; + + vkGetPhysicalDeviceMemoryProperties2(device->get_physical_device(), &props); + + for (uint32_t i = 0; i < num_heaps; i++) + { + auto &heap = heap_budgets[i]; + heap.max_size = mem_props.memoryHeaps[i].size; + heap.budget_size = budget_props.heapBudget[i]; + heap.device_usage = budget_props.heapUsage[i]; + heap.tracked_usage = heaps[i].size; + } + } + else + { + for (uint32_t i = 0; i < num_heaps; i++) + { + auto &heap = heap_budgets[i]; + heap.max_size = mem_props.memoryHeaps[i].size; + // Allow 75%. + heap.budget_size = heap.max_size - (heap.max_size / 4); + heap.tracked_usage = heaps[i].size; + heap.device_usage = heaps[i].size; + } + } +} + +void DeviceAllocator::get_memory_budget(HeapBudget *heap_budgets) +{ + get_memory_budget_nolock(heap_budgets); +} + +bool DeviceAllocator::internal_allocate( + uint32_t size, uint32_t memory_type, AllocationMode mode, + VkDeviceMemory *memory, uint8_t **host_memory, + VkObjectType object_type, uint64_t dedicated_object, ExternalHandle *external) +{ + uint32_t heap_index = mem_props.memoryTypes[memory_type].heapIndex; + auto &heap = heaps[heap_index]; + + // Naive searching is fine here as vkAllocate blocks are *huge* and we won't have many of them. + auto itr = end(heap.blocks); + if (dedicated_object == 0 && !external) + { + itr = find_if(begin(heap.blocks), end(heap.blocks), + [=](const Allocation &alloc) { return size == alloc.size && memory_type == alloc.type && mode == alloc.mode; }); + } + + bool host_visible = (mem_props.memoryTypes[memory_type].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0 && + host_memory != nullptr; + + // Found previously used block. + if (itr != end(heap.blocks)) + { + *memory = itr->memory; + if (host_visible) + { + if (table->vkMapMemory(device->get_device(), itr->memory, 0, VK_WHOLE_SIZE, + 0, reinterpret_cast(host_memory)) != VK_SUCCESS) + return false; + } + heap.blocks.erase(itr); + return true; + } + + // Don't bother checking against budgets on external memory. + // It's not very meaningful. + if (!external) + { + HeapBudget budgets[VK_MAX_MEMORY_HEAPS]; + get_memory_budget_nolock(budgets); + +#ifdef VULKAN_DEBUG + LOGI("Allocating %.1f MiB on heap #%u (mode #%u), before allocating budget: (%.1f MiB / %.1f MiB) [%.1f / %.1f].\n", + double(size) / double(1024 * 1024), heap_index, unsigned(mode), + double(budgets[heap_index].device_usage) / double(1024 * 1024), + double(budgets[heap_index].budget_size) / double(1024 * 1024), + double(budgets[heap_index].tracked_usage) / double(1024 * 1024), + double(budgets[heap_index].max_size) / double(1024 * 1024)); +#endif + + const auto log_heap_index = [&]() + { + LOGW(" Size: %u MiB.\n", unsigned(size / (1024 * 1024))); + LOGW(" Device usage: %u MiB.\n", unsigned(budgets[heap_index].device_usage / (1024 * 1024))); + LOGW(" Tracked usage: %u MiB.\n", unsigned(budgets[heap_index].tracked_usage / (1024 * 1024))); + LOGW(" Budget size: %u MiB.\n", unsigned(budgets[heap_index].budget_size / (1024 * 1024))); + LOGW(" Max size: %u MiB.\n", unsigned(budgets[heap_index].max_size / (1024 * 1024))); + }; + + // If we're going to blow out the budget, we should recycle a bit. + if (budgets[heap_index].device_usage + size >= budgets[heap_index].budget_size) + { + LOGW("Will exceed memory budget, cleaning up ...\n"); + log_heap_index(); + heap.garbage_collect(device); + } + + get_memory_budget_nolock(budgets); + if (budgets[heap_index].device_usage + size >= budgets[heap_index].budget_size) + { + LOGW("Even after garbage collection, we will exceed budget ...\n"); + if (memory_heap_is_budget_critical[heap_index]) + return false; + log_heap_index(); + } + } + + VkMemoryAllocateInfo info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, nullptr, size, memory_type }; + VkMemoryDedicatedAllocateInfo dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO }; + VkExportMemoryAllocateInfo export_info = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO }; + VkMemoryPriorityAllocateInfoEXT priority_info = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT }; + VkMemoryAllocateFlagsInfo flags_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO }; +#ifdef _WIN32 + VkImportMemoryWin32HandleInfoKHR import_info = { VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR }; +#else + VkImportMemoryFdInfoKHR import_info = { VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR }; +#endif + + if (dedicated_object != 0) + { + if (object_type == VK_OBJECT_TYPE_IMAGE) + dedicated.image = (VkImage)dedicated_object; + else if (object_type == VK_OBJECT_TYPE_BUFFER) + dedicated.buffer = (VkBuffer)dedicated_object; + info.pNext = &dedicated; + } + + if (external) + { + VK_ASSERT(dedicated_object); + + if (bool(*external)) + { + import_info.handleType = external->memory_handle_type; + import_info.pNext = info.pNext; + info.pNext = &import_info; + +#ifdef _WIN32 + import_info.handle = external->handle; +#else + import_info.fd = external->handle; +#endif + } + else + { + export_info.handleTypes = external->memory_handle_type; + export_info.pNext = info.pNext; + info.pNext = &export_info; + } + } + + // Don't bother with memory priority on external objects. + if (device->get_device_features().memory_priority_features.memoryPriority && !external) + { + switch (mode) + { + case AllocationMode::LinearDeviceHighPriority: + case AllocationMode::OptimalRenderTarget: + priority_info.priority = 1.0f; + break; + + case AllocationMode::LinearDevice: + case AllocationMode::OptimalResource: + priority_info.priority = 0.5f; + break; + + default: + priority_info.priority = 0.0f; + break; + } + + priority_info.pNext = info.pNext; + info.pNext = &priority_info; + } + + if (device->get_device_features().vk12_features.bufferDeviceAddress && + allocation_mode_supports_bda(mode)) + { + flags_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; + flags_info.pNext = info.pNext; + info.pNext = &flags_info; + } + + VkDeviceMemory device_memory; + VkResult res; + { + GRANITE_SCOPED_TIMELINE_EVENT_FILE(device->get_system_handles().timeline_trace_file, "vkAllocateMemory"); + res = table->vkAllocateMemory(device->get_device(), &info, nullptr, &device_memory); + } + + // If we're importing, make sure we consume the native handle. + if (external && bool(*external) && + ExternalHandle::memory_handle_type_imports_by_reference(external->memory_handle_type)) + { +#ifdef _WIN32 + ::CloseHandle(external->handle); +#else + ::close(external->handle); +#endif + } + + if (res == VK_SUCCESS) + { + heap.size += size; + *memory = device_memory; + + if (host_visible) + { + if (table->vkMapMemory(device->get_device(), device_memory, 0, VK_WHOLE_SIZE, + 0, reinterpret_cast(host_memory)) != VK_SUCCESS) + { + table->vkFreeMemory(device->get_device(), device_memory, nullptr); + heap.size -= size; + return false; + } + } + + return true; + } + else + { + // Look through our heap and see if there are blocks of other types we can free. + auto block_itr = begin(heap.blocks); + while (res != VK_SUCCESS && itr != end(heap.blocks)) + { + table->vkFreeMemory(device->get_device(), block_itr->memory, nullptr); + heap.size -= block_itr->size; + { + GRANITE_SCOPED_TIMELINE_EVENT_FILE(device->get_system_handles().timeline_trace_file, + "vkAllocateMemory"); + res = table->vkAllocateMemory(device->get_device(), &info, nullptr, &device_memory); + } + ++block_itr; + } + + heap.blocks.erase(begin(heap.blocks), block_itr); + + if (res == VK_SUCCESS) + { + heap.size += size; + *memory = device_memory; + + if (host_visible) + { + if (table->vkMapMemory(device->get_device(), device_memory, 0, size, 0, reinterpret_cast(host_memory)) != + VK_SUCCESS) + { + table->vkFreeMemory(device->get_device(), device_memory, nullptr); + heap.size -= size; + return false; + } + } + + return true; + } + else + return false; + } +} + +DeviceAllocationOwner::DeviceAllocationOwner(Device *device_, const DeviceAllocation &alloc_) + : device(device_), alloc(alloc_) +{ +} + +DeviceAllocationOwner::~DeviceAllocationOwner() +{ + if (alloc.get_memory()) + device->free_memory(alloc); +} + +const DeviceAllocation &DeviceAllocationOwner::get_allocation() const +{ + return alloc; +} + +void DeviceAllocationDeleter::operator()(DeviceAllocationOwner *owner) +{ + owner->device->handle_pool.allocations.free(owner); +} + +static VkDeviceSize align(VkDeviceSize value, uint32_t alignment) +{ + return (value + alignment - 1) & ~VkDeviceSize(alignment - 1); +} + +bool DescriptorBufferAllocator::init(Vulkan::Device *device_) +{ + device = device_; + + if (!device->get_device_features().supports_descriptor_buffer_or_heap) + return true; + + alignment = device->get_device_features().resource_heap_offset_alignment; + sub_block_size = std::max(device->get_gpu_properties().limits.nonCoherentAtomSize, alignment); + + VkDeviceSize max_range, max_descriptor_size; + auto &heap_props = device->get_device_features().descriptor_heap_properties; + auto heap = device->get_device_features().descriptor_heap_features.descriptorHeap; + + if (heap) + { + max_range = device->get_device_features().descriptor_heap_properties.maxResourceHeapSize; + + auto image_size = align(heap_props.imageDescriptorSize, heap_props.imageDescriptorAlignment); + auto buffer_size = align(heap_props.bufferDescriptorSize, heap_props.bufferDescriptorAlignment); + + max_descriptor_size = std::max(image_size, buffer_size); + + // We may use combinedImageSampler mode which is 20-bit index. + max_range = std::min(max_range, image_size * 1024 * 1024); + } + else + { + max_range = std::min( + device->get_device_features().descriptor_buffer_properties.maxResourceDescriptorBufferRange, + device->get_device_features().descriptor_buffer_properties.maxSamplerDescriptorBufferRange); + + max_descriptor_size = std::max( + device->get_device_features().descriptor_buffer_properties.sampledImageDescriptorSize, + device->get_device_features().descriptor_buffer_properties.robustStorageBufferDescriptorSize); + } + + // Allocate this early so we're guaranteed to fit in smol BAR as well. + BufferCreateInfo info = {}; + + // Aim for a global heap of about 1M descriptors. Should be enough to avoid exhaustion. + max_range = std::min(max_range, 1024ull * 1024ull * max_descriptor_size); + + auto max_sub_blocks = max_range / sub_block_size; + auto max_sub_blocks_log2 = Util::floor_log2(max_sub_blocks); + info.size = VkDeviceSize(sub_block_size) << max_sub_blocks_log2; + Util::SliceAllocator::init(sub_block_size, max_sub_blocks_log2, &backing_va); + + if (heap) + { + // Only allow dynamic allocation from lower half of the heap. Upper range is slab allocated. + max_sub_blocks /= 2; + max_sub_blocks_log2--; + } + + info.domain = BufferDomain::LinkedDeviceHost; + + if (heap) + { + info.usage = VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT; + } + else + { + info.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT | + VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT; + } + + auto buf = device->create_buffer(info); + if (!buf) + { + LOGE("Failed to allocate descriptor buffer.\n"); + return false; + } + device->set_name(*buf, "resource-heap"); + + init_copy_func(sampled_image_copy, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + init_copy_func(storage_image_copy, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); + init_copy_func(input_attachment_copy, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT); + init_copy_func(combined_image_copy, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + init_copy_func(sampler_copy, VK_DESCRIPTOR_TYPE_SAMPLER); + init_copy_func(uniform_texel_copy, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + init_copy_func(storage_texel_copy, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); + init_copy_func(ubo_copy, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + init_copy_func(ssbo_copy, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + + resource_buffer = buf.release(); + + resource_heap.size = info.size; + resource_heap.mapped = static_cast(device->map_host_buffer(*resource_buffer, MEMORY_ACCESS_WRITE_BIT)); + resource_heap.va = resource_buffer->get_device_address(); + + if (heap) + { + resource_heap.reserved_offset = info.size - heap_props.minResourceHeapReservedRange; + // Ensure reserved offset is valid. + resource_heap.reserved_offset &= ~VkDeviceSize(alignment - 1); + + // Split the resource heap in two. + // Lower half is POT sized and allows for dynamic allocation. + // This is used to spill out UBOs and SSBOs which must live as descriptors. + // Also used to allocate bindless images for GPU perf. + auto heap_dynamic_allocator_size = VkDeviceSize(sub_block_size) << max_sub_blocks_log2; + auto num_application_resources = + (resource_heap.reserved_offset - heap_dynamic_allocator_size) >> device->get_device_features().resource_heap_resource_desc_size_log2; + auto resource_slab_offset = heap_dynamic_allocator_size >> device->get_device_features().resource_heap_resource_desc_size_log2; + + heap_resource_indices.reserve(num_application_resources); + for (uint32_t i = num_application_resources; i; i--) + heap_resource_indices.push_back(resource_slab_offset + i - 1); + + // Allocate the sampler heap. We only slab allocate out of this since it's so small. + auto sampler_size = align(heap_props.samplerDescriptorSize, heap_props.samplerDescriptorAlignment); + info.size = std::min(heap_props.maxSamplerHeapSize, 4096 * sampler_size); + + buf = device->create_buffer(info); + if (!buf) + { + LOGE("Failed to allocate sampler heap.\n"); + return false; + } + + device->set_name(*buf, "sampler-heap"); + sampler_buffer = buf.release(); + + sampler_heap.size = info.size; + sampler_heap.reserved_offset = info.size - heap_props.minSamplerHeapReservedRange; + sampler_heap.mapped = static_cast(device->map_host_buffer(*sampler_buffer, MEMORY_ACCESS_WRITE_BIT)); + sampler_heap.va = sampler_buffer->get_device_address(); + + sampler_heap.reserved_offset &= ~VkDeviceSize(heap_props.samplerDescriptorAlignment - 1); + auto num_application_samplers = sampler_heap.reserved_offset / sampler_size; + heap_sampler_indices.reserve(num_application_samplers); + for (uint32_t i = num_application_samplers; i; i--) + heap_sampler_indices.push_back(i - 1); + } + + return true; +} + +template +static void static_memcpy(uint8_t *dst, const uint8_t *src, size_t) +{ + // memcpy with static size is way more efficient than dynamic size. + memcpy(dst, src, N); +} + +static void dynamic_memcpy(uint8_t *dst, const uint8_t *src, size_t n) +{ + memcpy(dst, src, n); +} + +template +static void static_memcpy_n(uint8_t *dst, const uint8_t * const *src, size_t count, size_t) +{ + // memcpy with static size is way more efficient than dynamic size. + for (size_t i = 0; i < count; i++, dst += N) + memcpy(dst, src[i], N); +} + +static void dynamic_memcpy_n(uint8_t *dst, const uint8_t * const *src, size_t count, size_t n) +{ + for (size_t i = 0; i < count; i++, dst += n) + memcpy(dst, src[i], n); +} + +static DescriptorCopyFunc get_optimized_copy_func(size_t size) +{ + switch (size) + { + case 0: return static_memcpy<0>; + case 4: return static_memcpy<4>; + case 8: return static_memcpy<8>; + case 16: return static_memcpy<16>; + case 32: return static_memcpy<32>; + case 48: return static_memcpy<48>; + case 64: return static_memcpy<64>; + case 96: return static_memcpy<96>; + case 128: return static_memcpy<128>; + case 192: return static_memcpy<192>; + case 256: return static_memcpy<256>; + default: LOGW("Unrecognized special memcpy size %zu. Using slow fallback.\n", size); return dynamic_memcpy; + } +} + +static DescriptorCopyNFunc get_optimized_copy_n_func(size_t size) +{ + switch (size) + { + case 0: return static_memcpy_n<0>; + case 4: return static_memcpy_n<4>; + case 8: return static_memcpy_n<8>; + case 16: return static_memcpy_n<16>; + case 32: return static_memcpy_n<32>; + case 48: return static_memcpy_n<48>; + case 64: return static_memcpy_n<64>; + case 96: return static_memcpy_n<96>; + case 128: return static_memcpy_n<128>; + case 192: return static_memcpy_n<192>; + case 256: return static_memcpy_n<256>; + default: LOGW("Unrecognized special memcpy size %zu. Using slow fallback.\n", size); return dynamic_memcpy_n; + } +} + +void DescriptorBufferAllocator::init_copy_func(DescriptorTypeInfo &info, VkDescriptorType type) const +{ + info.size = get_descriptor_size_for_type(type); + info.func = get_optimized_copy_func(info.size); + info.func_n = get_optimized_copy_n_func(info.size); + info.slab.init(info.size); +} + +void DescriptorBufferAllocator::free(const DescriptorBufferAllocation &alloc) +{ + std::lock_guard holder{lock}; + Util::SliceAllocator::free(alloc.backing_slice); +} + +void DescriptorBufferAllocator::free(const DescriptorBufferAllocation *alloc, size_t count) +{ + std::lock_guard holder{lock}; + for (size_t i = 0; i < count; i++) + { + total_size -= alloc[i].backing_slice.count; + Util::SliceAllocator::free(alloc[i].backing_slice); + } +} + +DescriptorBufferAllocation DescriptorBufferAllocator::allocate(VkDeviceSize size) +{ + size = (size + alignment - 1) & ~(alignment - 1); + + std::lock_guard holder{lock}; + + DescriptorBufferAllocation alloc = {}; + if (!Util::SliceAllocator::allocate(size, &alloc.backing_slice)) + { + LOGE("Descriptor buffer arena is exhausted! This should not happen.\n"); + return alloc; + } + + total_size += alloc.backing_slice.count; + if (total_size > high_water_mark) + { + high_water_mark = total_size; +#ifdef VULKAN_DEBUG + LOGI("Descriptor arena high water mark increased to: %llu bytes.\n", + static_cast(high_water_mark)); +#endif + } + + return alloc; +} + +void DescriptorBufferAllocator::teardown() +{ + if (resource_buffer) + { + resource_buffer->set_internal_sync_object(); + resource_buffer->release_reference(); + resource_buffer = nullptr; + } + + if (sampler_buffer) + { + sampler_buffer->set_internal_sync_object(); + sampler_buffer->release_reference(); + sampler_buffer = nullptr; + } +} + +VkSampler DescriptorBufferAllocator::create_sampler(const VkSamplerCreateInfo *info) +{ + if (device->get_device_features().descriptor_heap_features.descriptorHeap) + { + uint32_t index; + { + std::lock_guard holder{lock}; + if (heap_sampler_indices.empty()) + return VK_NULL_HANDLE; + + index = heap_sampler_indices.back(); + heap_sampler_indices.pop_back(); + } + + auto &props = device->get_device_features().descriptor_heap_properties; + uint8_t *mapped = sampler_heap.mapped + index * align(props.samplerDescriptorSize, props.samplerDescriptorAlignment); + + VkHostAddressRangeEXT addr = {}; + addr.address = mapped; + addr.size = props.samplerDescriptorSize; + device->get_device_table().vkWriteSamplerDescriptorsEXT(device->get_device(), 1, info, &addr); + + return (VkSampler)(uint64_t(index) | (1ull << 63)); + } + else + { + VkSampler samp = VK_NULL_HANDLE; + if (device->get_device_table().vkCreateSampler(device->get_device(), info, nullptr, &samp) != VK_SUCCESS) + return VK_NULL_HANDLE; + return samp; + } +} + +void DescriptorBufferAllocator::destroy_sampler(VkSampler sampler) +{ + if (device->get_device_features().descriptor_heap_features.descriptorHeap) + { + if (sampler) + { + VK_ASSERT(((uint64_t)sampler) >> 63); + std::lock_guard holder{lock}; + heap_sampler_indices.push_back((uint64_t)sampler); + } + } + else + { + device->get_device_table().vkDestroySampler(device->get_device(), sampler, nullptr); + } +} + +uint32_t DescriptorBufferAllocator::allocate_single_resource_heap_entry() +{ + std::lock_guard holder{lock}; + if (heap_resource_indices.empty()) + { + LOGE("Resource heap is empty.\n"); + return UINT32_MAX; + } + + auto ret = heap_resource_indices.back(); + heap_resource_indices.pop_back(); + return ret; +} + +void DescriptorBufferAllocator::free_single_resource_heap_entry(uint32_t index) +{ + std::lock_guard holder{lock}; + heap_resource_indices.push_back(index); +} + +DescriptorBufferAllocator::~DescriptorBufferAllocator() +{ + // Call teardown before destroying device. + VK_ASSERT(!resource_buffer); + VK_ASSERT(!sampler_buffer); + VK_ASSERT(total_size == 0); +} + +uint32_t DescriptorBufferAllocator::get_descriptor_size_for_type(VkDescriptorType type) const +{ + auto &ext = device->get_device_features(); + + if (ext.descriptor_heap_features.descriptorHeap) + { + // We could query the types individually but lots of other code relies + // on these being normalized around a common value. + + switch (type) + { + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + // Is never used directly. + return 0; + + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + return align(ext.descriptor_heap_properties.bufferDescriptorSize, + ext.descriptor_heap_properties.bufferDescriptorAlignment); + + default: + return align(ext.descriptor_heap_properties.imageDescriptorSize, + ext.descriptor_heap_properties.imageDescriptorAlignment); + } + } + else + { + switch (type) + { + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return ext.descriptor_buffer_properties.combinedImageSamplerDescriptorSize; + case VK_DESCRIPTOR_TYPE_SAMPLER: + return ext.descriptor_buffer_properties.samplerDescriptorSize; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + return ext.descriptor_buffer_properties.sampledImageDescriptorSize; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + return ext.descriptor_buffer_properties.inputAttachmentDescriptorSize; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + return ext.descriptor_buffer_properties.storageImageDescriptorSize; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + if (ext.enabled_features.robustBufferAccess) + return ext.descriptor_buffer_properties.robustUniformBufferDescriptorSize; + else + return ext.descriptor_buffer_properties.uniformBufferDescriptorSize; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + if (ext.enabled_features.robustBufferAccess) + return ext.descriptor_buffer_properties.robustUniformTexelBufferDescriptorSize; + else + return ext.descriptor_buffer_properties.uniformTexelBufferDescriptorSize; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + if (ext.enabled_features.robustBufferAccess) + return ext.descriptor_buffer_properties.robustStorageBufferDescriptorSize; + else + return ext.descriptor_buffer_properties.storageBufferDescriptorSize; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + if (ext.enabled_features.robustBufferAccess) + return ext.descriptor_buffer_properties.robustStorageTexelBufferDescriptorSize; + else + return ext.descriptor_buffer_properties.storageTexelBufferDescriptorSize; + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + return ext.descriptor_buffer_properties.accelerationStructureDescriptorSize; + default: + LOGE("Invalid descriptor type %u\n", type); + return 0; + } + } +} + +void DescriptorBufferAllocator::free_cached_descriptors(const CachedDescriptorPayload *payloads, size_t count) +{ + bool heap = device->get_device_features().descriptor_heap_features.descriptorHeap == VK_TRUE; + + for (size_t i = 0; i < count; i++) + { + if (!payloads[i].ptr) + continue; + + switch (payloads[i].type) + { + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + combined_image_copy.slab.free(payloads[i].ptr); + break; + case VK_DESCRIPTOR_TYPE_SAMPLER: + sampler_copy.slab.free(payloads[i].ptr); + break; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + sampled_image_copy.slab.free(payloads[i].ptr); + break; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + input_attachment_copy.slab.free(payloads[i].ptr); + break; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + storage_image_copy.slab.free(payloads[i].ptr); + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + ubo_copy.slab.free(payloads[i].ptr); + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + uniform_texel_copy.slab.free(payloads[i].ptr); + break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + ssbo_copy.slab.free(payloads[i].ptr); + break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + storage_texel_copy.slab.free(payloads[i].ptr); + break; + default: + break; + } + + if (heap) + free_single_resource_heap_entry(payloads[i].heap_index); + } +} + +bool DescriptorBufferAllocator::create_image_view(const VkImageViewCreateInfo &info, VkImageUsageFlags usage, + ImageLayout layout, CachedImageView &view) +{ + view = {}; + bool heap = device->get_device_features().descriptor_heap_features.descriptorHeap == VK_TRUE; + + static constexpr VkImageUsageFlags force_view_flags = + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | + VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR; + + VkImageViewUsageCreateInfo view_usage_create_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO }; + auto tmpinfo = info; + view_usage_create_info.usage = usage; + view_usage_create_info.pNext = tmpinfo.pNext; + tmpinfo.pNext = &view_usage_create_info; + if (heap) + view_usage_create_info.usage &= force_view_flags; + + bool need_image_view_object = !heap || (usage & force_view_flags) != 0; + auto &table = device->get_device_table(); + + if (need_image_view_object && + table.vkCreateImageView(device->get_device(), &tmpinfo, nullptr, &view.view) != VK_SUCCESS) + return false; + + if (heap) + { + VkResourceDescriptorInfoEXT infos[4]; + VkImageDescriptorInfoEXT images[4]; + VkHostAddressRangeEXT addrs[4]; + uint32_t count = 0; + + if (usage & VK_IMAGE_USAGE_SAMPLED_BIT) + { + view.sampled = alloc_sampled_image(); + view.sampled.heap_index = allocate_single_resource_heap_entry(); + if (view.sampled.heap_index == UINT32_MAX) + return false; + + infos[count] = { VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT }; + infos[count].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + infos[count].data.pImage = &images[count]; + + images[count] = { VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT }; + images[count].pView = &info; + images[count].layout = layout == ImageLayout::Optimal ? VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL; + + addrs[count].address = view.sampled.ptr; + addrs[count].size = get_descriptor_size_for_type(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + count++; + } + + if (usage & VK_IMAGE_USAGE_STORAGE_BIT) + { + view.storage = alloc_storage_image(); + view.storage.heap_index = allocate_single_resource_heap_entry(); + if (view.storage.heap_index == UINT32_MAX) + return false; + + infos[count] = { VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT }; + infos[count].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + infos[count].data.pImage = &images[count]; + + images[count] = { VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT }; + images[count].pView = &info; + images[count].layout = VK_IMAGE_LAYOUT_GENERAL; + + addrs[count].address = view.storage.ptr; + addrs[count].size = get_descriptor_size_for_type(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); + count++; + } + + if (usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) + { + view.input_attachment = alloc_input_attachment(); + view.input_attachment.heap_index = allocate_single_resource_heap_entry(); + if (view.input_attachment.heap_index == UINT32_MAX) + return false; + + view.input_attachment_feedback = alloc_input_attachment(); + view.input_attachment_feedback.heap_index = allocate_single_resource_heap_entry(); + if (view.input_attachment_feedback.heap_index == UINT32_MAX) + return false; + + for (int i = 0; i < 2; i++) + { + infos[count] = { VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT }; + infos[count].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + infos[count].data.pImage = &images[count]; + + images[count] = { VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT }; + images[count].pView = &info; + images[count].layout = i == 0 && layout == ImageLayout::Optimal + ? VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL + : VK_IMAGE_LAYOUT_GENERAL; + + addrs[count].address = i ? view.input_attachment_feedback.ptr : view.input_attachment.ptr; + addrs[count].size = get_descriptor_size_for_type(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT); + count++; + } + } + + if (count) + table.vkWriteResourceDescriptorsEXT(device->get_device(), count, infos, addrs); + + auto desc_size = device->get_device_features().resource_heap_resource_desc_size; + + if (usage & VK_IMAGE_USAGE_SAMPLED_BIT) + copy_sampled_image(resource_heap.mapped + view.sampled.heap_index * desc_size, view.sampled.ptr); + + if (usage & VK_IMAGE_USAGE_STORAGE_BIT) + copy_storage_image(resource_heap.mapped + view.storage.heap_index * desc_size, view.storage.ptr); + + if (usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) + { + copy_storage_image(resource_heap.mapped + view.input_attachment.heap_index * desc_size, view.input_attachment.ptr); + copy_storage_image(resource_heap.mapped + view.input_attachment_feedback.heap_index * desc_size, view.input_attachment_feedback.ptr); + } + } + else if (device->get_device_features().descriptor_buffer_features.descriptorBuffer && + need_image_view_object) + { + VkDescriptorImageInfo image_info = {}; + image_info.imageView = view.view; + + VkDescriptorGetInfoEXT get_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT }; + get_info.data.pSampledImage = &image_info; + + auto &props = device->get_device_features().descriptor_buffer_properties; + + if (usage & VK_IMAGE_USAGE_SAMPLED_BIT) + { + get_info.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + image_info.imageLayout = layout == ImageLayout::Optimal ? VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL; + view.sampled = alloc_sampled_image(); + table.vkGetDescriptorEXT(device->get_device(), &get_info, props.sampledImageDescriptorSize, view.sampled.ptr); + } + + if (usage & VK_IMAGE_USAGE_STORAGE_BIT) + { + get_info.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + view.storage = alloc_storage_image(); + table.vkGetDescriptorEXT(device->get_device(), &get_info, props.storageImageDescriptorSize, view.storage.ptr); + } + + if (usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) + { + get_info.type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + + image_info.imageLayout = layout == ImageLayout::Optimal ? VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL; + view.input_attachment = alloc_input_attachment(); + table.vkGetDescriptorEXT(device->get_device(), &get_info, + props.inputAttachmentDescriptorSize, view.input_attachment.ptr); + + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + view.input_attachment_feedback = alloc_input_attachment(); + table.vkGetDescriptorEXT(device->get_device(), &get_info, + props.inputAttachmentDescriptorSize, view.input_attachment_feedback.ptr); + } + } + + return true; +} + +void DescriptorBufferAllocator::free_image_view(const CachedImageView &view) +{ + if (view.view) + device->get_device_table().vkDestroyImageView(device->get_device(), view.view, nullptr); + + free_cached_descriptors(&view.sampled, 1); + free_cached_descriptors(&view.storage, 1); + free_cached_descriptors(&view.input_attachment, 1); + free_cached_descriptors(&view.input_attachment_feedback, 1); +} + +bool DescriptorBufferAllocator::create_buffer_view( + const BufferViewCreateInfo &info, CachedBufferView &view) +{ + bool heap = device->get_device_features().descriptor_heap_features.descriptorHeap == VK_TRUE; + auto &table = device->get_device_table(); + view = {}; + + if (!device->get_device_features().supports_descriptor_buffer_or_heap) + { + VkBufferViewCreateInfo vk_info = { VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO }; + vk_info.buffer = info.buffer->get_buffer(); + vk_info.format = info.format; + vk_info.offset = info.offset; + vk_info.range = info.range; + + if (table.vkCreateBufferView(device->get_device(), &vk_info, nullptr, &view.view) != VK_SUCCESS) + return false; + } + else if (heap) + { + VkTexelBufferDescriptorInfoEXT texel = { VK_STRUCTURE_TYPE_TEXEL_BUFFER_DESCRIPTOR_INFO_EXT }; + VkResourceDescriptorInfoEXT infos[2]; + VkHostAddressRangeEXT addrs[2]; + uint32_t count = 0; + + VkFormatProperties3 props3 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 }; + device->get_format_properties(info.format, &props3); + + texel.addressRange.address = info.buffer->get_device_address() + info.offset; + if (info.range == VK_WHOLE_SIZE) + texel.addressRange.size = info.buffer->get_create_info().size - info.offset; + else + texel.addressRange.size = info.range; + texel.format = info.format; + + bool uniform = + (info.buffer->get_create_info().usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) != 0 && + (props3.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) != 0; + + bool storage = + (info.buffer->get_create_info().usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) != 0 && + (props3.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) != 0; + + if (uniform) + { + view.uniform = alloc_uniform_texel(); + view.uniform.heap_index = allocate_single_resource_heap_entry(); + + infos[count] = { VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT }; + infos[count].type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + infos[count].data.pTexelBuffer = &texel; + addrs[count].address = view.uniform.ptr; + addrs[count].size = get_descriptor_size_for_type(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + count++; + } + + if (storage) + { + view.storage = alloc_storage_texel(); + view.storage.heap_index = allocate_single_resource_heap_entry(); + + infos[count] = { VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT }; + infos[count].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + infos[count].data.pTexelBuffer = &texel; + addrs[count].address = view.storage.ptr; + addrs[count].size = get_descriptor_size_for_type(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); + count++; + } + + auto desc_size = device->get_device_features().resource_heap_resource_desc_size; + table.vkWriteResourceDescriptorsEXT(device->get_device(), count, infos, addrs); + + if (uniform) + copy_uniform_texel(resource_heap.mapped + view.uniform.heap_index * desc_size, view.uniform.ptr); + if (storage) + copy_storage_texel(resource_heap.mapped + view.storage.heap_index * desc_size, view.storage.ptr); + } + else + { + VkDescriptorAddressInfoEXT addr = { VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT }; + VkDescriptorGetInfoEXT get_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT }; + + addr.address = info.buffer->get_device_address() + info.offset; + if (info.range == VK_WHOLE_SIZE) + addr.range = info.buffer->get_create_info().size - info.offset; + else + addr.range = info.range; + addr.format = info.format; + + VkFormatProperties3 props3 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 }; + device->get_format_properties(info.format, &props3); + + if ((info.buffer->get_create_info().usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) != 0 && + (props3.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) != 0) + { + view.uniform = alloc_uniform_texel(); + get_info.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + get_info.data.pUniformTexelBuffer = &addr; + table.vkGetDescriptorEXT(device->get_device(), &get_info, + get_descriptor_size_for_type(get_info.type), view.uniform.ptr); + } + + if ((info.buffer->get_create_info().usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) != 0 && + (props3.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) != 0) + { + view.storage = alloc_storage_texel(); + get_info.type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + get_info.data.pStorageTexelBuffer = &addr; + table.vkGetDescriptorEXT( + device->get_device(), &get_info, get_descriptor_size_for_type(get_info.type), view.storage.ptr); + } + } + + return true; +} + +void DescriptorBufferAllocator::free_buffer_view(const CachedBufferView &view) +{ + if (view.view) + device->get_device_table().vkDestroyBufferView(device->get_device(), view.view, nullptr); + + free_cached_descriptors(&view.uniform, 1); + free_cached_descriptors(&view.storage, 1); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/memory_allocator.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/memory_allocator.hpp new file mode 100644 index 00000000..8af7d2b1 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/memory_allocator.hpp @@ -0,0 +1,434 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "intrusive.hpp" +#include "object_pool.hpp" +#include "slab_allocator.hpp" +#include "intrusive_list.hpp" +#include "vulkan_headers.hpp" +#include "logging.hpp" +#include "bitops.hpp" +#include "enum_cast.hpp" +#include "vulkan_common.hpp" +#include "arena_allocator.hpp" +#include +#include +#include +#include +#include + +namespace Vulkan +{ +class Device; + +enum class ImageLayout; + +enum class MemoryClass : uint8_t +{ + Small = 0, + Medium, + Large, + Huge, + Count +}; + +enum class AllocationMode : uint8_t +{ + LinearHostMappable = 0, + LinearDevice, + LinearDeviceHighPriority, + OptimalResource, + OptimalRenderTarget, + External, + Count +}; + +enum MemoryAccessFlag : uint32_t +{ + MEMORY_ACCESS_WRITE_BIT = 1, + MEMORY_ACCESS_READ_BIT = 2, + MEMORY_ACCESS_READ_WRITE_BIT = MEMORY_ACCESS_WRITE_BIT | MEMORY_ACCESS_READ_BIT +}; +using MemoryAccessFlags = uint32_t; + +struct DeviceAllocation; +class DeviceAllocator; + +class ClassAllocator; +class DeviceAllocator; +class Allocator; +class Device; + +using MiniHeap = Util::LegionHeap; + +struct DeviceAllocation +{ + friend class Util::ArenaAllocator; + friend class ClassAllocator; + friend class Allocator; + friend class DeviceAllocator; + friend class Device; + friend class ImageResourceHolder; + +public: + inline VkDeviceMemory get_memory() const + { + return base; + } + + inline bool allocation_is_global() const + { + return !alloc && base; + } + + inline uint32_t get_offset() const + { + return offset; + } + + inline uint32_t get_size() const + { + return size; + } + + inline uint32_t get_mask() const + { + return mask; + } + + inline bool is_host_allocation() const + { + return host_base != nullptr; + } + + static DeviceAllocation make_imported_allocation(VkDeviceMemory memory, VkDeviceSize size, uint32_t memory_type); + + ExternalHandle export_handle(Device &device); + +private: + VkDeviceMemory base = VK_NULL_HANDLE; + uint8_t *host_base = nullptr; + ClassAllocator *alloc = nullptr; + Util::IntrusiveList::Iterator heap = {}; + uint32_t offset = 0; + uint32_t mask = 0; + uint32_t size = 0; + VkExternalMemoryHandleTypeFlags exportable_types = 0; + + AllocationMode mode = AllocationMode::Count; + uint8_t memory_type = 0; + + void free_global(DeviceAllocator &allocator, uint32_t size, uint32_t memory_type); + void free_immediate(); + void free_immediate(DeviceAllocator &allocator); +}; + +class DeviceAllocationOwner; +struct DeviceAllocationDeleter +{ + void operator()(DeviceAllocationOwner *owner); +}; + +class DeviceAllocationOwner : public Util::IntrusivePtrEnabled +{ +public: + friend class Util::ObjectPool; + friend struct DeviceAllocationDeleter; + + ~DeviceAllocationOwner(); + const DeviceAllocation &get_allocation() const; + +private: + DeviceAllocationOwner(Device *device, const DeviceAllocation &alloc); + Device *device; + DeviceAllocation alloc; +}; +using DeviceAllocationOwnerHandle = Util::IntrusivePtr; + +struct MemoryAllocateInfo +{ + VkMemoryRequirements requirements = {}; + VkMemoryPropertyFlags required_properties = 0; + AllocationMode mode = {}; +}; + +class ClassAllocator : public Util::ArenaAllocator +{ +public: + friend class Util::ArenaAllocator; + + inline void set_global_allocator(DeviceAllocator *allocator, AllocationMode mode, uint32_t memory_type_) + { + global_allocator = allocator; + global_allocator_mode = mode; + memory_type = memory_type_; + } + + inline void set_parent(ClassAllocator *allocator) + { + parent = allocator; + } + +private: + ClassAllocator *parent = nullptr; + uint32_t memory_type = 0; + DeviceAllocator *global_allocator = nullptr; + AllocationMode global_allocator_mode = AllocationMode::Count; + + // Implements curious recurring template pattern calls. + bool allocate_backing_heap(DeviceAllocation *allocation); + void free_backing_heap(DeviceAllocation *allocation); + void prepare_allocation(DeviceAllocation *allocation, Util::IntrusiveList::Iterator heap_itr, + const Util::SuballocationResult &suballoc); +}; + +class Allocator +{ +public: + explicit Allocator(Util::ObjectPool &object_pool); + void operator=(const Allocator &) = delete; + Allocator(const Allocator &) = delete; + + bool allocate(uint32_t size, uint32_t alignment, AllocationMode mode, DeviceAllocation *alloc); + bool allocate_global(uint32_t size, AllocationMode mode, DeviceAllocation *alloc); + bool allocate_dedicated(uint32_t size, AllocationMode mode, DeviceAllocation *alloc, + VkObjectType object_type, uint64_t object, ExternalHandle *external); + + inline ClassAllocator &get_class_allocator(MemoryClass clazz, AllocationMode mode) + { + return classes[unsigned(clazz)][unsigned(mode)]; + } + + static void free(DeviceAllocation *alloc) + { + alloc->free_immediate(); + } + + void set_global_allocator(DeviceAllocator *allocator, uint32_t memory_type_) + { + memory_type = memory_type_; + for (auto &sub : classes) + for (int i = 0; i < Util::ecast(AllocationMode::Count); i++) + sub[i].set_global_allocator(allocator, AllocationMode(i), memory_type); + global_allocator = allocator; + } + +private: + ClassAllocator classes[Util::ecast(MemoryClass::Count)][Util::ecast(AllocationMode::Count)]; + DeviceAllocator *global_allocator = nullptr; + uint32_t memory_type = 0; +}; + +struct HeapBudget +{ + VkDeviceSize max_size; + VkDeviceSize budget_size; + VkDeviceSize tracked_usage; + VkDeviceSize device_usage; +}; + +class DeviceAllocator +{ +public: + void init(Device *device); + + ~DeviceAllocator(); + + bool allocate_generic_memory(uint32_t size, uint32_t alignment, AllocationMode mode, uint32_t memory_type, + DeviceAllocation *alloc); + bool allocate_buffer_memory(uint32_t size, uint32_t alignment, AllocationMode mode, uint32_t memory_type, + VkBuffer buffer, DeviceAllocation *alloc, ExternalHandle *external); + bool allocate_image_memory(uint32_t size, uint32_t alignment, AllocationMode mode, uint32_t memory_type, + VkImage image, bool force_no_dedicated, DeviceAllocation *alloc, ExternalHandle *external); + + void garbage_collect(); + void *map_memory(const DeviceAllocation &alloc, MemoryAccessFlags flags, VkDeviceSize offset, VkDeviceSize length); + void unmap_memory(const DeviceAllocation &alloc, MemoryAccessFlags flags, VkDeviceSize offset, VkDeviceSize length); + + void get_memory_budget(HeapBudget *heaps); + + bool internal_allocate(uint32_t size, uint32_t memory_type, AllocationMode mode, + VkDeviceMemory *memory, uint8_t **host_memory, + VkObjectType object_type, uint64_t dedicated_object, ExternalHandle *external); + void internal_free(uint32_t size, uint32_t memory_type, AllocationMode mode, VkDeviceMemory memory, bool is_mapped); + void internal_free_no_recycle(uint32_t size, uint32_t memory_type, VkDeviceMemory memory); + +private: + Util::ObjectPool object_pool; + std::vector> allocators; + Device *device = nullptr; + const VolkDeviceTable *table = nullptr; + VkPhysicalDeviceMemoryProperties mem_props; + VkDeviceSize atom_alignment = 1; + struct Allocation + { + VkDeviceMemory memory; + uint32_t size; + uint32_t type; + AllocationMode mode; + }; + + struct Heap + { + uint64_t size = 0; + std::vector blocks; + void garbage_collect(Device *device); + }; + + std::vector heaps; + bool memory_heap_is_budget_critical[VK_MAX_MEMORY_HEAPS] = {}; + void get_memory_budget_nolock(HeapBudget *heaps); +}; + +// Avoid cross-dependency in header. +class Buffer; + +struct DescriptorBufferAllocation +{ + inline VkDeviceSize get_offset() const { return backing_slice.offset; } + inline VkDeviceSize get_size() const { return backing_slice.count; } + + // Internal detail. + Util::AllocatedSlice backing_slice; +}; + +using DescriptorCopyFunc = void (*)(uint8_t *, const uint8_t *, size_t size); +using DescriptorCopyNFunc = void (*)(uint8_t *, const uint8_t * const *, size_t count, size_t size); + +struct CachedDescriptorPayload +{ + uint8_t *ptr; + VkDescriptorType type; + uint32_t heap_index; + explicit operator bool() const { return ptr != nullptr; } +}; + +struct CachedImageView +{ + VkImageView view; // For legacy and descriptor buffer. + + // For DB, this is used all the time. For heap, only occasionally as needed, + // usually for bindless. + CachedDescriptorPayload sampled; // SHADER_READ_ONLY + CachedDescriptorPayload input_attachment; // INPUT_ATTACHMENT + read only (if applicable) + CachedDescriptorPayload input_attachment_feedback; // INPUT_ATTACHMENT + GENERAL (if applicable) + CachedDescriptorPayload storage; // For storage image, always GENERAL layout. +}; + +struct CachedBufferView +{ + VkBufferView view; + CachedDescriptorPayload uniform; + CachedDescriptorPayload storage; +}; + +struct BufferViewCreateInfo; + +class DescriptorBufferAllocator : private Util::SliceAllocator +{ +public: + bool init(Device *device); + ~DescriptorBufferAllocator(); + + void teardown(); + + struct HeapInfo + { + VkDeviceAddress va; + uint8_t *mapped; + VkDeviceSize reserved_offset; + VkDeviceSize size; + }; + + HeapInfo get_resource_heap() const { return resource_heap; } + // Only for descriptor_heap. + HeapInfo get_sampler_heap() const { return sampler_heap; } + + DescriptorBufferAllocation allocate(VkDeviceSize size); + void free(const DescriptorBufferAllocation &alloc); + void free(const DescriptorBufferAllocation *alloc, size_t count); + + uint32_t get_descriptor_size_for_type(VkDescriptorType type) const; + + bool create_image_view(const VkImageViewCreateInfo &info, VkImageUsageFlags usage, + ImageLayout layout, CachedImageView &view); + void free_image_view(const CachedImageView &view); + + bool create_buffer_view(const BufferViewCreateInfo &info, CachedBufferView &view); + void free_buffer_view(const CachedBufferView &view); + +#define IMPL_TYPE(type, desc_type) \ + inline void copy_##type(uint8_t *dst, const uint8_t *src) const { type##_copy.func(dst, src, type##_copy.size); } \ + inline void copy_##type##_n(uint8_t *dst, const uint8_t * const *src, size_t count) const { type##_copy.func_n(dst, src, count, type##_copy.size); } \ + inline CachedDescriptorPayload alloc_##type() { return { type##_copy.slab.allocate(), desc_type }; } \ + inline void free_##type(uint8_t *ptr) { type##_copy.slab.free(ptr); } + + IMPL_TYPE(combined_image, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) + IMPL_TYPE(sampled_image, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) + IMPL_TYPE(storage_image, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) + IMPL_TYPE(sampler, VK_DESCRIPTOR_TYPE_SAMPLER) + IMPL_TYPE(input_attachment, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) + IMPL_TYPE(ubo, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) + IMPL_TYPE(ssbo, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) + IMPL_TYPE(uniform_texel, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) + IMPL_TYPE(storage_texel, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) + + void free_cached_descriptors(const CachedDescriptorPayload *payloads, size_t count); + + // On heap, this is a dummy handle. + VkSampler create_sampler(const VkSamplerCreateInfo *info); + void destroy_sampler(VkSampler sampler); + +private: + Device *device = nullptr; + Buffer *resource_buffer = nullptr; + Buffer *sampler_buffer = nullptr; + Util::SliceBackingAllocatorVA backing_va; + VkDeviceSize alignment = 0; + VkDeviceSize sub_block_size = 0; + std::mutex lock; + + HeapInfo resource_heap = {}, sampler_heap = {}; + + struct DescriptorTypeInfo + { + DescriptorCopyFunc func; + DescriptorCopyNFunc func_n; + size_t size; + Util::ThreadSafeSlabAllocator slab; + }; + DescriptorTypeInfo sampled_image_copy, storage_image_copy, combined_image_copy, sampler_copy, input_attachment_copy; + DescriptorTypeInfo ubo_copy, ssbo_copy, uniform_texel_copy, storage_texel_copy; + void init_copy_func(DescriptorTypeInfo &info, VkDescriptorType type) const; + + VkDeviceSize total_size = 0; + VkDeviceSize high_water_mark = 0; + std::vector heap_resource_indices; + std::vector heap_sampler_indices; + + // For descriptor heap. + uint32_t allocate_single_resource_heap_entry(); + void free_single_resource_heap_entry(uint32_t index); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/mesh/meshlet.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/mesh/meshlet.cpp new file mode 100644 index 00000000..1b0484bc --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/mesh/meshlet.cpp @@ -0,0 +1,281 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "meshlet.hpp" +#include "command_buffer.hpp" +#include "buffer.hpp" +#include "device.hpp" +#include "filesystem.hpp" + +namespace Vulkan +{ +namespace Meshlet +{ +MeshView create_mesh_view(const Granite::FileMapping &mapping) +{ + MeshView view = {}; + + if (mapping.get_size() < sizeof(magic) + sizeof(FormatHeader)) + { + LOGE("MESHLET2 file too small.\n"); + return view; + } + + auto *ptr = mapping.data(); + auto *end_ptr = ptr + mapping.get_size(); + + if (memcmp(ptr, magic, sizeof(magic)) != 0) + { + LOGE("Invalid MESHLET2 magic.\n"); + return {}; + } + + ptr += sizeof(magic); + + view.format_header = reinterpret_cast(ptr); + ptr += sizeof(*view.format_header); + + if (end_ptr - ptr < ptrdiff_t(view.format_header->meshlet_count * sizeof(Bound))) + return {}; + view.bounds = reinterpret_cast(ptr); + ptr += view.format_header->meshlet_count * sizeof(Bound); + + size_t num_bounds_256 = (view.format_header->meshlet_count + ChunkFactor - 1) / ChunkFactor; + + if (end_ptr - ptr < ptrdiff_t(num_bounds_256 * sizeof(Bound))) + return {}; + view.bounds_256 = reinterpret_cast(ptr); + ptr += num_bounds_256 * sizeof(Bound); + + view.num_bounds = view.format_header->meshlet_count; + view.num_bounds_256 = num_bounds_256; + + if (end_ptr - ptr < ptrdiff_t(view.format_header->meshlet_count * view.format_header->stream_count * sizeof(Stream))) + return {}; + view.streams = reinterpret_cast(ptr); + ptr += view.format_header->meshlet_count * view.format_header->stream_count * sizeof(Stream); + + if (!view.format_header->payload_size_words) + return {}; + + if (end_ptr - ptr < ptrdiff_t(view.format_header->payload_size_words * sizeof(PayloadWord))) + return {}; + view.payload = reinterpret_cast(ptr); + + for (uint32_t i = 0, n = view.format_header->meshlet_count; i < n; i++) + { + auto counts = view.streams[i * view.format_header->stream_count].u.counts; + view.total_primitives += counts.prim_count; + view.total_vertices += counts.vert_count; + } + + return view; +} + +static void upload_indirect_buffer(CommandBuffer &cmd, const Vulkan::Buffer &indirect_buffer, uint32_t alloc_offset, + const MeshView &view, RuntimeStyle runtime_style, + uint32_t global_prim_offset, uint32_t global_vert_offset) +{ + size_t total_padded_meshlets = view.num_bounds_256 * ChunkFactor; + size_t total_meshlets = view.format_header->meshlet_count; + + uint32_t prim_offset = global_prim_offset; + uint32_t vert_offset = global_vert_offset; + + if (runtime_style == RuntimeStyle::Meshlet) + { + constexpr size_t Stride = sizeof(RuntimeHeaderDecoded) * ChunkFactor; + auto *indirect = static_cast( + cmd.update_buffer(indirect_buffer, alloc_offset * Stride, + view.num_bounds_256 * Stride)); + + for (uint32_t i = 0; i < total_meshlets; i++) + { + auto &counts = view.streams[i * view.format_header->stream_count].u.counts; + uint32_t prim_count = counts.prim_count; + uint32_t vert_count = counts.vert_count; + + indirect[i].primitive_offset = prim_offset; + indirect[i].vertex_offset = vert_offset; + indirect[i].primitive_count = prim_count; + indirect[i].vertex_count = vert_count; + + prim_offset += prim_count; + vert_offset += vert_count; + } + + memset(indirect + total_meshlets, 0, + (total_padded_meshlets - total_meshlets) * sizeof(RuntimeHeaderDecoded)); + } + else + { + constexpr size_t Stride = sizeof(RuntimeHeaderDecodedMDI); + auto *indirect = static_cast( + cmd.update_buffer(indirect_buffer, alloc_offset * Stride, + view.num_bounds_256 * Stride)); + + for (uint32_t i = 0; i < view.num_bounds_256; i++) + { + uint32_t chunks = std::min(total_meshlets - i * ChunkFactor, ChunkFactor); + + RuntimeHeaderDecodedMDI draw = {}; + draw.firstIndex = 3 * prim_offset; + draw.vertexOffset = int32_t(vert_offset); + + for (uint32_t chunk = 0; chunk < chunks; chunk++) + { + auto &counts = view.streams[(i * ChunkFactor + chunk) * + view.format_header->stream_count].u.counts; + draw.indexCount += counts.prim_count; + vert_offset += counts.vert_count; + prim_offset += counts.prim_count; + } + + draw.indexCount *= 3; + indirect[i] = draw; + } + } +} + +bool decode_mesh(CommandBuffer &cmd, const DecodeInfo &info, const MeshView &view) +{ + if (!cmd.get_device().supports_subgroup_size_log2(true, 5, 7)) + { + LOGE("Device does not support subgroup paths.\n"); + return false; + } + + if (!info.streams[0]) + { + LOGE("Decode stream 0 must be set.\n"); + return false; + } + + if (!info.ibo) + { + LOGE("Output IBO must be set.\n"); + return false; + } + + BufferCreateInfo buf_info = {}; + buf_info.domain = BufferDomain::LinkedDeviceHost; + buf_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + + buf_info.size = view.format_header->meshlet_count * view.format_header->stream_count * sizeof(*view.streams); + auto meshlet_stream_buffer = cmd.get_device().create_buffer(buf_info, view.streams); + + bool meshlet_runtime = info.runtime_style == RuntimeStyle::Meshlet; + cmd.set_program("builtin://shaders/decode/meshlet_decode.comp"); + + cmd.enable_subgroup_size_control(true); + if (cmd.get_device().supports_subgroup_size_log2(true, 5, 5)) + cmd.set_subgroup_size_log2(true, 5, 5); + else + cmd.set_subgroup_size_log2(true, 5, 7); + + cmd.set_storage_buffer(0, 0, *meshlet_stream_buffer); + cmd.set_storage_buffer(0, 1, *info.payload); + cmd.set_storage_buffer(0, 2, *info.ibo); + + cmd.set_specialization_constant_mask(0x1f); + cmd.set_specialization_constant(0, view.format_header->stream_count); + cmd.set_specialization_constant(1, (info.flags & DECODE_MODE_UNROLLED_MESH) != 0); + cmd.set_specialization_constant(2, uint32_t(info.target_style)); + cmd.set_specialization_constant(3, uint32_t(meshlet_runtime)); + cmd.set_specialization_constant(4, (info.flags & DECODE_MODE_INDEX_16) != 0); + + for (unsigned i = 0; i < 3; i++) + cmd.set_storage_buffer(0, 3 + i, info.streams[i] ? *info.streams[i] : *info.streams[0]); + + struct Offsets + { + uint32_t primitive_output_offset; + uint32_t vertex_output_offset; + uint32_t index_offset; + }; + + std::vector decode_offsets; + Offsets offsets = {}; + + decode_offsets.reserve(view.format_header->meshlet_count); + for (uint32_t i = 0; i < view.format_header->meshlet_count; i++) + { + if (info.runtime_style == RuntimeStyle::MDI && (info.flags & DECODE_MODE_UNROLLED_MESH) == 0) + { + uint32_t mdi_start_index = i & ~(Meshlet::ChunkFactor - 1); + if (mdi_start_index == i) + offsets.index_offset = 0; + } + + decode_offsets.push_back(offsets); + + auto &counts = view.streams[i * view.format_header->stream_count].u.counts; + offsets.primitive_output_offset += counts.prim_count; + offsets.vertex_output_offset += counts.vert_count; + + if (!meshlet_runtime) + offsets.index_offset += counts.vert_count; + } + + buf_info.domain = BufferDomain::LinkedDeviceHost; + buf_info.size = decode_offsets.size() * sizeof(decode_offsets.front()); + auto output_offsets_buffer = cmd.get_device().create_buffer(buf_info, decode_offsets.data()); + + cmd.set_storage_buffer(0, 6, *output_offsets_buffer); + + uint32_t wg_x = (view.format_header->meshlet_count + 7) / 8; + + struct Push + { + uint32_t primitive_offset; + uint32_t vertex_offset; + uint32_t meshlet_count; + uint32_t wg_offset; + } push = {}; + + push.primitive_offset = info.push.primitive_offset; + push.vertex_offset = info.push.vertex_offset; + push.meshlet_count = view.format_header->meshlet_count; + push.wg_offset = 0; + + const uint32_t max_wgx = cmd.get_device().get_gpu_properties().limits.maxComputeWorkGroupCount[0]; + for (uint32_t i = 0; i < wg_x; i += max_wgx) + { + uint32_t to_dispatch = std::min(wg_x - i, max_wgx); + push.wg_offset = i; + cmd.push_constants(&push, 0, sizeof(push)); + cmd.dispatch(to_dispatch, 1, 1); + } + + cmd.set_specialization_constant_mask(0); + cmd.enable_subgroup_size_control(false); + + if (info.indirect) + { + upload_indirect_buffer(cmd, *info.indirect, info.indirect_offset, view, info.runtime_style, + info.push.primitive_offset, info.push.vertex_offset); + } + + return true; +} +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/mesh/meshlet.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/mesh/meshlet.hpp new file mode 100644 index 00000000..bc662769 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/mesh/meshlet.hpp @@ -0,0 +1,160 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Granite +{ +class FileMapping; +} + +namespace Vulkan +{ +class CommandBuffer; +class Buffer; +} + +namespace Vulkan +{ +// MESHLET1 format. +namespace Meshlet +{ +static constexpr unsigned MaxStreams = 8; +static constexpr unsigned MaxElements = 32; +static constexpr unsigned ChunkFactor = 256 / MaxElements; + +struct Stream +{ + union + { + uint32_t base_value[2]; + struct { uint32_t prim_count; uint32_t vert_count; } counts; + } u; + uint32_t bits; + uint32_t offset_in_words; +}; +static_assert(sizeof(Stream) == 16, "Unexpected Stream size."); + +struct RuntimeHeaderEncoded +{ + uint32_t stream_offset; +}; + +struct RuntimeHeaderDecoded +{ + uint32_t primitive_offset; + uint32_t vertex_offset; + uint32_t primitive_count; + uint32_t vertex_count; +}; + +struct RuntimeHeaderDecodedMDI +{ + uint32_t indexCount; + uint32_t firstIndex; + int32_t vertexOffset; +}; + +struct Bound +{ + float center[3]; + float radius; + float cone_axis_cutoff[4]; +}; + +enum class StreamType +{ + Primitive = 0, // RGB8_UINT (fixed 5-bit encoding, fixed base value of 0) + Position, // RGB16_SINT * 2^aux + NormalTangentOct8, // Octahedron encoding in RG8, BA8 for tangent. Following uvec4 encodes 1-bit sign. + UV, // (0.5 * (R16G16_SINT * 2^aux) + 0.5 + BoneIndices, // RGBA8_UINT + BoneWeights, // RGBA8_UNORM +}; + +enum class MeshStyle : uint32_t +{ + Wireframe = 0, // Primitive + Position + Textured, // Untextured + TangentOct8 + UV + Skinned // Textured + Bone* +}; + +struct FormatHeader +{ + MeshStyle style; + uint32_t stream_count; + uint32_t meshlet_count; + uint32_t payload_size_words; +}; + +using PayloadWord = uint32_t; + +struct MeshView +{ + const FormatHeader *format_header; + const Bound *bounds; + const Bound *bounds_256; + const Stream *streams; + const PayloadWord *payload; + uint32_t total_primitives; + uint32_t total_vertices; + uint32_t num_bounds; + uint32_t num_bounds_256; +}; + +static const char magic[8] = { 'M', 'E', 'S', 'H', 'L', 'E', 'T', '4' }; + +MeshView create_mesh_view(const Granite::FileMapping &mapping); + +enum DecodeModeFlagBits : uint32_t +{ + DECODE_MODE_UNROLLED_MESH = 1 << 0, + DECODE_MODE_INDEX_16 = 1 << 1, +}; +using DecodeModeFlags = uint32_t; + +enum class RuntimeStyle +{ + MDI, + Meshlet +}; + +struct DecodeInfo +{ + const Vulkan::Buffer *ibo, *streams[3], *indirect, *payload; + DecodeModeFlags flags; + MeshStyle target_style; + RuntimeStyle runtime_style; + + struct + { + uint32_t primitive_offset; + uint32_t vertex_offset; + } push; + uint32_t indirect_offset; +}; + +bool decode_mesh(Vulkan::CommandBuffer &cmd, const DecodeInfo &decode_info, const MeshView &view); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_cache.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_cache.cpp new file mode 100644 index 00000000..473f29b7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_cache.cpp @@ -0,0 +1,680 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "pipeline_cache.hpp" +#include "device.hpp" + +namespace Vulkan +{ +PipelineCache::Binary::Binary(const VkPipelineBinaryKeyKHR &key_, const void *payload_, size_t payload_size_) + : device(nullptr), key(key_), payload(payload_), payload_size(payload_size_) +{ +} + +PipelineCache::Binary::Binary(Vulkan::Device &device_, const VkPipelineBinaryKeyKHR &key_, VkPipelineBinaryKHR binary_) + : device(&device_), key(key_), binary(binary_) +{ + VkPipelineBinaryDataInfoKHR data_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_DATA_INFO_KHR }; + VkPipelineBinaryKeyKHR dummy_key = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_KEY_KHR }; + data_info.pipelineBinary = binary; + device->get_device_table().vkGetPipelineBinaryDataKHR(device->get_device(), &data_info, &dummy_key, &payload_size, nullptr); +} + +PipelineCache::Binary::~Binary() +{ + if (device) + device->get_device_table().vkDestroyPipelineBinaryKHR(device->get_device(), binary, nullptr); +} + +PipelineCache::PipelineCache(Device *device_) + : device(*device_), new_entries(false) +{ +} + +PipelineCache::~PipelineCache() +{ +} + +Util::Hash PipelineCache::get_create_info_key(const void *create_info) const +{ + VkPipelineCreateInfoKHR key_create_info = { VK_STRUCTURE_TYPE_PIPELINE_CREATE_INFO_KHR }; + VkPipelineBinaryKeyKHR global_key = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_KEY_KHR }; + key_create_info.pNext = const_cast(create_info); + if (device.get_device_table().vkGetPipelineKeyKHR(device.get_device(), &key_create_info, &global_key) != VK_SUCCESS) + return false; + + Util::Hasher h; + h.data(global_key.key, global_key.keySize); + return h.get(); +} + +bool PipelineCache::place_binary(VkPipelineBinaryKHR binary, Util::Hash *hash) +{ + VkPipelineBinaryDataInfoKHR data_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_DATA_INFO_KHR }; + VkPipelineBinaryKeyKHR key = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_KEY_KHR }; + data_info.pipelineBinary = binary; + size_t data_size = 0; + + if (device.get_device_table().vkGetPipelineBinaryDataKHR( + device.get_device(), &data_info, &key, &data_size, nullptr) != VK_SUCCESS) + { + LOGE("Failed to get pipeline binary key.\n"); + return false; + } + + VK_ASSERT(key.keySize); + + Util::Hasher h; + h.data(key.key, key.keySize); + *hash = h.get(); + + static constexpr uint32_t AllZero[VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR] = {}; + if (memcmp(AllZero, key.key, VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR) == 0) + { + LOGW("Driver seems broken? Key is all zeros ...\n"); + return false; + } + + if (binaries.find(h.get())) + device.get_device_table().vkDestroyPipelineBinaryKHR(device.get_device(), binary, nullptr); + else + binaries.emplace_yield(h.get(), device, key, binary); + + return true; +} + +void PipelineCache::place_pipeline(Util::Hash hash, VkPipeline pipeline) +{ + const auto release_binaries = [&]() + { + VkReleaseCapturedPipelineDataInfoKHR release_info = { VK_STRUCTURE_TYPE_RELEASE_CAPTURED_PIPELINE_DATA_INFO_KHR }; + release_info.pipeline = pipeline; + device.get_device_table().vkReleaseCapturedPipelineDataKHR(device.get_device(), &release_info, nullptr); + }; + + if (binary_mapping.find(hash) != nullptr) + { + release_binaries(); + return; + } + + VkPipelineBinaryCreateInfoKHR create_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_CREATE_INFO_KHR }; + create_info.pipeline = pipeline; + VkPipelineBinaryHandlesInfoKHR handles_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_HANDLES_INFO_KHR }; + + if (device.get_device_table().vkCreatePipelineBinariesKHR( + device.get_device(), &create_info, nullptr, &handles_info) != VK_SUCCESS || + handles_info.pipelineBinaryCount == 0) + { + LOGE("Failed to query pipeline binaries from pipeline.\n"); + release_binaries(); + return; + } + + Util::SmallVector out_binaries(handles_info.pipelineBinaryCount); + handles_info.pPipelineBinaries = out_binaries.data(); + + if (device.get_device_table().vkCreatePipelineBinariesKHR( + device.get_device(), &create_info, nullptr, &handles_info) != VK_SUCCESS) + { + LOGE("Failed to query pipeline binaries from pipeline.\n"); + release_binaries(); + return; + } + + release_binaries(); + + Util::SmallVector keys; + keys.resize(out_binaries.size()); + auto *pkeys = keys.data(); + + for (auto &binary : out_binaries) + if (!place_binary(binary, pkeys++)) + return; + + binary_mapping.emplace_yield(hash, std::move(keys)); + new_entries.store(true, std::memory_order_release); +} + +bool PipelineCache::find_pipeline_binaries_from_internal_cache(const void *pso_create_info, + Util::SmallVector &out_binaries, + Util::SmallVector &out_binaries_owned) +{ + out_binaries.clear(); + out_binaries_owned.clear(); + + VkPipelineBinaryCreateInfoKHR create_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_CREATE_INFO_KHR }; + VkPipelineCreateInfoKHR pipeline_create_info = { VK_STRUCTURE_TYPE_PIPELINE_CREATE_INFO_KHR, const_cast(pso_create_info) }; + create_info.pPipelineCreateInfo = &pipeline_create_info; + + out_binaries.resize(32); + + // Ideally we don't query twice, just assume we're not going to receive more than 32 binaries in one go. + // For graphics and compute, this is surely fine ... :') + VkPipelineBinaryHandlesInfoKHR handles_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_HANDLES_INFO_KHR }; + handles_info.pPipelineBinaries = out_binaries.data(); + handles_info.pipelineBinaryCount = 32; + + auto result = device.get_device_table().vkCreatePipelineBinariesKHR( + device.get_device(), &create_info, nullptr, &handles_info); + + out_binaries.resize(handles_info.pipelineBinaryCount); + + if (result != VK_SUCCESS) + { + for (auto &b : out_binaries) + device.get_device_table().vkDestroyPipelineBinaryKHR(device.get_device(), b, nullptr); + out_binaries.clear(); + return false; + } + + for (uint32_t i = 0; i < handles_info.pipelineBinaryCount; i++) + out_binaries_owned.push_back(true); + + return true; +} + +bool PipelineCache::find_pipeline_binaries(Util::Hash pso_hash, + Util::SmallVector &out_binaries, + Util::SmallVector &out_binaries_owned) +{ + auto *mapped = binary_mapping.find(pso_hash); + if (!mapped) + return false; + + out_binaries.clear(); + out_binaries_owned.clear(); + + for (auto &hash : mapped->hashes) + { + auto *existing_binary = binaries.find(hash); + + if (!existing_binary) + { + for (auto &binary: out_binaries) + device.get_device_table().vkDestroyPipelineBinaryKHR(device.get_device(), binary, nullptr); + out_binaries.clear(); + return false; + } + + VkPipelineBinaryKHR binary = VK_NULL_HANDLE; + + if (existing_binary->binary) + { + binary = existing_binary->binary; + out_binaries_owned.push_back(false); + } + else + { + VkPipelineBinaryCreateInfoKHR create_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_CREATE_INFO_KHR }; + VkPipelineBinaryKeysAndDataKHR keys_and_data_info = {}; + VkPipelineBinaryDataKHR binary_data = {}; + keys_and_data_info.binaryCount = 1; + keys_and_data_info.pPipelineBinaryKeys = &existing_binary->key; + VK_ASSERT(existing_binary->key.keySize); + keys_and_data_info.pPipelineBinaryData = &binary_data; + create_info.pKeysAndDataInfo = &keys_and_data_info; + binary_data.pData = const_cast(existing_binary->payload); + binary_data.dataSize = existing_binary->payload_size; + + VkPipelineBinaryHandlesInfoKHR handles_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_HANDLES_INFO_KHR }; + handles_info.pPipelineBinaries = &binary; + handles_info.pipelineBinaryCount = 1; + + if (device.get_device_table().vkCreatePipelineBinariesKHR( + device.get_device(), &create_info, nullptr, &handles_info) != VK_SUCCESS || + handles_info.pipelineBinaryCount != 1 || + handles_info.pPipelineBinaries[0] == VK_NULL_HANDLE) + { + for (auto &b : out_binaries) + device.get_device_table().vkDestroyPipelineBinaryKHR(device.get_device(), b, nullptr); + out_binaries.clear(); + return false; + } + } + + out_binaries_owned.push_back(existing_binary->binary == VK_NULL_HANDLE); + out_binaries.push_back(binary); + } + + return true; +} + +bool PipelineCache::init_from_payload(const void *payload, size_t size, bool persistent_mapping) +{ + if (!size) + return true; + + if (!persistent_mapping) + { + payload_holder.reset(new uint8_t[size]); + memcpy(payload_holder.get(), payload, size); + payload = payload_holder.get(); + } + + if (!parse(payload, size)) + return false; + + return true; +} + +static constexpr char CacheUUID[VK_UUID_SIZE] = "GraniteBinary1"; + +bool PipelineCache::parse(const void *payload_, size_t size) +{ + if (!device.get_device_features().pipeline_binary_features.pipelineBinaries) + return false; + + constexpr size_t minimum_size = VK_UUID_SIZE + sizeof(uint32_t) + + VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR + sizeof(uint32_t); + if (size < minimum_size) + return false; + + auto *payload = static_cast(payload_); + + if (memcmp(payload, CacheUUID, sizeof(CacheUUID)) != 0) + return false; + payload += VK_UUID_SIZE; + + VkPipelineBinaryKeyKHR key = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_KEY_KHR }; + device.get_device_table().vkGetPipelineKeyKHR(device.get_device(), nullptr, &key); + + if (memcmp(payload, &key.keySize, sizeof(uint32_t)) != 0) + { + LOGW("Pipeline binary global key changed, resetting the cache ...\n"); + return true; + } + + payload += sizeof(uint32_t); + + if (memcmp(payload, key.key, key.keySize) != 0) + { + LOGW("Pipeline binary global key changed, resetting the cache ...\n"); + return true; + } + payload += VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR; + + uint32_t num_pipelines = *reinterpret_cast(payload); + payload += sizeof(uint32_t); + auto *payload64 = reinterpret_cast(payload); + size -= minimum_size; + + const auto read_u64 = [&]() -> uint64_t { + if (size >= sizeof(uint64_t)) + { + auto data = *payload64++; + size -= sizeof(uint64_t); + return data; + } + else + return 0; + }; + + for (uint32_t i = 0; i < num_pipelines; i++) + { + Util::SmallVector hashes; + auto hash = read_u64(); + auto num_hashes = uint32_t(read_u64()); + for (uint32_t j = 0; j < num_hashes; j++) + hashes.push_back(read_u64()); + binary_mapping.emplace_yield(hash, std::move(hashes)); + } + + auto num_binaries = uint32_t(read_u64()); + for (uint32_t i = 0; i < num_binaries; i++) + { + auto hash = read_u64(); + + union + { + struct + { + uint32_t size; + uint32_t key_size; + }; + uint64_t word; + } u; + u.word = read_u64(); + + if (size < VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR) + return false; + + key.keySize = u.key_size; + memcpy(key.key, payload64, sizeof(key.key)); + payload64 += VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR / sizeof(uint64_t); + size -= VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR; + + auto padded_size = (u.size + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1); + + if (size < padded_size) + return false; + + binaries.emplace_yield(hash, key, payload64, u.size); + payload64 += padded_size / sizeof(uint64_t); + size -= padded_size; + } + + if (size == 0) + LOGI("Successfully parsed %u pipelines and %u binary blobs.\n", num_pipelines, num_binaries); + + return size == 0; +} + +bool PipelineCache::has_new_binary_entries() const +{ + return new_entries.load(std::memory_order_acquire); +} + +size_t PipelineCache::get_serialized_size() const +{ + // Granite's magic UUID. + size_t size = VK_UUID_SIZE; + + // Driver's global key. + size += sizeof(uint32_t); + size += VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR; + + // Pipeline number count. + size += sizeof(uint32_t); + + for (auto &mapping : binary_mapping.get_thread_unsafe()) + { + // Count + Keys per pipeline. + size += sizeof(Util::Hash) + sizeof(uint64_t) + mapping.hashes.size() * sizeof(Util::Hash); + } + + // Binary count. + size += sizeof(uint64_t); + + for (auto &binary : binaries.get_thread_unsafe()) + { + size += sizeof(Util::Hash); // Hash + size += sizeof(uint32_t); // Size + size += sizeof(uint32_t); // Key size + size += VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR; + size += (binary.payload_size + 7) & ~size_t(7); // Padded payload + } + + return size; +} + +bool PipelineCache::serialize(void *data_, size_t size) const +{ + if (size < get_serialized_size()) + return false; + + auto *data = static_cast(data_); + memcpy(data, CacheUUID, sizeof(CacheUUID)); + data += VK_UUID_SIZE; + + VkPipelineBinaryKeyKHR key = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_KEY_KHR }; + device.get_device_table().vkGetPipelineKeyKHR(device.get_device(), nullptr, &key); + memcpy(data, &key.keySize, sizeof(key.keySize)); + data += sizeof(uint32_t); + memcpy(data, key.key, sizeof(key.key)); + data += sizeof(key.key); + + uint32_t pipeline_count = 0; + for (auto &mapping : binary_mapping.get_thread_unsafe()) + { + (void)mapping; + pipeline_count++; + } + + memcpy(data, &pipeline_count, sizeof(pipeline_count)); + data += sizeof(uint32_t); + + auto *data64 = reinterpret_cast(data); + + for (auto &mapping : binary_mapping.get_thread_unsafe()) + { + *data64++ = mapping.get_hash(); + *data64++ = mapping.hashes.size(); + for (auto &hash : mapping.hashes) + *data64++ = hash; + } + + uint32_t binary_count = 0; + for (auto &mapping : binaries.get_thread_unsafe()) + { + (void)mapping; + binary_count++; + } + + *data64++ = binary_count; + for (auto &mapping : binaries.get_thread_unsafe()) + { + *data64++ = mapping.get_hash(); + const uint32_t words[] = { uint32_t(mapping.payload_size), mapping.key.keySize }; + memcpy(data64, words, sizeof(words)); + data64++; + memcpy(data64, mapping.key.key, sizeof(mapping.key.key)); + data64 += VK_MAX_PIPELINE_BINARY_KEY_SIZE_KHR / sizeof(uint64_t); + + VK_ASSERT(mapping.binary || mapping.payload); + + if (mapping.binary) + { + // TODO: Ignore compressed property for now. + VkPipelineBinaryDataInfoKHR data_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_DATA_INFO_KHR }; + VkPipelineBinaryKeyKHR dummy_key = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_KEY_KHR }; + data_info.pipelineBinary = mapping.binary; + size_t payload_size = mapping.payload_size; + device.get_device_table().vkGetPipelineBinaryDataKHR(device.get_device(), &data_info, &dummy_key, + &payload_size, data64); + } + else + { + memcpy(data64, mapping.payload, mapping.payload_size); + } + + data64 += (mapping.payload_size + sizeof(uint64_t) - 1) / sizeof(uint64_t); + } + + LOGI("Serialized %u pipelines and %u binary blobs.\n", pipeline_count, binary_count); + return true; +} + +template +static inline const T *find_pnext(VkStructureType type, const void *pNext) +{ + while (pNext != nullptr) + { + auto *sin = static_cast(pNext); + if (sin->sType == type) + return static_cast(pNext); + + pNext = sin->pNext; + } + + return nullptr; +} + +VkPipeline PipelineCache::create_pipeline_and_place(Util::Hash pso_key, void *plain_info) +{ + auto *graphics_info = static_cast(plain_info); + auto *compute_info = static_cast(plain_info); + if (graphics_info && graphics_info->sType != VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO) + graphics_info = nullptr; + if (compute_info && compute_info->sType != VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO) + compute_info = nullptr; + + VkPipelineCreateFlags2CreateInfoKHR flags2 = { VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR }; + VkPipeline pipe = VK_NULL_HANDLE; + + if (!device.get_device_features().pipeline_binary_properties.pipelineBinaryPrefersInternalCache) + { + auto *existing_flags2 = find_pnext( + VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR, plain_info); + + if (existing_flags2) + { + const_cast(existing_flags2)->flags |= + VK_PIPELINE_CREATE_2_CAPTURE_DATA_BIT_KHR; + } + else + { + flags2.flags = VK_PIPELINE_CREATE_2_CAPTURE_DATA_BIT_KHR; + + if (graphics_info) + { + flags2.flags |= graphics_info->flags; + flags2.pNext = graphics_info->pNext; + graphics_info->pNext = &flags2; + } + else if (compute_info) + { + flags2.flags |= compute_info->flags; + flags2.pNext = compute_info->pNext; + compute_info->pNext = &flags2; + } + } + } + + if ((compute_info && device.get_device_table().vkCreateComputePipelines( + device.get_device(), VK_NULL_HANDLE, 1, compute_info, nullptr, &pipe) != VK_SUCCESS) || + (graphics_info && device.get_device_table().vkCreateGraphicsPipelines( + device.get_device(), VK_NULL_HANDLE, 1, graphics_info, nullptr, &pipe) != VK_SUCCESS)) + { + LOGE("Failed to create pipeline from binaries.\n"); + pipe = VK_NULL_HANDLE; + } + + if (!device.get_device_features().pipeline_binary_properties.pipelineBinaryPrefersInternalCache && + pipe != VK_NULL_HANDLE) + { + place_pipeline(pso_key, pipe); + } + + return pipe; +} + +VkPipeline +PipelineCache::create_pipeline_from_binaries( + void *plain_info, const VkPipelineBinaryKHR *found_binaries, + const bool *binaries_owned, size_t binary_count) +{ + auto *graphics_info = static_cast(plain_info); + auto *compute_info = static_cast(plain_info); + if (graphics_info && graphics_info->sType != VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO) + graphics_info = nullptr; + if (compute_info && compute_info->sType != VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO) + compute_info = nullptr; + + // Cache hit :3 + VkPipelineBinaryInfoKHR binary_info = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_INFO_KHR }; + binary_info.pPipelineBinaries = found_binaries; + binary_info.binaryCount = binary_count; + + constexpr VkPipelineCreateFlags invalid_flags = + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT | + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT; + + if (compute_info) + { + compute_info->stage.module = VK_NULL_HANDLE; + binary_info.pNext = compute_info->pNext; + compute_info->pNext = &binary_info; + compute_info->flags &= ~invalid_flags; + } + else if (graphics_info) + { + for (uint32_t i = 0; i < graphics_info->stageCount; i++) + const_cast(graphics_info->pStages[i]).module = VK_NULL_HANDLE; + binary_info.pNext = graphics_info->pNext; + graphics_info->pNext = &binary_info; + graphics_info->flags &= ~invalid_flags; + } + + VkPipeline pipe = VK_NULL_HANDLE; + + if ((compute_info && device.get_device_table().vkCreateComputePipelines( + device.get_device(), VK_NULL_HANDLE, 1, compute_info, nullptr, &pipe) != VK_SUCCESS) || + (graphics_info && device.get_device_table().vkCreateGraphicsPipelines( + device.get_device(), VK_NULL_HANDLE, 1, graphics_info, nullptr, &pipe) != VK_SUCCESS)) + { + LOGE("Failed to create pipeline from binaries.\n"); + pipe = VK_NULL_HANDLE; + } + + for (size_t i = 0; i < binary_count; i++) + if (binaries_owned[i]) + device.get_device_table().vkDestroyPipelineBinaryKHR(device.get_device(), found_binaries[i], nullptr); + + return pipe; +} + +VkResult PipelineCache::create_pipeline(void *plain_info, VkPipelineCache cache, VkPipeline *pipe) +{ + *pipe = VK_NULL_HANDLE; + auto *graphics_info = static_cast(plain_info); + auto *compute_info = static_cast(plain_info); + if (graphics_info && graphics_info->sType != VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO) + graphics_info = nullptr; + if (compute_info && compute_info->sType != VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO) + compute_info = nullptr; + + if (!device.get_device_features().pipeline_binary_features.pipelineBinaries) + { + if (compute_info) + { + return device.get_device_table().vkCreateComputePipelines( + device.get_device(), cache, 1, compute_info, nullptr, pipe); + } + else if (graphics_info) + { + return device.get_device_table().vkCreateGraphicsPipelines( + device.get_device(), cache, 1, graphics_info, nullptr, pipe); + } + else + return VK_ERROR_INITIALIZATION_FAILED; + } + + auto pso_key = get_create_info_key(plain_info); + Util::SmallVector pipeline_binaries; + Util::SmallVector pipeline_binaries_owned; + + if (find_pipeline_binaries(pso_key, pipeline_binaries, pipeline_binaries_owned)) + { + *pipe = create_pipeline_from_binaries(plain_info, pipeline_binaries.data(), pipeline_binaries_owned.data(), + pipeline_binaries.size()); + return *pipe ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY; + } + + if (device.get_device_features().pipeline_binary_properties.pipelineBinaryInternalCache && + !device.get_device_features().pipeline_binary_internal_cache_control.disableInternalCache && + find_pipeline_binaries_from_internal_cache(plain_info, pipeline_binaries, pipeline_binaries_owned)) + { + *pipe = create_pipeline_from_binaries(plain_info, pipeline_binaries.data(), pipeline_binaries_owned.data(), + pipeline_binaries.size()); + return *pipe ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY; + } + + if (graphics_info && (graphics_info->flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0) + return VK_PIPELINE_COMPILE_REQUIRED; + if (compute_info && (compute_info->flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0) + return VK_PIPELINE_COMPILE_REQUIRED; + + *pipe = create_pipeline_and_place(pso_key, plain_info); + return *pipe ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_cache.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_cache.hpp new file mode 100644 index 00000000..7820d79f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_cache.hpp @@ -0,0 +1,92 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include +#include "vulkan_headers.hpp" +#include "small_vector.hpp" +#include "intrusive_hash_map.hpp" +#include +#include + +namespace Vulkan +{ +class Device; +class PipelineCache +{ +public: + explicit PipelineCache(Device *device); + ~PipelineCache(); + + bool init_from_payload(const void *payload, size_t size, bool persistent_mapping); + bool has_new_binary_entries() const; + size_t get_serialized_size() const; + bool serialize(void *data, size_t size) const; + + VkResult create_pipeline(void *info, VkPipelineCache cache, VkPipeline *pipe); + +private: + Device &device; + std::unique_ptr payload_holder; + + struct PipelineBinaryMapping : Util::IntrusiveHashMapEnabled + { + explicit PipelineBinaryMapping(Util::SmallVector hashes_) + : hashes(std::move(hashes_)) {} + Util::SmallVector hashes; + }; + Util::ThreadSafeIntrusiveHashMap binary_mapping; + + struct Binary : Util::IntrusiveHashMapEnabled + { + Binary(Device &device, const VkPipelineBinaryKeyKHR &key, VkPipelineBinaryKHR binary); + Binary(const VkPipelineBinaryKeyKHR &key, const void *payload, size_t payload_size); + ~Binary(); + + Device *device; + VkPipelineBinaryKeyKHR key = { VK_STRUCTURE_TYPE_PIPELINE_BINARY_KEY_KHR }; + VkPipelineBinaryKHR binary = VK_NULL_HANDLE; + const void *payload = nullptr; + size_t payload_size = 0; + }; + Util::ThreadSafeIntrusiveHashMap binaries; + + bool place_binary(VkPipelineBinaryKHR binary, Util::Hash *hash); + bool parse(const void *payload, size_t size); + std::atomic_bool new_entries; + + Util::Hash get_create_info_key(const void *create_info) const; + bool find_pipeline_binaries(Util::Hash hash, + Util::SmallVector &binaries, + Util::SmallVector &binaries_owned); + + bool find_pipeline_binaries_from_internal_cache(const void *create_info, + Util::SmallVector &binaries, + Util::SmallVector &binaries_owned); + + void place_pipeline(Util::Hash hash, VkPipeline pipeline); + VkPipeline create_pipeline_from_binaries( + void *info, const VkPipelineBinaryKHR *binaries, const bool *binaries_owned, size_t binary_count); + VkPipeline create_pipeline_and_place(Util::Hash pso_key, void *info); +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_event.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_event.cpp new file mode 100644 index 00000000..0d53d610 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_event.cpp @@ -0,0 +1,43 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "pipeline_event.hpp" +#include "device.hpp" + +namespace Vulkan +{ +EventHolder::~EventHolder() +{ + if (event) + { + if (internal_sync) + device->destroy_event_nolock(event); + else + device->destroy_event(event); + } +} + +void EventHolderDeleter::operator()(Vulkan::EventHolder *event) +{ + event->device->handle_pool.events.free(event); +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_event.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_event.hpp new file mode 100644 index 00000000..93a0e34c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/pipeline_event.hpp @@ -0,0 +1,67 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include "vulkan_common.hpp" +#include "cookie.hpp" +#include "object_pool.hpp" + +namespace Vulkan +{ +class Device; +class EventHolder; + +struct EventHolderDeleter +{ + void operator()(EventHolder *event); +}; + +class EventHolder : public Util::IntrusivePtrEnabled, + public InternalSyncEnabled +{ +public: + friend struct EventHolderDeleter; + + ~EventHolder(); + + const VkEvent &get_event() const + { + return event; + } + +private: + friend class Util::ObjectPool; + EventHolder(Device *device_, VkEvent event_) + : device(device_) + , event(event_) + { + } + + Device *device; + VkEvent event; +}; + +using PipelineEvent = Util::IntrusivePtr; + +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/CMakeLists.txt b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/CMakeLists.txt new file mode 100644 index 00000000..7500f538 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/CMakeLists.txt @@ -0,0 +1,25 @@ +add_granite_internal_lib(granite-vulkan-post-mortem + post_mortem.cpp post_mortem.hpp) + +target_include_directories(granite-vulkan-post-mortem PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(granite-vulkan-post-mortem PRIVATE granite-util) + +if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + set(AFTERMATH_ARCH x64) +else() + set(AFTERMATH_ARCH x86) +endif() + +find_library(GFSDK_LIBRARY GFSDK_Aftermath_Lib.x64 HINTS ${AFTERMATH_SDK_PATH}/lib/${AFTERMATH_ARCH}) + +if (GFSDK_LIBRARY) + target_sources(granite-vulkan-post-mortem PRIVATE + NsightAftermathGpuCrashTracker.cpp NsightAftermathGpuCrashTracker.h + NsightAftermathHelpers.h) + target_compile_definitions(granite-vulkan-post-mortem PRIVATE HAVE_AFTERMATH_SDK) + target_link_libraries(granite-vulkan-post-mortem PRIVATE ${GFSDK_LIBRARY} granite-volk-headers) + target_include_directories(granite-vulkan-post-mortem PRIVATE ${AFTERMATH_SDK_PATH}/include) + message("Found Aftermath SDK.") +else() + message("Did not find Aftermath SDK in AFTERMATH_SDK_PATH=${AFTERMATH_SDK_PATH}.") +endif() diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/NsightAftermathGpuCrashTracker.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/NsightAftermathGpuCrashTracker.cpp new file mode 100644 index 00000000..06176b2c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/NsightAftermathGpuCrashTracker.cpp @@ -0,0 +1,422 @@ +//********************************************************* +// +// Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. +// +// 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. +// +//********************************************************* + +#include +#include +#include +#include +#include "logging.hpp" + +#include "NsightAftermathGpuCrashTracker.h" + +#ifdef _WIN32 +#include +#endif + +// Modified from the official sample to fit Granite better. + +//********************************************************* +// GpuCrashTracker implementation +//********************************************************* + +GpuCrashTracker::GpuCrashTracker(const MarkerMap& markerMap) + : m_initialized(false) + , m_mutex() + , m_shaderDebugInfo() + , m_markerMap(markerMap) +{ +} + +GpuCrashTracker::~GpuCrashTracker() +{ + // If initialized, disable GPU crash dumps + if (m_initialized) + { + GFSDK_Aftermath_DisableGpuCrashDumps(); + } +} + +// Initialize the GPU Crash Dump Tracker +void GpuCrashTracker::Initialize() +{ + // Enable GPU crash dumps and set up the callbacks for crash dump notifications, + // shader debug information notifications, and providing additional crash + // dump description data.Only the crash dump callback is mandatory. The other two + // callbacks are optional and can be omitted, by passing nullptr, if the corresponding + // functionality is not used. + // The DeferDebugInfoCallbacks flag enables caching of shader debug information data + // in memory. If the flag is set, ShaderDebugInfoCallback will be called only + // in the event of a crash, right before GpuCrashDumpCallback. If the flag is not set, + // ShaderDebugInfoCallback will be called for every shader that is compiled. + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_EnableGpuCrashDumps( + GFSDK_Aftermath_Version_API, + GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_Vulkan, + GFSDK_Aftermath_GpuCrashDumpFeatureFlags_DeferDebugInfoCallbacks, // Let the Nsight Aftermath library cache shader debug information. + GpuCrashDumpCallback, // Register callback for GPU crash dumps. + ShaderDebugInfoCallback, // Register callback for shader debug information. + CrashDumpDescriptionCallback, // Register callback for GPU crash dump description. + ResolveMarkerCallback, // Register callback for resolving application-managed markers. + this)); // Set the GpuCrashTracker object as user data for the above callbacks. + + m_initialized = true; +} + +// Handler for GPU crash dump callbacks from Nsight Aftermath +void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) +{ + // Make sure only one thread at a time... + std::lock_guard lock(m_mutex); + + // Write to file for later in-depth analysis with Nsight Graphics. + WriteGpuCrashDumpToFile(pGpuCrashDump, gpuCrashDumpSize); +} + +// Handler for shader debug information callbacks +void GpuCrashTracker::OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize) +{ + // Make sure only one thread at a time... + std::lock_guard lock(m_mutex); + + // Get shader debug information identifier + GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier = {}; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderDebugInfoIdentifier( + GFSDK_Aftermath_Version_API, + pShaderDebugInfo, + shaderDebugInfoSize, + &identifier)); + + // Store information for decoding of GPU crash dumps with shader address mapping + // from within the application. + std::vector data((uint8_t*)pShaderDebugInfo, (uint8_t*)pShaderDebugInfo + shaderDebugInfoSize); + m_shaderDebugInfo[identifier].swap(data); + + // Write to file for later in-depth analysis of crash dumps with Nsight Graphics + WriteShaderDebugInformationToFile(identifier, pShaderDebugInfo, shaderDebugInfoSize); +} + +// Handler for GPU crash dump description callbacks +void GpuCrashTracker::OnDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription) +{ + // Add some basic description about the crash. This is called after the GPU crash happens, but before + // the actual GPU crash dump callback. The provided data is included in the crash dump and can be + // retrieved using GFSDK_Aftermath_GpuCrashDump_GetDescription(). + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, "Granite"); + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationVersion, "v1.0"); +} + +// Handler for app-managed marker resolve callback +void GpuCrashTracker::OnResolveMarker(const void* pMarkerData, const uint32_t, void** ppResolvedMarkerData, uint32_t* pResolvedMarkerDataSize) +{ + // Important: the pointer passed back via ppResolvedMarkerData must remain valid after this function returns + // using references for all of the m_markerMap accesses ensures that the pointers refer to the persistent data + for (auto& map : m_markerMap) + { + const auto& foundMarker = map.find((uint64_t)pMarkerData); + if (foundMarker != map.end()) + { + const std::string& foundMarkerData = foundMarker->second; + // std::string::data() will return a valid pointer until the string is next modified + // we don't modify the string after calling data() here, so the pointer should remain valid + *ppResolvedMarkerData = (void*)foundMarkerData.data(); + *pResolvedMarkerDataSize = (uint32_t)foundMarkerData.length(); + return; + } + } +} + +// Helper for writing a GPU crash dump to a file +void GpuCrashTracker::WriteGpuCrashDumpToFile(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) +{ + // Create a GPU crash dump decoder object for the GPU crash dump. + GFSDK_Aftermath_GpuCrashDump_Decoder decoder = {}; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_CreateDecoder( + GFSDK_Aftermath_Version_API, + pGpuCrashDump, + gpuCrashDumpSize, + &decoder)); + + // Use the decoder object to read basic information, like application + // name, PID, etc. from the GPU crash dump. + GFSDK_Aftermath_GpuCrashDump_BaseInfo baseInfo = {}; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetBaseInfo(decoder, &baseInfo)); + + // Use the decoder object to query the application name that was set + // in the GPU crash dump description. + uint32_t applicationNameLength = 0; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetDescriptionSize( + decoder, + GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, + &applicationNameLength)); + + std::vector applicationName(applicationNameLength, '\0'); + + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetDescription( + decoder, + GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, + uint32_t(applicationName.size()), + applicationName.data())); + + // Create a unique file name for writing the crash dump data to a file. + // Note: due to an Nsight Aftermath bug (will be fixed in an upcoming + // driver release) we may see redundant crash dumps. As a workaround, + // attach a unique count to each generated file name. + static int count = 0; + const std::string baseFileName = + std::string(applicationName.data()) + + "-" + + std::to_string(baseInfo.pid) + + "-" + + std::to_string(++count); + + // Write the crash dump data to a file using the .nv-gpudmp extension + // registered with Nsight Graphics. + const std::string crashDumpFileName = baseFileName + ".nv-gpudmp"; + std::ofstream dumpFile(crashDumpFileName, std::ios::out | std::ios::binary); + if (dumpFile) + { + dumpFile.write((const char*)pGpuCrashDump, gpuCrashDumpSize); + dumpFile.close(); + LOGI("Wrote crash dump file to: %s.\n", crashDumpFileName.c_str()); + } + + // Decode the crash dump to a JSON string. + // Step 1: Generate the JSON and get the size. + uint32_t jsonSize = 0; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GenerateJSON( + decoder, + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_ALL_INFO, + GFSDK_Aftermath_GpuCrashDumpFormatterFlags_NONE, + ShaderDebugInfoLookupCallback, + ShaderLookupCallback, + ShaderSourceDebugInfoLookupCallback, + this, + &jsonSize)); + + // Step 2: Allocate a buffer and fetch the generated JSON. + std::vector json(jsonSize); + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetJSON( + decoder, + uint32_t(json.size()), + json.data())); + + // Write the crash dump data as JSON to a file. + const std::string jsonFileName = crashDumpFileName + ".json"; + std::ofstream jsonFile(jsonFileName, std::ios::out | std::ios::binary); + if (jsonFile) + { + // Write the JSON to the file (excluding string termination) + jsonFile.write(json.data(), json.size() - 1); + jsonFile.close(); + LOGI("Wrote crash dump JSON file to: %s.\n", jsonFileName.c_str()); + } + + // Dump active SPIR-V files. + uint32_t shader_count = 0; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfoCount(decoder, &shader_count)); + std::vector shader_infos(shader_count); + AFTERMATH_CHECK_ERROR( + GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfo(decoder, shader_count, shader_infos.data())); + + for (auto &shader : shader_infos) + { + GFSDK_Aftermath_ShaderBinaryHash hash; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderHashForShaderInfo(decoder, &shader, &hash)); + + std::lock_guard holder{ shader_lock }; + auto itr = shader_db.find(hash); + if (itr != shader_db.end()) + { + const std::string spirvFilePath = "shader_" + std::to_string(hash) + ".spv"; + std::ofstream spirvFile(spirvFilePath, std::ios::out | std::ios::binary); + if (spirvFile) + { + spirvFile.write((const char *)itr->second.data(), itr->second.size() * sizeof(uint32_t)); + LOGI("Wrote SPIR-V shader file to: %s.\n", spirvFilePath.c_str()); + } + } + } + + // Destroy the GPU crash dump decoder object. + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_DestroyDecoder(decoder)); + +#ifdef _WIN32 + char print_buffer[1024]; + char current_dir[1024]; + + GetCurrentDirectoryA(sizeof(current_dir), current_dir); + snprintf(print_buffer, sizeof(print_buffer), + "GPU hang detected with NV Aftermath. Dump files have been written to %s\\%s. Terminating process ...", + current_dir, crashDumpFileName.c_str()); + MessageBoxA(nullptr, print_buffer, "VK_ERROR_DEVICE_LOST", MB_OK); + TerminateProcess(GetCurrentProcess(), 1); +#else + std::terminate(); +#endif +} + +void GpuCrashTracker::RegisterShader(const void *code, size_t size) +{ + std::vector data(static_cast(code), + static_cast(code) + size / sizeof(uint32_t)); + + // Create shader hash for the shader + const GFSDK_Aftermath_SpirvCode shader{{data.data()}, uint32_t(size)}; + GFSDK_Aftermath_ShaderBinaryHash shaderHash; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderHashSpirv( + GFSDK_Aftermath_Version_API, + &shader, + &shaderHash)); + + // Store the data for shader mapping when decoding GPU crash dumps. + // cf. FindShaderBinary() + std::lock_guard holder{shader_lock}; + shader_db[shaderHash].swap(data); +} + +// Helper for writing shader debug information to a file +void GpuCrashTracker::WriteShaderDebugInformationToFile( + GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier, + const void* pShaderDebugInfo, + const uint32_t shaderDebugInfoSize) +{ + // Create a unique file name. + const std::string filePath = "shader-" + std::to_string(identifier) + ".nvdbg"; + + std::ofstream f(filePath, std::ios::out | std::ios::binary); + if (f) + { + f.write((const char*)pShaderDebugInfo, shaderDebugInfoSize); + LOGI("Wrote shader file to: %s.\n", filePath.c_str()); + } +} + +// Handler for shader debug information lookup callbacks. +// This is used by the JSON decoder for mapping shader instruction +// addresses to SPIR-V IL lines or GLSL source lines. +void GpuCrashTracker::OnShaderDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo) const +{ + auto itr = m_shaderDebugInfo.find(identifier); + if (itr != m_shaderDebugInfo.end()) + setShaderDebugInfo(itr->second.data(), uint32_t(itr->second.size())); +} + +// Handler for shader lookup callbacks. +// This is used by the JSON decoder for mapping shader instruction +// addresses to SPIR-V IL lines or GLSL source lines. +// NOTE: If the application loads stripped shader binaries (ie; --strip-all in spirv-remap), +// Aftermath will require access to both the stripped and the not stripped +// shader binaries. +void GpuCrashTracker::OnShaderLookup( + const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const +{ + std::lock_guard holder{shader_lock}; + auto itr = shader_db.find(shaderHash); + if (itr != shader_db.end()) + setShaderBinary(itr->second.data(), itr->second.size() * sizeof(uint32_t)); +} + +// Handler for shader source debug info lookup callbacks. +// This is used by the JSON decoder for mapping shader instruction addresses to +// GLSL source lines, if the shaders used by the application were compiled with +// separate debug info data files. +void GpuCrashTracker::OnShaderSourceDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugName&, + PFN_GFSDK_Aftermath_SetData) const +{ + // Granite doesn't do this. +} + +// Static callback wrapper for OnCrashDump +void GpuCrashTracker::GpuCrashDumpCallback( + const void* pGpuCrashDump, + const uint32_t gpuCrashDumpSize, + void* pUserData) +{ + auto* pGpuCrashTracker = static_cast(pUserData); + pGpuCrashTracker->OnCrashDump(pGpuCrashDump, gpuCrashDumpSize); +} + +// Static callback wrapper for OnShaderDebugInfo +void GpuCrashTracker::ShaderDebugInfoCallback( + const void* pShaderDebugInfo, + const uint32_t shaderDebugInfoSize, + void* pUserData) +{ + auto* pGpuCrashTracker = static_cast(pUserData); + pGpuCrashTracker->OnShaderDebugInfo(pShaderDebugInfo, shaderDebugInfoSize); +} + +// Static callback wrapper for OnDescription +void GpuCrashTracker::CrashDumpDescriptionCallback( + PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, + void* pUserData) +{ + auto* pGpuCrashTracker = static_cast(pUserData); + pGpuCrashTracker->OnDescription(addDescription); +} + +// Static callback wrapper for OnResolveMarker +void GpuCrashTracker::ResolveMarkerCallback( + const void* pMarkerData, + const uint32_t markerDataSize, + void* pUserData, + void** ppResolvedMarkerData, + uint32_t* pResolvedMarkerDataSize) +{ + auto* pGpuCrashTracker = static_cast(pUserData); + pGpuCrashTracker->OnResolveMarker(pMarkerData, markerDataSize, ppResolvedMarkerData, pResolvedMarkerDataSize); +} + +// Static callback wrapper for OnShaderDebugInfoLookup +void GpuCrashTracker::ShaderDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, + void* pUserData) +{ + auto* pGpuCrashTracker = static_cast(pUserData); + pGpuCrashTracker->OnShaderDebugInfoLookup(*pIdentifier, setShaderDebugInfo); +} + +// Static callback wrapper for OnShaderLookup +void GpuCrashTracker::ShaderLookupCallback( + const GFSDK_Aftermath_ShaderBinaryHash* pShaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData) +{ + auto* pGpuCrashTracker = static_cast(pUserData); + pGpuCrashTracker->OnShaderLookup(*pShaderHash, setShaderBinary); +} + +// Static callback wrapper for OnShaderSourceDebugInfoLookup +void GpuCrashTracker::ShaderSourceDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData) +{ + auto* pGpuCrashTracker = static_cast(pUserData); + pGpuCrashTracker->OnShaderSourceDebugInfoLookup(*pShaderDebugName, setShaderBinary); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/NsightAftermathGpuCrashTracker.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/NsightAftermathGpuCrashTracker.h new file mode 100644 index 00000000..09c132c3 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/NsightAftermathGpuCrashTracker.h @@ -0,0 +1,170 @@ +//********************************************************* +// +// Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. +// +// 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. +// +//********************************************************* + +#pragma once + +#include +#include +#include +#include +#include + +#include "NsightAftermathHelpers.h" + +//********************************************************* +// Implements GPU crash dump tracking using the Nsight +// Aftermath API. +// +class GpuCrashTracker +{ +public: + // keep four frames worth of marker history + const static unsigned int c_markerFrameHistory = 4; + typedef std::array, c_markerFrameHistory> MarkerMap; + + GpuCrashTracker(const MarkerMap& markerMap); + ~GpuCrashTracker(); + + // Initialize the GPU crash dump tracker. + void Initialize(); + + void RegisterShader(const void *code, size_t size); + +private: + + //********************************************************* + // Callback handlers for GPU crash dumps and related data. + // + + // Handler for GPU crash dump callbacks. + void OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize); + + // Handler for shader debug information callbacks. + void OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize); + + // Handler for GPU crash dump description callbacks. + void OnDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription); + + // Handler for app-managed marker resolve callback + void OnResolveMarker(const void* pMarkerData, const uint32_t markerDataSize, void** ppResolvedMarkerData, uint32_t* pResolvedMarkerDataSize); + + //********************************************************* + // Helpers for writing a GPU crash dump and debug information + // data to files. + // + + // Helper for writing a GPU crash dump to a file. + void WriteGpuCrashDumpToFile(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize); + + // Helper for writing shader debug information to a file + void WriteShaderDebugInformationToFile( + GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier, + const void* pShaderDebugInfo, + const uint32_t shaderDebugInfoSize); + + //********************************************************* + // Helpers for decoding GPU crash dump to JSON. + // + + // Handler for shader debug info lookup callbacks. + void OnShaderDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo) const; + + // Handler for shader lookup callbacks. + void OnShaderLookup( + const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const; + + // Handler for shader source debug info lookup callbacks. + void OnShaderSourceDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const; + + //********************************************************* + // Static callback wrappers. + // + + // GPU crash dump callback. + static void GpuCrashDumpCallback( + const void* pGpuCrashDump, + const uint32_t gpuCrashDumpSize, + void* pUserData); + + // Shader debug information callback. + static void ShaderDebugInfoCallback( + const void* pShaderDebugInfo, + const uint32_t shaderDebugInfoSize, + void* pUserData); + + // GPU crash dump description callback. + static void CrashDumpDescriptionCallback( + PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, + void* pUserData); + + // App-managed marker resolve callback + static void ResolveMarkerCallback( + const void* pMarkerData, + const uint32_t markerDataSize, + void* pUserData, + void** ppResolvedMarkerData, + uint32_t* pResolvedMarkerDataSize); + + // Shader debug information lookup callback. + static void ShaderDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, + void* pUserData); + + // Shader lookup callback. + static void ShaderLookupCallback( + const GFSDK_Aftermath_ShaderBinaryHash* pShaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData); + + // Shader source debug info lookup callback. + static void ShaderSourceDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData); + + //********************************************************* + // GPU crash tracker state. + // + + // Is the GPU crash dump tracker initialized? + bool m_initialized; + + // For thread-safe access of GPU crash tracker state. + mutable std::mutex m_mutex; + + // List of Shader Debug Information by ShaderDebugInfoIdentifier. + std::map> m_shaderDebugInfo; + + // App-managed marker tracking + const MarkerMap& m_markerMap; + + mutable std::mutex shader_lock; + std::map> shader_db; +}; diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/NsightAftermathHelpers.h b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/NsightAftermathHelpers.h new file mode 100644 index 00000000..ebc29d48 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/NsightAftermathHelpers.h @@ -0,0 +1,131 @@ +//********************************************************* +// +// Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. +// +// 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. +// +//********************************************************* + +#pragma once + +#include +#include +#include +#include + +#include "GFSDK_Aftermath.h" +#include "GFSDK_Aftermath_GpuCrashDump.h" +#include "GFSDK_Aftermath_GpuCrashDumpDecoding.h" + +//********************************************************* +// Some std::to_string overloads for some Nsight Aftermath +// API types. +// + +namespace std +{ + template + inline std::string to_hex_string(T n) + { + std::stringstream stream; + stream << std::setfill('0') << std::setw(2 * sizeof(T)) << std::hex << n; + return stream.str(); + } + + inline std::string to_string(GFSDK_Aftermath_Result result) + { + return std::string("0x") + to_hex_string(static_cast(result)); + } + + inline std::string to_string(const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier) + { + return to_hex_string(identifier.id[0]) + "-" + to_hex_string(identifier.id[1]); + } + + inline std::string to_string(const GFSDK_Aftermath_ShaderBinaryHash& hash) + { + return to_hex_string(hash.hash); + } +} // namespace std + +//********************************************************* +// Helper for comparing shader hashes and debug info identifier. +// + +// Helper for comparing GFSDK_Aftermath_ShaderDebugInfoIdentifier. +inline bool operator<(const GFSDK_Aftermath_ShaderDebugInfoIdentifier& lhs, const GFSDK_Aftermath_ShaderDebugInfoIdentifier& rhs) +{ + if (lhs.id[0] == rhs.id[0]) + { + return lhs.id[1] < rhs.id[1]; + } + return lhs.id[0] < rhs.id[0]; +} + +// Helper for comparing GFSDK_Aftermath_ShaderBinaryHash. +inline bool operator<(const GFSDK_Aftermath_ShaderBinaryHash& lhs, const GFSDK_Aftermath_ShaderBinaryHash& rhs) +{ + return lhs.hash < rhs.hash; +} + +// Helper for comparing GFSDK_Aftermath_ShaderDebugName. +inline bool operator<(const GFSDK_Aftermath_ShaderDebugName& lhs, const GFSDK_Aftermath_ShaderDebugName& rhs) +{ + return strncmp(lhs.name, rhs.name, sizeof(lhs.name)) < 0; +} + +//********************************************************* +// Helper for checking Nsight Aftermath failures. +// + +inline std::string AftermathErrorMessage(GFSDK_Aftermath_Result result) +{ + switch (result) + { + case GFSDK_Aftermath_Result_FAIL_DriverVersionNotSupported: + return "Unsupported driver version - requires an NVIDIA R495 display driver or newer."; + default: + return "Aftermath Error 0x" + std::to_hex_string(result); + } +} + +// Helper macro for checking Nsight Aftermath results and throwing exception +// in case of a failure. +#ifdef _WIN32 +#define AFTERMATH_CHECK_ERROR(FC) \ +[&]() { \ + GFSDK_Aftermath_Result _result = FC; \ + if (!GFSDK_Aftermath_SUCCEED(_result)) \ + { \ + MessageBoxA(0, AftermathErrorMessage(_result).c_str(), "Aftermath Error", MB_OK); \ + exit(1); \ + } \ +}() +#else +#define AFTERMATH_CHECK_ERROR(FC) \ +[&]() { \ + GFSDK_Aftermath_Result _result = FC; \ + if (!GFSDK_Aftermath_SUCCEED(_result)) \ + { \ + printf("%s\n", AftermathErrorMessage(_result).c_str()); \ + fflush(stdout); \ + exit(1); \ + } \ +}() +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/post_mortem.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/post_mortem.cpp new file mode 100644 index 00000000..28a7b029 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/post_mortem.cpp @@ -0,0 +1,75 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "post_mortem.hpp" + +#ifdef HAVE_AFTERMATH_SDK +#include "NsightAftermathGpuCrashTracker.h" +#endif + +namespace Vulkan +{ +namespace PostMortem +{ +class CrashTracker +{ +public: + virtual ~CrashTracker() = default; + virtual void register_shader(const void *data, size_t size) = 0; +}; + +static std::unique_ptr global_tracker; + +#ifdef HAVE_AFTERMATH_SDK +struct NsightCrashTracker : CrashTracker +{ + GpuCrashTracker::MarkerMap marker; + GpuCrashTracker tracker; + NsightCrashTracker() : tracker(marker) {} + void register_shader(const void *data, size_t size) override { tracker.RegisterShader(data, size); } +}; +#endif + +void init_nv_aftermath() +{ + if (global_tracker) + return; + +#ifdef HAVE_AFTERMATH_SDK + auto tracker = std::make_unique(); + tracker->tracker.Initialize(); + global_tracker = std::move(tracker); +#endif +} + +void register_shader(const void *data, size_t size) +{ + if (global_tracker) + global_tracker->register_shader(data, size); +} + +void deinit() +{ + global_tracker.reset(); +} +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/post_mortem.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/post_mortem.hpp new file mode 100644 index 00000000..5b07430a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/post-mortem/post_mortem.hpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Vulkan +{ +namespace PostMortem +{ +void init_nv_aftermath(); +void deinit(); +void register_shader(const void *code, size_t size); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/query_pool.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/query_pool.cpp new file mode 100644 index 00000000..083c6e85 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/query_pool.cpp @@ -0,0 +1,550 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "query_pool.hpp" +#include "device.hpp" +#include + +namespace Vulkan +{ +static const char *storage_to_str(VkPerformanceCounterStorageKHR storage) +{ + switch (storage) + { + case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR: + return "float32"; + case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR: + return "float64"; + case VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR: + return "int32"; + case VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR: + return "int64"; + case VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR: + return "uint32"; + case VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR: + return "uint64"; + default: + return "???"; + } +} + +static const char *scope_to_str(VkPerformanceCounterScopeKHR scope) +{ + switch (scope) + { + case VK_QUERY_SCOPE_COMMAND_BUFFER_KHR: + return "command buffer"; + case VK_QUERY_SCOPE_RENDER_PASS_KHR: + return "render pass"; + case VK_QUERY_SCOPE_COMMAND_KHR: + return "command"; + default: + return "???"; + } +} + +static const char *unit_to_str(VkPerformanceCounterUnitKHR unit) +{ + switch (unit) + { + case VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR: + return "A"; + case VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR: + return "bytes"; + case VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR: + return "bytes / second"; + case VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR: + return "cycles"; + case VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR: + return "units"; + case VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR: + return "Hz"; + case VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR: + return "K"; + case VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR: + return "ns"; + case VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR: + return "%"; + case VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR: + return "V"; + case VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR: + return "W"; + default: + return "???"; + } +} + +void PerformanceQueryPool::log_available_counters(const VkPerformanceCounterKHR *counters, + const VkPerformanceCounterDescriptionKHR *descs, + uint32_t count) +{ + for (uint32_t i = 0; i < count; i++) + { + LOGI(" %s: %s\n", descs[i].name, descs[i].description); + LOGI(" Storage: %s\n", storage_to_str(counters[i].storage)); + LOGI(" Scope: %s\n", scope_to_str(counters[i].scope)); + LOGI(" Unit: %s\n", unit_to_str(counters[i].unit)); + } +} + +void PerformanceQueryPool::init_device(Device *device_, uint32_t queue_family_index_) +{ + device = device_; + queue_family_index = queue_family_index_; + + if (!device->get_device_features().performance_query_features.performanceCounterQueryPools) + return; + + uint32_t num_counters = 0; + if (vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( + device->get_physical_device(), + queue_family_index, + &num_counters, + nullptr, nullptr) != VK_SUCCESS) + { + LOGE("Failed to enumerate performance counters.\n"); + return; + } + + counters.resize(num_counters, { VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR }); + counter_descriptions.resize(num_counters, { VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR }); + + if (vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( + device->get_physical_device(), + queue_family_index, + &num_counters, + counters.data(), counter_descriptions.data()) != VK_SUCCESS) + { + LOGE("Failed to enumerate performance counters.\n"); + return; + } +} + +PerformanceQueryPool::~PerformanceQueryPool() +{ + if (pool) + device->get_device_table().vkDestroyQueryPool(device->get_device(), pool, nullptr); +} + +void PerformanceQueryPool::begin_command_buffer(VkCommandBuffer cmd) +{ + if (!pool) + return; + + auto &table = device->get_device_table(); + if (device->get_device_features().vk12_features.hostQueryReset) + table.vkResetQueryPool(device->get_device(), pool, 0, 1); + else + table.vkCmdResetQueryPool(cmd, pool, 0, 1); + table.vkCmdBeginQuery(cmd, pool, 0, 0); + + VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER }; + barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT; + table.vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, 1, &barrier, 0, nullptr, 0, nullptr); +} + +void PerformanceQueryPool::end_command_buffer(VkCommandBuffer cmd) +{ + if (!pool) + return; + + auto &table = device->get_device_table(); + + VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER }; + barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT; + table.vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, 1, &barrier, 0, nullptr, 0, nullptr); + table.vkCmdEndQuery(cmd, pool, 0); +} + +void PerformanceQueryPool::report() +{ + if (pool == VK_NULL_HANDLE) + { + LOGE("No query pool is set up.\n"); + return; + } + + auto &table = device->get_device_table(); + if (table.vkGetQueryPoolResults(device->get_device(), pool, + 0, 1, + results.size() * sizeof(VkPerformanceCounterResultKHR), + results.data(), + sizeof(VkPerformanceCounterResultKHR), + VK_QUERY_RESULT_WAIT_BIT) != VK_SUCCESS) + { + LOGE("Getting performance counters did not succeed.\n"); + } + + size_t num_counters = results.size(); + + LOGI("\n=== Profiling result ===\n"); + for (size_t i = 0; i < num_counters; i++) + { + auto &counter = counters[active_indices[i]]; + auto &desc = counter_descriptions[active_indices[i]]; + + switch (counter.storage) + { + case VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR: + LOGI(" %s (%s): %d %s\n", desc.name, desc.description, results[i].int32, unit_to_str(counter.unit)); + break; + case VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR: + LOGI(" %s (%s): %lld %s\n", desc.name, desc.description, static_cast(results[i].int64), unit_to_str(counter.unit)); + break; + case VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR: + LOGI(" %s (%s): %u %s\n", desc.name, desc.description, results[i].uint32, unit_to_str(counter.unit)); + break; + case VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR: + LOGI(" %s (%s): %llu %s\n", desc.name, desc.description, static_cast(results[i].uint64), unit_to_str(counter.unit)); + break; + case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR: + LOGI(" %s (%s): %g %s\n", desc.name, desc.description, results[i].float32, unit_to_str(counter.unit)); + break; + case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR: + LOGI(" %s (%s): %g %s\n", desc.name, desc.description, results[i].float64, unit_to_str(counter.unit)); + break; + default: + break; + } + } + LOGI("================================\n\n"); +} + +uint32_t PerformanceQueryPool::get_num_counters() const +{ + return uint32_t(counters.size()); +} + +const VkPerformanceCounterKHR *PerformanceQueryPool::get_available_counters() const +{ + return counters.data(); +} + +const VkPerformanceCounterDescriptionKHR *PerformanceQueryPool::get_available_counter_descs() const +{ + return counter_descriptions.data(); +} + +bool PerformanceQueryPool::init_counters(const std::vector &counter_names) +{ + if (!device->get_device_features().performance_query_features.performanceCounterQueryPools) + { + LOGE("Device does not support VK_KHR_performance_query.\n"); + return false; + } + + if (!device->get_device_features().vk12_features.hostQueryReset) + { + LOGE("Device does not support host query reset.\n"); + return false; + } + + auto &table = device->get_device_table(); + if (pool) + table.vkDestroyQueryPool(device->get_device(), pool, nullptr); + pool = VK_NULL_HANDLE; + + VkQueryPoolPerformanceCreateInfoKHR performance_info = { VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR }; + VkQueryPoolCreateInfo info = { VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO }; + info.pNext = &performance_info; + + info.queryType = VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR; + info.queryCount = 1; + + active_indices.clear(); + + for (auto &name : counter_names) + { + auto itr = find_if(begin(counter_descriptions), end(counter_descriptions), [&](const VkPerformanceCounterDescriptionKHR &desc) { + return name == desc.name; + }); + + if (itr != end(counter_descriptions)) + { + LOGI("Found counter %s: %s\n", itr->name, itr->description); + active_indices.push_back(itr - begin(counter_descriptions)); + } + } + + if (active_indices.empty()) + { + LOGW("No performance counters were enabled.\n"); + return false; + } + + performance_info.queueFamilyIndex = queue_family_index; + performance_info.counterIndexCount = active_indices.size(); + performance_info.pCounterIndices = active_indices.data(); + results.resize(active_indices.size()); + + uint32_t num_passes = 0; + vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(device->get_physical_device(), + &performance_info, &num_passes); + + if (num_passes != 1) + { + LOGE("Implementation requires %u passes to query performance counters. Cannot create query pool.\n", + num_passes); + return false; + } + + if (table.vkCreateQueryPool(device->get_device(), &info, nullptr, &pool) != VK_SUCCESS) + { + LOGE("Failed to create performance query pool.\n"); + return false; + } + + return true; +} + +QueryPool::QueryPool(Device *device_, VkQueryType type_) + : device(device_) + , table(device_->get_device_table()) + , type(type_) +{ + supports_type = false; + + if (type == VK_QUERY_TYPE_TIMESTAMP) + { + // Ignore timestampValidBits and friends for now. + supports_type = device->get_gpu_properties().limits.timestampComputeAndGraphics; + } + else if (type == VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR) + { + supports_type = device->get_device_features().rtas_features.accelerationStructure == VK_TRUE; + } + + if (supports_type) + add_pool(); +} + +QueryPool::~QueryPool() +{ + for (auto &pool : pools) + table.vkDestroyQueryPool(device->get_device(), pool.pool, nullptr); +} + +void QueryPool::begin() +{ + for (unsigned i = 0; i <= pool_index; i++) + { + if (i >= pools.size()) + continue; + + auto &pool = pools[i]; + if (pool.index == 0) + continue; + + table.vkGetQueryPoolResults(device->get_device(), pool.pool, + 0, pool.index, + pool.index * sizeof(uint64_t), + pool.query_results.data(), + sizeof(uint64_t), + VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); + + for (unsigned j = 0; j < pool.index; j++) + pool.cookies[j]->signal_value(pool.query_results[j]); + + if (device->get_device_features().vk12_features.hostQueryReset) + table.vkResetQueryPool(device->get_device(), pool.pool, 0, pool.index); + } + + pool_index = 0; + for (auto &pool : pools) + pool.index = 0; +} + +void QueryPool::add_pool() +{ + VkQueryPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO }; + pool_info.queryType = type; + pool_info.queryCount = 64; + + Pool pool; + table.vkCreateQueryPool(device->get_device(), &pool_info, nullptr, &pool.pool); + pool.size = pool_info.queryCount; + pool.index = 0; + pool.query_results.resize(pool.size); + pool.cookies.resize(pool.size); + + if (device->get_device_features().vk12_features.hostQueryReset) + table.vkResetQueryPool(device->get_device(), pool.pool, 0, pool.size); + + pools.push_back(std::move(pool)); +} + +QueryPoolHandle QueryPool::write_timestamp(VkCommandBuffer cmd, VkPipelineStageFlags2 stage) +{ + if (!supports_type) + { + LOGI("Timestamps are not supported on this implementation.\n"); + return {}; + } + + VK_ASSERT((stage & (stage - 1)) == 0); + + auto handle = allocate_query(cmd); + table.vkCmdWriteTimestamp2(cmd, stage, handle->get_query_pool(), handle->get_query_pool_index()); + return handle; +} + +QueryPoolHandle QueryPool::allocate_query(VkCommandBuffer cmd) +{ + if (!supports_type) + { + LOGI("Query type %u not supported on this implementation.\n", type); + return {}; + } + + if (pools[pool_index].index >= pools[pool_index].size) + pool_index++; + + if (pool_index >= pools.size()) + add_pool(); + + auto &pool = pools[pool_index]; + + auto cookie = QueryPoolHandle(device->handle_pool.query.allocate(device, type == VK_QUERY_TYPE_TIMESTAMP, type, pool.pool, pool.index)); + pool.cookies[pool.index] = cookie; + + if (!device->get_device_features().vk12_features.hostQueryReset) + table.vkCmdResetQueryPool(cmd, pool.pool, pool.index, 1); + + pool.index++; + return cookie; +} + +void QueryPoolResultDeleter::operator()(QueryPoolResult *query) +{ + query->device->handle_pool.query.free(query); +} + +void TimestampInterval::mark_end_of_frame_context() +{ + if (total_time > 0.0) + total_frame_iterations++; +} + +uint64_t TimestampInterval::get_total_accumulations() const +{ + return total_accumulations; +} + +uint64_t TimestampInterval::get_total_frame_iterations() const +{ + return total_frame_iterations; +} + +double TimestampInterval::get_total_time() const +{ + return total_time; +} + +void TimestampInterval::accumulate_time(double t) +{ + total_time += t; + total_accumulations++; +} + +double TimestampInterval::get_time_per_iteration() const +{ + if (total_frame_iterations) + return total_time / double(total_frame_iterations); + else + return 0.0; +} + +double TimestampInterval::get_time_per_accumulation() const +{ + if (total_accumulations) + return total_time / double(total_accumulations); + else + return 0.0; +} + +const std::string &TimestampInterval::get_tag() const +{ + return tag; +} + +void TimestampInterval::reset() +{ + total_time = 0.0; + total_accumulations = 0; + total_frame_iterations = 0; +} + +TimestampInterval::TimestampInterval(std::string tag_) + : tag(std::move(tag_)) +{ +} + +TimestampInterval *TimestampIntervalManager::get_timestamp_tag(const char *tag) +{ + Util::Hasher h; + h.string(tag); + return timestamps.emplace_yield(h.get(), tag); +} + +void TimestampIntervalManager::mark_end_of_frame_context() +{ + for (auto ×tamp : timestamps) + timestamp.mark_end_of_frame_context(); +} + +void TimestampIntervalManager::reset() +{ + for (auto ×tamp : timestamps) + timestamp.reset(); +} + +void TimestampIntervalManager::log_simple(const TimestampIntervalReportCallback &func) const +{ + for (auto ×tamp : timestamps) + { + if (timestamp.get_total_frame_iterations()) + { + TimestampIntervalReport report = {}; + report.time_per_accumulation = timestamp.get_time_per_accumulation(); + report.time_per_frame_context = timestamp.get_time_per_iteration(); + report.accumulations_per_frame_context = + double(timestamp.get_total_accumulations()) / double(timestamp.get_total_frame_iterations()); + + if (func) + { + func(timestamp.get_tag(), report); + } + else + { + LOGI("Timestamp tag report: %s\n", timestamp.get_tag().c_str()); + LOGI(" %.3f ms / iteration\n", 1000.0 * report.time_per_accumulation); + LOGI(" %.3f ms / frame context\n", 1000.0 * report.time_per_frame_context); + LOGI(" %.3f iterations / frame context\n", report.accumulations_per_frame_context); + } + } + } +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/query_pool.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/query_pool.hpp new file mode 100644 index 00000000..3c2e79c8 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/query_pool.hpp @@ -0,0 +1,208 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include "vulkan_common.hpp" +#include "object_pool.hpp" +#include + +namespace Vulkan +{ +class Device; + +class PerformanceQueryPool +{ +public: + void init_device(Device *device, uint32_t queue_family_index); + ~PerformanceQueryPool(); + bool init_counters(const std::vector &enable_counter_names); + + void begin_command_buffer(VkCommandBuffer cmd); + void end_command_buffer(VkCommandBuffer cmd); + + void report(); + + uint32_t get_num_counters() const; + const VkPerformanceCounterKHR *get_available_counters() const; + const VkPerformanceCounterDescriptionKHR *get_available_counter_descs() const; + + static void log_available_counters(const VkPerformanceCounterKHR *counters, + const VkPerformanceCounterDescriptionKHR *descs, + uint32_t count); + +private: + Device *device = nullptr; + uint32_t queue_family_index = 0; + VkQueryPool pool = VK_NULL_HANDLE; + std::vector results; + std::vector counters; + std::vector counter_descriptions; + std::vector active_indices; +}; + +class QueryPoolResult; + +struct QueryPoolResultDeleter +{ + void operator()(QueryPoolResult *query); +}; + +class QueryPoolResult : public Util::IntrusivePtrEnabled +{ +public: + friend struct QueryPoolResultDeleter; + + inline void signal_value(uint64_t ticks) + { + value = ticks; + has_value = true; + } + + // Compatibility alias. + inline uint64_t get_timestamp_ticks() const + { + VK_ASSERT(type == VK_QUERY_TYPE_TIMESTAMP); + return value; + } + + inline uint64_t get_value() const + { + return value; + } + + inline bool is_signalled() const + { + return has_value; + } + + inline bool is_device_timebase() const + { + return device_timebase; + } + + inline VkQueryPool get_query_pool() const + { + return pool; + } + + inline uint32_t get_query_pool_index() const + { + return index; + } + +private: + friend class Util::ObjectPool; + + explicit QueryPoolResult(Device *device_, bool device_timebase_, VkQueryType type_, + VkQueryPool pool_, uint32_t index_) + : device(device_), device_timebase(device_timebase_), type(type_), pool(pool_), index(index_) + {} + + Device *device; + uint64_t value = 0; + bool has_value = false; + bool device_timebase = false; + VkQueryType type; + VkQueryPool pool; + uint32_t index; +}; + +using QueryPoolHandle = Util::IntrusivePtr; + +class QueryPool +{ +public: + QueryPool(Device *device, VkQueryType type); + ~QueryPool(); + + void begin(); + + QueryPoolHandle write_timestamp(VkCommandBuffer cmd, VkPipelineStageFlags2 stage); + QueryPoolHandle allocate_query(VkCommandBuffer cmd); + +private: + Device *device; + const VolkDeviceTable &table; + VkQueryType type; + + struct Pool + { + VkQueryPool pool = VK_NULL_HANDLE; + std::vector query_results; + std::vector cookies; + unsigned index = 0; + unsigned size = 0; + }; + std::vector pools; + unsigned pool_index = 0; + + void add_pool(); + + bool supports_type = false; +}; + +class TimestampInterval : public Util::IntrusiveHashMapEnabled +{ +public: + explicit TimestampInterval(std::string tag); + + void accumulate_time(double t); + double get_time_per_iteration() const; + double get_time_per_accumulation() const; + const std::string &get_tag() const; + void mark_end_of_frame_context(); + + double get_total_time() const; + uint64_t get_total_frame_iterations() const; + uint64_t get_total_accumulations() const; + void reset(); + +private: + std::string tag; + double total_time = 0.0; + uint64_t total_frame_iterations = 0; + uint64_t total_accumulations = 0; +}; + +struct TimestampIntervalReport +{ + double time_per_accumulation; + double time_per_frame_context; + double accumulations_per_frame_context; +}; + +using TimestampIntervalReportCallback = std::function; + +class TimestampIntervalManager +{ +public: + TimestampInterval *get_timestamp_tag(const char *tag); + void mark_end_of_frame_context(); + void reset(); + void log_simple(const TimestampIntervalReportCallback &func = {}) const; + +private: + Util::IntrusiveHashMap timestamps; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/quirks.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/quirks.hpp new file mode 100644 index 00000000..fd5708c9 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/quirks.hpp @@ -0,0 +1,50 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +namespace Vulkan +{ +struct ImplementationQuirks +{ + bool instance_deferred_lights = true; + bool merge_subpasses = true; + bool use_transient_color = true; + bool use_transient_depth_stencil = true; + bool queue_wait_on_submission = false; + bool use_async_compute_post = true; + bool render_graph_force_single_queue = false; + bool force_no_subgroups = false; + bool force_no_subgroup_shuffle = false; + bool force_no_subgroup_size_control = false; + + static ImplementationQuirks &get(); +}; + +struct ImplementationWorkarounds +{ + bool emulate_event_as_pipeline_barrier = false; + bool broken_pipeline_cache_control = false; + bool force_host_cached = false; + bool broken_present_fence = false; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/render_pass.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/render_pass.cpp new file mode 100644 index 00000000..c158bb0b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/render_pass.cpp @@ -0,0 +1,1031 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "render_pass.hpp" +#include "stack_allocator.hpp" +#include "device.hpp" +#include "quirks.hpp" +#include +#include + +using namespace Util; + +#define LOCK() std::lock_guard holder__{lock} + +namespace Vulkan +{ +void RenderPass::setup_subpasses(const VkRenderPassCreateInfo2 &create_info) +{ + auto *attachments = create_info.pAttachments; + + // Store the important subpass information for later. + for (uint32_t i = 0; i < create_info.subpassCount; i++) + { + auto &subpass = create_info.pSubpasses[i]; + + SubpassInfo subpass_info = {}; + subpass_info.num_color_attachments = subpass.colorAttachmentCount; + subpass_info.num_input_attachments = subpass.inputAttachmentCount; + subpass_info.depth_stencil_attachment = *subpass.pDepthStencilAttachment; + memcpy(subpass_info.color_attachments, subpass.pColorAttachments, + subpass.colorAttachmentCount * sizeof(*subpass.pColorAttachments)); + memcpy(subpass_info.input_attachments, subpass.pInputAttachments, + subpass.inputAttachmentCount * sizeof(*subpass.pInputAttachments)); + + unsigned samples = 0; + for (unsigned att = 0; att < subpass_info.num_color_attachments; att++) + { + if (subpass_info.color_attachments[att].attachment == VK_ATTACHMENT_UNUSED) + continue; + + unsigned samp = attachments[subpass_info.color_attachments[att].attachment].samples; + if (samples && (samp != samples)) + VK_ASSERT(samp == samples); + samples = samp; + } + + if (subpass_info.depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED) + { + unsigned samp = attachments[subpass_info.depth_stencil_attachment.attachment].samples; + if (samples && (samp != samples)) + VK_ASSERT(samp == samples); + samples = samp; + } + + VK_ASSERT(samples > 0); + subpass_info.samples = samples; + subpasses_info.push_back(subpass_info); + } +} + +RenderPass::RenderPass(Hash hash, Device *device_, const VkRenderPassCreateInfo2 &create_info) + : IntrusiveHashMapEnabled(hash) + , device(device_) +{ + auto &table = device->get_device_table(); + unsigned num_color_attachments = 0; + if (create_info.attachmentCount > 0) + { + auto &att = create_info.pAttachments[create_info.attachmentCount - 1]; + if (format_has_depth_or_stencil_aspect(att.format)) + { + depth_stencil = att.format; + num_color_attachments = create_info.attachmentCount - 1; + } + else + num_color_attachments = create_info.attachmentCount; + } + + for (unsigned i = 0; i < num_color_attachments; i++) + color_attachments[i] = create_info.pAttachments[i].format; + + // Store the important subpass information for later. + setup_subpasses(create_info); + +#ifdef VULKAN_DEBUG + LOGI("Creating render pass.\n"); +#endif + if (table.vkCreateRenderPass2(device->get_device(), &create_info, nullptr, &render_pass) != VK_SUCCESS) + LOGE("Failed to create render pass."); + +#ifdef GRANITE_VULKAN_FOSSILIZE + device->register_render_pass(render_pass, get_hash(), create_info); +#endif +} + +RenderPass::RenderPass(Hash hash, Device *device_, const RenderPassInfo &info) + : IntrusiveHashMapEnabled(hash) + , device(device_) +{ + std::fill(std::begin(color_attachments), std::end(color_attachments), VK_FORMAT_UNDEFINED); + + VK_ASSERT(info.num_color_attachments || info.depth_stencil); + + // Want to make load/store to transient a very explicit thing to do, since it will kill performance. + bool enable_transient_store = (info.op_flags & RENDER_PASS_OP_ENABLE_TRANSIENT_STORE_BIT) != 0; + bool enable_transient_load = (info.op_flags & RENDER_PASS_OP_ENABLE_TRANSIENT_LOAD_BIT) != 0; + bool multiview = info.num_layers > 1; + + // Set up default subpass info structure if we don't have it. + auto *subpass_infos = info.subpasses; + unsigned num_subpasses = info.num_subpasses; + RenderPassInfo::Subpass default_subpass_info; + if (!info.subpasses) + { + default_subpass_info.num_color_attachments = info.num_color_attachments; + if (info.op_flags & RENDER_PASS_OP_DEPTH_STENCIL_READ_ONLY_BIT) + default_subpass_info.depth_stencil_mode = RenderPassInfo::DepthStencil::ReadOnly; + else + default_subpass_info.depth_stencil_mode = RenderPassInfo::DepthStencil::ReadWrite; + + for (unsigned i = 0; i < info.num_color_attachments; i++) + default_subpass_info.color_attachments[i] = i; + num_subpasses = 1; + subpass_infos = &default_subpass_info; + } + + // First, set up attachment descriptions. + const unsigned num_attachments = info.num_color_attachments + (info.depth_stencil ? 1 : 0); + VkAttachmentDescription2 attachments[VULKAN_NUM_ATTACHMENTS + 1]; + uint32_t implicit_transitions = 0; + uint32_t implicit_bottom_of_pipe = 0; + + VkAttachmentLoadOp ds_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + VkAttachmentStoreOp ds_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE; + + VK_ASSERT(!(info.clear_attachments & info.load_attachments)); + + const auto color_load_op = [&info](unsigned index) -> VkAttachmentLoadOp { + if ((info.clear_attachments & (1u << index)) != 0) + return VK_ATTACHMENT_LOAD_OP_CLEAR; + else if ((info.load_attachments & (1u << index)) != 0) + return VK_ATTACHMENT_LOAD_OP_LOAD; + else + return VK_ATTACHMENT_LOAD_OP_DONT_CARE; + }; + + const auto color_store_op = [&info](unsigned index) -> VkAttachmentStoreOp { + if ((info.store_attachments & (1u << index)) != 0) + return VK_ATTACHMENT_STORE_OP_STORE; + else + return VK_ATTACHMENT_STORE_OP_DONT_CARE; + }; + + if (info.op_flags & RENDER_PASS_OP_CLEAR_DEPTH_STENCIL_BIT) + ds_load_op = VK_ATTACHMENT_LOAD_OP_CLEAR; + else if (info.op_flags & RENDER_PASS_OP_LOAD_DEPTH_STENCIL_BIT) + ds_load_op = VK_ATTACHMENT_LOAD_OP_LOAD; + + if (info.op_flags & RENDER_PASS_OP_STORE_DEPTH_STENCIL_BIT) + { + ds_store_op = VK_ATTACHMENT_STORE_OP_STORE; + } + else if (info.op_flags & RENDER_PASS_OP_PRESERVE_DEPTH_STENCIL_BIT) + { + ds_store_op = device->get_device_features().supports_store_op_none ? + VK_ATTACHMENT_STORE_OP_NONE : VK_ATTACHMENT_STORE_OP_STORE; + + if (ds_load_op != VK_ATTACHMENT_LOAD_OP_LOAD) + ds_store_op = VK_ATTACHMENT_STORE_OP_STORE; + } + + bool ds_read_only = (info.op_flags & RENDER_PASS_OP_DEPTH_STENCIL_READ_ONLY_BIT) != 0; + VkImageLayout depth_stencil_layout = VK_IMAGE_LAYOUT_UNDEFINED; + if (info.depth_stencil) + { + depth_stencil_layout = info.depth_stencil->get_image().get_layout( + ds_read_only ? + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL : + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL); + } + + for (unsigned i = 0; i < info.num_color_attachments; i++) + { + VK_ASSERT(info.color_attachments[i]); + color_attachments[i] = info.color_attachments[i]->get_format(); + auto &image = info.color_attachments[i]->get_image(); + auto &att = attachments[i]; + att = { VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 }; + att.format = color_attachments[i]; + att.samples = image.get_create_info().samples; + att.loadOp = color_load_op(i); + att.storeOp = color_store_op(i); + att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + // Undefined final layout here for now means that we will just use the layout of the last + // subpass which uses this attachment to avoid any dummy transition at the end. + att.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + if (image.get_create_info().domain == ImageDomain::Transient) + { + if (enable_transient_load) + { + // The transient will behave like a normal image. + att.initialLayout = info.color_attachments[i]->get_image().get_layout(VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL); + } + else + { + // Force a clean discard. + VK_ASSERT(att.loadOp != VK_ATTACHMENT_LOAD_OP_LOAD); + att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + if (!enable_transient_store) + att.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + + implicit_transitions |= 1u << i; + } + else if (image.is_swapchain_image()) + { + if (att.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD) + att.initialLayout = image.get_swapchain_layout(); + else + att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + att.finalLayout = image.get_swapchain_layout(); + + // If we transition from PRESENT_SRC_KHR, this came from an implicit external subpass dependency + // which happens in BOTTOM_OF_PIPE. To properly transition away from it, we must wait for BOTTOM_OF_PIPE, + // without any memory barriers, since memory has been made available in the implicit barrier. + if (att.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD) + implicit_bottom_of_pipe |= 1u << i; + implicit_transitions |= 1u << i; + } + else + att.initialLayout = info.color_attachments[i]->get_image().get_layout(VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL); + } + + depth_stencil = info.depth_stencil ? info.depth_stencil->get_format() : VK_FORMAT_UNDEFINED; + if (info.depth_stencil) + { + auto &image = info.depth_stencil->get_image(); + auto &att = attachments[info.num_color_attachments]; + att = { VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 }; + att.format = depth_stencil; + att.samples = image.get_create_info().samples; + att.loadOp = ds_load_op; + att.storeOp = ds_store_op; + // Undefined final layout here for now means that we will just use the layout of the last + // subpass which uses this attachment to avoid any dummy transition at the end. + att.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + if (format_to_aspect_mask(depth_stencil) & VK_IMAGE_ASPECT_STENCIL_BIT) + { + att.stencilLoadOp = ds_load_op; + att.stencilStoreOp = ds_store_op; + } + else + { + att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + } + + if (image.get_create_info().domain == ImageDomain::Transient) + { + if (enable_transient_load) + { + // The transient will behave like a normal image. + att.initialLayout = depth_stencil_layout; + } + else + { + if (att.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD) + att.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + if (att.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD) + att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + + // For transient attachments we force the layouts. + att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + if (!enable_transient_store) + { + att.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + } + + implicit_transitions |= 1u << info.num_color_attachments; + } + else + att.initialLayout = depth_stencil_layout; + } + + Util::StackAllocator reference_allocator; + Util::StackAllocator preserve_allocator; + std::vector subpasses(num_subpasses); + std::vector external_dependencies; + + for (unsigned i = 0; i < num_subpasses; i++) + { + auto *colors = reference_allocator.allocate_cleared(subpass_infos[i].num_color_attachments); + auto *inputs = reference_allocator.allocate_cleared(subpass_infos[i].num_input_attachments); + auto *resolves = reference_allocator.allocate_cleared(subpass_infos[i].num_color_attachments); + auto *depth = reference_allocator.allocate_cleared(1); + + auto &subpass = subpasses[i]; + subpass = { VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 }; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = subpass_infos[i].num_color_attachments; + subpass.pColorAttachments = colors; + subpass.inputAttachmentCount = subpass_infos[i].num_input_attachments; + subpass.pInputAttachments = inputs; + subpass.pDepthStencilAttachment = depth; + + if (multiview && device->get_device_features().vk11_features.multiview) + subpass.viewMask = ((1u << info.num_layers) - 1u) << info.base_layer; + else if (multiview) + LOGE("Multiview not supported. Pretending render pass is not multiview."); + + if (subpass_infos[i].num_resolve_attachments) + { + VK_ASSERT(subpass_infos[i].num_color_attachments == subpass_infos[i].num_resolve_attachments); + subpass.pResolveAttachments = resolves; + } + + for (unsigned j = 0; j < subpass.colorAttachmentCount; j++) + { + auto att = subpass_infos[i].color_attachments[j]; + VK_ASSERT(att == VK_ATTACHMENT_UNUSED || (att < num_attachments)); + colors[j].sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; + colors[j].attachment = att; + // Fill in later. + colors[j].layout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + for (unsigned j = 0; j < subpass.inputAttachmentCount; j++) + { + auto att = subpass_infos[i].input_attachments[j]; + VK_ASSERT(att == VK_ATTACHMENT_UNUSED || (att < num_attachments)); + inputs[j].sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; + inputs[j].attachment = att; + if (att != VK_ATTACHMENT_UNUSED) + { + if (att < info.num_color_attachments) + inputs[j].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + else + inputs[j].aspectMask = format_to_aspect_mask(info.depth_stencil->get_format()); + } + // Fill in later. + inputs[j].layout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + if (subpass.pResolveAttachments) + { + for (unsigned j = 0; j < subpass.colorAttachmentCount; j++) + { + auto att = subpass_infos[i].resolve_attachments[j]; + VK_ASSERT(att == VK_ATTACHMENT_UNUSED || (att < num_attachments)); + resolves[j].sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; + resolves[j].attachment = att; + // Fill in later. + resolves[j].layout = VK_IMAGE_LAYOUT_UNDEFINED; + } + } + + depth->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; + + if (info.depth_stencil && subpass_infos[i].depth_stencil_mode != RenderPassInfo::DepthStencil::None) + { + depth->attachment = info.num_color_attachments; + // Fill in later. + depth->layout = VK_IMAGE_LAYOUT_UNDEFINED; + } + else + { + depth->attachment = VK_ATTACHMENT_UNUSED; + depth->layout = VK_IMAGE_LAYOUT_UNDEFINED; + } + } + + const auto find_color = [&](unsigned subpass, unsigned attachment) -> VkAttachmentReference2 * { + auto *colors = subpasses[subpass].pColorAttachments; + for (unsigned i = 0; i < subpasses[subpass].colorAttachmentCount; i++) + if (colors[i].attachment == attachment) + return const_cast(&colors[i]); + return nullptr; + }; + + const auto find_resolve = [&](unsigned subpass, unsigned attachment) -> VkAttachmentReference2 * { + if (!subpasses[subpass].pResolveAttachments) + return nullptr; + + auto *resolves = subpasses[subpass].pResolveAttachments; + for (unsigned i = 0; i < subpasses[subpass].colorAttachmentCount; i++) + if (resolves[i].attachment == attachment) + return const_cast(&resolves[i]); + return nullptr; + }; + + const auto find_input = [&](unsigned subpass, unsigned attachment) -> VkAttachmentReference2 * { + auto *inputs = subpasses[subpass].pInputAttachments; + for (unsigned i = 0; i < subpasses[subpass].inputAttachmentCount; i++) + if (inputs[i].attachment == attachment) + return const_cast(&inputs[i]); + return nullptr; + }; + + const auto find_depth_stencil = [&](unsigned subpass, unsigned attachment) -> VkAttachmentReference2 * { + if (subpasses[subpass].pDepthStencilAttachment->attachment == attachment) + return const_cast(subpasses[subpass].pDepthStencilAttachment); + else + return nullptr; + }; + + // Now, figure out how each attachment is used throughout the subpasses. + // Either we don't care (inherit previous pass), or we need something specific. + // Start with initial layouts. + uint32_t preserve_masks[VULKAN_NUM_ATTACHMENTS + 1] = {}; + + // Last subpass which makes use of an attachment. + unsigned last_subpass_for_attachment[VULKAN_NUM_ATTACHMENTS + 1] = {}; + + VK_ASSERT(num_subpasses <= 32); + + // 1 << subpass bit set if there are color attachment self-dependencies in the subpass. + uint32_t color_self_dependencies = 0; + // 1 << subpass bit set if there are depth-stencil attachment self-dependencies in the subpass. + uint32_t depth_self_dependencies = 0; + + // 1 << subpass bit set if any input attachment is read in the subpass. + uint32_t input_attachment_read = 0; + uint32_t color_attachment_read_write = 0; + uint32_t depth_stencil_attachment_write = 0; + uint32_t depth_stencil_attachment_read = 0; + + uint32_t external_color_dependencies = 0; + uint32_t external_depth_dependencies = 0; + uint32_t external_input_dependencies = 0; + uint32_t external_bottom_of_pipe_dependencies = 0; + + for (unsigned attachment = 0; attachment < num_attachments; attachment++) + { + bool used = false; + auto current_layout = attachments[attachment].initialLayout; + for (unsigned subpass = 0; subpass < num_subpasses; subpass++) + { + auto *color = find_color(subpass, attachment); + auto *resolve = find_resolve(subpass, attachment); + auto *input = find_input(subpass, attachment); + auto *depth = find_depth_stencil(subpass, attachment); + + // Sanity check. + if (color || resolve) + VK_ASSERT(!depth); + if (depth) + VK_ASSERT(!color && !resolve); + if (resolve) + VK_ASSERT(!color && !depth); + + if (!color && !input && !depth && !resolve) + { + if (used) + preserve_masks[attachment] |= 1u << subpass; + continue; + } + + if (!used && (implicit_transitions & (1u << attachment))) + { + // This is the first subpass we need implicit transitions. + if (color) + external_color_dependencies |= 1u << subpass; + if (depth) + external_depth_dependencies |= 1u << subpass; + if (input) + external_input_dependencies |= 1u << subpass; + } + + if (!used && (implicit_bottom_of_pipe & (1u << attachment))) + external_bottom_of_pipe_dependencies |= 1u << subpass; + + if (resolve && input) // If used as both resolve attachment and input attachment in same subpass, need GENERAL. + { + current_layout = VK_IMAGE_LAYOUT_GENERAL; + resolve->layout = current_layout; + input->layout = current_layout; + + // If the attachment is first used as a feedback attachment, the initial layout should actually be GENERAL. + if (!used && attachments[attachment].initialLayout != VK_IMAGE_LAYOUT_UNDEFINED) + attachments[attachment].initialLayout = current_layout; + + // If first subpass changes the layout, we'll need to inject an external subpass dependency. + if (!used && attachments[attachment].initialLayout != current_layout) + { + external_color_dependencies |= 1u << subpass; + external_input_dependencies |= 1u << subpass; + } + + used = true; + last_subpass_for_attachment[attachment] = subpass; + + color_attachment_read_write |= 1u << subpass; + input_attachment_read |= 1u << subpass; + } + else if (resolve) + { + if (current_layout != VK_IMAGE_LAYOUT_GENERAL) + current_layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; + + // If first subpass changes the layout, we'll need to inject an external subpass dependency. + if (!used && attachments[attachment].initialLayout != current_layout) + external_color_dependencies |= 1u << subpass; + + resolve->layout = current_layout; + used = true; + last_subpass_for_attachment[attachment] = subpass; + color_attachment_read_write |= 1u << subpass; + } + else if (color && input) // If used as both input attachment and color attachment in same subpass, need GENERAL. + { + current_layout = VK_IMAGE_LAYOUT_GENERAL; + color->layout = current_layout; + input->layout = current_layout; + + // If the attachment is first used as a feedback attachment, the initial layout should actually be GENERAL. + if (!used && attachments[attachment].initialLayout != VK_IMAGE_LAYOUT_UNDEFINED) + attachments[attachment].initialLayout = current_layout; + + // If first subpass changes the layout, we'll need to inject an external subpass dependency. + if (!used && attachments[attachment].initialLayout != current_layout) + { + external_color_dependencies |= 1u << subpass; + external_input_dependencies |= 1u << subpass; + } + + used = true; + last_subpass_for_attachment[attachment] = subpass; + color_self_dependencies |= 1u << subpass; + + color_attachment_read_write |= 1u << subpass; + input_attachment_read |= 1u << subpass; + } + else if (color) // No particular preference + { + if (current_layout != VK_IMAGE_LAYOUT_GENERAL) + current_layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; + color->layout = current_layout; + + // If first subpass changes the layout, we'll need to inject an external subpass dependency. + if (!used && attachments[attachment].initialLayout != current_layout) + external_color_dependencies |= 1u << subpass; + + used = true; + last_subpass_for_attachment[attachment] = subpass; + color_attachment_read_write |= 1u << subpass; + } + else if (depth && input) // Depends on the depth mode + { + VK_ASSERT(subpass_infos[subpass].depth_stencil_mode != RenderPassInfo::DepthStencil::None); + if (subpass_infos[subpass].depth_stencil_mode == RenderPassInfo::DepthStencil::ReadWrite) + { + depth_self_dependencies |= 1u << subpass; + current_layout = VK_IMAGE_LAYOUT_GENERAL; + depth_stencil_attachment_write |= 1u << subpass; + + // If the attachment is first used as a feedback attachment, the initial layout should actually be GENERAL. + if (!used && attachments[attachment].initialLayout != VK_IMAGE_LAYOUT_UNDEFINED) + attachments[attachment].initialLayout = current_layout; + } + else + { + if (current_layout != VK_IMAGE_LAYOUT_GENERAL) + current_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + } + + // If first subpass changes the layout, we'll need to inject an external subpass dependency. + if (!used && attachments[attachment].initialLayout != current_layout) + { + external_input_dependencies |= 1u << subpass; + external_depth_dependencies |= 1u << subpass; + } + + depth_stencil_attachment_read |= 1u << subpass; + input_attachment_read |= 1u << subpass; + depth->layout = current_layout; + input->layout = current_layout; + used = true; + last_subpass_for_attachment[attachment] = subpass; + } + else if (depth) + { + if (subpass_infos[subpass].depth_stencil_mode == RenderPassInfo::DepthStencil::ReadWrite) + { + depth_stencil_attachment_write |= 1u << subpass; + if (current_layout != VK_IMAGE_LAYOUT_GENERAL) + current_layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; + } + else + { + if (current_layout != VK_IMAGE_LAYOUT_GENERAL) + current_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + } + + // If first subpass changes the layout, we'll need to inject an external subpass dependency. + if (!used && attachments[attachment].initialLayout != current_layout) + external_depth_dependencies |= 1u << subpass; + + depth_stencil_attachment_read |= 1u << subpass; + depth->layout = current_layout; + used = true; + last_subpass_for_attachment[attachment] = subpass; + } + else if (input) + { + if (current_layout != VK_IMAGE_LAYOUT_GENERAL) + current_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + + // If the attachment is first used as an input attachment, the initial layout should actually be + // READ_ONLY_OPTIMAL. + if (!used && attachments[attachment].initialLayout == VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL) + attachments[attachment].initialLayout = current_layout; + + // If first subpass changes the layout, we'll need to inject an external subpass dependency. + if (!used && attachments[attachment].initialLayout != current_layout) + external_input_dependencies |= 1u << subpass; + + input->layout = current_layout; + used = true; + last_subpass_for_attachment[attachment] = subpass; + input_attachment_read |= 1u << subpass; + } + else + { + VK_ASSERT(0 && "Unhandled attachment usage."); + } + } + + // If we don't have a specific layout we need to end up in, just + // use the last one. + // Assert that we actually use all the attachments we have ... + VK_ASSERT(used); + if (attachments[attachment].finalLayout == VK_IMAGE_LAYOUT_UNDEFINED) + { + VK_ASSERT(current_layout != VK_IMAGE_LAYOUT_UNDEFINED); + attachments[attachment].finalLayout = current_layout; + } + } + + // Only consider preserve masks before last subpass which uses an attachment. + for (unsigned attachment = 0; attachment < num_attachments; attachment++) + preserve_masks[attachment] &= (1u << last_subpass_for_attachment[attachment]) - 1; + + // Add preserve attachments as needed. + for (unsigned subpass = 0; subpass < num_subpasses; subpass++) + { + auto &pass = subpasses[subpass]; + unsigned preserve_count = 0; + for (unsigned attachment = 0; attachment < num_attachments; attachment++) + if (preserve_masks[attachment] & (1u << subpass)) + preserve_count++; + + auto *preserve = preserve_allocator.allocate_cleared(preserve_count); + pass.pPreserveAttachments = preserve; + pass.preserveAttachmentCount = preserve_count; + for (unsigned attachment = 0; attachment < num_attachments; attachment++) + if (preserve_masks[attachment] & (1u << subpass)) + *preserve++ = attachment; + } + + VK_ASSERT(num_subpasses > 0); + VkRenderPassCreateInfo2 rp_info = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 }; + rp_info.subpassCount = num_subpasses; + rp_info.pSubpasses = subpasses.data(); + rp_info.pAttachments = attachments; + rp_info.attachmentCount = num_attachments; + + // Add external subpass dependencies. + for_each_bit(external_color_dependencies | external_depth_dependencies | external_input_dependencies, + [&](unsigned subpass) { + external_dependencies.emplace_back(); + auto &dep = external_dependencies.back(); + dep = { VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 }; + dep.srcSubpass = VK_SUBPASS_EXTERNAL; + dep.dstSubpass = subpass; + + // Could use sync2 NONE here, but we'd like to avoid letting render passes be keyed off sync2 support. + if (external_bottom_of_pipe_dependencies & (1u << subpass)) + dep.srcStageMask |= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + + if (external_color_dependencies & (1u << subpass)) + { + dep.srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dep.dstStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dep.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dep.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + } + + if (external_depth_dependencies & (1u << subpass)) + { + dep.srcStageMask |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dep.dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dep.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dep.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + } + + if (external_input_dependencies & (1u << subpass)) + { + dep.srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dep.dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dep.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dep.dstAccessMask |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + } + }); + + // Queue up self-dependencies (COLOR | DEPTH) -> INPUT. + for_each_bit(color_self_dependencies | depth_self_dependencies, [&](unsigned subpass) { + external_dependencies.emplace_back(); + auto &dep = external_dependencies.back(); + dep = { VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 }; + dep.srcSubpass = subpass; + dep.dstSubpass = subpass; + dep.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + if (multiview) + dep.dependencyFlags |= VK_DEPENDENCY_VIEW_LOCAL_BIT; + + if (color_self_dependencies & (1u << subpass)) + { + dep.srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dep.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + } + + if (depth_self_dependencies & (1u << subpass)) + { + dep.srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dep.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + } + + dep.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dep.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + }); + + // Flush and invalidate caches between each subpass. + for (unsigned subpass = 1; subpass < num_subpasses; subpass++) + { + external_dependencies.emplace_back(); + auto &dep = external_dependencies.back(); + dep = { VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 }; + dep.srcSubpass = subpass - 1; + dep.dstSubpass = subpass; + dep.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + if (multiview) + dep.dependencyFlags |= VK_DEPENDENCY_VIEW_LOCAL_BIT; + + if (color_attachment_read_write & (1u << (subpass - 1))) + { + dep.srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dep.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + } + + if (depth_stencil_attachment_write & (1u << (subpass - 1))) + { + dep.srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dep.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + } + + if (color_attachment_read_write & (1u << subpass)) + { + dep.dstStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dep.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + } + + if (depth_stencil_attachment_read & (1u << subpass)) + { + dep.dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dep.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + + // The store op that comes later will need to write and storeOp accesses in WRITE_BIT. + // It's unclear if we need this barrier, but VVL complains if we don't ... + if (ds_store_op != VK_ATTACHMENT_STORE_OP_NONE && + (depth_stencil_attachment_write & (1u << (subpass - 1)))) + { + dep.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + } + } + + if (depth_stencil_attachment_write & (1u << subpass)) + { + dep.dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dep.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + } + + if (input_attachment_read & (1u << subpass)) + { + dep.dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dep.dstAccessMask |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + } + } + + if (!external_dependencies.empty()) + { + rp_info.dependencyCount = external_dependencies.size(); + rp_info.pDependencies = external_dependencies.data(); + } + + // Store the important subpass information for later. + setup_subpasses(rp_info); + +#ifdef VULKAN_DEBUG + LOGI("Creating render pass.\n"); +#endif + auto &table = device->get_device_table(); + if (table.vkCreateRenderPass2(device->get_device(), &rp_info, nullptr, &render_pass) != VK_SUCCESS) + LOGE("Failed to create render pass."); + +#ifdef GRANITE_VULKAN_FOSSILIZE + device->register_render_pass(render_pass, get_hash(), rp_info); +#endif +} + +RenderPass::~RenderPass() +{ + auto &table = device->get_device_table(); + if (render_pass != VK_NULL_HANDLE) + table.vkDestroyRenderPass(device->get_device(), render_pass, nullptr); +} + +unsigned Framebuffer::setup_raw_views(VkImageView *views, const RenderPassInfo &info) +{ + unsigned num_views = 0; + for (unsigned i = 0; i < info.num_color_attachments; i++) + { + VK_ASSERT(info.color_attachments[i]); + + // For multiview, we use view indices to pick right layers. + if (info.num_layers > 1) + views[num_views++] = info.color_attachments[i]->get_view().view; + else + views[num_views++] = info.color_attachments[i]->get_render_target_view(info.base_layer).view; + } + + if (info.depth_stencil) + { + // For multiview, we use view indices to pick right layers. + if (info.num_layers > 1) + views[num_views++] = info.depth_stencil->get_view().view; + else + views[num_views++] = info.depth_stencil->get_render_target_view(info.base_layer).view; + } + + return num_views; +} + +static const ImageView *get_image_view(const RenderPassInfo &info, unsigned index) +{ + if (index < info.num_color_attachments) + return info.color_attachments[index]; + else + return info.depth_stencil; +} + +void Framebuffer::compute_attachment_dimensions(const RenderPassInfo &info, unsigned index, + uint32_t &width, uint32_t &height) +{ + auto *view = get_image_view(info, index); + VK_ASSERT(view); + unsigned lod = view->get_create_info().base_level; + width = view->get_image().get_width(lod); + height = view->get_image().get_height(lod); +} + +void Framebuffer::compute_dimensions(const RenderPassInfo &info, uint32_t &width, uint32_t &height) +{ + width = UINT32_MAX; + height = UINT32_MAX; + VK_ASSERT(info.num_color_attachments || info.depth_stencil); + + for (unsigned i = 0; i < info.num_color_attachments; i++) + { + VK_ASSERT(info.color_attachments[i]); + width = std::min(width, info.color_attachments[i]->get_view_width()); + height = std::min(height, info.color_attachments[i]->get_view_height()); + } + + if (info.depth_stencil) + { + width = std::min(width, info.depth_stencil->get_view_width()); + height = std::min(height, info.depth_stencil->get_view_height()); + } +} + +Framebuffer::Framebuffer(Device *device_, const RenderPass &rp, const RenderPassInfo &info_) + : Cookie(device_) + , device(device_) + , render_pass(rp) + , info(info_) +{ + compute_dimensions(info_, width, height); + VkImageView views[VULKAN_NUM_ATTACHMENTS + 1]; + unsigned num_views = 0; + + num_views = setup_raw_views(views, info_); + + VkFramebufferCreateInfo fb_info = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO }; + fb_info.renderPass = rp.get_render_pass(); + fb_info.attachmentCount = num_views; + fb_info.pAttachments = views; + fb_info.width = width; + fb_info.height = height; + fb_info.layers = 1; // For multiview, layers must be 1. The render pass encodes a mask. + + auto &table = device->get_device_table(); + if (table.vkCreateFramebuffer(device->get_device(), &fb_info, nullptr, &framebuffer) != VK_SUCCESS) + LOGE("Failed to create framebuffer."); +} + +Framebuffer::~Framebuffer() +{ + if (framebuffer != VK_NULL_HANDLE) + { + if (internal_sync) + device->destroy_framebuffer_nolock(framebuffer); + else + device->destroy_framebuffer(framebuffer); + } +} + +FramebufferAllocator::FramebufferAllocator(Device *device_) + : device(device_) +{ +} + +void FramebufferAllocator::clear() +{ + framebuffers.clear(); +} + +void FramebufferAllocator::begin_frame() +{ + framebuffers.begin_frame(); +} + +Framebuffer &FramebufferAllocator::request_framebuffer(const RenderPassInfo &info) +{ + auto &rp = device->request_render_pass(info, true); + Hasher h; + h.u64(rp.get_hash()); + + for (unsigned i = 0; i < info.num_color_attachments; i++) + { + VK_ASSERT(info.color_attachments[i]); + h.u64(info.color_attachments[i]->get_cookie()); + } + + if (info.depth_stencil) + h.u64(info.depth_stencil->get_cookie()); + + // For multiview we bind the whole attachment, and base layer is encoded in the render pass. + if (info.num_layers > 1) + h.u32(0); + else + h.u32(info.base_layer); + + auto hash = h.get(); + + LOCK(); + auto *node = framebuffers.request(hash); + if (node) + return *node; + + return *framebuffers.emplace(hash, device, rp, info); +} + +void TransientAttachmentAllocator::clear() +{ + attachments.clear(); +} + +void TransientAttachmentAllocator::begin_frame() +{ + attachments.begin_frame(); +} + +ImageHandle TransientAttachmentAllocator::request_attachment(unsigned width, unsigned height, VkFormat format, + unsigned index, unsigned samples, unsigned layers) +{ + Hasher h; + h.u32(width); + h.u32(height); + h.u32(format); + h.u32(index); + h.u32(samples); + h.u32(layers); + + auto hash = h.get(); + + LOCK(); + auto *node = attachments.request(hash); + if (node) + return node->handle; + + auto image_info = ImageCreateInfo::transient_render_target(width, height, format); + + image_info.samples = static_cast(samples); + image_info.layers = layers; + node = attachments.emplace(hash, device->create_image(image_info, nullptr)); + node->handle->set_internal_sync_object(); + node->handle->get_view().set_internal_sync_object(); + device->set_name(*node->handle, "AttachmentAllocator"); + return node->handle; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/render_pass.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/render_pass.hpp new file mode 100644 index 00000000..fa8231f7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/render_pass.hpp @@ -0,0 +1,270 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "cookie.hpp" +#include "hash.hpp" +#include "image.hpp" +#include "intrusive.hpp" +#include "limits.hpp" +#include "object_pool.hpp" +#include "temporary_hashmap.hpp" +#include "vulkan_headers.hpp" + +namespace Vulkan +{ +enum RenderPassOp +{ + RENDER_PASS_OP_CLEAR_DEPTH_STENCIL_BIT = 1 << 0, + RENDER_PASS_OP_LOAD_DEPTH_STENCIL_BIT = 1 << 1, + RENDER_PASS_OP_STORE_DEPTH_STENCIL_BIT = 1 << 2, + RENDER_PASS_OP_DEPTH_STENCIL_READ_ONLY_BIT = 1 << 3, + RENDER_PASS_OP_ENABLE_TRANSIENT_STORE_BIT = 1 << 4, + RENDER_PASS_OP_ENABLE_TRANSIENT_LOAD_BIT = 1 << 5, + RENDER_PASS_OP_PRESERVE_DEPTH_STENCIL_BIT = 1 << 6 +}; +using RenderPassOpFlags = uint32_t; + +class ImageView; +struct RenderPassInfo +{ + const ImageView *color_attachments[VULKAN_NUM_ATTACHMENTS]; + const ImageView *depth_stencil = nullptr; + unsigned num_color_attachments = 0; + RenderPassOpFlags op_flags = 0; + uint32_t clear_attachments = 0; + uint32_t load_attachments = 0; + uint32_t store_attachments = 0; + uint32_t base_layer = 0; + uint32_t num_layers = 1; + + // Render area will be clipped to the actual framebuffer. + VkRect2D render_area = { { 0, 0 }, { UINT32_MAX, UINT32_MAX } }; + + VkClearColorValue clear_color[VULKAN_NUM_ATTACHMENTS] = {}; + VkClearDepthStencilValue clear_depth_stencil = {}; + + enum class DepthStencil + { + None, + ReadOnly, + ReadWrite + }; + + struct Subpass + { + uint32_t color_attachments[VULKAN_NUM_ATTACHMENTS]; + uint32_t input_attachments[VULKAN_NUM_ATTACHMENTS]; + uint32_t resolve_attachments[VULKAN_NUM_ATTACHMENTS]; + unsigned num_color_attachments = 0; + unsigned num_input_attachments = 0; + unsigned num_resolve_attachments = 0; + DepthStencil depth_stencil_mode = DepthStencil::ReadWrite; + }; + // If 0/nullptr, assume a default subpass. + const Subpass *subpasses = nullptr; + unsigned num_subpasses = 0; +}; + +class RenderPass : public HashedObject, public NoCopyNoMove +{ +public: + struct SubpassInfo + { + VkAttachmentReference2 color_attachments[VULKAN_NUM_ATTACHMENTS]; + unsigned num_color_attachments; + VkAttachmentReference2 input_attachments[VULKAN_NUM_ATTACHMENTS]; + unsigned num_input_attachments; + VkAttachmentReference2 depth_stencil_attachment; + + unsigned samples; + }; + + RenderPass(Util::Hash hash, Device *device, const RenderPassInfo &info); + RenderPass(Util::Hash hash, Device *device, const VkRenderPassCreateInfo2 &create_info); + ~RenderPass(); + + unsigned get_num_subpasses() const + { + return unsigned(subpasses_info.size()); + } + + VkRenderPass get_render_pass() const + { + return render_pass; + } + + uint32_t get_sample_count(unsigned subpass) const + { + VK_ASSERT(subpass < subpasses_info.size()); + return subpasses_info[subpass].samples; + } + + unsigned get_num_color_attachments(unsigned subpass) const + { + VK_ASSERT(subpass < subpasses_info.size()); + return subpasses_info[subpass].num_color_attachments; + } + + unsigned get_num_input_attachments(unsigned subpass) const + { + VK_ASSERT(subpass < subpasses_info.size()); + return subpasses_info[subpass].num_input_attachments; + } + + const VkAttachmentReference2 &get_color_attachment(unsigned subpass, unsigned index) const + { + VK_ASSERT(subpass < subpasses_info.size()); + VK_ASSERT(index < subpasses_info[subpass].num_color_attachments); + return subpasses_info[subpass].color_attachments[index]; + } + + const VkAttachmentReference2 &get_input_attachment(unsigned subpass, unsigned index) const + { + VK_ASSERT(subpass < subpasses_info.size()); + VK_ASSERT(index < subpasses_info[subpass].num_input_attachments); + return subpasses_info[subpass].input_attachments[index]; + } + + bool has_depth(unsigned subpass) const + { + VK_ASSERT(subpass < subpasses_info.size()); + return subpasses_info[subpass].depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED && + format_has_depth_aspect(depth_stencil); + } + + bool has_stencil(unsigned subpass) const + { + VK_ASSERT(subpass < subpasses_info.size()); + return subpasses_info[subpass].depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED && + format_has_stencil_aspect(depth_stencil); + } + +private: + Device *device; + VkRenderPass render_pass = VK_NULL_HANDLE; + + VkFormat color_attachments[VULKAN_NUM_ATTACHMENTS] = {}; + VkFormat depth_stencil = VK_FORMAT_UNDEFINED; + std::vector subpasses_info; + + void setup_subpasses(const VkRenderPassCreateInfo2 &create_info); +}; + +class Framebuffer : public Cookie, public NoCopyNoMove, public InternalSyncEnabled +{ +public: + Framebuffer(Device *device, const RenderPass &rp, const RenderPassInfo &info); + ~Framebuffer(); + + VkFramebuffer get_framebuffer() const + { + return framebuffer; + } + + static unsigned setup_raw_views(VkImageView *views, const RenderPassInfo &info); + static void compute_dimensions(const RenderPassInfo &info, uint32_t &width, uint32_t &height); + static void compute_attachment_dimensions(const RenderPassInfo &info, unsigned index, uint32_t &width, uint32_t &height); + + uint32_t get_width() const + { + return width; + } + + uint32_t get_height() const + { + return height; + } + + const RenderPass &get_compatible_render_pass() const + { + return render_pass; + } + +private: + Device *device; + VkFramebuffer framebuffer = VK_NULL_HANDLE; + const RenderPass &render_pass; + RenderPassInfo info; + uint32_t width = 0; + uint32_t height = 0; +}; + +static const unsigned VULKAN_FRAMEBUFFER_RING_SIZE = 16; +class FramebufferAllocator +{ +public: + explicit FramebufferAllocator(Device *device); + Framebuffer &request_framebuffer(const RenderPassInfo &info); + + void begin_frame(); + void clear(); + +private: + struct FramebufferNode : Util::TemporaryHashmapEnabled, + Util::IntrusiveListEnabled, + Framebuffer + { + FramebufferNode(Device *device_, const RenderPass &rp, const RenderPassInfo &info_) + : Framebuffer(device_, rp, info_) + { + set_internal_sync_object(); + } + }; + + Device *device; + Util::TemporaryHashmap framebuffers; + std::mutex lock; +}; + +class TransientAttachmentAllocator +{ +public: + TransientAttachmentAllocator(Device *device_) + : device(device_) + { + } + + ImageHandle request_attachment(unsigned width, unsigned height, VkFormat format, + unsigned index = 0, unsigned samples = 1, unsigned layers = 1); + + void begin_frame(); + void clear(); + +private: + struct TransientNode : Util::TemporaryHashmapEnabled, Util::IntrusiveListEnabled + { + explicit TransientNode(ImageHandle handle_) + : handle(std::move(handle_)) + { + } + + ImageHandle handle; + }; + + Device *device; + Util::TemporaryHashmap attachments; + std::mutex lock; +}; +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/renderdoc_capture.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/renderdoc_capture.cpp new file mode 100644 index 00000000..e7948e8b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/renderdoc_capture.cpp @@ -0,0 +1,127 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "device.hpp" +#include "renderdoc_app.h" +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#endif + +namespace Vulkan +{ +static std::mutex module_lock; +#ifdef _WIN32 +static HMODULE renderdoc_module; +#else +static void *renderdoc_module; +#endif + +static RENDERDOC_API_1_0_0 *renderdoc_api; + +bool Device::init_renderdoc_capture() +{ + std::lock_guard holder{module_lock}; + if (renderdoc_module) + return true; + +#ifdef _WIN32 + renderdoc_module = GetModuleHandleA("renderdoc.dll"); +#elif defined(ANDROID) + renderdoc_module = dlopen("libVkLayer_GLES_RenderDoc.so", RTLD_NOW | RTLD_NOLOAD); +#else + renderdoc_module = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD); +#endif + + if (!renderdoc_module) + { + LOGE("Failed to load RenderDoc, make sure RenderDoc started the application in capture mode.\n"); + return false; + } + +#ifdef _WIN32 + // Workaround GCC warning about FARPROC mismatch. + auto *gpa = GetProcAddress(renderdoc_module, "RENDERDOC_GetAPI"); + pRENDERDOC_GetAPI func; + memcpy(&func, &gpa, sizeof(func)); + + if (!func) + { + LOGE("Failed to load RENDERDOC_GetAPI function.\n"); + return false; + } +#else + auto *func = reinterpret_cast(dlsym(renderdoc_module, "RENDERDOC_GetAPI")); + if (!func) + { + LOGE("Failed to load RENDERDOC_GetAPI function.\n"); + return false; + } +#endif + + if (!func(eRENDERDOC_API_Version_1_0_0, reinterpret_cast(&renderdoc_api))) + { + LOGE("Failed to obtain RenderDoc 1.0.0 API.\n"); + return false; + } + else + { + int major, minor, patch; + renderdoc_api->GetAPIVersion(&major, &minor, &patch); + LOGI("Initialized RenderDoc API %d.%d.%d.\n", major, minor, patch); + } + + return true; +} + +void Device::begin_renderdoc_capture() +{ + std::lock_guard holder{module_lock}; + if (!renderdoc_api) + { + LOGE("RenderDoc API is not loaded, cannot trigger capture.\n"); + return; + } + next_frame_context(); + + LOGI("Starting RenderDoc frame capture.\n"); + renderdoc_api->StartFrameCapture(nullptr, nullptr); +} + +void Device::end_renderdoc_capture() +{ + std::lock_guard holder{module_lock}; + if (!renderdoc_api) + { + LOGE("RenderDoc API is not loaded, cannot trigger capture.\n"); + return; + } + next_frame_context(); + renderdoc_api->EndFrameCapture(nullptr, nullptr); + LOGI("Ended RenderDoc frame capture.\n"); +} + +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/rtas.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/rtas.cpp new file mode 100644 index 00000000..5a07caec --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/rtas.cpp @@ -0,0 +1,61 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "rtas.hpp" +#include "device.hpp" + +namespace Vulkan +{ +RTAS::RTAS(Device *device_, VkAccelerationStructureKHR rtas_, + VkAccelerationStructureTypeKHR type_, BufferHandle backing_) + : Cookie(device_) + , device(device_) + , rtas(rtas_) + , type(type_) + , backing(std::move(backing_)) +{ + VkAccelerationStructureDeviceAddressInfoKHR info = + { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR }; + info.accelerationStructure = rtas; + bda = device->get_device_table().vkGetAccelerationStructureDeviceAddressKHR(device->get_device(), &info); +} + +VkDeviceSize RTAS::get_scratch_size(BuildMode mode) const +{ + return mode == BuildMode::Build ? build_size : update_size; +} + +RTAS::~RTAS() +{ + device->destroy_rtas(rtas); +} + +void RTASDeleter::operator()(Vulkan::RTAS *rtas) +{ + // Avoid hitting destruction callback inside a callback. + rtas->backing.reset(); + + rtas->device->handle_pool.rtas.free(rtas); +} +} + + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/rtas.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/rtas.hpp new file mode 100644 index 00000000..b119e5d9 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/rtas.hpp @@ -0,0 +1,131 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "cookie.hpp" +#include "vulkan_common.hpp" +#include "memory_allocator.hpp" +#include "buffer.hpp" + +namespace Vulkan +{ +class RTAS; +class Device; + +struct RTASDeleter +{ + void operator()(RTAS *rtas); +}; + +enum class BLASMode +{ + Static, // fast trace, compactable, not updateable + Skinned // fast update, updateable +}; + +enum class BuildMode +{ + Build, + Update +}; + +struct BottomRTASGeometry +{ + VkFormat format; + VkDeviceAddress vbo; + uint32_t num_vertices; + uint32_t stride; + + VkDeviceAddress ibo; + VkIndexType index_type; + uint32_t num_primitives; + + VkDeviceAddress transform; +}; + +struct BottomRTASCreateInfo +{ + BLASMode mode; + const BottomRTASGeometry *geometries; + size_t count; +}; + +struct RTASInstance +{ + // One of the two. + const VkAccelerationStructureInstanceKHR *instance; + VkDeviceAddress bda; +}; + +struct TopRTASCreateInfo +{ + const RTASInstance *instances; + size_t count; +}; + +class RTAS : public Util::IntrusivePtrEnabled, + public Cookie +{ +public: + friend struct RTASDeleter; + ~RTAS(); + + inline VkAccelerationStructureKHR get_rtas() const + { + return rtas; + } + + inline VkAccelerationStructureTypeKHR get_type() const + { + return type; + } + + inline VkDeviceAddress get_device_address() const + { + return bda; + } + + VkDeviceSize get_scratch_size(BuildMode mode) const; + + inline void set_scratch_size(VkDeviceSize build_size_, VkDeviceSize update_size_) + { + build_size = build_size_; + update_size = update_size_; + } + +private: + friend class Util::ObjectPool; + RTAS(Device *device, VkAccelerationStructureKHR rtas, + VkAccelerationStructureTypeKHR type, BufferHandle backing); + Device *device; + VkAccelerationStructureKHR rtas; + VkAccelerationStructureTypeKHR type; + BufferHandle backing; + VkDeviceSize build_size; + VkDeviceSize update_size; + VkDeviceAddress bda = 0; +}; + +using RTASHandle = Util::IntrusivePtr; +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/sampler.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/sampler.cpp new file mode 100644 index 00000000..6c184b6c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/sampler.cpp @@ -0,0 +1,173 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "sampler.hpp" +#include "device.hpp" + +namespace Vulkan +{ +Sampler::Sampler(Device *device_, VkSampler sampler_, const SamplerCreateInfo &info, bool immutable_) + : Cookie(device_) + , device(device_) + , sampler(sampler_) + , create_info(info) + , immutable(immutable_) +{ + // In heap, the VkSampler is a dummy object which is literally just the index into heap. + + if (device->get_device_features().supports_descriptor_buffer && + !device->get_device_features().descriptor_heap_features.descriptorHeap) + { + payload = device->managers.descriptor_buffer.alloc_sampler(); + VkDescriptorGetInfoEXT get_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT }; + get_info.type = VK_DESCRIPTOR_TYPE_SAMPLER; + get_info.data.pSampler = &sampler; + device->get_device_table().vkGetDescriptorEXT( + device->get_device(), + &get_info, + device->get_device_features().descriptor_buffer_properties.samplerDescriptorSize, + payload.ptr); + } +} + +Sampler::~Sampler() +{ + if (sampler) + { + if (immutable) + device->managers.descriptor_buffer.destroy_sampler(sampler); + else if (internal_sync) + device->destroy_sampler_nolock(sampler); + else + device->destroy_sampler(sampler); + } + + if (payload) + { + if (internal_sync) + device->free_cached_descriptor_payload_nolock(payload); + else + device->free_cached_descriptor_payload(payload); + } +} + +void SamplerDeleter::operator()(Sampler *sampler) +{ + sampler->device->handle_pool.samplers.free(sampler); +} + +SamplerCreateInfo Sampler::fill_sampler_info(const VkSamplerCreateInfo &info) +{ + SamplerCreateInfo sampler_info = {}; + + sampler_info.mag_filter = info.magFilter; + sampler_info.min_filter = info.minFilter; + sampler_info.mipmap_mode = info.mipmapMode; + sampler_info.address_mode_u = info.addressModeU; + sampler_info.address_mode_v = info.addressModeV; + sampler_info.address_mode_w = info.addressModeW; + sampler_info.mip_lod_bias = info.mipLodBias; + sampler_info.anisotropy_enable = info.anisotropyEnable; + sampler_info.max_anisotropy = info.maxAnisotropy; + sampler_info.compare_enable = info.compareEnable; + sampler_info.compare_op = info.compareOp; + sampler_info.min_lod = info.minLod; + sampler_info.max_lod = info.maxLod; + sampler_info.border_color = info.borderColor; + sampler_info.unnormalized_coordinates = info.unnormalizedCoordinates; + return sampler_info; +} + +VkSamplerCreateInfo Sampler::fill_vk_sampler_info(const SamplerCreateInfo &sampler_info) +{ + VkSamplerCreateInfo info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; + + info.magFilter = sampler_info.mag_filter; + info.minFilter = sampler_info.min_filter; + info.mipmapMode = sampler_info.mipmap_mode; + info.addressModeU = sampler_info.address_mode_u; + info.addressModeV = sampler_info.address_mode_v; + info.addressModeW = sampler_info.address_mode_w; + info.mipLodBias = sampler_info.mip_lod_bias; + info.anisotropyEnable = sampler_info.anisotropy_enable; + info.maxAnisotropy = sampler_info.max_anisotropy; + info.compareEnable = sampler_info.compare_enable; + info.compareOp = sampler_info.compare_op; + info.minLod = sampler_info.min_lod; + info.maxLod = sampler_info.max_lod; + info.borderColor = sampler_info.border_color; + info.unnormalizedCoordinates = sampler_info.unnormalized_coordinates; + return info; +} + +ImmutableSampler::ImmutableSampler(Util::Hash hash, Device *device_, const SamplerCreateInfo &sampler_info, + const ImmutableYcbcrConversion *ycbcr_) + : HashedObject(hash), device(device_), ycbcr(ycbcr_) +{ + VkSamplerYcbcrConversionInfo conv_info = { VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO }; + auto info = Sampler::fill_vk_sampler_info(sampler_info); + + if (ycbcr) + { + conv_info.conversion = ycbcr->get_conversion(); + info.pNext = &conv_info; + } + + VkSampler vk_sampler = device->managers.descriptor_buffer.create_sampler(&info); + +#ifdef GRANITE_VULKAN_FOSSILIZE + // Immutable samplers are on the chopping block ... + if (!device->get_device_features().supports_descriptor_buffer_or_heap) + device->register_sampler(vk_sampler, hash, info); +#endif + + sampler = SamplerHandle(device->handle_pool.samplers.allocate(device, vk_sampler, sampler_info, true)); +} + +ImmutableYcbcrConversion::ImmutableYcbcrConversion(Util::Hash hash, Device *device_, + const VkSamplerYcbcrConversionCreateInfo &info) + : HashedObject(hash), device(device_) +{ + if (device->get_device_features().vk11_features.samplerYcbcrConversion) + { + if (device->get_device_table().vkCreateSamplerYcbcrConversion(device->get_device(), &info, nullptr, + &conversion) != VK_SUCCESS) + { + LOGE("Failed to create YCbCr conversion.\n"); + } + else + { +#ifdef GRANITE_VULKAN_FOSSILIZE + device->register_sampler_ycbcr_conversion(conversion, info); +#endif + } + } + else + LOGE("Ycbcr conversion is not supported on this device.\n"); +} + +ImmutableYcbcrConversion::~ImmutableYcbcrConversion() +{ + if (conversion) + device->get_device_table().vkDestroySamplerYcbcrConversion(device->get_device(), conversion, nullptr); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/sampler.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/sampler.hpp new file mode 100644 index 00000000..241d027c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/sampler.hpp @@ -0,0 +1,154 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "cookie.hpp" +#include "vulkan_common.hpp" +#include "vulkan_headers.hpp" +#include "object_pool.hpp" +#include "memory_allocator.hpp" + +namespace Vulkan +{ +enum class StockSampler +{ + NearestClamp, + LinearClamp, + TrilinearClamp, + NearestWrap, + LinearWrap, + TrilinearWrap, + NearestShadow, + LinearShadow, + DefaultGeometryFilterClamp, + DefaultGeometryFilterWrap, + Count +}; + +struct SamplerCreateInfo +{ + VkFilter mag_filter; + VkFilter min_filter; + VkSamplerMipmapMode mipmap_mode; + VkSamplerAddressMode address_mode_u; + VkSamplerAddressMode address_mode_v; + VkSamplerAddressMode address_mode_w; + float mip_lod_bias; + VkBool32 anisotropy_enable; + float max_anisotropy; + VkBool32 compare_enable; + VkCompareOp compare_op; + float min_lod; + float max_lod; + VkBorderColor border_color; + VkBool32 unnormalized_coordinates; +}; + +class Sampler; +struct SamplerDeleter +{ + void operator()(Sampler *sampler); +}; + +class Sampler : public Util::IntrusivePtrEnabled, + public Cookie, public InternalSyncEnabled +{ +public: + friend struct SamplerDeleter; + ~Sampler(); + + VkSampler get_sampler() const + { + return sampler; + } + + const CachedDescriptorPayload &get_descriptor_payload() const + { + VK_ASSERT(payload && payload.type == VK_DESCRIPTOR_TYPE_SAMPLER); + return payload; + } + + const SamplerCreateInfo &get_create_info() const + { + return create_info; + } + + static VkSamplerCreateInfo fill_vk_sampler_info(const SamplerCreateInfo &sampler_info); + static SamplerCreateInfo fill_sampler_info(const VkSamplerCreateInfo &sampler_info); + +private: + friend class Util::ObjectPool; + Sampler(Device *device, VkSampler sampler, const SamplerCreateInfo &info, bool immutable); + + Device *device; + VkSampler sampler; + CachedDescriptorPayload payload; + SamplerCreateInfo create_info; + bool immutable; +}; +using SamplerHandle = Util::IntrusivePtr; + +class ImmutableYcbcrConversion : public HashedObject +{ +public: + ImmutableYcbcrConversion(Util::Hash hash, Device *device, + const VkSamplerYcbcrConversionCreateInfo &info); + ~ImmutableYcbcrConversion(); + void operator=(const ImmutableYcbcrConversion &) = delete; + ImmutableYcbcrConversion(const ImmutableYcbcrConversion &) = delete; + + VkSamplerYcbcrConversion get_conversion() const + { + return conversion; + } + +private: + Device *device; + VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE; +}; + +class ImmutableSampler : public HashedObject +{ +public: + ImmutableSampler(Util::Hash hash, Device *device, + const SamplerCreateInfo &info, + const ImmutableYcbcrConversion *ycbcr); + void operator=(const ImmutableSampler &) = delete; + ImmutableSampler(const ImmutableSampler &) = delete; + + const Sampler &get_sampler() const + { + return *sampler; + } + + VkSamplerYcbcrConversion get_ycbcr_conversion() const + { + return ycbcr ? ycbcr->get_conversion() : VK_NULL_HANDLE; + } + +private: + Device *device; + const ImmutableYcbcrConversion *ycbcr; + SamplerHandle sampler; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore.cpp new file mode 100644 index 00000000..03e55b2e --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore.cpp @@ -0,0 +1,244 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "semaphore.hpp" +#include "device.hpp" + +#ifndef _WIN32 +#include +#else +#define WIN32_LEAN_AND_MEAN +#include +#endif + +namespace Vulkan +{ +SemaphoreHolder::~SemaphoreHolder() +{ + recycle_semaphore(); +} + +void SemaphoreHolder::recycle_semaphore() +{ + if (!owned) + return; + + VK_ASSERT(semaphore); + + if (internal_sync) + { + if (semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE || external_compatible_features) + { + device->destroy_semaphore_nolock(semaphore); + } + else if (is_signalled()) + { + // We can't just destroy a semaphore if we don't know who signals it (e.g. WSI). + // Have to consume it by waiting then recycle. + if (signal_is_foreign_queue) + device->consume_semaphore_nolock(semaphore); + else + device->destroy_semaphore_nolock(semaphore); + } + else + device->recycle_semaphore_nolock(semaphore); + } + else + { + if (semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE || external_compatible_features) + { + device->destroy_semaphore(semaphore); + } + else if (is_signalled()) + { + // We can't just destroy a semaphore if we don't know who signals it (e.g. WSI). + // Have to consume it by waiting then recycle. + if (signal_is_foreign_queue) + device->consume_semaphore(semaphore); + else + device->destroy_semaphore(semaphore); + } + else + device->recycle_semaphore(semaphore); + } +} + +bool SemaphoreHolder::wait_timeline_timeout(uint64_t value, uint64_t timeout) +{ + VK_ASSERT(semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE); + VK_ASSERT(is_proxy_timeline()); + + VkSemaphoreWaitInfo wait_info = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO }; + wait_info.pSemaphores = &semaphore; + wait_info.semaphoreCount = 1; + wait_info.pValues = &value; + return device->get_device_table().vkWaitSemaphores(device->get_device(), &wait_info, timeout) == VK_SUCCESS; +} + +void SemaphoreHolder::wait_timeline(uint64_t value) +{ + wait_timeline_timeout(value, UINT64_MAX); +} + +SemaphoreHolder &SemaphoreHolder::operator=(SemaphoreHolder &&other) noexcept +{ + if (this == &other) + return *this; + + assert(device == other.device); + recycle_semaphore(); + + semaphore = other.semaphore; + timeline = other.timeline; + signalled = other.signalled; + pending_wait = other.pending_wait; + semaphore_type = other.semaphore_type; + owned = other.owned; + + other.semaphore = VK_NULL_HANDLE; + other.timeline = 0; + other.signalled = false; + other.pending_wait = false; + other.owned = false; + + return *this; +} + +ExternalHandle SemaphoreHolder::export_to_handle() +{ + ExternalHandle h; + + if ((external_compatible_features & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0) + { + LOGE("Semaphore is not export compatible.\n"); + return h; + } + + if (!semaphore) + { + LOGE("Semaphore has already been consumed.\n"); + return h; + } + + // Technically we can export early with reference transference, but it's a bit dubious. + // We want to remain compatible with copy transference for later, e.g. SYNC_FD. + if (!signalled && semaphore_type == VK_SEMAPHORE_TYPE_BINARY) + { + LOGE("Cannot export payload from a semaphore that is not queued up for signal.\n"); + return h; + } + +#ifdef _WIN32 + VkSemaphoreGetWin32HandleInfoKHR handle_info = { VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR }; + handle_info.semaphore = semaphore; + handle_info.handleType = external_compatible_handle_type; + + if (device->get_device_table().vkGetSemaphoreWin32HandleKHR(device->get_device(), &handle_info, &h.handle) != VK_SUCCESS) + { + LOGE("Failed to export to opaque handle.\n"); + h.handle = nullptr; + } +#else + VkSemaphoreGetFdInfoKHR fd_info = { VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR }; + fd_info.semaphore = semaphore; + fd_info.handleType = external_compatible_handle_type; + + if (device->get_device_table().vkGetSemaphoreFdKHR(device->get_device(), &fd_info, &h.handle) != VK_SUCCESS) + { + LOGE("Failed to export to opaque FD.\n"); + h.handle = -1; + } +#endif + + h.semaphore_handle_type = external_compatible_handle_type; + return h; +} + +bool SemaphoreHolder::import_from_handle(ExternalHandle handle) +{ + if ((external_compatible_features & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0) + { + LOGE("Semaphore is not import compatible.\n"); + return false; + } + + if (!semaphore) + { + LOGE("Semaphore has already been consumed.\n"); + return false; + } + + if (signalled) + { + LOGE("Cannot import payload to semaphore that is already signalled.\n"); + return false; + } + + if (handle.semaphore_handle_type != external_compatible_handle_type) + { + LOGE("Mismatch in semaphore handle type.\n"); + return false; + } + +#ifdef _WIN32 + VkImportSemaphoreWin32HandleInfoKHR import = { VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR }; + import.handle = handle.handle; + import.semaphore = semaphore; + import.handleType = handle.semaphore_handle_type; + import.flags = semaphore_type == VK_SEMAPHORE_TYPE_BINARY_KHR ? VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : 0; + if (device->get_device_table().vkImportSemaphoreWin32HandleKHR(device->get_device(), &import) != VK_SUCCESS) + { + LOGE("Failed to import semaphore handle %p!\n", handle.handle); + return false; + } +#else + VkImportSemaphoreFdInfoKHR import = { VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR }; + import.fd = handle.handle; + import.semaphore = semaphore; + import.handleType = handle.semaphore_handle_type; + import.flags = semaphore_type == VK_SEMAPHORE_TYPE_BINARY_KHR ? VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : 0; + if (device->get_device_table().vkImportSemaphoreFdKHR(device->get_device(), &import) != VK_SUCCESS) + { + LOGE("Failed to import semaphore FD %d!\n", handle.handle); + return false; + } +#endif + + if (ExternalHandle::semaphore_handle_type_imports_by_reference(import.handleType)) + { +#ifdef _WIN32 + // Consume the handle, since the VkSemaphore holds a reference on Win32. + ::CloseHandle(handle.handle); +#else + ::close(handle.handle); +#endif + } + + signal_external(); + return true; +} + +void SemaphoreHolderDeleter::operator()(Vulkan::SemaphoreHolder *semaphore) +{ + semaphore->device->handle_pool.semaphores.free(semaphore); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore.hpp new file mode 100644 index 00000000..92baf723 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore.hpp @@ -0,0 +1,211 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_common.hpp" +#include "vulkan_headers.hpp" +#include "cookie.hpp" +#include "object_pool.hpp" + +namespace Vulkan +{ +class Device; + +class SemaphoreHolder; +struct SemaphoreHolderDeleter +{ + void operator()(SemaphoreHolder *semaphore); +}; + +class SemaphoreHolder : public Util::IntrusivePtrEnabled, + public InternalSyncEnabled +{ +public: + friend struct SemaphoreHolderDeleter; + + ~SemaphoreHolder(); + + const VkSemaphore &get_semaphore() const + { + return semaphore; + } + + bool is_signalled() const + { + return signalled; + } + + uint64_t get_timeline_value() const + { + VK_ASSERT(!owned && semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE_KHR); + return timeline; + } + + bool is_owned() const + { + return owned; + } + + VkSemaphore consume() + { + auto ret = semaphore; + VK_ASSERT(semaphore); + VK_ASSERT(signalled); + semaphore = VK_NULL_HANDLE; + signalled = false; + owned = false; + return ret; + } + + VkSemaphore release_semaphore() + { + auto ret = semaphore; + semaphore = VK_NULL_HANDLE; + signalled = false; + owned = false; + return ret; + } + + void wait_external() + { + VK_ASSERT(semaphore); + VK_ASSERT(signalled); + signalled = false; + } + + void signal_external() + { + VK_ASSERT(!signalled); + VK_ASSERT(semaphore); + signalled = true; + } + + void set_signal_is_foreign_queue() + { + VK_ASSERT(signalled); + signal_is_foreign_queue = true; + } + + void set_pending_wait() + { + pending_wait = true; + } + + bool is_pending_wait() const + { + return pending_wait; + } + + void set_external_object_compatible(VkExternalSemaphoreHandleTypeFlagBits handle_type, + VkExternalSemaphoreFeatureFlags features) + { + external_compatible_handle_type = handle_type; + external_compatible_features = features; + } + + bool is_external_object_compatible() const + { + return external_compatible_features != 0; + } + + VkSemaphoreTypeKHR get_semaphore_type() const + { + return semaphore_type; + } + + bool is_proxy_timeline() const + { + return proxy_timeline; + } + + void set_proxy_timeline() + { + proxy_timeline = true; + signalled = false; + } + + // If successful, importing takes ownership of the handle/fd. + // Application can use dup() / DuplicateHandle() to keep a reference. + // Imported semaphores are assumed to be signalled, or pending to be signalled. + // All imports are performed with TEMPORARY permanence. + ExternalHandle export_to_handle(); + bool import_from_handle(ExternalHandle handle); + + VkExternalSemaphoreFeatureFlags get_external_features() const + { + return external_compatible_features; + } + + VkExternalSemaphoreHandleTypeFlagBits get_external_handle_type() const + { + return external_compatible_handle_type; + } + + SemaphoreHolder &operator=(SemaphoreHolder &&other) noexcept; + + void wait_timeline(uint64_t value); + bool wait_timeline_timeout(uint64_t value, uint64_t timeout); + +private: + friend class Util::ObjectPool; + SemaphoreHolder(Device *device_, VkSemaphore semaphore_, bool signalled_, bool owned_) + : device(device_) + , semaphore(semaphore_) + , timeline(0) + , semaphore_type(VK_SEMAPHORE_TYPE_BINARY_KHR) + , signalled(signalled_) + , owned(owned_) + { + } + + SemaphoreHolder(Device *device_, uint64_t timeline_, VkSemaphore semaphore_, bool owned_) + : device(device_) + , semaphore(semaphore_) + , timeline(timeline_) + , semaphore_type(VK_SEMAPHORE_TYPE_TIMELINE_KHR) + , owned(owned_) + { + } + + explicit SemaphoreHolder(Device *device_) + : device(device_) + { + } + + void recycle_semaphore(); + + Device *device; + VkSemaphore semaphore = VK_NULL_HANDLE; + uint64_t timeline = 0; + VkSemaphoreTypeKHR semaphore_type = VK_SEMAPHORE_TYPE_BINARY_KHR; + bool signalled = false; + bool pending_wait = false; + bool owned = false; + bool proxy_timeline = false; + bool signal_is_foreign_queue = false; + VkExternalSemaphoreHandleTypeFlagBits external_compatible_handle_type = {}; + VkExternalSemaphoreFeatureFlags external_compatible_features = 0; +}; + +using Semaphore = Util::IntrusivePtr; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore_manager.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore_manager.cpp new file mode 100644 index 00000000..62abe403 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore_manager.cpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "semaphore_manager.hpp" +#include "device.hpp" + +namespace Vulkan +{ +void SemaphoreManager::init(Device *device_) +{ + device = device_; + table = &device->get_device_table(); +} + +SemaphoreManager::~SemaphoreManager() +{ + for (auto &sem : semaphores) + table->vkDestroySemaphore(device->get_device(), sem, nullptr); +} + +void SemaphoreManager::recycle(VkSemaphore sem) +{ + if (sem != VK_NULL_HANDLE) + semaphores.push_back(sem); +} + +VkSemaphore SemaphoreManager::request_cleared_semaphore() +{ + if (semaphores.empty()) + { + VkSemaphoreCreateInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; + VkSemaphore semaphore; + + if (table->vkCreateSemaphore(device->get_device(), &info, nullptr, &semaphore) != VK_SUCCESS) + { + LOGE("Failed to create semaphore.\n"); + semaphore = VK_NULL_HANDLE; + } + + return semaphore; + } + else + { + auto sem = semaphores.back(); + semaphores.pop_back(); + return sem; + } +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore_manager.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore_manager.hpp new file mode 100644 index 00000000..b5a224a2 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/semaphore_manager.hpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include + +namespace Vulkan +{ +class Device; +class SemaphoreManager +{ +public: + void init(Device *device); + ~SemaphoreManager(); + + VkSemaphore request_cleared_semaphore(); + void recycle(VkSemaphore semaphore); + +private: + Device *device = nullptr; + const VolkDeviceTable *table = nullptr; + std::vector semaphores; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/shader.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/shader.cpp new file mode 100644 index 00000000..c048290a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/shader.cpp @@ -0,0 +1,1165 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "shader.hpp" +#include "device.hpp" +#ifdef GRANITE_VULKAN_SPIRV_CROSS +#include "spirv_cross.hpp" +using namespace spirv_cross; +#endif + +#ifdef HAVE_GRANITE_VULKAN_POST_MORTEM +#include "post_mortem.hpp" +#endif + +using namespace Util; + +namespace Vulkan +{ +void ImmutableSamplerBank::hash(Util::Hasher &h, const ImmutableSamplerBank *sampler_bank) +{ + h.u32(0); + if (sampler_bank) + { + unsigned index = 0; + for (auto &set : sampler_bank->samplers) + { + for (auto *binding : set) + { + if (binding) + { + h.u32(index); + h.u64(binding->get_hash()); + } + index++; + } + } + } +} + +// 32 bytes is a decent amount in most cases. For cases with lots of resources, just fallback to heap slice. +static constexpr uint32_t MaxInlineSizePerSet = (256 - VULKAN_PUSH_CONSTANT_SIZE) / VULKAN_NUM_DESCRIPTOR_SETS; +// Worst case we can always fall back to heap slice or indirect table for images. This requires at most one BDA. +static constexpr uint32_t MaxBufferInlineSizePerSet = MaxInlineSizePerSet - sizeof(VkDeviceAddress); + +static uint32_t align(uint32_t size, uint32_t alignment) +{ + return (size + alignment - 1) & ~(alignment - 1); +} + +void PipelineLayout::init_heap_buffers(uint32_t set_index) +{ + auto buffer_desc_size = + align(device->get_device_features().descriptor_heap_properties.bufferDescriptorSize, + device->get_device_features().descriptor_heap_properties.bufferDescriptorAlignment); + auto &push_data_offset = heap.push_data_size; + + auto &desc_set = layout.sets[set_index]; + + auto raw_buffer_mask = desc_set.uniform_buffer_mask | desc_set.storage_buffer_mask | desc_set.rtas_mask; + + uint32_t num_buffer_descriptors = 0; + bool requires_array_length_or_array = device->get_device_features().enabled_features.robustBufferAccess == VK_TRUE; + Util::for_each_bit(raw_buffer_mask, [&](unsigned bit) + { + num_buffer_descriptors += desc_set.meta[bit].array_size; + if (desc_set.meta[bit].array_size > 1) + requires_array_length_or_array = true; + }); + + auto required_inline_size = num_buffer_descriptors * sizeof(VkDeviceAddress); + + // If we enable robustness, we cannot use PUSH_ADDRESS. + Util::for_each_bit(raw_buffer_mask, [&](unsigned bit) + { + if (desc_set.meta[bit].requires_descriptor_size) + requires_array_length_or_array = true; + }); + + // Raw PUSH_ADDRESS is always preferred. + if (required_inline_size <= MaxBufferInlineSizePerSet && !requires_array_length_or_array) + { + heap.buffer_strategies[set_index] = DescriptorStrategy::Inline; + + if (required_inline_size) + push_data_offset = align(push_data_offset, sizeof(VkDeviceAddress)); + + heap.push_inline_offsets[set_index] = push_data_offset; + heap.push_inline_size[set_index] += required_inline_size; + push_data_offset += required_inline_size; + } + else if (requires_array_length_or_array) + { + heap.buffer_strategies[set_index] = DescriptorStrategy::HeapSlice; + heap.push_buffer_offsets[set_index] = push_data_offset; + // A single u32 will do. + push_data_offset += sizeof(uint32_t); + + // Allocate N descriptors from the heap and write them directly. + heap.heap_slice_size[set_index] = align(heap.heap_slice_size[set_index], buffer_desc_size); + heap.heap_slice_size[set_index] += num_buffer_descriptors * buffer_desc_size; + } + else + { + // Small buffer of BDAs. Don't want to allocate from the precious heap if possible. + heap.buffer_strategies[set_index] = DescriptorStrategy::IndirectTable; + push_data_offset = align(push_data_offset, sizeof(VkDeviceAddress)); + heap.push_buffer_offsets[set_index] = push_data_offset; + push_data_offset += sizeof(VkDeviceAddress); + + heap.heap_table_size[set_index] += required_inline_size; + } +} + +void PipelineLayout::init_heap_image(uint32_t set_index) +{ + auto image_desc_size = + align(device->get_device_features().descriptor_heap_properties.imageDescriptorSize, + device->get_device_features().descriptor_heap_properties.imageDescriptorAlignment); + + auto &push_data_offset = heap.push_data_size; + auto &desc_set = layout.sets[set_index]; + + auto image_sampler_mask = + desc_set.sampled_image_mask | + desc_set.separate_image_mask | desc_set.storage_image_mask | + desc_set.sampled_texel_buffer_mask | desc_set.storage_texel_buffer_mask | + desc_set.input_attachment_mask | + desc_set.sampler_mask; + + auto sampler_mask = desc_set.sampled_image_mask | desc_set.sampler_mask; + uint32_t num_image_descriptors = 0; + Util::for_each_bit(image_sampler_mask, [&](unsigned bit) + { + num_image_descriptors += desc_set.meta[bit].array_size; + }); + bool requires_array_of_image = false; + + Util::for_each_bit(image_sampler_mask, [&](unsigned bit) + { + if (desc_set.meta[bit].array_size > 1) + requires_array_of_image = true; + }); + + uint32_t available_inline_indices = (MaxInlineSizePerSet - heap.push_inline_size[set_index]) / sizeof(uint32_t); + + // Array of resources would need either heap slice or indirection table. + if (num_image_descriptors <= available_inline_indices && !requires_array_of_image) + { + heap.image_strategies[set_index] = DescriptorStrategy::Inline; + + if (heap.buffer_strategies[set_index] != DescriptorStrategy::Inline) + heap.push_inline_offsets[set_index] = push_data_offset; + + heap.push_inline_size[set_index] += num_image_descriptors * sizeof(uint32_t); + push_data_offset += num_image_descriptors * sizeof(uint32_t); + } + else if (sampler_mask != 0 && (layout.bindless_descriptor_set_mask & (1u << set_index)) == 0) + { + // We cannot lower sampler to heap slice since sampler heap is so tiny. + // Force indirection table. + // TODO: It's in theory possible to split this up + // so that samplers are push index inlined while everything else is heap sliced. + + // This isn't ideal, but what can you do. + heap.image_strategies[set_index] = DescriptorStrategy::IndirectTable; + + // Buffers and images can share the same indirection table. + if (heap.buffer_strategies[set_index] == DescriptorStrategy::IndirectTable) + { + heap.push_image_offsets[set_index] = heap.push_buffer_offsets[set_index]; + } + else + { + push_data_offset = align(push_data_offset, sizeof(VkDeviceAddress)); + heap.push_image_offsets[set_index] = push_data_offset; + push_data_offset += sizeof(VkDeviceAddress); + } + + // Buffers go first, for alignment purposes. + heap.heap_table_size[set_index] += num_image_descriptors * sizeof(uint32_t); + } + else + { + heap.image_strategies[set_index] = DescriptorStrategy::HeapSlice; + + if (heap.buffer_strategies[set_index] == DescriptorStrategy::HeapSlice) + { + heap.push_image_offsets[set_index] = heap.push_buffer_offsets[set_index]; + } + else + { + heap.push_image_offsets[set_index] = push_data_offset; + push_data_offset += sizeof(uint32_t); + } + + if ((layout.bindless_descriptor_set_mask & (1u << set_index)) == 0) + { + // Allocate N descriptors from the heap and write them directly. + heap.heap_slice_size[set_index] = align(heap.heap_slice_size[set_index], image_desc_size); + heap.heap_slice_size[set_index] += num_image_descriptors * image_desc_size; + } + } +} + +void PipelineLayout::init_heap_offsets(uint32_t set_index) +{ + auto buffer_desc_size = + align(device->get_device_features().descriptor_heap_properties.bufferDescriptorSize, + device->get_device_features().descriptor_heap_properties.bufferDescriptorAlignment); + + auto image_desc_size = + align(device->get_device_features().descriptor_heap_properties.imageDescriptorSize, + device->get_device_features().descriptor_heap_properties.imageDescriptorAlignment); + + auto sampler_desc_size = + align(device->get_device_features().descriptor_heap_properties.samplerDescriptorSize, + device->get_device_features().descriptor_heap_properties.samplerDescriptorAlignment); + + auto &desc_set = layout.sets[set_index]; + + auto image_sampler_mask = + desc_set.sampled_image_mask | + desc_set.separate_image_mask | desc_set.storage_image_mask | + desc_set.sampled_texel_buffer_mask | desc_set.storage_texel_buffer_mask | + desc_set.input_attachment_mask | + desc_set.sampler_mask; + + auto buffer_mask = desc_set.uniform_buffer_mask | desc_set.storage_buffer_mask | desc_set.rtas_mask; + + uint32_t push_offset = 0; + uint32_t table_offset = 0; + uint32_t slice_offset = 0; + + VkDescriptorSetAndBindingMappingEXT buffer_template = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_AND_BINDING_MAPPING_EXT }; + buffer_template.resourceMask = VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT | + VK_SPIRV_RESOURCE_TYPE_READ_WRITE_STORAGE_BUFFER_BIT_EXT | + VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT; + if (device->get_device_features().rtas_features.accelerationStructure) + buffer_template.resourceMask |= VK_SPIRV_RESOURCE_TYPE_ACCELERATION_STRUCTURE_BIT_EXT; + + VkDescriptorSetAndBindingMappingEXT image_template = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_AND_BINDING_MAPPING_EXT }; + image_template.resourceMask = VK_SPIRV_RESOURCE_TYPE_SAMPLED_IMAGE_BIT_EXT | + VK_SPIRV_RESOURCE_TYPE_READ_WRITE_STORAGE_BUFFER_BIT_EXT | + VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT | + VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT | + VK_SPIRV_RESOURCE_TYPE_READ_WRITE_IMAGE_BIT_EXT; + + switch (heap.buffer_strategies[set_index]) + { + case DescriptorStrategy::Inline: + Util::for_each_bit(buffer_mask, [&](unsigned bit) + { + heap.desc_offsets[set_index][bit] = push_offset; + auto mapping = buffer_template; + mapping.descriptorSet = set_index; + mapping.firstBinding = bit; + VK_ASSERT(desc_set.meta[bit].array_size == 1); + mapping.bindingCount = 1; + mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_ADDRESS_EXT; + mapping.sourceData.pushAddressOffset = push_offset + heap.push_inline_offsets[set_index]; + push_offset += sizeof(VkDeviceAddress); + heap.mappings.push_back(mapping); + }); + break; + + case DescriptorStrategy::HeapSlice: + Util::for_each_bit(buffer_mask, [&](unsigned bit) + { + slice_offset = align(slice_offset, buffer_desc_size); + auto mapping = buffer_template; + mapping.descriptorSet = set_index; + mapping.firstBinding = bit; + mapping.bindingCount = desc_set.meta[bit].array_size; + mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT; + mapping.sourceData.pushIndex.pushOffset = heap.push_buffer_offsets[set_index]; + mapping.sourceData.pushIndex.heapArrayStride = buffer_desc_size; + mapping.sourceData.pushIndex.heapIndexStride = device->get_device_features().resource_heap_resource_desc_size; + mapping.sourceData.pushIndex.heapOffset = slice_offset; + for (unsigned i = 0; i < mapping.bindingCount; i++) + { + heap.desc_offsets[set_index][bit + i] = slice_offset; + slice_offset += buffer_desc_size; + } + heap.mappings.push_back(mapping); + }); + break; + + case DescriptorStrategy::IndirectTable: + Util::for_each_bit(buffer_mask, [&](unsigned bit) + { + table_offset = align(table_offset, sizeof(VkDeviceAddress)); + heap.desc_offsets[set_index][bit] = table_offset; + auto mapping = buffer_template; + mapping.descriptorSet = set_index; + mapping.firstBinding = bit; + VK_ASSERT(desc_set.meta[bit].array_size == 1); + mapping.bindingCount = 1; + mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_INDIRECT_ADDRESS_EXT; + mapping.sourceData.indirectAddress.pushOffset = heap.push_buffer_offsets[set_index]; + mapping.sourceData.indirectAddress.addressOffset = table_offset; + table_offset += sizeof(VkDeviceAddress); + heap.mappings.push_back(mapping); + }); + break; + + default: + break; + } + + bool bindless = (layout.bindless_descriptor_set_mask & (1u << set_index)) != 0; + VK_ASSERT(!bindless || slice_offset == 0); + + switch (heap.image_strategies[set_index]) + { + case DescriptorStrategy::Inline: + Util::for_each_bit(image_sampler_mask, [&](unsigned bit) + { + heap.desc_offsets[set_index][bit] = push_offset; + auto mapping = image_template; + mapping.descriptorSet = set_index; + mapping.firstBinding = bit; + VK_ASSERT(desc_set.meta[bit].array_size == 1); + mapping.bindingCount = 1; + mapping.resourceMask |= VK_SPIRV_RESOURCE_TYPE_COMBINED_SAMPLED_IMAGE_BIT_EXT; + mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT; + mapping.sourceData.pushIndex.pushOffset = push_offset + heap.push_inline_offsets[set_index]; + mapping.sourceData.pushIndex.heapOffset = 0; + mapping.sourceData.pushIndex.heapArrayStride = device->get_device_features().resource_heap_resource_desc_size; + mapping.sourceData.pushIndex.heapIndexStride = device->get_device_features().resource_heap_resource_desc_size; + + if ((desc_set.sampled_image_mask & (1u << bit)) != 0) + { + mapping.sourceData.pushIndex.useCombinedImageSamplerIndex = VK_TRUE; + mapping.sourceData.pushIndex.samplerHeapArrayStride = sampler_desc_size; + mapping.sourceData.pushIndex.samplerHeapIndexStride = sampler_desc_size; + } + + if ((desc_set.sampler_mask & (1u << bit)) == 0) + heap.mappings.push_back(mapping); + + mapping.resourceMask = VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT; + mapping.sourceData.pushIndex = {}; + mapping.sourceData.pushIndex.pushOffset = push_offset + heap.push_inline_offsets[set_index]; + mapping.sourceData.pushIndex.heapArrayStride = sampler_desc_size; + mapping.sourceData.pushIndex.heapIndexStride = sampler_desc_size; + if ((desc_set.sampler_mask & (1u << bit)) != 0) + heap.mappings.push_back(mapping); + + push_offset += sizeof(uint32_t); + }); + break; + + case DescriptorStrategy::HeapSlice: + Util::for_each_bit(image_sampler_mask, [&](unsigned bit) + { + slice_offset = align(slice_offset, image_desc_size); + auto mapping = image_template; + mapping.descriptorSet = set_index; + mapping.firstBinding = bit; + mapping.bindingCount = bindless ? 1 : desc_set.meta[bit].array_size; + mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT; + // HeapSlice is not compatible with sampler and combined image sampler. + mapping.sourceData.pushIndex.pushOffset = heap.push_image_offsets[set_index]; + mapping.sourceData.pushIndex.heapArrayStride = image_desc_size; + mapping.sourceData.pushIndex.heapIndexStride = device->get_device_features().resource_heap_resource_desc_size; + mapping.sourceData.pushIndex.heapOffset = slice_offset; + + if (!bindless) + { + for (unsigned i = 0; i < mapping.bindingCount; i++) + { + heap.desc_offsets[set_index][bit + i] = slice_offset; + slice_offset += image_desc_size; + } + } + + heap.mappings.push_back(mapping); + }); + break; + + case DescriptorStrategy::IndirectTable: + Util::for_each_bit(image_sampler_mask, [&](unsigned bit) + { + table_offset = align(table_offset, sizeof(uint32_t)); + heap.desc_offsets[set_index][bit] = table_offset; + auto mapping = image_template; + mapping.descriptorSet = set_index; + mapping.firstBinding = bit; + mapping.bindingCount = desc_set.meta[bit].array_size; + mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT; + mapping.resourceMask |= VK_SPIRV_RESOURCE_TYPE_COMBINED_SAMPLED_IMAGE_BIT_EXT; + mapping.sourceData.indirectIndexArray.pushOffset = heap.push_image_offsets[set_index]; + mapping.sourceData.indirectIndexArray.heapOffset = 0; + mapping.sourceData.indirectIndexArray.samplerHeapOffset = 0; + mapping.sourceData.indirectIndexArray.addressOffset = table_offset; + mapping.sourceData.indirectIndexArray.heapIndexStride = device->get_device_features().resource_heap_resource_desc_size; + + if ((desc_set.sampled_image_mask & (1u << bit)) != 0) + { + mapping.sourceData.indirectIndexArray.useCombinedImageSamplerIndex = VK_TRUE; + mapping.sourceData.indirectIndexArray.samplerHeapIndexStride = sampler_desc_size; + } + + if ((desc_set.sampler_mask & (1u << bit)) == 0) + heap.mappings.push_back(mapping); + + mapping.resourceMask = VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT; + mapping.sourceData.indirectIndexArray = {}; + mapping.sourceData.indirectIndexArray.pushOffset = heap.push_image_offsets[set_index]; + mapping.sourceData.indirectIndexArray.heapOffset = 0; + mapping.sourceData.indirectIndexArray.addressOffset = table_offset; + mapping.sourceData.indirectIndexArray.heapIndexStride = sampler_desc_size; + if ((desc_set.sampler_mask & (1u << bit)) != 0) + heap.mappings.push_back(mapping); + + for (unsigned i = 0; i < mapping.bindingCount; i++) + { + heap.desc_offsets[set_index][bit + i] = table_offset; + table_offset += sizeof(uint32_t); + } + }); + break; + + default: + break; + } + + VK_ASSERT(push_offset <= MaxInlineSizePerSet); + VK_ASSERT(push_offset == heap.push_inline_size[set_index]); + VK_ASSERT(table_offset == heap.heap_table_size[set_index]); + VK_ASSERT(slice_offset == heap.heap_slice_size[set_index]); +} + +void PipelineLayout::init_heap(uint32_t set_index) +{ + init_heap_buffers(set_index); + init_heap_image(set_index); + init_heap_offsets(set_index); +} + +void PipelineLayout::init_heap() +{ + uint32_t push_data_offset = layout.push_constant_range.offset + layout.push_constant_range.size; + heap.push_data_size = push_data_offset; + + for (unsigned i = 0; i < VULKAN_NUM_DESCRIPTOR_SETS; i++) + { + if ((layout.descriptor_set_mask & (1u << i)) != 0) + { + init_heap(i); + + // Only used to track when we need to invalidate sets. + set_allocators[i] = device->request_descriptor_set_allocator( + layout.sets[i], layout.stages_for_bindings[i], nullptr); + } + } + + VK_ASSERT(heap.push_data_size <= VULKAN_PUSH_DATA_SIZE); +} + +void PipelineLayout::init_legacy(const ImmutableSamplerBank *immutable_samplers) +{ + VkDescriptorSetLayout layouts[VULKAN_NUM_DESCRIPTOR_SETS] = {}; + unsigned num_sets = 0; + for (unsigned i = 0; i < VULKAN_NUM_DESCRIPTOR_SETS; i++) + { + set_allocators[i] = device->request_descriptor_set_allocator(layout.sets[i], layout.stages_for_bindings[i], + immutable_samplers ? immutable_samplers->samplers[i] : nullptr); + layouts[i] = set_allocators[i]->get_layout_for_pool(); + if (layout.descriptor_set_mask & (1u << i)) + { + num_sets = i + 1; + + // Assume the last set index in layout is the highest frequency update one, make that push descriptor if possible. + // Only one descriptor set can be push descriptor. + bool has_push_layout = set_allocators[i]->get_layout_for_push() != VK_NULL_HANDLE; + if (has_push_layout) + push_set_index = i; + } + } + + if (push_set_index != UINT32_MAX) + layouts[push_set_index] = set_allocators[push_set_index]->get_layout_for_push(); + + if (num_sets > VULKAN_NUM_DESCRIPTOR_SETS) + LOGE("Number of sets %u exceeds limit of %u.\n", num_sets, VULKAN_NUM_DESCRIPTOR_SETS); + + VkPipelineLayoutCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; + if (num_sets) + { + info.setLayoutCount = num_sets; + info.pSetLayouts = layouts; + } + + if (layout.push_constant_range.stageFlags != 0) + { + info.pushConstantRangeCount = 1; + info.pPushConstantRanges = &layout.push_constant_range; + } + +#ifdef VULKAN_DEBUG + LOGI("Creating pipeline layout.\n"); +#endif + auto &table = device->get_device_table(); + if (table.vkCreatePipelineLayout(device->get_device(), &info, nullptr, &pipe_layout) != VK_SUCCESS) + LOGE("Failed to create pipeline layout.\n"); +#ifdef GRANITE_VULKAN_FOSSILIZE + device->register_pipeline_layout(pipe_layout, get_hash(), info); +#endif + + if (!device->get_device_features().descriptor_buffer_features.descriptorBuffer) + create_update_templates(); +} + +PipelineLayout::PipelineLayout(Hash hash, Device *device_, const CombinedResourceLayout &layout_, + const ImmutableSamplerBank *immutable_samplers) + : IntrusiveHashMapEnabled(hash) + , device(device_) + , layout(layout_) +{ + if (device->get_device_features().descriptor_heap_features.descriptorHeap) + init_heap(); + else + init_legacy(immutable_samplers); +} + +void PipelineLayout::create_update_templates() +{ + auto &table = device->get_device_table(); + for (unsigned desc_set = 0; desc_set < VULKAN_NUM_DESCRIPTOR_SETS; desc_set++) + { + if ((layout.descriptor_set_mask & (1u << desc_set)) == 0) + continue; + if ((layout.bindless_descriptor_set_mask & (1u << desc_set)) != 0) + continue; + + VkDescriptorUpdateTemplateEntry update_entries[VULKAN_NUM_BINDINGS]; + uint32_t update_count = 0; + + auto &set_layout = layout.sets[desc_set]; + + for_each_bit(set_layout.uniform_buffer_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + // Work around a RenderDoc capture bug where descriptorCount > 1 is not handled correctly. + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + entry.offset = offsetof(ResourceBinding, buffer) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + for_each_bit(set_layout.storage_buffer_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + entry.offset = offsetof(ResourceBinding, buffer) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + for_each_bit(set_layout.rtas_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + entry.offset = offsetof(ResourceBinding, rtas) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + for_each_bit(set_layout.sampled_texel_buffer_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + entry.offset = offsetof(ResourceBinding, buffer_view.handle) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + for_each_bit(set_layout.storage_texel_buffer_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + entry.offset = offsetof(ResourceBinding, buffer_view.handle) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + for_each_bit(set_layout.sampled_image_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + if (set_layout.fp_mask & (1u << binding)) + entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i); + else + entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + for_each_bit(set_layout.separate_image_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + if (set_layout.fp_mask & (1u << binding)) + entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i); + else + entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + for_each_bit(set_layout.sampler_mask & ~set_layout.immutable_sampler_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + for_each_bit(set_layout.storage_image_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + for_each_bit(set_layout.input_attachment_mask, [&](uint32_t binding) { + unsigned array_size = set_layout.meta[binding].array_size; + VK_ASSERT(update_count < VULKAN_NUM_BINDINGS); + for (unsigned i = 0; i < array_size; i++) + { + auto &entry = update_entries[update_count++]; + entry.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + entry.dstBinding = binding; + entry.dstArrayElement = i; + entry.descriptorCount = 1; + if (set_layout.fp_mask & (1u << binding)) + entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i); + else + entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * (binding + i); + entry.stride = sizeof(ResourceBinding); + } + }); + + VkDescriptorUpdateTemplateCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO }; + info.pipelineLayout = pipe_layout; + + if (desc_set == push_set_index) + { + info.descriptorSetLayout = set_allocators[desc_set]->get_layout_for_push(); + info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS; + } + else + { + info.descriptorSetLayout = set_allocators[desc_set]->get_layout_for_pool(); + info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; + } + + info.set = desc_set; + info.descriptorUpdateEntryCount = update_count; + info.pDescriptorUpdateEntries = update_entries; + info.pipelineBindPoint = (layout.stages_for_sets[desc_set] & VK_SHADER_STAGE_COMPUTE_BIT) ? + VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS; + + if (table.vkCreateDescriptorUpdateTemplate(device->get_device(), &info, nullptr, + &update_template[desc_set]) != VK_SUCCESS) + { + LOGE("Failed to create descriptor update template.\n"); + } + } +} + +PipelineLayout::~PipelineLayout() +{ + auto &table = device->get_device_table(); + if (pipe_layout != VK_NULL_HANDLE) + table.vkDestroyPipelineLayout(device->get_device(), pipe_layout, nullptr); + + for (auto &update : update_template) + if (update != VK_NULL_HANDLE) + table.vkDestroyDescriptorUpdateTemplate(device->get_device(), update, nullptr); +} + +const char *Shader::stage_to_name(ShaderStage stage) +{ + switch (stage) + { + case ShaderStage::Compute: + return "compute"; + case ShaderStage::Vertex: + return "vertex"; + case ShaderStage::Fragment: + return "fragment"; + case ShaderStage::Task: + return "task"; + case ShaderStage::Mesh: + return "mesh"; + default: + return "unknown"; + } +} + +// Implicitly also checks for endian issues. +static const uint16_t reflection_magic[] = { 'G', 'R', 'A', ResourceLayout::Version }; + +size_t ResourceLayout::serialization_size() +{ + return sizeof(ResourceLayout) + sizeof(reflection_magic); +} + +bool ResourceLayout::serialize(uint8_t *data, size_t size) const +{ + if (size != serialization_size()) + return false; + + // Cannot serialize externally defined immutable samplers. + for (auto &set : sets) + if (set.immutable_sampler_mask != 0) + return false; + + memcpy(data, reflection_magic, sizeof(reflection_magic)); + memcpy(data + sizeof(reflection_magic), this, sizeof(*this)); + return true; +} + +bool ResourceLayout::unserialize(const uint8_t *data, size_t size) +{ + if (size != sizeof(*this) + sizeof(reflection_magic)) + { + LOGE("Reflection size mismatch.\n"); + return false; + } + + if (memcmp(data, reflection_magic, sizeof(reflection_magic)) != 0) + { + LOGE("Magic mismatch.\n"); + return false; + } + + memcpy(this, data + sizeof(reflection_magic), sizeof(*this)); + return true; +} + +Util::Hash Shader::hash(const uint32_t *data, size_t size) +{ + Util::Hasher hasher; + hasher.data(data, size); + return hasher.get(); +} + +#ifdef GRANITE_VULKAN_SPIRV_CROSS +static void update_array_info(ResourceLayout &layout, const SPIRType &type, unsigned set, unsigned binding) +{ + auto &meta = layout.sets[set].meta[binding]; + + if (!type.array.empty()) + { + if (type.array.size() != 1) + LOGE("Array dimension must be 1.\n"); + else if (!type.array_size_literal.front()) + LOGE("Array dimension must be a literal.\n"); + else + { + if (type.array.front() == 0) + { + if (binding != 0) + LOGE("Bindless textures can only be used with binding = 0 in a set.\n"); + + if (type.basetype != SPIRType::Image || type.image.dim == spv::DimBuffer) + { + LOGE("Can only use bindless for sampled images.\n"); + } + else + { + layout.bindless_set_mask |= 1u << set; + // Ignore fp_mask for bindless since we can mix and match. + layout.sets[set].fp_mask = 0; + } + + meta.array_size = DescriptorSetLayout::UNSIZED_ARRAY; + } + else if (meta.array_size && meta.array_size != type.array.front()) + LOGE("Array dimension for (%u, %u) is inconsistent.\n", set, binding); + else if (type.array.front() + binding > VULKAN_NUM_BINDINGS) + LOGE("Binding array will go out of bounds.\n"); + else + meta.array_size = uint8_t(type.array.front()); + } + } + else + { + if (meta.array_size && meta.array_size != 1) + LOGE("Array dimension for (%u, %u) is inconsistent.\n", set, binding); + meta.array_size = 1; + } +} + +bool Shader::reflect_resource_layout(ResourceLayout &layout, const uint32_t *data, size_t size) +{ + Compiler compiler(data, size / sizeof(uint32_t)); + +#ifdef VULKAN_DEBUG + LOGI("Reflecting shader layout.\n"); +#endif + + bool has_array_length = false; + auto &ir = compiler.get_ir(); + + ir.for_each_typed_id([&](uint32_t, const SPIRBlock &block) + { + if (has_array_length) + return; + + for (auto &op : block.ops) + { + auto spvop = spv::Op(op.op); + if (spvop == spv::OpArrayLength) + { + has_array_length = true; + return; + } + } + }); + + auto resources = compiler.get_shader_resources(); + for (auto &image : resources.sampled_images) + { + auto set = compiler.get_decoration(image.id, spv::DecorationDescriptorSet); + auto binding = compiler.get_decoration(image.id, spv::DecorationBinding); + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + auto &type = compiler.get_type(image.type_id); + if (type.image.dim == spv::DimBuffer) + layout.sets[set].sampled_texel_buffer_mask |= 1u << binding; + else + layout.sets[set].sampled_image_mask |= 1u << binding; + + if (compiler.get_type(type.image.type).basetype == SPIRType::BaseType::Float) + layout.sets[set].fp_mask |= 1u << binding; + + update_array_info(layout, type, set, binding); + } + + for (auto &image : resources.subpass_inputs) + { + auto set = compiler.get_decoration(image.id, spv::DecorationDescriptorSet); + auto binding = compiler.get_decoration(image.id, spv::DecorationBinding); + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + layout.sets[set].input_attachment_mask |= 1u << binding; + + auto &type = compiler.get_type(image.type_id); + if (compiler.get_type(type.image.type).basetype == SPIRType::BaseType::Float) + layout.sets[set].fp_mask |= 1u << binding; + update_array_info(layout, type, set, binding); + } + + for (auto &image : resources.separate_images) + { + auto set = compiler.get_decoration(image.id, spv::DecorationDescriptorSet); + auto binding = compiler.get_decoration(image.id, spv::DecorationBinding); + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + auto &type = compiler.get_type(image.type_id); + if (compiler.get_type(type.image.type).basetype == SPIRType::BaseType::Float) + layout.sets[set].fp_mask |= 1u << binding; + + if (type.image.dim == spv::DimBuffer) + layout.sets[set].sampled_texel_buffer_mask |= 1u << binding; + else + layout.sets[set].separate_image_mask |= 1u << binding; + + update_array_info(layout, type, set, binding); + } + + for (auto &image : resources.separate_samplers) + { + auto set = compiler.get_decoration(image.id, spv::DecorationDescriptorSet); + auto binding = compiler.get_decoration(image.id, spv::DecorationBinding); + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + layout.sets[set].sampler_mask |= 1u << binding; + update_array_info(layout, compiler.get_type(image.type_id), set, binding); + } + + for (auto &image : resources.storage_images) + { + auto set = compiler.get_decoration(image.id, spv::DecorationDescriptorSet); + auto binding = compiler.get_decoration(image.id, spv::DecorationBinding); + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + auto &type = compiler.get_type(image.type_id); + if (type.image.dim == spv::DimBuffer) + layout.sets[set].storage_texel_buffer_mask |= 1u << binding; + else + layout.sets[set].storage_image_mask |= 1u << binding; + + if (compiler.get_type(type.image.type).basetype == SPIRType::BaseType::Float) + layout.sets[set].fp_mask |= 1u << binding; + + update_array_info(layout, type, set, binding); + } + + for (auto &buffer : resources.uniform_buffers) + { + auto set = compiler.get_decoration(buffer.id, spv::DecorationDescriptorSet); + auto binding = compiler.get_decoration(buffer.id, spv::DecorationBinding); + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + layout.sets[set].uniform_buffer_mask |= 1u << binding; + update_array_info(layout, compiler.get_type(buffer.type_id), set, binding); + } + + for (auto &buffer : resources.storage_buffers) + { + auto set = compiler.get_decoration(buffer.id, spv::DecorationDescriptorSet); + auto binding = compiler.get_decoration(buffer.id, spv::DecorationBinding); + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + layout.sets[set].storage_buffer_mask |= 1u << binding; + update_array_info(layout, compiler.get_type(buffer.type_id), set, binding); + + if (has_array_length) + layout.sets[set].meta[binding].requires_descriptor_size = 1; + } + + for (auto &buffer : resources.acceleration_structures) + { + auto set = compiler.get_decoration(buffer.id, spv::DecorationDescriptorSet); + auto binding = compiler.get_decoration(buffer.id, spv::DecorationBinding); + VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + + layout.sets[set].rtas_mask |= 1u << binding; + update_array_info(layout, compiler.get_type(buffer.type_id), set, binding); + } + + for (auto &attrib : resources.stage_inputs) + { + auto location = compiler.get_decoration(attrib.id, spv::DecorationLocation); + layout.input_mask |= 1u << location; + } + + for (auto &attrib : resources.stage_outputs) + { + auto location = compiler.get_decoration(attrib.id, spv::DecorationLocation); + layout.output_mask |= 1u << location; + } + + if (!resources.push_constant_buffers.empty()) + { + // Don't bother trying to extract which part of a push constant block we're using. + // Just assume we're accessing everything. At least on older validation layers, + // it did not do a static analysis to determine similar information, so we got a lot + // of false positives. + layout.push_constant_size = + compiler.get_declared_struct_size(compiler.get_type(resources.push_constant_buffers.front().base_type_id)); + } + + auto spec_constants = compiler.get_specialization_constants(); + for (auto &c : spec_constants) + { + if (c.constant_id >= VULKAN_NUM_TOTAL_SPEC_CONSTANTS) + { + LOGE("Spec constant ID: %u is out of range, will be ignored.\n", c.constant_id); + continue; + } + + layout.spec_constant_mask |= 1u << c.constant_id; + } + + return true; +} +#else +bool Shader::reflect_resource_layout(ResourceLayout &, const uint32_t *, size_t) +{ + return false; +} +#endif + +Shader::Shader(Hash hash, Device *device_, const uint32_t *data, size_t size, + const ResourceLayout *resource_layout) + : IntrusiveHashMapEnabled(hash) + , device(device_) +{ + VkShaderModuleCreateInfo info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO }; + info.codeSize = size; + info.pCode = data; + +#ifdef VULKAN_DEBUG + LOGI("Creating shader module.\n"); +#endif + auto &table = device->get_device_table(); + if (table.vkCreateShaderModule(device->get_device(), &info, nullptr, &module) != VK_SUCCESS) + LOGE("Failed to create shader module.\n"); + +#ifdef HAVE_GRANITE_VULKAN_POST_MORTEM + PostMortem::register_shader(data, size); +#endif + +#ifdef GRANITE_VULKAN_FOSSILIZE + device->register_shader_module(module, get_hash(), info); +#endif + + if (resource_layout) + layout = *resource_layout; +#ifdef GRANITE_VULKAN_SPIRV_CROSS + else if (!reflect_resource_layout(layout, data, size)) + LOGE("Failed to reflect resource layout.\n"); +#endif + + if (layout.bindless_set_mask != 0 && !device->get_device_features().vk12_features.descriptorIndexing) + LOGE("Sufficient features for descriptor indexing is not supported on this device.\n"); +} + +Shader::~Shader() +{ + auto &table = device->get_device_table(); + if (module) + table.vkDestroyShaderModule(device->get_device(), module, nullptr); +} + +void Program::set_shader(ShaderStage stage, Shader *handle) +{ + shaders[Util::ecast(stage)] = handle; +} + +Program::Program(Device *device_, Shader *vertex, Shader *fragment, const ImmutableSamplerBank *sampler_bank) + : device(device_) +{ + set_shader(ShaderStage::Vertex, vertex); + set_shader(ShaderStage::Fragment, fragment); + device->bake_program(*this, sampler_bank); +} + +Program::Program(Device *device_, Shader *task, Shader *mesh, Shader *fragment, const ImmutableSamplerBank *sampler_bank) + : device(device_) +{ + if (task) + set_shader(ShaderStage::Task, task); + set_shader(ShaderStage::Mesh, mesh); + set_shader(ShaderStage::Fragment, fragment); + device->bake_program(*this, sampler_bank); +} + +Program::Program(Device *device_, Shader *compute_shader, const ImmutableSamplerBank *sampler_bank) + : device(device_) +{ + set_shader(ShaderStage::Compute, compute_shader); + device->bake_program(*this, sampler_bank); +} + +Pipeline Program::get_pipeline(Hash hash) const +{ + auto *ret = pipelines.find(hash); + return ret ? ret->get() : Pipeline{}; +} + +Pipeline Program::add_pipeline(Hash hash, const Pipeline &pipeline) +{ + return pipelines.emplace_yield(hash, pipeline)->get(); +} + +void Program::destroy_pipeline(const Pipeline &pipeline) +{ + device->get_device_table().vkDestroyPipeline(device->get_device(), pipeline.pipeline, nullptr); +} + +void Program::promote_read_write_to_read_only() +{ + pipelines.move_to_read_only(); +} + +Program::~Program() +{ + for (auto &pipe : pipelines.get_read_only()) + destroy_pipeline(pipe.get()); + for (auto &pipe : pipelines.get_read_write()) + destroy_pipeline(pipe.get()); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/shader.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/shader.hpp new file mode 100644 index 00000000..333d9f38 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/shader.hpp @@ -0,0 +1,357 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "cookie.hpp" +#include "descriptor_set.hpp" +#include "hash.hpp" +#include "intrusive.hpp" +#include "limits.hpp" +#include "vulkan_headers.hpp" +#include "enum_cast.hpp" + +namespace spirv_cross +{ +struct SPIRType; +} + +namespace Vulkan +{ +class Device; + +enum class ShaderStage +{ + Vertex = 0, + Fragment = 4, // Skip over tess/geom to match Vulkan ordering. + Compute, + Task, + Mesh, + Count +}; + +struct ResourceLayout +{ + DescriptorSetLayout sets[VULKAN_NUM_DESCRIPTOR_SETS]; + uint32_t input_mask = 0; + uint32_t output_mask = 0; + uint32_t push_constant_size = 0; + uint32_t spec_constant_mask = 0; + uint32_t bindless_set_mask = 0; + enum { Version = 7 }; + + bool unserialize(const uint8_t *data, size_t size); + bool serialize(uint8_t *data, size_t size) const; + static size_t serialization_size(); +}; +static_assert(sizeof(DescriptorSetLayout) % 8 == 0, "Size of DescriptorSetLayout does not align to 64 bits."); + +struct CombinedResourceLayout +{ + uint32_t attribute_mask = 0; + uint32_t render_target_mask = 0; + DescriptorSetLayout sets[VULKAN_NUM_DESCRIPTOR_SETS] = {}; + uint32_t stages_for_bindings[VULKAN_NUM_DESCRIPTOR_SETS][VULKAN_NUM_BINDINGS] = {}; + uint32_t stages_for_sets[VULKAN_NUM_DESCRIPTOR_SETS] = {}; + VkPushConstantRange push_constant_range = {}; + uint32_t descriptor_set_mask = 0; + uint32_t bindless_descriptor_set_mask = 0; + uint32_t spec_constant_mask[Util::ecast(ShaderStage::Count)] = {}; + uint32_t combined_spec_constant_mask = 0; + Util::Hash push_constant_layout_hash = 0; +}; + +union CombinedImageSamplerIndex +{ + struct + { + uint32_t image_heap_index : 20; + uint32_t sampler_heap_index : 12; + }; + uint32_t word; +}; +static_assert(sizeof(CombinedImageSamplerIndex) == sizeof(uint32_t), "Unexpected size of CombinedImageSamplerIndex."); + +union ResourceBinding +{ + VkDescriptorBufferInfo buffer; + + struct + { + VkDescriptorImageInfo fp; + VkDescriptorImageInfo integer; + const uint8_t *fp_ptr; + const uint8_t *integer_ptr; + const uint8_t *sampler_ptr; + CombinedImageSamplerIndex fp_heap_index; + CombinedImageSamplerIndex integer_heap_index; + } image; + + VkDescriptorAddressInfoEXT buffer_addr_buffer; + VkDeviceAddressRangeEXT buffer_addr_heap; + VkAccelerationStructureKHR rtas; + + union + { + VkBufferView handle; + struct + { + const uint8_t *ptr; + uint32_t heap_index; + } buffer; + } buffer_view; +}; + +struct ResourceBindings +{ + ResourceBinding bindings[VULKAN_NUM_DESCRIPTOR_SETS][VULKAN_NUM_BINDINGS]; + uint64_t cookies[VULKAN_NUM_DESCRIPTOR_SETS][VULKAN_NUM_BINDINGS]; + uint64_t secondary_cookies[VULKAN_NUM_DESCRIPTOR_SETS][VULKAN_NUM_BINDINGS]; + uint8_t push_constant_data[VULKAN_PUSH_CONSTANT_SIZE]; + + union + { + uint32_t push_data_words[(VULKAN_PUSH_DATA_SIZE - VULKAN_PUSH_CONSTANT_SIZE) / (VULKAN_NUM_DESCRIPTOR_SETS * sizeof(uint32_t))]; + VkDeviceAddress push_data_addr[(VULKAN_PUSH_DATA_SIZE - VULKAN_PUSH_CONSTANT_SIZE) / (VULKAN_NUM_DESCRIPTOR_SETS * sizeof(VkDeviceAddress))]; + } inline_descriptors[VULKAN_NUM_DESCRIPTOR_SETS]; +}; + +struct ImmutableSamplerBank +{ + const ImmutableSampler *samplers[VULKAN_NUM_DESCRIPTOR_SETS][VULKAN_NUM_BINDINGS]; + static void hash(Util::Hasher &h, const ImmutableSamplerBank *bank); +}; + +class PipelineLayout : public HashedObject +{ +public: + PipelineLayout(Util::Hash hash, Device *device, const CombinedResourceLayout &layout, + const ImmutableSamplerBank *sampler_bank); + ~PipelineLayout(); + + const CombinedResourceLayout &get_resource_layout() const + { + return layout; + } + + // Legacy + VkPipelineLayout get_layout() const + { + return pipe_layout; + } + + DescriptorSetAllocator *get_allocator(unsigned set) const + { + return set_allocators[set]; + } + + VkDescriptorUpdateTemplate get_update_template(unsigned set) const + { + return update_template[set]; + } + + uint32_t get_push_set_index() const + { + return push_set_index; + } + + // Heap + enum class DescriptorStrategy + { + // For images: a u32 index. For buffers: PUSH_ADDRESS. + Inline, + // Not compatible with array of samplers or combined image samplers. + // Not compatible with SSBO that need ArrayLength. + HeapSlice, + // Indirect version of inline, for larger sets. + IndirectTable, + }; + + // Allocation size from indirection table UBO. + uint32_t get_heap_table_size(uint32_t desc_set) const + { + return heap.heap_table_size[desc_set]; + } + + // Allocation size from descriptor heap. + // Used when we want to copy descriptors straight into the heap. + uint32_t get_heap_slice_size(uint32_t desc_set) const + { + return heap.heap_slice_size[desc_set]; + } + + uint32_t get_descriptor_set_push_buffer_offset(uint32_t desc_set) const + { + VK_ASSERT(desc_set < VULKAN_NUM_DESCRIPTOR_SETS); + return heap.push_buffer_offsets[desc_set]; + } + + uint32_t get_descriptor_set_push_image_offset(uint32_t desc_set) const + { + VK_ASSERT(desc_set < VULKAN_NUM_DESCRIPTOR_SETS); + return heap.push_image_offsets[desc_set]; + } + + uint32_t get_descriptor_set_inline_offsets(uint32_t desc_set) const + { + VK_ASSERT(desc_set < VULKAN_NUM_DESCRIPTOR_SETS); + return heap.push_inline_offsets[desc_set]; + } + + uint32_t get_descriptor_set_inline_size(uint32_t desc_set) const + { + VK_ASSERT(desc_set < VULKAN_NUM_DESCRIPTOR_SETS); + return heap.push_inline_size[desc_set]; + } + + DescriptorStrategy get_heap_buffer_descriptor_strategy(uint32_t desc_set) const + { + VK_ASSERT(desc_set < VULKAN_NUM_DESCRIPTOR_SETS); + return heap.buffer_strategies[desc_set]; + } + + DescriptorStrategy get_heap_image_descriptor_strategy(uint32_t desc_set) const + { + VK_ASSERT(desc_set < VULKAN_NUM_DESCRIPTOR_SETS); + return heap.image_strategies[desc_set]; + } + + // Inline: local offset into inline push data + // HeapSlice: offset into allocated heap slice + // IndirectTable: offset into indirect table + uint32_t get_descriptor_offset(uint32_t desc_set, uint32_t binding) const + { + VK_ASSERT(desc_set < VULKAN_NUM_DESCRIPTOR_SETS); + VK_ASSERT(binding < VULKAN_NUM_BINDINGS); + return heap.desc_offsets[desc_set][binding]; + } + + // Passed directly to CreatePipeline. + const std::vector &get_heap_mappings() const + { + return heap.mappings; + } + +private: + Device *device; + VkPipelineLayout pipe_layout = VK_NULL_HANDLE; + CombinedResourceLayout layout; + DescriptorSetAllocator *set_allocators[VULKAN_NUM_DESCRIPTOR_SETS] = {}; + VkDescriptorUpdateTemplate update_template[VULKAN_NUM_DESCRIPTOR_SETS] = {}; + uint32_t push_set_index = UINT32_MAX; + void create_update_templates(); + + void init_heap(); + void init_heap(uint32_t set_index); + void init_heap_buffers(uint32_t set_index); + void init_heap_image(uint32_t set_index); + void init_heap_offsets(uint32_t set_index); + void init_legacy(const ImmutableSamplerBank *immutable_samplers); + + struct + { + std::vector mappings; + // Inline descriptors are packed together. + uint32_t push_inline_offsets[VULKAN_NUM_DESCRIPTOR_SETS]; + uint32_t push_inline_size[VULKAN_NUM_DESCRIPTOR_SETS]; + // For tables and slices. + uint32_t push_buffer_offsets[VULKAN_NUM_DESCRIPTOR_SETS]; + uint32_t push_image_offsets[VULKAN_NUM_DESCRIPTOR_SETS]; + uint32_t heap_table_size[VULKAN_NUM_DESCRIPTOR_SETS]; + uint32_t heap_slice_size[VULKAN_NUM_DESCRIPTOR_SETS]; + DescriptorStrategy buffer_strategies[VULKAN_NUM_DESCRIPTOR_SETS]; + DescriptorStrategy image_strategies[VULKAN_NUM_DESCRIPTOR_SETS]; + uint32_t desc_offsets[VULKAN_NUM_DESCRIPTOR_SETS][VULKAN_NUM_BINDINGS]; + uint32_t push_data_size; + } heap = {}; +}; + +class Shader : public HashedObject +{ +public: + Shader(Util::Hash binding, Device *device, const uint32_t *data, size_t size, + const ResourceLayout *layout = nullptr); + ~Shader(); + + const ResourceLayout &get_layout() const + { + return layout; + } + + VkShaderModule get_module() const + { + return module; + } + + static bool reflect_resource_layout(ResourceLayout &layout, const uint32_t *spirv_data, size_t spirv_size); + static const char *stage_to_name(ShaderStage stage); + static Util::Hash hash(const uint32_t *data, size_t size); + +private: + Device *device; + VkShaderModule module = VK_NULL_HANDLE; + ResourceLayout layout; +}; + +struct Pipeline +{ + VkPipeline pipeline; + uint32_t dynamic_mask; +}; + +class Program : public HashedObject +{ +public: + Program(Device *device, Shader *vertex, Shader *fragment, const ImmutableSamplerBank *sampler_bank); + Program(Device *device, Shader *task, Shader *mesh, Shader *fragment, const ImmutableSamplerBank *sampler_bank); + Program(Device *device, Shader *compute, const ImmutableSamplerBank *sampler_bank); + ~Program(); + + inline const Shader *get_shader(ShaderStage stage) const + { + return shaders[Util::ecast(stage)]; + } + + void set_pipeline_layout(const PipelineLayout *new_layout) + { + layout = new_layout; + } + + const PipelineLayout *get_pipeline_layout() const + { + return layout; + } + + Pipeline get_pipeline(Util::Hash hash) const; + Pipeline add_pipeline(Util::Hash hash, const Pipeline &pipeline); + + void promote_read_write_to_read_only(); + +private: + void set_shader(ShaderStage stage, Shader *handle); + Device *device; + Shader *shaders[Util::ecast(ShaderStage::Count)] = {}; + const PipelineLayout *layout = nullptr; + VulkanCache> pipelines; + void destroy_pipeline(const Pipeline &pipeline); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/memory_mapped_texture.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/memory_mapped_texture.cpp new file mode 100644 index 00000000..be4fff74 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/memory_mapped_texture.cpp @@ -0,0 +1,346 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "memory_mapped_texture.hpp" +#include +#include + +namespace Vulkan +{ +struct MemoryMappedHeader +{ + char magic[16]; + VkImageType type; + VkFormat format; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t layers; + uint32_t levels; + uint32_t flags; + uint64_t payload_size; + uint64_t reserved1; +}; +static const size_t header_size = 16 + 8 * 4 + 2 * 8; +static_assert(sizeof(MemoryMappedHeader) == header_size, "Header size is not properly packed."); + +static const char MAGIC[16] = "GRANITE TEXFMT1"; + +void MemoryMappedTexture::set_generate_mipmaps_on_load(bool enable) +{ + mipgen_on_load = enable; +} + +void MemoryMappedTexture::set_flags(MemoryMappedTextureFlags flags) +{ + bool new_cube = (flags & MEMORY_MAPPED_TEXTURE_CUBE_MAP_COMPATIBLE_BIT) != 0; + if (new_cube != cube) + abort(); + set_generate_mipmaps_on_load((flags & MEMORY_MAPPED_TEXTURE_GENERATE_MIPMAP_ON_LOAD_BIT) != 0); +} + +MemoryMappedTextureFlags MemoryMappedTexture::get_flags() const +{ + MemoryMappedTextureFlags flags = 0; + if (cube) + flags |= MEMORY_MAPPED_TEXTURE_CUBE_MAP_COMPATIBLE_BIT; + if (mipgen_on_load) + flags |= MEMORY_MAPPED_TEXTURE_GENERATE_MIPMAP_ON_LOAD_BIT; + + flags |= swizzle.r << MEMORY_MAPPED_TEXTURE_SWIZZLE_R_SHIFT; + flags |= swizzle.g << MEMORY_MAPPED_TEXTURE_SWIZZLE_G_SHIFT; + flags |= swizzle.b << MEMORY_MAPPED_TEXTURE_SWIZZLE_B_SHIFT; + flags |= swizzle.a << MEMORY_MAPPED_TEXTURE_SWIZZLE_A_SHIFT; + return flags; +} + +void MemoryMappedTexture::set_1d(VkFormat format, uint32_t width, uint32_t layers, uint32_t levels) +{ + layout.set_1d(format, width, layers, levels); + cube = false; +} + +void MemoryMappedTexture::set_2d(VkFormat format, uint32_t width, uint32_t height, uint32_t layers, uint32_t levels) +{ + layout.set_2d(format, width, height, layers, levels); + cube = false; +} + +void MemoryMappedTexture::set_3d(VkFormat format, uint32_t width, uint32_t height, uint32_t depth, uint32_t levels) +{ + layout.set_3d(format, width, height, depth, levels); + cube = false; +} + +void MemoryMappedTexture::set_cube(VkFormat format, uint32_t size, uint32_t cube_layers, uint32_t levels) +{ + layout.set_2d(format, size, size, cube_layers * 6, levels); + cube = true; +} + +bool MemoryMappedTexture::copy_to_path(Granite::Filesystem &fs, const std::string &path) +{ + if (layout.get_required_size() == 0 || !mapped) + return false; + + auto target_file = fs.open(path, Granite::FileMode::WriteOnly); + if (!target_file) + return false; + + auto new_mapped = target_file->map_write(get_required_size()); + if (!new_mapped) + return false; + + memcpy(new_mapped->mutable_data(), mapped, get_required_size()); + return true; +} + +bool MemoryMappedTexture::map_write(Granite::FileMappingHandle new_file) +{ + file = std::move(new_file); + mapped = file->mutable_data(); + + MemoryMappedHeader header = {}; + memcpy(header.magic, MAGIC, sizeof(MAGIC)); + header.width = layout.get_width(); + header.height = layout.get_height(); + header.depth = layout.get_depth(); + header.flags = get_flags(); + header.layers = layout.get_layers(); + header.levels = layout.get_levels(); + header.payload_size = layout.get_required_size(); + header.type = layout.get_image_type(); + header.format = layout.get_format(); + memcpy(mapped, &header, sizeof(header)); + + layout.set_buffer(mapped + sizeof(header), layout.get_required_size()); + return true; +} + +bool MemoryMappedTexture::map_write(Granite::Filesystem &fs, const std::string &path) +{ + if (layout.get_required_size() == 0) + return false; + + auto new_file = fs.open(path, Granite::FileMode::WriteOnly); + if (!new_file) + return false; + + auto map_handle = new_file->map_write(get_required_size()); + if (!map_handle) + return false; + + return map_write(std::move(map_handle)); +} + +struct ScratchFile final : Granite::File +{ + ScratchFile(const void *mapped, size_t size) + { + data.resize(size); + if (mapped) + memcpy(data.data(), mapped, size); + } + + Granite::FileMappingHandle map_subset(uint64_t offset, size_t range) override + { + if (offset + range > data.size()) + return {}; + + return Util::make_handle( + reference_from_this(), offset, + data.data() + offset, range, + 0, range); + } + + Granite::FileMappingHandle map_write(size_t size) override + { + data.resize(size); + return map_subset(0, size); + } + + void unmap(void *, size_t) override + { + } + + uint64_t get_size() override + { + return data.size(); + } + + std::vector data; +}; + +void MemoryMappedTexture::make_local_copy() +{ + if (empty()) + return; + + auto new_file = Util::make_handle(mapped, get_required_size()); + file = new_file->map(); + mapped = file->mutable_data(); + layout.set_buffer(mapped + sizeof(MemoryMappedHeader), + get_required_size() - sizeof(MemoryMappedHeader)); +} + +bool MemoryMappedTexture::map_write_scratch() +{ + if (layout.get_required_size() == 0) + return false; + + auto new_file = Util::make_handle(nullptr, get_required_size()); + if (new_file->get_size() < sizeof(MemoryMappedHeader)) + return false; + + auto new_mapped = new_file->map_write(get_required_size()); + return map_write(std::move(new_mapped)); +} + +size_t MemoryMappedTexture::get_required_size() const +{ + return layout.get_required_size() + sizeof(MemoryMappedHeader); +} + +void MemoryMappedTexture::set_swizzle(const VkComponentMapping &swizzle_) +{ + swizzle = swizzle_; +} + +static void remap(VkComponentSwizzle &output, VkComponentSwizzle input, + const VkComponentMapping &mapping, VkComponentSwizzle identity) +{ + if (input == VK_COMPONENT_SWIZZLE_IDENTITY) + input = identity; + + switch (input) + { + case VK_COMPONENT_SWIZZLE_R: + output = mapping.r; + break; + + case VK_COMPONENT_SWIZZLE_G: + output = mapping.g; + break; + + case VK_COMPONENT_SWIZZLE_B: + output = mapping.b; + break; + + case VK_COMPONENT_SWIZZLE_A: + output = mapping.a; + break; + + case VK_COMPONENT_SWIZZLE_ONE: + case VK_COMPONENT_SWIZZLE_ZERO: + output = input; + break; + + default: + output = VK_COMPONENT_SWIZZLE_IDENTITY; + break; + } +} + +void MemoryMappedTexture::remap_swizzle(VkComponentMapping &mapping) const +{ + VkComponentMapping new_mapping; + + remap(new_mapping.r, swizzle.r, mapping, VK_COMPONENT_SWIZZLE_R); + remap(new_mapping.g, swizzle.g, mapping, VK_COMPONENT_SWIZZLE_G); + remap(new_mapping.b, swizzle.b, mapping, VK_COMPONENT_SWIZZLE_B); + remap(new_mapping.a, swizzle.a, mapping, VK_COMPONENT_SWIZZLE_A); + mapping = new_mapping; +} + +bool MemoryMappedTexture::map_copy(const void *mapped_, size_t size) +{ + auto new_file = Util::make_handle(mapped_, size); + if (new_file->get_size() < sizeof(MemoryMappedHeader)) + return false; + + auto new_mapped = new_file->map(); + return map_read(std::move(new_mapped)); +} + +bool MemoryMappedTexture::map_read(Granite::FileMappingHandle new_file) +{ + file = std::move(new_file); + mapped = const_cast(file->data()); + + auto *header = reinterpret_cast(mapped); + switch (header->type) + { + case VK_IMAGE_TYPE_1D: + layout.set_1d(header->format, header->width, header->layers, header->levels); + break; + + case VK_IMAGE_TYPE_2D: + layout.set_2d(header->format, header->width, header->height, header->layers, header->levels); + break; + + case VK_IMAGE_TYPE_3D: + layout.set_3d(header->format, header->width, header->height, header->depth, header->levels); + break; + + default: + return false; + } + + cube = (header->flags & MEMORY_MAPPED_TEXTURE_CUBE_MAP_COMPATIBLE_BIT) != 0; + mipgen_on_load = (header->flags & MEMORY_MAPPED_TEXTURE_GENERATE_MIPMAP_ON_LOAD_BIT) != 0; + swizzle.r = static_cast((header->flags >> MEMORY_MAPPED_TEXTURE_SWIZZLE_R_SHIFT) & MEMORY_MAPPED_TEXTURE_SWIZZLE_MASK); + swizzle.g = static_cast((header->flags >> MEMORY_MAPPED_TEXTURE_SWIZZLE_G_SHIFT) & MEMORY_MAPPED_TEXTURE_SWIZZLE_MASK); + swizzle.b = static_cast((header->flags >> MEMORY_MAPPED_TEXTURE_SWIZZLE_B_SHIFT) & MEMORY_MAPPED_TEXTURE_SWIZZLE_MASK); + swizzle.a = static_cast((header->flags >> MEMORY_MAPPED_TEXTURE_SWIZZLE_A_SHIFT) & MEMORY_MAPPED_TEXTURE_SWIZZLE_MASK); + + if ((layout.get_required_size() + sizeof(MemoryMappedHeader)) < file->get_size()) + return false; + if (header->payload_size != layout.get_required_size()) + return false; + + layout.set_buffer(static_cast(mapped) + sizeof(MemoryMappedHeader), header->payload_size); + return true; +} + +bool MemoryMappedTexture::map_read(Granite::Filesystem &fs, const std::string &path) +{ + auto loaded_file = fs.open(path, Granite::FileMode::ReadOnly); + if (!loaded_file) + return false; + + if (loaded_file->get_size() < sizeof(MemoryMappedHeader)) + return false; + + auto new_mapped = loaded_file->map(); + if (!new_mapped) + return false; + + return map_read(std::move(new_mapped)); +} + +bool MemoryMappedTexture::is_header(const void *mapped_, size_t size) +{ + if (size < sizeof(MemoryMappedHeader)) + return false; + return memcmp(mapped_, MAGIC, sizeof(MAGIC)) == 0; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/memory_mapped_texture.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/memory_mapped_texture.hpp new file mode 100644 index 00000000..66fec0db --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/memory_mapped_texture.hpp @@ -0,0 +1,94 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "texture_format.hpp" +#include "filesystem.hpp" + +namespace Vulkan +{ +enum MemoryMappedTextureFlagBits +{ + MEMORY_MAPPED_TEXTURE_CUBE_MAP_COMPATIBLE_BIT = 1 << 0, + MEMORY_MAPPED_TEXTURE_GENERATE_MIPMAP_ON_LOAD_BIT = 1 << 1, + MEMORY_MAPPED_TEXTURE_SWIZZLE_R_SHIFT = 16, + MEMORY_MAPPED_TEXTURE_SWIZZLE_G_SHIFT = 19, + MEMORY_MAPPED_TEXTURE_SWIZZLE_B_SHIFT = 22, + MEMORY_MAPPED_TEXTURE_SWIZZLE_A_SHIFT = 25, + MEMORY_MAPPED_TEXTURE_SWIZZLE_MASK = 0x7 +}; +using MemoryMappedTextureFlags = uint32_t; + +class MemoryMappedTexture +{ +public: + void set_1d(VkFormat format, uint32_t width, uint32_t layers = 1, uint32_t levels = 1); + void set_2d(VkFormat format, uint32_t width, uint32_t height, uint32_t layers = 1, uint32_t levels = 1); + void set_3d(VkFormat format, uint32_t width, uint32_t height, uint32_t depth, uint32_t levels = 1); + void set_cube(VkFormat format, uint32_t size, uint32_t cube_layers = 1, uint32_t levels = 1); + + static bool is_header(const void *mapped, size_t size); + + bool map_write(Granite::Filesystem &fs, const std::string &path); + bool map_write(Granite::FileMappingHandle file); + bool map_read(Granite::Filesystem &fs, const std::string &path); + bool map_read(Granite::FileMappingHandle file); + bool map_copy(const void *mapped, size_t size); + bool map_write_scratch(); + bool copy_to_path(Granite::Filesystem &fs, const std::string &path); + void make_local_copy(); + + inline const Vulkan::TextureFormatLayout &get_layout() const + { + return layout; + } + + void set_generate_mipmaps_on_load(bool enable = true); + + MemoryMappedTextureFlags get_flags() const; + void set_flags(MemoryMappedTextureFlags flags); + + size_t get_required_size() const; + void set_swizzle(const VkComponentMapping &swizzle); + + void remap_swizzle(VkComponentMapping &mapping) const; + + inline bool empty() const + { + return get_layout().get_required_size() == 0; + } + +private: + Vulkan::TextureFormatLayout layout; + Granite::FileMappingHandle file; + uint8_t *mapped = nullptr; + bool cube = false; + bool mipgen_on_load = false; + VkComponentMapping swizzle = { + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A, + }; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_decoder.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_decoder.cpp new file mode 100644 index 00000000..94e64615 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_decoder.cpp @@ -0,0 +1,1425 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "texture_decoder.hpp" +#include "logging.hpp" + +namespace Granite +{ +static VkFormat compressed_format_to_decoded_format(VkFormat format, VkFormat preferred_decode_format) +{ + switch (format) + { + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + case VK_FORMAT_BC2_SRGB_BLOCK: + case VK_FORMAT_BC3_SRGB_BLOCK: + case VK_FORMAT_BC7_SRGB_BLOCK: + return VK_FORMAT_R8G8B8A8_SRGB; + + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + case VK_FORMAT_BC2_UNORM_BLOCK: + case VK_FORMAT_BC3_UNORM_BLOCK: + case VK_FORMAT_BC7_UNORM_BLOCK: + return VK_FORMAT_R8G8B8A8_UNORM; + + case VK_FORMAT_BC4_UNORM_BLOCK: + return VK_FORMAT_R8_UNORM; + case VK_FORMAT_BC5_UNORM_BLOCK: + return VK_FORMAT_R8G8_UNORM; + + case VK_FORMAT_BC4_SNORM_BLOCK: + case VK_FORMAT_BC5_SNORM_BLOCK: + case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: + case VK_FORMAT_EAC_R11_SNORM_BLOCK: + LOGE("SNORM formats are not supported.\n"); + return VK_FORMAT_UNDEFINED; + + case VK_FORMAT_BC6H_SFLOAT_BLOCK: + case VK_FORMAT_BC6H_UFLOAT_BLOCK: + return VK_FORMAT_R16G16B16A16_SFLOAT; + + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + return VK_FORMAT_R8G8B8A8_SRGB; + + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + return VK_FORMAT_R8G8B8A8_UNORM; + + case VK_FORMAT_EAC_R11_UNORM_BLOCK: + return VK_FORMAT_R16_SFLOAT; + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: + return VK_FORMAT_R16G16_SFLOAT; + + case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: + case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: + case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: + case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: + case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: + case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: + case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: + return preferred_decode_format == VK_FORMAT_R16G16B16A16_SFLOAT ? + preferred_decode_format : VK_FORMAT_R8G8B8A8_UNORM; + + case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: + return VK_FORMAT_R8G8B8A8_SRGB; + + case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT: + return VK_FORMAT_R16G16B16A16_SFLOAT; + + default: + return VK_FORMAT_UNDEFINED; + } +} + +static VkFormat compressed_format_to_payload_format(VkFormat format) +{ + auto block_size = Vulkan::TextureFormatLayout::format_block_size(format, VK_IMAGE_ASPECT_COLOR_BIT); + + if (block_size == 4) + return VK_FORMAT_R32_UINT; + else if (block_size == 8) + return VK_FORMAT_R32G32_UINT; + else if (block_size == 16) + return VK_FORMAT_R32G32B32A32_UINT; + else + return VK_FORMAT_UNDEFINED; +} + +static VkFormat to_storage_format(VkFormat format, VkFormat orig_format = VK_FORMAT_UNDEFINED) +{ + switch (format) + { + case VK_FORMAT_R8G8B8A8_SRGB: + case VK_FORMAT_R8G8B8A8_UNORM: + if (orig_format == VK_FORMAT_BC1_RGBA_UNORM_BLOCK || + orig_format == VK_FORMAT_BC1_RGBA_SRGB_BLOCK || + orig_format == VK_FORMAT_BC1_RGB_SRGB_BLOCK || + orig_format == VK_FORMAT_BC1_RGB_UNORM_BLOCK || + orig_format == VK_FORMAT_BC2_SRGB_BLOCK || + orig_format == VK_FORMAT_BC2_UNORM_BLOCK || + orig_format == VK_FORMAT_BC3_SRGB_BLOCK || + orig_format == VK_FORMAT_BC3_UNORM_BLOCK) + return VK_FORMAT_R8G8B8A8_UNORM; + else + return VK_FORMAT_R8G8B8A8_UINT; + + case VK_FORMAT_R8_UNORM: + if (orig_format == VK_FORMAT_BC4_UNORM_BLOCK) + return VK_FORMAT_R8_UNORM; + else + return VK_FORMAT_R8_UINT; + + case VK_FORMAT_R8G8_UNORM: + if (orig_format == VK_FORMAT_BC5_UNORM_BLOCK) + return VK_FORMAT_R8G8_UNORM; + else + return VK_FORMAT_R8G8_UINT; + + case VK_FORMAT_R16_SFLOAT: + case VK_FORMAT_R16G16_SFLOAT: + return format; + + case VK_FORMAT_R16G16B16A16_SFLOAT: + return VK_FORMAT_R16G16B16A16_UINT; + + default: + return VK_FORMAT_UNDEFINED; + } +} + +struct ASTCQuantizationMode +{ + uint8_t bits, trits, quints; +}; + +static void build_astc_unquant_weight_lut(uint8_t *lut, size_t range, const ASTCQuantizationMode &mode) +{ + for (size_t i = 0; i < range; i++) + { + auto &v = lut[i]; + + if (!mode.quints && !mode.trits) + { + switch (mode.bits) + { + case 1: + v = i * 63; + break; + + case 2: + v = i * 0x15; + break; + + case 3: + v = i * 9; + break; + + case 4: + v = (i << 2) | (i >> 2); + break; + + case 5: + v = (i << 1) | (i >> 4); + break; + + default: + v = 0; + break; + } + } + else if (mode.bits == 0) + { + if (mode.trits) + v = 32 * i; + else + v = 16 * i; + } + else + { + unsigned b = (i >> 1) & 1; + unsigned c = (i >> 2) & 1; + unsigned A, B, C, D; + + A = 0x7f * (i & 1); + D = i >> mode.bits; + B = 0; + + if (mode.trits) + { + static const unsigned Cs[3] = { 50, 23, 11 }; + C = Cs[mode.bits - 1]; + if (mode.bits == 2) + B = 0x45 * b; + else if (mode.bits == 3) + B = 0x21 * b + 0x42 * c; + } + else + { + static const unsigned Cs[2] = { 28, 13 }; + C = Cs[mode.bits - 1]; + if (mode.bits == 2) + B = 0x42 * b; + } + + unsigned unq = D * C + B; + unq ^= A; + unq = (A & 0x20) | (unq >> 2); + v = unq; + } + + // Expand [0, 63] to [0, 64]. + if (mode.bits != 0 && v > 32) + v++; + } +} + +static void build_astc_unquant_endpoint_lut(uint8_t *lut, size_t range, const ASTCQuantizationMode &mode) +{ + for (size_t i = 0; i < range; i++) + { + auto &v = lut[i]; + + if (!mode.quints && !mode.trits) + { + // Bit-replication. + switch (mode.bits) + { + case 1: + v = i * 0xff; + break; + + case 2: + v = i * 0x55; + break; + + case 3: + v = (i << 5) | (i << 2) | (i >> 1); + break; + + case 4: + v = i * 0x11; + break; + + case 5: + v = (i << 3) | (i >> 2); + break; + + case 6: + v = (i << 2) | (i >> 4); + break; + + case 7: + v = (i << 1) | (i >> 6); + break; + + default: + v = i; + break; + } + } + else + { + unsigned A, B, C, D; + unsigned b = (i >> 1) & 1; + unsigned c = (i >> 2) & 1; + unsigned d = (i >> 3) & 1; + unsigned e = (i >> 4) & 1; + unsigned f = (i >> 5) & 1; + + B = 0; + D = i >> mode.bits; + A = (i & 1) * 0x1ff; + + if (mode.trits) + { + static const unsigned Cs[6] = { 204, 93, 44, 22, 11, 5 }; + C = Cs[mode.bits - 1]; + + switch (mode.bits) + { + case 2: + B = b * 0x116; + break; + + case 3: + B = b * 0x85 + c * 0x10a; + break; + + case 4: + B = b * 0x41 + c * 0x82 + d * 0x104; + break; + + case 5: + B = b * 0x20 + c * 0x40 + d * 0x81 + e * 0x102; + break; + + case 6: + B = b * 0x10 + c * 0x20 + d * 0x40 + e * 0x80 + f * 0x101; + break; + } + } + else + { + static const unsigned Cs[5] = { 113, 54, 26, 13, 6 }; + C = Cs[mode.bits - 1]; + + switch (mode.bits) + { + case 2: + B = b * 0x10c; + break; + + case 3: + B = b * 0x82 + c * 0x105; + break; + + case 4: + B = b * 0x40 + c * 0x81 + d * 0x102; + break; + + case 5: + B = b * 0x20 + c * 0x40 + d * 0x80 + e * 0x101; + break; + } + } + + unsigned unq = D * C + B; + unq ^= A; + unq = (A & 0x80) | (unq >> 2); + v = uint8_t(unq); + } + } +} + +static unsigned astc_value_range(const ASTCQuantizationMode &mode) +{ + unsigned value_range = 1u << mode.bits; + if (mode.trits) + value_range *= 3; + if (mode.quints) + value_range *= 5; + + if (value_range == 1) + value_range = 0; + return value_range; +} + +// In order to decode color endpoints, we need to convert available bits and number of values +// into a format of (bits, trits, quints). A simple LUT texture is a reasonable approach for this. +// Decoders are expected to have some form of LUT to deal with this ... +static const ASTCQuantizationMode astc_quantization_modes[] = { + { 8, 0, 0 }, + { 6, 1, 0 }, + { 5, 0, 1 }, + { 7, 0, 0 }, + { 5, 1, 0 }, + { 4, 0, 1 }, + { 6, 0, 0 }, + { 4, 1, 0 }, + { 3, 0, 1 }, + { 5, 0, 0 }, + { 3, 1, 0 }, + { 2, 0, 1 }, + { 4, 0, 0 }, + { 2, 1, 0 }, + { 1, 0, 1 }, + { 3, 0, 0 }, + { 1, 1, 0 }, +}; + +constexpr size_t astc_num_quantization_modes = sizeof(astc_quantization_modes) / sizeof(astc_quantization_modes[0]); + +static const ASTCQuantizationMode astc_weight_modes[] = { + { 0, 0, 0 }, // Invalid + { 0, 0, 0 }, // Invalid + { 1, 0, 0 }, + { 0, 1, 0 }, + { 2, 0, 0 }, + { 0, 0, 1 }, + { 1, 1, 0 }, + { 3, 0, 0 }, + { 0, 0, 0 }, // Invalid + { 0, 0, 0 }, // Invalid + { 1, 0, 1 }, + { 2, 1, 0 }, + { 4, 0, 0 }, + { 2, 0, 1 }, + { 3, 1, 0 }, + { 5, 0, 0 }, +}; + +constexpr size_t astc_num_weight_modes = sizeof(astc_weight_modes) / sizeof(astc_weight_modes[0]); + +struct ASTCLutHolder +{ + ASTCLutHolder(); + + void init_color_endpoint(); + void init_weight_luts(); + void init_trits_quints(); + + struct + { + size_t unquant_offset = 0; + uint8_t unquant_lut[2048]; + uint16_t lut[9][128][4]; + size_t unquant_lut_offsets[astc_num_quantization_modes]; + } color_endpoint; + + struct + { + size_t unquant_offset = 0; + uint8_t unquant_lut[2048]; + uint8_t lut[astc_num_weight_modes][4]; + } weights; + + struct + { + uint16_t trits_quints[256 + 128]; + } integer; + + struct PartitionTable + { + PartitionTable() = default; + PartitionTable(unsigned width, unsigned height); + std::vector lut_buffer; + unsigned lut_width = 0; + unsigned lut_height = 0; + }; + + std::mutex table_lock; + std::unordered_map tables; + + PartitionTable &get_partition_table(unsigned width, unsigned height); +}; + +static uint32_t astc_hash52(uint32_t p) +{ + p ^= p >> 15; p -= p << 17; p += p << 7; p += p << 4; + p ^= p >> 5; p += p << 16; p ^= p >> 7; p ^= p >> 3; + p ^= p << 6; p ^= p >> 17; + return p; +} + +// Copy-paste from spec. +static int astc_select_partition(int seed, int x, int y, int z, int partitioncount, bool small_block) +{ + if (small_block) + { + x <<= 1; + y <<= 1; + z <<= 1; + } + + seed += (partitioncount - 1) * 1024; + uint32_t rnum = astc_hash52(seed); + uint8_t seed1 = rnum & 0xF; + uint8_t seed2 = (rnum >> 4) & 0xF; + uint8_t seed3 = (rnum >> 8) & 0xF; + uint8_t seed4 = (rnum >> 12) & 0xF; + uint8_t seed5 = (rnum >> 16) & 0xF; + uint8_t seed6 = (rnum >> 20) & 0xF; + uint8_t seed7 = (rnum >> 24) & 0xF; + uint8_t seed8 = (rnum >> 28) & 0xF; + uint8_t seed9 = (rnum >> 18) & 0xF; + uint8_t seed10 = (rnum >> 22) & 0xF; + uint8_t seed11 = (rnum >> 26) & 0xF; + uint8_t seed12 = ((rnum >> 30) | (rnum << 2)) & 0xF; + + seed1 *= seed1; seed2 *= seed2; seed3 *= seed3; seed4 *= seed4; + seed5 *= seed5; seed6 *= seed6; seed7 *= seed7; seed8 *= seed8; + seed9 *= seed9; seed10 *= seed10; seed11 *= seed11; seed12 *= seed12; + + int sh1, sh2, sh3; + if (seed & 1) + { + sh1 = seed & 2 ? 4 : 5; + sh2 = partitioncount == 3 ? 6 : 5; + } + else + { + sh1 = partitioncount == 3 ? 6 : 5; + sh2 = seed & 2 ? 4 : 5; + } + sh3 = (seed & 0x10) ? sh1 : sh2; + + seed1 >>= sh1; seed2 >>= sh2; seed3 >>= sh1; seed4 >>= sh2; + seed5 >>= sh1; seed6 >>= sh2; seed7 >>= sh1; seed8 >>= sh2; + seed9 >>= sh3; seed10 >>= sh3; seed11 >>= sh3; seed12 >>= sh3; + + int a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14); + int b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10); + int c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6); + int d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2); + + a &= 0x3f; b &= 0x3f; c &= 0x3f; d &= 0x3f; + + if (partitioncount < 4) + d = 0; + if (partitioncount < 3) + c = 0; + + if (a >= b && a >= c && a >= d) + return 0; + else if (b >= c && b >= d) + return 1; + else if (c >= d) + return 2; + else + return 3; +} + +ASTCLutHolder::PartitionTable::PartitionTable(unsigned block_width, unsigned block_height) +{ + bool small_block = (block_width * block_height) < 31; + + lut_width = block_width * 32; + lut_height = block_height * 32; + lut_buffer.resize(lut_width * lut_height); + + for (unsigned seed_y = 0; seed_y < 32; seed_y++) + { + for (unsigned seed_x = 0; seed_x < 32; seed_x++) + { + unsigned seed = seed_y * 32 + seed_x; + for (unsigned block_y = 0; block_y < block_height; block_y++) + { + for (unsigned block_x = 0; block_x < block_width; block_x++) + { + int part2 = astc_select_partition(seed, block_x, block_y, 0, 2, small_block); + int part3 = astc_select_partition(seed, block_x, block_y, 0, 3, small_block); + int part4 = astc_select_partition(seed, block_x, block_y, 0, 4, small_block); + lut_buffer[(seed_y * block_height + block_y) * lut_width + (seed_x * block_width + block_x)] = + (part2 << 0) | (part3 << 2) | (part4 << 4); + } + } + } + } +} + +ASTCLutHolder::PartitionTable &ASTCLutHolder::get_partition_table(unsigned width, unsigned height) +{ + std::lock_guard holder{table_lock}; + auto itr = tables.find(width * 16 + height); + if (itr != tables.end()) + { + return itr->second; + } + else + { + auto &t = tables[width * 16 + height]; + t = { width, height }; + return t; + } +} + +static ASTCLutHolder &get_astc_luts() +{ + static ASTCLutHolder holder; + return holder; +} + +ASTCLutHolder::ASTCLutHolder() +{ + init_color_endpoint(); + init_weight_luts(); + init_trits_quints(); +} + +void ASTCLutHolder::init_color_endpoint() +{ + auto &unquant_lut = color_endpoint.unquant_lut; + + for (size_t i = 0; i < astc_num_quantization_modes; i++) + { + auto value_range = astc_value_range(astc_quantization_modes[i]); + color_endpoint.unquant_lut_offsets[i] = color_endpoint.unquant_offset; + build_astc_unquant_endpoint_lut(unquant_lut + color_endpoint.unquant_offset, value_range, astc_quantization_modes[i]); + color_endpoint.unquant_offset += value_range; + } + + auto &lut = color_endpoint.lut; + + // We can have a maximum of 9 endpoint pairs, i.e. 18 endpoint values in total. + for (unsigned pairs_minus_1 = 0; pairs_minus_1 < 9; pairs_minus_1++) + { + for (unsigned remaining = 0; remaining < 128; remaining++) + { + bool found_mode = false; + for (auto &mode : astc_quantization_modes) + { + unsigned num_values = (pairs_minus_1 + 1) * 2; + unsigned total_bits = mode.bits * num_values + + (mode.quints * 7 * num_values + 2) / 3 + + (mode.trits * 8 * num_values + 4) / 5; + + if (total_bits <= remaining) + { + found_mode = true; + lut[pairs_minus_1][remaining][0] = mode.bits; + lut[pairs_minus_1][remaining][1] = mode.trits; + lut[pairs_minus_1][remaining][2] = mode.quints; + lut[pairs_minus_1][remaining][3] = color_endpoint.unquant_lut_offsets[&mode - astc_quantization_modes]; + break; + } + } + + if (!found_mode) + memset(lut[pairs_minus_1][remaining], 0, sizeof(lut[pairs_minus_1][remaining])); + } + } +} + +void ASTCLutHolder::init_weight_luts() +{ + auto &lut = weights.lut; + auto &unquant_lut = weights.unquant_lut; + auto &unquant_offset = weights.unquant_offset; + + for (size_t i = 0; i < astc_num_weight_modes; i++) + { + auto value_range = astc_value_range(astc_weight_modes[i]); + lut[i][0] = astc_weight_modes[i].bits; + lut[i][1] = astc_weight_modes[i].trits; + lut[i][2] = astc_weight_modes[i].quints; + lut[i][3] = unquant_offset; + build_astc_unquant_weight_lut(unquant_lut + unquant_offset, value_range, astc_weight_modes[i]); + unquant_offset += value_range; + } + + assert(unquant_offset <= 256); +} + +void ASTCLutHolder::init_trits_quints() +{ + // From specification. + auto &trits_quints = integer.trits_quints; + + for (unsigned T = 0; T < 256; T++) + { + unsigned C; + uint8_t t0, t1, t2, t3, t4; + + if (((T >> 2) & 7) == 7) + { + C = (((T >> 5) & 7) << 2) | (T & 3); + t4 = t3 = 2; + } + else + { + C = T & 0x1f; + if (((T >> 5) & 3) == 3) + { + t4 = 2; + t3 = (T >> 7) & 1; + } + else + { + t4 = (T >> 7) & 1; + t3 = (T >> 5) & 3; + } + } + + if ((C & 3) == 3) + { + t2 = 2; + t1 = (C >> 4) & 1; + t0 = (((C >> 3) & 1) << 1) | (((C >> 2) & 1) & ~(((C >> 3) & 1))); + } + else if (((C >> 2) & 3) == 3) + { + t2 = 2; + t1 = 2; + t0 = C & 3; + } + else + { + t2 = (C >> 4) & 1; + t1 = (C >> 2) & 3; + t0 = (((C >> 1) & 1) << 1) | ((C & 1) & ~(((C >> 1) & 1))); + } + + trits_quints[T] = t0 | (t1 << 3) | (t2 << 6) | (t3 << 9) | (t4 << 12); + } + + for (unsigned Q = 0; Q < 128; Q++) + { + unsigned C; + uint8_t q0, q1, q2; + if (((Q >> 1) & 3) == 3 && ((Q >> 5) & 3) == 0) + { + q2 = ((Q & 1) << 2) | ((((Q >> 4) & 1) & ~(Q & 1)) << 1) | (((Q >> 3) & 1) & ~(Q & 1)); + q1 = q0 = 4; + } + else + { + if (((Q >> 1) & 3) == 3) + { + q2 = 4; + C = (((Q >> 3) & 3) << 3) | ((~(Q >> 5) & 3) << 1) | (Q & 1); + } + else + { + q2 = (Q >> 5) & 3; + C = Q & 0x1f; + } + + if ((C & 7) == 5) + { + q1 = 4; + q0 = (C >> 3) & 3; + } + else + { + q1 = (C >> 3) & 3; + q0 = C & 7; + } + } + + trits_quints[256 + Q] = q0 | (q1 << 3) | (q2 << 6); + } +} + +static void setup_astc_lut_color_endpoint(Vulkan::CommandBuffer &cmd) +{ + auto &luts = get_astc_luts(); + + { + Vulkan::BufferCreateInfo info = {}; + info.size = sizeof(luts.color_endpoint.lut); + info.domain = Vulkan::BufferDomain::LinkedDeviceHost; + info.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + auto lut_buffer = cmd.get_device().create_buffer(info, luts.color_endpoint.lut); + + Vulkan::BufferViewCreateInfo view_info = {}; + view_info.buffer = lut_buffer.get(); + view_info.format = VK_FORMAT_R16G16B16A16_UINT; + view_info.range = sizeof(luts.color_endpoint.lut); + auto lut_view = cmd.get_device().create_buffer_view(view_info); + cmd.set_buffer_view(1, 0, *lut_view); + } + + { + Vulkan::BufferCreateInfo info = {}; + info.size = luts.color_endpoint.unquant_offset; + info.domain = Vulkan::BufferDomain::LinkedDeviceHost; + info.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + auto unquant_buffer = cmd.get_device().create_buffer(info, luts.color_endpoint.unquant_lut); + + Vulkan::BufferViewCreateInfo view_info = {}; + view_info.buffer = unquant_buffer.get(); + view_info.format = VK_FORMAT_R8_UINT; + view_info.range = luts.color_endpoint.unquant_offset; + + auto unquant_view = cmd.get_device().create_buffer_view(view_info); + cmd.set_buffer_view(1, 1, *unquant_view); + } +} + +static void setup_astc_lut_weights(Vulkan::CommandBuffer &cmd) +{ + auto &luts = get_astc_luts(); + + { + Vulkan::BufferCreateInfo info = {}; + info.size = sizeof(luts.weights.lut); + info.domain = Vulkan::BufferDomain::LinkedDeviceHost; + info.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + auto lut_buffer = cmd.get_device().create_buffer(info, luts.weights.lut); + + Vulkan::BufferViewCreateInfo view_info = {}; + view_info.buffer = lut_buffer.get(); + view_info.format = VK_FORMAT_R8G8B8A8_UINT; + view_info.range = sizeof(luts.weights.lut); + auto lut_view = cmd.get_device().create_buffer_view(view_info); + cmd.set_buffer_view(1, 2, *lut_view); + } + + { + Vulkan::BufferCreateInfo info = {}; + info.size = luts.weights.unquant_offset; + info.domain = Vulkan::BufferDomain::LinkedDeviceHost; + info.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + auto unquant_buffer = cmd.get_device().create_buffer(info, luts.weights.unquant_lut); + + Vulkan::BufferViewCreateInfo view_info = {}; + view_info.buffer = unquant_buffer.get(); + view_info.format = VK_FORMAT_R8_UINT; + view_info.range = luts.weights.unquant_offset; + + auto unquant_view = cmd.get_device().create_buffer_view(view_info); + cmd.set_buffer_view(1, 3, *unquant_view); + } +} + +static void setup_astc_lut_trits_quints(Vulkan::CommandBuffer &cmd) +{ + auto &luts = get_astc_luts(); + + Vulkan::BufferCreateInfo info = {}; + info.size = sizeof(luts.integer.trits_quints); + info.domain = Vulkan::BufferDomain::LinkedDeviceHost; + info.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + auto lut_buffer = cmd.get_device().create_buffer(info, luts.integer.trits_quints); + + Vulkan::BufferViewCreateInfo view_info = {}; + view_info.buffer = lut_buffer.get(); + view_info.format = VK_FORMAT_R16_UINT; + view_info.range = sizeof(luts.integer.trits_quints); + auto trits_quints_buffer = cmd.get_device().create_buffer_view(view_info); + cmd.set_buffer_view(1, 4, *trits_quints_buffer); +} + + +static void setup_astc_lut_partition_table(Vulkan::CommandBuffer &cmd, VkFormat format) +{ + uint32_t block_width, block_height; + Vulkan::TextureFormatLayout::format_block_dim(format, block_width, block_height); + + auto &luts = get_astc_luts(); + auto &table = luts.get_partition_table(block_width, block_height); + + auto info = Vulkan::ImageCreateInfo::immutable_2d_image(table.lut_width, table.lut_height, VK_FORMAT_R8_UINT); + info.misc = Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT; + Vulkan::ImageInitialData data = {}; + data.data = table.lut_buffer.data(); + auto lut_image = cmd.get_device().create_image(info, &data); + cmd.set_texture(1, 5, lut_image->get_view()); +} + +static void setup_astc_luts(Vulkan::CommandBuffer &cmd, VkFormat format) +{ + setup_astc_lut_color_endpoint(cmd); + setup_astc_lut_weights(cmd); + setup_astc_lut_trits_quints(cmd); + setup_astc_lut_partition_table(cmd, format); +} + +static bool set_compute_decoder(Vulkan::CommandBuffer &cmd, VkFormat format) +{ + switch (format) + { + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + case VK_FORMAT_BC2_SRGB_BLOCK: + case VK_FORMAT_BC2_UNORM_BLOCK: + case VK_FORMAT_BC3_SRGB_BLOCK: + case VK_FORMAT_BC3_UNORM_BLOCK: + cmd.set_program("builtin://shaders/decode/s3tc.comp"); + break; + + case VK_FORMAT_BC4_UNORM_BLOCK: + case VK_FORMAT_BC5_UNORM_BLOCK: + cmd.set_program("builtin://shaders/decode/rgtc.comp"); + break; + + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + cmd.set_program("builtin://shaders/decode/etc2.comp"); + break; + + case VK_FORMAT_EAC_R11_UNORM_BLOCK: + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: + cmd.set_program("builtin://shaders/decode/eac.comp"); + break; + + case VK_FORMAT_BC6H_SFLOAT_BLOCK: + case VK_FORMAT_BC6H_UFLOAT_BLOCK: + cmd.set_program("builtin://shaders/decode/bc6.comp"); + break; + + case VK_FORMAT_BC7_SRGB_BLOCK: + case VK_FORMAT_BC7_UNORM_BLOCK: + cmd.set_program("builtin://shaders/decode/bc7.comp"); + break; + + case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: + case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: + case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: + case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: + case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: + case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: + case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: + case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: + case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT: + setup_astc_luts(cmd, format); + cmd.set_program("builtin://shaders/decode/astc.comp"); + break; + + default: + return false; + } + + return true; +} + +static void dispatch_kernel_eac(Vulkan::CommandBuffer &cmd, uint32_t width, uint32_t height, VkFormat format) +{ + struct Push + { + uint32_t width, height; + } push; + + push.width = width; + push.height = height; + cmd.push_constants(&push, 0, sizeof(push)); + + cmd.set_specialization_constant_mask(1); + cmd.set_specialization_constant(0, uint32_t(format == VK_FORMAT_EAC_R11G11_UNORM_BLOCK ? 2 : 1)); + + width = (width + 7) / 8; + height = (height + 7) / 8; + + cmd.dispatch(width, height, 1); +} + +static void dispatch_kernel_bc6(Vulkan::CommandBuffer &cmd, uint32_t width, uint32_t height, VkFormat format) +{ + struct Push + { + uint32_t width, height; + } push; + + push.width = width; + push.height = height; + cmd.push_constants(&push, 0, sizeof(push)); + + cmd.set_specialization_constant_mask(1); + cmd.set_specialization_constant(0, uint32_t(format == VK_FORMAT_BC6H_SFLOAT_BLOCK)); + + width = (width + 7) / 8; + height = (height + 7) / 8; + cmd.dispatch(width, height, 1); +} + +static void dispatch_kernel_astc(Vulkan::CommandBuffer &cmd, uint32_t width, uint32_t height, VkFormat format, bool HDR) +{ + struct Push + { + uint32_t error_color[4]; + uint32_t width, height; + } push; + + push.width = width; + push.height = height; + + if (HDR) + { + push.error_color[0] = 0xffff; + push.error_color[1] = 0xffff; + push.error_color[2] = 0xffff; + push.error_color[3] = 0xffff; + } + else + { + push.error_color[0] = 0xff; + push.error_color[1] = 0; + push.error_color[2] = 0xff; + push.error_color[3] = 0xff; + } + + cmd.push_constants(&push, 0, sizeof(push)); + + uint32_t block_width, block_height; + Vulkan::TextureFormatLayout::format_block_dim(format, block_width, block_height); + + cmd.set_specialization_constant_mask(7); + cmd.set_specialization_constant(0, block_width); + cmd.set_specialization_constant(1, block_height); + cmd.set_specialization_constant(2, uint32_t(!HDR)); + + cmd.dispatch((width + 2 * block_width - 1) / (2 * block_width), + (height + 2 * block_height - 1) / (2 * block_height), + 1); +} + +static void dispatch_kernel_bc7(Vulkan::CommandBuffer &cmd, uint32_t width, uint32_t height, VkFormat) +{ + struct Push + { + uint32_t width, height; + } push; + + push.width = width; + push.height = height; + cmd.push_constants(&push, 0, sizeof(push)); + + width = (width + 7) / 8; + height = (height + 7) / 8; + cmd.dispatch(width, height, 1); +} + +static void dispatch_kernel_etc2(Vulkan::CommandBuffer &cmd, uint32_t width, uint32_t height, VkFormat format) +{ + struct Push + { + uint32_t width, height; + } push; + + push.width = width; + push.height = height; + cmd.push_constants(&push, 0, sizeof(push)); + + cmd.set_specialization_constant_mask(1); + switch (format) + { + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + cmd.set_specialization_constant(0, uint32_t(0)); + break; + + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + cmd.set_specialization_constant(0, uint32_t(1)); + break; + + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + cmd.set_specialization_constant(0, uint32_t(8)); + break; + + default: + break; + } + + width = (width + 7) / 8; + height = (height + 7) / 8; + cmd.dispatch(width, height, 1); +} + +static void dispatch_kernel_rgtc(Vulkan::CommandBuffer &cmd, uint32_t width, uint32_t height, VkFormat format) +{ + struct Push + { + uint32_t width, height; + } push; + + push.width = width; + push.height = height; + cmd.push_constants(&push, 0, sizeof(push)); + + cmd.set_specialization_constant_mask(1); + cmd.set_specialization_constant(0, uint32_t(format == VK_FORMAT_BC5_UNORM_BLOCK)); + + width = (width + 7) / 8; + height = (height + 7) / 8; + cmd.dispatch(width, height, 1); +} + +static void dispatch_kernel_s3tc(Vulkan::CommandBuffer &cmd, uint32_t width, uint32_t height, VkFormat format) +{ + struct Push + { + uint32_t width, height; + } push; + + push.width = width; + push.height = height; + cmd.push_constants(&push, 0, sizeof(push)); + + cmd.set_specialization_constant_mask(3); + + switch (format) + { + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + cmd.set_specialization_constant(0, uint32_t(0)); + break; + + default: + cmd.set_specialization_constant(0, uint32_t(1)); + break; + } + + switch (format) + { + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + cmd.set_specialization_constant(1, uint32_t(1)); + break; + + case VK_FORMAT_BC2_UNORM_BLOCK: + case VK_FORMAT_BC2_SRGB_BLOCK: + cmd.set_specialization_constant(1, uint32_t(2)); + break; + + case VK_FORMAT_BC3_UNORM_BLOCK: + case VK_FORMAT_BC3_SRGB_BLOCK: + cmd.set_specialization_constant(1, uint32_t(3)); + break; + + default: + break; + } + + width = (width + 7) / 8; + height = (height + 7) / 8; + cmd.dispatch(width, height, 1); +} + +static void dispatch_kernel(Vulkan::CommandBuffer &cmd, uint32_t width, uint32_t height, VkFormat format, + VkFormat preferred_decode_format) +{ + switch (format) + { + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + case VK_FORMAT_BC2_SRGB_BLOCK: + case VK_FORMAT_BC2_UNORM_BLOCK: + case VK_FORMAT_BC3_SRGB_BLOCK: + case VK_FORMAT_BC3_UNORM_BLOCK: + dispatch_kernel_s3tc(cmd, width, height, format); + break; + + case VK_FORMAT_BC4_UNORM_BLOCK: + case VK_FORMAT_BC5_UNORM_BLOCK: + dispatch_kernel_rgtc(cmd, width, height, format); + break; + + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + dispatch_kernel_etc2(cmd, width, height, format); + break; + + case VK_FORMAT_EAC_R11_UNORM_BLOCK: + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: + dispatch_kernel_eac(cmd, width, height, format); + break; + + case VK_FORMAT_BC6H_SFLOAT_BLOCK: + case VK_FORMAT_BC6H_UFLOAT_BLOCK: + dispatch_kernel_bc6(cmd, width, height, format); + break; + + case VK_FORMAT_BC7_SRGB_BLOCK: + case VK_FORMAT_BC7_UNORM_BLOCK: + dispatch_kernel_bc7(cmd, width, height, format); + break; + + case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: + case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: + case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: + case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: + case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: + case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: + case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: + case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: + dispatch_kernel_astc(cmd, width, height, format, + preferred_decode_format == VK_FORMAT_R16G16B16A16_SFLOAT); + break; + + case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: + case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: + case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: + case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: + dispatch_kernel_astc(cmd, width, height, format, false); + break; + + case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT: + case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT: + dispatch_kernel_astc(cmd, width, height, format, true); + break; + + default: + break; + } +} + +Vulkan::ImageHandle decode_compressed_image(Vulkan::CommandBuffer &cmd, const Vulkan::TextureFormatLayout &layout, + VkFormat preferred_decode_format, + const VkComponentMapping &swizzle) +{ + auto &device = cmd.get_device(); + + if (!device.get_device_features().enabled_features.shaderStorageImageWriteWithoutFormat) + { + LOGE("Require shaderStorageImageWriteWithoutFormat.\n"); + return {}; + } + + uint32_t block_width, block_height; + Vulkan::TextureFormatLayout::format_block_dim(layout.get_format(), block_width, block_height); + if (block_width == 1 || block_height == 1) + { + LOGE("Not a compressed format.\n"); + return {}; + } + + auto image_info = Vulkan::ImageCreateInfo::immutable_image(layout); + image_info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + image_info.format = compressed_format_to_decoded_format(layout.get_format(), preferred_decode_format); + image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + image_info.flags = VK_IMAGE_CREATE_EXTENDED_USAGE_BIT | VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + image_info.swizzle = swizzle; + if (image_info.format == VK_FORMAT_UNDEFINED) + return {}; + auto decoded_image = device.create_image(image_info); + + auto staging = device.create_image_staging_buffer(layout); + for (auto &blit : staging.blits) + { + blit.bufferRowLength = (blit.bufferRowLength + block_width - 1) / block_width; + blit.bufferImageHeight = (blit.bufferImageHeight + block_height - 1) / block_height; + blit.imageExtent.width = (blit.imageExtent.width + block_width - 1) / block_width; + blit.imageExtent.height = (blit.imageExtent.height + block_height - 1) / block_height; + } + + // Need to upload each miplevel on its own since the mip-chain size will be cut off too short. + // Could use BLOCK_VIEW flag to work around this, but don't really need to rely on it. + Vulkan::InitialImageBuffer split_staging; + split_staging.buffer = staging.buffer; + split_staging.host = staging.host; + split_staging.blits.resize(1); + Util::SmallVector uploaded_images(layout.get_levels()); + + image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + image_info.format = compressed_format_to_payload_format(layout.get_format()); + if (image_info.format == VK_FORMAT_UNDEFINED) + return {}; + image_info.swizzle = { VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A }; + image_info.misc = Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_GRAPHICS_BIT | + Vulkan::IMAGE_MISC_CONCURRENT_QUEUE_ASYNC_COMPUTE_BIT; + image_info.initial_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + image_info.levels = 1; + + for (auto &blit : staging.blits) + { + // Should be monotonic, but not guaranteed. + unsigned level = blit.imageSubresource.mipLevel; + split_staging.blits[0] = blit; + split_staging.blits[0].imageSubresource.mipLevel = 0; + image_info.width = (layout.get_width(level) + block_width - 1) / block_width; + image_info.height = (layout.get_height(level) + block_height - 1) / block_height; + uploaded_images[level] = device.create_image_from_staging_buffer(image_info, &split_staging); + } + + Vulkan::ImageViewCreateInfo view_info; + view_info.image = decoded_image.get(); + view_info.view_type = VK_IMAGE_VIEW_TYPE_2D; + view_info.levels = 1; + view_info.layers = 1; + view_info.format = to_storage_format(compressed_format_to_decoded_format(layout.get_format(), preferred_decode_format), + layout.get_format()); + + Vulkan::ImageViewCreateInfo input_view_info; + input_view_info.view_type = VK_IMAGE_VIEW_TYPE_2D; + input_view_info.levels = 1; + input_view_info.layers = 1; + input_view_info.base_level = 0; + + cmd.image_barrier(*decoded_image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_NONE, 0, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + + if (!set_compute_decoder(cmd, layout.get_format())) + { + LOGE("Failed to set the compute decoder.\n"); + return {}; + } + + auto start_ts = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + for (unsigned level = 0; level < layout.get_levels(); level++) + { + uint32_t mip_width = layout.get_width(level); + uint32_t mip_height = layout.get_height(level); + + for (unsigned layer = 0; layer < layout.get_layers(); layer++) + { + input_view_info.image = uploaded_images[level].get(); + view_info.base_layer = input_view_info.base_layer = layer; + view_info.base_level = level; + auto storage_view = device.create_image_view(view_info); + auto payload_view = device.create_image_view(input_view_info); + + cmd.set_storage_texture(0, 0, *storage_view); + cmd.set_texture(0, 1, *payload_view); + dispatch_kernel(cmd, mip_width, mip_height, layout.get_format(), preferred_decode_format); + } + } + + cmd.image_barrier(*decoded_image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + + auto end_ts = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + cmd.get_device().register_time_interval("GPU", std::move(start_ts), std::move(end_ts), "texture-decode"); + cmd.set_specialization_constant_mask(0); + return decoded_image; +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_decoder.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_decoder.hpp new file mode 100644 index 00000000..21f710ca --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_decoder.hpp @@ -0,0 +1,39 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "texture_format.hpp" +#include "command_buffer.hpp" +#include "device.hpp" + +namespace Granite +{ +Vulkan::ImageHandle decode_compressed_image(Vulkan::CommandBuffer &cmd, const Vulkan::TextureFormatLayout &layout, + VkFormat preferred_decode_format, + const VkComponentMapping &swizzle = { + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A, + }); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_files.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_files.cpp new file mode 100644 index 00000000..8dd28738 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_files.cpp @@ -0,0 +1,124 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "texture_files.hpp" +#include "stb_image.h" +#include "filesystem.hpp" +#include "muglm/muglm_impl.hpp" +#include + +namespace Vulkan +{ +static MemoryMappedTexture load_stb(const void *data, size_t size, ColorSpace color) +{ + int width, height; + int components; + auto *buffer = stbi_load_from_memory(static_cast(data), size, &width, &height, &components, 4); + + if (!buffer) + return {}; + + MemoryMappedTexture tex; + tex.set_2d(color == ColorSpace::sRGB ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM, width, height); + tex.set_generate_mipmaps_on_load(true); + if (!tex.map_write_scratch()) + return {}; + + memcpy(tex.get_layout().data(), buffer, width * height * 4); + stbi_image_free(buffer); + return tex; +} + +static MemoryMappedTexture load_hdr(const void *data, size_t size) +{ + int width, height; + int components; + auto *buffer = stbi_loadf_from_memory(static_cast(data), size, &width, &height, &components, 3); + + MemoryMappedTexture tex; + tex.set_2d(VK_FORMAT_R16G16B16A16_SFLOAT, width, height); + if (!tex.map_write_scratch()) + return {}; + tex.set_generate_mipmaps_on_load(true); + + auto *converted = static_cast(tex.get_layout().data()); + for (int i = 0; i < width * height; i++) + { + converted[i] = muglm::floatToHalf(muglm::vec4(buffer[3 * i + 0], buffer[3 * i + 1], buffer[3 * i + 2], 1.0f)); + } + stbi_image_free(buffer); + return tex; +} + +MemoryMappedTexture load_texture_from_memory(const void *data, size_t size, ColorSpace color) +{ + static const uint8_t png_magic[] = { + 0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a, + }; + + static const uint8_t jpg_magic[] = { + 0xff, 0xd8, + }; + + static const uint8_t hdr_magic[] = { + 0x23, 0x3f, 0x52, 0x41, 0x44, 0x49, 0x41, 0x4e, 0x43, 0x45, 0x0a, + }; + + if (size >= sizeof(png_magic) && memcmp(data, png_magic, sizeof(png_magic)) == 0) + return load_stb(data, size, color); + else if (size >= 2 && memcmp(data, jpg_magic, sizeof(jpg_magic)) == 0) + return load_stb(data, size, color); + else if (size >= sizeof(hdr_magic) && memcmp(data, hdr_magic, sizeof(hdr_magic)) == 0) + return load_hdr(data, size); + else if (MemoryMappedTexture::is_header(data, size)) + { + MemoryMappedTexture mapped; + mapped.map_copy(data, size); + return mapped; + } + else + { + // YOLO! + return load_stb(data, size, color); + } +} + +MemoryMappedTexture load_texture_from_file(Granite::Filesystem &fs, const std::string &path, ColorSpace color) +{ + auto file = fs.open(path, Granite::FileMode::ReadOnly); + if (!file) + return {}; + + auto mapped = file->map(); + if (!mapped) + return {}; + + if (MemoryMappedTexture::is_header(mapped->data(), mapped->get_size())) + { + MemoryMappedTexture tex; + tex.map_read(std::move(mapped)); + return tex; + } + + return load_texture_from_memory(mapped->data(), mapped->get_size(), color); +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_files.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_files.hpp new file mode 100644 index 00000000..357e6528 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_files.hpp @@ -0,0 +1,44 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "format.hpp" +#include "memory_mapped_texture.hpp" + +namespace Granite +{ +class Filesystem; +} + +namespace Vulkan +{ +enum class ColorSpace +{ + Linear, + sRGB +}; + +MemoryMappedTexture load_texture_from_file(Granite::Filesystem &fs, const std::string &path, ColorSpace color = ColorSpace::sRGB); +MemoryMappedTexture load_texture_from_memory(const void *data, size_t size, + ColorSpace color = ColorSpace::sRGB); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_format.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_format.cpp new file mode 100644 index 00000000..3e57c36b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_format.cpp @@ -0,0 +1,518 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "texture_format.hpp" +#include "format.hpp" +#include + +namespace Vulkan +{ +uint32_t TextureFormatLayout::num_miplevels(uint32_t width, uint32_t height, uint32_t depth) +{ + uint32_t size = unsigned(std::max(std::max(width, height), depth)); + uint32_t levels = 0; + while (size) + { + levels++; + size >>= 1; + } + return levels; +} + +void TextureFormatLayout::format_block_dim(VkFormat format, uint32_t &width, uint32_t &height) +{ +#define fmt(x, w, h) \ + case VK_FORMAT_##x: \ + width = w; \ + height = h; \ + break + + switch (format) + { + fmt(ETC2_R8G8B8A8_UNORM_BLOCK, 4, 4); + fmt(ETC2_R8G8B8A8_SRGB_BLOCK, 4, 4); + fmt(ETC2_R8G8B8A1_UNORM_BLOCK, 4, 4); + fmt(ETC2_R8G8B8A1_SRGB_BLOCK, 4, 4); + fmt(ETC2_R8G8B8_UNORM_BLOCK, 4, 4); + fmt(ETC2_R8G8B8_SRGB_BLOCK, 4, 4); + fmt(EAC_R11_UNORM_BLOCK, 4, 4); + fmt(EAC_R11_SNORM_BLOCK, 4, 4); + fmt(EAC_R11G11_UNORM_BLOCK, 4, 4); + fmt(EAC_R11G11_SNORM_BLOCK, 4, 4); + + fmt(BC1_RGB_UNORM_BLOCK, 4, 4); + fmt(BC1_RGB_SRGB_BLOCK, 4, 4); + fmt(BC1_RGBA_UNORM_BLOCK, 4, 4); + fmt(BC1_RGBA_SRGB_BLOCK, 4, 4); + fmt(BC2_UNORM_BLOCK, 4, 4); + fmt(BC2_SRGB_BLOCK, 4, 4); + fmt(BC3_UNORM_BLOCK, 4, 4); + fmt(BC3_SRGB_BLOCK, 4, 4); + fmt(BC4_UNORM_BLOCK, 4, 4); + fmt(BC4_SNORM_BLOCK, 4, 4); + fmt(BC5_UNORM_BLOCK, 4, 4); + fmt(BC5_SNORM_BLOCK, 4, 4); + fmt(BC6H_UFLOAT_BLOCK, 4, 4); + fmt(BC6H_SFLOAT_BLOCK, 4, 4); + fmt(BC7_SRGB_BLOCK, 4, 4); + fmt(BC7_UNORM_BLOCK, 4, 4); + +#define astc_fmt(w, h) \ + fmt(ASTC_##w##x##h##_UNORM_BLOCK, w, h); \ + fmt(ASTC_##w##x##h##_SRGB_BLOCK, w, h); \ + fmt(ASTC_##w##x##h##_SFLOAT_BLOCK_EXT, w, h) + + astc_fmt(4, 4); + astc_fmt(5, 4); + astc_fmt(5, 5); + astc_fmt(6, 5); + astc_fmt(6, 6); + astc_fmt(8, 5); + astc_fmt(8, 6); + astc_fmt(8, 8); + astc_fmt(10, 5); + astc_fmt(10, 6); + astc_fmt(10, 8); + astc_fmt(10, 10); + astc_fmt(12, 10); + astc_fmt(12, 12); + + default: + width = 1; + height = 1; + break; + } + +#undef fmt +#undef astc_fmt +} + +uint32_t TextureFormatLayout::format_block_size(VkFormat format, VkImageAspectFlags aspect) +{ +#define fmt(x, bpp) \ + case VK_FORMAT_##x: \ + return bpp + +#define fmt2(x, bpp0, bpp1) \ + case VK_FORMAT_##x: \ + return aspect == VK_IMAGE_ASPECT_PLANE_0_BIT ? bpp0 : bpp1 + + switch (format) + { + fmt(R4G4_UNORM_PACK8, 1); + fmt(R4G4B4A4_UNORM_PACK16, 2); + fmt(B4G4R4A4_UNORM_PACK16, 2); + fmt(R5G6B5_UNORM_PACK16, 2); + fmt(B5G6R5_UNORM_PACK16, 2); + fmt(R5G5B5A1_UNORM_PACK16, 2); + fmt(B5G5R5A1_UNORM_PACK16, 2); + fmt(A1R5G5B5_UNORM_PACK16, 2); + fmt(R8_UNORM, 1); + fmt(R8_SNORM, 1); + fmt(R8_USCALED, 1); + fmt(R8_SSCALED, 1); + fmt(R8_UINT, 1); + fmt(R8_SINT, 1); + fmt(R8_SRGB, 1); + fmt(R8G8_UNORM, 2); + fmt(R8G8_SNORM, 2); + fmt(R8G8_USCALED, 2); + fmt(R8G8_SSCALED, 2); + fmt(R8G8_UINT, 2); + fmt(R8G8_SINT, 2); + fmt(R8G8_SRGB, 2); + fmt(R8G8B8_UNORM, 3); + fmt(R8G8B8_SNORM, 3); + fmt(R8G8B8_USCALED, 3); + fmt(R8G8B8_SSCALED, 3); + fmt(R8G8B8_UINT, 3); + fmt(R8G8B8_SINT, 3); + fmt(R8G8B8_SRGB, 3); + fmt(R8G8B8A8_UNORM, 4); + fmt(R8G8B8A8_SNORM, 4); + fmt(R8G8B8A8_USCALED, 4); + fmt(R8G8B8A8_SSCALED, 4); + fmt(R8G8B8A8_UINT, 4); + fmt(R8G8B8A8_SINT, 4); + fmt(R8G8B8A8_SRGB, 4); + fmt(B8G8R8A8_UNORM, 4); + fmt(B8G8R8A8_SNORM, 4); + fmt(B8G8R8A8_USCALED, 4); + fmt(B8G8R8A8_SSCALED, 4); + fmt(B8G8R8A8_UINT, 4); + fmt(B8G8R8A8_SINT, 4); + fmt(B8G8R8A8_SRGB, 4); + fmt(A8B8G8R8_UNORM_PACK32, 4); + fmt(A8B8G8R8_SNORM_PACK32, 4); + fmt(A8B8G8R8_USCALED_PACK32, 4); + fmt(A8B8G8R8_SSCALED_PACK32, 4); + fmt(A8B8G8R8_UINT_PACK32, 4); + fmt(A8B8G8R8_SINT_PACK32, 4); + fmt(A8B8G8R8_SRGB_PACK32, 4); + fmt(A2B10G10R10_UNORM_PACK32, 4); + fmt(A2B10G10R10_SNORM_PACK32, 4); + fmt(A2B10G10R10_USCALED_PACK32, 4); + fmt(A2B10G10R10_SSCALED_PACK32, 4); + fmt(A2B10G10R10_UINT_PACK32, 4); + fmt(A2B10G10R10_SINT_PACK32, 4); + fmt(A2R10G10B10_UNORM_PACK32, 4); + fmt(A2R10G10B10_SNORM_PACK32, 4); + fmt(A2R10G10B10_USCALED_PACK32, 4); + fmt(A2R10G10B10_SSCALED_PACK32, 4); + fmt(A2R10G10B10_UINT_PACK32, 4); + fmt(A2R10G10B10_SINT_PACK32, 4); + fmt(R16_UNORM, 2); + fmt(R16_SNORM, 2); + fmt(R16_USCALED, 2); + fmt(R16_SSCALED, 2); + fmt(R16_UINT, 2); + fmt(R16_SINT, 2); + fmt(R16_SFLOAT, 2); + fmt(R16G16_UNORM, 4); + fmt(R16G16_SNORM, 4); + fmt(R16G16_USCALED, 4); + fmt(R16G16_SSCALED, 4); + fmt(R16G16_UINT, 4); + fmt(R16G16_SINT, 4); + fmt(R16G16_SFLOAT, 4); + fmt(R16G16B16_UNORM, 6); + fmt(R16G16B16_SNORM, 6); + fmt(R16G16B16_USCALED, 6); + fmt(R16G16B16_SSCALED, 6); + fmt(R16G16B16_UINT, 6); + fmt(R16G16B16_SINT, 6); + fmt(R16G16B16_SFLOAT, 6); + fmt(R16G16B16A16_UNORM, 8); + fmt(R16G16B16A16_SNORM, 8); + fmt(R16G16B16A16_USCALED, 8); + fmt(R16G16B16A16_SSCALED, 8); + fmt(R16G16B16A16_UINT, 8); + fmt(R16G16B16A16_SINT, 8); + fmt(R16G16B16A16_SFLOAT, 8); + fmt(R32_UINT, 4); + fmt(R32_SINT, 4); + fmt(R32_SFLOAT, 4); + fmt(R32G32_UINT, 8); + fmt(R32G32_SINT, 8); + fmt(R32G32_SFLOAT, 8); + fmt(R32G32B32_UINT, 12); + fmt(R32G32B32_SINT, 12); + fmt(R32G32B32_SFLOAT, 12); + fmt(R32G32B32A32_UINT, 16); + fmt(R32G32B32A32_SINT, 16); + fmt(R32G32B32A32_SFLOAT, 16); + fmt(R64_UINT, 8); + fmt(R64_SINT, 8); + fmt(R64_SFLOAT, 8); + fmt(R64G64_UINT, 16); + fmt(R64G64_SINT, 16); + fmt(R64G64_SFLOAT, 16); + fmt(R64G64B64_UINT, 24); + fmt(R64G64B64_SINT, 24); + fmt(R64G64B64_SFLOAT, 24); + fmt(R64G64B64A64_UINT, 32); + fmt(R64G64B64A64_SINT, 32); + fmt(R64G64B64A64_SFLOAT, 32); + fmt(B10G11R11_UFLOAT_PACK32, 4); + fmt(E5B9G9R9_UFLOAT_PACK32, 4); + + fmt(D16_UNORM, 2); + fmt(X8_D24_UNORM_PACK32, 4); + fmt(D32_SFLOAT, 4); + fmt(S8_UINT, 1); + + case VK_FORMAT_D16_UNORM_S8_UINT: + return aspect == VK_IMAGE_ASPECT_DEPTH_BIT ? 2 : 1; + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return aspect == VK_IMAGE_ASPECT_DEPTH_BIT ? 4 : 1; + + // ETC2 + fmt(ETC2_R8G8B8A8_UNORM_BLOCK, 16); + fmt(ETC2_R8G8B8A8_SRGB_BLOCK, 16); + fmt(ETC2_R8G8B8A1_UNORM_BLOCK, 8); + fmt(ETC2_R8G8B8A1_SRGB_BLOCK, 8); + fmt(ETC2_R8G8B8_UNORM_BLOCK, 8); + fmt(ETC2_R8G8B8_SRGB_BLOCK, 8); + fmt(EAC_R11_UNORM_BLOCK, 8); + fmt(EAC_R11_SNORM_BLOCK, 8); + fmt(EAC_R11G11_UNORM_BLOCK, 16); + fmt(EAC_R11G11_SNORM_BLOCK, 16); + + // BC + fmt(BC1_RGB_UNORM_BLOCK, 8); + fmt(BC1_RGB_SRGB_BLOCK, 8); + fmt(BC1_RGBA_UNORM_BLOCK, 8); + fmt(BC1_RGBA_SRGB_BLOCK, 8); + fmt(BC2_UNORM_BLOCK, 16); + fmt(BC2_SRGB_BLOCK, 16); + fmt(BC3_UNORM_BLOCK, 16); + fmt(BC3_SRGB_BLOCK, 16); + fmt(BC4_UNORM_BLOCK, 8); + fmt(BC4_SNORM_BLOCK, 8); + fmt(BC5_UNORM_BLOCK, 16); + fmt(BC5_SNORM_BLOCK, 16); + fmt(BC6H_UFLOAT_BLOCK, 16); + fmt(BC6H_SFLOAT_BLOCK, 16); + fmt(BC7_SRGB_BLOCK, 16); + fmt(BC7_UNORM_BLOCK, 16); + + // ASTC +#define astc_fmt(w, h) \ + fmt(ASTC_##w##x##h##_UNORM_BLOCK, 16); \ + fmt(ASTC_##w##x##h##_SRGB_BLOCK, 16); \ + fmt(ASTC_##w##x##h##_SFLOAT_BLOCK_EXT, 16) + + astc_fmt(4, 4); + astc_fmt(5, 4); + astc_fmt(5, 5); + astc_fmt(6, 5); + astc_fmt(6, 6); + astc_fmt(8, 5); + astc_fmt(8, 6); + astc_fmt(8, 8); + astc_fmt(10, 5); + astc_fmt(10, 6); + astc_fmt(10, 8); + astc_fmt(10, 10); + astc_fmt(12, 10); + astc_fmt(12, 12); + + fmt(G8B8G8R8_422_UNORM, 4); + fmt(B8G8R8G8_422_UNORM, 4); + + fmt(G8_B8_R8_3PLANE_420_UNORM, 1); + fmt2(G8_B8R8_2PLANE_420_UNORM, 1, 2); + fmt(G8_B8_R8_3PLANE_422_UNORM, 1); + fmt2(G8_B8R8_2PLANE_422_UNORM, 1, 2); + fmt(G8_B8_R8_3PLANE_444_UNORM, 1); + + fmt(R10X6_UNORM_PACK16, 2); + fmt(R10X6G10X6_UNORM_2PACK16, 4); + fmt(R10X6G10X6B10X6A10X6_UNORM_4PACK16, 8); + fmt(G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, 8); + fmt(B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, 8); + fmt(G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, 2); + fmt(G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, 2); + fmt(G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, 2); + fmt2(G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, 2, 4); + fmt2(G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, 2, 4); + + fmt(R12X4_UNORM_PACK16, 2); + fmt(R12X4G12X4_UNORM_2PACK16, 4); + fmt(R12X4G12X4B12X4A12X4_UNORM_4PACK16, 8); + fmt(G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, 8); + fmt(B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, 8); + fmt(G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, 2); + fmt(G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, 2); + fmt(G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, 2); + fmt2(G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, 2, 4); + fmt2(G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, 2, 4); + + fmt(G16B16G16R16_422_UNORM, 8); + fmt(B16G16R16G16_422_UNORM, 8); + fmt(G16_B16_R16_3PLANE_420_UNORM, 2); + fmt(G16_B16_R16_3PLANE_422_UNORM, 2); + fmt(G16_B16_R16_3PLANE_444_UNORM, 2); + fmt2(G16_B16R16_2PLANE_420_UNORM, 2, 4); + fmt2(G16_B16R16_2PLANE_422_UNORM, 2, 4); + + default: + assert(0 && "Unknown format."); + return 0; + } +#undef fmt +#undef fmt2 +#undef astc_fmt +} + +void TextureFormatLayout::fill_mipinfo(uint32_t width, uint32_t height, uint32_t depth) +{ + block_stride = format_block_size(format, 0); + format_block_dim(format, block_dim_x, block_dim_y); + + if (mip_levels == 0) + mip_levels = num_miplevels(width, height, depth); + + size_t offset = 0; + + for (uint32_t mip = 0; mip < mip_levels; mip++) + { + offset = (offset + 15) & ~15; + + uint32_t blocks_x = (width + block_dim_x - 1) / block_dim_x; + uint32_t blocks_y = (height + block_dim_y - 1) / block_dim_y; + size_t mip_size = blocks_x * blocks_y * array_layers * depth * block_stride; + + mips[mip].offset = offset; + + mips[mip].block_row_length = blocks_x; + mips[mip].block_image_height = blocks_y; + + mips[mip].row_length = blocks_x * block_dim_x; + mips[mip].image_height = blocks_y * block_dim_y; + + mips[mip].width = width; + mips[mip].height = height; + mips[mip].depth = depth; + + offset += mip_size; + + width = std::max((width >> 1u), 1u); + height = std::max((height >> 1u), 1u); + depth = std::max((depth >> 1u), 1u); + } + + required_size = offset; +} + +void TextureFormatLayout::set_1d(VkFormat format_, uint32_t width, uint32_t array_layers_, uint32_t mip_levels_) +{ + image_type = VK_IMAGE_TYPE_1D; + format = format_; + array_layers = array_layers_; + mip_levels = mip_levels_; + + fill_mipinfo(width, 1, 1); +} + +void TextureFormatLayout::set_2d(VkFormat format_, uint32_t width, uint32_t height, + uint32_t array_layers_, uint32_t mip_levels_) +{ + image_type = VK_IMAGE_TYPE_2D; + format = format_; + array_layers = array_layers_; + mip_levels = mip_levels_; + + fill_mipinfo(width, height, 1); +} + +void TextureFormatLayout::set_3d(VkFormat format_, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels_) +{ + image_type = VK_IMAGE_TYPE_3D; + format = format_; + array_layers = 1; + mip_levels = mip_levels_; + + fill_mipinfo(width, height, depth); +} + +void TextureFormatLayout::set_buffer(void *buffer_, size_t size) +{ + buffer = static_cast(buffer_); + buffer_size = size; +} + +uint32_t TextureFormatLayout::get_width(uint32_t mip) const +{ + return mips[mip].width; +} + +uint32_t TextureFormatLayout::get_height(uint32_t mip) const +{ + return mips[mip].height; +} + +uint32_t TextureFormatLayout::get_depth(uint32_t mip) const +{ + return mips[mip].depth; +} + +uint32_t TextureFormatLayout::get_layers() const +{ + return array_layers; +} + +VkImageType TextureFormatLayout::get_image_type() const +{ + return image_type; +} + +VkFormat TextureFormatLayout::get_format() const +{ + return format; +} + +uint32_t TextureFormatLayout::get_block_stride() const +{ + return block_stride; +} + +uint32_t TextureFormatLayout::get_levels() const +{ + return mip_levels; +} + +size_t TextureFormatLayout::get_required_size() const +{ + return required_size; +} + +const TextureFormatLayout::MipInfo &TextureFormatLayout::get_mip_info(uint32_t mip) const +{ + return mips[mip]; +} + +uint32_t TextureFormatLayout::get_block_dim_x() const +{ + return block_dim_x; +} + +uint32_t TextureFormatLayout::get_block_dim_y() const +{ + return block_dim_y; +} + +size_t TextureFormatLayout::row_byte_stride(uint32_t row_length) const +{ + return ((row_length + block_dim_x - 1) / block_dim_x) * block_stride; +} + +size_t TextureFormatLayout::layer_byte_stride(uint32_t image_height, size_t row_byte_stride) const +{ + return ((image_height + block_dim_y - 1) / block_dim_y) * row_byte_stride; +} + +void TextureFormatLayout::build_buffer_image_copies(Util::SmallVector &copies) const +{ + copies.resize(mip_levels); + for (unsigned level = 0; level < mip_levels; level++) + { + const auto &mip_info = mips[level]; + + auto &blit = copies[level]; + blit = {}; + blit.bufferOffset = mip_info.offset; + blit.bufferRowLength = mip_info.row_length; + blit.bufferImageHeight = mip_info.image_height; + blit.imageSubresource.aspectMask = format_to_aspect_mask(format); + blit.imageSubresource.mipLevel = level; + blit.imageSubresource.baseArrayLayer = 0; + blit.imageSubresource.layerCount = array_layers; + blit.imageExtent.width = mip_info.width; + blit.imageExtent.height = mip_info.height; + blit.imageExtent.depth = mip_info.depth; + } +} + +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_format.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_format.hpp new file mode 100644 index 00000000..7e38650f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/texture/texture_format.hpp @@ -0,0 +1,178 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" +#include "small_vector.hpp" +#include +#include +#include + +namespace Vulkan +{ +class TextureFormatLayout +{ +public: + void set_1d(VkFormat format, uint32_t width, uint32_t array_layers = 1, uint32_t mip_levels = 1); + void set_2d(VkFormat format, uint32_t width, uint32_t height, uint32_t array_layers = 1, uint32_t mip_levels = 1); + void set_3d(VkFormat format, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels = 1); + + static uint32_t format_block_size(VkFormat format, VkImageAspectFlags aspect); + static void format_block_dim(VkFormat format, uint32_t &width, uint32_t &height); + static uint32_t num_miplevels(uint32_t width, uint32_t height = 1, uint32_t depth = 1); + + void set_buffer(void *buffer, size_t size); + inline void *get_buffer() + { + return buffer; + } + + uint32_t get_width(uint32_t mip = 0) const; + uint32_t get_height(uint32_t mip = 0) const; + uint32_t get_depth(uint32_t mip = 0) const; + uint32_t get_levels() const; + uint32_t get_layers() const; + uint32_t get_block_stride() const; + uint32_t get_block_dim_x() const; + uint32_t get_block_dim_y() const; + VkImageType get_image_type() const; + VkFormat get_format() const; + + size_t get_required_size() const; + + size_t row_byte_stride(uint32_t row_length) const; + size_t layer_byte_stride(uint32_t row_length, size_t row_byte_stride) const; + + inline size_t get_row_size(uint32_t mip) const + { + return size_t(mips[mip].block_row_length) * block_stride; + } + + inline size_t get_layer_size(uint32_t mip) const + { + return size_t(mips[mip].block_image_height) * get_row_size(mip); + } + + struct MipInfo + { + size_t offset = 0; + uint32_t width = 1; + uint32_t height = 1; + uint32_t depth = 1; + + uint32_t block_image_height = 0; + uint32_t block_row_length = 0; + uint32_t image_height = 0; + uint32_t row_length = 0; + }; + + const MipInfo &get_mip_info(uint32_t mip) const; + + inline void *data(uint32_t layer = 0, uint32_t mip = 0) const + { + assert(buffer); + assert(buffer_size == required_size); + auto &mip_info = mips[mip]; + uint8_t *slice = buffer + mip_info.offset; + slice += block_stride * layer * mip_info.block_row_length * mip_info.block_image_height; + return slice; + } + + template + inline T *data_generic(uint32_t x, uint32_t y, uint32_t slice_index, uint32_t mip = 0) const + { + auto &mip_info = mips[mip]; + T *slice = reinterpret_cast(buffer + mip_info.offset); + slice += slice_index * mip_info.block_row_length * mip_info.block_image_height; + slice += y * mip_info.block_row_length; + slice += x; + return slice; + } + + inline void *data_opaque(uint32_t x, uint32_t y, uint32_t slice_index, uint32_t mip = 0) const + { + auto &mip_info = mips[mip]; + uint8_t *slice = buffer + mip_info.offset; + size_t off = slice_index * mip_info.block_row_length * mip_info.block_image_height; + off += y * mip_info.block_row_length; + off += x; + return slice + off * block_stride; + } + + template + inline T *data_generic() const + { + return data_generic(0, 0, 0, 0); + } + + template + inline T *data_1d(uint32_t x, uint32_t layer = 0, uint32_t mip = 0) const + { + assert(sizeof(T) == block_stride); + assert(buffer); + assert(image_type == VK_IMAGE_TYPE_1D); + assert(buffer_size == required_size); + return data_generic(x, 0, layer, mip); + } + + template + inline T *data_2d(uint32_t x, uint32_t y, uint32_t layer = 0, uint32_t mip = 0) const + { + assert(sizeof(T) == block_stride); + assert(buffer); + assert(image_type == VK_IMAGE_TYPE_2D); + assert(buffer_size == required_size); + return data_generic(x, y, layer, mip); + } + + template + inline T *data_3d(uint32_t x, uint32_t y, uint32_t z, uint32_t mip = 0) const + { + assert(sizeof(T) == block_stride); + assert(buffer); + assert(image_type == VK_IMAGE_TYPE_3D); + assert(buffer_size == required_size); + return data_generic(x, y, z, mip); + } + + void build_buffer_image_copies(Util::SmallVector &copies) const; + +private: + uint8_t *buffer = nullptr; + size_t buffer_size = 0; + + VkImageType image_type = VK_IMAGE_TYPE_MAX_ENUM; + VkFormat format = VK_FORMAT_UNDEFINED; + size_t required_size = 0; + + uint32_t block_stride = 1; + uint32_t mip_levels = 1; + uint32_t array_layers = 1; + uint32_t block_dim_x = 1; + uint32_t block_dim_y = 1; + + MipInfo mips[16]; + + void fill_mipinfo(uint32_t width, uint32_t height, uint32_t depth); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/type_to_string.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/type_to_string.hpp new file mode 100644 index 00000000..09b00fd5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/type_to_string.hpp @@ -0,0 +1,117 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include + +namespace Vulkan +{ +static inline const char *layout_to_string(VkImageLayout layout) +{ + switch (layout) + { + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return "SHADER_READ_ONLY"; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return "DS_READ_ONLY"; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return "DS"; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return "COLOR"; + case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL: + return "ATTACHMENT"; + case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL: + return "READ_ONLY"; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + return "TRANSFER_DST"; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + return "TRANSFER_SRC"; + case VK_IMAGE_LAYOUT_GENERAL: + return "GENERAL"; + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return "PRESENT"; + default: + return "UNDEFINED"; + } +} + +static inline std::string access_flags_to_string(VkAccessFlags2 flags) +{ + std::string result; + + if (flags & VK_ACCESS_SHADER_READ_BIT) + result += "SHADER_READ "; + if (flags & VK_ACCESS_SHADER_WRITE_BIT) + result += "SHADER_WRITE "; + if (flags & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) + result += "DS_WRITE "; + if (flags & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT) + result += "DS_READ "; + if (flags & VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) + result += "COLOR_READ "; + if (flags & VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) + result += "COLOR_WRITE "; + if (flags & VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) + result += "INPUT_READ "; + if (flags & VK_ACCESS_TRANSFER_WRITE_BIT) + result += "TRANSFER_WRITE "; + if (flags & VK_ACCESS_TRANSFER_READ_BIT) + result += "TRANSFER_READ "; + if (flags & VK_ACCESS_UNIFORM_READ_BIT) + result += "UNIFORM_READ "; + + if (!result.empty()) + result.pop_back(); + else + result = "NONE"; + + return result; +} + +static inline std::string stage_flags_to_string(VkPipelineStageFlags2 flags) +{ + std::string result; + + if (flags & VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT) + result += "GRAPHICS "; + if (flags & (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT)) + result += "DEPTH "; + if (flags & VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) + result += "COLOR "; + if (flags & VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) + result += "FRAGMENT "; + if (flags & VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) + result += "COMPUTE "; + if (flags & VK_PIPELINE_STAGE_TRANSFER_BIT) + result += "TRANSFER "; + if (flags & (VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT)) + result += "VERTEX "; + + if (!result.empty()) + result.pop_back(); + else + result = "NONE"; + + return result; +} +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/vulkan_common.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/vulkan_common.hpp new file mode 100644 index 00000000..60232db7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/vulkan_common.hpp @@ -0,0 +1,141 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "intrusive.hpp" +#include "object_pool.hpp" +#include "intrusive_hash_map.hpp" +#include "vulkan_headers.hpp" + +namespace Vulkan +{ +using HandleCounter = Util::MultiThreadCounter; + +template +using VulkanObjectPool = Util::ThreadSafeObjectPool; +template +using VulkanCache = Util::ThreadSafeIntrusiveHashMapReadCached; +template +using VulkanCacheReadWrite = Util::ThreadSafeIntrusiveHashMap; + +enum QueueIndices +{ + QUEUE_INDEX_GRAPHICS, + QUEUE_INDEX_COMPUTE, + QUEUE_INDEX_TRANSFER, + QUEUE_INDEX_VIDEO_DECODE, + QUEUE_INDEX_VIDEO_ENCODE, + QUEUE_INDEX_COUNT +}; + +struct ExternalHandle +{ +#ifdef _WIN32 + using NativeHandle = void *; + NativeHandle handle = nullptr; +#else + using NativeHandle = int; + NativeHandle handle = -1; +#endif + + VkExternalMemoryHandleTypeFlagBits memory_handle_type = get_opaque_memory_handle_type(); + VkExternalSemaphoreHandleTypeFlagBits semaphore_handle_type = get_opaque_semaphore_handle_type(); + + constexpr static VkExternalMemoryHandleTypeFlagBits get_opaque_memory_handle_type() + { +#ifdef _WIN32 + return VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; +#else + return VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; +#endif + } + + constexpr static VkExternalSemaphoreHandleTypeFlagBits get_opaque_semaphore_handle_type() + { +#ifdef _WIN32 + return VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT; +#else + return VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; +#endif + } + + inline explicit operator bool() const + { +#ifdef _WIN32 + return handle != nullptr; +#else + return handle >= 0; +#endif + } + + static bool memory_handle_type_imports_by_reference(VkExternalMemoryHandleTypeFlagBits type) + { + VK_ASSERT(type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || + type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT || + type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT || + type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT || + type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT || + type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT || + type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT || + type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); + + return type != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT && + type != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT && + type != VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT && + type != VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + } + + static bool semaphore_handle_type_imports_by_reference(VkExternalSemaphoreHandleTypeFlagBits type) + { + VK_ASSERT(type == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT || + type == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT || + type == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT || + type == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT || + type == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT); + + // D3D11 fence aliases D3D12 fence. It's basically the same thing, just D3D11.3. + return type != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT && + type != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT && + type != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + } +}; + +template +static inline const T *find_pnext(const void *pnext, VkStructureType sType) +{ + auto *chain = static_cast(pnext); + while (chain) + { + if (chain->sType == sType) + break; + chain = static_cast(chain->pNext); + } + return reinterpret_cast(chain); +} + +struct BufferMarkerHandle +{ + enum : uint32_t { Invalid = UINT32_MAX }; + uint32_t index = Invalid; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/vulkan_headers.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/vulkan_headers.hpp new file mode 100644 index 00000000..30537e2d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/vulkan_headers.hpp @@ -0,0 +1,71 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#if defined(_WIN32) && !defined(VK_USE_PLATFORM_WIN32_KHR) +#define VK_USE_PLATFORM_WIN32_KHR +#endif + +#if defined(VULKAN_H_) || defined(VULKAN_CORE_H_) +#error "Must include vulkan_headers.hpp before Vulkan headers" +#endif + +#include "volk.h" +#include +#include "logging.hpp" +#include + +// Workaround silly Xlib headers that define macros for these globally :( +#ifdef None +#undef None +#endif +#ifdef Bool +#undef Bool +#endif +#ifdef Status +#undef Status +#endif + +#ifdef VULKAN_DEBUG +#define VK_ASSERT(x) \ + do \ + { \ + if (!bool(x)) \ + { \ + LOGE("Vulkan error at %s:%d.\n", __FILE__, __LINE__); \ + abort(); \ + } \ + } while (0) +#else +#define VK_ASSERT(x) ((void)0) +#endif + +namespace Vulkan +{ +struct NoCopyNoMove +{ + NoCopyNoMove() = default; + NoCopyNoMove(const NoCopyNoMove &) = delete; + void operator=(const NoCopyNoMove &) = delete; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/vulkan_prerotate.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/vulkan_prerotate.hpp new file mode 100644 index 00000000..296f954b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/vulkan_prerotate.hpp @@ -0,0 +1,169 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "vulkan_headers.hpp" + +namespace Vulkan +{ +// FIXME: Also consider that we might have to flip X or Y w.r.t. dimensions, +// but that only matters for partial rendering ... +static inline bool surface_transform_swaps_xy(VkSurfaceTransformFlagBitsKHR transform) +{ + return (transform & ( + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR | + VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR)) != 0; +} + +static inline void viewport_transform_xy(VkViewport &vp, VkSurfaceTransformFlagBitsKHR transform, + uint32_t fb_width, uint32_t fb_height) +{ + switch (transform) + { + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: + { + float new_y = vp.x; + float new_x = float(fb_width) - (vp.y + vp.height); + vp.x = new_x; + vp.y = new_y; + std::swap(vp.width, vp.height); + break; + } + + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: + { + // Untested. Cannot make Android trigger this mode. + float new_left = float(fb_width) - (vp.x + vp.width); + float new_top = float(fb_height) - (vp.y + vp.height); + vp.x = new_left; + vp.y = new_top; + break; + } + + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: + { + float new_x = vp.y; + float new_y = float(fb_height) - (vp.x + vp.width); + vp.x = new_x; + vp.y = new_y; + std::swap(vp.width, vp.height); + break; + } + + default: + break; + } +} + +static inline void rect2d_clip(VkRect2D &rect) +{ + if (rect.offset.x < 0) + { + rect.extent.width += rect.offset.x; + rect.offset.x = 0; + } + + if (rect.offset.y < 0) + { + rect.extent.height += rect.offset.y; + rect.offset.y = 0; + } + + rect.extent.width = std::min(rect.extent.width, 0x7fffffffu - rect.offset.x); + rect.extent.height = std::min(rect.extent.height, 0x7fffffffu - rect.offset.y); +} + +static inline void rect2d_transform_xy(VkRect2D &rect, VkSurfaceTransformFlagBitsKHR transform, + uint32_t fb_width, uint32_t fb_height) +{ + switch (transform) + { + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: + { + int new_y = rect.offset.x; + int new_x = int(fb_width) - int(rect.offset.y + rect.extent.height); + rect.offset = { new_x, new_y }; + std::swap(rect.extent.width, rect.extent.height); + break; + } + + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: + { + // Untested. Cannot make Android trigger this mode. + int new_left = int(fb_width) - int(rect.offset.x + rect.extent.width); + int new_top = int(fb_height) - int(rect.offset.y + rect.extent.height); + rect.offset = { new_left, new_top }; + break; + } + + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: + { + int new_x = rect.offset.y; + int new_y = int(fb_height) - int(rect.offset.x + rect.extent.width); + rect.offset = { new_x, new_y }; + std::swap(rect.extent.width, rect.extent.height); + break; + } + + default: + break; + } +} + +static inline void build_prerotate_matrix_2x2(VkSurfaceTransformFlagBitsKHR pre_rotate, float mat[4]) +{ + // TODO: HORIZONTAL_MIRROR. + switch (pre_rotate) + { + default: + mat[0] = 1.0f; + mat[1] = 0.0f; + mat[2] = 0.0f; + mat[3] = 1.0f; + break; + + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: + mat[0] = 0.0f; + mat[1] = 1.0f; + mat[2] = -1.0f; + mat[3] = 0.0f; + break; + + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: + mat[0] = 0.0f; + mat[1] = -1.0f; + mat[2] = 1.0f; + mat[3] = 0.0f; + break; + + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: + mat[0] = -1.0f; + mat[1] = 0.0f; + mat[2] = 0.0f; + mat[3] = -1.0f; + break; + } +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi.cpp new file mode 100644 index 00000000..120b4c1d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi.cpp @@ -0,0 +1,2907 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#define NOMINMAX +#include "wsi.hpp" +#include "environment.hpp" +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#if defined(ANDROID) && defined(HAVE_SWAPPY) +#include "swappy/swappyVk.h" +#endif + +static constexpr uint32_t PresentTimingQueueSize = 16; + +namespace Vulkan +{ +WSI::WSI() +{ + // With frame latency of 1, we get the ideal latency where + // we present, and then wait for the previous present to complete. + // Once this unblocks, it means that the present we just queued up is scheduled to complete next vblank, + // and the next frame to be recorded will have to be ready in 2 frames. + // This is ideal, since worst case for full performance, we will have a pipeline of CPU -> GPU, + // where CPU can spend 1 frame's worth of time, and GPU can spend one frame's worth of time. + // For mobile, opt for 2 frames of latency, since TBDR likes deeper pipelines and we can absorb more + // surfaceflinger jank. +#ifdef ANDROID + present_frame_latency = 2; +#else + present_frame_latency = 1; +#endif + + present_frame_latency = Util::get_environment_uint("GRANITE_VULKAN_PRESENT_WAIT_LATENCY", present_frame_latency); + LOGI("Targeting VK_KHR_present_wait latency to %u frames.\n", present_frame_latency); + + // Primaries are ST.2020 with D65 whitepoint as specified. + hdr_metadata.displayPrimaryRed = { 0.708f, 0.292f }; + hdr_metadata.displayPrimaryGreen = { 0.170f, 0.797f }; + hdr_metadata.displayPrimaryBlue = { 0.131f, 0.046f }; + hdr_metadata.whitePoint = { 0.3127f, 0.3290f }; + + // HDR10 range? Just arbitrary values, user can override later. + hdr_metadata.minLuminance = 0.01f; + hdr_metadata.maxLuminance = 1000.0f; + hdr_metadata.maxContentLightLevel = 1000.0f; + hdr_metadata.maxFrameAverageLightLevel = 200.0f; +} + +void WSI::set_present_wait_latency(uint32_t latency) +{ + present_frame_latency = latency; +} + +void WSI::set_hdr_metadata(const VkHdrMetadataEXT &hdr) +{ + hdr_metadata = hdr; + valid_hdr_metadata = true; + + if (swapchain && swapchain_surface_format.colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT && + device->get_device_features().supports_hdr_metadata) + { + table->vkSetHdrMetadataEXT(device->get_device(), 1, &swapchain, &hdr_metadata); + } +} + +void WSIPlatform::set_window_title(const std::string &) +{ +} + +void WSIPlatform::destroy_surface(VkInstance instance, VkSurfaceKHR surface) +{ + vkDestroySurfaceKHR(instance, surface, nullptr); +} + +uintptr_t WSIPlatform::get_fullscreen_monitor() +{ + return 0; +} + +uintptr_t WSIPlatform::get_native_window() +{ + return 0; +} + +const VkApplicationInfo *WSIPlatform::get_application_info() +{ + return nullptr; +} + +void WSI::set_window_title(const std::string &title) +{ + if (platform) + platform->set_window_title(title); +} + +double WSI::get_smooth_elapsed_time() const +{ + return smooth_elapsed_time; +} + +double WSI::get_smooth_frame_time() const +{ + return smooth_frame_time; +} + +bool WSI::init_from_existing_context(ContextHandle existing_context) +{ + VK_ASSERT(platform); + if (platform && device) + platform->event_device_destroyed(); + device.reset(); + context = std::move(existing_context); + table = &context->get_device_table(); + return true; +} + +bool WSI::init_external_swapchain(std::vector swapchain_images_) +{ + VK_ASSERT(context); + VK_ASSERT(device); + swapchain_width = platform->get_surface_width(); + swapchain_height = platform->get_surface_height(); + swapchain_aspect_ratio = platform->get_aspect_ratio(); + + external_swapchain_images = std::move(swapchain_images_); + + swapchain_width = external_swapchain_images.front()->get_width(); + swapchain_height = external_swapchain_images.front()->get_height(); + swapchain_surface_format = { external_swapchain_images.front()->get_format(), VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + + LOGI("Created swapchain %u x %u (fmt: %u).\n", + swapchain_width, swapchain_height, static_cast(swapchain_surface_format.format)); + + platform->event_swapchain_destroyed(); + platform->event_swapchain_created(device.get(), VK_NULL_HANDLE, swapchain_width, swapchain_height, + swapchain_aspect_ratio, + external_swapchain_images.size(), + swapchain_surface_format.format, swapchain_surface_format.colorSpace, + swapchain_current_prerotate); + + device->init_external_swapchain(this->external_swapchain_images); + platform->get_frame_timer().reset(); + external_acquire.reset(); + external_release.reset(); + return true; +} + +void WSI::set_platform(WSIPlatform *platform_) +{ + platform = platform_; +} + +bool WSI::init_device() +{ + VK_ASSERT(context); + VK_ASSERT(!device); + device = Util::make_handle(); + device->set_context(*context); + platform->event_device_created(device.get()); + +#ifdef HAVE_WSI_DXGI_INTEROP + dxgi.reset(new DXGIInteropSwapchain); + if (!dxgi->init_interop_device(*device)) + dxgi.reset(); + else + platform->get_frame_timer().reset(); +#endif + return true; +} + +bool WSI::init_device(DeviceHandle device_handle) +{ + VK_ASSERT(context); + device = std::move(device_handle); + platform->event_device_created(device.get()); + +#ifdef HAVE_WSI_DXGI_INTEROP + dxgi.reset(new DXGIInteropSwapchain); + if (!dxgi->init_interop_device(*device)) + dxgi.reset(); + else + platform->get_frame_timer().reset(); +#endif + return true; +} + +#ifdef HAVE_WSI_DXGI_INTEROP +bool WSI::init_surface_swapchain_dxgi(unsigned width, unsigned height) +{ + if (!dxgi) + return false; + + // Anything fancy like compute present cannot use DXGI. + if (current_extra_usage) + return false; + + HWND hwnd = reinterpret_cast(platform->get_native_window()); + if (!hwnd) + return false; + + VkSurfaceFormatKHR format = {}; + switch (current_backbuffer_format) + { + case BackbufferFormat::UNORM: + format = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + break; + + case BackbufferFormat::sRGB: + format = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + break; + + case BackbufferFormat::HDR10: + format = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_HDR10_ST2084_EXT }; + break; + + case BackbufferFormat::scRGB: + format = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT }; + break; + + default: + return false; + } + + constexpr unsigned num_images = 3; + + if (!dxgi->init_swapchain(hwnd, format, width, height, num_images)) + return false; + + LOGI("Initialized DXGI interop swapchain!\n"); + + swapchain_width = width; + swapchain_height = height; + swapchain_aspect_ratio = platform->get_aspect_ratio(); + swapchain_current_prerotate = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + swapchain_surface_format = dxgi->get_current_surface_format(); + has_acquired_swapchain_index = false; + + const uint32_t queue_present_support = 1u << context->get_queue_info().family_indices[QUEUE_INDEX_GRAPHICS]; + device->set_swapchain_queue_family_support(queue_present_support); + + swapchain_images = { dxgi->get_vulkan_image() }; + device->init_swapchain(swapchain_images, swapchain_width, swapchain_height, + swapchain_surface_format.format, + swapchain_current_prerotate, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + + platform->event_swapchain_destroyed(); + platform->event_swapchain_created(device.get(), swapchain, swapchain_width, swapchain_height, + swapchain_aspect_ratio, num_images, + swapchain_surface_format.format, + swapchain_surface_format.colorSpace, + swapchain_current_prerotate); + + return true; +} +#endif + +bool WSI::init_surface_swapchain() +{ + VK_ASSERT(surface == VK_NULL_HANDLE); + VK_ASSERT(context); + VK_ASSERT(device); + + unsigned width = platform->get_surface_width(); + unsigned height = platform->get_surface_height(); + +#ifdef HAVE_WSI_DXGI_INTEROP + if (init_surface_swapchain_dxgi(width, height)) + return true; + else + dxgi.reset(); +#endif + + surface = platform->create_surface(context->get_instance(), context->get_gpu()); + if (surface == VK_NULL_HANDLE) + { + LOGE("Failed to create VkSurfaceKHR.\n"); + return false; + } + + swapchain_aspect_ratio = platform->get_aspect_ratio(); + + VkBool32 supported = VK_FALSE; + uint32_t queue_present_support = 0; + + // TODO: Ideally we need to create surface earlier and negotiate physical device based on that support. + for (auto &index : context->get_queue_info().family_indices) + { + if (index != VK_QUEUE_FAMILY_IGNORED) + { + if (vkGetPhysicalDeviceSurfaceSupportKHR(context->get_gpu(), index, surface, &supported) == + VK_SUCCESS && supported) + { + queue_present_support |= 1u << index; + } + } + } + + if ((queue_present_support & (1u << context->get_queue_info().family_indices[QUEUE_INDEX_GRAPHICS])) == 0) + { + LOGE("No presentation queue found for GPU. Is it connected to a display?\n"); + return false; + } + + device->set_swapchain_queue_family_support(queue_present_support); + + if (!blocking_init_swapchain(width, height)) + { + LOGE("Failed to create swapchain.\n"); + return false; + } + + device->init_swapchain(swapchain_images, swapchain_width, swapchain_height, swapchain_surface_format.format, + swapchain_current_prerotate, + current_extra_usage | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + platform->get_frame_timer().reset(); + return true; +} + +bool WSI::init_simple(unsigned num_thread_indices, const Context::SystemHandles &system_handles) +{ + if (!init_context_from_platform(num_thread_indices, system_handles)) + return false; + if (!init_device()) + return false; + if (!init_surface_swapchain()) + return false; + return true; +} + +bool WSI::init_context_from_platform(unsigned num_thread_indices, const Context::SystemHandles &system_handles) +{ + VK_ASSERT(platform); + auto instance_ext = platform->get_instance_extensions(); + auto device_ext = platform->get_device_extensions(); + auto new_context = Util::make_handle(); + +#ifdef HAVE_FFMPEG_VULKAN + constexpr ContextCreationFlags video_context_flags = + CONTEXT_CREATION_ENABLE_VIDEO_DECODE_BIT | + CONTEXT_CREATION_ENABLE_VIDEO_ENCODE_BIT | + CONTEXT_CREATION_ENABLE_VIDEO_H264_BIT | + CONTEXT_CREATION_ENABLE_VIDEO_H265_BIT; +#else + constexpr ContextCreationFlags video_context_flags = 0; +#endif + + new_context->set_application_info(platform->get_application_info()); + new_context->set_num_thread_indices(num_thread_indices); + new_context->set_system_handles(system_handles); + + constexpr ContextCreationFlags context_flags = + CONTEXT_CREATION_ENABLE_ADVANCED_WSI_BIT | + CONTEXT_CREATION_ENABLE_PUSH_DESCRIPTOR_BIT | + CONTEXT_CREATION_ENABLE_DESCRIPTOR_BUFFER_BIT | + CONTEXT_CREATION_ENABLE_DESCRIPTOR_HEAP_BIT | +#ifdef GRANITE_VULKAN_SYSTEM_HANDLES + //CONTEXT_CREATION_ENABLE_PIPELINE_BINARY_BIT | +#endif + video_context_flags; + + if (!new_context->init_instance( + instance_ext.data(), instance_ext.size(), + context_flags)) + { + LOGE("Failed to create Vulkan instance.\n"); + return false; + } + + VkSurfaceKHR tmp_surface = platform->create_surface(new_context->get_instance(), VK_NULL_HANDLE); + + bool ret = new_context->init_device( + VK_NULL_HANDLE, tmp_surface, + device_ext.data(), device_ext.size(), + context_flags); + + if (tmp_surface) + platform->destroy_surface(new_context->get_instance(), tmp_surface); + + if (!ret) + { + LOGE("Failed to create Vulkan device.\n"); + return false; + } + + return init_from_existing_context(std::move(new_context)); +} + +void WSI::reinit_surface_and_swapchain(VkSurfaceKHR new_surface) +{ + LOGI("init_surface_and_swapchain()\n"); + if (new_surface != VK_NULL_HANDLE) + { + VK_ASSERT(surface == VK_NULL_HANDLE); + surface = new_surface; + } + + swapchain_width = platform->get_surface_width(); + swapchain_height = platform->get_surface_height(); + update_framebuffer(swapchain_width, swapchain_height); +} + +VkResult WSI::wait_for_present(uint64_t id, uint64_t timeout) +{ + if (!swapchain) + return VK_SUCCESS; + + if (id > present_last_id) + return VK_NOT_READY; + + bool timeout_is_fault = false; + if (device->get_device_features().supports_post_mortem && timeout == UINT64_MAX) + { + timeout = PostMortemTimeout; + timeout_is_fault = true; + } + + VkResult vr; + + if (supports_present_wait2 && device->get_device_features().present_wait2_features.presentWait2) + { + VkPresentWait2InfoKHR wait_info = { VK_STRUCTURE_TYPE_PRESENT_WAIT_2_INFO_KHR }; + wait_info.presentId = id; + wait_info.timeout = timeout; + vr = table->vkWaitForPresent2KHR(context->get_device(), swapchain, &wait_info); + } + else if (device->get_device_features().present_wait_features.presentWait) + vr = table->vkWaitForPresentKHR(context->get_device(), swapchain, id, timeout); + else + return VK_NOT_READY; + + if (timeout_is_fault && (vr == VK_TIMEOUT || vr == VK_ERROR_DEVICE_LOST)) + device->managers.breadcrumbs.notify_device_hung(); + return vr; +} + +void WSI::nonblock_delete_swapchain_resources() +{ + // If we can help it, don't try to destroy swapchains until we know the new swapchain has presented at least one frame on screen. + if (swapchain != VK_NULL_HANDLE && wait_for_present(1, 0) != VK_SUCCESS) + return; + + Util::SmallVector keep; + size_t pending = deferred_swapchains.size(); + for (auto &swap : deferred_swapchains) + { + if (!swap.fence || swap.fence->wait_timeout(0)) + { + platform->destroy_swapchain_resources(swap.swapchain); + table->vkDestroySwapchainKHR(device->get_device(), swap.swapchain, nullptr); + } + else if (pending >= 2) + { + swap.fence->wait(); + platform->destroy_swapchain_resources(swap.swapchain); + table->vkDestroySwapchainKHR(device->get_device(), swap.swapchain, nullptr); + } + else + keep.push_back(std::move(swap)); + + pending--; + } + + deferred_swapchains = std::move(keep); + + auto itr = std::remove_if(deferred_semaphore.begin(), deferred_semaphore.end(), [](DeferredDeletionSemaphore &sem) { + return !sem.fence || sem.fence->wait_timeout(0); + }); + deferred_semaphore.erase(itr, deferred_semaphore.end()); +} + +void WSI::drain_swapchain(bool in_tear_down) +{ + release_semaphores.clear(); + device->set_acquire_semaphore(0, Semaphore{}); + device->consume_release_semaphore(); + + if (device->get_device_features().swapchain_maintenance1_features.swapchainMaintenance1) + { + // If we're just resizing, there's no need to block, defer deletions for later. + if (in_tear_down) + { + if (last_present_fence) + { + last_present_fence->wait(); + last_present_fence.reset(); + } + + for (auto &old_swap : deferred_swapchains) + { + if (old_swap.fence) + old_swap.fence->wait(); + platform->destroy_swapchain_resources(old_swap.swapchain); + table->vkDestroySwapchainKHR(context->get_device(), old_swap.swapchain, nullptr); + } + + deferred_swapchains.clear(); + deferred_semaphore.clear(); + } + } + else if (swapchain != VK_NULL_HANDLE) + { + wait_for_present(present_last_id); + + device->external_queue_lock(); + table->vkDeviceWaitIdle(device->get_device()); + device->external_queue_unlock(); + } +} + +void WSI::tear_down_swapchain() +{ +#ifdef HAVE_WSI_DXGI_INTEROP + // We only do explicit teardown on exit. + dxgi.reset(); +#endif + + drain_swapchain(true); + platform->event_swapchain_destroyed(); + platform->destroy_swapchain_resources(swapchain); + table->vkDestroySwapchainKHR(context->get_device(), swapchain, nullptr); + swapchain = VK_NULL_HANDLE; + has_acquired_swapchain_index = false; + next_present_id = 1; + present_last_id = 0; + device->set_present_id(VK_NULL_HANDLE, 0); +} + +void WSI::deinit_surface_and_swapchain() +{ + LOGI("deinit_surface_and_swapchain()\n"); + + tear_down_swapchain(); + + if (surface != VK_NULL_HANDLE) + { + platform->destroy_surface(context->get_instance(), surface); + surface = VK_NULL_HANDLE; + } +} + +void WSI::set_external_frame(unsigned index, Semaphore acquire_semaphore, double frame_time) +{ + external_frame_index = index; + external_acquire = std::move(acquire_semaphore); + frame_is_external = true; + external_frame_time = frame_time; +} + +bool WSI::begin_frame_external() +{ + device->next_frame_context(); + + // Need to handle this stuff from outside. + if (has_acquired_swapchain_index) + return false; + + auto frame_time = platform->get_frame_timer().frame(external_frame_time); + auto elapsed_time = platform->get_frame_timer().get_elapsed(); + + // Assume we have been given a smooth frame pacing. + smooth_frame_time = frame_time; + smooth_elapsed_time = elapsed_time; + + // Poll after acquire as well for optimal latency. + platform->poll_input(); + + swapchain_index = external_frame_index; + platform->event_frame_tick(frame_time, elapsed_time); + + platform->event_swapchain_index(device.get(), swapchain_index); + device->set_acquire_semaphore(swapchain_index, external_acquire); + external_acquire.reset(); + return true; +} + +Semaphore WSI::consume_external_release_semaphore() +{ + Semaphore sem; + std::swap(external_release, sem); + return sem; +} + +//#define VULKAN_WSI_TIMING_DEBUG + +void WSI::wait_swapchain_latency() +{ + unsigned effective_latency = low_latency_mode_enable_present ? 0 : present_frame_latency; + + if (device->get_device_features().supports_low_latency2_nv && swapchain && low_latency_mode_enable_gpu_submit) + { + if (!low_latency_semaphore) + low_latency_semaphore = device->request_semaphore(VK_SEMAPHORE_TYPE_TIMELINE); + + auto wait_ts = device->write_calibrated_timestamp(); + VkLatencySleepInfoNV sleep_info = { VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV }; + sleep_info.signalSemaphore = low_latency_semaphore->get_semaphore(); + sleep_info.value = ++low_latency_semaphore_value; + if (device->get_device_table().vkLatencySleepNV(device->get_device(), swapchain, &sleep_info) == VK_SUCCESS) + low_latency_semaphore->wait_timeline(low_latency_semaphore_value); + else + LOGE("Failed to call vkLatencySleepNV.\n"); + device->register_time_interval("WSI", std::move(wait_ts), device->write_calibrated_timestamp(), "low_latency_sleep"); + + VkSetLatencyMarkerInfoNV latency_marker_info = { VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV }; + latency_marker_info.marker = VK_LATENCY_MARKER_INPUT_SAMPLE_NV; + latency_marker_info.presentID = next_present_id; + device->get_device_table().vkSetLatencyMarkerNV(device->get_device(), swapchain, &latency_marker_info); + + latency_marker_info.marker = VK_LATENCY_MARKER_SIMULATION_START_NV; + device->get_device_table().vkSetLatencyMarkerNV(device->get_device(), swapchain, &latency_marker_info); + + // Avoid conflicting wait cycles when doing reflex style latency limiting. + effective_latency = std::max(effective_latency, 2); + } + else if (device->get_device_features().anti_lag_features.antiLag) + { + auto wait_ts = device->write_calibrated_timestamp(); + + VkAntiLagDataAMD anti_lag = { VK_STRUCTURE_TYPE_ANTI_LAG_DATA_AMD }; + VkAntiLagPresentationInfoAMD present_info = { VK_STRUCTURE_TYPE_ANTI_LAG_PRESENTATION_INFO_AMD }; + anti_lag.pPresentationInfo = &present_info; + present_info.stage = VK_ANTI_LAG_STAGE_INPUT_AMD; + present_info.frameIndex = ++low_latency_semaphore_value; + anti_lag.mode = low_latency_mode_enable_gpu_submit ? VK_ANTI_LAG_MODE_ON_AMD : VK_ANTI_LAG_MODE_OFF_AMD; + device->get_device_table().vkAntiLagUpdateAMD(device->get_device(), &anti_lag); + low_latency_anti_lag_present_valid = low_latency_mode_enable_gpu_submit; + device->register_time_interval("WSI", std::move(wait_ts), device->write_calibrated_timestamp(), + "low_latency_sleep"); + + if (low_latency_mode_enable_gpu_submit) + { + // Avoid conflicting wait cycles when doing reflex style latency limiting. + effective_latency = std::max(effective_latency, 2); + } + } + + // If we're using duped frames, make sure we're waiting for the previous "real" frame, + // instead of a duped one. + // E.g. when doing frame dupes: + // 0, 1, 2, 3, 4, 5 ... + // real, dup, real, dup, real, dup ... + // With present frame latency of 1 (default), after presenting 2 + // we will wait for 0 to be done rather than 1. + // Similarly, after presenting 3 we'll still wait for 0 to be done, so we can get on submitting work + // for the next real frame, 4 before the GPU drains of work. + effective_latency += last_duplicated_frames; + + if ((device->get_device_features().present_wait_features.presentWait || supports_present_wait2) && + present_last_id > effective_latency && + current_present_mode == PresentMode::SyncToVBlank) + { + // The effective latency is more like present_frame_latency + 1. + // If 0, we wait for vblank, and we must do CPU work and GPU work in one frame + // to hit next vblank. + uint64_t target = present_last_id - effective_latency; + +#ifdef VULKAN_WSI_TIMING_DEBUG + auto begin_wait = Util::get_current_time_nsecs(); +#endif + auto wait_ts = device->write_calibrated_timestamp(); + auto wait_result = wait_for_present(target); + + device->register_time_interval("WSI", std::move(wait_ts), + device->write_calibrated_timestamp(), "wait_frame_latency"); + if (wait_result < 0) + LOGE("vkWaitForPresentKHR failed, vr %d.\n", wait_result); +#ifdef VULKAN_WSI_TIMING_DEBUG + auto end_wait = Util::get_current_time_nsecs(); + LOGI("WaitForPresentKHR took %.3f ms.\n", 1e-6 * double(end_wait - begin_wait)); +#endif + } +} + +void WSI::emit_end_of_frame_markers() +{ + if (device->get_device_features().supports_low_latency2_nv && swapchain && + low_latency_mode_enable_gpu_submit) + { + VkSetLatencyMarkerInfoNV latency_marker_info = { VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV }; + latency_marker_info.marker = VK_LATENCY_MARKER_SIMULATION_END_NV; + latency_marker_info.presentID = next_present_id; + device->get_device_table().vkSetLatencyMarkerNV(device->get_device(), swapchain, &latency_marker_info); + + latency_marker_info.marker = VK_LATENCY_MARKER_RENDERSUBMIT_END_NV; + device->get_device_table().vkSetLatencyMarkerNV(device->get_device(), swapchain, &latency_marker_info); + } +} + +void WSI::emit_marker_pre_present() +{ + if (device->get_device_features().supports_low_latency2_nv && swapchain && + low_latency_mode_enable_gpu_submit) + { + VkSetLatencyMarkerInfoNV latency_marker_info = { VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV }; + latency_marker_info.marker = VK_LATENCY_MARKER_PRESENT_START_NV; + latency_marker_info.presentID = next_present_id; + device->get_device_table().vkSetLatencyMarkerNV(device->get_device(), swapchain, &latency_marker_info); + } + else if (device->get_device_features().anti_lag_features.antiLag && low_latency_anti_lag_present_valid) + { + VkAntiLagDataAMD anti_lag = { VK_STRUCTURE_TYPE_ANTI_LAG_DATA_AMD }; + VkAntiLagPresentationInfoAMD present_info = { VK_STRUCTURE_TYPE_ANTI_LAG_PRESENTATION_INFO_AMD }; + anti_lag.pPresentationInfo = &present_info; + present_info.stage = VK_ANTI_LAG_STAGE_PRESENT_AMD; + present_info.frameIndex = low_latency_semaphore_value; + anti_lag.mode = low_latency_mode_enable_gpu_submit ? VK_ANTI_LAG_MODE_ON_AMD : VK_ANTI_LAG_MODE_OFF_AMD; + device->get_device_table().vkAntiLagUpdateAMD(device->get_device(), &anti_lag); + low_latency_anti_lag_present_valid = false; + } +} + +void WSI::emit_marker_post_present() +{ + if (device->get_device_features().supports_low_latency2_nv && swapchain && + low_latency_mode_enable_gpu_submit) + { + VkSetLatencyMarkerInfoNV latency_marker_info = { VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV }; + latency_marker_info.marker = VK_LATENCY_MARKER_PRESENT_END_NV; + latency_marker_info.presentID = next_present_id; + device->get_device_table().vkSetLatencyMarkerNV(device->get_device(), swapchain, &latency_marker_info); + } +} + +void WSI::set_present_low_latency_mode(bool enable) +{ + low_latency_mode_enable_present = enable; +} + +void WSI::set_gpu_submit_low_latency_mode(bool enable) +{ + if (device && device->get_device_features().supports_low_latency2_nv && swapchain && + low_latency_mode_enable_gpu_submit != enable) + { + VkLatencySleepModeInfoNV sleep_mode_info = { VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV }; + sleep_mode_info.lowLatencyBoost = enable; + sleep_mode_info.lowLatencyMode = enable; + if (table->vkSetLatencySleepModeNV(context->get_device(), swapchain, &sleep_mode_info) != VK_SUCCESS) + LOGE("Failed to set low latency sleep mode.\n"); + } + + low_latency_mode_enable_gpu_submit = enable; +} + +#ifdef HAVE_WSI_DXGI_INTEROP +bool WSI::begin_frame_dxgi() +{ + Semaphore acquire; + + while (!acquire) + { + if (!dxgi->acquire(acquire)) + return false; + + swapchain_index = 0; + acquire->signal_external(); + has_acquired_swapchain_index = true; + + // Poll after acquire as well for optimal latency. + platform->poll_input(); + + // Polling input may trigger a resize event. Trying to present in that situation without ResizeBuffers + // cause wonky issues on DXGI. + if (platform->should_resize()) + update_framebuffer(platform->get_surface_width(), platform->get_surface_height()); + + // If update_framebuffer caused a resize, we won't have an acquire index anymore, reacquire. + if (!has_acquired_swapchain_index) + acquire.reset(); + } + + auto wait_ts = device->write_calibrated_timestamp(); + if (!dxgi->wait_latency(present_frame_latency)) + { + LOGE("Failed to wait on latency handle.\n"); + return false; + } + device->register_time_interval("WSI", std::move(wait_ts), device->write_calibrated_timestamp(), + "DXGI wait latency"); + + auto frame_time = platform->get_frame_timer().frame(); + auto elapsed_time = platform->get_frame_timer().get_elapsed(); + + smooth_frame_time = frame_time; + smooth_elapsed_time = elapsed_time; + + platform->event_frame_tick(frame_time, elapsed_time); + platform->event_swapchain_index(device.get(), swapchain_index); + device->set_acquire_semaphore(swapchain_index, std::move(acquire)); + + return true; +} +#endif + +void WSI::update_present_timing_properties() +{ + VkSwapchainTimingPropertiesEXT props = { VK_STRUCTURE_TYPE_SWAPCHAIN_TIMING_PROPERTIES_EXT }; + uint64_t counter = 0; + if (table->vkGetSwapchainTimingPropertiesEXT(context->get_device(), swapchain, &props, &counter) != VK_SUCCESS) + return; + + if (counter == present_timing.refresh_counter && present_timing.has_refresh_feedback) + return; + + present_timing.refresh_counter = counter; + present_timing.refresh_duration = props.refreshDuration; + present_timing.refresh_interval = props.refreshInterval; + + const char *refresh_mode = "Unknown"; + + if (props.refreshInterval == 0) + { + // Wayland issue: It cannot figure out VRR vs FRR. Seems like we will need presentation-timing v3. + present_timing.refresh_mode = RefreshMode::Unknown; + } + else if (props.refreshInterval == UINT64_MAX) + { + present_timing.refresh_mode = RefreshMode::VRR; + refresh_mode = "VRR"; + } + else + { + present_timing.refresh_mode = RefreshMode::FRR; + refresh_mode = "FRR"; + } + + if (present_timing.refresh_duration) + { + (void)refresh_mode; +#ifdef VULKAN_DEBUG + LOGI("Present timing (count %llu): detected refresh duration of %llu nsec (%.6f Hz), mode %s.\n", + static_cast(counter), + static_cast(present_timing.refresh_duration), + 1e9 / double(present_timing.refresh_duration), refresh_mode); +#endif + } + + present_timing.has_refresh_feedback = true; +} + +void WSI::recalibrate_present_timing_domains() +{ + if (!context->get_enabled_device_features().supports_calibrated_timestamps) + return; + + present_timing.calibration.clear(); + + uint32_t count; + vkGetPhysicalDeviceCalibrateableTimeDomainsKHR(context->get_gpu(), &count, nullptr); + Util::SmallVector domains(count); + vkGetPhysicalDeviceCalibrateableTimeDomainsKHR(context->get_gpu(), &count, domains.data()); + domains.resize(count); + +#ifdef _WIN32 + constexpr auto host_domain = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR; +#else + constexpr auto host_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR; +#endif + + if (std::find(domains.begin(), domains.end(), host_domain) == domains.end()) + { + LOGW("Cannot calibrate timestamp domain %u\n", host_domain); + return; + } + + present_timing.calibration.resize(present_timing.time_domains.size()); + + for (size_t i = 0, n = present_timing.time_domains.size(); i < n; i++) + { + if (present_timing.time_domains[i] == host_domain) + { + present_timing.calibration[i] = { 1, { 1, 1, 1, 1 } }; + continue; + } + + if (std::find(domains.begin(), domains.end(), present_timing.time_domains[i]) == domains.end()) + { + LOGW("Cannot calibrate timestamp domain %u\n", host_domain); + return; + } + + VkCalibratedTimestampInfoKHR infos[2] = {}; + infos[0].sType = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_KHR; + infos[1].sType = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_KHR; + infos[0].timeDomain = host_domain; + infos[1].timeDomain = present_timing.time_domains[i]; + uint64_t timestamps[2] = {}; + uint64_t max_deviation; + + VkSwapchainCalibratedTimestampInfoEXT swapchain_info = + { VK_STRUCTURE_TYPE_SWAPCHAIN_CALIBRATED_TIMESTAMP_INFO_EXT }; + + if (present_timing.time_domains[i] == VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT) + { + // Every present stage has a unique time domain, query each stage one-by-one. + infos[1].pNext = &swapchain_info; + swapchain_info.timeDomainId = present_timing.time_domain_ids[i]; + swapchain_info.swapchain = swapchain; + + Util::for_each_bit(supports_present_timing.feedback, [&](unsigned bit) { + swapchain_info.presentStage = 1u << bit; + + if (table->vkGetCalibratedTimestampsKHR(context->get_device(), 2, infos, + timestamps, &max_deviation) != VK_SUCCESS) + { + LOGE("Failed to get calibrated timestamps.\n"); + return; + } + + present_timing.calibration[i].host_time = timestamps[0]; + present_timing.calibration[i].stage_times[bit] = timestamps[1]; + }); + } + else if (present_timing.time_domains[i] == VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT) + { + infos[1].pNext = &swapchain_info; + swapchain_info.timeDomainId = present_timing.time_domain_ids[i]; + swapchain_info.swapchain = swapchain; + + if (table->vkGetCalibratedTimestampsKHR(context->get_device(), 2, infos, + timestamps, &max_deviation) != VK_SUCCESS) + { + LOGE("Failed to get calibrated timestamps.\n"); + return; + } + + present_timing.calibration[i].host_time = timestamps[0]; + Util::for_each_bit(supports_present_timing.feedback, [&](unsigned bit) { + present_timing.calibration[i].stage_times[bit] = timestamps[1]; + }); + } + else + { + // This probably needs spec clarification. + // We assume it's normal nanoseconds for now. + if (infos[1].timeDomain == VK_TIME_DOMAIN_DEVICE_KHR && + (context->get_gpu_props().limits.timestampPeriod != 1.0f || + context->get_queue_info().timestamp_valid_bits != 64)) + { + LOGW("Implementation reports DEVICE domain timestamps, " + "but it's unclear how to deal with non-trivial periods and valid bits.\n"); + } + + if (table->vkGetCalibratedTimestampsKHR(context->get_device(), 2, infos, + timestamps, &max_deviation) != VK_SUCCESS) + { + LOGE("Failed to get calibrated timestamps.\n"); + return; + } + + present_timing.calibration[i].host_time = timestamps[0]; + Util::for_each_bit(supports_present_timing.feedback, [&](unsigned bit) { + present_timing.calibration[i].stage_times[bit] = timestamps[1]; + }); + } + } + +#ifdef _WIN32 + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + for (auto &calibration : present_timing.calibration) + calibration.host_time = uint64_t(1e9 * calibration.host_time / double(freq.QuadPart)); +#endif + + if (present_timing.present_stage == 0) + { + // Make sure that our requests use a supported time domain, otherwise NV driver gets confused. + for (size_t i = 0, n = present_timing.calibration.size(); i < n; i++) + { + auto &cal = present_timing.calibration[i]; + if (cal.host_time && + std::any_of(std::begin(cal.stage_times), std::end(cal.stage_times), [](uint64_t v) { return v != 0; })) + { + present_timing.time_domain = present_timing.time_domains[i]; + present_timing.time_domain_id = present_timing.time_domain_ids[i]; + break; + } + } + } +} + +void WSI::update_time_domain_properties() +{ + VkSwapchainTimeDomainPropertiesEXT time_domain_properties = { VK_STRUCTURE_TYPE_SWAPCHAIN_TIME_DOMAIN_PROPERTIES_EXT }; + time_domain_properties.timeDomainCount = 1; // Workaround VVL. + if (table->vkGetSwapchainTimeDomainPropertiesEXT(context->get_device(), swapchain, &time_domain_properties, nullptr) != VK_SUCCESS) + { + LOGE("Failed to query time domain properties.\n"); + return; + } + + present_timing.time_domains.resize(time_domain_properties.timeDomainCount); + present_timing.time_domain_ids.resize(time_domain_properties.timeDomainCount); + time_domain_properties.pTimeDomains = present_timing.time_domains.data(); + time_domain_properties.pTimeDomainIds = present_timing.time_domain_ids.data(); + + if (table->vkGetSwapchainTimeDomainPropertiesEXT(context->get_device(), swapchain, + &time_domain_properties, + &present_timing.time_domain_counter) != VK_SUCCESS) + { + LOGE("Failed to query time domain properties.\n"); + return; + } + +#ifdef VULKAN_DEBUG + for (uint32_t i = 0; i < time_domain_properties.timeDomainCount; i++) + { + LOGI("Got time domain %u, ID %llu\n", + present_timing.time_domains[i], + static_cast(present_timing.time_domain_ids[i])); + } +#endif + + present_timing.has_time_domain_props = true; + present_timing.need_recalibration = true; +} + +void WSI::poll_present_timing_feedback() +{ + VkPastPresentationTimingEXT timings[PresentTimingQueueSize] = {}; + VkPresentStageTimeEXT stage_time[PresentTimingQueueSize][4] = {}; + + for (uint32_t i = 0; i < PresentTimingQueueSize; i++) + { + auto &t = timings[i]; + t.sType = VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_EXT; + t.pPresentStages = stage_time[i]; + t.presentStageCount = 4; + + // VVL workaround + for (auto &s : stage_time[i]) + s.stage = VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT; + } + + VkPastPresentationTimingInfoEXT info = { VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_INFO_EXT }; + VkPastPresentationTimingPropertiesEXT props = { VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_PROPERTIES_EXT }; + props.presentationTimingCount = PresentTimingQueueSize; + props.pPresentationTimings = timings; + info.swapchain = swapchain; + + if (table->vkGetPastPresentationTimingEXT(context->get_device(), &info, &props) != VK_SUCCESS) + return; + + if (props.presentationTimingCount == 0) + return; + + if (props.timingPropertiesCounter != present_timing.refresh_counter) + update_present_timing_properties(); + + // NV bug on X11: props.timingPropertiesCounter is always 0, even if TimingPropertiesEXT returns 1. + if (props.timingPropertiesCounter != 0 && props.timingPropertiesCounter != present_timing.refresh_counter) + { + LOGW("Got presentation timing counter (%llu) which does not map to current state of swapchain (%llu).\n", + static_cast(props.timingPropertiesCounter), + static_cast(present_timing.refresh_counter)); + } + + // NV bug on X11: timeDomainsCount remains 0. + if ((props.timeDomainsCounter != 0 && props.timeDomainsCounter != present_timing.time_domain_counter) || + !present_timing.has_time_domain_props) + { + update_time_domain_properties(); + } + + auto current_time = Util::get_current_time_nsecs(); + if (present_timing.last_recalibration_time + 1000000000 < current_time) + { + present_timing.need_recalibration = true; + present_timing.last_recalibration_time = current_time; + } + + if (present_timing.need_recalibration) + { + recalibrate_present_timing_domains(); + present_timing.need_recalibration = false; + } + + for (uint32_t i = 0; i < props.presentationTimingCount; i++) + { + // By default, these reports must be sorted based on QueuePresent(). + + auto &timing = props.pPresentationTimings[i]; + + if (!timing.reportComplete) + { + // This should never happen since we don't request partial timestamps. + LOGE("Implementation does not report complete timestamps?\n"); + continue; + } + +#ifdef VULKAN_DEBUG + LOGI("Timing for presentID %llu, time domain %u, time domain ID %llu:\n", + static_cast(timing.presentId), + timing.timeDomain, static_cast(timing.timeDomainId)); +#endif + + present_timing.present_stage = 0; + present_timing.reference_time = 0; + present_timing.present_id = timing.presentId; + present_timing.time_domain = timing.timeDomain; + present_timing.time_domain_id = timing.timeDomainId; + + // Try to calibrate the timestamp so we can report them in host time domain. + const CalibratedTimestamp *calibrated = nullptr; + for (size_t j = 0, n = present_timing.time_domain_ids.size(); j < n; j++) + { + if (present_timing.time_domain_ids[j] == timing.timeDomainId) + { + if (j < present_timing.calibration.size()) + calibrated = &present_timing.calibration[j]; + break; + } + } + + if (calibrated && calibrated->host_time == 0) + calibrated = nullptr; + + std::sort(timing.pPresentStages, timing.pPresentStages + timing.presentStageCount, + [](const VkPresentStageTimeEXT &a, const VkPresentStageTimeEXT &b) { return a.stage < b.stage; }); + + present_timing.present_done_host_time = 0; + present_timing.gpu_done_host_time = 0; + + for (uint32_t stage_index = 0; stage_index < timing.presentStageCount; stage_index++) + { + auto &stage = timing.pPresentStages[stage_index]; + + // Safety. Shouldn't happen since we don't request it. + // Time of 0 can happen according to spec and means timing information is not available. + // Can happen for e.g. discarded, occluded surfaces on WL. Just skip the update. + if (stage.stage > VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT || stage.stage == 0 || stage.time == 0) + continue; + + uint64_t calibrated_stage_time = calibrated ? calibrated->stage_times[Util::trailing_zeroes(stage.stage)] : 0; +#ifdef VULKAN_DEBUG + static const char *stage_tags[] = { "QueueOperations", "Dequeued", "FirstPixelOut", "FirstPixelVisible" }; + const char *stage_tag = stage_tags[Util::trailing_zeroes(stage.stage)]; +#endif + + if (calibrated) + { + uint64_t calibrated_ts = calibrated->host_time + (stage.time - calibrated_stage_time); + if (stage.stage == VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT) + present_timing.gpu_done_host_time = calibrated_ts; + else + present_timing.present_done_host_time = calibrated_ts; +#ifdef VULKAN_DEBUG + LOGI(" %s: %.3f s (calibrated)\n", stage_tag, calibrated_ts * 1e-9); +#endif + } +#ifdef VULKAN_DEBUG + else + { + LOGI(" %s: %llu (raw ns)\n", stage_tag, static_cast(stage.time)); + } +#endif + + present_timing.present_stage = stage.stage; + present_timing.reference_time = stage.time; + } + + auto itr = std::find_if( + present_timing.error_stats.begin(), present_timing.error_stats.end(), + [&](const ErrorStats &err) { + return err.present_id == timing.presentId; + }); + + present_timing.presentation_time_error = 0; + + if (itr != present_timing.error_stats.end()) + { + // Retire the pending compensation. + present_timing.pending_compensation -= itr->compensation; + + if (present_timing.present_done_host_time && itr->target_absolute) + { + auto err = int64_t(present_timing.present_done_host_time) - int64_t(itr->target_absolute); + present_timing.presentation_time_error = err; +#ifdef VULKAN_DEBUG + LOGI(" Error: %.3f ms\n", 1e-6 * double(err)); +#endif + } + + present_timing.error_stats.erase(itr); + } + + frr_pacer.set_frame_time_ns(present_timing.refresh_duration); + + if (present_timing.present_done_host_time && present_timing.gpu_done_host_time) + { + frr_pacer.update_feedback(present_timing.present_id, present_timing.gpu_done_host_time, + present_timing.present_done_host_time); + } + } +} + +void WSI::set_present_timing_request(VkPresentTimingInfoEXT &timing) +{ + // No stable way to set targets yet. + if (present_timing.refresh_duration == 0 || present_timing.reference_time == 0 || + present_timing.present_done_host_time == 0) + return; + + // Presentation timing is only meaningful for FIFO. + if (active_present_mode != VK_PRESENT_MODE_FIFO_KHR && + active_present_mode != VK_PRESENT_MODE_FIFO_RELAXED_KHR && + active_present_mode != VK_PRESENT_MODE_FIFO_LATEST_READY_KHR) + return; + + // Not supported. + if (!supports_present_timing.absolute && !supports_present_timing.relative) + return; + + // No request to set time. + if (present_timing.target_absolute_time == 0 && present_timing.target_relative_time == 0) + return; + + uint64_t relative_time = present_timing.target_relative_time; + if (relative_time && !present_timing.force_vrr && present_timing.refresh_mode != RefreshMode::VRR) + { + // If we keep accumulating relative time in a non-locked way, we'll get terrible pacing. + // Realign the relative time to boundary unless we're in VRR mode. + + uint64_t interval = present_timing.refresh_duration; + relative_time = std::max(relative_time, interval); + + // The refresh interval represents the alignment of a refresh cycle. + // Duration is a multiple of interval. + if (present_timing.refresh_interval) + interval = present_timing.refresh_interval; + + auto cycles = (relative_time + interval - 1) / interval; + relative_time = interval * cycles; + } + + // VRR does not have to align to boundaries, so rounding is somewhat meaningless. + if (present_timing.refresh_mode != RefreshMode::VRR && !present_timing.force_vrr) + timing.flags |= VK_PRESENT_TIMING_INFO_PRESENT_AT_NEAREST_REFRESH_CYCLE_BIT_EXT; + + if (present_timing.time_domain == VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT) + timing.targetTimeDomainPresentStage = present_timing.present_stage; + + uint64_t minimum_interval = present_timing.refresh_duration; + + if (supports_present_timing.relative && relative_time) + { + // Relative time is very nice, since it's not our job to align frames :) + timing.flags |= VK_PRESENT_TIMING_INFO_PRESENT_AT_RELATIVE_TIME_BIT_EXT; + timing.targetTime = relative_time; + + // If we're using pure relative timing, we don't care about error accumulation and compensation, + // since it's expected that application will be driven by feedback rather than opposite. + } + else + { + if (!supports_present_timing.absolute) + { + // Ensure that we don't attempt to compensate for errors when absolute times are very tight. + // The emulated relative time must never be smaller than duration. + relative_time = std::max(relative_time, present_timing.refresh_duration); + } + + // If presentations get sufficiently delayed, we will need to catch up with our internal accumulator. + // If we're using present interval > 1, we'll catch up in a few frames. + uint64_t estimated_minimum_time = present_timing.present_done_host_time + + (present_last_id - present_timing.present_id) * minimum_interval; + + present_timing.last_absolute_target_time = + std::max(present_timing.last_absolute_target_time, estimated_minimum_time); + + // Compute the target absolute timing. + uint64_t next_absolute_time = std::max( + present_timing.last_absolute_target_time + relative_time, + present_timing.target_absolute_time); + + int64_t compensation = 0; + + if (supports_present_timing.absolute) + { + timing.targetTime = next_absolute_time; + } + else + { + if (present_timing.last_absolute_target_time) + { + // This is kinda crude. We're emulating absolute timestamp with relative. + timing.targetTime = std::max(next_absolute_time, present_timing.last_absolute_target_time) - + present_timing.last_absolute_target_time; + + // Safety against deadlocks. + timing.targetTime = std::min(timing.targetTime, 1000 * 1000 * 1000); + + // If we lost frames, relative timing will remain delayed, so pull back the relative timing + // to realign with absolute time. + // The value can be negative in theory if we got back frames too early, + // but that shouldn't really happen. + int64_t in_flight_error = present_timing.presentation_time_error - present_timing.pending_compensation; + + VK_ASSERT(timing.targetTime >= present_timing.refresh_duration); + + // Don't aim to compensate all error in one go. That seems to create some unfortunate feedback loop effects, + // especially on Windows. We'll accept some error as long as it means more stable pacing. + compensation = std::min(timing.targetTime - present_timing.refresh_duration, in_flight_error / 2); + timing.targetTime -= compensation; + +#ifdef _WIN32 + if (device->get_device_features().driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY && + (timing.flags & VK_PRESENT_TIMING_INFO_PRESENT_AT_NEAREST_REFRESH_CYCLE_BIT_EXT) != 0) + { + // The driver seems very temperamental here, and it seems to round down the relative time + // to DXGI present intervals or something (which is a bug) ... Realign the next_absolute_time exactly. + uint64_t interval = present_timing.refresh_interval ? + present_timing.refresh_interval : present_timing.refresh_duration; + + auto cycles = (timing.targetTime + interval / 2) / interval; + auto new_relative_time = cycles * interval; + auto adj = new_relative_time - timing.targetTime; + next_absolute_time += adj; + compensation -= adj; + timing.targetTime = new_relative_time; + } +#endif + + present_timing.pending_compensation += compensation; + +#ifdef VULKAN_DEBUG + LOGI("Relative target time: %.3f ms.\n", timing.targetTime * 1e-6); + LOGI(" Abs target time: %.3f ms.\n", next_absolute_time * 1e-6); + LOGI(" Compensation offset: %.3f ms\n", compensation * 1e-6); +#endif + } + + timing.flags |= VK_PRESENT_TIMING_INFO_PRESENT_AT_RELATIVE_TIME_BIT_EXT; + } + + present_timing.last_absolute_target_time = next_absolute_time; + present_timing.error_stats.push_back({ next_present_id, next_absolute_time, compensation }); + + // If we keep accumulating time through relative time emulation, we need to account for clock drift. + if (supports_present_timing.absolute && relative_time && + present_timing.refresh_mode != RefreshMode::VRR && !present_timing.force_vrr) + { + uint64_t interval = present_timing.refresh_interval ? + present_timing.refresh_interval : present_timing.refresh_duration; + + uint64_t align = + (present_timing.last_absolute_target_time - present_timing.present_done_host_time) % interval; + + // Try to quickly-ish align to a refresh cycle. + if (align > interval / 2) + present_timing.last_absolute_target_time += (interval - align) / 8; + else + present_timing.last_absolute_target_time -= align / 8; + } + } + + if ((timing.flags & VK_PRESENT_TIMING_INFO_PRESENT_AT_RELATIVE_TIME_BIT_EXT) == 0) + { + bool has_calibrated_time = false; + size_t n = std::min(present_timing.time_domain_ids.size(), present_timing.calibration.size()); + + for (size_t i = 0; i < n; i++) + { + if (present_timing.time_domain_ids[i] == timing.timeDomainId) + { + auto &c = present_timing.calibration[i]; + + // Spec seems to suggest that targetTime is always in terms of FIRST_PIXEL_VISIBLE, + // but we can only use timestamps based on the latest present stage we get feedback for. + uint64_t stage_time = c.stage_times[Util::trailing_zeroes(present_timing.present_stage)]; + + if (stage_time == 0) + { + LOGW("Cannot compute targetTime.\n"); + } + else + { + // Recompute the absolute time to target the domain. + timing.targetTime = (timing.targetTime - c.host_time) + stage_time; + + if (timing.targetTime >= (1ull << 63)) + LOGW("Detected strange overflow, ignoring time request.\n"); + else + has_calibrated_time = true; + } + + break; + } + } + + if (!has_calibrated_time) + timing.targetTime = 0; + } + + // Completely meaningless to keep targeting absolute. + present_timing.target_absolute_time = 0; +} + +bool WSI::get_presentation_stats(PresentationStats &stats) const +{ + if (!present_timing.reference_time) + return false; + + stats.feedback_present_id = present_timing.present_id; + stats.gpu_done_ts = present_timing.gpu_done_host_time; + stats.present_done_ts = present_timing.present_done_host_time; + stats.error = present_timing.presentation_time_error; + return true; +} + +bool WSI::get_refresh_rate_info(RefreshRateInfo &info) const +{ + if (present_timing.refresh_duration == 0) + return false; + + info.refresh_duration = present_timing.refresh_duration; + info.refresh_interval = present_timing.refresh_interval; + info.mode = present_timing.refresh_mode; + return true; +} + +uint64_t WSI::get_last_submitted_present_id() const +{ + return present_last_id; +} + +bool WSI::set_target_presentation_time(uint64_t absolute_time_ns, uint64_t relative_time_ns, bool force_vrr) +{ + present_timing.target_absolute_time = absolute_time_ns; + present_timing.target_relative_time = relative_time_ns; + present_timing.force_vrr = force_vrr; + + if (absolute_time_ns || relative_time_ns) + present_feedback_enable = true; + + if (active_present_mode != VK_PRESENT_MODE_FIFO_KHR && + active_present_mode != VK_PRESENT_MODE_FIFO_RELAXED_KHR && + active_present_mode != VK_PRESENT_MODE_FIFO_LATEST_READY_KHR) + return false; + + return present_timing.refresh_duration != 0 && present_timing.reference_time != 0 && + present_timing.present_done_host_time != 0 && + (supports_present_timing.relative || supports_present_timing.absolute); +} + +void WSI::set_enable_timing_feedback(bool enable) +{ + present_feedback_enable = enable; +} + +void WSI::set_fixed_rate_low_latency_pacer(bool enable) +{ + frr_pacer_enable = enable; + if (!frr_pacer_enable) + frr_pacer.reset(); +} + +FixedRefreshRatePacer &WSI::get_fixed_rate_pacer() +{ + return frr_pacer; +} + +bool WSI::begin_frame() +{ + if (frame_is_external) + return begin_frame_external(); + +#ifdef VULKAN_WSI_TIMING_DEBUG + auto next_frame_start = Util::get_current_time_nsecs(); +#endif + + device->next_frame_context(); + external_release.reset(); + +#ifdef VULKAN_WSI_TIMING_DEBUG + auto next_frame_end = Util::get_current_time_nsecs(); + LOGI("Waited for vacant frame context for %.3f ms.\n", (next_frame_end - next_frame_start) * 1e-6); +#endif + +#ifdef HAVE_WSI_DXGI_INTEROP + if (dxgi) + { + if (platform->should_resize()) + update_framebuffer(platform->get_surface_width(), platform->get_surface_height()); + + if (has_acquired_swapchain_index) + return true; + return begin_frame_dxgi(); + } + else +#endif + { + if (swapchain == VK_NULL_HANDLE || platform->should_resize() || swapchain_is_suboptimal) + update_framebuffer(platform->get_surface_width(), platform->get_surface_height()); + if (has_acquired_swapchain_index) + return true; + } + + if (swapchain == VK_NULL_HANDLE) + { + LOGE("Completely lost swapchain. Cannot continue.\n"); + return false; + } + + VkResult result; + do + { + auto acquire = device->request_semaphore(VK_SEMAPHORE_TYPE_BINARY); + +#ifdef VULKAN_WSI_TIMING_DEBUG + auto acquire_start = Util::get_current_time_nsecs(); +#endif + + Fence fence; + + // TODO: Improve this with fancier approaches as needed. + if (low_latency_mode_enable_present && + !device->get_device_features().present_wait_features.presentWait && + !supports_present_wait2 && + current_present_mode == PresentMode::SyncToVBlank) + { + fence = device->request_legacy_fence(); + } + + auto acquire_ts = device->write_calibrated_timestamp(); + result = table->vkAcquireNextImageKHR(context->get_device(), swapchain, UINT64_MAX, acquire->get_semaphore(), + fence ? fence->get_fence() : VK_NULL_HANDLE, &swapchain_index); + device->register_time_interval("WSI", std::move(acquire_ts), device->write_calibrated_timestamp(), "acquire"); + + if (fence) + fence->wait(); + +#if defined(ANDROID) + // Android 10 can return suboptimal here, only because of pre-transform. + // We don't care about that, and treat this as success. + if (result == VK_SUBOPTIMAL_KHR && !support_prerotate) + result = VK_SUCCESS; +#endif + + if (result == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) + { + LOGE("Lost exclusive full-screen ...\n"); + } + +#ifdef VULKAN_WSI_TIMING_DEBUG + auto acquire_end = Util::get_current_time_nsecs(); + LOGI("vkAcquireNextImageKHR took %.3f ms.\n", (acquire_end - acquire_start) * 1e-6); +#endif + + if (result == VK_SUBOPTIMAL_KHR) + { +#ifdef VULKAN_DEBUG + LOGI("AcquireNextImageKHR is suboptimal, will recreate.\n"); +#endif + swapchain_is_suboptimal = true; + LOGW("Swapchain suboptimal.\n"); + } + + if (result >= 0) + { + has_acquired_swapchain_index = true; + acquire->signal_external(); + + // WSI signals this, which exists outside the domain of our Vulkan queues. + acquire->set_signal_is_foreign_queue(); + + wait_swapchain_latency(); + + if (supports_present_timing.feedback) + { + update_present_timing_properties(); + poll_present_timing_feedback(); + } + + if (frr_pacer_enable) + { + auto pace_start_ts = device->write_calibrated_timestamp(); + frr_pacer.begin_frame_submission(next_present_id); + device->register_time_interval( + "WSI", std::move(pace_start_ts), device->write_calibrated_timestamp(), + "pacer-wait"); + } + + auto frame_time = platform->get_frame_timer().frame(); + auto elapsed_time = platform->get_frame_timer().get_elapsed(); + + smooth_frame_time = frame_time; + smooth_elapsed_time = elapsed_time; + + // Poll after acquire as well for optimal latency. + platform->poll_input(); + platform->event_frame_tick(frame_time, elapsed_time); + + platform->event_swapchain_index(device.get(), swapchain_index); + + device->set_acquire_semaphore(swapchain_index, acquire); + if (device->get_device_features().present_id_features.presentId || + device->get_device_features().present_id2_features.presentId2) + { + device->set_present_id(swapchain, next_present_id); + } + } + else if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) + { + LOGW("Swapchain out of date.\n"); + VK_ASSERT(swapchain_width != 0); + VK_ASSERT(swapchain_height != 0); + + tear_down_swapchain(); + + if (!blocking_init_swapchain(swapchain_width, swapchain_height)) + return false; + device->init_swapchain(swapchain_images, swapchain_width, swapchain_height, + swapchain_surface_format.format, swapchain_current_prerotate, + current_extra_usage | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + } + else + { + return false; + } + } while (result < 0); + return true; +} + +#ifdef HAVE_WSI_DXGI_INTEROP +bool WSI::end_frame_dxgi() +{ + auto release = device->consume_release_semaphore(); + VK_ASSERT(release); + VK_ASSERT(release->is_signalled()); + VK_ASSERT(!release->is_pending_wait()); + return dxgi->present(std::move(release), current_present_mode == PresentMode::SyncToVBlank); +} +#endif + +void WSI::set_frame_duplication_aware(bool enable, uint32_t target_image_count) +{ + frame_dupe_aware = enable; + frame_dupe_target_images = target_image_count; + + if (!has_acquired_swapchain_index && (current_frame_dupe_aware != frame_dupe_aware || + current_frame_dupe_target_images != frame_dupe_target_images)) + { + current_frame_dupe_aware = frame_dupe_aware; + current_frame_dupe_target_images = frame_dupe_target_images; + update_framebuffer(swapchain_width, swapchain_height); + } +} + +void WSI::set_next_present_is_duplicated() +{ + next_present_is_dupe = true; +} + +bool WSI::end_frame() +{ + device->end_frame_context(); + + // Take ownership of the release semaphore so that the external user can use it. + if (frame_is_external) + { + // If we didn't render into the swapchain this frame, we will return a blank semaphore. + external_release = device->consume_release_semaphore(); + VK_ASSERT(!external_release || external_release->is_signalled()); + frame_is_external = false; + } + else + { + if (!device->swapchain_touched()) + return true; + + emit_end_of_frame_markers(); + has_acquired_swapchain_index = false; + +#ifdef HAVE_WSI_DXGI_INTEROP + if (dxgi) + return end_frame_dxgi(); +#endif + + auto release = device->consume_release_semaphore(); + VK_ASSERT(release); + VK_ASSERT(release->is_signalled()); + VK_ASSERT(!release->is_pending_wait()); + + auto release_semaphore = release->get_semaphore(); + VK_ASSERT(release_semaphore != VK_NULL_HANDLE); + + VkResult result = VK_SUCCESS; + VkPresentInfoKHR info = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; + info.waitSemaphoreCount = 1; + info.pWaitSemaphores = &release_semaphore; + info.swapchainCount = 1; + info.pSwapchains = &swapchain; + info.pImageIndices = &swapchain_index; + info.pResults = &result; + + VkSwapchainPresentFenceInfoKHR present_fence = { VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_KHR }; + VkSwapchainPresentModeInfoKHR present_mode_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_KHR }; + VkPresentIdKHR present_id_info = { VK_STRUCTURE_TYPE_PRESENT_ID_KHR }; + VkPresentId2KHR present_id2_info = { VK_STRUCTURE_TYPE_PRESENT_ID_2_KHR }; + VkPresentTimingsInfoEXT timings_info = { VK_STRUCTURE_TYPE_PRESENT_TIMINGS_INFO_EXT }; + VkPresentTimingInfoEXT timing_info = { VK_STRUCTURE_TYPE_PRESENT_TIMING_INFO_EXT }; + + if (supports_present_wait2) + { + present_id2_info.swapchainCount = 1; + present_id2_info.pPresentIds = &next_present_id; + present_id2_info.pNext = info.pNext; + info.pNext = &present_id2_info; + } + else if (device->get_device_features().present_id_features.presentId) + { + present_id_info.swapchainCount = 1; + present_id_info.pPresentIds = &next_present_id; + present_id_info.pNext = info.pNext; + info.pNext = &present_id_info; + } + + // If we can, just promote the new presentation mode right away. + update_active_presentation_mode(present_mode); + + if (device->get_device_features().swapchain_maintenance1_features.swapchainMaintenance1) + { + if (!device->get_workarounds().broken_present_fence) + { + last_present_fence = device->request_legacy_fence(); + present_fence.swapchainCount = 1; + present_fence.pFences = &last_present_fence->get_fence(); + present_fence.pNext = const_cast(info.pNext); + info.pNext = &present_fence; + } + + present_mode_info.swapchainCount = 1; + present_mode_info.pPresentModes = &active_present_mode; + present_mode_info.pNext = const_cast(info.pNext); + info.pNext = &present_mode_info; + } + + if (supports_present_timing.feedback && present_feedback_enable) + { + timing_info.presentStageQueries = supports_present_timing.feedback; + timing_info.timeDomainId = present_timing.time_domain_id; + set_present_timing_request(timing_info); + + timings_info.swapchainCount = 1; + timings_info.pTimingInfos = &timing_info; + timings_info.pNext = info.pNext; + info.pNext = &timings_info; + } + +#ifdef VULKAN_WSI_TIMING_DEBUG + auto present_start = Util::get_current_time_nsecs(); +#endif + + auto present_ts = device->write_calibrated_timestamp(); + + device->external_queue_lock(); + emit_marker_pre_present(); +#if defined(ANDROID) && defined(HAVE_SWAPPY) + VkResult overall = SwappyVk_queuePresent(device->get_current_present_queue(), &info); +#else + VkResult overall = table->vkQueuePresentKHR(device->get_current_present_queue(), &info); +#endif + emit_marker_post_present(); + device->external_queue_unlock(); + + device->register_time_interval("WSI", std::move(present_ts), device->write_calibrated_timestamp(), "present"); + +#if defined(ANDROID) + // Android 10 can return suboptimal here, only because of pre-transform. + // We don't care about that, and treat this as success. + if (overall == VK_SUBOPTIMAL_KHR && !support_prerotate) + overall = VK_SUCCESS; + if (result == VK_SUBOPTIMAL_KHR && !support_prerotate) + result = VK_SUCCESS; +#endif + + if (overall == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT || + result == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) + { + LOGE("Lost exclusive full-screen ...\n"); + } + +#ifdef VULKAN_WSI_TIMING_DEBUG + auto present_end = Util::get_current_time_nsecs(); + LOGI("vkQueuePresentKHR took %.3f ms.\n", (present_end - present_start) * 1e-6); +#endif + + bool dupes_frame = next_present_is_dupe && current_frame_dupe_aware && !low_latency_mode_enable_present; + + // The presentID only seems to get updated if QueuePresent returns success. + // This makes sense I guess. Record the latest present ID which was successfully presented + // so we don't risk deadlock. + if ((result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) && + (device->get_device_features().present_id_features.presentId || supports_present_wait2) && + !dupes_frame) + { + present_last_id = next_present_id; + } + + next_present_id++; + next_present_is_dupe = false; + + if (dupes_frame) + { + duplicated_frames++; + } + else + { + last_duplicated_frames = duplicated_frames; + duplicated_frames = 0; + } + + if (overall == VK_SUBOPTIMAL_KHR || result == VK_SUBOPTIMAL_KHR) + { +#ifdef VULKAN_DEBUG + LOGI("QueuePresent is suboptimal, will recreate.\n"); +#endif + swapchain_is_suboptimal = true; + } + + // The present semaphore is consumed even on OUT_OF_DATE, etc. + release->wait_external(); + + if (!device->get_workarounds().broken_present_fence && + device->get_device_features().swapchain_maintenance1_features.swapchainMaintenance1) + { + deferred_semaphore.push_back({ std::move(release), last_present_fence }); + release = {}; + } + + if (overall < 0 || result < 0) + { + LOGE("vkQueuePresentKHR failed.\n"); + release.reset(); + tear_down_swapchain(); + return false; + } + else + { + // Cannot release the WSI wait semaphore until we observe that the image has been + // waited on again. + // Could make this a bit tighter with swapchain_maintenance1, but not that important here. + release_semaphores[swapchain_index] = std::move(release); + } + + // Re-init swapchain. + if (present_mode != current_present_mode || + has_backbuffer_format_delta() || + extra_usage != current_extra_usage || + compression.type != current_compression.type || + compression.fixed_rates != current_compression.fixed_rates || + frame_dupe_aware != current_frame_dupe_aware || + frame_dupe_target_images != current_frame_dupe_target_images) + { + current_present_mode = present_mode; + current_backbuffer_format = backbuffer_format; + current_extra_usage = extra_usage; + current_compression = compression; + current_custom_backbuffer_format = custom_backbuffer_format; + current_frame_dupe_aware = frame_dupe_aware; + current_frame_dupe_target_images = frame_dupe_target_images; + update_framebuffer(swapchain_width, swapchain_height); + } + } + + nonblock_delete_swapchain_resources(); + return true; +} + +bool WSI::has_backbuffer_format_delta() const +{ + bool has_format_delta = backbuffer_format != current_backbuffer_format; + if (!has_format_delta && backbuffer_format == BackbufferFormat::Custom) + { + has_format_delta = current_custom_backbuffer_format.format != custom_backbuffer_format.format || + current_custom_backbuffer_format.colorSpace != custom_backbuffer_format.colorSpace; + } + + return has_format_delta; +} + +void WSI::update_framebuffer(unsigned width, unsigned height) +{ + if (context && device) + { +#ifdef HAVE_WSI_DXGI_INTEROP + if (dxgi) + { + if (!init_surface_swapchain_dxgi(width, height)) + LOGE("Failed to resize DXGI swapchain.\n"); + } + else +#endif + { + drain_swapchain(false); + if (blocking_init_swapchain(width, height)) + { + device->init_swapchain(swapchain_images, swapchain_width, swapchain_height, + swapchain_surface_format.format, swapchain_current_prerotate, + current_extra_usage | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + } + } + } + + if (platform) + platform->notify_current_swapchain_dimensions(swapchain_width, swapchain_height); +} + +bool WSI::update_active_presentation_mode(PresentMode mode) +{ + if (current_present_mode == mode) + return true; + +#ifdef HAVE_WSI_DXGI_INTEROP + // We set this on Present time. + if (dxgi) + { + current_present_mode = mode; + return true; + } +#endif + + for (auto m : present_mode_compat_group) + { + bool match = false; + switch (m) + { + case VK_PRESENT_MODE_FIFO_KHR: + match = mode == PresentMode::SyncToVBlank; + break; + + case VK_PRESENT_MODE_IMMEDIATE_KHR: + match = mode == PresentMode::UnlockedMaybeTear || + mode == PresentMode::UnlockedForceTearing; + break; + + case VK_PRESENT_MODE_MAILBOX_KHR: + match = mode == PresentMode::UnlockedNoTearing || + mode == PresentMode::UnlockedMaybeTear; + break; + + default: + break; + } + + if (match) + { + active_present_mode = m; + current_present_mode = mode; + return true; + } + } + + return false; +} + +void WSI::set_present_mode(PresentMode mode) +{ + present_mode = mode; + if (!has_acquired_swapchain_index && present_mode != current_present_mode) + { + if (!update_active_presentation_mode(present_mode)) + { + current_present_mode = present_mode; + update_framebuffer(swapchain_width, swapchain_height); + } + } +} + +void WSI::set_extra_usage_flags(VkImageUsageFlags usage) +{ + extra_usage = usage; + if (!has_acquired_swapchain_index && extra_usage != current_extra_usage) + { + current_extra_usage = extra_usage; + update_framebuffer(swapchain_width, swapchain_height); + } +} + +void WSI::set_backbuffer_format(BackbufferFormat format) +{ + backbuffer_format = format; + + if (!has_acquired_swapchain_index && has_backbuffer_format_delta()) + { + current_backbuffer_format = backbuffer_format; + current_custom_backbuffer_format = custom_backbuffer_format; + update_framebuffer(swapchain_width, swapchain_height); + } +} + +void WSI::set_image_compression_control(const ImageCompression &comp) +{ + if (device && !device->get_device_features().image_compression_control_swapchain_features.imageCompressionControlSwapchain) + return; + + compression = comp; + if (!has_acquired_swapchain_index && + (compression.type != current_compression.type || + compression.fixed_rates != current_compression.fixed_rates)) + { + current_compression = compression; + update_framebuffer(swapchain_width, swapchain_height); + } +} + +void WSI::set_custom_backbuffer_format(VkSurfaceFormatKHR format) +{ + custom_backbuffer_format = format; + set_backbuffer_format(BackbufferFormat::Custom); +} + +void WSI::set_backbuffer_srgb(bool enable) +{ + set_backbuffer_format(enable ? BackbufferFormat::sRGB : BackbufferFormat::UNORM); +} + +void WSI::teardown() +{ + low_latency_semaphore.reset(); + + if (platform) + platform->release_resources(); + + if (context) + tear_down_swapchain(); + + if (surface != VK_NULL_HANDLE) + { + platform->destroy_surface(context->get_instance(), surface); + surface = VK_NULL_HANDLE; + } + + if (platform) + platform->event_device_destroyed(); + external_release.reset(); + external_acquire.reset(); + external_swapchain_images.clear(); + device.reset(); + context.reset(); +} + +bool WSI::blocking_init_swapchain(unsigned width, unsigned height) +{ + SwapchainError err; + unsigned retry_counter = 0; + do + { + swapchain_aspect_ratio = platform->get_aspect_ratio(); + err = init_swapchain(width, height); + + if (err != SwapchainError::None) + platform->notify_current_swapchain_dimensions(0, 0); + + if (err == SwapchainError::Error) + { + if (++retry_counter > 3) + return false; + + // Try to not reuse the swapchain. + tear_down_swapchain(); + } + else if (err == SwapchainError::NoSurface) + { + LOGW("WSI cannot make forward progress due to minimization, blocking ...\n"); + device->set_enable_async_thread_frame_context(true); + platform->block_until_wsi_forward_progress(*this); + device->set_enable_async_thread_frame_context(false); + LOGW("Woke up!\n"); + } + } while (err != SwapchainError::None); + + frr_pacer.reset(); + return swapchain != VK_NULL_HANDLE; +} + +VkSurfaceFormatKHR WSI::find_suitable_present_format(const std::vector &formats, BackbufferFormat desired_format) const +{ + size_t format_count = formats.size(); + VkSurfaceFormatKHR format = { VK_FORMAT_UNDEFINED }; + + VkFormatFeatureFlags features = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; + if ((current_extra_usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) + features |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT; + + if (format_count == 0) + { + LOGE("Surface has no formats?\n"); + return format; + } + + for (size_t i = 0; i < format_count; i++) + { + if (!device->image_format_is_supported(formats[i].format, features)) + continue; + + if (desired_format == BackbufferFormat::Custom) + { + if (formats[i].colorSpace == current_custom_backbuffer_format.colorSpace && + formats[i].format == current_custom_backbuffer_format.format) + { + format = formats[i]; + break; + } + } + else if (desired_format == BackbufferFormat::DisplayP3) + { + if (formats[i].colorSpace == VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT && + (formats[i].format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 || + formats[i].format == VK_FORMAT_A2R10G10B10_UNORM_PACK32)) + { + format = formats[i]; + break; + } + } + else if (desired_format == BackbufferFormat::UNORMPassthrough) + { + if (formats[i].colorSpace == VK_COLOR_SPACE_PASS_THROUGH_EXT && + (formats[i].format == VK_FORMAT_R8G8B8A8_UNORM || + formats[i].format == VK_FORMAT_B8G8R8A8_UNORM || + formats[i].format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 || + formats[i].format == VK_FORMAT_A2R10G10B10_UNORM_PACK32)) + { + format = formats[i]; + break; + } + } + else if (desired_format == BackbufferFormat::HDR10) + { + if (formats[i].colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT && + (formats[i].format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 || + formats[i].format == VK_FORMAT_A2R10G10B10_UNORM_PACK32)) + { + format = formats[i]; + break; + } + } + else if (desired_format == BackbufferFormat::scRGB) + { + if (formats[i].colorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT && + formats[i].format == VK_FORMAT_R16G16B16A16_SFLOAT) + { + format = formats[i]; + break; + } + } + else if (desired_format == BackbufferFormat::sRGB) + { + if (formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR && + (formats[i].format == VK_FORMAT_R8G8B8A8_SRGB || + formats[i].format == VK_FORMAT_B8G8R8A8_SRGB || + formats[i].format == VK_FORMAT_A8B8G8R8_SRGB_PACK32)) + { + format = formats[i]; + break; + } + } + else + { + if (formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR && + (formats[i].format == VK_FORMAT_R8G8B8A8_UNORM || + formats[i].format == VK_FORMAT_B8G8R8A8_UNORM || + formats[i].format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 || + formats[i].format == VK_FORMAT_A2R10G10B10_UNORM_PACK32 || + formats[i].format == VK_FORMAT_A8B8G8R8_UNORM_PACK32)) + { + format = formats[i]; + break; + } + } + } + + return format; +} + +struct SurfaceInfo +{ + VkPhysicalDeviceSurfaceInfo2KHR surface_info; + VkSurfacePresentModeKHR present_mode; + VkSurfaceCapabilitiesKHR surface_capabilities; + std::vector formats; + VkSwapchainPresentModesCreateInfoKHR present_modes_info; + VkImageCompressionControlEXT compression_control; + VkImageCompressionFixedRateFlagsEXT compression_control_fixed_rates; + VkSurfaceCapabilitiesPresentId2KHR present_id2; + VkSurfaceCapabilitiesPresentWait2KHR present_wait2; + VkPresentTimingSurfaceCapabilitiesEXT present_timing; + std::vector present_mode_compat_group; + const void *swapchain_pnext; + VkSwapchainLatencyCreateInfoNV latency_create_info; +#ifdef _WIN32 + VkSurfaceFullScreenExclusiveInfoEXT exclusive_info; + VkSurfaceFullScreenExclusiveWin32InfoEXT exclusive_info_win32; +#endif +}; + +static bool init_surface_info(Device &device, WSIPlatform &platform, + VkSurfaceKHR surface, BackbufferFormat format, + const WSI::ImageCompression &compression, + PresentMode present_mode, SurfaceInfo &info, bool low_latency_mode_enable) +{ + if (surface == VK_NULL_HANDLE) + { + LOGE("Cannot create swapchain with surface == VK_NULL_HANDLE.\n"); + return false; + } + + info.surface_info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR }; + info.surface_info.surface = surface; + info.swapchain_pnext = nullptr; + + auto &ext = device.get_device_features(); + +#ifdef _WIN32 + if (ext.supports_full_screen_exclusive) + { + info.exclusive_info = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT }; + auto monitor = reinterpret_cast(platform.get_fullscreen_monitor()); + info.swapchain_pnext = &info.exclusive_info; + info.surface_info.pNext = &info.exclusive_info; + + if (monitor != nullptr) + { + info.exclusive_info_win32 = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT }; + info.exclusive_info.pNext = &info.exclusive_info_win32; + info.exclusive_info_win32.hmonitor = monitor; + LOGI("Win32: Got a full-screen monitor.\n"); + } + else + LOGI("Win32: Not running full-screen.\n"); + + bool prefer_exclusive = Util::get_environment_bool("GRANITE_EXCLUSIVE_FULL_SCREEN", false) || low_latency_mode_enable; + if (ext.driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) + prefer_exclusive = false; // Broken on Intel Windows + + if (ext.driver_id == VK_DRIVER_ID_AMD_PROPRIETARY && + (format == BackbufferFormat::HDR10 || format == BackbufferFormat::scRGB)) + { + LOGI("Win32: HDR requested on AMD Windows. Forcing exclusive fullscreen, or HDR will not work properly.\n"); + prefer_exclusive = true; + } + + if (prefer_exclusive && monitor != nullptr) + { + LOGI("Win32: Opting in to exclusive full-screen!\n"); + info.exclusive_info.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT; + + // Try to promote this to application controlled exclusive. + VkSurfaceCapabilities2KHR surface_capabilities2 = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR }; + VkSurfaceCapabilitiesFullScreenExclusiveEXT capability_full_screen_exclusive = { + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT + }; + surface_capabilities2.pNext = &capability_full_screen_exclusive; + + if (vkGetPhysicalDeviceSurfaceCapabilities2KHR(device.get_physical_device(), &info.surface_info, + &surface_capabilities2) != VK_SUCCESS) + return false; + + if (capability_full_screen_exclusive.fullScreenExclusiveSupported) + { + LOGI("Win32: Opting for exclusive fullscreen access.\n"); + info.exclusive_info.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT; + } + } + else + { + LOGI("Win32: Opting out of exclusive full-screen!\n"); + info.exclusive_info.fullScreenExclusive = + prefer_exclusive ? VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT : VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT; + } + } +#else + (void)platform; + (void)format; +#endif + + std::vector present_modes; + uint32_t num_present_modes = 0; + auto gpu = device.get_physical_device(); + +#ifdef _WIN32 + if (ext.supports_surface_capabilities2 && ext.supports_full_screen_exclusive) + { + if (vkGetPhysicalDeviceSurfacePresentModes2EXT(gpu, &info.surface_info, &num_present_modes, nullptr) != + VK_SUCCESS) + { + return false; + } + present_modes.resize(num_present_modes); + if (vkGetPhysicalDeviceSurfacePresentModes2EXT(gpu, &info.surface_info, &num_present_modes, + present_modes.data()) != VK_SUCCESS) + { + return false; + } + } + else +#endif + { + if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &num_present_modes, nullptr) != VK_SUCCESS) + return false; + present_modes.resize(num_present_modes); + if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &num_present_modes, present_modes.data()) != VK_SUCCESS) + return false; + } + + auto swapchain_present_mode = VK_PRESENT_MODE_FIFO_KHR; + bool use_vsync = present_mode == PresentMode::SyncToVBlank; + if (!use_vsync) + { + bool allow_mailbox = present_mode != PresentMode::UnlockedForceTearing; + bool allow_immediate = present_mode != PresentMode::UnlockedNoTearing; + +#ifdef _WIN32 + // If we're trying to go exclusive full-screen, + // we need to ban certain types of present modes which apparently do not work as we expect. + if (info.exclusive_info.fullScreenExclusive == VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT) + allow_mailbox = false; +#endif + + for (auto &mode : present_modes) + { + if ((allow_immediate && mode == VK_PRESENT_MODE_IMMEDIATE_KHR) || + (allow_mailbox && mode == VK_PRESENT_MODE_MAILBOX_KHR)) + { + swapchain_present_mode = mode; + break; + } + } + } + + if (swapchain_present_mode == VK_PRESENT_MODE_FIFO_KHR && low_latency_mode_enable) + for (auto mode : present_modes) + if (mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR) + swapchain_present_mode = mode; + + LOGI("Using present mode: %u.\n", swapchain_present_mode); + + // First, query minImageCount without any present mode. + // Avoid opting for present mode compat that is pathological in nature, + // e.g. Xorg MAILBOX where minImageCount shoots up to 5 for stupid reasons. + if (ext.supports_surface_capabilities2) + { + VkSurfaceCapabilities2KHR surface_capabilities2 = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR }; + + if (ext.present_id2_features.presentId2 && ext.present_wait2_features.presentWait2) + { + info.present_wait2 = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_WAIT_2_KHR }; + info.present_id2 = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_ID_2_KHR }; + info.present_wait2.pNext = &info.present_id2; + surface_capabilities2.pNext = &info.present_wait2; + } + + if (ext.present_timing_features.presentTiming) + { + info.present_timing = { VK_STRUCTURE_TYPE_PRESENT_TIMING_SURFACE_CAPABILITIES_EXT }; + info.present_timing.pNext = surface_capabilities2.pNext; + surface_capabilities2.pNext = &info.present_timing; + } + + if (vkGetPhysicalDeviceSurfaceCapabilities2KHR(gpu, &info.surface_info, &surface_capabilities2) != VK_SUCCESS) + return false; + info.surface_capabilities = surface_capabilities2.surfaceCapabilities; + } + else + { + if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &info.surface_capabilities) != VK_SUCCESS) + return false; + } + + // Make sure we query surface caps tied to the present mode for correct results. + if (ext.swapchain_maintenance1_features.swapchainMaintenance1 && + ext.supports_surface_capabilities2) + { + VkSurfaceCapabilities2KHR surface_capabilities2 = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR }; + VkSurfacePresentModeCompatibilityKHR present_mode_caps = + { VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_KHR }; + std::vector present_mode_compat_group; + + present_mode_compat_group.resize(32); + present_mode_caps.presentModeCount = present_mode_compat_group.size(); + present_mode_caps.pPresentModes = present_mode_compat_group.data(); + + info.present_mode.pNext = const_cast(info.surface_info.pNext); + info.surface_info.pNext = &info.present_mode; + info.present_mode = { VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_KHR }; + info.present_mode.presentMode = swapchain_present_mode; + + surface_capabilities2.pNext = &present_mode_caps; + if (vkGetPhysicalDeviceSurfaceCapabilities2KHR(gpu, &info.surface_info, &surface_capabilities2) != VK_SUCCESS) + return false; + surface_capabilities2.pNext = present_mode_caps.pNext; + + info.surface_capabilities.minImageCount = surface_capabilities2.surfaceCapabilities.minImageCount; + present_mode_compat_group.resize(present_mode_caps.presentModeCount); + info.present_mode_compat_group.reserve(present_mode_caps.presentModeCount); + info.present_mode_compat_group.push_back(swapchain_present_mode); + + for (auto mode : present_mode_compat_group) + { + if (mode == swapchain_present_mode) + continue; + + // Only allow sensible present modes that we know of. + if (mode != VK_PRESENT_MODE_FIFO_KHR && + mode != VK_PRESENT_MODE_FIFO_RELAXED_KHR && + mode != VK_PRESENT_MODE_IMMEDIATE_KHR && + mode != VK_PRESENT_MODE_MAILBOX_KHR) + { + continue; + } + + info.present_mode.presentMode = mode; + if (vkGetPhysicalDeviceSurfaceCapabilities2KHR(gpu, &info.surface_info, &surface_capabilities2) != VK_SUCCESS) + return false; + + // Accept the present mode if it does not modify minImageCount. + // If image count changes, we should probably recreate the swapchain. + // If we have present wait we're at no risk of adding more latency, so just go ahead. + if (surface_capabilities2.surfaceCapabilities.minImageCount == info.surface_capabilities.minImageCount || + device.get_device_features().present_wait_features.presentWait || + info.present_wait2.presentWait2Supported) + { + info.present_mode_compat_group.push_back(mode); + info.surface_capabilities.minImageCount = + std::max(info.surface_capabilities.minImageCount, + surface_capabilities2.surfaceCapabilities.minImageCount); + } + } + } + + uint32_t format_count = 0; + if (ext.supports_surface_capabilities2) + { + if (vkGetPhysicalDeviceSurfaceFormats2KHR(device.get_physical_device(), + &info.surface_info, &format_count, + nullptr) != VK_SUCCESS) + { + return false; + } + + std::vector formats2(format_count); + + for (auto &f : formats2) + { + f = {}; + f.sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR; + } + + if (vkGetPhysicalDeviceSurfaceFormats2KHR(gpu, &info.surface_info, &format_count, formats2.data()) != VK_SUCCESS) + return false; + + info.formats.reserve(format_count); + for (auto &f : formats2) + info.formats.push_back(f.surfaceFormat); + } + else + { + if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &format_count, nullptr) != VK_SUCCESS) + return false; + info.formats.resize(format_count); + if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &format_count, info.formats.data()) != VK_SUCCESS) + return false; + } + + // Ensure that 10-bit formats come before other formats. + std::sort(info.formats.begin(), info.formats.end(), [](const VkSurfaceFormatKHR &a, const VkSurfaceFormatKHR &b) { + const auto qual = [](VkFormat fmt) { + // Prefer a consistent ordering so Fossilize caches are more effective. + if (fmt == VK_FORMAT_A2B10G10R10_UNORM_PACK32) + return 3; + else if (fmt == VK_FORMAT_A2R10G10B10_UNORM_PACK32) + return 2; + else if (fmt == VK_FORMAT_B8G8R8A8_UNORM) + return 1; + else + return 0; + }; + return qual(a.format) > qual(b.format); + }); + + // Allow for seamless toggle between presentation modes. + if (ext.swapchain_maintenance1_features.swapchainMaintenance1) + { + info.present_modes_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_KHR }; + info.present_modes_info.pNext = const_cast(info.swapchain_pnext); + info.present_modes_info.presentModeCount = info.present_mode_compat_group.size(); + info.present_modes_info.pPresentModes = info.present_mode_compat_group.data(); + info.swapchain_pnext = &info.present_modes_info; + } + + info.present_mode.presentMode = swapchain_present_mode; + + if (ext.image_compression_control_swapchain_features.imageCompressionControlSwapchain && + compression.type != VK_IMAGE_COMPRESSION_DEFAULT_EXT) + { + // There is no VU that we cannot just pass in whatever we want here, + // but we might not be honored if we pass in something unsupported. + // That's fine for now. + info.compression_control = { VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT }; + info.compression_control.pNext = info.swapchain_pnext; + info.compression_control.flags = compression.type; + if (compression.type == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT) + { + info.compression_control_fixed_rates = compression.fixed_rates; + info.compression_control.pFixedRateFlags = &info.compression_control_fixed_rates; + info.compression_control.compressionControlPlaneCount = 1; + LOGI("Using fixed-rate compression for swapchain (flags #%08x).\n", compression.fixed_rates); + } + else if (compression.type == VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT) + LOGI("Using default fixed-rate compression for swapchain.\n"); + else if (compression.type == VK_IMAGE_COMPRESSION_DISABLED_EXT) + LOGI("Disabling compression for swapchain.\n"); + + info.swapchain_pnext = &info.compression_control; + } + + if (ext.supports_low_latency2_nv) + { + info.latency_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV }; + info.latency_create_info.latencyModeEnable = VK_TRUE; + info.latency_create_info.pNext = info.swapchain_pnext; + info.swapchain_pnext = &info.latency_create_info; + } + + return true; +} + +WSI::SwapchainError WSI::init_swapchain(unsigned width, unsigned height) +{ + SurfaceInfo surface_info = {}; + if (!init_surface_info(*device, *platform, surface, current_backbuffer_format, current_compression, + current_present_mode, surface_info, low_latency_mode_enable_present)) + { + return SwapchainError::Error; + } + const auto &caps = surface_info.surface_capabilities; + + // Happens on Windows when you minimize a window. + if (caps.maxImageExtent.width == 0 && caps.maxImageExtent.height == 0) + return SwapchainError::NoSurface; + + if (current_extra_usage && support_prerotate) + { + LOGW("Disabling prerotate support due to extra usage flags in swapchain.\n"); + support_prerotate = false; + } + + if (current_extra_usage & ~caps.supportedUsageFlags) + { + LOGW("Attempting to use unsupported usage flags 0x%x for swapchain.\n", current_extra_usage); + current_extra_usage &= caps.supportedUsageFlags; + extra_usage = current_extra_usage; + } + + auto attempt_backbuffer_format = current_backbuffer_format; + auto surface_format = find_suitable_present_format(surface_info.formats, attempt_backbuffer_format); + + if (surface_format.format == VK_FORMAT_UNDEFINED && + (attempt_backbuffer_format == BackbufferFormat::HDR10 || + attempt_backbuffer_format == BackbufferFormat::scRGB || + attempt_backbuffer_format == BackbufferFormat::DisplayP3 || + attempt_backbuffer_format == BackbufferFormat::UNORMPassthrough || + attempt_backbuffer_format == BackbufferFormat::Custom)) + { + LOGW("Could not find suitable present format for HDR. Attempting fallback to UNORM.\n"); + attempt_backbuffer_format = BackbufferFormat::UNORM; + surface_format = find_suitable_present_format(surface_info.formats, attempt_backbuffer_format); + } + + if (surface_format.format == VK_FORMAT_UNDEFINED) + { + LOGW("Could not find supported format for swapchain usage flags 0x%x.\n", current_extra_usage); + current_extra_usage = 0; + extra_usage = 0; + surface_format = find_suitable_present_format(surface_info.formats, attempt_backbuffer_format); + } + + if (surface_format.format == VK_FORMAT_UNDEFINED) + { + LOGE("Failed to find any suitable format for swapchain.\n"); + return SwapchainError::Error; + } + + static const char *transform_names[] = { + "IDENTITY_BIT_KHR", + "ROTATE_90_BIT_KHR", + "ROTATE_180_BIT_KHR", + "ROTATE_270_BIT_KHR", + "HORIZONTAL_MIRROR_BIT_KHR", + "HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR", + "HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR", + "HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR", + "INHERIT_BIT_KHR", + }; + + LOGI("Current transform is enum 0x%x.\n", unsigned(caps.currentTransform)); + + for (unsigned i = 0; i <= 8; i++) + { + if (caps.supportedTransforms & (1u << i)) + LOGI("Supported transform 0x%x: %s.\n", 1u << i, transform_names[i]); + } + + VkSurfaceTransformFlagBitsKHR pre_transform; + if (!support_prerotate && (caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) != 0) + pre_transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + else + { + // Only attempt to use prerotate if we can deal with it purely using a XY clip fixup. + // For horizontal flip we need to start flipping front-face as well ... + if ((caps.currentTransform & ( + VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | + VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR | + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR)) != 0) + pre_transform = caps.currentTransform; + else + pre_transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + } + + if (pre_transform != caps.currentTransform) + { + LOGW("surfaceTransform (0x%x) != currentTransform (0x%u). Might get performance penalty.\n", + unsigned(pre_transform), unsigned(caps.currentTransform)); + } + + swapchain_current_prerotate = pre_transform; + + VkExtent2D swapchain_size; + LOGI("Swapchain current extent: %d x %d\n", + int(caps.currentExtent.width), + int(caps.currentExtent.height)); + + if (width == 0) + { + if (caps.currentExtent.width != ~0u) + width = caps.currentExtent.width; + else + width = 1280; + LOGI("Auto selected width = %u.\n", width); + } + + if (height == 0) + { + if (caps.currentExtent.height != ~0u) + height = caps.currentExtent.height; + else + height = 720; + LOGI("Auto selected height = %u.\n", height); + } + + // Try to match the swapchain size up with what we expect w.r.t. aspect ratio. + float target_aspect_ratio = float(width) / float(height); + if ((swapchain_aspect_ratio > 1.0f && target_aspect_ratio < 1.0f) || + (swapchain_aspect_ratio < 1.0f && target_aspect_ratio > 1.0f)) + { + std::swap(width, height); + } + + // If we are using pre-rotate of 90 or 270 degrees, we need to flip width and height again. + if (swapchain_current_prerotate & + (VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR)) + { + std::swap(width, height); + } + + // Clamp the target width, height to boundaries. + swapchain_size.width = + std::max(std::min(width, caps.maxImageExtent.width), caps.minImageExtent.width); + swapchain_size.height = + std::max(std::min(height, caps.maxImageExtent.height), caps.minImageExtent.height); + + uint32_t desired_swapchain_images = + low_latency_mode_enable_present && current_present_mode == PresentMode::SyncToVBlank ? 2 : 3; + + supports_present_wait2 = + surface_info.present_id2.presentId2Supported && surface_info.present_wait2.presentWait2Supported; + + // Need a deeper swapchain to avoid potential stalls when duping frames. + // We only do this when present wait is supported, so latency should not be compromised. + if (current_frame_dupe_aware && (device->get_device_features().present_wait_features.presentWait || supports_present_wait2)) + desired_swapchain_images = current_frame_dupe_target_images; + + desired_swapchain_images = Util::get_environment_uint("GRANITE_VULKAN_SWAPCHAIN_IMAGES", desired_swapchain_images); + LOGI("Targeting %u swapchain images.\n", desired_swapchain_images); + + if (desired_swapchain_images < caps.minImageCount) + desired_swapchain_images = caps.minImageCount; + + if ((caps.maxImageCount > 0) && (desired_swapchain_images > caps.maxImageCount)) + desired_swapchain_images = caps.maxImageCount; + + VkCompositeAlphaFlagBitsKHR composite_mode = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + if (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) + composite_mode = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + else if (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) + composite_mode = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; + else if (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) + composite_mode = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR; + else if (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) + composite_mode = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; + else + LOGW("No sensible composite mode supported?\n"); + + VkSwapchainKHR old_swapchain = swapchain; + + VkSwapchainCreateInfoKHR info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR }; + info.surface = surface; + info.pNext = surface_info.swapchain_pnext; + info.minImageCount = desired_swapchain_images; + info.imageFormat = surface_format.format; + info.imageColorSpace = surface_format.colorSpace; + info.imageExtent.width = swapchain_size.width; + info.imageExtent.height = swapchain_size.height; + info.imageArrayLayers = 1; + info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | current_extra_usage; + info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.preTransform = pre_transform; + info.compositeAlpha = composite_mode; + info.presentMode = surface_info.present_mode.presentMode; + info.clipped = VK_TRUE; + info.oldSwapchain = old_swapchain; + + // Defer the deletion instead. + if (device->get_device_features().swapchain_maintenance1_features.swapchainMaintenance1 && + old_swapchain != VK_NULL_HANDLE && !device->get_workarounds().broken_present_fence) + { + deferred_swapchains.push_back({ old_swapchain, last_present_fence }); + old_swapchain = VK_NULL_HANDLE; + } + + platform->event_swapchain_destroyed(); + + supports_present_timing.feedback = surface_info.present_timing.presentTimingSupported ? + surface_info.present_timing.presentStageQueries : 0; + + // Only ackknowledge present stages we understand in case there are future extensions. + supports_present_timing.feedback &= + VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT | + VK_PRESENT_STAGE_REQUEST_DEQUEUED_BIT_EXT | + VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT | + VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT; + + supports_present_timing.absolute = surface_info.present_timing.presentTimingSupported && + surface_info.present_timing.presentAtAbsoluteTimeSupported; + + supports_present_timing.relative = surface_info.present_timing.presentTimingSupported && + surface_info.present_timing.presentAtRelativeTimeSupported; + + if (supports_present_wait2) + info.flags |= VK_SWAPCHAIN_CREATE_PRESENT_ID_2_BIT_KHR | VK_SWAPCHAIN_CREATE_PRESENT_WAIT_2_BIT_KHR; + else + supports_present_timing.feedback = 0; + + if (supports_present_timing.feedback) + { + info.flags |= VK_SWAPCHAIN_CREATE_PRESENT_TIMING_BIT_EXT; + LOGI("Enabling present timing, queries #%x, absolute %u, relative %u.\n", + supports_present_timing.feedback, + supports_present_timing.absolute, + supports_present_timing.relative); + } + + auto res = table->vkCreateSwapchainKHR(context->get_device(), &info, nullptr, &swapchain); + if (res < 0) + swapchain = VK_NULL_HANDLE; + + if (res == VK_SUCCESS && supports_present_timing.feedback) + { + table->vkSetSwapchainPresentTimingQueueSizeEXT(context->get_device(), swapchain, PresentTimingQueueSize); + present_timing = {}; + update_present_timing_properties(); + update_time_domain_properties(); + recalibrate_present_timing_domains(); + } + + platform->destroy_swapchain_resources(old_swapchain); + table->vkDestroySwapchainKHR(context->get_device(), old_swapchain, nullptr); + has_acquired_swapchain_index = false; + next_present_id = 1; + present_last_id = 0; + device->set_present_id(VK_NULL_HANDLE, 0); + + if (res == VK_SUCCESS && device->get_device_features().supports_low_latency2_nv) + { + VkLatencySleepModeInfoNV sleep_mode_info = { VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV }; + sleep_mode_info.lowLatencyBoost = low_latency_mode_enable_gpu_submit; + sleep_mode_info.lowLatencyMode = low_latency_mode_enable_gpu_submit; + if (table->vkSetLatencySleepModeNV(context->get_device(), swapchain, &sleep_mode_info) != VK_SUCCESS) + LOGE("Failed to set low latency sleep mode.\n"); + } + + active_present_mode = info.presentMode; + present_mode_compat_group = std::move(surface_info.present_mode_compat_group); + +#ifdef _WIN32 + if (surface_info.exclusive_info.fullScreenExclusive == VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT) + { + bool success = vkAcquireFullScreenExclusiveModeEXT(context->get_device(), swapchain) == VK_SUCCESS; + if (success) + LOGI("Successfully acquired exclusive full-screen.\n"); + else + LOGI("Failed to acquire exclusive full-screen. Using borderless windowed.\n"); + } +#endif + + if (res != VK_SUCCESS) + { + LOGE("Failed to create swapchain (code: %d)\n", int(res)); + swapchain = VK_NULL_HANDLE; + return SwapchainError::Error; + } + + swapchain_width = swapchain_size.width; + swapchain_height = swapchain_size.height; + swapchain_surface_format = surface_format; + swapchain_is_suboptimal = false; + + LOGI("Created swapchain %u x %u (fmt: %u, transform: %u).\n", swapchain_width, swapchain_height, + unsigned(swapchain_surface_format.format), unsigned(swapchain_current_prerotate)); + + uint32_t image_count; + if (table->vkGetSwapchainImagesKHR(context->get_device(), swapchain, &image_count, nullptr) != VK_SUCCESS) + return SwapchainError::Error; + swapchain_images.resize(image_count); + release_semaphores.resize(image_count); + if (table->vkGetSwapchainImagesKHR(context->get_device(), swapchain, &image_count, swapchain_images.data()) != VK_SUCCESS) + return SwapchainError::Error; + + LOGI("Got %u swapchain images.\n", image_count); + + platform->event_swapchain_created(device.get(), swapchain, swapchain_width, swapchain_height, + swapchain_aspect_ratio, image_count, + swapchain_surface_format.format, + swapchain_surface_format.colorSpace, + swapchain_current_prerotate); + + if (swapchain_surface_format.colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT && + valid_hdr_metadata && device->get_device_features().supports_hdr_metadata) + { + table->vkSetHdrMetadataEXT(device->get_device(), 1, &swapchain, &hdr_metadata); + } + + return SwapchainError::None; +} + +void WSI::set_support_prerotate(bool enable) +{ + support_prerotate = enable; +} + +VkSurfaceTransformFlagBitsKHR WSI::get_current_prerotate() const +{ + return swapchain_current_prerotate; +} + +CommandBuffer::Type WSI::get_current_present_queue_type() const +{ + return device->get_current_present_queue_type(); +} + +WSI::~WSI() +{ + teardown(); +} + +void WSIPlatform::event_device_created(Device *) {} +void WSIPlatform::event_device_destroyed() {} +void WSIPlatform::event_swapchain_created(Device *, VkSwapchainKHR, unsigned, unsigned, float, size_t, + VkFormat, VkColorSpaceKHR, + VkSurfaceTransformFlagBitsKHR) {} +void WSIPlatform::event_swapchain_destroyed() {} +void WSIPlatform::destroy_swapchain_resources(VkSwapchainKHR) {} +void WSIPlatform::event_frame_tick(double, double) {} +void WSIPlatform::event_swapchain_index(Device *, unsigned) {} +void WSIPlatform::begin_drop_event() {} +void WSIPlatform::begin_soft_keyboard(const std::string &) {} +void WSIPlatform::end_soft_keyboard() {} +void WSIPlatform::show_message_box(const std::string &, Vulkan::WSIPlatform::MessageType) {} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi.hpp new file mode 100644 index 00000000..fecdc66a --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi.hpp @@ -0,0 +1,576 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "device.hpp" +#include "semaphore_manager.hpp" +#include "vulkan_headers.hpp" +#include "wsi_pacer.hpp" +#include "timer.hpp" +#include +#include +#include +#include + +#ifdef HAVE_WSI_DXGI_INTEROP +#include "wsi_dxgi.hpp" +#endif + +namespace Granite +{ +class InputTrackerHandler; +} + +namespace Vulkan +{ +class WSI; + +class WSIPlatform +{ +public: + virtual ~WSIPlatform() = default; + + virtual VkSurfaceKHR create_surface(VkInstance instance, VkPhysicalDevice gpu) = 0; + // This is virtual so that application can hold ownership over the surface handle, for e.g. Qt interop. + virtual void destroy_surface(VkInstance instance, VkSurfaceKHR surface); + virtual std::vector get_instance_extensions() = 0; + virtual std::vector get_device_extensions() + { + return { "VK_KHR_swapchain" }; + } + + virtual VkFormat get_preferred_format() + { + return VK_FORMAT_B8G8R8A8_SRGB; + } + + bool should_resize() + { + return resize; + } + + virtual void notify_current_swapchain_dimensions(unsigned width, unsigned height) + { + resize = false; + current_swapchain_width = width; + current_swapchain_height = height; + } + + virtual uint32_t get_surface_width() = 0; + virtual uint32_t get_surface_height() = 0; + + virtual float get_aspect_ratio() + { + return float(get_surface_width()) / float(get_surface_height()); + } + + virtual bool alive(WSI &wsi) = 0; + virtual void poll_input() = 0; + virtual void poll_input_async(Granite::InputTrackerHandler *handler) = 0; + virtual bool has_external_swapchain() + { + return false; + } + + virtual void block_until_wsi_forward_progress(WSI &wsi) + { + get_frame_timer().enter_idle(); + while (!resize && alive(wsi)) + { + poll_input(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + get_frame_timer().leave_idle(); + } + + Util::FrameTimer &get_frame_timer() + { + return timer; + } + + virtual void release_resources() + { + } + + virtual void event_device_created(Device *device); + virtual void event_device_destroyed(); + virtual void event_swapchain_created(Device *device, VkSwapchainKHR swapchain, + unsigned width, unsigned height, + float aspect_ratio, size_t num_swapchain_images, + VkFormat format, VkColorSpaceKHR color_space, + VkSurfaceTransformFlagBitsKHR pre_rotate); + virtual void destroy_swapchain_resources(VkSwapchainKHR swapchain); + virtual void event_swapchain_destroyed(); + virtual void event_frame_tick(double frame, double elapsed); + virtual void event_swapchain_index(Device *device, unsigned index); + + virtual void set_window_title(const std::string &title); + + virtual uintptr_t get_fullscreen_monitor(); + virtual uintptr_t get_native_window(); + + virtual const VkApplicationInfo *get_application_info(); + + virtual void begin_drop_event(); + virtual void begin_soft_keyboard(const std::string &initial); + virtual void end_soft_keyboard(); + + enum class MessageType { Error, Warning, Info }; + virtual void show_message_box(const std::string &str, MessageType type); + +protected: + unsigned current_swapchain_width = 0; + unsigned current_swapchain_height = 0; + bool resize = false; + +private: + Util::FrameTimer timer; +}; + +enum class PresentMode +{ + SyncToVBlank, // Force FIFO + UnlockedMaybeTear, // MAILBOX or IMMEDIATE + UnlockedForceTearing, // Force IMMEDIATE + UnlockedNoTearing // Force MAILBOX +}; + +enum class BackbufferFormat +{ + UNORM, + sRGB, + HDR10, + DisplayP3, + UNORMPassthrough, + scRGB, + Custom +}; + +struct PresentationStats +{ + // Correlate with WSI::get_last_submitted_present_id() + 1. + uint64_t feedback_present_id; + + // QUEUE_COMPLETE query. May be 0 if implementation does not support it. + // Application can trivially implement this on its own if needed. + uint64_t gpu_done_ts; + + // This is the latest stage that is reported. + uint64_t present_done_ts; + + // actual presented - intended target presentation. + // Intended target presentation may be adjusted internally, + // especially when emulating absolute over relative and vice versa. + int64_t error; +}; + +enum class RefreshMode { Unknown, FRR, VRR }; + +struct RefreshRateInfo +{ + RefreshMode mode; + uint64_t refresh_duration; + uint64_t refresh_interval; +}; + +class WSI +{ +public: + WSI(); + void set_platform(WSIPlatform *platform); + void set_present_mode(PresentMode mode); + void set_backbuffer_format(BackbufferFormat format); + // This is mostly for debug/development, ignores exposed formats and forces it. + void set_custom_backbuffer_format(VkSurfaceFormatKHR format); + + struct ImageCompression + { + VkImageCompressionFlagBitsEXT type = VK_IMAGE_COMPRESSION_DEFAULT_EXT; + VkImageCompressionFixedRateFlagsEXT fixed_rates = 0; + }; + void set_image_compression_control(const ImageCompression &compression); + + // Latency is normally pretty low, but this aims to target + // really low latency. Only suitable for cases where rendering loads are extremely simple. + void set_present_low_latency_mode(bool enable); + // Engages NV_low_latency2 / AMD_anti_lag, etc, which aim to reduce CPU <-> GPU submit delays. + void set_gpu_submit_low_latency_mode(bool enable); + + inline BackbufferFormat get_backbuffer_format() const + { + return backbuffer_format; + } + + inline VkColorSpaceKHR get_backbuffer_color_space() const + { + return swapchain_surface_format.colorSpace; + } + + void set_support_prerotate(bool enable); + void set_extra_usage_flags(VkImageUsageFlags usage); + VkSurfaceTransformFlagBitsKHR get_current_prerotate() const; + + inline PresentMode get_present_mode() const + { + return present_mode; + } + + // Deprecated, use set_backbuffer_format(). + void set_backbuffer_srgb(bool enable); + inline bool get_backbuffer_srgb() const + { + return backbuffer_format == BackbufferFormat::sRGB; + } + + void set_hdr_metadata(const VkHdrMetadataEXT &metadata); + inline const VkHdrMetadataEXT &get_hdr_metadata() const + { + return hdr_metadata; + } + + // First, we need a Util::IntrinsivePtr. + // This holds the instance and device. + + // The simple approach. WSI internally creates the context with instance + device. + // Required information about extensions etc, is pulled from the platform. + bool init_context_from_platform(unsigned num_thread_indices, const Context::SystemHandles &system_handles); + + // If you have your own VkInstance and/or VkDevice, you must create your own Vulkan::Context with + // the appropriate init() call. Based on the platform you use, you must make sure to enable the + // required extensions. + bool init_from_existing_context(ContextHandle context); + + // Then we initialize the Vulkan::Device. Either lets WSI create its own device or reuse an existing handle. + // A device provided here must have been bound to the context. + bool init_device(); + bool init_device(DeviceHandle device); + + // Called after we have a device and context. + // Either we can use a swapchain based on VkSurfaceKHR, or we can supply our own images + // to create a virtual swapchain. + // init_surface_swapchain() is called once. + // Here we create the surface and perform creation of the first swapchain. + bool init_surface_swapchain(); + bool init_external_swapchain(std::vector external_images); + + // Calls init_context_from_platform -> init_device -> init_surface_swapchain in succession. + bool init_simple(unsigned num_thread_indices, const Context::SystemHandles &system_handles); + + ~WSI(); + + inline Context &get_context() + { + return *context; + } + + inline Device &get_device() + { + return *device; + } + + // Acquires a frame from swapchain, also calls poll_input() after acquire + // since acquire tends to block. + bool begin_frame(); + // Presents and iterates frame context. + // Present is skipped if swapchain resource was not touched. + // The normal app loop is something like begin_frame() -> submit work -> end_frame(). + bool end_frame(); + + // Signals that the next present is merely a dupe (or generated) of a previous one, + // and that frame should not participate in present wait. + void set_next_present_is_duplicated(); + + // If true, and present wait is supported, the implementation will use more swapchain images than normal, + // and make it feasible to render duplicate frames without needlessly draining the GPU of work. + // This is mostly just a thing for an emulator which may be outputting at 30 unique FPS, but at 60 VI/s, + // meaning the same frames is duplicated. + // With a large enough image count, can feasibly be used for multi-frame-gen or similar shenanigans. + void set_frame_duplication_aware(bool enable, uint32_t target_swapchain_images = 5); + + // Overrides the present wait latency. + // 0 -> waits until last frame was presented before polling input. Hardest low-latency situation. + // Forced when low-latency present is enabled. + // 1 -> Normal ideal situation where we wait for previous frame's present to complete. + // Allows 1 frame worth of work for CPU to keep GPU fed properly. + // 2 -> Conservative, but useful when GPU bound to avoid pumping. Forced when using low gpu submit latency path. + void set_present_wait_latency(uint32_t latency); + + // For external swapchains we don't have a normal acquire -> present cycle. + // - set_external_frame() + // - index replaces the acquire next image index. + // - acquire_semaphore replaces semaphore from acquire next image. + // - frame_time controls the frame time passed down. + // - begin_frame() + // - submit work + // - end_frame() + // - consume_external_release_semaphore() + // - Returns the release semaphore that can passed to the equivalent of QueuePresentKHR. + void set_external_frame(unsigned index, Semaphore acquire_semaphore, double frame_time); + Semaphore consume_external_release_semaphore(); + + CommandBuffer::Type get_current_present_queue_type() const; + + // Equivalent to calling destructor. + void teardown(); + + WSIPlatform &get_platform() + { + VK_ASSERT(platform); + return *platform; + } + + // For Android. Used in response to APP_CMD_{INIT,TERM}_WINDOW once + // we have a proper swapchain going. + // We have to completely drain swapchain before the window is terminated on Android. + void deinit_surface_and_swapchain(); + void reinit_surface_and_swapchain(VkSurfaceKHR new_surface); + + void set_window_title(const std::string &title); + + double get_smooth_frame_time() const; + double get_smooth_elapsed_time() const; + + bool get_presentation_stats(PresentationStats &stats) const; + bool get_refresh_rate_info(RefreshRateInfo &info) const; + uint64_t get_last_submitted_present_id() const; + + // Absolute time is in terms of the Util::get_current_time_nsec() domain, + // i.e., time reported in presentation stats. + // + // For absolute time, the image must not be presented before the time given. + // For relative time, the time is intended to be abs_time = last_present + rel_time. + // + // If relative time is supported by implementation and relative_time_ns is not 0, + // absolute time requests are ignored. If absolute time is supported by implementation, + // a target absolute time will be computed based on absolute_time_ns and relative_time_ns. + // + // Rounding adjustments are allowed when the absolute time aligns closely + // with a refresh cycle, up to half a refresh cycle for FRR. For VRR, no adjustments are made. + // + // If this returns true, the request is expected to work as intended. + // If false, either it's unsupported, or we're not yet in a steady state where + // presentation timing reliably work (the first few frames after a swapchain is created may hit this). + // This state remains set until another request is made. + // For relative timings, this will work as expected as a method to set absolute target automatically, + // but absolute time obviously will not, since application is expected to set a new target time every frame. + // If force_vrr is true, the relative or absolute times are passed down with no bias. + bool set_target_presentation_time(uint64_t absolute_time_ns, uint64_t relative_time_ns, bool force_vrr); + void set_enable_timing_feedback(bool enable); + + FixedRefreshRatePacer &get_fixed_rate_pacer(); + void set_fixed_rate_low_latency_pacer(bool enable); + +private: + void update_framebuffer(unsigned width, unsigned height); + + ContextHandle context; + VkSurfaceKHR surface = VK_NULL_HANDLE; + VkSwapchainKHR swapchain = VK_NULL_HANDLE; + std::vector swapchain_images; + std::vector release_semaphores; + DeviceHandle device; + const VolkDeviceTable *table = nullptr; + FixedRefreshRatePacer frr_pacer; + bool frr_pacer_enable = false; + + unsigned swapchain_width = 0; + unsigned swapchain_height = 0; + float swapchain_aspect_ratio = 1.0f; + VkSurfaceFormatKHR swapchain_surface_format = { VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + PresentMode current_present_mode = PresentMode::SyncToVBlank; + PresentMode present_mode = PresentMode::SyncToVBlank; + bool low_latency_mode_enable_present = false; + bool low_latency_mode_enable_gpu_submit = false; + bool low_latency_anti_lag_present_valid = false; + + void emit_marker_pre_present(); + void emit_marker_post_present(); + void emit_end_of_frame_markers(); + + VkPresentModeKHR active_present_mode = VK_PRESENT_MODE_FIFO_KHR; + std::vector present_mode_compat_group; + bool update_active_presentation_mode(PresentMode mode); + + VkImageUsageFlags current_extra_usage = 0; + VkImageUsageFlags extra_usage = 0; + bool swapchain_is_suboptimal = false; + ImageCompression current_compression, compression; + + enum class SwapchainError + { + None, + NoSurface, + Error + }; + SwapchainError init_swapchain(unsigned width, unsigned height); + bool blocking_init_swapchain(unsigned width, unsigned height); + + uint32_t swapchain_index = 0; + bool has_acquired_swapchain_index = false; + + WSIPlatform *platform = nullptr; + + std::vector external_swapchain_images; + + unsigned external_frame_index = 0; + Semaphore external_acquire; + Semaphore external_release; + bool frame_is_external = false; + + BackbufferFormat backbuffer_format = BackbufferFormat::sRGB; + BackbufferFormat current_backbuffer_format = BackbufferFormat::sRGB; + VkSurfaceFormatKHR current_custom_backbuffer_format = {}; + VkSurfaceFormatKHR custom_backbuffer_format = {}; + + bool has_backbuffer_format_delta() const; + + bool support_prerotate = false; + VkSurfaceTransformFlagBitsKHR swapchain_current_prerotate = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + + bool begin_frame_external(); + double external_frame_time = 0.0; + + double smooth_frame_time = 0.0; + double smooth_elapsed_time = 0.0; + + uint64_t next_present_id = 1; + uint64_t present_last_id = 0; + unsigned present_frame_latency = 0; + bool supports_present_wait2 = false; + + struct + { + VkPresentStageFlagsEXT feedback; + bool absolute; + bool relative; + } supports_present_timing = {}; + + struct CalibratedTimestamp + { + uint64_t host_time; + uint64_t stage_times[4]; + }; + + struct ErrorStats + { + uint64_t present_id; + uint64_t target_absolute; + int64_t compensation; + }; + + struct + { + // Used for setting target time. + VkPresentStageFlagsEXT present_stage; + uint64_t reference_time; + VkTimeDomainKHR time_domain; + uint64_t time_domain_id; + + // Target + uint64_t target_absolute_time; + uint64_t target_relative_time; + uint64_t last_absolute_target_time; + bool force_vrr; + + // Feedback. + uint64_t gpu_done_host_time; + uint64_t present_done_host_time; + uint64_t present_id; + + // Display refresh rate information. + uint64_t refresh_duration; + uint64_t refresh_interval; + uint64_t refresh_counter; + bool has_refresh_feedback; + RefreshMode refresh_mode = RefreshMode::Unknown; + + // Calibration information. + uint64_t time_domain_counter; + bool has_time_domain_props; + Util::SmallVector time_domains; + Util::SmallVector time_domain_ids; + Util::SmallVector calibration; + + bool need_recalibration; + int64_t last_recalibration_time; + + int64_t presentation_time_error; + int64_t pending_compensation; + Util::SmallVector error_stats; + } present_timing = {}; + + bool present_feedback_enable = false; + + void update_present_timing_properties(); + void poll_present_timing_feedback(); + void recalibrate_present_timing_domains(); + void update_time_domain_properties(); + void set_present_timing_request(VkPresentTimingInfoEXT &timing); + + Semaphore low_latency_semaphore; + uint64_t low_latency_semaphore_value = 0; + + bool next_present_is_dupe = false; + bool frame_dupe_aware = false; + bool current_frame_dupe_aware = false; + unsigned frame_dupe_target_images = 5; + unsigned current_frame_dupe_target_images = 5; + unsigned duplicated_frames = 0; + unsigned last_duplicated_frames = 0; + + void tear_down_swapchain(); + void drain_swapchain(bool in_tear_down); + void wait_swapchain_latency(); + + VkHdrMetadataEXT hdr_metadata = { VK_STRUCTURE_TYPE_HDR_METADATA_EXT }; + bool valid_hdr_metadata = false; + + struct DeferredDeletionSwapchain + { + VkSwapchainKHR swapchain; + Fence fence; + }; + + struct DeferredDeletionSemaphore + { + Semaphore semaphore; + Fence fence; + }; + + Util::SmallVector deferred_swapchains; + Util::SmallVector deferred_semaphore; + Vulkan::Fence last_present_fence; + void nonblock_delete_swapchain_resources(); + + VkSurfaceFormatKHR find_suitable_present_format(const std::vector &formats, BackbufferFormat desired_format) const; + + VkResult wait_for_present(uint64_t id, uint64_t timeout = UINT64_MAX); + +#ifdef HAVE_WSI_DXGI_INTEROP + std::unique_ptr dxgi; + bool init_surface_swapchain_dxgi(unsigned width, unsigned height); + bool begin_frame_dxgi(); + bool end_frame_dxgi(); +#endif +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_dxgi.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_dxgi.cpp new file mode 100644 index 00000000..fb734062 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_dxgi.cpp @@ -0,0 +1,519 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "wsi_dxgi.hpp" +#include + +namespace Vulkan +{ +DXGIInteropSwapchain::~DXGIInteropSwapchain() +{ + // Wait-for-idle before teardown. + if (fence) + fence->SetEventOnCompletion(fence_value, nullptr); + if (latency_handle) + CloseHandle(latency_handle); +} + +static bool is_running_on_wine() +{ + // If we're running in Wine for whatever reason, interop like this is completely useless. + HMODULE ntdll = GetModuleHandleA("ntdll.dll"); + return !ntdll || GetProcAddress(ntdll, "wine_get_version"); +} + +static bool is_running_in_tool(Device &device) +{ + auto &ext = device.get_device_features(); + if (ext.supports_tooling_info && vkGetPhysicalDeviceToolPropertiesEXT) + { + auto gpu = device.get_physical_device(); + uint32_t count = 0; + vkGetPhysicalDeviceToolPropertiesEXT(gpu, &count, nullptr); + Util::SmallVector tool_props(count); + for (auto &t : tool_props) + t = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT }; + vkGetPhysicalDeviceToolPropertiesEXT(gpu, &count, tool_props.data()); + + // It's okay for validation to not force this path. We're mostly concerned with RenderDoc, RGP and Nsight. + for (auto &t : tool_props) + if (t.purposes & (VK_TOOL_PURPOSE_PROFILING_BIT | VK_TOOL_PURPOSE_TRACING_BIT)) + return true; + } + + return false; +} + +bool DXGIInteropSwapchain::init_interop_device(Device &vk_device_) +{ + vk_device = &vk_device_; + + // If we're running in Wine for whatever reason, interop like this is more harmful than good. + if (is_running_on_wine()) + return false; + + // If we're running in some capture tool, we need to use Vulkan WSI to avoid confusing it. + if (is_running_in_tool(*vk_device)) + return false; + + if (!vk_device->get_device_features().vk11_props.deviceLUIDValid) + return false; + + d3d12_lib = Util::DynamicLibrary("d3d12.dll"); + dxgi_lib = Util::DynamicLibrary("dxgi.dll"); + + if (!d3d12_lib) + { + LOGE("Failed to find d3d12.dll. Ignoring interop device.\n"); + return false; + } + + if (!dxgi_lib) + { + LOGE("Failed to find dxgi.dll. Ignoring interop device.\n"); + return false; + } + + auto pfn_CreateDXGIFactory1 = + dxgi_lib.get_symbol("CreateDXGIFactory1"); + auto pfn_D3D12CreateDevice = + d3d12_lib.get_symbol("D3D12CreateDevice"); + + if (!pfn_CreateDXGIFactory1 || !pfn_D3D12CreateDevice) + { + LOGE("Failed to find entry points.\n"); + return false; + } + + HRESULT hr; + if (FAILED(hr = pfn_CreateDXGIFactory1(IID_PPV_ARGS(&dxgi_factory)))) + { + LOGE("Failed to create DXGI factory, hr #%x.\n", unsigned(hr)); + return false; + } + + LUID luid = {}; + ComPtr adapter; + memcpy(&luid, vk_device->get_device_features().vk11_props.deviceLUID, VK_LUID_SIZE); + if (FAILED(hr = dxgi_factory->EnumAdapterByLuid(luid, IID_PPV_ARGS(&adapter)))) + { + LOGE("Failed to enumerate DXGI adapter by LUID.\n"); + return false; + } + + if (FAILED(hr = pfn_D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device)))) + { + LOGE("Failed to create D3D12Device, hr #%x.\n", unsigned(hr)); + return false; + } + + D3D12_COMMAND_QUEUE_DESC queue_desc = {}; + queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + if (FAILED(hr = device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&queue)))) + { + LOGE("Failed to create command queue, hr #%x.\n", unsigned(hr)); + return false; + } + + if (FAILED(hr = device->CreateCommandList1( + 0, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_LIST_FLAG_NONE, IID_PPV_ARGS(&list)))) + { + LOGE("Failed to create command list, hr #%x.\n", unsigned(hr)); + return false; + } + + if (FAILED(hr = device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&fence)))) + { + LOGE("Failed to create shared fence, hr #%x.\n", unsigned(hr)); + return false; + } + + // Import D3D12 timeline into Vulkan. + // Other way around is not as well-supported. + vk_fence = vk_device->request_semaphore_external( + VK_SEMAPHORE_TYPE_TIMELINE, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT); + if (!vk_fence) + { + LOGE("Failed to create timeline.\n"); + return EXIT_FAILURE; + } + + ExternalHandle fence_handle; + fence_handle.semaphore_handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT; + if (FAILED(device->CreateSharedHandle(fence.Get(), nullptr, + GENERIC_ALL, nullptr, &fence_handle.handle))) + { + LOGE("Failed to create shared fence handle.\n"); + return EXIT_FAILURE; + } + + if (!vk_fence->import_from_handle(fence_handle)) + { + LOGE("Failed to import timeline.\n"); + CloseHandle(fence_handle.handle); + return false; + } + + return true; +} + +VkImage DXGIInteropSwapchain::get_vulkan_image() const +{ + return vulkan_backbuffer->get_image(); +} + +static DXGI_FORMAT convert_vk_format(VkFormat fmt) +{ + switch (fmt) + { + case VK_FORMAT_R8G8B8A8_UNORM: + case VK_FORMAT_R8G8B8A8_SRGB: + // D3D12 fails to create SRGB swapchain for some reason. + // We'll import the memory as sRGB however, and it works fine ... + return DXGI_FORMAT_R8G8B8A8_UNORM; + case VK_FORMAT_B8G8R8A8_UNORM: + case VK_FORMAT_B8G8R8A8_SRGB: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case VK_FORMAT_A2B10G10R10_UNORM_PACK32: + return DXGI_FORMAT_R10G10B10A2_UNORM; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + default: + return DXGI_FORMAT_UNKNOWN; + } +} + +static DXGI_COLOR_SPACE_TYPE convert_vk_color_space(VkColorSpaceKHR colspace) +{ + switch (colspace) + { + case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT: + return DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709; + case VK_COLOR_SPACE_HDR10_ST2084_EXT: + return DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; + case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR: + return DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + default: + return DXGI_COLOR_SPACE_RESERVED; + } +} + +void DXGIInteropSwapchain::reset_backbuffer_state() +{ + for (auto &buf : backbuffers) + if (fence) + fence->SetEventOnCompletion(buf.wait_fence_value, nullptr); + backbuffers.clear(); +} + +bool DXGIInteropSwapchain::setup_per_frame_state(PerFrameState &state, unsigned index) +{ + HRESULT hr; + if (FAILED(hr = swapchain->GetBuffer(index, IID_PPV_ARGS(&state.backbuffer)))) + { + LOGE("Failed to get backbuffer, hr #%x.\n", unsigned(hr)); + return false; + } + + if (FAILED(hr = device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&state.allocator)))) + { + LOGE("Failed to create command allocator, hr #%x.\n", unsigned(hr)); + return false; + } + + return true; +} + +bool DXGIInteropSwapchain::init_swapchain(HWND hwnd_, VkSurfaceFormatKHR format, + unsigned width, unsigned height, unsigned count) +{ + if (hwnd && hwnd_ != hwnd) + { + reset_backbuffer_state(); + swapchain.Reset(); + } + + hwnd = hwnd_; + + DXGI_SWAP_CHAIN_DESC1 desc = {}; + desc.Width = width; + desc.Height = height; + desc.BufferCount = count; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + desc.SampleDesc.Count = 1; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.Format = convert_vk_format(format.format); + if (!desc.Format) + return false; + + auto color_space = convert_vk_color_space(format.colorSpace); + if (color_space == DXGI_COLOR_SPACE_RESERVED) + return false; + + BOOL allow_tear = FALSE; + if (SUCCEEDED(dxgi_factory->CheckFeatureSupport( + DXGI_FEATURE_PRESENT_ALLOW_TEARING, + &allow_tear, sizeof(allow_tear)) && allow_tear)) + { + desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + allow_tearing = true; + } + desc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + + ComPtr swap; + HRESULT hr; + + reset_backbuffer_state(); + + // If we already have a swapchain we can just use ResizeBuffers. + if (!swapchain) + { + if (FAILED(hr = dxgi_factory->CreateSwapChainForHwnd( + queue.Get(), hwnd, &desc, nullptr, nullptr, &swap))) + { + LOGE("Failed to create swapchain, hr #%x.\n", unsigned(hr)); + return false; + } + + completed_presents = 0; + completed_waits = 0; + + if (FAILED(swap.As(&swapchain))) + { + LOGE("Failed to query swapchain interface.\n"); + return false; + } + + if (latency_handle) + CloseHandle(latency_handle); + latency_handle = swapchain->GetFrameLatencyWaitableObject(); + + if (!latency_handle) + { + LOGE("Failed to query latency handle.\n"); + return false; + } + + // Drop semaphore to 0 right away to make code less awkward later. + if (WaitForSingleObject(latency_handle, INFINITE) != WAIT_OBJECT_0) + { + LOGE("Failed to wait for latency object.\n"); + return false; + } + } + else + { + if (FAILED(hr = swapchain->ResizeBuffers(count, width, height, desc.Format, desc.Flags))) + { + LOGE("Failed to resize buffers, hr #%x.\n", unsigned(hr)); + return false; + } + } + + if (FAILED(dxgi_factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_WINDOW_CHANGES))) + { + LOGE("Failed to make window association.\n"); + return false; + } + + surface_format = format; + + UINT space_support = 0; + if (FAILED(swapchain->CheckColorSpaceSupport(color_space, &space_support)) || + ((space_support & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) == 0)) + { + // Fallback to SDR if HDR doesn't pass check. + if (FAILED(swapchain->CheckColorSpaceSupport(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, &space_support)) || + ((space_support & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) == 0)) + { + return false; + } + + LOGW("HDR10 not supported by DXGI swapchain, falling back to SDR.\n"); + surface_format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + color_space = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + } + + if (FAILED(swapchain->SetColorSpace1(color_space))) + { + LOGE("Failed to set color space.\n"); + return false; + } + + backbuffers.resize(desc.BufferCount); + for (unsigned i = 0; i < desc.BufferCount; i++) + if (!setup_per_frame_state(backbuffers[i], i)) + return false; + + ExternalHandle imported_image; + imported_image.memory_handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT; + + D3D12_RESOURCE_DESC blit_desc = {}; + blit_desc.Width = width; + blit_desc.Height = height; + blit_desc.Format = desc.Format; + blit_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + blit_desc.SampleDesc.Count = 1; + blit_desc.DepthOrArraySize = 1; + blit_desc.MipLevels = 1; + blit_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + blit_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + + D3D12_HEAP_PROPERTIES heap_props = {}; + heap_props.Type = D3D12_HEAP_TYPE_DEFAULT; + + blit_backbuffer.Reset(); + if (FAILED(hr = device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_SHARED, &blit_desc, + D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&blit_backbuffer)))) + { + LOGE("Failed to create blit render target, hr #%x.\n", unsigned(hr)); + return false; + } + + if (FAILED(hr = device->CreateSharedHandle(blit_backbuffer.Get(), nullptr, GENERIC_ALL, nullptr, + &imported_image.handle))) + { + LOGE("Failed to create shared handle, hr #%x.\n", unsigned(hr)); + return false; + } + + auto image_info = ImageCreateInfo::render_target(width, height, format.format); + image_info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + image_info.misc = IMAGE_MISC_EXTERNAL_MEMORY_BIT; + image_info.external = imported_image; + + vulkan_backbuffer = vk_device->create_image(image_info); + if (!vulkan_backbuffer) + { + LOGE("Failed to create shared Vulkan image, hr #%x.\n", unsigned(hr)); + return false; + } + vulkan_backbuffer->set_swapchain_layout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + + return true; +} + +VkSurfaceFormatKHR DXGIInteropSwapchain::get_current_surface_format() const +{ + return surface_format; +} + +bool DXGIInteropSwapchain::wait_latency(unsigned latency_frames) +{ + uint64_t target_wait_count = completed_presents - latency_frames; + + if (latency_handle && (target_wait_count & (1ull << 63)) == 0) + { + while (completed_waits < target_wait_count) + { + if (WaitForSingleObject(latency_handle, INFINITE) != WAIT_OBJECT_0) + { + LOGE("Failed to wait for latency object.\n"); + return false; + } + completed_waits++; + } + } + + return true; +} + +bool DXGIInteropSwapchain::acquire(Semaphore &acquire_semaphore) +{ + // AMD workaround. Driver freaks out if trying to wait for D3D12 timeline value of 0. + queue->Signal(fence.Get(), ++fence_value); + + acquire_semaphore = vk_device->request_timeline_semaphore_as_binary(*vk_fence, fence_value); + return true; +} + +bool DXGIInteropSwapchain::present(Vulkan::Semaphore release_semaphore, bool vsync) +{ + unsigned index = swapchain->GetCurrentBackBufferIndex(); + auto &per_frame = backbuffers[index]; + + vk_device->add_wait_semaphore(CommandBuffer::Type::Generic, std::move(release_semaphore), + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, true); + + auto cmd = vk_device->request_command_buffer(); + cmd->release_image_barrier(*vulkan_backbuffer, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0); + + vk_device->submit(cmd); + auto timeline_signal = vk_device->request_timeline_semaphore_as_binary(*vk_fence, ++fence_value); + vk_device->submit_empty(CommandBuffer::Type::Generic, nullptr, timeline_signal.get()); + queue->Wait(fence.Get(), fence_value); + + fence->SetEventOnCompletion(per_frame.wait_fence_value, nullptr); + + if (FAILED(per_frame.allocator->Reset())) + { + LOGE("Failed to reset command allocator.\n"); + return false; + } + + list->Reset(per_frame.allocator.Get(), nullptr); + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.pResource = per_frame.backbuffer.Get(); + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; + list->ResourceBarrier(1, &barrier); + + D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {}; + dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dst.pResource = per_frame.backbuffer.Get(); + src.pResource = blit_backbuffer.Get(); + list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr); + + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + list->ResourceBarrier(1, &barrier); + + if (FAILED(list->Close())) + { + LOGE("Failed to close command list.\n"); + return false; + } + + ID3D12CommandList *cmdlist = list.Get(); + queue->ExecuteCommandLists(1, &cmdlist); + queue->Signal(fence.Get(), ++fence_value); + per_frame.wait_fence_value = fence_value; + + HRESULT hr = swapchain->Present(vsync ? 1 : 0, !vsync && allow_tearing ? DXGI_PRESENT_ALLOW_TEARING : 0); + if (FAILED(hr)) + { + LOGE("Failed to present, hr #%x.\n", unsigned(hr)); + return false; + } + + completed_presents++; + return true; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_dxgi.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_dxgi.hpp new file mode 100644 index 00000000..b9f1a93f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_dxgi.hpp @@ -0,0 +1,84 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once + +#include "device.hpp" +#include "image.hpp" +#include "d3d12.h" +#include "dxgi1_6.h" +#include "small_vector.hpp" +#include "dynamic_library.hpp" +#include + +namespace Vulkan +{ +template +using ComPtr = Microsoft::WRL::ComPtr; + +class DXGIInteropSwapchain +{ +public: + bool init_interop_device(Device &device); + ~DXGIInteropSwapchain(); + + bool init_swapchain(HWND hwnd, VkSurfaceFormatKHR format, unsigned width, unsigned height, unsigned count); + VkImage get_vulkan_image() const; + VkSurfaceFormatKHR get_current_surface_format() const; + + bool acquire(Semaphore &acquire_semaphore); + bool present(Semaphore release_semaphore, bool vsync); + bool wait_latency(unsigned latency_frames); + +private: + Device *vk_device = nullptr; + Util::DynamicLibrary d3d12_lib, dxgi_lib; + HWND hwnd = nullptr; + HANDLE latency_handle = nullptr; + ComPtr device; + ComPtr queue; + ComPtr dxgi_factory; + ComPtr swapchain; + ComPtr list; + ComPtr fence; + Semaphore vk_fence; + uint64_t fence_value = 0; + VkSurfaceFormatKHR surface_format = {}; + bool allow_tearing = false; + + struct PerFrameState + { + ComPtr allocator; + ComPtr backbuffer; + uint64_t wait_fence_value = 0; + }; + Util::SmallVector backbuffers; + ComPtr blit_backbuffer; + ImageHandle vulkan_backbuffer; + + bool setup_per_frame_state(PerFrameState &state, unsigned index); + void reset_backbuffer_state(); + + uint64_t completed_presents = 0; + uint64_t completed_waits = 0; +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_pacer.cpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_pacer.cpp new file mode 100644 index 00000000..beecc5cf --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_pacer.cpp @@ -0,0 +1,324 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen + * + * 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. + */ + +#include "wsi_pacer.hpp" +#include "timer.hpp" + +FixedRefreshRatePacer::FixedRefreshRatePacer() +{ + reset(); +} + +FixedRefreshRatePacer::~FixedRefreshRatePacer() +{ +#if 0 + for (int i = 0; i < NumHistogramEntries; i++) + { + LOGI("Success rate: band [%.3f ms - %.3f ms] -> %.3f %% (last failure %llu) (overall %llu failures)\n", double(i * GapQuantumNS) * 1e-6, + double((i + 1) * GapQuantumNS) * 1e-6, histogram[i].confidence * 100.0, + static_cast(histogram[i].last_failure_present_id), + static_cast(histogram[i].num_relevant_present_failures)); + } +#endif +} + +void FixedRefreshRatePacer::reset() +{ + feedbacks.clear(); + last_feedback = {}; + frame_time_ns = 0; + estimated_present_gap_ns = UINT64_MAX; + estimated_frame_latency_ns = UINT64_MAX; + for (auto &entry : histogram) + entry = {}; + overall = {}; + minimum_confidence_for_promotion = 0.0; +} + +void FixedRefreshRatePacer::discard_pacing_statistics(uint64_t present_id) +{ + find_and_remove_feedback(present_id); +} + +FixedRefreshRatePacer::Feedback FixedRefreshRatePacer::find_and_remove_feedback(uint64_t present_id) +{ + auto itr = std::find_if(feedbacks.begin(), feedbacks.end(), [=](const Feedback &f) + { + return f.present_id == present_id; + }); + + if (itr == feedbacks.end()) + return {}; + + auto ret = *itr; + feedbacks.erase(itr); + return ret; +} + +void FixedRefreshRatePacer::set_frame_time_ns(uint64_t frame_time) +{ + frame_time_ns = frame_time; + + // Dynamically adjust as we get completed frames coming in. + estimated_present_gap_ns = std::min(frame_time_ns / 2, estimated_present_gap_ns); + + // Stay in the center of the histogram range to avoid annoying rounding errors when quantizing results + // to histogram. + estimated_present_gap_ns = (estimated_present_gap_ns / GapQuantumNS) * GapQuantumNS + (GapQuantumNS / 2); +} + +void FixedRefreshRatePacer::override_gpu_done_time(uint64_t present_id, uint64_t queue_done_ns) +{ + auto itr = + std::find_if(feedbacks.begin(), feedbacks.end(), [=](const Feedback &f) { return f.present_id == present_id; }); + if (itr != feedbacks.end()) + itr->queue_done_ns = queue_done_ns; +} + +void FixedRefreshRatePacer::update_feedback(uint64_t present_id, uint64_t queue_done_ns, uint64_t complete_ns) +{ + auto feedback = find_and_remove_feedback(present_id); + + if (feedback.queue_done_ns) + queue_done_ns = feedback.queue_done_ns; + + last_feedback.present_id = present_id; + last_feedback.queue_done_ns = queue_done_ns; + last_feedback.complete_ns = complete_ns; + + if (feedback.present_id != present_id) + return; + + // Safety. + queue_done_ns = std::min(queue_done_ns, complete_ns); + + // The present happened when we expected it to. If it falls meaningfully outside of this, we have VRR + // and a FRR pacer isn't super useful to begin with. + if (complete_ns <= feedback.estimated_complete_ns + frame_time_ns / 8) + { + // With an ideal setup queue_done_ns can be arbitrarily close to complete_ns before we start dropping frames, + // but that's not realistic. + uint64_t present_gap_ns = complete_ns - queue_done_ns; + + if (estimated_present_gap_ns == UINT64_MAX) + { + // Initialize the estimate. + estimated_present_gap_ns = frame_time_ns / 2; + } + + register_present_gap(present_id, present_gap_ns, true); + + if (present_gap_ns <= estimated_present_gap_ns) + { + // The compositor was able to deal with current tight timings, update our estimate accordingly (slowly). + uint64_t candidate_ns = std::max(estimated_present_gap_ns, GapQuantumNS) - GapQuantumNS; + + // Only lower if history shows this to be a sound decision. + if (safe_to_lower_gap_to(present_id, present_gap_ns, candidate_ns)) + estimated_present_gap_ns = candidate_ns; + } + } + else if (complete_ns > feedback.estimated_complete_ns + frame_time_ns / 2 && + queue_done_ns < feedback.estimated_complete_ns) + { + // The GPU was done in time, but we dropped a frame regardless. + // Likely the compositor has a queueing delay we need to consider. + + estimated_present_gap_ns += GapQuantumNS; + uint64_t potential_present_gap_ns = feedback.estimated_complete_ns - queue_done_ns; + + // If the present gap is over half a frame, it's likely the compositor just derping out for no good reason. + if (potential_present_gap_ns < frame_time_ns / 2) + { + // We have a potential present gap that failed to flip properly. + register_present_gap(present_id, potential_present_gap_ns, false); + } + } + + // Otherwise the GPU was simply too slow to render. + // The frame latency will have to increase as expected. + + uint64_t frame_latency_ns = std::max(feedback.frame_submission_ns, queue_done_ns) - + feedback.frame_submission_ns; + + // Keep a running estimate of how long time it takes to process CPU -> GPU. + // This will inform sleep targets. + if (estimated_frame_latency_ns != UINT64_MAX) + estimated_frame_latency_ns = (estimated_frame_latency_ns * 15 + frame_latency_ns) / 16; + else + estimated_frame_latency_ns = frame_latency_ns; +} + +void FixedRefreshRatePacer::register_present_gap(uint64_t present_id, uint64_t gap_ns, bool success) +{ + if (!success) + { + overall.confidence *= 0.5; + overall.last_failure_present_id = present_id; + overall.num_relevant_present_failures++; + } + else + { + // This estimate should move very slowly. + overall.confidence = overall.confidence * 0.99 + 0.01; + if (overall.confidence > 0.9999999) + { + if (overall.num_relevant_present_failures) + { + // If we're resetting, put a higher bar of confidence if we want to promote so + // that we don't instantly start to see failures. + minimum_confidence_for_promotion = 0.7499 + minimum_confidence_for_promotion * 0.25; + } + + overall.num_relevant_present_failures = 0; + } + } + + int index = int(gap_ns / GapQuantumNS); + if (index >= NumHistogramEntries) + return; + + auto &entry = histogram[index]; + + if (!success) + { + // Avoid denorm hell, but also reset the counter if we cannot get reliable successes multiple times in a row. + if (entry.confidence < 0.25) + entry.confidence = 0.0; + entry.confidence = entry.confidence * 0.5; + entry.last_failure_present_id = present_id; + entry.num_relevant_present_failures++; + } + else + { + // This gap seems super stable now. + entry.confidence = entry.confidence * 0.95 + 0.05; + if (entry.confidence > 0.999999) + entry.num_relevant_present_failures = 0; + } +} + +FixedRefreshRatePacer::HistogramStats FixedRefreshRatePacer::get_current_histogram_stats() const +{ + if (estimated_present_gap_ns == UINT64_MAX) + return {}; + + int index = int(estimated_present_gap_ns / GapQuantumNS); + if (index >= NumHistogramEntries) + return {}; + return histogram[index]; +} + +double FixedRefreshRatePacer::get_minimum_confidence_for_promotion() const +{ + return minimum_confidence_for_promotion; +} + +FixedRefreshRatePacer::HistogramStats FixedRefreshRatePacer::get_candidate_histogram_stats() const +{ + if (estimated_present_gap_ns == UINT64_MAX) + return {}; + + int index = int(estimated_present_gap_ns / GapQuantumNS) - 1; + if (index >= NumHistogramEntries || index < 0) + return {}; + return histogram[index]; +} + +FixedRefreshRatePacer::HistogramStats FixedRefreshRatePacer::get_overall_histogram_stats() const +{ + return overall; +} + +uint64_t FixedRefreshRatePacer::get_estimated_present_gap_ns() const +{ + return estimated_present_gap_ns; +} + +uint64_t FixedRefreshRatePacer::get_estimated_cpu_gpu_idle_latency_ns() const +{ + return estimated_frame_latency_ns; +} + +bool FixedRefreshRatePacer::safe_to_lower_gap_to(uint64_t present_id, uint64_t observed_gap_ns, uint64_t to_ns) const +{ + // If we can prove some safety of the target gap, go for it. + int to_index = int(to_ns / GapQuantumNS); + int from_index = int(observed_gap_ns / GapQuantumNS); + if (to_index >= NumHistogramEntries || from_index >= NumHistogramEntries) + return true; + + // Don't lower until overall success probability is solid. + uint64_t frames_since_last_observed_failure = present_id - overall.last_failure_present_id; + auto num_failures = std::min(16, overall.num_relevant_present_failures); + if (frames_since_last_observed_failure < (1u << num_failures)) + return false; + + // We're confident the update will work well. + if (histogram[to_index].confidence >= 0.999) + return true; + + // The bar to clear is higher now. If we never saw any failures, go ahead, we need to learn. + if (histogram[to_index].confidence < minimum_confidence_for_promotion && + histogram[to_index].num_relevant_present_failures != 0) + return false; + + // We haven't proved this rate is solid. + if (histogram[from_index].confidence < 0.999) + return false; + + // We've never observed a failure at this gap before, should be good to test until we observe failures. + if (histogram[to_index].last_failure_present_id == 0) + return true; + + // Check statistics per histogram. + frames_since_last_observed_failure = present_id - histogram[to_index].last_failure_present_id; + + // Backoff algorithm which scales the number of safety frames based on failures observed overall. + // Eventually, we have enough failures that we never trust it blindly. + num_failures = std::min(16, histogram[to_index].num_relevant_present_failures); + return frames_since_last_observed_failure >= (60u << num_failures); +} + +void FixedRefreshRatePacer::begin_frame_submission(uint64_t current_present_id) +{ + if (last_feedback.present_id == 0 || frame_time_ns == 0) + return; + + uint64_t estimated_complete_ns = + (current_present_id - last_feedback.present_id) * frame_time_ns + + last_feedback.complete_ns; + + if (estimated_present_gap_ns != UINT64_MAX) + { + uint64_t target_gap_ns = estimated_present_gap_ns; + target_gap_ns += estimated_frame_latency_ns; + int64_t sleep_target_ns = int64_t(estimated_complete_ns) - int64_t(target_gap_ns); + Util::sleep_until_nsecs(sleep_target_ns); + } + + // Safety clear in case it's never polled. + if (feedbacks.size() > 16) + feedbacks.clear(); + + feedbacks.push_back({ current_present_id, uint64_t(Util::get_current_time_nsecs()), estimated_complete_ns }); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_pacer.hpp b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_pacer.hpp new file mode 100644 index 00000000..353b9cf7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/Granite/vulkan/wsi_pacer.hpp @@ -0,0 +1,92 @@ +/* Copyright (c) 2017-2026 Hans-Kristian Arntzen +* + * 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. + */ + +#pragma once + +#include "small_vector.hpp" +#include + +// Designed for lowest possible latency on fixed rate displays. +// The GPU workload is expected to be very light and stable (e.g. video decoding). +class FixedRefreshRatePacer +{ +public: + FixedRefreshRatePacer(); + ~FixedRefreshRatePacer(); + + void set_frame_time_ns(uint64_t frame_time); + void update_feedback(uint64_t present_id, uint64_t queue_done_ns, uint64_t complete_ns); + + // Sleeps as needed. Should be called before sampling inputs, etc. + void begin_frame_submission(uint64_t current_present_id); + + // This frame will not be valid for purposes of statistics. + void discard_pacing_statistics(uint64_t present_id); + + // Can avoid some weird interactions with async compute and such. + void override_gpu_done_time(uint64_t present_id, uint64_t queue_done_ns); + + void reset(); + + struct HistogramStats + { + double confidence = 0.0; + uint64_t last_failure_present_id = 0; + uint64_t num_relevant_present_failures = 0; + }; + + // Debugging. + HistogramStats get_current_histogram_stats() const; + HistogramStats get_candidate_histogram_stats() const; + HistogramStats get_overall_histogram_stats() const; + uint64_t get_estimated_present_gap_ns() const; + uint64_t get_estimated_cpu_gpu_idle_latency_ns() const; + double get_minimum_confidence_for_promotion() const; + +private: + uint64_t frame_time_ns = 0; + uint64_t estimated_present_gap_ns = UINT64_MAX; + uint64_t estimated_frame_latency_ns = UINT64_MAX; + double minimum_confidence_for_promotion = 0.0; + + struct Feedback + { + uint64_t present_id; + uint64_t frame_submission_ns; + uint64_t estimated_complete_ns; + uint64_t queue_done_ns; + uint64_t complete_ns; + }; + + Util::SmallVector feedbacks; + Feedback last_feedback = {}; + Feedback find_and_remove_feedback(uint64_t present_id); + + // Don't make the quant interval too narrow, or we won't be able capture statistics well. + enum { GapQuantumNS = 250 * 1000, NumHistogramEntries = 64 }; + + HistogramStats histogram[NumHistogramEntries]; + HistogramStats overall; + + void register_present_gap(uint64_t present_id, uint64_t gap_ns, bool success); + bool safe_to_lower_gap_to(uint64_t present_id, uint64_t observed_gap_ns, uint64_t to_ns) const; +}; diff --git a/crates/pyrowave-sys/vendor/pyrowave/LICENSE b/crates/pyrowave-sys/vendor/pyrowave/LICENSE new file mode 100644 index 00000000..3392479d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2025 Hans-Kristian Arntzen + +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. diff --git a/crates/pyrowave-sys/vendor/pyrowave/PUNKTFUNK-VENDOR.txt b/crates/pyrowave-sys/vendor/pyrowave/PUNKTFUNK-VENDOR.txt new file mode 100644 index 00000000..c7dd7b94 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/PUNKTFUNK-VENDOR.txt @@ -0,0 +1,10 @@ +Vendored by scripts/vendor-pyrowave.sh — do not edit by hand. + +pyrowave: 509e4f887b585a3f97471fcc804e9de649f2c16f +Granite: 44362775d36e0c4139352f83efd96bab4e239f66 +volk: 47cddf7ed97b94118a08aacb548a411188e016cc +vulkan-headers: 015e25c3c91b70eb1a754d36fb14c4ba6ad9b0b9 + +Tree is pruned to what the pyrowave-sys standalone build needs +(see the rm -rf list in the script). All parts are MIT-licensed +(pyrowave, Granite) or Apache-2.0/MIT (volk, Vulkan-Headers). diff --git a/crates/pyrowave-sys/vendor/pyrowave/README.md b/crates/pyrowave-sys/vendor/pyrowave/README.md new file mode 100644 index 00000000..51da0665 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/README.md @@ -0,0 +1,113 @@ +# PyroWave + +PyroWave is an intra-only video codec (practially speaking a still-image codec) +that is optimized for extremely fast GPU encode (< ~0.1 ms encode and decode at 1080p, < ~0.2 ms at 4K). +It is fully implemented in Vulkan compute shaders. + +The targeted bit-rates are quite high (~200+ mbit/s) and the intended use case is +local network game streaming over ethernet with absolute minimum latency where bandwidth is less of a concern. + +It is integrated as part of my [pyrofling](https://github.com/Themaister/pyrofling) project. + +It is similar in scope to my [master thesis from 2014](https://ntnuopen.ntnu.no/ntnu-xmlui/handle/11250/2400689), +except the use case now is game streaming instead of adaptation of raw video to ethernet links. + +## Overview + +### Colorspace + +Currently implemented YCbCr 4:2:0 and 4:4:4. + +### Wavelets + +The images are transformed with the Discrete Wavelet Transform using CDF 9/7 filter. +This is basically the exact same as JPEG2000. + +### Exact rate control + +The encoder can target exact maximum bitrate for an encoded image. + +### Trivial "entropy" coding + +The encoding of coefficients is trivial compared to normal image codecs, +and is responsible for a large increase in bit-rate, especially at higher compression ratios. +This simplicity massively improves encode/decode performance, since it's extremely parallelizable. +It also makes it possible to do a single-pass exact rate control for an entire image. + +It should be possible in theory to add a more proper entropy coder to the encoded bit-planes to achieve somewhat +competent compression, but that has not been explored and is out of scope. +High Throughput JPEG2000 is likely a good place to look for that anyway. + +### Robustness against packet loss + +Being intra-only and encoding 64x64 blocks of coefficients in isolation ensures great recovery against packet loss. +PyroWave has been battled tested over long distance streaming over fiber links. + +### Bitstream definition + +See [docs/bitstream.md]() + +## Building + +PyroWave is intended to be built alongside PyroFling with Granite in the normal case. + +### Standalone C API + +NOTE: This API is still under development and the API/ABI is not yet quite stable. + +A small portion of Granite needs to be checked out. + +``` +bash checkout_granite.sh +``` + +Build normally with CMake and a C API is installed. + +``` +$ mkdir build +$ cd build +$ cmake .. -DCMAKE_INSTALL_PREFIX=output -DCMAKE_BUILD_TYPE=Release -G Ninja +$ ninja install + +[0/1] Install the project... +-- Install configuration: "Release" +-- Installing: ...../build/output/include/pyrowave/pyrowave.h +-- Installing: ...../build/output/lib/libpyrowave-shared.so.0.0.0 +-- Installing: ...../build/output/lib/libpyrowave-shared.so.0 +-- Installing: ...../build/output/lib/libpyrowave-shared.so +-- Installing: ...../build/output/share/pyrowave-shared/cmake/pyrowave-sharedConfig.cmake +-- Installing: ...../build/output/share/pyrowave-shared/cmake/pyrowave-sharedConfig-release.cmake +-- Installing: ...../build/output/share/pkgconfig/pyrowave-shared.pc +``` + +The build is tested on Linux, MinGW, msys2 and MSVC. +See `pyrowave-c-test` which unit tests the shared C API. +That test also serves as a basic user guide for the API. + +`build-steamrt.sh` builds against the Sniper SDK and is also supported. + +### Local development and CLI + +For the sample and test applications in this repo however, check out +the full https://github.com/Themaister/Granite before invoking CMake. +Build with `-DPYROWAVE_DEVEL=ON` to get the "full" build. + +```shell +git clone --depth 1 --recursive --shallow-submodules https://github.com/Themaister/Granite Granite +``` + +#### Basic encoder/decoder CLI + +The basic CLI takes a y4m and dumps out a raw bitstream. This is just intended for local testing. + +```shell +pyrowave-encode test.y4m out.wave 400000 +``` + +This encodes a raw bitstream where each frame consumes maximum 400 KB. +To decode back to y4m: + +```shell +pyrowave-decode out.wave out.y4m +``` + diff --git a/crates/pyrowave-sys/vendor/pyrowave/bench.cpp b/crates/pyrowave-sys/vendor/pyrowave/bench.cpp new file mode 100644 index 00000000..99bc4503 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/bench.cpp @@ -0,0 +1,255 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#include + +#include "global_managers_init.hpp" +#include "device.hpp" +#include "context.hpp" +#include "pyrowave_encoder.hpp" +#include "pyrowave_decoder.hpp" +#include "yuv4mpeg.hpp" +#include "shaders/slangmosh.hpp" + +using namespace Granite; +using namespace Vulkan; + +static std::vector example_payload; + +static void run_decoder_test(Device &device, PyroWave::Decoder &dec, const PyroWave::ViewBuffers &output) +{ + for (uint32_t i = 0; i < 10000; i++) + { + dec.clear(); + dec.push_packet(example_payload.data(), example_payload.size()); + if (!dec.decode_is_ready(false)) + return; + + auto cmd = device.request_command_buffer(); + + cmd->begin_barrier_batch(); + for (auto &plane: output.planes) + { + if (PyroWave::Decoder::device_prefers_fragment_path(device)) + { + cmd->image_barrier(plane->get_image(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT); + } + else + { + cmd->image_barrier(plane->get_image(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + } + } + cmd->end_barrier_batch(); + + auto start_ts = cmd->write_timestamp(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + dec.decode(*cmd, output); + auto end_ts = cmd->write_timestamp(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + device.register_time_interval("GPU", std::move(start_ts), std::move(end_ts), "Overall Decode"); + device.submit(cmd); + device.next_frame_context(); + //LOGI("Submitted decoder frame %05u ...\n", i); + } +} + +static void run_encoder_test(Device &device, + PyroWave::Encoder &enc, + const PyroWave::ViewBuffers &inputs) +{ + BufferCreateInfo buffer_info = {}; + buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + constexpr uint32_t bitstream_size = 500000; + + buffer_info.size = enc.get_meta_required_size(); + buffer_info.domain = BufferDomain::Device; + auto meta = device.create_buffer(buffer_info); + buffer_info.domain = BufferDomain::CachedHost; + auto meta_host = device.create_buffer(buffer_info); + + buffer_info.size = bitstream_size + 2 * enc.get_meta_required_size(); + buffer_info.domain = BufferDomain::Device; + auto bitstream = device.create_buffer(buffer_info); + buffer_info.domain = BufferDomain::CachedHost; + auto bitstream_host = device.create_buffer(buffer_info); + + PyroWave::Encoder::BitstreamBuffers buffers = {}; + buffers.meta.buffer = meta.get(); + buffers.meta.size = meta->get_create_info().size; + buffers.bitstream.buffer = bitstream.get(); + buffers.bitstream.size = bitstream->get_create_info().size; + buffers.target_size = bitstream_size; + + Fence fence; + + for (uint32_t i = 0; i < 10000; i++) + { + auto cmd = device.request_command_buffer(CommandBuffer::Type::AsyncCompute); + auto start_ts = cmd->write_timestamp(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + enc.encode(*cmd, inputs, buffers); + cmd->barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_READ_BIT); + auto end_ts = cmd->write_timestamp(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + device.register_time_interval("GPU", std::move(start_ts), std::move(end_ts), "Overall Encode"); + start_ts = cmd->write_timestamp(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + cmd->copy_buffer(*bitstream_host, *bitstream); + cmd->copy_buffer(*meta_host, *meta); + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_HOST_READ_BIT); + end_ts = cmd->write_timestamp(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + device.register_time_interval("GPU", std::move(start_ts), std::move(end_ts), "Bitstream Readback"); + fence.reset(); + device.submit(cmd, &fence); + device.next_frame_context(); + //LOGI("Submitted encoder frame %05u ...\n", i); + } + + fence->wait(); + + PyroWave::Encoder::Packet packet = {}; + example_payload.resize(500000); + auto num_packets = enc.compute_num_packets(device.map_host_buffer(*meta_host, MEMORY_ACCESS_READ_BIT), 500000); + (void)num_packets; + assert(num_packets == 1); + enc.packetize(&packet, 500000, example_payload.data(), example_payload.size(), + device.map_host_buffer(*meta_host, MEMORY_ACCESS_READ_BIT), + device.map_host_buffer(*bitstream_host, MEMORY_ACCESS_READ_BIT)); + example_payload.resize(packet.size); +} + +struct YCbCrImages +{ + Vulkan::ImageHandle images[3]; + PyroWave::ViewBuffers views; +}; + +static YCbCrImages create_ycbcr_images(Device &device, int width, int height, VkFormat fmt, PyroWave::ChromaSubsampling chroma) +{ + YCbCrImages images; + auto info = ImageCreateInfo::immutable_2d_image(width, height, fmt); + info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + images.images[0] = device.create_image(info); + device.set_name(*images.images[0], "Y"); + + if (chroma == PyroWave::ChromaSubsampling::Chroma420) + { + info.width >>= 1; + info.height >>= 1; + } + + images.images[1] = device.create_image(info); + device.set_name(*images.images[1], "Cb"); + + images.images[2] = device.create_image(info); + device.set_name(*images.images[2], "Cr"); + + for (int i = 0; i < 3; i++) + images.views.planes[i] = &images.images[i]->get_view(); + + return images; +} + +static void run_vulkan_test(Device &device, const char *in_path) +{ + YUV4MPEGFile input; + + if (!input.open_read(in_path)) + return; + + auto width = input.get_width(); + auto height = input.get_height(); + + auto fmt = YUV4MPEGFile::format_to_bytes_per_component(input.get_format()) == 2 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R8_UNORM; + auto chroma = YUV4MPEGFile::format_has_subsampling(input.get_format()) ? PyroWave::ChromaSubsampling::Chroma420 : PyroWave::ChromaSubsampling::Chroma444; + auto inputs = create_ycbcr_images(device, width, height, fmt, chroma); + + PyroWave::Encoder enc; + PyroWave::Decoder dec; + if (!enc.init(&device, width, height, chroma)) + return; + + if (!dec.init(&device, width, height, chroma, PyroWave::Decoder::device_prefers_fragment_path(device))) + return; + + if (!input.begin_frame()) + return; + + auto cmd = device.request_command_buffer(); + + for (int i = 0; i < 3; i++) + { + cmd->image_barrier(*inputs.images[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 0, 0, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT); + } + + for (int i = 0; i < 3; i++) + { + auto *y = cmd->update_image(*inputs.images[i]); + if (!input.read(y, inputs.images[i]->get_width() * inputs.images[i]->get_height())) + { + LOGE("Failed to read plane.\n"); + device.submit_discard(cmd); + return; + } + } + + for (int i = 0; i < 3; i++) + { + cmd->image_barrier(*inputs.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + + device.submit(cmd); + + run_encoder_test(device, enc, inputs.views); + for (int i = 0; i < 4; i++) + device.next_frame_context(); + device.timestamp_log([](const std::string &tag, const TimestampIntervalReport &report) + { + LOGI("%s -> %.3f us avg\n", tag.c_str(), report.time_per_frame_context * 1e6); + }); + device.timestamp_log_reset(); + + run_decoder_test(device, dec, inputs.views); + for (int i = 0; i < 4; i++) + device.next_frame_context(); + device.timestamp_log([](const std::string &tag, const TimestampIntervalReport &report) + { + LOGI("%s -> %.3f us avg\n", tag.c_str(), report.time_per_frame_context * 1e6); + }); + device.timestamp_log_reset(); +} + +static void run_vulkan_test(const char *in_path) +{ + if (!Context::init_loader(nullptr)) + return; + + Context ctx; + + if (!ctx.init_instance_and_device(nullptr, 0, nullptr, 0, CONTEXT_CREATION_ENABLE_PUSH_DESCRIPTOR_BIT)) + return; + + Device dev; + dev.set_context(ctx); + + run_vulkan_test(dev, in_path); +} + +int main(int argc, char **argv) +{ + if (argc != 2) + return EXIT_FAILURE; + + run_vulkan_test(argv[1]); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/bitstream/bitstream.md b/crates/pyrowave-sys/vendor/pyrowave/bitstream/bitstream.md new file mode 100644 index 00000000..f4582414 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/bitstream/bitstream.md @@ -0,0 +1,537 @@ +# Bitstream definition + +### Disclaimer + +This specification is considered a draft and may change at any time. + +## Introduction + +PyroWave is a byte oriented image codec which is organized into a series of *packets*. +It is intended to be transmitted over transmission mediums such as IP networks. +There is no defined mapping to bit-oriented mediums such as serial interfaces. +Such adaptations must define a convention separately. + +The codec is intended to be implemented efficiently as (Vulkan) compute shaders running on mainstream consumer GPUs, +designed for extremely high throughput with very low latency for both encoding and decoding +while maintaining reasonable compression ratios. + +### Previous work + +The design of this codec is a reimagining of [my master thesis from 2014](https://ntnuopen.ntnu.no/ntnu-xmlui/handle/11250/2400689), +with laser focus on the local game streaming use case. + +### Conventions + +#### Endianness + +A byte is assumed to be 8 bits. +When multi-byte values are encoded, little-endian layout is assumed. + +#### Code snippet interpretation + +The decoding process is explained with C99 and GLSL. +Right-shift on signed integers is assumed to be an arithmetic right shift. +All structures presented are assumed to be tightly packed, i.e., no padding between fields. + +### Intra video codec + +PyroWave is fundamentally a still-image codec which is designed to be used for video as a series of still images. +This is often called intra-only video. This is in contrast to most video codecs which rely on inter-prediction as well +to significantly reduce bit-rate. + +## Wavelet transform + +PyroWave uses the Discrete Wavelet Transform (DWT) with 5 levels of decomposition. + +``` +************************* +* LL4 * HL4 * * +************* HL3 * +* LH4 * HH4 * * +************************* +* * * +* LH3 * HH3 * +* * * +************************* + . + . + . + . + . + HH0 +``` + +Note that some implementations would start counting at 1 instead of 0. +It was more convenient to start counting at 0 for purposes of programming. +The full-resolution image would be considered LL-1 in this diagram. + +The basic concept is that a single image component (Y, Cb or Cr) is transformed into 4 sub-bands, then subsampled. +In the forward transform, the image is filtered horizontally with two filter kernels, a low-pass and a high-pass. +The even samples become the low-pass band, and odd samples become the high-pass band, +effectively deinterleaving the values after critically sub-sampling the bands. +This process repeats vertically for the two sub-bands. +This forms 4 subbands. LL is low-pass filtered both horizontally and vertically, +HL is high-pass filtered horizontally and low-pass filtered vertically. +Once the first LL0 band is computed, that band is further decomposed into {LL,HL,LH,HH}1 sub-bands, and so it goes +until the final LL4 sub-band is complete. No other LL sub-band is transmitted, since they are reconstructed from +the other bands. + +The inverse transform performs the operations in reverse. The 4 subbands are interleaved back to full resolution, +then synthesis filters are applied. This transform is fully reversible assuming infinite precision. + +PyroWave uses the irreversible [CDF 9/7 filter](https://en.wikipedia.org/wiki/Cohen%E2%80%93Daubechies%E2%80%93Feauveau_wavelet). +This is the same as used in JPEG2000. +This filter can be implemented using a lifting scheme. +See section F.4.8.2 in ITU-T Rec T.800 (06/2019) for reference on how to implement the lifting scheme. + +Signal extension to define the filtering kernel on image edges works like JPEG2000 as well. +The input pixels are mirrored on the edges. The mirror applies to both forward and inverse transforms equally. +This can be efficiently implemented with `VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT` and `textureGather()` on GPUs. +See source code for the trick on how to do it. Note that GPU mirroring is not quite the same as JPEG2000 mirroring. + +The decoding process is not bit-exact. +This is generally the case for the CDF 9/7 since it is defined in floating-point. +The inverse wavelet transform must be performed with at least FP16 precision. +The range of intermediate floating point values can exceed +/- 1.0. +Intermediate values above +/- 4.0 may be saturated to that range for practical reasons. +Inf and NaN cannot occur. + +### Image dimension alignment and padding + +The internal image dimensions are padded and aligned to make the transform easier to deal with. + +```c +int DecompositionLevels = 5; +int Alignment = 1 << DecompositionLevels; +int MinimumImageSize = 4 << DecompositionLevels; +int NumComponents = 3; +int NumFrequencyBandsPerLevel = 4; +``` + +```c +int align(int value, int align) +{ + return (value + align - 1) & ~(align - 1); +} + +int max(int a, int b) +{ + return (a > b) ? a : b; +} +``` + +`Width` and `Height` can take any value from 1 up to `2^14` (16K). +These values are defined by `BitstreamSequenceHeader` (defined later). + +```c +AlignedWidth = align(Width, Alignment); +AlignedHeight = align(Height, Alignment); +AlignedWidth = max(AlignedWidth, MinimumImageSize); +AlignedHeight = max(AlignedHeight, MinimumImageSize); +``` + +The dimensions of each sub-band is defined as: + +``` +for (int level = 0; level < DecompositionLevels; level++) +{ + SubbandWidth[level] = AlignedWidth >> (level + 1); + SubbandHeight[level] = AlignedHeight >> (level + 1); +} +``` + +During encoding, if `Width < AlignedWidth` or `Height < AlignedHeight`, +the image is extended using clamp-to-edge semantics on right and bottom edges. +When encoding, it is possible to fold clamp-to-edge semantics +with the wrapping behavior required by DWT into one sampling operation by cleverly adjusting the coordinates. + +When decoding edge pixels, outputs which lie past the image's `Width` and `Height` are discarded after decoding. + +When 4:2:0 chroma sub-sampling is used, the highest resolution sub-band does not exist, +and 4 levels of decomposition is used instead for chroma. +Decoding of Cb and Cr components stop once LL0 is decoded. + +## Decoding process + +Decoding happens in four stages: + +- Decoding wavelet coefficients +- Scaling wavelet coefficients into floating-point (de-quantization) +- Inverse DWT per component (Y, Cb, Cr) +- DC shift fixup + clamping to [0, 1] range. + +The first two and two latter can trivially be fused together for purposes of implementation. + +### Decoding wavelet coefficients + +Each sub-band is organized into blocks of 32x32 coefficients. +A 32x32 block of coefficients is signalled in isolation with no prediction or context. +If a 32x32 block is missing (either deliberately or by packet loss), +all coefficients are assumed to be 0.0. + +A 32x32 block starts with an 8 byte header: + +```c +struct BitstreamHeader +{ + uint16_t ballot; + uint16_t payload_words : 12; + uint16_t sequence : 3; + uint16_t extended : 1; + uint32_t quant_code : 8; + uint32_t block_index : 24; +}; +``` + +- `ballot` signals 1 bit per 8x8 block inside the 32x32 block. + If a bit is 0, the group of 8x8 coefficients is all 0, and are skipped. + The assumed layout of the 8x8 blocks is row-major with respect to bit-position. + If `ballot` is 0, the 32x32 block should not be transmitted at all. + A decoder can safely ignore such a block if it is observed. +- `payload_words` is the number of u32 words contained within the 32x32 block, including this header. + The effective byte size is `payload_words * sizeof(uint32_t)`. + This alignment can lead to padding bytes at the end. The content of alignment bytes is ignored. + When multiple 32x32 blocks are packed into a network packet, this field is sufficient to extract the individual blocks. +- `sequence` is a wrapping counter used to detect frame progression. It increases by one (modulo 8) every frame transmitted. + This can be used to detect when a new frame begins, and if there have been frame drops. Signalling presentation timing + is left to external mechanisms. +- `extended` is 1 if this packet contains "special" information which is not related to decoding wavelet coefficients. +- `quant_code` encodes how to scale wavelet coefficients into floating-point (de-quantization). +- `block_index` is a linear block index. Every possible 32x32 block is assigned a block index (defined later). + Out of range block indices must be recognized and skipped by a decoder, + but a decoder is allowed to discard any previously received data if observed. + +#### Start of frame header + +If `extended` is 1, the definition of the header is reinterpreted to: + +```c +enum +{ + BITSTREAM_EXTENDED_CODE_START_OF_FRAME = 0, +}; + +enum +{ + CHROMA_RESOLUTION_420 = 0, + CHROMA_RESOLUTION_444 = 1 +}; + +enum +{ + CHROMA_SITING_CENTER = 0, + CHROMA_SITING_LEFT = 1 +}; + +enum +{ + YCBCR_RANGE_FULL = 0, + YCBCR_RANGE_LIMITED = 1 +}; + +enum +{ + COLOR_PRIMARIES_BT709 = 0, + COLOR_PRIMARIES_BT2020 = 1 +}; + +enum +{ + YCBCR_TRANSFORM_BT709 = 0, + YCBCR_TRANSFORM_BT2020 = 1 +}; + +enum +{ + TRANSFER_FUNCTION_BT709 = 0, + TRANSFER_FUNCTION_PQ = 1 +}; + +struct BitstreamSequenceHeader +{ + uint32_t width_minus_1 : 14; + uint32_t height_minus_1 : 14; + uint32_t sequence : 3; + uint32_t extended : 1; + uint32_t total_blocks : 24; + uint32_t code : 2; + uint32_t chroma_resolution : 1; + uint32_t color_primaries : 1; + uint32_t transfer_function : 1; + uint32_t ycbcr_transform : 1; + uint32_t ycbcr_range : 1; + uint32_t chroma_siting : 1; +}; +``` + +The only defined extended header is currently this one. The kind of header is signalled by +`code` for which only `BITSTREAM_EXTENDED_CODE_START_OF_FRAME` is defined. +Other values for `code` is reserved for future use which can extend this definition in any required way. + +A `BITSTREAM_EXTENDED_CODE_START_OF_FRAME` should be transmitted for every frame of video. +This packet may be sent in any order relative to other packets for any given frame. +A decoder may discard received packet until it has observed +`BITSTREAM_EXTENDED_CODE_START_OF_FRAME` at least once. + +In a video sequence, `width_minus_1`, `height_minus_1` and `chroma_resolution` must remain invariant. +What a "video sequence" is, is not defined here, but left to relevant higher-level protocols. +These fields may also be provided through external means allowing a decoder to be instantiated before any +packet data is received by decoder, but this mechanism is also not defined here. + +`total_blocks` specifies up-front how many non-zero 32x32 blocks are encoded for the given frame `sequence`. +When the decoder observes that a given `sequence` has received enough packets to decode this many +blocks, the decoding process can begin immediately. + +If the received number of unique packets is less than `total_blocks`, this indicates packet loss or similar. +Any missing block is decoded as all zero values. If a missing block belongs +to any high-pass band, this leads to intermittent blurring which may be barely noticeable. +A loss in the LL4 band is more severe, and selectively applying Forward Error Correction to those packets in particular +may be considered. Other error masking techniques may be employed as desired, which is not defined here. +The decoder may reject duplicate `block_index` for the same `sequence` as well. +The encoder may send duplicate `block_index` values for the same `sequence` for purposes of crude error correction. + +Decoding an incomplete frame may be forced by external means. Typical reasons to force a decode can be: + +- A timeout was reached while waiting for all packets to come through +- The next sequence count was observed, meaning we likely won't see any more packets from the previous sequence. + +Image dimensions are signalled here: + +```c +Width = width_minus_1 + 1; +Height = height_minus_1 + 1; +``` + +`chroma_resolution` signals if 420 sub-sampling is used or not. If 420 is used, level = 0 for non-luma components +are skipped, and are not assigned a `block_index`. +If 420 subsampling is used, `Width` and `Height` must be even. + +The last 5 fields are purely "video usability" information. It has no semantic impact on the decoding process, +but are used to signal how to interpret the output Y, Cb and Cr values. +The definitions of full/limited, bt709/bt2020, etc, are left to the respective specifications. +bt2020 YCbCr transform is the NCL variant. + +There is no distinction for 8-bit and 10-bit. +The decoding process is defined in floating-point, and it is not specified how the final decoded values are quantized into a UNORM image. + +#### Decoding 8x8 blocks + +After the 8 byte header follows `N` values, packed into two arrays to make memory access more practical: + +```c +BitstreamHeader Header; +uint16_t CodeWords[N]; +uint8_t QScale[N]; +uint8_t Payload[PayloadSize]; +uint8_t SignPayload[SignSize]; +``` + +where `N` is `popcount(ballot)` (the number of bits set to 1 in `ballot`). +For any given 8x8 block, the index into the array is given by how many preceding `ballot` bits are set to 1, +i.e., the 8x8 blocks are tightly packed. + +An 8x8 block may be fully out of range of the particular sub-band. +In this case, the decoded values are discarded after dequantization. +An encoder should not encode an out of range 8x8 block. +If an 8x8 block is partially out of range, only the out of range coefficients are discarded after dequantization. + +```c +if (ballot & (1u << RowMajor8x8Index)) + Compacted8x8Index = popcount(ballot & ((1u << RowMajor8x8Index) - 1u)); +else + Compacted8x8Index = undefined; +``` + +`PayloadSize` depends on the contents of `CodeWords` and `QScale`. +`SignSize` depends on the coefficient values. + +The wavelet coefficients are organized as bit-planes, without any entropy coding. +This ensures extremely fast and parallel encoding and decoding at the cost of bitrate. +Each 8x8 block is organized into 8 4x2 subblocks. The ordering of these subblocks is given as: + +``` +subblock order: +------> +x +| 0 4 +| 1 5 +| 2 6 +| 3 7 ++y +``` + +Within a 4x2 subblock, the ordering is given as: + +``` +pixel order: +---------> +x +| 0 2 4 6 +| 1 3 5 7 ++y +``` + +Decoding a linear index between 0 and 63 into a 8x8 coordinate can be done with this GLSL snippet as an example: + +```glsl +ivec2 unswizzle8x8(uint index) +{ + uint y = bitfieldExtract(index, 0, 1); + uint x = bitfieldExtract(index, 1, 2); + y |= bitfieldExtract(index, 3, 2) << 1; + x |= bitfieldExtract(index, 5, 1) << 2; + return ivec2(x, y); +} +``` + +Each subblock encodes 8 magnitude values with a variable number of bits. +The number of bits is encoded `CodeWords[i]` and `QScale[i]`. + +```c +int SubblockPosition4x2(int IndexWithin8x8Block) +{ + return IndexWithin8x8Block >> 3; +} + +BitPlanes = (CodeWords[Compacted8x8Index] >> (2 * SubblockPosition4x2(IndexWithin8x8Block))) & 0x3; +BitPlanes += QScale[Compacted8x8Index] & 0xf; +``` + +The bitplanes are organized starting with the most significant, down to least significant. +The ordering of the bits corresponds to the pixel order for a 4x2 subblock. +The bitplanes are loaded from the `Payload[]` array. The offset to use for each 4x2 subblock is implicit. +All payload data is tightly packed organized as: + +```c +// Pseudo-code + +int offset = 0; +foreach_bit(BlockIndex8x8 in ballot) +{ + for (int SubblockIndex = 0; SubblockIndex < 8; SubblockIndex++) + { + // Figure out BitPlanes based on CodeWords and QScale. + + // Decode 8 values in one go + int8 values = int8(0); + for (int plane = 0; plane < BitPlanes; plane++) + { + values <<= 1; + // bit 0 -> element 0 + // bit 1 -> element 1 + // ... etc + values |= ConvertBitsToVector(Payload[offset++]); + } + } +} +``` + +After decoding magnitude values, all non-zero coefficients also decode a sign bit. +The sign bits are tightly packed after all magnitude bit-planes. +The bit position of the sign bit is the number of non-zero coefficients that come before it in the 32x32 block. +The ordering of coefficients is the same as for magnitude planes: 8x8 block, then subblock, then pixel within subblock. +In every byte of `SignPayload[]`, signs are packed such that smaller to larger index go from LSBs to MSBs. +If a sign bit is 1, the resulting coefficient is negative. + +#### Dequantization + +After integer coefficients are decoded, they are converted to floating-point by scaling it with a factor. +The factor depends on `quant_code` from the 32x32 block header as well as `QScale[]` per 8x8 block. +The effective factor is computed as: + +```c +float Block32x32Scale(uint8_t quant_code) +{ + const int MaxScaleExp = 4; + // Custom FP formulation for numbers in (0, 16) range. + int e = MaxScaleExp - (quant_code >> 3); + int m = quant_code & 0x7; + float inv_quant = (1.0f / (8.0f * 1024.0f * 1024.0f)) * (float)((8 + m) * (1 << (20 + e))); + return inv_quant; +} + +float Block8x8Scale(uint8_t code) +{ + return (float)code / 8.0 + 0.25; +} + +float scale = Block32x32Scale(quant_code) * Block8x8Scale((QScale[i] >> 4) & 0xf); + +// Output from coefficient decoding. +float DecodedCoefficientFloat = DecodedCoefficient; + +// Apply deadzone. +if (DecodedCoefficientFloat > 0.0) + DecodedCoefficientFloat += 0.5; +else if (DecodedCoefficientFloat < 0.0) + DecodedCoefficientFloat -= 0.5; + +float DequantizedCoefficient = scale * DecodedCoefficientFloat; +``` + +A deadzone quantizer is used here, meaning that quantization biases towards zero. + +#### Block index ordering + +Components are ordered from 0 to 2: + +- Component 0: Y +- Component 1: Cb +- Component 2: Cr + +Bands are ordered from 0 to 3: + +- Band 0: LL (low-pass) +- Band 1: HL (horizontal high-pass, vertical low-pass) +- Band 2: LH (horizontal low-pass, vertical high-pass) +- Band 3: HH (high-pass) + +```c +int block_index = 0; + +for (int level = DecompositionLevels - 1; level >= 0; level--) +{ + for (int component = 0; component < NumComponents; component++) + { + if (level == 0 && component != 0 && IsYCbCr420) + continue; + + for (int band = (level == DecompositionLevels - 1 ? 0 : 1); band < 4; band++) + { + uint32_t level_width = AlignedWidth >> (level + 1); + uint32_t level_height = AlignedHeight >> (level + 1); + + int blocks_x_32x32 = (level_width + 31) / 32; + int blocks_y_32x32 = (level_height + 31) / 32; + + for (int y = 0; y < blocks_y_32x32; y++) + for (int x = 0; x < blocks_x_32x32; x++) + AssignBlockIndex(level, component, band, block_index++); + } + } +} +``` + +#### Inverse DC shift + +After completing the decoding process, wavelet values are shifted and clamped into `[0, 1]` range. +The bit-depth of the decoded image is not specified and may depend on the use case of the image. +E.g. a PQ encoded image may desire a higher bit-depth. + +```c +float clamp(float v, float lo, float hi) +{ + if (v < lo) + return lo; + else if (v > hi) + return hi; + else + return v; +} + +LumaShifted = clamp(DecodedLuma + 0.5, 0.0, 1.0); +CbShifted = clamp(DecodedCb + 0.5, 0.0, 1.0); +CrShifted = clamp(DecodedCr + 0.5, 0.0, 1.0); + +WriteToImage(LumaShifted); +WriteToImage(CbShifted); +WriteToImage(CrShifted); +``` \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/build-steamrt-helper.sh b/crates/pyrowave-sys/vendor/pyrowave/build-steamrt-helper.sh new file mode 100755 index 00000000..1d863940 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/build-steamrt-helper.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# This is run from inside the container. +# Useful as an initial template. +# +ls -l + +mkdir -p build-steamrt +cd build-steamrt + +cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=../steamrt-output \ + -DPYTHON_EXECUTABLE=$(which python3) \ + -G Ninja + +ninja install/strip -v + diff --git a/crates/pyrowave-sys/vendor/pyrowave/build-steamrt.sh b/crates/pyrowave-sys/vendor/pyrowave/build-steamrt.sh new file mode 100755 index 00000000..238eadad --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/build-steamrt.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +docker run -it --init --rm -u $UID -w /pyro -v $(pwd):/pyro registry.gitlab.steamos.cloud/steamrt/sniper/sdk ./build-steamrt-helper.sh + diff --git a/crates/pyrowave-sys/vendor/pyrowave/build_aarch64.sh b/crates/pyrowave-sys/vendor/pyrowave/build_aarch64.sh new file mode 100755 index 00000000..6812b852 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/build_aarch64.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# This script should be run inside distrobox. +# distrobox create --image registry.gitlab.steamos.cloud/steamrt/steamrt4/sdk/arm64-on-amd64 --name aarch64 +# distrobox enter aarch64 + +export PKG_CONFIG_PATH=$(pwd)/output-aarch64/lib/aarch64-linux-gnu/pkgconfig + +cmake -S . -DCMAKE_BUILD_TYPE=Release \ + -Bbuild-aarch64 \ + -DPYROWAVE_DEVEL=ON \ + -DCMAKE_INSTALL_PREFIX=output-aarch64 \ + -DGRANITE_SHIPPING=ON \ + -DGRANITE_SYSTEM_SDL=OFF \ + --toolchain=/usr/share/steamrt/cmake/aarch64-linux-gnu-gcc.cmake \ + -G Ninja + +ninja -C build-aarch64 install/strip diff --git a/crates/pyrowave-sys/vendor/pyrowave/checkout_granite.sh b/crates/pyrowave-sys/vendor/pyrowave/checkout_granite.sh new file mode 100755 index 00000000..31e7bf2d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/checkout_granite.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Only checks out what is necessary to build standalone. +# +GRANITE_COMMIT=44362775d36e0c4139352f83efd96bab4e239f66 + +if [ -d Granite ]; then + cd Granite + git fetch origin + git checkout $GRANITE_COMMIT +else + git clone https://github.com/Themaister/Granite + cd Granite + git checkout $GRANITE_COMMIT +fi + +cd .. + +update() { + git submodule sync $1 + git submodule update --init $1 +} + +cd Granite +update third_party/volk +update third_party/khronos/vulkan-headers diff --git a/crates/pyrowave-sys/vendor/pyrowave/com_ptr.hpp b/crates/pyrowave-sys/vendor/pyrowave/com_ptr.hpp new file mode 100644 index 00000000..7a9eeb43 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/com_ptr.hpp @@ -0,0 +1,69 @@ +/* Copyright (c) 2025-2026 Hans-Kristian Arntzen for Valve Corporation + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include + +template +class ComPtr +{ +public: + ComPtr() = default; + ~ComPtr() { release(); } + + ComPtr(const ComPtr &other) { *this = other; } + ComPtr &operator=(const ComPtr &other); + ComPtr &operator=(ComPtr &&other) noexcept; + + ComPtr(ComPtr &&other) noexcept { *this = std::move(other); } + ComPtr &operator=(T *ptr_) { release(); ptr = ptr_; return *this; } + + T *operator->() { return ptr; } + T *get() const { return ptr; } + void **ppv() { release(); return reinterpret_cast(&ptr); } + + void operator&() = delete; + explicit operator bool() const { return ptr != nullptr; } + + static ComPtr create() { return ComPtr(new T); } + static ComPtr addref(T *ptr_) { ptr_->AddRef(); return ComPtr(ptr_); } + +private: + T *ptr = nullptr; + void release() + { + if (ptr) + ptr->Release(); + ptr = nullptr; + } + ComPtr *self_addr() { return this; } + const ComPtr *self_addr() const { return this; } + ComPtr(T *ptr_) : ptr(ptr_) {} +}; + +template +ComPtr &ComPtr::operator=(const ComPtr &other) +{ + if (this == other.self_addr()) + return *this; + if (other.ptr) + other.ptr->AddRef(); + release(); + ptr = other.ptr; + return *this; +} + +template +ComPtr &ComPtr::operator=(ComPtr &&other) noexcept +{ + if (this == other.self_addr()) + return *this; + release(); + if (other.ptr) + ptr = other.ptr; + other.ptr = nullptr; + return *this; +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/decode.cpp b/crates/pyrowave-sys/vendor/pyrowave/decode.cpp new file mode 100644 index 00000000..8f4b5e20 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/decode.cpp @@ -0,0 +1,287 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#include + +#include "global_managers_init.hpp" +#include "device.hpp" +#include "context.hpp" +#include "pyrowave_decoder.hpp" +#include "pyrowave_common.hpp" +#include "yuv4mpeg.hpp" +#include "shaders/slangmosh.hpp" + +using namespace Granite; +using namespace Vulkan; + +struct DecodedBuffer +{ + BufferHandle planes[3]; + Fence fence; +}; + +static DecodedBuffer run_decoder_frame(CommandBufferHandle &cmd, + PyroWave::Decoder &dec, + const PyroWave::ViewBuffers &outputs, + uint32_t frame_index) +{ + auto &device = cmd->get_device(); + DecodedBuffer decoded; + + for (int i = 0; i < 3; i++) + { + BufferCreateInfo bufinfo = {}; + bufinfo.domain = BufferDomain::CachedHost; + bufinfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + bufinfo.size = format_get_layer_size(outputs.planes[i]->get_format(), + VK_IMAGE_ASPECT_COLOR_BIT, + outputs.planes[i]->get_view_width(), + outputs.planes[i]->get_view_height(), 1); + decoded.planes[i] = device.create_buffer(bufinfo); + } + + dec.decode(*cmd, outputs); + + for (auto &plane : outputs.planes) + { + cmd->image_barrier(plane->get_image(), + VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_READ_BIT); + } + + for (int i = 0; i < 3; i++) + { + cmd->copy_image_to_buffer(*decoded.planes[i], outputs.planes[i]->get_image(), 0, + {}, { outputs.planes[i]->get_view_width(), + outputs.planes[i]->get_view_height(), + outputs.planes[i]->get_view_depth() }, + 0, 0, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }); + } + + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_HOST_BIT, VK_ACCESS_HOST_READ_BIT); + device.submit(cmd, &decoded.fence); + device.next_frame_context(); + + LOGI("Submitted frame %06u ...\n", frame_index); + return decoded; +} + +struct YCbCrImages +{ + Vulkan::ImageHandle images[3]; + PyroWave::ViewBuffers views; +}; + +static YCbCrImages create_ycbcr_images(Device &device, int width, int height, VkFormat fmt, PyroWave::ChromaSubsampling chroma) +{ + YCbCrImages images; + auto info = ImageCreateInfo::immutable_2d_image(width, height, fmt); + info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + images.images[0] = device.create_image(info); + device.set_name(*images.images[0], "Y"); + + if (chroma == PyroWave::ChromaSubsampling::Chroma420) + { + info.width >>= 1; + info.height >>= 1; + } + + images.images[1] = device.create_image(info); + device.set_name(*images.images[1], "Cb"); + + images.images[2] = device.create_image(info); + device.set_name(*images.images[2], "Cr"); + + for (int i = 0; i < 3; i++) + images.views.planes[i] = &images.images[i]->get_view(); + + return images; +} + +static bool write_payload(YUV4MPEGFile &file, Device &device, const DecodedBuffer &decoded) +{ + if (!file.begin_frame()) + return false; + + for (auto &plane_ptr : decoded.planes) + { + auto *plane = device.map_host_buffer(*plane_ptr, MEMORY_ACCESS_READ_BIT); + if (!file.write(plane, plane_ptr->get_create_info().size)) + return false; + } + + return true; +} + +static bool read_payload(FILE *file, PyroWave::Decoder &decoder) +{ + std::vector packetized_data; + uint32_t u32_size; + + for (;;) + { + if (fread(&u32_size, sizeof(u32_size), 1, file) != 1) + return false; + packetized_data.resize(u32_size); + if (fread(packetized_data.data(), 1, u32_size, file) != u32_size) + return false; + + if (!decoder.push_packet(packetized_data.data(), packetized_data.size())) + return false; + + if (decoder.decode_is_ready(false)) + return true; + } +} + +static const char *format_to_str(YUV4MPEGFile::Format fmt) +{ + switch (fmt) + { + case YUV4MPEGFile::Format::YUV420P: + return "C420"; + case YUV4MPEGFile::Format::YUV420P16: + return "C420p16"; + case YUV4MPEGFile::Format::YUV444P: + return "C444"; + case YUV4MPEGFile::Format::YUV444P16: + return "C444p16"; + default: + return "???"; + } +} + +static void run_decoder(Device &device, const char *out_path, const char *in_path) +{ + struct FILEDeleter { void operator()(FILE *file) { if (file) fclose(file); } }; + std::unique_ptr infile; + + infile.reset(fopen(in_path, "rb")); + if (!infile) + { + LOGE("Failed to open input file.\n"); + return; + } + + char magic[9] = {}; + if (fread(magic, 1, 8, infile.get()) != 8) + { + LOGE("Failed to read magic.\n"); + return; + } + + if (strcmp(magic, "PYROWAVE") != 0) + { + LOGE("Invalid magic.\n"); + return; + } + + int32_t u32_params[8]; + if (fread(u32_params, sizeof(u32_params), 1, infile.get()) != 1) + { + LOGE("Failed to read parameters.\n"); + return; + } + + PyroWave::Decoder dec; + int width = u32_params[0]; + int height = u32_params[1]; + auto format = YUV4MPEGFile::Format(u32_params[2]); + auto chroma = PyroWave::ChromaSubsampling(u32_params[3]); + bool is_full = u32_params[4] != 0; + int frame_rate_num = u32_params[5]; + int frame_rate_den = u32_params[6]; + // Unused chroma siting. YUV4MPEG doesn't seem to have proper support for that. + if (!dec.init(&device, width, height, chroma)) + return; + + YUV4MPEGFile output; + char params[1024]; + + snprintf(params, sizeof(params), "YUV4MPEG2 W%d H%d F%d:%d Ip A1:1 XCOLORRANGE=%s %s\n", + width, height, frame_rate_num, frame_rate_den, is_full ? "FULL" : "LIMITED", format_to_str(format)); + + if (!output.open_write(out_path, params)) + { + LOGE("Failed to open input file.\n"); + return; + } + + auto fmt = YUV4MPEGFile::format_to_bytes_per_component(output.get_format()) == 2 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R8_UNORM; + auto outputs = create_ycbcr_images(device, width, height, fmt, chroma); + + DecodedBuffer queue[2]; + uint32_t frame_index = 0; + + for (;;) + { + auto &q = queue[frame_index & 1]; + if (q.fence) + { + q.fence->wait(); + q.fence.reset(); + if (!write_payload(output, device, q)) + { + LOGE("Failed to write payload.\n"); + break; + } + } + + if (!read_payload(infile.get(), dec)) + break; + + auto cmd = device.request_command_buffer(); + + for (auto &img : outputs.images) + { + cmd->image_barrier(*img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_2_COPY_BIT, 0, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + } + + queue[frame_index & 1] = run_decoder_frame(cmd, dec, outputs.views, frame_index); + frame_index++; + } + + frame_index--; + + auto &q = queue[frame_index & 1]; + if (q.fence) + { + q.fence->wait(); + if (!write_payload(output, device, q)) + LOGE("Failed to write payload.\n"); + } +} + +static void run_decoder(const char *out_path, const char *in_path) +{ + if (!Context::init_loader(nullptr)) + return; + + Context ctx; + + if (!ctx.init_instance_and_device(nullptr, 0, nullptr, 0, CONTEXT_CREATION_ENABLE_PUSH_DESCRIPTOR_BIT)) + return; + + Device dev; + dev.set_context(ctx); + + run_decoder(dev, out_path, in_path); +} + +int main(int argc, char **argv) +{ + if (argc != 3) + { + LOGE("Usage: pyrowave-encode \n"); + return EXIT_FAILURE; + } + + run_decoder(argv[2], argv[1]); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/encode.cpp b/crates/pyrowave-sys/vendor/pyrowave/encode.cpp new file mode 100644 index 00000000..95725551 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/encode.cpp @@ -0,0 +1,261 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#include + +#include "global_managers_init.hpp" +#include "device.hpp" +#include "context.hpp" +#include "pyrowave_encoder.hpp" +#include "yuv4mpeg.hpp" +#include "shaders/slangmosh.hpp" + +using namespace Granite; +using namespace Vulkan; + +struct EncodedBuffer +{ + BufferHandle payload; + BufferHandle meta; + Fence fence; +}; + +static EncodedBuffer run_encoder_frame(CommandBufferHandle &cmd, + PyroWave::Encoder &enc, + const PyroWave::ViewBuffers &inputs, + uint32_t frame_index, + uint32_t bitstream_size) +{ + auto &device = cmd->get_device(); + + EncodedBuffer encoded; + BufferCreateInfo buffer_info = {}; + buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + buffer_info.size = enc.get_meta_required_size(); + buffer_info.domain = BufferDomain::Device; + auto meta = device.create_buffer(buffer_info); + buffer_info.domain = BufferDomain::CachedHost; + encoded.meta = device.create_buffer(buffer_info); + + buffer_info.size = bitstream_size + 2 * enc.get_meta_required_size(); + buffer_info.domain = BufferDomain::Device; + auto bitstream = device.create_buffer(buffer_info); + buffer_info.domain = BufferDomain::CachedHost; + encoded.payload = device.create_buffer(buffer_info); + + PyroWave::Encoder::BitstreamBuffers buffers = {}; + buffers.meta.buffer = meta.get(); + buffers.meta.size = meta->get_create_info().size; + buffers.bitstream.buffer = bitstream.get(); + buffers.bitstream.size = bitstream->get_create_info().size; + buffers.target_size = bitstream_size; + + enc.encode(*cmd, inputs, buffers); + cmd->copy_buffer(*encoded.payload, *bitstream); + cmd->copy_buffer(*encoded.meta, *meta); + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_HOST_READ_BIT); + device.submit(cmd, &encoded.fence); + device.next_frame_context(); + + LOGI("Submitted frame %06u ...\n", frame_index); + return encoded; +} + +struct YCbCrImages +{ + Vulkan::ImageHandle images[3]; + PyroWave::ViewBuffers views; +}; + +static YCbCrImages create_ycbcr_images(Device &device, int width, int height, VkFormat fmt, PyroWave::ChromaSubsampling chroma) +{ + YCbCrImages images; + auto info = ImageCreateInfo::immutable_2d_image(width, height, fmt); + info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + images.images[0] = device.create_image(info); + device.set_name(*images.images[0], "Y"); + + if (chroma == PyroWave::ChromaSubsampling::Chroma420) + { + info.width >>= 1; + info.height >>= 1; + } + + images.images[1] = device.create_image(info); + device.set_name(*images.images[1], "Cb"); + + images.images[2] = device.create_image(info); + device.set_name(*images.images[2], "Cr"); + + for (int i = 0; i < 3; i++) + images.views.planes[i] = &images.images[i]->get_view(); + + return images; +} + +static bool write_payload(FILE *file, PyroWave::Encoder &encoder, Device &device, const Buffer &payload, const Buffer &meta) +{ + auto *mapped_payload = device.map_host_buffer(payload, MEMORY_ACCESS_READ_BIT); + auto *mapped_meta = device.map_host_buffer(meta, MEMORY_ACCESS_READ_BIT); + + std::vector packetized_data(payload.get_create_info().size); + + PyroWave::Encoder::Packet packet = {}; + if (encoder.packetize(&packet, payload.get_create_info().size, + packetized_data.data(), packetized_data.size(), + mapped_meta, mapped_payload) != 1) + { + LOGE("Something went terribly wrong ...\n"); + std::terminate(); + } + + uint32_t u32_size = packet.size; + if (fwrite(&u32_size, sizeof(u32_size), 1, file) != 1) + return false; + return fwrite(packetized_data.data() + packet.offset, 1, packet.size, file) == packet.size; +} + +static void run_encoder(Device &device, const char *out_path, const char *in_path, uint32_t bitstream_size) +{ + YUV4MPEGFile input; + + if (!input.open_read(in_path)) + { + LOGE("Failed to open input file.\n"); + return; + } + + struct FILEDeleter { void operator()(FILE *file) { if (file) fclose(file); } }; + std::unique_ptr out; + + out.reset(fopen(out_path, "wb")); + if (!out) + { + LOGE("Failed to open output file.\n"); + return; + } + + if (fwrite("PYROWAVE", 1, 8, out.get()) != 8) + { + LOGE("Failed to write magic.\n"); + return; + } + + int32_t width = input.get_width(); + int32_t height = input.get_height(); + auto fmt = YUV4MPEGFile::format_to_bytes_per_component(input.get_format()) == 2 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R8_UNORM; + auto chroma = YUV4MPEGFile::format_has_subsampling(input.get_format()) ? PyroWave::ChromaSubsampling::Chroma420 : PyroWave::ChromaSubsampling::Chroma444; + + int32_t u32_params[8] = { + width, height, int(input.get_format()), int(chroma), input.is_full_range(), + input.get_frame_rate_num(), input.get_frame_rate_den(), 0 /* placeholder for unknown chroma siting */ + }; + + if (fwrite(u32_params, sizeof(u32_params), 1, out.get()) != 1) + { + LOGE("Failed to write u32 params.\n"); + return; + } + + auto inputs = create_ycbcr_images(device, width, height, fmt, chroma); + + PyroWave::Encoder enc; + if (!enc.init(&device, width, height, chroma)) + return; + + EncodedBuffer queue[2]; + uint32_t frame_index = 0; + + for (;;) + { + auto &q = queue[frame_index & 1]; + if (q.fence) + { + q.fence->wait(); + q.fence.reset(); + if (!write_payload(out.get(), enc, device, *q.payload, *q.meta)) + { + LOGE("Failed to write payload.\n"); + break; + } + } + + if (!input.begin_frame()) + break; + + auto cmd = device.request_command_buffer(); + + for (auto &img : inputs.images) + { + cmd->image_barrier(*img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 0, 0, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT); + } + + for (auto &img : inputs.images) + { + auto *y = cmd->update_image(*img); + if (!input.read(y, img->get_width() * img->get_height())) + { + LOGE("Failed to read plane.\n"); + device.submit_discard(cmd); + break; + } + } + + for (auto &img : inputs.images) + { + cmd->image_barrier(*img, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + + queue[frame_index & 1] = run_encoder_frame(cmd, enc, inputs.views, frame_index, bitstream_size); + frame_index++; + } + + frame_index--; + + auto &q = queue[frame_index & 1]; + if (q.fence) + { + q.fence->wait(); + q.fence.reset(); + if (!write_payload(out.get(), enc, device, *q.payload, *q.meta)) + LOGE("Failed to write payload.\n"); + } +} + +static void run_encoder(const char *out_path, const char *in_path, uint32_t bytes_per_frame) +{ + if (!Context::init_loader(nullptr)) + return; + + Context ctx; + + if (!ctx.init_instance_and_device(nullptr, 0, nullptr, 0, CONTEXT_CREATION_ENABLE_PUSH_DESCRIPTOR_BIT)) + return; + + Device dev; + dev.set_context(ctx); + + run_encoder(dev, out_path, in_path, bytes_per_frame); +} + +int main(int argc, char **argv) +{ + if (argc != 4) + { + LOGE("Usage: pyrowave-encode \n"); + return EXIT_FAILURE; + } + + run_encoder(argv[2], argv[1], strtoul(argv[3], nullptr, 0)); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/link.T b/crates/pyrowave-sys/vendor/pyrowave/link.T new file mode 100644 index 00000000..1974e0b7 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/link.T @@ -0,0 +1,4 @@ +{ + global: pyrowave_*; + local: *; +}; diff --git a/crates/pyrowave-sys/vendor/pyrowave/metrics/plot.py b/crates/pyrowave-sys/vendor/pyrowave/metrics/plot.py new file mode 100644 index 00000000..6406b054 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/metrics/plot.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +import plotly.express as px +import plotly.graph_objects as go +import pandas as pd +import sys +import csv +import os + +def main(): + codecs = ['h264_nvenc', 'hevc_nvenc', 'av1_nvenc', 'pyrowave'] + cols = ['xpsnr', 'ssim', 'ssimulacra2', 'vmaf', 'vmafneg'] + + codec_name = { + 'h264_nvenc' : 'H.264 NVENC', + 'hevc_nvenc' : 'H.265 NVENC', + 'av1_nvenc' : 'AV1 NVENC', + 'pyrowave' : 'PyroWave' } + + metric_name = { + 'xpsnr' : 'W-XPSNR', + 'ssim' : 'SSIM', + 'ssimulacra2' : 'SSIMULACRA2', + 'vmaf' : 'VMAF', + 'vmafneg' : 'VMAF NEG' } + + data_sets = {} + + for codec in codecs: + with open(os.path.join(sys.argv[1], codec + '.csv')) as f: + reader = csv.DictReader(f) + bpps = [] + results = dict() + for col in cols: + results[col] = [] + for row in reader: + bpp = row['bpp'] + bpps.append(bpp) + for col in cols: + results[col].append(float(row[col])) + data_sets[codec] = ([float(x) for x in bpps], results) + + print(data_sets) + + for col in cols: + fig = go.Figure() + for codec in codecs: + codec_results = data_sets[codec] + fig.add_trace(go.Scatter(x = codec_results[0], y = codec_results[1][col], name = codec_name[codec], showlegend = True)) + fig.update_traces(mode = 'markers+lines') + fig.update_xaxes(title_text = 'bits per pixel') + fig.update_yaxes(title_text = metric_name[col]) + fig.update_layout(legend = dict(title = dict(text = 'codec'))) + fig.update_layout(title = os.path.basename(sys.argv[1])) + fig.write_image(os.path.join(sys.argv[1], col + '.png')) + +if __name__ == '__main__': + main() diff --git a/crates/pyrowave-sys/vendor/pyrowave/metrics/triage.sh b/crates/pyrowave-sys/vendor/pyrowave/metrics/triage.sh new file mode 100644 index 00000000..90a5161b --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/metrics/triage.sh @@ -0,0 +1,168 @@ +#!/bin/bash + +set -e + +input_file="$1" +output_dir="$2" + +if [ -z $input_file ]; then + echo "Need to specify input." + exit 1 +fi + +if [ -z $output_dir ]; then + echo "Need to specify output." + exit 1 +fi + +mkdir -p "$output_dir" +rm -f "$output_dir"/*.csv + +csv_header="bpp,xpsnr,ssim,ssimulacra2,vmaf,vmafneg" +echo $csv_header > "$output_dir"/h264_nvenc.csv +echo $csv_header > "$output_dir"/hevc_nvenc.csv +echo $csv_header > "$output_dir"/av1_nvenc.csv +#echo $csv_header > "$output_dir"/h264_vaapi.csv +#echo $csv_header > "$output_dir"/hevc_vaapi.csv +#echo $csv_header > "$output_dir"/av1_vaapi.csv +echo $csv_header > "$output_dir"/pyrowave.csv + +append_stats_to_csv() +{ + stats=$1 + csv=$2 + + bpp=$(grep "BPP =" $stats | grep -oE '[^ ]+$') + xpsnr=$(grep "W-XPSNR:" $stats | grep -oE '[^ ]+$') + ssim=$(grep "SSIM Score:" $stats | grep -oE '[^ ]+$') + ssimulacra2=$(grep "Average:" $stats | grep -oE '[^ ]+$') + vmaf=$(grep "VMAF:" $stats | grep -oE '[^ ]+$') + vmafneg=$(grep "VMAF NEG:" $stats | grep -oE '[^ ]+$') + + echo "$bpp,$xpsnr,$ssim,$ssimulacra2,$vmaf,$vmafneg" >> $csv +} + +encode_nvenc() +{ + bit_rate=$1k + # Round up to not give codec an impossible situation + buf_size=$(($1 / 60 + 1))k + codec=$2 + encoded_name="$output_dir"/${codec}_nvenc_${bit_rate}.mkv + stats=""$output_dir"/${codec}_nvenc_stats_${bit_rate}.txt" + + echo "=============" + echo "Encoding with NVENC, bitrate ${bit_rate}." + echo ffmpeg -y -i $input_file -b:v $bit_rate -c:v ${codec}_nvenc \ + -preset p1 -tune ull -g 1 -rc cbr -bufsize $buf_size $encoded_name + ffmpeg -y -i $input_file -b:v $bit_rate -c:v ${codec}_nvenc \ + -preset p1 -tune ull -g 1 -rc cbr -bufsize $buf_size $encoded_name >/dev/null 2>/dev/null + ffmpeg -y -i $encoded_name $encoded_name.y4m >/dev/null 2>/dev/null + psy-ex-scores.py $input_file $encoded_name.y4m -t 16 -e 4 | ansi2txt > $stats + rm $encoded_name.y4m + echo "Stats in ${stats}, reference output in ${encoded_name}." + du -b $encoded_name + echo "=============" + + actual_size=$(stat -c %s $encoded_name) + input_size=$(stat -c %s $input_file) + bpp=$(echo "scale=3; 12 * $actual_size / $input_size" | bc) + echo "BPP = $bpp" >> $stats + + append_stats_to_csv $stats "$output_dir"/${codec}_nvenc.csv + + rm $encoded_name +} + +encode_vaapi() +{ + bit_rate=${1}k + # Round up to not give codec an impossible situation + buf_size=$(($1 / 60 + 1))k + codec=$2 + encoded_name="$output_dir"/${codec}_vaapi_${bit_rate}.mkv + stats=""$output_dir"/${codec}_vaapi_stats_${bit_rate}.txt" + echo "=============" + echo "Encoding with VAAPI, bitrate ${bit_rate}." + ffmpeg -y -vaapi_device /dev/dri/renderD128 -i $input_file -c:v ${codec}_vaapi \ + -idr_interval 1 -g 1 -rc_mode CBR -b:v $bit_rate -bufsize $buf_size \ + -vf format=nv12,hwupload $encoded_name >/dev/null 2>/dev/null + ffmpeg -y -i $encoded_name $encoded_name.y4m >/dev/null 2>/dev/null + psy-ex-scores.py $input_file $encoded_name.y4m -t 16 -e 4 | ansi2txt > $stats + rm $encoded_name.y4m + echo "Stats in ${stats}, reference output in ${encoded_name}." + du -b $encoded_name + echo "=============" + + actual_size=$(stat -c %s $encoded_name) + input_size=$(stat -c %s $input_file) + bpp=$(echo "scale=3; 12 * $actual_size / $input_size" | bc) + echo "BPP = $bpp" >> $stats + + append_stats_to_csv $stats "$output_dir"/${codec}_vaapi.csv + + rm $encoded_name +} + +encode_pyrowave() +{ + bit_rate=${1}k + bytes_per_image=$((($1 * 1000) / (60 * 8))) + encoded_name="$output_dir"/pyrowave_${bit_rate}.y4m + stats=""$output_dir"/pyrowave_stats_${bit_rate}.txt" + echo "=============" + echo "Encoding with PyroWave, bitrate ${bit_rate}, $bytes_per_image bytes per image." + pyrowave-sandbox $input_file $encoded_name $bytes_per_image 2>/dev/null + psy-ex-scores.py $input_file $encoded_name -t 16 -e 4 | ansi2txt > $stats + echo "Stats in ${stats}, reference output in ${encoded_name}." + echo "=============" + + bpp=$(echo "scale=3; 8 * $bytes_per_image / (1920 * 1080)" | bc) + echo "BPP = $bpp" >> $stats + append_stats_to_csv $stats "$output_dir"/pyrowave.csv + + rm $encoded_name +} + +encode_nvenc_group() +{ + encode_nvenc $1 h264 + encode_nvenc $1 hevc + encode_nvenc $1 av1 +} + +encode_vaapi_group() +{ + encode_vaapi $1 h264 + encode_vaapi $1 hevc + encode_vaapi $1 av1 +} + +encode_accel_group() +{ + encode_nvenc_group $1 + # VAAPI seems to not understand what CBR rate control means :') Ignore it. + #encode_vaapi_group $1 +} + +encode_pyrowave 50000 +encode_pyrowave 75000 +encode_pyrowave 100000 +encode_pyrowave 150000 +encode_pyrowave 200000 +encode_pyrowave 250000 +encode_pyrowave 300000 +encode_pyrowave 400000 +encode_pyrowave 500000 +encode_accel_group 50000 +encode_accel_group 75000 +encode_accel_group 100000 +encode_accel_group 150000 +encode_accel_group 200000 +encode_accel_group 250000 +encode_accel_group 300000 +encode_accel_group 400000 +encode_accel_group 500000 + +python plot.py $output_dir + diff --git a/crates/pyrowave-sys/vendor/pyrowave/pkg-config/pyrowave-shared.pc.in b/crates/pyrowave-sys/vendor/pyrowave/pkg-config/pyrowave-shared.pc.in new file mode 100644 index 00000000..2226f75f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pkg-config/pyrowave-shared.pc.in @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@PYROWAVE_INSTALL_LIB_DIR@ +sharedlibdir=@PYROWAVE_INSTALL_LIB_DIR@ +includedir=@PYROWAVE_INSTALL_INC_DIR@ + +Name: pyrowave-shared +Description: C API for pyrowave +Version: @PYROWAVE_API_VERSION@ + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lpyrowave-shared +Cflags: -I${includedir} diff --git a/crates/pyrowave-sys/vendor/pyrowave/psnr.cpp b/crates/pyrowave-sys/vendor/pyrowave/psnr.cpp new file mode 100644 index 00000000..15557566 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/psnr.cpp @@ -0,0 +1,117 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#include "yuv4mpeg.hpp" +#include +#include + +int main(int argc, char **argv) +{ + if (argc != 3) + { + fprintf(stderr, "Usage: a.y4m b.y4m\n"); + return EXIT_FAILURE; + } + + YUV4MPEGFile a, b; + + if (!a.open_read(argv[1])) + { + fprintf(stderr, "Failed to open %s.\n", argv[1]); + return EXIT_FAILURE; + } + + if (!b.open_read(argv[2])) + { + fprintf(stderr, "Failed to open %s.\n", argv[2]); + return EXIT_FAILURE; + } + + if (a.get_width() != b.get_width() || a.get_height() != b.get_height()) + { + fprintf(stderr, "Mismatch in parameters (%d, %d) != (%d, %d)\n", + a.get_width(), a.get_height(), b.get_width(), b.get_height()); + return EXIT_FAILURE; + } + + int num_luma_pixels = a.get_width() * a.get_height(); + int num_chroma_pixels = (a.get_width() / 2) * (a.get_height() / 2); + std::unique_ptr Y[2] = { + std::unique_ptr(new uint8_t[num_luma_pixels]), + std::unique_ptr(new uint8_t[num_luma_pixels]) }; + + std::unique_ptr Cb[2] = { + std::unique_ptr(new uint8_t[num_chroma_pixels]), + std::unique_ptr(new uint8_t[num_chroma_pixels]) }; + + std::unique_ptr Cr[2] = { + std::unique_ptr(new uint8_t[num_chroma_pixels]), + std::unique_ptr(new uint8_t[num_chroma_pixels]) }; + + uint64_t total_peak_signal[3] = {}; + uint64_t total_error[3] = {}; + uint64_t frame_peak_signal[3] = {}; + uint64_t frame_error[3] = {}; + + for (;;) + { + if (!a.begin_frame() || !b.begin_frame()) + break; + + if (!a.read(Y[0].get(), num_luma_pixels)) + break; + if (!b.read(Y[1].get(), num_luma_pixels)) + break; + + if (!a.read(Cb[0].get(), num_chroma_pixels)) + break; + if (!b.read(Cb[1].get(), num_chroma_pixels)) + break; + + if (!a.read(Cr[0].get(), num_chroma_pixels)) + break; + if (!b.read(Cr[1].get(), num_chroma_pixels)) + break; + + for (int i = 0; i < 3; i++) + frame_error[i] = 0; + + for (int i = 0; i < num_luma_pixels; i++) + { + int dY = Y[0][i] - Y[1][i]; + dY *= dY; + frame_error[0] += dY; + } + + for (int i = 0; i < num_chroma_pixels; i++) + { + int dCb = Cb[0][i] - Cb[1][i]; + int dCr = Cr[0][i] - Cr[1][i]; + dCb *= dCb; + dCr *= dCr; + frame_error[1] += dCb; + frame_error[2] += dCr; + } + + frame_peak_signal[0] = num_luma_pixels * 255ull * 255ull; + frame_peak_signal[1] = num_chroma_pixels * 255ull * 255ull; + frame_peak_signal[2] = num_chroma_pixels * 255ull * 255ull; + + fprintf(stderr, "PSNR: (Y) %4.4f dB, (Cb) %4.4f dB, (Cr) %4.4f dB\n", + 10.0 * std::log10(double(frame_peak_signal[0]) / double(frame_error[0])), + 10.0 * std::log10(double(frame_peak_signal[1]) / double(frame_error[1])), + 10.0 * std::log10(double(frame_peak_signal[2]) / double(frame_error[2]))); + + for (int i = 0; i < 3; i++) + { + total_peak_signal[i] += frame_peak_signal[i]; + total_error[i] += frame_error[i]; + } + } + + fprintf(stderr, "Overall PSNR: (Y) %4.4f dB, (Cb) %4.4f dB, (Cr) %4.4f dB\n", + 10.0 * std::log10(double(total_peak_signal[0]) / double(total_error[0])), + 10.0 * std::log10(double(total_peak_signal[1]) / double(total_error[1])), + 10.0 * std::log10(double(total_peak_signal[2]) / double(total_error[2]))); + +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave-shared.def b/crates/pyrowave-sys/vendor/pyrowave/pyrowave-shared.def new file mode 100644 index 00000000..13f4de7f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave-shared.def @@ -0,0 +1,38 @@ +LIBRARY libpyrowave-shared-0.dll + +EXPORTS + pyrowave_get_api_version + pyrowave_create_default_device + pyrowave_create_device_by_compat + pyrowave_create_device + pyrowave_device_set_command_buffer + pyrowave_device_report_performance_stats + pyrowave_device_get_vk_device_handles + pyrowave_device_confirm_interop_support + pyrowave_device_set_queue_type + pyrowave_device_destroy + pyrowave_sync_object_create + pyrowave_sync_object_get_semaphore + pyrowave_sync_object_export_handle + pyrowave_sync_object_cpu_wait + pyrowave_sync_object_cpu_signal + pyrowave_sync_object_destroy + pyrowave_image_create + pyrowave_image_get_handle + pyrowave_image_get_image_view + pyrowave_image_destroy + pyrowave_encoder_create + pyrowave_encoder_encode_gpu_synchronous + pyrowave_encoder_encode_cpu_synchronous + pyrowave_encoder_compute_num_packets + pyrowave_encoder_packetize + pyrowave_encoder_destroy + pyrowave_decoder_device_prefers_fragment_path + pyrowave_decoder_create + pyrowave_decoder_clear + pyrowave_decoder_push_packet + pyrowave_decoder_decode_is_ready + pyrowave_decoder_decode_gpu_buffer + pyrowave_decoder_decode_cpu_buffer_synchronous + pyrowave_decoder_destroy + diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave.h b/crates/pyrowave-sys/vendor/pyrowave/pyrowave.h new file mode 100644 index 00000000..fc0d5834 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave.h @@ -0,0 +1,546 @@ +// Copyright (c) 2026 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#ifndef PYROWAVE_H_ +#define PYROWAVE_H_ + +#if !defined(VULKAN_CORE_H_) +#error "Must include vulkan headers before including pyrowave.h" +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#else +#include +#endif + +// API and ABI is not considered stable until MAJOR version hits 1! + +#define PYROWAVE_API_VERSION_MAJOR 0 +#define PYROWAVE_API_VERSION_MINOR 4 +#define PYROWAVE_API_VERSION_PATCH 0 + +#if !defined(PYROWAVE_PUBLIC_API) +#if defined(PYROWAVE_EXPORT_SYMBOLS) +#if defined(__GNUC__) +#define PYROWAVE_PUBLIC_API __attribute__((visibility("default"))) +#elif defined(_MSC_VER) +#define PYROWAVE_PUBLIC_API __declspec(dllexport) +#else +#define PYROWAVE_PUBLIC_API +#endif +#else +#define PYROWAVE_PUBLIC_API +#endif +#else +#define PYROWAVE_PUBLIC_API +#endif + +typedef void (*pyrowave_message_cb)(void *userdata, const char *msg); + +typedef enum pyrowave_result +{ + PYROWAVE_SUCCESS = 0, + PYROWAVE_TIMEOUT = 1, + PYROWAVE_ERROR_GENERIC = -1, + PYROWAVE_ERROR_INVALID_ARGUMENT = -2, + PYROWAVE_ERROR_OUT_OF_HOST_MEMORY = -3, + PYROWAVE_ERROR_OUT_OF_DEVICE_MEMORY = -4, + PYROWAVE_ERROR_NO_VULKAN = -5, + PYROWAVE_ERROR_NOT_IMPLEMENTED = -6, + PYROWAVE_ERROR_UNSUPPORTED_EXTERNAL_HANDLE = -7, + PYROWAVE_ERROR_FAILED_EXTERNAL_HANDLE = -8, + PYROWAVE_ERROR_INT_MAX = 0x7fffffff +} pyrowave_result; + +typedef enum pyrowave_chroma_subsampling +{ + PYROWAVE_CHROMA_SUBSAMPLING_420 = 0, + PYROWAVE_CHROMA_SUBSAMPLING_444 = 1, + PYROWAVE_CHROMA_SUBSAMPLING_INT_MAX = 0x7fffffff +} pyrowave_chroma_subsampling; + +typedef struct pyrowave_encoder_opaque *pyrowave_encoder; +typedef struct pyrowave_decoder_opaque *pyrowave_decoder; +typedef struct pyrowave_device_opaque *pyrowave_device; +typedef struct pyrowave_sync_object_opaque *pyrowave_sync_object; +typedef struct pyrowave_image_opaque *pyrowave_image; + +// Used to dynamically detect any API/ABI incompatibility. +// This entry point is stable. +PYROWAVE_PUBLIC_API void pyrowave_get_api_version(uint32_t *major, uint32_t *minor, uint32_t *patch); + +// Device API. +PYROWAVE_PUBLIC_API pyrowave_result pyrowave_create_default_device(pyrowave_device *device); + +typedef struct pyrowave_device_create_queue_info +{ + VkQueue queue; + uint32_t familyIndex; + uint32_t index; +} pyrowave_device_create_queue_info; + +// Locks and unlocks submissions to all VkQueues on the VkDevice which the pyrowave_device as access to +// (either via vkGetDeviceQueue or queue_info structs). +typedef void (*pyrowave_queue_lock_cb)(void *userdata); + +typedef struct pyrowave_device_create_info +{ + // The vkGetInstanceProcAddr entry point for a valid Vulkan loader. + PFN_vkGetInstanceProcAddr GetInstanceProcAddr; + + // The Vulkan handles used to create the device. + VkInstance instance; + VkPhysicalDevice physical_device; + VkDevice device; + + // The CreateInfos used to create instance and device. + // The pointers and all contents inside them must remain valid for the lifetime of the pyrowave_device. + // device_create_info needs to supply valid queue create infos as well as + // extensions and pNext needs to contain PDF2 struct. + // Instance create infos needs valid extensions as well as a compatible pApplicationInfo w.r.t apiVersion. + // apiVersion should be at least Vulkan 1.3. + // At least one graphics capable queue must be present. + const VkInstanceCreateInfo *instance_create_info; + const VkDeviceCreateInfo *device_create_info; + + // Rather than calling vkGetDeviceQueue to get queues, + // implementation will look for a valid queue here first. + // This allows passing only graphics queue #2 for example. + // These queues should only be used for spurious uploads as needed. + pyrowave_device_create_queue_info *queue_info; + uint32_t queue_info_count; + + // Misc callbacks. Can be NULL. If device was created with VK_KHR_implicitly_synchronized_queued, locking + // callbacks are not needed. + // pyrowave device will only submit queue commands inside pyrowave device API calls, + // so that is another way to ensure synchronization. + pyrowave_queue_lock_cb queue_lock_callback; + pyrowave_queue_lock_cb queue_unlock_callback; + + // Userdata provided to callbacks. + void *userdata; +} pyrowave_device_create_info; + +typedef struct pyrowave_uuid +{ + uint8_t uuid[VK_UUID_SIZE]; +} pyrowave_uuid; + +typedef struct pyrowave_luid +{ + uint8_t luid[VK_LUID_SIZE]; +} pyrowave_luid; + +// Direct API that shares a VkDevice. Avoids needing to use external memory to encode and decode. +// Encoder expects features: +// - Basic subgroup support. ARITHMETIC, SHUFFLE, SHUFFLE_RELATIVE, VOTE, BALLOT, CLUSTERED, BASIC (Vulkan 1.1 core). +// - Subgroup size control (Vulkan 1.3 core). +// - Subgroup size control enough to force wave16, wave32 or wave64. +// - shaderInt16 +// - storageBuffer8BitAccess +// This covers all desktop GPUs and most mobile GPUs. +// Optional: +// - shaderFloat16 +// Decoder expects features: +// - Basic subgroup support. ARITHMETIC, SHUFFLE, SHUFFLE_RELATIVE, VOTE, BALLOT, BASIC (Vulkan 1.1 core). +// - Subgroup size control (Vulkan 1.3 core). +// - Anything from wave4 to wave128 goes as long as it supports subgroup size control. +// Should cover anything remotely relevant. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_create_device(const pyrowave_device_create_info *info, pyrowave_device *device); + +// On Windows, LUID is generally used, but other OS-es may need device_uuid/driver_uuid. +PYROWAVE_PUBLIC_API pyrowave_result pyrowave_create_device_by_compat( + // If non-zero, needs to match VkPhysicalDeviceProperties::vendorID/deviceID. + // Risks picking the wrong device if there are multiple ICDs for the same GPU. + uint32_t vid, uint32_t pid, + const pyrowave_uuid *device_uuid, // If non-NULL, needs to match VkPhysicalDeviceIDProperties::deviceUUID + const pyrowave_uuid *driver_uuid, // If non-NULL, needs to match VkPhysicalDeviceIDProperties::driverUUID + const pyrowave_luid *device_luid, // If non-NULL, needs to match VkPhysicalDeviceIDProperties::deviceLUID + pyrowave_device *device); + +// For performance debugging, reports GPU timestamps. +PYROWAVE_PUBLIC_API void +pyrowave_device_report_performance_stats(pyrowave_device device, pyrowave_message_cb cb, void *userdata, bool reset); + +// Out pointers can be NULL, in which case nothing is written to them. +PYROWAVE_PUBLIC_API void pyrowave_device_get_vk_device_handles( + pyrowave_device device, + VkInstance *vk_instance, VkPhysicalDevice *vk_physical_device, + VkDevice *vk_device); + +// If a command buffer is set on the device, any encoder or decoder commands which record Vulkan commands +// will record to cmd instead. +// pyrowave_device will not submit or close the command buffer. +// Any state on the command buffer is assumed to be clobbered. +// When recording is complete, set cmd to VK_NULL_HANDLE. +// pyrowave_device will only record commands directly inside an API entry point. +// The command buffer must be created for a an appropriate queue family based on how its used. +// Encoder: VK_QUEUE_COMPUTE_BIT. +// Decoder: VK_QUEUE_COMPUTE_BIT (if using normal path), VK_QUEUE_GRAPHICS_BIT (if using fragment path). +PYROWAVE_PUBLIC_API void +pyrowave_device_set_command_buffer(pyrowave_device device, VkCommandBuffer cmd); + +// When an explicit command buffer is not used, controls which queue family is preferred for encode or decode operations. +// This is typically used to select between graphics or async compute encoding. +// These methods have tradeoffs, but for cross-process encoding, it makes more sense to use async compute encode, +// since the graphics queue may become busy. +// If encoding in-process on QueuePresent or similar, graphics queue might make more sense, since it guarantees lowest possible encoding latency. +// For decoding, graphics queue is natural since the result will immediately be consumed there. +// Valid values for queue_flags are VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT. +// For borrowed devices, pyrowave must have been provided an async compute queue, or it will fallback to graphics. +// If there are no async compute queues on the device, graphics queue will be used instead. +// When explicit command buffers are used, queue_flags denotes which queue type the command buffer belongs to. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_device_set_queue_type(pyrowave_device device, VkQueueFlagBits queue_flags); + +PYROWAVE_PUBLIC_API bool +pyrowave_device_confirm_interop_support(pyrowave_device device); + +// All encoders and decoders must have been destroyed before destroying the device. +PYROWAVE_PUBLIC_API void pyrowave_device_destroy(pyrowave_device device); +//// + +// External sync API +// On Windows, this is a HANDLE reinterpreted as uintptr_t. +// On POSIX, it's a file descriptor int casted to uintptr_t. +typedef uintptr_t pyrowave_os_handle; + +typedef struct pyrowave_sync_object_create_info +{ + pyrowave_device device; + + // If this is an invalid handle according to the OS (NULL HANDLE, negative fd), + // the sync object is created as an exportable handle. + // If a handle is imported successfully, pyrowave_sync_object takes ownership of the OS handle. + pyrowave_os_handle external_handle; + + // Must be one of the supported handle types by the device. + // The implementation will fail the call with an appropriate error if not supported. + // Recognized types: + // - OPAQUE_FD + // - SYNC_FD_BIT + // - OPAQUE_WIN32_BIT + // - OPAQUE_WIN32_KMT_BIT + // - D3D12_FENCE_BIT (D3D11_FENCE_BIT is alias of D3D12_FENCE_BIT) + // NOTE: When importing NT handles, the implementation will take ownership and close the HANDLE on import. + // The semaphore holds a reference to the underlying object. + // It may be a good idea to call DuplicateHandle() and hand that over to the implementation instead. + // This has been known to workaround some weird bugs in the wild, but the root cause is unknown. + VkExternalSemaphoreHandleTypeFlagBits handle_type; + + // Binary or Timeline. For D3D11/D3D12 fence import, this must be TIMELINE. + VkSemaphoreType semaphore_type; + + // Only relevant for importing. + // For binary semaphores, this must be TEMPORARY for now. + // This makes the sync object fire and forget and can only be used once. + // TEMPORARY must not be used for timeline semaphores. + VkSemaphoreImportFlags import_flags; +} pyrowave_sync_object_create_info; + +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_sync_object_create(const pyrowave_sync_object_create_info *info, pyrowave_sync_object *sync); + +PYROWAVE_PUBLIC_API VkSemaphore +pyrowave_sync_object_get_semaphore(pyrowave_sync_object sync); + +// Called after signaling a semaphore, the sync payload can be exported to a handle. +// For timeline semaphores this can be called at any time if was created exportable. +// The common use case on Windows is to import a D3D12 fence timeline, never export, since +// not all implementations support exporting a timeline semaphore on that platform, +// but all support importing. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_sync_object_export_handle(pyrowave_sync_object sync, pyrowave_os_handle *handle); + +// Timeout interpreted as Vulkan API. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_sync_object_cpu_wait(pyrowave_sync_object sync, uint64_t value, uint64_t timeout); + +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_sync_object_cpu_signal(pyrowave_sync_object sync, uint64_t value); + +PYROWAVE_PUBLIC_API void pyrowave_sync_object_destroy(pyrowave_sync_object sync); +//// + +// External resource API +typedef struct pyrowave_image_view +{ + VkImage image; + // Extent of mip0. Must be consistent with width/height used to create the encoder. + // If the view is taking chroma of a planar image, + // the width/height is for the luma plane, i.e. the base image. + uint32_t width; + uint32_t height; + // Base format used to create the image. + VkFormat image_format; + + // Must be UNORM in some way and be supported for sampling and storage. + // For planar image_format, the image must have been created with + // VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT to be able to take plane views. + VkFormat view_format; + uint32_t mip_level; + uint32_t layer; + // If using a planar image format, needs to be e.g. VK_IMAGE_ASPECT_PLANE_*_BIT. + VkImageAspectFlagBits aspect; + // For decode path, must be IDENTITY or R. + VkComponentSwizzle swizzle; + // Must be VK_IMAGE_LAYOUT_(SHADER_)READ_ONLY_OPTIMAL (encode only) or VK_IMAGE_LAYOUT_GENERAL. + // For fragment decode path, must be (COLOR_)ATTACHMENT_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL. + // Pyrowave will not perform any image layout transitions on its own in the GPU buffer paths. + VkImageLayout layout; +} pyrowave_image_view; + +typedef struct pyrowave_image_create_info +{ + pyrowave_device device; + + // Must be a valid external handle. + // NOTE: When importing NT handles, the implementation will take ownership and close the HANDLE on import. + // The image holds a reference to the underlying object. + // It may be a good idea to call DuplicateHandle() and hand that over to the implementation instead. + // This has been known to workaround some weird bugs in the wild, but the root cause is unknown. + pyrowave_os_handle external_handle; + VkExternalMemoryHandleTypeFlagBits handle_type; + + // For OPAQUE handles, the create info must be conformant to spec requirements where the create infos + // have to match between creator and consumer. + // (In practice, this can be awkward especially when sharing between e.g. GL and Vulkan, + // spec calls for enabling "all" flags). + // For other types, image_create_info has to be compatible enough to make the sharing work. + // + // - Tiling must be OPTIMAL or DRM_FORMAT_MODIFIER_EXT. + // - Sharing mode must be EXCLUSIVE. + // - If a planar format like NV12 is used, the image must have MUTABLE_BIT image creation set. + const VkImageCreateInfo *image_create_info; + + // DRM format modifier usage: + // - Set image_create_info->tiling to VK_IMAGE_TILING_DRM_FORMAT_MODIFIER. + // - handle_type must be VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT. + // - VkImageDrmFormatModifierExplicitCreateInfoEXT must be chained into the pNext of image_create_info. + + // External images are always assumed to be in GENERAL layout. +} pyrowave_image_create_info; + +// Only intended to be used with external memory. For pyrowave_create_device() path +// application should create its own images and set the image view struct without going through this API. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_image_create(const pyrowave_image_create_info *info, pyrowave_image *image); + +PYROWAVE_PUBLIC_API VkImage +pyrowave_image_get_handle(pyrowave_image image); + +// Generates an image view from an (imported) image automatically for convenience. +// - Aspect must be VK_IMAGE_ASPECT_PLANE_0_BIT, PLANE_1_BIT or PLANE_2_BIT. +// - For 2-plane YCbCr image formats or two component image formats, image view swizzles are used to synthesize 3 planes. +// - For single component image formats, the aspect is ignored (the image is the plane itself). +// - For 3-component image formats, the aspect selects the component index through image swizzle. +// +// Some validation rules: +// - For 2-plane YCbCr image formats, usage must not be STORAGE_BIT. +// - For non-YCbCr image formats with more than 1 component, usage must not be STORAGE_BIT. +// - Usage must be VK_IMAGE_USAGE_STORAGE_BIT (for decode) or VK_IMAGE_USAGE_SAMPLED_BIT (for encode). +// - The format of the image must be recognized. Highly unusual formats may be rejected. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_image_get_image_view(pyrowave_image image, VkImageAspectFlagBits aspect, + VkImageUsageFlagBits usage, pyrowave_image_view *view); + +PYROWAVE_PUBLIC_API void pyrowave_image_destroy(pyrowave_image image); +//// + +// Encoder API +typedef struct pyrowave_encoder_create_info +{ + pyrowave_device device; + // For 420 subsampling, must be even. + int width; + int height; + pyrowave_chroma_subsampling chroma; +} pyrowave_encoder_create_info; + +typedef struct pyrowave_packet +{ + size_t offset; + size_t size; +} pyrowave_packet; + +typedef struct pyrowave_sync_point +{ + // Can be VK_NULL_HANDLE, in which case it means "no sync". + VkSemaphore semaphore; + + // If semaphore is a binary semaphore, value must be 0. + // NOTE: While waiting for a timeline semaphore value of 0 is valid Vulkan, + // it's a noop and can be replaced with that. + uint64_t value; +} pyrowave_sync_point; + +typedef struct pyrowave_gpu_external_reference +{ + pyrowave_image image; + // VK_QUEUE_FAMILY_EXTERNAL, _FOREIGN, _IGNORED or a normal queue family index. + uint32_t queue_family_index; +} pyrowave_gpu_external_reference; + +typedef struct pyrowave_gpu_buffers +{ + // All 3 planes must be provided. For NV12 images, pass in the same plane for Cb and Cr, but use swizzle + // to select R and G planes to fake a YUV420P image. + // Very slightly less efficient, but should barely be measurable. + // pyrowave_image_get_image_view() can be used as a helper to fill these in. + pyrowave_image_view planes[3]; +} pyrowave_gpu_buffers; + +typedef struct pyrowave_gpu_sync_operation +{ + // If interacting with external images, it's expected that implementation needs to acquire and release the image. + // Decode only: + // If acquiring from QUEUE_FAMILY_IGNORED, + // the image will be transitioned away from VK_IMAGE_LAYOUT_UNDEFINED instead rather than taking ownership. + // In Vulkan, if content does not have to be preserved (i.e. decoding), it can just be discarded with UNDEFINED. + const pyrowave_gpu_external_reference *images; + size_t num_images; + pyrowave_sync_point sync; +} pyrowave_gpu_sync_operation; + +// TODO: Add support for importing external memory as GPU buffers. + +// The CPU path is mostly for bringup testing. +typedef enum pyrowave_cpu_buffer_format +{ + PYROWAVE_CPU_BUFFER_FORMAT_NV12 = 0, // 2 planes. Y packed in 8bpp, then CbCr packed in 16bpp. Only supported for encoding. + PYROWAVE_CPU_BUFFER_FORMAT_YUV420P = 1, // 3 planes. Y, Cb, Cr packed into separate planes. Native format for pyrowave. + PYROWAVE_CPU_BUFFER_FORMAT_YUV444P = 2, // 3 planes. Y, Cb, Cr packed into separate planes. Native format for pyrowave. + PYROWAVE_CPU_BUFFER_FORMAT_INT_MAX = 0x7fffffff +} pyrowave_cpu_buffer_format; + +typedef struct pyrowave_cpu_buffer +{ + // Written in decoder, read-only in encoder. + void *data[3]; + // Must be at least width for plane times texel size of the plane. + size_t row_stride_in_bytes[3]; + // Must be at least row_stride times height of plane. + size_t plane_size_in_bytes[3]; + // Size of the luma plane. Size of chroma is implied by format. + // Must be same extent as decoder. + int width; + int height; + pyrowave_cpu_buffer_format format; +} pyrowave_cpu_buffer; + +typedef struct pyrowave_rate_control +{ + // Very basic, target bitstream for an image must not exceed this size. + size_t maximum_bitstream_size; +} pyrowave_rate_control; + +// The entry points for encoder are not thread safe. Application must ensure synchronization. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_encoder_create(const pyrowave_encoder_create_info *info, pyrowave_encoder *encoder); + +// Synchronous encode API. For low-latency use cases, overlapping frames in encode is meaningless +// due to latency and the encoder is so fast anyway. This function will not block, but subsequent functions will. +// Calling an encode operation with synchronous API clobbers any previous encoded frame. +// The encoded stream will contain a small sequence counter that tracks frame ordering. +// acquire and release can be NULL if no sync is required. +// If command buffer is set on pyrowave_device, acquire and release must both be NULL. +// If command buffer is set on pyrowave_device, applications is responsible for submitting that work to GPU +// and waiting for it before calling pyrowave_encoder_compute_num_packets or pyrowave_encoder_packetize. +// If command buffer is set, application must ensure synchronization as: +// - Before, the layouts in buffers must be correct. +// Memory must be visible to COMPUTE_SHADER / SHADER_SAMPLED_READ. +// - After: Application must add execution barrier on COMPUTE_SHADER stage before writing to images. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_encoder_encode_gpu_synchronous(pyrowave_encoder encoder, + const pyrowave_gpu_sync_operation *acquire, + const pyrowave_gpu_sync_operation *release, + const pyrowave_gpu_buffers *buffers, + const pyrowave_rate_control *rate_control); + +// A command buffer must not be set on pyrowave_device. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_encoder_encode_cpu_synchronous(pyrowave_encoder encoder, const pyrowave_cpu_buffer *buffers, + const pyrowave_rate_control *rate_control); + +// Can only be called after a successful encoding operation and result is only valid for that particular frame. +// Computes the number of network packets required if each packet can consume a provided number of bytes. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_encoder_compute_num_packets(pyrowave_encoder encoder, size_t packet_boundary, size_t *num_packets); + +// Number of packets is implied to be greater-than-equal to num_packets as returned earlier. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_encoder_packetize(pyrowave_encoder encoder, pyrowave_packet *packets, size_t packet_boundary, + size_t *out_packets, void *bitstream, size_t size); + +// Implementation ensures GPU is idle before destroying objects. +PYROWAVE_PUBLIC_API void +pyrowave_encoder_destroy(pyrowave_encoder encoder); +////// + +// Decoder +typedef struct pyrowave_decoder_create_info +{ + pyrowave_device device; + // For 420 subsampling, must be even. + int width; + int height; + pyrowave_chroma_subsampling chroma; + bool fragment_path; +} pyrowave_decoder_create_info; + +// Fragment path is optimized for typical mobile GPUs which have weak compute support. +// iDWT is instead computed entirely in traditional render passes and fragment shaders. +// This path is *not* recommended for desktop-class chips. +PYROWAVE_PUBLIC_API bool +pyrowave_decoder_device_prefers_fragment_path(pyrowave_device device); + +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_decoder_create(const pyrowave_decoder_create_info *info, pyrowave_decoder *decoder); + +// Throws away all queued packets. +PYROWAVE_PUBLIC_API void pyrowave_decoder_clear(pyrowave_decoder decoder); + +// A frame is potentially split into multiple packets. +// If a packet is pushed for a frame that is deemed to arrive earlier, it is dropped. +// A packet that is pushed for a frame with a higher frame sequence will clear out the old queued frame and start a new frame. +// Packets are pushed into the decoder until decode_is_ready says it's ready. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_decoder_push_packet(pyrowave_decoder decoder, const void *data, size_t size); + +// For error correction purposes, it may be okay to decode a frame which dropped some packets. +PYROWAVE_PUBLIC_API bool +pyrowave_decoder_decode_is_ready(pyrowave_decoder decoder, bool allow_partial_frame); + +// Decoding can be done at any time, leading to potentially corrupt/incomplete results if packets are missing. +// Missing wavelet weights are assumed to be 0 which can lead to extra blurring. +// See pyrowave_decoder_decode_is_ready() to determine if the final result is known to be complete. +// acquire and release can be NULL if no sync is required. +// If command buffer is set on pyrowave_device, acquire and release must both be NULL. +// If command buffer is set, application must ensure synchronization as: +// - Before, the layouts in buffers must be correct. +// If fragment path, memory must be visible to COLOR_ATTACHMENT_OUTPUT / COLOR_ATTACHMENT_WRITE. +// If compute path, memory must be visible to COMPUTE_SHADER / SHADER_STORAGE_WRITE. +// - After: Application must synchronize against the stages above before it can read or transition away. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_decoder_decode_gpu_buffer(pyrowave_decoder decoder, + const pyrowave_gpu_sync_operation *acquire, + const pyrowave_gpu_sync_operation *release, + const pyrowave_gpu_buffers *buffers); + +// A command buffer must not be set on pyrowave_device. +PYROWAVE_PUBLIC_API pyrowave_result +pyrowave_decoder_decode_cpu_buffer_synchronous(pyrowave_decoder decoder, const pyrowave_cpu_buffer *buffers); + +// Implementation ensures GPU is idle before destroying objects. +PYROWAVE_PUBLIC_API void pyrowave_decoder_destroy(pyrowave_decoder decoder); +////// + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_c.cpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_c.cpp new file mode 100644 index 00000000..114b0bfc --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_c.cpp @@ -0,0 +1,1498 @@ +// Copyright (c) 2026 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#include "context.hpp" +#include "device.hpp" +#include "image.hpp" +#include "buffer.hpp" +#include "pyrowave.h" +#include "pyrowave_decoder.hpp" +#include "pyrowave_encoder.hpp" +#include "logging.hpp" + +using namespace Granite; +using namespace Vulkan; +using namespace PyroWave; + +struct NullLogger : Util::LoggingInterface +{ + bool log(const char *, const char *, va_list) override + { +#ifdef VULKAN_DEBUG + return false; +#else + return true; +#endif + } +}; + +static NullLogger null_logger; + +extern "C" { +void pyrowave_get_api_version(uint32_t *major, uint32_t *minor, uint32_t *patch) +{ + *major = PYROWAVE_API_VERSION_MAJOR; + *minor = PYROWAVE_API_VERSION_MINOR; + *patch = PYROWAVE_API_VERSION_PATCH; +} + +struct pyrowave_device_opaque +{ + Context context; + Device device; + VkCommandBuffer cmd = VK_NULL_HANDLE; + CommandBuffer::Type queue_type = CommandBuffer::Type::Generic; +}; + +void pyrowave_device_set_command_buffer(pyrowave_device device, VkCommandBuffer cmd) +{ + device->cmd = cmd; +} + +pyrowave_result pyrowave_create_device_by_compat( + // If non-zero, needs to match VkPhysicalDeviceProperties::vendorID/deviceID. + // Risks picking the wrong device if there are multiple ICDs for the same GPU. + uint32_t vid, uint32_t pid, + const pyrowave_uuid *device_uuid, // If non-NULL, needs to match VkPhysicalDeviceIDProperties::deviceUUID + const pyrowave_uuid *driver_uuid, // If non-NULL, needs to match VkPhysicalDeviceIDProperties::driverUUID + const pyrowave_luid *device_luid, // If non-NULL, needs to match VkPhysicalDeviceIDProperties::deviceLUID + pyrowave_device *device) +{ + // TODO: Find a better way to do this. + Util::set_thread_logging_interface(&null_logger); + + if (!Context::init_loader(nullptr)) + return PYROWAVE_ERROR_NO_VULKAN; + + auto *dev = new pyrowave_device_opaque(); + dev->context.set_num_thread_indices(1); + dev->context.set_system_handles({}); + + VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; + app_info.apiVersion = VK_API_VERSION_1_2; + app_info.pApplicationName = "pyrowave-c"; + app_info.pEngineName = "Granite"; + dev->context.set_application_info(&app_info); + + // Just enable video extensions so that we can use video image usage, but don't bother creating queues for it, etc. + if (!dev->context.init_instance(nullptr, 0, CONTEXT_CREATION_ENABLE_VIDEO_FEATURE_ONLY_BIT)) + { + delete dev; + return PYROWAVE_ERROR_NO_VULKAN; + } + + uint32_t count; + if (vkEnumeratePhysicalDevices(dev->context.get_instance(), &count, nullptr) != VK_SUCCESS) + { + delete dev; + return PYROWAVE_ERROR_NO_VULKAN; + } + + std::vector gpus(count); + + if (vkEnumeratePhysicalDevices(dev->context.get_instance(), &count, gpus.data()) < 0) + { + delete dev; + return PYROWAVE_ERROR_NO_VULKAN; + } + + VkPhysicalDevice selected_gpu = VK_NULL_HANDLE; + + for (auto &gpu : gpus) + { + VkPhysicalDeviceProperties props = {}; + vkGetPhysicalDeviceProperties(gpu, &props); + // Is this even possible these days? + if (props.apiVersion < VK_API_VERSION_1_2) + continue; + + VkPhysicalDeviceIDProperties ids = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES }; + VkPhysicalDeviceProperties2 props2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &ids }; + vkGetPhysicalDeviceProperties2(gpu, &props2); + + if (vid && props2.properties.vendorID != vid) + continue; + if (pid && props2.properties.deviceID != pid) + continue; + + if (device_uuid && memcmp(device_uuid, ids.deviceUUID, VK_UUID_SIZE) != 0) + continue; + if (driver_uuid && memcmp(driver_uuid, ids.driverUUID, VK_UUID_SIZE) != 0) + continue; + if (device_luid && !ids.deviceLUIDValid) + continue; + if (device_luid && memcmp(device_luid, ids.deviceLUID, VK_LUID_SIZE) != 0) + continue; + + if (dev->context.init_device(gpu, VK_NULL_HANDLE, nullptr, 0, CONTEXT_CREATION_ENABLE_VIDEO_FEATURE_ONLY_BIT)) + { + selected_gpu = gpu; + break; + } + } + + if (!selected_gpu) + { + delete dev; + return PYROWAVE_ERROR_NO_VULKAN; + } + + dev->device.set_context(dev->context); + *device = dev; + return PYROWAVE_SUCCESS; +} + +pyrowave_result pyrowave_create_default_device(pyrowave_device *device) +{ + return pyrowave_create_device_by_compat(0, 0, nullptr, nullptr, nullptr, device); +} + +static std::mutex global_device_lock; + +pyrowave_result pyrowave_create_device(const pyrowave_device_create_info *info, pyrowave_device *out_device) +{ + // TODO: Find a better way to do this. + Util::set_thread_logging_interface(&null_logger); + + // Safety against concurrent device creations since we're setting global function pointer state here. + std::lock_guard holder{global_device_lock}; + + if (!Context::init_loader(info->GetInstanceProcAddr)) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + struct MyInstanceFactory : InstanceFactory + { + const pyrowave_device_create_info *info = nullptr; + + VkInstance create_instance(const VkInstanceCreateInfo *) override + { + return info->instance; + } + + // Lifetime of any data in create info must remain as long as Context is alive. + const VkInstanceCreateInfo *get_existing_create_info() override + { + return info->instance_create_info; + } + + bool factory_owns_created_instance() override + { + return true; + } + } instance; + + struct MyDeviceFactory : DeviceFactory + { + const pyrowave_device_create_info *info = nullptr; + + VkDevice create_device(VkPhysicalDevice, const VkDeviceCreateInfo *) override + { + return info->device; + } + + const VkDeviceCreateInfo *get_existing_create_info() override + { + return info->device_create_info; + } + + bool factory_owns_created_device() override + { + return true; + } + + VkQueue get_queue(uint32_t family_index, uint32_t index) override + { + for (uint32_t i = 0; i < info->queue_info_count; i++) + if (info->queue_info[i].familyIndex == family_index && info->queue_info[i].index == index) + return info->queue_info[i].queue; + return VK_NULL_HANDLE; + } + } device; + + instance.info = info; + device.info = info; + + auto dev = new pyrowave_device_opaque; + dev->context.set_instance_factory(&instance); + dev->context.set_device_factory(&device); + + if (!dev->context.init_instance(nullptr, 0)) + return PYROWAVE_ERROR_NO_VULKAN; + + if (!dev->context.init_device(info->physical_device, VK_NULL_HANDLE, nullptr, 0)) + return PYROWAVE_ERROR_NO_VULKAN; + + dev->device.set_context(dev->context); + + dev->device.set_queue_lock( + [cb = info->queue_lock_callback, userdata = info->userdata]() { + if (cb) + cb(userdata); + }, + [cb = info->queue_unlock_callback, userdata = info->userdata]() { + if (cb) + cb(userdata); + }); + + *out_device = dev; + return PYROWAVE_SUCCESS; +} + +void pyrowave_device_report_performance_stats(pyrowave_device device, pyrowave_message_cb cb, void *userdata, bool reset) +{ + Util::set_thread_logging_interface(&null_logger); + + device->device.timestamp_log([=](const std::string &tag, const TimestampIntervalReport &report) + { + char msg[256]; + snprintf(msg, sizeof(msg), "%s: %.3f ms per frame\n", tag.c_str(), report.time_per_frame_context * 1e3); + cb(userdata, msg); + }); + + if (reset) + device->device.timestamp_log_reset(); +} + +void pyrowave_device_get_vk_device_handles( + pyrowave_device device, + VkInstance *vk_instance, VkPhysicalDevice *vk_physical_device, + VkDevice *vk_device) +{ + Util::set_thread_logging_interface(&null_logger); + + if (vk_instance) + *vk_instance = device->device.get_instance(); + if (vk_physical_device) + *vk_physical_device = device->device.get_physical_device(); + if (vk_device) + *vk_device = device->device.get_device(); +} + +static bool pyrowave_device_confirm_external_semaphore_support(pyrowave_device device) +{ + VkSemaphoreTypeCreateInfo type_info = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO }; + VkPhysicalDeviceExternalSemaphoreInfo sem_info = + { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, &type_info }; + VkExternalSemaphoreProperties sem_props = { VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES }; + +#ifdef _WIN32 + sem_info.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT; +#else + sem_info.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; +#endif + + type_info.semaphoreType = VK_SEMAPHORE_TYPE_BINARY; + vkGetPhysicalDeviceExternalSemaphoreProperties(device->device.get_physical_device(), &sem_info, &sem_props); + if (!(sem_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) + return false; + + type_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; + vkGetPhysicalDeviceExternalSemaphoreProperties(device->device.get_physical_device(), &sem_info, &sem_props); + if (!(sem_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) + return false; + +#ifdef _WIN32 + // Despite being a timeline, D3D12_FENCE was added before TIMELINE was added, and AMD drivers have + // at least gotten confused when trying to use TIMELINE type here in the past. + sem_info.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT; + sem_info.pNext = nullptr; + vkGetPhysicalDeviceExternalSemaphoreProperties(device->device.get_physical_device(), &sem_info, &sem_props); + if (!(sem_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) + return false; +#endif + + return true; +} + +static bool pyrowave_device_confirm_external_memory_support(pyrowave_device device) +{ + VkExternalImageFormatProperties external_props = { VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES }; + VkImageFormatProperties2 props2 = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, &external_props }; + VkPhysicalDeviceExternalImageFormatInfo external_format_info = + { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO }; + + // TODO: Android? +#ifndef _WIN32 + if (!device->device.get_device_features().supports_drm_modifiers) + return false; +#endif + + static const VkExternalMemoryHandleTypeFlagBits required_external_types[] = { +#ifdef _WIN32 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, +#else + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, +#endif + }; + + VkPhysicalDeviceImageDrmFormatModifierInfoEXT modifier_info = + { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT }; + + for (auto type : required_external_types) + { + external_format_info.handleType = type; + external_format_info.pNext = nullptr; + + if (type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) + { + VkDrmFormatModifierPropertiesEXT mod; + VkDrmFormatModifierPropertiesListEXT modifier_list = + { VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT }; + modifier_list.drmFormatModifierCount = 1; + modifier_list.pDrmFormatModifierProperties = &mod; + VkFormatProperties3 props3 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, &modifier_list }; + device->device.get_format_properties(VK_FORMAT_R8_UNORM, &props3); + + if (modifier_list.drmFormatModifierCount != 1) + return false; + + modifier_info.drmFormatModifier = mod.drmFormatModifier; + modifier_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + external_format_info.pNext = &modifier_info; + } + + if (!device->device.get_image_format_properties( + VK_FORMAT_R8_UNORM, VK_IMAGE_TYPE_2D, type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT ? + VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + 0, &external_format_info, &props2)) + return false; + + if (!(external_props.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) + return false; + } + + return true; +} + +bool pyrowave_device_confirm_interop_support(pyrowave_device device) +{ + Util::set_thread_logging_interface(&null_logger); + if (!device->device.get_device_features().supports_external) + return false; + if (!pyrowave_device_confirm_external_semaphore_support(device)) + return false; + if (!pyrowave_device_confirm_external_memory_support(device)) + return false; + + return true; +} + +pyrowave_result +pyrowave_device_set_queue_type(pyrowave_device device, VkQueueFlagBits queue_flags) +{ + if (!device) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + if (queue_flags != VK_QUEUE_GRAPHICS_BIT && queue_flags != VK_QUEUE_COMPUTE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + device->queue_type = queue_flags == VK_QUEUE_GRAPHICS_BIT ? CommandBuffer::Type::Generic : CommandBuffer::Type::AsyncCompute; + return PYROWAVE_SUCCESS; +} + +void pyrowave_device_destroy(pyrowave_device device) +{ + Util::set_thread_logging_interface(&null_logger); + + delete device; +} + +struct pyrowave_sync_object_opaque +{ + Device *device = nullptr; + Semaphore semaphore; +}; + +pyrowave_result +pyrowave_sync_object_create(const pyrowave_sync_object_create_info *info, pyrowave_sync_object *out_sync) +{ + Util::set_thread_logging_interface(&null_logger); + + if (!info->device) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if ((info->handle_type & ( + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT | + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT | + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT | + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) == 0) + { + return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + + auto &device = info->device->device; + + if (!device.get_device_features().supports_external) + return PYROWAVE_ERROR_NOT_IMPLEMENTED; + + auto sem = device.request_semaphore_external(info->semaphore_type, info->handle_type); + if (!sem) + return PYROWAVE_ERROR_UNSUPPORTED_EXTERNAL_HANDLE; + + ExternalHandle ext = {}; + ext.handle = (decltype(ext.handle))info->external_handle; + ext.semaphore_handle_type = info->handle_type; + if (ext && !sem->import_from_handle(ext)) + return PYROWAVE_ERROR_FAILED_EXTERNAL_HANDLE; + + if (!ext && !(info->import_flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT)) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + auto *sync = new pyrowave_sync_object_opaque(); + sync->device = &device; + sync->semaphore = std::move(sem); + + *out_sync = sync; + return PYROWAVE_SUCCESS; +} + +VkSemaphore +pyrowave_sync_object_get_semaphore(pyrowave_sync_object sync) +{ + if (!sync) + return VK_NULL_HANDLE; + + Util::set_thread_logging_interface(&null_logger); + return sync->semaphore->get_semaphore(); +} + +pyrowave_result +pyrowave_sync_object_export_handle(pyrowave_sync_object sync, pyrowave_os_handle *handle) +{ + if (!sync) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + Util::set_thread_logging_interface(&null_logger); + if (auto native_handle = sync->semaphore->export_to_handle()) + { + *handle = (pyrowave_os_handle)native_handle.handle; + return PYROWAVE_SUCCESS; + } + else + { + return PYROWAVE_ERROR_FAILED_EXTERNAL_HANDLE; + } +} + +pyrowave_result +pyrowave_sync_object_cpu_wait(pyrowave_sync_object sync, uint64_t value, uint64_t timeout) +{ + if (!sync || sync->semaphore->get_semaphore_type() != VK_SEMAPHORE_TYPE_TIMELINE) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + Util::set_thread_logging_interface(&null_logger); + return sync->semaphore->wait_timeline_timeout(value, timeout) ? PYROWAVE_SUCCESS : PYROWAVE_TIMEOUT; +} + +pyrowave_result +pyrowave_sync_object_cpu_signal(pyrowave_sync_object sync, uint64_t value) +{ + if (!sync || sync->semaphore->get_semaphore_type() != VK_SEMAPHORE_TYPE_TIMELINE) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + Util::set_thread_logging_interface(&null_logger); + auto &table = sync->device->get_device_table(); + + VkSemaphoreSignalInfo signal_info = { VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO }; + signal_info.semaphore = sync->semaphore->get_semaphore(); + signal_info.value = value; + VkResult vr; + + if (table.vkSignalSemaphore) + vr = table.vkSignalSemaphore(sync->device->get_device(), &signal_info); + else if (table.vkSignalSemaphoreKHR) + vr = table.vkSignalSemaphoreKHR(sync->device->get_device(), &signal_info); + else + return PYROWAVE_ERROR_GENERIC; + + return vr == VK_SUCCESS ? PYROWAVE_SUCCESS : PYROWAVE_ERROR_GENERIC; +} + +void pyrowave_sync_object_destroy(pyrowave_sync_object sync) +{ + auto *device = sync->device; + Util::set_thread_logging_interface(&null_logger); + delete sync; + device->next_frame_context(); +} + +struct pyrowave_image_opaque +{ + Device *device = nullptr; + ImageHandle img; +}; + +pyrowave_result pyrowave_image_create(const pyrowave_image_create_info *info, pyrowave_image *out_image) +{ + Util::set_thread_logging_interface(&null_logger); + if (!info->device || !info->image_create_info) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + auto &device = info->device->device; + + if (info->image_create_info->sharingMode != VK_SHARING_MODE_EXCLUSIVE) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (info->handle_type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT && + info->image_create_info->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (info->handle_type != VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT && + info->image_create_info->tiling != VK_IMAGE_TILING_OPTIMAL) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (info->image_create_info->imageType != VK_IMAGE_TYPE_2D) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + ImageCreateInfo image_create_info = {}; + image_create_info.domain = ImageDomain::Physical; + image_create_info.misc = IMAGE_MISC_EXTERNAL_MEMORY_BIT | IMAGE_MISC_NO_DEFAULT_VIEWS_BIT; + image_create_info.external.handle = (decltype(image_create_info.external.handle))info->external_handle; + image_create_info.external.memory_handle_type = info->handle_type; + image_create_info.pnext = const_cast(info->image_create_info->pNext); + image_create_info.layout = ImageLayout::General; + image_create_info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + image_create_info.type = info->image_create_info->imageType; + image_create_info.format = info->image_create_info->format; + image_create_info.flags = info->image_create_info->flags; + image_create_info.width = info->image_create_info->extent.width; + image_create_info.height = info->image_create_info->extent.height; + image_create_info.depth = info->image_create_info->extent.depth; + image_create_info.layers = info->image_create_info->arrayLayers; + image_create_info.levels = info->image_create_info->mipLevels; + image_create_info.samples = info->image_create_info->samples; + image_create_info.usage = info->image_create_info->usage; + + if (device.get_device_features().driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY && + (info->handle_type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT || + info->handle_type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) + { + VkFormatProperties3 format_properties = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 }; + device.get_format_properties(image_create_info.format, &format_properties); + + if (format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR) + { + // NVIDIA workaround. For planar formats, the D3D side assumes video compatible layouts. + image_create_info.usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + + // If we're on an older driver, just pass it through as-is. + // Normally we have to pass down a codec profile, but this is mostly noise. + if (device.get_device_features().video_maintenance1_features.videoMaintenance1) + image_create_info.flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR; + } + } + + auto img = device.create_image(image_create_info); + if (!img) + return PYROWAVE_ERROR_FAILED_EXTERNAL_HANDLE; + + auto *image = new pyrowave_image_opaque(); + image->device = &device; + image->img = std::move(img); + + *out_image = image; + return PYROWAVE_SUCCESS; +} + +VkImage pyrowave_image_get_handle(pyrowave_image image) +{ + Util::set_thread_logging_interface(&null_logger); + return image->img->get_image(); +} + +pyrowave_result +pyrowave_image_get_image_view(pyrowave_image image, VkImageAspectFlagBits aspect, + VkImageUsageFlagBits usage, pyrowave_image_view *view) +{ + Util::set_thread_logging_interface(&null_logger); + + if ((aspect & (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)) == 0) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + if (usage != VK_IMAGE_USAGE_SAMPLED_BIT && usage != VK_IMAGE_USAGE_STORAGE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + auto &img = *image->img; + + *view = {}; + view->image = img.get_image(); + view->image_format = img.get_format(); + view->width = img.get_width(); + view->height = img.get_height(); + view->layout = VK_IMAGE_LAYOUT_GENERAL; + + // Handle the usual suspects. + switch (img.get_format()) + { + // Normal explicit planar formats. + case VK_FORMAT_R8_UNORM: + case VK_FORMAT_R16_UNORM: + view->aspect = VK_IMAGE_ASPECT_COLOR_BIT; + view->swizzle = VK_COMPONENT_SWIZZLE_IDENTITY; + view->view_format = img.get_format(); + break; + + case VK_FORMAT_R8G8_UNORM: + case VK_FORMAT_R16G16_UNORM: + if (usage == VK_IMAGE_USAGE_STORAGE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + if (aspect == VK_IMAGE_ASPECT_PLANE_0_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + view->aspect = VK_IMAGE_ASPECT_COLOR_BIT; + view->swizzle = aspect == VK_IMAGE_ASPECT_PLANE_2_BIT ? VK_COMPONENT_SWIZZLE_G : VK_COMPONENT_SWIZZLE_R; + view->view_format = img.get_format(); + break; + + // Special 4:4:4 HDR10 format + case VK_FORMAT_A2R10G10B10_UNORM_PACK32: + if (usage == VK_IMAGE_USAGE_STORAGE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + view->aspect = VK_IMAGE_ASPECT_COLOR_BIT; + view->view_format = img.get_format(); + + switch (aspect) + { + case VK_IMAGE_ASPECT_PLANE_0_BIT: view->swizzle = VK_COMPONENT_SWIZZLE_R; break; + case VK_IMAGE_ASPECT_PLANE_1_BIT: view->swizzle = VK_COMPONENT_SWIZZLE_G; break; + case VK_IMAGE_ASPECT_PLANE_2_BIT: view->swizzle = VK_COMPONENT_SWIZZLE_B; break; + default: return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + break; + + // 3-plane YCbCr + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: + view->view_format = VK_FORMAT_R8_UNORM; + view->aspect = aspect; + break; + + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: + view->view_format = VK_FORMAT_R10X6_UNORM_PACK16; + view->aspect = aspect; + break; + + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: + view->view_format = VK_FORMAT_R16_UNORM; + view->aspect = aspect; + break; + + // 2-plane YCbCr + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM: + switch (aspect) + { + case VK_IMAGE_ASPECT_PLANE_0_BIT: + view->view_format = VK_FORMAT_R8_UNORM; + view->aspect = VK_IMAGE_ASPECT_PLANE_0_BIT; + break; + + case VK_IMAGE_ASPECT_PLANE_1_BIT: + if (usage == VK_IMAGE_USAGE_STORAGE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + view->swizzle = VK_COMPONENT_SWIZZLE_R; + view->view_format = VK_FORMAT_R8G8_UNORM; + view->aspect = VK_IMAGE_ASPECT_PLANE_1_BIT; + break; + + case VK_IMAGE_ASPECT_PLANE_2_BIT: + if (usage == VK_IMAGE_USAGE_STORAGE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + view->swizzle = VK_COMPONENT_SWIZZLE_G; + view->view_format = VK_FORMAT_R8G8_UNORM; + view->aspect = VK_IMAGE_ASPECT_PLANE_1_BIT; + break; + + default: + return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + break; + + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16: + switch (aspect) + { + case VK_IMAGE_ASPECT_PLANE_0_BIT: + view->view_format = VK_FORMAT_R10X6_UNORM_PACK16; + view->aspect = VK_IMAGE_ASPECT_PLANE_0_BIT; + break; + + case VK_IMAGE_ASPECT_PLANE_1_BIT: + if (usage == VK_IMAGE_USAGE_STORAGE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + view->swizzle = VK_COMPONENT_SWIZZLE_R; + view->view_format = VK_FORMAT_R10X6G10X6_UNORM_2PACK16; + view->aspect = VK_IMAGE_ASPECT_PLANE_1_BIT; + break; + + case VK_IMAGE_ASPECT_PLANE_2_BIT: + if (usage == VK_IMAGE_USAGE_STORAGE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + view->swizzle = VK_COMPONENT_SWIZZLE_G; + view->view_format = VK_FORMAT_R10X6G10X6_UNORM_2PACK16; + view->aspect = VK_IMAGE_ASPECT_PLANE_1_BIT; + break; + + default: + return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + break; + + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM: + switch (aspect) + { + case VK_IMAGE_ASPECT_PLANE_0_BIT: + view->view_format = VK_FORMAT_R16_UNORM; + view->aspect = VK_IMAGE_ASPECT_PLANE_0_BIT; + break; + + case VK_IMAGE_ASPECT_PLANE_1_BIT: + if (usage == VK_IMAGE_USAGE_STORAGE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + view->swizzle = VK_COMPONENT_SWIZZLE_R; + view->view_format = VK_FORMAT_R16G16_UNORM; + view->aspect = VK_IMAGE_ASPECT_PLANE_1_BIT; + break; + + case VK_IMAGE_ASPECT_PLANE_2_BIT: + if (usage == VK_IMAGE_USAGE_STORAGE_BIT) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + view->swizzle = VK_COMPONENT_SWIZZLE_G; + view->view_format = VK_FORMAT_R16G16_UNORM; + view->aspect = VK_IMAGE_ASPECT_PLANE_1_BIT; + break; + + default: + return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + break; + + default: + return PYROWAVE_ERROR_NOT_IMPLEMENTED; + } + + return PYROWAVE_SUCCESS; +} + +void pyrowave_image_destroy(pyrowave_image image) +{ + auto *device = image->device; + Util::set_thread_logging_interface(&null_logger); + delete image; + + // Pump frame contexts through to make sure memory gets freed eventually. + device->next_frame_context(); +} + +struct pyrowave_encoder_opaque +{ + Device *device = nullptr; + pyrowave_device pyro_device = nullptr; + Encoder encoder; + Fence queued_fence; + BufferHandle queued_meta; + BufferHandle queued_bitstream; + ChromaSubsampling chroma = {}; + int width = 0; + int height = 0; +}; + +pyrowave_result +pyrowave_encoder_create(const pyrowave_encoder_create_info *info, pyrowave_encoder *encoder) +{ + Util::set_thread_logging_interface(&null_logger); + + if (!info->device) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (info->width <= 0 || info->height <= 0) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (info->chroma == PYROWAVE_CHROMA_SUBSAMPLING_420 && (info->width % 2 || info->height % 2)) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + auto *enc = new pyrowave_encoder_opaque(); + enc->pyro_device = info->device; + enc->device = &info->device->device; + enc->chroma = ChromaSubsampling(info->chroma); + enc->width = info->width; + enc->height = info->height; + + if (!enc->encoder.init(&info->device->device, info->width, info->height, enc->chroma)) + { + delete enc; + return PYROWAVE_ERROR_GENERIC; + } + + *encoder = enc; + return PYROWAVE_SUCCESS; +} + +struct WrappedViewBuffers : ViewBuffers +{ + ImageHandle wrapped_images[3]; + ImageViewHandle image_views[3]; + bool wrap(Device *device, const pyrowave_gpu_buffers *buffers, VkImageUsageFlags usage); +}; + +bool WrappedViewBuffers::wrap(Device *device, const pyrowave_gpu_buffers *buffers, VkImageUsageFlags usage) +{ + for (int i = 0; i < 3; i++) + { + ImageCreateInfo image_info = {}; + image_info.usage = usage; + image_info.type = VK_IMAGE_TYPE_2D; + image_info.domain = ImageDomain::Physical; + image_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + image_info.width = buffers->planes[i].width; + image_info.height = buffers->planes[i].height; + image_info.format = buffers->planes[i].image_format; + + // The exact numbers aren't important. + image_info.layers = buffers->planes[i].layer + 1; + image_info.levels = buffers->planes[i].mip_level + 1; + + image_info.layout = + buffers->planes[i].layout == VK_IMAGE_LAYOUT_GENERAL ? ImageLayout::General : ImageLayout::Optimal; + wrapped_images[i] = device->wrap_image(image_info, buffers->planes[i].image); + if (!wrapped_images[i]) + return false; + + ImageViewCreateInfo view_info = {}; + view_info.image = wrapped_images[i].get(); + view_info.format = buffers->planes[i].view_format; + view_info.view_type = VK_IMAGE_VIEW_TYPE_2D; + view_info.layers = 1; + view_info.levels = 1; + view_info.base_level = buffers->planes[i].mip_level; + view_info.base_layer = buffers->planes[i].layer; + view_info.swizzle.r = buffers->planes[i].swizzle; + view_info.swizzle.g = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.swizzle.b = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.swizzle.a = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.aspect = buffers->planes[i].aspect; + image_views[i] = device->create_image_view(view_info); + if (!image_views[i]) + return false; + + planes[i] = image_views[i].get(); + } + + return true; +} + +static void pyrowave_device_wait_semaphore(Device *device, CommandBuffer::Type queue_type, const pyrowave_gpu_sync_operation *acquire, VkPipelineStageFlags2 stages) +{ + if (acquire && acquire->sync.semaphore != VK_NULL_HANDLE) + { + auto sem = device->request_semaphore( + acquire->sync.value != 0 ? VK_SEMAPHORE_TYPE_TIMELINE : VK_SEMAPHORE_TYPE_BINARY, acquire->sync.semaphore); + sem->signal_external(); + + if (acquire->sync.value) + { + sem = device->request_timeline_semaphore_as_binary(*sem, acquire->sync.value); + sem->signal_external(); + } + + device->add_wait_semaphore(queue_type, std::move(sem), stages, false); + } +} + +static void pyrowave_device_signal_semaphore(Device *device, CommandBuffer::Type queue_type, const pyrowave_gpu_sync_operation *release) +{ + if (release && release->sync.semaphore != VK_NULL_HANDLE) + { + auto signal = device->request_semaphore( + release->sync.value != 0 ? VK_SEMAPHORE_TYPE_TIMELINE : VK_SEMAPHORE_TYPE_BINARY, release->sync.semaphore); + + if (release->sync.value) + signal = device->request_timeline_semaphore_as_binary(*signal, release->sync.value); + + if (signal) + device->submit_empty(queue_type, nullptr, signal.get()); + } +} + +pyrowave_result +pyrowave_encoder_encode_gpu_synchronous(pyrowave_encoder encoder, + const pyrowave_gpu_sync_operation *acquire, + const pyrowave_gpu_sync_operation *release, + const pyrowave_gpu_buffers *buffers, + const pyrowave_rate_control *rate_control) +{ + if (encoder->pyro_device->cmd && (acquire || release)) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + Util::set_thread_logging_interface(&null_logger); + auto *device = encoder->device; + + device->next_frame_context(); + + BufferCreateInfo bufinfo = {}; + bufinfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + bufinfo.size = encoder->encoder.get_meta_required_size(); + bufinfo.domain = BufferDomain::CachedHost; + encoder->queued_meta = device->create_buffer(bufinfo); + + if (!encoder->queued_meta) + return PYROWAVE_ERROR_OUT_OF_HOST_MEMORY; + + bufinfo.domain = BufferDomain::Device; + auto queued_meta_gpu = device->create_buffer(bufinfo); + + if (!queued_meta_gpu) + return PYROWAVE_ERROR_OUT_OF_DEVICE_MEMORY; + + auto target_bitstream_size = rate_control->maximum_bitstream_size & ~VkDeviceSize(3u); + + // Check for bogus sizes. + if (target_bitstream_size > UINT32_MAX || target_bitstream_size == 0) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + bufinfo.size = target_bitstream_size + encoder->encoder.get_meta_required_size(); + bufinfo.domain = BufferDomain::CachedHost; + encoder->queued_bitstream = device->create_buffer(bufinfo); + + if (!encoder->queued_bitstream) + return PYROWAVE_ERROR_OUT_OF_HOST_MEMORY; + + bufinfo.domain = BufferDomain::Device; + auto queued_bitstream_gpu = device->create_buffer(bufinfo); + + if (!queued_bitstream_gpu) + return PYROWAVE_ERROR_OUT_OF_DEVICE_MEMORY; + + Encoder::BitstreamBuffers bitstream_buffers = {}; + + WrappedViewBuffers views = {}; + if (!views.wrap(device, buffers, VK_IMAGE_USAGE_SAMPLED_BIT)) + return PYROWAVE_ERROR_OUT_OF_HOST_MEMORY; + + bitstream_buffers.meta.buffer = queued_meta_gpu.get(); + bitstream_buffers.meta.size = queued_meta_gpu->get_create_info().size; + bitstream_buffers.bitstream.buffer = queued_bitstream_gpu.get(); + bitstream_buffers.bitstream.size = queued_bitstream_gpu->get_create_info().size; + bitstream_buffers.target_size = target_bitstream_size; + + auto cmd = + encoder->pyro_device->cmd + ? device->request_borrowed_command_buffer(encoder->pyro_device->cmd) + : device->request_command_buffer(encoder->pyro_device->queue_type); + + if (acquire) + { + for (size_t i = 0; i < acquire->num_images; i++) + { + cmd->acquire_image_barrier(*acquire->images[i].image->img, + VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_2_SHADER_SAMPLED_READ_BIT, + acquire->images[i].queue_family_index); + } + } + + auto ret = encoder->encoder.encode(*cmd, views, bitstream_buffers); + if (!ret) + { + device->submit_discard(cmd); + return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + + if (release) + { + for (size_t i = 0; i < release->num_images; i++) + { + cmd->release_image_barrier(*release->images[i].image->img, + VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + release->images[i].queue_family_index); + } + } + + // NVIDIA really doesn't like it if we write bitstream to cached host. + // Performance issue since these memory types are mapped coherent on the GPU. + // A staging copy is just better. Could avoid it on iGPU, but iGPU isn't really supposed to be + // used as the encoder when streaming. + cmd->copy_buffer(*encoder->queued_meta, *queued_meta_gpu); + cmd->copy_buffer(*encoder->queued_bitstream, *queued_bitstream_gpu); + + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_HOST_BIT, VK_ACCESS_HOST_READ_BIT); + + pyrowave_device_wait_semaphore(device, encoder->pyro_device->queue_type, acquire, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + encoder->queued_fence.reset(); + + if (encoder->pyro_device->cmd) + { + device->submit_discard(cmd); + + // Technicality, image views we created have not been submitted yet to Vulkan. + // Need to signal the GPU queues before we can move the context along. + device->submit_external(encoder->pyro_device->queue_type); + } + else + device->submit(cmd, &encoder->queued_fence); + + pyrowave_device_signal_semaphore(device, encoder->pyro_device->queue_type, release); + + return PYROWAVE_SUCCESS; +} + +pyrowave_result +pyrowave_encoder_encode_cpu_synchronous(pyrowave_encoder encoder, const pyrowave_cpu_buffer *buffers, + const pyrowave_rate_control *rate_control) +{ + Util::set_thread_logging_interface(&null_logger); + int num_planes = buffers->format == PYROWAVE_CPU_BUFFER_FORMAT_NV12 ? 2 : 3; + auto *device = encoder->device; + ImageHandle images[3]; + + // Validate some assumptions. + if (buffers->width != encoder->width || buffers->height != encoder->height) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (encoder->chroma == ChromaSubsampling::Chroma420 && buffers->format == PYROWAVE_CPU_BUFFER_FORMAT_YUV444P) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + if (encoder->chroma == ChromaSubsampling::Chroma444 && buffers->format != PYROWAVE_CPU_BUFFER_FORMAT_YUV444P) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + for (int plane = 0; plane < num_planes; plane++) + { + int plane_width = encoder->width; + int plane_height = encoder->height; + + if (plane != 0 && encoder->chroma == ChromaSubsampling::Chroma420) + { + plane_width /= 2; + plane_height /= 2; + } + + const size_t plane_bpp = num_planes == 2 && plane == 1 ? 2 : 1; + + if (buffers->row_stride_in_bytes[plane] < plane_width * plane_bpp) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + if (buffers->row_stride_in_bytes[plane] * plane_height > buffers->plane_size_in_bytes[plane]) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + + for (int plane = 0; plane < num_planes; plane++) + { + unsigned plane_bpp = num_planes == 2 && plane == 1 ? 2 : 1; + + const ImageInitialData initial = { + buffers->data[plane], + uint32_t(buffers->row_stride_in_bytes[plane] / plane_bpp) + }; + + auto info = ImageCreateInfo::immutable_2d_image( + buffers->width, buffers->height, + plane_bpp == 2 ? VK_FORMAT_R8G8_UNORM : VK_FORMAT_R8_UNORM); + + if (plane != 0 && encoder->chroma == ChromaSubsampling::Chroma420) + { + info.width /= 2; + info.height /= 2; + } + + images[plane] = device->create_image(info, &initial); + if (!images[plane]) + return PYROWAVE_ERROR_OUT_OF_DEVICE_MEMORY; + } + + pyrowave_gpu_buffers gpu_buffers = {}; + + for (int plane = 0; plane < 3; plane++) + { + auto &p = gpu_buffers.planes[plane]; + p.width = images[plane] ? images[plane]->get_width() : images[1]->get_width(); + p.height = images[plane] ? images[plane]->get_height() : images[1]->get_height(); + + p.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + p.swizzle = num_planes == 2 && plane == 2 ? VK_COMPONENT_SWIZZLE_G : VK_COMPONENT_SWIZZLE_R; + p.image_format = images[plane] ? images[plane]->get_format() : VK_FORMAT_R8G8_UNORM; + p.view_format = p.image_format; + p.layout = images[plane] + ? images[plane]->get_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL) + : images[1]->get_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); + p.image = images[plane] ? images[plane]->get_image() : images[1]->get_image(); + } + + auto ret = pyrowave_encoder_encode_gpu_synchronous(encoder, nullptr, nullptr, &gpu_buffers, rate_control); + return ret; +} + +pyrowave_result +pyrowave_encoder_compute_num_packets(pyrowave_encoder encoder, size_t packet_boundary, size_t *num_packets) +{ + Util::set_thread_logging_interface(&null_logger); + if (encoder->queued_fence) + encoder->queued_fence->wait(); + + if (!encoder->queued_meta) + return PYROWAVE_ERROR_GENERIC; + + auto *mapped_meta = encoder->device->map_host_buffer(*encoder->queued_meta, MEMORY_ACCESS_READ_BIT); + *num_packets = encoder->encoder.compute_num_packets(mapped_meta, packet_boundary); + return PYROWAVE_SUCCESS; +} + +pyrowave_result +pyrowave_encoder_packetize(pyrowave_encoder encoder, pyrowave_packet *packets, size_t packet_boundary, + size_t *out_packets, void *bitstream, size_t size) +{ + Util::set_thread_logging_interface(&null_logger); + if (encoder->queued_fence) + encoder->queued_fence->wait(); + + if (!encoder->queued_meta || !encoder->queued_bitstream) + return PYROWAVE_ERROR_GENERIC; + + auto *mapped_meta = encoder->device->map_host_buffer(*encoder->queued_meta, MEMORY_ACCESS_READ_BIT); + auto *mapped_bitstream = encoder->device->map_host_buffer(*encoder->queued_bitstream, MEMORY_ACCESS_READ_BIT); + + *out_packets = encoder->encoder.packetize( + reinterpret_cast(packets), packet_boundary, bitstream, + size, mapped_meta, mapped_bitstream); + + return PYROWAVE_SUCCESS; +} + +void pyrowave_encoder_destroy(pyrowave_encoder encoder) +{ + auto *device = encoder->device; + Util::set_thread_logging_interface(&null_logger); + delete encoder; + device->next_frame_context(); +} + +struct pyrowave_decoder_opaque +{ + Device *device = nullptr; + pyrowave_device pyro_device = nullptr; + Decoder decoder; + ImageHandle planes[3]; + bool fragment_path = false; + ChromaSubsampling chroma = {}; + int width = 0; + int height = 0; +}; + +bool pyrowave_decoder_device_prefers_fragment_path(pyrowave_device device) +{ + Util::set_thread_logging_interface(&null_logger); + return Decoder::device_prefers_fragment_path(device->device); +} + +pyrowave_result +pyrowave_decoder_create(const pyrowave_decoder_create_info *info, pyrowave_decoder *decoder) +{ + Util::set_thread_logging_interface(&null_logger); + if (!info->device) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (info->width <= 0 || info->height <= 0) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (info->chroma == PYROWAVE_CHROMA_SUBSAMPLING_420 && (info->width % 2 || info->height % 2)) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + auto *dec = new pyrowave_decoder_opaque(); + dec->pyro_device = info->device; + dec->device = &info->device->device; + dec->chroma = ChromaSubsampling(info->chroma); + dec->fragment_path = info->fragment_path; + dec->width = info->width; + dec->height = info->height; + + if (!dec->decoder.init(dec->device, info->width, info->height, dec->chroma, info->fragment_path)) + { + delete dec; + return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + + *decoder = dec; + return PYROWAVE_SUCCESS; +} + +void pyrowave_decoder_clear(pyrowave_decoder decoder) +{ + Util::set_thread_logging_interface(&null_logger); + decoder->decoder.clear(); +} + +// A frame is potentially split into multiple packets. +pyrowave_result +pyrowave_decoder_push_packet(pyrowave_decoder decoder, const void *data, size_t size) +{ + Util::set_thread_logging_interface(&null_logger); + bool ret = decoder->decoder.push_packet(data, size); + return ret ? PYROWAVE_SUCCESS : PYROWAVE_ERROR_INVALID_ARGUMENT; +} + +// For error correction purposes, it may be okay to decode a frame which dropped some packets. +bool pyrowave_decoder_decode_is_ready(pyrowave_decoder decoder, bool allow_partial_frame) +{ + Util::set_thread_logging_interface(&null_logger); + return decoder->decoder.decode_is_ready(allow_partial_frame); +} + +pyrowave_result +pyrowave_decoder_decode_gpu_buffer(pyrowave_decoder decoder, + const pyrowave_gpu_sync_operation *acquire, + const pyrowave_gpu_sync_operation *release, + const pyrowave_gpu_buffers *buffers) +{ + if (decoder->pyro_device->cmd && (acquire || release)) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + Util::set_thread_logging_interface(&null_logger); + auto *device = decoder->device; + device->next_frame_context(); + + WrappedViewBuffers views = {}; + if (!views.wrap(device, buffers, decoder->fragment_path ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : VK_IMAGE_USAGE_STORAGE_BIT)) + return PYROWAVE_ERROR_OUT_OF_HOST_MEMORY; + + // Just use normal graphics queue here since the result will likely be consumed there. + auto cmd = decoder->pyro_device->cmd + ? device->request_borrowed_command_buffer(decoder->pyro_device->cmd) + : device->request_command_buffer(decoder->pyro_device->queue_type); + + VkPipelineStageFlags2 stages = decoder->fragment_path + ? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT + : VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + + VkAccessFlags2 access = decoder->fragment_path + ? VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT + : VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT; + + if (acquire) + { + for (size_t i = 0; i < acquire->num_images; i++) + { + if (acquire->images[i].queue_family_index != VK_QUEUE_FAMILY_IGNORED) + { + cmd->acquire_image_barrier(*acquire->images[i].image->img, + VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, + stages, access, acquire->images[i].queue_family_index); + } + else + { + cmd->image_barrier(*acquire->images[i].image->img, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + stages, 0, stages, access); + } + } + } + + auto ret = decoder->decoder.decode(*cmd, views); + if (!ret) + { + device->submit_discard(cmd); + return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + + if (release) + { + for (size_t i = 0; i < release->num_images; i++) + { + cmd->release_image_barrier(*release->images[i].image->img, + VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, + stages, access, release->images[i].queue_family_index); + } + } + + pyrowave_device_wait_semaphore(device, decoder->pyro_device->queue_type, acquire, stages); + + // This just queues up a command buffer, flush only happens when sync objects are signaled. + if (decoder->pyro_device->cmd) + { + device->submit_discard(cmd); + + // Technicality, image views we created have not been submitted yet to Vulkan. + // Need to signal the GPU queues before we can move the context along. + device->submit_external(decoder->pyro_device->queue_type); + } + else + device->submit(cmd); + + pyrowave_device_signal_semaphore(device, decoder->pyro_device->queue_type, release); + + return PYROWAVE_SUCCESS; +} + +pyrowave_result +pyrowave_decoder_decode_cpu_buffer_synchronous(pyrowave_decoder decoder, const pyrowave_cpu_buffer *buffers) +{ + if (decoder->pyro_device->cmd) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + Util::set_thread_logging_interface(&null_logger); + auto *device = decoder->device; + + if (buffers->width != decoder->width || buffers->height != decoder->height) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (buffers->format == PYROWAVE_CPU_BUFFER_FORMAT_NV12) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + if (decoder->chroma == ChromaSubsampling::Chroma420 && buffers->format == PYROWAVE_CPU_BUFFER_FORMAT_YUV444P) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + if (decoder->chroma == ChromaSubsampling::Chroma444 && buffers->format != PYROWAVE_CPU_BUFFER_FORMAT_YUV444P) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + + for (int plane = 0; plane < 3; plane++) + { + int plane_width = decoder->width; + int plane_height = decoder->height; + + if (plane != 0 && decoder->chroma == ChromaSubsampling::Chroma420) + { + plane_width /= 2; + plane_height /= 2; + } + + const size_t plane_bpp = 1; + + if (buffers->row_stride_in_bytes[plane] < plane_width * plane_bpp) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + if (buffers->row_stride_in_bytes[plane] * plane_height > buffers->plane_size_in_bytes[plane]) + return PYROWAVE_ERROR_INVALID_ARGUMENT; + } + + for (int plane = 0; plane < 3; plane++) + { + auto &img = decoder->planes[plane]; + + if (!img) + { + auto info = ImageCreateInfo::immutable_2d_image(buffers->width, buffers->height, VK_FORMAT_R8_UNORM); + info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + if (decoder->fragment_path) + { + info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + else + { + info.usage |= VK_IMAGE_USAGE_STORAGE_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_GENERAL; + info.layout = ImageLayout::General; + } + + if (plane != 0 && decoder->chroma == ChromaSubsampling::Chroma420) + { + info.width /= 2; + info.height /= 2; + } + + img = device->create_image(info); + if (!img) + return PYROWAVE_ERROR_OUT_OF_DEVICE_MEMORY; + } + } + + if (decoder->fragment_path) + { + auto cmd = device->request_command_buffer(decoder->pyro_device->queue_type); + cmd->begin_barrier_batch(); + for (auto &img : decoder->planes) + { + cmd->image_barrier(*img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_2_COPY_BIT, 0, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, + VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT); + } + cmd->end_barrier_batch(); + + // This just queues up a command buffer, flush only happens when sync objects are signaled. + device->submit(cmd); + } + + pyrowave_gpu_buffers gpu_buffers = {}; + for (int plane = 0; plane < 3; plane++) + { + auto &p = gpu_buffers.planes[plane]; + p.image = decoder->planes[plane]->get_image(); + p.width = decoder->planes[plane]->get_width(); + p.height = decoder->planes[plane]->get_height(); + p.image_format = decoder->planes[plane]->get_format(); + p.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + p.swizzle = VK_COMPONENT_SWIZZLE_IDENTITY; + p.view_format = p.image_format; + p.layout = decoder->fragment_path ? VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL; + } + + BufferCreateInfo bufinfo = {}; + BufferHandle readback_buffers[3]; + + auto res = pyrowave_decoder_decode_gpu_buffer(decoder, nullptr, nullptr, &gpu_buffers); + if (res != PYROWAVE_SUCCESS) + return res; + + auto cmd = device->request_command_buffer(decoder->pyro_device->queue_type); + + if (decoder->fragment_path) + { + cmd->begin_barrier_batch(); + for (auto &img : decoder->planes) + { + cmd->image_barrier(*img, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_READ_BIT); + } + cmd->end_barrier_batch(); + } + else + { + cmd->barrier(VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_READ_BIT); + } + + for (int plane = 0; plane < 3; plane++) + { + bufinfo.size = buffers->plane_size_in_bytes[plane]; + bufinfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + bufinfo.domain = BufferDomain::CachedHost; + readback_buffers[plane] = device->create_buffer(bufinfo); + + cmd->copy_image_to_buffer(*readback_buffers[plane], *decoder->planes[plane], 0, {}, + {decoder->planes[plane]->get_width(), decoder->planes[plane]->get_height(), 1}, + buffers->row_stride_in_bytes[plane], 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}); + } + + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_HOST_BIT, VK_ACCESS_2_HOST_READ_BIT); + + Fence fence; + device->submit(cmd, &fence); + fence->wait(); + + for (int plane = 0; plane < 3; plane++) + { + void *mapped = device->map_host_buffer(*readback_buffers[plane], MEMORY_ACCESS_READ_BIT); + memcpy(buffers->data[plane], mapped, buffers->plane_size_in_bytes[plane]); + } + + return PYROWAVE_SUCCESS; +} + +void pyrowave_decoder_destroy(pyrowave_decoder decoder) +{ + auto *device = decoder->device; + Util::set_thread_logging_interface(&null_logger); + delete decoder; + device->next_frame_context(); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_c_interop_test.cpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_c_interop_test.cpp new file mode 100644 index 00000000..65f8fde1 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_c_interop_test.cpp @@ -0,0 +1,1911 @@ +// Copyright (c) 2026 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#define INITGUID + +#include "device.hpp" +#include "context.hpp" +#include "image.hpp" + +#include "pyrowave.h" +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#include "com_ptr.hpp" +#endif + +using namespace Vulkan; + +#define ASSERT_THAT(x) do { \ + if (!(x)) { fprintf(stderr, "Fatal error executing %s at line %d.\n", #x, __LINE__); std::terminate(); } \ +} while(false) + +#define CHECKED(x) do { \ + pyrowave_result _res = x; \ + if (_res != PYROWAVE_SUCCESS) { fprintf(stderr, "Got pyrowave result %d while executing %s at line %d.\n", _res, #x, __LINE__); std::terminate(); } \ +} while(false) + +#define CHECK_HRESULT(x) ASSERT_THAT(SUCCEEDED(x)) + +static pyrowave_device create_device_from_granite(Device &device) +{ + // Verify that we can create a device from UUID/LUID. + VkPhysicalDeviceIDProperties ids = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES }; + VkPhysicalDeviceProperties2 props2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &ids }; + vkGetPhysicalDeviceProperties2(device.get_physical_device(), &props2); + + pyrowave_uuid device_uuid, driver_uuid; + pyrowave_luid device_luid; + + memcpy(device_uuid.uuid, ids.deviceUUID, VK_UUID_SIZE); + memcpy(driver_uuid.uuid, ids.driverUUID, VK_UUID_SIZE); + memcpy(device_luid.luid, ids.deviceLUID, VK_LUID_SIZE); + + pyrowave_device pyro_device; + CHECKED(pyrowave_create_device_by_compat(device.get_gpu_properties().vendorID, + device.get_gpu_properties().deviceID, &device_uuid, &driver_uuid, + ids.deviceLUIDValid ? &device_luid : nullptr, &pyro_device)); + + return pyro_device; +} + +static pyrowave_sync_object create_sync_object_from_timeline(pyrowave_device device, SemaphoreHolder &sem) +{ + auto exported_timeline = sem.export_to_handle(); + ASSERT_THAT(exported_timeline); + + pyrowave_sync_object_create_info sync_info = {}; + sync_info.device = device; + sync_info.handle_type = exported_timeline.semaphore_handle_type; + sync_info.semaphore_type = VK_SEMAPHORE_TYPE_TIMELINE; + sync_info.external_handle = (pyrowave_os_handle)exported_timeline.handle; + pyrowave_sync_object imported_timeline; + CHECKED(pyrowave_sync_object_create(&sync_info, &imported_timeline)); + return imported_timeline; +} + +static pyrowave_sync_object create_sync_object_from_binary(pyrowave_device device, SemaphoreHolder &sem) +{ + auto exported_timeline = sem.export_to_handle(); + ASSERT_THAT(exported_timeline); + + pyrowave_sync_object_create_info sync_info = {}; + sync_info.device = device; + sync_info.handle_type = exported_timeline.semaphore_handle_type; + sync_info.semaphore_type = VK_SEMAPHORE_TYPE_BINARY; + sync_info.external_handle = (pyrowave_os_handle)exported_timeline.handle; + sync_info.import_flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT; + pyrowave_sync_object imported_timeline; + CHECKED(pyrowave_sync_object_create(&sync_info, &imported_timeline)); + return imported_timeline; +} + +static pyrowave_image create_imported_image(pyrowave_device pyro_device, Device &device, Image &img) +{ + auto exported = img.export_handle(); + ASSERT_THAT(exported); + + VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + image_create_info.flags = img.get_create_info().flags; + image_create_info.usage = img.get_create_info().usage; + image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_create_info.format = img.get_create_info().format; + image_create_info.samples = img.get_create_info().samples; + image_create_info.mipLevels = img.get_create_info().levels; + image_create_info.arrayLayers = img.get_create_info().layers; + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + image_create_info.imageType = img.get_create_info().type; + image_create_info.extent = { img.get_width(), img.get_height(), img.get_depth() }; + + pyrowave_image_create_info image_info = {}; + image_info.device = pyro_device; + image_info.handle_type = exported.memory_handle_type; + image_info.external_handle = (pyrowave_os_handle)exported.handle; + image_info.image_create_info = &image_create_info; + + VkImageDrmFormatModifierExplicitCreateInfoEXT modifier_info = + { VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT }; + VkImageFormatListCreateInfo format_list = + { VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO }; + std::vector drm_plane_layouts; + + if (exported.memory_handle_type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) + { + image_create_info.pNext = &modifier_info; + image_create_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; + + if (img.get_format() == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM) + { + static const VkFormat nv12_formats[] = { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM }; + format_list.viewFormatCount = 2; + format_list.pViewFormats = nv12_formats; + } + else if (img.get_format() == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) + { + static const VkFormat yuv420p_formats[] = { VK_FORMAT_R8_UNORM }; + format_list.viewFormatCount = 1; + format_list.pViewFormats = yuv420p_formats; + } + else + { + format_list.viewFormatCount = 1; + format_list.pViewFormats = &image_create_info.format; + } + + // Query which DRM modifier the implementation picked for us and pass it along. + VkImageDrmFormatModifierPropertiesEXT props = { VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT }; + device.get_device_table().vkGetImageDrmFormatModifierPropertiesEXT( + device.get_device(), img.get_image(), &props); + modifier_info.drmFormatModifier = props.drmFormatModifier; + + VkDrmFormatModifierPropertiesListEXT modifiers = { VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT }; + VkFormatProperties3 props3 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, &modifiers }; + device.get_format_properties(image_create_info.format, &props3); + std::vector modifiers_props(modifiers.drmFormatModifierCount); + modifiers.pDrmFormatModifierProperties = modifiers_props.data(); + device.get_format_properties(image_create_info.format, &props3); + + auto itr = std::find_if(modifiers_props.begin(), modifiers_props.end(), [&](const VkDrmFormatModifierPropertiesEXT &prop) + { + return prop.drmFormatModifier == props.drmFormatModifier; + }); + + ASSERT_THAT(itr != modifiers_props.end()); + uint32_t num_memory_planes = itr->drmFormatModifierPlaneCount; + drm_plane_layouts.resize(num_memory_planes); + + // DRM format modifiers have per-plane stride information that needs to be queried ... + for (uint32_t i = 0; i < num_memory_planes; i++) + { + VkImageSubresource subresource = { + VkImageAspectFlags(VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT << i), + 0, 0 + }; + + device.get_device_table().vkGetImageSubresourceLayout(device.get_device(), + img.get_image(), &subresource, &drm_plane_layouts[i]); + + // On import, these must be cleared to be valid. + drm_plane_layouts[i].size = 0; + drm_plane_layouts[i].depthPitch = 0; + if (image_create_info.arrayLayers == 1) + drm_plane_layouts[i].arrayPitch = 0; + } + + // Pass it along to import. + modifier_info.drmFormatModifierPlaneCount = num_memory_planes; + modifier_info.pPlaneLayouts = drm_plane_layouts.data(); + modifier_info.pNext = &format_list; + } + + pyrowave_image imported_image; + CHECKED(pyrowave_image_create(&image_info, &imported_image)); + return imported_image; +} + +static uint8_t mirror(int v) +{ + v &= 511; + if (v > 255) + v = 511 - v; + ASSERT_THAT(v >= 0 && v <= 255); + return uint8_t(v); +} + +static ImageHandle create_exportable_test_image(Device &device, VkExternalMemoryHandleTypeFlagBits handle_type, + VkFormat format) +{ + auto info = ImageCreateInfo::immutable_2d_image(1280, 720, format); + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; + info.misc = IMAGE_MISC_NO_DEFAULT_VIEWS_BIT | IMAGE_MISC_EXTERNAL_MEMORY_BIT; + info.layout = ImageLayout::General; + info.initial_layout = VK_IMAGE_LAYOUT_GENERAL; + info.external.memory_handle_type = handle_type; + + // DRM format modifiers require explicit cast list when MUTABLE is used. + VkImageFormatListCreateInfo format_list = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO }; + + VkImageDrmFormatModifierListCreateInfoEXT allowed_modifiers_info = + { VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT }; + std::vector allowed_modifiers; + + if (handle_type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) + { + // Query all modifiers potentially supported by a format. + VkDrmFormatModifierPropertiesListEXT modifiers = { VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT }; + VkFormatProperties3 props3 = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, &modifiers }; + device.get_format_properties(info.format, &props3); + std::vector modifiers_props(modifiers.drmFormatModifierCount); + modifiers.pDrmFormatModifierProperties = modifiers_props.data(); + device.get_format_properties(info.format, &props3); + + if (format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM) + { + static const VkFormat nv12_formats[] = { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM }; + format_list.viewFormatCount = 2; + format_list.pViewFormats = nv12_formats; + } + else if (format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) + { + static const VkFormat yuv420p_formats[] = { VK_FORMAT_R8_UNORM }; + format_list.viewFormatCount = 1; + format_list.pViewFormats = yuv420p_formats; + } + else + { + format_list.viewFormatCount = 1; + format_list.pViewFormats = &format; + } + + for (uint32_t i = 0; i < modifiers.drmFormatModifierCount; i++) + { + auto &mod = modifiers.pDrmFormatModifierProperties[i]; + VkPhysicalDeviceImageDrmFormatModifierInfoEXT modinfo = + { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, &format_list }; + + modinfo.drmFormatModifier = mod.drmFormatModifier; + + VkImageFormatProperties2 props2 = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 }; + + // For DRM modifiers, it's a bit involved. + // Step 1 is to query which modifiers are supported for a given image. + if (device.get_image_format_properties(info.format, info.type, + VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, + info.usage, info.flags, &modinfo, &props2) && + info.width <= props2.imageFormatProperties.maxExtent.width && + info.height <= props2.imageFormatProperties.maxExtent.height) + { + allowed_modifiers.push_back(mod.drmFormatModifier); + } + } + + ASSERT_THAT(!allowed_modifiers.empty()); + + // Implementation picks one of the allowed modifiers. + allowed_modifiers_info.drmFormatModifierCount = allowed_modifiers.size(); + allowed_modifiers_info.pDrmFormatModifiers = allowed_modifiers.data(); + allowed_modifiers_info.pNext = &format_list; + info.pnext = &allowed_modifiers_info; + } + + auto img = device.create_image(info); + + if (format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM) + { + auto cmd = device.request_command_buffer(); + + auto *luma = static_cast(cmd->update_image(*img, {}, { 1280, 720, 1 }, 1280, 720, { VK_IMAGE_ASPECT_PLANE_0_BIT, 0, 0, 1 })); + auto *chroma = static_cast(cmd->update_image(*img, {}, { 640, 360, 1 }, 640, 360, { VK_IMAGE_ASPECT_PLANE_1_BIT, 0, 0, 1 })); + + for (int y = 0; y < 720; y++) + for (int x = 0; x < 1280; x++) + luma[y * 1280 + x] = mirror(y * 3 + 5 * x); + + for (int y = 0; y < 360; y++) + for (int x = 0; x < 640; x++) + chroma[y * 640 + x] = (uint16_t(mirror(y * 7 + 5 * x)) << 8) | mirror(y + 3 * x); + + device.submit(cmd); + } + + return img; +} + +static constexpr size_t BitstreamSize = 1000000; + +static void send_image_to_encoder(pyrowave_image pyro_image, + pyrowave_sync_object pyro_sync_acquire, uint64_t acquire_value, + pyrowave_sync_object pyro_sync_release, uint64_t release_value, + pyrowave_encoder encoder) +{ + pyrowave_gpu_external_reference ref = { pyro_image, VK_QUEUE_FAMILY_EXTERNAL }; + + pyrowave_gpu_sync_operation acquire = {}; + pyrowave_gpu_sync_operation release = {}; + pyrowave_gpu_buffers buffers = {}; + pyrowave_rate_control rate_control = { BitstreamSize }; + + CHECKED(pyrowave_image_get_image_view(pyro_image, + VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_USAGE_SAMPLED_BIT, &buffers.planes[0])); + CHECKED(pyrowave_image_get_image_view(pyro_image, + VK_IMAGE_ASPECT_PLANE_1_BIT, VK_IMAGE_USAGE_SAMPLED_BIT, &buffers.planes[1])); + CHECKED(pyrowave_image_get_image_view(pyro_image, + VK_IMAGE_ASPECT_PLANE_2_BIT, VK_IMAGE_USAGE_SAMPLED_BIT, &buffers.planes[2])); + + acquire.num_images = 1; + acquire.images = &ref; + acquire.sync.semaphore = pyrowave_sync_object_get_semaphore(pyro_sync_acquire); + acquire.sync.value = acquire_value; + + release.num_images = 1; + release.images = &ref; + release.sync.semaphore = pyrowave_sync_object_get_semaphore(pyro_sync_release); + release.sync.value = release_value; + + CHECKED(pyrowave_encoder_encode_gpu_synchronous(encoder, &acquire, &release, &buffers, &rate_control)); +} + +static void send_granite_image_to_encoder(Device &device, Image &granite_image, pyrowave_image pyro_image, + SemaphoreHolder &granite_sync, pyrowave_sync_object pyro_sync_acquire, uint64_t acquire_value, + pyrowave_sync_object pyro_sync_release, uint64_t release_value, + pyrowave_encoder encoder) +{ + auto cmd = device.request_command_buffer(); + cmd->release_image_barrier(granite_image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_QUEUE_FAMILY_EXTERNAL); + device.submit(cmd); + + if (acquire_value) + { + auto signal = device.request_timeline_semaphore_as_binary(granite_sync, acquire_value); + device.submit_empty(CommandBuffer::Type::Generic, nullptr, signal.get()); + } + +#ifdef VULKAN_DEBUG + // VVL doesn't quite understand it when a different device increments the shared timeline. + // It thinks that we're doing a rewind, but that's not the case. + // Only observed on Windows for some reason, but avoids a dumb false positive. + device.wait_idle(); +#endif + + send_image_to_encoder(pyro_image, pyro_sync_acquire, acquire_value, + pyro_sync_release, release_value, encoder); + + // Verify that the release value was signaled properly in finite time. + VkSemaphoreWaitInfo wait_info = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO }; + wait_info.pSemaphores = &granite_sync.get_semaphore(); + wait_info.semaphoreCount = 1; + wait_info.pValues = &release_value; + auto vr = device.get_device_table().vkWaitSemaphores(device.get_device(), &wait_info, 1000000000); + ASSERT_THAT(vr == VK_SUCCESS); +} + +static void decode_image(pyrowave_image *pyro_image, bool multiplane, + pyrowave_sync_object pyro_sync, uint64_t release_value, + pyrowave_decoder decoder) +{ + // Discard the image(s). + pyrowave_gpu_external_reference acquire_ref[3] = {}; + pyrowave_gpu_external_reference release_ref[3] = {}; + + pyrowave_gpu_sync_operation acquire = {}; + pyrowave_gpu_sync_operation release = {}; + pyrowave_gpu_buffers buffers = {}; + + for (int plane = 0; plane < (multiplane ? 1 : 3); plane++) + { + // Discard the output. + acquire_ref[plane] = { pyro_image[plane], VK_QUEUE_FAMILY_IGNORED }; + // Release back to other device. + release_ref[plane] = { pyro_image[plane], VK_QUEUE_FAMILY_EXTERNAL }; + } + + acquire.num_images = multiplane ? 1 : 3; + acquire.images = acquire_ref; + + release.num_images = multiplane ? 1 : 3; + release.images = release_ref; + release.sync.semaphore = pyrowave_sync_object_get_semaphore(pyro_sync); + release.sync.value = release_value; + + CHECKED(pyrowave_image_get_image_view(pyro_image[0], + VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_USAGE_STORAGE_BIT, &buffers.planes[0])); + CHECKED(pyrowave_image_get_image_view(pyro_image[multiplane ? 0 : 1], + VK_IMAGE_ASPECT_PLANE_1_BIT, VK_IMAGE_USAGE_STORAGE_BIT, &buffers.planes[1])); + CHECKED(pyrowave_image_get_image_view(pyro_image[multiplane ? 0 : 2], + VK_IMAGE_ASPECT_PLANE_2_BIT, VK_IMAGE_USAGE_STORAGE_BIT, &buffers.planes[2])); + + CHECKED(pyrowave_decoder_decode_gpu_buffer(decoder, &acquire, &release, &buffers)); +} + +static void send_payload_to_decoder(pyrowave_encoder encoder, pyrowave_decoder decoder) +{ + size_t num_packets; + CHECKED(pyrowave_encoder_compute_num_packets(encoder, BitstreamSize, &num_packets)); + ASSERT_THAT(num_packets == 1); + + pyrowave_packet packet; + std::unique_ptr bitstream(new uint8_t[BitstreamSize]); + CHECKED(pyrowave_encoder_packetize(encoder, &packet, BitstreamSize, &num_packets, bitstream.get(), BitstreamSize)); + CHECKED(pyrowave_decoder_push_packet(decoder, bitstream.get() + packet.offset, packet.size)); + ASSERT_THAT(pyrowave_decoder_decode_is_ready(decoder, false)); +} + +static void validate_mirror_buffer(const uint8_t *ptr, int width, int height, int row_stride, int dx, int dy) +{ + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + int reference = mirror(x * dx + y * dy); + int value = ptr[y * row_stride + x]; + int d = std::abs(reference - value); + ASSERT_THAT(d <= 1); + } + } +} + +static void validate_mirror_buffer(Device &device, Buffer &buf, int width, int height, int dx, int dy) +{ + auto *ptr = static_cast(device.map_host_buffer(buf, MEMORY_ACCESS_READ_BIT)); + validate_mirror_buffer(ptr, width, height, width, dx, dy); +} + +static void validate_granite_image(Device &device, Image &img, SemaphoreHolder &sem, uint64_t acquire_value) +{ + auto wait_sem = device.request_timeline_semaphore_as_binary(sem, acquire_value); + wait_sem->signal_external(); + device.add_wait_semaphore(CommandBuffer::Type::Generic, std::move(wait_sem), VK_PIPELINE_STAGE_2_COPY_BIT, true); + + auto cmd = device.request_command_buffer(); + + BufferCreateInfo bufinfo = {}; + bufinfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + bufinfo.size = img.get_width() * img.get_height(); + bufinfo.domain = BufferDomain::CachedHost; + + auto y = device.create_buffer(bufinfo); + + bufinfo.size /= 4; + auto cb = device.create_buffer(bufinfo); + auto cr = device.create_buffer(bufinfo); + + cmd->acquire_image_barrier(img, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_READ_BIT, VK_QUEUE_FAMILY_EXTERNAL); + + cmd->copy_image_to_buffer(*y, img, 0, {}, { img.get_width(), img.get_height(), 1 }, 1280, 720, + { VK_IMAGE_ASPECT_PLANE_0_BIT, 0, 0, 1 }); + cmd->copy_image_to_buffer(*cb, img, 0, {}, { img.get_width() / 2, img.get_height() / 2, 1 }, 640, 360, + { VK_IMAGE_ASPECT_PLANE_1_BIT, 0, 0, 1 }); + cmd->copy_image_to_buffer(*cr, img, 0, {}, { img.get_width() / 2, img.get_height() / 2, 1 }, 640, 360, + { VK_IMAGE_ASPECT_PLANE_2_BIT, 0, 0, 1 }); + + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_HOST_BIT, VK_ACCESS_2_HOST_WRITE_BIT); + + Fence fence; + device.submit(cmd, &fence); + fence->wait(); + + validate_mirror_buffer(device, *y, 1280, 720, 5, 3); + validate_mirror_buffer(device, *cb, 640, 360, 3, 1); + validate_mirror_buffer(device, *cr, 640, 360, 5, 7); +} + +static void test_direct_interop() +{ + ASSERT_THAT(Context::init_loader(nullptr)); + + Context ctx; + ctx.set_num_thread_indices(1); + ctx.set_system_handles({}); + + VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; + app_info.apiVersion = VK_API_VERSION_1_3; + app_info.pApplicationName = "pyrowave-c-test"; + app_info.pEngineName = "Granite"; + ctx.set_application_info(&app_info); + + ASSERT_THAT(ctx.init_instance_and_device(nullptr, 0, nullptr, 0)); + + Device device; + device.set_context(ctx); + + // Fill in a proxy instance create info. + VkInstanceCreateInfo instance_create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; + instance_create_info.enabledExtensionCount = device.get_device_features().num_instance_extensions; + instance_create_info.ppEnabledExtensionNames = device.get_device_features().instance_extensions; + instance_create_info.pApplicationInfo = &ctx.get_application_info(); + + // Fill in a proxy device create info. + VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + VkDeviceQueueCreateInfo queue_info = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; + queue_info.queueFamilyIndex = device.get_queue_info().family_indices[QUEUE_INDEX_GRAPHICS]; + queue_info.queueCount = 1; + device_create_info.pNext = ctx.get_enabled_device_features().pdf2; + device_create_info.enabledExtensionCount = ctx.get_enabled_device_features().num_device_extensions; + device_create_info.ppEnabledExtensionNames = ctx.get_enabled_device_features().device_extensions; + device_create_info.queueCreateInfoCount = 1; + device_create_info.pQueueCreateInfos = &queue_info; + + // Hand over a concrete VkQueue we want implementation to use. + pyrowave_device_create_queue_info device_queue_info = {}; + device_queue_info.familyIndex = queue_info.queueFamilyIndex; + device_queue_info.index = 0; + device_queue_info.queue = device.get_queue_info().queues[QUEUE_INDEX_GRAPHICS]; + + pyrowave_device_create_info info = {}; + info.GetInstanceProcAddr = vkGetInstanceProcAddr; + info.instance = ctx.get_instance(); + info.physical_device = ctx.get_gpu(); + info.device = ctx.get_device(); + info.device_create_info = &device_create_info; + info.instance_create_info = &instance_create_info; + info.queue_info_count = 1; + info.queue_info = &device_queue_info; + info.userdata = &device; + info.queue_lock_callback = [](void *userdata) { static_cast(userdata)->external_queue_lock(); }; + info.queue_unlock_callback = [](void *userdata) { static_cast(userdata)->external_queue_unlock(); }; + + pyrowave_encoder encoder; + pyrowave_decoder decoder; + pyrowave_device pyro_device; + CHECKED(pyrowave_create_device(&info, &pyro_device)); + + pyrowave_encoder_create_info encoder_info = {}; + encoder_info.device = pyro_device; + encoder_info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_444; + encoder_info.width = 64; + encoder_info.height = 64; + CHECKED(pyrowave_encoder_create(&encoder_info, &encoder)); + + pyrowave_decoder_create_info decoder_info = {}; + decoder_info.device = pyro_device; + decoder_info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_444; + decoder_info.width = 64; + decoder_info.height = 64; + CHECKED(pyrowave_decoder_create(&decoder_info, &decoder)); + + uint8_t plane_data[3][64][64]; + + for (int y = 0; y < 64; y++) + { + for (int x = 0; x < 64; x++) + { + plane_data[0][y][x] = y + x + 1; + plane_data[1][y][x] = y + x + 2; + plane_data[2][y][x] = y + x + 3; + } + } + + auto image_info = ImageCreateInfo::immutable_2d_image(64, 64, VK_FORMAT_R8_UNORM); + image_info.layers = 3; + image_info.initial_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + ImageInitialData initial_data[3] = { { plane_data[0] }, { plane_data[1] }, { plane_data[2] } }; + auto input_image = device.create_image(image_info, initial_data); + ASSERT_THAT(input_image); + + image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT; + image_info.initial_layout = VK_IMAGE_LAYOUT_GENERAL; + auto output_image = device.create_image(image_info); + ASSERT_THAT(output_image); + + pyrowave_rate_control rate_control = { 100000 }; + pyrowave_gpu_buffers gpu_buffers = {}; + + for (int i = 0; i < 3; i++) + { + gpu_buffers.planes[i].image = input_image->get_image(); + gpu_buffers.planes[i].width = 64; + gpu_buffers.planes[i].height = 64; + gpu_buffers.planes[i].image_format = VK_FORMAT_R8_UNORM; + gpu_buffers.planes[i].view_format = VK_FORMAT_R8_UNORM; + gpu_buffers.planes[i].layer = i; + gpu_buffers.planes[i].layout = input_image->get_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); + gpu_buffers.planes[i].mip_level = 0; + gpu_buffers.planes[i].aspect = VK_IMAGE_ASPECT_COLOR_BIT; + } + + auto cmd = device.request_command_buffer(); + + // Encode to provided cmd. + // Redirect commands here. + pyrowave_device_set_command_buffer(pyro_device, cmd->get_command_buffer()); + CHECKED(pyrowave_encoder_encode_gpu_synchronous(encoder, nullptr, nullptr, &gpu_buffers, &rate_control)); + pyrowave_device_set_command_buffer(pyro_device, VK_NULL_HANDLE); + + // Wait on CPU before we call packetization. + Fence fence; + device.submit(cmd, &fence); + fence->wait(); + + size_t num_packets; + CHECKED(pyrowave_encoder_compute_num_packets(encoder, rate_control.maximum_bitstream_size, &num_packets)); + ASSERT_THAT(num_packets == 1); + + std::unique_ptr bitstream(new uint8_t[rate_control.maximum_bitstream_size]); + pyrowave_packet packet; + CHECKED(pyrowave_encoder_packetize(encoder, &packet, rate_control.maximum_bitstream_size, &num_packets, + bitstream.get(), rate_control.maximum_bitstream_size)); + + CHECKED(pyrowave_decoder_push_packet(decoder, bitstream.get() + packet.offset, packet.size)); + ASSERT_THAT(pyrowave_decoder_decode_is_ready(decoder, false)); + + for (auto &plane : gpu_buffers.planes) + { + plane.image = output_image->get_image(); + plane.layout = VK_IMAGE_LAYOUT_GENERAL; + } + + cmd = device.request_command_buffer(); + // Redirect commands here. + pyrowave_device_set_command_buffer(pyro_device, cmd->get_command_buffer()); + CHECKED(pyrowave_decoder_decode_gpu_buffer(decoder, nullptr, nullptr, &gpu_buffers)); + pyrowave_device_set_command_buffer(pyro_device, VK_NULL_HANDLE); + + cmd->image_barrier(*output_image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_READ_BIT); + + BufferCreateInfo bufinfo = {}; + bufinfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + bufinfo.size = 64 * 64 * 3; + bufinfo.domain = BufferDomain::CachedHost; + + auto readback_buffer = device.create_buffer(bufinfo); + cmd->copy_image_to_buffer(*readback_buffer, *output_image, 0, {}, { 64, 64, 1 }, 0, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 3 }); + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_HOST_BIT, VK_ACCESS_2_HOST_READ_BIT); + fence.reset(); + device.submit(cmd, &fence); + fence->wait(); + + auto *readback_ptr = static_cast(device.map_host_buffer(*readback_buffer, MEMORY_ACCESS_READ_BIT)); + + for (int y = 0; y < 64; y++) + { + for (int x = 0; x < 64; x++) + { + int y_delta = std::abs(readback_ptr[0 * 64 * 64 + y * 64 + x] - (y + x + 1)); + int cb_delta = std::abs(readback_ptr[1 * 64 * 64 + y * 64 + x] - (y + x + 2)); + int cr_delta = std::abs(readback_ptr[2 * 64 * 64 + y * 64 + x] - (y + x + 3)); + ASSERT_THAT(y_delta <= 1); + ASSERT_THAT(cb_delta <= 1); + ASSERT_THAT(cr_delta <= 1); + } + } + + pyrowave_encoder_destroy(encoder); + pyrowave_decoder_destroy(decoder); + pyrowave_device_destroy(pyro_device); +} + +// Most basic interop scenario, OPAQUE_FD for everything. +static void test_opaque_interop(bool win32_kmt) +{ + ASSERT_THAT(Context::init_loader(nullptr)); + + Context ctx; + ctx.set_num_thread_indices(1); + ctx.set_system_handles({}); + ASSERT_THAT(ctx.init_instance_and_device(nullptr, 0, nullptr, 0)); + + Device device; + device.set_context(ctx); + + pyrowave_device pyro_device = create_device_from_granite(device); + + auto semaphore_type = win32_kmt ? + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT : ExternalHandle::get_opaque_semaphore_handle_type(); + auto memory_type = win32_kmt ? + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT : ExternalHandle::get_opaque_memory_handle_type(); + + // No impl seems to support OPAQUE_KMT timelines. + auto timeline_sem = device.request_semaphore_external(VK_SEMAPHORE_TYPE_TIMELINE, ExternalHandle::get_opaque_semaphore_handle_type()); + + ASSERT_THAT(timeline_sem); + pyrowave_sync_object imported_timeline = create_sync_object_from_timeline(pyro_device, *timeline_sem); + + auto exportable_nv12_image = create_exportable_test_image( + device, memory_type, + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM); + auto exportable_yuv420p_image = create_exportable_test_image( + device, memory_type, + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM); + + pyrowave_image imported_nv12_image = create_imported_image(pyro_device, device, *exportable_nv12_image); + pyrowave_image imported_yuv420p_image = create_imported_image(pyro_device, device, *exportable_yuv420p_image); + + auto binary_sem = device.request_semaphore_external(VK_SEMAPHORE_TYPE_BINARY, semaphore_type); + ASSERT_THAT(binary_sem); + device.submit_empty(CommandBuffer::Type::Generic, nullptr, binary_sem.get()); + pyrowave_sync_object imported_binary = create_sync_object_from_binary(pyro_device, *binary_sem); + + pyrowave_encoder_create_info encoder_info = {}; + encoder_info.device = pyro_device; + encoder_info.width = 1280; + encoder_info.height = 720; + encoder_info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_420; + pyrowave_encoder encoder; + CHECKED(pyrowave_encoder_create(&encoder_info, &encoder)); + + // Test the two ways we can send a sync payload, binary + temporary or persistent timeline. + // Verify it doesn't explode. + send_granite_image_to_encoder(device, *exportable_nv12_image, imported_nv12_image, + *timeline_sem, imported_timeline, 1, + imported_timeline, 2, + encoder); + + send_granite_image_to_encoder(device, *exportable_nv12_image, imported_nv12_image, + *timeline_sem, imported_binary, 0, + imported_timeline, 3, + encoder); + + // Pyrowave (or rather, Granite) API destroys objects in a deferred way. + pyrowave_sync_object_destroy(imported_binary); + + pyrowave_decoder_create_info decoder_info = {}; + decoder_info.device = pyro_device; + decoder_info.width = 1280; + decoder_info.height = 720; + decoder_info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_420; + pyrowave_decoder decoder; + CHECKED(pyrowave_decoder_create(&decoder_info, &decoder)); + + send_payload_to_decoder(encoder, decoder); + decode_image(&imported_yuv420p_image, true, imported_timeline, 4, decoder); + validate_granite_image(device, *exportable_yuv420p_image, *timeline_sem, 4); + + pyrowave_sync_object_destroy(imported_timeline); + pyrowave_image_destroy(imported_nv12_image); + pyrowave_image_destroy(imported_yuv420p_image); + pyrowave_encoder_destroy(encoder); + pyrowave_decoder_destroy(decoder); + pyrowave_device_destroy(pyro_device); +} + +static void test_drm_modifier_interop() +{ + ASSERT_THAT(Context::init_loader(nullptr)); + + Context ctx; + ctx.set_num_thread_indices(1); + ctx.set_system_handles({}); + ASSERT_THAT(ctx.init_instance_and_device(nullptr, 0, nullptr, 0)); + + Device device; + device.set_context(ctx); + + if (!device.get_device_features().supports_drm_modifiers) + { + printf("Device does not support DRM modifiers, skipping test ...\n"); + return; + } + + pyrowave_device pyro_device = create_device_from_granite(device); + + auto timeline_sem = device.request_semaphore_external(VK_SEMAPHORE_TYPE_TIMELINE, + ExternalHandle::get_opaque_semaphore_handle_type()); + ASSERT_THAT(timeline_sem); + pyrowave_sync_object imported_timeline = create_sync_object_from_timeline(pyro_device, *timeline_sem); + + auto exportable_nv12_image = create_exportable_test_image( + device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM); + auto exportable_yuv420p_image = create_exportable_test_image( + device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM); + + pyrowave_image imported_nv12_image = create_imported_image(pyro_device, device, *exportable_nv12_image); + pyrowave_image imported_yuv420p_image = create_imported_image(pyro_device, device, *exportable_yuv420p_image); + + pyrowave_encoder_create_info encoder_info = {}; + encoder_info.device = pyro_device; + encoder_info.width = 1280; + encoder_info.height = 720; + encoder_info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_420; + pyrowave_encoder encoder; + CHECKED(pyrowave_encoder_create(&encoder_info, &encoder)); + + // Test the two ways we can send a sync payload, binary + temporary or persistent timeline. + // Verify it doesn't explode. + send_granite_image_to_encoder(device, *exportable_nv12_image, imported_nv12_image, + *timeline_sem, imported_timeline, 1, + imported_timeline, 2, + encoder); + + pyrowave_decoder_create_info decoder_info = {}; + decoder_info.device = pyro_device; + decoder_info.width = 1280; + decoder_info.height = 720; + decoder_info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_420; + pyrowave_decoder decoder; + CHECKED(pyrowave_decoder_create(&decoder_info, &decoder)); + + send_payload_to_decoder(encoder, decoder); + decode_image(&imported_yuv420p_image, true, imported_timeline, 3, decoder); + validate_granite_image(device, *exportable_yuv420p_image, *timeline_sem, 3); + + pyrowave_sync_object_destroy(imported_timeline); + pyrowave_image_destroy(imported_nv12_image); + pyrowave_image_destroy(imported_yuv420p_image); + pyrowave_encoder_destroy(encoder); + pyrowave_decoder_destroy(decoder); + pyrowave_device_destroy(pyro_device); +} + +#ifdef _WIN32 + +static VkFormat convert_dxgi_format(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_NV12: return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; + case DXGI_FORMAT_R8_UNORM: return VK_FORMAT_R8_UNORM; + default: ASSERT_THAT(0 && "augment as needed"); + } + + return VK_FORMAT_UNDEFINED; +} + +static pyrowave_image create_pyrowave_image_from_d3d12(pyrowave_device pyro_device, ID3D12Device *device, ID3D12Resource *resource, bool storage) +{ + HANDLE shared_handle; + CHECK_HRESULT(device->CreateSharedHandle(resource, nullptr, GENERIC_ALL, nullptr, &shared_handle)); + + auto desc = resource->GetDesc(); + + VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + image_create_info.imageType = VK_IMAGE_TYPE_2D; + image_create_info.extent = { uint32_t(desc.Width), desc.Height, 1u }; + image_create_info.mipLevels = desc.MipLevels; + // MUTABLE is needed since we will take plane views. Extended usage since the base planar format doesn't support STORAGE. + image_create_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + + // The usage flags don't matter that much. + image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + if (storage) + image_create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT; + + image_create_info.format = convert_dxgi_format(desc.Format); + image_create_info.samples = static_cast(desc.SampleDesc.Count); + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_create_info.arrayLayers = desc.DepthOrArraySize; + + pyrowave_image_create_info info = {}; + info.device = pyro_device; + info.external_handle = (pyrowave_os_handle)shared_handle; + info.handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT; + info.image_create_info = &image_create_info; + + pyrowave_image image; + CHECKED(pyrowave_image_create(&info, &image)); + return image; +} + +static pyrowave_image create_pyrowave_image_from_d3d11(pyrowave_device pyro_device, ID3D11Texture2D *resource, bool kmt) +{ + HANDLE shared_handle; + ComPtr res; + resource->QueryInterface(IID_IDXGIResource1, res.ppv()); + + if (kmt) + { + CHECK_HRESULT(res->GetSharedHandle(&shared_handle)); + } + else + { + CHECK_HRESULT(res->CreateSharedHandle(nullptr, GENERIC_ALL, nullptr, &shared_handle)); + } + + D3D11_TEXTURE2D_DESC desc; + resource->GetDesc(&desc); + + VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + image_create_info.imageType = VK_IMAGE_TYPE_2D; + image_create_info.extent = { uint32_t(desc.Width), desc.Height, 1u }; + image_create_info.mipLevels = desc.MipLevels; + // MUTABLE is needed since we will take plane views. Extended usage since the base planar format doesn't support STORAGE. + image_create_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + + // The usage flags don't matter that much. + image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + + image_create_info.format = convert_dxgi_format(desc.Format); + image_create_info.samples = static_cast(desc.SampleDesc.Count); + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_create_info.arrayLayers = desc.ArraySize; + + pyrowave_image_create_info info = {}; + info.device = pyro_device; + info.external_handle = (pyrowave_os_handle)shared_handle; + info.handle_type = kmt ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT : VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; + info.image_create_info = &image_create_info; + + pyrowave_image image; + CHECKED(pyrowave_image_create(&info, &image)); + return image; +} + +static pyrowave_sync_object create_pyrowave_sync_from_d3d12_handle(pyrowave_device device, HANDLE handle) +{ + pyrowave_sync_object_create_info info = {}; + info.device = device; + info.external_handle = (pyrowave_os_handle)handle; + // D3D11 fence is aliased with D3D12 fence, it's the same thing in Windows 10+. + info.handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT; + // Technically it's BINARY in the spec since this sharing API predated timeline, but it gets fixed up by Granite as needed. + info.semaphore_type = VK_SEMAPHORE_TYPE_TIMELINE; + + pyrowave_sync_object sync; + CHECKED(pyrowave_sync_object_create(&info, &sync)); + return sync; +} + +static void upload_mirror_image(ID3D12Device *device, ID3D12GraphicsCommandList *list, ID3D12Resource *resource, + UINT subresource, ComPtr &staging, + int dx0, int dy0, int dx1, int dy1) +{ + auto desc = resource->GetDesc(); + UINT64 total_bytes = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint; + device->GetCopyableFootprints(&desc, subresource, 1, 0, &footprint, nullptr, nullptr, &total_bytes); + ASSERT_THAT(total_bytes != UINT64_MAX); + + D3D12_RESOURCE_DESC staging_desc = {}; + staging_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + staging_desc.Width = total_bytes; + staging_desc.Height = 1; + staging_desc.DepthOrArraySize = 1; + staging_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + staging_desc.MipLevels = 1; + staging_desc.SampleDesc.Count = 1; + D3D12_HEAP_PROPERTIES heap_props = {}; + heap_props.Type = D3D12_HEAP_TYPE_UPLOAD; + CHECK_HRESULT(device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_NONE, &staging_desc, + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_ID3D12Resource, staging.ppv())); + + uint8_t *ptr; + CHECK_HRESULT(staging->Map(0, nullptr, reinterpret_cast(&ptr))); + + for (int y = 0; y < int(footprint.Footprint.Height); y++) + { + for (int x = 0; x < int(footprint.Footprint.Width); x++) + { + if (subresource == 0) + { + ptr[x] = mirror(y * dy0 + x * dx0); + } + else + { + ptr[2 * x + 0] = mirror(y * dy0 + x * dx0); + ptr[2 * x + 1] = mirror(y * dy1 + x * dx1); + } + } + + ptr += footprint.Footprint.RowPitch; + } + + staging->Unmap(0, nullptr); + + D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {}; + dst.pResource = resource; + dst.SubresourceIndex = subresource; + dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + + src.PlacedFootprint = footprint; + src.pResource = staging.get(); + src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + + list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr); +} + +static ComPtr readback_image(ID3D12Device *device, ID3D12GraphicsCommandList *list, ID3D12Resource *resource, UINT subresource, UINT64 *row_pitch) +{ + auto desc = resource->GetDesc(); + UINT64 total_bytes = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint; + device->GetCopyableFootprints(&desc, subresource, 1, 0, &footprint, nullptr, nullptr, &total_bytes); + ASSERT_THAT(total_bytes != UINT64_MAX); + + D3D12_RESOURCE_DESC staging_desc = {}; + staging_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + staging_desc.Width = total_bytes; + staging_desc.Height = 1; + staging_desc.DepthOrArraySize = 1; + staging_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + staging_desc.MipLevels = 1; + staging_desc.SampleDesc.Count = 1; + D3D12_HEAP_PROPERTIES heap_props = {}; + heap_props.Type = D3D12_HEAP_TYPE_READBACK; + + ComPtr staging; + CHECK_HRESULT(device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_NONE, &staging_desc, + D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_ID3D12Resource, staging.ppv())); + + D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {}; + src.pResource = resource; + src.SubresourceIndex = subresource; + src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + + dst.PlacedFootprint = footprint; + dst.pResource = staging.get(); + dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + + list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr); + + *row_pitch = footprint.Footprint.RowPitch; + + return staging; +} + +static void validate_d3d12_image(ID3D12Resource *readback, int width, int height, int row_stride, int dx, int dy) +{ + uint8_t *ptr; + CHECK_HRESULT(readback->Map(0, nullptr, reinterpret_cast(&ptr))); + validate_mirror_buffer(ptr, width, height, row_stride, dx, dy); + readback->Unmap(0, nullptr); +} + +static void test_nv12_interop() +{ + // NV12 layout on NVIDIA is bizarre and requires us to hack around it when we import it in Vulkan. + // Smoke-test for debugging any interop issues. + ComPtr device; + ComPtr queue; + ComPtr fence; + ComPtr list; + ComPtr allocator; + uint64_t timeline = 0; + + CHECK_HRESULT(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_ID3D12Device, device.ppv())); + CHECK_HRESULT(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_ID3D12CommandAllocator, allocator.ppv())); + CHECK_HRESULT(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator.get(), nullptr, IID_ID3D12GraphicsCommandList, list.ppv())); + // Base API create command list starts a new command list, which we usually need to close right away ... + CHECK_HRESULT(list->Close()); + D3D12_COMMAND_QUEUE_DESC queue_desc = {}; + queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + CHECK_HRESULT(device->CreateCommandQueue(&queue_desc, IID_ID3D12CommandQueue, queue.ppv())); + + CHECK_HRESULT(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_ID3D12Fence, fence.ppv())); + + LUID luid = device->GetAdapterLuid(); + static_assert(sizeof(luid) == sizeof(pyrowave_luid), "LUID struct size does not match."); + + Context context; + Device dev; + + ASSERT_THAT(Context::init_loader(nullptr)); + context.set_num_thread_indices(1); + context.set_system_handles({}); + + // Just enable video extensions so that we can use video image usage, but don't bother creating queues for it, etc. + ASSERT_THAT(context.init_instance(nullptr, 0, CONTEXT_CREATION_ENABLE_VIDEO_FEATURE_ONLY_BIT)); + uint32_t count; + ASSERT_THAT(vkEnumeratePhysicalDevices(context.get_instance(), &count, nullptr) == VK_SUCCESS); + std::vector gpus(count); + ASSERT_THAT(vkEnumeratePhysicalDevices(context.get_instance(), &count, gpus.data()) == VK_SUCCESS); + + VkPhysicalDevice selected_gpu = VK_NULL_HANDLE; + + for (auto &gpu : gpus) + { + VkPhysicalDeviceProperties props = {}; + vkGetPhysicalDeviceProperties(gpu, &props); + // Is this even possible these days? + if (props.apiVersion < VK_API_VERSION_1_2) + continue; + + VkPhysicalDeviceIDProperties ids = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES }; + VkPhysicalDeviceProperties2 props2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &ids }; + vkGetPhysicalDeviceProperties2(gpu, &props2); + + if (!ids.deviceLUIDValid) + continue; + if (memcmp(&luid, ids.deviceLUID, VK_LUID_SIZE) != 0) + continue; + + ASSERT_THAT(context.init_device(gpu, VK_NULL_HANDLE, nullptr, 0, CONTEXT_CREATION_ENABLE_VIDEO_FEATURE_ONLY_BIT)); + selected_gpu = gpu; + } + + ASSERT_THAT(selected_gpu); + dev.set_context(context); + + // NV Windows is quite broken here and no matter what we do, + // it will only work for very specific resource sizes it seems, even with the video usage hacks ... + constexpr uint32_t Width = 1024; + constexpr uint32_t Height = 1024; + + D3D12_RESOURCE_DESC resource_desc = {}; + resource_desc.Width = Width; + resource_desc.Height = Height; + resource_desc.DepthOrArraySize = 1; + resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + resource_desc.SampleDesc.Count = 1; + resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resource_desc.MipLevels = 1; + + D3D12_HEAP_PROPERTIES heap_props = {}; + heap_props.Type = D3D12_HEAP_TYPE_DEFAULT; + + ComPtr nv12; + resource_desc.Format = DXGI_FORMAT_NV12; + CHECK_HRESULT(device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_SHARED, &resource_desc, + D3D12_RESOURCE_STATE_COMMON, nullptr, IID_ID3D12Resource, nv12.ppv())); + + // Upload frame to NV12 image async. + list->Reset(allocator.get(), nullptr); + ComPtr staging_buffers[2]; // Verify that sync works somewhat so defer destroy these. + upload_mirror_image(device.get(), list.get(), nv12.get(), 0, staging_buffers[0], 5, 3, 0, 0); + upload_mirror_image(device.get(), list.get(), nv12.get(), 1, staging_buffers[1], 3, 1, 5, 7); + list->Close(); + + ID3D12CommandList *lists[] = { list.get() }; + queue->ExecuteCommandLists(1, lists); + queue->Signal(fence.get(), ++timeline); + fence->SetEventOnCompletion(timeline, nullptr); + + allocator->Reset(); + list->Reset(allocator.get(), nullptr); + ComPtr readback_buffer; + UINT64 row_pitch = {}; + readback_buffer = readback_image(device.get(), list.get(), nv12.get(), 1, &row_pitch); + list->Close(); + queue->ExecuteCommandLists(1, lists); + queue->Signal(fence.get(), ++timeline); + fence->SetEventOnCompletion(timeline, nullptr); + + auto img_info = ImageCreateInfo::immutable_2d_image(Width, Height, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM); + img_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + img_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT | VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR; + img_info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + img_info.misc = IMAGE_MISC_EXTERNAL_MEMORY_BIT | IMAGE_MISC_NO_DEFAULT_VIEWS_BIT; + CHECK_HRESULT(device->CreateSharedHandle(nv12.get(), nullptr, GENERIC_ALL, nullptr, &img_info.external.handle)); + img_info.external.memory_handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT; + auto img = dev.create_image(img_info); + ASSERT_THAT(img); + + BufferCreateInfo bufinfo = {}; + bufinfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + bufinfo.domain = BufferDomain::CachedHost; + bufinfo.size = Width * Height / 2; + auto buffer = dev.create_buffer(bufinfo); + + auto cmd = dev.request_command_buffer(); + cmd->acquire_image_barrier(*img, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_READ_BIT); + cmd->copy_image_to_buffer(*buffer, *img, 0, {}, { Width / 2, Height / 2, 1 }, Width / 2, Height / 2, { VK_IMAGE_ASPECT_PLANE_1_BIT, 0, 0, 1 }); + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_2_HOST_BIT, VK_ACCESS_2_HOST_READ_BIT); + Fence sync; + dev.submit(cmd, &sync); + sync->wait(); + + uint8_t *d3d12_ptr; + CHECK_HRESULT(readback_buffer->Map(0, nullptr, (void **)&d3d12_ptr)); + + const auto *ptr = static_cast(dev.map_host_buffer(*buffer, MEMORY_ACCESS_READ_BIT)); + + for (uint32_t y = 0; y < Height / 2; y++) + { + for (uint32_t x = 0; x < Width / 2; x++) + { + uint32_t pix = y * Width / 2 + x; + ASSERT_THAT(ptr[2 * pix + 0] == d3d12_ptr[y * row_pitch + 2 * x + 0]); + ASSERT_THAT(ptr[2 * pix + 1] == d3d12_ptr[y * row_pitch + 2 * x + 1]); + } + } + + readback_buffer->Unmap(0, nullptr); +} + +static void test_d3d12_interop_allocation_stress(ID3D12Device *device, pyrowave_device pyro_device) +{ + D3D12_RESOURCE_DESC resource_desc = {}; + resource_desc.Width = 4096; + resource_desc.Height = 4096; + resource_desc.DepthOrArraySize = 1; + resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + resource_desc.SampleDesc.Count = 1; + resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resource_desc.MipLevels = 1; + + D3D12_HEAP_PROPERTIES heap_props = {}; + heap_props.Type = D3D12_HEAP_TYPE_DEFAULT; + + for (int i = 0; i < 10000; i++) + { + ComPtr img; + resource_desc.Format = DXGI_FORMAT_R8_UNORM; + CHECK_HRESULT(device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_SHARED, &resource_desc, + D3D12_RESOURCE_STATE_COMMON, nullptr, IID_ID3D12Resource, img.ppv())); + pyrowave_image pyro_img = create_pyrowave_image_from_d3d12(pyro_device, device, img.get(), true); + + // Check to see if destruction order matters. + + if (i % 2) + { + pyrowave_image_destroy(pyro_img); + img = {}; + } + else + { + img = {}; + pyrowave_image_destroy(pyro_img); + } + } + + for (int i = 0; i < 10000; i++) + { + // Sharing D3D12 to Vulkan is well supported. Other way around, not so much. + ComPtr fence; + CHECK_HRESULT(device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_ID3D12Fence, fence.ppv())); + HANDLE fence_handle; + CHECK_HRESULT(device->CreateSharedHandle(fence.get(), nullptr, GENERIC_ALL, nullptr, &fence_handle)); + + pyrowave_sync_object pyro_sync = create_pyrowave_sync_from_d3d12_handle(pyro_device, fence_handle); + + // Check to see if destruction order matters. + if (i % 2) + { + pyrowave_sync_object_destroy(pyro_sync); + fence = {}; + } + else + { + fence = {}; + pyrowave_sync_object_destroy(pyro_sync); + } + } +} + +static void test_d3d11_interop() +{ + uint32_t index = 0; + if (const char *env = getenv("ADAPTER")) + index = strtoul(env, nullptr, 0); + + bool validate = false; + if (const char *env = getenv("VALIDATE")) + validate = strtoul(env, nullptr, 0) != 0; + + ComPtr factory; + ComPtr adapter; + ComPtr device; + ComPtr device5; + ComPtr context; + ComPtr context4; + ComPtr fence; + CHECK_HRESULT(CreateDXGIFactory1(IID_IDXGIFactory, factory.ppv())); + CHECK_HRESULT(factory->EnumAdapters(index, (IDXGIAdapter **)adapter.ppv())); + + HRESULT hr = D3D11CreateDevice(adapter.get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, validate ? D3D11_CREATE_DEVICE_DEBUG : 0, nullptr, 0, D3D11_SDK_VERSION, + (ID3D11Device **)device.ppv(), nullptr, (ID3D11DeviceContext **)context.ppv()); + ASSERT_THAT(SUCCEEDED(hr)); + CHECK_HRESULT(device->QueryInterface(IID_ID3D11Device5, device5.ppv())); + + DXGI_ADAPTER_DESC adapter_desc; + CHECK_HRESULT(adapter->GetDesc(&adapter_desc)); + LUID luid = adapter_desc.AdapterLuid; + static_assert(sizeof(luid) == sizeof(pyrowave_luid), "LUID struct size does not match."); + + CHECK_HRESULT(context->QueryInterface(IID_ID3D11DeviceContext4, context4.ppv())); + + pyrowave_device pyro_device; + CHECKED(pyrowave_create_device_by_compat(0, 0, nullptr, nullptr, + reinterpret_cast(&luid), &pyro_device)); + + for (int i = 0; i < 10000; i++) + { + ComPtr tex; + D3D11_TEXTURE2D_DESC desc = {}; + desc.Format = DXGI_FORMAT_R8_UNORM; + desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE; + desc.SampleDesc.Count = 1; + desc.Width = 4096; + desc.Height = 4096; + desc.ArraySize = 1; + desc.MipLevels = 1; + CHECK_HRESULT(device5->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D **)tex.ppv())); + + pyrowave_image pyro_img = create_pyrowave_image_from_d3d11(pyro_device, tex.get(), false); + + // Check to see if destruction order matters. + if (i % 2) + { + pyrowave_image_destroy(pyro_img); + fence = {}; + } + else + { + fence = {}; + pyrowave_image_destroy(pyro_img); + } + + // Flushing seems to be load bearing here or GPU memory usage baloons out of control. + context->Flush(); + } + + for (int i = 0; i < 10000; i++) + { + ComPtr tex; + D3D11_TEXTURE2D_DESC desc = {}; + desc.Format = DXGI_FORMAT_R8_UNORM; + desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; + desc.SampleDesc.Count = 1; + desc.Width = 4096; + desc.Height = 4096; + desc.ArraySize = 1; + desc.MipLevels = 1; + CHECK_HRESULT(device5->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D **)tex.ppv())); + + pyrowave_image pyro_img = create_pyrowave_image_from_d3d11(pyro_device, tex.get(), true); + + // Check to see if destruction order matters. + if (i % 2) + { + pyrowave_image_destroy(pyro_img); + fence = {}; + } + else + { + fence = {}; + pyrowave_image_destroy(pyro_img); + } + + // Flushing seems to be load bearing here or GPU memory usage baloons out of control. + context->Flush(); + } + + for (int i = 0; i < 10000; i++) + { + // Sharing D3D11 to Vulkan is well supported. Other way around, not so much. + ComPtr share_fence; + CHECK_HRESULT(device5->CreateFence(0, D3D11_FENCE_FLAG_SHARED, IID_ID3D11Fence, share_fence.ppv())); + HANDLE fence_handle; + CHECK_HRESULT(share_fence->CreateSharedHandle(nullptr, GENERIC_ALL, nullptr, &fence_handle)); + + context4->Signal(share_fence.get(), 1); + share_fence = {}; + + pyrowave_sync_object pyro_sync = create_pyrowave_sync_from_d3d12_handle(pyro_device, fence_handle); + + // Check to see if destruction order matters. + if (i % 2) + { + pyrowave_sync_object_destroy(pyro_sync); + fence = {}; + } + else + { + fence = {}; + pyrowave_sync_object_destroy(pyro_sync); + } + + context->Flush(); + } + + pyrowave_device_destroy(pyro_device); +} + +static void test_d3d12_interop() +{ + ComPtr device; + ComPtr queue; + ComPtr fence; + ComPtr list; + ComPtr allocator; + uint64_t timeline = 0; + + uint32_t index = 0; + if (const char *env = getenv("ADAPTER")) + index = strtoul(env, nullptr, 0); + + ComPtr factory; + ComPtr adapter; + CHECK_HRESULT(CreateDXGIFactory1(IID_IDXGIFactory, factory.ppv())); + CHECK_HRESULT(factory->EnumAdapters(index, (IDXGIAdapter **)adapter.ppv())); + + CHECK_HRESULT(D3D12CreateDevice(adapter.get(), D3D_FEATURE_LEVEL_11_0, IID_ID3D12Device, device.ppv())); + CHECK_HRESULT(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_ID3D12CommandAllocator, allocator.ppv())); + CHECK_HRESULT(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator.get(), nullptr, IID_ID3D12GraphicsCommandList, list.ppv())); + // Base API create command list starts a new command list, which we usually need to close right away ... + CHECK_HRESULT(list->Close()); + D3D12_COMMAND_QUEUE_DESC queue_desc = {}; + queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + CHECK_HRESULT(device->CreateCommandQueue(&queue_desc, IID_ID3D12CommandQueue, queue.ppv())); + + // Sharing D3D12 to Vulkan is well supported. Other way around, not so much. + CHECK_HRESULT(device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_ID3D12Fence, fence.ppv())); + + LUID luid = device->GetAdapterLuid(); + static_assert(sizeof(luid) == sizeof(pyrowave_luid), "LUID struct size does not match."); + + pyrowave_device pyro_device; + CHECKED(pyrowave_create_device_by_compat(0, 0, nullptr, nullptr, + reinterpret_cast(&luid), &pyro_device)); + + test_d3d12_interop_allocation_stress(device.get(), pyro_device); + + // NV Windows is quite broken here and no matter what we do, it will only work for very specific resource sizes it seems ... + constexpr uint32_t Width = 1024; + constexpr uint32_t Height = 1024; + + D3D12_RESOURCE_DESC resource_desc = {}; + resource_desc.Width = Width; + resource_desc.Height = Height; + resource_desc.DepthOrArraySize = 1; + resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + resource_desc.SampleDesc.Count = 1; + resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resource_desc.MipLevels = 1; + + D3D12_HEAP_PROPERTIES heap_props = {}; + heap_props.Type = D3D12_HEAP_TYPE_DEFAULT; + + ComPtr nv12, yuv420p[3]; + resource_desc.Format = DXGI_FORMAT_NV12; + CHECK_HRESULT(device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_SHARED, &resource_desc, + D3D12_RESOURCE_STATE_COMMON, nullptr, IID_ID3D12Resource, nv12.ppv())); + + // DXGI doesn't have proper 3-plane format. Just test the path with 3x R8 images. + // Also adds some test coverage to that path. + resource_desc.Format = DXGI_FORMAT_R8_UNORM; + CHECK_HRESULT(device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_SHARED, &resource_desc, + D3D12_RESOURCE_STATE_COMMON, nullptr, IID_ID3D12Resource, yuv420p[0].ppv())); + resource_desc.Width /= 2; + resource_desc.Height /= 2; + for (int plane = 1; plane < 3; plane++) + { + CHECK_HRESULT(device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_SHARED, &resource_desc, + D3D12_RESOURCE_STATE_COMMON, nullptr, IID_ID3D12Resource, yuv420p[plane].ppv())); + } + + pyrowave_image pyro_nv12 = create_pyrowave_image_from_d3d12(pyro_device, device.get(), nv12.get(), false); + pyrowave_image pyro_yuv420p[3] = {}; + for (int plane = 0; plane < 3; plane++) + pyro_yuv420p[plane] = create_pyrowave_image_from_d3d12(pyro_device, device.get(), yuv420p[plane].get(), true); + + HANDLE fence_handle; + CHECK_HRESULT(device->CreateSharedHandle(fence.get(), nullptr, GENERIC_ALL, nullptr, &fence_handle)); + pyrowave_sync_object pyro_sync = create_pyrowave_sync_from_d3d12_handle(pyro_device, fence_handle); + + pyrowave_encoder_create_info encoder_info = {}; + encoder_info.device = pyro_device; + encoder_info.width = Width; + encoder_info.height = Height; + pyrowave_encoder encoder; + CHECKED(pyrowave_encoder_create(&encoder_info, &encoder)); + + pyrowave_decoder_create_info decoder_info = {}; + decoder_info.device = pyro_device; + decoder_info.width = Width; + decoder_info.height = Height; + pyrowave_decoder decoder; + CHECKED(pyrowave_decoder_create(&decoder_info, &decoder)); + + // Upload frame to NV12 image async. + list->Reset(allocator.get(), nullptr); + ComPtr staging_buffers[2]; // Verify that sync works somewhat so defer destroy these. + upload_mirror_image(device.get(), list.get(), nv12.get(), 0, staging_buffers[0], 5, 3, 0, 0); + upload_mirror_image(device.get(), list.get(), nv12.get(), 1, staging_buffers[1], 3, 1, 5, 7); + list->Close(); + + // Submit to D3D12 queue and signal the shared timeline. + ID3D12CommandList *lists[] = { list.get() }; + queue->ExecuteCommandLists(1, lists); + queue->Signal(fence.get(), ++timeline); + + send_image_to_encoder(pyro_nv12, pyro_sync, timeline, pyro_sync, timeline + 1, encoder); + timeline++; + + // This is a blocking call since we read back the payload on CPU (hopefully on a different machine). + send_payload_to_decoder(encoder, decoder); + + // Decode and send image back to D3D12. + decode_image(pyro_yuv420p, false, pyro_sync, ++timeline, decoder); + + queue->Wait(fence.get(), timeline); + + allocator->Reset(); + list->Reset(allocator.get(), nullptr); + ComPtr readback_buffers[3]; + UINT64 row_pitch[3] = {}; + for (int plane = 0; plane < 3; plane++) + readback_buffers[plane] = readback_image(device.get(), list.get(), yuv420p[plane].get(), 0, &row_pitch[plane]); + CHECK_HRESULT(list->Close()); + queue->ExecuteCommandLists(1, lists); + + // Wait for device to go idle. + queue->Signal(fence.get(), ++timeline); + // null event handle blocks on CPU directly. + fence->SetEventOnCompletion(timeline, nullptr); + + validate_d3d12_image(readback_buffers[0].get(), Width, Height, row_pitch[0], 5, 3); + validate_d3d12_image(readback_buffers[1].get(), Width / 2, Height / 2, row_pitch[1], 3, 1); + validate_d3d12_image(readback_buffers[2].get(), Width / 2, Height / 2, row_pitch[2], 5, 7); + + pyrowave_image_destroy(pyro_nv12); + for (auto &img : pyro_yuv420p) + pyrowave_image_destroy(img); + pyrowave_sync_object_destroy(pyro_sync); + pyrowave_decoder_destroy(decoder); + pyrowave_encoder_destroy(encoder); + pyrowave_device_destroy(pyro_device); +} + +struct SharedBlock +{ + HANDLE texture[3]; + HANDLE fence; + HANDLE sem; + LUID luid; + uint32_t width, height; + uint8_t payload[1024 * 1024]; + uint32_t payload_size; + uint64_t wait_value; + uint64_t signal_value; + bool dead; +}; + +static void test_d3d11_cross_process_encode() +{ + ComPtr factory; + ComPtr adapter; + ComPtr device; + ComPtr device5; + ComPtr context; + ComPtr context4; + ComPtr fence; + + uint32_t index = 0; + if (const char *env = getenv("ADAPTER")) + index = strtoul(env, nullptr, 0); + + CHECK_HRESULT(CreateDXGIFactory1(IID_IDXGIFactory, factory.ppv())); + CHECK_HRESULT(factory->EnumAdapters(index, (IDXGIAdapter **)adapter.ppv())); + + HRESULT hr = D3D11CreateDevice(adapter.get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, + (ID3D11Device **)device.ppv(), nullptr, (ID3D11DeviceContext **)context.ppv()); + ASSERT_THAT(SUCCEEDED(hr)); + CHECK_HRESULT(device->QueryInterface(IID_ID3D11Device5, device5.ppv())); + + DXGI_ADAPTER_DESC adapter_desc; + CHECK_HRESULT(adapter->GetDesc(&adapter_desc)); + LUID luid = adapter_desc.AdapterLuid; + static_assert(sizeof(luid) == sizeof(pyrowave_luid), "LUID struct size does not match."); + + HANDLE mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, sizeof(SharedBlock), "PyroFlingTestDummy"); + ASSERT_THAT(mapping != INVALID_HANDLE_VALUE && mapping != nullptr); + auto *shared = static_cast(MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(SharedBlock))); + ASSERT_THAT(shared); + + memset(shared, 0, sizeof(*shared)); + + shared->luid = luid; + shared->width = 1280; + shared->height = 720; + + CHECK_HRESULT(context->QueryInterface(IID_ID3D11DeviceContext4, context4.ppv())); + + char self[4096]; + DWORD ret = GetModuleFileNameA(GetModuleHandle(nullptr), self, sizeof(self)); + self[ret] = '\0'; + + strcat(self, " --child"); + + HANDLE job_handle = CreateJobObjectA(nullptr, nullptr); + ASSERT_THAT(job_handle); + + // Kill all child processes if the parent dies. + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {}; + jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + ASSERT_THAT(SetInformationJobObject(job_handle, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli))); + + STARTUPINFOA si = {}; + si.cb = sizeof(STARTUPINFOA); + PROCESS_INFORMATION pi; + ASSERT_THAT(CreateProcessA(nullptr, self, nullptr, nullptr, TRUE, CREATE_NO_WINDOW | CREATE_SUSPENDED, + nullptr, nullptr, &si, &pi)); + + ASSERT_THAT(AssignProcessToJobObject(job_handle, pi.hProcess)); + + HANDLE semaphore = CreateSemaphoreA(nullptr, 0, 1, "PyroFlingSemDummy"); + ASSERT_THAT(semaphore); + + shared->wait_value = 1; + shared->signal_value = 2; + + ResumeThread(pi.hThread); + + pyrowave_device pyro_device; + CHECKED(pyrowave_create_default_device(&pyro_device)); + pyrowave_decoder decoder; + pyrowave_decoder_create_info decoder_info = {}; + decoder_info.device = pyro_device; + decoder_info.width = 1280; + decoder_info.height = 720; + CHECKED(pyrowave_decoder_create(&decoder_info, &decoder)); + + std::unique_ptr y_data(new uint8_t[1280 * 720]); + std::unique_ptr c_data(new uint8_t[640 * 360]); + + std::unique_ptr decoded_y_data(new uint8_t[1280 * 720]); + std::unique_ptr decoded_cb_data(new uint8_t[640 * 360]); + std::unique_ptr decoded_cr_data(new uint8_t[640 * 360]); + + ComPtr tex[3]; + + // Do encoding work. + for (int i = 0; i < 1000; i++) + { + // Create new handles every so often. + if (i % 10 == 0) + { + D3D11_TEXTURE2D_DESC desc = {}; + desc.Format = DXGI_FORMAT_R8_UNORM; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE; + desc.SampleDesc.Count = 1; + desc.Width = 1280; + desc.Height = 720; + desc.ArraySize = 1; + desc.MipLevels = 1; + CHECK_HRESULT(device5->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D **)tex[0].ppv())); + desc.Width /= 2; + desc.Height /= 2; + CHECK_HRESULT(device5->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D **)tex[1].ppv())); + CHECK_HRESULT(device5->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D **)tex[2].ppv())); + + for (int j = 0; j < 3; j++) + { + ComPtr res; + tex[j]->QueryInterface(IID_IDXGIResource1, res.ppv()); + HANDLE shared_handle; + CHECK_HRESULT(res->CreateSharedHandle(nullptr, GENERIC_ALL, nullptr, &shared_handle)); + ASSERT_THAT(DuplicateHandle(GetCurrentProcess(), shared_handle, pi.hProcess, + &shared->texture[j], GENERIC_ALL, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)); + } + + CHECK_HRESULT(device5->CreateFence(0, D3D11_FENCE_FLAG_SHARED, IID_ID3D11Fence, fence.ppv())); + HANDLE shared_handle; + CHECK_HRESULT(fence->CreateSharedHandle(nullptr, GENERIC_ALL, nullptr, &shared_handle)); + ASSERT_THAT(DuplicateHandle(GetCurrentProcess(), shared_handle, pi.hProcess, + &shared->fence, GENERIC_ALL, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)); + } + + D3D11_BOX box = {}; + box.right = 1280; + box.bottom = 720; + box.back = 1; + memset(y_data.get(), i & 0xff, 1280 * 720); + context->UpdateSubresource(tex[0].get(), 0, &box, y_data.get(), 1280, 1280 * 720); + box.right = 640; + box.bottom = 360; + memset(c_data.get(), (i + 1) & 0xff, 640 * 360); + context->UpdateSubresource(tex[1].get(), 0, &box, c_data.get(), 640, 640 * 360); + memset(c_data.get(), (i + 2) & 0xff, 640 * 360); + context->UpdateSubresource(tex[2].get(), 0, &box, c_data.get(), 640, 640 * 360); + + context4->Signal(fence.get(), shared->wait_value); + ASSERT_THAT(ReleaseSemaphore(semaphore, 1, nullptr)); + + // Wait until encoder is done. + CHECK_HRESULT(fence->SetEventOnCompletion(shared->signal_value, nullptr)); + + ASSERT_THAT(shared->payload_size); + pyrowave_decoder_clear(decoder); + CHECKED(pyrowave_decoder_push_packet(decoder, shared->payload, shared->payload_size)); + ASSERT_THAT(pyrowave_decoder_decode_is_ready(decoder, false)); + + pyrowave_cpu_buffer cpu_buffers = {}; + cpu_buffers.data[0] = decoded_y_data.get(); + cpu_buffers.data[1] = decoded_cb_data.get(); + cpu_buffers.data[2] = decoded_cr_data.get(); + cpu_buffers.width = 1280; + cpu_buffers.height = 720; + cpu_buffers.format = PYROWAVE_CPU_BUFFER_FORMAT_YUV420P; + cpu_buffers.plane_size_in_bytes[0] = 1280 * 720; + cpu_buffers.plane_size_in_bytes[1] = 640 * 360; + cpu_buffers.plane_size_in_bytes[2] = 640 * 360; + cpu_buffers.row_stride_in_bytes[0] = 1280; + cpu_buffers.row_stride_in_bytes[1] = 640; + cpu_buffers.row_stride_in_bytes[2] = 640; + + CHECKED(pyrowave_decoder_decode_cpu_buffer_synchronous(decoder, &cpu_buffers)); + + for (int pix = 0; pix < 1280 * 720; pix++) + ASSERT_THAT(decoded_y_data[pix] == (i & 0xff)); + + for (int pix = 0; pix < 640 * 360; pix++) + ASSERT_THAT(decoded_cb_data[pix] == ((i + 1) & 0xff)); + + for (int pix = 0; pix < 640 * 360; pix++) + ASSERT_THAT(decoded_cr_data[pix] == ((i + 2) & 0xff)); + + shared->wait_value += 2; + shared->signal_value += 2; + + LOGI("Running cross-process frame %u / 1000 ...\n", i); + } + + CloseHandle(pi.hThread); + + shared->dead = true; + ASSERT_THAT(ReleaseSemaphore(semaphore, 1, nullptr)); + + ASSERT_THAT(WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_OBJECT_0); + ASSERT_THAT(!shared->dead); + CloseHandle(pi.hProcess); + CloseHandle(semaphore); + CloseHandle(job_handle); + + pyrowave_decoder_destroy(decoder); + pyrowave_device_destroy(pyro_device); +} + +static void test_child_interop() +{ + //__debugbreak(); + + // Open shared handles. + HANDLE semaphore = CreateSemaphoreA(nullptr, 0, 1, "PyroFlingSemDummy"); + ASSERT_THAT(semaphore); + + HANDLE mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, sizeof(SharedBlock), "PyroFlingTestDummy"); + ASSERT_THAT(mapping != INVALID_HANDLE_VALUE && mapping != nullptr); + auto *shared = static_cast(MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(SharedBlock))); + ASSERT_THAT(shared); + + pyrowave_device device; + CHECKED(pyrowave_create_device_by_compat(0, 0, nullptr, nullptr, reinterpret_cast(&shared->luid), &device)); + + pyrowave_image img[3] = {}; + pyrowave_sync_object sync = {}; + pyrowave_encoder encoder = {}; + + pyrowave_encoder_create_info encoder_info = {}; + encoder_info.device = device; + encoder_info.width = shared->width; + encoder_info.height = shared->height; + encoder_info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_420; + CHECKED(pyrowave_encoder_create(&encoder_info, &encoder)); + + pyrowave_gpu_external_reference refs[3]; + + // Encode loop + + for (;;) + { + WaitForSingleObject(semaphore, INFINITE); + if (shared->dead) + break; + + for (int i = 0; i < 3; i++) + { + if (shared->texture[i]) + { + if (img[i]) + pyrowave_image_destroy(img[i]); + + VkImageCreateInfo image_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + image_info.extent = { shared->width / (i ? 2 : 1), shared->height / (i ? 2 : 1), 1 }; + image_info.format = VK_FORMAT_R8_UNORM; + image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.arrayLayers = 1; + image_info.mipLevels = 1; + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.imageType = VK_IMAGE_TYPE_2D; + + pyrowave_image_create_info info = {}; + info.device = device; + info.handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; + info.external_handle = (pyrowave_os_handle)shared->texture[i]; + info.image_create_info = &image_info; + + CHECKED(pyrowave_image_create(&info, &img[i])); + + refs[i] = { img[i], VK_QUEUE_FAMILY_EXTERNAL }; + shared->texture[i] = nullptr; + } + } + + if (shared->fence) + { + if (sync) + pyrowave_sync_object_destroy(sync); + + pyrowave_sync_object_create_info sync_info = {}; + sync_info.device = device; + sync_info.external_handle = (pyrowave_os_handle)shared->fence; + sync_info.handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT; + sync_info.semaphore_type = VK_SEMAPHORE_TYPE_TIMELINE; + CHECKED(pyrowave_sync_object_create(&sync_info, &sync)); + + shared->fence = nullptr; + } + + pyrowave_rate_control rate_control = { sizeof(shared->payload) }; + pyrowave_gpu_buffers buffers = {}; + pyrowave_gpu_sync_operation acquire = {}; + pyrowave_gpu_sync_operation release = {}; + acquire.sync.semaphore = pyrowave_sync_object_get_semaphore(sync); + acquire.sync.value = shared->wait_value; + + acquire.num_images = 3; + acquire.images = refs; + release.num_images = 3; + release.images = refs; + + for (int i = 0; i < 3; i++) + CHECKED(pyrowave_image_get_image_view(img[i], VkImageAspectFlagBits(VK_IMAGE_ASPECT_PLANE_0_BIT << i), VK_IMAGE_USAGE_SAMPLED_BIT, &buffers.planes[i])); + CHECKED(pyrowave_encoder_encode_gpu_synchronous(encoder, &acquire, &release, &buffers, &rate_control)); + + pyrowave_packet packet; + size_t out_packets = 1; + CHECKED(pyrowave_encoder_packetize(encoder, &packet, sizeof(shared->payload), &out_packets, shared->payload, sizeof(shared->payload))); + shared->payload_size = packet.size; + + // API sanity check. + CHECKED(pyrowave_sync_object_cpu_wait(sync, shared->wait_value, UINT64_MAX)); + + // Signal on CPU. + CHECKED(pyrowave_sync_object_cpu_signal(sync, shared->signal_value)); + } + + //__debugbreak(); + + shared->dead = false; + + pyrowave_sync_object_destroy(sync); + for (auto &i : img) + pyrowave_image_destroy(i); + pyrowave_encoder_destroy(encoder); + pyrowave_device_destroy(device); +} +#endif + +int main(int argc, char **argv) +{ +#ifdef _WIN32 + if (getenv("VALIDATE")) + { + ComPtr debug; + if (SUCCEEDED(D3D12GetDebugInterface(IID_ID3D12Debug, debug.ppv()))) + debug->EnableDebugLayer(); + } + + if (argc == 2 && strcmp(argv[1], "--child") == 0) + { + test_child_interop(); + return EXIT_SUCCESS; + } + + test_d3d11_cross_process_encode(); + + printf("Running NV12 interop test ...\n"); + test_nv12_interop(); + + printf("Running D3D11 interop test ...\n"); + test_d3d11_interop(); + + printf("Running D3D12 interop test ...\n"); + test_d3d12_interop(); +#else + (void)argc; + (void)argv; +#endif + + printf("Running Vulkan <-> Vulkan interop test with direct device share ...\n"); + test_direct_interop(); + + printf("Running opaque Vulkan <-> Vulkan interop test ...\n"); + test_opaque_interop(false); + +#ifdef _WIN32 + printf("Running opaque Vulkan <-> Vulkan interop test (KMT handles) ...\n"); + test_opaque_interop(true); +#endif + + printf("Running drm modifier Vulkan <-> Vulkan interop test ...\n"); + test_drm_modifier_interop(); + + printf("Interop tests passed!\n"); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_c_test.cpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_c_test.cpp new file mode 100644 index 00000000..a7b7a362 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_c_test.cpp @@ -0,0 +1,574 @@ +// Copyright (c) 2026 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#include "vulkan/vulkan.h" +#include "pyrowave.h" +#include +#include +#include +#include + +// Smoke test the C API. + +#define ASSERT_THAT(x) do { \ + if (!(x)) { fprintf(stderr, "Fatal error executing %s at line %d.\n", #x, __LINE__); std::terminate(); } \ +} while(false) + +#define CHECKED(x) do { \ + pyrowave_result res = x; \ + if (res != PYROWAVE_SUCCESS) { fprintf(stderr, "Got pyrowave result %d while executing %s at line %d.\n", res, #x, __LINE__); std::terminate(); } \ +} while(false) + +static void test_encoder_create_validation() +{ + pyrowave_encoder_create_info info = {}; + info.width = 64; + info.height = 64; + + // No device. + pyrowave_encoder encoder, dummy; + ASSERT_THAT(pyrowave_encoder_create(&info, &encoder) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + pyrowave_device device; + CHECKED(pyrowave_create_default_device(&device)); + + info.device = device; + CHECKED(pyrowave_encoder_create(&info, &encoder)); + + // 0 size not allowed. + info.width = 0; + info.height = 0; + ASSERT_THAT(pyrowave_encoder_create(&info, &dummy) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + // Odd size not allowed. + info.width = 65; + info.height = 64; + ASSERT_THAT(pyrowave_encoder_create(&info, &dummy) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + info.width = 64; + info.height = 65; + ASSERT_THAT(pyrowave_encoder_create(&info, &dummy) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + // Odd size allowed for 444. + info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_444; + CHECKED(pyrowave_encoder_create(&info, &dummy)); + pyrowave_encoder_destroy(dummy); + + pyrowave_encoder_destroy(encoder); + pyrowave_device_destroy(device); +} + +static void test_decoder_create_validation() +{ + pyrowave_decoder_create_info info = {}; + info.width = 64; + info.height = 64; + + // No device. + pyrowave_decoder decoder, dummy; + ASSERT_THAT(pyrowave_decoder_create(&info, &decoder) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + pyrowave_device device; + CHECKED(pyrowave_create_default_device(&device)); + + info.device = device; + CHECKED(pyrowave_decoder_create(&info, &decoder)); + + // 0 size not allowed. + info.width = 0; + info.height = 0; + ASSERT_THAT(pyrowave_decoder_create(&info, &dummy) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + // Odd size not allowed. + info.width = 65; + info.height = 64; + ASSERT_THAT(pyrowave_decoder_create(&info, &dummy) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + info.width = 64; + info.height = 65; + ASSERT_THAT(pyrowave_decoder_create(&info, &dummy) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + // Odd size allowed for 444. + info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_444; + CHECKED(pyrowave_decoder_create(&info, &dummy)); + pyrowave_decoder_destroy(dummy); + + // Smoke test that creating device on fragment path doesn't explode. + info.fragment_path = true; + CHECKED(pyrowave_decoder_create(&info, &dummy)); + pyrowave_decoder_destroy(dummy); + + pyrowave_decoder_destroy(decoder); + pyrowave_device_destroy(device); +} + +static void test_decode_cpu_buffer_validation(bool fragment_path) +{ + pyrowave_decoder_create_info info = {}; + info.width = 16; + info.height = 16; + info.fragment_path = fragment_path; + + pyrowave_decoder decoder; + CHECKED(pyrowave_create_default_device(&info.device)); + CHECKED(pyrowave_decoder_create(&info, &decoder)); + + // This shouldn't be ready. + ASSERT_THAT(!pyrowave_decoder_decode_is_ready(decoder, false)); + ASSERT_THAT(!pyrowave_decoder_decode_is_ready(decoder, true)); + + pyrowave_cpu_buffer cpu_buffer = {}; + + uint8_t luma[16][16] = {}; + uint8_t cb[8][16] = {}; // Test strided readback while we're at it. + uint8_t cr[8][16] = {}; + + cpu_buffer.format = PYROWAVE_CPU_BUFFER_FORMAT_YUV420P; + cpu_buffer.row_stride_in_bytes[0] = 16; + cpu_buffer.row_stride_in_bytes[1] = 16; + cpu_buffer.row_stride_in_bytes[2] = 16; + cpu_buffer.plane_size_in_bytes[0] = 16 * 16; + cpu_buffer.plane_size_in_bytes[1] = 16 * 8; + cpu_buffer.plane_size_in_bytes[2] = 16 * 8; + cpu_buffer.data[0] = &luma[0][0]; + cpu_buffer.data[1] = &cb[0][0]; + cpu_buffer.data[2] = &cr[0][0]; + + cpu_buffer.width = 16; + cpu_buffer.height = 16; + + // NV12 is banned for decode. + cpu_buffer.format = PYROWAVE_CPU_BUFFER_FORMAT_NV12; + ASSERT_THAT(pyrowave_decoder_decode_cpu_buffer_synchronous(decoder, &cpu_buffer) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + cpu_buffer.format = PYROWAVE_CPU_BUFFER_FORMAT_YUV420P; + CHECKED(pyrowave_decoder_decode_cpu_buffer_synchronous(decoder, &cpu_buffer)); + + // Assert that we do indeed decode a gray image. + for (uint32_t y = 0; y < 16; y++) + for (uint32_t x = 0; x < 16; x++) + ASSERT_THAT(luma[y][x] == 0x7f || luma[y][x] == 0x80); + + for (uint32_t y = 0; y < 8; y++) + for (uint32_t x = 0; x < 8; x++) + ASSERT_THAT(cb[y][x] == 0x7f || cb[y][x] == 0x80); + + for (uint32_t y = 0; y < 8; y++) + for (uint32_t x = 0; x < 8; x++) + ASSERT_THAT(cr[y][x] == 0x7f || cr[y][x] == 0x80); + + pyrowave_decoder_destroy(decoder); + pyrowave_device_destroy(info.device); +} + +static void test_encode_cpu_buffer_validation(bool nv12) +{ + pyrowave_encoder_create_info info = {}; + info.width = 16; + info.height = 16; + + pyrowave_encoder encoder; + CHECKED(pyrowave_create_default_device(&info.device)); + CHECKED(pyrowave_encoder_create(&info, &encoder)); + + const pyrowave_rate_control rate_control = { 1024 }; + pyrowave_cpu_buffer cpu_buffer = {}; + + uint8_t y[16][16] = {}; + uint8_t cb[8][8] = {}; + uint8_t cr[8][8] = {}; + + cpu_buffer.format = nv12 ? PYROWAVE_CPU_BUFFER_FORMAT_NV12 : PYROWAVE_CPU_BUFFER_FORMAT_YUV420P; + cpu_buffer.row_stride_in_bytes[0] = 16; + cpu_buffer.row_stride_in_bytes[1] = nv12 ? 16 : 8; + cpu_buffer.row_stride_in_bytes[2] = nv12 ? 0 : 8; + cpu_buffer.plane_size_in_bytes[0] = 16 * 16; + cpu_buffer.plane_size_in_bytes[1] = (nv12 ? 2 : 1) * 8 * 8; + cpu_buffer.plane_size_in_bytes[2] = nv12 ? 0 : 8 * 8; + cpu_buffer.data[0] = &y[0][0]; + cpu_buffer.data[1] = &cb[0][0]; + cpu_buffer.data[2] = &cr[0][0]; + + cpu_buffer.width = 16; + cpu_buffer.height = 16; + CHECKED(pyrowave_encoder_encode_cpu_synchronous(encoder, &cpu_buffer, &rate_control)); + + // Mismatching width/height against encoder. + cpu_buffer.width = 15; + cpu_buffer.height = 16; + ASSERT_THAT(pyrowave_encoder_encode_cpu_synchronous(encoder, &cpu_buffer, &rate_control) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + cpu_buffer.width = 16; + cpu_buffer.height = 15; + ASSERT_THAT(pyrowave_encoder_encode_cpu_synchronous(encoder, &cpu_buffer, &rate_control) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + // Too small row strides. + cpu_buffer.width = 16; + cpu_buffer.height = 16; + cpu_buffer.row_stride_in_bytes[1] = nv12 ? 15 : 7; + ASSERT_THAT(pyrowave_encoder_encode_cpu_synchronous(encoder, &cpu_buffer, &rate_control) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + // Too small plane size. + cpu_buffer.row_stride_in_bytes[1] = nv12 ? 16 : 8; + cpu_buffer.plane_size_in_bytes[1] = (nv12 ? 2 : 1) * 8 * 8 - 1; + ASSERT_THAT(pyrowave_encoder_encode_cpu_synchronous(encoder, &cpu_buffer, &rate_control) == PYROWAVE_ERROR_INVALID_ARGUMENT); + + pyrowave_encoder_destroy(encoder); + pyrowave_device_destroy(info.device); +} + +static void test_basic_encoder_roundtrip(bool fragment_decode, bool nv12_encode, pyrowave_chroma_subsampling chroma) +{ + if (chroma == PYROWAVE_CHROMA_SUBSAMPLING_444 && nv12_encode) + return; + + if (fragment_decode) + return; + + pyrowave_device device; + CHECKED(pyrowave_create_default_device(&device)); + + constexpr int Width = 34; + constexpr int Height = 30; + + pyrowave_decoder_create_info decoder_info = {}; + decoder_info.device = device; + decoder_info.width = Width; // Test somewhat odd size. Quite relevant for fragment path as well. + decoder_info.height = Height; + decoder_info.fragment_path = fragment_decode; + decoder_info.chroma = chroma; + + pyrowave_encoder_create_info encoder_info = {}; + encoder_info.device = device; + encoder_info.width = Width; + encoder_info.height = Height; + encoder_info.chroma = chroma; + + pyrowave_decoder decoder; + pyrowave_encoder encoder; + CHECKED(pyrowave_decoder_create(&decoder_info, &decoder)); + CHECKED(pyrowave_encoder_create(&encoder_info, &encoder)); + + uint8_t luma[Height][Width] = {}; + uint8_t cb[Height][Width] = {}; + uint8_t cr[Height][Width] = {}; + uint8_t cbcr[Height][Width][2] = {}; + + uint8_t decode_luma[Height][Width] = {}; + uint8_t decode_cb[Height][Width] = {}; + uint8_t decode_cr[Height][Width] = {}; + + pyrowave_cpu_buffer cpu_buffer = {}; + + cpu_buffer.format = + nv12_encode + ? PYROWAVE_CPU_BUFFER_FORMAT_NV12 + : (chroma == PYROWAVE_CHROMA_SUBSAMPLING_444 + ? PYROWAVE_CPU_BUFFER_FORMAT_YUV444P + : PYROWAVE_CPU_BUFFER_FORMAT_YUV420P); + + cpu_buffer.row_stride_in_bytes[0] = Width; + cpu_buffer.row_stride_in_bytes[1] = nv12_encode ? sizeof(cbcr[0]) : sizeof(cb[0]); + cpu_buffer.row_stride_in_bytes[2] = nv12_encode ? 0 : sizeof(cr[0]); + cpu_buffer.plane_size_in_bytes[0] = sizeof(luma); + cpu_buffer.plane_size_in_bytes[1] = nv12_encode ? sizeof(cbcr) : sizeof(cb); + cpu_buffer.plane_size_in_bytes[2] = nv12_encode ? 0 : sizeof(cr); + cpu_buffer.data[0] = &luma[0][0]; + + if (nv12_encode) + { + cpu_buffer.data[1] = &cbcr[0][0][0]; + } + else + { + cpu_buffer.data[1] = &cb[0][0]; + cpu_buffer.data[2] = &cr[0][0]; + } + + for (int y = 0; y < Height; y++) + { + for (int x = 0; x < Width; x++) + { + luma[y][x] = uint8_t(3 * x + 5 * y); + + uint8_t cb_signal = 7 * x + 3 * y; + uint8_t cr_signal = 3 * x + 5 * y; + + if (nv12_encode) + { + cbcr[y][x][0] = cb_signal; + cbcr[y][x][1] = cr_signal; + } + else + { + cb[y][x] = cb_signal; + cr[y][x] = cr_signal; + } + } + } + + cpu_buffer.width = Width; + cpu_buffer.height = Height; + const pyrowave_rate_control rate_control = { 64 * 1024 }; // Just give it something massive. + CHECKED(pyrowave_encoder_encode_cpu_synchronous(encoder, &cpu_buffer, &rate_control)); + + size_t num_packets; + CHECKED(pyrowave_encoder_compute_num_packets(encoder, 64 * 1024, &num_packets)); + ASSERT_THAT(num_packets == 1); + + std::vector bitstream(64 * 1024); + pyrowave_packet packet = {}; + CHECKED(pyrowave_encoder_packetize(encoder, &packet, 64 * 1024, &num_packets, bitstream.data(), bitstream.size())); + ASSERT_THAT(num_packets == 1); + ASSERT_THAT(packet.offset == 0); + ASSERT_THAT(packet.size != 0); + ASSERT_THAT(packet.size <= bitstream.size()); + bitstream.resize(packet.size); + + CHECKED(pyrowave_decoder_push_packet(decoder, bitstream.data() + packet.offset, packet.size)); + ASSERT_THAT(pyrowave_decoder_decode_is_ready(decoder, false)); + pyrowave_decoder_clear(decoder); + ASSERT_THAT(!pyrowave_decoder_decode_is_ready(decoder, false)); + CHECKED(pyrowave_decoder_push_packet(decoder, bitstream.data() + packet.offset, packet.size)); + ASSERT_THAT(pyrowave_decoder_decode_is_ready(decoder, false)); + + cpu_buffer.data[0] = &decode_luma[0][0]; + cpu_buffer.data[1] = &decode_cb[0][0]; + cpu_buffer.data[2] = &decode_cr[0][0]; + cpu_buffer.row_stride_in_bytes[1] = sizeof(decode_cb[0]); + cpu_buffer.row_stride_in_bytes[2] = sizeof(decode_cr[0]); + cpu_buffer.plane_size_in_bytes[1] = sizeof(decode_cb); + cpu_buffer.plane_size_in_bytes[2] = sizeof(decode_cr); + cpu_buffer.format = chroma == PYROWAVE_CHROMA_SUBSAMPLING_444 ? + PYROWAVE_CPU_BUFFER_FORMAT_YUV444P : PYROWAVE_CPU_BUFFER_FORMAT_YUV420P; + + CHECKED(pyrowave_decoder_decode_cpu_buffer_synchronous(decoder, &cpu_buffer)); + + for (int y = 0; y < Height; y++) + { + for (int x = 0; x < Width; x++) + { + int d = std::abs(int(decode_luma[y][x]) - int(luma[y][x])); + // With the "infinite" bitrate we get here, + // accept a maximum 1 ULP error. + ASSERT_THAT(d <= 1); + + if (chroma == PYROWAVE_CHROMA_SUBSAMPLING_444 || (!nv12_encode && y < Height / 2 && x < Width / 2)) + { + // Allow more error for chroma. + d = std::abs(int(decode_cb[y][x]) - int(cb[y][x])); + ASSERT_THAT(d <= 1); + d = std::abs(int(decode_cr[y][x]) - int(cr[y][x])); + ASSERT_THAT(d <= 1); + } + } + } + + if (nv12_encode) + { + for (int y = 0; y < Height / 2; y++) + { + for (int x = 0; x < Width / 2; x++) + { + int d = std::abs(int(decode_cb[y][x]) - int(cbcr[y][x][0])); + ASSERT_THAT(d <= 1); + d = std::abs(int(decode_cr[y][x]) - int(cbcr[y][x][1])); + ASSERT_THAT(d <= 1); + } + } + } + + pyrowave_decoder_destroy(decoder); + pyrowave_encoder_destroy(encoder); +} + +static void test_basic_system_stability() +{ + pyrowave_device device; + CHECKED(pyrowave_create_default_device(&device)); + + // 4K, upper bound of normal usage. + constexpr int Width = 3840; + constexpr int Height = 2160; + + pyrowave_decoder_create_info decoder_info = {}; + decoder_info.device = device; + decoder_info.width = Width; // Test somewhat odd size. Quite relevant for fragment path as well. + decoder_info.height = Height; + + pyrowave_encoder_create_info encoder_info = {}; + encoder_info.device = device; + encoder_info.width = Width; + encoder_info.height = Height; + + pyrowave_decoder decoder; + pyrowave_encoder encoder; + CHECKED(pyrowave_decoder_create(&decoder_info, &decoder)); + CHECKED(pyrowave_encoder_create(&encoder_info, &encoder)); + + std::vector luma(Width * Height); + std::vector cbcr(Width * Height / 4); + std::vector decode_luma(Width * Height); + std::vector decode_cb(Width * Height / 4); + std::vector decode_cr(Width * Height / 4); + + pyrowave_cpu_buffer encode_buffer = {}, decode_buffer = {}; + + encode_buffer.format = PYROWAVE_CPU_BUFFER_FORMAT_NV12; + encode_buffer.row_stride_in_bytes[0] = Width; + encode_buffer.row_stride_in_bytes[1] = Width; + encode_buffer.plane_size_in_bytes[0] = Width * Height; + encode_buffer.plane_size_in_bytes[1] = Width * Height / 2; + encode_buffer.data[0] = luma.data(); + encode_buffer.data[1] = cbcr.data(); + encode_buffer.width = Width; + encode_buffer.height = Height; + + decode_buffer.format = PYROWAVE_CPU_BUFFER_FORMAT_YUV420P; + decode_buffer.row_stride_in_bytes[0] = Width; + decode_buffer.row_stride_in_bytes[1] = Width / 2; + decode_buffer.row_stride_in_bytes[2] = Width / 2; + decode_buffer.plane_size_in_bytes[0] = Width * Height; + decode_buffer.plane_size_in_bytes[1] = Width * Height / 4; + decode_buffer.plane_size_in_bytes[2] = Width * Height / 4; + decode_buffer.data[0] = decode_luma.data(); + decode_buffer.data[1] = decode_cb.data(); + decode_buffer.data[2] = decode_cr.data(); + decode_buffer.width = Width; + decode_buffer.height = Height; + + const auto mirror = [](int v) -> uint8_t + { + v &= 511; + if (v > 255) + v = 511 - v; + ASSERT_THAT(v >= 0 && v <= 255); + return uint8_t(v); + }; + + // Just generate a synthetic signal. + for (int y = 0; y < Height; y++) + for (int x = 0; x < Width; x++) + luma[y * Width + x] = mirror(3 * x + 5 * y); + + for (int y = 0; y < Height / 2; y++) + for (int x = 0; x < Width / 2; x++) + cbcr[y * Width / 2 + x] = mirror(7 * x + y * 3) * 0x100 + mirror(y * 5 + x * 7); + + std::vector bitstream; + std::vector packets; + + for (int iter = 0; iter < 100; iter++) + { + // 240mbit equivalent for 60 fps. + const pyrowave_rate_control rate_control = { 500000 }; + + // Get some test coverage for async compute path. + CHECKED(pyrowave_device_set_queue_type(device, iter % 2 ? VK_QUEUE_COMPUTE_BIT : VK_QUEUE_GRAPHICS_BIT)); + + bitstream.reserve(rate_control.maximum_bitstream_size); + CHECKED(pyrowave_encoder_encode_cpu_synchronous(encoder, &encode_buffer, &rate_control)); + + size_t num_packets, after_packets; + CHECKED(pyrowave_encoder_compute_num_packets(encoder, 8 * 1024, &num_packets)); + ASSERT_THAT(num_packets > 1); + + packets.resize(num_packets); + bitstream.resize(rate_control.maximum_bitstream_size); + CHECKED(pyrowave_encoder_packetize(encoder, packets.data(), 8 * 1024, &after_packets, bitstream.data(), bitstream.size())); + ASSERT_THAT(num_packets == after_packets); + + // Verify that the bitstream is sound. We should be able to decode it. + size_t total_bitstream_size = 0; + + for (auto &packet : packets) + { + CHECKED(pyrowave_decoder_push_packet(decoder, bitstream.data() + packet.offset, packet.size)); + // When we push the last packet, we should get a complete frame. + ASSERT_THAT(pyrowave_decoder_decode_is_ready(decoder, false) == (&packet == &packets.back())); + total_bitstream_size += packet.size; + } + + // Verify that we tightly hit our rate control budget. + ASSERT_THAT(total_bitstream_size <= rate_control.maximum_bitstream_size); + ASSERT_THAT(total_bitstream_size >= 95 * rate_control.maximum_bitstream_size / 100); + + CHECKED(pyrowave_decoder_decode_cpu_buffer_synchronous(decoder, &decode_buffer)); + } + + pyrowave_decoder_destroy(decoder); + pyrowave_encoder_destroy(encoder); + + // Verify that PSNR is under control. + double y_error = 0.0; + double cb_error = 0.0; + double cr_error = 0.0; + + for (int i = 0; i < Width * Height; i++) + { + double y_d = double(luma[i]) - double(decode_luma[i]); + y_error += y_d * y_d; + } + + for (int i = 0; i < Width * Height / 4; i++) + { + double cb_d = double(cbcr[i] & 0xff) - double(decode_cb[i]); + cb_error += cb_d * cb_d; + double cr_d = double(cbcr[i] >> 8) - double(decode_cr[i]); + cr_error += cr_d * cr_d; + } + + double y_signal = 255.0 * 255.0 * Width * Height; + double chroma_signal = 255.0 * 255.0 * (Width * Height / 4); + double y_psnr = y_signal / y_error; + double cb_psnr = chroma_signal / cb_error; + double cr_psnr = chroma_signal / cr_error; + + // 40 dB, arbitrarily chosen for testing purposes. + ASSERT_THAT(y_psnr > 10000.0); + ASSERT_THAT(cb_psnr > 10000.0); + ASSERT_THAT(cr_psnr > 10000.0); + + // We're not hitting 60 dB. That'd mean we cheated or something or added bugs in the test code. + ASSERT_THAT(y_psnr < 1000000.0); + ASSERT_THAT(cb_psnr < 1000000.0); + ASSERT_THAT(cr_psnr < 1000000.0); + + int blah = 0; + pyrowave_device_report_performance_stats(device, [](void *userdata, const char *msg) + { + *static_cast(userdata) = 42; + printf("performance cb: %s\n", msg); + }, &blah, true); + + // Verify that userdata gets passed correctly. + ASSERT_THAT(blah == 42); + + pyrowave_device_destroy(device); +} + +int main() +{ + printf("Running system stability test ...\n"); + test_basic_system_stability(); + + // Correctness tests for small-ish outputs. + for (int variant = 0; variant < 8; variant++) + { + printf("Running roundtrip variant %d test ...\n", variant); + test_basic_encoder_roundtrip( + (variant & 1) != 0, (variant & 2) != 0, + (variant & 4) != 0 ? PYROWAVE_CHROMA_SUBSAMPLING_444 : PYROWAVE_CHROMA_SUBSAMPLING_420); + } + + // Validate that we handle error inputs gracefully. + printf("Running error handling tests ...\n"); + test_decode_cpu_buffer_validation(false); + test_decode_cpu_buffer_validation(true); + test_encode_cpu_buffer_validation(false); + test_encode_cpu_buffer_validation(true); + test_encoder_create_validation(); + test_decoder_create_validation(); + + printf("Passed all tests :)\n"); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_common.cpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_common.cpp new file mode 100644 index 00000000..a796f4c3 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_common.cpp @@ -0,0 +1,288 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#include "pyrowave_common.hpp" + +#if PYROWAVE_PRECISION < 0 || PYROWAVE_PRECISION > 2 +#error "PYROWAVE_PRECISION must be in range [0, 2]." +#endif + +constexpr int WaveletFP16Levels = 2; + +namespace PyroWave +{ +using namespace Vulkan; + +Configuration::Configuration() +{ + precision = PYROWAVE_PRECISION; + if (const char *env = getenv("PYROWAVE_PRECISION")) + precision = int(strtol(env, nullptr, 0)); + + if (precision < 0 || precision > 2) + { + fprintf(stderr, "pyrowave: precision must be in range [0, 2].\n"); + precision = PYROWAVE_PRECISION; + } + + LOGI("Selection precision level: %d\n", precision); +} + +Configuration &Configuration::get() +{ + static Configuration config; + return config; +} + +int Configuration::get_precision() const +{ + return precision; +} + +void WaveletBuffers::init_samplers() +{ + SamplerCreateInfo samp = {}; + samp.address_mode_u = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + samp.address_mode_v = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + samp.address_mode_w = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + samp.min_filter = VK_FILTER_NEAREST; + samp.mag_filter = VK_FILTER_NEAREST; + samp.mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + mirror_repeat_sampler = device->create_sampler(samp); + + samp.address_mode_u = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samp.address_mode_v = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samp.address_mode_w = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samp.border_color = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + border_sampler = device->create_sampler(samp); +} + +void WaveletBuffers::allocate_images_fragment() +{ + auto format = Configuration::get().get_precision() == 2 ? + VK_FORMAT_R32_SFLOAT : VK_FORMAT_R16_SFLOAT; + auto vert_chroma_format = Configuration::get().get_precision() == 2 ? + VK_FORMAT_R32G32_SFLOAT : VK_FORMAT_R16G16_SFLOAT; + + for (int level = 0; level < DecompositionLevels; level++) + { + uint32_t horiz_output_width = aligned_width >> (level + 1); + uint32_t horiz_output_height = aligned_height >> (level + 1); + uint32_t vert_input_width = horiz_output_width; + uint32_t vert_input_height = horiz_output_height * 2; + + auto info = ImageCreateInfo::render_target(horiz_output_width, horiz_output_height, format); + info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + char label[64]; + for (int comp = 0; comp < 3; comp++) + { + info.width = horiz_output_width; + info.height = horiz_output_height; + info.format = format; + fragment.levels[level].horiz[comp] = device->create_image(info); + snprintf(label, sizeof(label), "Horiz Output (level %u, comp %u)", level, comp); + device->set_name(*fragment.levels[level].horiz[comp], label); + + if (comp < 2) + { + info.width = vert_input_width; + info.height = vert_input_height; + info.format = comp == 0 ? format : vert_chroma_format; + fragment.levels[level].vert[0][comp] = device->create_image(info); + fragment.levels[level].vert[1][comp] = device->create_image(info); + + snprintf(label, sizeof(label), "Vert Even Input (level %u, comp %u)", level, comp); + device->set_name(*fragment.levels[level].vert[0][comp], label); + snprintf(label, sizeof(label), "Vert Odd Input (level %u, comp %u)", level, comp); + device->set_name(*fragment.levels[level].vert[1][comp], label); + } + } + + for (int comp = 0; comp < NumComponents; comp++) + { + auto &dequant_view = component_layer_views[comp][level]; + + for (int band = 0; band < NumFrequencyBandsPerLevel; band++) + { + Vulkan::ImageViewCreateInfo view_info = {}; + view_info.view_type = VK_IMAGE_VIEW_TYPE_2D; + view_info.levels = 1; + view_info.layers = 1; + + if (band == 0 && level < DecompositionLevels - 1) + { + view_info.image = fragment.levels[level].horiz[comp].get(); + view_info.base_level = 0; + view_info.base_layer = 0; + } + else if (dequant_view) + { + view_info.image = dequant_view->get_create_info().image; + view_info.base_level = dequant_view->get_create_info().base_level; + view_info.base_layer = dequant_view->get_create_info().base_layer; + view_info.base_layer += band; + } + + fragment.levels[level].decoded[comp][band] = device->create_image_view(view_info); + } + } + } +} + +void WaveletBuffers::allocate_images() +{ + auto info = ImageCreateInfo::immutable_2d_image( + aligned_width / 2, aligned_height / 2, + Configuration::get().get_precision() == 2 ? VK_FORMAT_R32_SFLOAT : VK_FORMAT_R16_SFLOAT); + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + info.layers = NumFrequencyBandsPerLevel * NumComponents; + info.layout = ImageLayout::General; + info.levels = Configuration::get().get_precision() != 1 ? DecompositionLevels : WaveletFP16Levels; + + wavelet_img_high_res = device->create_image(info); + device->set_name(*wavelet_img_high_res, "wavelet-buffer-high-res"); + + if (Configuration::get().get_precision() == 1) + { + // For the lowest level bands, we want to maintain precision as much as possible and bandwidth here is trivial. + info.levels = DecompositionLevels - info.levels; + info.format = VK_FORMAT_R32_SFLOAT; + info.width >>= WaveletFP16Levels; + info.height >>= WaveletFP16Levels; + wavelet_img_low_res = device->create_image(info); + device->set_name(*wavelet_img_low_res, "wavelet-buffer-low-res"); + } + + for (int level = 0; level < DecompositionLevels; level++) + { + ImageViewCreateInfo view_info = {}; + view_info.levels = 1; + view_info.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + + if (Configuration::get().get_precision() != 1 || level < WaveletFP16Levels) + { + view_info.base_level = level; + view_info.image = wavelet_img_high_res.get(); + } + else + { + view_info.base_level = level - WaveletFP16Levels; + view_info.image = wavelet_img_low_res.get(); + } + + for (int component = 0; component < NumComponents; component++) + { + view_info.base_layer = 4 * component; + + view_info.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + view_info.layers = 4; + component_layer_views[component][level] = device->create_image_view(view_info); + + view_info.view_type = VK_IMAGE_VIEW_TYPE_2D; + view_info.layers = 1; + component_ll_views[component][level] = device->create_image_view(view_info); + } + } +} + +void WaveletBuffers::accumulate_block_mapping(int blocks_x_8x8, int blocks_y_8x8) +{ + int blocks_x_32x32 = (blocks_x_8x8 + 3) / 4; + int blocks_y_32x32 = (blocks_y_8x8 + 3) / 4; + + for (int y = 0; y < blocks_y_32x32; y++) + { + for (int x = 0; x < blocks_x_32x32; x++) + { + BlockMapping mapping = {}; + mapping.block_offset_8x8 = block_count_8x8 + 4 * y * blocks_x_8x8 + 4 * x; + mapping.block_stride_8x8 = blocks_x_8x8; + mapping.block_width_8x8 = std::min(4, blocks_x_8x8 - 4 * x); + mapping.block_height_8x8 = std::min(4, blocks_y_8x8 - 4 * y); + block_32x32_to_8x8_mapping.push_back(mapping); + block_count_32x32++; + } + } + + block_count_8x8 += blocks_x_8x8 * blocks_y_8x8; +} + +void WaveletBuffers::init_block_meta() +{ + for (int level = DecompositionLevels - 1; level >= 0; level--) + { + for (int component = 0; component < NumComponents; component++) + { + // Ignore top-level CbCr when doing 420 subsampling. + if (level == 0 && component != 0 && chroma == ChromaSubsampling::Chroma420) + continue; + + for (int band = (level == DecompositionLevels - 1 ? 0 : 1); band < 4; band++) + { + uint32_t level_width = wavelet_img_high_res->get_width(level); + uint32_t level_height = wavelet_img_high_res->get_height(level); + + int blocks_x_8x8 = (level_width + 7) / 8; + int blocks_y_8x8 = (level_height + 7) / 8; + int blocks_x_32x32 = (level_width + 31) / 32; + + block_meta[component][level][band] = { + block_count_8x8, blocks_x_8x8, + block_count_32x32, blocks_x_32x32, + }; + + accumulate_block_mapping(blocks_x_8x8, blocks_y_8x8); + } + } + } +} + +bool WaveletBuffers::init(Device *device_, int width_, int height_, ChromaSubsampling chroma_, bool fragment_path_) +{ + device = device_; + width = width_; + height = height_; + chroma = chroma_; + fragment_path = fragment_path_; + + aligned_width = align(width, Alignment); + aligned_height = align(height, Alignment); + aligned_width = std::max(aligned_width, MinimumImageSize); + aligned_height = std::max(aligned_height, MinimumImageSize); + + init_samplers(); + allocate_images(); + if (fragment_path) + allocate_images_fragment(); + + init_block_meta(); + + Vulkan::ResourceLayout layout; + + // If the GPU is sufficiently competent with texel buffers, we can use that as a fallback to 8-bit storage. + if (device->get_gpu_properties().limits.maxTexelBufferElements >= 16 * 1024 * 1024) + { + auto vendor_id = device->get_gpu_properties().vendorID; + if (!device->get_device_features().vk12_features.storageBuffer8BitAccess || + (vendor_id != VENDOR_ID_AMD && vendor_id != VENDOR_ID_INTEL && vendor_id != VENDOR_ID_NVIDIA && + device->get_device_features().driver_id != VK_DRIVER_ID_SAMSUNG_PROPRIETARY)) + { + use_readonly_texel_buffer = true; + } + } + + if (use_readonly_texel_buffer) + LOGI("Using texel buffers instead of SSBO.\n"); + + shaders = Shaders<>(*device, layout, [this](const char *, const char *env) { + if (strcmp(env, "FP16") == 0) + return device->get_device_features().vk12_features.shaderFloat16 ? 1 : 0; + return 0; + }); + + return true; +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_common.hpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_common.hpp new file mode 100644 index 00000000..3babf07f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_common.hpp @@ -0,0 +1,221 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#pragma once + +#include +#include "device.hpp" +#include "buffer.hpp" +#include "image.hpp" +#include "pyrowave_config.hpp" +#include "shaders/slangmosh.hpp" + +namespace PyroWave +{ +struct BitstreamPacket +{ + uint32_t offset_u32; + uint32_t num_words; +}; + +struct BitstreamHeader +{ + uint16_t ballot; + uint16_t payload_words : 12; + uint16_t sequence : 3; + uint16_t extended : 1; + uint32_t quant_code : 8; + uint32_t block_index : 24; +}; + +static_assert(sizeof(BitstreamHeader) == 8, "BitstreamHeader is not 8 bytes."); + +enum +{ + BITSTREAM_EXTENDED_CODE_START_OF_FRAME = 0, +}; + +enum +{ + CHROMA_RESOLUTION_420 = 0, + CHROMA_RESOLUTION_444 = 1 +}; + +enum +{ + CHROMA_SITING_CENTER = 0, + CHROMA_SITING_LEFT = 1 +}; + +enum +{ + YCBCR_RANGE_FULL = 0, + YCBCR_RANGE_LIMITED = 1 +}; + +enum +{ + COLOR_PRIMARIES_BT709 = 0, + COLOR_PRIMARIES_BT2020 = 1 +}; + +enum +{ + YCBCR_TRANSFORM_BT709 = 0, + YCBCR_TRANSFORM_BT2020 = 1 +}; + +enum +{ + TRANSFER_FUNCTION_BT709 = 0, + TRANSFER_FUNCTION_PQ = 1 +}; + +static constexpr uint32_t SequenceCountMask = 0x7; + +struct BitstreamSequenceHeader +{ + uint32_t width_minus_1 : 14; + uint32_t height_minus_1 : 14; + uint32_t sequence : 3; + uint32_t extended : 1; + uint32_t total_blocks : 24; + uint32_t code : 2; + uint32_t chroma_resolution : 1; + uint32_t color_primaries : 1; + uint32_t transfer_function : 1; + uint32_t ycbcr_transform : 1; + uint32_t ycbcr_range : 1; + uint32_t chroma_siting : 1; +}; + +static_assert(sizeof(BitstreamSequenceHeader) == 8, "BitstreamSequenceHeader is not 8 bytes."); + +struct QuantStats +{ + uint16_t square_error_fp16; + uint16_t encode_cost_bits; +}; + +struct BlockStats +{ + uint32_t num_planes; + QuantStats stats[15]; +}; +static_assert(sizeof(BlockStats) == 64, "BlockStats is not 64 bytes."); + +struct BlockMeta +{ + uint32_t code_word; + uint32_t offset; +}; + +static constexpr int DecompositionLevels = 5; +static constexpr int Alignment = 1 << DecompositionLevels; +// If the final decomposition band is too small, the mirroring will break since it starts double mirroring. +static constexpr int MinimumImageSize = 4 << DecompositionLevels; +static constexpr int NumComponents = 3; +static constexpr int NumFrequencyBandsPerLevel = 4; + +static inline int align(int value, int align) +{ + return (value + align - 1) & ~(align - 1); +} + +static constexpr int MaxScaleExp = 4; + +static inline float decode_quant(uint8_t quant_code) +{ + // Custom FP formulation for numbers in (0, 2) range. + int e = MaxScaleExp - (quant_code >> 3); + int m = quant_code & 0x7; + float inv_quant = (1.0f / (8.0f * 1024.0f * 1024.0f)) * float((8 + m) * (1 << (20 + e))); + return inv_quant; +} + +static inline uint8_t encode_quant(float decoder_q_scale) +{ + uint32_t v; + memcpy(&v, &decoder_q_scale, sizeof(decoder_q_scale)); + + int e = ((v >> 23) & 0xff) - 127 - MaxScaleExp; + int m = (v >> 20) & 0x7; + e = -e; + assert(e >= 0 && e <= 20); + return (e << 3) | m; +} + +class Configuration +{ +public: + static Configuration &get(); + int get_precision() const; +private: + Configuration(); + int precision; +}; + +struct WaveletBuffers +{ + bool init(Vulkan::Device *device, int width, int height, ChromaSubsampling chroma, bool fragment_path); + + Vulkan::Device *device = nullptr; + Vulkan::ImageHandle wavelet_img_low_res; + Vulkan::ImageHandle wavelet_img_high_res; + Vulkan::SamplerHandle mirror_repeat_sampler; + Vulkan::SamplerHandle border_sampler; + Vulkan::ImageViewHandle component_layer_views[NumComponents][DecompositionLevels]; + Vulkan::ImageViewHandle component_ll_views[NumComponents][DecompositionLevels]; + + // For fragment based iDWT. + struct + { + struct + { + Vulkan::ImageHandle vert[2][2]; + Vulkan::ImageHandle horiz[NumComponents]; + Vulkan::ImageViewHandle decoded[NumComponents][NumFrequencyBandsPerLevel]; + } levels[DecompositionLevels]; + } fragment; + + struct BlockInfo + { + int block_offset_8x8; + int block_stride_8x8; + int block_offset_32x32; + int block_stride_32x32; + }; + BlockInfo block_meta[NumComponents][DecompositionLevels][4] = {}; + + struct BlockMapping + { + int block_offset_8x8; + int block_stride_8x8; + int block_width_8x8; + int block_height_8x8; + }; + std::vector block_32x32_to_8x8_mapping; + + int block_count_8x8 = 0; + int block_count_32x32 = 0; + + int width = 0; + int height = 0; + int aligned_width = 0; + int aligned_height = 0; + + bool use_readonly_texel_buffer = false; + bool fragment_path = false; + +protected: + void init_samplers(); + void allocate_images(); + void allocate_images_fragment(); + virtual void init_block_meta(); + ChromaSubsampling chroma = {}; + + Shaders<> shaders; + +private: + void accumulate_block_mapping(int blocks_x_8x8, int blocks_y_8x8); +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_config.hpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_config.hpp new file mode 100644 index 00000000..ec3f82ae --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_config.hpp @@ -0,0 +1,22 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#pragma once + +namespace Vulkan +{ +class ImageView; +} + +namespace PyroWave +{ +struct ViewBuffers +{ + const Vulkan::ImageView *planes[3]; +}; + +enum class ChromaSubsampling +{ + Chroma420, + Chroma444 +}; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_decoder.cpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_decoder.cpp new file mode 100644 index 00000000..64958bd0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_decoder.cpp @@ -0,0 +1,986 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#include "pyrowave_decoder.hpp" +#include "device.hpp" +#include "buffer.hpp" +#include "image.hpp" +#include "math.hpp" +#include "pyrowave_common.hpp" +#include + +namespace PyroWave +{ +using namespace Granite; +using namespace Vulkan; + +struct DequantizerPushData +{ + ivec2 resolution; + int32_t output_layer; + int32_t block_offset_32x32; + int32_t block_stride_32x32; +}; + +struct Decoder::Impl final : public WaveletBuffers +{ + BufferHandle dequant_offset_buffer, payload_data; + BufferViewHandle payload_u32_view, payload_u16_view, payload_u8_view; + + // Turbo-hacky path. + DeviceAllocationOwnerHandle linear_memory; + ImageHandle payload_r8_image, payload_r16_image, payload_r32_image; + bool need_image_transition = true; + + std::vector dequant_offset_buffer_cpu; + std::vector payload_data_cpu; + int decoded_blocks = 0; + int total_blocks_in_sequence = 0; + uint32_t last_seq = UINT32_MAX; + bool decoded_frame_for_current_sequence = false; + + bool push_packet(const void *data, size_t size); + bool decode(CommandBuffer &cmd, const ViewBuffers &views); + bool decode_is_ready(bool allow_partial_frame) const; + + bool decode_packet(const BitstreamHeader *header); + + bool dequant(CommandBuffer &cmd); + bool idwt(CommandBuffer &cmd, const ViewBuffers &views); + bool idwt_fragment(CommandBuffer &cmd, const ViewBuffers &views); + void init_block_meta() override; + void clear(); + + void upload_payload(CommandBuffer &cmd); + + void check_linear_texture_support(); +}; + +Decoder::Decoder() +{ + impl.reset(new Impl); +} + +Decoder::~Decoder() +{ +} + +void Decoder::Impl::upload_payload(CommandBuffer &cmd) +{ + VkDeviceSize required_size = payload_data_cpu.size() * sizeof(uint32_t); + + // Avoid edge case OOB access without robustness on the payload buffer during dequant. + VkDeviceSize required_size_padded = required_size + 16; + + if (!payload_data || required_size_padded > payload_data->get_create_info().size) + { + BufferCreateInfo bufinfo; + bufinfo.size = std::max(64 * 1024, required_size_padded * 2); + bufinfo.usage = + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + bufinfo.domain = BufferDomain::Device; + payload_data = device->create_buffer(bufinfo); + device->set_name(*payload_data, "payload-data"); + + if (use_readonly_texel_buffer) + { + BufferViewCreateInfo view_info = {}; + view_info.buffer = payload_data.get(); + view_info.range = VK_WHOLE_SIZE; + + view_info.format = VK_FORMAT_R8_UINT; + payload_u8_view = device->create_buffer_view(view_info); + view_info.format = VK_FORMAT_R16_UINT; + payload_u16_view = device->create_buffer_view(view_info); + view_info.format = VK_FORMAT_R32_UINT; + payload_u32_view = device->create_buffer_view(view_info); + } + + // This shouldn't happen to demote to texel buffers if we need to deal with massive gigantic payloads. + payload_r8_image.reset(); + payload_r16_image.reset(); + payload_r32_image.reset(); + } + + if (need_image_transition) + { + cmd.begin_barrier_batch(); + const Image *imgs[] = { payload_r8_image.get(), payload_r16_image.get(), payload_r32_image.get() }; + for (auto *img : imgs) + { + if (img) + { + cmd.image_barrier(*img, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_GENERAL, + 0, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + } + cmd.end_barrier_batch(); + need_image_transition = false; + } + + if (!payload_data_cpu.empty()) + memcpy(cmd.update_buffer(*payload_data, 0, required_size), payload_data_cpu.data(), required_size); +} + +bool Decoder::Impl::decode_packet(const BitstreamHeader *header) +{ + auto &offset = dequant_offset_buffer_cpu[header->block_index]; + if (offset == UINT32_MAX) + { + decoded_blocks++; + offset = payload_data_cpu.size(); + } + else + { + return true; + } + + auto *payload_words = reinterpret_cast(header); + + if (sizeof(*header) / sizeof(uint32_t) > header->payload_words) + { + LOGE("payload_words is not large enough.\n"); + return false; + } + + payload_data_cpu.insert( + payload_data_cpu.end(), + payload_words, + payload_words + header->payload_words); + return true; +} + +bool Decoder::Impl::push_packet(const void *data_, size_t size) +{ + auto *data = static_cast(data_); + while (size >= sizeof(BitstreamHeader)) + { + auto *header = reinterpret_cast(data); + + if (header->extended != 0) + { + auto *seq = reinterpret_cast(header); + + if (sizeof(*header) > size) + { + LOGE("Parsing sequence header, but only %zu bytes left to parse.\n", size); + return false; + } + + if (seq->chroma_resolution != int(chroma)) + { + LOGE("Chroma resolution mismatch!\n"); + return false; + } + + uint8_t diff = (header->sequence - last_seq) & SequenceCountMask; + if (last_seq != UINT32_MAX && diff > (SequenceCountMask / 2)) + { + return true; + } + + if (last_seq == UINT32_MAX || diff != 0) + { + clear(); + last_seq = header->sequence; + } + + if (seq->code == BITSTREAM_EXTENDED_CODE_START_OF_FRAME) + { + if (seq->width_minus_1 + 1 != width || seq->height_minus_1 + 1 != height) + { + LOGE("Dimension mismatch in seq packet, (%d, %d) != (%d, %d)\n", + seq->width_minus_1 + 1, seq->height_minus_1 + 1, width, height); + return false; + } + + total_blocks_in_sequence = int(seq->total_blocks); + } + else + { + LOGE("Unrecognized sequence header mode %u.\n", seq->code); + return false; + } + + data += sizeof(*header); + size -= sizeof(*header); + + continue; + } + + size_t packet_size = header->payload_words * sizeof(uint32_t); + + if (packet_size > size) + { + LOGE("Packet header states %zu bytes, but only %zu bytes left to parse.\n", packet_size, size); + return false; + } + + bool restart; + + if (last_seq == UINT32_MAX) + { + restart = true; + } + else + { + uint8_t diff = (header->sequence - last_seq) & SequenceCountMask; + if (diff > (SequenceCountMask / 2)) + { + return true; + } + restart = diff != 0; + } + + if (restart) + { + clear(); + last_seq = header->sequence; + } + + if (header->block_index >= uint32_t(block_count_32x32)) + { + LOGE("block_index %u is out of bounds (>= %d).\n", header->block_index, block_count_32x32); + return false; + } + + if (!decode_packet(header)) + return false; + + data += packet_size; + size -= packet_size; + } + + if (size != 0) + { + LOGE("Did not consume packet completely.\n"); + return false; + } + + return true; +} + +void Decoder::Impl::init_block_meta() +{ + WaveletBuffers::init_block_meta(); + + BufferCreateInfo info; + info.domain = BufferDomain::Device; + info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + + info.size = block_count_32x32 * sizeof(uint32_t); + dequant_offset_buffer = device->create_buffer(info); + device->set_name(*dequant_offset_buffer, "meta-buffer"); + dequant_offset_buffer_cpu.resize(block_count_32x32); + + payload_data_cpu.reserve(1024 * 1024); +} + +bool Decoder::Impl::dequant(CommandBuffer &cmd) +{ + DequantizerPushData push = {}; + + cmd.set_specialization_constant_mask(0); + cmd.enable_subgroup_size_control(true); + + if (device->supports_subgroup_size_log2(true, 4, 7)) + { + cmd.set_subgroup_size_log2(true, 4, 7); + } + else if (device->supports_subgroup_size_log2(true, 2, 7)) + { + cmd.set_subgroup_size_log2(true, 2, 7); + } + else + { + LOGE("No compatible subgroup size config.\n"); + return false; + } + + if (payload_r8_image && payload_r16_image && payload_r32_image) + cmd.set_program(shaders.wavelet_dequant[2]); + else if (use_readonly_texel_buffer) + cmd.set_program(shaders.wavelet_dequant[1]); + else + cmd.set_program(shaders.wavelet_dequant[0]); + + cmd.begin_region("DWT dequant"); + auto start_dequant = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + + cmd.image_barrier(*wavelet_img_high_res, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + + if (wavelet_img_low_res) + { + cmd.image_barrier(*wavelet_img_low_res, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + } + + // De-quantize + for (int level = 0; level < DecompositionLevels; level++) + { + for (int component = 0; component < NumComponents; component++) + { + // Ignore top-level CbCr when doing 420 subsampling. + if (level == 0 && component != 0 && chroma == ChromaSubsampling::Chroma420) + continue; + + char label[128]; + snprintf(label, sizeof(label), "level %d - component %d", level, component); + cmd.begin_region(label); + + for (int band = (level == DecompositionLevels - 1 ? 0 : 1); band < 4; band++) + { + push.resolution.x = wavelet_img_high_res->get_width(level); + push.resolution.y = wavelet_img_high_res->get_height(level); + push.output_layer = band; + push.block_offset_32x32 = block_meta[component][level][band].block_offset_32x32; + push.block_stride_32x32 = block_meta[component][level][band].block_stride_32x32; + cmd.push_constants(&push, 0, sizeof(push)); + + cmd.set_storage_texture(0, 0, *component_layer_views[component][level]); + cmd.set_storage_buffer(0, 1, *dequant_offset_buffer); + + if (payload_r8_image && payload_r16_image && payload_r32_image) + { + cmd.set_texture(0, 2, payload_r32_image->get_view()); + cmd.set_texture(0, 3, payload_r16_image->get_view()); + cmd.set_texture(0, 4, payload_r8_image->get_view()); + } + else if (use_readonly_texel_buffer) + { + cmd.set_buffer_view(0, 2, *payload_u32_view); + cmd.set_buffer_view(0, 3, *payload_u16_view); + cmd.set_buffer_view(0, 4, *payload_u8_view); + } + else + cmd.set_storage_buffer(0, 2, *payload_data); + + cmd.dispatch((push.resolution.x + 31) / 32, (push.resolution.y + 31) / 32, 1); + } + + cmd.end_region(); + } + } + + cmd.barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + fragment_path ? VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT : VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + + auto end_dequant = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + cmd.end_region(); + cmd.enable_subgroup_size_control(false); + device->register_time_interval("GPU", std::move(start_dequant), std::move(end_dequant), "Dequant"); + + return true; +} + +bool Decoder::Impl::idwt_fragment(CommandBuffer &cmd, const ViewBuffers &views) +{ + const auto add_discard = [&](const Vulkan::Image *img) { + if (img) + { + cmd.image_barrier(*img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + } + }; + + const auto add_read_only = [&](const Vulkan::Image *img) { + if (img) + { + cmd.image_barrier(*img, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + }; + + cmd.begin_barrier_batch(); + for (auto &level : fragment.levels) + { + for (auto &vert : level.vert) + for (auto &comp : vert) + add_discard(comp.get()); + for (auto &comp : level.horiz) + add_discard(comp.get()); + } + cmd.end_barrier_batch(); + + auto start_idwt = cmd.write_timestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + + struct Push + { + float u_offset; + float v_offset; + float half_texel_offset_u; + float half_texel_offset_v; + float vp_scale; + uint32_t pivot_size; + } push = {}; + + for (int input_level = DecompositionLevels - 1; input_level >= 0; input_level--) + { + int output_level = input_level - 1; + + char label[128]; + if (output_level >= 0) + snprintf(label, sizeof(label), "Fragment iDWT level %u", output_level); + else + snprintf(label, sizeof(label), "Fragment iDWT final"); + cmd.begin_region(label); + + Vulkan::RenderPassInfo rp_info = {}; + + bool has_chroma_output = output_level >= 0 || chroma == ChromaSubsampling::Chroma444; + + Vulkan::Program *vert_prog; + Vulkan::Program *horiz_prog; + + if (has_chroma_output) + { + rp_info.store_attachments = 0x3; + rp_info.num_color_attachments = 2; + vert_prog = device->request_program(shaders.idwt_vs, shaders.idwt_fs[1]); + horiz_prog = device->request_program(shaders.idwt_vs, shaders.idwt_fs[2]); + } + else + { + rp_info.store_attachments = 0x1; + rp_info.num_color_attachments = 1; + vert_prog = device->request_program(shaders.idwt_vs, shaders.idwt_fs[0]); + horiz_prog = vert_prog; + } + + // Vertical passes. + for (int vert_pass = 0; vert_pass < 2; vert_pass++) + { + rp_info.color_attachments[0] = &fragment.levels[input_level].vert[vert_pass][0]->get_view(); + if (has_chroma_output) + rp_info.color_attachments[1] = &fragment.levels[input_level].vert[vert_pass][1]->get_view(); + + cmd.begin_render_pass(rp_info); + cmd.set_program(vert_prog); + cmd.set_opaque_sprite_state(); + cmd.set_specialization_constant_mask(0x1 | 0x8); + cmd.set_specialization_constant(0, true); + + cmd.set_texture(0, 0, *fragment.levels[input_level].decoded[0][vert_pass + 0]); + cmd.set_texture(0, 1, *fragment.levels[input_level].decoded[0][vert_pass + 2]); + cmd.set_sampler(0, 2, *mirror_repeat_sampler); + + if (has_chroma_output) + { + cmd.set_texture(0, 3, *fragment.levels[input_level].decoded[1][vert_pass + 0]); + cmd.set_texture(0, 4, *fragment.levels[input_level].decoded[1][vert_pass + 2]); + cmd.set_texture(0, 5, *fragment.levels[input_level].decoded[2][vert_pass + 0]); + cmd.set_texture(0, 6, *fragment.levels[input_level].decoded[2][vert_pass + 2]); + } + + uint32_t render_width = rp_info.color_attachments[0]->get_view_width(); + uint32_t render_height = rp_info.color_attachments[0]->get_view_height(); + + // Set mirror point. + // Work around broken Mali r38.1 compiler. + // If it sees negative texture offsets it breaks the output for whatever reason (!?!?!?!). + auto *input_view = fragment.levels[input_level].decoded[0][0].get(); + push.u_offset = 0.0f; + push.v_offset = -2.0f / float(input_view->get_view_height()); + push.half_texel_offset_u = 0.5f / float(input_view->get_view_width()); + push.half_texel_offset_v = 0.5f / float(input_view->get_view_height()); + push.vp_scale = cmd.get_viewport().height; + push.pivot_size = render_height; + cmd.push_constants(&push, 0, sizeof(push)); + + // Render top edge condition. + cmd.set_specialization_constant(3, -1); + cmd.set_scissor({{ 0, 0 }, { render_width, 8 }}); + cmd.draw(3); + + // Render normal path + cmd.set_specialization_constant(3, 0); + cmd.set_scissor({{ 0, 8 }, { render_width, render_height - 16 }}); + cmd.draw(3); + + // Render bottom edge condition + cmd.set_specialization_constant(3, +1); + cmd.set_scissor({{ 0, int(render_height) - 8 }, { render_width, 8 }}); + cmd.draw(3); + + cmd.end_render_pass(); + } + + cmd.begin_barrier_batch(); + for (auto &vert : fragment.levels[input_level].vert) + for (auto &comp : vert) + add_read_only(comp.get()); + cmd.end_barrier_batch(); + + if (has_chroma_output) + { + rp_info.num_color_attachments = 3; + rp_info.store_attachments = 0x7; + } + else + { + rp_info.num_color_attachments = 1; + rp_info.store_attachments = 0x1; + } + + for (uint32_t comp = 0; comp < rp_info.num_color_attachments; comp++) + { + if (output_level < 0 || (output_level == 0 && chroma == ChromaSubsampling::Chroma420 && comp != 0)) + rp_info.color_attachments[comp] = views.planes[comp]; + else + rp_info.color_attachments[comp] = &fragment.levels[output_level].horiz[comp]->get_view(); + } + + cmd.begin_render_pass(rp_info); + cmd.set_program(horiz_prog); + cmd.set_opaque_sprite_state(); + cmd.set_specialization_constant_mask(0xf); + cmd.set_specialization_constant(0, false); + cmd.set_specialization_constant(1, output_level < 0); + cmd.set_specialization_constant(2, output_level < 0 || (output_level == 0 && chroma == ChromaSubsampling::Chroma420)); + + cmd.set_texture(0, 0, fragment.levels[input_level].vert[0][0]->get_view()); + cmd.set_texture(0, 1, fragment.levels[input_level].vert[1][0]->get_view()); + cmd.set_sampler(0, 2, *mirror_repeat_sampler); + + if (has_chroma_output) + { + cmd.set_texture(0, 3, fragment.levels[input_level].vert[0][1]->get_view()); + cmd.set_texture(0, 4, fragment.levels[input_level].vert[1][1]->get_view()); + } + + uint32_t aligned_render_width = aligned_width >> (output_level + 1); + uint32_t aligned_render_height = aligned_height >> (output_level + 1); + + // Chroma output might be smaller than Y in output_level == 0 due to not using alignment. + // This is reflected in the actual render area, which is equal to default viewport. + auto render_width = uint32_t(cmd.get_viewport().width); + auto render_height = uint32_t(cmd.get_viewport().height); + + // In case we're rendering to an output texture, + // the render area might be smaller than we expect for purposes of alignment. + // Use properly scaled viewport that we scissor away as needed. + cmd.set_viewport({ 0, 0, float(aligned_render_width), float(aligned_render_height), 0, 1 }); + + // Set mirror point. + auto *input_view = &fragment.levels[input_level].vert[0][0]->get_view(); + push.u_offset = -2.0f / float(input_view->get_view_width()); + push.v_offset = 0.0f; + push.half_texel_offset_u = 0.5f / float(input_view->get_view_width()); + push.half_texel_offset_v = 0.5f / float(input_view->get_view_height()); + push.vp_scale = cmd.get_viewport().width; + push.pivot_size = aligned_render_width; + cmd.push_constants(&push, 0, sizeof(push)); + + // Render left edge condition. + cmd.set_specialization_constant(3, -1); + cmd.set_scissor({{ 0, 0 }, { 8, render_height }}); + cmd.draw(3); + + // Render normal condition + cmd.set_specialization_constant(3, 0); + cmd.set_scissor({{ 8, 0 }, { std::min(render_width - 8, aligned_render_width - 16), render_height }}); + cmd.draw(3); + + uint32_t aligned_x = aligned_render_width - 8; + if (aligned_x < render_width) + { + // Render right edge condition + cmd.set_specialization_constant(3, +1); + cmd.set_scissor({{ int(aligned_x), 0 }, { render_width - aligned_x, render_height }}); + cmd.draw(3); + } + + cmd.end_render_pass(); + + // If chroma is subsampled, we cannot render the fully padded region in one render pass due to + // rules regarding renderArea. renderArea cannot exceed the smallest image in the render pass. + // We cannot use subpasses either, so split the render pass, but that's mostly fine, + // since renderArea is non-overlapping. + if (output_level == 0 && chroma == ChromaSubsampling::Chroma420) + { + rp_info.num_color_attachments = 1; + rp_info.store_attachments = 0x1; + + VkMemoryBarrier2 by_region = { VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 }; + by_region.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + by_region.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + by_region.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + by_region.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + VkDependencyInfo dep = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO }; + dep.memoryBarrierCount = 1; + dep.pMemoryBarriers = &by_region; + dep.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + // Need vertical fixup (very common for 1080p). + if (rp_info.color_attachments[1]->get_view_height() < rp_info.color_attachments[0]->get_view_height()) + { + // Insert a simple by_region barrier to ensure we follow Vulkan rules for RW access. + cmd.barrier(dep); + + rp_info.render_area.extent.width = rp_info.color_attachments[0]->get_view_width(); + rp_info.render_area.extent.height = + rp_info.color_attachments[0]->get_view_height() - + rp_info.color_attachments[1]->get_view_height(); + rp_info.render_area.offset.x = 0; + rp_info.render_area.offset.y = rp_info.color_attachments[1]->get_view_height(); + + cmd.begin_render_pass(rp_info); + cmd.set_program(device->request_program(shaders.idwt_vs, shaders.idwt_fs[0])); + cmd.set_opaque_sprite_state(); + cmd.set_texture(0, 0, fragment.levels[input_level].vert[0][0]->get_view()); + cmd.set_texture(0, 1, fragment.levels[input_level].vert[1][0]->get_view()); + cmd.set_sampler(0, 2, *mirror_repeat_sampler); + cmd.set_viewport({ 0, 0, float(aligned_render_width), float(aligned_render_height), 0, 1 }); + cmd.set_specialization_constant_mask(0x8); + cmd.push_constants(&push, 0, sizeof(push)); + cmd.set_specialization_constant(3, 1); // Always consider edge handling. + cmd.draw(3); + cmd.end_render_pass(); + } + + // Need horizontal fixup (very rare). + if (rp_info.color_attachments[1]->get_view_width() < rp_info.color_attachments[0]->get_view_width()) + { + cmd.barrier(dep); + + rp_info.render_area.extent.width = + rp_info.color_attachments[0]->get_view_width() - + rp_info.color_attachments[1]->get_view_width(); + rp_info.render_area.extent.height = rp_info.color_attachments[0]->get_view_height(); + rp_info.render_area.offset.x = rp_info.color_attachments[1]->get_view_width(); + rp_info.render_area.offset.y = 0; + + cmd.begin_render_pass(rp_info); + cmd.set_program(device->request_program(shaders.idwt_vs, shaders.idwt_fs[0])); + cmd.set_opaque_sprite_state(); + cmd.set_texture(0, 0, fragment.levels[input_level].vert[0][0]->get_view()); + cmd.set_texture(0, 1, fragment.levels[input_level].vert[1][0]->get_view()); + cmd.set_sampler(0, 2, *mirror_repeat_sampler); + cmd.set_viewport({ 0, 0, float(aligned_render_width), float(aligned_render_height), 0, 1 }); + cmd.set_specialization_constant_mask(0x8); + cmd.push_constants(&push, 0, sizeof(push)); + cmd.set_specialization_constant(3, 1); // Always consider edge handling. + cmd.draw(3); + cmd.end_render_pass(); + } + } + + if (output_level >= 0) + { + cmd.begin_barrier_batch(); + for (auto &comp: fragment.levels[output_level].horiz) + add_read_only(comp.get()); + cmd.end_barrier_batch(); + } + + cmd.end_region(); + } + + auto end_idwt = cmd.write_timestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + device->register_time_interval("GPU", std::move(start_idwt), std::move(end_idwt), "iDWT fragment"); + + cmd.set_specialization_constant_mask(0); + + // Avoid WAR hazard for dequantization. + cmd.barrier(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0); + + return true; +} + +bool Decoder::Impl::idwt(CommandBuffer &cmd, const ViewBuffers &views) +{ + cmd.set_program(shaders.idwt[Configuration::get().get_precision()]); + cmd.enable_subgroup_size_control(false); + + auto start_idwt = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + + struct + { + ivec2 resolution; + vec2 inv_resolution; + } push = {}; + + for (int input_level = DecompositionLevels - 1; input_level >= 0; input_level--) + { + // Transposed. + push.resolution.x = component_layer_views[0][input_level]->get_view_height(); + push.resolution.y = component_layer_views[0][input_level]->get_view_width(); + push.inv_resolution.x = 1.0f / float(push.resolution.x); + push.inv_resolution.y = 1.0f / float(push.resolution.y); + cmd.push_constants(&push, 0, sizeof(push)); + cmd.set_specialization_constant_mask(1); + cmd.set_specialization_constant(0, false); + + if (input_level == 0) + { + cmd.set_specialization_constant(0, true); + if (chroma == ChromaSubsampling::Chroma444) + { + for (int c = 0; c < NumComponents; c++) + { + char label[64]; + snprintf(label, sizeof(label), "iDWT final, component %u", c); + cmd.begin_region(label); + cmd.set_storage_texture(0, 1, *views.planes[c]); + cmd.set_texture(0, 0, *component_layer_views[c][input_level], *mirror_repeat_sampler); + cmd.dispatch((push.resolution.x + 15) / 16, (push.resolution.y + 15) / 16, 1); + cmd.end_region(); + } + } + else + { + cmd.set_storage_texture(0, 1, *views.planes[0]); + cmd.begin_region("iDWT final"); + cmd.set_texture(0, 0, *component_layer_views[0][input_level], *mirror_repeat_sampler); + cmd.dispatch((push.resolution.x + 15) / 16, (push.resolution.y + 15) / 16, 1); + cmd.end_region(); + } + } + else + { + for (int c = 0; c < NumComponents; c++) + { + cmd.set_texture(0, 0, *component_layer_views[c][input_level], *mirror_repeat_sampler); + + if (chroma == ChromaSubsampling::Chroma420 && c != 0 && input_level == 1) + { + cmd.set_storage_texture(0, 1, *views.planes[c]); + cmd.set_specialization_constant(0, true); + } + else + cmd.set_storage_texture(0, 1, *component_ll_views[c][input_level - 1]); + + char label[64]; + snprintf(label, sizeof(label), "iDWT level %u, component %u", input_level - 1, c); + cmd.begin_region(label); + cmd.dispatch((push.resolution.x + 15) / 16, (push.resolution.y + 15) / 16, 1); + cmd.end_region(); + } + } + + cmd.set_specialization_constant_mask(0); + cmd.barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + + auto end_idwt = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + device->register_time_interval("GPU", std::move(start_idwt), std::move(end_idwt), "iDWT"); + return true; +} + +bool Decoder::Impl::decode_is_ready(bool allow_partial_frame) const +{ + if (decoded_frame_for_current_sequence) + return false; + + if (last_seq == UINT32_MAX) + return false; + + // Need at least half of the frame decoded to accept, otherwise we assume the frame is complete garbage. + if (decoded_blocks < total_blocks_in_sequence) + if (!allow_partial_frame || decoded_blocks <= total_blocks_in_sequence / 2) + return false; + + return true; +} + +bool Decoder::Impl::decode(CommandBuffer &cmd, const ViewBuffers &views) +{ + cmd.begin_region("Decode uploads"); + { + upload_payload(cmd); + + memcpy(cmd.update_buffer(*dequant_offset_buffer, 0, + dequant_offset_buffer_cpu.size() * sizeof(dequant_offset_buffer_cpu.front())), + dequant_offset_buffer_cpu.data(), dequant_offset_buffer_cpu.size() * sizeof(dequant_offset_buffer_cpu.front())); + + cmd.barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + use_readonly_texel_buffer ? VK_ACCESS_2_SHADER_SAMPLED_READ_BIT : VK_ACCESS_2_SHADER_STORAGE_READ_BIT); + } + cmd.end_region(); + + if (!dequant(cmd)) + return false; + + cmd.barrier(VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, 0, VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT); + + if (fragment_path) + { + if (!idwt_fragment(cmd, views)) + return false; + } + else + { + if (!idwt(cmd, views)) + return false; + } + + decoded_frame_for_current_sequence = true; + return true; +} + +void Decoder::Impl::clear() +{ + std::fill(dequant_offset_buffer_cpu.begin(), dequant_offset_buffer_cpu.end(), UINT32_MAX); + decoded_blocks = 0; + last_seq = UINT32_MAX; + decoded_frame_for_current_sequence = false; + total_blocks_in_sequence = block_count_32x32; + payload_data_cpu.clear(); +} + +bool Decoder::device_prefers_fragment_path(Vulkan::Device &device) +{ + switch (device.get_device_features().driver_id) + { + // QCOM hardware struggles with compute in general and prefers fragment. + // Turnip seems to like compute path just fine though ... + case VK_DRIVER_ID_QUALCOMM_PROPRIETARY: + return true; + + // Mali heavily favors texture sampling over LS heavy content. + case VK_DRIVER_ID_ARM_PROPRIETARY: + case VK_DRIVER_ID_MESA_PANVK: + return true; + + default: + return false; + } +} + +void Decoder::Impl::check_linear_texture_support() +{ + if (!use_readonly_texel_buffer) + return; + + // Texel buffers hit LS path on at least Mali, and most likely they hit slow paths on most mobile IHVs. + // Try to promote to linear 2D images instead if we can get away with it. + // Texture sampling performance is what mobile IHVs tend to optimize for. + const struct + { + VkFormat fmt; + uint32_t width; + ImageHandle *out_handle; + } reqs[] = { + { VK_FORMAT_R8_UINT, 4096, &payload_r8_image }, + { VK_FORMAT_R16_UINT, 2048, &payload_r16_image }, + { VK_FORMAT_R32_UINT, 1024, &payload_r32_image } + }; + + // Just assume this works. Can't imagine any GPU where this wouldn't work tightly packed. + + BufferCreateInfo bufinfo; + bufinfo.size = 4 * 1024 * 1024; + bufinfo.usage = + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + bufinfo.domain = BufferDomain::Device; + bufinfo.allocation_requirements.alignment = 64 * 1024; + bufinfo.allocation_requirements.size = 4 * 1024 * 1024; + bufinfo.allocation_requirements.memoryTypeBits = UINT32_MAX; + payload_data = device->create_buffer(bufinfo); + device->set_name(*payload_data, "payload-data"); + + const auto *alias = &payload_data->get_allocation(); + + // Try to force all linear images to alias each other. + for (auto &req : reqs) + { + VkImageFormatProperties2 props2 = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 }; + if (device->get_image_format_properties(req.fmt, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_LINEAR, + VK_IMAGE_USAGE_SAMPLED_BIT, 0, + nullptr, &props2)) + { + if (props2.imageFormatProperties.maxExtent.width >= req.width && + props2.imageFormatProperties.maxExtent.height >= 1024) + { + auto info = ImageCreateInfo::immutable_2d_image(req.width, 1024, req.fmt); + info.domain = ImageDomain::LinearHost; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + info.num_memory_aliases = 1; + info.layout = ImageLayout::General; + info.memory_aliases = &alias; + *req.out_handle = device->create_image(info); + } + } + } + + if (payload_r8_image && payload_r16_image && payload_r32_image) + LOGI("Using linear textures instead of texel buffers.\n"); +} + +bool Decoder::init(Vulkan::Device *device, int width, int height, ChromaSubsampling chroma_, bool fragment_path_) +{ + auto ops = device->get_device_features().vk11_props.subgroupSupportedOperations; + constexpr VkSubgroupFeatureFlags required_features = + VK_SUBGROUP_FEATURE_VOTE_BIT | + VK_SUBGROUP_FEATURE_BALLOT_BIT | + VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | + VK_SUBGROUP_FEATURE_SHUFFLE_BIT | + VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT | + VK_SUBGROUP_FEATURE_BASIC_BIT; + + if ((ops & required_features) != required_features) + { + LOGE("There are missing subgroup features. Device supports #%x, but requires #%x.\n", + ops, required_features); + return false; + } + + // The decoder is more lenient. + if (!device->supports_subgroup_size_log2(true, 2, 7)) + { + LOGE("Device doesn't support basic subgroup size control.\n"); + return false; + } + + if (!impl->init(device, width, height, chroma_, fragment_path_)) + { + LOGE("Failed to initialize.\n"); + return false; + } + + if (!device->get_device_features().vk12_features.storageBuffer8BitAccess && + !impl->use_readonly_texel_buffer) + { + LOGE("Device doesn't support 8-bit storage or large texel buffers.\n"); + return false; + } + + impl->check_linear_texture_support(); + + clear(); + return true; +} + +void Decoder::clear() +{ + impl->clear(); +} + +bool Decoder::push_packet(const void *data, size_t size) +{ + return impl->push_packet(data, size); +} + +bool Decoder::decode(Vulkan::CommandBuffer &cmd, const ViewBuffers &views) +{ + return impl->decode(cmd, views); +} + +bool Decoder::decode_is_ready(bool allow_partial_frame) const +{ + return impl->decode_is_ready(allow_partial_frame); +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_decoder.hpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_decoder.hpp new file mode 100644 index 00000000..20e322c0 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_decoder.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#pragma once + +#include +#include +#include +#include "pyrowave_config.hpp" + +namespace Vulkan +{ +class Device; +class ImageView; +class CommandBuffer; +} + +namespace PyroWave +{ +class Decoder +{ +public: + Decoder(); + ~Decoder(); + + // Fragment path is optimized for typical mobile GPUs which have weak compute support. + // iDWT is instead computed entirely in traditional render passes and fragment shaders. + // This path is *not* recommended for desktop-class chips. + bool init(Vulkan::Device *device, int width, int height, + ChromaSubsampling chroma, bool fragment_path = false); + + static bool device_prefers_fragment_path(Vulkan::Device &device); + + void clear(); + bool push_packet(const void *data, size_t size); + + // If fragment path is enabled, the command buffer must support graphics operations. + // To synchronize, synchronize with COLOR_OUTPUT / COLOR_ATTACHMENT_WRITE / COLOR_ATTACHMENT_OPTIMAL. + // Views must be created with VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. + bool decode(Vulkan::CommandBuffer &cmd, const ViewBuffers &views); + + bool decode_is_ready(bool allow_partial_frame) const; + +private: + struct Impl; + std::unique_ptr impl; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_device_validation.cpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_device_validation.cpp new file mode 100644 index 00000000..3242ade3 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_device_validation.cpp @@ -0,0 +1,250 @@ +// Copyright (c) 2026 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#include "volk.h" +#include "pyrowave.h" +#include "cli_parser.hpp" +#include +#include +#include +#include +#include +#include +#include +#include "logging.hpp" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +using namespace Util; + +enum +{ + EXIT_CODE_BAD_CLI = 1, + EXIT_CODE_NO_VULKAN_DEVICE = 2, + EXIT_CODE_TIMEOUT = 3, + EXIT_CODE_MISSING_SUPPORT = 4, + EXIT_CODE_ROUNDTRIP_FAILURE = 5, +}; + +static void print_help() +{ + LOGI("Usage: pyrowave-device-validation\n" + "\t[--luid ] (Windows only)\n" + "\t[--vid ]\n" + "\t[--pid ]\n" + "\t[--external (verifies support for importing external handles)]\n" + "\t[--roundtrip (verifies that encoding and decoding produces sound output)]\n" + "\t[--timeout ]\n" + "\tIf no device compatibility information is provided, the first Vulkan device will be used.\n"); +} + +static bool verify_roundtrip(pyrowave_device device) +{ + constexpr int Width = 34; + constexpr int Height = 30; + + pyrowave_decoder_create_info decoder_info = {}; + decoder_info.device = device; + decoder_info.width = Width; // Test somewhat odd size. Quite relevant for fragment path as well. + decoder_info.height = Height; + decoder_info.fragment_path = pyrowave_decoder_device_prefers_fragment_path(device); + decoder_info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_420; + + pyrowave_encoder_create_info encoder_info = {}; + encoder_info.device = device; + encoder_info.width = Width; + encoder_info.height = Height; + encoder_info.chroma = PYROWAVE_CHROMA_SUBSAMPLING_420; + + struct EncoderDeleter { void operator()(pyrowave_encoder encoder) { if (encoder) pyrowave_encoder_destroy(encoder); }}; + struct DecoderDeleter { void operator()(pyrowave_decoder decoder) { if (decoder) pyrowave_decoder_destroy(decoder); }}; + std::unique_ptr encoder; + std::unique_ptr decoder; + + pyrowave_encoder encoder_tmp; + pyrowave_decoder decoder_tmp; + + if (pyrowave_decoder_create(&decoder_info, &decoder_tmp) != PYROWAVE_SUCCESS) + return false; + decoder.reset(decoder_tmp); + + if (pyrowave_encoder_create(&encoder_info, &encoder_tmp) != PYROWAVE_SUCCESS) + return false; + encoder.reset(encoder_tmp); + + uint8_t luma[Height][Width] = {}; + uint8_t cb[Height][Width] = {}; + uint8_t cr[Height][Width] = {}; + + uint8_t decode_luma[Height][Width] = {}; + uint8_t decode_cb[Height][Width] = {}; + uint8_t decode_cr[Height][Width] = {}; + + pyrowave_cpu_buffer cpu_buffer = {}; + + cpu_buffer.format = PYROWAVE_CPU_BUFFER_FORMAT_YUV420P; + + cpu_buffer.row_stride_in_bytes[0] = Width; + cpu_buffer.row_stride_in_bytes[1] = sizeof(cb[0]); + cpu_buffer.row_stride_in_bytes[2] = sizeof(cr[0]); + cpu_buffer.plane_size_in_bytes[0] = sizeof(luma); + cpu_buffer.plane_size_in_bytes[1] = sizeof(cb); + cpu_buffer.plane_size_in_bytes[2] = sizeof(cr); + cpu_buffer.data[0] = &luma[0][0]; + cpu_buffer.data[1] = &cb[0][0]; + cpu_buffer.data[2] = &cr[0][0]; + + for (int y = 0; y < Height; y++) + { + for (int x = 0; x < Width; x++) + { + luma[y][x] = uint8_t(3 * x + 5 * y); + uint8_t cb_signal = 7 * x + 3 * y; + uint8_t cr_signal = 3 * x + 5 * y; + cb[y][x] = cb_signal; + cr[y][x] = cr_signal; + } + } + + cpu_buffer.width = Width; + cpu_buffer.height = Height; + const pyrowave_rate_control rate_control = { 64 * 1024 }; // Just give it something massive. + if (pyrowave_encoder_encode_cpu_synchronous(encoder.get(), &cpu_buffer, &rate_control) != PYROWAVE_SUCCESS) + return false; + + size_t num_packets; + if (pyrowave_encoder_compute_num_packets(encoder.get(), 64 * 1024, &num_packets) != PYROWAVE_SUCCESS) + return false; + if (num_packets != 1) + return false; + + std::vector bitstream(64 * 1024); + pyrowave_packet packet = {}; + if (pyrowave_encoder_packetize(encoder.get(), &packet, 64 * 1024, &num_packets, bitstream.data(), bitstream.size()) != PYROWAVE_SUCCESS) + return false; + if (num_packets != 1 || packet.offset != 0 || packet.size == 0 || packet.size > bitstream.size()) + return false; + bitstream.resize(packet.size); + + if (pyrowave_decoder_push_packet(decoder.get(), bitstream.data() + packet.offset, packet.size) != PYROWAVE_SUCCESS) + return false; + if (!pyrowave_decoder_decode_is_ready(decoder.get(), false)) + return false; + + cpu_buffer.data[0] = &decode_luma[0][0]; + cpu_buffer.data[1] = &decode_cb[0][0]; + cpu_buffer.data[2] = &decode_cr[0][0]; + cpu_buffer.row_stride_in_bytes[1] = sizeof(decode_cb[0]); + cpu_buffer.row_stride_in_bytes[2] = sizeof(decode_cr[0]); + cpu_buffer.plane_size_in_bytes[1] = sizeof(decode_cb); + cpu_buffer.plane_size_in_bytes[2] = sizeof(decode_cr); + cpu_buffer.format = PYROWAVE_CPU_BUFFER_FORMAT_YUV420P; + + if (pyrowave_decoder_decode_cpu_buffer_synchronous(decoder.get(), &cpu_buffer) != PYROWAVE_SUCCESS) + return false; + + for (int y = 0; y < Height; y++) + { + for (int x = 0; x < Width; x++) + { + int d = std::abs(int(decode_luma[y][x]) - int(luma[y][x])); + + // With the "infinite" bitrate we get here, + // accept a maximum 1 ULP error. + if (d > 1) + return false; + + if (y < Height / 2 && x < Width / 2) + { + // Allow more error for chroma. + d = std::abs(int(decode_cb[y][x]) - int(cb[y][x])); + if (d > 2) + return false; + d = std::abs(int(decode_cr[y][x]) - int(cr[y][x])); + if (d > 2) + return false; + } + } + } + + return true; +} + +int main(int argc, char **argv) +{ + CLICallbacks cbs; + uint32_t vid = 0; + uint32_t pid = 0; + pyrowave_luid luid = {}; + bool use_luid = false; + bool external = false; + bool roundtrip = false; + int timeout = 0; + static_assert(sizeof(luid) == sizeof(uint64_t), "Unexpected LUID size.\n"); + + cbs.add("--luid", [&](CLIParser &parser) + { + uint64_t luid_value = strtoull(parser.next_string(), nullptr, 16); + memcpy(&luid, &luid_value, sizeof(luid)); + use_luid = true; + }); + + cbs.add("--vid", [&](CLIParser &parser) { vid = strtoul(parser.next_string(), nullptr, 16); }); + cbs.add("--pid", [&](CLIParser &parser) { pid = strtoul(parser.next_string(), nullptr, 16); }); + cbs.add("--external", [&](CLIParser &) { external = true; }); + cbs.add("--roundtrip", [&](CLIParser &) { roundtrip = true; }); + cbs.add("--timeout", [&](CLIParser &parser) { timeout = int(parser.next_uint()); }); + cbs.add("--help", [](CLIParser &parser) { parser.end(); }); + + CLIParser parser(std::move(cbs), argc - 1, argv + 1); + if (!parser.parse()) + { + print_help(); + return EXIT_CODE_BAD_CLI; + } + else if (parser.is_ended_state()) + { + print_help(); + return EXIT_SUCCESS; + } + + // Run this in a thread since the test could just timeout due to hangs/stalls, and we'd have to force-kill the process. + std::future async_task = std::async(std::launch::async, [=]() -> int + { + pyrowave_device device; + auto ret = pyrowave_create_device_by_compat( + vid, pid, nullptr, nullptr, use_luid ? &luid : nullptr, &device); + + if (ret != PYROWAVE_SUCCESS) + return EXIT_CODE_NO_VULKAN_DEVICE; + + if (external && !pyrowave_device_confirm_interop_support(device)) + { + pyrowave_device_destroy(device); + return EXIT_CODE_MISSING_SUPPORT; + } + + if (roundtrip && !verify_roundtrip(device)) + { + pyrowave_device_destroy(device); + return EXIT_CODE_ROUNDTRIP_FAILURE; + } + + pyrowave_device_destroy(device); + return EXIT_SUCCESS; + }); + + if (timeout > 0 && async_task.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) + { +#ifdef _WIN32 + TerminateProcess(GetCurrentProcess(), EXIT_CODE_TIMEOUT); +#else + std::quick_exit(EXIT_CODE_TIMEOUT); +#endif + } + + return async_task.get(); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_encoder.cpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_encoder.cpp new file mode 100644 index 00000000..f5ac6dcc --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_encoder.cpp @@ -0,0 +1,1263 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#include "pyrowave_encoder.hpp" +#include "device.hpp" +#include "buffer.hpp" +#include "image.hpp" +#include "math.hpp" +#include "pyrowave_common.hpp" +#include +#include + +namespace PyroWave +{ +using namespace Granite; +using namespace Vulkan; + +static constexpr int BlockSpaceSubdivision = 16; +static constexpr int NumRDOBuckets = 128; +static constexpr int RDOBucketOffset = 64; + +static int compute_block_count_per_subdivision(int num_blocks) +{ + int per_subdivision = align(num_blocks, BlockSpaceSubdivision) / BlockSpaceSubdivision; + per_subdivision = int(Util::next_pow2(per_subdivision)); + return per_subdivision; +} + +struct QuantizerPushData +{ + ivec2 resolution; + ivec2 resolution_8x8_blocks; + vec2 inv_resolution; + float input_layer; + float quant_resolution; + int32_t block_offset; + int32_t block_stride; + float rdo_distortion_scale; +}; + +struct BlockPackingPushData +{ + ivec2 resolution; + ivec2 resolution_32x32_blocks; + ivec2 resolution_8x8_blocks; + uint32_t quant_resolution_code; + uint32_t sequence_count; + uint32_t block_offset_32x32; + uint32_t block_stride_32x32; + uint32_t block_offset_8x8; + uint32_t block_stride_8x8; +}; + +struct AnalyzeRateControlPushData +{ + ivec2 resolution; + ivec2 resolution_8x8_blocks; + int32_t block_offset_8x8; + int32_t block_stride_8x8; + int32_t block_offset_32x32; + int32_t block_stride_32x32; + uint32_t total_wg_count; + uint32_t num_blocks_aligned; + uint32_t block_index_shamt; +}; + +struct RDOperation +{ + int32_t quant; + uint16_t block_offset; + uint16_t block_saving; +}; + +struct Encoder::Impl final : public WaveletBuffers +{ + BufferHandle bucket_buffer, meta_buffer, block_stat_buffer, payload_data, quant_buffer; + + bool encode(CommandBuffer &cmd, const ViewBuffers &views, const BitstreamBuffers &buffers); + bool encode_pre_transformed(CommandBuffer &cmd, const BitstreamBuffers &buffers, float quant_scale); + bool encode_quant_and_coding(CommandBuffer &cmd, const BitstreamBuffers &buffers, float quant_scale); + + bool dwt(CommandBuffer &cmd, const ViewBuffers &views); + bool quant(CommandBuffer &cmd, float quant_scale); + bool analyze_rdo(CommandBuffer &cmd); + bool resolve_rdo(CommandBuffer &cmd, size_t target_payload_size); + bool block_packing(CommandBuffer &cmd, const BitstreamBuffers &buffers, float quant_scale); + + float get_noise_power_normalized_quant_resolution(int level, int component, int band) const; + float get_quant_resolution(int level, int component, int band) const; + float get_quant_rdo_distortion_scale(int level, int component, int band) const; + + void init_block_meta() override; + + size_t compute_num_packets(const void *meta, size_t packet_boundary) const; + + size_t packetize(Packet *packets, size_t packet_boundary, + void *bitstream, size_t size, + const void *mapped_meta, const void *mapped_bitstream) const; + + void report_stats(const void *mapped_meta, const void *mapped_bitstream) const; + void analyze_alternative_packing(const void *mapped_meta, const void *mapped_bitstream) const; + + bool validate_bitstream(const uint32_t *bitstream_u32, const BitstreamPacket *meta, uint32_t block_index) const; + + uint32_t sequence_count = 0; +}; + +float Encoder::Impl::get_quant_rdo_distortion_scale(int level, int component, int band) const +{ + // From my Linelet master thesis. Copy paste 11 years later, ah yes :D + float horiz_midpoint = (band & 1) ? 0.75f : 0.25f; + float vert_midpoint = (band & 2) ? 0.75f : 0.25f; + + // Normal PC monitors. + constexpr float dpi = 96.0f; + // Compromise between couch gaming and desktop. + constexpr float viewing_distance = 1.0f; + constexpr float cpd_nyquist = 0.34f * viewing_distance * dpi; + + float cpd = std::sqrt(horiz_midpoint * horiz_midpoint + vert_midpoint * vert_midpoint) * + cpd_nyquist * std::exp2(-float(level)); + + // Don't allow a situation where we're quantizing LL band hard. + cpd = std::max(cpd, 8.0f); + + float csf = 2.6f * (0.0192f + 0.114f * cpd) * std::exp(-std::pow(0.114f * cpd, 1.1f)); + + // Heavily discount chroma quality. + if (component != 0 && level != DecompositionLevels - 1) + { + // Consider chroma a little more important if we're not subsampling. + if (chroma == ChromaSubsampling::Chroma420) + csf *= 0.6f; + } + + // Due to filtering, distortion in lower bands will result in more noise power. + // By scaling the distortion by this factor, we ensure uniform results. + float resolution = get_noise_power_normalized_quant_resolution(level, component, band); + float weighted_resolution = csf * resolution; + + // The distortion is scaled in terms of power, not amplitude. + return weighted_resolution * weighted_resolution; +} + +float Encoder::Impl::get_quant_resolution(int level, int component, int band) const +{ + // FP16 range is limited, and this is more than a good enough initial estimate. + return std::min( + Configuration::get().get_precision() >= 1 ? 4096.0f : 512.0f, + get_noise_power_normalized_quant_resolution(level, component, band)); +} + +float Encoder::Impl::get_noise_power_normalized_quant_resolution(int level, int component, int band) const +{ + // The initial quantization resolution aims for a flat spectrum with noise power normalization. + // The low-pass gain for CDF 9/7 is 6 dB (1 bit). Every decomposition level subtracts 6 dB. + + // Maybe make this based on the max rate to have a decent initial estimate. + int bits = Configuration::get().get_precision() >= 1 ? 8 : 6; + + if (band == 0) + bits += 2; + else if (band < 3) + bits += 1; + + bits += level; + + // Chroma starts at level 1, subtract one bit. + if (component != 0) + bits--; + + return float(1 << bits); +} + +void Encoder::Impl::init_block_meta() +{ + WaveletBuffers::init_block_meta(); + + BufferCreateInfo info; + info.domain = BufferDomain::Device; + info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + + info.size = block_count_8x8 * sizeof(BlockStats); + block_stat_buffer = device->create_buffer(info); + device->set_name(*block_stat_buffer, "block-stat-buffer"); + + info.size = block_count_8x8 * sizeof(BlockMeta); + meta_buffer = device->create_buffer(info); + device->set_name(*meta_buffer, "meta-buffer"); + + // Worst case estimate. + info.size = aligned_width * aligned_height * 2; + payload_data = device->create_buffer(info); + device->set_name(*payload_data, "payload-data"); + + info.size = block_count_32x32 * sizeof(uint32_t); + quant_buffer = device->create_buffer(info); + device->set_name(*quant_buffer, "quant-buffer"); + + info.size = RDOBucketOffset; + info.size += NumRDOBuckets * BlockSpaceSubdivision * sizeof(uint32_t); + info.size += NumRDOBuckets * compute_block_count_per_subdivision(block_count_32x32) * + BlockSpaceSubdivision * sizeof(RDOperation); + bucket_buffer = device->create_buffer(info); + device->set_name(*bucket_buffer, "bucket-buffer"); +} + +bool Encoder::Impl::block_packing(CommandBuffer &cmd, const BitstreamBuffers &buffers, float quant_scale) +{ + cmd.begin_region("DWT block packing"); + auto start_packing = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + cmd.set_program(shaders.block_packing); + cmd.set_storage_buffer(0, 0, *buffers.bitstream.buffer, buffers.bitstream.offset, buffers.bitstream.size); + cmd.set_storage_buffer(0, 1, *buffers.meta.buffer, buffers.meta.offset, buffers.meta.size); + cmd.set_storage_buffer(0, 2, *meta_buffer); + cmd.set_storage_buffer(0, 3, *payload_data); + cmd.set_storage_buffer(0, 4, *block_stat_buffer); + cmd.set_storage_buffer(0, 5, *quant_buffer); + + if (device->supports_subgroup_size_log2(true, 4, 6)) + { + cmd.set_subgroup_size_log2(true, 4, 6); + } + else + { + LOGI("No compatible subgroup size config.\n"); + return false; + } + + for (int level = 0; level < DecompositionLevels; level++) + { + auto level_width = wavelet_img_high_res->get_width(level); + auto level_height = wavelet_img_high_res->get_height(level); + + for (int component = 0; component < NumComponents; component++) + { + // Ignore top-level CbCr when doing 420 subsampling. + if (level == 0 && component != 0 && chroma == ChromaSubsampling::Chroma420) + continue; + + char label[128]; + snprintf(label, sizeof(label), "level %d, component %d", level, component); + cmd.begin_region(label); + + for (int band = (level == DecompositionLevels - 1 ? 0 : 1); band < 4; band++) + { + BlockPackingPushData packing_push = {}; + packing_push.resolution = ivec2(level_width, level_height); + packing_push.resolution_32x32_blocks = ivec2((level_width + 31) / 32, (level_height + 31) / 32); + packing_push.resolution_8x8_blocks = ivec2((level_width + 7) / 8, (level_height + 7) / 8); + + auto quant_res = quant_scale < 0.0f ? get_quant_resolution(level, component, band) : quant_scale; + packing_push.quant_resolution_code = encode_quant(1.0f / quant_res); + packing_push.sequence_count = sequence_count; + + auto &meta = block_meta[component][level][band]; + + packing_push.block_offset_32x32 = meta.block_offset_32x32; + packing_push.block_stride_32x32 = meta.block_stride_32x32; + packing_push.block_offset_8x8 = meta.block_offset_8x8; + packing_push.block_stride_8x8 = meta.block_stride_8x8; + cmd.push_constants(&packing_push, 0, sizeof(packing_push)); + + cmd.dispatch((packing_push.resolution_32x32_blocks.x + 1) / 2, + (packing_push.resolution_32x32_blocks.y + 1) / 2, + 1); + } + + cmd.end_region(); + } + } + + auto end_packing = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + cmd.barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_2_CLEAR_BIT | VK_PIPELINE_STAGE_2_COPY_BIT, + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT | VK_ACCESS_2_TRANSFER_READ_BIT); + + device->register_time_interval("GPU", std::move(start_packing), std::move(end_packing), "Packing"); + cmd.end_region(); + + return true; +} + +bool Encoder::Impl::resolve_rdo(CommandBuffer &cmd, size_t target_payload_size) +{ + cmd.begin_region("DWT resolve"); + + auto start_resolve = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + + if (target_payload_size >= sizeof(BitstreamSequenceHeader)) + target_payload_size -= sizeof(BitstreamSequenceHeader); + + cmd.set_specialization_constant_mask(1); + + if (device->supports_subgroup_size_log2(true, 6, 6)) + { + cmd.set_specialization_constant(0, 64); + cmd.set_subgroup_size_log2(true, 6, 6); + } + else if (device->supports_subgroup_size_log2(true, 4, 4)) + { + cmd.set_specialization_constant(0, 16); + cmd.set_subgroup_size_log2(true, 4, 4); + } + else if (device->supports_subgroup_size_log2(true, 5, 5)) + { + cmd.set_specialization_constant(0, 32); + cmd.set_subgroup_size_log2(true, 5, 5); + } + else + { + LOGI("No compatible subgroup size config.\n"); + return false; + } + + cmd.set_program(shaders.resolve_rate_control); + + struct + { + uint32_t target_payload_size; + uint32_t num_blocks_per_subdivision; + } push = {}; + + push.target_payload_size = target_payload_size / sizeof(uint32_t); + push.num_blocks_per_subdivision = compute_block_count_per_subdivision(block_count_32x32); + cmd.push_constants(&push, 0, sizeof(push)); + cmd.set_storage_buffer(0, 0, *bucket_buffer); + cmd.set_storage_buffer(0, 1, *quant_buffer); + cmd.dispatch(NumRDOBuckets * BlockSpaceSubdivision, 1, 1); + + cmd.barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_READ_BIT); + cmd.end_region(); + + auto end_resolve = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + device->register_time_interval("GPU", std::move(start_resolve), std::move(end_resolve), "Resolve"); + cmd.set_specialization_constant_mask(0); + return true; +} + +bool Encoder::Impl::analyze_rdo(CommandBuffer &cmd) +{ + auto start_analyze = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + cmd.begin_region("DWT analyze"); + cmd.set_program(shaders.analyze_rate_control); + + if (device->supports_subgroup_size_log2(true, 4, 6)) + { + cmd.set_subgroup_size_log2(true, 4, 6); + } + else + { + LOGI("No compatible subgroup size config.\n"); + return false; + } + + // Quantize + for (int level = 0; level < DecompositionLevels; level++) + { + for (int component = 0; component < NumComponents; component++) + { + // Ignore top-level CbCr when doing 420 subsampling. + if (level == 0 && component != 0 && chroma == ChromaSubsampling::Chroma420) + continue; + + AnalyzeRateControlPushData push = {}; + + char label[128]; + snprintf(label, sizeof(label), "level %d, component %d", level, component); + cmd.begin_region(label); + + for (int band = (level == DecompositionLevels - 1 ? 0 : 1); band < 4; band++) + { + auto level_width = wavelet_img_high_res->get_width(level); + auto level_height = wavelet_img_high_res->get_height(level); + + push.resolution.x = level_width; + push.resolution.y = level_height; + push.resolution_8x8_blocks.x = (level_width + 7) / 8; + push.resolution_8x8_blocks.y = (level_height + 7) / 8; + push.block_offset_8x8 = block_meta[component][level][band].block_offset_8x8; + push.block_stride_8x8 = block_meta[component][level][band].block_stride_8x8; + push.block_offset_32x32 = block_meta[component][level][band].block_offset_32x32; + push.block_stride_32x32 = block_meta[component][level][band].block_stride_32x32; + push.total_wg_count = block_count_32x32; + push.num_blocks_aligned = compute_block_count_per_subdivision(block_count_32x32) * BlockSpaceSubdivision; + push.block_index_shamt = Util::floor_log2(compute_block_count_per_subdivision(block_count_32x32)); + + cmd.push_constants(&push, 0, sizeof(push)); + + cmd.set_storage_buffer(0, 0, *bucket_buffer); + cmd.set_storage_buffer(0, 1, *block_stat_buffer); + + cmd.dispatch((level_width + 31) / 32, (level_height + 31) / 32, 1); + } + + cmd.end_region(); + } + } + + cmd.barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_READ_BIT); + + cmd.set_program(shaders.analyze_rate_control_finalize); + cmd.dispatch(1, 1, 1); + + cmd.barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_READ_BIT); + + cmd.end_region(); + auto end_analyze = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + device->register_time_interval("GPU", std::move(start_analyze), std::move(end_analyze), "Analyze"); + return true; +} + +bool Encoder::Impl::quant(CommandBuffer &cmd, float quant_scale) +{ + auto start_quant = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + cmd.begin_region("DWT quantize"); + cmd.set_program(shaders.wavelet_quant); + + cmd.set_specialization_constant_mask(0); + if (device->supports_subgroup_size_log2(true, 3, 7)) + { + cmd.set_subgroup_size_log2(true, 3, 7); + } + else + { + LOGI("No compatible subgroup size config.\n"); + return false; + } + + // Quantize + for (int level = 0; level < DecompositionLevels; level++) + { + for (int component = 0; component < NumComponents; component++) + { + // Ignore top-level CbCr when doing 420 subsampling. + if (level == 0 && component != 0 && chroma == ChromaSubsampling::Chroma420) + continue; + + QuantizerPushData push = {}; + + char label[128]; + snprintf(label, sizeof(label), "DWT quant, level %d, component %d", level, component); + cmd.begin_region(label); + + for (int band = (level == DecompositionLevels - 1 ? 0 : 1); band < 4; band++) + { + float quant_res = quant_scale < 0.0f ? get_quant_resolution(level, component, band) : quant_scale; + + push.resolution.x = wavelet_img_high_res->get_width(level); + push.resolution.y = wavelet_img_high_res->get_height(level); + push.resolution_8x8_blocks.x = (push.resolution.x + 7) / 8; + push.resolution_8x8_blocks.y = (push.resolution.y + 7) / 8; + push.inv_resolution.x = 1.0f / float(push.resolution.x); + push.inv_resolution.y = 1.0f / float(push.resolution.y); + push.input_layer = float(band); + push.quant_resolution = 1.0f / decode_quant(encode_quant(1.0f / quant_res)); + push.rdo_distortion_scale = get_quant_rdo_distortion_scale(level, component, band) * (1.0f / 256.0f); + + int blocks_x = (push.resolution.x + 31) / 32; + int blocks_y = (push.resolution.y + 31) / 32; + + push.block_offset = block_meta[component][level][band].block_offset_8x8; + push.block_stride = block_meta[component][level][band].block_stride_8x8; + + cmd.push_constants(&push, 0, sizeof(push)); + + cmd.set_texture(0, 0, *component_layer_views[component][level], *border_sampler); + cmd.set_storage_buffer(0, 1, *meta_buffer); + cmd.set_storage_buffer(0, 2, *block_stat_buffer); + cmd.set_storage_buffer(0, 3, *payload_data); + + cmd.dispatch(blocks_x, blocks_y, 1); + } + + cmd.end_region(); + } + } + + cmd.end_region(); + cmd.barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_READ_BIT); + + auto end_quant = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + device->register_time_interval("GPU", std::move(start_quant), std::move(end_quant), "Quant"); + return true; +} + +bool Encoder::Impl::dwt(CommandBuffer &cmd, const ViewBuffers &views) +{ + struct Push + { + uvec2 resolution; + vec2 inv_resolution; + uvec2 aligned_resolution; + } push = {}; + + // Forward transforms. + cmd.set_program(shaders.dwt[PYROWAVE_PRECISION]); + + // Only need simple 2-lane swaps. + cmd.set_subgroup_size_log2(true, 2, 7); + cmd.set_specialization_constant_mask(1); + cmd.set_specialization_constant(0, false); + + auto start_dwt = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + + for (int output_level = 0; output_level < DecompositionLevels; output_level++) + { + if (output_level > 0) + { + push.resolution = uvec2(component_ll_views[0][output_level - 1]->get_view_width(), + component_ll_views[0][output_level - 1]->get_view_height()); + push.aligned_resolution = push.resolution; + } + else + { + push.resolution = uvec2(views.planes[0]->get_view_width(), views.planes[0]->get_view_height()); + push.aligned_resolution.x = aligned_width; + push.aligned_resolution.y = aligned_height; + } + + push.inv_resolution.x = 1.0f / float(push.resolution.x); + push.inv_resolution.y = 1.0f / float(push.resolution.y); + cmd.push_constants(&push, 0, sizeof(push)); + + if (output_level == 0) + { + cmd.set_specialization_constant(0, true); + + if (chroma == ChromaSubsampling::Chroma444) + { + for (int c = 0; c < NumComponents; c++) + { + char label[64]; + snprintf(label, sizeof(label), "DWT level 0, component %u", c); + cmd.begin_region(label); + cmd.set_texture(0, 0, *views.planes[c], *mirror_repeat_sampler); + cmd.set_storage_texture(0, 1, *component_layer_views[c][output_level]); + cmd.dispatch((push.aligned_resolution.x + 31) / 32, (push.aligned_resolution.y + 31) / 32, 1); + cmd.end_region(); + } + } + else + { + cmd.set_texture(0, 0, *views.planes[0], *mirror_repeat_sampler); + cmd.set_storage_texture(0, 1, *component_layer_views[0][output_level]); + cmd.begin_region("DWT level 0 Y"); + cmd.dispatch((push.aligned_resolution.x + 31) / 32, (push.aligned_resolution.y + 31) / 32, 1); + cmd.end_region(); + } + } + else + { + for (int c = 0; c < NumComponents; c++) + { + if (chroma == ChromaSubsampling::Chroma420 && c != 0 && output_level == 1) + { + push.resolution = uvec2(views.planes[c]->get_view_width(), views.planes[c]->get_view_height()); + push.aligned_resolution.x = aligned_width >> output_level; + push.aligned_resolution.y = aligned_height >> output_level; + push.inv_resolution.x = 1.0f / float(push.resolution.x); + push.inv_resolution.y = 1.0f / float(push.resolution.y); + cmd.push_constants(&push, 0, sizeof(push)); + cmd.set_texture(0, 0, *views.planes[c], *mirror_repeat_sampler); + cmd.set_specialization_constant(0, true); + } + else + { + cmd.set_texture(0, 0, *component_ll_views[c][output_level - 1], *mirror_repeat_sampler); + } + + cmd.set_storage_texture(0, 1, *component_layer_views[c][output_level]); + + char label[64]; + snprintf(label, sizeof(label), "DWT level %u, component %u", output_level, c); + cmd.begin_region(label); + cmd.dispatch((push.aligned_resolution.x + 31) / 32, (push.aligned_resolution.y + 31) / 32, 1); + cmd.end_region(); + } + } + + cmd.barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + + cmd.set_specialization_constant(0, false); + } + + auto end_dwt = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + device->register_time_interval("GPU", std::move(start_dwt), std::move(end_dwt), "DWT"); + cmd.set_specialization_constant_mask(0); + return true; +} + +size_t Encoder::Impl::compute_num_packets(const void *meta_, size_t packet_boundary) const +{ + auto *meta = static_cast(meta_); + size_t num_packets = 0; + size_t size_in_packet = 0; + + size_in_packet += sizeof(BitstreamSequenceHeader); + + for (int i = 0; i < block_count_32x32; i++) + { + size_t packet_size = meta[i].num_words * sizeof(uint32_t); + if (!packet_size) + continue; + + if (size_in_packet + packet_size > packet_boundary) + { + size_in_packet = 0; + num_packets++; + } + + size_in_packet += packet_size; + } + + if (size_in_packet) + num_packets++; + + return num_packets; +} + +#if 0 +static int max_magnitude(const int (&values)[64][64], int off_x, int off_y, int w, int h) +{ + int max_magnitude = 0; + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + max_magnitude = std::max(max_magnitude, std::abs(values[off_y + y][off_x + x])); + return max_magnitude; +} + +static int num_significant_values(const int (&values)[64][64], int off_x, int off_y, int w, int h) +{ + int num_significant = 0; + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + if (values[off_y + y][off_x + x] != 0) + num_significant++; + return num_significant; +} + +static bool has_significant_value(const int (&values)[64][64], int off_x, int off_y, int w, int h) +{ + return max_magnitude(values, off_x, off_y, w, h) != 0; +} + +template +static int analyze_cost(const int (&values)[64][64]) +{ + int cost = 0; + + for (int y = 0; y < 64; y += PacketBlockHeight) + for (int x = 0; x < 64; x += PacketBlockWidth) + if (has_significant_value(values, x, y, PacketBlockWidth, PacketBlockHeight)) + cost += 8; + + constexpr int BlockWidth = PacketBlockWidth / 4; + constexpr int BlockHeight = PacketBlockHeight / 4; + + for (int y = 0; y < 64; y += BlockHeight) + { + for (int x = 0; x < 64; x += BlockWidth) + { + int mag = max_magnitude(values, x, y, BlockWidth, BlockHeight); + + constexpr int NumSubBlocksX = BlockWidth / SubBlockWidth; + constexpr int NumSubBlocksY = BlockHeight / SubBlockHeight; + + if (mag != 0) + { + cost += 2 * NumSubBlocksX * NumSubBlocksY / 8; // 2 bits to encode planes. + cost += 1; // 4 bits to encode Q_bits, 4 bits to encode quant scale per block. + } + else + { + continue; + } + + constexpr int MaxDeltaQ = 3; + + uint32_t q_bits = 0; + { + uint32_t num_magnitude_bits = 32 - Util::leading_zeroes(mag); + if (num_magnitude_bits > MaxDeltaQ) + q_bits = num_magnitude_bits - MaxDeltaQ; + } + + int weight_bits = 0; + + for (int subblock_y = 0; subblock_y < NumSubBlocksY; subblock_y++) + { + for (int subblock_x = 0; subblock_x < NumSubBlocksX; subblock_x++) + { + int subblock_mag = max_magnitude(values, + x + subblock_x * SubBlockWidth, + y + subblock_y * SubBlockHeight, + SubBlockWidth, SubBlockHeight); + + uint32_t num_magnitude_bits = subblock_mag != 0 ? (32 - Util::leading_zeroes(subblock_mag)) : 0; + num_magnitude_bits = std::max(num_magnitude_bits, q_bits); + weight_bits += SubBlockWidth * SubBlockHeight * num_magnitude_bits; + } + } + + int num_sign_bits = num_significant_values(values, x, y, BlockWidth, BlockHeight); + //cost += 4 * ((weight_bits + num_sign_bits + 31) / 32); + cost += ((weight_bits + num_sign_bits + 7) / 8); + } + } + + return cost; +} + +void Encoder::Impl::analyze_alternative_packing(const void *mapped_meta, const void *mapped_bitstream) const +{ + auto *meta = static_cast(mapped_meta); + auto *bitstream = static_cast(mapped_bitstream); + + int cost_32x32_quad = 0; + int cost_32x32_horiz = 0; + int cost_32x32_vert = 0; + int cost_64x32 = 0; + int cost_64x64 = 0; + + for (int component = 0; component < NumComponents; component++) + { + for (int level = 0; level < DecompositionLevels; level++) + { + // Ignore top-level CbCr when doing 420 subsampling. + if (level == 0 && component != 0) + continue; + + auto band_width = wavelet_img->get_width(level); + auto band_height = wavelet_img->get_height(level); + int blocks_x_64x64 = (band_width + 63) / 64; + int blocks_y_64x64 = (band_height + 63) / 64; + + for (int band = 3; band >= (level == DecompositionLevels - 1 ? 0 : 1); band--) + { + auto &block_mapping = block_meta[component][level][band]; + + for (int block_y = 0; block_y < blocks_y_64x64; block_y++) + { + for (int block_x = 0; block_x < blocks_x_64x64; block_x++) + { + int block_index = block_mapping.block_offset_64x64 + block_y * block_mapping.block_stride_64x64 + block_x; + if (meta[block_index].num_words == 0) + continue; + + int dequant_values[64][64] = {}; + + const auto &mapping = block_64x64_to_16x16_mapping[block_index]; + + auto *header = reinterpret_cast(bitstream + meta[block_index].offset_u32); + int blocks_16x16 = int(Util::popcount32(header->ballot)); + + auto *control_words = bitstream + meta[block_index].offset_u32 + 2; + auto *payload_words = control_words + blocks_16x16; + + Util::for_each_bit(header->ballot, [&](unsigned bit) { + int block_16x16_x = int(bit & 3); + int block_16x16_y = int(bit >> 2); + int block_16x16 = mapping.block_offset_16x16 + mapping.block_stride_16x16 * block_16x16_y + block_16x16_x; + auto &mapping_16x16 = block_meta_16x16[block_16x16]; + auto q_bits = (*control_words >> 16) & 0xf; + + Util::for_each_bit(mapping_16x16.block_mask, [&](unsigned bit_offset) { + auto num_planes = q_bits + ((*control_words >> bit_offset) & 0x3); + if (num_planes == 0) + return; + num_planes++; + + int subblock_x = int(bit_offset >> 3u) & 1; + int subblock_y = int(bit_offset >> 1u) & 3; + + int base_x = block_16x16_x * 16 + subblock_x * 8; + int base_y = block_16x16_y * 16 + subblock_y * 4; + + for (int y = 0; y < 4; y++) + { + for (int x = 0; x < 8; x++) + { + int swizzled = 0; + swizzled |= ((x >> 0) & 1) << 0; + swizzled |= ((y >> 0) & 3) << 1; + swizzled |= ((x >> 1) & 3) << 3; + assert(swizzled < 32); + + for (uint32_t plane = 1; plane < num_planes; plane++) + { + dequant_values[base_y + y][base_x + x] <<= 1; + dequant_values[base_y + y][base_x + x] |= int(payload_words[plane] >> swizzled) & 1; + } + + if ((payload_words[0] & (1u << swizzled)) != 0) + dequant_values[base_y + y][base_x + x] *= -1; + } + } + + payload_words += num_planes; + }); + + control_words++; + }); + + cost_32x32_quad += analyze_cost<32, 32, 2, 2>(dequant_values); + cost_32x32_horiz += analyze_cost<32, 32, 4, 2>(dequant_values); + cost_32x32_vert += analyze_cost<32, 32, 2, 4>(dequant_values); + cost_64x32 += analyze_cost<64, 32, 4, 4>(dequant_values); + cost_64x64 += analyze_cost<64, 64, 8, 4>(dequant_values); + + auto payload_offset = payload_words - (bitstream + meta[block_index].offset_u32 + meta[block_index].num_words); + if (payload_offset != 0) + abort(); + } + } + } + } + } + + LOGI("32x32 (2x2) cost: %d bytes\n", cost_32x32_quad); + LOGI("32x32 (4x2) cost: %d bytes\n", cost_32x32_horiz); + LOGI("32x32 (2x4) cost: %d bytes\n", cost_32x32_vert); + LOGI("64x32 cost: %d bytes\n", cost_64x32); + LOGI("64x64 cost: %d bytes\n", cost_64x64); +} + +void Encoder::Impl::report_stats(const void *mapped_meta, const void *mapped_bitstream) const +{ + auto *meta = static_cast(mapped_meta); + auto *bitstream = static_cast(mapped_bitstream); + + int total_pixels = 0; + int total_words = 0; + + static const char *components[] = { "Y", "Cb", "Cr" }; + static const char *bands[] = { "LL", "HL", "LH", "HH" }; + + constexpr int MaxPlanes = 16; + int plane_histogram[MaxPlanes][256] = {}; + int total_planes[MaxPlanes] = {}; + + for (int component = 0; component < NumComponents; component++) + { + for (int level = 0; level < DecompositionLevels; level++) + { + int total_words_in_level = 0; + + // Ignore top-level CbCr when doing 420 subsampling. + if (level == 0 && component != 0) + continue; + + auto band_width = wavelet_img->get_width(level); + auto band_height = wavelet_img->get_height(level); + int blocks_x_64x64 = (band_width + 63) / 64; + int blocks_y_64x64 = (band_height + 63) / 64; + + for (int band = 3; band >= (level == DecompositionLevels - 1 ? 0 : 1); band--) + { + auto &block_mapping = block_meta[component][level][band]; + + int words = 0; + for (int block_y = 0; block_y < blocks_y_64x64; block_y++) + { + for (int block_x = 0; block_x < blocks_x_64x64; block_x++) + { + int block_index = block_mapping.block_offset_64x64 + block_y * block_mapping.block_stride_64x64 + block_x; + if (meta[block_index].num_words == 0) + continue; + + const auto &mapping = block_64x64_to_16x16_mapping[block_index]; + + words += meta[block_index].num_words; + + auto *header = reinterpret_cast(bitstream + meta[block_index].offset_u32); + int blocks_16x16 = int(Util::popcount32(header->ballot)); + + auto *control_words = bitstream + meta[block_index].offset_u32 + 2; + auto *payload_words = control_words + blocks_16x16; + + Util::for_each_bit(header->ballot, [&](unsigned bit) { + int x = int(bit & 3); + int y = int(bit >> 2); + int block_16x16 = mapping.block_offset_16x16 + mapping.block_stride_16x16 * y + x; + auto &mapping_16x16 = block_meta_16x16[block_16x16]; + auto q_bits = (*control_words >> 16) & 0xf; + + Util::for_each_bit(mapping_16x16.block_mask, [&](unsigned bit_offset) { + auto num_planes = q_bits + ((*control_words >> bit_offset) & 0x3); + if (num_planes != 0) + num_planes++; + + for (uint32_t j = 0; j < num_planes; j++) + { + plane_histogram[j][(payload_words[j] >> 0) & 0xff]++; + plane_histogram[j][(payload_words[j] >> 8) & 0xff]++; + plane_histogram[j][(payload_words[j] >> 16) & 0xff]++; + plane_histogram[j][(payload_words[j] >> 24) & 0xff]++; + total_planes[j] += 4; + } + payload_words += num_planes; + }); + + control_words++; + }); + + auto payload_offset = payload_words - (bitstream + meta[block_index].offset_u32 + meta[block_index].num_words); + if (payload_offset != 0) + abort(); + } + } + + int bytes = words * 4; + double bpp = (bytes * 8.0) / (band_width * band_height); + + LOGI("%s: decomposition level %d, band %s: %.3f bpp\n", + components[component], level, bands[band], bpp); + + total_words += words; + + if (component == 0) + total_pixels += band_width * band_height; + + total_words_in_level += words; + } + + LOGI("%s: decomposition level %d: %d bytes\n", components[component], level, total_words_in_level * 4); + } + } + + double plane_entropy[MaxPlanes] = {}; + + for (int i = 0; i < 256; i++) + { + for (int j = 0; j < MaxPlanes; j++) + { + if (total_planes[j] && plane_histogram[j][i]) + { + auto p = double(plane_histogram[j][i]) / double(total_planes[j]); + plane_entropy[j] -= p * log2(p); + } + } + } + + for (int i = 0; i < MaxPlanes; i++) + { + LOGI(" Plane %d entropy: %.3f %%\n", i, 100.0 * plane_entropy[i] / 8.0); + LOGI(" Plane %d bytes: %d\n", i, total_planes[i]); + } + + LOGI("Overall: %.3f bpp\n", (total_words * 32.0) / total_pixels); + + analyze_alternative_packing(mapped_meta, mapped_bitstream); +} +#endif + +bool Encoder::Impl::validate_bitstream( + const uint32_t *bitstream_u32, const BitstreamPacket *meta, uint32_t block_index) const +{ + if (meta[block_index].num_words == 0) + return true; + + bitstream_u32 += meta[block_index].offset_u32; + auto *header = reinterpret_cast(bitstream_u32); + if (header->block_index != block_index) + { + LOGI("Mismatch in block index. header: %u, meta: %u\n", header->block_index, block_index); + return false; + } + + if (header->payload_words != meta[block_index].num_words) + { + LOGI("Mismatch in payload words, header: %u, meta: %u\n", header->payload_words, meta[block_index].num_words); + return false; + } + + // 32x32 block layout: + // N = popcount(ballot) + // N * u16 control words. 2 bits per active 4x2 block. + // N * u8 control words. 4 bits Q, 4 bits quant scale. + // Plane data: M * u8. + // Tightly packed sign data follows. Depends on number of significant values while decoding plane data. + + int blocks_8x8 = int(Util::popcount32(header->ballot)); + auto *bitstream_u8 = reinterpret_cast(bitstream_u32); + auto *block_control_words = reinterpret_cast(bitstream_u32 + 2); + auto *q_control_words = reinterpret_cast(block_control_words + blocks_8x8); + uint32_t offset = sizeof(BitstreamHeader) + 3 * blocks_8x8; + + if (offset > header->payload_words * 4) + { + LOGE("payload_words is not large enough.\n"); + return false; + } + + const auto &mapping = block_32x32_to_8x8_mapping[header->block_index]; + bool invalid_packet = false; + int num_significant_values = 0; + + Util::for_each_bit(header->ballot, [&](unsigned bit) { + int x = int(bit & 3); + int y = int(bit >> 2); + + if (x < mapping.block_width_8x8 && y < mapping.block_height_8x8) + { + auto q_bits = *q_control_words & 0xf; + + for (int subblock_offset = 0; subblock_offset < 16; subblock_offset += 2) + { + int num_planes = q_bits + ((*block_control_words >> subblock_offset) & 3); + int plane_significance = 0; + for (int plane = 0; plane < num_planes; plane++) + plane_significance |= bitstream_u8[offset++]; + num_significant_values += int(Util::popcount32(plane_significance)); + } + + block_control_words++; + q_control_words++; + } + else + { + LOGE("block_index %u: 8x8 block is out of bounds. (%d, %d) >= (%d, %d)\n", + block_index, x, y, mapping.block_width_8x8, mapping.block_height_8x8); + invalid_packet = true; + } + }); + + if (invalid_packet) + return false; + + // We expect this many sign bits to have come through. + offset += (num_significant_values + 7) / 8; + + auto offset_words = (offset + 3) / 4; + + if (offset_words != header->payload_words) + { + LOGE("Block index %u, offset %u != %u\n", block_index, offset_words, header->payload_words); + return false; + } + + return true; +} + +size_t Encoder::Impl::packetize(Packet *packets, size_t packet_boundary, + void *output_bitstream_, size_t size, + const void *mapped_meta, + const void *mapped_bitstream) const +{ + size_t num_packets = 0; + size_t size_in_packet = 0; + size_t packet_offset = 0; + size_t output_offset = 0; + auto *meta = static_cast(mapped_meta); + auto *input_bitstream = static_cast(mapped_bitstream); + auto *output_bitstream = static_cast(output_bitstream_); + (void)size; + + size_t num_non_zero_blocks = 0; + for (int i = 0; i < block_count_32x32; i++) + if (meta[i].num_words != 0) + num_non_zero_blocks++; + + BitstreamSequenceHeader header = {}; + header.width_minus_1 = width - 1; + header.height_minus_1 = height - 1; + header.sequence = reinterpret_cast(input_bitstream + meta[0].offset_u32)->sequence; + header.extended = 1; + header.code = BITSTREAM_EXTENDED_CODE_START_OF_FRAME; + header.total_blocks = num_non_zero_blocks; + header.chroma_resolution = chroma == ChromaSubsampling::Chroma444 ? CHROMA_RESOLUTION_444 : CHROMA_RESOLUTION_420; + + assert(sizeof(header) <= size); + memcpy(output_bitstream, &header, sizeof(header)); + output_offset += sizeof(header); + size_in_packet += sizeof(header); + + //for (int i = 0; i < block_count_32x32; i++) + // if (!validate_bitstream(input_bitstream, meta, i)) + // return false; + + for (int i = 0; i < block_count_32x32; i++) + { + size_t packet_size = meta[i].num_words * sizeof(uint32_t); + if (!packet_size) + continue; + + if (size_in_packet + packet_size > packet_boundary) + { + packets[num_packets++] = { packet_offset, size_in_packet }; + size_in_packet = 0; + packet_offset = output_offset; + } + + assert(output_offset + packet_size <= size); + assert(packet_size >= sizeof(BitstreamHeader) / sizeof(uint32_t)); + + uint16_t block = reinterpret_cast(input_bitstream + meta[i].offset_u32)->block_index; + (void)block; + assert(block == i); + + memcpy(output_bitstream + output_offset, input_bitstream + meta[i].offset_u32, packet_size); + + output_offset += packet_size; + size_in_packet += packet_size; + } + + if (size_in_packet) + packets[num_packets++] = { packet_offset, size_in_packet }; + + return num_packets; +} + +bool Encoder::Impl::encode_quant_and_coding( + Vulkan::CommandBuffer &cmd, const BitstreamBuffers &buffers, float quant_scale) +{ + cmd.enable_subgroup_size_control(true); + + if (!quant(cmd, quant_scale)) + return false; + + if (!analyze_rdo(cmd)) + return false; + + if (!resolve_rdo(cmd, buffers.target_size)) + return false; + + if (!block_packing(cmd, buffers, quant_scale)) + return false; + + cmd.enable_subgroup_size_control(false); + return true; +} + +bool Encoder::Impl::encode_pre_transformed( + Vulkan::CommandBuffer &cmd, const BitstreamBuffers &buffers, float quant_scale) +{ + cmd.fill_buffer(*payload_data, 0, 0, 2 * sizeof(uint32_t)); + cmd.fill_buffer(*bucket_buffer, 0); + cmd.fill_buffer(*quant_buffer, 0); + + // Don't need to read the payload offset counter until quantizer. + cmd.barrier(VK_PIPELINE_STAGE_2_CLEAR_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_2_SHADER_STORAGE_READ_BIT | VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + + return encode_quant_and_coding(cmd, buffers, quant_scale); +} + +bool Encoder::Impl::encode(CommandBuffer &cmd, const ViewBuffers &views, const BitstreamBuffers &buffers) +{ + sequence_count = (sequence_count + 1) & SequenceCountMask; + + cmd.image_barrier(*wavelet_img_high_res, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + + if (wavelet_img_low_res) + { + cmd.image_barrier(*wavelet_img_low_res, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + } + + cmd.fill_buffer(*payload_data, 0, 0, 2 * sizeof(uint32_t)); + cmd.fill_buffer(*bucket_buffer, 0); + cmd.fill_buffer(*quant_buffer, 0); + + cmd.enable_subgroup_size_control(true); + if (!dwt(cmd, views)) + return false; + cmd.enable_subgroup_size_control(false); + + // Don't need to read the payload offset counter until quantizer. + cmd.barrier(VK_PIPELINE_STAGE_2_CLEAR_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_2_SHADER_STORAGE_READ_BIT | VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + + return encode_quant_and_coding(cmd, buffers, -1.0f); +} + +Encoder::Encoder() +{ + impl.reset(new Impl); +} + +bool Encoder::init(Device *device, int width_, int height_, ChromaSubsampling chroma_) +{ + auto ops = device->get_device_features().vk11_props.subgroupSupportedOperations; + constexpr VkSubgroupFeatureFlags required_features = + VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | + VK_SUBGROUP_FEATURE_SHUFFLE_BIT | + VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT | + VK_SUBGROUP_FEATURE_VOTE_BIT | + VK_SUBGROUP_FEATURE_BALLOT_BIT | + VK_SUBGROUP_FEATURE_CLUSTERED_BIT | + VK_SUBGROUP_FEATURE_BASIC_BIT; + + if ((ops & required_features) != required_features) + { + LOGE("There are missing subgroup features. Device supports #%x, but requires #%x.\n", + ops, required_features); + return false; + } + + if (!device->get_device_features().vk12_features.storageBuffer8BitAccess) + return false; + if (!device->get_device_features().enabled_features.shaderInt16) + return false; + + // This should cover any HW I care about. + if (!device->supports_subgroup_size_log2(true, 4, 4) && + !device->supports_subgroup_size_log2(true, 5, 5) && + !device->supports_subgroup_size_log2(true, 6, 6)) + return false; + + return impl->init(device, width_, height_, chroma_, false); +} + +bool Encoder::encode(CommandBuffer &cmd, const ViewBuffers &views, const BitstreamBuffers &buffers) +{ + return impl->encode(cmd, views, buffers); +} + +const Vulkan::ImageView &Encoder::get_wavelet_band(int component, int level) +{ + return *impl->component_layer_views[component][level]; +} + +bool Encoder::encode_pre_transformed(Vulkan::CommandBuffer &cmd, const BitstreamBuffers &buffers, float quant_scale) +{ + return impl->encode_pre_transformed(cmd, buffers, quant_scale); +} + +size_t Encoder::compute_num_packets(const void *meta, size_t packet_boundary) const +{ + return impl->compute_num_packets(meta, packet_boundary); +} + +size_t Encoder::packetize(Packet *packets, size_t packet_boundary, + void *bitstream, size_t size, + const void *mapped_meta, const void *mapped_bitstream) const +{ + return impl->packetize(packets, packet_boundary, bitstream, size, mapped_meta, mapped_bitstream); +} + +void Encoder::report_stats(const void *, const void *) const +{ + //impl->report_stats(mapped_meta, mapped_bitstream); +} + +uint64_t Encoder::get_meta_required_size() const +{ + return impl->block_count_32x32 * sizeof(BitstreamPacket); +} + +Encoder::~Encoder() +{ +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/pyrowave_encoder.hpp b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_encoder.hpp new file mode 100644 index 00000000..a65447d5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/pyrowave_encoder.hpp @@ -0,0 +1,64 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#pragma once + +#include +#include +#include +#include "pyrowave_config.hpp" + +namespace Vulkan +{ +class Device; +class Buffer; +class ImageView; +class CommandBuffer; +} + +namespace PyroWave +{ +class Encoder +{ +public: + Encoder(); + ~Encoder(); + + struct BitstreamBuffers + { + struct + { + const Vulkan::Buffer *buffer; + uint64_t offset; + uint64_t size; + } meta, bitstream; + size_t target_size; + }; + + bool init(Vulkan::Device *device, int width, int height, ChromaSubsampling chroma); + bool encode(Vulkan::CommandBuffer &cmd, const ViewBuffers &views, const BitstreamBuffers &buffers); + + // Debug hackery + const Vulkan::ImageView &get_wavelet_band(int component, int level); + bool encode_pre_transformed(Vulkan::CommandBuffer &cmd, const BitstreamBuffers &buffers, float quant_scale); + // + + uint64_t get_meta_required_size() const; + + struct Packet + { + size_t offset; + size_t size; + }; + + size_t compute_num_packets(const void *mapped_meta, size_t packet_boundary) const; + size_t packetize(Packet *packets, size_t packet_boundary, + void *bitstream, size_t size, + const void *mapped_meta, const void *mapped_bitstream) const; + + void report_stats(const void *mapped_meta, const void *mapped_bitstream) const; + +private: + struct Impl; + std::unique_ptr impl; +}; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/sandbox.cpp b/crates/pyrowave-sys/vendor/pyrowave/sandbox.cpp new file mode 100644 index 00000000..674bfc8d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/sandbox.cpp @@ -0,0 +1,368 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#include + +#include "global_managers_init.hpp" +#include "application.hpp" +#include "filesystem.hpp" +#include "device.hpp" +#include "context.hpp" +#include "thread_group.hpp" +#include "pyrowave_encoder.hpp" +#include "pyrowave_decoder.hpp" +#include "pyrowave_common.hpp" +#include +#include "fft.hpp" +#include "yuv4mpeg.hpp" +#include "shaders/slangmosh.hpp" +#include "math.hpp" +#include "muglm/muglm_impl.hpp" + +using namespace Granite; +using namespace Vulkan; + +static void run_encoder_test(Device &device, + PyroWave::Encoder &enc, + PyroWave::Decoder &dec, + const PyroWave::ViewBuffers &inputs, + const PyroWave::ViewBuffers &outputs, + size_t bitstream_size, YUV4MPEGFile &f) +{ + BufferCreateInfo buffer_info = {}; + buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + buffer_info.size = enc.get_meta_required_size(); + buffer_info.domain = BufferDomain::Device; + auto meta = device.create_buffer(buffer_info); + buffer_info.domain = BufferDomain::CachedHost; + auto meta_host = device.create_buffer(buffer_info); + + buffer_info.size = bitstream_size + 2 * enc.get_meta_required_size(); + buffer_info.domain = BufferDomain::Device; + auto bitstream = device.create_buffer(buffer_info); + buffer_info.domain = BufferDomain::CachedHost; + auto bitstream_host = device.create_buffer(buffer_info); + + PyroWave::Encoder::BitstreamBuffers buffers = {}; + buffers.meta.buffer = meta.get(); + buffers.meta.size = meta->get_create_info().size; + buffers.bitstream.buffer = bitstream.get(); + buffers.bitstream.size = bitstream->get_create_info().size; + buffers.target_size = bitstream_size; + + { + auto cmd = device.request_command_buffer(); +#if 1 + enc.encode(*cmd, inputs, buffers); +#else + cmd->image_barrier(enc.get_wavelet_band(0, 0).get_image(), + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + VK_PIPELINE_STAGE_2_CLEAR_BIT, VK_ACCESS_TRANSFER_WRITE_BIT); + + cmd->clear_image(enc.get_wavelet_band(0, 0).get_image(), {}); + + cmd->barrier(VK_PIPELINE_STAGE_2_CLEAR_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT); + + constexpr int w = 32; + constexpr int h = 32; + + auto *coeffs = static_cast( + cmd->update_image(enc.get_wavelet_band(0, 0).get_image(), + {}, { w, h, 1 }, w, 256, { VK_IMAGE_ASPECT_COLOR_BIT, 3, 1, 1 })); + + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + coeffs[w * y + x] = floatToHalf((float(x) + (x ? 0.5f : 0.0f)) * (y & 1 ? -1.0f : 1.0f)); + + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + + enc.encode_pre_transformed(*cmd, buffers, 1.0f); +#endif + + cmd->copy_buffer(*bitstream_host, *bitstream); + cmd->copy_buffer(*meta_host, *meta); + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_HOST_BIT, VK_ACCESS_HOST_READ_BIT); + + Fence fence; + device.submit(cmd, &fence); + device.next_frame_context(); + fence->wait(); + } + + auto *mapped_meta = static_cast( + device.map_host_buffer(*meta_host, MEMORY_ACCESS_READ_BIT)); + auto *mapped_bits = static_cast( + device.map_host_buffer(*bitstream_host, MEMORY_ACCESS_READ_BIT)); + + std::vector reordered_packet_buffer(8 * 1024 * 1024); + size_t num_packets = enc.compute_num_packets(mapped_meta, 8 * 1024); + std::vector packets(num_packets); + size_t out_packets = enc.packetize(packets.data(), 8 * 1024, + reordered_packet_buffer.data(), + reordered_packet_buffer.size(), + mapped_meta, mapped_bits); + enc.report_stats(mapped_meta, mapped_bits); + (void)out_packets; + + size_t encoded_size = 0; + for (auto &p : packets) + encoded_size += p.size; + + LOGI("Total encoded size: %zu\n", encoded_size); + + if (encoded_size > bitstream_size) + { + LOGE("Broken rate control\n"); + return; + } + + assert(out_packets == num_packets); + +#if 0 + struct DummyPacket + { + alignas(uint32_t) PyroWave::BitstreamHeader header; + uint16_t code[16]; + uint8_t q[16]; + uint8_t planes[16]; + uint8_t signs[16]; + }; + + DummyPacket packet = {}; + packet.header.payload_words = sizeof(DummyPacket) / sizeof(uint32_t); + packet.header.ballot = 0xffff; + packet.header.quant_code = PyroWave::encode_quant(1.0f); + for (auto &c : packet.code) + c = 0x1; + for (auto &q : packet.q) + q = 6 << 4; + for (auto &p : packet.planes) + p = 0x7; + packet.signs[0] = 0xff; + packet.signs[1] = 0xff; + packet.signs[2] = 0xff; + packet.signs[3] = 0xff; + packet.signs[4] = 0xff; + dec.push_packet(&packet, sizeof(packet)); +#endif + +#if 1 + for (auto &p : packets) + if (!dec.push_packet(reordered_packet_buffer.data() + p.offset, p.size)) + return; +#endif + + BufferHandle out_buffers[3]; + int bytes_per_pixel = YUV4MPEGFile::format_to_bytes_per_component(f.get_format()); + for (int i = 0; i < 3; i++) + { + BufferCreateInfo info = {}; + info.size = outputs.planes[i]->get_view_width() * outputs.planes[i]->get_view_height() * bytes_per_pixel; + info.domain = BufferDomain::CachedHost; + info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + out_buffers[i] = device.create_buffer(info); + } + + { + auto cmd = device.request_command_buffer(); + //if (!dec.decode_is_ready(false)) + // return; + if (!dec.decode(*cmd, outputs)) + return; + + for (int i = 0; i < 3; i++) + { + cmd->image_barrier(outputs.planes[i]->get_image(), + VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_READ_BIT); + } + + for (int i = 0; i < 3; i++) + { + cmd->copy_image_to_buffer(*out_buffers[i], outputs.planes[i]->get_image(), 0, {}, + { outputs.planes[i]->get_view_width(), outputs.planes[i]->get_view_height(), 1 }, + 0, 0, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }); + } + + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_HOST_BIT, VK_ACCESS_2_HOST_READ_BIT); + + Fence fence; + device.submit(cmd, &fence); + device.next_frame_context(); + fence->wait(); + + if (!f.begin_frame()) + return; + + for (auto &buf : out_buffers) + { + const void *mapped = device.map_host_buffer(*buf, MEMORY_ACCESS_READ_BIT); + if (!f.write(mapped, buf->get_create_info().size)) + { + LOGE("Failed to write plane.\n"); + return; + } + } + } +} + +struct YCbCrImages +{ + Vulkan::ImageHandle images[3]; + PyroWave::ViewBuffers views; +}; + +static YCbCrImages create_ycbcr_images(Device &device, int width, int height, VkFormat fmt, PyroWave::ChromaSubsampling chroma) +{ + YCbCrImages images; + auto info = ImageCreateInfo::immutable_2d_image(width, height, fmt); + info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + images.images[0] = device.create_image(info); + device.set_name(*images.images[0], "Y"); + + if (chroma == PyroWave::ChromaSubsampling::Chroma420) + { + info.width >>= 1; + info.height >>= 1; + } + + images.images[1] = device.create_image(info); + device.set_name(*images.images[1], "Cb"); + + images.images[2] = device.create_image(info); + device.set_name(*images.images[2], "Cr"); + + for (int i = 0; i < 3; i++) + images.views.planes[i] = &images.images[i]->get_view(); + + return images; +} + +struct BlockCounts +{ + int offset; + int count; +}; + +static void run_vulkan_test(Device &device, const char *in_path, const char *out_path, size_t bitstream_size) +{ + YUV4MPEGFile input, output; + + if (!input.open_read(in_path)) + return; + + if (!output.open_write(out_path, input.get_params())) + return; + + auto width = input.get_width(); + auto height = input.get_height(); + + auto fmt = YUV4MPEGFile::format_to_bytes_per_component(input.get_format()) == 2 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R8_UNORM; + auto chroma = YUV4MPEGFile::format_has_subsampling(input.get_format()) ? PyroWave::ChromaSubsampling::Chroma420 : PyroWave::ChromaSubsampling::Chroma444; + auto inputs = create_ycbcr_images(device, width, height, fmt, chroma); + auto outputs = create_ycbcr_images(device, width, height, fmt, chroma); + + PyroWave::Encoder enc; + if (!enc.init(&device, width, height, chroma)) + return; + + PyroWave::Decoder dec; + if (!dec.init(&device, width, height, chroma)) + return; + + bool has_rdoc = Device::init_renderdoc_capture(); + unsigned frames = 0; + + if (has_rdoc) + device.begin_renderdoc_capture(); + + for (;;) + { + if (!input.begin_frame()) + break; + + auto cmd = device.request_command_buffer(); + + for (int i = 0; i < 3; i++) + { + cmd->image_barrier(*inputs.images[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 0, 0, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT); + cmd->image_barrier(*outputs.images[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + 0, 0, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + } + + for (int i = 0; i < 3; i++) + { + auto *y = cmd->update_image(*inputs.images[i]); + if (!input.read(y, inputs.images[i]->get_width() * inputs.images[i]->get_height() * YUV4MPEGFile::format_to_bytes_per_component(input.get_format()))) + { + LOGE("Failed to read plane.\n"); + device.submit_discard(cmd); + return; + } + } + + for (int i = 0; i < 3; i++) + { + cmd->image_barrier(*inputs.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + + device.submit(cmd); + run_encoder_test(device, enc, dec, inputs.views, outputs.views, bitstream_size, output); + frames++; + if (has_rdoc && frames >= 10) + break; + } + + if (has_rdoc) + device.end_renderdoc_capture(); +} + +static void run_vulkan_test(const char *in_path, const char *out_path, size_t bitstream_size) +{ + Global::init(Global::MANAGER_FEATURE_EVENT_BIT | Global::MANAGER_FEATURE_FILESYSTEM_BIT | + Global::MANAGER_FEATURE_THREAD_GROUP_BIT, 1); + + Filesystem::setup_default_filesystem(GRANITE_FILESYSTEM(), ASSET_DIRECTORY); + + if (!Context::init_loader(nullptr)) + return; + + Context::SystemHandles handles = {}; + handles.thread_group = GRANITE_THREAD_GROUP(); + handles.filesystem = GRANITE_FILESYSTEM(); + + Context ctx; + ctx.set_system_handles(handles); + + if (!ctx.init_instance_and_device(nullptr, 0, nullptr, 0, CONTEXT_CREATION_ENABLE_PUSH_DESCRIPTOR_BIT)) + return; + + Device dev; + dev.set_context(ctx); + + //run_noise_power_test(dev); + run_vulkan_test(dev, in_path, out_path, bitstream_size); +} + +int main(int argc, char **argv) +{ + if (argc != 4) + return EXIT_FAILURE; + + run_vulkan_test(argv[1], argv[2], strtoul(argv[3], nullptr, 0)); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/setup_android_build.sh b/crates/pyrowave-sys/vendor/pyrowave/setup_android_build.sh new file mode 100755 index 00000000..5f21c317 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/setup_android_build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +./Granite/tools/create_android_build.py \ + --output-gradle android \ + --application-id net.themaister.pyrowave_viewer \ + --granite-dir Granite \ + --native-target pyrowave-viewer \ + --app-name "PyroWave Viewer" \ + --abis arm64-v8a \ + --cmake-lists-toplevel CMakeLists.txt \ + --assets shaders \ + --builtin Granite/assets +echo org.gradle.jvmargs=-Xmx4096M >> gradle.properties diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/analyze_rate_control.comp b/crates/pyrowave-sys/vendor/pyrowave/shaders/analyze_rate_control.comp new file mode 100644 index 00000000..365d2999 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/analyze_rate_control.comp @@ -0,0 +1,221 @@ +#version 450 +#extension GL_KHR_shader_subgroup_basic : require +#extension GL_KHR_shader_subgroup_ballot : require +#extension GL_KHR_shader_subgroup_arithmetic : require +#extension GL_KHR_shader_subgroup_vote : require +#extension GL_KHR_shader_subgroup_shuffle_relative : require +#extension GL_KHR_shader_subgroup_shuffle : require +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require + +#include "dwt_quant_scale.h" +#include "constants.h" + +layout(local_size_x = 64) in; + +struct BlockMeta +{ + uint code_word; + uint offset; +}; + +struct RDOperation +{ + int quant; + uint block_offset_saving; +}; + +const int BLOCK_SPACE_SUBDIVISION = 16; + +layout(set = 0, binding = 0) buffer Buckets +{ + uint count; + uint consumed_payload; + layout(offset = 64) uint total_savings_per_bucket[128 * BLOCK_SPACE_SUBDIVISION]; + RDOperation rdo_operations[]; +} buckets; + +struct QuantStats +{ + float16_t square_error; + uint16_t payload_cost; +}; + +struct BlockStats +{ + uint num_planes; + QuantStats errors[15]; +}; + +layout(set = 0, binding = 1) readonly buffer SSBOBlockStats +{ + BlockStats stats[]; +} block_stats; + +layout(push_constant) uniform Registers +{ + ivec2 resolution; + ivec2 resolution_8x8_blocks; + int block_offset_8x8; + int block_stride_8x8; + int block_offset_32x32; + int block_stride_32x32; + uint total_wg_count; + uint num_blocks_aligned; + uint block_index_shamt; +} registers; + +shared uint shared_rate_cost[16]; +shared float shared_distortion[16]; +shared uint shared_tmp[4]; + +// Perform operations that cause lower distortion first. +uint distortion_to_bucket_index(float d, float cost, float d_base, float cost_base) +{ + if (cost == cost_base) + return 0; + + // Compress a large range into 64 possible buckets. + // Every band is ~1.5 dB. + // Greedily chase least added (weighted) distortion per byte removed from code stream. + float index = 60.0 + 2.0 * log2(max(d - d_base, 0.0) / (cost_base - cost)); + return uint(max(index + 0.5, 0.0)); +} + +uint inclusive_max_clustered16(uint v) +{ + // Ensures that we never end up with a value > 127. + v = min(v, 128 - 16 + gl_SubgroupInvocationID); + + for (uint i = 1; i < 16; i *= 2) + { + // Ensure monotonic progression for buckets. + // Separate every quant level out by at least one bucket. + uint up = subgroupShuffleUp(v, i) + i; + v = max(v, gl_SubgroupInvocationID >= i ? up : 0); + } + + return v; +} + +void emit_rdo_operations() +{ + float distortion; + float cost; + + if (gl_SubgroupInvocationID < 16) + { + cost = float(shared_rate_cost[gl_SubgroupInvocationID]); + distortion = shared_distortion[gl_SubgroupInvocationID]; + } + else + { + // Dummy values. + cost = float(shared_rate_cost[gl_SubgroupInvocationID]); + distortion = 1e30; + } + + uint bucket_index = distortion_to_bucket_index(distortion, cost, shared_distortion[0], float(shared_rate_cost[0])); + if (gl_SubgroupInvocationID == 0) + bucket_index = 0; + + // Constraints: + // bucket_index for Q1 must be less than bucket_index for Q2 if Q1 < Q2. + // If a high quant target sees very favorable RD, lower bucket indices for lower Q values. + uint inclusive_bucket_index = inclusive_max_clustered16(bucket_index); + + if (gl_SubgroupInvocationID == 0) + { + uint unquantized_cost = shared_rate_cost[0]; + atomicAdd(buckets.consumed_payload, unquantized_cost); + } + else if (gl_SubgroupInvocationID < 16) + { + uint saving = shared_rate_cost[gl_SubgroupInvocationID - 1] - shared_rate_cost[gl_SubgroupInvocationID]; + + if (saving != 0) + { + ivec2 block32x32_index = ivec2(gl_WorkGroupID.xy); + int block_index = registers.block_offset_32x32 + + block32x32_index.y * registers.block_stride_32x32 + block32x32_index.x; + uint subdivision = block_index >> registers.block_index_shamt; + atomicAdd(buckets.total_savings_per_bucket[inclusive_bucket_index * BLOCK_SPACE_SUBDIVISION + subdivision], saving); + buckets.rdo_operations[block_index + inclusive_bucket_index * registers.num_blocks_aligned] = + RDOperation(int(gl_SubgroupInvocationID), block_index | (saving << 16)); + } + } +} + +void main() +{ + // Each workgroup processes a 64x64 block and computes all possible rate wins for every potential quant rate. + uint index = gl_SubgroupInvocationID + gl_SubgroupSize * gl_SubgroupID; + ivec2 block32x32_index = ivec2(gl_WorkGroupID.xy); + ivec2 local_block_index = ivec2(bitfieldExtract(index, 0, 2), bitfieldExtract(index, 2, 2)); + ivec2 block8x8_index = 4 * block32x32_index + local_block_index; + + uint num_active_planes; + + bool block8x8_in_range = all(lessThan(block8x8_index, registers.resolution_8x8_blocks)); + int block_index_8x8 = registers.block_offset_8x8 + + registers.block_stride_8x8 * block8x8_index.y + + block8x8_index.x; + + if (block8x8_in_range) + num_active_planes = block_stats.stats[block_index_8x8].num_planes; + + uint bit_index = index >> 4; + + for (uint i = bit_index; i < 16; i += 4) + { + float dist = 0.0; + uint cost = 0; + + if (block8x8_in_range) + { + QuantStats stats = block_stats.stats[block_index_8x8].errors[min(i, num_active_planes)]; + dist = float(stats.square_error); + cost = uint(stats.payload_cost); + } + + // 16 bits to encode the control codes, 8 bits to encode Q bits + quant scale. + // Cost is encoded in terms of bits. 8x8 blocks are decoded in isolation. + if (cost != 0) + cost += 24; + + if (gl_SubgroupSize == 16) + { + cost = subgroupAdd(cost); + dist = subgroupAdd(dist); + } + else + { + cost += subgroupShuffleXor(cost, 1); + cost += subgroupShuffleXor(cost, 2); + cost += subgroupShuffleXor(cost, 4); + cost += subgroupShuffleXor(cost, 8); + + dist += subgroupShuffleXor(dist, 1); + dist += subgroupShuffleXor(dist, 2); + dist += subgroupShuffleXor(dist, 4); + dist += subgroupShuffleXor(dist, 8); + } + + if ((index & 15u) == 0u) + { + // Need to encode a header. + // We can eliminate 32x32 blocks if everything decodes to 0. + if (cost != 0) + cost += 64; + + // Each packet is aligned to 4 bytes for practical reasons. + shared_rate_cost[i] = (cost + 31) >> 5; + shared_distortion[i] = dist; + } + } + + barrier(); + + if (gl_SubgroupID == 0) + emit_rdo_operations(); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/analyze_rate_control_finalize.comp b/crates/pyrowave-sys/vendor/pyrowave/shaders/analyze_rate_control_finalize.comp new file mode 100644 index 00000000..2defbfda --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/analyze_rate_control_finalize.comp @@ -0,0 +1,39 @@ +#version 450 + +layout(local_size_x = 512) in; + +const int BLOCK_SPACE_SUBDIVISION = 16; + +layout(set = 0, binding = 0) buffer Buckets +{ + layout(offset = 64) uvec4 total_savings_per_bucket[128 * BLOCK_SPACE_SUBDIVISION / 4]; +} buckets; + +shared uint shared_scan[512]; + +void main() +{ + uvec4 v = buckets.total_savings_per_bucket[gl_LocalInvocationIndex]; + v.y += v.x; + v.z += v.y; + v.w += v.z; + shared_scan[gl_LocalInvocationIndex] = v.w; + + barrier(); + + for (uint step = 1u; step < gl_WorkGroupSize.x / 2u; step *= 2u) + { + barrier(); + + uint shuffled_up = 0; + if (gl_LocalInvocationIndex >= step) + shuffled_up = shared_scan[gl_LocalInvocationIndex - step]; + + barrier(); + + v += shuffled_up; + shared_scan[gl_LocalInvocationIndex] = v.w; + } + + buckets.total_savings_per_bucket[gl_LocalInvocationIndex] = v; +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/block_packing.comp b/crates/pyrowave-sys/vendor/pyrowave/shaders/block_packing.comp new file mode 100644 index 00000000..28f52087 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/block_packing.comp @@ -0,0 +1,379 @@ +#version 450 +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#extension GL_KHR_shader_subgroup_basic : require +#extension GL_KHR_shader_subgroup_ballot : require +#extension GL_KHR_shader_subgroup_arithmetic : require +#extension GL_KHR_shader_subgroup_shuffle_relative : require +#extension GL_KHR_shader_subgroup_shuffle : require +#extension GL_KHR_shader_subgroup_clustered : require +#extension GL_KHR_shader_subgroup_vote : require +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require +#extension GL_EXT_shader_8bit_storage : require + +#include "constants.h" + +layout(local_size_x = 64) in; + +struct BlockMeta +{ + uint code_word; + uint offset; +}; + +struct BitstreamPacket +{ + uint offset; + uint num_words; +}; + +layout(set = 0, binding = 0) writeonly buffer BitstreamPayload +{ + uint data[]; +} bitstream_data; + +layout(set = 0, binding = 0) writeonly buffer BitstreamPayload16Bit +{ + uint16_t data[]; +} bitstream_data_16b; + +layout(set = 0, binding = 0) writeonly buffer BitstreamPayload8Bit +{ + uint8_t data[]; +} bitstream_data_8b; + +layout(set = 0, binding = 1) writeonly buffer BitstreamMeta +{ + BitstreamPacket packets[]; +} bitstream_meta; + +layout(set = 0, binding = 2) readonly buffer SSBOMeta +{ + BlockMeta meta[]; +} block_meta; + +layout(set = 0, binding = 3) buffer Payloads +{ + layout(offset = 4) uint bitstream_payload_counter; + layout(offset = 8) uint8_t data[]; +} payload_data; + +struct QuantStats +{ + float16_t square_error; + uint16_t payload_cost; +}; + +struct BlockStats +{ + uint num_planes; + QuantStats errors[15]; +}; + +layout(set = 0, binding = 4) readonly buffer SSBOBlockStats +{ + BlockStats stats[]; +} block_stats; + +layout(set = 0, binding = 5) readonly buffer RateControlQuant +{ + int data[]; +} quant_data; + +layout(push_constant) uniform Registers +{ + ivec2 resolution; + ivec2 resolution_32x32_blocks; + ivec2 resolution_8x8_blocks; + uint quant_resolution_code; + uint sequence_code; + int block_offset_32x32; + int block_stride_32x32; + int block_offset_8x8; + int block_stride_8x8; +} registers; + +uint compute_required_8x8_size(uint control_word) +{ + int q_bits = int(bitfieldExtract(control_word, Q_PLANES_OFFSET, Q_PLANES_BITS)); + uint lsbs = control_word & 0x5555u; + uint msbs = control_word & 0xaaaau; + uint msbs_shift = msbs >> 1; + msbs |= msbs_shift; + return bitCount(lsbs) + bitCount(msbs) + q_bits * 8; +} + +uint quantize_code_word(uint control_word, int quant) +{ + if (quant != 0 && control_word != 0) + { + int q_bits = int(bitfieldExtract(control_word, Q_PLANES_OFFSET, Q_PLANES_BITS)); + int sub_quant = min(q_bits, quant); + q_bits -= sub_quant; + quant -= sub_quant; + + if (quant != 0) + { + quant = min(quant, 3); + + uint plane0 = control_word & 0x5555u; + uint plane1 = (control_word & 0xaaaau) >> 1; + uint plane2 = plane0 & plane1; + + do + { + plane0 = plane1; + plane1 = plane2; + plane2 = 0; + quant--; + } while (quant != 0); + + plane0 &= ~plane1; + + uint new_control_word = plane0 | (plane1 << 1); + control_word = bitfieldInsert(control_word, new_control_word, 0, 16); + } + + control_word = bitfieldInsert(control_word, uint(q_bits), Q_PLANES_OFFSET, Q_PLANES_BITS); + } + + return control_word; +} + +uint copy_bytes(inout uint output_offset, uint input_offset, uint count) +{ + uint significant_mask = 0; + + do + { + uint in_data = uint(payload_data.data[input_offset]); + // If we observe any 1 in the non-sign planes, it's not deadzone quantized. + significant_mask |= in_data; + bitstream_data_8b.data[output_offset++] = uint8_t(in_data); + count--; + input_offset++; + } while (count > 0); + + return significant_mask; +} + +uint modify_quant_code(uint code, int quant) +{ + int e = int(bitfieldExtract(code, 3, 5)); + e = max(e - quant, 0); + code = bitfieldInsert(code, e, 3, 5); + return code; +} + +uint inclusive_add_clustered16(uint v) +{ + for (uint i = 1; i < 16; i *= 2) + { + uint up = subgroupShuffleUp(v, i); + v += (gl_SubgroupInvocationID & 15) >= i ? up : 0; + } + + return v; +} + +shared uint shared_sign_bank[4][1024 / 32]; +uint pending_sign_write = 0; +uint pending_sign_mask = 0; + +void append_sign_plane(uint bank, inout uint local_sign_offset, uint sign_mask, uint significant_mask) +{ + // Clock out one bit a time. This seems kinda slow. + while (significant_mask != 0) + { + int bit = findLSB(significant_mask); + significant_mask &= significant_mask - 1; + int out_bit = int(local_sign_offset & 31u); + pending_sign_write = bitfieldInsert(pending_sign_write, bitfieldExtract(sign_mask, bit, 1), out_bit, 1); + pending_sign_mask = bitfieldInsert(pending_sign_mask, 1, out_bit, 1); + + if (out_bit == 31) + { + if (pending_sign_mask == ~0u) + { + shared_sign_bank[bank][local_sign_offset / 32] = pending_sign_write; + } + else + { + atomicAnd(shared_sign_bank[bank][local_sign_offset / 32], ~pending_sign_mask); + atomicOr(shared_sign_bank[bank][local_sign_offset / 32], pending_sign_write & pending_sign_mask); + } + + pending_sign_mask = 0; + } + + local_sign_offset++; + } +} + +void flush_sign_plane(uint bank, uint local_sign_offset) +{ + if (pending_sign_mask != 0) + { + atomicAnd(shared_sign_bank[bank][local_sign_offset / 32], ~pending_sign_mask); + atomicOr(shared_sign_bank[bank][local_sign_offset / 32], pending_sign_write & pending_sign_mask); + pending_sign_mask = 0; + } +} + +void main() +{ + uint index = gl_SubgroupInvocationID + gl_SubgroupSize * gl_SubgroupID; + uint linear_block_32x32_index = index >> 4; + ivec2 block32x32_index = 2 * ivec2(gl_WorkGroupID.xy); + block32x32_index.x += int(bitfieldExtract(index, 4, 1)); + block32x32_index.y += int(bitfieldExtract(index, 5, 1)); + ivec2 local_block_index = ivec2(bitfieldExtract(index, 0, 2), bitfieldExtract(index, 2, 2)); + ivec2 block8x8_index = 4 * block32x32_index + local_block_index; + + BlockMeta meta; + int quant; + + bool in_range_8x8 = all(lessThan(block8x8_index, registers.resolution_8x8_blocks)); + bool in_range_32x32 = all(lessThan(block32x32_index, registers.resolution_32x32_blocks)); + uint num_bits_for_q = 0; + + if (in_range_32x32) + { + int block_index = registers.block_offset_32x32 + + registers.block_stride_32x32 * block32x32_index.y + + block32x32_index.x; + quant = quant_data.data[block_index]; + } + else + { + quant = 0; + } + + if (in_range_8x8) + { + int block_index = registers.block_offset_8x8 + + registers.block_stride_8x8 * block8x8_index.y + + block8x8_index.x; + meta = block_meta.meta[block_index]; + uint num_planes = block_stats.stats[block_index].num_planes; + num_bits_for_q = uint(block_stats.stats[block_index].errors[min(num_planes, quant)].payload_cost); + } + else + { + meta = BlockMeta(0, 0); + } + + uint code_word = quantize_code_word(meta.code_word, quant); + bool active_code_word = (code_word & 0xffffu) != 0; + + uvec4 code_word_ballot = subgroupBallot(active_code_word); + uint local_ballot = gl_SubgroupSize >= 64 && linear_block_32x32_index >= 2 ? code_word_ballot.y : code_word_ballot.x; + local_ballot = bitfieldExtract(local_ballot, int(16u * (linear_block_32x32_index & 1u)), 16); + + uint required_plane_bytes = compute_required_8x8_size(code_word); + uint required_sign_bits = num_bits_for_q - required_plane_bytes * 8; + + uint required_bits_with_meta = num_bits_for_q; + if (required_bits_with_meta != 0) + required_bits_with_meta += 24; + + const uint HeaderSize = 2; + bool writes_header = + all(lessThan(block32x32_index, registers.resolution_32x32_blocks)) && (index & 15u) == 15u; + + uint payload_total_bits = subgroupClusteredAdd(required_bits_with_meta, 16); + uint payload_total_words = (payload_total_bits + 31) / 32; + if (payload_total_words != 0) + payload_total_words += HeaderSize; + + uint global_payload_offset = 0; + if (writes_header && payload_total_words != 0) + global_payload_offset = atomicAdd(payload_data.bitstream_payload_counter, payload_total_words); + global_payload_offset = subgroupShuffle(global_payload_offset, gl_SubgroupInvocationID | 15u); + + if (writes_header) + { + uint block_index = registers.block_offset_32x32 + + block32x32_index.y * registers.block_stride_32x32 + block32x32_index.x; + + if (payload_total_words != 0) + { + bitstream_data.data[global_payload_offset + 0] = + local_ballot | (payload_total_words << 16) | (registers.sequence_code << 28); + bitstream_data.data[global_payload_offset + 1] = + modify_quant_code(registers.quant_resolution_code, quant) | (block_index << 8); + } + + bitstream_meta.packets[block_index] = BitstreamPacket(global_payload_offset, payload_total_words); + } + + uint total_subblocks = bitCount(local_ballot); + + uint total_sign_bits = inclusive_add_clustered16(required_sign_bits); + uint local_planes_offset = inclusive_add_clustered16(required_plane_bytes) - required_plane_bytes; + uint local_sign_offset = total_sign_bits - required_sign_bits; + uint global_planes_offset = 4 * global_payload_offset + 3 * total_subblocks + 4 * HeaderSize; + uint global_sign_offset = global_planes_offset + subgroupClusteredAdd(required_plane_bytes, 16); + global_planes_offset += local_planes_offset; + + uint total_sign_bytes = (subgroupShuffle(total_sign_bits, gl_SubgroupInvocationID | 15u) + 7) / 8; + + // Followed by N code words which map to the local ballot of active 16x16 regions. + if (active_code_word) + { + uint block_header_offset = bitCount(bitfieldExtract( + local_ballot, 0, local_block_index.y * 4 + local_block_index.x)); + + uint in_q_bits = bitfieldExtract(meta.code_word, Q_PLANES_OFFSET, Q_PLANES_BITS); + uint out_q_bits = bitfieldExtract(code_word, Q_PLANES_OFFSET, Q_PLANES_BITS); + uint input_offset = meta.offset; + uint output_offset = global_planes_offset; + + for (int bit_offset = 0; bit_offset < 16; bit_offset += 2) + { + uint out_planes = bitfieldExtract(code_word, bit_offset, 2) + out_q_bits; + uint in_planes = bitfieldExtract(meta.code_word, bit_offset, 2) + in_q_bits; + if (in_planes != 0) + in_planes++; + + uint sign_plane = uint(payload_data.data[input_offset]); + + if (out_planes != 0) + { + uint significant_mask = copy_bytes(output_offset, input_offset + 1, out_planes); + append_sign_plane(linear_block_32x32_index, local_sign_offset, sign_plane, significant_mask); + } + + input_offset += in_planes; + } + + flush_sign_plane(linear_block_32x32_index, local_sign_offset); + + bitstream_data_16b.data[2 * global_payload_offset + block_header_offset + 2 * HeaderSize] = + uint16_t(code_word); + bitstream_data_8b.data[4 * global_payload_offset + 2 * total_subblocks + block_header_offset + 4 * HeaderSize] = + uint8_t(code_word >> 16); + } + + subgroupBarrier(); + + // Copy out all sign planes for any given group. + for (uint i = index & 15u; i < total_sign_bytes / 4; i += 16) + { + uint sign_word = shared_sign_bank[linear_block_32x32_index][i]; + uint offset_8b = global_sign_offset + 4 * i; + bitstream_data_8b.data[offset_8b + 0] = uint8_t(sign_word >> 0); + bitstream_data_8b.data[offset_8b + 1] = uint8_t(sign_word >> 8); + bitstream_data_8b.data[offset_8b + 2] = uint8_t(sign_word >> 16); + bitstream_data_8b.data[offset_8b + 3] = uint8_t(sign_word >> 24); + } + + // Copy out any stragglers. + for (uint i = (total_sign_bytes & ~3u) + (index & 15u); i < total_sign_bytes; i += 16) + { + uint sign_word = shared_sign_bank[linear_block_32x32_index][i / 4]; + uint offset_8b = global_sign_offset + i; + bitstream_data_8b.data[offset_8b] = uint8_t(sign_word >> (8 * (i & 3u))); + } +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/constants.h b/crates/pyrowave-sys/vendor/pyrowave/shaders/constants.h new file mode 100644 index 00000000..8443949c --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/constants.h @@ -0,0 +1,10 @@ +#ifndef CONSTANTS_H_ +#define CONSTANTS_H_ + +const int Q_PLANES_OFFSET = 16; +const int Q_PLANES_BITS = 4; + +const int QUANT_SCALE_OFFSET = 20; +const int QUANT_SCALE_BITS = 4; + +#endif \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt.comp b/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt.comp new file mode 100644 index 00000000..3d03093d --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt.comp @@ -0,0 +1,234 @@ +#version 450 +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#extension GL_KHR_shader_subgroup_basic : require +#if FP16 +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#endif + +layout(local_size_x = 64) in; + +layout(set = 0, binding = 0) uniform mediump sampler2D uTexture; +layout(set = 0, binding = 1) writeonly uniform mediump image2DArray uOutput; + +layout(constant_id = 0) const bool DCShift = false; + +layout(push_constant) uniform Registers +{ + ivec2 resolution; + vec2 inv_resolution; + ivec2 aligned_resolution; +}; + +uint local_index; + +#include "dwt_common.h" + +vec2 generate_mirror_uv(ivec2 coord) +{ + coord -= ivec2(lessThan(coord, ivec2(0))); + coord += 1; + ivec2 end_mirrored_clamp = (2 * aligned_resolution) - resolution; + ivec2 past_wrapped_coord = coord + 2 * (resolution - aligned_resolution) + 1; + coord = mix(min(coord, resolution), past_wrapped_coord, greaterThanEqual(coord, end_mirrored_clamp)); + + return vec2(coord) * inv_resolution; +} + +void load_image_with_apron() +{ + ivec2 base_coord = ivec2(gl_WorkGroupID.xy) * ivec2(BLOCK_SIZE, BLOCK_SIZE) - APRON; + ivec2 local_coord0 = 2 * unswizzle8x8(local_index); + ivec2 coord0 = base_coord + local_coord0; + + VEC4 texels0 = VEC4(textureGather(uTexture, generate_mirror_uv(coord0))).wzxy; + VEC4 texels1 = VEC4(textureGather(uTexture, generate_mirror_uv(coord0 + ivec2(16, 0)))).wzxy; + VEC4 texels2 = VEC4(textureGather(uTexture, generate_mirror_uv(coord0 + ivec2(0, 16)))).wzxy; + VEC4 texels3 = VEC4(textureGather(uTexture, generate_mirror_uv(coord0 + ivec2(16, 16)))).wzxy; + if (DCShift) { texels0 -= FLOAT(0.5); texels1 -= FLOAT(0.5); texels2 -= FLOAT(0.5); texels3 -= FLOAT(0.5); } + + int local_coord0_y_half = local_coord0.y >> 1; + + // Pack two lines together in one vec2. This allows packed FP16 math easily by processing two lines in parallel. + store_shared(local_coord0_y_half + 0, local_coord0.x + 0, texels0.xz); + store_shared(local_coord0_y_half + 0, local_coord0.x + 1, texels0.yw); + store_shared(local_coord0_y_half + 0, local_coord0.x + 16, texels1.xz); + store_shared(local_coord0_y_half + 0, local_coord0.x + 17, texels1.yw); + store_shared(local_coord0_y_half + 8, local_coord0.x + 0, texels2.xz); + store_shared(local_coord0_y_half + 8, local_coord0.x + 1, texels2.yw); + store_shared(local_coord0_y_half + 8, local_coord0.x + 16, texels3.xz); + store_shared(local_coord0_y_half + 8, local_coord0.x + 17, texels3.yw); + + // Load the top-right apron + { + ivec2 local_coord = ivec2(BLOCK_SIZE + 2 * (local_index % 4u), 2 * (local_index / 4u)); + VEC4 texels = VEC4(textureGather(uTexture, generate_mirror_uv(base_coord + local_coord))).wzxy; + if (DCShift) { texels -= FLOAT(0.5); } + store_shared(local_coord.y >> 1, local_coord.x + 0, texels.xz); + store_shared(local_coord.y >> 1, local_coord.x + 1, texels.yw); + } + + // Load the bottom-left apron + { + ivec2 local_coord = ivec2(2 * (local_index % 16u), BLOCK_SIZE + 2 * (local_index / 16u)); + VEC4 texels = VEC4(textureGather(uTexture, generate_mirror_uv(base_coord + local_coord))).wzxy; + if (DCShift) { texels -= FLOAT(0.5); } + store_shared(local_coord.y >> 1, local_coord.x + 0, texels.xz); + store_shared(local_coord.y >> 1, local_coord.x + 1, texels.yw); + } + + if (local_index < 16) + { + // Load the bottom-right apron + ivec2 local_coord = ivec2(BLOCK_SIZE + 2 * (local_index % 4u), BLOCK_SIZE + 2 * (local_index / 4u)); + VEC4 texels = VEC4(textureGather(uTexture, generate_mirror_uv(base_coord + local_coord))).wzxy; + if (DCShift) { texels -= FLOAT(0.5); } + store_shared(local_coord.y >> 1, local_coord.x + 0, texels.xz); + store_shared(local_coord.y >> 1, local_coord.x + 1, texels.yw); + } +} + +void forward_transform8x2() +{ + const int SIZE = 8; + const int PADDED_SIZE = SIZE + 2 * APRON; + const int PADDED_SIZE_HALF = PADDED_SIZE / 2; + VEC2 values[PADDED_SIZE]; + + ivec2 local_coord = ivec2(8 * (local_index % 4u), local_index / 4u); + + for (int i = 0; i < PADDED_SIZE; i++) + { + VEC2 v = load_shared(local_coord.y, local_coord.x + i); + values[i] = v; + } + + // CDF 9/7 lifting steps. + // Arith go brrr. + for (int i = 1; i < PADDED_SIZE - 1; i += 2) + values[i] += ALPHA * (values[i - 1] + values[i + 1]); + for (int i = 2; i < PADDED_SIZE - 2; i += 2) + values[i] += BETA * (values[i - 1] + values[i + 1]); + for (int i = 3; i < PADDED_SIZE - 3; i += 2) + values[i] += GAMMA * (values[i - 1] + values[i + 1]); + for (int i = 4; i < PADDED_SIZE - 4; i += 2) + values[i] += DELTA * (values[i - 1] + values[i + 1]); + + // Avoid WAR hazard. + barrier(); + + for (int i = APRON_HALF; i < PADDED_SIZE_HALF - APRON_HALF; i++) + { + VEC2 a = values[2 * i + 0]; + VEC2 b = values[2 * i + 1]; + + // Filter kernel rescale. + a *= inv_K; + b *= K; + + // Transpose the 2x2 block. + VEC2 t0 = VEC2(a.x, b.x); + VEC2 t1 = VEC2(a.y, b.y); + + // Transpose write + int y_coord = (local_coord.x >> 1) + (i - APRON_HALF); + store_shared(y_coord, 2 * local_coord.y + 0, t0); + store_shared(y_coord, 2 * local_coord.y + 1, t1); + } +} + +void forward_transform4x2(bool active_lane, int y_offset) +{ + const int SIZE = 4; + const int PADDED_SIZE = SIZE + 2 * APRON; + const int PADDED_SIZE_HALF = PADDED_SIZE / 2; + VEC2 values[PADDED_SIZE]; + + ivec2 local_coord = ivec2(4 * (local_index % 8u), local_index / 8u + y_offset); + + if (active_lane) + { + for (int i = 0; i < PADDED_SIZE; i++) + { + VEC2 v = load_shared(local_coord.y, local_coord.x + i); + values[i] = v; + } + + // CDF 9/7 lifting steps. + // Arith go brrr. + for (int i = 1; i < PADDED_SIZE - 1; i += 2) + values[i] += ALPHA * (values[i - 1] + values[i + 1]); + for (int i = 2; i < PADDED_SIZE - 2; i += 2) + values[i] += BETA * (values[i - 1] + values[i + 1]); + for (int i = 3; i < PADDED_SIZE - 3; i += 2) + values[i] += GAMMA * (values[i - 1] + values[i + 1]); + for (int i = 4; i < PADDED_SIZE - 4; i += 2) + values[i] += DELTA * (values[i - 1] + values[i + 1]); + } + + // Avoid WAR hazard. + barrier(); + + if (active_lane) + { + for (int i = APRON_HALF; i < PADDED_SIZE_HALF - APRON_HALF; i++) + { + VEC2 a = values[2 * i + 0]; + VEC2 b = values[2 * i + 1]; + + // Filter kernel rescale. + a *= inv_K; + b *= K; + + // Transpose the 2x2 block. + VEC2 t0 = VEC2(a.x, b.x); + VEC2 t1 = VEC2(a.y, b.y); + + // Transpose write + int y_coord = (local_coord.x >> 1) + (i - APRON_HALF); + store_shared(y_coord, 2 * local_coord.y + 0, t0); + store_shared(y_coord, 2 * local_coord.y + 1, t1); + } + } +} + +void main() +{ + local_index = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID; + + load_image_with_apron(); + + barrier(); + + // Horizontal transform. + forward_transform8x2(); + + // Also need to transform the apron. + forward_transform4x2(local_index < 32, BLOCK_SIZE_HALF); + + barrier(); + + // Vertical transform. + forward_transform8x2(); + + barrier(); + + ivec2 local_coord = unswizzle8x8(local_index); + for (int y = local_coord.y; y < BLOCK_SIZE_HALF; y += 8) + { + for (int x = local_coord.x * 2; x < BLOCK_SIZE; x += 16) + { + VEC2 v0 = load_shared(y, x + 0); + VEC2 v1 = load_shared(y, x + 1); + + int img_x = x >> 1; + int img_y = y; + + ivec2 base_image_coord = ivec2(gl_WorkGroupID.xy) * (BLOCK_SIZE / 2) + ivec2(img_x, img_y); + imageStore(uOutput, ivec3(base_image_coord, 0), v0.xxxx); + imageStore(uOutput, ivec3(base_image_coord, 2), v0.yyyy); + imageStore(uOutput, ivec3(base_image_coord, 1), v1.xxxx); + imageStore(uOutput, ivec3(base_image_coord, 3), v1.yyyy); + } + } +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt_common.h b/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt_common.h new file mode 100644 index 00000000..06b773ee --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt_common.h @@ -0,0 +1,60 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#ifndef DWT_COMMON_H_ +#define DWT_COMMON_H_ + +const int APRON = 4; +const int APRON_HALF = APRON / 2; +const int BLOCK_SIZE = 32; +const int BLOCK_SIZE_HALF = BLOCK_SIZE >> 1; + +#if !FP16 && PRECISION == 0 +#undef PRECISION +#define PRECISION 1 +#endif + +#if PRECISION == 2 +#define FLOAT float +#define VEC2 vec2 +#define VEC4 vec4 +#define SHARED_VEC2 vec2 +#elif PRECISION == 1 +#define FLOAT float +#define VEC2 vec2 +#define VEC4 vec4 +#if FP16 +#define SHARED_VEC2 f16vec2 +#else +#define SHARED_VEC2 uint +#endif +#else +#define FLOAT float16_t +#define VEC2 f16vec2 +#define VEC4 f16vec4 +#define SHARED_VEC2 f16vec2 +#endif + +const FLOAT ALPHA = FLOAT(-1.586134342059924); +const FLOAT BETA = FLOAT(-0.052980118572961); +const FLOAT GAMMA = FLOAT(0.882911075530934); +const FLOAT DELTA = FLOAT(0.443506852043971); +const FLOAT K = FLOAT(1.230174104914001); +const FLOAT inv_K = FLOAT(1.0 / 1.230174104914001); + +shared SHARED_VEC2 shared_block[(BLOCK_SIZE + 2 * APRON) / 2][(BLOCK_SIZE + 2 * APRON) + 1]; +#if !FP16 && PRECISION == 1 +VEC2 load_shared(uint y, uint x) { return unpackHalf2x16(shared_block[y][x]); } +void store_shared(uint y, uint x, VEC2 v) { shared_block[y][x] = packHalf2x16(v); } +#else +VEC2 load_shared(uint y, uint x) { return VEC2(shared_block[y][x]); } +void store_shared(uint y, uint x, VEC2 v) { shared_block[y][x] = SHARED_VEC2(v); } +#endif + +bvec2 band(bvec2 a, bvec2 b) +{ + return bvec2(a.x && b.x, a.y && b.y); +} + +#include "dwt_swizzle.h" + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt_quant_scale.h b/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt_quant_scale.h new file mode 100644 index 00000000..9f53d14e --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt_quant_scale.h @@ -0,0 +1,21 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#ifndef DWT_QUANT_SCALE_H_ +#define DWT_QUANT_SCALE_H_ + +float decode_quant_scale(uint code) +{ + // Minimum scale: 0.25 + // Maximum scale: ~2.2 + return float(code) / 8.0 + 0.25; +} + +const uint ENCODE_QUANT_IDENTITY = 6; + +uint encode_quant_scale(float scale) +{ + // Round the quant scale FP up so that the quantizer scale effectively rounds down. + return uint(ceil((scale - 0.25) * 8.0)); +} + +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt_swizzle.h b/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt_swizzle.h new file mode 100644 index 00000000..63b10882 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/dwt_swizzle.h @@ -0,0 +1,23 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#ifndef DWT_SWIZZLE_H_ +#define DWT_SWIZZLE_H_ + +ivec2 unswizzle4x8(uint index) +{ + uint y = bitfieldExtract(index, 0, 1); + uint x = bitfieldExtract(index, 1, 2); + y |= bitfieldExtract(index, 3, 2) << 1; + return ivec2(x, y); +} + +ivec2 unswizzle8x8(uint index) +{ + uint y = bitfieldExtract(index, 0, 1); + uint x = bitfieldExtract(index, 1, 2); + y |= bitfieldExtract(index, 3, 2) << 1; + x |= bitfieldExtract(index, 5, 1) << 2; + return ivec2(x, y); +} + +#endif \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/idwt.comp b/crates/pyrowave-sys/vendor/pyrowave/shaders/idwt.comp new file mode 100644 index 00000000..d6847aff --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/idwt.comp @@ -0,0 +1,214 @@ +#version 450 +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#if FP16 +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#endif + +layout(local_size_x = 64) in; +layout(constant_id = 0) const bool DCShift = false; + +uint local_index; + +#include "dwt_common.h" + +layout(set = 0, binding = 0) uniform mediump sampler2DArray uTexture; +layout(set = 0, binding = 1) writeonly mediump uniform image2D uOutput; + +layout(push_constant) uniform Registers +{ + ivec2 resolution; + vec2 inv_resolution; +}; + +vec2 generate_mirror_uv(ivec2 coord, bool even_x, bool even_y) +{ + coord -= ivec2(band(bvec2(even_x, even_y), lessThan(coord, ivec2(0)))); + coord += 1; + coord += ivec2(band(bvec2(!even_x, !even_y), greaterThanEqual(coord, resolution))); + vec2 uv = vec2(coord) * inv_resolution; + return uv.yx; // Transpose on load. +} + +void write_shared_4x4(ivec2 coord, VEC4 texels0, VEC4 texels1, VEC4 texels2, VEC4 texels3) +{ + store_shared(coord.y + 0, 2 * coord.x + 0, VEC2(texels0.x, texels2.x)); + store_shared(coord.y + 0, 2 * coord.x + 1, VEC2(texels1.x, texels3.x)); + store_shared(coord.y + 0, 2 * coord.x + 2, VEC2(texels0.y, texels2.y)); + store_shared(coord.y + 0, 2 * coord.x + 3, VEC2(texels1.y, texels3.y)); + store_shared(coord.y + 1, 2 * coord.x + 0, VEC2(texels0.z, texels2.z)); + store_shared(coord.y + 1, 2 * coord.x + 1, VEC2(texels1.z, texels3.z)); + store_shared(coord.y + 1, 2 * coord.x + 2, VEC2(texels0.w, texels2.w)); + store_shared(coord.y + 1, 2 * coord.x + 3, VEC2(texels1.w, texels3.w)); +} + +void load_image_with_apron() +{ + ivec2 base_coord = ivec2(gl_WorkGroupID.xy) * ivec2(BLOCK_SIZE_HALF) - APRON_HALF; + ivec2 local_coord0 = 2 * unswizzle8x8(local_index); + ivec2 coord0 = base_coord + local_coord0; + + // Transpose on load. + VEC4 texels0 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(coord0, true, true), 0.0), 0)).wxzy; + VEC4 texels1 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(coord0, false, true), 2.0), 0)).wxzy; + VEC4 texels2 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(coord0, true, false), 1.0), 0)).wxzy; + VEC4 texels3 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(coord0, false, false), 3.0), 0)).wxzy; + write_shared_4x4(local_coord0, texels0, texels1, texels2, texels3); + + ivec2 local_coord_horiz = ivec2(BLOCK_SIZE_HALF + 2 * (local_index % 2u), 2 * (local_index / 2u)); + if (local_coord_horiz.y < BLOCK_SIZE_HALF + 2 * APRON_HALF) + { + texels0 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(base_coord + local_coord_horiz, true, true), 0.0), 0)).wxzy; + texels1 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(base_coord + local_coord_horiz, false, true), 2.0), 0)).wxzy; + texels2 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(base_coord + local_coord_horiz, true, false), 1.0), 0)).wxzy; + texels3 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(base_coord + local_coord_horiz, false, false), 3.0), 0)).wxzy; + write_shared_4x4(local_coord_horiz, texels0, texels1, texels2, texels3); + } + + ivec2 local_coord_vert = local_coord_horiz.yx; + if (local_coord_vert.x < BLOCK_SIZE_HALF) + { + texels0 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(base_coord + local_coord_vert, true, true), 0.0), 0)).wxzy; + texels1 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(base_coord + local_coord_vert, false, true), 2.0), 0)).wxzy; + texels2 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(base_coord + local_coord_vert, true, false), 1.0), 0)).wxzy; + texels3 = VEC4(textureGather(uTexture, vec3(generate_mirror_uv(base_coord + local_coord_vert, false, false), 3.0), 0)).wxzy; + write_shared_4x4(local_coord_vert, texels0, texels1, texels2, texels3); + } + + barrier(); +} + +void inverse_transform8x2() +{ + const int SIZE = 8; + const int PADDED_SIZE = SIZE + 2 * APRON; + const int PADDED_SIZE_HALF = PADDED_SIZE / 2; + VEC2 values[PADDED_SIZE]; + + ivec2 local_coord = ivec2(8 * (local_index % 4u), local_index / 4u); + + for (int i = 0; i < PADDED_SIZE; i += 2) + { + VEC2 v0 = load_shared(local_coord.y, local_coord.x + i + 0); + VEC2 v1 = load_shared(local_coord.y, local_coord.x + i + 1); + values[i + 0] = v0 * K; + values[i + 1] = v1 * inv_K; + } + + // CDF 9/7 lifting steps. + // Arith go brrr. + for (int i = 2; i < PADDED_SIZE - 1; i += 2) + values[i] -= DELTA * (values[i - 1] + values[i + 1]); + for (int i = 3; i < PADDED_SIZE - 2; i += 2) + values[i] -= GAMMA * (values[i - 1] + values[i + 1]); + for (int i = 4; i < PADDED_SIZE - 3; i += 2) + values[i] -= BETA * (values[i - 1] + values[i + 1]); + for (int i = 5; i < PADDED_SIZE - 4; i += 2) + values[i] -= ALPHA * (values[i - 1] + values[i + 1]); + + // Avoid WAR hazard. + barrier(); + + for (int i = APRON_HALF; i < PADDED_SIZE_HALF - APRON_HALF; i++) + { + VEC2 a = values[2 * i + 0]; + VEC2 b = values[2 * i + 1]; + + // Transpose the 2x2 block. + VEC2 t0 = VEC2(a.x, b.x); + VEC2 t1 = VEC2(a.y, b.y); + + // Transpose write + int y_coord = (local_coord.x >> 1) + (i - APRON_HALF); + store_shared(y_coord, 2 * local_coord.y + 0, t0); + store_shared(y_coord, 2 * local_coord.y + 1, t1); + } +} + +void inverse_transform4x2(bool active_lane, int y_offset) +{ + const int SIZE = 4; + const int PADDED_SIZE = SIZE + 2 * APRON; + const int PADDED_SIZE_HALF = PADDED_SIZE / 2; + VEC2 values[PADDED_SIZE]; + + ivec2 local_coord = ivec2(4 * (local_index % 8u), local_index / 8u + y_offset); + + if (active_lane) + { + for (int i = 0; i < PADDED_SIZE; i += 2) + { + VEC2 v0 = load_shared(local_coord.y, local_coord.x + i + 0); + VEC2 v1 = load_shared(local_coord.y, local_coord.x + i + 1); + values[i + 0] = v0 * K; + values[i + 1] = v1 * inv_K; + } + + // CDF 9/7 lifting steps. + // Arith go brrr. + for (int i = 2; i < PADDED_SIZE - 1; i += 2) + values[i] -= DELTA * (values[i - 1] + values[i + 1]); + for (int i = 3; i < PADDED_SIZE - 2; i += 2) + values[i] -= GAMMA * (values[i - 1] + values[i + 1]); + for (int i = 4; i < PADDED_SIZE - 3; i += 2) + values[i] -= BETA * (values[i - 1] + values[i + 1]); + for (int i = 5; i < PADDED_SIZE - 4; i += 2) + values[i] -= ALPHA * (values[i - 1] + values[i + 1]); + } + + // Avoid WAR hazard. + barrier(); + + if (active_lane) + { + for (int i = APRON_HALF; i < PADDED_SIZE_HALF - APRON_HALF; i++) + { + VEC2 a = values[2 * i + 0]; + VEC2 b = values[2 * i + 1]; + + // Transpose the 2x2 block. + VEC2 t0 = VEC2(a.x, b.x); + VEC2 t1 = VEC2(a.y, b.y); + + // Transpose write + int y_coord = (local_coord.x >> 1) + (i - APRON_HALF); + store_shared(y_coord, 2 * local_coord.y + 0, t0); + store_shared(y_coord, 2 * local_coord.y + 1, t1); + } + } +} + +void main() +{ + local_index = gl_LocalInvocationIndex; + + load_image_with_apron(); + + // Horizontal transform. + inverse_transform8x2(); + + // Also need to transform the apron. + inverse_transform4x2(local_index < 32, BLOCK_SIZE_HALF); + + barrier(); + + // Vertical transform. + inverse_transform8x2(); + + barrier(); + + ivec2 local_coord = unswizzle8x8(local_index); + + for (int y = local_coord.y; y < BLOCK_SIZE_HALF; y += 8) + { + for (int x = local_coord.x; x < BLOCK_SIZE; x += 8) + { + VEC2 v = load_shared(y, x); + if (DCShift) + v += FLOAT(0.5); + imageStore(uOutput, ivec2(2 * y + 0, x) + BLOCK_SIZE * ivec2(gl_WorkGroupID.yx), v.xxxx); + imageStore(uOutput, ivec2(2 * y + 1, x) + BLOCK_SIZE * ivec2(gl_WorkGroupID.yx), v.yyyy); + } + } +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/idwt.frag b/crates/pyrowave-sys/vendor/pyrowave/shaders/idwt.frag new file mode 100644 index 00000000..db264be5 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/idwt.frag @@ -0,0 +1,252 @@ +#version 450 +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#extension GL_EXT_control_flow_attributes : require + +layout(location = 0) in vec2 vUV; +layout(location = 0, component = 2) in float vIntCoord; + +#if CHROMA_CONFIG == 0 +#define OUTPUT_PLANES 1 +#define INPUT_PLANES 1 +#elif CHROMA_CONFIG == 1 +#define OUTPUT_PLANES 2 +#define INPUT_PLANES 3 +#elif CHROMA_CONFIG == 2 +#define OUTPUT_PLANES 3 +#define INPUT_PLANES 2 +#else +#error "Invalid chroma config" +#endif + +layout(location = 0) out mediump float oY; +#if OUTPUT_PLANES == 2 +layout(location = 1) out mediump vec2 oCbCr; +#elif OUTPUT_PLANES == 3 +layout(location = 1) out mediump float oCb; +layout(location = 2) out mediump float oCr; +#endif + +layout(set = 0, binding = 0) uniform mediump texture2D uYEven; +layout(set = 0, binding = 1) uniform mediump texture2D uYOdd; +layout(set = 0, binding = 2) uniform mediump sampler uSampler; +#if INPUT_PLANES == 3 +layout(set = 0, binding = 3) uniform mediump texture2D uCbEven; +layout(set = 0, binding = 4) uniform mediump texture2D uCbOdd; +layout(set = 0, binding = 5) uniform mediump texture2D uCrEven; +layout(set = 0, binding = 6) uniform mediump texture2D uCrOdd; +#elif INPUT_PLANES == 2 +layout(set = 0, binding = 3) uniform mediump texture2D uCbCrEven; +layout(set = 0, binding = 4) uniform mediump texture2D uCbCrOdd; +#endif + +// Direct and naive implementing of the CDF 9/7 synthesis filters. +// Optimized for the mobile GPUs which don't have any +// competent compute/shared memory performance whatsoever, +// i.e. anything not AMD/NV/Intel. + +layout(constant_id = 0) const bool VERTICAL = false; +layout(constant_id = 1) const bool FINAL_Y = false; +layout(constant_id = 2) const bool FINAL_CBCR = false; +layout(constant_id = 3) const int EDGE_CONDITION = 0; +const ivec2 OFFSET_M2 = VERTICAL ? ivec2(0, 0) : ivec2(0, 0); +const ivec2 OFFSET_M1 = VERTICAL ? ivec2(0, 1) : ivec2(1, 0); +const ivec2 OFFSET_C = VERTICAL ? ivec2(0, 2) : ivec2(2, 0); +const ivec2 OFFSET_P1 = VERTICAL ? ivec2(0, 3) : ivec2(3, 0); +const ivec2 OFFSET_P2 = VERTICAL ? ivec2(0, 4) : ivec2(4, 0); + +const float SYNTHESIS_LP_0 = 1.11508705; +const float SYNTHESIS_LP_1 = 0.591271763114; +const float SYNTHESIS_LP_2 = -0.057543526229; +const float SYNTHESIS_LP_3 = -0.091271763114; + +const float SYNTHESIS_HP_0 = 0.602949018236; +const float SYNTHESIS_HP_1 = -0.266864118443; +const float SYNTHESIS_HP_2 = -0.078223266529; +const float SYNTHESIS_HP_3 = 0.016864118443; +const float SYNTHESIS_HP_4 = 0.026748757411; + +layout(push_constant) uniform Registers +{ + vec2 uv_offset; + vec2 half_texel_offset; + float res_scale; + int aligned_transform_size; +}; + +float[10] sample_component_gather(mediump texture2D tex_even, mediump texture2D tex_odd) +{ + float components[10]; + vec2 gather_uv = vUV + half_texel_offset; + vec2 even0, even1, odd0, odd1; + + if (VERTICAL) + { + even0 = textureGatherOffset(sampler2D(tex_even, uSampler), gather_uv, OFFSET_M1).wx; + even1 = textureGatherOffset(sampler2D(tex_even, uSampler), gather_uv, OFFSET_P1).wx; + odd0 = textureGatherOffset(sampler2D(tex_odd, uSampler), gather_uv, OFFSET_M2).wx; + odd1 = textureGatherOffset(sampler2D(tex_odd, uSampler), gather_uv, OFFSET_C).wx; + } + else + { + even0 = textureGatherOffset(sampler2D(tex_even, uSampler), gather_uv, OFFSET_M1).wz; + even1 = textureGatherOffset(sampler2D(tex_even, uSampler), gather_uv, OFFSET_P1).wz; + odd0 = textureGatherOffset(sampler2D(tex_odd, uSampler), gather_uv, OFFSET_M2).wz; + odd1 = textureGatherOffset(sampler2D(tex_odd, uSampler), gather_uv, OFFSET_C).wz; + } + + components[0] = 0.0; + components[1] = odd0.x; + components[2] = even0.x; + components[3] = odd0.y; + components[4] = even0.y; + components[5] = odd1.x; + components[6] = even1.x; + components[7] = odd1.y; + components[8] = even1.y; + components[9] = textureLodOffset(sampler2D(tex_odd, uSampler), vUV, 0.0, OFFSET_P2).x; + + return components; +} + +vec2[10] sample_component_gather2(mediump texture2D tex_even, mediump texture2D tex_odd) +{ + vec2 components[10]; + + // Little point in using gather here, at least for now. + components[0] = vec2(0.0); + components[1] = textureLodOffset(sampler2D(tex_odd, uSampler), vUV, 0.0, OFFSET_M2).xy; + components[2] = textureLodOffset(sampler2D(tex_even, uSampler), vUV, 0.0, OFFSET_M1).xy; + components[3] = textureLodOffset(sampler2D(tex_odd, uSampler), vUV, 0.0, OFFSET_M1).xy; + components[4] = textureLodOffset(sampler2D(tex_even, uSampler), vUV, 0.0, OFFSET_C).xy; + components[5] = textureLodOffset(sampler2D(tex_odd, uSampler), vUV, 0.0, OFFSET_C).xy; + components[6] = textureLodOffset(sampler2D(tex_even, uSampler), vUV, 0.0, OFFSET_P1).xy; + components[7] = textureLodOffset(sampler2D(tex_odd, uSampler), vUV, 0.0, OFFSET_P1).xy; + components[8] = textureLodOffset(sampler2D(tex_even, uSampler), vUV, 0.0, OFFSET_P2).xy; + components[9] = textureLodOffset(sampler2D(tex_odd, uSampler), vUV, 0.0, OFFSET_P2).xy; + + return components; +} + +void main() +{ + bool is_odd = (int(vIntCoord) & 1) != 0; + + float Y[10] = sample_component_gather(uYEven, uYOdd); +#if INPUT_PLANES == 2 + vec2 CbCr[10] = sample_component_gather2(uCbCrEven, uCbCrOdd); +#elif INPUT_PLANES == 3 + float Cb[10] = sample_component_gather(uCbEven, uCbOdd); + float Cr[10] = sample_component_gather(uCrEven, uCrOdd); + vec2 CbCr[10]; + [[unroll]] + for (int i = 0; i < 10; i++) + CbCr[i] = vec2(Cb[i], Cr[i]); +#endif + + if (EDGE_CONDITION < 0) + { + // The mirroring rules are particular. + // For odd inputs we can rely on the mirrored sampling to get intended behavior. + if (vIntCoord < 1.0) + { + // Y4 is the pivot. + Y[2] = Y[6]; +#if INPUT_SAMPLES > 1 + CbCr[2] = CbCr[6]; +#endif + } + } + else if (EDGE_CONDITION > 0) + { + if (vIntCoord + 2.0 > aligned_transform_size) + { + // We're on the last two pixels. + // Y5 is the pivot. LP inputs behave as expected when using mirroring. + Y[7] = Y[3]; + Y[9] = Y[1]; +#if INPUT_SAMPLES > 1 + CbCr[7] = CbCr[3]; + CbCr[9] = CbCr[1]; +#endif + } + else if (vIntCoord + 4.0 >= aligned_transform_size) + { + // Y7 is the pivot. + Y[9] = Y[5]; +#if INPUT_SAMPLES > 1 + CbCr[9] = CbCr[5]; +#endif + } + } + +#if INPUT_PLANES > 1 +#define AccumT vec3 +#define GenInput(comp) vec3(Y[comp], CbCr[comp]) +#else +#define AccumT float +#define GenInput(comp) Y[comp] +#endif + + AccumT C0, C1, C2, C3, C4; + float W0, W1, W2, W3, W4; + + // Not ideal, but gotta do what we gotta do. + // GPU will have to take both paths here, + // but at least we avoid dynamic load-store which is RIP perf on these chips ... + if (is_odd) + { + C0 = GenInput(5); + C1 = GenInput(4) + GenInput(6); + C2 = GenInput(3) + GenInput(7); + C3 = GenInput(2) + GenInput(8); + C4 = GenInput(1) + GenInput(9); + + W0 = SYNTHESIS_HP_0; + W1 = SYNTHESIS_LP_1; + W2 = SYNTHESIS_HP_2; + W3 = SYNTHESIS_LP_3; + W4 = SYNTHESIS_HP_4; + } + else + { + C0 = GenInput(4); + C1 = GenInput(3) + GenInput(5); + C2 = GenInput(2) + GenInput(6); + C3 = GenInput(1) + GenInput(7); + C4 = AccumT(0.0); + + W0 = SYNTHESIS_LP_0; + W1 = SYNTHESIS_HP_1; + W2 = SYNTHESIS_LP_2; + W3 = SYNTHESIS_HP_3; + W4 = 0.0; + } + + AccumT result = C0 * W0 + C1 * W1 + C2 * W2 + C3 * W3 + C4 * W4; + +#if OUTPUT_PLANES == 3 + oY = result.x; + oCb = result.y; + oCr = result.z; +#elif OUTPUT_PLANES == 2 + oY = result.x; + oCbCr = result.yz; +#else + oY = result; +#endif + + if (FINAL_Y) + oY += 0.5; + + if (FINAL_CBCR) + { +#if OUTPUT_PLANES == 3 + oCb += 0.5; + oCr += 0.5; +#elif OUTPUT_PLANES == 2 + oCbCr += 0.5; +#endif + } +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/idwt.vert b/crates/pyrowave-sys/vendor/pyrowave/shaders/idwt.vert new file mode 100644 index 00000000..a96177fc --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/idwt.vert @@ -0,0 +1,34 @@ +#version 450 +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +layout(location = 0) out vec2 vUV; +layout(location = 0, component = 2) out float vIntCoord; + +layout(push_constant) uniform Registers +{ + vec2 uv_offset; + vec2 half_texel_offset; + float res_scale; +}; + +layout(constant_id = 0) const bool VERTICAL = false; + +void main() +{ + if (gl_VertexIndex == 0) + vUV = vec2(0.0, 0.0); + else if (gl_VertexIndex == 1) + vUV = vec2(0.0, 2.0); + else + vUV = vec2(2.0, 0.0); + + gl_Position = vec4(vUV * 2.0 - 1.0, 0.0, 1.0); + + if (VERTICAL) + vIntCoord = vUV.y * res_scale; + else + vIntCoord = vUV.x * res_scale; + + vUV += uv_offset; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/power_to_db.comp b/crates/pyrowave-sys/vendor/pyrowave/shaders/power_to_db.comp new file mode 100644 index 00000000..e0371ce4 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/power_to_db.comp @@ -0,0 +1,33 @@ +#version 450 +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#extension GL_EXT_samplerless_texture_functions : require + +layout(set = 0, binding = 0) uniform texture2D uTex; +layout(set = 0, binding = 1) writeonly uniform image2D uImage; + +layout(local_size_x = 8, local_size_y = 8) in; + +float power_to_db(float p) +{ + return max(10.0 * log2(p) / log2(10.0), -100.0); +} + +void main() +{ + float input_power = 0.0; + const int Stride = 8; + for (int y = 0; y < Stride; y++) + { + for (int x = 0; x < Stride; x++) + { + if (any(notEqual(ivec4(gl_GlobalInvocationID.xy, x, y), ivec4(0)))) + { + vec2 c = texelFetch(uTex, ivec2(gl_GlobalInvocationID.xy) * Stride + ivec2(x, y), 0).xy; + input_power += dot(c, c); + } + } + } + + imageStore(uImage, ivec2(gl_GlobalInvocationID.xy), vec4(power_to_db(input_power))); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/resolve_rate_control.comp b/crates/pyrowave-sys/vendor/pyrowave/shaders/resolve_rate_control.comp new file mode 100644 index 00000000..0b8f8e22 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/resolve_rate_control.comp @@ -0,0 +1,81 @@ +#version 450 +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#extension GL_KHR_shader_subgroup_basic : require +#extension GL_KHR_shader_subgroup_ballot : require +#extension GL_KHR_shader_subgroup_arithmetic : require +#extension GL_KHR_shader_subgroup_shuffle_relative : require +#extension GL_KHR_shader_subgroup_shuffle : require + +layout(local_size_x_id = 0) in; + +struct RDOperation +{ + int quant; + uint block_offset_saving; +}; + +const int BLOCK_SPACE_SUBDIVISION = 16; + +layout(set = 0, binding = 0) readonly buffer Buckets +{ + layout(offset = 4) int consumed_payload; + layout(offset = 64) int total_savings_per_bucket[128 * BLOCK_SPACE_SUBDIVISION]; + RDOperation rdo_operations[]; +} buckets; + +layout(set = 0, binding = 1) buffer QuantList +{ + int data[]; +} quant_data; + +layout(push_constant) uniform Registers +{ + uint target_payload_size; + uint num_blocks_per_subdivision; +} registers; + +void main() +{ + int required_savings_per_bucket = int(buckets.consumed_payload) - int(registers.target_payload_size); + if (gl_WorkGroupID.x != 0) + { + int prev_bucket_total = buckets.total_savings_per_bucket[gl_WorkGroupID.x - 1]; + // This bucket is empty. + if (buckets.total_savings_per_bucket[gl_WorkGroupID.x] == prev_bucket_total) + return; + + required_savings_per_bucket -= prev_bucket_total; + } + else + { + // This bucket is empty. + if (buckets.total_savings_per_bucket[gl_WorkGroupID.x] == 0) + return; + } + + // If all previous buckets can complete the job, skip. + if (required_savings_per_bucket <= 0) + return; + + uint total_saved = 0; + + for (uint i = 0; i < registers.num_blocks_per_subdivision && total_saved < required_savings_per_bucket; i += gl_SubgroupSize) + { + RDOperation op = RDOperation(0, 0); + if (i + gl_SubgroupInvocationID < registers.num_blocks_per_subdivision) + op = buckets.rdo_operations[gl_WorkGroupID.x * registers.num_blocks_per_subdivision + i + gl_SubgroupInvocationID]; + + uint saving = bitfieldExtract(op.block_offset_saving, 16, 16); + uint block_offset = bitfieldExtract(op.block_offset_saving, 0, 16); + + uint scan_saving = subgroupInclusiveAdd(saving); + + bool should_apply_quant = total_saved + scan_saving - saving < required_savings_per_bucket; + if (should_apply_quant && saving != 0) + atomicMax(quant_data.data[block_offset], op.quant); + + total_saved += subgroupShuffle(scan_saving, gl_SubgroupSize - 1); + } +} + diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/slangmosh.hpp b/crates/pyrowave-sys/vendor/pyrowave/shaders/slangmosh.hpp new file mode 100644 index 00000000..4804d9ae --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/slangmosh.hpp @@ -0,0 +1,7729 @@ +// Autogenerated from slangmosh, do not edit. +#ifndef SLANGMOSH_GENERATED_PyroWaveiface_H +#define SLANGMOSH_GENERATED_PyroWaveiface_H +#include +namespace Vulkan +{ +class Program; +class Shader; +} + +namespace PyroWave +{ +template +struct Shaders +{ + Program dwt[3] = {}; + Program block_packing = {}; + Program idwt[3] = {}; + Shader idwt_vs = {}; + Shader idwt_fs[3] = {}; + Program power_to_db = {}; + Program analyze_rate_control = {}; + Program analyze_rate_control_finalize = {}; + Program resolve_rate_control = {}; + Program wavelet_quant = {}; + Program wavelet_dequant[3] = {}; + Shaders() = default; + + template + Shaders(Device &device, Layout &layout, const Resolver &resolver); +}; +} +#endif +// Autogenerated from slangmosh, do not edit. +#ifndef SLANGMOSH_GENERATED_PyroWaveH +#define SLANGMOSH_GENERATED_PyroWaveH +#include +namespace Vulkan +{ +class Program; +class Shader; +} + +namespace PyroWave +{ +static const uint32_t spirv_bank[] = +{ + 0x07230203u, 0x00010300u, 0x000d000bu, 0x00000a30u, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, + 0x00000038u, 0x00020011u, 0x0000003du, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, + 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0009000fu, 0x00000005u, 0x00000004u, 0x6e69616du, + 0x00000000u, 0x00000093u, 0x000003b3u, 0x000003b5u, 0x000003b8u, 0x00060010u, 0x00000004u, 0x00000011u, + 0x00000040u, 0x00000001u, 0x00000001u, 0x00030047u, 0x00000068u, 0x00000002u, 0x00050048u, 0x00000068u, + 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x00000068u, 0x00000001u, 0x00000023u, 0x00000008u, + 0x00050048u, 0x00000068u, 0x00000002u, 0x00000023u, 0x00000010u, 0x00040047u, 0x00000093u, 0x0000000bu, + 0x0000001au, 0x00030047u, 0x000000b0u, 0x00000000u, 0x00040047u, 0x000000b0u, 0x00000021u, 0x00000000u, + 0x00040047u, 0x000000b0u, 0x00000022u, 0x00000000u, 0x00040047u, 0x000000d3u, 0x00000001u, 0x00000000u, + 0x00040047u, 0x000003b3u, 0x0000000bu, 0x00000028u, 0x00030047u, 0x000003b5u, 0x00000000u, 0x00040047u, + 0x000003b5u, 0x0000000bu, 0x00000024u, 0x00030047u, 0x000003b6u, 0x00000000u, 0x00030047u, 0x000003b8u, + 0x00000000u, 0x00040047u, 0x000003b8u, 0x0000000bu, 0x00000029u, 0x00030047u, 0x000003b9u, 0x00000000u, + 0x00030047u, 0x000003ffu, 0x00000000u, 0x00030047u, 0x000003ffu, 0x00000019u, 0x00040047u, 0x000003ffu, + 0x00000021u, 0x00000001u, 0x00040047u, 0x000003ffu, 0x00000022u, 0x00000000u, 0x00030047u, 0x00000400u, + 0x00000000u, 0x00030047u, 0x00000408u, 0x00000000u, 0x00030047u, 0x0000040fu, 0x00000000u, 0x00030047u, + 0x00000416u, 0x00000000u, 0x00040047u, 0x00000422u, 0x0000000bu, 0x00000019u, 0x00030047u, 0x00000471u, + 0x00000000u, 0x00030047u, 0x00000474u, 0x00000000u, 0x00030047u, 0x00000476u, 0x00000000u, 0x00030047u, + 0x0000047au, 0x00000000u, 0x00030047u, 0x0000047cu, 0x00000000u, 0x00030047u, 0x00000480u, 0x00000000u, + 0x00030047u, 0x00000482u, 0x00000000u, 0x00030047u, 0x00000486u, 0x00000000u, 0x00030047u, 0x000004f3u, + 0x00000000u, 0x00030047u, 0x000004f8u, 0x00000000u, 0x00030047u, 0x0000051fu, 0x00000000u, 0x00030047u, + 0x00000524u, 0x00000000u, 0x00030047u, 0x0000054fu, 0x00000000u, 0x00030047u, 0x00000554u, 0x00000000u, + 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, + 0x00000000u, 0x00030016u, 0x00000008u, 0x00000020u, 0x00040017u, 0x00000009u, 0x00000008u, 0x00000002u, + 0x00040020u, 0x0000000fu, 0x00000007u, 0x00000009u, 0x00040015u, 0x00000016u, 0x00000020u, 0x00000001u, + 0x00040017u, 0x00000017u, 0x00000016u, 0x00000002u, 0x00020014u, 0x00000025u, 0x0004002bu, 0x00000006u, + 0x0000002du, 0x00000029u, 0x0004001cu, 0x0000002eu, 0x00000006u, 0x0000002du, 0x0004002bu, 0x00000006u, + 0x0000002fu, 0x00000014u, 0x0004001cu, 0x00000030u, 0x0000002eu, 0x0000002fu, 0x00040020u, 0x00000031u, + 0x00000004u, 0x00000030u, 0x0004003bu, 0x00000031u, 0x00000032u, 0x00000004u, 0x00040020u, 0x00000035u, + 0x00000004u, 0x00000006u, 0x0004002bu, 0x00000016u, 0x00000042u, 0x00000000u, 0x0004002bu, 0x00000016u, + 0x00000043u, 0x00000001u, 0x0004002bu, 0x00000016u, 0x00000047u, 0x00000002u, 0x0004002bu, 0x00000016u, + 0x0000004au, 0x00000003u, 0x0004002bu, 0x00000016u, 0x00000050u, 0x00000005u, 0x0005002cu, 0x00000017u, + 0x0000005du, 0x00000042u, 0x00000042u, 0x00040017u, 0x0000005eu, 0x00000025u, 0x00000002u, 0x0005002cu, + 0x00000017u, 0x00000060u, 0x00000043u, 0x00000043u, 0x0005001eu, 0x00000068u, 0x00000017u, 0x00000009u, + 0x00000017u, 0x00040020u, 0x00000069u, 0x00000009u, 0x00000068u, 0x0004003bu, 0x00000069u, 0x0000006au, + 0x00000009u, 0x00040020u, 0x0000006bu, 0x00000009u, 0x00000017u, 0x00040020u, 0x0000008au, 0x00000009u, + 0x00000009u, 0x00040017u, 0x00000091u, 0x00000006u, 0x00000003u, 0x00040020u, 0x00000092u, 0x00000001u, + 0x00000091u, 0x0004003bu, 0x00000092u, 0x00000093u, 0x00000001u, 0x00040017u, 0x00000094u, 0x00000006u, + 0x00000002u, 0x0004002bu, 0x00000016u, 0x00000098u, 0x00000020u, 0x0005002cu, 0x00000017u, 0x00000099u, + 0x00000098u, 0x00000098u, 0x0004002bu, 0x00000016u, 0x0000009bu, 0x00000004u, 0x00040017u, 0x000000aau, + 0x00000008u, 0x00000004u, 0x00090019u, 0x000000adu, 0x00000008u, 0x00000001u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000001u, 0x00000000u, 0x0003001bu, 0x000000aeu, 0x000000adu, 0x00040020u, 0x000000afu, + 0x00000000u, 0x000000aeu, 0x0004003bu, 0x000000afu, 0x000000b0u, 0x00000000u, 0x0004002bu, 0x00000016u, + 0x000000bau, 0x00000010u, 0x0005002cu, 0x00000017u, 0x000000bbu, 0x000000bau, 0x00000042u, 0x0005002cu, + 0x00000017u, 0x000000c4u, 0x00000042u, 0x000000bau, 0x0005002cu, 0x00000017u, 0x000000cdu, 0x000000bau, + 0x000000bau, 0x00030031u, 0x00000025u, 0x000000d3u, 0x0004002bu, 0x00000008u, 0x000000d6u, 0x3f000000u, + 0x0004002bu, 0x00000006u, 0x000000e4u, 0x00000001u, 0x0004002bu, 0x00000016u, 0x00000115u, 0x00000011u, + 0x0004002bu, 0x00000016u, 0x0000011fu, 0x00000008u, 0x0004002bu, 0x00000006u, 0x00000154u, 0x00000020u, + 0x0004002bu, 0x00000006u, 0x00000155u, 0x00000002u, 0x0004002bu, 0x00000006u, 0x00000157u, 0x00000004u, + 0x0004002bu, 0x00000006u, 0x0000018du, 0x00000010u, 0x0004002bu, 0x00000006u, 0x000001fcu, 0x00000008u, + 0x0004001cu, 0x00000219u, 0x00000009u, 0x0000018du, 0x00040020u, 0x0000021au, 0x00000007u, 0x00000219u, + 0x0004002bu, 0x00000016u, 0x00000228u, 0x0000000fu, 0x0004002bu, 0x00000008u, 0x0000022bu, 0xbfcb0673u, + 0x0004002bu, 0x00000016u, 0x00000243u, 0x0000000eu, 0x0004002bu, 0x00000008u, 0x00000246u, 0xbd5901aeu, + 0x0004002bu, 0x00000016u, 0x0000025eu, 0x0000000du, 0x0004002bu, 0x00000008u, 0x00000261u, 0x3f620676u, + 0x0004002bu, 0x00000016u, 0x00000279u, 0x0000000cu, 0x0004002bu, 0x00000008u, 0x0000027cu, 0x3ee31355u, + 0x0004002bu, 0x00000006u, 0x0000028du, 0x00000108u, 0x0004002bu, 0x00000016u, 0x00000295u, 0x00000006u, + 0x0004002bu, 0x00000008u, 0x000002a3u, 0x3f5019c3u, 0x0004002bu, 0x00000008u, 0x000002a6u, 0x3f9d7658u, + 0x0004002bu, 0x00000006u, 0x000002fau, 0x0000000cu, 0x0004001cu, 0x000002fbu, 0x00000009u, 0x000002fau, + 0x00040020u, 0x000002fcu, 0x00000007u, 0x000002fbu, 0x0004002bu, 0x00000016u, 0x0000030au, 0x0000000bu, + 0x0004002bu, 0x00000016u, 0x00000324u, 0x0000000au, 0x0004002bu, 0x00000016u, 0x0000033eu, 0x00000009u, + 0x00040020u, 0x000003b2u, 0x00000001u, 0x00000006u, 0x0004003bu, 0x000003b2u, 0x000003b3u, 0x00000001u, + 0x0004003bu, 0x000003b2u, 0x000003b5u, 0x00000001u, 0x0004003bu, 0x000003b2u, 0x000003b8u, 0x00000001u, + 0x00090019u, 0x000003fdu, 0x00000008u, 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000002u, + 0x00000000u, 0x00040020u, 0x000003feu, 0x00000000u, 0x000003fdu, 0x0004003bu, 0x000003feu, 0x000003ffu, + 0x00000000u, 0x00040017u, 0x00000402u, 0x00000016u, 0x00000003u, 0x0004002bu, 0x00000006u, 0x00000421u, + 0x00000040u, 0x0006002cu, 0x00000091u, 0x00000422u, 0x00000421u, 0x000000e4u, 0x000000e4u, 0x0005002cu, + 0x00000017u, 0x00000a2du, 0x0000009bu, 0x0000009bu, 0x0005002cu, 0x00000017u, 0x00000a2eu, 0x00000047u, + 0x00000047u, 0x0007002cu, 0x000000aau, 0x00000a2fu, 0x000000d6u, 0x000000d6u, 0x000000d6u, 0x000000d6u, + 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, + 0x0000021au, 0x000008dfu, 0x00000007u, 0x0004003bu, 0x000002fcu, 0x000007f6u, 0x00000007u, 0x0004003bu, + 0x0000021au, 0x00000716u, 0x00000007u, 0x0004003du, 0x00000006u, 0x000003b4u, 0x000003b3u, 0x0004003du, + 0x00000006u, 0x000003b6u, 0x000003b5u, 0x00050084u, 0x00000006u, 0x000003b7u, 0x000003b4u, 0x000003b6u, + 0x0004003du, 0x00000006u, 0x000003b9u, 0x000003b8u, 0x00050080u, 0x00000006u, 0x000003bau, 0x000003b7u, + 0x000003b9u, 0x0004003du, 0x00000091u, 0x00000464u, 0x00000093u, 0x0007004fu, 0x00000094u, 0x00000465u, + 0x00000464u, 0x00000464u, 0x00000000u, 0x00000001u, 0x0004007cu, 0x00000017u, 0x00000466u, 0x00000465u, + 0x00050084u, 0x00000017u, 0x00000467u, 0x00000466u, 0x00000099u, 0x00050082u, 0x00000017u, 0x00000469u, + 0x00000467u, 0x00000a2du, 0x000600cbu, 0x00000006u, 0x00000577u, 0x000003bau, 0x00000042u, 0x00000043u, + 0x000600cbu, 0x00000006u, 0x00000579u, 0x000003bau, 0x00000043u, 0x00000047u, 0x000600cbu, 0x00000006u, + 0x0000057bu, 0x000003bau, 0x0000004au, 0x00000047u, 0x000500c4u, 0x00000006u, 0x0000057cu, 0x0000057bu, + 0x00000043u, 0x000500c5u, 0x00000006u, 0x0000057eu, 0x00000577u, 0x0000057cu, 0x000600cbu, 0x00000006u, + 0x00000580u, 0x000003bau, 0x00000050u, 0x00000043u, 0x000500c4u, 0x00000006u, 0x00000581u, 0x00000580u, + 0x00000047u, 0x000500c5u, 0x00000006u, 0x00000583u, 0x00000579u, 0x00000581u, 0x0004007cu, 0x00000016u, + 0x00000585u, 0x00000583u, 0x0004007cu, 0x00000016u, 0x00000587u, 0x0000057eu, 0x00050050u, 0x00000017u, + 0x00000588u, 0x00000585u, 0x00000587u, 0x00050084u, 0x00000017u, 0x0000046du, 0x00000a2eu, 0x00000588u, + 0x00050080u, 0x00000017u, 0x00000470u, 0x00000469u, 0x0000046du, 0x0004003du, 0x000000aeu, 0x00000471u, + 0x000000b0u, 0x000500b1u, 0x0000005eu, 0x0000058eu, 0x00000470u, 0x0000005du, 0x000600a9u, 0x00000017u, + 0x0000058fu, 0x0000058eu, 0x00000060u, 0x0000005du, 0x00050082u, 0x00000017u, 0x00000591u, 0x00000470u, + 0x0000058fu, 0x00050080u, 0x00000017u, 0x00000594u, 0x00000591u, 0x00000060u, 0x00050041u, 0x0000006bu, + 0x00000595u, 0x0000006au, 0x00000047u, 0x0004003du, 0x00000017u, 0x00000596u, 0x00000595u, 0x00050084u, + 0x00000017u, 0x00000598u, 0x00000a2eu, 0x00000596u, 0x00050041u, 0x0000006bu, 0x00000599u, 0x0000006au, + 0x00000042u, 0x0004003du, 0x00000017u, 0x0000059au, 0x00000599u, 0x00050082u, 0x00000017u, 0x0000059bu, + 0x00000598u, 0x0000059au, 0x00050082u, 0x00000017u, 0x000005a1u, 0x0000059au, 0x00000596u, 0x00050084u, + 0x00000017u, 0x000005a3u, 0x00000a2eu, 0x000005a1u, 0x00050080u, 0x00000017u, 0x000005a4u, 0x00000594u, + 0x000005a3u, 0x00050080u, 0x00000017u, 0x000005a6u, 0x000005a4u, 0x00000060u, 0x0007000cu, 0x00000017u, + 0x000005aau, 0x00000001u, 0x00000027u, 0x00000594u, 0x0000059au, 0x000500afu, 0x0000005eu, 0x000005aeu, + 0x00000594u, 0x0000059bu, 0x000600a9u, 0x00000017u, 0x000005afu, 0x000005aeu, 0x000005a6u, 0x000005aau, + 0x0004006fu, 0x00000009u, 0x000005b1u, 0x000005afu, 0x00050041u, 0x0000008au, 0x000005b2u, 0x0000006au, + 0x00000043u, 0x0004003du, 0x00000009u, 0x000005b3u, 0x000005b2u, 0x00050085u, 0x00000009u, 0x000005b4u, + 0x000005b1u, 0x000005b3u, 0x00060060u, 0x000000aau, 0x00000474u, 0x00000471u, 0x000005b4u, 0x00000042u, + 0x0009004fu, 0x000000aau, 0x00000475u, 0x00000474u, 0x00000474u, 0x00000003u, 0x00000002u, 0x00000000u, + 0x00000001u, 0x0004003du, 0x000000aeu, 0x00000476u, 0x000000b0u, 0x00050080u, 0x00000017u, 0x00000478u, + 0x00000470u, 0x000000bbu, 0x000500b1u, 0x0000005eu, 0x000005bau, 0x00000478u, 0x0000005du, 0x000600a9u, + 0x00000017u, 0x000005bbu, 0x000005bau, 0x00000060u, 0x0000005du, 0x00050082u, 0x00000017u, 0x000005bdu, + 0x00000478u, 0x000005bbu, 0x00050080u, 0x00000017u, 0x000005c0u, 0x000005bdu, 0x00000060u, 0x00050080u, + 0x00000017u, 0x000005d0u, 0x000005c0u, 0x000005a3u, 0x00050080u, 0x00000017u, 0x000005d2u, 0x000005d0u, + 0x00000060u, 0x0007000cu, 0x00000017u, 0x000005d6u, 0x00000001u, 0x00000027u, 0x000005c0u, 0x0000059au, + 0x000500afu, 0x0000005eu, 0x000005dau, 0x000005c0u, 0x0000059bu, 0x000600a9u, 0x00000017u, 0x000005dbu, + 0x000005dau, 0x000005d2u, 0x000005d6u, 0x0004006fu, 0x00000009u, 0x000005ddu, 0x000005dbu, 0x00050085u, + 0x00000009u, 0x000005e0u, 0x000005ddu, 0x000005b3u, 0x00060060u, 0x000000aau, 0x0000047au, 0x00000476u, + 0x000005e0u, 0x00000042u, 0x0009004fu, 0x000000aau, 0x0000047bu, 0x0000047au, 0x0000047au, 0x00000003u, + 0x00000002u, 0x00000000u, 0x00000001u, 0x0004003du, 0x000000aeu, 0x0000047cu, 0x000000b0u, 0x00050080u, + 0x00000017u, 0x0000047eu, 0x00000470u, 0x000000c4u, 0x000500b1u, 0x0000005eu, 0x000005e6u, 0x0000047eu, + 0x0000005du, 0x000600a9u, 0x00000017u, 0x000005e7u, 0x000005e6u, 0x00000060u, 0x0000005du, 0x00050082u, + 0x00000017u, 0x000005e9u, 0x0000047eu, 0x000005e7u, 0x00050080u, 0x00000017u, 0x000005ecu, 0x000005e9u, + 0x00000060u, 0x00050080u, 0x00000017u, 0x000005fcu, 0x000005ecu, 0x000005a3u, 0x00050080u, 0x00000017u, + 0x000005feu, 0x000005fcu, 0x00000060u, 0x0007000cu, 0x00000017u, 0x00000602u, 0x00000001u, 0x00000027u, + 0x000005ecu, 0x0000059au, 0x000500afu, 0x0000005eu, 0x00000606u, 0x000005ecu, 0x0000059bu, 0x000600a9u, + 0x00000017u, 0x00000607u, 0x00000606u, 0x000005feu, 0x00000602u, 0x0004006fu, 0x00000009u, 0x00000609u, + 0x00000607u, 0x00050085u, 0x00000009u, 0x0000060cu, 0x00000609u, 0x000005b3u, 0x00060060u, 0x000000aau, + 0x00000480u, 0x0000047cu, 0x0000060cu, 0x00000042u, 0x0009004fu, 0x000000aau, 0x00000481u, 0x00000480u, + 0x00000480u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x0004003du, 0x000000aeu, 0x00000482u, + 0x000000b0u, 0x00050080u, 0x00000017u, 0x00000484u, 0x00000470u, 0x000000cdu, 0x000500b1u, 0x0000005eu, + 0x00000612u, 0x00000484u, 0x0000005du, 0x000600a9u, 0x00000017u, 0x00000613u, 0x00000612u, 0x00000060u, + 0x0000005du, 0x00050082u, 0x00000017u, 0x00000615u, 0x00000484u, 0x00000613u, 0x00050080u, 0x00000017u, + 0x00000618u, 0x00000615u, 0x00000060u, 0x00050080u, 0x00000017u, 0x00000628u, 0x00000618u, 0x000005a3u, + 0x00050080u, 0x00000017u, 0x0000062au, 0x00000628u, 0x00000060u, 0x0007000cu, 0x00000017u, 0x0000062eu, + 0x00000001u, 0x00000027u, 0x00000618u, 0x0000059au, 0x000500afu, 0x0000005eu, 0x00000632u, 0x00000618u, + 0x0000059bu, 0x000600a9u, 0x00000017u, 0x00000633u, 0x00000632u, 0x0000062au, 0x0000062eu, 0x0004006fu, + 0x00000009u, 0x00000635u, 0x00000633u, 0x00050085u, 0x00000009u, 0x00000638u, 0x00000635u, 0x000005b3u, + 0x00060060u, 0x000000aau, 0x00000486u, 0x00000482u, 0x00000638u, 0x00000042u, 0x0009004fu, 0x000000aau, + 0x00000487u, 0x00000486u, 0x00000486u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, + 0x00000495u, 0x00000000u, 0x000400fau, 0x000000d3u, 0x00000488u, 0x00000495u, 0x000200f8u, 0x00000488u, + 0x00050083u, 0x000000aau, 0x0000048bu, 0x00000475u, 0x00000a2fu, 0x00050083u, 0x000000aau, 0x0000048eu, + 0x0000047bu, 0x00000a2fu, 0x00050083u, 0x000000aau, 0x00000491u, 0x00000481u, 0x00000a2fu, 0x00050083u, + 0x000000aau, 0x00000494u, 0x00000487u, 0x00000a2fu, 0x000200f9u, 0x00000495u, 0x000200f8u, 0x00000495u, + 0x000700f5u, 0x000000aau, 0x00000a14u, 0x00000487u, 0x00000005u, 0x00000494u, 0x00000488u, 0x000700f5u, + 0x000000aau, 0x00000a13u, 0x00000481u, 0x00000005u, 0x00000491u, 0x00000488u, 0x000700f5u, 0x000000aau, + 0x00000a12u, 0x0000047bu, 0x00000005u, 0x0000048eu, 0x00000488u, 0x000700f5u, 0x000000aau, 0x00000a11u, + 0x00000475u, 0x00000005u, 0x0000048bu, 0x00000488u, 0x00050051u, 0x00000016u, 0x00000497u, 0x0000046du, + 0x00000001u, 0x000500c3u, 0x00000016u, 0x00000498u, 0x00000497u, 0x00000043u, 0x0004007cu, 0x00000006u, + 0x0000049bu, 0x00000498u, 0x00050051u, 0x00000016u, 0x0000049du, 0x0000046du, 0x00000000u, 0x0004007cu, + 0x00000006u, 0x0000049fu, 0x0000049du, 0x0007004fu, 0x00000009u, 0x000004a1u, 0x00000a11u, 0x00000a11u, + 0x00000000u, 0x00000002u, 0x0006000cu, 0x00000006u, 0x0000063du, 0x00000001u, 0x0000003au, 0x000004a1u, + 0x00060041u, 0x00000035u, 0x0000063eu, 0x00000032u, 0x0000049bu, 0x0000049fu, 0x0003003eu, 0x0000063eu, + 0x0000063du, 0x00050080u, 0x00000016u, 0x000004a8u, 0x0000049du, 0x00000043u, 0x0004007cu, 0x00000006u, + 0x000004a9u, 0x000004a8u, 0x0007004fu, 0x00000009u, 0x000004abu, 0x00000a11u, 0x00000a11u, 0x00000001u, + 0x00000003u, 0x0006000cu, 0x00000006u, 0x00000643u, 0x00000001u, 0x0000003au, 0x000004abu, 0x00060041u, + 0x00000035u, 0x00000644u, 0x00000032u, 0x0000049bu, 0x000004a9u, 0x0003003eu, 0x00000644u, 0x00000643u, + 0x00050080u, 0x00000016u, 0x000004b2u, 0x0000049du, 0x000000bau, 0x0004007cu, 0x00000006u, 0x000004b3u, + 0x000004b2u, 0x0007004fu, 0x00000009u, 0x000004b5u, 0x00000a12u, 0x00000a12u, 0x00000000u, 0x00000002u, + 0x0006000cu, 0x00000006u, 0x00000649u, 0x00000001u, 0x0000003au, 0x000004b5u, 0x00060041u, 0x00000035u, + 0x0000064au, 0x00000032u, 0x0000049bu, 0x000004b3u, 0x0003003eu, 0x0000064au, 0x00000649u, 0x00050080u, + 0x00000016u, 0x000004bcu, 0x0000049du, 0x00000115u, 0x0004007cu, 0x00000006u, 0x000004bdu, 0x000004bcu, + 0x0007004fu, 0x00000009u, 0x000004bfu, 0x00000a12u, 0x00000a12u, 0x00000001u, 0x00000003u, 0x0006000cu, + 0x00000006u, 0x0000064fu, 0x00000001u, 0x0000003au, 0x000004bfu, 0x00060041u, 0x00000035u, 0x00000650u, + 0x00000032u, 0x0000049bu, 0x000004bdu, 0x0003003eu, 0x00000650u, 0x0000064fu, 0x00050080u, 0x00000016u, + 0x000004c2u, 0x00000498u, 0x0000011fu, 0x0004007cu, 0x00000006u, 0x000004c3u, 0x000004c2u, 0x0007004fu, + 0x00000009u, 0x000004c9u, 0x00000a13u, 0x00000a13u, 0x00000000u, 0x00000002u, 0x0006000cu, 0x00000006u, + 0x00000655u, 0x00000001u, 0x0000003au, 0x000004c9u, 0x00060041u, 0x00000035u, 0x00000656u, 0x00000032u, + 0x000004c3u, 0x0000049fu, 0x0003003eu, 0x00000656u, 0x00000655u, 0x0007004fu, 0x00000009u, 0x000004d3u, + 0x00000a13u, 0x00000a13u, 0x00000001u, 0x00000003u, 0x0006000cu, 0x00000006u, 0x0000065bu, 0x00000001u, + 0x0000003au, 0x000004d3u, 0x00060041u, 0x00000035u, 0x0000065cu, 0x00000032u, 0x000004c3u, 0x000004a9u, + 0x0003003eu, 0x0000065cu, 0x0000065bu, 0x0007004fu, 0x00000009u, 0x000004ddu, 0x00000a14u, 0x00000a14u, + 0x00000000u, 0x00000002u, 0x0006000cu, 0x00000006u, 0x00000661u, 0x00000001u, 0x0000003au, 0x000004ddu, + 0x00060041u, 0x00000035u, 0x00000662u, 0x00000032u, 0x000004c3u, 0x000004b3u, 0x0003003eu, 0x00000662u, + 0x00000661u, 0x0007004fu, 0x00000009u, 0x000004e7u, 0x00000a14u, 0x00000a14u, 0x00000001u, 0x00000003u, + 0x0006000cu, 0x00000006u, 0x00000667u, 0x00000001u, 0x0000003au, 0x000004e7u, 0x00060041u, 0x00000035u, + 0x00000668u, 0x00000032u, 0x000004c3u, 0x000004bdu, 0x0003003eu, 0x00000668u, 0x00000667u, 0x00050089u, + 0x00000006u, 0x000004eau, 0x000003bau, 0x00000157u, 0x00050084u, 0x00000006u, 0x000004ebu, 0x00000155u, + 0x000004eau, 0x00050080u, 0x00000006u, 0x000004ecu, 0x00000154u, 0x000004ebu, 0x0004007cu, 0x00000016u, + 0x000004edu, 0x000004ecu, 0x00050086u, 0x00000006u, 0x000004efu, 0x000003bau, 0x00000157u, 0x00050084u, + 0x00000006u, 0x000004f0u, 0x00000155u, 0x000004efu, 0x0004007cu, 0x00000016u, 0x000004f1u, 0x000004f0u, + 0x00050050u, 0x00000017u, 0x000004f2u, 0x000004edu, 0x000004f1u, 0x0004003du, 0x000000aeu, 0x000004f3u, + 0x000000b0u, 0x00050080u, 0x00000017u, 0x000004f6u, 0x00000469u, 0x000004f2u, 0x000500b1u, 0x0000005eu, + 0x0000066eu, 0x000004f6u, 0x0000005du, 0x000600a9u, 0x00000017u, 0x0000066fu, 0x0000066eu, 0x00000060u, + 0x0000005du, 0x00050082u, 0x00000017u, 0x00000671u, 0x000004f6u, 0x0000066fu, 0x00050080u, 0x00000017u, + 0x00000674u, 0x00000671u, 0x00000060u, 0x00050080u, 0x00000017u, 0x00000684u, 0x00000674u, 0x000005a3u, + 0x00050080u, 0x00000017u, 0x00000686u, 0x00000684u, 0x00000060u, 0x0007000cu, 0x00000017u, 0x0000068au, + 0x00000001u, 0x00000027u, 0x00000674u, 0x0000059au, 0x000500afu, 0x0000005eu, 0x0000068eu, 0x00000674u, + 0x0000059bu, 0x000600a9u, 0x00000017u, 0x0000068fu, 0x0000068eu, 0x00000686u, 0x0000068au, 0x0004006fu, + 0x00000009u, 0x00000691u, 0x0000068fu, 0x00050085u, 0x00000009u, 0x00000694u, 0x00000691u, 0x000005b3u, + 0x00060060u, 0x000000aau, 0x000004f8u, 0x000004f3u, 0x00000694u, 0x00000042u, 0x0009004fu, 0x000000aau, + 0x000004f9u, 0x000004f8u, 0x000004f8u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, + 0x000004feu, 0x00000000u, 0x000400fau, 0x000000d3u, 0x000004fau, 0x000004feu, 0x000200f8u, 0x000004fau, + 0x00050083u, 0x000000aau, 0x000004fdu, 0x000004f9u, 0x00000a2fu, 0x000200f9u, 0x000004feu, 0x000200f8u, + 0x000004feu, 0x000700f5u, 0x000000aau, 0x00000a15u, 0x000004f9u, 0x00000495u, 0x000004fdu, 0x000004fau, + 0x000500c3u, 0x00000016u, 0x00000501u, 0x000004f1u, 0x00000043u, 0x0004007cu, 0x00000006u, 0x00000502u, + 0x00000501u, 0x0007004fu, 0x00000009u, 0x00000508u, 0x00000a15u, 0x00000a15u, 0x00000000u, 0x00000002u, + 0x0006000cu, 0x00000006u, 0x00000699u, 0x00000001u, 0x0000003au, 0x00000508u, 0x00060041u, 0x00000035u, + 0x0000069au, 0x00000032u, 0x00000502u, 0x000004ecu, 0x0003003eu, 0x0000069au, 0x00000699u, 0x00050080u, + 0x00000016u, 0x00000510u, 0x000004edu, 0x00000043u, 0x0004007cu, 0x00000006u, 0x00000511u, 0x00000510u, + 0x0007004fu, 0x00000009u, 0x00000513u, 0x00000a15u, 0x00000a15u, 0x00000001u, 0x00000003u, 0x0006000cu, + 0x00000006u, 0x0000069fu, 0x00000001u, 0x0000003au, 0x00000513u, 0x00060041u, 0x00000035u, 0x000006a0u, + 0x00000032u, 0x00000502u, 0x00000511u, 0x0003003eu, 0x000006a0u, 0x0000069fu, 0x00050089u, 0x00000006u, + 0x00000516u, 0x000003bau, 0x0000018du, 0x00050084u, 0x00000006u, 0x00000517u, 0x00000155u, 0x00000516u, + 0x0004007cu, 0x00000016u, 0x00000518u, 0x00000517u, 0x00050086u, 0x00000006u, 0x0000051au, 0x000003bau, + 0x0000018du, 0x00050084u, 0x00000006u, 0x0000051bu, 0x00000155u, 0x0000051au, 0x00050080u, 0x00000006u, + 0x0000051cu, 0x00000154u, 0x0000051bu, 0x0004007cu, 0x00000016u, 0x0000051du, 0x0000051cu, 0x00050050u, + 0x00000017u, 0x0000051eu, 0x00000518u, 0x0000051du, 0x0004003du, 0x000000aeu, 0x0000051fu, 0x000000b0u, + 0x00050080u, 0x00000017u, 0x00000522u, 0x00000469u, 0x0000051eu, 0x000500b1u, 0x0000005eu, 0x000006a6u, + 0x00000522u, 0x0000005du, 0x000600a9u, 0x00000017u, 0x000006a7u, 0x000006a6u, 0x00000060u, 0x0000005du, + 0x00050082u, 0x00000017u, 0x000006a9u, 0x00000522u, 0x000006a7u, 0x00050080u, 0x00000017u, 0x000006acu, + 0x000006a9u, 0x00000060u, 0x00050080u, 0x00000017u, 0x000006bcu, 0x000006acu, 0x000005a3u, 0x00050080u, + 0x00000017u, 0x000006beu, 0x000006bcu, 0x00000060u, 0x0007000cu, 0x00000017u, 0x000006c2u, 0x00000001u, + 0x00000027u, 0x000006acu, 0x0000059au, 0x000500afu, 0x0000005eu, 0x000006c6u, 0x000006acu, 0x0000059bu, + 0x000600a9u, 0x00000017u, 0x000006c7u, 0x000006c6u, 0x000006beu, 0x000006c2u, 0x0004006fu, 0x00000009u, + 0x000006c9u, 0x000006c7u, 0x00050085u, 0x00000009u, 0x000006ccu, 0x000006c9u, 0x000005b3u, 0x00060060u, + 0x000000aau, 0x00000524u, 0x0000051fu, 0x000006ccu, 0x00000042u, 0x0009004fu, 0x000000aau, 0x00000525u, + 0x00000524u, 0x00000524u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, 0x0000052au, + 0x00000000u, 0x000400fau, 0x000000d3u, 0x00000526u, 0x0000052au, 0x000200f8u, 0x00000526u, 0x00050083u, + 0x000000aau, 0x00000529u, 0x00000525u, 0x00000a2fu, 0x000200f9u, 0x0000052au, 0x000200f8u, 0x0000052au, + 0x000700f5u, 0x000000aau, 0x00000a16u, 0x00000525u, 0x000004feu, 0x00000529u, 0x00000526u, 0x000500c3u, + 0x00000016u, 0x0000052du, 0x0000051du, 0x00000043u, 0x0004007cu, 0x00000006u, 0x0000052eu, 0x0000052du, + 0x0007004fu, 0x00000009u, 0x00000534u, 0x00000a16u, 0x00000a16u, 0x00000000u, 0x00000002u, 0x0006000cu, + 0x00000006u, 0x000006d1u, 0x00000001u, 0x0000003au, 0x00000534u, 0x00060041u, 0x00000035u, 0x000006d2u, + 0x00000032u, 0x0000052eu, 0x00000517u, 0x0003003eu, 0x000006d2u, 0x000006d1u, 0x00050080u, 0x00000016u, + 0x0000053cu, 0x00000518u, 0x00000043u, 0x0004007cu, 0x00000006u, 0x0000053du, 0x0000053cu, 0x0007004fu, + 0x00000009u, 0x0000053fu, 0x00000a16u, 0x00000a16u, 0x00000001u, 0x00000003u, 0x0006000cu, 0x00000006u, + 0x000006d7u, 0x00000001u, 0x0000003au, 0x0000053fu, 0x00060041u, 0x00000035u, 0x000006d8u, 0x00000032u, + 0x0000052eu, 0x0000053du, 0x0003003eu, 0x000006d8u, 0x000006d7u, 0x000500b0u, 0x00000025u, 0x00000542u, + 0x000003bau, 0x0000018du, 0x000300f7u, 0x00000571u, 0x00000000u, 0x000400fau, 0x00000542u, 0x00000543u, + 0x00000571u, 0x000200f8u, 0x00000543u, 0x00050080u, 0x00000006u, 0x0000054cu, 0x00000154u, 0x000004f0u, + 0x0004007cu, 0x00000016u, 0x0000054du, 0x0000054cu, 0x00050050u, 0x00000017u, 0x0000054eu, 0x000004edu, + 0x0000054du, 0x0004003du, 0x000000aeu, 0x0000054fu, 0x000000b0u, 0x00050080u, 0x00000017u, 0x00000552u, + 0x00000469u, 0x0000054eu, 0x000500b1u, 0x0000005eu, 0x000006deu, 0x00000552u, 0x0000005du, 0x000600a9u, + 0x00000017u, 0x000006dfu, 0x000006deu, 0x00000060u, 0x0000005du, 0x00050082u, 0x00000017u, 0x000006e1u, + 0x00000552u, 0x000006dfu, 0x00050080u, 0x00000017u, 0x000006e4u, 0x000006e1u, 0x00000060u, 0x00050080u, + 0x00000017u, 0x000006f4u, 0x000006e4u, 0x000005a3u, 0x00050080u, 0x00000017u, 0x000006f6u, 0x000006f4u, + 0x00000060u, 0x0007000cu, 0x00000017u, 0x000006fau, 0x00000001u, 0x00000027u, 0x000006e4u, 0x0000059au, + 0x000500afu, 0x0000005eu, 0x000006feu, 0x000006e4u, 0x0000059bu, 0x000600a9u, 0x00000017u, 0x000006ffu, + 0x000006feu, 0x000006f6u, 0x000006fau, 0x0004006fu, 0x00000009u, 0x00000701u, 0x000006ffu, 0x00050085u, + 0x00000009u, 0x00000704u, 0x00000701u, 0x000005b3u, 0x00060060u, 0x000000aau, 0x00000554u, 0x0000054fu, + 0x00000704u, 0x00000042u, 0x0009004fu, 0x000000aau, 0x00000555u, 0x00000554u, 0x00000554u, 0x00000003u, + 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, 0x0000055au, 0x00000000u, 0x000400fau, 0x000000d3u, + 0x00000556u, 0x0000055au, 0x000200f8u, 0x00000556u, 0x00050083u, 0x000000aau, 0x00000559u, 0x00000555u, + 0x00000a2fu, 0x000200f9u, 0x0000055au, 0x000200f8u, 0x0000055au, 0x000700f5u, 0x000000aau, 0x00000a17u, + 0x00000555u, 0x00000543u, 0x00000559u, 0x00000556u, 0x000500c3u, 0x00000016u, 0x0000055du, 0x0000054du, + 0x00000043u, 0x0004007cu, 0x00000006u, 0x0000055eu, 0x0000055du, 0x0007004fu, 0x00000009u, 0x00000564u, + 0x00000a17u, 0x00000a17u, 0x00000000u, 0x00000002u, 0x0006000cu, 0x00000006u, 0x00000709u, 0x00000001u, + 0x0000003au, 0x00000564u, 0x00060041u, 0x00000035u, 0x0000070au, 0x00000032u, 0x0000055eu, 0x000004ecu, + 0x0003003eu, 0x0000070au, 0x00000709u, 0x0007004fu, 0x00000009u, 0x0000056fu, 0x00000a17u, 0x00000a17u, + 0x00000001u, 0x00000003u, 0x0006000cu, 0x00000006u, 0x0000070fu, 0x00000001u, 0x0000003au, 0x0000056fu, + 0x00060041u, 0x00000035u, 0x00000710u, 0x00000032u, 0x0000055eu, 0x00000511u, 0x0003003eu, 0x00000710u, + 0x0000070fu, 0x000200f9u, 0x00000571u, 0x000200f8u, 0x00000571u, 0x000400e0u, 0x00000155u, 0x00000155u, + 0x0000028du, 0x00050084u, 0x00000006u, 0x0000072au, 0x000001fcu, 0x000004eau, 0x0004007cu, 0x00000016u, + 0x0000072bu, 0x0000072au, 0x0004007cu, 0x00000016u, 0x0000072eu, 0x000004efu, 0x000200f9u, 0x00000730u, + 0x000200f8u, 0x00000730u, 0x000700f5u, 0x00000016u, 0x00000a18u, 0x00000042u, 0x00000571u, 0x00000743u, + 0x00000734u, 0x000500b1u, 0x00000025u, 0x00000733u, 0x00000a18u, 0x000000bau, 0x000400f6u, 0x00000744u, + 0x00000734u, 0x00000000u, 0x000400fau, 0x00000733u, 0x00000734u, 0x00000744u, 0x000200f8u, 0x00000734u, + 0x00050080u, 0x00000016u, 0x0000073bu, 0x0000072bu, 0x00000a18u, 0x0004007cu, 0x00000006u, 0x0000073cu, + 0x0000073bu, 0x00060041u, 0x00000035u, 0x000007e2u, 0x00000032u, 0x000004efu, 0x0000073cu, 0x0004003du, + 0x00000006u, 0x000007e3u, 0x000007e2u, 0x0006000cu, 0x00000009u, 0x000007e4u, 0x00000001u, 0x0000003eu, + 0x000007e3u, 0x00050041u, 0x0000000fu, 0x00000740u, 0x00000716u, 0x00000a18u, 0x0003003eu, 0x00000740u, + 0x000007e4u, 0x00050080u, 0x00000016u, 0x00000743u, 0x00000a18u, 0x00000043u, 0x000200f9u, 0x00000730u, + 0x000200f8u, 0x00000744u, 0x000200f9u, 0x00000745u, 0x000200f8u, 0x00000745u, 0x000700f5u, 0x00000016u, + 0x00000a19u, 0x00000043u, 0x00000744u, 0x0000075bu, 0x00000749u, 0x000500b1u, 0x00000025u, 0x00000748u, + 0x00000a19u, 0x00000228u, 0x000400f6u, 0x0000075cu, 0x00000749u, 0x00000000u, 0x000400fau, 0x00000748u, + 0x00000749u, 0x0000075cu, 0x000200f8u, 0x00000749u, 0x00050082u, 0x00000016u, 0x0000074cu, 0x00000a19u, + 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000074du, 0x00000716u, 0x0000074cu, 0x0004003du, 0x00000009u, + 0x0000074eu, 0x0000074du, 0x00050080u, 0x00000016u, 0x00000750u, 0x00000a19u, 0x00000043u, 0x00050041u, + 0x0000000fu, 0x00000751u, 0x00000716u, 0x00000750u, 0x0004003du, 0x00000009u, 0x00000752u, 0x00000751u, + 0x00050081u, 0x00000009u, 0x00000753u, 0x0000074eu, 0x00000752u, 0x0005008eu, 0x00000009u, 0x00000754u, + 0x00000753u, 0x0000022bu, 0x00050041u, 0x0000000fu, 0x00000755u, 0x00000716u, 0x00000a19u, 0x0004003du, + 0x00000009u, 0x00000756u, 0x00000755u, 0x00050081u, 0x00000009u, 0x00000757u, 0x00000756u, 0x00000754u, + 0x0003003eu, 0x00000755u, 0x00000757u, 0x00050080u, 0x00000016u, 0x0000075bu, 0x00000a19u, 0x00000047u, + 0x000200f9u, 0x00000745u, 0x000200f8u, 0x0000075cu, 0x000200f9u, 0x0000075du, 0x000200f8u, 0x0000075du, + 0x000700f5u, 0x00000016u, 0x00000a1au, 0x00000047u, 0x0000075cu, 0x00000773u, 0x00000761u, 0x000500b1u, + 0x00000025u, 0x00000760u, 0x00000a1au, 0x00000243u, 0x000400f6u, 0x00000774u, 0x00000761u, 0x00000000u, + 0x000400fau, 0x00000760u, 0x00000761u, 0x00000774u, 0x000200f8u, 0x00000761u, 0x00050082u, 0x00000016u, + 0x00000764u, 0x00000a1au, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000765u, 0x00000716u, 0x00000764u, + 0x0004003du, 0x00000009u, 0x00000766u, 0x00000765u, 0x00050080u, 0x00000016u, 0x00000768u, 0x00000a1au, + 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000769u, 0x00000716u, 0x00000768u, 0x0004003du, 0x00000009u, + 0x0000076au, 0x00000769u, 0x00050081u, 0x00000009u, 0x0000076bu, 0x00000766u, 0x0000076au, 0x0005008eu, + 0x00000009u, 0x0000076cu, 0x0000076bu, 0x00000246u, 0x00050041u, 0x0000000fu, 0x0000076du, 0x00000716u, + 0x00000a1au, 0x0004003du, 0x00000009u, 0x0000076eu, 0x0000076du, 0x00050081u, 0x00000009u, 0x0000076fu, + 0x0000076eu, 0x0000076cu, 0x0003003eu, 0x0000076du, 0x0000076fu, 0x00050080u, 0x00000016u, 0x00000773u, + 0x00000a1au, 0x00000047u, 0x000200f9u, 0x0000075du, 0x000200f8u, 0x00000774u, 0x000200f9u, 0x00000775u, + 0x000200f8u, 0x00000775u, 0x000700f5u, 0x00000016u, 0x00000a1bu, 0x0000004au, 0x00000774u, 0x0000078bu, + 0x00000779u, 0x000500b1u, 0x00000025u, 0x00000778u, 0x00000a1bu, 0x0000025eu, 0x000400f6u, 0x0000078cu, + 0x00000779u, 0x00000000u, 0x000400fau, 0x00000778u, 0x00000779u, 0x0000078cu, 0x000200f8u, 0x00000779u, + 0x00050082u, 0x00000016u, 0x0000077cu, 0x00000a1bu, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000077du, + 0x00000716u, 0x0000077cu, 0x0004003du, 0x00000009u, 0x0000077eu, 0x0000077du, 0x00050080u, 0x00000016u, + 0x00000780u, 0x00000a1bu, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000781u, 0x00000716u, 0x00000780u, + 0x0004003du, 0x00000009u, 0x00000782u, 0x00000781u, 0x00050081u, 0x00000009u, 0x00000783u, 0x0000077eu, + 0x00000782u, 0x0005008eu, 0x00000009u, 0x00000784u, 0x00000783u, 0x00000261u, 0x00050041u, 0x0000000fu, + 0x00000785u, 0x00000716u, 0x00000a1bu, 0x0004003du, 0x00000009u, 0x00000786u, 0x00000785u, 0x00050081u, + 0x00000009u, 0x00000787u, 0x00000786u, 0x00000784u, 0x0003003eu, 0x00000785u, 0x00000787u, 0x00050080u, + 0x00000016u, 0x0000078bu, 0x00000a1bu, 0x00000047u, 0x000200f9u, 0x00000775u, 0x000200f8u, 0x0000078cu, + 0x000200f9u, 0x0000078du, 0x000200f8u, 0x0000078du, 0x000700f5u, 0x00000016u, 0x00000a1cu, 0x0000009bu, + 0x0000078cu, 0x000007a3u, 0x00000791u, 0x000500b1u, 0x00000025u, 0x00000790u, 0x00000a1cu, 0x00000279u, + 0x000400f6u, 0x000007a4u, 0x00000791u, 0x00000000u, 0x000400fau, 0x00000790u, 0x00000791u, 0x000007a4u, + 0x000200f8u, 0x00000791u, 0x00050082u, 0x00000016u, 0x00000794u, 0x00000a1cu, 0x00000043u, 0x00050041u, + 0x0000000fu, 0x00000795u, 0x00000716u, 0x00000794u, 0x0004003du, 0x00000009u, 0x00000796u, 0x00000795u, + 0x00050080u, 0x00000016u, 0x00000798u, 0x00000a1cu, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000799u, + 0x00000716u, 0x00000798u, 0x0004003du, 0x00000009u, 0x0000079au, 0x00000799u, 0x00050081u, 0x00000009u, + 0x0000079bu, 0x00000796u, 0x0000079au, 0x0005008eu, 0x00000009u, 0x0000079cu, 0x0000079bu, 0x0000027cu, + 0x00050041u, 0x0000000fu, 0x0000079du, 0x00000716u, 0x00000a1cu, 0x0004003du, 0x00000009u, 0x0000079eu, + 0x0000079du, 0x00050081u, 0x00000009u, 0x0000079fu, 0x0000079eu, 0x0000079cu, 0x0003003eu, 0x0000079du, + 0x0000079fu, 0x00050080u, 0x00000016u, 0x000007a3u, 0x00000a1cu, 0x00000047u, 0x000200f9u, 0x0000078du, + 0x000200f8u, 0x000007a4u, 0x000400e0u, 0x00000155u, 0x00000155u, 0x0000028du, 0x000200f9u, 0x000007a5u, + 0x000200f8u, 0x000007a5u, 0x000700f5u, 0x00000016u, 0x00000a1du, 0x00000047u, 0x000007a4u, 0x000007dcu, + 0x000007a9u, 0x000500b1u, 0x00000025u, 0x000007a8u, 0x00000a1du, 0x00000295u, 0x000400f6u, 0x000007ddu, + 0x000007a9u, 0x00000000u, 0x000400fau, 0x000007a8u, 0x000007a9u, 0x000007ddu, 0x000200f8u, 0x000007a9u, + 0x00050084u, 0x00000016u, 0x000007abu, 0x00000047u, 0x00000a1du, 0x00050041u, 0x0000000fu, 0x000007adu, + 0x00000716u, 0x000007abu, 0x0004003du, 0x00000009u, 0x000007aeu, 0x000007adu, 0x00050080u, 0x00000016u, + 0x000007b1u, 0x000007abu, 0x00000043u, 0x00050041u, 0x0000000fu, 0x000007b2u, 0x00000716u, 0x000007b1u, + 0x0004003du, 0x00000009u, 0x000007b3u, 0x000007b2u, 0x0005008eu, 0x00000009u, 0x000007b5u, 0x000007aeu, + 0x000002a3u, 0x0005008eu, 0x00000009u, 0x000007b7u, 0x000007b3u, 0x000002a6u, 0x00050051u, 0x00000008u, + 0x000007b9u, 0x000007b5u, 0x00000000u, 0x00050051u, 0x00000008u, 0x000007bbu, 0x000007b7u, 0x00000000u, + 0x00050050u, 0x00000009u, 0x000007bcu, 0x000007b9u, 0x000007bbu, 0x00050051u, 0x00000008u, 0x000007beu, + 0x000007b5u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000007c0u, 0x000007b7u, 0x00000001u, 0x00050050u, + 0x00000009u, 0x000007c1u, 0x000007beu, 0x000007c0u, 0x000500c3u, 0x00000016u, 0x000007c4u, 0x0000072bu, + 0x00000043u, 0x00050082u, 0x00000016u, 0x000007c6u, 0x00000a1du, 0x00000047u, 0x00050080u, 0x00000016u, + 0x000007c7u, 0x000007c4u, 0x000007c6u, 0x0004007cu, 0x00000006u, 0x000007c9u, 0x000007c7u, 0x00050084u, + 0x00000016u, 0x000007ccu, 0x00000047u, 0x0000072eu, 0x0004007cu, 0x00000006u, 0x000007ceu, 0x000007ccu, + 0x0006000cu, 0x00000006u, 0x000007e9u, 0x00000001u, 0x0000003au, 0x000007bcu, 0x00060041u, 0x00000035u, + 0x000007eau, 0x00000032u, 0x000007c9u, 0x000007ceu, 0x0003003eu, 0x000007eau, 0x000007e9u, 0x00050080u, + 0x00000016u, 0x000007d6u, 0x000007ccu, 0x00000043u, 0x0004007cu, 0x00000006u, 0x000007d7u, 0x000007d6u, + 0x0006000cu, 0x00000006u, 0x000007efu, 0x00000001u, 0x0000003au, 0x000007c1u, 0x00060041u, 0x00000035u, + 0x000007f0u, 0x00000032u, 0x000007c9u, 0x000007d7u, 0x0003003eu, 0x000007f0u, 0x000007efu, 0x00050080u, + 0x00000016u, 0x000007dcu, 0x00000a1du, 0x00000043u, 0x000200f9u, 0x000007a5u, 0x000200f8u, 0x000007ddu, + 0x000500b0u, 0x00000025u, 0x000003beu, 0x000003bau, 0x00000154u, 0x00050089u, 0x00000006u, 0x00000809u, + 0x000003bau, 0x000001fcu, 0x00050084u, 0x00000006u, 0x0000080au, 0x00000157u, 0x00000809u, 0x0004007cu, + 0x00000016u, 0x0000080bu, 0x0000080au, 0x00050086u, 0x00000006u, 0x0000080du, 0x000003bau, 0x000001fcu, + 0x00050080u, 0x00000006u, 0x00000810u, 0x0000080du, 0x0000018du, 0x0004007cu, 0x00000016u, 0x00000811u, + 0x00000810u, 0x000300f7u, 0x0000088au, 0x00000000u, 0x000400fau, 0x000003beu, 0x00000814u, 0x0000088au, + 0x000200f8u, 0x00000814u, 0x000200f9u, 0x00000815u, 0x000200f8u, 0x00000815u, 0x000700f5u, 0x00000016u, + 0x00000a1eu, 0x00000042u, 0x00000814u, 0x00000828u, 0x00000819u, 0x000500b1u, 0x00000025u, 0x00000818u, + 0x00000a1eu, 0x00000279u, 0x000400f6u, 0x00000829u, 0x00000819u, 0x00000000u, 0x000400fau, 0x00000818u, + 0x00000819u, 0x00000829u, 0x000200f8u, 0x00000819u, 0x00050080u, 0x00000016u, 0x00000820u, 0x0000080bu, + 0x00000a1eu, 0x0004007cu, 0x00000006u, 0x00000821u, 0x00000820u, 0x00060041u, 0x00000035u, 0x000008cbu, + 0x00000032u, 0x00000810u, 0x00000821u, 0x0004003du, 0x00000006u, 0x000008ccu, 0x000008cbu, 0x0006000cu, + 0x00000009u, 0x000008cdu, 0x00000001u, 0x0000003eu, 0x000008ccu, 0x00050041u, 0x0000000fu, 0x00000825u, + 0x000007f6u, 0x00000a1eu, 0x0003003eu, 0x00000825u, 0x000008cdu, 0x00050080u, 0x00000016u, 0x00000828u, + 0x00000a1eu, 0x00000043u, 0x000200f9u, 0x00000815u, 0x000200f8u, 0x00000829u, 0x000200f9u, 0x0000082au, + 0x000200f8u, 0x0000082au, 0x000700f5u, 0x00000016u, 0x00000a1fu, 0x00000043u, 0x00000829u, 0x00000840u, + 0x0000082eu, 0x000500b1u, 0x00000025u, 0x0000082du, 0x00000a1fu, 0x0000030au, 0x000400f6u, 0x00000841u, + 0x0000082eu, 0x00000000u, 0x000400fau, 0x0000082du, 0x0000082eu, 0x00000841u, 0x000200f8u, 0x0000082eu, + 0x00050082u, 0x00000016u, 0x00000831u, 0x00000a1fu, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000832u, + 0x000007f6u, 0x00000831u, 0x0004003du, 0x00000009u, 0x00000833u, 0x00000832u, 0x00050080u, 0x00000016u, + 0x00000835u, 0x00000a1fu, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000836u, 0x000007f6u, 0x00000835u, + 0x0004003du, 0x00000009u, 0x00000837u, 0x00000836u, 0x00050081u, 0x00000009u, 0x00000838u, 0x00000833u, + 0x00000837u, 0x0005008eu, 0x00000009u, 0x00000839u, 0x00000838u, 0x0000022bu, 0x00050041u, 0x0000000fu, + 0x0000083au, 0x000007f6u, 0x00000a1fu, 0x0004003du, 0x00000009u, 0x0000083bu, 0x0000083au, 0x00050081u, + 0x00000009u, 0x0000083cu, 0x0000083bu, 0x00000839u, 0x0003003eu, 0x0000083au, 0x0000083cu, 0x00050080u, + 0x00000016u, 0x00000840u, 0x00000a1fu, 0x00000047u, 0x000200f9u, 0x0000082au, 0x000200f8u, 0x00000841u, + 0x000200f9u, 0x00000842u, 0x000200f8u, 0x00000842u, 0x000700f5u, 0x00000016u, 0x00000a20u, 0x00000047u, + 0x00000841u, 0x00000858u, 0x00000846u, 0x000500b1u, 0x00000025u, 0x00000845u, 0x00000a20u, 0x00000324u, + 0x000400f6u, 0x00000859u, 0x00000846u, 0x00000000u, 0x000400fau, 0x00000845u, 0x00000846u, 0x00000859u, + 0x000200f8u, 0x00000846u, 0x00050082u, 0x00000016u, 0x00000849u, 0x00000a20u, 0x00000043u, 0x00050041u, + 0x0000000fu, 0x0000084au, 0x000007f6u, 0x00000849u, 0x0004003du, 0x00000009u, 0x0000084bu, 0x0000084au, + 0x00050080u, 0x00000016u, 0x0000084du, 0x00000a20u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000084eu, + 0x000007f6u, 0x0000084du, 0x0004003du, 0x00000009u, 0x0000084fu, 0x0000084eu, 0x00050081u, 0x00000009u, + 0x00000850u, 0x0000084bu, 0x0000084fu, 0x0005008eu, 0x00000009u, 0x00000851u, 0x00000850u, 0x00000246u, + 0x00050041u, 0x0000000fu, 0x00000852u, 0x000007f6u, 0x00000a20u, 0x0004003du, 0x00000009u, 0x00000853u, + 0x00000852u, 0x00050081u, 0x00000009u, 0x00000854u, 0x00000853u, 0x00000851u, 0x0003003eu, 0x00000852u, + 0x00000854u, 0x00050080u, 0x00000016u, 0x00000858u, 0x00000a20u, 0x00000047u, 0x000200f9u, 0x00000842u, + 0x000200f8u, 0x00000859u, 0x000200f9u, 0x0000085au, 0x000200f8u, 0x0000085au, 0x000700f5u, 0x00000016u, + 0x00000a21u, 0x0000004au, 0x00000859u, 0x00000870u, 0x0000085eu, 0x000500b1u, 0x00000025u, 0x0000085du, + 0x00000a21u, 0x0000033eu, 0x000400f6u, 0x00000871u, 0x0000085eu, 0x00000000u, 0x000400fau, 0x0000085du, + 0x0000085eu, 0x00000871u, 0x000200f8u, 0x0000085eu, 0x00050082u, 0x00000016u, 0x00000861u, 0x00000a21u, + 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000862u, 0x000007f6u, 0x00000861u, 0x0004003du, 0x00000009u, + 0x00000863u, 0x00000862u, 0x00050080u, 0x00000016u, 0x00000865u, 0x00000a21u, 0x00000043u, 0x00050041u, + 0x0000000fu, 0x00000866u, 0x000007f6u, 0x00000865u, 0x0004003du, 0x00000009u, 0x00000867u, 0x00000866u, + 0x00050081u, 0x00000009u, 0x00000868u, 0x00000863u, 0x00000867u, 0x0005008eu, 0x00000009u, 0x00000869u, + 0x00000868u, 0x00000261u, 0x00050041u, 0x0000000fu, 0x0000086au, 0x000007f6u, 0x00000a21u, 0x0004003du, + 0x00000009u, 0x0000086bu, 0x0000086au, 0x00050081u, 0x00000009u, 0x0000086cu, 0x0000086bu, 0x00000869u, + 0x0003003eu, 0x0000086au, 0x0000086cu, 0x00050080u, 0x00000016u, 0x00000870u, 0x00000a21u, 0x00000047u, + 0x000200f9u, 0x0000085au, 0x000200f8u, 0x00000871u, 0x000200f9u, 0x00000872u, 0x000200f8u, 0x00000872u, + 0x000700f5u, 0x00000016u, 0x00000a22u, 0x0000009bu, 0x00000871u, 0x00000888u, 0x00000876u, 0x000500b1u, + 0x00000025u, 0x00000875u, 0x00000a22u, 0x0000011fu, 0x000400f6u, 0x00000889u, 0x00000876u, 0x00000000u, + 0x000400fau, 0x00000875u, 0x00000876u, 0x00000889u, 0x000200f8u, 0x00000876u, 0x00050082u, 0x00000016u, + 0x00000879u, 0x00000a22u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000087au, 0x000007f6u, 0x00000879u, + 0x0004003du, 0x00000009u, 0x0000087bu, 0x0000087au, 0x00050080u, 0x00000016u, 0x0000087du, 0x00000a22u, + 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000087eu, 0x000007f6u, 0x0000087du, 0x0004003du, 0x00000009u, + 0x0000087fu, 0x0000087eu, 0x00050081u, 0x00000009u, 0x00000880u, 0x0000087bu, 0x0000087fu, 0x0005008eu, + 0x00000009u, 0x00000881u, 0x00000880u, 0x0000027cu, 0x00050041u, 0x0000000fu, 0x00000882u, 0x000007f6u, + 0x00000a22u, 0x0004003du, 0x00000009u, 0x00000883u, 0x00000882u, 0x00050081u, 0x00000009u, 0x00000884u, + 0x00000883u, 0x00000881u, 0x0003003eu, 0x00000882u, 0x00000884u, 0x00050080u, 0x00000016u, 0x00000888u, + 0x00000a22u, 0x00000047u, 0x000200f9u, 0x00000872u, 0x000200f8u, 0x00000889u, 0x000200f9u, 0x0000088au, + 0x000200f8u, 0x0000088au, 0x000400e0u, 0x00000155u, 0x00000155u, 0x0000028du, 0x000300f7u, 0x000008c6u, + 0x00000000u, 0x000400fau, 0x000003beu, 0x0000088cu, 0x000008c6u, 0x000200f8u, 0x0000088cu, 0x000200f9u, + 0x0000088du, 0x000200f8u, 0x0000088du, 0x000700f5u, 0x00000016u, 0x00000a23u, 0x00000047u, 0x0000088cu, + 0x000008c4u, 0x00000891u, 0x000500b1u, 0x00000025u, 0x00000890u, 0x00000a23u, 0x0000009bu, 0x000400f6u, + 0x000008c5u, 0x00000891u, 0x00000000u, 0x000400fau, 0x00000890u, 0x00000891u, 0x000008c5u, 0x000200f8u, + 0x00000891u, 0x00050084u, 0x00000016u, 0x00000893u, 0x00000047u, 0x00000a23u, 0x00050041u, 0x0000000fu, + 0x00000895u, 0x000007f6u, 0x00000893u, 0x0004003du, 0x00000009u, 0x00000896u, 0x00000895u, 0x00050080u, + 0x00000016u, 0x00000899u, 0x00000893u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000089au, 0x000007f6u, + 0x00000899u, 0x0004003du, 0x00000009u, 0x0000089bu, 0x0000089au, 0x0005008eu, 0x00000009u, 0x0000089du, + 0x00000896u, 0x000002a3u, 0x0005008eu, 0x00000009u, 0x0000089fu, 0x0000089bu, 0x000002a6u, 0x00050051u, + 0x00000008u, 0x000008a1u, 0x0000089du, 0x00000000u, 0x00050051u, 0x00000008u, 0x000008a3u, 0x0000089fu, + 0x00000000u, 0x00050050u, 0x00000009u, 0x000008a4u, 0x000008a1u, 0x000008a3u, 0x00050051u, 0x00000008u, + 0x000008a6u, 0x0000089du, 0x00000001u, 0x00050051u, 0x00000008u, 0x000008a8u, 0x0000089fu, 0x00000001u, + 0x00050050u, 0x00000009u, 0x000008a9u, 0x000008a6u, 0x000008a8u, 0x000500c3u, 0x00000016u, 0x000008acu, + 0x0000080bu, 0x00000043u, 0x00050082u, 0x00000016u, 0x000008aeu, 0x00000a23u, 0x00000047u, 0x00050080u, + 0x00000016u, 0x000008afu, 0x000008acu, 0x000008aeu, 0x0004007cu, 0x00000006u, 0x000008b1u, 0x000008afu, + 0x00050084u, 0x00000016u, 0x000008b4u, 0x00000047u, 0x00000811u, 0x0004007cu, 0x00000006u, 0x000008b6u, + 0x000008b4u, 0x0006000cu, 0x00000006u, 0x000008d2u, 0x00000001u, 0x0000003au, 0x000008a4u, 0x00060041u, + 0x00000035u, 0x000008d3u, 0x00000032u, 0x000008b1u, 0x000008b6u, 0x0003003eu, 0x000008d3u, 0x000008d2u, + 0x00050080u, 0x00000016u, 0x000008beu, 0x000008b4u, 0x00000043u, 0x0004007cu, 0x00000006u, 0x000008bfu, + 0x000008beu, 0x0006000cu, 0x00000006u, 0x000008d8u, 0x00000001u, 0x0000003au, 0x000008a9u, 0x00060041u, + 0x00000035u, 0x000008d9u, 0x00000032u, 0x000008b1u, 0x000008bfu, 0x0003003eu, 0x000008d9u, 0x000008d8u, + 0x00050080u, 0x00000016u, 0x000008c4u, 0x00000a23u, 0x00000043u, 0x000200f9u, 0x0000088du, 0x000200f8u, + 0x000008c5u, 0x000200f9u, 0x000008c6u, 0x000200f8u, 0x000008c6u, 0x000400e0u, 0x00000155u, 0x00000155u, + 0x0000028du, 0x000200f9u, 0x000008f9u, 0x000200f8u, 0x000008f9u, 0x000700f5u, 0x00000016u, 0x00000a24u, + 0x00000042u, 0x000008c6u, 0x0000090cu, 0x000008fdu, 0x000500b1u, 0x00000025u, 0x000008fcu, 0x00000a24u, + 0x000000bau, 0x000400f6u, 0x0000090du, 0x000008fdu, 0x00000000u, 0x000400fau, 0x000008fcu, 0x000008fdu, + 0x0000090du, 0x000200f8u, 0x000008fdu, 0x00050080u, 0x00000016u, 0x00000904u, 0x0000072bu, 0x00000a24u, + 0x0004007cu, 0x00000006u, 0x00000905u, 0x00000904u, 0x00060041u, 0x00000035u, 0x000009abu, 0x00000032u, + 0x000004efu, 0x00000905u, 0x0004003du, 0x00000006u, 0x000009acu, 0x000009abu, 0x0006000cu, 0x00000009u, + 0x000009adu, 0x00000001u, 0x0000003eu, 0x000009acu, 0x00050041u, 0x0000000fu, 0x00000909u, 0x000008dfu, + 0x00000a24u, 0x0003003eu, 0x00000909u, 0x000009adu, 0x00050080u, 0x00000016u, 0x0000090cu, 0x00000a24u, + 0x00000043u, 0x000200f9u, 0x000008f9u, 0x000200f8u, 0x0000090du, 0x000200f9u, 0x0000090eu, 0x000200f8u, + 0x0000090eu, 0x000700f5u, 0x00000016u, 0x00000a25u, 0x00000043u, 0x0000090du, 0x00000924u, 0x00000912u, + 0x000500b1u, 0x00000025u, 0x00000911u, 0x00000a25u, 0x00000228u, 0x000400f6u, 0x00000925u, 0x00000912u, + 0x00000000u, 0x000400fau, 0x00000911u, 0x00000912u, 0x00000925u, 0x000200f8u, 0x00000912u, 0x00050082u, + 0x00000016u, 0x00000915u, 0x00000a25u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000916u, 0x000008dfu, + 0x00000915u, 0x0004003du, 0x00000009u, 0x00000917u, 0x00000916u, 0x00050080u, 0x00000016u, 0x00000919u, + 0x00000a25u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000091au, 0x000008dfu, 0x00000919u, 0x0004003du, + 0x00000009u, 0x0000091bu, 0x0000091au, 0x00050081u, 0x00000009u, 0x0000091cu, 0x00000917u, 0x0000091bu, + 0x0005008eu, 0x00000009u, 0x0000091du, 0x0000091cu, 0x0000022bu, 0x00050041u, 0x0000000fu, 0x0000091eu, + 0x000008dfu, 0x00000a25u, 0x0004003du, 0x00000009u, 0x0000091fu, 0x0000091eu, 0x00050081u, 0x00000009u, + 0x00000920u, 0x0000091fu, 0x0000091du, 0x0003003eu, 0x0000091eu, 0x00000920u, 0x00050080u, 0x00000016u, + 0x00000924u, 0x00000a25u, 0x00000047u, 0x000200f9u, 0x0000090eu, 0x000200f8u, 0x00000925u, 0x000200f9u, + 0x00000926u, 0x000200f8u, 0x00000926u, 0x000700f5u, 0x00000016u, 0x00000a26u, 0x00000047u, 0x00000925u, + 0x0000093cu, 0x0000092au, 0x000500b1u, 0x00000025u, 0x00000929u, 0x00000a26u, 0x00000243u, 0x000400f6u, + 0x0000093du, 0x0000092au, 0x00000000u, 0x000400fau, 0x00000929u, 0x0000092au, 0x0000093du, 0x000200f8u, + 0x0000092au, 0x00050082u, 0x00000016u, 0x0000092du, 0x00000a26u, 0x00000043u, 0x00050041u, 0x0000000fu, + 0x0000092eu, 0x000008dfu, 0x0000092du, 0x0004003du, 0x00000009u, 0x0000092fu, 0x0000092eu, 0x00050080u, + 0x00000016u, 0x00000931u, 0x00000a26u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000932u, 0x000008dfu, + 0x00000931u, 0x0004003du, 0x00000009u, 0x00000933u, 0x00000932u, 0x00050081u, 0x00000009u, 0x00000934u, + 0x0000092fu, 0x00000933u, 0x0005008eu, 0x00000009u, 0x00000935u, 0x00000934u, 0x00000246u, 0x00050041u, + 0x0000000fu, 0x00000936u, 0x000008dfu, 0x00000a26u, 0x0004003du, 0x00000009u, 0x00000937u, 0x00000936u, + 0x00050081u, 0x00000009u, 0x00000938u, 0x00000937u, 0x00000935u, 0x0003003eu, 0x00000936u, 0x00000938u, + 0x00050080u, 0x00000016u, 0x0000093cu, 0x00000a26u, 0x00000047u, 0x000200f9u, 0x00000926u, 0x000200f8u, + 0x0000093du, 0x000200f9u, 0x0000093eu, 0x000200f8u, 0x0000093eu, 0x000700f5u, 0x00000016u, 0x00000a27u, + 0x0000004au, 0x0000093du, 0x00000954u, 0x00000942u, 0x000500b1u, 0x00000025u, 0x00000941u, 0x00000a27u, + 0x0000025eu, 0x000400f6u, 0x00000955u, 0x00000942u, 0x00000000u, 0x000400fau, 0x00000941u, 0x00000942u, + 0x00000955u, 0x000200f8u, 0x00000942u, 0x00050082u, 0x00000016u, 0x00000945u, 0x00000a27u, 0x00000043u, + 0x00050041u, 0x0000000fu, 0x00000946u, 0x000008dfu, 0x00000945u, 0x0004003du, 0x00000009u, 0x00000947u, + 0x00000946u, 0x00050080u, 0x00000016u, 0x00000949u, 0x00000a27u, 0x00000043u, 0x00050041u, 0x0000000fu, + 0x0000094au, 0x000008dfu, 0x00000949u, 0x0004003du, 0x00000009u, 0x0000094bu, 0x0000094au, 0x00050081u, + 0x00000009u, 0x0000094cu, 0x00000947u, 0x0000094bu, 0x0005008eu, 0x00000009u, 0x0000094du, 0x0000094cu, + 0x00000261u, 0x00050041u, 0x0000000fu, 0x0000094eu, 0x000008dfu, 0x00000a27u, 0x0004003du, 0x00000009u, + 0x0000094fu, 0x0000094eu, 0x00050081u, 0x00000009u, 0x00000950u, 0x0000094fu, 0x0000094du, 0x0003003eu, + 0x0000094eu, 0x00000950u, 0x00050080u, 0x00000016u, 0x00000954u, 0x00000a27u, 0x00000047u, 0x000200f9u, + 0x0000093eu, 0x000200f8u, 0x00000955u, 0x000200f9u, 0x00000956u, 0x000200f8u, 0x00000956u, 0x000700f5u, + 0x00000016u, 0x00000a28u, 0x0000009bu, 0x00000955u, 0x0000096cu, 0x0000095au, 0x000500b1u, 0x00000025u, + 0x00000959u, 0x00000a28u, 0x00000279u, 0x000400f6u, 0x0000096du, 0x0000095au, 0x00000000u, 0x000400fau, + 0x00000959u, 0x0000095au, 0x0000096du, 0x000200f8u, 0x0000095au, 0x00050082u, 0x00000016u, 0x0000095du, + 0x00000a28u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000095eu, 0x000008dfu, 0x0000095du, 0x0004003du, + 0x00000009u, 0x0000095fu, 0x0000095eu, 0x00050080u, 0x00000016u, 0x00000961u, 0x00000a28u, 0x00000043u, + 0x00050041u, 0x0000000fu, 0x00000962u, 0x000008dfu, 0x00000961u, 0x0004003du, 0x00000009u, 0x00000963u, + 0x00000962u, 0x00050081u, 0x00000009u, 0x00000964u, 0x0000095fu, 0x00000963u, 0x0005008eu, 0x00000009u, + 0x00000965u, 0x00000964u, 0x0000027cu, 0x00050041u, 0x0000000fu, 0x00000966u, 0x000008dfu, 0x00000a28u, + 0x0004003du, 0x00000009u, 0x00000967u, 0x00000966u, 0x00050081u, 0x00000009u, 0x00000968u, 0x00000967u, + 0x00000965u, 0x0003003eu, 0x00000966u, 0x00000968u, 0x00050080u, 0x00000016u, 0x0000096cu, 0x00000a28u, + 0x00000047u, 0x000200f9u, 0x00000956u, 0x000200f8u, 0x0000096du, 0x000400e0u, 0x00000155u, 0x00000155u, + 0x0000028du, 0x000200f9u, 0x0000096eu, 0x000200f8u, 0x0000096eu, 0x000700f5u, 0x00000016u, 0x00000a29u, + 0x00000047u, 0x0000096du, 0x000009a5u, 0x00000972u, 0x000500b1u, 0x00000025u, 0x00000971u, 0x00000a29u, + 0x00000295u, 0x000400f6u, 0x000009a6u, 0x00000972u, 0x00000000u, 0x000400fau, 0x00000971u, 0x00000972u, + 0x000009a6u, 0x000200f8u, 0x00000972u, 0x00050084u, 0x00000016u, 0x00000974u, 0x00000047u, 0x00000a29u, + 0x00050041u, 0x0000000fu, 0x00000976u, 0x000008dfu, 0x00000974u, 0x0004003du, 0x00000009u, 0x00000977u, + 0x00000976u, 0x00050080u, 0x00000016u, 0x0000097au, 0x00000974u, 0x00000043u, 0x00050041u, 0x0000000fu, + 0x0000097bu, 0x000008dfu, 0x0000097au, 0x0004003du, 0x00000009u, 0x0000097cu, 0x0000097bu, 0x0005008eu, + 0x00000009u, 0x0000097eu, 0x00000977u, 0x000002a3u, 0x0005008eu, 0x00000009u, 0x00000980u, 0x0000097cu, + 0x000002a6u, 0x00050051u, 0x00000008u, 0x00000982u, 0x0000097eu, 0x00000000u, 0x00050051u, 0x00000008u, + 0x00000984u, 0x00000980u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000985u, 0x00000982u, 0x00000984u, + 0x00050051u, 0x00000008u, 0x00000987u, 0x0000097eu, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000989u, + 0x00000980u, 0x00000001u, 0x00050050u, 0x00000009u, 0x0000098au, 0x00000987u, 0x00000989u, 0x000500c3u, + 0x00000016u, 0x0000098du, 0x0000072bu, 0x00000043u, 0x00050082u, 0x00000016u, 0x0000098fu, 0x00000a29u, + 0x00000047u, 0x00050080u, 0x00000016u, 0x00000990u, 0x0000098du, 0x0000098fu, 0x0004007cu, 0x00000006u, + 0x00000992u, 0x00000990u, 0x00050084u, 0x00000016u, 0x00000995u, 0x00000047u, 0x0000072eu, 0x0004007cu, + 0x00000006u, 0x00000997u, 0x00000995u, 0x0006000cu, 0x00000006u, 0x000009b2u, 0x00000001u, 0x0000003au, + 0x00000985u, 0x00060041u, 0x00000035u, 0x000009b3u, 0x00000032u, 0x00000992u, 0x00000997u, 0x0003003eu, + 0x000009b3u, 0x000009b2u, 0x00050080u, 0x00000016u, 0x0000099fu, 0x00000995u, 0x00000043u, 0x0004007cu, + 0x00000006u, 0x000009a0u, 0x0000099fu, 0x0006000cu, 0x00000006u, 0x000009b8u, 0x00000001u, 0x0000003au, + 0x0000098au, 0x00060041u, 0x00000035u, 0x000009b9u, 0x00000032u, 0x00000992u, 0x000009a0u, 0x0003003eu, + 0x000009b9u, 0x000009b8u, 0x00050080u, 0x00000016u, 0x000009a5u, 0x00000a29u, 0x00000043u, 0x000200f9u, + 0x0000096eu, 0x000200f8u, 0x000009a6u, 0x000400e0u, 0x00000155u, 0x00000155u, 0x0000028du, 0x000200f9u, + 0x000003cau, 0x000200f8u, 0x000003cau, 0x000700f5u, 0x00000016u, 0x00000a2au, 0x00000587u, 0x000009a6u, + 0x00000420u, 0x000003cdu, 0x000500b1u, 0x00000025u, 0x000003d0u, 0x00000a2au, 0x000000bau, 0x000400f6u, + 0x000003ccu, 0x000003cdu, 0x00000000u, 0x000400fau, 0x000003d0u, 0x000003cbu, 0x000003ccu, 0x000200f8u, + 0x000003cbu, 0x00050084u, 0x00000016u, 0x000003d4u, 0x00000585u, 0x00000047u, 0x000200f9u, 0x000003d5u, + 0x000200f8u, 0x000003d5u, 0x000700f5u, 0x00000016u, 0x00000a2bu, 0x000003d4u, 0x000003cbu, 0x0000041eu, + 0x000003d6u, 0x000500b1u, 0x00000025u, 0x000003dbu, 0x00000a2bu, 0x00000098u, 0x000400f6u, 0x000003d7u, + 0x000003d6u, 0x00000000u, 0x000400fau, 0x000003dbu, 0x000003d6u, 0x000003d7u, 0x000200f8u, 0x000003d6u, + 0x0004007cu, 0x00000006u, 0x000003deu, 0x00000a2au, 0x0004007cu, 0x00000006u, 0x000003e1u, 0x00000a2bu, + 0x00060041u, 0x00000035u, 0x000009d5u, 0x00000032u, 0x000003deu, 0x000003e1u, 0x0004003du, 0x00000006u, + 0x000009d6u, 0x000009d5u, 0x0006000cu, 0x00000009u, 0x000009d7u, 0x00000001u, 0x0000003eu, 0x000009d6u, + 0x00050080u, 0x00000016u, 0x000003e9u, 0x00000a2bu, 0x00000043u, 0x0004007cu, 0x00000006u, 0x000003eau, + 0x000003e9u, 0x00060041u, 0x00000035u, 0x000009dcu, 0x00000032u, 0x000003deu, 0x000003eau, 0x0004003du, + 0x00000006u, 0x000009ddu, 0x000009dcu, 0x0006000cu, 0x00000009u, 0x000009deu, 0x00000001u, 0x0000003eu, + 0x000009ddu, 0x000500c3u, 0x00000016u, 0x000003f0u, 0x00000a2bu, 0x00000043u, 0x00050084u, 0x00000017u, + 0x000003f8u, 0x00000466u, 0x000000cdu, 0x00050050u, 0x00000017u, 0x000003fbu, 0x000003f0u, 0x00000a2au, + 0x00050080u, 0x00000017u, 0x000003fcu, 0x000003f8u, 0x000003fbu, 0x0004003du, 0x000003fdu, 0x00000400u, + 0x000003ffu, 0x00050051u, 0x00000016u, 0x00000403u, 0x000003fcu, 0x00000000u, 0x00050051u, 0x00000016u, + 0x00000404u, 0x000003fcu, 0x00000001u, 0x00060050u, 0x00000402u, 0x00000405u, 0x00000403u, 0x00000404u, + 0x00000042u, 0x0009004fu, 0x000000aau, 0x00000407u, 0x000009d7u, 0x000009d7u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00040063u, 0x00000400u, 0x00000405u, 0x00000407u, 0x0004003du, 0x000003fdu, + 0x00000408u, 0x000003ffu, 0x00060050u, 0x00000402u, 0x0000040cu, 0x00000403u, 0x00000404u, 0x00000047u, + 0x0009004fu, 0x000000aau, 0x0000040eu, 0x000009d7u, 0x000009d7u, 0x00000001u, 0x00000001u, 0x00000001u, + 0x00000001u, 0x00040063u, 0x00000408u, 0x0000040cu, 0x0000040eu, 0x0004003du, 0x000003fdu, 0x0000040fu, + 0x000003ffu, 0x00060050u, 0x00000402u, 0x00000413u, 0x00000403u, 0x00000404u, 0x00000043u, 0x0009004fu, + 0x000000aau, 0x00000415u, 0x000009deu, 0x000009deu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00040063u, 0x0000040fu, 0x00000413u, 0x00000415u, 0x0004003du, 0x000003fdu, 0x00000416u, 0x000003ffu, + 0x00060050u, 0x00000402u, 0x0000041au, 0x00000403u, 0x00000404u, 0x0000004au, 0x0009004fu, 0x000000aau, + 0x0000041cu, 0x000009deu, 0x000009deu, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00040063u, + 0x00000416u, 0x0000041au, 0x0000041cu, 0x00050080u, 0x00000016u, 0x0000041eu, 0x00000a2bu, 0x000000bau, + 0x000200f9u, 0x000003d5u, 0x000200f8u, 0x000003d7u, 0x000200f9u, 0x000003cdu, 0x000200f8u, 0x000003cdu, + 0x00050080u, 0x00000016u, 0x00000420u, 0x00000a2au, 0x0000011fu, 0x000200f9u, 0x000003cau, 0x000200f8u, + 0x000003ccu, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, 0x00000a15u, 0x00000000u, + 0x00020011u, 0x00000001u, 0x00020011u, 0x00000038u, 0x00020011u, 0x0000003du, 0x0006000bu, 0x00000001u, + 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0009000fu, + 0x00000005u, 0x00000004u, 0x6e69616du, 0x00000000u, 0x00000091u, 0x000003b1u, 0x000003b3u, 0x000003b6u, + 0x00060010u, 0x00000004u, 0x00000011u, 0x00000040u, 0x00000001u, 0x00000001u, 0x00030047u, 0x00000066u, + 0x00000002u, 0x00050048u, 0x00000066u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x00000066u, + 0x00000001u, 0x00000023u, 0x00000008u, 0x00050048u, 0x00000066u, 0x00000002u, 0x00000023u, 0x00000010u, + 0x00040047u, 0x00000091u, 0x0000000bu, 0x0000001au, 0x00030047u, 0x000000aeu, 0x00000000u, 0x00040047u, + 0x000000aeu, 0x00000021u, 0x00000000u, 0x00040047u, 0x000000aeu, 0x00000022u, 0x00000000u, 0x00040047u, + 0x000000d1u, 0x00000001u, 0x00000000u, 0x00040047u, 0x000003b1u, 0x0000000bu, 0x00000028u, 0x00030047u, + 0x000003b3u, 0x00000000u, 0x00040047u, 0x000003b3u, 0x0000000bu, 0x00000024u, 0x00030047u, 0x000003b4u, + 0x00000000u, 0x00030047u, 0x000003b6u, 0x00000000u, 0x00040047u, 0x000003b6u, 0x0000000bu, 0x00000029u, + 0x00030047u, 0x000003b7u, 0x00000000u, 0x00030047u, 0x000003fdu, 0x00000000u, 0x00030047u, 0x000003fdu, + 0x00000019u, 0x00040047u, 0x000003fdu, 0x00000021u, 0x00000001u, 0x00040047u, 0x000003fdu, 0x00000022u, + 0x00000000u, 0x00030047u, 0x000003feu, 0x00000000u, 0x00030047u, 0x00000406u, 0x00000000u, 0x00030047u, + 0x0000040du, 0x00000000u, 0x00030047u, 0x00000414u, 0x00000000u, 0x00040047u, 0x00000420u, 0x0000000bu, + 0x00000019u, 0x00030047u, 0x0000046fu, 0x00000000u, 0x00030047u, 0x00000472u, 0x00000000u, 0x00030047u, + 0x00000474u, 0x00000000u, 0x00030047u, 0x00000478u, 0x00000000u, 0x00030047u, 0x0000047au, 0x00000000u, + 0x00030047u, 0x0000047eu, 0x00000000u, 0x00030047u, 0x00000480u, 0x00000000u, 0x00030047u, 0x00000484u, + 0x00000000u, 0x00030047u, 0x000004f1u, 0x00000000u, 0x00030047u, 0x000004f6u, 0x00000000u, 0x00030047u, + 0x0000051du, 0x00000000u, 0x00030047u, 0x00000522u, 0x00000000u, 0x00030047u, 0x0000054du, 0x00000000u, + 0x00030047u, 0x00000552u, 0x00000000u, 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, + 0x00040015u, 0x00000006u, 0x00000020u, 0x00000000u, 0x00030016u, 0x00000008u, 0x00000020u, 0x00040017u, + 0x00000009u, 0x00000008u, 0x00000002u, 0x00040020u, 0x0000000fu, 0x00000007u, 0x00000009u, 0x00040015u, + 0x00000016u, 0x00000020u, 0x00000001u, 0x00040017u, 0x00000017u, 0x00000016u, 0x00000002u, 0x00020014u, + 0x00000025u, 0x0004002bu, 0x00000006u, 0x0000002du, 0x00000029u, 0x0004001cu, 0x0000002eu, 0x00000009u, + 0x0000002du, 0x0004002bu, 0x00000006u, 0x0000002fu, 0x00000014u, 0x0004001cu, 0x00000030u, 0x0000002eu, + 0x0000002fu, 0x00040020u, 0x00000031u, 0x00000004u, 0x00000030u, 0x0004003bu, 0x00000031u, 0x00000032u, + 0x00000004u, 0x00040020u, 0x00000035u, 0x00000004u, 0x00000009u, 0x0004002bu, 0x00000016u, 0x00000040u, + 0x00000000u, 0x0004002bu, 0x00000016u, 0x00000041u, 0x00000001u, 0x0004002bu, 0x00000016u, 0x00000045u, + 0x00000002u, 0x0004002bu, 0x00000016u, 0x00000048u, 0x00000003u, 0x0004002bu, 0x00000016u, 0x0000004eu, + 0x00000005u, 0x0005002cu, 0x00000017u, 0x0000005bu, 0x00000040u, 0x00000040u, 0x00040017u, 0x0000005cu, + 0x00000025u, 0x00000002u, 0x0005002cu, 0x00000017u, 0x0000005eu, 0x00000041u, 0x00000041u, 0x0005001eu, + 0x00000066u, 0x00000017u, 0x00000009u, 0x00000017u, 0x00040020u, 0x00000067u, 0x00000009u, 0x00000066u, + 0x0004003bu, 0x00000067u, 0x00000068u, 0x00000009u, 0x00040020u, 0x00000069u, 0x00000009u, 0x00000017u, + 0x00040020u, 0x00000088u, 0x00000009u, 0x00000009u, 0x00040017u, 0x0000008fu, 0x00000006u, 0x00000003u, + 0x00040020u, 0x00000090u, 0x00000001u, 0x0000008fu, 0x0004003bu, 0x00000090u, 0x00000091u, 0x00000001u, + 0x00040017u, 0x00000092u, 0x00000006u, 0x00000002u, 0x0004002bu, 0x00000016u, 0x00000096u, 0x00000020u, + 0x0005002cu, 0x00000017u, 0x00000097u, 0x00000096u, 0x00000096u, 0x0004002bu, 0x00000016u, 0x00000099u, + 0x00000004u, 0x00040017u, 0x000000a8u, 0x00000008u, 0x00000004u, 0x00090019u, 0x000000abu, 0x00000008u, + 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x0003001bu, 0x000000acu, + 0x000000abu, 0x00040020u, 0x000000adu, 0x00000000u, 0x000000acu, 0x0004003bu, 0x000000adu, 0x000000aeu, + 0x00000000u, 0x0004002bu, 0x00000016u, 0x000000b8u, 0x00000010u, 0x0005002cu, 0x00000017u, 0x000000b9u, + 0x000000b8u, 0x00000040u, 0x0005002cu, 0x00000017u, 0x000000c2u, 0x00000040u, 0x000000b8u, 0x0005002cu, + 0x00000017u, 0x000000cbu, 0x000000b8u, 0x000000b8u, 0x00030031u, 0x00000025u, 0x000000d1u, 0x0004002bu, + 0x00000008u, 0x000000d4u, 0x3f000000u, 0x0004002bu, 0x00000006u, 0x000000e2u, 0x00000001u, 0x0004002bu, + 0x00000016u, 0x00000113u, 0x00000011u, 0x0004002bu, 0x00000016u, 0x0000011du, 0x00000008u, 0x0004002bu, + 0x00000006u, 0x00000152u, 0x00000020u, 0x0004002bu, 0x00000006u, 0x00000153u, 0x00000002u, 0x0004002bu, + 0x00000006u, 0x00000155u, 0x00000004u, 0x0004002bu, 0x00000006u, 0x0000018bu, 0x00000010u, 0x0004002bu, + 0x00000006u, 0x000001fau, 0x00000008u, 0x0004001cu, 0x00000217u, 0x00000009u, 0x0000018bu, 0x00040020u, + 0x00000218u, 0x00000007u, 0x00000217u, 0x0004002bu, 0x00000016u, 0x00000226u, 0x0000000fu, 0x0004002bu, + 0x00000008u, 0x00000229u, 0xbfcb0673u, 0x0004002bu, 0x00000016u, 0x00000241u, 0x0000000eu, 0x0004002bu, + 0x00000008u, 0x00000244u, 0xbd5901aeu, 0x0004002bu, 0x00000016u, 0x0000025cu, 0x0000000du, 0x0004002bu, + 0x00000008u, 0x0000025fu, 0x3f620676u, 0x0004002bu, 0x00000016u, 0x00000277u, 0x0000000cu, 0x0004002bu, + 0x00000008u, 0x0000027au, 0x3ee31355u, 0x0004002bu, 0x00000006u, 0x0000028bu, 0x00000108u, 0x0004002bu, + 0x00000016u, 0x00000293u, 0x00000006u, 0x0004002bu, 0x00000008u, 0x000002a1u, 0x3f5019c3u, 0x0004002bu, + 0x00000008u, 0x000002a4u, 0x3f9d7658u, 0x0004002bu, 0x00000006u, 0x000002f8u, 0x0000000cu, 0x0004001cu, + 0x000002f9u, 0x00000009u, 0x000002f8u, 0x00040020u, 0x000002fau, 0x00000007u, 0x000002f9u, 0x0004002bu, + 0x00000016u, 0x00000308u, 0x0000000bu, 0x0004002bu, 0x00000016u, 0x00000322u, 0x0000000au, 0x0004002bu, + 0x00000016u, 0x0000033cu, 0x00000009u, 0x00040020u, 0x000003b0u, 0x00000001u, 0x00000006u, 0x0004003bu, + 0x000003b0u, 0x000003b1u, 0x00000001u, 0x0004003bu, 0x000003b0u, 0x000003b3u, 0x00000001u, 0x0004003bu, + 0x000003b0u, 0x000003b6u, 0x00000001u, 0x00090019u, 0x000003fbu, 0x00000008u, 0x00000001u, 0x00000000u, + 0x00000001u, 0x00000000u, 0x00000002u, 0x00000000u, 0x00040020u, 0x000003fcu, 0x00000000u, 0x000003fbu, + 0x0004003bu, 0x000003fcu, 0x000003fdu, 0x00000000u, 0x00040017u, 0x00000400u, 0x00000016u, 0x00000003u, + 0x0004002bu, 0x00000006u, 0x0000041fu, 0x00000040u, 0x0006002cu, 0x0000008fu, 0x00000420u, 0x0000041fu, + 0x000000e2u, 0x000000e2u, 0x0005002cu, 0x00000017u, 0x00000a12u, 0x00000099u, 0x00000099u, 0x0005002cu, + 0x00000017u, 0x00000a13u, 0x00000045u, 0x00000045u, 0x0007002cu, 0x000000a8u, 0x00000a14u, 0x000000d4u, + 0x000000d4u, 0x000000d4u, 0x000000d4u, 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, + 0x000200f8u, 0x00000005u, 0x0004003bu, 0x00000218u, 0x000008c9u, 0x00000007u, 0x0004003bu, 0x000002fau, + 0x000007e3u, 0x00000007u, 0x0004003bu, 0x00000218u, 0x00000706u, 0x00000007u, 0x0004003du, 0x00000006u, + 0x000003b2u, 0x000003b1u, 0x0004003du, 0x00000006u, 0x000003b4u, 0x000003b3u, 0x00050084u, 0x00000006u, + 0x000003b5u, 0x000003b2u, 0x000003b4u, 0x0004003du, 0x00000006u, 0x000003b7u, 0x000003b6u, 0x00050080u, + 0x00000006u, 0x000003b8u, 0x000003b5u, 0x000003b7u, 0x0004003du, 0x0000008fu, 0x00000462u, 0x00000091u, + 0x0007004fu, 0x00000092u, 0x00000463u, 0x00000462u, 0x00000462u, 0x00000000u, 0x00000001u, 0x0004007cu, + 0x00000017u, 0x00000464u, 0x00000463u, 0x00050084u, 0x00000017u, 0x00000465u, 0x00000464u, 0x00000097u, + 0x00050082u, 0x00000017u, 0x00000467u, 0x00000465u, 0x00000a12u, 0x000600cbu, 0x00000006u, 0x00000575u, + 0x000003b8u, 0x00000040u, 0x00000041u, 0x000600cbu, 0x00000006u, 0x00000577u, 0x000003b8u, 0x00000041u, + 0x00000045u, 0x000600cbu, 0x00000006u, 0x00000579u, 0x000003b8u, 0x00000048u, 0x00000045u, 0x000500c4u, + 0x00000006u, 0x0000057au, 0x00000579u, 0x00000041u, 0x000500c5u, 0x00000006u, 0x0000057cu, 0x00000575u, + 0x0000057au, 0x000600cbu, 0x00000006u, 0x0000057eu, 0x000003b8u, 0x0000004eu, 0x00000041u, 0x000500c4u, + 0x00000006u, 0x0000057fu, 0x0000057eu, 0x00000045u, 0x000500c5u, 0x00000006u, 0x00000581u, 0x00000577u, + 0x0000057fu, 0x0004007cu, 0x00000016u, 0x00000583u, 0x00000581u, 0x0004007cu, 0x00000016u, 0x00000585u, + 0x0000057cu, 0x00050050u, 0x00000017u, 0x00000586u, 0x00000583u, 0x00000585u, 0x00050084u, 0x00000017u, + 0x0000046bu, 0x00000a13u, 0x00000586u, 0x00050080u, 0x00000017u, 0x0000046eu, 0x00000467u, 0x0000046bu, + 0x0004003du, 0x000000acu, 0x0000046fu, 0x000000aeu, 0x000500b1u, 0x0000005cu, 0x0000058cu, 0x0000046eu, + 0x0000005bu, 0x000600a9u, 0x00000017u, 0x0000058du, 0x0000058cu, 0x0000005eu, 0x0000005bu, 0x00050082u, + 0x00000017u, 0x0000058fu, 0x0000046eu, 0x0000058du, 0x00050080u, 0x00000017u, 0x00000592u, 0x0000058fu, + 0x0000005eu, 0x00050041u, 0x00000069u, 0x00000593u, 0x00000068u, 0x00000045u, 0x0004003du, 0x00000017u, + 0x00000594u, 0x00000593u, 0x00050084u, 0x00000017u, 0x00000596u, 0x00000a13u, 0x00000594u, 0x00050041u, + 0x00000069u, 0x00000597u, 0x00000068u, 0x00000040u, 0x0004003du, 0x00000017u, 0x00000598u, 0x00000597u, + 0x00050082u, 0x00000017u, 0x00000599u, 0x00000596u, 0x00000598u, 0x00050082u, 0x00000017u, 0x0000059fu, + 0x00000598u, 0x00000594u, 0x00050084u, 0x00000017u, 0x000005a1u, 0x00000a13u, 0x0000059fu, 0x00050080u, + 0x00000017u, 0x000005a2u, 0x00000592u, 0x000005a1u, 0x00050080u, 0x00000017u, 0x000005a4u, 0x000005a2u, + 0x0000005eu, 0x0007000cu, 0x00000017u, 0x000005a8u, 0x00000001u, 0x00000027u, 0x00000592u, 0x00000598u, + 0x000500afu, 0x0000005cu, 0x000005acu, 0x00000592u, 0x00000599u, 0x000600a9u, 0x00000017u, 0x000005adu, + 0x000005acu, 0x000005a4u, 0x000005a8u, 0x0004006fu, 0x00000009u, 0x000005afu, 0x000005adu, 0x00050041u, + 0x00000088u, 0x000005b0u, 0x00000068u, 0x00000041u, 0x0004003du, 0x00000009u, 0x000005b1u, 0x000005b0u, + 0x00050085u, 0x00000009u, 0x000005b2u, 0x000005afu, 0x000005b1u, 0x00060060u, 0x000000a8u, 0x00000472u, + 0x0000046fu, 0x000005b2u, 0x00000040u, 0x0009004fu, 0x000000a8u, 0x00000473u, 0x00000472u, 0x00000472u, + 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x0004003du, 0x000000acu, 0x00000474u, 0x000000aeu, + 0x00050080u, 0x00000017u, 0x00000476u, 0x0000046eu, 0x000000b9u, 0x000500b1u, 0x0000005cu, 0x000005b8u, + 0x00000476u, 0x0000005bu, 0x000600a9u, 0x00000017u, 0x000005b9u, 0x000005b8u, 0x0000005eu, 0x0000005bu, + 0x00050082u, 0x00000017u, 0x000005bbu, 0x00000476u, 0x000005b9u, 0x00050080u, 0x00000017u, 0x000005beu, + 0x000005bbu, 0x0000005eu, 0x00050080u, 0x00000017u, 0x000005ceu, 0x000005beu, 0x000005a1u, 0x00050080u, + 0x00000017u, 0x000005d0u, 0x000005ceu, 0x0000005eu, 0x0007000cu, 0x00000017u, 0x000005d4u, 0x00000001u, + 0x00000027u, 0x000005beu, 0x00000598u, 0x000500afu, 0x0000005cu, 0x000005d8u, 0x000005beu, 0x00000599u, + 0x000600a9u, 0x00000017u, 0x000005d9u, 0x000005d8u, 0x000005d0u, 0x000005d4u, 0x0004006fu, 0x00000009u, + 0x000005dbu, 0x000005d9u, 0x00050085u, 0x00000009u, 0x000005deu, 0x000005dbu, 0x000005b1u, 0x00060060u, + 0x000000a8u, 0x00000478u, 0x00000474u, 0x000005deu, 0x00000040u, 0x0009004fu, 0x000000a8u, 0x00000479u, + 0x00000478u, 0x00000478u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x0004003du, 0x000000acu, + 0x0000047au, 0x000000aeu, 0x00050080u, 0x00000017u, 0x0000047cu, 0x0000046eu, 0x000000c2u, 0x000500b1u, + 0x0000005cu, 0x000005e4u, 0x0000047cu, 0x0000005bu, 0x000600a9u, 0x00000017u, 0x000005e5u, 0x000005e4u, + 0x0000005eu, 0x0000005bu, 0x00050082u, 0x00000017u, 0x000005e7u, 0x0000047cu, 0x000005e5u, 0x00050080u, + 0x00000017u, 0x000005eau, 0x000005e7u, 0x0000005eu, 0x00050080u, 0x00000017u, 0x000005fau, 0x000005eau, + 0x000005a1u, 0x00050080u, 0x00000017u, 0x000005fcu, 0x000005fau, 0x0000005eu, 0x0007000cu, 0x00000017u, + 0x00000600u, 0x00000001u, 0x00000027u, 0x000005eau, 0x00000598u, 0x000500afu, 0x0000005cu, 0x00000604u, + 0x000005eau, 0x00000599u, 0x000600a9u, 0x00000017u, 0x00000605u, 0x00000604u, 0x000005fcu, 0x00000600u, + 0x0004006fu, 0x00000009u, 0x00000607u, 0x00000605u, 0x00050085u, 0x00000009u, 0x0000060au, 0x00000607u, + 0x000005b1u, 0x00060060u, 0x000000a8u, 0x0000047eu, 0x0000047au, 0x0000060au, 0x00000040u, 0x0009004fu, + 0x000000a8u, 0x0000047fu, 0x0000047eu, 0x0000047eu, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, + 0x0004003du, 0x000000acu, 0x00000480u, 0x000000aeu, 0x00050080u, 0x00000017u, 0x00000482u, 0x0000046eu, + 0x000000cbu, 0x000500b1u, 0x0000005cu, 0x00000610u, 0x00000482u, 0x0000005bu, 0x000600a9u, 0x00000017u, + 0x00000611u, 0x00000610u, 0x0000005eu, 0x0000005bu, 0x00050082u, 0x00000017u, 0x00000613u, 0x00000482u, + 0x00000611u, 0x00050080u, 0x00000017u, 0x00000616u, 0x00000613u, 0x0000005eu, 0x00050080u, 0x00000017u, + 0x00000626u, 0x00000616u, 0x000005a1u, 0x00050080u, 0x00000017u, 0x00000628u, 0x00000626u, 0x0000005eu, + 0x0007000cu, 0x00000017u, 0x0000062cu, 0x00000001u, 0x00000027u, 0x00000616u, 0x00000598u, 0x000500afu, + 0x0000005cu, 0x00000630u, 0x00000616u, 0x00000599u, 0x000600a9u, 0x00000017u, 0x00000631u, 0x00000630u, + 0x00000628u, 0x0000062cu, 0x0004006fu, 0x00000009u, 0x00000633u, 0x00000631u, 0x00050085u, 0x00000009u, + 0x00000636u, 0x00000633u, 0x000005b1u, 0x00060060u, 0x000000a8u, 0x00000484u, 0x00000480u, 0x00000636u, + 0x00000040u, 0x0009004fu, 0x000000a8u, 0x00000485u, 0x00000484u, 0x00000484u, 0x00000003u, 0x00000002u, + 0x00000000u, 0x00000001u, 0x000300f7u, 0x00000493u, 0x00000000u, 0x000400fau, 0x000000d1u, 0x00000486u, + 0x00000493u, 0x000200f8u, 0x00000486u, 0x00050083u, 0x000000a8u, 0x00000489u, 0x00000473u, 0x00000a14u, + 0x00050083u, 0x000000a8u, 0x0000048cu, 0x00000479u, 0x00000a14u, 0x00050083u, 0x000000a8u, 0x0000048fu, + 0x0000047fu, 0x00000a14u, 0x00050083u, 0x000000a8u, 0x00000492u, 0x00000485u, 0x00000a14u, 0x000200f9u, + 0x00000493u, 0x000200f8u, 0x00000493u, 0x000700f5u, 0x000000a8u, 0x000009f9u, 0x00000485u, 0x00000005u, + 0x00000492u, 0x00000486u, 0x000700f5u, 0x000000a8u, 0x000009f8u, 0x0000047fu, 0x00000005u, 0x0000048fu, + 0x00000486u, 0x000700f5u, 0x000000a8u, 0x000009f7u, 0x00000479u, 0x00000005u, 0x0000048cu, 0x00000486u, + 0x000700f5u, 0x000000a8u, 0x000009f6u, 0x00000473u, 0x00000005u, 0x00000489u, 0x00000486u, 0x00050051u, + 0x00000016u, 0x00000495u, 0x0000046bu, 0x00000001u, 0x000500c3u, 0x00000016u, 0x00000496u, 0x00000495u, + 0x00000041u, 0x0004007cu, 0x00000006u, 0x00000499u, 0x00000496u, 0x00050051u, 0x00000016u, 0x0000049bu, + 0x0000046bu, 0x00000000u, 0x0004007cu, 0x00000006u, 0x0000049du, 0x0000049bu, 0x0007004fu, 0x00000009u, + 0x0000049fu, 0x000009f6u, 0x000009f6u, 0x00000000u, 0x00000002u, 0x00060041u, 0x00000035u, 0x0000063bu, + 0x00000032u, 0x00000499u, 0x0000049du, 0x0003003eu, 0x0000063bu, 0x0000049fu, 0x00050080u, 0x00000016u, + 0x000004a6u, 0x0000049bu, 0x00000041u, 0x0004007cu, 0x00000006u, 0x000004a7u, 0x000004a6u, 0x0007004fu, + 0x00000009u, 0x000004a9u, 0x000009f6u, 0x000009f6u, 0x00000001u, 0x00000003u, 0x00060041u, 0x00000035u, + 0x00000640u, 0x00000032u, 0x00000499u, 0x000004a7u, 0x0003003eu, 0x00000640u, 0x000004a9u, 0x00050080u, + 0x00000016u, 0x000004b0u, 0x0000049bu, 0x000000b8u, 0x0004007cu, 0x00000006u, 0x000004b1u, 0x000004b0u, + 0x0007004fu, 0x00000009u, 0x000004b3u, 0x000009f7u, 0x000009f7u, 0x00000000u, 0x00000002u, 0x00060041u, + 0x00000035u, 0x00000645u, 0x00000032u, 0x00000499u, 0x000004b1u, 0x0003003eu, 0x00000645u, 0x000004b3u, + 0x00050080u, 0x00000016u, 0x000004bau, 0x0000049bu, 0x00000113u, 0x0004007cu, 0x00000006u, 0x000004bbu, + 0x000004bau, 0x0007004fu, 0x00000009u, 0x000004bdu, 0x000009f7u, 0x000009f7u, 0x00000001u, 0x00000003u, + 0x00060041u, 0x00000035u, 0x0000064au, 0x00000032u, 0x00000499u, 0x000004bbu, 0x0003003eu, 0x0000064au, + 0x000004bdu, 0x00050080u, 0x00000016u, 0x000004c0u, 0x00000496u, 0x0000011du, 0x0004007cu, 0x00000006u, + 0x000004c1u, 0x000004c0u, 0x0007004fu, 0x00000009u, 0x000004c7u, 0x000009f8u, 0x000009f8u, 0x00000000u, + 0x00000002u, 0x00060041u, 0x00000035u, 0x0000064fu, 0x00000032u, 0x000004c1u, 0x0000049du, 0x0003003eu, + 0x0000064fu, 0x000004c7u, 0x0007004fu, 0x00000009u, 0x000004d1u, 0x000009f8u, 0x000009f8u, 0x00000001u, + 0x00000003u, 0x00060041u, 0x00000035u, 0x00000654u, 0x00000032u, 0x000004c1u, 0x000004a7u, 0x0003003eu, + 0x00000654u, 0x000004d1u, 0x0007004fu, 0x00000009u, 0x000004dbu, 0x000009f9u, 0x000009f9u, 0x00000000u, + 0x00000002u, 0x00060041u, 0x00000035u, 0x00000659u, 0x00000032u, 0x000004c1u, 0x000004b1u, 0x0003003eu, + 0x00000659u, 0x000004dbu, 0x0007004fu, 0x00000009u, 0x000004e5u, 0x000009f9u, 0x000009f9u, 0x00000001u, + 0x00000003u, 0x00060041u, 0x00000035u, 0x0000065eu, 0x00000032u, 0x000004c1u, 0x000004bbu, 0x0003003eu, + 0x0000065eu, 0x000004e5u, 0x00050089u, 0x00000006u, 0x000004e8u, 0x000003b8u, 0x00000155u, 0x00050084u, + 0x00000006u, 0x000004e9u, 0x00000153u, 0x000004e8u, 0x00050080u, 0x00000006u, 0x000004eau, 0x00000152u, + 0x000004e9u, 0x0004007cu, 0x00000016u, 0x000004ebu, 0x000004eau, 0x00050086u, 0x00000006u, 0x000004edu, + 0x000003b8u, 0x00000155u, 0x00050084u, 0x00000006u, 0x000004eeu, 0x00000153u, 0x000004edu, 0x0004007cu, + 0x00000016u, 0x000004efu, 0x000004eeu, 0x00050050u, 0x00000017u, 0x000004f0u, 0x000004ebu, 0x000004efu, + 0x0004003du, 0x000000acu, 0x000004f1u, 0x000000aeu, 0x00050080u, 0x00000017u, 0x000004f4u, 0x00000467u, + 0x000004f0u, 0x000500b1u, 0x0000005cu, 0x00000664u, 0x000004f4u, 0x0000005bu, 0x000600a9u, 0x00000017u, + 0x00000665u, 0x00000664u, 0x0000005eu, 0x0000005bu, 0x00050082u, 0x00000017u, 0x00000667u, 0x000004f4u, + 0x00000665u, 0x00050080u, 0x00000017u, 0x0000066au, 0x00000667u, 0x0000005eu, 0x00050080u, 0x00000017u, + 0x0000067au, 0x0000066au, 0x000005a1u, 0x00050080u, 0x00000017u, 0x0000067cu, 0x0000067au, 0x0000005eu, + 0x0007000cu, 0x00000017u, 0x00000680u, 0x00000001u, 0x00000027u, 0x0000066au, 0x00000598u, 0x000500afu, + 0x0000005cu, 0x00000684u, 0x0000066au, 0x00000599u, 0x000600a9u, 0x00000017u, 0x00000685u, 0x00000684u, + 0x0000067cu, 0x00000680u, 0x0004006fu, 0x00000009u, 0x00000687u, 0x00000685u, 0x00050085u, 0x00000009u, + 0x0000068au, 0x00000687u, 0x000005b1u, 0x00060060u, 0x000000a8u, 0x000004f6u, 0x000004f1u, 0x0000068au, + 0x00000040u, 0x0009004fu, 0x000000a8u, 0x000004f7u, 0x000004f6u, 0x000004f6u, 0x00000003u, 0x00000002u, + 0x00000000u, 0x00000001u, 0x000300f7u, 0x000004fcu, 0x00000000u, 0x000400fau, 0x000000d1u, 0x000004f8u, + 0x000004fcu, 0x000200f8u, 0x000004f8u, 0x00050083u, 0x000000a8u, 0x000004fbu, 0x000004f7u, 0x00000a14u, + 0x000200f9u, 0x000004fcu, 0x000200f8u, 0x000004fcu, 0x000700f5u, 0x000000a8u, 0x000009fau, 0x000004f7u, + 0x00000493u, 0x000004fbu, 0x000004f8u, 0x000500c3u, 0x00000016u, 0x000004ffu, 0x000004efu, 0x00000041u, + 0x0004007cu, 0x00000006u, 0x00000500u, 0x000004ffu, 0x0007004fu, 0x00000009u, 0x00000506u, 0x000009fau, + 0x000009fau, 0x00000000u, 0x00000002u, 0x00060041u, 0x00000035u, 0x0000068fu, 0x00000032u, 0x00000500u, + 0x000004eau, 0x0003003eu, 0x0000068fu, 0x00000506u, 0x00050080u, 0x00000016u, 0x0000050eu, 0x000004ebu, + 0x00000041u, 0x0004007cu, 0x00000006u, 0x0000050fu, 0x0000050eu, 0x0007004fu, 0x00000009u, 0x00000511u, + 0x000009fau, 0x000009fau, 0x00000001u, 0x00000003u, 0x00060041u, 0x00000035u, 0x00000694u, 0x00000032u, + 0x00000500u, 0x0000050fu, 0x0003003eu, 0x00000694u, 0x00000511u, 0x00050089u, 0x00000006u, 0x00000514u, + 0x000003b8u, 0x0000018bu, 0x00050084u, 0x00000006u, 0x00000515u, 0x00000153u, 0x00000514u, 0x0004007cu, + 0x00000016u, 0x00000516u, 0x00000515u, 0x00050086u, 0x00000006u, 0x00000518u, 0x000003b8u, 0x0000018bu, + 0x00050084u, 0x00000006u, 0x00000519u, 0x00000153u, 0x00000518u, 0x00050080u, 0x00000006u, 0x0000051au, + 0x00000152u, 0x00000519u, 0x0004007cu, 0x00000016u, 0x0000051bu, 0x0000051au, 0x00050050u, 0x00000017u, + 0x0000051cu, 0x00000516u, 0x0000051bu, 0x0004003du, 0x000000acu, 0x0000051du, 0x000000aeu, 0x00050080u, + 0x00000017u, 0x00000520u, 0x00000467u, 0x0000051cu, 0x000500b1u, 0x0000005cu, 0x0000069au, 0x00000520u, + 0x0000005bu, 0x000600a9u, 0x00000017u, 0x0000069bu, 0x0000069au, 0x0000005eu, 0x0000005bu, 0x00050082u, + 0x00000017u, 0x0000069du, 0x00000520u, 0x0000069bu, 0x00050080u, 0x00000017u, 0x000006a0u, 0x0000069du, + 0x0000005eu, 0x00050080u, 0x00000017u, 0x000006b0u, 0x000006a0u, 0x000005a1u, 0x00050080u, 0x00000017u, + 0x000006b2u, 0x000006b0u, 0x0000005eu, 0x0007000cu, 0x00000017u, 0x000006b6u, 0x00000001u, 0x00000027u, + 0x000006a0u, 0x00000598u, 0x000500afu, 0x0000005cu, 0x000006bau, 0x000006a0u, 0x00000599u, 0x000600a9u, + 0x00000017u, 0x000006bbu, 0x000006bau, 0x000006b2u, 0x000006b6u, 0x0004006fu, 0x00000009u, 0x000006bdu, + 0x000006bbu, 0x00050085u, 0x00000009u, 0x000006c0u, 0x000006bdu, 0x000005b1u, 0x00060060u, 0x000000a8u, + 0x00000522u, 0x0000051du, 0x000006c0u, 0x00000040u, 0x0009004fu, 0x000000a8u, 0x00000523u, 0x00000522u, + 0x00000522u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, 0x00000528u, 0x00000000u, + 0x000400fau, 0x000000d1u, 0x00000524u, 0x00000528u, 0x000200f8u, 0x00000524u, 0x00050083u, 0x000000a8u, + 0x00000527u, 0x00000523u, 0x00000a14u, 0x000200f9u, 0x00000528u, 0x000200f8u, 0x00000528u, 0x000700f5u, + 0x000000a8u, 0x000009fbu, 0x00000523u, 0x000004fcu, 0x00000527u, 0x00000524u, 0x000500c3u, 0x00000016u, + 0x0000052bu, 0x0000051bu, 0x00000041u, 0x0004007cu, 0x00000006u, 0x0000052cu, 0x0000052bu, 0x0007004fu, + 0x00000009u, 0x00000532u, 0x000009fbu, 0x000009fbu, 0x00000000u, 0x00000002u, 0x00060041u, 0x00000035u, + 0x000006c5u, 0x00000032u, 0x0000052cu, 0x00000515u, 0x0003003eu, 0x000006c5u, 0x00000532u, 0x00050080u, + 0x00000016u, 0x0000053au, 0x00000516u, 0x00000041u, 0x0004007cu, 0x00000006u, 0x0000053bu, 0x0000053au, + 0x0007004fu, 0x00000009u, 0x0000053du, 0x000009fbu, 0x000009fbu, 0x00000001u, 0x00000003u, 0x00060041u, + 0x00000035u, 0x000006cau, 0x00000032u, 0x0000052cu, 0x0000053bu, 0x0003003eu, 0x000006cau, 0x0000053du, + 0x000500b0u, 0x00000025u, 0x00000540u, 0x000003b8u, 0x0000018bu, 0x000300f7u, 0x0000056fu, 0x00000000u, + 0x000400fau, 0x00000540u, 0x00000541u, 0x0000056fu, 0x000200f8u, 0x00000541u, 0x00050080u, 0x00000006u, + 0x0000054au, 0x00000152u, 0x000004eeu, 0x0004007cu, 0x00000016u, 0x0000054bu, 0x0000054au, 0x00050050u, + 0x00000017u, 0x0000054cu, 0x000004ebu, 0x0000054bu, 0x0004003du, 0x000000acu, 0x0000054du, 0x000000aeu, + 0x00050080u, 0x00000017u, 0x00000550u, 0x00000467u, 0x0000054cu, 0x000500b1u, 0x0000005cu, 0x000006d0u, + 0x00000550u, 0x0000005bu, 0x000600a9u, 0x00000017u, 0x000006d1u, 0x000006d0u, 0x0000005eu, 0x0000005bu, + 0x00050082u, 0x00000017u, 0x000006d3u, 0x00000550u, 0x000006d1u, 0x00050080u, 0x00000017u, 0x000006d6u, + 0x000006d3u, 0x0000005eu, 0x00050080u, 0x00000017u, 0x000006e6u, 0x000006d6u, 0x000005a1u, 0x00050080u, + 0x00000017u, 0x000006e8u, 0x000006e6u, 0x0000005eu, 0x0007000cu, 0x00000017u, 0x000006ecu, 0x00000001u, + 0x00000027u, 0x000006d6u, 0x00000598u, 0x000500afu, 0x0000005cu, 0x000006f0u, 0x000006d6u, 0x00000599u, + 0x000600a9u, 0x00000017u, 0x000006f1u, 0x000006f0u, 0x000006e8u, 0x000006ecu, 0x0004006fu, 0x00000009u, + 0x000006f3u, 0x000006f1u, 0x00050085u, 0x00000009u, 0x000006f6u, 0x000006f3u, 0x000005b1u, 0x00060060u, + 0x000000a8u, 0x00000552u, 0x0000054du, 0x000006f6u, 0x00000040u, 0x0009004fu, 0x000000a8u, 0x00000553u, + 0x00000552u, 0x00000552u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, 0x00000558u, + 0x00000000u, 0x000400fau, 0x000000d1u, 0x00000554u, 0x00000558u, 0x000200f8u, 0x00000554u, 0x00050083u, + 0x000000a8u, 0x00000557u, 0x00000553u, 0x00000a14u, 0x000200f9u, 0x00000558u, 0x000200f8u, 0x00000558u, + 0x000700f5u, 0x000000a8u, 0x000009fcu, 0x00000553u, 0x00000541u, 0x00000557u, 0x00000554u, 0x000500c3u, + 0x00000016u, 0x0000055bu, 0x0000054bu, 0x00000041u, 0x0004007cu, 0x00000006u, 0x0000055cu, 0x0000055bu, + 0x0007004fu, 0x00000009u, 0x00000562u, 0x000009fcu, 0x000009fcu, 0x00000000u, 0x00000002u, 0x00060041u, + 0x00000035u, 0x000006fbu, 0x00000032u, 0x0000055cu, 0x000004eau, 0x0003003eu, 0x000006fbu, 0x00000562u, + 0x0007004fu, 0x00000009u, 0x0000056du, 0x000009fcu, 0x000009fcu, 0x00000001u, 0x00000003u, 0x00060041u, + 0x00000035u, 0x00000700u, 0x00000032u, 0x0000055cu, 0x0000050fu, 0x0003003eu, 0x00000700u, 0x0000056du, + 0x000200f9u, 0x0000056fu, 0x000200f8u, 0x0000056fu, 0x000400e0u, 0x00000153u, 0x00000153u, 0x0000028bu, + 0x00050084u, 0x00000006u, 0x0000071au, 0x000001fau, 0x000004e8u, 0x0004007cu, 0x00000016u, 0x0000071bu, + 0x0000071au, 0x0004007cu, 0x00000016u, 0x0000071eu, 0x000004edu, 0x000200f9u, 0x00000720u, 0x000200f8u, + 0x00000720u, 0x000700f5u, 0x00000016u, 0x000009fdu, 0x00000040u, 0x0000056fu, 0x00000733u, 0x00000724u, + 0x000500b1u, 0x00000025u, 0x00000723u, 0x000009fdu, 0x000000b8u, 0x000400f6u, 0x00000734u, 0x00000724u, + 0x00000000u, 0x000400fau, 0x00000723u, 0x00000724u, 0x00000734u, 0x000200f8u, 0x00000724u, 0x00050080u, + 0x00000016u, 0x0000072bu, 0x0000071bu, 0x000009fdu, 0x0004007cu, 0x00000006u, 0x0000072cu, 0x0000072bu, + 0x00060041u, 0x00000035u, 0x000007d2u, 0x00000032u, 0x000004edu, 0x0000072cu, 0x0004003du, 0x00000009u, + 0x000007d3u, 0x000007d2u, 0x00050041u, 0x0000000fu, 0x00000730u, 0x00000706u, 0x000009fdu, 0x0003003eu, + 0x00000730u, 0x000007d3u, 0x00050080u, 0x00000016u, 0x00000733u, 0x000009fdu, 0x00000041u, 0x000200f9u, + 0x00000720u, 0x000200f8u, 0x00000734u, 0x000200f9u, 0x00000735u, 0x000200f8u, 0x00000735u, 0x000700f5u, + 0x00000016u, 0x000009feu, 0x00000041u, 0x00000734u, 0x0000074bu, 0x00000739u, 0x000500b1u, 0x00000025u, + 0x00000738u, 0x000009feu, 0x00000226u, 0x000400f6u, 0x0000074cu, 0x00000739u, 0x00000000u, 0x000400fau, + 0x00000738u, 0x00000739u, 0x0000074cu, 0x000200f8u, 0x00000739u, 0x00050082u, 0x00000016u, 0x0000073cu, + 0x000009feu, 0x00000041u, 0x00050041u, 0x0000000fu, 0x0000073du, 0x00000706u, 0x0000073cu, 0x0004003du, + 0x00000009u, 0x0000073eu, 0x0000073du, 0x00050080u, 0x00000016u, 0x00000740u, 0x000009feu, 0x00000041u, + 0x00050041u, 0x0000000fu, 0x00000741u, 0x00000706u, 0x00000740u, 0x0004003du, 0x00000009u, 0x00000742u, + 0x00000741u, 0x00050081u, 0x00000009u, 0x00000743u, 0x0000073eu, 0x00000742u, 0x0005008eu, 0x00000009u, + 0x00000744u, 0x00000743u, 0x00000229u, 0x00050041u, 0x0000000fu, 0x00000745u, 0x00000706u, 0x000009feu, + 0x0004003du, 0x00000009u, 0x00000746u, 0x00000745u, 0x00050081u, 0x00000009u, 0x00000747u, 0x00000746u, + 0x00000744u, 0x0003003eu, 0x00000745u, 0x00000747u, 0x00050080u, 0x00000016u, 0x0000074bu, 0x000009feu, + 0x00000045u, 0x000200f9u, 0x00000735u, 0x000200f8u, 0x0000074cu, 0x000200f9u, 0x0000074du, 0x000200f8u, + 0x0000074du, 0x000700f5u, 0x00000016u, 0x000009ffu, 0x00000045u, 0x0000074cu, 0x00000763u, 0x00000751u, + 0x000500b1u, 0x00000025u, 0x00000750u, 0x000009ffu, 0x00000241u, 0x000400f6u, 0x00000764u, 0x00000751u, + 0x00000000u, 0x000400fau, 0x00000750u, 0x00000751u, 0x00000764u, 0x000200f8u, 0x00000751u, 0x00050082u, + 0x00000016u, 0x00000754u, 0x000009ffu, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000755u, 0x00000706u, + 0x00000754u, 0x0004003du, 0x00000009u, 0x00000756u, 0x00000755u, 0x00050080u, 0x00000016u, 0x00000758u, + 0x000009ffu, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000759u, 0x00000706u, 0x00000758u, 0x0004003du, + 0x00000009u, 0x0000075au, 0x00000759u, 0x00050081u, 0x00000009u, 0x0000075bu, 0x00000756u, 0x0000075au, + 0x0005008eu, 0x00000009u, 0x0000075cu, 0x0000075bu, 0x00000244u, 0x00050041u, 0x0000000fu, 0x0000075du, + 0x00000706u, 0x000009ffu, 0x0004003du, 0x00000009u, 0x0000075eu, 0x0000075du, 0x00050081u, 0x00000009u, + 0x0000075fu, 0x0000075eu, 0x0000075cu, 0x0003003eu, 0x0000075du, 0x0000075fu, 0x00050080u, 0x00000016u, + 0x00000763u, 0x000009ffu, 0x00000045u, 0x000200f9u, 0x0000074du, 0x000200f8u, 0x00000764u, 0x000200f9u, + 0x00000765u, 0x000200f8u, 0x00000765u, 0x000700f5u, 0x00000016u, 0x00000a00u, 0x00000048u, 0x00000764u, + 0x0000077bu, 0x00000769u, 0x000500b1u, 0x00000025u, 0x00000768u, 0x00000a00u, 0x0000025cu, 0x000400f6u, + 0x0000077cu, 0x00000769u, 0x00000000u, 0x000400fau, 0x00000768u, 0x00000769u, 0x0000077cu, 0x000200f8u, + 0x00000769u, 0x00050082u, 0x00000016u, 0x0000076cu, 0x00000a00u, 0x00000041u, 0x00050041u, 0x0000000fu, + 0x0000076du, 0x00000706u, 0x0000076cu, 0x0004003du, 0x00000009u, 0x0000076eu, 0x0000076du, 0x00050080u, + 0x00000016u, 0x00000770u, 0x00000a00u, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000771u, 0x00000706u, + 0x00000770u, 0x0004003du, 0x00000009u, 0x00000772u, 0x00000771u, 0x00050081u, 0x00000009u, 0x00000773u, + 0x0000076eu, 0x00000772u, 0x0005008eu, 0x00000009u, 0x00000774u, 0x00000773u, 0x0000025fu, 0x00050041u, + 0x0000000fu, 0x00000775u, 0x00000706u, 0x00000a00u, 0x0004003du, 0x00000009u, 0x00000776u, 0x00000775u, + 0x00050081u, 0x00000009u, 0x00000777u, 0x00000776u, 0x00000774u, 0x0003003eu, 0x00000775u, 0x00000777u, + 0x00050080u, 0x00000016u, 0x0000077bu, 0x00000a00u, 0x00000045u, 0x000200f9u, 0x00000765u, 0x000200f8u, + 0x0000077cu, 0x000200f9u, 0x0000077du, 0x000200f8u, 0x0000077du, 0x000700f5u, 0x00000016u, 0x00000a01u, + 0x00000099u, 0x0000077cu, 0x00000793u, 0x00000781u, 0x000500b1u, 0x00000025u, 0x00000780u, 0x00000a01u, + 0x00000277u, 0x000400f6u, 0x00000794u, 0x00000781u, 0x00000000u, 0x000400fau, 0x00000780u, 0x00000781u, + 0x00000794u, 0x000200f8u, 0x00000781u, 0x00050082u, 0x00000016u, 0x00000784u, 0x00000a01u, 0x00000041u, + 0x00050041u, 0x0000000fu, 0x00000785u, 0x00000706u, 0x00000784u, 0x0004003du, 0x00000009u, 0x00000786u, + 0x00000785u, 0x00050080u, 0x00000016u, 0x00000788u, 0x00000a01u, 0x00000041u, 0x00050041u, 0x0000000fu, + 0x00000789u, 0x00000706u, 0x00000788u, 0x0004003du, 0x00000009u, 0x0000078au, 0x00000789u, 0x00050081u, + 0x00000009u, 0x0000078bu, 0x00000786u, 0x0000078au, 0x0005008eu, 0x00000009u, 0x0000078cu, 0x0000078bu, + 0x0000027au, 0x00050041u, 0x0000000fu, 0x0000078du, 0x00000706u, 0x00000a01u, 0x0004003du, 0x00000009u, + 0x0000078eu, 0x0000078du, 0x00050081u, 0x00000009u, 0x0000078fu, 0x0000078eu, 0x0000078cu, 0x0003003eu, + 0x0000078du, 0x0000078fu, 0x00050080u, 0x00000016u, 0x00000793u, 0x00000a01u, 0x00000045u, 0x000200f9u, + 0x0000077du, 0x000200f8u, 0x00000794u, 0x000400e0u, 0x00000153u, 0x00000153u, 0x0000028bu, 0x000200f9u, + 0x00000795u, 0x000200f8u, 0x00000795u, 0x000700f5u, 0x00000016u, 0x00000a02u, 0x00000045u, 0x00000794u, + 0x000007ccu, 0x00000799u, 0x000500b1u, 0x00000025u, 0x00000798u, 0x00000a02u, 0x00000293u, 0x000400f6u, + 0x000007cdu, 0x00000799u, 0x00000000u, 0x000400fau, 0x00000798u, 0x00000799u, 0x000007cdu, 0x000200f8u, + 0x00000799u, 0x00050084u, 0x00000016u, 0x0000079bu, 0x00000045u, 0x00000a02u, 0x00050041u, 0x0000000fu, + 0x0000079du, 0x00000706u, 0x0000079bu, 0x0004003du, 0x00000009u, 0x0000079eu, 0x0000079du, 0x00050080u, + 0x00000016u, 0x000007a1u, 0x0000079bu, 0x00000041u, 0x00050041u, 0x0000000fu, 0x000007a2u, 0x00000706u, + 0x000007a1u, 0x0004003du, 0x00000009u, 0x000007a3u, 0x000007a2u, 0x0005008eu, 0x00000009u, 0x000007a5u, + 0x0000079eu, 0x000002a1u, 0x0005008eu, 0x00000009u, 0x000007a7u, 0x000007a3u, 0x000002a4u, 0x00050051u, + 0x00000008u, 0x000007a9u, 0x000007a5u, 0x00000000u, 0x00050051u, 0x00000008u, 0x000007abu, 0x000007a7u, + 0x00000000u, 0x00050050u, 0x00000009u, 0x000007acu, 0x000007a9u, 0x000007abu, 0x00050051u, 0x00000008u, + 0x000007aeu, 0x000007a5u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000007b0u, 0x000007a7u, 0x00000001u, + 0x00050050u, 0x00000009u, 0x000007b1u, 0x000007aeu, 0x000007b0u, 0x000500c3u, 0x00000016u, 0x000007b4u, + 0x0000071bu, 0x00000041u, 0x00050082u, 0x00000016u, 0x000007b6u, 0x00000a02u, 0x00000045u, 0x00050080u, + 0x00000016u, 0x000007b7u, 0x000007b4u, 0x000007b6u, 0x0004007cu, 0x00000006u, 0x000007b9u, 0x000007b7u, + 0x00050084u, 0x00000016u, 0x000007bcu, 0x00000045u, 0x0000071eu, 0x0004007cu, 0x00000006u, 0x000007beu, + 0x000007bcu, 0x00060041u, 0x00000035u, 0x000007d8u, 0x00000032u, 0x000007b9u, 0x000007beu, 0x0003003eu, + 0x000007d8u, 0x000007acu, 0x00050080u, 0x00000016u, 0x000007c6u, 0x000007bcu, 0x00000041u, 0x0004007cu, + 0x00000006u, 0x000007c7u, 0x000007c6u, 0x00060041u, 0x00000035u, 0x000007ddu, 0x00000032u, 0x000007b9u, + 0x000007c7u, 0x0003003eu, 0x000007ddu, 0x000007b1u, 0x00050080u, 0x00000016u, 0x000007ccu, 0x00000a02u, + 0x00000041u, 0x000200f9u, 0x00000795u, 0x000200f8u, 0x000007cdu, 0x000500b0u, 0x00000025u, 0x000003bcu, + 0x000003b8u, 0x00000152u, 0x00050089u, 0x00000006u, 0x000007f6u, 0x000003b8u, 0x000001fau, 0x00050084u, + 0x00000006u, 0x000007f7u, 0x00000155u, 0x000007f6u, 0x0004007cu, 0x00000016u, 0x000007f8u, 0x000007f7u, + 0x00050086u, 0x00000006u, 0x000007fau, 0x000003b8u, 0x000001fau, 0x00050080u, 0x00000006u, 0x000007fdu, + 0x000007fau, 0x0000018bu, 0x0004007cu, 0x00000016u, 0x000007feu, 0x000007fdu, 0x000300f7u, 0x00000877u, + 0x00000000u, 0x000400fau, 0x000003bcu, 0x00000801u, 0x00000877u, 0x000200f8u, 0x00000801u, 0x000200f9u, + 0x00000802u, 0x000200f8u, 0x00000802u, 0x000700f5u, 0x00000016u, 0x00000a03u, 0x00000040u, 0x00000801u, + 0x00000815u, 0x00000806u, 0x000500b1u, 0x00000025u, 0x00000805u, 0x00000a03u, 0x00000277u, 0x000400f6u, + 0x00000816u, 0x00000806u, 0x00000000u, 0x000400fau, 0x00000805u, 0x00000806u, 0x00000816u, 0x000200f8u, + 0x00000806u, 0x00050080u, 0x00000016u, 0x0000080du, 0x000007f8u, 0x00000a03u, 0x0004007cu, 0x00000006u, + 0x0000080eu, 0x0000080du, 0x00060041u, 0x00000035u, 0x000008b8u, 0x00000032u, 0x000007fdu, 0x0000080eu, + 0x0004003du, 0x00000009u, 0x000008b9u, 0x000008b8u, 0x00050041u, 0x0000000fu, 0x00000812u, 0x000007e3u, + 0x00000a03u, 0x0003003eu, 0x00000812u, 0x000008b9u, 0x00050080u, 0x00000016u, 0x00000815u, 0x00000a03u, + 0x00000041u, 0x000200f9u, 0x00000802u, 0x000200f8u, 0x00000816u, 0x000200f9u, 0x00000817u, 0x000200f8u, + 0x00000817u, 0x000700f5u, 0x00000016u, 0x00000a04u, 0x00000041u, 0x00000816u, 0x0000082du, 0x0000081bu, + 0x000500b1u, 0x00000025u, 0x0000081au, 0x00000a04u, 0x00000308u, 0x000400f6u, 0x0000082eu, 0x0000081bu, + 0x00000000u, 0x000400fau, 0x0000081au, 0x0000081bu, 0x0000082eu, 0x000200f8u, 0x0000081bu, 0x00050082u, + 0x00000016u, 0x0000081eu, 0x00000a04u, 0x00000041u, 0x00050041u, 0x0000000fu, 0x0000081fu, 0x000007e3u, + 0x0000081eu, 0x0004003du, 0x00000009u, 0x00000820u, 0x0000081fu, 0x00050080u, 0x00000016u, 0x00000822u, + 0x00000a04u, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000823u, 0x000007e3u, 0x00000822u, 0x0004003du, + 0x00000009u, 0x00000824u, 0x00000823u, 0x00050081u, 0x00000009u, 0x00000825u, 0x00000820u, 0x00000824u, + 0x0005008eu, 0x00000009u, 0x00000826u, 0x00000825u, 0x00000229u, 0x00050041u, 0x0000000fu, 0x00000827u, + 0x000007e3u, 0x00000a04u, 0x0004003du, 0x00000009u, 0x00000828u, 0x00000827u, 0x00050081u, 0x00000009u, + 0x00000829u, 0x00000828u, 0x00000826u, 0x0003003eu, 0x00000827u, 0x00000829u, 0x00050080u, 0x00000016u, + 0x0000082du, 0x00000a04u, 0x00000045u, 0x000200f9u, 0x00000817u, 0x000200f8u, 0x0000082eu, 0x000200f9u, + 0x0000082fu, 0x000200f8u, 0x0000082fu, 0x000700f5u, 0x00000016u, 0x00000a05u, 0x00000045u, 0x0000082eu, + 0x00000845u, 0x00000833u, 0x000500b1u, 0x00000025u, 0x00000832u, 0x00000a05u, 0x00000322u, 0x000400f6u, + 0x00000846u, 0x00000833u, 0x00000000u, 0x000400fau, 0x00000832u, 0x00000833u, 0x00000846u, 0x000200f8u, + 0x00000833u, 0x00050082u, 0x00000016u, 0x00000836u, 0x00000a05u, 0x00000041u, 0x00050041u, 0x0000000fu, + 0x00000837u, 0x000007e3u, 0x00000836u, 0x0004003du, 0x00000009u, 0x00000838u, 0x00000837u, 0x00050080u, + 0x00000016u, 0x0000083au, 0x00000a05u, 0x00000041u, 0x00050041u, 0x0000000fu, 0x0000083bu, 0x000007e3u, + 0x0000083au, 0x0004003du, 0x00000009u, 0x0000083cu, 0x0000083bu, 0x00050081u, 0x00000009u, 0x0000083du, + 0x00000838u, 0x0000083cu, 0x0005008eu, 0x00000009u, 0x0000083eu, 0x0000083du, 0x00000244u, 0x00050041u, + 0x0000000fu, 0x0000083fu, 0x000007e3u, 0x00000a05u, 0x0004003du, 0x00000009u, 0x00000840u, 0x0000083fu, + 0x00050081u, 0x00000009u, 0x00000841u, 0x00000840u, 0x0000083eu, 0x0003003eu, 0x0000083fu, 0x00000841u, + 0x00050080u, 0x00000016u, 0x00000845u, 0x00000a05u, 0x00000045u, 0x000200f9u, 0x0000082fu, 0x000200f8u, + 0x00000846u, 0x000200f9u, 0x00000847u, 0x000200f8u, 0x00000847u, 0x000700f5u, 0x00000016u, 0x00000a06u, + 0x00000048u, 0x00000846u, 0x0000085du, 0x0000084bu, 0x000500b1u, 0x00000025u, 0x0000084au, 0x00000a06u, + 0x0000033cu, 0x000400f6u, 0x0000085eu, 0x0000084bu, 0x00000000u, 0x000400fau, 0x0000084au, 0x0000084bu, + 0x0000085eu, 0x000200f8u, 0x0000084bu, 0x00050082u, 0x00000016u, 0x0000084eu, 0x00000a06u, 0x00000041u, + 0x00050041u, 0x0000000fu, 0x0000084fu, 0x000007e3u, 0x0000084eu, 0x0004003du, 0x00000009u, 0x00000850u, + 0x0000084fu, 0x00050080u, 0x00000016u, 0x00000852u, 0x00000a06u, 0x00000041u, 0x00050041u, 0x0000000fu, + 0x00000853u, 0x000007e3u, 0x00000852u, 0x0004003du, 0x00000009u, 0x00000854u, 0x00000853u, 0x00050081u, + 0x00000009u, 0x00000855u, 0x00000850u, 0x00000854u, 0x0005008eu, 0x00000009u, 0x00000856u, 0x00000855u, + 0x0000025fu, 0x00050041u, 0x0000000fu, 0x00000857u, 0x000007e3u, 0x00000a06u, 0x0004003du, 0x00000009u, + 0x00000858u, 0x00000857u, 0x00050081u, 0x00000009u, 0x00000859u, 0x00000858u, 0x00000856u, 0x0003003eu, + 0x00000857u, 0x00000859u, 0x00050080u, 0x00000016u, 0x0000085du, 0x00000a06u, 0x00000045u, 0x000200f9u, + 0x00000847u, 0x000200f8u, 0x0000085eu, 0x000200f9u, 0x0000085fu, 0x000200f8u, 0x0000085fu, 0x000700f5u, + 0x00000016u, 0x00000a07u, 0x00000099u, 0x0000085eu, 0x00000875u, 0x00000863u, 0x000500b1u, 0x00000025u, + 0x00000862u, 0x00000a07u, 0x0000011du, 0x000400f6u, 0x00000876u, 0x00000863u, 0x00000000u, 0x000400fau, + 0x00000862u, 0x00000863u, 0x00000876u, 0x000200f8u, 0x00000863u, 0x00050082u, 0x00000016u, 0x00000866u, + 0x00000a07u, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000867u, 0x000007e3u, 0x00000866u, 0x0004003du, + 0x00000009u, 0x00000868u, 0x00000867u, 0x00050080u, 0x00000016u, 0x0000086au, 0x00000a07u, 0x00000041u, + 0x00050041u, 0x0000000fu, 0x0000086bu, 0x000007e3u, 0x0000086au, 0x0004003du, 0x00000009u, 0x0000086cu, + 0x0000086bu, 0x00050081u, 0x00000009u, 0x0000086du, 0x00000868u, 0x0000086cu, 0x0005008eu, 0x00000009u, + 0x0000086eu, 0x0000086du, 0x0000027au, 0x00050041u, 0x0000000fu, 0x0000086fu, 0x000007e3u, 0x00000a07u, + 0x0004003du, 0x00000009u, 0x00000870u, 0x0000086fu, 0x00050081u, 0x00000009u, 0x00000871u, 0x00000870u, + 0x0000086eu, 0x0003003eu, 0x0000086fu, 0x00000871u, 0x00050080u, 0x00000016u, 0x00000875u, 0x00000a07u, + 0x00000045u, 0x000200f9u, 0x0000085fu, 0x000200f8u, 0x00000876u, 0x000200f9u, 0x00000877u, 0x000200f8u, + 0x00000877u, 0x000400e0u, 0x00000153u, 0x00000153u, 0x0000028bu, 0x000300f7u, 0x000008b3u, 0x00000000u, + 0x000400fau, 0x000003bcu, 0x00000879u, 0x000008b3u, 0x000200f8u, 0x00000879u, 0x000200f9u, 0x0000087au, + 0x000200f8u, 0x0000087au, 0x000700f5u, 0x00000016u, 0x00000a08u, 0x00000045u, 0x00000879u, 0x000008b1u, + 0x0000087eu, 0x000500b1u, 0x00000025u, 0x0000087du, 0x00000a08u, 0x00000099u, 0x000400f6u, 0x000008b2u, + 0x0000087eu, 0x00000000u, 0x000400fau, 0x0000087du, 0x0000087eu, 0x000008b2u, 0x000200f8u, 0x0000087eu, + 0x00050084u, 0x00000016u, 0x00000880u, 0x00000045u, 0x00000a08u, 0x00050041u, 0x0000000fu, 0x00000882u, + 0x000007e3u, 0x00000880u, 0x0004003du, 0x00000009u, 0x00000883u, 0x00000882u, 0x00050080u, 0x00000016u, + 0x00000886u, 0x00000880u, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000887u, 0x000007e3u, 0x00000886u, + 0x0004003du, 0x00000009u, 0x00000888u, 0x00000887u, 0x0005008eu, 0x00000009u, 0x0000088au, 0x00000883u, + 0x000002a1u, 0x0005008eu, 0x00000009u, 0x0000088cu, 0x00000888u, 0x000002a4u, 0x00050051u, 0x00000008u, + 0x0000088eu, 0x0000088au, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000890u, 0x0000088cu, 0x00000000u, + 0x00050050u, 0x00000009u, 0x00000891u, 0x0000088eu, 0x00000890u, 0x00050051u, 0x00000008u, 0x00000893u, + 0x0000088au, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000895u, 0x0000088cu, 0x00000001u, 0x00050050u, + 0x00000009u, 0x00000896u, 0x00000893u, 0x00000895u, 0x000500c3u, 0x00000016u, 0x00000899u, 0x000007f8u, + 0x00000041u, 0x00050082u, 0x00000016u, 0x0000089bu, 0x00000a08u, 0x00000045u, 0x00050080u, 0x00000016u, + 0x0000089cu, 0x00000899u, 0x0000089bu, 0x0004007cu, 0x00000006u, 0x0000089eu, 0x0000089cu, 0x00050084u, + 0x00000016u, 0x000008a1u, 0x00000045u, 0x000007feu, 0x0004007cu, 0x00000006u, 0x000008a3u, 0x000008a1u, + 0x00060041u, 0x00000035u, 0x000008beu, 0x00000032u, 0x0000089eu, 0x000008a3u, 0x0003003eu, 0x000008beu, + 0x00000891u, 0x00050080u, 0x00000016u, 0x000008abu, 0x000008a1u, 0x00000041u, 0x0004007cu, 0x00000006u, + 0x000008acu, 0x000008abu, 0x00060041u, 0x00000035u, 0x000008c3u, 0x00000032u, 0x0000089eu, 0x000008acu, + 0x0003003eu, 0x000008c3u, 0x00000896u, 0x00050080u, 0x00000016u, 0x000008b1u, 0x00000a08u, 0x00000041u, + 0x000200f9u, 0x0000087au, 0x000200f8u, 0x000008b2u, 0x000200f9u, 0x000008b3u, 0x000200f8u, 0x000008b3u, + 0x000400e0u, 0x00000153u, 0x00000153u, 0x0000028bu, 0x000200f9u, 0x000008e3u, 0x000200f8u, 0x000008e3u, + 0x000700f5u, 0x00000016u, 0x00000a09u, 0x00000040u, 0x000008b3u, 0x000008f6u, 0x000008e7u, 0x000500b1u, + 0x00000025u, 0x000008e6u, 0x00000a09u, 0x000000b8u, 0x000400f6u, 0x000008f7u, 0x000008e7u, 0x00000000u, + 0x000400fau, 0x000008e6u, 0x000008e7u, 0x000008f7u, 0x000200f8u, 0x000008e7u, 0x00050080u, 0x00000016u, + 0x000008eeu, 0x0000071bu, 0x00000a09u, 0x0004007cu, 0x00000006u, 0x000008efu, 0x000008eeu, 0x00060041u, + 0x00000035u, 0x00000995u, 0x00000032u, 0x000004edu, 0x000008efu, 0x0004003du, 0x00000009u, 0x00000996u, + 0x00000995u, 0x00050041u, 0x0000000fu, 0x000008f3u, 0x000008c9u, 0x00000a09u, 0x0003003eu, 0x000008f3u, + 0x00000996u, 0x00050080u, 0x00000016u, 0x000008f6u, 0x00000a09u, 0x00000041u, 0x000200f9u, 0x000008e3u, + 0x000200f8u, 0x000008f7u, 0x000200f9u, 0x000008f8u, 0x000200f8u, 0x000008f8u, 0x000700f5u, 0x00000016u, + 0x00000a0au, 0x00000041u, 0x000008f7u, 0x0000090eu, 0x000008fcu, 0x000500b1u, 0x00000025u, 0x000008fbu, + 0x00000a0au, 0x00000226u, 0x000400f6u, 0x0000090fu, 0x000008fcu, 0x00000000u, 0x000400fau, 0x000008fbu, + 0x000008fcu, 0x0000090fu, 0x000200f8u, 0x000008fcu, 0x00050082u, 0x00000016u, 0x000008ffu, 0x00000a0au, + 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000900u, 0x000008c9u, 0x000008ffu, 0x0004003du, 0x00000009u, + 0x00000901u, 0x00000900u, 0x00050080u, 0x00000016u, 0x00000903u, 0x00000a0au, 0x00000041u, 0x00050041u, + 0x0000000fu, 0x00000904u, 0x000008c9u, 0x00000903u, 0x0004003du, 0x00000009u, 0x00000905u, 0x00000904u, + 0x00050081u, 0x00000009u, 0x00000906u, 0x00000901u, 0x00000905u, 0x0005008eu, 0x00000009u, 0x00000907u, + 0x00000906u, 0x00000229u, 0x00050041u, 0x0000000fu, 0x00000908u, 0x000008c9u, 0x00000a0au, 0x0004003du, + 0x00000009u, 0x00000909u, 0x00000908u, 0x00050081u, 0x00000009u, 0x0000090au, 0x00000909u, 0x00000907u, + 0x0003003eu, 0x00000908u, 0x0000090au, 0x00050080u, 0x00000016u, 0x0000090eu, 0x00000a0au, 0x00000045u, + 0x000200f9u, 0x000008f8u, 0x000200f8u, 0x0000090fu, 0x000200f9u, 0x00000910u, 0x000200f8u, 0x00000910u, + 0x000700f5u, 0x00000016u, 0x00000a0bu, 0x00000045u, 0x0000090fu, 0x00000926u, 0x00000914u, 0x000500b1u, + 0x00000025u, 0x00000913u, 0x00000a0bu, 0x00000241u, 0x000400f6u, 0x00000927u, 0x00000914u, 0x00000000u, + 0x000400fau, 0x00000913u, 0x00000914u, 0x00000927u, 0x000200f8u, 0x00000914u, 0x00050082u, 0x00000016u, + 0x00000917u, 0x00000a0bu, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000918u, 0x000008c9u, 0x00000917u, + 0x0004003du, 0x00000009u, 0x00000919u, 0x00000918u, 0x00050080u, 0x00000016u, 0x0000091bu, 0x00000a0bu, + 0x00000041u, 0x00050041u, 0x0000000fu, 0x0000091cu, 0x000008c9u, 0x0000091bu, 0x0004003du, 0x00000009u, + 0x0000091du, 0x0000091cu, 0x00050081u, 0x00000009u, 0x0000091eu, 0x00000919u, 0x0000091du, 0x0005008eu, + 0x00000009u, 0x0000091fu, 0x0000091eu, 0x00000244u, 0x00050041u, 0x0000000fu, 0x00000920u, 0x000008c9u, + 0x00000a0bu, 0x0004003du, 0x00000009u, 0x00000921u, 0x00000920u, 0x00050081u, 0x00000009u, 0x00000922u, + 0x00000921u, 0x0000091fu, 0x0003003eu, 0x00000920u, 0x00000922u, 0x00050080u, 0x00000016u, 0x00000926u, + 0x00000a0bu, 0x00000045u, 0x000200f9u, 0x00000910u, 0x000200f8u, 0x00000927u, 0x000200f9u, 0x00000928u, + 0x000200f8u, 0x00000928u, 0x000700f5u, 0x00000016u, 0x00000a0cu, 0x00000048u, 0x00000927u, 0x0000093eu, + 0x0000092cu, 0x000500b1u, 0x00000025u, 0x0000092bu, 0x00000a0cu, 0x0000025cu, 0x000400f6u, 0x0000093fu, + 0x0000092cu, 0x00000000u, 0x000400fau, 0x0000092bu, 0x0000092cu, 0x0000093fu, 0x000200f8u, 0x0000092cu, + 0x00050082u, 0x00000016u, 0x0000092fu, 0x00000a0cu, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000930u, + 0x000008c9u, 0x0000092fu, 0x0004003du, 0x00000009u, 0x00000931u, 0x00000930u, 0x00050080u, 0x00000016u, + 0x00000933u, 0x00000a0cu, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000934u, 0x000008c9u, 0x00000933u, + 0x0004003du, 0x00000009u, 0x00000935u, 0x00000934u, 0x00050081u, 0x00000009u, 0x00000936u, 0x00000931u, + 0x00000935u, 0x0005008eu, 0x00000009u, 0x00000937u, 0x00000936u, 0x0000025fu, 0x00050041u, 0x0000000fu, + 0x00000938u, 0x000008c9u, 0x00000a0cu, 0x0004003du, 0x00000009u, 0x00000939u, 0x00000938u, 0x00050081u, + 0x00000009u, 0x0000093au, 0x00000939u, 0x00000937u, 0x0003003eu, 0x00000938u, 0x0000093au, 0x00050080u, + 0x00000016u, 0x0000093eu, 0x00000a0cu, 0x00000045u, 0x000200f9u, 0x00000928u, 0x000200f8u, 0x0000093fu, + 0x000200f9u, 0x00000940u, 0x000200f8u, 0x00000940u, 0x000700f5u, 0x00000016u, 0x00000a0du, 0x00000099u, + 0x0000093fu, 0x00000956u, 0x00000944u, 0x000500b1u, 0x00000025u, 0x00000943u, 0x00000a0du, 0x00000277u, + 0x000400f6u, 0x00000957u, 0x00000944u, 0x00000000u, 0x000400fau, 0x00000943u, 0x00000944u, 0x00000957u, + 0x000200f8u, 0x00000944u, 0x00050082u, 0x00000016u, 0x00000947u, 0x00000a0du, 0x00000041u, 0x00050041u, + 0x0000000fu, 0x00000948u, 0x000008c9u, 0x00000947u, 0x0004003du, 0x00000009u, 0x00000949u, 0x00000948u, + 0x00050080u, 0x00000016u, 0x0000094bu, 0x00000a0du, 0x00000041u, 0x00050041u, 0x0000000fu, 0x0000094cu, + 0x000008c9u, 0x0000094bu, 0x0004003du, 0x00000009u, 0x0000094du, 0x0000094cu, 0x00050081u, 0x00000009u, + 0x0000094eu, 0x00000949u, 0x0000094du, 0x0005008eu, 0x00000009u, 0x0000094fu, 0x0000094eu, 0x0000027au, + 0x00050041u, 0x0000000fu, 0x00000950u, 0x000008c9u, 0x00000a0du, 0x0004003du, 0x00000009u, 0x00000951u, + 0x00000950u, 0x00050081u, 0x00000009u, 0x00000952u, 0x00000951u, 0x0000094fu, 0x0003003eu, 0x00000950u, + 0x00000952u, 0x00050080u, 0x00000016u, 0x00000956u, 0x00000a0du, 0x00000045u, 0x000200f9u, 0x00000940u, + 0x000200f8u, 0x00000957u, 0x000400e0u, 0x00000153u, 0x00000153u, 0x0000028bu, 0x000200f9u, 0x00000958u, + 0x000200f8u, 0x00000958u, 0x000700f5u, 0x00000016u, 0x00000a0eu, 0x00000045u, 0x00000957u, 0x0000098fu, + 0x0000095cu, 0x000500b1u, 0x00000025u, 0x0000095bu, 0x00000a0eu, 0x00000293u, 0x000400f6u, 0x00000990u, + 0x0000095cu, 0x00000000u, 0x000400fau, 0x0000095bu, 0x0000095cu, 0x00000990u, 0x000200f8u, 0x0000095cu, + 0x00050084u, 0x00000016u, 0x0000095eu, 0x00000045u, 0x00000a0eu, 0x00050041u, 0x0000000fu, 0x00000960u, + 0x000008c9u, 0x0000095eu, 0x0004003du, 0x00000009u, 0x00000961u, 0x00000960u, 0x00050080u, 0x00000016u, + 0x00000964u, 0x0000095eu, 0x00000041u, 0x00050041u, 0x0000000fu, 0x00000965u, 0x000008c9u, 0x00000964u, + 0x0004003du, 0x00000009u, 0x00000966u, 0x00000965u, 0x0005008eu, 0x00000009u, 0x00000968u, 0x00000961u, + 0x000002a1u, 0x0005008eu, 0x00000009u, 0x0000096au, 0x00000966u, 0x000002a4u, 0x00050051u, 0x00000008u, + 0x0000096cu, 0x00000968u, 0x00000000u, 0x00050051u, 0x00000008u, 0x0000096eu, 0x0000096au, 0x00000000u, + 0x00050050u, 0x00000009u, 0x0000096fu, 0x0000096cu, 0x0000096eu, 0x00050051u, 0x00000008u, 0x00000971u, + 0x00000968u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000973u, 0x0000096au, 0x00000001u, 0x00050050u, + 0x00000009u, 0x00000974u, 0x00000971u, 0x00000973u, 0x000500c3u, 0x00000016u, 0x00000977u, 0x0000071bu, + 0x00000041u, 0x00050082u, 0x00000016u, 0x00000979u, 0x00000a0eu, 0x00000045u, 0x00050080u, 0x00000016u, + 0x0000097au, 0x00000977u, 0x00000979u, 0x0004007cu, 0x00000006u, 0x0000097cu, 0x0000097au, 0x00050084u, + 0x00000016u, 0x0000097fu, 0x00000045u, 0x0000071eu, 0x0004007cu, 0x00000006u, 0x00000981u, 0x0000097fu, + 0x00060041u, 0x00000035u, 0x0000099bu, 0x00000032u, 0x0000097cu, 0x00000981u, 0x0003003eu, 0x0000099bu, + 0x0000096fu, 0x00050080u, 0x00000016u, 0x00000989u, 0x0000097fu, 0x00000041u, 0x0004007cu, 0x00000006u, + 0x0000098au, 0x00000989u, 0x00060041u, 0x00000035u, 0x000009a0u, 0x00000032u, 0x0000097cu, 0x0000098au, + 0x0003003eu, 0x000009a0u, 0x00000974u, 0x00050080u, 0x00000016u, 0x0000098fu, 0x00000a0eu, 0x00000041u, + 0x000200f9u, 0x00000958u, 0x000200f8u, 0x00000990u, 0x000400e0u, 0x00000153u, 0x00000153u, 0x0000028bu, + 0x000200f9u, 0x000003c8u, 0x000200f8u, 0x000003c8u, 0x000700f5u, 0x00000016u, 0x00000a0fu, 0x00000585u, + 0x00000990u, 0x0000041eu, 0x000003cbu, 0x000500b1u, 0x00000025u, 0x000003ceu, 0x00000a0fu, 0x000000b8u, + 0x000400f6u, 0x000003cau, 0x000003cbu, 0x00000000u, 0x000400fau, 0x000003ceu, 0x000003c9u, 0x000003cau, + 0x000200f8u, 0x000003c9u, 0x00050084u, 0x00000016u, 0x000003d2u, 0x00000583u, 0x00000045u, 0x000200f9u, + 0x000003d3u, 0x000200f8u, 0x000003d3u, 0x000700f5u, 0x00000016u, 0x00000a10u, 0x000003d2u, 0x000003c9u, + 0x0000041cu, 0x000003d4u, 0x000500b1u, 0x00000025u, 0x000003d9u, 0x00000a10u, 0x00000096u, 0x000400f6u, + 0x000003d5u, 0x000003d4u, 0x00000000u, 0x000400fau, 0x000003d9u, 0x000003d4u, 0x000003d5u, 0x000200f8u, + 0x000003d4u, 0x0004007cu, 0x00000006u, 0x000003dcu, 0x00000a0fu, 0x0004007cu, 0x00000006u, 0x000003dfu, + 0x00000a10u, 0x00060041u, 0x00000035u, 0x000009bcu, 0x00000032u, 0x000003dcu, 0x000003dfu, 0x0004003du, + 0x00000009u, 0x000009bdu, 0x000009bcu, 0x00050080u, 0x00000016u, 0x000003e7u, 0x00000a10u, 0x00000041u, + 0x0004007cu, 0x00000006u, 0x000003e8u, 0x000003e7u, 0x00060041u, 0x00000035u, 0x000009c2u, 0x00000032u, + 0x000003dcu, 0x000003e8u, 0x0004003du, 0x00000009u, 0x000009c3u, 0x000009c2u, 0x000500c3u, 0x00000016u, + 0x000003eeu, 0x00000a10u, 0x00000041u, 0x00050084u, 0x00000017u, 0x000003f6u, 0x00000464u, 0x000000cbu, + 0x00050050u, 0x00000017u, 0x000003f9u, 0x000003eeu, 0x00000a0fu, 0x00050080u, 0x00000017u, 0x000003fau, + 0x000003f6u, 0x000003f9u, 0x0004003du, 0x000003fbu, 0x000003feu, 0x000003fdu, 0x00050051u, 0x00000016u, + 0x00000401u, 0x000003fau, 0x00000000u, 0x00050051u, 0x00000016u, 0x00000402u, 0x000003fau, 0x00000001u, + 0x00060050u, 0x00000400u, 0x00000403u, 0x00000401u, 0x00000402u, 0x00000040u, 0x0009004fu, 0x000000a8u, + 0x00000405u, 0x000009bdu, 0x000009bdu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00040063u, + 0x000003feu, 0x00000403u, 0x00000405u, 0x0004003du, 0x000003fbu, 0x00000406u, 0x000003fdu, 0x00060050u, + 0x00000400u, 0x0000040au, 0x00000401u, 0x00000402u, 0x00000045u, 0x0009004fu, 0x000000a8u, 0x0000040cu, + 0x000009bdu, 0x000009bdu, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00040063u, 0x00000406u, + 0x0000040au, 0x0000040cu, 0x0004003du, 0x000003fbu, 0x0000040du, 0x000003fdu, 0x00060050u, 0x00000400u, + 0x00000411u, 0x00000401u, 0x00000402u, 0x00000041u, 0x0009004fu, 0x000000a8u, 0x00000413u, 0x000009c3u, + 0x000009c3u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00040063u, 0x0000040du, 0x00000411u, + 0x00000413u, 0x0004003du, 0x000003fbu, 0x00000414u, 0x000003fdu, 0x00060050u, 0x00000400u, 0x00000418u, + 0x00000401u, 0x00000402u, 0x00000048u, 0x0009004fu, 0x000000a8u, 0x0000041au, 0x000009c3u, 0x000009c3u, + 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00040063u, 0x00000414u, 0x00000418u, 0x0000041au, + 0x00050080u, 0x00000016u, 0x0000041cu, 0x00000a10u, 0x000000b8u, 0x000200f9u, 0x000003d3u, 0x000200f8u, + 0x000003d5u, 0x000200f9u, 0x000003cbu, 0x000200f8u, 0x000003cbu, 0x00050080u, 0x00000016u, 0x0000041eu, + 0x00000a0fu, 0x0000011du, 0x000200f9u, 0x000003c8u, 0x000200f8u, 0x000003cau, 0x000100fdu, 0x00010038u, + 0x07230203u, 0x00010300u, 0x000d000bu, 0x00000a2bu, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, + 0x00000009u, 0x00020011u, 0x00000038u, 0x00020011u, 0x0000003du, 0x0006000bu, 0x00000001u, 0x4c534c47u, + 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0009000fu, 0x00000005u, + 0x00000004u, 0x6e69616du, 0x00000000u, 0x00000093u, 0x000003bbu, 0x000003bdu, 0x000003c0u, 0x00060010u, + 0x00000004u, 0x00000011u, 0x00000040u, 0x00000001u, 0x00000001u, 0x00030047u, 0x00000068u, 0x00000002u, + 0x00050048u, 0x00000068u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x00000068u, 0x00000001u, + 0x00000023u, 0x00000008u, 0x00050048u, 0x00000068u, 0x00000002u, 0x00000023u, 0x00000010u, 0x00040047u, + 0x00000093u, 0x0000000bu, 0x0000001au, 0x00030047u, 0x000000b0u, 0x00000000u, 0x00040047u, 0x000000b0u, + 0x00000021u, 0x00000000u, 0x00040047u, 0x000000b0u, 0x00000022u, 0x00000000u, 0x00040047u, 0x000000d8u, + 0x00000001u, 0x00000000u, 0x00040047u, 0x000003bbu, 0x0000000bu, 0x00000028u, 0x00030047u, 0x000003bdu, + 0x00000000u, 0x00040047u, 0x000003bdu, 0x0000000bu, 0x00000024u, 0x00030047u, 0x000003beu, 0x00000000u, + 0x00030047u, 0x000003c0u, 0x00000000u, 0x00040047u, 0x000003c0u, 0x0000000bu, 0x00000029u, 0x00030047u, + 0x000003c1u, 0x00000000u, 0x00030047u, 0x00000407u, 0x00000000u, 0x00030047u, 0x00000407u, 0x00000019u, + 0x00040047u, 0x00000407u, 0x00000021u, 0x00000001u, 0x00040047u, 0x00000407u, 0x00000022u, 0x00000000u, + 0x00030047u, 0x00000408u, 0x00000000u, 0x00030047u, 0x00000411u, 0x00000000u, 0x00030047u, 0x00000419u, + 0x00000000u, 0x00030047u, 0x00000421u, 0x00000000u, 0x00040047u, 0x0000042eu, 0x0000000bu, 0x00000019u, + 0x00030047u, 0x0000047du, 0x00000000u, 0x00030047u, 0x00000480u, 0x00000000u, 0x00030047u, 0x00000483u, + 0x00000000u, 0x00030047u, 0x00000487u, 0x00000000u, 0x00030047u, 0x0000048au, 0x00000000u, 0x00030047u, + 0x0000048eu, 0x00000000u, 0x00030047u, 0x00000491u, 0x00000000u, 0x00030047u, 0x00000495u, 0x00000000u, + 0x00030047u, 0x00000503u, 0x00000000u, 0x00030047u, 0x00000508u, 0x00000000u, 0x00030047u, 0x00000530u, + 0x00000000u, 0x00030047u, 0x00000535u, 0x00000000u, 0x00030047u, 0x00000561u, 0x00000000u, 0x00030047u, + 0x00000566u, 0x00000000u, 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, + 0x00000006u, 0x00000020u, 0x00000000u, 0x00030016u, 0x00000008u, 0x00000010u, 0x00040017u, 0x00000009u, + 0x00000008u, 0x00000002u, 0x00040020u, 0x0000000fu, 0x00000007u, 0x00000009u, 0x00040015u, 0x00000016u, + 0x00000020u, 0x00000001u, 0x00040017u, 0x00000017u, 0x00000016u, 0x00000002u, 0x00030016u, 0x0000001du, + 0x00000020u, 0x00040017u, 0x0000001eu, 0x0000001du, 0x00000002u, 0x00020014u, 0x00000027u, 0x0004002bu, + 0x00000006u, 0x0000002fu, 0x00000029u, 0x0004001cu, 0x00000030u, 0x00000009u, 0x0000002fu, 0x0004002bu, + 0x00000006u, 0x00000031u, 0x00000014u, 0x0004001cu, 0x00000032u, 0x00000030u, 0x00000031u, 0x00040020u, + 0x00000033u, 0x00000004u, 0x00000032u, 0x0004003bu, 0x00000033u, 0x00000034u, 0x00000004u, 0x00040020u, + 0x00000037u, 0x00000004u, 0x00000009u, 0x0004002bu, 0x00000016u, 0x00000042u, 0x00000000u, 0x0004002bu, + 0x00000016u, 0x00000043u, 0x00000001u, 0x0004002bu, 0x00000016u, 0x00000047u, 0x00000002u, 0x0004002bu, + 0x00000016u, 0x0000004au, 0x00000003u, 0x0004002bu, 0x00000016u, 0x00000050u, 0x00000005u, 0x0005002cu, + 0x00000017u, 0x0000005du, 0x00000042u, 0x00000042u, 0x00040017u, 0x0000005eu, 0x00000027u, 0x00000002u, + 0x0005002cu, 0x00000017u, 0x00000060u, 0x00000043u, 0x00000043u, 0x0005001eu, 0x00000068u, 0x00000017u, + 0x0000001eu, 0x00000017u, 0x00040020u, 0x00000069u, 0x00000009u, 0x00000068u, 0x0004003bu, 0x00000069u, + 0x0000006au, 0x00000009u, 0x00040020u, 0x0000006bu, 0x00000009u, 0x00000017u, 0x00040020u, 0x0000008au, + 0x00000009u, 0x0000001eu, 0x00040017u, 0x00000091u, 0x00000006u, 0x00000003u, 0x00040020u, 0x00000092u, + 0x00000001u, 0x00000091u, 0x0004003bu, 0x00000092u, 0x00000093u, 0x00000001u, 0x00040017u, 0x00000094u, + 0x00000006u, 0x00000002u, 0x0004002bu, 0x00000016u, 0x00000098u, 0x00000020u, 0x0005002cu, 0x00000017u, + 0x00000099u, 0x00000098u, 0x00000098u, 0x0004002bu, 0x00000016u, 0x0000009bu, 0x00000004u, 0x00040017u, + 0x000000aau, 0x00000008u, 0x00000004u, 0x00090019u, 0x000000adu, 0x0000001du, 0x00000001u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x0003001bu, 0x000000aeu, 0x000000adu, 0x00040020u, + 0x000000afu, 0x00000000u, 0x000000aeu, 0x0004003bu, 0x000000afu, 0x000000b0u, 0x00000000u, 0x00040017u, + 0x000000b5u, 0x0000001du, 0x00000004u, 0x0004002bu, 0x00000016u, 0x000000bcu, 0x00000010u, 0x0005002cu, + 0x00000017u, 0x000000bdu, 0x000000bcu, 0x00000042u, 0x0005002cu, 0x00000017u, 0x000000c7u, 0x00000042u, + 0x000000bcu, 0x0005002cu, 0x00000017u, 0x000000d1u, 0x000000bcu, 0x000000bcu, 0x00030031u, 0x00000027u, + 0x000000d8u, 0x0004002bu, 0x00000008u, 0x000000dbu, 0x00003800u, 0x0004002bu, 0x00000006u, 0x000000e9u, + 0x00000001u, 0x0004002bu, 0x00000016u, 0x0000011au, 0x00000011u, 0x0004002bu, 0x00000016u, 0x00000124u, + 0x00000008u, 0x0004002bu, 0x00000006u, 0x00000159u, 0x00000020u, 0x0004002bu, 0x00000006u, 0x0000015au, + 0x00000002u, 0x0004002bu, 0x00000006u, 0x0000015cu, 0x00000004u, 0x0004002bu, 0x00000006u, 0x00000193u, + 0x00000010u, 0x0004002bu, 0x00000006u, 0x00000204u, 0x00000008u, 0x0004001cu, 0x00000221u, 0x00000009u, + 0x00000193u, 0x00040020u, 0x00000222u, 0x00000007u, 0x00000221u, 0x0004002bu, 0x00000016u, 0x00000230u, + 0x0000000fu, 0x0004002bu, 0x00000008u, 0x00000233u, 0x0000be58u, 0x0004002bu, 0x00000016u, 0x0000024bu, + 0x0000000eu, 0x0004002bu, 0x00000008u, 0x0000024eu, 0x0000aac8u, 0x0004002bu, 0x00000016u, 0x00000266u, + 0x0000000du, 0x0004002bu, 0x00000008u, 0x00000269u, 0x00003b10u, 0x0004002bu, 0x00000016u, 0x00000281u, + 0x0000000cu, 0x0004002bu, 0x00000008u, 0x00000284u, 0x00003718u, 0x0004002bu, 0x00000006u, 0x00000295u, + 0x00000108u, 0x0004002bu, 0x00000016u, 0x0000029du, 0x00000006u, 0x0004002bu, 0x00000008u, 0x000002abu, + 0x00003a80u, 0x0004002bu, 0x00000008u, 0x000002aeu, 0x00003cebu, 0x0004002bu, 0x00000006u, 0x00000302u, + 0x0000000cu, 0x0004001cu, 0x00000303u, 0x00000009u, 0x00000302u, 0x00040020u, 0x00000304u, 0x00000007u, + 0x00000303u, 0x0004002bu, 0x00000016u, 0x00000312u, 0x0000000bu, 0x0004002bu, 0x00000016u, 0x0000032cu, + 0x0000000au, 0x0004002bu, 0x00000016u, 0x00000346u, 0x00000009u, 0x00040020u, 0x000003bau, 0x00000001u, + 0x00000006u, 0x0004003bu, 0x000003bau, 0x000003bbu, 0x00000001u, 0x0004003bu, 0x000003bau, 0x000003bdu, + 0x00000001u, 0x0004003bu, 0x000003bau, 0x000003c0u, 0x00000001u, 0x00090019u, 0x00000405u, 0x0000001du, + 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000002u, 0x00000000u, 0x00040020u, 0x00000406u, + 0x00000000u, 0x00000405u, 0x0004003bu, 0x00000406u, 0x00000407u, 0x00000000u, 0x00040017u, 0x0000040au, + 0x00000016u, 0x00000003u, 0x0004002bu, 0x00000006u, 0x0000042du, 0x00000040u, 0x0006002cu, 0x00000091u, + 0x0000042eu, 0x0000042du, 0x000000e9u, 0x000000e9u, 0x0005002cu, 0x00000017u, 0x00000a28u, 0x0000009bu, + 0x0000009bu, 0x0005002cu, 0x00000017u, 0x00000a29u, 0x00000047u, 0x00000047u, 0x0007002cu, 0x000000aau, + 0x00000a2au, 0x000000dbu, 0x000000dbu, 0x000000dbu, 0x000000dbu, 0x00050036u, 0x00000002u, 0x00000004u, + 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, 0x00000222u, 0x000008dfu, 0x00000007u, + 0x0004003bu, 0x00000304u, 0x000007f9u, 0x00000007u, 0x0004003bu, 0x00000222u, 0x0000071cu, 0x00000007u, + 0x0004003du, 0x00000006u, 0x000003bcu, 0x000003bbu, 0x0004003du, 0x00000006u, 0x000003beu, 0x000003bdu, + 0x00050084u, 0x00000006u, 0x000003bfu, 0x000003bcu, 0x000003beu, 0x0004003du, 0x00000006u, 0x000003c1u, + 0x000003c0u, 0x00050080u, 0x00000006u, 0x000003c2u, 0x000003bfu, 0x000003c1u, 0x0004003du, 0x00000091u, + 0x00000470u, 0x00000093u, 0x0007004fu, 0x00000094u, 0x00000471u, 0x00000470u, 0x00000470u, 0x00000000u, + 0x00000001u, 0x0004007cu, 0x00000017u, 0x00000472u, 0x00000471u, 0x00050084u, 0x00000017u, 0x00000473u, + 0x00000472u, 0x00000099u, 0x00050082u, 0x00000017u, 0x00000475u, 0x00000473u, 0x00000a28u, 0x000600cbu, + 0x00000006u, 0x0000058au, 0x000003c2u, 0x00000042u, 0x00000043u, 0x000600cbu, 0x00000006u, 0x0000058cu, + 0x000003c2u, 0x00000043u, 0x00000047u, 0x000600cbu, 0x00000006u, 0x0000058eu, 0x000003c2u, 0x0000004au, + 0x00000047u, 0x000500c4u, 0x00000006u, 0x0000058fu, 0x0000058eu, 0x00000043u, 0x000500c5u, 0x00000006u, + 0x00000591u, 0x0000058au, 0x0000058fu, 0x000600cbu, 0x00000006u, 0x00000593u, 0x000003c2u, 0x00000050u, + 0x00000043u, 0x000500c4u, 0x00000006u, 0x00000594u, 0x00000593u, 0x00000047u, 0x000500c5u, 0x00000006u, + 0x00000596u, 0x0000058cu, 0x00000594u, 0x0004007cu, 0x00000016u, 0x00000598u, 0x00000596u, 0x0004007cu, + 0x00000016u, 0x0000059au, 0x00000591u, 0x00050050u, 0x00000017u, 0x0000059bu, 0x00000598u, 0x0000059au, + 0x00050084u, 0x00000017u, 0x00000479u, 0x00000a29u, 0x0000059bu, 0x00050080u, 0x00000017u, 0x0000047cu, + 0x00000475u, 0x00000479u, 0x0004003du, 0x000000aeu, 0x0000047du, 0x000000b0u, 0x000500b1u, 0x0000005eu, + 0x000005a2u, 0x0000047cu, 0x0000005du, 0x000600a9u, 0x00000017u, 0x000005a3u, 0x000005a2u, 0x00000060u, + 0x0000005du, 0x00050082u, 0x00000017u, 0x000005a5u, 0x0000047cu, 0x000005a3u, 0x00050080u, 0x00000017u, + 0x000005a8u, 0x000005a5u, 0x00000060u, 0x00050041u, 0x0000006bu, 0x000005a9u, 0x0000006au, 0x00000047u, + 0x0004003du, 0x00000017u, 0x000005aau, 0x000005a9u, 0x00050084u, 0x00000017u, 0x000005acu, 0x00000a29u, + 0x000005aau, 0x00050041u, 0x0000006bu, 0x000005adu, 0x0000006au, 0x00000042u, 0x0004003du, 0x00000017u, + 0x000005aeu, 0x000005adu, 0x00050082u, 0x00000017u, 0x000005afu, 0x000005acu, 0x000005aeu, 0x00050082u, + 0x00000017u, 0x000005b5u, 0x000005aeu, 0x000005aau, 0x00050084u, 0x00000017u, 0x000005b7u, 0x00000a29u, + 0x000005b5u, 0x00050080u, 0x00000017u, 0x000005b8u, 0x000005a8u, 0x000005b7u, 0x00050080u, 0x00000017u, + 0x000005bau, 0x000005b8u, 0x00000060u, 0x0007000cu, 0x00000017u, 0x000005beu, 0x00000001u, 0x00000027u, + 0x000005a8u, 0x000005aeu, 0x000500afu, 0x0000005eu, 0x000005c2u, 0x000005a8u, 0x000005afu, 0x000600a9u, + 0x00000017u, 0x000005c3u, 0x000005c2u, 0x000005bau, 0x000005beu, 0x0004006fu, 0x0000001eu, 0x000005c5u, + 0x000005c3u, 0x00050041u, 0x0000008au, 0x000005c6u, 0x0000006au, 0x00000043u, 0x0004003du, 0x0000001eu, + 0x000005c7u, 0x000005c6u, 0x00050085u, 0x0000001eu, 0x000005c8u, 0x000005c5u, 0x000005c7u, 0x00060060u, + 0x000000b5u, 0x00000480u, 0x0000047du, 0x000005c8u, 0x00000042u, 0x00040073u, 0x000000aau, 0x00000481u, + 0x00000480u, 0x0009004fu, 0x000000aau, 0x00000482u, 0x00000481u, 0x00000481u, 0x00000003u, 0x00000002u, + 0x00000000u, 0x00000001u, 0x0004003du, 0x000000aeu, 0x00000483u, 0x000000b0u, 0x00050080u, 0x00000017u, + 0x00000485u, 0x0000047cu, 0x000000bdu, 0x000500b1u, 0x0000005eu, 0x000005ceu, 0x00000485u, 0x0000005du, + 0x000600a9u, 0x00000017u, 0x000005cfu, 0x000005ceu, 0x00000060u, 0x0000005du, 0x00050082u, 0x00000017u, + 0x000005d1u, 0x00000485u, 0x000005cfu, 0x00050080u, 0x00000017u, 0x000005d4u, 0x000005d1u, 0x00000060u, + 0x00050080u, 0x00000017u, 0x000005e4u, 0x000005d4u, 0x000005b7u, 0x00050080u, 0x00000017u, 0x000005e6u, + 0x000005e4u, 0x00000060u, 0x0007000cu, 0x00000017u, 0x000005eau, 0x00000001u, 0x00000027u, 0x000005d4u, + 0x000005aeu, 0x000500afu, 0x0000005eu, 0x000005eeu, 0x000005d4u, 0x000005afu, 0x000600a9u, 0x00000017u, + 0x000005efu, 0x000005eeu, 0x000005e6u, 0x000005eau, 0x0004006fu, 0x0000001eu, 0x000005f1u, 0x000005efu, + 0x00050085u, 0x0000001eu, 0x000005f4u, 0x000005f1u, 0x000005c7u, 0x00060060u, 0x000000b5u, 0x00000487u, + 0x00000483u, 0x000005f4u, 0x00000042u, 0x00040073u, 0x000000aau, 0x00000488u, 0x00000487u, 0x0009004fu, + 0x000000aau, 0x00000489u, 0x00000488u, 0x00000488u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, + 0x0004003du, 0x000000aeu, 0x0000048au, 0x000000b0u, 0x00050080u, 0x00000017u, 0x0000048cu, 0x0000047cu, + 0x000000c7u, 0x000500b1u, 0x0000005eu, 0x000005fau, 0x0000048cu, 0x0000005du, 0x000600a9u, 0x00000017u, + 0x000005fbu, 0x000005fau, 0x00000060u, 0x0000005du, 0x00050082u, 0x00000017u, 0x000005fdu, 0x0000048cu, + 0x000005fbu, 0x00050080u, 0x00000017u, 0x00000600u, 0x000005fdu, 0x00000060u, 0x00050080u, 0x00000017u, + 0x00000610u, 0x00000600u, 0x000005b7u, 0x00050080u, 0x00000017u, 0x00000612u, 0x00000610u, 0x00000060u, + 0x0007000cu, 0x00000017u, 0x00000616u, 0x00000001u, 0x00000027u, 0x00000600u, 0x000005aeu, 0x000500afu, + 0x0000005eu, 0x0000061au, 0x00000600u, 0x000005afu, 0x000600a9u, 0x00000017u, 0x0000061bu, 0x0000061au, + 0x00000612u, 0x00000616u, 0x0004006fu, 0x0000001eu, 0x0000061du, 0x0000061bu, 0x00050085u, 0x0000001eu, + 0x00000620u, 0x0000061du, 0x000005c7u, 0x00060060u, 0x000000b5u, 0x0000048eu, 0x0000048au, 0x00000620u, + 0x00000042u, 0x00040073u, 0x000000aau, 0x0000048fu, 0x0000048eu, 0x0009004fu, 0x000000aau, 0x00000490u, + 0x0000048fu, 0x0000048fu, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x0004003du, 0x000000aeu, + 0x00000491u, 0x000000b0u, 0x00050080u, 0x00000017u, 0x00000493u, 0x0000047cu, 0x000000d1u, 0x000500b1u, + 0x0000005eu, 0x00000626u, 0x00000493u, 0x0000005du, 0x000600a9u, 0x00000017u, 0x00000627u, 0x00000626u, + 0x00000060u, 0x0000005du, 0x00050082u, 0x00000017u, 0x00000629u, 0x00000493u, 0x00000627u, 0x00050080u, + 0x00000017u, 0x0000062cu, 0x00000629u, 0x00000060u, 0x00050080u, 0x00000017u, 0x0000063cu, 0x0000062cu, + 0x000005b7u, 0x00050080u, 0x00000017u, 0x0000063eu, 0x0000063cu, 0x00000060u, 0x0007000cu, 0x00000017u, + 0x00000642u, 0x00000001u, 0x00000027u, 0x0000062cu, 0x000005aeu, 0x000500afu, 0x0000005eu, 0x00000646u, + 0x0000062cu, 0x000005afu, 0x000600a9u, 0x00000017u, 0x00000647u, 0x00000646u, 0x0000063eu, 0x00000642u, + 0x0004006fu, 0x0000001eu, 0x00000649u, 0x00000647u, 0x00050085u, 0x0000001eu, 0x0000064cu, 0x00000649u, + 0x000005c7u, 0x00060060u, 0x000000b5u, 0x00000495u, 0x00000491u, 0x0000064cu, 0x00000042u, 0x00040073u, + 0x000000aau, 0x00000496u, 0x00000495u, 0x0009004fu, 0x000000aau, 0x00000497u, 0x00000496u, 0x00000496u, + 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, 0x000004a5u, 0x00000000u, 0x000400fau, + 0x000000d8u, 0x00000498u, 0x000004a5u, 0x000200f8u, 0x00000498u, 0x00050083u, 0x000000aau, 0x0000049bu, + 0x00000482u, 0x00000a2au, 0x00050083u, 0x000000aau, 0x0000049eu, 0x00000489u, 0x00000a2au, 0x00050083u, + 0x000000aau, 0x000004a1u, 0x00000490u, 0x00000a2au, 0x00050083u, 0x000000aau, 0x000004a4u, 0x00000497u, + 0x00000a2au, 0x000200f9u, 0x000004a5u, 0x000200f8u, 0x000004a5u, 0x000700f5u, 0x000000aau, 0x00000a0fu, + 0x00000497u, 0x00000005u, 0x000004a4u, 0x00000498u, 0x000700f5u, 0x000000aau, 0x00000a0eu, 0x00000490u, + 0x00000005u, 0x000004a1u, 0x00000498u, 0x000700f5u, 0x000000aau, 0x00000a0du, 0x00000489u, 0x00000005u, + 0x0000049eu, 0x00000498u, 0x000700f5u, 0x000000aau, 0x00000a0cu, 0x00000482u, 0x00000005u, 0x0000049bu, + 0x00000498u, 0x00050051u, 0x00000016u, 0x000004a7u, 0x00000479u, 0x00000001u, 0x000500c3u, 0x00000016u, + 0x000004a8u, 0x000004a7u, 0x00000043u, 0x0004007cu, 0x00000006u, 0x000004abu, 0x000004a8u, 0x00050051u, + 0x00000016u, 0x000004adu, 0x00000479u, 0x00000000u, 0x0004007cu, 0x00000006u, 0x000004afu, 0x000004adu, + 0x0007004fu, 0x00000009u, 0x000004b1u, 0x00000a0cu, 0x00000a0cu, 0x00000000u, 0x00000002u, 0x00060041u, + 0x00000037u, 0x00000651u, 0x00000034u, 0x000004abu, 0x000004afu, 0x0003003eu, 0x00000651u, 0x000004b1u, + 0x00050080u, 0x00000016u, 0x000004b8u, 0x000004adu, 0x00000043u, 0x0004007cu, 0x00000006u, 0x000004b9u, + 0x000004b8u, 0x0007004fu, 0x00000009u, 0x000004bbu, 0x00000a0cu, 0x00000a0cu, 0x00000001u, 0x00000003u, + 0x00060041u, 0x00000037u, 0x00000656u, 0x00000034u, 0x000004abu, 0x000004b9u, 0x0003003eu, 0x00000656u, + 0x000004bbu, 0x00050080u, 0x00000016u, 0x000004c2u, 0x000004adu, 0x000000bcu, 0x0004007cu, 0x00000006u, + 0x000004c3u, 0x000004c2u, 0x0007004fu, 0x00000009u, 0x000004c5u, 0x00000a0du, 0x00000a0du, 0x00000000u, + 0x00000002u, 0x00060041u, 0x00000037u, 0x0000065bu, 0x00000034u, 0x000004abu, 0x000004c3u, 0x0003003eu, + 0x0000065bu, 0x000004c5u, 0x00050080u, 0x00000016u, 0x000004ccu, 0x000004adu, 0x0000011au, 0x0004007cu, + 0x00000006u, 0x000004cdu, 0x000004ccu, 0x0007004fu, 0x00000009u, 0x000004cfu, 0x00000a0du, 0x00000a0du, + 0x00000001u, 0x00000003u, 0x00060041u, 0x00000037u, 0x00000660u, 0x00000034u, 0x000004abu, 0x000004cdu, + 0x0003003eu, 0x00000660u, 0x000004cfu, 0x00050080u, 0x00000016u, 0x000004d2u, 0x000004a8u, 0x00000124u, + 0x0004007cu, 0x00000006u, 0x000004d3u, 0x000004d2u, 0x0007004fu, 0x00000009u, 0x000004d9u, 0x00000a0eu, + 0x00000a0eu, 0x00000000u, 0x00000002u, 0x00060041u, 0x00000037u, 0x00000665u, 0x00000034u, 0x000004d3u, + 0x000004afu, 0x0003003eu, 0x00000665u, 0x000004d9u, 0x0007004fu, 0x00000009u, 0x000004e3u, 0x00000a0eu, + 0x00000a0eu, 0x00000001u, 0x00000003u, 0x00060041u, 0x00000037u, 0x0000066au, 0x00000034u, 0x000004d3u, + 0x000004b9u, 0x0003003eu, 0x0000066au, 0x000004e3u, 0x0007004fu, 0x00000009u, 0x000004edu, 0x00000a0fu, + 0x00000a0fu, 0x00000000u, 0x00000002u, 0x00060041u, 0x00000037u, 0x0000066fu, 0x00000034u, 0x000004d3u, + 0x000004c3u, 0x0003003eu, 0x0000066fu, 0x000004edu, 0x0007004fu, 0x00000009u, 0x000004f7u, 0x00000a0fu, + 0x00000a0fu, 0x00000001u, 0x00000003u, 0x00060041u, 0x00000037u, 0x00000674u, 0x00000034u, 0x000004d3u, + 0x000004cdu, 0x0003003eu, 0x00000674u, 0x000004f7u, 0x00050089u, 0x00000006u, 0x000004fau, 0x000003c2u, + 0x0000015cu, 0x00050084u, 0x00000006u, 0x000004fbu, 0x0000015au, 0x000004fau, 0x00050080u, 0x00000006u, + 0x000004fcu, 0x00000159u, 0x000004fbu, 0x0004007cu, 0x00000016u, 0x000004fdu, 0x000004fcu, 0x00050086u, + 0x00000006u, 0x000004ffu, 0x000003c2u, 0x0000015cu, 0x00050084u, 0x00000006u, 0x00000500u, 0x0000015au, + 0x000004ffu, 0x0004007cu, 0x00000016u, 0x00000501u, 0x00000500u, 0x00050050u, 0x00000017u, 0x00000502u, + 0x000004fdu, 0x00000501u, 0x0004003du, 0x000000aeu, 0x00000503u, 0x000000b0u, 0x00050080u, 0x00000017u, + 0x00000506u, 0x00000475u, 0x00000502u, 0x000500b1u, 0x0000005eu, 0x0000067au, 0x00000506u, 0x0000005du, + 0x000600a9u, 0x00000017u, 0x0000067bu, 0x0000067au, 0x00000060u, 0x0000005du, 0x00050082u, 0x00000017u, + 0x0000067du, 0x00000506u, 0x0000067bu, 0x00050080u, 0x00000017u, 0x00000680u, 0x0000067du, 0x00000060u, + 0x00050080u, 0x00000017u, 0x00000690u, 0x00000680u, 0x000005b7u, 0x00050080u, 0x00000017u, 0x00000692u, + 0x00000690u, 0x00000060u, 0x0007000cu, 0x00000017u, 0x00000696u, 0x00000001u, 0x00000027u, 0x00000680u, + 0x000005aeu, 0x000500afu, 0x0000005eu, 0x0000069au, 0x00000680u, 0x000005afu, 0x000600a9u, 0x00000017u, + 0x0000069bu, 0x0000069au, 0x00000692u, 0x00000696u, 0x0004006fu, 0x0000001eu, 0x0000069du, 0x0000069bu, + 0x00050085u, 0x0000001eu, 0x000006a0u, 0x0000069du, 0x000005c7u, 0x00060060u, 0x000000b5u, 0x00000508u, + 0x00000503u, 0x000006a0u, 0x00000042u, 0x00040073u, 0x000000aau, 0x00000509u, 0x00000508u, 0x0009004fu, + 0x000000aau, 0x0000050au, 0x00000509u, 0x00000509u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, + 0x000300f7u, 0x0000050fu, 0x00000000u, 0x000400fau, 0x000000d8u, 0x0000050bu, 0x0000050fu, 0x000200f8u, + 0x0000050bu, 0x00050083u, 0x000000aau, 0x0000050eu, 0x0000050au, 0x00000a2au, 0x000200f9u, 0x0000050fu, + 0x000200f8u, 0x0000050fu, 0x000700f5u, 0x000000aau, 0x00000a10u, 0x0000050au, 0x000004a5u, 0x0000050eu, + 0x0000050bu, 0x000500c3u, 0x00000016u, 0x00000512u, 0x00000501u, 0x00000043u, 0x0004007cu, 0x00000006u, + 0x00000513u, 0x00000512u, 0x0007004fu, 0x00000009u, 0x00000519u, 0x00000a10u, 0x00000a10u, 0x00000000u, + 0x00000002u, 0x00060041u, 0x00000037u, 0x000006a5u, 0x00000034u, 0x00000513u, 0x000004fcu, 0x0003003eu, + 0x000006a5u, 0x00000519u, 0x00050080u, 0x00000016u, 0x00000521u, 0x000004fdu, 0x00000043u, 0x0004007cu, + 0x00000006u, 0x00000522u, 0x00000521u, 0x0007004fu, 0x00000009u, 0x00000524u, 0x00000a10u, 0x00000a10u, + 0x00000001u, 0x00000003u, 0x00060041u, 0x00000037u, 0x000006aau, 0x00000034u, 0x00000513u, 0x00000522u, + 0x0003003eu, 0x000006aau, 0x00000524u, 0x00050089u, 0x00000006u, 0x00000527u, 0x000003c2u, 0x00000193u, + 0x00050084u, 0x00000006u, 0x00000528u, 0x0000015au, 0x00000527u, 0x0004007cu, 0x00000016u, 0x00000529u, + 0x00000528u, 0x00050086u, 0x00000006u, 0x0000052bu, 0x000003c2u, 0x00000193u, 0x00050084u, 0x00000006u, + 0x0000052cu, 0x0000015au, 0x0000052bu, 0x00050080u, 0x00000006u, 0x0000052du, 0x00000159u, 0x0000052cu, + 0x0004007cu, 0x00000016u, 0x0000052eu, 0x0000052du, 0x00050050u, 0x00000017u, 0x0000052fu, 0x00000529u, + 0x0000052eu, 0x0004003du, 0x000000aeu, 0x00000530u, 0x000000b0u, 0x00050080u, 0x00000017u, 0x00000533u, + 0x00000475u, 0x0000052fu, 0x000500b1u, 0x0000005eu, 0x000006b0u, 0x00000533u, 0x0000005du, 0x000600a9u, + 0x00000017u, 0x000006b1u, 0x000006b0u, 0x00000060u, 0x0000005du, 0x00050082u, 0x00000017u, 0x000006b3u, + 0x00000533u, 0x000006b1u, 0x00050080u, 0x00000017u, 0x000006b6u, 0x000006b3u, 0x00000060u, 0x00050080u, + 0x00000017u, 0x000006c6u, 0x000006b6u, 0x000005b7u, 0x00050080u, 0x00000017u, 0x000006c8u, 0x000006c6u, + 0x00000060u, 0x0007000cu, 0x00000017u, 0x000006ccu, 0x00000001u, 0x00000027u, 0x000006b6u, 0x000005aeu, + 0x000500afu, 0x0000005eu, 0x000006d0u, 0x000006b6u, 0x000005afu, 0x000600a9u, 0x00000017u, 0x000006d1u, + 0x000006d0u, 0x000006c8u, 0x000006ccu, 0x0004006fu, 0x0000001eu, 0x000006d3u, 0x000006d1u, 0x00050085u, + 0x0000001eu, 0x000006d6u, 0x000006d3u, 0x000005c7u, 0x00060060u, 0x000000b5u, 0x00000535u, 0x00000530u, + 0x000006d6u, 0x00000042u, 0x00040073u, 0x000000aau, 0x00000536u, 0x00000535u, 0x0009004fu, 0x000000aau, + 0x00000537u, 0x00000536u, 0x00000536u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, + 0x0000053cu, 0x00000000u, 0x000400fau, 0x000000d8u, 0x00000538u, 0x0000053cu, 0x000200f8u, 0x00000538u, + 0x00050083u, 0x000000aau, 0x0000053bu, 0x00000537u, 0x00000a2au, 0x000200f9u, 0x0000053cu, 0x000200f8u, + 0x0000053cu, 0x000700f5u, 0x000000aau, 0x00000a11u, 0x00000537u, 0x0000050fu, 0x0000053bu, 0x00000538u, + 0x000500c3u, 0x00000016u, 0x0000053fu, 0x0000052eu, 0x00000043u, 0x0004007cu, 0x00000006u, 0x00000540u, + 0x0000053fu, 0x0007004fu, 0x00000009u, 0x00000546u, 0x00000a11u, 0x00000a11u, 0x00000000u, 0x00000002u, + 0x00060041u, 0x00000037u, 0x000006dbu, 0x00000034u, 0x00000540u, 0x00000528u, 0x0003003eu, 0x000006dbu, + 0x00000546u, 0x00050080u, 0x00000016u, 0x0000054eu, 0x00000529u, 0x00000043u, 0x0004007cu, 0x00000006u, + 0x0000054fu, 0x0000054eu, 0x0007004fu, 0x00000009u, 0x00000551u, 0x00000a11u, 0x00000a11u, 0x00000001u, + 0x00000003u, 0x00060041u, 0x00000037u, 0x000006e0u, 0x00000034u, 0x00000540u, 0x0000054fu, 0x0003003eu, + 0x000006e0u, 0x00000551u, 0x000500b0u, 0x00000027u, 0x00000554u, 0x000003c2u, 0x00000193u, 0x000300f7u, + 0x00000584u, 0x00000000u, 0x000400fau, 0x00000554u, 0x00000555u, 0x00000584u, 0x000200f8u, 0x00000555u, + 0x00050080u, 0x00000006u, 0x0000055eu, 0x00000159u, 0x00000500u, 0x0004007cu, 0x00000016u, 0x0000055fu, + 0x0000055eu, 0x00050050u, 0x00000017u, 0x00000560u, 0x000004fdu, 0x0000055fu, 0x0004003du, 0x000000aeu, + 0x00000561u, 0x000000b0u, 0x00050080u, 0x00000017u, 0x00000564u, 0x00000475u, 0x00000560u, 0x000500b1u, + 0x0000005eu, 0x000006e6u, 0x00000564u, 0x0000005du, 0x000600a9u, 0x00000017u, 0x000006e7u, 0x000006e6u, + 0x00000060u, 0x0000005du, 0x00050082u, 0x00000017u, 0x000006e9u, 0x00000564u, 0x000006e7u, 0x00050080u, + 0x00000017u, 0x000006ecu, 0x000006e9u, 0x00000060u, 0x00050080u, 0x00000017u, 0x000006fcu, 0x000006ecu, + 0x000005b7u, 0x00050080u, 0x00000017u, 0x000006feu, 0x000006fcu, 0x00000060u, 0x0007000cu, 0x00000017u, + 0x00000702u, 0x00000001u, 0x00000027u, 0x000006ecu, 0x000005aeu, 0x000500afu, 0x0000005eu, 0x00000706u, + 0x000006ecu, 0x000005afu, 0x000600a9u, 0x00000017u, 0x00000707u, 0x00000706u, 0x000006feu, 0x00000702u, + 0x0004006fu, 0x0000001eu, 0x00000709u, 0x00000707u, 0x00050085u, 0x0000001eu, 0x0000070cu, 0x00000709u, + 0x000005c7u, 0x00060060u, 0x000000b5u, 0x00000566u, 0x00000561u, 0x0000070cu, 0x00000042u, 0x00040073u, + 0x000000aau, 0x00000567u, 0x00000566u, 0x0009004fu, 0x000000aau, 0x00000568u, 0x00000567u, 0x00000567u, + 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, 0x0000056du, 0x00000000u, 0x000400fau, + 0x000000d8u, 0x00000569u, 0x0000056du, 0x000200f8u, 0x00000569u, 0x00050083u, 0x000000aau, 0x0000056cu, + 0x00000568u, 0x00000a2au, 0x000200f9u, 0x0000056du, 0x000200f8u, 0x0000056du, 0x000700f5u, 0x000000aau, + 0x00000a12u, 0x00000568u, 0x00000555u, 0x0000056cu, 0x00000569u, 0x000500c3u, 0x00000016u, 0x00000570u, + 0x0000055fu, 0x00000043u, 0x0004007cu, 0x00000006u, 0x00000571u, 0x00000570u, 0x0007004fu, 0x00000009u, + 0x00000577u, 0x00000a12u, 0x00000a12u, 0x00000000u, 0x00000002u, 0x00060041u, 0x00000037u, 0x00000711u, + 0x00000034u, 0x00000571u, 0x000004fcu, 0x0003003eu, 0x00000711u, 0x00000577u, 0x0007004fu, 0x00000009u, + 0x00000582u, 0x00000a12u, 0x00000a12u, 0x00000001u, 0x00000003u, 0x00060041u, 0x00000037u, 0x00000716u, + 0x00000034u, 0x00000571u, 0x00000522u, 0x0003003eu, 0x00000716u, 0x00000582u, 0x000200f9u, 0x00000584u, + 0x000200f8u, 0x00000584u, 0x000400e0u, 0x0000015au, 0x0000015au, 0x00000295u, 0x00050084u, 0x00000006u, + 0x00000730u, 0x00000204u, 0x000004fau, 0x0004007cu, 0x00000016u, 0x00000731u, 0x00000730u, 0x0004007cu, + 0x00000016u, 0x00000734u, 0x000004ffu, 0x000200f9u, 0x00000736u, 0x000200f8u, 0x00000736u, 0x000700f5u, + 0x00000016u, 0x00000a13u, 0x00000042u, 0x00000584u, 0x00000749u, 0x0000073au, 0x000500b1u, 0x00000027u, + 0x00000739u, 0x00000a13u, 0x000000bcu, 0x000400f6u, 0x0000074au, 0x0000073au, 0x00000000u, 0x000400fau, + 0x00000739u, 0x0000073au, 0x0000074au, 0x000200f8u, 0x0000073au, 0x00050080u, 0x00000016u, 0x00000741u, + 0x00000731u, 0x00000a13u, 0x0004007cu, 0x00000006u, 0x00000742u, 0x00000741u, 0x00060041u, 0x00000037u, + 0x000007e8u, 0x00000034u, 0x000004ffu, 0x00000742u, 0x0004003du, 0x00000009u, 0x000007e9u, 0x000007e8u, + 0x00050041u, 0x0000000fu, 0x00000746u, 0x0000071cu, 0x00000a13u, 0x0003003eu, 0x00000746u, 0x000007e9u, + 0x00050080u, 0x00000016u, 0x00000749u, 0x00000a13u, 0x00000043u, 0x000200f9u, 0x00000736u, 0x000200f8u, + 0x0000074au, 0x000200f9u, 0x0000074bu, 0x000200f8u, 0x0000074bu, 0x000700f5u, 0x00000016u, 0x00000a14u, + 0x00000043u, 0x0000074au, 0x00000761u, 0x0000074fu, 0x000500b1u, 0x00000027u, 0x0000074eu, 0x00000a14u, + 0x00000230u, 0x000400f6u, 0x00000762u, 0x0000074fu, 0x00000000u, 0x000400fau, 0x0000074eu, 0x0000074fu, + 0x00000762u, 0x000200f8u, 0x0000074fu, 0x00050082u, 0x00000016u, 0x00000752u, 0x00000a14u, 0x00000043u, + 0x00050041u, 0x0000000fu, 0x00000753u, 0x0000071cu, 0x00000752u, 0x0004003du, 0x00000009u, 0x00000754u, + 0x00000753u, 0x00050080u, 0x00000016u, 0x00000756u, 0x00000a14u, 0x00000043u, 0x00050041u, 0x0000000fu, + 0x00000757u, 0x0000071cu, 0x00000756u, 0x0004003du, 0x00000009u, 0x00000758u, 0x00000757u, 0x00050081u, + 0x00000009u, 0x00000759u, 0x00000754u, 0x00000758u, 0x0005008eu, 0x00000009u, 0x0000075au, 0x00000759u, + 0x00000233u, 0x00050041u, 0x0000000fu, 0x0000075bu, 0x0000071cu, 0x00000a14u, 0x0004003du, 0x00000009u, + 0x0000075cu, 0x0000075bu, 0x00050081u, 0x00000009u, 0x0000075du, 0x0000075cu, 0x0000075au, 0x0003003eu, + 0x0000075bu, 0x0000075du, 0x00050080u, 0x00000016u, 0x00000761u, 0x00000a14u, 0x00000047u, 0x000200f9u, + 0x0000074bu, 0x000200f8u, 0x00000762u, 0x000200f9u, 0x00000763u, 0x000200f8u, 0x00000763u, 0x000700f5u, + 0x00000016u, 0x00000a15u, 0x00000047u, 0x00000762u, 0x00000779u, 0x00000767u, 0x000500b1u, 0x00000027u, + 0x00000766u, 0x00000a15u, 0x0000024bu, 0x000400f6u, 0x0000077au, 0x00000767u, 0x00000000u, 0x000400fau, + 0x00000766u, 0x00000767u, 0x0000077au, 0x000200f8u, 0x00000767u, 0x00050082u, 0x00000016u, 0x0000076au, + 0x00000a15u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000076bu, 0x0000071cu, 0x0000076au, 0x0004003du, + 0x00000009u, 0x0000076cu, 0x0000076bu, 0x00050080u, 0x00000016u, 0x0000076eu, 0x00000a15u, 0x00000043u, + 0x00050041u, 0x0000000fu, 0x0000076fu, 0x0000071cu, 0x0000076eu, 0x0004003du, 0x00000009u, 0x00000770u, + 0x0000076fu, 0x00050081u, 0x00000009u, 0x00000771u, 0x0000076cu, 0x00000770u, 0x0005008eu, 0x00000009u, + 0x00000772u, 0x00000771u, 0x0000024eu, 0x00050041u, 0x0000000fu, 0x00000773u, 0x0000071cu, 0x00000a15u, + 0x0004003du, 0x00000009u, 0x00000774u, 0x00000773u, 0x00050081u, 0x00000009u, 0x00000775u, 0x00000774u, + 0x00000772u, 0x0003003eu, 0x00000773u, 0x00000775u, 0x00050080u, 0x00000016u, 0x00000779u, 0x00000a15u, + 0x00000047u, 0x000200f9u, 0x00000763u, 0x000200f8u, 0x0000077au, 0x000200f9u, 0x0000077bu, 0x000200f8u, + 0x0000077bu, 0x000700f5u, 0x00000016u, 0x00000a16u, 0x0000004au, 0x0000077au, 0x00000791u, 0x0000077fu, + 0x000500b1u, 0x00000027u, 0x0000077eu, 0x00000a16u, 0x00000266u, 0x000400f6u, 0x00000792u, 0x0000077fu, + 0x00000000u, 0x000400fau, 0x0000077eu, 0x0000077fu, 0x00000792u, 0x000200f8u, 0x0000077fu, 0x00050082u, + 0x00000016u, 0x00000782u, 0x00000a16u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000783u, 0x0000071cu, + 0x00000782u, 0x0004003du, 0x00000009u, 0x00000784u, 0x00000783u, 0x00050080u, 0x00000016u, 0x00000786u, + 0x00000a16u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000787u, 0x0000071cu, 0x00000786u, 0x0004003du, + 0x00000009u, 0x00000788u, 0x00000787u, 0x00050081u, 0x00000009u, 0x00000789u, 0x00000784u, 0x00000788u, + 0x0005008eu, 0x00000009u, 0x0000078au, 0x00000789u, 0x00000269u, 0x00050041u, 0x0000000fu, 0x0000078bu, + 0x0000071cu, 0x00000a16u, 0x0004003du, 0x00000009u, 0x0000078cu, 0x0000078bu, 0x00050081u, 0x00000009u, + 0x0000078du, 0x0000078cu, 0x0000078au, 0x0003003eu, 0x0000078bu, 0x0000078du, 0x00050080u, 0x00000016u, + 0x00000791u, 0x00000a16u, 0x00000047u, 0x000200f9u, 0x0000077bu, 0x000200f8u, 0x00000792u, 0x000200f9u, + 0x00000793u, 0x000200f8u, 0x00000793u, 0x000700f5u, 0x00000016u, 0x00000a17u, 0x0000009bu, 0x00000792u, + 0x000007a9u, 0x00000797u, 0x000500b1u, 0x00000027u, 0x00000796u, 0x00000a17u, 0x00000281u, 0x000400f6u, + 0x000007aau, 0x00000797u, 0x00000000u, 0x000400fau, 0x00000796u, 0x00000797u, 0x000007aau, 0x000200f8u, + 0x00000797u, 0x00050082u, 0x00000016u, 0x0000079au, 0x00000a17u, 0x00000043u, 0x00050041u, 0x0000000fu, + 0x0000079bu, 0x0000071cu, 0x0000079au, 0x0004003du, 0x00000009u, 0x0000079cu, 0x0000079bu, 0x00050080u, + 0x00000016u, 0x0000079eu, 0x00000a17u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000079fu, 0x0000071cu, + 0x0000079eu, 0x0004003du, 0x00000009u, 0x000007a0u, 0x0000079fu, 0x00050081u, 0x00000009u, 0x000007a1u, + 0x0000079cu, 0x000007a0u, 0x0005008eu, 0x00000009u, 0x000007a2u, 0x000007a1u, 0x00000284u, 0x00050041u, + 0x0000000fu, 0x000007a3u, 0x0000071cu, 0x00000a17u, 0x0004003du, 0x00000009u, 0x000007a4u, 0x000007a3u, + 0x00050081u, 0x00000009u, 0x000007a5u, 0x000007a4u, 0x000007a2u, 0x0003003eu, 0x000007a3u, 0x000007a5u, + 0x00050080u, 0x00000016u, 0x000007a9u, 0x00000a17u, 0x00000047u, 0x000200f9u, 0x00000793u, 0x000200f8u, + 0x000007aau, 0x000400e0u, 0x0000015au, 0x0000015au, 0x00000295u, 0x000200f9u, 0x000007abu, 0x000200f8u, + 0x000007abu, 0x000700f5u, 0x00000016u, 0x00000a18u, 0x00000047u, 0x000007aau, 0x000007e2u, 0x000007afu, + 0x000500b1u, 0x00000027u, 0x000007aeu, 0x00000a18u, 0x0000029du, 0x000400f6u, 0x000007e3u, 0x000007afu, + 0x00000000u, 0x000400fau, 0x000007aeu, 0x000007afu, 0x000007e3u, 0x000200f8u, 0x000007afu, 0x00050084u, + 0x00000016u, 0x000007b1u, 0x00000047u, 0x00000a18u, 0x00050041u, 0x0000000fu, 0x000007b3u, 0x0000071cu, + 0x000007b1u, 0x0004003du, 0x00000009u, 0x000007b4u, 0x000007b3u, 0x00050080u, 0x00000016u, 0x000007b7u, + 0x000007b1u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x000007b8u, 0x0000071cu, 0x000007b7u, 0x0004003du, + 0x00000009u, 0x000007b9u, 0x000007b8u, 0x0005008eu, 0x00000009u, 0x000007bbu, 0x000007b4u, 0x000002abu, + 0x0005008eu, 0x00000009u, 0x000007bdu, 0x000007b9u, 0x000002aeu, 0x00050051u, 0x00000008u, 0x000007bfu, + 0x000007bbu, 0x00000000u, 0x00050051u, 0x00000008u, 0x000007c1u, 0x000007bdu, 0x00000000u, 0x00050050u, + 0x00000009u, 0x000007c2u, 0x000007bfu, 0x000007c1u, 0x00050051u, 0x00000008u, 0x000007c4u, 0x000007bbu, + 0x00000001u, 0x00050051u, 0x00000008u, 0x000007c6u, 0x000007bdu, 0x00000001u, 0x00050050u, 0x00000009u, + 0x000007c7u, 0x000007c4u, 0x000007c6u, 0x000500c3u, 0x00000016u, 0x000007cau, 0x00000731u, 0x00000043u, + 0x00050082u, 0x00000016u, 0x000007ccu, 0x00000a18u, 0x00000047u, 0x00050080u, 0x00000016u, 0x000007cdu, + 0x000007cau, 0x000007ccu, 0x0004007cu, 0x00000006u, 0x000007cfu, 0x000007cdu, 0x00050084u, 0x00000016u, + 0x000007d2u, 0x00000047u, 0x00000734u, 0x0004007cu, 0x00000006u, 0x000007d4u, 0x000007d2u, 0x00060041u, + 0x00000037u, 0x000007eeu, 0x00000034u, 0x000007cfu, 0x000007d4u, 0x0003003eu, 0x000007eeu, 0x000007c2u, + 0x00050080u, 0x00000016u, 0x000007dcu, 0x000007d2u, 0x00000043u, 0x0004007cu, 0x00000006u, 0x000007ddu, + 0x000007dcu, 0x00060041u, 0x00000037u, 0x000007f3u, 0x00000034u, 0x000007cfu, 0x000007ddu, 0x0003003eu, + 0x000007f3u, 0x000007c7u, 0x00050080u, 0x00000016u, 0x000007e2u, 0x00000a18u, 0x00000043u, 0x000200f9u, + 0x000007abu, 0x000200f8u, 0x000007e3u, 0x000500b0u, 0x00000027u, 0x000003c6u, 0x000003c2u, 0x00000159u, + 0x00050089u, 0x00000006u, 0x0000080cu, 0x000003c2u, 0x00000204u, 0x00050084u, 0x00000006u, 0x0000080du, + 0x0000015cu, 0x0000080cu, 0x0004007cu, 0x00000016u, 0x0000080eu, 0x0000080du, 0x00050086u, 0x00000006u, + 0x00000810u, 0x000003c2u, 0x00000204u, 0x00050080u, 0x00000006u, 0x00000813u, 0x00000810u, 0x00000193u, + 0x0004007cu, 0x00000016u, 0x00000814u, 0x00000813u, 0x000300f7u, 0x0000088du, 0x00000000u, 0x000400fau, + 0x000003c6u, 0x00000817u, 0x0000088du, 0x000200f8u, 0x00000817u, 0x000200f9u, 0x00000818u, 0x000200f8u, + 0x00000818u, 0x000700f5u, 0x00000016u, 0x00000a19u, 0x00000042u, 0x00000817u, 0x0000082bu, 0x0000081cu, + 0x000500b1u, 0x00000027u, 0x0000081bu, 0x00000a19u, 0x00000281u, 0x000400f6u, 0x0000082cu, 0x0000081cu, + 0x00000000u, 0x000400fau, 0x0000081bu, 0x0000081cu, 0x0000082cu, 0x000200f8u, 0x0000081cu, 0x00050080u, + 0x00000016u, 0x00000823u, 0x0000080eu, 0x00000a19u, 0x0004007cu, 0x00000006u, 0x00000824u, 0x00000823u, + 0x00060041u, 0x00000037u, 0x000008ceu, 0x00000034u, 0x00000813u, 0x00000824u, 0x0004003du, 0x00000009u, + 0x000008cfu, 0x000008ceu, 0x00050041u, 0x0000000fu, 0x00000828u, 0x000007f9u, 0x00000a19u, 0x0003003eu, + 0x00000828u, 0x000008cfu, 0x00050080u, 0x00000016u, 0x0000082bu, 0x00000a19u, 0x00000043u, 0x000200f9u, + 0x00000818u, 0x000200f8u, 0x0000082cu, 0x000200f9u, 0x0000082du, 0x000200f8u, 0x0000082du, 0x000700f5u, + 0x00000016u, 0x00000a1au, 0x00000043u, 0x0000082cu, 0x00000843u, 0x00000831u, 0x000500b1u, 0x00000027u, + 0x00000830u, 0x00000a1au, 0x00000312u, 0x000400f6u, 0x00000844u, 0x00000831u, 0x00000000u, 0x000400fau, + 0x00000830u, 0x00000831u, 0x00000844u, 0x000200f8u, 0x00000831u, 0x00050082u, 0x00000016u, 0x00000834u, + 0x00000a1au, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000835u, 0x000007f9u, 0x00000834u, 0x0004003du, + 0x00000009u, 0x00000836u, 0x00000835u, 0x00050080u, 0x00000016u, 0x00000838u, 0x00000a1au, 0x00000043u, + 0x00050041u, 0x0000000fu, 0x00000839u, 0x000007f9u, 0x00000838u, 0x0004003du, 0x00000009u, 0x0000083au, + 0x00000839u, 0x00050081u, 0x00000009u, 0x0000083bu, 0x00000836u, 0x0000083au, 0x0005008eu, 0x00000009u, + 0x0000083cu, 0x0000083bu, 0x00000233u, 0x00050041u, 0x0000000fu, 0x0000083du, 0x000007f9u, 0x00000a1au, + 0x0004003du, 0x00000009u, 0x0000083eu, 0x0000083du, 0x00050081u, 0x00000009u, 0x0000083fu, 0x0000083eu, + 0x0000083cu, 0x0003003eu, 0x0000083du, 0x0000083fu, 0x00050080u, 0x00000016u, 0x00000843u, 0x00000a1au, + 0x00000047u, 0x000200f9u, 0x0000082du, 0x000200f8u, 0x00000844u, 0x000200f9u, 0x00000845u, 0x000200f8u, + 0x00000845u, 0x000700f5u, 0x00000016u, 0x00000a1bu, 0x00000047u, 0x00000844u, 0x0000085bu, 0x00000849u, + 0x000500b1u, 0x00000027u, 0x00000848u, 0x00000a1bu, 0x0000032cu, 0x000400f6u, 0x0000085cu, 0x00000849u, + 0x00000000u, 0x000400fau, 0x00000848u, 0x00000849u, 0x0000085cu, 0x000200f8u, 0x00000849u, 0x00050082u, + 0x00000016u, 0x0000084cu, 0x00000a1bu, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000084du, 0x000007f9u, + 0x0000084cu, 0x0004003du, 0x00000009u, 0x0000084eu, 0x0000084du, 0x00050080u, 0x00000016u, 0x00000850u, + 0x00000a1bu, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000851u, 0x000007f9u, 0x00000850u, 0x0004003du, + 0x00000009u, 0x00000852u, 0x00000851u, 0x00050081u, 0x00000009u, 0x00000853u, 0x0000084eu, 0x00000852u, + 0x0005008eu, 0x00000009u, 0x00000854u, 0x00000853u, 0x0000024eu, 0x00050041u, 0x0000000fu, 0x00000855u, + 0x000007f9u, 0x00000a1bu, 0x0004003du, 0x00000009u, 0x00000856u, 0x00000855u, 0x00050081u, 0x00000009u, + 0x00000857u, 0x00000856u, 0x00000854u, 0x0003003eu, 0x00000855u, 0x00000857u, 0x00050080u, 0x00000016u, + 0x0000085bu, 0x00000a1bu, 0x00000047u, 0x000200f9u, 0x00000845u, 0x000200f8u, 0x0000085cu, 0x000200f9u, + 0x0000085du, 0x000200f8u, 0x0000085du, 0x000700f5u, 0x00000016u, 0x00000a1cu, 0x0000004au, 0x0000085cu, + 0x00000873u, 0x00000861u, 0x000500b1u, 0x00000027u, 0x00000860u, 0x00000a1cu, 0x00000346u, 0x000400f6u, + 0x00000874u, 0x00000861u, 0x00000000u, 0x000400fau, 0x00000860u, 0x00000861u, 0x00000874u, 0x000200f8u, + 0x00000861u, 0x00050082u, 0x00000016u, 0x00000864u, 0x00000a1cu, 0x00000043u, 0x00050041u, 0x0000000fu, + 0x00000865u, 0x000007f9u, 0x00000864u, 0x0004003du, 0x00000009u, 0x00000866u, 0x00000865u, 0x00050080u, + 0x00000016u, 0x00000868u, 0x00000a1cu, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000869u, 0x000007f9u, + 0x00000868u, 0x0004003du, 0x00000009u, 0x0000086au, 0x00000869u, 0x00050081u, 0x00000009u, 0x0000086bu, + 0x00000866u, 0x0000086au, 0x0005008eu, 0x00000009u, 0x0000086cu, 0x0000086bu, 0x00000269u, 0x00050041u, + 0x0000000fu, 0x0000086du, 0x000007f9u, 0x00000a1cu, 0x0004003du, 0x00000009u, 0x0000086eu, 0x0000086du, + 0x00050081u, 0x00000009u, 0x0000086fu, 0x0000086eu, 0x0000086cu, 0x0003003eu, 0x0000086du, 0x0000086fu, + 0x00050080u, 0x00000016u, 0x00000873u, 0x00000a1cu, 0x00000047u, 0x000200f9u, 0x0000085du, 0x000200f8u, + 0x00000874u, 0x000200f9u, 0x00000875u, 0x000200f8u, 0x00000875u, 0x000700f5u, 0x00000016u, 0x00000a1du, + 0x0000009bu, 0x00000874u, 0x0000088bu, 0x00000879u, 0x000500b1u, 0x00000027u, 0x00000878u, 0x00000a1du, + 0x00000124u, 0x000400f6u, 0x0000088cu, 0x00000879u, 0x00000000u, 0x000400fau, 0x00000878u, 0x00000879u, + 0x0000088cu, 0x000200f8u, 0x00000879u, 0x00050082u, 0x00000016u, 0x0000087cu, 0x00000a1du, 0x00000043u, + 0x00050041u, 0x0000000fu, 0x0000087du, 0x000007f9u, 0x0000087cu, 0x0004003du, 0x00000009u, 0x0000087eu, + 0x0000087du, 0x00050080u, 0x00000016u, 0x00000880u, 0x00000a1du, 0x00000043u, 0x00050041u, 0x0000000fu, + 0x00000881u, 0x000007f9u, 0x00000880u, 0x0004003du, 0x00000009u, 0x00000882u, 0x00000881u, 0x00050081u, + 0x00000009u, 0x00000883u, 0x0000087eu, 0x00000882u, 0x0005008eu, 0x00000009u, 0x00000884u, 0x00000883u, + 0x00000284u, 0x00050041u, 0x0000000fu, 0x00000885u, 0x000007f9u, 0x00000a1du, 0x0004003du, 0x00000009u, + 0x00000886u, 0x00000885u, 0x00050081u, 0x00000009u, 0x00000887u, 0x00000886u, 0x00000884u, 0x0003003eu, + 0x00000885u, 0x00000887u, 0x00050080u, 0x00000016u, 0x0000088bu, 0x00000a1du, 0x00000047u, 0x000200f9u, + 0x00000875u, 0x000200f8u, 0x0000088cu, 0x000200f9u, 0x0000088du, 0x000200f8u, 0x0000088du, 0x000400e0u, + 0x0000015au, 0x0000015au, 0x00000295u, 0x000300f7u, 0x000008c9u, 0x00000000u, 0x000400fau, 0x000003c6u, + 0x0000088fu, 0x000008c9u, 0x000200f8u, 0x0000088fu, 0x000200f9u, 0x00000890u, 0x000200f8u, 0x00000890u, + 0x000700f5u, 0x00000016u, 0x00000a1eu, 0x00000047u, 0x0000088fu, 0x000008c7u, 0x00000894u, 0x000500b1u, + 0x00000027u, 0x00000893u, 0x00000a1eu, 0x0000009bu, 0x000400f6u, 0x000008c8u, 0x00000894u, 0x00000000u, + 0x000400fau, 0x00000893u, 0x00000894u, 0x000008c8u, 0x000200f8u, 0x00000894u, 0x00050084u, 0x00000016u, + 0x00000896u, 0x00000047u, 0x00000a1eu, 0x00050041u, 0x0000000fu, 0x00000898u, 0x000007f9u, 0x00000896u, + 0x0004003du, 0x00000009u, 0x00000899u, 0x00000898u, 0x00050080u, 0x00000016u, 0x0000089cu, 0x00000896u, + 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000089du, 0x000007f9u, 0x0000089cu, 0x0004003du, 0x00000009u, + 0x0000089eu, 0x0000089du, 0x0005008eu, 0x00000009u, 0x000008a0u, 0x00000899u, 0x000002abu, 0x0005008eu, + 0x00000009u, 0x000008a2u, 0x0000089eu, 0x000002aeu, 0x00050051u, 0x00000008u, 0x000008a4u, 0x000008a0u, + 0x00000000u, 0x00050051u, 0x00000008u, 0x000008a6u, 0x000008a2u, 0x00000000u, 0x00050050u, 0x00000009u, + 0x000008a7u, 0x000008a4u, 0x000008a6u, 0x00050051u, 0x00000008u, 0x000008a9u, 0x000008a0u, 0x00000001u, + 0x00050051u, 0x00000008u, 0x000008abu, 0x000008a2u, 0x00000001u, 0x00050050u, 0x00000009u, 0x000008acu, + 0x000008a9u, 0x000008abu, 0x000500c3u, 0x00000016u, 0x000008afu, 0x0000080eu, 0x00000043u, 0x00050082u, + 0x00000016u, 0x000008b1u, 0x00000a1eu, 0x00000047u, 0x00050080u, 0x00000016u, 0x000008b2u, 0x000008afu, + 0x000008b1u, 0x0004007cu, 0x00000006u, 0x000008b4u, 0x000008b2u, 0x00050084u, 0x00000016u, 0x000008b7u, + 0x00000047u, 0x00000814u, 0x0004007cu, 0x00000006u, 0x000008b9u, 0x000008b7u, 0x00060041u, 0x00000037u, + 0x000008d4u, 0x00000034u, 0x000008b4u, 0x000008b9u, 0x0003003eu, 0x000008d4u, 0x000008a7u, 0x00050080u, + 0x00000016u, 0x000008c1u, 0x000008b7u, 0x00000043u, 0x0004007cu, 0x00000006u, 0x000008c2u, 0x000008c1u, + 0x00060041u, 0x00000037u, 0x000008d9u, 0x00000034u, 0x000008b4u, 0x000008c2u, 0x0003003eu, 0x000008d9u, + 0x000008acu, 0x00050080u, 0x00000016u, 0x000008c7u, 0x00000a1eu, 0x00000043u, 0x000200f9u, 0x00000890u, + 0x000200f8u, 0x000008c8u, 0x000200f9u, 0x000008c9u, 0x000200f8u, 0x000008c9u, 0x000400e0u, 0x0000015au, + 0x0000015au, 0x00000295u, 0x000200f9u, 0x000008f9u, 0x000200f8u, 0x000008f9u, 0x000700f5u, 0x00000016u, + 0x00000a1fu, 0x00000042u, 0x000008c9u, 0x0000090cu, 0x000008fdu, 0x000500b1u, 0x00000027u, 0x000008fcu, + 0x00000a1fu, 0x000000bcu, 0x000400f6u, 0x0000090du, 0x000008fdu, 0x00000000u, 0x000400fau, 0x000008fcu, + 0x000008fdu, 0x0000090du, 0x000200f8u, 0x000008fdu, 0x00050080u, 0x00000016u, 0x00000904u, 0x00000731u, + 0x00000a1fu, 0x0004007cu, 0x00000006u, 0x00000905u, 0x00000904u, 0x00060041u, 0x00000037u, 0x000009abu, + 0x00000034u, 0x000004ffu, 0x00000905u, 0x0004003du, 0x00000009u, 0x000009acu, 0x000009abu, 0x00050041u, + 0x0000000fu, 0x00000909u, 0x000008dfu, 0x00000a1fu, 0x0003003eu, 0x00000909u, 0x000009acu, 0x00050080u, + 0x00000016u, 0x0000090cu, 0x00000a1fu, 0x00000043u, 0x000200f9u, 0x000008f9u, 0x000200f8u, 0x0000090du, + 0x000200f9u, 0x0000090eu, 0x000200f8u, 0x0000090eu, 0x000700f5u, 0x00000016u, 0x00000a20u, 0x00000043u, + 0x0000090du, 0x00000924u, 0x00000912u, 0x000500b1u, 0x00000027u, 0x00000911u, 0x00000a20u, 0x00000230u, + 0x000400f6u, 0x00000925u, 0x00000912u, 0x00000000u, 0x000400fau, 0x00000911u, 0x00000912u, 0x00000925u, + 0x000200f8u, 0x00000912u, 0x00050082u, 0x00000016u, 0x00000915u, 0x00000a20u, 0x00000043u, 0x00050041u, + 0x0000000fu, 0x00000916u, 0x000008dfu, 0x00000915u, 0x0004003du, 0x00000009u, 0x00000917u, 0x00000916u, + 0x00050080u, 0x00000016u, 0x00000919u, 0x00000a20u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000091au, + 0x000008dfu, 0x00000919u, 0x0004003du, 0x00000009u, 0x0000091bu, 0x0000091au, 0x00050081u, 0x00000009u, + 0x0000091cu, 0x00000917u, 0x0000091bu, 0x0005008eu, 0x00000009u, 0x0000091du, 0x0000091cu, 0x00000233u, + 0x00050041u, 0x0000000fu, 0x0000091eu, 0x000008dfu, 0x00000a20u, 0x0004003du, 0x00000009u, 0x0000091fu, + 0x0000091eu, 0x00050081u, 0x00000009u, 0x00000920u, 0x0000091fu, 0x0000091du, 0x0003003eu, 0x0000091eu, + 0x00000920u, 0x00050080u, 0x00000016u, 0x00000924u, 0x00000a20u, 0x00000047u, 0x000200f9u, 0x0000090eu, + 0x000200f8u, 0x00000925u, 0x000200f9u, 0x00000926u, 0x000200f8u, 0x00000926u, 0x000700f5u, 0x00000016u, + 0x00000a21u, 0x00000047u, 0x00000925u, 0x0000093cu, 0x0000092au, 0x000500b1u, 0x00000027u, 0x00000929u, + 0x00000a21u, 0x0000024bu, 0x000400f6u, 0x0000093du, 0x0000092au, 0x00000000u, 0x000400fau, 0x00000929u, + 0x0000092au, 0x0000093du, 0x000200f8u, 0x0000092au, 0x00050082u, 0x00000016u, 0x0000092du, 0x00000a21u, + 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000092eu, 0x000008dfu, 0x0000092du, 0x0004003du, 0x00000009u, + 0x0000092fu, 0x0000092eu, 0x00050080u, 0x00000016u, 0x00000931u, 0x00000a21u, 0x00000043u, 0x00050041u, + 0x0000000fu, 0x00000932u, 0x000008dfu, 0x00000931u, 0x0004003du, 0x00000009u, 0x00000933u, 0x00000932u, + 0x00050081u, 0x00000009u, 0x00000934u, 0x0000092fu, 0x00000933u, 0x0005008eu, 0x00000009u, 0x00000935u, + 0x00000934u, 0x0000024eu, 0x00050041u, 0x0000000fu, 0x00000936u, 0x000008dfu, 0x00000a21u, 0x0004003du, + 0x00000009u, 0x00000937u, 0x00000936u, 0x00050081u, 0x00000009u, 0x00000938u, 0x00000937u, 0x00000935u, + 0x0003003eu, 0x00000936u, 0x00000938u, 0x00050080u, 0x00000016u, 0x0000093cu, 0x00000a21u, 0x00000047u, + 0x000200f9u, 0x00000926u, 0x000200f8u, 0x0000093du, 0x000200f9u, 0x0000093eu, 0x000200f8u, 0x0000093eu, + 0x000700f5u, 0x00000016u, 0x00000a22u, 0x0000004au, 0x0000093du, 0x00000954u, 0x00000942u, 0x000500b1u, + 0x00000027u, 0x00000941u, 0x00000a22u, 0x00000266u, 0x000400f6u, 0x00000955u, 0x00000942u, 0x00000000u, + 0x000400fau, 0x00000941u, 0x00000942u, 0x00000955u, 0x000200f8u, 0x00000942u, 0x00050082u, 0x00000016u, + 0x00000945u, 0x00000a22u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000946u, 0x000008dfu, 0x00000945u, + 0x0004003du, 0x00000009u, 0x00000947u, 0x00000946u, 0x00050080u, 0x00000016u, 0x00000949u, 0x00000a22u, + 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000094au, 0x000008dfu, 0x00000949u, 0x0004003du, 0x00000009u, + 0x0000094bu, 0x0000094au, 0x00050081u, 0x00000009u, 0x0000094cu, 0x00000947u, 0x0000094bu, 0x0005008eu, + 0x00000009u, 0x0000094du, 0x0000094cu, 0x00000269u, 0x00050041u, 0x0000000fu, 0x0000094eu, 0x000008dfu, + 0x00000a22u, 0x0004003du, 0x00000009u, 0x0000094fu, 0x0000094eu, 0x00050081u, 0x00000009u, 0x00000950u, + 0x0000094fu, 0x0000094du, 0x0003003eu, 0x0000094eu, 0x00000950u, 0x00050080u, 0x00000016u, 0x00000954u, + 0x00000a22u, 0x00000047u, 0x000200f9u, 0x0000093eu, 0x000200f8u, 0x00000955u, 0x000200f9u, 0x00000956u, + 0x000200f8u, 0x00000956u, 0x000700f5u, 0x00000016u, 0x00000a23u, 0x0000009bu, 0x00000955u, 0x0000096cu, + 0x0000095au, 0x000500b1u, 0x00000027u, 0x00000959u, 0x00000a23u, 0x00000281u, 0x000400f6u, 0x0000096du, + 0x0000095au, 0x00000000u, 0x000400fau, 0x00000959u, 0x0000095au, 0x0000096du, 0x000200f8u, 0x0000095au, + 0x00050082u, 0x00000016u, 0x0000095du, 0x00000a23u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000095eu, + 0x000008dfu, 0x0000095du, 0x0004003du, 0x00000009u, 0x0000095fu, 0x0000095eu, 0x00050080u, 0x00000016u, + 0x00000961u, 0x00000a23u, 0x00000043u, 0x00050041u, 0x0000000fu, 0x00000962u, 0x000008dfu, 0x00000961u, + 0x0004003du, 0x00000009u, 0x00000963u, 0x00000962u, 0x00050081u, 0x00000009u, 0x00000964u, 0x0000095fu, + 0x00000963u, 0x0005008eu, 0x00000009u, 0x00000965u, 0x00000964u, 0x00000284u, 0x00050041u, 0x0000000fu, + 0x00000966u, 0x000008dfu, 0x00000a23u, 0x0004003du, 0x00000009u, 0x00000967u, 0x00000966u, 0x00050081u, + 0x00000009u, 0x00000968u, 0x00000967u, 0x00000965u, 0x0003003eu, 0x00000966u, 0x00000968u, 0x00050080u, + 0x00000016u, 0x0000096cu, 0x00000a23u, 0x00000047u, 0x000200f9u, 0x00000956u, 0x000200f8u, 0x0000096du, + 0x000400e0u, 0x0000015au, 0x0000015au, 0x00000295u, 0x000200f9u, 0x0000096eu, 0x000200f8u, 0x0000096eu, + 0x000700f5u, 0x00000016u, 0x00000a24u, 0x00000047u, 0x0000096du, 0x000009a5u, 0x00000972u, 0x000500b1u, + 0x00000027u, 0x00000971u, 0x00000a24u, 0x0000029du, 0x000400f6u, 0x000009a6u, 0x00000972u, 0x00000000u, + 0x000400fau, 0x00000971u, 0x00000972u, 0x000009a6u, 0x000200f8u, 0x00000972u, 0x00050084u, 0x00000016u, + 0x00000974u, 0x00000047u, 0x00000a24u, 0x00050041u, 0x0000000fu, 0x00000976u, 0x000008dfu, 0x00000974u, + 0x0004003du, 0x00000009u, 0x00000977u, 0x00000976u, 0x00050080u, 0x00000016u, 0x0000097au, 0x00000974u, + 0x00000043u, 0x00050041u, 0x0000000fu, 0x0000097bu, 0x000008dfu, 0x0000097au, 0x0004003du, 0x00000009u, + 0x0000097cu, 0x0000097bu, 0x0005008eu, 0x00000009u, 0x0000097eu, 0x00000977u, 0x000002abu, 0x0005008eu, + 0x00000009u, 0x00000980u, 0x0000097cu, 0x000002aeu, 0x00050051u, 0x00000008u, 0x00000982u, 0x0000097eu, + 0x00000000u, 0x00050051u, 0x00000008u, 0x00000984u, 0x00000980u, 0x00000000u, 0x00050050u, 0x00000009u, + 0x00000985u, 0x00000982u, 0x00000984u, 0x00050051u, 0x00000008u, 0x00000987u, 0x0000097eu, 0x00000001u, + 0x00050051u, 0x00000008u, 0x00000989u, 0x00000980u, 0x00000001u, 0x00050050u, 0x00000009u, 0x0000098au, + 0x00000987u, 0x00000989u, 0x000500c3u, 0x00000016u, 0x0000098du, 0x00000731u, 0x00000043u, 0x00050082u, + 0x00000016u, 0x0000098fu, 0x00000a24u, 0x00000047u, 0x00050080u, 0x00000016u, 0x00000990u, 0x0000098du, + 0x0000098fu, 0x0004007cu, 0x00000006u, 0x00000992u, 0x00000990u, 0x00050084u, 0x00000016u, 0x00000995u, + 0x00000047u, 0x00000734u, 0x0004007cu, 0x00000006u, 0x00000997u, 0x00000995u, 0x00060041u, 0x00000037u, + 0x000009b1u, 0x00000034u, 0x00000992u, 0x00000997u, 0x0003003eu, 0x000009b1u, 0x00000985u, 0x00050080u, + 0x00000016u, 0x0000099fu, 0x00000995u, 0x00000043u, 0x0004007cu, 0x00000006u, 0x000009a0u, 0x0000099fu, + 0x00060041u, 0x00000037u, 0x000009b6u, 0x00000034u, 0x00000992u, 0x000009a0u, 0x0003003eu, 0x000009b6u, + 0x0000098au, 0x00050080u, 0x00000016u, 0x000009a5u, 0x00000a24u, 0x00000043u, 0x000200f9u, 0x0000096eu, + 0x000200f8u, 0x000009a6u, 0x000400e0u, 0x0000015au, 0x0000015au, 0x00000295u, 0x000200f9u, 0x000003d2u, + 0x000200f8u, 0x000003d2u, 0x000700f5u, 0x00000016u, 0x00000a25u, 0x0000059au, 0x000009a6u, 0x0000042cu, + 0x000003d5u, 0x000500b1u, 0x00000027u, 0x000003d8u, 0x00000a25u, 0x000000bcu, 0x000400f6u, 0x000003d4u, + 0x000003d5u, 0x00000000u, 0x000400fau, 0x000003d8u, 0x000003d3u, 0x000003d4u, 0x000200f8u, 0x000003d3u, + 0x00050084u, 0x00000016u, 0x000003dcu, 0x00000598u, 0x00000047u, 0x000200f9u, 0x000003ddu, 0x000200f8u, + 0x000003ddu, 0x000700f5u, 0x00000016u, 0x00000a26u, 0x000003dcu, 0x000003d3u, 0x0000042au, 0x000003deu, + 0x000500b1u, 0x00000027u, 0x000003e3u, 0x00000a26u, 0x00000098u, 0x000400f6u, 0x000003dfu, 0x000003deu, + 0x00000000u, 0x000400fau, 0x000003e3u, 0x000003deu, 0x000003dfu, 0x000200f8u, 0x000003deu, 0x0004007cu, + 0x00000006u, 0x000003e6u, 0x00000a25u, 0x0004007cu, 0x00000006u, 0x000003e9u, 0x00000a26u, 0x00060041u, + 0x00000037u, 0x000009d2u, 0x00000034u, 0x000003e6u, 0x000003e9u, 0x0004003du, 0x00000009u, 0x000009d3u, + 0x000009d2u, 0x00050080u, 0x00000016u, 0x000003f1u, 0x00000a26u, 0x00000043u, 0x0004007cu, 0x00000006u, + 0x000003f2u, 0x000003f1u, 0x00060041u, 0x00000037u, 0x000009d8u, 0x00000034u, 0x000003e6u, 0x000003f2u, + 0x0004003du, 0x00000009u, 0x000009d9u, 0x000009d8u, 0x000500c3u, 0x00000016u, 0x000003f8u, 0x00000a26u, + 0x00000043u, 0x00050084u, 0x00000017u, 0x00000400u, 0x00000472u, 0x000000d1u, 0x00050050u, 0x00000017u, + 0x00000403u, 0x000003f8u, 0x00000a25u, 0x00050080u, 0x00000017u, 0x00000404u, 0x00000400u, 0x00000403u, + 0x0004003du, 0x00000405u, 0x00000408u, 0x00000407u, 0x00050051u, 0x00000016u, 0x0000040bu, 0x00000404u, + 0x00000000u, 0x00050051u, 0x00000016u, 0x0000040cu, 0x00000404u, 0x00000001u, 0x00060050u, 0x0000040au, + 0x0000040du, 0x0000040bu, 0x0000040cu, 0x00000042u, 0x0009004fu, 0x000000aau, 0x0000040fu, 0x000009d3u, + 0x000009d3u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00040073u, 0x000000b5u, 0x00000410u, + 0x0000040fu, 0x00040063u, 0x00000408u, 0x0000040du, 0x00000410u, 0x0004003du, 0x00000405u, 0x00000411u, + 0x00000407u, 0x00060050u, 0x0000040au, 0x00000415u, 0x0000040bu, 0x0000040cu, 0x00000047u, 0x0009004fu, + 0x000000aau, 0x00000417u, 0x000009d3u, 0x000009d3u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, + 0x00040073u, 0x000000b5u, 0x00000418u, 0x00000417u, 0x00040063u, 0x00000411u, 0x00000415u, 0x00000418u, + 0x0004003du, 0x00000405u, 0x00000419u, 0x00000407u, 0x00060050u, 0x0000040au, 0x0000041du, 0x0000040bu, + 0x0000040cu, 0x00000043u, 0x0009004fu, 0x000000aau, 0x0000041fu, 0x000009d9u, 0x000009d9u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00040073u, 0x000000b5u, 0x00000420u, 0x0000041fu, 0x00040063u, + 0x00000419u, 0x0000041du, 0x00000420u, 0x0004003du, 0x00000405u, 0x00000421u, 0x00000407u, 0x00060050u, + 0x0000040au, 0x00000425u, 0x0000040bu, 0x0000040cu, 0x0000004au, 0x0009004fu, 0x000000aau, 0x00000427u, + 0x000009d9u, 0x000009d9u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00040073u, 0x000000b5u, + 0x00000428u, 0x00000427u, 0x00040063u, 0x00000421u, 0x00000425u, 0x00000428u, 0x00050080u, 0x00000016u, + 0x0000042au, 0x00000a26u, 0x000000bcu, 0x000200f9u, 0x000003ddu, 0x000200f8u, 0x000003dfu, 0x000200f9u, + 0x000003d5u, 0x000200f8u, 0x000003d5u, 0x00050080u, 0x00000016u, 0x0000042cu, 0x00000a25u, 0x00000124u, + 0x000200f9u, 0x000003d2u, 0x000200f8u, 0x000003d4u, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, + 0x000d000bu, 0x00000a32u, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, 0x00000009u, 0x00020011u, + 0x00000038u, 0x00020011u, 0x0000003du, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, + 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0009000fu, 0x00000005u, 0x00000004u, 0x6e69616du, + 0x00000000u, 0x00000095u, 0x000003b5u, 0x000003b7u, 0x000003bau, 0x00060010u, 0x00000004u, 0x00000011u, + 0x00000040u, 0x00000001u, 0x00000001u, 0x00030047u, 0x0000006au, 0x00000002u, 0x00050048u, 0x0000006au, + 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x0000006au, 0x00000001u, 0x00000023u, 0x00000008u, + 0x00050048u, 0x0000006au, 0x00000002u, 0x00000023u, 0x00000010u, 0x00040047u, 0x00000095u, 0x0000000bu, + 0x0000001au, 0x00030047u, 0x000000b2u, 0x00000000u, 0x00040047u, 0x000000b2u, 0x00000021u, 0x00000000u, + 0x00040047u, 0x000000b2u, 0x00000022u, 0x00000000u, 0x00040047u, 0x000000d5u, 0x00000001u, 0x00000000u, + 0x00040047u, 0x000003b5u, 0x0000000bu, 0x00000028u, 0x00030047u, 0x000003b7u, 0x00000000u, 0x00040047u, + 0x000003b7u, 0x0000000bu, 0x00000024u, 0x00030047u, 0x000003b8u, 0x00000000u, 0x00030047u, 0x000003bau, + 0x00000000u, 0x00040047u, 0x000003bau, 0x0000000bu, 0x00000029u, 0x00030047u, 0x000003bbu, 0x00000000u, + 0x00030047u, 0x00000401u, 0x00000000u, 0x00030047u, 0x00000401u, 0x00000019u, 0x00040047u, 0x00000401u, + 0x00000021u, 0x00000001u, 0x00040047u, 0x00000401u, 0x00000022u, 0x00000000u, 0x00030047u, 0x00000402u, + 0x00000000u, 0x00030047u, 0x0000040au, 0x00000000u, 0x00030047u, 0x00000411u, 0x00000000u, 0x00030047u, + 0x00000418u, 0x00000000u, 0x00040047u, 0x00000424u, 0x0000000bu, 0x00000019u, 0x00030047u, 0x00000473u, + 0x00000000u, 0x00030047u, 0x00000476u, 0x00000000u, 0x00030047u, 0x00000478u, 0x00000000u, 0x00030047u, + 0x0000047cu, 0x00000000u, 0x00030047u, 0x0000047eu, 0x00000000u, 0x00030047u, 0x00000482u, 0x00000000u, + 0x00030047u, 0x00000484u, 0x00000000u, 0x00030047u, 0x00000488u, 0x00000000u, 0x00030047u, 0x000004f5u, + 0x00000000u, 0x00030047u, 0x000004fau, 0x00000000u, 0x00030047u, 0x00000521u, 0x00000000u, 0x00030047u, + 0x00000526u, 0x00000000u, 0x00030047u, 0x00000551u, 0x00000000u, 0x00030047u, 0x00000556u, 0x00000000u, + 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, + 0x00000000u, 0x00030016u, 0x00000008u, 0x00000020u, 0x00040017u, 0x00000009u, 0x00000008u, 0x00000002u, + 0x00040020u, 0x0000000fu, 0x00000007u, 0x00000009u, 0x00040015u, 0x00000016u, 0x00000020u, 0x00000001u, + 0x00040017u, 0x00000017u, 0x00000016u, 0x00000002u, 0x00020014u, 0x00000025u, 0x00030016u, 0x0000002du, + 0x00000010u, 0x00040017u, 0x0000002eu, 0x0000002du, 0x00000002u, 0x0004002bu, 0x00000006u, 0x0000002fu, + 0x00000029u, 0x0004001cu, 0x00000030u, 0x0000002eu, 0x0000002fu, 0x0004002bu, 0x00000006u, 0x00000031u, + 0x00000014u, 0x0004001cu, 0x00000032u, 0x00000030u, 0x00000031u, 0x00040020u, 0x00000033u, 0x00000004u, + 0x00000032u, 0x0004003bu, 0x00000033u, 0x00000034u, 0x00000004u, 0x00040020u, 0x00000037u, 0x00000004u, + 0x0000002eu, 0x0004002bu, 0x00000016u, 0x00000044u, 0x00000000u, 0x0004002bu, 0x00000016u, 0x00000045u, + 0x00000001u, 0x0004002bu, 0x00000016u, 0x00000049u, 0x00000002u, 0x0004002bu, 0x00000016u, 0x0000004cu, + 0x00000003u, 0x0004002bu, 0x00000016u, 0x00000052u, 0x00000005u, 0x0005002cu, 0x00000017u, 0x0000005fu, + 0x00000044u, 0x00000044u, 0x00040017u, 0x00000060u, 0x00000025u, 0x00000002u, 0x0005002cu, 0x00000017u, + 0x00000062u, 0x00000045u, 0x00000045u, 0x0005001eu, 0x0000006au, 0x00000017u, 0x00000009u, 0x00000017u, + 0x00040020u, 0x0000006bu, 0x00000009u, 0x0000006au, 0x0004003bu, 0x0000006bu, 0x0000006cu, 0x00000009u, + 0x00040020u, 0x0000006du, 0x00000009u, 0x00000017u, 0x00040020u, 0x0000008cu, 0x00000009u, 0x00000009u, + 0x00040017u, 0x00000093u, 0x00000006u, 0x00000003u, 0x00040020u, 0x00000094u, 0x00000001u, 0x00000093u, + 0x0004003bu, 0x00000094u, 0x00000095u, 0x00000001u, 0x00040017u, 0x00000096u, 0x00000006u, 0x00000002u, + 0x0004002bu, 0x00000016u, 0x0000009au, 0x00000020u, 0x0005002cu, 0x00000017u, 0x0000009bu, 0x0000009au, + 0x0000009au, 0x0004002bu, 0x00000016u, 0x0000009du, 0x00000004u, 0x00040017u, 0x000000acu, 0x00000008u, + 0x00000004u, 0x00090019u, 0x000000afu, 0x00000008u, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000001u, 0x00000000u, 0x0003001bu, 0x000000b0u, 0x000000afu, 0x00040020u, 0x000000b1u, 0x00000000u, + 0x000000b0u, 0x0004003bu, 0x000000b1u, 0x000000b2u, 0x00000000u, 0x0004002bu, 0x00000016u, 0x000000bcu, + 0x00000010u, 0x0005002cu, 0x00000017u, 0x000000bdu, 0x000000bcu, 0x00000044u, 0x0005002cu, 0x00000017u, + 0x000000c6u, 0x00000044u, 0x000000bcu, 0x0005002cu, 0x00000017u, 0x000000cfu, 0x000000bcu, 0x000000bcu, + 0x00030031u, 0x00000025u, 0x000000d5u, 0x0004002bu, 0x00000008u, 0x000000d8u, 0x3f000000u, 0x0004002bu, + 0x00000006u, 0x000000e6u, 0x00000001u, 0x0004002bu, 0x00000016u, 0x00000117u, 0x00000011u, 0x0004002bu, + 0x00000016u, 0x00000121u, 0x00000008u, 0x0004002bu, 0x00000006u, 0x00000156u, 0x00000020u, 0x0004002bu, + 0x00000006u, 0x00000157u, 0x00000002u, 0x0004002bu, 0x00000006u, 0x00000159u, 0x00000004u, 0x0004002bu, + 0x00000006u, 0x0000018fu, 0x00000010u, 0x0004002bu, 0x00000006u, 0x000001feu, 0x00000008u, 0x0004001cu, + 0x0000021bu, 0x00000009u, 0x0000018fu, 0x00040020u, 0x0000021cu, 0x00000007u, 0x0000021bu, 0x0004002bu, + 0x00000016u, 0x0000022au, 0x0000000fu, 0x0004002bu, 0x00000008u, 0x0000022du, 0xbfcb0673u, 0x0004002bu, + 0x00000016u, 0x00000245u, 0x0000000eu, 0x0004002bu, 0x00000008u, 0x00000248u, 0xbd5901aeu, 0x0004002bu, + 0x00000016u, 0x00000260u, 0x0000000du, 0x0004002bu, 0x00000008u, 0x00000263u, 0x3f620676u, 0x0004002bu, + 0x00000016u, 0x0000027bu, 0x0000000cu, 0x0004002bu, 0x00000008u, 0x0000027eu, 0x3ee31355u, 0x0004002bu, + 0x00000006u, 0x0000028fu, 0x00000108u, 0x0004002bu, 0x00000016u, 0x00000297u, 0x00000006u, 0x0004002bu, + 0x00000008u, 0x000002a5u, 0x3f5019c3u, 0x0004002bu, 0x00000008u, 0x000002a8u, 0x3f9d7658u, 0x0004002bu, + 0x00000006u, 0x000002fcu, 0x0000000cu, 0x0004001cu, 0x000002fdu, 0x00000009u, 0x000002fcu, 0x00040020u, + 0x000002feu, 0x00000007u, 0x000002fdu, 0x0004002bu, 0x00000016u, 0x0000030cu, 0x0000000bu, 0x0004002bu, + 0x00000016u, 0x00000326u, 0x0000000au, 0x0004002bu, 0x00000016u, 0x00000340u, 0x00000009u, 0x00040020u, + 0x000003b4u, 0x00000001u, 0x00000006u, 0x0004003bu, 0x000003b4u, 0x000003b5u, 0x00000001u, 0x0004003bu, + 0x000003b4u, 0x000003b7u, 0x00000001u, 0x0004003bu, 0x000003b4u, 0x000003bau, 0x00000001u, 0x00090019u, + 0x000003ffu, 0x00000008u, 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000002u, 0x00000000u, + 0x00040020u, 0x00000400u, 0x00000000u, 0x000003ffu, 0x0004003bu, 0x00000400u, 0x00000401u, 0x00000000u, + 0x00040017u, 0x00000404u, 0x00000016u, 0x00000003u, 0x0004002bu, 0x00000006u, 0x00000423u, 0x00000040u, + 0x0006002cu, 0x00000093u, 0x00000424u, 0x00000423u, 0x000000e6u, 0x000000e6u, 0x0005002cu, 0x00000017u, + 0x00000a2fu, 0x0000009du, 0x0000009du, 0x0005002cu, 0x00000017u, 0x00000a30u, 0x00000049u, 0x00000049u, + 0x0007002cu, 0x000000acu, 0x00000a31u, 0x000000d8u, 0x000000d8u, 0x000000d8u, 0x000000d8u, 0x00050036u, + 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, 0x0000021cu, + 0x000008e1u, 0x00000007u, 0x0004003bu, 0x000002feu, 0x000007f8u, 0x00000007u, 0x0004003bu, 0x0000021cu, + 0x00000718u, 0x00000007u, 0x0004003du, 0x00000006u, 0x000003b6u, 0x000003b5u, 0x0004003du, 0x00000006u, + 0x000003b8u, 0x000003b7u, 0x00050084u, 0x00000006u, 0x000003b9u, 0x000003b6u, 0x000003b8u, 0x0004003du, + 0x00000006u, 0x000003bbu, 0x000003bau, 0x00050080u, 0x00000006u, 0x000003bcu, 0x000003b9u, 0x000003bbu, + 0x0004003du, 0x00000093u, 0x00000466u, 0x00000095u, 0x0007004fu, 0x00000096u, 0x00000467u, 0x00000466u, + 0x00000466u, 0x00000000u, 0x00000001u, 0x0004007cu, 0x00000017u, 0x00000468u, 0x00000467u, 0x00050084u, + 0x00000017u, 0x00000469u, 0x00000468u, 0x0000009bu, 0x00050082u, 0x00000017u, 0x0000046bu, 0x00000469u, + 0x00000a2fu, 0x000600cbu, 0x00000006u, 0x00000579u, 0x000003bcu, 0x00000044u, 0x00000045u, 0x000600cbu, + 0x00000006u, 0x0000057bu, 0x000003bcu, 0x00000045u, 0x00000049u, 0x000600cbu, 0x00000006u, 0x0000057du, + 0x000003bcu, 0x0000004cu, 0x00000049u, 0x000500c4u, 0x00000006u, 0x0000057eu, 0x0000057du, 0x00000045u, + 0x000500c5u, 0x00000006u, 0x00000580u, 0x00000579u, 0x0000057eu, 0x000600cbu, 0x00000006u, 0x00000582u, + 0x000003bcu, 0x00000052u, 0x00000045u, 0x000500c4u, 0x00000006u, 0x00000583u, 0x00000582u, 0x00000049u, + 0x000500c5u, 0x00000006u, 0x00000585u, 0x0000057bu, 0x00000583u, 0x0004007cu, 0x00000016u, 0x00000587u, + 0x00000585u, 0x0004007cu, 0x00000016u, 0x00000589u, 0x00000580u, 0x00050050u, 0x00000017u, 0x0000058au, + 0x00000587u, 0x00000589u, 0x00050084u, 0x00000017u, 0x0000046fu, 0x00000a30u, 0x0000058au, 0x00050080u, + 0x00000017u, 0x00000472u, 0x0000046bu, 0x0000046fu, 0x0004003du, 0x000000b0u, 0x00000473u, 0x000000b2u, + 0x000500b1u, 0x00000060u, 0x00000590u, 0x00000472u, 0x0000005fu, 0x000600a9u, 0x00000017u, 0x00000591u, + 0x00000590u, 0x00000062u, 0x0000005fu, 0x00050082u, 0x00000017u, 0x00000593u, 0x00000472u, 0x00000591u, + 0x00050080u, 0x00000017u, 0x00000596u, 0x00000593u, 0x00000062u, 0x00050041u, 0x0000006du, 0x00000597u, + 0x0000006cu, 0x00000049u, 0x0004003du, 0x00000017u, 0x00000598u, 0x00000597u, 0x00050084u, 0x00000017u, + 0x0000059au, 0x00000a30u, 0x00000598u, 0x00050041u, 0x0000006du, 0x0000059bu, 0x0000006cu, 0x00000044u, + 0x0004003du, 0x00000017u, 0x0000059cu, 0x0000059bu, 0x00050082u, 0x00000017u, 0x0000059du, 0x0000059au, + 0x0000059cu, 0x00050082u, 0x00000017u, 0x000005a3u, 0x0000059cu, 0x00000598u, 0x00050084u, 0x00000017u, + 0x000005a5u, 0x00000a30u, 0x000005a3u, 0x00050080u, 0x00000017u, 0x000005a6u, 0x00000596u, 0x000005a5u, + 0x00050080u, 0x00000017u, 0x000005a8u, 0x000005a6u, 0x00000062u, 0x0007000cu, 0x00000017u, 0x000005acu, + 0x00000001u, 0x00000027u, 0x00000596u, 0x0000059cu, 0x000500afu, 0x00000060u, 0x000005b0u, 0x00000596u, + 0x0000059du, 0x000600a9u, 0x00000017u, 0x000005b1u, 0x000005b0u, 0x000005a8u, 0x000005acu, 0x0004006fu, + 0x00000009u, 0x000005b3u, 0x000005b1u, 0x00050041u, 0x0000008cu, 0x000005b4u, 0x0000006cu, 0x00000045u, + 0x0004003du, 0x00000009u, 0x000005b5u, 0x000005b4u, 0x00050085u, 0x00000009u, 0x000005b6u, 0x000005b3u, + 0x000005b5u, 0x00060060u, 0x000000acu, 0x00000476u, 0x00000473u, 0x000005b6u, 0x00000044u, 0x0009004fu, + 0x000000acu, 0x00000477u, 0x00000476u, 0x00000476u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, + 0x0004003du, 0x000000b0u, 0x00000478u, 0x000000b2u, 0x00050080u, 0x00000017u, 0x0000047au, 0x00000472u, + 0x000000bdu, 0x000500b1u, 0x00000060u, 0x000005bcu, 0x0000047au, 0x0000005fu, 0x000600a9u, 0x00000017u, + 0x000005bdu, 0x000005bcu, 0x00000062u, 0x0000005fu, 0x00050082u, 0x00000017u, 0x000005bfu, 0x0000047au, + 0x000005bdu, 0x00050080u, 0x00000017u, 0x000005c2u, 0x000005bfu, 0x00000062u, 0x00050080u, 0x00000017u, + 0x000005d2u, 0x000005c2u, 0x000005a5u, 0x00050080u, 0x00000017u, 0x000005d4u, 0x000005d2u, 0x00000062u, + 0x0007000cu, 0x00000017u, 0x000005d8u, 0x00000001u, 0x00000027u, 0x000005c2u, 0x0000059cu, 0x000500afu, + 0x00000060u, 0x000005dcu, 0x000005c2u, 0x0000059du, 0x000600a9u, 0x00000017u, 0x000005ddu, 0x000005dcu, + 0x000005d4u, 0x000005d8u, 0x0004006fu, 0x00000009u, 0x000005dfu, 0x000005ddu, 0x00050085u, 0x00000009u, + 0x000005e2u, 0x000005dfu, 0x000005b5u, 0x00060060u, 0x000000acu, 0x0000047cu, 0x00000478u, 0x000005e2u, + 0x00000044u, 0x0009004fu, 0x000000acu, 0x0000047du, 0x0000047cu, 0x0000047cu, 0x00000003u, 0x00000002u, + 0x00000000u, 0x00000001u, 0x0004003du, 0x000000b0u, 0x0000047eu, 0x000000b2u, 0x00050080u, 0x00000017u, + 0x00000480u, 0x00000472u, 0x000000c6u, 0x000500b1u, 0x00000060u, 0x000005e8u, 0x00000480u, 0x0000005fu, + 0x000600a9u, 0x00000017u, 0x000005e9u, 0x000005e8u, 0x00000062u, 0x0000005fu, 0x00050082u, 0x00000017u, + 0x000005ebu, 0x00000480u, 0x000005e9u, 0x00050080u, 0x00000017u, 0x000005eeu, 0x000005ebu, 0x00000062u, + 0x00050080u, 0x00000017u, 0x000005feu, 0x000005eeu, 0x000005a5u, 0x00050080u, 0x00000017u, 0x00000600u, + 0x000005feu, 0x00000062u, 0x0007000cu, 0x00000017u, 0x00000604u, 0x00000001u, 0x00000027u, 0x000005eeu, + 0x0000059cu, 0x000500afu, 0x00000060u, 0x00000608u, 0x000005eeu, 0x0000059du, 0x000600a9u, 0x00000017u, + 0x00000609u, 0x00000608u, 0x00000600u, 0x00000604u, 0x0004006fu, 0x00000009u, 0x0000060bu, 0x00000609u, + 0x00050085u, 0x00000009u, 0x0000060eu, 0x0000060bu, 0x000005b5u, 0x00060060u, 0x000000acu, 0x00000482u, + 0x0000047eu, 0x0000060eu, 0x00000044u, 0x0009004fu, 0x000000acu, 0x00000483u, 0x00000482u, 0x00000482u, + 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x0004003du, 0x000000b0u, 0x00000484u, 0x000000b2u, + 0x00050080u, 0x00000017u, 0x00000486u, 0x00000472u, 0x000000cfu, 0x000500b1u, 0x00000060u, 0x00000614u, + 0x00000486u, 0x0000005fu, 0x000600a9u, 0x00000017u, 0x00000615u, 0x00000614u, 0x00000062u, 0x0000005fu, + 0x00050082u, 0x00000017u, 0x00000617u, 0x00000486u, 0x00000615u, 0x00050080u, 0x00000017u, 0x0000061au, + 0x00000617u, 0x00000062u, 0x00050080u, 0x00000017u, 0x0000062au, 0x0000061au, 0x000005a5u, 0x00050080u, + 0x00000017u, 0x0000062cu, 0x0000062au, 0x00000062u, 0x0007000cu, 0x00000017u, 0x00000630u, 0x00000001u, + 0x00000027u, 0x0000061au, 0x0000059cu, 0x000500afu, 0x00000060u, 0x00000634u, 0x0000061au, 0x0000059du, + 0x000600a9u, 0x00000017u, 0x00000635u, 0x00000634u, 0x0000062cu, 0x00000630u, 0x0004006fu, 0x00000009u, + 0x00000637u, 0x00000635u, 0x00050085u, 0x00000009u, 0x0000063au, 0x00000637u, 0x000005b5u, 0x00060060u, + 0x000000acu, 0x00000488u, 0x00000484u, 0x0000063au, 0x00000044u, 0x0009004fu, 0x000000acu, 0x00000489u, + 0x00000488u, 0x00000488u, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, 0x00000497u, + 0x00000000u, 0x000400fau, 0x000000d5u, 0x0000048au, 0x00000497u, 0x000200f8u, 0x0000048au, 0x00050083u, + 0x000000acu, 0x0000048du, 0x00000477u, 0x00000a31u, 0x00050083u, 0x000000acu, 0x00000490u, 0x0000047du, + 0x00000a31u, 0x00050083u, 0x000000acu, 0x00000493u, 0x00000483u, 0x00000a31u, 0x00050083u, 0x000000acu, + 0x00000496u, 0x00000489u, 0x00000a31u, 0x000200f9u, 0x00000497u, 0x000200f8u, 0x00000497u, 0x000700f5u, + 0x000000acu, 0x00000a16u, 0x00000489u, 0x00000005u, 0x00000496u, 0x0000048au, 0x000700f5u, 0x000000acu, + 0x00000a15u, 0x00000483u, 0x00000005u, 0x00000493u, 0x0000048au, 0x000700f5u, 0x000000acu, 0x00000a14u, + 0x0000047du, 0x00000005u, 0x00000490u, 0x0000048au, 0x000700f5u, 0x000000acu, 0x00000a13u, 0x00000477u, + 0x00000005u, 0x0000048du, 0x0000048au, 0x00050051u, 0x00000016u, 0x00000499u, 0x0000046fu, 0x00000001u, + 0x000500c3u, 0x00000016u, 0x0000049au, 0x00000499u, 0x00000045u, 0x0004007cu, 0x00000006u, 0x0000049du, + 0x0000049au, 0x00050051u, 0x00000016u, 0x0000049fu, 0x0000046fu, 0x00000000u, 0x0004007cu, 0x00000006u, + 0x000004a1u, 0x0000049fu, 0x0007004fu, 0x00000009u, 0x000004a3u, 0x00000a13u, 0x00000a13u, 0x00000000u, + 0x00000002u, 0x00040073u, 0x0000002eu, 0x0000063fu, 0x000004a3u, 0x00060041u, 0x00000037u, 0x00000640u, + 0x00000034u, 0x0000049du, 0x000004a1u, 0x0003003eu, 0x00000640u, 0x0000063fu, 0x00050080u, 0x00000016u, + 0x000004aau, 0x0000049fu, 0x00000045u, 0x0004007cu, 0x00000006u, 0x000004abu, 0x000004aau, 0x0007004fu, + 0x00000009u, 0x000004adu, 0x00000a13u, 0x00000a13u, 0x00000001u, 0x00000003u, 0x00040073u, 0x0000002eu, + 0x00000645u, 0x000004adu, 0x00060041u, 0x00000037u, 0x00000646u, 0x00000034u, 0x0000049du, 0x000004abu, + 0x0003003eu, 0x00000646u, 0x00000645u, 0x00050080u, 0x00000016u, 0x000004b4u, 0x0000049fu, 0x000000bcu, + 0x0004007cu, 0x00000006u, 0x000004b5u, 0x000004b4u, 0x0007004fu, 0x00000009u, 0x000004b7u, 0x00000a14u, + 0x00000a14u, 0x00000000u, 0x00000002u, 0x00040073u, 0x0000002eu, 0x0000064bu, 0x000004b7u, 0x00060041u, + 0x00000037u, 0x0000064cu, 0x00000034u, 0x0000049du, 0x000004b5u, 0x0003003eu, 0x0000064cu, 0x0000064bu, + 0x00050080u, 0x00000016u, 0x000004beu, 0x0000049fu, 0x00000117u, 0x0004007cu, 0x00000006u, 0x000004bfu, + 0x000004beu, 0x0007004fu, 0x00000009u, 0x000004c1u, 0x00000a14u, 0x00000a14u, 0x00000001u, 0x00000003u, + 0x00040073u, 0x0000002eu, 0x00000651u, 0x000004c1u, 0x00060041u, 0x00000037u, 0x00000652u, 0x00000034u, + 0x0000049du, 0x000004bfu, 0x0003003eu, 0x00000652u, 0x00000651u, 0x00050080u, 0x00000016u, 0x000004c4u, + 0x0000049au, 0x00000121u, 0x0004007cu, 0x00000006u, 0x000004c5u, 0x000004c4u, 0x0007004fu, 0x00000009u, + 0x000004cbu, 0x00000a15u, 0x00000a15u, 0x00000000u, 0x00000002u, 0x00040073u, 0x0000002eu, 0x00000657u, + 0x000004cbu, 0x00060041u, 0x00000037u, 0x00000658u, 0x00000034u, 0x000004c5u, 0x000004a1u, 0x0003003eu, + 0x00000658u, 0x00000657u, 0x0007004fu, 0x00000009u, 0x000004d5u, 0x00000a15u, 0x00000a15u, 0x00000001u, + 0x00000003u, 0x00040073u, 0x0000002eu, 0x0000065du, 0x000004d5u, 0x00060041u, 0x00000037u, 0x0000065eu, + 0x00000034u, 0x000004c5u, 0x000004abu, 0x0003003eu, 0x0000065eu, 0x0000065du, 0x0007004fu, 0x00000009u, + 0x000004dfu, 0x00000a16u, 0x00000a16u, 0x00000000u, 0x00000002u, 0x00040073u, 0x0000002eu, 0x00000663u, + 0x000004dfu, 0x00060041u, 0x00000037u, 0x00000664u, 0x00000034u, 0x000004c5u, 0x000004b5u, 0x0003003eu, + 0x00000664u, 0x00000663u, 0x0007004fu, 0x00000009u, 0x000004e9u, 0x00000a16u, 0x00000a16u, 0x00000001u, + 0x00000003u, 0x00040073u, 0x0000002eu, 0x00000669u, 0x000004e9u, 0x00060041u, 0x00000037u, 0x0000066au, + 0x00000034u, 0x000004c5u, 0x000004bfu, 0x0003003eu, 0x0000066au, 0x00000669u, 0x00050089u, 0x00000006u, + 0x000004ecu, 0x000003bcu, 0x00000159u, 0x00050084u, 0x00000006u, 0x000004edu, 0x00000157u, 0x000004ecu, + 0x00050080u, 0x00000006u, 0x000004eeu, 0x00000156u, 0x000004edu, 0x0004007cu, 0x00000016u, 0x000004efu, + 0x000004eeu, 0x00050086u, 0x00000006u, 0x000004f1u, 0x000003bcu, 0x00000159u, 0x00050084u, 0x00000006u, + 0x000004f2u, 0x00000157u, 0x000004f1u, 0x0004007cu, 0x00000016u, 0x000004f3u, 0x000004f2u, 0x00050050u, + 0x00000017u, 0x000004f4u, 0x000004efu, 0x000004f3u, 0x0004003du, 0x000000b0u, 0x000004f5u, 0x000000b2u, + 0x00050080u, 0x00000017u, 0x000004f8u, 0x0000046bu, 0x000004f4u, 0x000500b1u, 0x00000060u, 0x00000670u, + 0x000004f8u, 0x0000005fu, 0x000600a9u, 0x00000017u, 0x00000671u, 0x00000670u, 0x00000062u, 0x0000005fu, + 0x00050082u, 0x00000017u, 0x00000673u, 0x000004f8u, 0x00000671u, 0x00050080u, 0x00000017u, 0x00000676u, + 0x00000673u, 0x00000062u, 0x00050080u, 0x00000017u, 0x00000686u, 0x00000676u, 0x000005a5u, 0x00050080u, + 0x00000017u, 0x00000688u, 0x00000686u, 0x00000062u, 0x0007000cu, 0x00000017u, 0x0000068cu, 0x00000001u, + 0x00000027u, 0x00000676u, 0x0000059cu, 0x000500afu, 0x00000060u, 0x00000690u, 0x00000676u, 0x0000059du, + 0x000600a9u, 0x00000017u, 0x00000691u, 0x00000690u, 0x00000688u, 0x0000068cu, 0x0004006fu, 0x00000009u, + 0x00000693u, 0x00000691u, 0x00050085u, 0x00000009u, 0x00000696u, 0x00000693u, 0x000005b5u, 0x00060060u, + 0x000000acu, 0x000004fau, 0x000004f5u, 0x00000696u, 0x00000044u, 0x0009004fu, 0x000000acu, 0x000004fbu, + 0x000004fau, 0x000004fau, 0x00000003u, 0x00000002u, 0x00000000u, 0x00000001u, 0x000300f7u, 0x00000500u, + 0x00000000u, 0x000400fau, 0x000000d5u, 0x000004fcu, 0x00000500u, 0x000200f8u, 0x000004fcu, 0x00050083u, + 0x000000acu, 0x000004ffu, 0x000004fbu, 0x00000a31u, 0x000200f9u, 0x00000500u, 0x000200f8u, 0x00000500u, + 0x000700f5u, 0x000000acu, 0x00000a17u, 0x000004fbu, 0x00000497u, 0x000004ffu, 0x000004fcu, 0x000500c3u, + 0x00000016u, 0x00000503u, 0x000004f3u, 0x00000045u, 0x0004007cu, 0x00000006u, 0x00000504u, 0x00000503u, + 0x0007004fu, 0x00000009u, 0x0000050au, 0x00000a17u, 0x00000a17u, 0x00000000u, 0x00000002u, 0x00040073u, + 0x0000002eu, 0x0000069bu, 0x0000050au, 0x00060041u, 0x00000037u, 0x0000069cu, 0x00000034u, 0x00000504u, + 0x000004eeu, 0x0003003eu, 0x0000069cu, 0x0000069bu, 0x00050080u, 0x00000016u, 0x00000512u, 0x000004efu, + 0x00000045u, 0x0004007cu, 0x00000006u, 0x00000513u, 0x00000512u, 0x0007004fu, 0x00000009u, 0x00000515u, + 0x00000a17u, 0x00000a17u, 0x00000001u, 0x00000003u, 0x00040073u, 0x0000002eu, 0x000006a1u, 0x00000515u, + 0x00060041u, 0x00000037u, 0x000006a2u, 0x00000034u, 0x00000504u, 0x00000513u, 0x0003003eu, 0x000006a2u, + 0x000006a1u, 0x00050089u, 0x00000006u, 0x00000518u, 0x000003bcu, 0x0000018fu, 0x00050084u, 0x00000006u, + 0x00000519u, 0x00000157u, 0x00000518u, 0x0004007cu, 0x00000016u, 0x0000051au, 0x00000519u, 0x00050086u, + 0x00000006u, 0x0000051cu, 0x000003bcu, 0x0000018fu, 0x00050084u, 0x00000006u, 0x0000051du, 0x00000157u, + 0x0000051cu, 0x00050080u, 0x00000006u, 0x0000051eu, 0x00000156u, 0x0000051du, 0x0004007cu, 0x00000016u, + 0x0000051fu, 0x0000051eu, 0x00050050u, 0x00000017u, 0x00000520u, 0x0000051au, 0x0000051fu, 0x0004003du, + 0x000000b0u, 0x00000521u, 0x000000b2u, 0x00050080u, 0x00000017u, 0x00000524u, 0x0000046bu, 0x00000520u, + 0x000500b1u, 0x00000060u, 0x000006a8u, 0x00000524u, 0x0000005fu, 0x000600a9u, 0x00000017u, 0x000006a9u, + 0x000006a8u, 0x00000062u, 0x0000005fu, 0x00050082u, 0x00000017u, 0x000006abu, 0x00000524u, 0x000006a9u, + 0x00050080u, 0x00000017u, 0x000006aeu, 0x000006abu, 0x00000062u, 0x00050080u, 0x00000017u, 0x000006beu, + 0x000006aeu, 0x000005a5u, 0x00050080u, 0x00000017u, 0x000006c0u, 0x000006beu, 0x00000062u, 0x0007000cu, + 0x00000017u, 0x000006c4u, 0x00000001u, 0x00000027u, 0x000006aeu, 0x0000059cu, 0x000500afu, 0x00000060u, + 0x000006c8u, 0x000006aeu, 0x0000059du, 0x000600a9u, 0x00000017u, 0x000006c9u, 0x000006c8u, 0x000006c0u, + 0x000006c4u, 0x0004006fu, 0x00000009u, 0x000006cbu, 0x000006c9u, 0x00050085u, 0x00000009u, 0x000006ceu, + 0x000006cbu, 0x000005b5u, 0x00060060u, 0x000000acu, 0x00000526u, 0x00000521u, 0x000006ceu, 0x00000044u, + 0x0009004fu, 0x000000acu, 0x00000527u, 0x00000526u, 0x00000526u, 0x00000003u, 0x00000002u, 0x00000000u, + 0x00000001u, 0x000300f7u, 0x0000052cu, 0x00000000u, 0x000400fau, 0x000000d5u, 0x00000528u, 0x0000052cu, + 0x000200f8u, 0x00000528u, 0x00050083u, 0x000000acu, 0x0000052bu, 0x00000527u, 0x00000a31u, 0x000200f9u, + 0x0000052cu, 0x000200f8u, 0x0000052cu, 0x000700f5u, 0x000000acu, 0x00000a18u, 0x00000527u, 0x00000500u, + 0x0000052bu, 0x00000528u, 0x000500c3u, 0x00000016u, 0x0000052fu, 0x0000051fu, 0x00000045u, 0x0004007cu, + 0x00000006u, 0x00000530u, 0x0000052fu, 0x0007004fu, 0x00000009u, 0x00000536u, 0x00000a18u, 0x00000a18u, + 0x00000000u, 0x00000002u, 0x00040073u, 0x0000002eu, 0x000006d3u, 0x00000536u, 0x00060041u, 0x00000037u, + 0x000006d4u, 0x00000034u, 0x00000530u, 0x00000519u, 0x0003003eu, 0x000006d4u, 0x000006d3u, 0x00050080u, + 0x00000016u, 0x0000053eu, 0x0000051au, 0x00000045u, 0x0004007cu, 0x00000006u, 0x0000053fu, 0x0000053eu, + 0x0007004fu, 0x00000009u, 0x00000541u, 0x00000a18u, 0x00000a18u, 0x00000001u, 0x00000003u, 0x00040073u, + 0x0000002eu, 0x000006d9u, 0x00000541u, 0x00060041u, 0x00000037u, 0x000006dau, 0x00000034u, 0x00000530u, + 0x0000053fu, 0x0003003eu, 0x000006dau, 0x000006d9u, 0x000500b0u, 0x00000025u, 0x00000544u, 0x000003bcu, + 0x0000018fu, 0x000300f7u, 0x00000573u, 0x00000000u, 0x000400fau, 0x00000544u, 0x00000545u, 0x00000573u, + 0x000200f8u, 0x00000545u, 0x00050080u, 0x00000006u, 0x0000054eu, 0x00000156u, 0x000004f2u, 0x0004007cu, + 0x00000016u, 0x0000054fu, 0x0000054eu, 0x00050050u, 0x00000017u, 0x00000550u, 0x000004efu, 0x0000054fu, + 0x0004003du, 0x000000b0u, 0x00000551u, 0x000000b2u, 0x00050080u, 0x00000017u, 0x00000554u, 0x0000046bu, + 0x00000550u, 0x000500b1u, 0x00000060u, 0x000006e0u, 0x00000554u, 0x0000005fu, 0x000600a9u, 0x00000017u, + 0x000006e1u, 0x000006e0u, 0x00000062u, 0x0000005fu, 0x00050082u, 0x00000017u, 0x000006e3u, 0x00000554u, + 0x000006e1u, 0x00050080u, 0x00000017u, 0x000006e6u, 0x000006e3u, 0x00000062u, 0x00050080u, 0x00000017u, + 0x000006f6u, 0x000006e6u, 0x000005a5u, 0x00050080u, 0x00000017u, 0x000006f8u, 0x000006f6u, 0x00000062u, + 0x0007000cu, 0x00000017u, 0x000006fcu, 0x00000001u, 0x00000027u, 0x000006e6u, 0x0000059cu, 0x000500afu, + 0x00000060u, 0x00000700u, 0x000006e6u, 0x0000059du, 0x000600a9u, 0x00000017u, 0x00000701u, 0x00000700u, + 0x000006f8u, 0x000006fcu, 0x0004006fu, 0x00000009u, 0x00000703u, 0x00000701u, 0x00050085u, 0x00000009u, + 0x00000706u, 0x00000703u, 0x000005b5u, 0x00060060u, 0x000000acu, 0x00000556u, 0x00000551u, 0x00000706u, + 0x00000044u, 0x0009004fu, 0x000000acu, 0x00000557u, 0x00000556u, 0x00000556u, 0x00000003u, 0x00000002u, + 0x00000000u, 0x00000001u, 0x000300f7u, 0x0000055cu, 0x00000000u, 0x000400fau, 0x000000d5u, 0x00000558u, + 0x0000055cu, 0x000200f8u, 0x00000558u, 0x00050083u, 0x000000acu, 0x0000055bu, 0x00000557u, 0x00000a31u, + 0x000200f9u, 0x0000055cu, 0x000200f8u, 0x0000055cu, 0x000700f5u, 0x000000acu, 0x00000a19u, 0x00000557u, + 0x00000545u, 0x0000055bu, 0x00000558u, 0x000500c3u, 0x00000016u, 0x0000055fu, 0x0000054fu, 0x00000045u, + 0x0004007cu, 0x00000006u, 0x00000560u, 0x0000055fu, 0x0007004fu, 0x00000009u, 0x00000566u, 0x00000a19u, + 0x00000a19u, 0x00000000u, 0x00000002u, 0x00040073u, 0x0000002eu, 0x0000070bu, 0x00000566u, 0x00060041u, + 0x00000037u, 0x0000070cu, 0x00000034u, 0x00000560u, 0x000004eeu, 0x0003003eu, 0x0000070cu, 0x0000070bu, + 0x0007004fu, 0x00000009u, 0x00000571u, 0x00000a19u, 0x00000a19u, 0x00000001u, 0x00000003u, 0x00040073u, + 0x0000002eu, 0x00000711u, 0x00000571u, 0x00060041u, 0x00000037u, 0x00000712u, 0x00000034u, 0x00000560u, + 0x00000513u, 0x0003003eu, 0x00000712u, 0x00000711u, 0x000200f9u, 0x00000573u, 0x000200f8u, 0x00000573u, + 0x000400e0u, 0x00000157u, 0x00000157u, 0x0000028fu, 0x00050084u, 0x00000006u, 0x0000072cu, 0x000001feu, + 0x000004ecu, 0x0004007cu, 0x00000016u, 0x0000072du, 0x0000072cu, 0x0004007cu, 0x00000016u, 0x00000730u, + 0x000004f1u, 0x000200f9u, 0x00000732u, 0x000200f8u, 0x00000732u, 0x000700f5u, 0x00000016u, 0x00000a1au, + 0x00000044u, 0x00000573u, 0x00000745u, 0x00000736u, 0x000500b1u, 0x00000025u, 0x00000735u, 0x00000a1au, + 0x000000bcu, 0x000400f6u, 0x00000746u, 0x00000736u, 0x00000000u, 0x000400fau, 0x00000735u, 0x00000736u, + 0x00000746u, 0x000200f8u, 0x00000736u, 0x00050080u, 0x00000016u, 0x0000073du, 0x0000072du, 0x00000a1au, + 0x0004007cu, 0x00000006u, 0x0000073eu, 0x0000073du, 0x00060041u, 0x00000037u, 0x000007e4u, 0x00000034u, + 0x000004f1u, 0x0000073eu, 0x0004003du, 0x0000002eu, 0x000007e5u, 0x000007e4u, 0x00040073u, 0x00000009u, + 0x000007e6u, 0x000007e5u, 0x00050041u, 0x0000000fu, 0x00000742u, 0x00000718u, 0x00000a1au, 0x0003003eu, + 0x00000742u, 0x000007e6u, 0x00050080u, 0x00000016u, 0x00000745u, 0x00000a1au, 0x00000045u, 0x000200f9u, + 0x00000732u, 0x000200f8u, 0x00000746u, 0x000200f9u, 0x00000747u, 0x000200f8u, 0x00000747u, 0x000700f5u, + 0x00000016u, 0x00000a1bu, 0x00000045u, 0x00000746u, 0x0000075du, 0x0000074bu, 0x000500b1u, 0x00000025u, + 0x0000074au, 0x00000a1bu, 0x0000022au, 0x000400f6u, 0x0000075eu, 0x0000074bu, 0x00000000u, 0x000400fau, + 0x0000074au, 0x0000074bu, 0x0000075eu, 0x000200f8u, 0x0000074bu, 0x00050082u, 0x00000016u, 0x0000074eu, + 0x00000a1bu, 0x00000045u, 0x00050041u, 0x0000000fu, 0x0000074fu, 0x00000718u, 0x0000074eu, 0x0004003du, + 0x00000009u, 0x00000750u, 0x0000074fu, 0x00050080u, 0x00000016u, 0x00000752u, 0x00000a1bu, 0x00000045u, + 0x00050041u, 0x0000000fu, 0x00000753u, 0x00000718u, 0x00000752u, 0x0004003du, 0x00000009u, 0x00000754u, + 0x00000753u, 0x00050081u, 0x00000009u, 0x00000755u, 0x00000750u, 0x00000754u, 0x0005008eu, 0x00000009u, + 0x00000756u, 0x00000755u, 0x0000022du, 0x00050041u, 0x0000000fu, 0x00000757u, 0x00000718u, 0x00000a1bu, + 0x0004003du, 0x00000009u, 0x00000758u, 0x00000757u, 0x00050081u, 0x00000009u, 0x00000759u, 0x00000758u, + 0x00000756u, 0x0003003eu, 0x00000757u, 0x00000759u, 0x00050080u, 0x00000016u, 0x0000075du, 0x00000a1bu, + 0x00000049u, 0x000200f9u, 0x00000747u, 0x000200f8u, 0x0000075eu, 0x000200f9u, 0x0000075fu, 0x000200f8u, + 0x0000075fu, 0x000700f5u, 0x00000016u, 0x00000a1cu, 0x00000049u, 0x0000075eu, 0x00000775u, 0x00000763u, + 0x000500b1u, 0x00000025u, 0x00000762u, 0x00000a1cu, 0x00000245u, 0x000400f6u, 0x00000776u, 0x00000763u, + 0x00000000u, 0x000400fau, 0x00000762u, 0x00000763u, 0x00000776u, 0x000200f8u, 0x00000763u, 0x00050082u, + 0x00000016u, 0x00000766u, 0x00000a1cu, 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000767u, 0x00000718u, + 0x00000766u, 0x0004003du, 0x00000009u, 0x00000768u, 0x00000767u, 0x00050080u, 0x00000016u, 0x0000076au, + 0x00000a1cu, 0x00000045u, 0x00050041u, 0x0000000fu, 0x0000076bu, 0x00000718u, 0x0000076au, 0x0004003du, + 0x00000009u, 0x0000076cu, 0x0000076bu, 0x00050081u, 0x00000009u, 0x0000076du, 0x00000768u, 0x0000076cu, + 0x0005008eu, 0x00000009u, 0x0000076eu, 0x0000076du, 0x00000248u, 0x00050041u, 0x0000000fu, 0x0000076fu, + 0x00000718u, 0x00000a1cu, 0x0004003du, 0x00000009u, 0x00000770u, 0x0000076fu, 0x00050081u, 0x00000009u, + 0x00000771u, 0x00000770u, 0x0000076eu, 0x0003003eu, 0x0000076fu, 0x00000771u, 0x00050080u, 0x00000016u, + 0x00000775u, 0x00000a1cu, 0x00000049u, 0x000200f9u, 0x0000075fu, 0x000200f8u, 0x00000776u, 0x000200f9u, + 0x00000777u, 0x000200f8u, 0x00000777u, 0x000700f5u, 0x00000016u, 0x00000a1du, 0x0000004cu, 0x00000776u, + 0x0000078du, 0x0000077bu, 0x000500b1u, 0x00000025u, 0x0000077au, 0x00000a1du, 0x00000260u, 0x000400f6u, + 0x0000078eu, 0x0000077bu, 0x00000000u, 0x000400fau, 0x0000077au, 0x0000077bu, 0x0000078eu, 0x000200f8u, + 0x0000077bu, 0x00050082u, 0x00000016u, 0x0000077eu, 0x00000a1du, 0x00000045u, 0x00050041u, 0x0000000fu, + 0x0000077fu, 0x00000718u, 0x0000077eu, 0x0004003du, 0x00000009u, 0x00000780u, 0x0000077fu, 0x00050080u, + 0x00000016u, 0x00000782u, 0x00000a1du, 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000783u, 0x00000718u, + 0x00000782u, 0x0004003du, 0x00000009u, 0x00000784u, 0x00000783u, 0x00050081u, 0x00000009u, 0x00000785u, + 0x00000780u, 0x00000784u, 0x0005008eu, 0x00000009u, 0x00000786u, 0x00000785u, 0x00000263u, 0x00050041u, + 0x0000000fu, 0x00000787u, 0x00000718u, 0x00000a1du, 0x0004003du, 0x00000009u, 0x00000788u, 0x00000787u, + 0x00050081u, 0x00000009u, 0x00000789u, 0x00000788u, 0x00000786u, 0x0003003eu, 0x00000787u, 0x00000789u, + 0x00050080u, 0x00000016u, 0x0000078du, 0x00000a1du, 0x00000049u, 0x000200f9u, 0x00000777u, 0x000200f8u, + 0x0000078eu, 0x000200f9u, 0x0000078fu, 0x000200f8u, 0x0000078fu, 0x000700f5u, 0x00000016u, 0x00000a1eu, + 0x0000009du, 0x0000078eu, 0x000007a5u, 0x00000793u, 0x000500b1u, 0x00000025u, 0x00000792u, 0x00000a1eu, + 0x0000027bu, 0x000400f6u, 0x000007a6u, 0x00000793u, 0x00000000u, 0x000400fau, 0x00000792u, 0x00000793u, + 0x000007a6u, 0x000200f8u, 0x00000793u, 0x00050082u, 0x00000016u, 0x00000796u, 0x00000a1eu, 0x00000045u, + 0x00050041u, 0x0000000fu, 0x00000797u, 0x00000718u, 0x00000796u, 0x0004003du, 0x00000009u, 0x00000798u, + 0x00000797u, 0x00050080u, 0x00000016u, 0x0000079au, 0x00000a1eu, 0x00000045u, 0x00050041u, 0x0000000fu, + 0x0000079bu, 0x00000718u, 0x0000079au, 0x0004003du, 0x00000009u, 0x0000079cu, 0x0000079bu, 0x00050081u, + 0x00000009u, 0x0000079du, 0x00000798u, 0x0000079cu, 0x0005008eu, 0x00000009u, 0x0000079eu, 0x0000079du, + 0x0000027eu, 0x00050041u, 0x0000000fu, 0x0000079fu, 0x00000718u, 0x00000a1eu, 0x0004003du, 0x00000009u, + 0x000007a0u, 0x0000079fu, 0x00050081u, 0x00000009u, 0x000007a1u, 0x000007a0u, 0x0000079eu, 0x0003003eu, + 0x0000079fu, 0x000007a1u, 0x00050080u, 0x00000016u, 0x000007a5u, 0x00000a1eu, 0x00000049u, 0x000200f9u, + 0x0000078fu, 0x000200f8u, 0x000007a6u, 0x000400e0u, 0x00000157u, 0x00000157u, 0x0000028fu, 0x000200f9u, + 0x000007a7u, 0x000200f8u, 0x000007a7u, 0x000700f5u, 0x00000016u, 0x00000a1fu, 0x00000049u, 0x000007a6u, + 0x000007deu, 0x000007abu, 0x000500b1u, 0x00000025u, 0x000007aau, 0x00000a1fu, 0x00000297u, 0x000400f6u, + 0x000007dfu, 0x000007abu, 0x00000000u, 0x000400fau, 0x000007aau, 0x000007abu, 0x000007dfu, 0x000200f8u, + 0x000007abu, 0x00050084u, 0x00000016u, 0x000007adu, 0x00000049u, 0x00000a1fu, 0x00050041u, 0x0000000fu, + 0x000007afu, 0x00000718u, 0x000007adu, 0x0004003du, 0x00000009u, 0x000007b0u, 0x000007afu, 0x00050080u, + 0x00000016u, 0x000007b3u, 0x000007adu, 0x00000045u, 0x00050041u, 0x0000000fu, 0x000007b4u, 0x00000718u, + 0x000007b3u, 0x0004003du, 0x00000009u, 0x000007b5u, 0x000007b4u, 0x0005008eu, 0x00000009u, 0x000007b7u, + 0x000007b0u, 0x000002a5u, 0x0005008eu, 0x00000009u, 0x000007b9u, 0x000007b5u, 0x000002a8u, 0x00050051u, + 0x00000008u, 0x000007bbu, 0x000007b7u, 0x00000000u, 0x00050051u, 0x00000008u, 0x000007bdu, 0x000007b9u, + 0x00000000u, 0x00050050u, 0x00000009u, 0x000007beu, 0x000007bbu, 0x000007bdu, 0x00050051u, 0x00000008u, + 0x000007c0u, 0x000007b7u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000007c2u, 0x000007b9u, 0x00000001u, + 0x00050050u, 0x00000009u, 0x000007c3u, 0x000007c0u, 0x000007c2u, 0x000500c3u, 0x00000016u, 0x000007c6u, + 0x0000072du, 0x00000045u, 0x00050082u, 0x00000016u, 0x000007c8u, 0x00000a1fu, 0x00000049u, 0x00050080u, + 0x00000016u, 0x000007c9u, 0x000007c6u, 0x000007c8u, 0x0004007cu, 0x00000006u, 0x000007cbu, 0x000007c9u, + 0x00050084u, 0x00000016u, 0x000007ceu, 0x00000049u, 0x00000730u, 0x0004007cu, 0x00000006u, 0x000007d0u, + 0x000007ceu, 0x00040073u, 0x0000002eu, 0x000007ebu, 0x000007beu, 0x00060041u, 0x00000037u, 0x000007ecu, + 0x00000034u, 0x000007cbu, 0x000007d0u, 0x0003003eu, 0x000007ecu, 0x000007ebu, 0x00050080u, 0x00000016u, + 0x000007d8u, 0x000007ceu, 0x00000045u, 0x0004007cu, 0x00000006u, 0x000007d9u, 0x000007d8u, 0x00040073u, + 0x0000002eu, 0x000007f1u, 0x000007c3u, 0x00060041u, 0x00000037u, 0x000007f2u, 0x00000034u, 0x000007cbu, + 0x000007d9u, 0x0003003eu, 0x000007f2u, 0x000007f1u, 0x00050080u, 0x00000016u, 0x000007deu, 0x00000a1fu, + 0x00000045u, 0x000200f9u, 0x000007a7u, 0x000200f8u, 0x000007dfu, 0x000500b0u, 0x00000025u, 0x000003c0u, + 0x000003bcu, 0x00000156u, 0x00050089u, 0x00000006u, 0x0000080bu, 0x000003bcu, 0x000001feu, 0x00050084u, + 0x00000006u, 0x0000080cu, 0x00000159u, 0x0000080bu, 0x0004007cu, 0x00000016u, 0x0000080du, 0x0000080cu, + 0x00050086u, 0x00000006u, 0x0000080fu, 0x000003bcu, 0x000001feu, 0x00050080u, 0x00000006u, 0x00000812u, + 0x0000080fu, 0x0000018fu, 0x0004007cu, 0x00000016u, 0x00000813u, 0x00000812u, 0x000300f7u, 0x0000088cu, + 0x00000000u, 0x000400fau, 0x000003c0u, 0x00000816u, 0x0000088cu, 0x000200f8u, 0x00000816u, 0x000200f9u, + 0x00000817u, 0x000200f8u, 0x00000817u, 0x000700f5u, 0x00000016u, 0x00000a20u, 0x00000044u, 0x00000816u, + 0x0000082au, 0x0000081bu, 0x000500b1u, 0x00000025u, 0x0000081au, 0x00000a20u, 0x0000027bu, 0x000400f6u, + 0x0000082bu, 0x0000081bu, 0x00000000u, 0x000400fau, 0x0000081au, 0x0000081bu, 0x0000082bu, 0x000200f8u, + 0x0000081bu, 0x00050080u, 0x00000016u, 0x00000822u, 0x0000080du, 0x00000a20u, 0x0004007cu, 0x00000006u, + 0x00000823u, 0x00000822u, 0x00060041u, 0x00000037u, 0x000008cdu, 0x00000034u, 0x00000812u, 0x00000823u, + 0x0004003du, 0x0000002eu, 0x000008ceu, 0x000008cdu, 0x00040073u, 0x00000009u, 0x000008cfu, 0x000008ceu, + 0x00050041u, 0x0000000fu, 0x00000827u, 0x000007f8u, 0x00000a20u, 0x0003003eu, 0x00000827u, 0x000008cfu, + 0x00050080u, 0x00000016u, 0x0000082au, 0x00000a20u, 0x00000045u, 0x000200f9u, 0x00000817u, 0x000200f8u, + 0x0000082bu, 0x000200f9u, 0x0000082cu, 0x000200f8u, 0x0000082cu, 0x000700f5u, 0x00000016u, 0x00000a21u, + 0x00000045u, 0x0000082bu, 0x00000842u, 0x00000830u, 0x000500b1u, 0x00000025u, 0x0000082fu, 0x00000a21u, + 0x0000030cu, 0x000400f6u, 0x00000843u, 0x00000830u, 0x00000000u, 0x000400fau, 0x0000082fu, 0x00000830u, + 0x00000843u, 0x000200f8u, 0x00000830u, 0x00050082u, 0x00000016u, 0x00000833u, 0x00000a21u, 0x00000045u, + 0x00050041u, 0x0000000fu, 0x00000834u, 0x000007f8u, 0x00000833u, 0x0004003du, 0x00000009u, 0x00000835u, + 0x00000834u, 0x00050080u, 0x00000016u, 0x00000837u, 0x00000a21u, 0x00000045u, 0x00050041u, 0x0000000fu, + 0x00000838u, 0x000007f8u, 0x00000837u, 0x0004003du, 0x00000009u, 0x00000839u, 0x00000838u, 0x00050081u, + 0x00000009u, 0x0000083au, 0x00000835u, 0x00000839u, 0x0005008eu, 0x00000009u, 0x0000083bu, 0x0000083au, + 0x0000022du, 0x00050041u, 0x0000000fu, 0x0000083cu, 0x000007f8u, 0x00000a21u, 0x0004003du, 0x00000009u, + 0x0000083du, 0x0000083cu, 0x00050081u, 0x00000009u, 0x0000083eu, 0x0000083du, 0x0000083bu, 0x0003003eu, + 0x0000083cu, 0x0000083eu, 0x00050080u, 0x00000016u, 0x00000842u, 0x00000a21u, 0x00000049u, 0x000200f9u, + 0x0000082cu, 0x000200f8u, 0x00000843u, 0x000200f9u, 0x00000844u, 0x000200f8u, 0x00000844u, 0x000700f5u, + 0x00000016u, 0x00000a22u, 0x00000049u, 0x00000843u, 0x0000085au, 0x00000848u, 0x000500b1u, 0x00000025u, + 0x00000847u, 0x00000a22u, 0x00000326u, 0x000400f6u, 0x0000085bu, 0x00000848u, 0x00000000u, 0x000400fau, + 0x00000847u, 0x00000848u, 0x0000085bu, 0x000200f8u, 0x00000848u, 0x00050082u, 0x00000016u, 0x0000084bu, + 0x00000a22u, 0x00000045u, 0x00050041u, 0x0000000fu, 0x0000084cu, 0x000007f8u, 0x0000084bu, 0x0004003du, + 0x00000009u, 0x0000084du, 0x0000084cu, 0x00050080u, 0x00000016u, 0x0000084fu, 0x00000a22u, 0x00000045u, + 0x00050041u, 0x0000000fu, 0x00000850u, 0x000007f8u, 0x0000084fu, 0x0004003du, 0x00000009u, 0x00000851u, + 0x00000850u, 0x00050081u, 0x00000009u, 0x00000852u, 0x0000084du, 0x00000851u, 0x0005008eu, 0x00000009u, + 0x00000853u, 0x00000852u, 0x00000248u, 0x00050041u, 0x0000000fu, 0x00000854u, 0x000007f8u, 0x00000a22u, + 0x0004003du, 0x00000009u, 0x00000855u, 0x00000854u, 0x00050081u, 0x00000009u, 0x00000856u, 0x00000855u, + 0x00000853u, 0x0003003eu, 0x00000854u, 0x00000856u, 0x00050080u, 0x00000016u, 0x0000085au, 0x00000a22u, + 0x00000049u, 0x000200f9u, 0x00000844u, 0x000200f8u, 0x0000085bu, 0x000200f9u, 0x0000085cu, 0x000200f8u, + 0x0000085cu, 0x000700f5u, 0x00000016u, 0x00000a23u, 0x0000004cu, 0x0000085bu, 0x00000872u, 0x00000860u, + 0x000500b1u, 0x00000025u, 0x0000085fu, 0x00000a23u, 0x00000340u, 0x000400f6u, 0x00000873u, 0x00000860u, + 0x00000000u, 0x000400fau, 0x0000085fu, 0x00000860u, 0x00000873u, 0x000200f8u, 0x00000860u, 0x00050082u, + 0x00000016u, 0x00000863u, 0x00000a23u, 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000864u, 0x000007f8u, + 0x00000863u, 0x0004003du, 0x00000009u, 0x00000865u, 0x00000864u, 0x00050080u, 0x00000016u, 0x00000867u, + 0x00000a23u, 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000868u, 0x000007f8u, 0x00000867u, 0x0004003du, + 0x00000009u, 0x00000869u, 0x00000868u, 0x00050081u, 0x00000009u, 0x0000086au, 0x00000865u, 0x00000869u, + 0x0005008eu, 0x00000009u, 0x0000086bu, 0x0000086au, 0x00000263u, 0x00050041u, 0x0000000fu, 0x0000086cu, + 0x000007f8u, 0x00000a23u, 0x0004003du, 0x00000009u, 0x0000086du, 0x0000086cu, 0x00050081u, 0x00000009u, + 0x0000086eu, 0x0000086du, 0x0000086bu, 0x0003003eu, 0x0000086cu, 0x0000086eu, 0x00050080u, 0x00000016u, + 0x00000872u, 0x00000a23u, 0x00000049u, 0x000200f9u, 0x0000085cu, 0x000200f8u, 0x00000873u, 0x000200f9u, + 0x00000874u, 0x000200f8u, 0x00000874u, 0x000700f5u, 0x00000016u, 0x00000a24u, 0x0000009du, 0x00000873u, + 0x0000088au, 0x00000878u, 0x000500b1u, 0x00000025u, 0x00000877u, 0x00000a24u, 0x00000121u, 0x000400f6u, + 0x0000088bu, 0x00000878u, 0x00000000u, 0x000400fau, 0x00000877u, 0x00000878u, 0x0000088bu, 0x000200f8u, + 0x00000878u, 0x00050082u, 0x00000016u, 0x0000087bu, 0x00000a24u, 0x00000045u, 0x00050041u, 0x0000000fu, + 0x0000087cu, 0x000007f8u, 0x0000087bu, 0x0004003du, 0x00000009u, 0x0000087du, 0x0000087cu, 0x00050080u, + 0x00000016u, 0x0000087fu, 0x00000a24u, 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000880u, 0x000007f8u, + 0x0000087fu, 0x0004003du, 0x00000009u, 0x00000881u, 0x00000880u, 0x00050081u, 0x00000009u, 0x00000882u, + 0x0000087du, 0x00000881u, 0x0005008eu, 0x00000009u, 0x00000883u, 0x00000882u, 0x0000027eu, 0x00050041u, + 0x0000000fu, 0x00000884u, 0x000007f8u, 0x00000a24u, 0x0004003du, 0x00000009u, 0x00000885u, 0x00000884u, + 0x00050081u, 0x00000009u, 0x00000886u, 0x00000885u, 0x00000883u, 0x0003003eu, 0x00000884u, 0x00000886u, + 0x00050080u, 0x00000016u, 0x0000088au, 0x00000a24u, 0x00000049u, 0x000200f9u, 0x00000874u, 0x000200f8u, + 0x0000088bu, 0x000200f9u, 0x0000088cu, 0x000200f8u, 0x0000088cu, 0x000400e0u, 0x00000157u, 0x00000157u, + 0x0000028fu, 0x000300f7u, 0x000008c8u, 0x00000000u, 0x000400fau, 0x000003c0u, 0x0000088eu, 0x000008c8u, + 0x000200f8u, 0x0000088eu, 0x000200f9u, 0x0000088fu, 0x000200f8u, 0x0000088fu, 0x000700f5u, 0x00000016u, + 0x00000a25u, 0x00000049u, 0x0000088eu, 0x000008c6u, 0x00000893u, 0x000500b1u, 0x00000025u, 0x00000892u, + 0x00000a25u, 0x0000009du, 0x000400f6u, 0x000008c7u, 0x00000893u, 0x00000000u, 0x000400fau, 0x00000892u, + 0x00000893u, 0x000008c7u, 0x000200f8u, 0x00000893u, 0x00050084u, 0x00000016u, 0x00000895u, 0x00000049u, + 0x00000a25u, 0x00050041u, 0x0000000fu, 0x00000897u, 0x000007f8u, 0x00000895u, 0x0004003du, 0x00000009u, + 0x00000898u, 0x00000897u, 0x00050080u, 0x00000016u, 0x0000089bu, 0x00000895u, 0x00000045u, 0x00050041u, + 0x0000000fu, 0x0000089cu, 0x000007f8u, 0x0000089bu, 0x0004003du, 0x00000009u, 0x0000089du, 0x0000089cu, + 0x0005008eu, 0x00000009u, 0x0000089fu, 0x00000898u, 0x000002a5u, 0x0005008eu, 0x00000009u, 0x000008a1u, + 0x0000089du, 0x000002a8u, 0x00050051u, 0x00000008u, 0x000008a3u, 0x0000089fu, 0x00000000u, 0x00050051u, + 0x00000008u, 0x000008a5u, 0x000008a1u, 0x00000000u, 0x00050050u, 0x00000009u, 0x000008a6u, 0x000008a3u, + 0x000008a5u, 0x00050051u, 0x00000008u, 0x000008a8u, 0x0000089fu, 0x00000001u, 0x00050051u, 0x00000008u, + 0x000008aau, 0x000008a1u, 0x00000001u, 0x00050050u, 0x00000009u, 0x000008abu, 0x000008a8u, 0x000008aau, + 0x000500c3u, 0x00000016u, 0x000008aeu, 0x0000080du, 0x00000045u, 0x00050082u, 0x00000016u, 0x000008b0u, + 0x00000a25u, 0x00000049u, 0x00050080u, 0x00000016u, 0x000008b1u, 0x000008aeu, 0x000008b0u, 0x0004007cu, + 0x00000006u, 0x000008b3u, 0x000008b1u, 0x00050084u, 0x00000016u, 0x000008b6u, 0x00000049u, 0x00000813u, + 0x0004007cu, 0x00000006u, 0x000008b8u, 0x000008b6u, 0x00040073u, 0x0000002eu, 0x000008d4u, 0x000008a6u, + 0x00060041u, 0x00000037u, 0x000008d5u, 0x00000034u, 0x000008b3u, 0x000008b8u, 0x0003003eu, 0x000008d5u, + 0x000008d4u, 0x00050080u, 0x00000016u, 0x000008c0u, 0x000008b6u, 0x00000045u, 0x0004007cu, 0x00000006u, + 0x000008c1u, 0x000008c0u, 0x00040073u, 0x0000002eu, 0x000008dau, 0x000008abu, 0x00060041u, 0x00000037u, + 0x000008dbu, 0x00000034u, 0x000008b3u, 0x000008c1u, 0x0003003eu, 0x000008dbu, 0x000008dau, 0x00050080u, + 0x00000016u, 0x000008c6u, 0x00000a25u, 0x00000045u, 0x000200f9u, 0x0000088fu, 0x000200f8u, 0x000008c7u, + 0x000200f9u, 0x000008c8u, 0x000200f8u, 0x000008c8u, 0x000400e0u, 0x00000157u, 0x00000157u, 0x0000028fu, + 0x000200f9u, 0x000008fbu, 0x000200f8u, 0x000008fbu, 0x000700f5u, 0x00000016u, 0x00000a26u, 0x00000044u, + 0x000008c8u, 0x0000090eu, 0x000008ffu, 0x000500b1u, 0x00000025u, 0x000008feu, 0x00000a26u, 0x000000bcu, + 0x000400f6u, 0x0000090fu, 0x000008ffu, 0x00000000u, 0x000400fau, 0x000008feu, 0x000008ffu, 0x0000090fu, + 0x000200f8u, 0x000008ffu, 0x00050080u, 0x00000016u, 0x00000906u, 0x0000072du, 0x00000a26u, 0x0004007cu, + 0x00000006u, 0x00000907u, 0x00000906u, 0x00060041u, 0x00000037u, 0x000009adu, 0x00000034u, 0x000004f1u, + 0x00000907u, 0x0004003du, 0x0000002eu, 0x000009aeu, 0x000009adu, 0x00040073u, 0x00000009u, 0x000009afu, + 0x000009aeu, 0x00050041u, 0x0000000fu, 0x0000090bu, 0x000008e1u, 0x00000a26u, 0x0003003eu, 0x0000090bu, + 0x000009afu, 0x00050080u, 0x00000016u, 0x0000090eu, 0x00000a26u, 0x00000045u, 0x000200f9u, 0x000008fbu, + 0x000200f8u, 0x0000090fu, 0x000200f9u, 0x00000910u, 0x000200f8u, 0x00000910u, 0x000700f5u, 0x00000016u, + 0x00000a27u, 0x00000045u, 0x0000090fu, 0x00000926u, 0x00000914u, 0x000500b1u, 0x00000025u, 0x00000913u, + 0x00000a27u, 0x0000022au, 0x000400f6u, 0x00000927u, 0x00000914u, 0x00000000u, 0x000400fau, 0x00000913u, + 0x00000914u, 0x00000927u, 0x000200f8u, 0x00000914u, 0x00050082u, 0x00000016u, 0x00000917u, 0x00000a27u, + 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000918u, 0x000008e1u, 0x00000917u, 0x0004003du, 0x00000009u, + 0x00000919u, 0x00000918u, 0x00050080u, 0x00000016u, 0x0000091bu, 0x00000a27u, 0x00000045u, 0x00050041u, + 0x0000000fu, 0x0000091cu, 0x000008e1u, 0x0000091bu, 0x0004003du, 0x00000009u, 0x0000091du, 0x0000091cu, + 0x00050081u, 0x00000009u, 0x0000091eu, 0x00000919u, 0x0000091du, 0x0005008eu, 0x00000009u, 0x0000091fu, + 0x0000091eu, 0x0000022du, 0x00050041u, 0x0000000fu, 0x00000920u, 0x000008e1u, 0x00000a27u, 0x0004003du, + 0x00000009u, 0x00000921u, 0x00000920u, 0x00050081u, 0x00000009u, 0x00000922u, 0x00000921u, 0x0000091fu, + 0x0003003eu, 0x00000920u, 0x00000922u, 0x00050080u, 0x00000016u, 0x00000926u, 0x00000a27u, 0x00000049u, + 0x000200f9u, 0x00000910u, 0x000200f8u, 0x00000927u, 0x000200f9u, 0x00000928u, 0x000200f8u, 0x00000928u, + 0x000700f5u, 0x00000016u, 0x00000a28u, 0x00000049u, 0x00000927u, 0x0000093eu, 0x0000092cu, 0x000500b1u, + 0x00000025u, 0x0000092bu, 0x00000a28u, 0x00000245u, 0x000400f6u, 0x0000093fu, 0x0000092cu, 0x00000000u, + 0x000400fau, 0x0000092bu, 0x0000092cu, 0x0000093fu, 0x000200f8u, 0x0000092cu, 0x00050082u, 0x00000016u, + 0x0000092fu, 0x00000a28u, 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000930u, 0x000008e1u, 0x0000092fu, + 0x0004003du, 0x00000009u, 0x00000931u, 0x00000930u, 0x00050080u, 0x00000016u, 0x00000933u, 0x00000a28u, + 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000934u, 0x000008e1u, 0x00000933u, 0x0004003du, 0x00000009u, + 0x00000935u, 0x00000934u, 0x00050081u, 0x00000009u, 0x00000936u, 0x00000931u, 0x00000935u, 0x0005008eu, + 0x00000009u, 0x00000937u, 0x00000936u, 0x00000248u, 0x00050041u, 0x0000000fu, 0x00000938u, 0x000008e1u, + 0x00000a28u, 0x0004003du, 0x00000009u, 0x00000939u, 0x00000938u, 0x00050081u, 0x00000009u, 0x0000093au, + 0x00000939u, 0x00000937u, 0x0003003eu, 0x00000938u, 0x0000093au, 0x00050080u, 0x00000016u, 0x0000093eu, + 0x00000a28u, 0x00000049u, 0x000200f9u, 0x00000928u, 0x000200f8u, 0x0000093fu, 0x000200f9u, 0x00000940u, + 0x000200f8u, 0x00000940u, 0x000700f5u, 0x00000016u, 0x00000a29u, 0x0000004cu, 0x0000093fu, 0x00000956u, + 0x00000944u, 0x000500b1u, 0x00000025u, 0x00000943u, 0x00000a29u, 0x00000260u, 0x000400f6u, 0x00000957u, + 0x00000944u, 0x00000000u, 0x000400fau, 0x00000943u, 0x00000944u, 0x00000957u, 0x000200f8u, 0x00000944u, + 0x00050082u, 0x00000016u, 0x00000947u, 0x00000a29u, 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000948u, + 0x000008e1u, 0x00000947u, 0x0004003du, 0x00000009u, 0x00000949u, 0x00000948u, 0x00050080u, 0x00000016u, + 0x0000094bu, 0x00000a29u, 0x00000045u, 0x00050041u, 0x0000000fu, 0x0000094cu, 0x000008e1u, 0x0000094bu, + 0x0004003du, 0x00000009u, 0x0000094du, 0x0000094cu, 0x00050081u, 0x00000009u, 0x0000094eu, 0x00000949u, + 0x0000094du, 0x0005008eu, 0x00000009u, 0x0000094fu, 0x0000094eu, 0x00000263u, 0x00050041u, 0x0000000fu, + 0x00000950u, 0x000008e1u, 0x00000a29u, 0x0004003du, 0x00000009u, 0x00000951u, 0x00000950u, 0x00050081u, + 0x00000009u, 0x00000952u, 0x00000951u, 0x0000094fu, 0x0003003eu, 0x00000950u, 0x00000952u, 0x00050080u, + 0x00000016u, 0x00000956u, 0x00000a29u, 0x00000049u, 0x000200f9u, 0x00000940u, 0x000200f8u, 0x00000957u, + 0x000200f9u, 0x00000958u, 0x000200f8u, 0x00000958u, 0x000700f5u, 0x00000016u, 0x00000a2au, 0x0000009du, + 0x00000957u, 0x0000096eu, 0x0000095cu, 0x000500b1u, 0x00000025u, 0x0000095bu, 0x00000a2au, 0x0000027bu, + 0x000400f6u, 0x0000096fu, 0x0000095cu, 0x00000000u, 0x000400fau, 0x0000095bu, 0x0000095cu, 0x0000096fu, + 0x000200f8u, 0x0000095cu, 0x00050082u, 0x00000016u, 0x0000095fu, 0x00000a2au, 0x00000045u, 0x00050041u, + 0x0000000fu, 0x00000960u, 0x000008e1u, 0x0000095fu, 0x0004003du, 0x00000009u, 0x00000961u, 0x00000960u, + 0x00050080u, 0x00000016u, 0x00000963u, 0x00000a2au, 0x00000045u, 0x00050041u, 0x0000000fu, 0x00000964u, + 0x000008e1u, 0x00000963u, 0x0004003du, 0x00000009u, 0x00000965u, 0x00000964u, 0x00050081u, 0x00000009u, + 0x00000966u, 0x00000961u, 0x00000965u, 0x0005008eu, 0x00000009u, 0x00000967u, 0x00000966u, 0x0000027eu, + 0x00050041u, 0x0000000fu, 0x00000968u, 0x000008e1u, 0x00000a2au, 0x0004003du, 0x00000009u, 0x00000969u, + 0x00000968u, 0x00050081u, 0x00000009u, 0x0000096au, 0x00000969u, 0x00000967u, 0x0003003eu, 0x00000968u, + 0x0000096au, 0x00050080u, 0x00000016u, 0x0000096eu, 0x00000a2au, 0x00000049u, 0x000200f9u, 0x00000958u, + 0x000200f8u, 0x0000096fu, 0x000400e0u, 0x00000157u, 0x00000157u, 0x0000028fu, 0x000200f9u, 0x00000970u, + 0x000200f8u, 0x00000970u, 0x000700f5u, 0x00000016u, 0x00000a2bu, 0x00000049u, 0x0000096fu, 0x000009a7u, + 0x00000974u, 0x000500b1u, 0x00000025u, 0x00000973u, 0x00000a2bu, 0x00000297u, 0x000400f6u, 0x000009a8u, + 0x00000974u, 0x00000000u, 0x000400fau, 0x00000973u, 0x00000974u, 0x000009a8u, 0x000200f8u, 0x00000974u, + 0x00050084u, 0x00000016u, 0x00000976u, 0x00000049u, 0x00000a2bu, 0x00050041u, 0x0000000fu, 0x00000978u, + 0x000008e1u, 0x00000976u, 0x0004003du, 0x00000009u, 0x00000979u, 0x00000978u, 0x00050080u, 0x00000016u, + 0x0000097cu, 0x00000976u, 0x00000045u, 0x00050041u, 0x0000000fu, 0x0000097du, 0x000008e1u, 0x0000097cu, + 0x0004003du, 0x00000009u, 0x0000097eu, 0x0000097du, 0x0005008eu, 0x00000009u, 0x00000980u, 0x00000979u, + 0x000002a5u, 0x0005008eu, 0x00000009u, 0x00000982u, 0x0000097eu, 0x000002a8u, 0x00050051u, 0x00000008u, + 0x00000984u, 0x00000980u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000986u, 0x00000982u, 0x00000000u, + 0x00050050u, 0x00000009u, 0x00000987u, 0x00000984u, 0x00000986u, 0x00050051u, 0x00000008u, 0x00000989u, + 0x00000980u, 0x00000001u, 0x00050051u, 0x00000008u, 0x0000098bu, 0x00000982u, 0x00000001u, 0x00050050u, + 0x00000009u, 0x0000098cu, 0x00000989u, 0x0000098bu, 0x000500c3u, 0x00000016u, 0x0000098fu, 0x0000072du, + 0x00000045u, 0x00050082u, 0x00000016u, 0x00000991u, 0x00000a2bu, 0x00000049u, 0x00050080u, 0x00000016u, + 0x00000992u, 0x0000098fu, 0x00000991u, 0x0004007cu, 0x00000006u, 0x00000994u, 0x00000992u, 0x00050084u, + 0x00000016u, 0x00000997u, 0x00000049u, 0x00000730u, 0x0004007cu, 0x00000006u, 0x00000999u, 0x00000997u, + 0x00040073u, 0x0000002eu, 0x000009b4u, 0x00000987u, 0x00060041u, 0x00000037u, 0x000009b5u, 0x00000034u, + 0x00000994u, 0x00000999u, 0x0003003eu, 0x000009b5u, 0x000009b4u, 0x00050080u, 0x00000016u, 0x000009a1u, + 0x00000997u, 0x00000045u, 0x0004007cu, 0x00000006u, 0x000009a2u, 0x000009a1u, 0x00040073u, 0x0000002eu, + 0x000009bau, 0x0000098cu, 0x00060041u, 0x00000037u, 0x000009bbu, 0x00000034u, 0x00000994u, 0x000009a2u, + 0x0003003eu, 0x000009bbu, 0x000009bau, 0x00050080u, 0x00000016u, 0x000009a7u, 0x00000a2bu, 0x00000045u, + 0x000200f9u, 0x00000970u, 0x000200f8u, 0x000009a8u, 0x000400e0u, 0x00000157u, 0x00000157u, 0x0000028fu, + 0x000200f9u, 0x000003ccu, 0x000200f8u, 0x000003ccu, 0x000700f5u, 0x00000016u, 0x00000a2cu, 0x00000589u, + 0x000009a8u, 0x00000422u, 0x000003cfu, 0x000500b1u, 0x00000025u, 0x000003d2u, 0x00000a2cu, 0x000000bcu, + 0x000400f6u, 0x000003ceu, 0x000003cfu, 0x00000000u, 0x000400fau, 0x000003d2u, 0x000003cdu, 0x000003ceu, + 0x000200f8u, 0x000003cdu, 0x00050084u, 0x00000016u, 0x000003d6u, 0x00000587u, 0x00000049u, 0x000200f9u, + 0x000003d7u, 0x000200f8u, 0x000003d7u, 0x000700f5u, 0x00000016u, 0x00000a2du, 0x000003d6u, 0x000003cdu, + 0x00000420u, 0x000003d8u, 0x000500b1u, 0x00000025u, 0x000003ddu, 0x00000a2du, 0x0000009au, 0x000400f6u, + 0x000003d9u, 0x000003d8u, 0x00000000u, 0x000400fau, 0x000003ddu, 0x000003d8u, 0x000003d9u, 0x000200f8u, + 0x000003d8u, 0x0004007cu, 0x00000006u, 0x000003e0u, 0x00000a2cu, 0x0004007cu, 0x00000006u, 0x000003e3u, + 0x00000a2du, 0x00060041u, 0x00000037u, 0x000009d7u, 0x00000034u, 0x000003e0u, 0x000003e3u, 0x0004003du, + 0x0000002eu, 0x000009d8u, 0x000009d7u, 0x00040073u, 0x00000009u, 0x000009d9u, 0x000009d8u, 0x00050080u, + 0x00000016u, 0x000003ebu, 0x00000a2du, 0x00000045u, 0x0004007cu, 0x00000006u, 0x000003ecu, 0x000003ebu, + 0x00060041u, 0x00000037u, 0x000009deu, 0x00000034u, 0x000003e0u, 0x000003ecu, 0x0004003du, 0x0000002eu, + 0x000009dfu, 0x000009deu, 0x00040073u, 0x00000009u, 0x000009e0u, 0x000009dfu, 0x000500c3u, 0x00000016u, + 0x000003f2u, 0x00000a2du, 0x00000045u, 0x00050084u, 0x00000017u, 0x000003fau, 0x00000468u, 0x000000cfu, + 0x00050050u, 0x00000017u, 0x000003fdu, 0x000003f2u, 0x00000a2cu, 0x00050080u, 0x00000017u, 0x000003feu, + 0x000003fau, 0x000003fdu, 0x0004003du, 0x000003ffu, 0x00000402u, 0x00000401u, 0x00050051u, 0x00000016u, + 0x00000405u, 0x000003feu, 0x00000000u, 0x00050051u, 0x00000016u, 0x00000406u, 0x000003feu, 0x00000001u, + 0x00060050u, 0x00000404u, 0x00000407u, 0x00000405u, 0x00000406u, 0x00000044u, 0x0009004fu, 0x000000acu, + 0x00000409u, 0x000009d9u, 0x000009d9u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00040063u, + 0x00000402u, 0x00000407u, 0x00000409u, 0x0004003du, 0x000003ffu, 0x0000040au, 0x00000401u, 0x00060050u, + 0x00000404u, 0x0000040eu, 0x00000405u, 0x00000406u, 0x00000049u, 0x0009004fu, 0x000000acu, 0x00000410u, + 0x000009d9u, 0x000009d9u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00040063u, 0x0000040au, + 0x0000040eu, 0x00000410u, 0x0004003du, 0x000003ffu, 0x00000411u, 0x00000401u, 0x00060050u, 0x00000404u, + 0x00000415u, 0x00000405u, 0x00000406u, 0x00000045u, 0x0009004fu, 0x000000acu, 0x00000417u, 0x000009e0u, + 0x000009e0u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00040063u, 0x00000411u, 0x00000415u, + 0x00000417u, 0x0004003du, 0x000003ffu, 0x00000418u, 0x00000401u, 0x00060050u, 0x00000404u, 0x0000041cu, + 0x00000405u, 0x00000406u, 0x0000004cu, 0x0009004fu, 0x000000acu, 0x0000041eu, 0x000009e0u, 0x000009e0u, + 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00040063u, 0x00000418u, 0x0000041cu, 0x0000041eu, + 0x00050080u, 0x00000016u, 0x00000420u, 0x00000a2du, 0x000000bcu, 0x000200f9u, 0x000003d7u, 0x000200f8u, + 0x000003d9u, 0x000200f9u, 0x000003cfu, 0x000200f8u, 0x000003cfu, 0x00050080u, 0x00000016u, 0x00000422u, + 0x00000a2cu, 0x00000121u, 0x000200f9u, 0x000003ccu, 0x000200f8u, 0x000003ceu, 0x000100fdu, 0x00010038u, + 0x07230203u, 0x00010300u, 0x000d000bu, 0x00000538u, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, + 0x0000003du, 0x00020011u, 0x00000040u, 0x00020011u, 0x00000041u, 0x00020011u, 0x00000042u, 0x00020011u, + 0x00000043u, 0x00020011u, 0x00001151u, 0x00020011u, 0x00001160u, 0x0007000au, 0x5f565053u, 0x5f52484bu, + 0x74696238u, 0x6f74735fu, 0x65676172u, 0x00000000u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, + 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0009000fu, 0x00000005u, 0x00000004u, + 0x6e69616du, 0x00000000u, 0x000000dcu, 0x00000145u, 0x00000147u, 0x00000154u, 0x00060010u, 0x00000004u, + 0x00000011u, 0x00000040u, 0x00000001u, 0x00000001u, 0x00040047u, 0x0000009eu, 0x00000006u, 0x00000001u, + 0x00030047u, 0x0000009fu, 0x00000002u, 0x00050048u, 0x0000009fu, 0x00000000u, 0x00000023u, 0x00000004u, + 0x00050048u, 0x0000009fu, 0x00000001u, 0x00000023u, 0x00000008u, 0x00040047u, 0x000000a1u, 0x00000021u, + 0x00000003u, 0x00040047u, 0x000000a1u, 0x00000022u, 0x00000000u, 0x00040047u, 0x000000aau, 0x00000006u, + 0x00000001u, 0x00030047u, 0x000000abu, 0x00000002u, 0x00040048u, 0x000000abu, 0x00000000u, 0x00000019u, + 0x00050048u, 0x000000abu, 0x00000000u, 0x00000023u, 0x00000000u, 0x00030047u, 0x000000adu, 0x00000019u, + 0x00040047u, 0x000000adu, 0x00000021u, 0x00000000u, 0x00040047u, 0x000000adu, 0x00000022u, 0x00000000u, + 0x00030047u, 0x000000dcu, 0x00000000u, 0x00040047u, 0x000000dcu, 0x0000000bu, 0x00000029u, 0x00030047u, + 0x00000144u, 0x00000000u, 0x00030047u, 0x00000145u, 0x00000000u, 0x00040047u, 0x00000145u, 0x0000000bu, + 0x00000024u, 0x00030047u, 0x00000146u, 0x00000000u, 0x00040047u, 0x00000147u, 0x0000000bu, 0x00000028u, + 0x00040047u, 0x00000154u, 0x0000000bu, 0x0000001au, 0x00030047u, 0x0000017au, 0x00000002u, 0x00050048u, + 0x0000017au, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x0000017au, 0x00000001u, 0x00000023u, + 0x00000008u, 0x00050048u, 0x0000017au, 0x00000002u, 0x00000023u, 0x00000010u, 0x00050048u, 0x0000017au, + 0x00000003u, 0x00000023u, 0x00000018u, 0x00050048u, 0x0000017au, 0x00000004u, 0x00000023u, 0x0000001cu, + 0x00050048u, 0x0000017au, 0x00000005u, 0x00000023u, 0x00000020u, 0x00050048u, 0x0000017au, 0x00000006u, + 0x00000023u, 0x00000024u, 0x00050048u, 0x0000017au, 0x00000007u, 0x00000023u, 0x00000028u, 0x00050048u, + 0x0000017au, 0x00000008u, 0x00000023u, 0x0000002cu, 0x00040047u, 0x0000019cu, 0x00000006u, 0x00000004u, + 0x00030047u, 0x0000019du, 0x00000002u, 0x00040048u, 0x0000019du, 0x00000000u, 0x00000018u, 0x00050048u, + 0x0000019du, 0x00000000u, 0x00000023u, 0x00000000u, 0x00030047u, 0x0000019fu, 0x00000018u, 0x00040047u, + 0x0000019fu, 0x00000021u, 0x00000005u, 0x00040047u, 0x0000019fu, 0x00000022u, 0x00000000u, 0x00050048u, + 0x000001b8u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x000001b8u, 0x00000001u, 0x00000023u, + 0x00000004u, 0x00040047u, 0x000001b9u, 0x00000006u, 0x00000008u, 0x00030047u, 0x000001bau, 0x00000002u, + 0x00040048u, 0x000001bau, 0x00000000u, 0x00000018u, 0x00050048u, 0x000001bau, 0x00000000u, 0x00000023u, + 0x00000000u, 0x00030047u, 0x000001bcu, 0x00000018u, 0x00040047u, 0x000001bcu, 0x00000021u, 0x00000002u, + 0x00040047u, 0x000001bcu, 0x00000022u, 0x00000000u, 0x00050048u, 0x000001c8u, 0x00000000u, 0x00000023u, + 0x00000000u, 0x00050048u, 0x000001c8u, 0x00000001u, 0x00000023u, 0x00000002u, 0x00040047u, 0x000001c9u, + 0x00000006u, 0x00000004u, 0x00050048u, 0x000001cau, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, + 0x000001cau, 0x00000001u, 0x00000023u, 0x00000004u, 0x00040047u, 0x000001cbu, 0x00000006u, 0x00000040u, + 0x00030047u, 0x000001ccu, 0x00000002u, 0x00040048u, 0x000001ccu, 0x00000000u, 0x00000018u, 0x00050048u, + 0x000001ccu, 0x00000000u, 0x00000023u, 0x00000000u, 0x00030047u, 0x000001ceu, 0x00000018u, 0x00040047u, + 0x000001ceu, 0x00000021u, 0x00000004u, 0x00040047u, 0x000001ceu, 0x00000022u, 0x00000000u, 0x00030047u, + 0x0000023du, 0x00000000u, 0x00040047u, 0x00000253u, 0x00000006u, 0x00000004u, 0x00030047u, 0x00000254u, + 0x00000002u, 0x00040048u, 0x00000254u, 0x00000000u, 0x00000019u, 0x00050048u, 0x00000254u, 0x00000000u, + 0x00000023u, 0x00000000u, 0x00030047u, 0x00000256u, 0x00000019u, 0x00040047u, 0x00000256u, 0x00000021u, + 0x00000000u, 0x00040047u, 0x00000256u, 0x00000022u, 0x00000000u, 0x00050048u, 0x00000270u, 0x00000000u, + 0x00000023u, 0x00000000u, 0x00050048u, 0x00000270u, 0x00000001u, 0x00000023u, 0x00000004u, 0x00040047u, + 0x00000271u, 0x00000006u, 0x00000008u, 0x00030047u, 0x00000272u, 0x00000002u, 0x00040048u, 0x00000272u, + 0x00000000u, 0x00000019u, 0x00050048u, 0x00000272u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00030047u, + 0x00000274u, 0x00000019u, 0x00040047u, 0x00000274u, 0x00000021u, 0x00000001u, 0x00040047u, 0x00000274u, + 0x00000022u, 0x00000000u, 0x00040047u, 0x00000305u, 0x00000006u, 0x00000002u, 0x00030047u, 0x00000306u, + 0x00000002u, 0x00040048u, 0x00000306u, 0x00000000u, 0x00000019u, 0x00050048u, 0x00000306u, 0x00000000u, + 0x00000023u, 0x00000000u, 0x00030047u, 0x00000308u, 0x00000019u, 0x00040047u, 0x00000308u, 0x00000021u, + 0x00000000u, 0x00040047u, 0x00000308u, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000373u, 0x0000000bu, + 0x00000019u, 0x00030047u, 0x000003eeu, 0x00000000u, 0x00030047u, 0x00000407u, 0x00000000u, 0x00020013u, + 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, 0x00000000u, + 0x00040015u, 0x0000000cu, 0x00000020u, 0x00000001u, 0x0004002bu, 0x00000006u, 0x0000002eu, 0x00000000u, + 0x0004002bu, 0x0000000cu, 0x00000032u, 0x00000010u, 0x0004002bu, 0x0000000cu, 0x00000033u, 0x00000004u, + 0x0004002bu, 0x00000006u, 0x00000038u, 0x00005555u, 0x0004002bu, 0x00000006u, 0x0000003cu, 0x0000aaaau, + 0x0004002bu, 0x0000000cu, 0x00000040u, 0x00000001u, 0x0004002bu, 0x0000000cu, 0x0000004bu, 0x00000008u, + 0x0004002bu, 0x0000000cu, 0x00000052u, 0x00000000u, 0x00020014u, 0x00000053u, 0x0004002bu, 0x0000000cu, + 0x0000006du, 0x00000003u, 0x00040015u, 0x0000009du, 0x00000008u, 0x00000000u, 0x0003001du, 0x0000009eu, + 0x0000009du, 0x0004001eu, 0x0000009fu, 0x00000006u, 0x0000009eu, 0x00040020u, 0x000000a0u, 0x0000000cu, + 0x0000009fu, 0x0004003bu, 0x000000a0u, 0x000000a1u, 0x0000000cu, 0x00040020u, 0x000000a3u, 0x0000000cu, + 0x0000009du, 0x0003001du, 0x000000aau, 0x0000009du, 0x0003001eu, 0x000000abu, 0x000000aau, 0x00040020u, + 0x000000acu, 0x0000000cu, 0x000000abu, 0x0004003bu, 0x000000acu, 0x000000adu, 0x0000000cu, 0x0004002bu, + 0x0000000cu, 0x000000beu, 0x00000005u, 0x0004002bu, 0x00000006u, 0x000000cdu, 0x00000001u, 0x0004002bu, + 0x00000006u, 0x000000d4u, 0x00000010u, 0x0004002bu, 0x00000006u, 0x000000d9u, 0x00000003u, 0x00040020u, + 0x000000dbu, 0x00000001u, 0x00000006u, 0x0004003bu, 0x000000dbu, 0x000000dcu, 0x00000001u, 0x0004002bu, + 0x00000006u, 0x000000deu, 0x0000000fu, 0x0004002bu, 0x00000006u, 0x000000e6u, 0x00000002u, 0x0004002bu, + 0x00000006u, 0x000000fcu, 0x0000001fu, 0x0004002bu, 0x0000000cu, 0x00000109u, 0x0000001fu, 0x0004002bu, + 0x00000006u, 0x0000010eu, 0xffffffffu, 0x0004002bu, 0x00000006u, 0x00000112u, 0x00000020u, 0x0004001cu, + 0x00000113u, 0x00000006u, 0x00000112u, 0x0004002bu, 0x00000006u, 0x00000114u, 0x00000004u, 0x0004001cu, + 0x00000115u, 0x00000113u, 0x00000114u, 0x00040020u, 0x00000116u, 0x00000004u, 0x00000115u, 0x0004003bu, + 0x00000116u, 0x00000117u, 0x00000004u, 0x00040020u, 0x0000011cu, 0x00000004u, 0x00000006u, 0x0004003bu, + 0x000000dbu, 0x00000145u, 0x00000001u, 0x0004003bu, 0x000000dbu, 0x00000147u, 0x00000001u, 0x00040017u, + 0x0000014eu, 0x0000000cu, 0x00000002u, 0x0004002bu, 0x0000000cu, 0x00000151u, 0x00000002u, 0x00040017u, + 0x00000152u, 0x00000006u, 0x00000003u, 0x00040020u, 0x00000153u, 0x00000001u, 0x00000152u, 0x0004003bu, + 0x00000153u, 0x00000154u, 0x00000001u, 0x00040017u, 0x00000155u, 0x00000006u, 0x00000002u, 0x000b001eu, + 0x0000017au, 0x0000014eu, 0x0000014eu, 0x0000014eu, 0x00000006u, 0x00000006u, 0x0000000cu, 0x0000000cu, + 0x0000000cu, 0x0000000cu, 0x00040020u, 0x0000017bu, 0x00000009u, 0x0000017au, 0x0004003bu, 0x0000017bu, + 0x0000017cu, 0x00000009u, 0x00040020u, 0x0000017du, 0x00000009u, 0x0000014eu, 0x00040017u, 0x00000180u, + 0x00000053u, 0x00000002u, 0x00040020u, 0x0000018eu, 0x00000009u, 0x0000000cu, 0x0004002bu, 0x0000000cu, + 0x00000191u, 0x00000006u, 0x0003001du, 0x0000019cu, 0x0000000cu, 0x0003001eu, 0x0000019du, 0x0000019cu, + 0x00040020u, 0x0000019eu, 0x0000000cu, 0x0000019du, 0x0004003bu, 0x0000019eu, 0x0000019fu, 0x0000000cu, + 0x00040020u, 0x000001a1u, 0x0000000cu, 0x0000000cu, 0x0004002bu, 0x0000000cu, 0x000001a9u, 0x00000007u, + 0x0004001eu, 0x000001b8u, 0x00000006u, 0x00000006u, 0x0003001du, 0x000001b9u, 0x000001b8u, 0x0003001eu, + 0x000001bau, 0x000001b9u, 0x00040020u, 0x000001bbu, 0x0000000cu, 0x000001bau, 0x0004003bu, 0x000001bbu, + 0x000001bcu, 0x0000000cu, 0x00040020u, 0x000001beu, 0x0000000cu, 0x000001b8u, 0x00030016u, 0x000001c6u, + 0x00000010u, 0x00040015u, 0x000001c7u, 0x00000010u, 0x00000000u, 0x0004001eu, 0x000001c8u, 0x000001c6u, + 0x000001c7u, 0x0004001cu, 0x000001c9u, 0x000001c8u, 0x000000deu, 0x0004001eu, 0x000001cau, 0x00000006u, + 0x000001c9u, 0x0003001du, 0x000001cbu, 0x000001cau, 0x0003001eu, 0x000001ccu, 0x000001cbu, 0x00040020u, + 0x000001cdu, 0x0000000cu, 0x000001ccu, 0x0004003bu, 0x000001cdu, 0x000001ceu, 0x0000000cu, 0x00040020u, + 0x000001d0u, 0x0000000cu, 0x00000006u, 0x00040020u, 0x000001d8u, 0x0000000cu, 0x000001c7u, 0x0004002bu, + 0x00000006u, 0x000001e7u, 0x0000ffffu, 0x00040017u, 0x000001eau, 0x00000006u, 0x00000004u, 0x0004002bu, + 0x00000006u, 0x000001f1u, 0x00000040u, 0x0004002bu, 0x00000006u, 0x0000020cu, 0x00000008u, 0x0004002bu, + 0x00000006u, 0x00000215u, 0x00000018u, 0x0003001du, 0x00000253u, 0x00000006u, 0x0003001eu, 0x00000254u, + 0x00000253u, 0x00040020u, 0x00000255u, 0x0000000cu, 0x00000254u, 0x0004003bu, 0x00000255u, 0x00000256u, + 0x0000000cu, 0x00040020u, 0x0000025du, 0x00000009u, 0x00000006u, 0x0004002bu, 0x0000000cu, 0x00000260u, + 0x0000001cu, 0x0004001eu, 0x00000270u, 0x00000006u, 0x00000006u, 0x0003001du, 0x00000271u, 0x00000270u, + 0x0003001eu, 0x00000272u, 0x00000271u, 0x00040020u, 0x00000273u, 0x0000000cu, 0x00000272u, 0x0004003bu, + 0x00000273u, 0x00000274u, 0x0000000cu, 0x0004002bu, 0x00000006u, 0x000002a6u, 0x00000007u, 0x0003001du, + 0x00000305u, 0x000001c7u, 0x0003001eu, 0x00000306u, 0x00000305u, 0x00040020u, 0x00000307u, 0x0000000cu, + 0x00000306u, 0x0004003bu, 0x00000307u, 0x00000308u, 0x0000000cu, 0x0004002bu, 0x00000006u, 0x0000031du, + 0x00000d48u, 0x0004002bu, 0x0000000cu, 0x00000349u, 0x00000018u, 0x0004002bu, 0x00000006u, 0x00000351u, + 0xfffffffcu, 0x0006002cu, 0x00000152u, 0x00000373u, 0x000001f1u, 0x000000cdu, 0x000000cdu, 0x0005002cu, + 0x0000014eu, 0x00000532u, 0x00000151u, 0x00000151u, 0x0005002cu, 0x0000014eu, 0x00000533u, 0x00000033u, + 0x00000033u, 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, + 0x0004003du, 0x00000006u, 0x00000144u, 0x000000dcu, 0x0004003du, 0x00000006u, 0x00000146u, 0x00000145u, + 0x0004003du, 0x00000006u, 0x00000148u, 0x00000147u, 0x00050084u, 0x00000006u, 0x00000149u, 0x00000146u, + 0x00000148u, 0x00050080u, 0x00000006u, 0x0000014au, 0x00000144u, 0x00000149u, 0x000500c2u, 0x00000006u, + 0x0000014du, 0x0000014au, 0x00000033u, 0x0004003du, 0x00000152u, 0x00000156u, 0x00000154u, 0x0007004fu, + 0x00000155u, 0x00000157u, 0x00000156u, 0x00000156u, 0x00000000u, 0x00000001u, 0x0004007cu, 0x0000014eu, + 0x00000158u, 0x00000157u, 0x00050084u, 0x0000014eu, 0x0000015au, 0x00000532u, 0x00000158u, 0x000600cbu, + 0x00000006u, 0x0000015cu, 0x0000014au, 0x00000033u, 0x00000040u, 0x0004007cu, 0x0000000cu, 0x0000015du, + 0x0000015cu, 0x00050051u, 0x0000000cu, 0x0000015fu, 0x0000015au, 0x00000000u, 0x00050080u, 0x0000000cu, + 0x00000160u, 0x0000015fu, 0x0000015du, 0x000600cbu, 0x00000006u, 0x00000163u, 0x0000014au, 0x000000beu, + 0x00000040u, 0x0004007cu, 0x0000000cu, 0x00000164u, 0x00000163u, 0x00050051u, 0x0000000cu, 0x00000166u, + 0x0000015au, 0x00000001u, 0x00050080u, 0x0000000cu, 0x00000167u, 0x00000166u, 0x00000164u, 0x00050050u, + 0x0000014eu, 0x00000536u, 0x00000160u, 0x00000167u, 0x000600cbu, 0x00000006u, 0x0000016bu, 0x0000014au, + 0x00000052u, 0x00000151u, 0x0004007cu, 0x0000000cu, 0x0000016cu, 0x0000016bu, 0x000600cbu, 0x00000006u, + 0x0000016eu, 0x0000014au, 0x00000151u, 0x00000151u, 0x0004007cu, 0x0000000cu, 0x0000016fu, 0x0000016eu, + 0x00050050u, 0x0000014eu, 0x00000170u, 0x0000016cu, 0x0000016fu, 0x00050084u, 0x0000014eu, 0x00000174u, + 0x00000533u, 0x00000536u, 0x00050080u, 0x0000014eu, 0x00000176u, 0x00000174u, 0x00000170u, 0x00050041u, + 0x0000017du, 0x0000017eu, 0x0000017cu, 0x00000151u, 0x0004003du, 0x0000014eu, 0x0000017fu, 0x0000017eu, + 0x000500b1u, 0x00000180u, 0x00000181u, 0x00000176u, 0x0000017fu, 0x0004009bu, 0x00000053u, 0x00000182u, + 0x00000181u, 0x00050041u, 0x0000017du, 0x00000185u, 0x0000017cu, 0x00000040u, 0x0004003du, 0x0000014eu, + 0x00000186u, 0x00000185u, 0x000500b1u, 0x00000180u, 0x00000187u, 0x00000536u, 0x00000186u, 0x0004009bu, + 0x00000053u, 0x00000188u, 0x00000187u, 0x000300f7u, 0x0000018cu, 0x00000000u, 0x000400fau, 0x00000188u, + 0x0000018bu, 0x000001a4u, 0x000200f8u, 0x0000018bu, 0x00050041u, 0x0000018eu, 0x0000018fu, 0x0000017cu, + 0x000000beu, 0x0004003du, 0x0000000cu, 0x00000190u, 0x0000018fu, 0x00050041u, 0x0000018eu, 0x00000192u, + 0x0000017cu, 0x00000191u, 0x0004003du, 0x0000000cu, 0x00000193u, 0x00000192u, 0x00050084u, 0x0000000cu, + 0x00000196u, 0x00000193u, 0x00000167u, 0x00050080u, 0x0000000cu, 0x00000197u, 0x00000190u, 0x00000196u, + 0x00050080u, 0x0000000cu, 0x0000019au, 0x00000197u, 0x00000160u, 0x00060041u, 0x000001a1u, 0x000001a2u, + 0x0000019fu, 0x00000052u, 0x0000019au, 0x0004003du, 0x0000000cu, 0x000001a3u, 0x000001a2u, 0x000200f9u, + 0x0000018cu, 0x000200f8u, 0x000001a4u, 0x000200f9u, 0x0000018cu, 0x000200f8u, 0x0000018cu, 0x000700f5u, + 0x0000000cu, 0x00000491u, 0x000001a3u, 0x0000018bu, 0x00000052u, 0x000001a4u, 0x000300f7u, 0x000001a7u, + 0x00000000u, 0x000400fau, 0x00000182u, 0x000001a6u, 0x000001dcu, 0x000200f8u, 0x000001a6u, 0x00050041u, + 0x0000018eu, 0x000001aau, 0x0000017cu, 0x000001a9u, 0x0004003du, 0x0000000cu, 0x000001abu, 0x000001aau, + 0x00050041u, 0x0000018eu, 0x000001acu, 0x0000017cu, 0x0000004bu, 0x0004003du, 0x0000000cu, 0x000001adu, + 0x000001acu, 0x00050051u, 0x0000000cu, 0x000001afu, 0x00000176u, 0x00000001u, 0x00050084u, 0x0000000cu, + 0x000001b0u, 0x000001adu, 0x000001afu, 0x00050080u, 0x0000000cu, 0x000001b1u, 0x000001abu, 0x000001b0u, + 0x00050051u, 0x0000000cu, 0x000001b3u, 0x00000176u, 0x00000000u, 0x00050080u, 0x0000000cu, 0x000001b4u, + 0x000001b1u, 0x000001b3u, 0x00060041u, 0x000001beu, 0x000001bfu, 0x000001bcu, 0x00000052u, 0x000001b4u, + 0x0004003du, 0x000001b8u, 0x000001c0u, 0x000001bfu, 0x00050051u, 0x00000006u, 0x000001c1u, 0x000001c0u, + 0x00000000u, 0x00050051u, 0x00000006u, 0x000001c3u, 0x000001c0u, 0x00000001u, 0x00070041u, 0x000001d0u, + 0x000001d1u, 0x000001ceu, 0x00000052u, 0x000001b4u, 0x00000052u, 0x0004003du, 0x00000006u, 0x000001d2u, + 0x000001d1u, 0x0004007cu, 0x00000006u, 0x000001d6u, 0x00000491u, 0x0007000cu, 0x00000006u, 0x000001d7u, + 0x00000001u, 0x00000026u, 0x000001d2u, 0x000001d6u, 0x00090041u, 0x000001d8u, 0x000001d9u, 0x000001ceu, + 0x00000052u, 0x000001b4u, 0x00000040u, 0x000001d7u, 0x00000040u, 0x0004003du, 0x000001c7u, 0x000001dau, + 0x000001d9u, 0x00040071u, 0x00000006u, 0x000001dbu, 0x000001dau, 0x000200f9u, 0x000001a7u, 0x000200f8u, + 0x000001dcu, 0x000200f9u, 0x000001a7u, 0x000200f8u, 0x000001a7u, 0x000700f5u, 0x00000006u, 0x000004ccu, + 0x000001c3u, 0x000001a6u, 0x0000002eu, 0x000001dcu, 0x000700f5u, 0x00000006u, 0x0000049du, 0x000001dbu, + 0x000001a6u, 0x0000002eu, 0x000001dcu, 0x000700f5u, 0x00000006u, 0x00000492u, 0x000001c1u, 0x000001a6u, + 0x0000002eu, 0x000001dcu, 0x000500abu, 0x00000053u, 0x0000037du, 0x00000491u, 0x00000052u, 0x000500abu, + 0x00000053u, 0x0000037fu, 0x00000492u, 0x0000002eu, 0x000500a7u, 0x00000053u, 0x00000380u, 0x0000037du, + 0x0000037fu, 0x000300f7u, 0x000003b5u, 0x00000000u, 0x000400fau, 0x00000380u, 0x00000381u, 0x000003b5u, + 0x000200f8u, 0x00000381u, 0x000600cbu, 0x00000006u, 0x00000383u, 0x00000492u, 0x00000032u, 0x00000033u, + 0x0004007cu, 0x0000000cu, 0x00000384u, 0x00000383u, 0x0007000cu, 0x0000000cu, 0x00000387u, 0x00000001u, + 0x00000027u, 0x00000384u, 0x00000491u, 0x00050082u, 0x0000000cu, 0x0000038au, 0x00000384u, 0x00000387u, + 0x00050082u, 0x0000000cu, 0x0000038du, 0x00000491u, 0x00000387u, 0x000500abu, 0x00000053u, 0x0000038fu, + 0x0000038du, 0x00000052u, 0x000300f7u, 0x000003b0u, 0x00000000u, 0x000400fau, 0x0000038fu, 0x00000390u, + 0x000003b0u, 0x000200f8u, 0x00000390u, 0x0007000cu, 0x0000000cu, 0x00000392u, 0x00000001u, 0x00000027u, + 0x0000038du, 0x0000006du, 0x000500c7u, 0x00000006u, 0x00000394u, 0x00000492u, 0x00000038u, 0x000500c7u, + 0x00000006u, 0x00000396u, 0x00000492u, 0x0000003cu, 0x000500c2u, 0x00000006u, 0x00000397u, 0x00000396u, + 0x00000040u, 0x000500c7u, 0x00000006u, 0x0000039au, 0x00000394u, 0x00000397u, 0x000200f9u, 0x0000039bu, + 0x000200f8u, 0x0000039bu, 0x000700f5u, 0x0000000cu, 0x00000496u, 0x00000392u, 0x00000390u, 0x000003a0u, + 0x0000039bu, 0x000700f5u, 0x00000006u, 0x00000495u, 0x0000039au, 0x00000390u, 0x0000002eu, 0x0000039bu, + 0x000700f5u, 0x00000006u, 0x00000494u, 0x00000397u, 0x00000390u, 0x00000495u, 0x0000039bu, 0x00050082u, + 0x0000000cu, 0x000003a0u, 0x00000496u, 0x00000040u, 0x000500abu, 0x00000053u, 0x000003a3u, 0x000003a0u, + 0x00000052u, 0x000400f6u, 0x000003a4u, 0x0000039bu, 0x00000000u, 0x000400fau, 0x000003a3u, 0x0000039bu, + 0x000003a4u, 0x000200f8u, 0x000003a4u, 0x000400c8u, 0x00000006u, 0x000003a6u, 0x00000495u, 0x000500c7u, + 0x00000006u, 0x000003a8u, 0x00000494u, 0x000003a6u, 0x000500c4u, 0x00000006u, 0x000003abu, 0x00000495u, + 0x00000040u, 0x000500c5u, 0x00000006u, 0x000003acu, 0x000003a8u, 0x000003abu, 0x000700c9u, 0x00000006u, + 0x000003afu, 0x00000492u, 0x000003acu, 0x00000052u, 0x00000032u, 0x000200f9u, 0x000003b0u, 0x000200f8u, + 0x000003b0u, 0x000700f5u, 0x00000006u, 0x00000498u, 0x00000492u, 0x00000381u, 0x000003afu, 0x000003a4u, + 0x0004007cu, 0x00000006u, 0x000003b3u, 0x0000038au, 0x000700c9u, 0x00000006u, 0x000003b4u, 0x00000498u, + 0x000003b3u, 0x00000032u, 0x00000033u, 0x000200f9u, 0x000003b5u, 0x000200f8u, 0x000003b5u, 0x000700f5u, + 0x00000006u, 0x00000499u, 0x00000492u, 0x000001a7u, 0x000003b4u, 0x000003b0u, 0x000500c7u, 0x00000006u, + 0x000001e8u, 0x00000499u, 0x000001e7u, 0x000500abu, 0x00000053u, 0x000001e9u, 0x000001e8u, 0x0000002eu, + 0x00050153u, 0x000001eau, 0x000001eeu, 0x000000d9u, 0x000001e9u, 0x000500aeu, 0x00000053u, 0x000001f2u, + 0x00000146u, 0x000001f1u, 0x000500aeu, 0x00000053u, 0x000001f4u, 0x0000014du, 0x000000e6u, 0x000500a7u, + 0x00000053u, 0x000001f5u, 0x000001f2u, 0x000001f4u, 0x000300f7u, 0x000001f8u, 0x00000000u, 0x000400fau, + 0x000001f5u, 0x000001f7u, 0x000001fbu, 0x000200f8u, 0x000001f7u, 0x00050051u, 0x00000006u, 0x000001fau, + 0x000001eeu, 0x00000001u, 0x000200f9u, 0x000001f8u, 0x000200f8u, 0x000001fbu, 0x00050051u, 0x00000006u, + 0x000001fdu, 0x000001eeu, 0x00000000u, 0x000200f9u, 0x000001f8u, 0x000200f8u, 0x000001f8u, 0x000700f5u, + 0x00000006u, 0x0000049au, 0x000001fau, 0x000001f7u, 0x000001fdu, 0x000001fbu, 0x000500c7u, 0x00000006u, + 0x00000201u, 0x0000014du, 0x000000cdu, 0x00050084u, 0x00000006u, 0x00000202u, 0x000000d4u, 0x00000201u, + 0x0004007cu, 0x0000000cu, 0x00000203u, 0x00000202u, 0x000600cbu, 0x00000006u, 0x00000204u, 0x0000049au, + 0x00000203u, 0x00000032u, 0x000600cbu, 0x00000006u, 0x000003beu, 0x00000499u, 0x00000032u, 0x00000033u, + 0x0004007cu, 0x0000000cu, 0x000003bfu, 0x000003beu, 0x000500c7u, 0x00000006u, 0x000003c1u, 0x00000499u, + 0x00000038u, 0x000500c7u, 0x00000006u, 0x000003c3u, 0x00000499u, 0x0000003cu, 0x000500c2u, 0x00000006u, + 0x000003c5u, 0x000003c3u, 0x00000040u, 0x000500c5u, 0x00000006u, 0x000003c8u, 0x000003c3u, 0x000003c5u, + 0x000400cdu, 0x0000000cu, 0x000003cau, 0x000003c1u, 0x000400cdu, 0x0000000cu, 0x000003ccu, 0x000003c8u, + 0x00050080u, 0x0000000cu, 0x000003cdu, 0x000003cau, 0x000003ccu, 0x00050084u, 0x0000000cu, 0x000003cfu, + 0x000003bfu, 0x0000004bu, 0x00050080u, 0x0000000cu, 0x000003d0u, 0x000003cdu, 0x000003cfu, 0x0004007cu, + 0x00000006u, 0x000003d1u, 0x000003d0u, 0x00050084u, 0x00000006u, 0x0000020du, 0x000003d1u, 0x0000020cu, + 0x00050082u, 0x00000006u, 0x0000020eu, 0x0000049du, 0x0000020du, 0x000500abu, 0x00000053u, 0x00000212u, + 0x0000049du, 0x0000002eu, 0x000300f7u, 0x00000214u, 0x00000000u, 0x000400fau, 0x00000212u, 0x00000213u, + 0x00000214u, 0x000200f8u, 0x00000213u, 0x00050080u, 0x00000006u, 0x00000217u, 0x0000049du, 0x00000215u, + 0x000200f9u, 0x00000214u, 0x000200f8u, 0x00000214u, 0x000700f5u, 0x00000006u, 0x000004a2u, 0x0000049du, + 0x000001f8u, 0x00000217u, 0x00000213u, 0x000300f7u, 0x0000021fu, 0x00000000u, 0x000400fau, 0x00000188u, + 0x0000021eu, 0x0000021fu, 0x000200f8u, 0x0000021eu, 0x000500c7u, 0x00000006u, 0x00000221u, 0x0000014au, + 0x000000deu, 0x000500aau, 0x00000053u, 0x00000222u, 0x00000221u, 0x000000deu, 0x000200f9u, 0x0000021fu, + 0x000200f8u, 0x0000021fu, 0x000700f5u, 0x00000053u, 0x00000223u, 0x00000188u, 0x00000214u, 0x00000222u, + 0x0000021eu, 0x0007015du, 0x00000006u, 0x00000226u, 0x000000d9u, 0x00000003u, 0x000004a2u, 0x000000d4u, + 0x00050080u, 0x00000006u, 0x00000229u, 0x00000226u, 0x000000fcu, 0x00050086u, 0x00000006u, 0x0000022au, + 0x00000229u, 0x00000112u, 0x000500abu, 0x00000053u, 0x0000022cu, 0x0000022au, 0x0000002eu, 0x000300f7u, + 0x0000022eu, 0x00000000u, 0x000400fau, 0x0000022cu, 0x0000022du, 0x0000022eu, 0x000200f8u, 0x0000022du, + 0x00050080u, 0x00000006u, 0x00000230u, 0x0000022au, 0x000000e6u, 0x000200f9u, 0x0000022eu, 0x000200f8u, + 0x0000022eu, 0x000700f5u, 0x00000006u, 0x000004a3u, 0x0000022au, 0x0000021fu, 0x00000230u, 0x0000022du, + 0x000500abu, 0x00000053u, 0x00000234u, 0x000004a3u, 0x0000002eu, 0x000500a7u, 0x00000053u, 0x00000235u, + 0x00000223u, 0x00000234u, 0x000300f7u, 0x00000237u, 0x00000000u, 0x000400fau, 0x00000235u, 0x00000236u, + 0x00000237u, 0x000200f8u, 0x00000236u, 0x00050041u, 0x000001d0u, 0x00000238u, 0x000000a1u, 0x00000052u, + 0x000700eau, 0x00000006u, 0x0000023au, 0x00000238u, 0x000000cdu, 0x0000002eu, 0x000004a3u, 0x000200f9u, + 0x00000237u, 0x000200f8u, 0x00000237u, 0x000700f5u, 0x00000006u, 0x000004a4u, 0x0000002eu, 0x0000022eu, + 0x0000023au, 0x00000236u, 0x000500c5u, 0x00000006u, 0x0000023du, 0x00000144u, 0x000000deu, 0x00060159u, + 0x00000006u, 0x0000023eu, 0x000000d9u, 0x000004a4u, 0x0000023du, 0x000300f7u, 0x00000241u, 0x00000000u, + 0x000400fau, 0x00000223u, 0x00000240u, 0x00000241u, 0x000200f8u, 0x00000240u, 0x00050041u, 0x0000018eu, + 0x00000243u, 0x0000017cu, 0x000000beu, 0x0004003du, 0x0000000cu, 0x00000244u, 0x00000243u, 0x00050041u, + 0x0000018eu, 0x00000247u, 0x0000017cu, 0x00000191u, 0x0004003du, 0x0000000cu, 0x00000248u, 0x00000247u, + 0x00050084u, 0x0000000cu, 0x00000249u, 0x00000167u, 0x00000248u, 0x00050080u, 0x0000000cu, 0x0000024au, + 0x00000244u, 0x00000249u, 0x00050080u, 0x0000000cu, 0x0000024du, 0x0000024au, 0x00000160u, 0x0004007cu, + 0x00000006u, 0x0000024eu, 0x0000024du, 0x000300f7u, 0x00000252u, 0x00000000u, 0x000400fau, 0x00000234u, + 0x00000251u, 0x00000252u, 0x000200f8u, 0x00000251u, 0x000500c4u, 0x00000006u, 0x0000025bu, 0x000004a3u, + 0x00000032u, 0x000500c5u, 0x00000006u, 0x0000025cu, 0x00000204u, 0x0000025bu, 0x00050041u, 0x0000025du, + 0x0000025eu, 0x0000017cu, 0x00000033u, 0x0004003du, 0x00000006u, 0x0000025fu, 0x0000025eu, 0x000500c4u, + 0x00000006u, 0x00000261u, 0x0000025fu, 0x00000260u, 0x000500c5u, 0x00000006u, 0x00000262u, 0x0000025cu, + 0x00000261u, 0x00060041u, 0x000001d0u, 0x00000263u, 0x00000256u, 0x00000052u, 0x0000023eu, 0x0003003eu, + 0x00000263u, 0x00000262u, 0x00050080u, 0x00000006u, 0x00000265u, 0x0000023eu, 0x000000cdu, 0x00050041u, + 0x0000025du, 0x00000267u, 0x0000017cu, 0x0000006du, 0x0004003du, 0x00000006u, 0x00000268u, 0x00000267u, + 0x000600cbu, 0x00000006u, 0x000003d6u, 0x00000268u, 0x0000006du, 0x000000beu, 0x0004007cu, 0x0000000cu, + 0x000003d7u, 0x000003d6u, 0x00050082u, 0x0000000cu, 0x000003dau, 0x000003d7u, 0x00000491u, 0x0007000cu, + 0x0000000cu, 0x000003dbu, 0x00000001u, 0x0000002au, 0x000003dau, 0x00000052u, 0x0004007cu, 0x00000006u, + 0x000003deu, 0x000003dbu, 0x000700c9u, 0x00000006u, 0x000003dfu, 0x00000268u, 0x000003deu, 0x0000006du, + 0x000000beu, 0x000500c4u, 0x00000006u, 0x0000026du, 0x0000024eu, 0x0000004bu, 0x000500c5u, 0x00000006u, + 0x0000026eu, 0x000003dfu, 0x0000026du, 0x00060041u, 0x000001d0u, 0x0000026fu, 0x00000256u, 0x00000052u, + 0x00000265u, 0x0003003eu, 0x0000026fu, 0x0000026eu, 0x000200f9u, 0x00000252u, 0x000200f8u, 0x00000252u, + 0x00070041u, 0x000001d0u, 0x0000027du, 0x00000274u, 0x00000052u, 0x0000024eu, 0x00000052u, 0x0003003eu, + 0x0000027du, 0x0000023eu, 0x00070041u, 0x000001d0u, 0x0000027fu, 0x00000274u, 0x00000052u, 0x0000024eu, + 0x00000040u, 0x0003003eu, 0x0000027fu, 0x000004a3u, 0x000200f9u, 0x00000241u, 0x000200f8u, 0x00000241u, + 0x000400cdu, 0x0000000cu, 0x00000282u, 0x00000204u, 0x0004007cu, 0x00000006u, 0x00000283u, 0x00000282u, + 0x000200f9u, 0x000003e5u, 0x000200f8u, 0x000003e5u, 0x000700f5u, 0x00000006u, 0x000004b1u, 0x0000020eu, + 0x00000241u, 0x000003f4u, 0x000003e9u, 0x000700f5u, 0x00000006u, 0x000004b0u, 0x000000cdu, 0x00000241u, + 0x000003f7u, 0x000003e9u, 0x000500b0u, 0x00000053u, 0x000003e8u, 0x000004b0u, 0x000000d4u, 0x000400f6u, + 0x000003f8u, 0x000003e9u, 0x00000000u, 0x000400fau, 0x000003e8u, 0x000003e9u, 0x000003f8u, 0x000200f8u, + 0x000003e9u, 0x0006015bu, 0x00000006u, 0x000003ecu, 0x000000d9u, 0x000004b1u, 0x000004b0u, 0x000500c7u, + 0x00000006u, 0x000003eeu, 0x00000144u, 0x000000deu, 0x000500aeu, 0x00000053u, 0x000003f0u, 0x000003eeu, + 0x000004b0u, 0x000600a9u, 0x00000006u, 0x000003f2u, 0x000003f0u, 0x000003ecu, 0x0000002eu, 0x00050080u, + 0x00000006u, 0x000003f4u, 0x000004b1u, 0x000003f2u, 0x00050084u, 0x00000006u, 0x000003f7u, 0x000004b0u, + 0x000000e6u, 0x000200f9u, 0x000003e5u, 0x000200f8u, 0x000003f8u, 0x000200f9u, 0x000003feu, 0x000200f8u, + 0x000003feu, 0x000700f5u, 0x00000006u, 0x000004b3u, 0x000003d1u, 0x000003f8u, 0x0000040du, 0x00000402u, + 0x000700f5u, 0x00000006u, 0x000004b2u, 0x000000cdu, 0x000003f8u, 0x00000410u, 0x00000402u, 0x000500b0u, + 0x00000053u, 0x00000401u, 0x000004b2u, 0x000000d4u, 0x000400f6u, 0x00000411u, 0x00000402u, 0x00000000u, + 0x000400fau, 0x00000401u, 0x00000402u, 0x00000411u, 0x000200f8u, 0x00000402u, 0x0006015bu, 0x00000006u, + 0x00000405u, 0x000000d9u, 0x000004b3u, 0x000004b2u, 0x000500c7u, 0x00000006u, 0x00000407u, 0x00000144u, + 0x000000deu, 0x000500aeu, 0x00000053u, 0x00000409u, 0x00000407u, 0x000004b2u, 0x000600a9u, 0x00000006u, + 0x0000040bu, 0x00000409u, 0x00000405u, 0x0000002eu, 0x00050080u, 0x00000006u, 0x0000040du, 0x000004b3u, + 0x0000040bu, 0x00050084u, 0x00000006u, 0x00000410u, 0x000004b2u, 0x000000e6u, 0x000200f9u, 0x000003feu, + 0x000200f8u, 0x00000411u, 0x00050082u, 0x00000006u, 0x0000028du, 0x000004b3u, 0x000003d1u, 0x00050082u, + 0x00000006u, 0x00000291u, 0x000004b1u, 0x0000020eu, 0x00050084u, 0x00000006u, 0x00000294u, 0x00000114u, + 0x0000023eu, 0x00050084u, 0x00000006u, 0x00000296u, 0x000000d9u, 0x00000283u, 0x00050080u, 0x00000006u, + 0x00000297u, 0x00000294u, 0x00000296u, 0x00050080u, 0x00000006u, 0x00000298u, 0x00000297u, 0x0000020cu, + 0x0007015du, 0x00000006u, 0x0000029cu, 0x000000d9u, 0x00000003u, 0x000003d1u, 0x000000d4u, 0x00050080u, + 0x00000006u, 0x0000029du, 0x00000298u, 0x0000029cu, 0x00050080u, 0x00000006u, 0x000002a0u, 0x00000298u, + 0x0000028du, 0x00060159u, 0x00000006u, 0x000002a5u, 0x000000d9u, 0x000004b1u, 0x0000023du, 0x00050080u, + 0x00000006u, 0x000002a7u, 0x000002a5u, 0x000002a6u, 0x00050086u, 0x00000006u, 0x000002a8u, 0x000002a7u, + 0x0000020cu, 0x000300f7u, 0x000002abu, 0x00000000u, 0x000400fau, 0x000001e9u, 0x000002aau, 0x000002abu, + 0x000200f8u, 0x000002aau, 0x00050084u, 0x0000000cu, 0x000002b0u, 0x0000016fu, 0x00000033u, 0x00050080u, + 0x0000000cu, 0x000002b3u, 0x000002b0u, 0x0000016cu, 0x000600cbu, 0x00000006u, 0x000002b4u, 0x00000204u, + 0x00000052u, 0x000002b3u, 0x000400cdu, 0x0000000cu, 0x000002b5u, 0x000002b4u, 0x0004007cu, 0x00000006u, + 0x000002b6u, 0x000002b5u, 0x000600cbu, 0x00000006u, 0x000002bau, 0x00000492u, 0x00000032u, 0x00000033u, + 0x000200f9u, 0x000002c4u, 0x000200f8u, 0x000002c4u, 0x000700f5u, 0x00000006u, 0x000004f8u, 0x000002a0u, + 0x000002aau, 0x00000523u, 0x000002c7u, 0x000700f5u, 0x00000006u, 0x000004f6u, 0x000004ccu, 0x000002aau, + 0x000002fdu, 0x000002c7u, 0x000700f5u, 0x00000006u, 0x000004e1u, 0x0000002eu, 0x000002aau, 0x00000516u, + 0x000002c7u, 0x000700f5u, 0x00000006u, 0x000004d2u, 0x0000002eu, 0x000002aau, 0x00000515u, 0x000002c7u, + 0x000700f5u, 0x00000006u, 0x000004d1u, 0x00000291u, 0x000002aau, 0x00000514u, 0x000002c7u, 0x000700f5u, + 0x0000000cu, 0x000004d0u, 0x00000052u, 0x000002aau, 0x000002ffu, 0x000002c7u, 0x000500b1u, 0x00000053u, + 0x000002cau, 0x000004d0u, 0x00000032u, 0x000400f6u, 0x000002c6u, 0x000002c7u, 0x00000000u, 0x000400fau, + 0x000002cau, 0x000002c5u, 0x000002c6u, 0x000200f8u, 0x000002c5u, 0x000600cbu, 0x00000006u, 0x000002ceu, + 0x00000499u, 0x000004d0u, 0x00000151u, 0x00050080u, 0x00000006u, 0x000002d0u, 0x000002ceu, 0x000003beu, + 0x000600cbu, 0x00000006u, 0x000002d5u, 0x00000492u, 0x000004d0u, 0x00000151u, 0x00050080u, 0x00000006u, + 0x000002d7u, 0x000002d5u, 0x000002bau, 0x000500abu, 0x00000053u, 0x000002d9u, 0x000002d7u, 0x0000002eu, + 0x000300f7u, 0x000002dbu, 0x00000000u, 0x000400fau, 0x000002d9u, 0x000002dau, 0x000002dbu, 0x000200f8u, + 0x000002dau, 0x00050080u, 0x00000006u, 0x000002ddu, 0x000002d7u, 0x00000040u, 0x000200f9u, 0x000002dbu, + 0x000200f8u, 0x000002dbu, 0x000700f5u, 0x00000006u, 0x00000502u, 0x000002d7u, 0x000002c5u, 0x000002ddu, + 0x000002dau, 0x00060041u, 0x000000a3u, 0x000002e0u, 0x000000a1u, 0x00000040u, 0x000004f6u, 0x0004003du, + 0x0000009du, 0x000002e1u, 0x000002e0u, 0x00040071u, 0x00000006u, 0x000002e2u, 0x000002e1u, 0x000500abu, + 0x00000053u, 0x000002e4u, 0x000002d0u, 0x0000002eu, 0x000300f7u, 0x000002e6u, 0x00000000u, 0x000400fau, + 0x000002e4u, 0x000002e5u, 0x000002e6u, 0x000200f8u, 0x000002e5u, 0x00050080u, 0x00000006u, 0x000002e9u, + 0x000004f6u, 0x000000cdu, 0x000200f9u, 0x00000417u, 0x000200f8u, 0x00000417u, 0x000700f5u, 0x00000006u, + 0x000004fcu, 0x000002d0u, 0x000002e5u, 0x00000426u, 0x00000417u, 0x000700f5u, 0x00000006u, 0x000004fbu, + 0x000004f8u, 0x000002e5u, 0x00000421u, 0x00000417u, 0x000700f5u, 0x00000006u, 0x000004fau, 0x0000002eu, + 0x000002e5u, 0x0000041fu, 0x00000417u, 0x000700f5u, 0x00000006u, 0x000004f9u, 0x000002e9u, 0x000002e5u, + 0x00000428u, 0x00000417u, 0x00060041u, 0x000000a3u, 0x0000041au, 0x000000a1u, 0x00000040u, 0x000004f9u, + 0x0004003du, 0x0000009du, 0x0000041bu, 0x0000041au, 0x00040071u, 0x00000006u, 0x0000041cu, 0x0000041bu, + 0x000500c5u, 0x00000006u, 0x0000041fu, 0x000004fau, 0x0000041cu, 0x00050080u, 0x00000006u, 0x00000421u, + 0x000004fbu, 0x00000040u, 0x00040071u, 0x0000009du, 0x00000423u, 0x0000041cu, 0x00060041u, 0x000000a3u, + 0x00000424u, 0x000000adu, 0x00000052u, 0x000004fbu, 0x0003003eu, 0x00000424u, 0x00000423u, 0x00050082u, + 0x00000006u, 0x00000426u, 0x000004fcu, 0x00000040u, 0x00050080u, 0x00000006u, 0x00000428u, 0x000004f9u, + 0x00000040u, 0x000500acu, 0x00000053u, 0x0000042bu, 0x00000426u, 0x0000002eu, 0x000400f6u, 0x0000042cu, + 0x00000417u, 0x00000000u, 0x000400fau, 0x0000042bu, 0x00000417u, 0x0000042cu, 0x000200f8u, 0x0000042cu, + 0x000200f9u, 0x00000431u, 0x000200f8u, 0x00000431u, 0x000700f5u, 0x00000006u, 0x0000050fu, 0x000004d2u, + 0x0000042cu, 0x00000537u, 0x00000467u, 0x000700f5u, 0x00000006u, 0x0000050cu, 0x000004e1u, 0x0000042cu, + 0x00000444u, 0x00000467u, 0x000700f5u, 0x00000006u, 0x00000500u, 0x000004d1u, 0x0000042cu, 0x00000466u, + 0x00000467u, 0x000700f5u, 0x00000006u, 0x000004ffu, 0x0000041fu, 0x0000042cu, 0x0000043bu, 0x00000467u, + 0x000500abu, 0x00000053u, 0x00000434u, 0x000004ffu, 0x0000002eu, 0x000400f6u, 0x00000468u, 0x00000467u, + 0x00000000u, 0x000400fau, 0x00000434u, 0x00000435u, 0x00000468u, 0x000200f8u, 0x00000435u, 0x0006000cu, + 0x0000000cu, 0x00000437u, 0x00000001u, 0x00000049u, 0x000004ffu, 0x00050082u, 0x00000006u, 0x00000439u, + 0x000004ffu, 0x000000cdu, 0x000500c7u, 0x00000006u, 0x0000043bu, 0x000004ffu, 0x00000439u, 0x000500c7u, + 0x00000006u, 0x0000043du, 0x00000500u, 0x000000fcu, 0x0004007cu, 0x0000000cu, 0x0000043eu, 0x0000043du, + 0x000600cbu, 0x00000006u, 0x00000442u, 0x000002e2u, 0x00000437u, 0x00000040u, 0x000700c9u, 0x00000006u, + 0x00000444u, 0x0000050cu, 0x00000442u, 0x0000043eu, 0x00000040u, 0x000700c9u, 0x00000006u, 0x00000447u, + 0x0000050fu, 0x000000cdu, 0x0000043eu, 0x00000040u, 0x000500aau, 0x00000053u, 0x00000449u, 0x0000043eu, + 0x00000109u, 0x000300f7u, 0x00000464u, 0x00000000u, 0x000400fau, 0x00000449u, 0x0000044au, 0x00000464u, + 0x000200f8u, 0x0000044au, 0x000500aau, 0x00000053u, 0x0000044cu, 0x00000447u, 0x0000010eu, 0x000300f7u, + 0x00000463u, 0x00000000u, 0x000400fau, 0x0000044cu, 0x0000044du, 0x00000453u, 0x000200f8u, 0x0000044du, + 0x00050086u, 0x00000006u, 0x00000450u, 0x00000500u, 0x00000112u, 0x00060041u, 0x0000011cu, 0x00000452u, + 0x00000117u, 0x0000014du, 0x00000450u, 0x0003003eu, 0x00000452u, 0x00000444u, 0x000200f9u, 0x00000463u, + 0x000200f8u, 0x00000453u, 0x00050086u, 0x00000006u, 0x00000456u, 0x00000500u, 0x00000112u, 0x00060041u, + 0x0000011cu, 0x00000457u, 0x00000117u, 0x0000014du, 0x00000456u, 0x000400c8u, 0x00000006u, 0x00000459u, + 0x00000447u, 0x000700f0u, 0x00000006u, 0x0000045au, 0x00000457u, 0x000000cdu, 0x0000002eu, 0x00000459u, + 0x000500c7u, 0x00000006u, 0x00000461u, 0x00000444u, 0x00000447u, 0x000700f1u, 0x00000006u, 0x00000462u, + 0x00000457u, 0x000000cdu, 0x0000002eu, 0x00000461u, 0x000200f9u, 0x00000463u, 0x000200f8u, 0x00000463u, + 0x000200f9u, 0x00000464u, 0x000200f8u, 0x00000464u, 0x000600a9u, 0x00000006u, 0x00000537u, 0x00000449u, + 0x0000002eu, 0x00000447u, 0x00050080u, 0x00000006u, 0x00000466u, 0x00000500u, 0x00000040u, 0x000200f9u, + 0x00000467u, 0x000200f8u, 0x00000467u, 0x000200f9u, 0x00000431u, 0x000200f8u, 0x00000468u, 0x000200f9u, + 0x000002e6u, 0x000200f8u, 0x000002e6u, 0x000700f5u, 0x00000006u, 0x00000523u, 0x000004f8u, 0x000002dbu, + 0x00000421u, 0x00000468u, 0x000700f5u, 0x00000006u, 0x00000516u, 0x000004e1u, 0x000002dbu, 0x0000050cu, + 0x00000468u, 0x000700f5u, 0x00000006u, 0x00000515u, 0x000004d2u, 0x000002dbu, 0x0000050fu, 0x00000468u, + 0x000700f5u, 0x00000006u, 0x00000514u, 0x000004d1u, 0x000002dbu, 0x00000500u, 0x00000468u, 0x00050080u, + 0x00000006u, 0x000002fdu, 0x000004f6u, 0x00000502u, 0x000200f9u, 0x000002c7u, 0x000200f8u, 0x000002c7u, + 0x00050080u, 0x0000000cu, 0x000002ffu, 0x000004d0u, 0x00000151u, 0x000200f9u, 0x000002c4u, 0x000200f8u, + 0x000002c6u, 0x000500abu, 0x00000053u, 0x0000046bu, 0x000004d2u, 0x0000002eu, 0x000300f7u, 0x0000047cu, + 0x00000000u, 0x000400fau, 0x0000046bu, 0x0000046cu, 0x0000047cu, 0x000200f8u, 0x0000046cu, 0x00050086u, + 0x00000006u, 0x0000046fu, 0x000004d1u, 0x00000112u, 0x00060041u, 0x0000011cu, 0x00000470u, 0x00000117u, + 0x0000014du, 0x0000046fu, 0x000400c8u, 0x00000006u, 0x00000472u, 0x000004d2u, 0x000700f0u, 0x00000006u, + 0x00000473u, 0x00000470u, 0x000000cdu, 0x0000002eu, 0x00000472u, 0x000500c7u, 0x00000006u, 0x0000047au, + 0x000004e1u, 0x000004d2u, 0x000700f1u, 0x00000006u, 0x0000047bu, 0x00000470u, 0x000000cdu, 0x0000002eu, + 0x0000047au, 0x000200f9u, 0x0000047cu, 0x000200f8u, 0x0000047cu, 0x00050084u, 0x00000006u, 0x0000030au, + 0x000000e6u, 0x0000023eu, 0x00050080u, 0x00000006u, 0x0000030cu, 0x0000030au, 0x000002b6u, 0x00050080u, + 0x00000006u, 0x0000030du, 0x0000030cu, 0x00000114u, 0x00040071u, 0x000001c7u, 0x0000030fu, 0x00000499u, + 0x00060041u, 0x000001d8u, 0x00000310u, 0x00000308u, 0x00000052u, 0x0000030du, 0x0003003eu, 0x00000310u, + 0x0000030fu, 0x00050084u, 0x00000006u, 0x00000314u, 0x000000e6u, 0x00000283u, 0x00050080u, 0x00000006u, + 0x00000315u, 0x00000294u, 0x00000314u, 0x00050080u, 0x00000006u, 0x00000317u, 0x00000315u, 0x000002b6u, + 0x00050080u, 0x00000006u, 0x00000318u, 0x00000317u, 0x0000020cu, 0x000500c2u, 0x00000006u, 0x0000031au, + 0x00000499u, 0x00000032u, 0x00040071u, 0x0000009du, 0x0000031bu, 0x0000031au, 0x00060041u, 0x000000a3u, + 0x0000031cu, 0x000000adu, 0x00000052u, 0x00000318u, 0x0003003eu, 0x0000031cu, 0x0000031bu, 0x000200f9u, + 0x000002abu, 0x000200f8u, 0x000002abu, 0x000400e0u, 0x000000d9u, 0x000000d9u, 0x0000031du, 0x000500c7u, + 0x00000006u, 0x00000320u, 0x0000014au, 0x000000deu, 0x000200f9u, 0x00000321u, 0x000200f8u, 0x00000321u, + 0x000700f5u, 0x00000006u, 0x000004f2u, 0x00000320u, 0x000002abu, 0x0000034eu, 0x00000322u, 0x00050086u, + 0x00000006u, 0x00000328u, 0x000002a8u, 0x00000114u, 0x000500b0u, 0x00000053u, 0x00000329u, 0x000004f2u, + 0x00000328u, 0x000400f6u, 0x00000323u, 0x00000322u, 0x00000000u, 0x000400fau, 0x00000329u, 0x00000322u, + 0x00000323u, 0x000200f8u, 0x00000322u, 0x00060041u, 0x0000011cu, 0x0000032du, 0x00000117u, 0x0000014du, + 0x000004f2u, 0x0004003du, 0x00000006u, 0x0000032eu, 0x0000032du, 0x00050084u, 0x00000006u, 0x00000332u, + 0x00000114u, 0x000004f2u, 0x00050080u, 0x00000006u, 0x00000333u, 0x0000029du, 0x00000332u, 0x00040071u, + 0x0000009du, 0x00000338u, 0x0000032eu, 0x00060041u, 0x000000a3u, 0x00000339u, 0x000000adu, 0x00000052u, + 0x00000333u, 0x0003003eu, 0x00000339u, 0x00000338u, 0x00050080u, 0x00000006u, 0x0000033bu, 0x00000333u, + 0x000000cdu, 0x000500c2u, 0x00000006u, 0x0000033du, 0x0000032eu, 0x0000004bu, 0x00040071u, 0x0000009du, + 0x0000033eu, 0x0000033du, 0x00060041u, 0x000000a3u, 0x0000033fu, 0x000000adu, 0x00000052u, 0x0000033bu, + 0x0003003eu, 0x0000033fu, 0x0000033eu, 0x00050080u, 0x00000006u, 0x00000341u, 0x00000333u, 0x000000e6u, + 0x000500c2u, 0x00000006u, 0x00000343u, 0x0000032eu, 0x00000032u, 0x00040071u, 0x0000009du, 0x00000344u, + 0x00000343u, 0x00060041u, 0x000000a3u, 0x00000345u, 0x000000adu, 0x00000052u, 0x00000341u, 0x0003003eu, + 0x00000345u, 0x00000344u, 0x00050080u, 0x00000006u, 0x00000347u, 0x00000333u, 0x000000d9u, 0x000500c2u, + 0x00000006u, 0x0000034au, 0x0000032eu, 0x00000349u, 0x00040071u, 0x0000009du, 0x0000034bu, 0x0000034au, + 0x00060041u, 0x000000a3u, 0x0000034cu, 0x000000adu, 0x00000052u, 0x00000347u, 0x0003003eu, 0x0000034cu, + 0x0000034bu, 0x00050080u, 0x00000006u, 0x0000034eu, 0x000004f2u, 0x000000d4u, 0x000200f9u, 0x00000321u, + 0x000200f8u, 0x00000323u, 0x000500c7u, 0x00000006u, 0x00000352u, 0x000002a8u, 0x00000351u, 0x00050080u, + 0x00000006u, 0x00000355u, 0x00000352u, 0x00000320u, 0x000200f9u, 0x00000356u, 0x000200f8u, 0x00000356u, + 0x000700f5u, 0x00000006u, 0x000004f3u, 0x00000355u, 0x00000323u, 0x00000371u, 0x00000357u, 0x000500b0u, + 0x00000053u, 0x0000035du, 0x000004f3u, 0x000002a8u, 0x000400f6u, 0x00000358u, 0x00000357u, 0x00000000u, + 0x000400fau, 0x0000035du, 0x00000357u, 0x00000358u, 0x000200f8u, 0x00000357u, 0x00050086u, 0x00000006u, + 0x00000361u, 0x000004f3u, 0x00000114u, 0x00060041u, 0x0000011cu, 0x00000362u, 0x00000117u, 0x0000014du, + 0x00000361u, 0x0004003du, 0x00000006u, 0x00000363u, 0x00000362u, 0x00050080u, 0x00000006u, 0x00000367u, + 0x0000029du, 0x000004f3u, 0x000500c7u, 0x00000006u, 0x0000036bu, 0x000004f3u, 0x000000d9u, 0x00050084u, + 0x00000006u, 0x0000036cu, 0x0000020cu, 0x0000036bu, 0x000500c2u, 0x00000006u, 0x0000036du, 0x00000363u, + 0x0000036cu, 0x00040071u, 0x0000009du, 0x0000036eu, 0x0000036du, 0x00060041u, 0x000000a3u, 0x0000036fu, + 0x000000adu, 0x00000052u, 0x00000367u, 0x0003003eu, 0x0000036fu, 0x0000036eu, 0x00050080u, 0x00000006u, + 0x00000371u, 0x000004f3u, 0x000000d4u, 0x000200f9u, 0x00000356u, 0x000200f8u, 0x00000358u, 0x000100fdu, + 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, 0x00000ec7u, 0x00000000u, 0x00020011u, 0x00000001u, + 0x00020011u, 0x00000038u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, + 0x0003000eu, 0x00000000u, 0x00000001u, 0x0007000fu, 0x00000005u, 0x00000004u, 0x6e69616du, 0x00000000u, + 0x00000142u, 0x00000412u, 0x00060010u, 0x00000004u, 0x00000011u, 0x00000040u, 0x00000001u, 0x00000001u, + 0x00030047u, 0x00000094u, 0x00000002u, 0x00050048u, 0x00000094u, 0x00000000u, 0x00000023u, 0x00000000u, + 0x00050048u, 0x00000094u, 0x00000001u, 0x00000023u, 0x00000008u, 0x00040047u, 0x00000142u, 0x0000000bu, + 0x0000001au, 0x00030047u, 0x0000015cu, 0x00000000u, 0x00040047u, 0x0000015cu, 0x00000021u, 0x00000000u, + 0x00040047u, 0x0000015cu, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000412u, 0x0000000bu, 0x0000001du, + 0x00040047u, 0x0000043eu, 0x00000001u, 0x00000000u, 0x00030047u, 0x00000447u, 0x00000000u, 0x00030047u, + 0x00000447u, 0x00000019u, 0x00040047u, 0x00000447u, 0x00000021u, 0x00000001u, 0x00040047u, 0x00000447u, + 0x00000022u, 0x00000000u, 0x00030047u, 0x00000448u, 0x00000000u, 0x00030047u, 0x00000456u, 0x00000000u, + 0x00040047u, 0x00000469u, 0x0000000bu, 0x00000019u, 0x00030047u, 0x000004b5u, 0x00000000u, 0x00030047u, + 0x000004bbu, 0x00000000u, 0x00030047u, 0x000004bdu, 0x00000000u, 0x00030047u, 0x000004c3u, 0x00000000u, + 0x00030047u, 0x000004c5u, 0x00000000u, 0x00030047u, 0x000004cbu, 0x00000000u, 0x00030047u, 0x000004cdu, + 0x00000000u, 0x00030047u, 0x000004d3u, 0x00000000u, 0x00030047u, 0x000004e9u, 0x00000000u, 0x00030047u, + 0x000004f1u, 0x00000000u, 0x00030047u, 0x000004f3u, 0x00000000u, 0x00030047u, 0x000004fbu, 0x00000000u, + 0x00030047u, 0x000004fdu, 0x00000000u, 0x00030047u, 0x00000505u, 0x00000000u, 0x00030047u, 0x00000507u, + 0x00000000u, 0x00030047u, 0x0000050fu, 0x00000000u, 0x00030047u, 0x0000051eu, 0x00000000u, 0x00030047u, + 0x00000526u, 0x00000000u, 0x00030047u, 0x00000528u, 0x00000000u, 0x00030047u, 0x00000530u, 0x00000000u, + 0x00030047u, 0x00000532u, 0x00000000u, 0x00030047u, 0x0000053au, 0x00000000u, 0x00030047u, 0x0000053cu, + 0x00000000u, 0x00030047u, 0x00000544u, 0x00000000u, 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, + 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, 0x00000000u, 0x00030016u, 0x00000008u, 0x00000020u, + 0x00040017u, 0x00000009u, 0x00000008u, 0x00000002u, 0x00040020u, 0x0000000fu, 0x00000007u, 0x00000009u, + 0x00020014u, 0x00000016u, 0x00040017u, 0x00000017u, 0x00000016u, 0x00000002u, 0x00040015u, 0x0000001eu, + 0x00000020u, 0x00000001u, 0x00040017u, 0x0000001fu, 0x0000001eu, 0x00000002u, 0x00040017u, 0x0000002cu, + 0x00000008u, 0x00000004u, 0x0004002bu, 0x00000006u, 0x00000040u, 0x00000029u, 0x0004001cu, 0x00000041u, + 0x00000006u, 0x00000040u, 0x0004002bu, 0x00000006u, 0x00000042u, 0x00000014u, 0x0004001cu, 0x00000043u, + 0x00000041u, 0x00000042u, 0x00040020u, 0x00000044u, 0x00000004u, 0x00000043u, 0x0004003bu, 0x00000044u, + 0x00000045u, 0x00000004u, 0x00040020u, 0x00000048u, 0x00000004u, 0x00000006u, 0x0004002bu, 0x00000006u, + 0x00000059u, 0x00000001u, 0x0004002bu, 0x0000001eu, 0x00000064u, 0x00000000u, 0x0004002bu, 0x0000001eu, + 0x00000065u, 0x00000001u, 0x0004002bu, 0x0000001eu, 0x00000069u, 0x00000002u, 0x0004002bu, 0x0000001eu, + 0x0000006cu, 0x00000003u, 0x0004002bu, 0x0000001eu, 0x00000072u, 0x00000005u, 0x0005002cu, 0x0000001fu, + 0x00000082u, 0x00000064u, 0x00000064u, 0x0005002cu, 0x0000001fu, 0x00000087u, 0x00000065u, 0x00000065u, + 0x0004001eu, 0x00000094u, 0x0000001fu, 0x00000009u, 0x00040020u, 0x00000095u, 0x00000009u, 0x00000094u, + 0x0004003bu, 0x00000095u, 0x00000096u, 0x00000009u, 0x00040020u, 0x00000097u, 0x00000009u, 0x0000001fu, + 0x00040020u, 0x000000a4u, 0x00000009u, 0x00000009u, 0x0004002bu, 0x00000006u, 0x000000feu, 0x00000002u, + 0x00040017u, 0x00000140u, 0x00000006u, 0x00000003u, 0x00040020u, 0x00000141u, 0x00000001u, 0x00000140u, + 0x0004003bu, 0x00000141u, 0x00000142u, 0x00000001u, 0x00040017u, 0x00000143u, 0x00000006u, 0x00000002u, + 0x0004002bu, 0x0000001eu, 0x00000147u, 0x00000010u, 0x0005002cu, 0x0000001fu, 0x00000148u, 0x00000147u, + 0x00000147u, 0x00090019u, 0x00000159u, 0x00000008u, 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, + 0x00000001u, 0x00000000u, 0x0003001bu, 0x0000015au, 0x00000159u, 0x00040020u, 0x0000015bu, 0x00000000u, + 0x0000015au, 0x0004003bu, 0x0000015bu, 0x0000015cu, 0x00000000u, 0x0004002bu, 0x00000008u, 0x00000164u, + 0x00000000u, 0x00040017u, 0x00000165u, 0x00000008u, 0x00000003u, 0x0003002au, 0x00000016u, 0x0000016du, + 0x0004002bu, 0x00000008u, 0x00000173u, 0x40000000u, 0x0004002bu, 0x00000008u, 0x00000180u, 0x3f800000u, + 0x0004002bu, 0x00000008u, 0x0000018du, 0x40400000u, 0x0004002bu, 0x00000006u, 0x0000019fu, 0x00000010u, + 0x0004002bu, 0x0000001eu, 0x000001acu, 0x00000014u, 0x0004002bu, 0x00000006u, 0x00000236u, 0x00000108u, + 0x0004002bu, 0x00000006u, 0x00000238u, 0x00000008u, 0x0004002bu, 0x00000006u, 0x0000023au, 0x00000004u, + 0x0004001cu, 0x00000264u, 0x00000009u, 0x0000019fu, 0x00040020u, 0x00000265u, 0x00000007u, 0x00000264u, + 0x0004002bu, 0x00000008u, 0x0000026au, 0x3f9d7658u, 0x0004002bu, 0x00000008u, 0x00000270u, 0x3f5019c3u, + 0x0004002bu, 0x0000001eu, 0x0000027cu, 0x0000000fu, 0x0004002bu, 0x00000008u, 0x0000027fu, 0x3ee31355u, + 0x0004002bu, 0x0000001eu, 0x00000297u, 0x0000000eu, 0x0004002bu, 0x00000008u, 0x0000029au, 0x3f620676u, + 0x0004002bu, 0x0000001eu, 0x000002acu, 0x00000004u, 0x0004002bu, 0x0000001eu, 0x000002b3u, 0x0000000du, + 0x0004002bu, 0x00000008u, 0x000002b6u, 0xbd5901aeu, 0x0004002bu, 0x0000001eu, 0x000002ceu, 0x0000000cu, + 0x0004002bu, 0x00000008u, 0x000002d1u, 0xbfcb0673u, 0x0004002bu, 0x0000001eu, 0x000002e9u, 0x00000006u, + 0x0004002bu, 0x00000006u, 0x00000355u, 0x0000000cu, 0x0004001cu, 0x00000356u, 0x00000009u, 0x00000355u, + 0x00040020u, 0x00000357u, 0x00000007u, 0x00000356u, 0x0004002bu, 0x0000001eu, 0x0000036cu, 0x0000000bu, + 0x0004002bu, 0x0000001eu, 0x00000386u, 0x0000000au, 0x0004002bu, 0x0000001eu, 0x000003a0u, 0x00000009u, + 0x0004002bu, 0x0000001eu, 0x000003bau, 0x00000008u, 0x00040020u, 0x00000411u, 0x00000001u, 0x00000006u, + 0x0004003bu, 0x00000411u, 0x00000412u, 0x00000001u, 0x0004002bu, 0x00000006u, 0x00000417u, 0x00000020u, + 0x0004002bu, 0x0000001eu, 0x00000434u, 0x00000020u, 0x00030031u, 0x00000016u, 0x0000043eu, 0x0004002bu, + 0x00000008u, 0x00000441u, 0x3f000000u, 0x00090019u, 0x00000445u, 0x00000008u, 0x00000001u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000002u, 0x00000000u, 0x00040020u, 0x00000446u, 0x00000000u, 0x00000445u, + 0x0004003bu, 0x00000446u, 0x00000447u, 0x00000000u, 0x0004002bu, 0x00000006u, 0x00000468u, 0x00000040u, + 0x0006002cu, 0x00000140u, 0x00000469u, 0x00000468u, 0x00000059u, 0x00000059u, 0x0005002cu, 0x0000001fu, + 0x00000ebfu, 0x00000069u, 0x00000069u, 0x0005002cu, 0x00000009u, 0x00000ec5u, 0x00000441u, 0x00000441u, + 0x0005002cu, 0x0000001fu, 0x00000ec6u, 0x00000434u, 0x00000434u, 0x00050036u, 0x00000002u, 0x00000004u, + 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, 0x00000265u, 0x00000cb4u, 0x00000007u, + 0x0004003bu, 0x00000357u, 0x00000bb3u, 0x00000007u, 0x0004003bu, 0x00000265u, 0x00000abbu, 0x00000007u, + 0x0004003du, 0x00000006u, 0x00000413u, 0x00000412u, 0x0004003du, 0x00000140u, 0x000004a8u, 0x00000142u, + 0x0007004fu, 0x00000143u, 0x000004a9u, 0x000004a8u, 0x000004a8u, 0x00000000u, 0x00000001u, 0x0004007cu, + 0x0000001fu, 0x000004aau, 0x000004a9u, 0x00050084u, 0x0000001fu, 0x000004abu, 0x000004aau, 0x00000148u, + 0x00050082u, 0x0000001fu, 0x000004adu, 0x000004abu, 0x00000ebfu, 0x000600cbu, 0x00000006u, 0x00000552u, + 0x00000413u, 0x00000064u, 0x00000065u, 0x000600cbu, 0x00000006u, 0x00000554u, 0x00000413u, 0x00000065u, + 0x00000069u, 0x000600cbu, 0x00000006u, 0x00000556u, 0x00000413u, 0x0000006cu, 0x00000069u, 0x000500c4u, + 0x00000006u, 0x00000557u, 0x00000556u, 0x00000065u, 0x000500c5u, 0x00000006u, 0x00000559u, 0x00000552u, + 0x00000557u, 0x000600cbu, 0x00000006u, 0x0000055bu, 0x00000413u, 0x00000072u, 0x00000065u, 0x000500c4u, + 0x00000006u, 0x0000055cu, 0x0000055bu, 0x00000069u, 0x000500c5u, 0x00000006u, 0x0000055eu, 0x00000554u, + 0x0000055cu, 0x0004007cu, 0x0000001eu, 0x00000560u, 0x0000055eu, 0x0004007cu, 0x0000001eu, 0x00000562u, + 0x00000559u, 0x00050050u, 0x0000001fu, 0x00000563u, 0x00000560u, 0x00000562u, 0x00050084u, 0x0000001fu, + 0x000004b1u, 0x00000ebfu, 0x00000563u, 0x00050080u, 0x0000001fu, 0x000004b4u, 0x000004adu, 0x000004b1u, + 0x0004003du, 0x0000015au, 0x000004b5u, 0x0000015cu, 0x000500b1u, 0x00000017u, 0x0000056fu, 0x000004b4u, + 0x00000082u, 0x00050051u, 0x00000016u, 0x00000590u, 0x0000056fu, 0x00000000u, 0x00050051u, 0x00000016u, + 0x00000595u, 0x0000056fu, 0x00000001u, 0x000600a9u, 0x0000001fu, 0x00000571u, 0x0000056fu, 0x00000087u, + 0x00000082u, 0x00050082u, 0x0000001fu, 0x00000573u, 0x000004b4u, 0x00000571u, 0x00050080u, 0x0000001fu, + 0x00000576u, 0x00000573u, 0x00000087u, 0x0004006fu, 0x00000009u, 0x00000585u, 0x00000576u, 0x00050041u, + 0x000000a4u, 0x00000586u, 0x00000096u, 0x00000065u, 0x0004003du, 0x00000009u, 0x00000587u, 0x00000586u, + 0x00050085u, 0x00000009u, 0x00000588u, 0x00000585u, 0x00000587u, 0x00050051u, 0x00000008u, 0x000004b8u, + 0x00000588u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000004b9u, 0x00000588u, 0x00000000u, 0x00060050u, + 0x00000165u, 0x000004bau, 0x000004b8u, 0x000004b9u, 0x00000164u, 0x00060060u, 0x0000002cu, 0x000004bbu, + 0x000004b5u, 0x000004bau, 0x00000064u, 0x0004003du, 0x0000015au, 0x000004bdu, 0x0000015cu, 0x00050050u, + 0x00000017u, 0x000005d8u, 0x0000016du, 0x00000595u, 0x000600a9u, 0x0000001fu, 0x000005b2u, 0x000005d8u, + 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, 0x000005b4u, 0x000004b4u, 0x000005b2u, 0x00050080u, + 0x0000001fu, 0x000005b7u, 0x000005b4u, 0x00000087u, 0x00050041u, 0x00000097u, 0x000005beu, 0x00000096u, + 0x00000064u, 0x0004003du, 0x0000001fu, 0x000005bfu, 0x000005beu, 0x000500afu, 0x00000017u, 0x000005c0u, + 0x000005b7u, 0x000005bfu, 0x00050051u, 0x00000016u, 0x000005deu, 0x000005c0u, 0x00000000u, 0x00050050u, + 0x00000017u, 0x000005e5u, 0x000005deu, 0x0000016du, 0x000600a9u, 0x0000001fu, 0x000005c2u, 0x000005e5u, + 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x000005c4u, 0x000005b7u, 0x000005c2u, 0x0004006fu, + 0x00000009u, 0x000005c6u, 0x000005c4u, 0x00050085u, 0x00000009u, 0x000005c9u, 0x000005c6u, 0x00000587u, + 0x00050051u, 0x00000008u, 0x000004c0u, 0x000005c9u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000004c1u, + 0x000005c9u, 0x00000000u, 0x00060050u, 0x00000165u, 0x000004c2u, 0x000004c0u, 0x000004c1u, 0x00000173u, + 0x00060060u, 0x0000002cu, 0x000004c3u, 0x000004bdu, 0x000004c2u, 0x00000064u, 0x0004003du, 0x0000015au, + 0x000004c5u, 0x0000015cu, 0x00050050u, 0x00000017u, 0x00000619u, 0x00000590u, 0x0000016du, 0x000600a9u, + 0x0000001fu, 0x000005f3u, 0x00000619u, 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, 0x000005f5u, + 0x000004b4u, 0x000005f3u, 0x00050080u, 0x0000001fu, 0x000005f8u, 0x000005f5u, 0x00000087u, 0x000500afu, + 0x00000017u, 0x00000601u, 0x000005f8u, 0x000005bfu, 0x00050051u, 0x00000016u, 0x00000624u, 0x00000601u, + 0x00000001u, 0x00050050u, 0x00000017u, 0x00000626u, 0x0000016du, 0x00000624u, 0x000600a9u, 0x0000001fu, + 0x00000603u, 0x00000626u, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x00000605u, 0x000005f8u, + 0x00000603u, 0x0004006fu, 0x00000009u, 0x00000607u, 0x00000605u, 0x00050085u, 0x00000009u, 0x0000060au, + 0x00000607u, 0x00000587u, 0x00050051u, 0x00000008u, 0x000004c8u, 0x0000060au, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000004c9u, 0x0000060au, 0x00000000u, 0x00060050u, 0x00000165u, 0x000004cau, 0x000004c8u, + 0x000004c9u, 0x00000180u, 0x00060060u, 0x0000002cu, 0x000004cbu, 0x000004c5u, 0x000004cau, 0x00000064u, + 0x0004003du, 0x0000015au, 0x000004cdu, 0x0000015cu, 0x00050080u, 0x0000001fu, 0x00000639u, 0x000004b4u, + 0x00000087u, 0x000500afu, 0x00000017u, 0x00000642u, 0x00000639u, 0x000005bfu, 0x000600a9u, 0x0000001fu, + 0x00000644u, 0x00000642u, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x00000646u, 0x00000639u, + 0x00000644u, 0x0004006fu, 0x00000009u, 0x00000648u, 0x00000646u, 0x00050085u, 0x00000009u, 0x0000064bu, + 0x00000648u, 0x00000587u, 0x00050051u, 0x00000008u, 0x000004d0u, 0x0000064bu, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000004d1u, 0x0000064bu, 0x00000000u, 0x00060050u, 0x00000165u, 0x000004d2u, 0x000004d0u, + 0x000004d1u, 0x0000018du, 0x00060060u, 0x0000002cu, 0x000004d3u, 0x000004cdu, 0x000004d2u, 0x00000064u, + 0x00050051u, 0x0000001eu, 0x00000682u, 0x000004b1u, 0x00000001u, 0x0004007cu, 0x00000006u, 0x00000684u, + 0x00000682u, 0x00050051u, 0x0000001eu, 0x00000686u, 0x000004b1u, 0x00000000u, 0x00050084u, 0x0000001eu, + 0x00000687u, 0x00000069u, 0x00000686u, 0x0004007cu, 0x00000006u, 0x00000689u, 0x00000687u, 0x00050051u, + 0x00000008u, 0x0000068bu, 0x000004bbu, 0x00000003u, 0x00050051u, 0x00000008u, 0x0000068du, 0x000004cbu, + 0x00000003u, 0x00050050u, 0x00000009u, 0x0000068eu, 0x0000068bu, 0x0000068du, 0x0006000cu, 0x00000006u, + 0x000006fdu, 0x00000001u, 0x0000003au, 0x0000068eu, 0x00060041u, 0x00000048u, 0x000006feu, 0x00000045u, + 0x00000684u, 0x00000689u, 0x0003003eu, 0x000006feu, 0x000006fdu, 0x00050080u, 0x0000001eu, 0x00000697u, + 0x00000687u, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000698u, 0x00000697u, 0x00050051u, 0x00000008u, + 0x0000069au, 0x000004c3u, 0x00000003u, 0x00050051u, 0x00000008u, 0x0000069cu, 0x000004d3u, 0x00000003u, + 0x00050050u, 0x00000009u, 0x0000069du, 0x0000069au, 0x0000069cu, 0x0006000cu, 0x00000006u, 0x00000703u, + 0x00000001u, 0x0000003au, 0x0000069du, 0x00060041u, 0x00000048u, 0x00000704u, 0x00000045u, 0x00000684u, + 0x00000698u, 0x0003003eu, 0x00000704u, 0x00000703u, 0x00050080u, 0x0000001eu, 0x000006a6u, 0x00000687u, + 0x00000069u, 0x0004007cu, 0x00000006u, 0x000006a7u, 0x000006a6u, 0x00050051u, 0x00000008u, 0x000006a9u, + 0x000004bbu, 0x00000000u, 0x00050051u, 0x00000008u, 0x000006abu, 0x000004cbu, 0x00000000u, 0x00050050u, + 0x00000009u, 0x000006acu, 0x000006a9u, 0x000006abu, 0x0006000cu, 0x00000006u, 0x00000709u, 0x00000001u, + 0x0000003au, 0x000006acu, 0x00060041u, 0x00000048u, 0x0000070au, 0x00000045u, 0x00000684u, 0x000006a7u, + 0x0003003eu, 0x0000070au, 0x00000709u, 0x00050080u, 0x0000001eu, 0x000006b5u, 0x00000687u, 0x0000006cu, + 0x0004007cu, 0x00000006u, 0x000006b6u, 0x000006b5u, 0x00050051u, 0x00000008u, 0x000006b8u, 0x000004c3u, + 0x00000000u, 0x00050051u, 0x00000008u, 0x000006bau, 0x000004d3u, 0x00000000u, 0x00050050u, 0x00000009u, + 0x000006bbu, 0x000006b8u, 0x000006bau, 0x0006000cu, 0x00000006u, 0x0000070fu, 0x00000001u, 0x0000003au, + 0x000006bbu, 0x00060041u, 0x00000048u, 0x00000710u, 0x00000045u, 0x00000684u, 0x000006b6u, 0x0003003eu, + 0x00000710u, 0x0000070fu, 0x00050080u, 0x0000001eu, 0x000006bfu, 0x00000682u, 0x00000065u, 0x0004007cu, + 0x00000006u, 0x000006c0u, 0x000006bfu, 0x00050051u, 0x00000008u, 0x000006c7u, 0x000004bbu, 0x00000002u, + 0x00050051u, 0x00000008u, 0x000006c9u, 0x000004cbu, 0x00000002u, 0x00050050u, 0x00000009u, 0x000006cau, + 0x000006c7u, 0x000006c9u, 0x0006000cu, 0x00000006u, 0x00000715u, 0x00000001u, 0x0000003au, 0x000006cau, + 0x00060041u, 0x00000048u, 0x00000716u, 0x00000045u, 0x000006c0u, 0x00000689u, 0x0003003eu, 0x00000716u, + 0x00000715u, 0x00050051u, 0x00000008u, 0x000006d6u, 0x000004c3u, 0x00000002u, 0x00050051u, 0x00000008u, + 0x000006d8u, 0x000004d3u, 0x00000002u, 0x00050050u, 0x00000009u, 0x000006d9u, 0x000006d6u, 0x000006d8u, + 0x0006000cu, 0x00000006u, 0x0000071bu, 0x00000001u, 0x0000003au, 0x000006d9u, 0x00060041u, 0x00000048u, + 0x0000071cu, 0x00000045u, 0x000006c0u, 0x00000698u, 0x0003003eu, 0x0000071cu, 0x0000071bu, 0x00050051u, + 0x00000008u, 0x000006e5u, 0x000004bbu, 0x00000001u, 0x00050051u, 0x00000008u, 0x000006e7u, 0x000004cbu, + 0x00000001u, 0x00050050u, 0x00000009u, 0x000006e8u, 0x000006e5u, 0x000006e7u, 0x0006000cu, 0x00000006u, + 0x00000721u, 0x00000001u, 0x0000003au, 0x000006e8u, 0x00060041u, 0x00000048u, 0x00000722u, 0x00000045u, + 0x000006c0u, 0x000006a7u, 0x0003003eu, 0x00000722u, 0x00000721u, 0x00050051u, 0x00000008u, 0x000006f4u, + 0x000004c3u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000006f6u, 0x000004d3u, 0x00000001u, 0x00050050u, + 0x00000009u, 0x000006f7u, 0x000006f4u, 0x000006f6u, 0x0006000cu, 0x00000006u, 0x00000727u, 0x00000001u, + 0x0000003au, 0x000006f7u, 0x00060041u, 0x00000048u, 0x00000728u, 0x00000045u, 0x000006c0u, 0x000006b6u, + 0x0003003eu, 0x00000728u, 0x00000727u, 0x00050089u, 0x00000006u, 0x000004dcu, 0x00000413u, 0x000000feu, + 0x00050084u, 0x00000006u, 0x000004ddu, 0x000000feu, 0x000004dcu, 0x00050080u, 0x00000006u, 0x000004deu, + 0x0000019fu, 0x000004ddu, 0x0004007cu, 0x0000001eu, 0x000004dfu, 0x000004deu, 0x00050086u, 0x00000006u, + 0x000004e1u, 0x00000413u, 0x000000feu, 0x00050084u, 0x00000006u, 0x000004e2u, 0x000000feu, 0x000004e1u, + 0x0004007cu, 0x0000001eu, 0x000004e3u, 0x000004e2u, 0x00050050u, 0x0000001fu, 0x000004e4u, 0x000004dfu, + 0x000004e3u, 0x000500b1u, 0x00000016u, 0x000004e7u, 0x000004e3u, 0x000001acu, 0x000300f7u, 0x00000517u, + 0x00000000u, 0x000400fau, 0x000004e7u, 0x000004e8u, 0x00000517u, 0x000200f8u, 0x000004e8u, 0x0004003du, + 0x0000015au, 0x000004e9u, 0x0000015cu, 0x00050080u, 0x0000001fu, 0x000004ecu, 0x000004adu, 0x000004e4u, + 0x000500b1u, 0x00000017u, 0x00000734u, 0x000004ecu, 0x00000082u, 0x00050051u, 0x00000016u, 0x00000755u, + 0x00000734u, 0x00000000u, 0x00050051u, 0x00000016u, 0x0000075au, 0x00000734u, 0x00000001u, 0x000600a9u, + 0x0000001fu, 0x00000736u, 0x00000734u, 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, 0x00000738u, + 0x000004ecu, 0x00000736u, 0x00050080u, 0x0000001fu, 0x0000073bu, 0x00000738u, 0x00000087u, 0x0004006fu, + 0x00000009u, 0x0000074au, 0x0000073bu, 0x00050085u, 0x00000009u, 0x0000074du, 0x0000074au, 0x00000587u, + 0x00050051u, 0x00000008u, 0x000004eeu, 0x0000074du, 0x00000001u, 0x00050051u, 0x00000008u, 0x000004efu, + 0x0000074du, 0x00000000u, 0x00060050u, 0x00000165u, 0x000004f0u, 0x000004eeu, 0x000004efu, 0x00000164u, + 0x00060060u, 0x0000002cu, 0x000004f1u, 0x000004e9u, 0x000004f0u, 0x00000064u, 0x0004003du, 0x0000015au, + 0x000004f3u, 0x0000015cu, 0x00050050u, 0x00000017u, 0x0000079du, 0x0000016du, 0x0000075au, 0x000600a9u, + 0x0000001fu, 0x00000777u, 0x0000079du, 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, 0x00000779u, + 0x000004ecu, 0x00000777u, 0x00050080u, 0x0000001fu, 0x0000077cu, 0x00000779u, 0x00000087u, 0x000500afu, + 0x00000017u, 0x00000785u, 0x0000077cu, 0x000005bfu, 0x00050051u, 0x00000016u, 0x000007a3u, 0x00000785u, + 0x00000000u, 0x00050050u, 0x00000017u, 0x000007aau, 0x000007a3u, 0x0000016du, 0x000600a9u, 0x0000001fu, + 0x00000787u, 0x000007aau, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x00000789u, 0x0000077cu, + 0x00000787u, 0x0004006fu, 0x00000009u, 0x0000078bu, 0x00000789u, 0x00050085u, 0x00000009u, 0x0000078eu, + 0x0000078bu, 0x00000587u, 0x00050051u, 0x00000008u, 0x000004f8u, 0x0000078eu, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000004f9u, 0x0000078eu, 0x00000000u, 0x00060050u, 0x00000165u, 0x000004fau, 0x000004f8u, + 0x000004f9u, 0x00000173u, 0x00060060u, 0x0000002cu, 0x000004fbu, 0x000004f3u, 0x000004fau, 0x00000064u, + 0x0004003du, 0x0000015au, 0x000004fdu, 0x0000015cu, 0x00050050u, 0x00000017u, 0x000007deu, 0x00000755u, + 0x0000016du, 0x000600a9u, 0x0000001fu, 0x000007b8u, 0x000007deu, 0x00000087u, 0x00000082u, 0x00050082u, + 0x0000001fu, 0x000007bau, 0x000004ecu, 0x000007b8u, 0x00050080u, 0x0000001fu, 0x000007bdu, 0x000007bau, + 0x00000087u, 0x000500afu, 0x00000017u, 0x000007c6u, 0x000007bdu, 0x000005bfu, 0x00050051u, 0x00000016u, + 0x000007e9u, 0x000007c6u, 0x00000001u, 0x00050050u, 0x00000017u, 0x000007ebu, 0x0000016du, 0x000007e9u, + 0x000600a9u, 0x0000001fu, 0x000007c8u, 0x000007ebu, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, + 0x000007cau, 0x000007bdu, 0x000007c8u, 0x0004006fu, 0x00000009u, 0x000007ccu, 0x000007cau, 0x00050085u, + 0x00000009u, 0x000007cfu, 0x000007ccu, 0x00000587u, 0x00050051u, 0x00000008u, 0x00000502u, 0x000007cfu, + 0x00000001u, 0x00050051u, 0x00000008u, 0x00000503u, 0x000007cfu, 0x00000000u, 0x00060050u, 0x00000165u, + 0x00000504u, 0x00000502u, 0x00000503u, 0x00000180u, 0x00060060u, 0x0000002cu, 0x00000505u, 0x000004fdu, + 0x00000504u, 0x00000064u, 0x0004003du, 0x0000015au, 0x00000507u, 0x0000015cu, 0x00050080u, 0x0000001fu, + 0x000007feu, 0x000004ecu, 0x00000087u, 0x000500afu, 0x00000017u, 0x00000807u, 0x000007feu, 0x000005bfu, + 0x000600a9u, 0x0000001fu, 0x00000809u, 0x00000807u, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, + 0x0000080bu, 0x000007feu, 0x00000809u, 0x0004006fu, 0x00000009u, 0x0000080du, 0x0000080bu, 0x00050085u, + 0x00000009u, 0x00000810u, 0x0000080du, 0x00000587u, 0x00050051u, 0x00000008u, 0x0000050cu, 0x00000810u, + 0x00000001u, 0x00050051u, 0x00000008u, 0x0000050du, 0x00000810u, 0x00000000u, 0x00060050u, 0x00000165u, + 0x0000050eu, 0x0000050cu, 0x0000050du, 0x0000018du, 0x00060060u, 0x0000002cu, 0x0000050fu, 0x00000507u, + 0x0000050eu, 0x00000064u, 0x00050084u, 0x0000001eu, 0x0000084cu, 0x00000069u, 0x000004dfu, 0x0004007cu, + 0x00000006u, 0x0000084eu, 0x0000084cu, 0x00050051u, 0x00000008u, 0x00000850u, 0x000004f1u, 0x00000003u, + 0x00050051u, 0x00000008u, 0x00000852u, 0x00000505u, 0x00000003u, 0x00050050u, 0x00000009u, 0x00000853u, + 0x00000850u, 0x00000852u, 0x0006000cu, 0x00000006u, 0x000008c2u, 0x00000001u, 0x0000003au, 0x00000853u, + 0x00060041u, 0x00000048u, 0x000008c3u, 0x00000045u, 0x000004e2u, 0x0000084eu, 0x0003003eu, 0x000008c3u, + 0x000008c2u, 0x00050080u, 0x0000001eu, 0x0000085cu, 0x0000084cu, 0x00000065u, 0x0004007cu, 0x00000006u, + 0x0000085du, 0x0000085cu, 0x00050051u, 0x00000008u, 0x0000085fu, 0x000004fbu, 0x00000003u, 0x00050051u, + 0x00000008u, 0x00000861u, 0x0000050fu, 0x00000003u, 0x00050050u, 0x00000009u, 0x00000862u, 0x0000085fu, + 0x00000861u, 0x0006000cu, 0x00000006u, 0x000008c8u, 0x00000001u, 0x0000003au, 0x00000862u, 0x00060041u, + 0x00000048u, 0x000008c9u, 0x00000045u, 0x000004e2u, 0x0000085du, 0x0003003eu, 0x000008c9u, 0x000008c8u, + 0x00050080u, 0x0000001eu, 0x0000086bu, 0x0000084cu, 0x00000069u, 0x0004007cu, 0x00000006u, 0x0000086cu, + 0x0000086bu, 0x00050051u, 0x00000008u, 0x0000086eu, 0x000004f1u, 0x00000000u, 0x00050051u, 0x00000008u, + 0x00000870u, 0x00000505u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000871u, 0x0000086eu, 0x00000870u, + 0x0006000cu, 0x00000006u, 0x000008ceu, 0x00000001u, 0x0000003au, 0x00000871u, 0x00060041u, 0x00000048u, + 0x000008cfu, 0x00000045u, 0x000004e2u, 0x0000086cu, 0x0003003eu, 0x000008cfu, 0x000008ceu, 0x00050080u, + 0x0000001eu, 0x0000087au, 0x0000084cu, 0x0000006cu, 0x0004007cu, 0x00000006u, 0x0000087bu, 0x0000087au, + 0x00050051u, 0x00000008u, 0x0000087du, 0x000004fbu, 0x00000000u, 0x00050051u, 0x00000008u, 0x0000087fu, + 0x0000050fu, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000880u, 0x0000087du, 0x0000087fu, 0x0006000cu, + 0x00000006u, 0x000008d4u, 0x00000001u, 0x0000003au, 0x00000880u, 0x00060041u, 0x00000048u, 0x000008d5u, + 0x00000045u, 0x000004e2u, 0x0000087bu, 0x0003003eu, 0x000008d5u, 0x000008d4u, 0x00050080u, 0x0000001eu, + 0x00000884u, 0x000004e3u, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000885u, 0x00000884u, 0x00050051u, + 0x00000008u, 0x0000088cu, 0x000004f1u, 0x00000002u, 0x00050051u, 0x00000008u, 0x0000088eu, 0x00000505u, + 0x00000002u, 0x00050050u, 0x00000009u, 0x0000088fu, 0x0000088cu, 0x0000088eu, 0x0006000cu, 0x00000006u, + 0x000008dau, 0x00000001u, 0x0000003au, 0x0000088fu, 0x00060041u, 0x00000048u, 0x000008dbu, 0x00000045u, + 0x00000885u, 0x0000084eu, 0x0003003eu, 0x000008dbu, 0x000008dau, 0x00050051u, 0x00000008u, 0x0000089bu, + 0x000004fbu, 0x00000002u, 0x00050051u, 0x00000008u, 0x0000089du, 0x0000050fu, 0x00000002u, 0x00050050u, + 0x00000009u, 0x0000089eu, 0x0000089bu, 0x0000089du, 0x0006000cu, 0x00000006u, 0x000008e0u, 0x00000001u, + 0x0000003au, 0x0000089eu, 0x00060041u, 0x00000048u, 0x000008e1u, 0x00000045u, 0x00000885u, 0x0000085du, + 0x0003003eu, 0x000008e1u, 0x000008e0u, 0x00050051u, 0x00000008u, 0x000008aau, 0x000004f1u, 0x00000001u, + 0x00050051u, 0x00000008u, 0x000008acu, 0x00000505u, 0x00000001u, 0x00050050u, 0x00000009u, 0x000008adu, + 0x000008aau, 0x000008acu, 0x0006000cu, 0x00000006u, 0x000008e6u, 0x00000001u, 0x0000003au, 0x000008adu, + 0x00060041u, 0x00000048u, 0x000008e7u, 0x00000045u, 0x00000885u, 0x0000086cu, 0x0003003eu, 0x000008e7u, + 0x000008e6u, 0x00050051u, 0x00000008u, 0x000008b9u, 0x000004fbu, 0x00000001u, 0x00050051u, 0x00000008u, + 0x000008bbu, 0x0000050fu, 0x00000001u, 0x00050050u, 0x00000009u, 0x000008bcu, 0x000008b9u, 0x000008bbu, + 0x0006000cu, 0x00000006u, 0x000008ecu, 0x00000001u, 0x0000003au, 0x000008bcu, 0x00060041u, 0x00000048u, + 0x000008edu, 0x00000045u, 0x00000885u, 0x0000087bu, 0x0003003eu, 0x000008edu, 0x000008ecu, 0x000200f9u, + 0x00000517u, 0x000200f8u, 0x00000517u, 0x0007004fu, 0x0000001fu, 0x00000519u, 0x000004e4u, 0x000004e4u, + 0x00000001u, 0x00000000u, 0x000500b1u, 0x00000016u, 0x0000051cu, 0x000004e3u, 0x00000147u, 0x000300f7u, + 0x0000054cu, 0x00000000u, 0x000400fau, 0x0000051cu, 0x0000051du, 0x0000054cu, 0x000200f8u, 0x0000051du, + 0x0004003du, 0x0000015au, 0x0000051eu, 0x0000015cu, 0x00050080u, 0x0000001fu, 0x00000521u, 0x000004adu, + 0x00000519u, 0x000500b1u, 0x00000017u, 0x000008f9u, 0x00000521u, 0x00000082u, 0x00050051u, 0x00000016u, + 0x0000091au, 0x000008f9u, 0x00000000u, 0x00050051u, 0x00000016u, 0x0000091fu, 0x000008f9u, 0x00000001u, + 0x000600a9u, 0x0000001fu, 0x000008fbu, 0x000008f9u, 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, + 0x000008fdu, 0x00000521u, 0x000008fbu, 0x00050080u, 0x0000001fu, 0x00000900u, 0x000008fdu, 0x00000087u, + 0x0004006fu, 0x00000009u, 0x0000090fu, 0x00000900u, 0x00050085u, 0x00000009u, 0x00000912u, 0x0000090fu, + 0x00000587u, 0x00050051u, 0x00000008u, 0x00000523u, 0x00000912u, 0x00000001u, 0x00050051u, 0x00000008u, + 0x00000524u, 0x00000912u, 0x00000000u, 0x00060050u, 0x00000165u, 0x00000525u, 0x00000523u, 0x00000524u, + 0x00000164u, 0x00060060u, 0x0000002cu, 0x00000526u, 0x0000051eu, 0x00000525u, 0x00000064u, 0x0004003du, + 0x0000015au, 0x00000528u, 0x0000015cu, 0x00050050u, 0x00000017u, 0x00000962u, 0x0000016du, 0x0000091fu, + 0x000600a9u, 0x0000001fu, 0x0000093cu, 0x00000962u, 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, + 0x0000093eu, 0x00000521u, 0x0000093cu, 0x00050080u, 0x0000001fu, 0x00000941u, 0x0000093eu, 0x00000087u, + 0x000500afu, 0x00000017u, 0x0000094au, 0x00000941u, 0x000005bfu, 0x00050051u, 0x00000016u, 0x00000968u, + 0x0000094au, 0x00000000u, 0x00050050u, 0x00000017u, 0x0000096fu, 0x00000968u, 0x0000016du, 0x000600a9u, + 0x0000001fu, 0x0000094cu, 0x0000096fu, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x0000094eu, + 0x00000941u, 0x0000094cu, 0x0004006fu, 0x00000009u, 0x00000950u, 0x0000094eu, 0x00050085u, 0x00000009u, + 0x00000953u, 0x00000950u, 0x00000587u, 0x00050051u, 0x00000008u, 0x0000052du, 0x00000953u, 0x00000001u, + 0x00050051u, 0x00000008u, 0x0000052eu, 0x00000953u, 0x00000000u, 0x00060050u, 0x00000165u, 0x0000052fu, + 0x0000052du, 0x0000052eu, 0x00000173u, 0x00060060u, 0x0000002cu, 0x00000530u, 0x00000528u, 0x0000052fu, + 0x00000064u, 0x0004003du, 0x0000015au, 0x00000532u, 0x0000015cu, 0x00050050u, 0x00000017u, 0x000009a3u, + 0x0000091au, 0x0000016du, 0x000600a9u, 0x0000001fu, 0x0000097du, 0x000009a3u, 0x00000087u, 0x00000082u, + 0x00050082u, 0x0000001fu, 0x0000097fu, 0x00000521u, 0x0000097du, 0x00050080u, 0x0000001fu, 0x00000982u, + 0x0000097fu, 0x00000087u, 0x000500afu, 0x00000017u, 0x0000098bu, 0x00000982u, 0x000005bfu, 0x00050051u, + 0x00000016u, 0x000009aeu, 0x0000098bu, 0x00000001u, 0x00050050u, 0x00000017u, 0x000009b0u, 0x0000016du, + 0x000009aeu, 0x000600a9u, 0x0000001fu, 0x0000098du, 0x000009b0u, 0x00000087u, 0x00000082u, 0x00050080u, + 0x0000001fu, 0x0000098fu, 0x00000982u, 0x0000098du, 0x0004006fu, 0x00000009u, 0x00000991u, 0x0000098fu, + 0x00050085u, 0x00000009u, 0x00000994u, 0x00000991u, 0x00000587u, 0x00050051u, 0x00000008u, 0x00000537u, + 0x00000994u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000538u, 0x00000994u, 0x00000000u, 0x00060050u, + 0x00000165u, 0x00000539u, 0x00000537u, 0x00000538u, 0x00000180u, 0x00060060u, 0x0000002cu, 0x0000053au, + 0x00000532u, 0x00000539u, 0x00000064u, 0x0004003du, 0x0000015au, 0x0000053cu, 0x0000015cu, 0x00050080u, + 0x0000001fu, 0x000009c3u, 0x00000521u, 0x00000087u, 0x000500afu, 0x00000017u, 0x000009ccu, 0x000009c3u, + 0x000005bfu, 0x000600a9u, 0x0000001fu, 0x000009ceu, 0x000009ccu, 0x00000087u, 0x00000082u, 0x00050080u, + 0x0000001fu, 0x000009d0u, 0x000009c3u, 0x000009ceu, 0x0004006fu, 0x00000009u, 0x000009d2u, 0x000009d0u, + 0x00050085u, 0x00000009u, 0x000009d5u, 0x000009d2u, 0x00000587u, 0x00050051u, 0x00000008u, 0x00000541u, + 0x000009d5u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000542u, 0x000009d5u, 0x00000000u, 0x00060050u, + 0x00000165u, 0x00000543u, 0x00000541u, 0x00000542u, 0x0000018du, 0x00060060u, 0x0000002cu, 0x00000544u, + 0x0000053cu, 0x00000543u, 0x00000064u, 0x00050084u, 0x0000001eu, 0x00000a11u, 0x00000069u, 0x000004e3u, + 0x0004007cu, 0x00000006u, 0x00000a13u, 0x00000a11u, 0x00050051u, 0x00000008u, 0x00000a15u, 0x00000526u, + 0x00000003u, 0x00050051u, 0x00000008u, 0x00000a17u, 0x0000053au, 0x00000003u, 0x00050050u, 0x00000009u, + 0x00000a18u, 0x00000a15u, 0x00000a17u, 0x0006000cu, 0x00000006u, 0x00000a87u, 0x00000001u, 0x0000003au, + 0x00000a18u, 0x00060041u, 0x00000048u, 0x00000a88u, 0x00000045u, 0x000004deu, 0x00000a13u, 0x0003003eu, + 0x00000a88u, 0x00000a87u, 0x00050080u, 0x0000001eu, 0x00000a21u, 0x00000a11u, 0x00000065u, 0x0004007cu, + 0x00000006u, 0x00000a22u, 0x00000a21u, 0x00050051u, 0x00000008u, 0x00000a24u, 0x00000530u, 0x00000003u, + 0x00050051u, 0x00000008u, 0x00000a26u, 0x00000544u, 0x00000003u, 0x00050050u, 0x00000009u, 0x00000a27u, + 0x00000a24u, 0x00000a26u, 0x0006000cu, 0x00000006u, 0x00000a8du, 0x00000001u, 0x0000003au, 0x00000a27u, + 0x00060041u, 0x00000048u, 0x00000a8eu, 0x00000045u, 0x000004deu, 0x00000a22u, 0x0003003eu, 0x00000a8eu, + 0x00000a8du, 0x00050080u, 0x0000001eu, 0x00000a30u, 0x00000a11u, 0x00000069u, 0x0004007cu, 0x00000006u, + 0x00000a31u, 0x00000a30u, 0x00050051u, 0x00000008u, 0x00000a33u, 0x00000526u, 0x00000000u, 0x00050051u, + 0x00000008u, 0x00000a35u, 0x0000053au, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000a36u, 0x00000a33u, + 0x00000a35u, 0x0006000cu, 0x00000006u, 0x00000a93u, 0x00000001u, 0x0000003au, 0x00000a36u, 0x00060041u, + 0x00000048u, 0x00000a94u, 0x00000045u, 0x000004deu, 0x00000a31u, 0x0003003eu, 0x00000a94u, 0x00000a93u, + 0x00050080u, 0x0000001eu, 0x00000a3fu, 0x00000a11u, 0x0000006cu, 0x0004007cu, 0x00000006u, 0x00000a40u, + 0x00000a3fu, 0x00050051u, 0x00000008u, 0x00000a42u, 0x00000530u, 0x00000000u, 0x00050051u, 0x00000008u, + 0x00000a44u, 0x00000544u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000a45u, 0x00000a42u, 0x00000a44u, + 0x0006000cu, 0x00000006u, 0x00000a99u, 0x00000001u, 0x0000003au, 0x00000a45u, 0x00060041u, 0x00000048u, + 0x00000a9au, 0x00000045u, 0x000004deu, 0x00000a40u, 0x0003003eu, 0x00000a9au, 0x00000a99u, 0x00050080u, + 0x0000001eu, 0x00000a49u, 0x000004dfu, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000a4au, 0x00000a49u, + 0x00050051u, 0x00000008u, 0x00000a51u, 0x00000526u, 0x00000002u, 0x00050051u, 0x00000008u, 0x00000a53u, + 0x0000053au, 0x00000002u, 0x00050050u, 0x00000009u, 0x00000a54u, 0x00000a51u, 0x00000a53u, 0x0006000cu, + 0x00000006u, 0x00000a9fu, 0x00000001u, 0x0000003au, 0x00000a54u, 0x00060041u, 0x00000048u, 0x00000aa0u, + 0x00000045u, 0x00000a4au, 0x00000a13u, 0x0003003eu, 0x00000aa0u, 0x00000a9fu, 0x00050051u, 0x00000008u, + 0x00000a60u, 0x00000530u, 0x00000002u, 0x00050051u, 0x00000008u, 0x00000a62u, 0x00000544u, 0x00000002u, + 0x00050050u, 0x00000009u, 0x00000a63u, 0x00000a60u, 0x00000a62u, 0x0006000cu, 0x00000006u, 0x00000aa5u, + 0x00000001u, 0x0000003au, 0x00000a63u, 0x00060041u, 0x00000048u, 0x00000aa6u, 0x00000045u, 0x00000a4au, + 0x00000a22u, 0x0003003eu, 0x00000aa6u, 0x00000aa5u, 0x00050051u, 0x00000008u, 0x00000a6fu, 0x00000526u, + 0x00000001u, 0x00050051u, 0x00000008u, 0x00000a71u, 0x0000053au, 0x00000001u, 0x00050050u, 0x00000009u, + 0x00000a72u, 0x00000a6fu, 0x00000a71u, 0x0006000cu, 0x00000006u, 0x00000aabu, 0x00000001u, 0x0000003au, + 0x00000a72u, 0x00060041u, 0x00000048u, 0x00000aacu, 0x00000045u, 0x00000a4au, 0x00000a31u, 0x0003003eu, + 0x00000aacu, 0x00000aabu, 0x00050051u, 0x00000008u, 0x00000a7eu, 0x00000530u, 0x00000001u, 0x00050051u, + 0x00000008u, 0x00000a80u, 0x00000544u, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000a81u, 0x00000a7eu, + 0x00000a80u, 0x0006000cu, 0x00000006u, 0x00000ab1u, 0x00000001u, 0x0000003au, 0x00000a81u, 0x00060041u, + 0x00000048u, 0x00000ab2u, 0x00000045u, 0x00000a4au, 0x00000a40u, 0x0003003eu, 0x00000ab2u, 0x00000ab1u, + 0x000200f9u, 0x0000054cu, 0x000200f8u, 0x0000054cu, 0x000400e0u, 0x000000feu, 0x000000feu, 0x00000236u, + 0x00050089u, 0x00000006u, 0x00000aceu, 0x00000413u, 0x0000023au, 0x00050084u, 0x00000006u, 0x00000acfu, + 0x00000238u, 0x00000aceu, 0x0004007cu, 0x0000001eu, 0x00000ad0u, 0x00000acfu, 0x00050086u, 0x00000006u, + 0x00000ad2u, 0x00000413u, 0x0000023au, 0x0004007cu, 0x0000001eu, 0x00000ad3u, 0x00000ad2u, 0x000200f9u, + 0x00000ad5u, 0x000200f8u, 0x00000ad5u, 0x000700f5u, 0x0000001eu, 0x00000ea7u, 0x00000064u, 0x0000054cu, + 0x00000afau, 0x00000ad9u, 0x000500b1u, 0x00000016u, 0x00000ad8u, 0x00000ea7u, 0x00000147u, 0x000400f6u, + 0x00000afbu, 0x00000ad9u, 0x00000000u, 0x000400fau, 0x00000ad8u, 0x00000ad9u, 0x00000afbu, 0x000200f8u, + 0x00000ad9u, 0x00050080u, 0x0000001eu, 0x00000ae0u, 0x00000ad0u, 0x00000ea7u, 0x0004007cu, 0x00000006u, + 0x00000ae2u, 0x00000ae0u, 0x00060041u, 0x00000048u, 0x00000b95u, 0x00000045u, 0x00000ad2u, 0x00000ae2u, + 0x0004003du, 0x00000006u, 0x00000b96u, 0x00000b95u, 0x0006000cu, 0x00000009u, 0x00000b97u, 0x00000001u, + 0x0000003eu, 0x00000b96u, 0x00050080u, 0x0000001eu, 0x00000aebu, 0x00000ae0u, 0x00000065u, 0x0004007cu, + 0x00000006u, 0x00000aecu, 0x00000aebu, 0x00060041u, 0x00000048u, 0x00000b9cu, 0x00000045u, 0x00000ad2u, + 0x00000aecu, 0x0004003du, 0x00000006u, 0x00000b9du, 0x00000b9cu, 0x0006000cu, 0x00000009u, 0x00000b9eu, + 0x00000001u, 0x0000003eu, 0x00000b9du, 0x0005008eu, 0x00000009u, 0x00000af1u, 0x00000b97u, 0x0000026au, + 0x00050041u, 0x0000000fu, 0x00000af2u, 0x00000abbu, 0x00000ea7u, 0x0003003eu, 0x00000af2u, 0x00000af1u, + 0x00050080u, 0x0000001eu, 0x00000af4u, 0x00000ea7u, 0x00000065u, 0x0005008eu, 0x00000009u, 0x00000af6u, + 0x00000b9eu, 0x00000270u, 0x00050041u, 0x0000000fu, 0x00000af7u, 0x00000abbu, 0x00000af4u, 0x0003003eu, + 0x00000af7u, 0x00000af6u, 0x00050080u, 0x0000001eu, 0x00000afau, 0x00000ea7u, 0x00000069u, 0x000200f9u, + 0x00000ad5u, 0x000200f8u, 0x00000afbu, 0x000200f9u, 0x00000afcu, 0x000200f8u, 0x00000afcu, 0x000700f5u, + 0x0000001eu, 0x00000ea8u, 0x00000069u, 0x00000afbu, 0x00000b12u, 0x00000b00u, 0x000500b1u, 0x00000016u, + 0x00000affu, 0x00000ea8u, 0x0000027cu, 0x000400f6u, 0x00000b13u, 0x00000b00u, 0x00000000u, 0x000400fau, + 0x00000affu, 0x00000b00u, 0x00000b13u, 0x000200f8u, 0x00000b00u, 0x00050082u, 0x0000001eu, 0x00000b03u, + 0x00000ea8u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b04u, 0x00000abbu, 0x00000b03u, 0x0004003du, + 0x00000009u, 0x00000b05u, 0x00000b04u, 0x00050080u, 0x0000001eu, 0x00000b07u, 0x00000ea8u, 0x00000065u, + 0x00050041u, 0x0000000fu, 0x00000b08u, 0x00000abbu, 0x00000b07u, 0x0004003du, 0x00000009u, 0x00000b09u, + 0x00000b08u, 0x00050081u, 0x00000009u, 0x00000b0au, 0x00000b05u, 0x00000b09u, 0x0005008eu, 0x00000009u, + 0x00000b0bu, 0x00000b0au, 0x0000027fu, 0x00050041u, 0x0000000fu, 0x00000b0cu, 0x00000abbu, 0x00000ea8u, + 0x0004003du, 0x00000009u, 0x00000b0du, 0x00000b0cu, 0x00050083u, 0x00000009u, 0x00000b0eu, 0x00000b0du, + 0x00000b0bu, 0x0003003eu, 0x00000b0cu, 0x00000b0eu, 0x00050080u, 0x0000001eu, 0x00000b12u, 0x00000ea8u, + 0x00000069u, 0x000200f9u, 0x00000afcu, 0x000200f8u, 0x00000b13u, 0x000200f9u, 0x00000b14u, 0x000200f8u, + 0x00000b14u, 0x000700f5u, 0x0000001eu, 0x00000ea9u, 0x0000006cu, 0x00000b13u, 0x00000b2au, 0x00000b18u, + 0x000500b1u, 0x00000016u, 0x00000b17u, 0x00000ea9u, 0x00000297u, 0x000400f6u, 0x00000b2bu, 0x00000b18u, + 0x00000000u, 0x000400fau, 0x00000b17u, 0x00000b18u, 0x00000b2bu, 0x000200f8u, 0x00000b18u, 0x00050082u, + 0x0000001eu, 0x00000b1bu, 0x00000ea9u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b1cu, 0x00000abbu, + 0x00000b1bu, 0x0004003du, 0x00000009u, 0x00000b1du, 0x00000b1cu, 0x00050080u, 0x0000001eu, 0x00000b1fu, + 0x00000ea9u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b20u, 0x00000abbu, 0x00000b1fu, 0x0004003du, + 0x00000009u, 0x00000b21u, 0x00000b20u, 0x00050081u, 0x00000009u, 0x00000b22u, 0x00000b1du, 0x00000b21u, + 0x0005008eu, 0x00000009u, 0x00000b23u, 0x00000b22u, 0x0000029au, 0x00050041u, 0x0000000fu, 0x00000b24u, + 0x00000abbu, 0x00000ea9u, 0x0004003du, 0x00000009u, 0x00000b25u, 0x00000b24u, 0x00050083u, 0x00000009u, + 0x00000b26u, 0x00000b25u, 0x00000b23u, 0x0003003eu, 0x00000b24u, 0x00000b26u, 0x00050080u, 0x0000001eu, + 0x00000b2au, 0x00000ea9u, 0x00000069u, 0x000200f9u, 0x00000b14u, 0x000200f8u, 0x00000b2bu, 0x000200f9u, + 0x00000b2cu, 0x000200f8u, 0x00000b2cu, 0x000700f5u, 0x0000001eu, 0x00000eaau, 0x000002acu, 0x00000b2bu, + 0x00000b42u, 0x00000b30u, 0x000500b1u, 0x00000016u, 0x00000b2fu, 0x00000eaau, 0x000002b3u, 0x000400f6u, + 0x00000b43u, 0x00000b30u, 0x00000000u, 0x000400fau, 0x00000b2fu, 0x00000b30u, 0x00000b43u, 0x000200f8u, + 0x00000b30u, 0x00050082u, 0x0000001eu, 0x00000b33u, 0x00000eaau, 0x00000065u, 0x00050041u, 0x0000000fu, + 0x00000b34u, 0x00000abbu, 0x00000b33u, 0x0004003du, 0x00000009u, 0x00000b35u, 0x00000b34u, 0x00050080u, + 0x0000001eu, 0x00000b37u, 0x00000eaau, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b38u, 0x00000abbu, + 0x00000b37u, 0x0004003du, 0x00000009u, 0x00000b39u, 0x00000b38u, 0x00050081u, 0x00000009u, 0x00000b3au, + 0x00000b35u, 0x00000b39u, 0x0005008eu, 0x00000009u, 0x00000b3bu, 0x00000b3au, 0x000002b6u, 0x00050041u, + 0x0000000fu, 0x00000b3cu, 0x00000abbu, 0x00000eaau, 0x0004003du, 0x00000009u, 0x00000b3du, 0x00000b3cu, + 0x00050083u, 0x00000009u, 0x00000b3eu, 0x00000b3du, 0x00000b3bu, 0x0003003eu, 0x00000b3cu, 0x00000b3eu, + 0x00050080u, 0x0000001eu, 0x00000b42u, 0x00000eaau, 0x00000069u, 0x000200f9u, 0x00000b2cu, 0x000200f8u, + 0x00000b43u, 0x000200f9u, 0x00000b44u, 0x000200f8u, 0x00000b44u, 0x000700f5u, 0x0000001eu, 0x00000eabu, + 0x00000072u, 0x00000b43u, 0x00000b5au, 0x00000b48u, 0x000500b1u, 0x00000016u, 0x00000b47u, 0x00000eabu, + 0x000002ceu, 0x000400f6u, 0x00000b5bu, 0x00000b48u, 0x00000000u, 0x000400fau, 0x00000b47u, 0x00000b48u, + 0x00000b5bu, 0x000200f8u, 0x00000b48u, 0x00050082u, 0x0000001eu, 0x00000b4bu, 0x00000eabu, 0x00000065u, + 0x00050041u, 0x0000000fu, 0x00000b4cu, 0x00000abbu, 0x00000b4bu, 0x0004003du, 0x00000009u, 0x00000b4du, + 0x00000b4cu, 0x00050080u, 0x0000001eu, 0x00000b4fu, 0x00000eabu, 0x00000065u, 0x00050041u, 0x0000000fu, + 0x00000b50u, 0x00000abbu, 0x00000b4fu, 0x0004003du, 0x00000009u, 0x00000b51u, 0x00000b50u, 0x00050081u, + 0x00000009u, 0x00000b52u, 0x00000b4du, 0x00000b51u, 0x0005008eu, 0x00000009u, 0x00000b53u, 0x00000b52u, + 0x000002d1u, 0x00050041u, 0x0000000fu, 0x00000b54u, 0x00000abbu, 0x00000eabu, 0x0004003du, 0x00000009u, + 0x00000b55u, 0x00000b54u, 0x00050083u, 0x00000009u, 0x00000b56u, 0x00000b55u, 0x00000b53u, 0x0003003eu, + 0x00000b54u, 0x00000b56u, 0x00050080u, 0x0000001eu, 0x00000b5au, 0x00000eabu, 0x00000069u, 0x000200f9u, + 0x00000b44u, 0x000200f8u, 0x00000b5bu, 0x000400e0u, 0x000000feu, 0x000000feu, 0x00000236u, 0x000200f9u, + 0x00000b5cu, 0x000200f8u, 0x00000b5cu, 0x000700f5u, 0x0000001eu, 0x00000eacu, 0x00000069u, 0x00000b5bu, + 0x00000b8fu, 0x00000b60u, 0x000500b1u, 0x00000016u, 0x00000b5fu, 0x00000eacu, 0x000002e9u, 0x000400f6u, + 0x00000b90u, 0x00000b60u, 0x00000000u, 0x000400fau, 0x00000b5fu, 0x00000b60u, 0x00000b90u, 0x000200f8u, + 0x00000b60u, 0x00050084u, 0x0000001eu, 0x00000b62u, 0x00000069u, 0x00000eacu, 0x00050041u, 0x0000000fu, + 0x00000b64u, 0x00000abbu, 0x00000b62u, 0x0004003du, 0x00000009u, 0x00000b65u, 0x00000b64u, 0x00050080u, + 0x0000001eu, 0x00000b68u, 0x00000b62u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b69u, 0x00000abbu, + 0x00000b68u, 0x0004003du, 0x00000009u, 0x00000b6au, 0x00000b69u, 0x00050051u, 0x00000008u, 0x00000b6cu, + 0x00000b65u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000b6eu, 0x00000b6au, 0x00000000u, 0x00050050u, + 0x00000009u, 0x00000b6fu, 0x00000b6cu, 0x00000b6eu, 0x00050051u, 0x00000008u, 0x00000b71u, 0x00000b65u, + 0x00000001u, 0x00050051u, 0x00000008u, 0x00000b73u, 0x00000b6au, 0x00000001u, 0x00050050u, 0x00000009u, + 0x00000b74u, 0x00000b71u, 0x00000b73u, 0x000500c3u, 0x0000001eu, 0x00000b77u, 0x00000ad0u, 0x00000065u, + 0x00050082u, 0x0000001eu, 0x00000b79u, 0x00000eacu, 0x00000069u, 0x00050080u, 0x0000001eu, 0x00000b7au, + 0x00000b77u, 0x00000b79u, 0x0004007cu, 0x00000006u, 0x00000b7cu, 0x00000b7au, 0x00050084u, 0x0000001eu, + 0x00000b7fu, 0x00000069u, 0x00000ad3u, 0x0004007cu, 0x00000006u, 0x00000b81u, 0x00000b7fu, 0x0006000cu, + 0x00000006u, 0x00000ba3u, 0x00000001u, 0x0000003au, 0x00000b6fu, 0x00060041u, 0x00000048u, 0x00000ba4u, + 0x00000045u, 0x00000b7cu, 0x00000b81u, 0x0003003eu, 0x00000ba4u, 0x00000ba3u, 0x00050080u, 0x0000001eu, + 0x00000b89u, 0x00000b7fu, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000b8au, 0x00000b89u, 0x0006000cu, + 0x00000006u, 0x00000ba9u, 0x00000001u, 0x0000003au, 0x00000b74u, 0x00060041u, 0x00000048u, 0x00000baau, + 0x00000045u, 0x00000b7cu, 0x00000b8au, 0x0003003eu, 0x00000baau, 0x00000ba9u, 0x00050080u, 0x0000001eu, + 0x00000b8fu, 0x00000eacu, 0x00000065u, 0x000200f9u, 0x00000b5cu, 0x000200f8u, 0x00000b90u, 0x000500b0u, + 0x00000016u, 0x00000418u, 0x00000413u, 0x00000417u, 0x00050089u, 0x00000006u, 0x00000bc6u, 0x00000413u, + 0x00000238u, 0x00050084u, 0x00000006u, 0x00000bc7u, 0x0000023au, 0x00000bc6u, 0x0004007cu, 0x0000001eu, + 0x00000bc8u, 0x00000bc7u, 0x00050086u, 0x00000006u, 0x00000bcau, 0x00000413u, 0x00000238u, 0x00050080u, + 0x00000006u, 0x00000bcdu, 0x00000bcau, 0x0000019fu, 0x0004007cu, 0x0000001eu, 0x00000bceu, 0x00000bcdu, + 0x000300f7u, 0x00000c59u, 0x00000000u, 0x000400fau, 0x00000418u, 0x00000bd1u, 0x00000c59u, 0x000200f8u, + 0x00000bd1u, 0x000200f9u, 0x00000bd2u, 0x000200f8u, 0x00000bd2u, 0x000700f5u, 0x0000001eu, 0x00000eadu, + 0x00000064u, 0x00000bd1u, 0x00000bf7u, 0x00000bd6u, 0x000500b1u, 0x00000016u, 0x00000bd5u, 0x00000eadu, + 0x000002ceu, 0x000400f6u, 0x00000bf8u, 0x00000bd6u, 0x00000000u, 0x000400fau, 0x00000bd5u, 0x00000bd6u, + 0x00000bf8u, 0x000200f8u, 0x00000bd6u, 0x00050080u, 0x0000001eu, 0x00000bddu, 0x00000bc8u, 0x00000eadu, + 0x0004007cu, 0x00000006u, 0x00000bdfu, 0x00000bddu, 0x00060041u, 0x00000048u, 0x00000c96u, 0x00000045u, + 0x00000bcdu, 0x00000bdfu, 0x0004003du, 0x00000006u, 0x00000c97u, 0x00000c96u, 0x0006000cu, 0x00000009u, + 0x00000c98u, 0x00000001u, 0x0000003eu, 0x00000c97u, 0x00050080u, 0x0000001eu, 0x00000be8u, 0x00000bddu, + 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000be9u, 0x00000be8u, 0x00060041u, 0x00000048u, 0x00000c9du, + 0x00000045u, 0x00000bcdu, 0x00000be9u, 0x0004003du, 0x00000006u, 0x00000c9eu, 0x00000c9du, 0x0006000cu, + 0x00000009u, 0x00000c9fu, 0x00000001u, 0x0000003eu, 0x00000c9eu, 0x0005008eu, 0x00000009u, 0x00000beeu, + 0x00000c98u, 0x0000026au, 0x00050041u, 0x0000000fu, 0x00000befu, 0x00000bb3u, 0x00000eadu, 0x0003003eu, + 0x00000befu, 0x00000beeu, 0x00050080u, 0x0000001eu, 0x00000bf1u, 0x00000eadu, 0x00000065u, 0x0005008eu, + 0x00000009u, 0x00000bf3u, 0x00000c9fu, 0x00000270u, 0x00050041u, 0x0000000fu, 0x00000bf4u, 0x00000bb3u, + 0x00000bf1u, 0x0003003eu, 0x00000bf4u, 0x00000bf3u, 0x00050080u, 0x0000001eu, 0x00000bf7u, 0x00000eadu, + 0x00000069u, 0x000200f9u, 0x00000bd2u, 0x000200f8u, 0x00000bf8u, 0x000200f9u, 0x00000bf9u, 0x000200f8u, + 0x00000bf9u, 0x000700f5u, 0x0000001eu, 0x00000eaeu, 0x00000069u, 0x00000bf8u, 0x00000c0fu, 0x00000bfdu, + 0x000500b1u, 0x00000016u, 0x00000bfcu, 0x00000eaeu, 0x0000036cu, 0x000400f6u, 0x00000c10u, 0x00000bfdu, + 0x00000000u, 0x000400fau, 0x00000bfcu, 0x00000bfdu, 0x00000c10u, 0x000200f8u, 0x00000bfdu, 0x00050082u, + 0x0000001eu, 0x00000c00u, 0x00000eaeu, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c01u, 0x00000bb3u, + 0x00000c00u, 0x0004003du, 0x00000009u, 0x00000c02u, 0x00000c01u, 0x00050080u, 0x0000001eu, 0x00000c04u, + 0x00000eaeu, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c05u, 0x00000bb3u, 0x00000c04u, 0x0004003du, + 0x00000009u, 0x00000c06u, 0x00000c05u, 0x00050081u, 0x00000009u, 0x00000c07u, 0x00000c02u, 0x00000c06u, + 0x0005008eu, 0x00000009u, 0x00000c08u, 0x00000c07u, 0x0000027fu, 0x00050041u, 0x0000000fu, 0x00000c09u, + 0x00000bb3u, 0x00000eaeu, 0x0004003du, 0x00000009u, 0x00000c0au, 0x00000c09u, 0x00050083u, 0x00000009u, + 0x00000c0bu, 0x00000c0au, 0x00000c08u, 0x0003003eu, 0x00000c09u, 0x00000c0bu, 0x00050080u, 0x0000001eu, + 0x00000c0fu, 0x00000eaeu, 0x00000069u, 0x000200f9u, 0x00000bf9u, 0x000200f8u, 0x00000c10u, 0x000200f9u, + 0x00000c11u, 0x000200f8u, 0x00000c11u, 0x000700f5u, 0x0000001eu, 0x00000eafu, 0x0000006cu, 0x00000c10u, + 0x00000c27u, 0x00000c15u, 0x000500b1u, 0x00000016u, 0x00000c14u, 0x00000eafu, 0x00000386u, 0x000400f6u, + 0x00000c28u, 0x00000c15u, 0x00000000u, 0x000400fau, 0x00000c14u, 0x00000c15u, 0x00000c28u, 0x000200f8u, + 0x00000c15u, 0x00050082u, 0x0000001eu, 0x00000c18u, 0x00000eafu, 0x00000065u, 0x00050041u, 0x0000000fu, + 0x00000c19u, 0x00000bb3u, 0x00000c18u, 0x0004003du, 0x00000009u, 0x00000c1au, 0x00000c19u, 0x00050080u, + 0x0000001eu, 0x00000c1cu, 0x00000eafu, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c1du, 0x00000bb3u, + 0x00000c1cu, 0x0004003du, 0x00000009u, 0x00000c1eu, 0x00000c1du, 0x00050081u, 0x00000009u, 0x00000c1fu, + 0x00000c1au, 0x00000c1eu, 0x0005008eu, 0x00000009u, 0x00000c20u, 0x00000c1fu, 0x0000029au, 0x00050041u, + 0x0000000fu, 0x00000c21u, 0x00000bb3u, 0x00000eafu, 0x0004003du, 0x00000009u, 0x00000c22u, 0x00000c21u, + 0x00050083u, 0x00000009u, 0x00000c23u, 0x00000c22u, 0x00000c20u, 0x0003003eu, 0x00000c21u, 0x00000c23u, + 0x00050080u, 0x0000001eu, 0x00000c27u, 0x00000eafu, 0x00000069u, 0x000200f9u, 0x00000c11u, 0x000200f8u, + 0x00000c28u, 0x000200f9u, 0x00000c29u, 0x000200f8u, 0x00000c29u, 0x000700f5u, 0x0000001eu, 0x00000eb0u, + 0x000002acu, 0x00000c28u, 0x00000c3fu, 0x00000c2du, 0x000500b1u, 0x00000016u, 0x00000c2cu, 0x00000eb0u, + 0x000003a0u, 0x000400f6u, 0x00000c40u, 0x00000c2du, 0x00000000u, 0x000400fau, 0x00000c2cu, 0x00000c2du, + 0x00000c40u, 0x000200f8u, 0x00000c2du, 0x00050082u, 0x0000001eu, 0x00000c30u, 0x00000eb0u, 0x00000065u, + 0x00050041u, 0x0000000fu, 0x00000c31u, 0x00000bb3u, 0x00000c30u, 0x0004003du, 0x00000009u, 0x00000c32u, + 0x00000c31u, 0x00050080u, 0x0000001eu, 0x00000c34u, 0x00000eb0u, 0x00000065u, 0x00050041u, 0x0000000fu, + 0x00000c35u, 0x00000bb3u, 0x00000c34u, 0x0004003du, 0x00000009u, 0x00000c36u, 0x00000c35u, 0x00050081u, + 0x00000009u, 0x00000c37u, 0x00000c32u, 0x00000c36u, 0x0005008eu, 0x00000009u, 0x00000c38u, 0x00000c37u, + 0x000002b6u, 0x00050041u, 0x0000000fu, 0x00000c39u, 0x00000bb3u, 0x00000eb0u, 0x0004003du, 0x00000009u, + 0x00000c3au, 0x00000c39u, 0x00050083u, 0x00000009u, 0x00000c3bu, 0x00000c3au, 0x00000c38u, 0x0003003eu, + 0x00000c39u, 0x00000c3bu, 0x00050080u, 0x0000001eu, 0x00000c3fu, 0x00000eb0u, 0x00000069u, 0x000200f9u, + 0x00000c29u, 0x000200f8u, 0x00000c40u, 0x000200f9u, 0x00000c41u, 0x000200f8u, 0x00000c41u, 0x000700f5u, + 0x0000001eu, 0x00000eb1u, 0x00000072u, 0x00000c40u, 0x00000c57u, 0x00000c45u, 0x000500b1u, 0x00000016u, + 0x00000c44u, 0x00000eb1u, 0x000003bau, 0x000400f6u, 0x00000c58u, 0x00000c45u, 0x00000000u, 0x000400fau, + 0x00000c44u, 0x00000c45u, 0x00000c58u, 0x000200f8u, 0x00000c45u, 0x00050082u, 0x0000001eu, 0x00000c48u, + 0x00000eb1u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c49u, 0x00000bb3u, 0x00000c48u, 0x0004003du, + 0x00000009u, 0x00000c4au, 0x00000c49u, 0x00050080u, 0x0000001eu, 0x00000c4cu, 0x00000eb1u, 0x00000065u, + 0x00050041u, 0x0000000fu, 0x00000c4du, 0x00000bb3u, 0x00000c4cu, 0x0004003du, 0x00000009u, 0x00000c4eu, + 0x00000c4du, 0x00050081u, 0x00000009u, 0x00000c4fu, 0x00000c4au, 0x00000c4eu, 0x0005008eu, 0x00000009u, + 0x00000c50u, 0x00000c4fu, 0x000002d1u, 0x00050041u, 0x0000000fu, 0x00000c51u, 0x00000bb3u, 0x00000eb1u, + 0x0004003du, 0x00000009u, 0x00000c52u, 0x00000c51u, 0x00050083u, 0x00000009u, 0x00000c53u, 0x00000c52u, + 0x00000c50u, 0x0003003eu, 0x00000c51u, 0x00000c53u, 0x00050080u, 0x0000001eu, 0x00000c57u, 0x00000eb1u, + 0x00000069u, 0x000200f9u, 0x00000c41u, 0x000200f8u, 0x00000c58u, 0x000200f9u, 0x00000c59u, 0x000200f8u, + 0x00000c59u, 0x000400e0u, 0x000000feu, 0x000000feu, 0x00000236u, 0x000300f7u, 0x00000c91u, 0x00000000u, + 0x000400fau, 0x00000418u, 0x00000c5bu, 0x00000c91u, 0x000200f8u, 0x00000c5bu, 0x000200f9u, 0x00000c5cu, + 0x000200f8u, 0x00000c5cu, 0x000700f5u, 0x0000001eu, 0x00000eb2u, 0x00000069u, 0x00000c5bu, 0x00000c8fu, + 0x00000c60u, 0x000500b1u, 0x00000016u, 0x00000c5fu, 0x00000eb2u, 0x000002acu, 0x000400f6u, 0x00000c90u, + 0x00000c60u, 0x00000000u, 0x000400fau, 0x00000c5fu, 0x00000c60u, 0x00000c90u, 0x000200f8u, 0x00000c60u, + 0x00050084u, 0x0000001eu, 0x00000c62u, 0x00000069u, 0x00000eb2u, 0x00050041u, 0x0000000fu, 0x00000c64u, + 0x00000bb3u, 0x00000c62u, 0x0004003du, 0x00000009u, 0x00000c65u, 0x00000c64u, 0x00050080u, 0x0000001eu, + 0x00000c68u, 0x00000c62u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c69u, 0x00000bb3u, 0x00000c68u, + 0x0004003du, 0x00000009u, 0x00000c6au, 0x00000c69u, 0x00050051u, 0x00000008u, 0x00000c6cu, 0x00000c65u, + 0x00000000u, 0x00050051u, 0x00000008u, 0x00000c6eu, 0x00000c6au, 0x00000000u, 0x00050050u, 0x00000009u, + 0x00000c6fu, 0x00000c6cu, 0x00000c6eu, 0x00050051u, 0x00000008u, 0x00000c71u, 0x00000c65u, 0x00000001u, + 0x00050051u, 0x00000008u, 0x00000c73u, 0x00000c6au, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000c74u, + 0x00000c71u, 0x00000c73u, 0x000500c3u, 0x0000001eu, 0x00000c77u, 0x00000bc8u, 0x00000065u, 0x00050082u, + 0x0000001eu, 0x00000c79u, 0x00000eb2u, 0x00000069u, 0x00050080u, 0x0000001eu, 0x00000c7au, 0x00000c77u, + 0x00000c79u, 0x0004007cu, 0x00000006u, 0x00000c7cu, 0x00000c7au, 0x00050084u, 0x0000001eu, 0x00000c7fu, + 0x00000069u, 0x00000bceu, 0x0004007cu, 0x00000006u, 0x00000c81u, 0x00000c7fu, 0x0006000cu, 0x00000006u, + 0x00000ca4u, 0x00000001u, 0x0000003au, 0x00000c6fu, 0x00060041u, 0x00000048u, 0x00000ca5u, 0x00000045u, + 0x00000c7cu, 0x00000c81u, 0x0003003eu, 0x00000ca5u, 0x00000ca4u, 0x00050080u, 0x0000001eu, 0x00000c89u, + 0x00000c7fu, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000c8au, 0x00000c89u, 0x0006000cu, 0x00000006u, + 0x00000caau, 0x00000001u, 0x0000003au, 0x00000c74u, 0x00060041u, 0x00000048u, 0x00000cabu, 0x00000045u, + 0x00000c7cu, 0x00000c8au, 0x0003003eu, 0x00000cabu, 0x00000caau, 0x00050080u, 0x0000001eu, 0x00000c8fu, + 0x00000eb2u, 0x00000065u, 0x000200f9u, 0x00000c5cu, 0x000200f8u, 0x00000c90u, 0x000200f9u, 0x00000c91u, + 0x000200f8u, 0x00000c91u, 0x000400e0u, 0x000000feu, 0x000000feu, 0x00000236u, 0x000200f9u, 0x00000cceu, + 0x000200f8u, 0x00000cceu, 0x000700f5u, 0x0000001eu, 0x00000eb3u, 0x00000064u, 0x00000c91u, 0x00000cf3u, + 0x00000cd2u, 0x000500b1u, 0x00000016u, 0x00000cd1u, 0x00000eb3u, 0x00000147u, 0x000400f6u, 0x00000cf4u, + 0x00000cd2u, 0x00000000u, 0x000400fau, 0x00000cd1u, 0x00000cd2u, 0x00000cf4u, 0x000200f8u, 0x00000cd2u, + 0x00050080u, 0x0000001eu, 0x00000cd9u, 0x00000ad0u, 0x00000eb3u, 0x0004007cu, 0x00000006u, 0x00000cdbu, + 0x00000cd9u, 0x00060041u, 0x00000048u, 0x00000d8eu, 0x00000045u, 0x00000ad2u, 0x00000cdbu, 0x0004003du, + 0x00000006u, 0x00000d8fu, 0x00000d8eu, 0x0006000cu, 0x00000009u, 0x00000d90u, 0x00000001u, 0x0000003eu, + 0x00000d8fu, 0x00050080u, 0x0000001eu, 0x00000ce4u, 0x00000cd9u, 0x00000065u, 0x0004007cu, 0x00000006u, + 0x00000ce5u, 0x00000ce4u, 0x00060041u, 0x00000048u, 0x00000d95u, 0x00000045u, 0x00000ad2u, 0x00000ce5u, + 0x0004003du, 0x00000006u, 0x00000d96u, 0x00000d95u, 0x0006000cu, 0x00000009u, 0x00000d97u, 0x00000001u, + 0x0000003eu, 0x00000d96u, 0x0005008eu, 0x00000009u, 0x00000ceau, 0x00000d90u, 0x0000026au, 0x00050041u, + 0x0000000fu, 0x00000cebu, 0x00000cb4u, 0x00000eb3u, 0x0003003eu, 0x00000cebu, 0x00000ceau, 0x00050080u, + 0x0000001eu, 0x00000cedu, 0x00000eb3u, 0x00000065u, 0x0005008eu, 0x00000009u, 0x00000cefu, 0x00000d97u, + 0x00000270u, 0x00050041u, 0x0000000fu, 0x00000cf0u, 0x00000cb4u, 0x00000cedu, 0x0003003eu, 0x00000cf0u, + 0x00000cefu, 0x00050080u, 0x0000001eu, 0x00000cf3u, 0x00000eb3u, 0x00000069u, 0x000200f9u, 0x00000cceu, + 0x000200f8u, 0x00000cf4u, 0x000200f9u, 0x00000cf5u, 0x000200f8u, 0x00000cf5u, 0x000700f5u, 0x0000001eu, + 0x00000eb4u, 0x00000069u, 0x00000cf4u, 0x00000d0bu, 0x00000cf9u, 0x000500b1u, 0x00000016u, 0x00000cf8u, + 0x00000eb4u, 0x0000027cu, 0x000400f6u, 0x00000d0cu, 0x00000cf9u, 0x00000000u, 0x000400fau, 0x00000cf8u, + 0x00000cf9u, 0x00000d0cu, 0x000200f8u, 0x00000cf9u, 0x00050082u, 0x0000001eu, 0x00000cfcu, 0x00000eb4u, + 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000cfdu, 0x00000cb4u, 0x00000cfcu, 0x0004003du, 0x00000009u, + 0x00000cfeu, 0x00000cfdu, 0x00050080u, 0x0000001eu, 0x00000d00u, 0x00000eb4u, 0x00000065u, 0x00050041u, + 0x0000000fu, 0x00000d01u, 0x00000cb4u, 0x00000d00u, 0x0004003du, 0x00000009u, 0x00000d02u, 0x00000d01u, + 0x00050081u, 0x00000009u, 0x00000d03u, 0x00000cfeu, 0x00000d02u, 0x0005008eu, 0x00000009u, 0x00000d04u, + 0x00000d03u, 0x0000027fu, 0x00050041u, 0x0000000fu, 0x00000d05u, 0x00000cb4u, 0x00000eb4u, 0x0004003du, + 0x00000009u, 0x00000d06u, 0x00000d05u, 0x00050083u, 0x00000009u, 0x00000d07u, 0x00000d06u, 0x00000d04u, + 0x0003003eu, 0x00000d05u, 0x00000d07u, 0x00050080u, 0x0000001eu, 0x00000d0bu, 0x00000eb4u, 0x00000069u, + 0x000200f9u, 0x00000cf5u, 0x000200f8u, 0x00000d0cu, 0x000200f9u, 0x00000d0du, 0x000200f8u, 0x00000d0du, + 0x000700f5u, 0x0000001eu, 0x00000eb5u, 0x0000006cu, 0x00000d0cu, 0x00000d23u, 0x00000d11u, 0x000500b1u, + 0x00000016u, 0x00000d10u, 0x00000eb5u, 0x00000297u, 0x000400f6u, 0x00000d24u, 0x00000d11u, 0x00000000u, + 0x000400fau, 0x00000d10u, 0x00000d11u, 0x00000d24u, 0x000200f8u, 0x00000d11u, 0x00050082u, 0x0000001eu, + 0x00000d14u, 0x00000eb5u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d15u, 0x00000cb4u, 0x00000d14u, + 0x0004003du, 0x00000009u, 0x00000d16u, 0x00000d15u, 0x00050080u, 0x0000001eu, 0x00000d18u, 0x00000eb5u, + 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d19u, 0x00000cb4u, 0x00000d18u, 0x0004003du, 0x00000009u, + 0x00000d1au, 0x00000d19u, 0x00050081u, 0x00000009u, 0x00000d1bu, 0x00000d16u, 0x00000d1au, 0x0005008eu, + 0x00000009u, 0x00000d1cu, 0x00000d1bu, 0x0000029au, 0x00050041u, 0x0000000fu, 0x00000d1du, 0x00000cb4u, + 0x00000eb5u, 0x0004003du, 0x00000009u, 0x00000d1eu, 0x00000d1du, 0x00050083u, 0x00000009u, 0x00000d1fu, + 0x00000d1eu, 0x00000d1cu, 0x0003003eu, 0x00000d1du, 0x00000d1fu, 0x00050080u, 0x0000001eu, 0x00000d23u, + 0x00000eb5u, 0x00000069u, 0x000200f9u, 0x00000d0du, 0x000200f8u, 0x00000d24u, 0x000200f9u, 0x00000d25u, + 0x000200f8u, 0x00000d25u, 0x000700f5u, 0x0000001eu, 0x00000eb6u, 0x000002acu, 0x00000d24u, 0x00000d3bu, + 0x00000d29u, 0x000500b1u, 0x00000016u, 0x00000d28u, 0x00000eb6u, 0x000002b3u, 0x000400f6u, 0x00000d3cu, + 0x00000d29u, 0x00000000u, 0x000400fau, 0x00000d28u, 0x00000d29u, 0x00000d3cu, 0x000200f8u, 0x00000d29u, + 0x00050082u, 0x0000001eu, 0x00000d2cu, 0x00000eb6u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d2du, + 0x00000cb4u, 0x00000d2cu, 0x0004003du, 0x00000009u, 0x00000d2eu, 0x00000d2du, 0x00050080u, 0x0000001eu, + 0x00000d30u, 0x00000eb6u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d31u, 0x00000cb4u, 0x00000d30u, + 0x0004003du, 0x00000009u, 0x00000d32u, 0x00000d31u, 0x00050081u, 0x00000009u, 0x00000d33u, 0x00000d2eu, + 0x00000d32u, 0x0005008eu, 0x00000009u, 0x00000d34u, 0x00000d33u, 0x000002b6u, 0x00050041u, 0x0000000fu, + 0x00000d35u, 0x00000cb4u, 0x00000eb6u, 0x0004003du, 0x00000009u, 0x00000d36u, 0x00000d35u, 0x00050083u, + 0x00000009u, 0x00000d37u, 0x00000d36u, 0x00000d34u, 0x0003003eu, 0x00000d35u, 0x00000d37u, 0x00050080u, + 0x0000001eu, 0x00000d3bu, 0x00000eb6u, 0x00000069u, 0x000200f9u, 0x00000d25u, 0x000200f8u, 0x00000d3cu, + 0x000200f9u, 0x00000d3du, 0x000200f8u, 0x00000d3du, 0x000700f5u, 0x0000001eu, 0x00000eb7u, 0x00000072u, + 0x00000d3cu, 0x00000d53u, 0x00000d41u, 0x000500b1u, 0x00000016u, 0x00000d40u, 0x00000eb7u, 0x000002ceu, + 0x000400f6u, 0x00000d54u, 0x00000d41u, 0x00000000u, 0x000400fau, 0x00000d40u, 0x00000d41u, 0x00000d54u, + 0x000200f8u, 0x00000d41u, 0x00050082u, 0x0000001eu, 0x00000d44u, 0x00000eb7u, 0x00000065u, 0x00050041u, + 0x0000000fu, 0x00000d45u, 0x00000cb4u, 0x00000d44u, 0x0004003du, 0x00000009u, 0x00000d46u, 0x00000d45u, + 0x00050080u, 0x0000001eu, 0x00000d48u, 0x00000eb7u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d49u, + 0x00000cb4u, 0x00000d48u, 0x0004003du, 0x00000009u, 0x00000d4au, 0x00000d49u, 0x00050081u, 0x00000009u, + 0x00000d4bu, 0x00000d46u, 0x00000d4au, 0x0005008eu, 0x00000009u, 0x00000d4cu, 0x00000d4bu, 0x000002d1u, + 0x00050041u, 0x0000000fu, 0x00000d4du, 0x00000cb4u, 0x00000eb7u, 0x0004003du, 0x00000009u, 0x00000d4eu, + 0x00000d4du, 0x00050083u, 0x00000009u, 0x00000d4fu, 0x00000d4eu, 0x00000d4cu, 0x0003003eu, 0x00000d4du, + 0x00000d4fu, 0x00050080u, 0x0000001eu, 0x00000d53u, 0x00000eb7u, 0x00000069u, 0x000200f9u, 0x00000d3du, + 0x000200f8u, 0x00000d54u, 0x000400e0u, 0x000000feu, 0x000000feu, 0x00000236u, 0x000200f9u, 0x00000d55u, + 0x000200f8u, 0x00000d55u, 0x000700f5u, 0x0000001eu, 0x00000eb8u, 0x00000069u, 0x00000d54u, 0x00000d88u, + 0x00000d59u, 0x000500b1u, 0x00000016u, 0x00000d58u, 0x00000eb8u, 0x000002e9u, 0x000400f6u, 0x00000d89u, + 0x00000d59u, 0x00000000u, 0x000400fau, 0x00000d58u, 0x00000d59u, 0x00000d89u, 0x000200f8u, 0x00000d59u, + 0x00050084u, 0x0000001eu, 0x00000d5bu, 0x00000069u, 0x00000eb8u, 0x00050041u, 0x0000000fu, 0x00000d5du, + 0x00000cb4u, 0x00000d5bu, 0x0004003du, 0x00000009u, 0x00000d5eu, 0x00000d5du, 0x00050080u, 0x0000001eu, + 0x00000d61u, 0x00000d5bu, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d62u, 0x00000cb4u, 0x00000d61u, + 0x0004003du, 0x00000009u, 0x00000d63u, 0x00000d62u, 0x00050051u, 0x00000008u, 0x00000d65u, 0x00000d5eu, + 0x00000000u, 0x00050051u, 0x00000008u, 0x00000d67u, 0x00000d63u, 0x00000000u, 0x00050050u, 0x00000009u, + 0x00000d68u, 0x00000d65u, 0x00000d67u, 0x00050051u, 0x00000008u, 0x00000d6au, 0x00000d5eu, 0x00000001u, + 0x00050051u, 0x00000008u, 0x00000d6cu, 0x00000d63u, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000d6du, + 0x00000d6au, 0x00000d6cu, 0x000500c3u, 0x0000001eu, 0x00000d70u, 0x00000ad0u, 0x00000065u, 0x00050082u, + 0x0000001eu, 0x00000d72u, 0x00000eb8u, 0x00000069u, 0x00050080u, 0x0000001eu, 0x00000d73u, 0x00000d70u, + 0x00000d72u, 0x0004007cu, 0x00000006u, 0x00000d75u, 0x00000d73u, 0x00050084u, 0x0000001eu, 0x00000d78u, + 0x00000069u, 0x00000ad3u, 0x0004007cu, 0x00000006u, 0x00000d7au, 0x00000d78u, 0x0006000cu, 0x00000006u, + 0x00000d9cu, 0x00000001u, 0x0000003au, 0x00000d68u, 0x00060041u, 0x00000048u, 0x00000d9du, 0x00000045u, + 0x00000d75u, 0x00000d7au, 0x0003003eu, 0x00000d9du, 0x00000d9cu, 0x00050080u, 0x0000001eu, 0x00000d82u, + 0x00000d78u, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000d83u, 0x00000d82u, 0x0006000cu, 0x00000006u, + 0x00000da2u, 0x00000001u, 0x0000003au, 0x00000d6du, 0x00060041u, 0x00000048u, 0x00000da3u, 0x00000045u, + 0x00000d75u, 0x00000d83u, 0x0003003eu, 0x00000da3u, 0x00000da2u, 0x00050080u, 0x0000001eu, 0x00000d88u, + 0x00000eb8u, 0x00000065u, 0x000200f9u, 0x00000d55u, 0x000200f8u, 0x00000d89u, 0x000400e0u, 0x000000feu, + 0x000000feu, 0x00000236u, 0x000200f9u, 0x00000424u, 0x000200f8u, 0x00000424u, 0x000700f5u, 0x0000001eu, + 0x00000eb9u, 0x00000562u, 0x00000d89u, 0x00000467u, 0x00000427u, 0x000500b1u, 0x00000016u, 0x0000042au, + 0x00000eb9u, 0x00000147u, 0x000400f6u, 0x00000426u, 0x00000427u, 0x00000000u, 0x000400fau, 0x0000042au, + 0x00000425u, 0x00000426u, 0x000200f8u, 0x00000425u, 0x000200f9u, 0x0000042eu, 0x000200f8u, 0x0000042eu, + 0x000700f5u, 0x0000001eu, 0x00000ebau, 0x00000560u, 0x00000425u, 0x00000465u, 0x00000431u, 0x000500b1u, + 0x00000016u, 0x00000435u, 0x00000ebau, 0x00000434u, 0x000400f6u, 0x00000430u, 0x00000431u, 0x00000000u, + 0x000400fau, 0x00000435u, 0x0000042fu, 0x00000430u, 0x000200f8u, 0x0000042fu, 0x0004007cu, 0x00000006u, + 0x00000438u, 0x00000eb9u, 0x0004007cu, 0x00000006u, 0x0000043au, 0x00000ebau, 0x00060041u, 0x00000048u, + 0x00000dbfu, 0x00000045u, 0x00000438u, 0x0000043au, 0x0004003du, 0x00000006u, 0x00000dc0u, 0x00000dbfu, + 0x0006000cu, 0x00000009u, 0x00000dc1u, 0x00000001u, 0x0000003eu, 0x00000dc0u, 0x000300f7u, 0x00000440u, + 0x00000000u, 0x000400fau, 0x0000043eu, 0x0000043fu, 0x00000440u, 0x000200f8u, 0x0000043fu, 0x00050081u, + 0x00000009u, 0x00000444u, 0x00000dc1u, 0x00000ec5u, 0x000200f9u, 0x00000440u, 0x000200f8u, 0x00000440u, + 0x000700f5u, 0x00000009u, 0x00000ebeu, 0x00000dc1u, 0x0000042fu, 0x00000444u, 0x0000043fu, 0x0004003du, + 0x00000445u, 0x00000448u, 0x00000447u, 0x00050084u, 0x0000001eu, 0x0000044au, 0x00000069u, 0x00000eb9u, + 0x00050050u, 0x0000001fu, 0x0000044du, 0x0000044au, 0x00000ebau, 0x0007004fu, 0x00000143u, 0x0000044fu, + 0x000004a8u, 0x000004a8u, 0x00000001u, 0x00000000u, 0x0004007cu, 0x0000001fu, 0x00000450u, 0x0000044fu, + 0x00050084u, 0x0000001fu, 0x00000452u, 0x00000ec6u, 0x00000450u, 0x00050080u, 0x0000001fu, 0x00000453u, + 0x0000044du, 0x00000452u, 0x0009004fu, 0x0000002cu, 0x00000455u, 0x00000ebeu, 0x00000ebeu, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00040063u, 0x00000448u, 0x00000453u, 0x00000455u, 0x0004003du, + 0x00000445u, 0x00000456u, 0x00000447u, 0x00050080u, 0x0000001eu, 0x00000459u, 0x0000044au, 0x00000065u, + 0x00050050u, 0x0000001fu, 0x0000045bu, 0x00000459u, 0x00000ebau, 0x00050080u, 0x0000001fu, 0x00000461u, + 0x0000045bu, 0x00000452u, 0x0009004fu, 0x0000002cu, 0x00000463u, 0x00000ebeu, 0x00000ebeu, 0x00000001u, + 0x00000001u, 0x00000001u, 0x00000001u, 0x00040063u, 0x00000456u, 0x00000461u, 0x00000463u, 0x000200f9u, + 0x00000431u, 0x000200f8u, 0x00000431u, 0x00050080u, 0x0000001eu, 0x00000465u, 0x00000ebau, 0x000003bau, + 0x000200f9u, 0x0000042eu, 0x000200f8u, 0x00000430u, 0x000200f9u, 0x00000427u, 0x000200f8u, 0x00000427u, + 0x00050080u, 0x0000001eu, 0x00000467u, 0x00000eb9u, 0x000003bau, 0x000200f9u, 0x00000424u, 0x000200f8u, + 0x00000426u, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, 0x00000ea0u, 0x00000000u, + 0x00020011u, 0x00000001u, 0x00020011u, 0x00000038u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, + 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0007000fu, 0x00000005u, 0x00000004u, + 0x6e69616du, 0x00000000u, 0x00000140u, 0x00000410u, 0x00060010u, 0x00000004u, 0x00000011u, 0x00000040u, + 0x00000001u, 0x00000001u, 0x00030047u, 0x00000092u, 0x00000002u, 0x00050048u, 0x00000092u, 0x00000000u, + 0x00000023u, 0x00000000u, 0x00050048u, 0x00000092u, 0x00000001u, 0x00000023u, 0x00000008u, 0x00040047u, + 0x00000140u, 0x0000000bu, 0x0000001au, 0x00030047u, 0x0000015au, 0x00000000u, 0x00040047u, 0x0000015au, + 0x00000021u, 0x00000000u, 0x00040047u, 0x0000015au, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000410u, + 0x0000000bu, 0x0000001du, 0x00040047u, 0x0000043cu, 0x00000001u, 0x00000000u, 0x00030047u, 0x00000445u, + 0x00000000u, 0x00030047u, 0x00000445u, 0x00000019u, 0x00040047u, 0x00000445u, 0x00000021u, 0x00000001u, + 0x00040047u, 0x00000445u, 0x00000022u, 0x00000000u, 0x00030047u, 0x00000446u, 0x00000000u, 0x00030047u, + 0x00000454u, 0x00000000u, 0x00040047u, 0x00000467u, 0x0000000bu, 0x00000019u, 0x00030047u, 0x000004b3u, + 0x00000000u, 0x00030047u, 0x000004b9u, 0x00000000u, 0x00030047u, 0x000004bbu, 0x00000000u, 0x00030047u, + 0x000004c1u, 0x00000000u, 0x00030047u, 0x000004c3u, 0x00000000u, 0x00030047u, 0x000004c9u, 0x00000000u, + 0x00030047u, 0x000004cbu, 0x00000000u, 0x00030047u, 0x000004d1u, 0x00000000u, 0x00030047u, 0x000004e7u, + 0x00000000u, 0x00030047u, 0x000004efu, 0x00000000u, 0x00030047u, 0x000004f1u, 0x00000000u, 0x00030047u, + 0x000004f9u, 0x00000000u, 0x00030047u, 0x000004fbu, 0x00000000u, 0x00030047u, 0x00000503u, 0x00000000u, + 0x00030047u, 0x00000505u, 0x00000000u, 0x00030047u, 0x0000050du, 0x00000000u, 0x00030047u, 0x0000051cu, + 0x00000000u, 0x00030047u, 0x00000524u, 0x00000000u, 0x00030047u, 0x00000526u, 0x00000000u, 0x00030047u, + 0x0000052eu, 0x00000000u, 0x00030047u, 0x00000530u, 0x00000000u, 0x00030047u, 0x00000538u, 0x00000000u, + 0x00030047u, 0x0000053au, 0x00000000u, 0x00030047u, 0x00000542u, 0x00000000u, 0x00020013u, 0x00000002u, + 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, 0x00000000u, 0x00030016u, + 0x00000008u, 0x00000020u, 0x00040017u, 0x00000009u, 0x00000008u, 0x00000002u, 0x00040020u, 0x0000000fu, + 0x00000007u, 0x00000009u, 0x00020014u, 0x00000016u, 0x00040017u, 0x00000017u, 0x00000016u, 0x00000002u, + 0x00040015u, 0x0000001eu, 0x00000020u, 0x00000001u, 0x00040017u, 0x0000001fu, 0x0000001eu, 0x00000002u, + 0x00040017u, 0x0000002cu, 0x00000008u, 0x00000004u, 0x0004002bu, 0x00000006u, 0x00000040u, 0x00000029u, + 0x0004001cu, 0x00000041u, 0x00000009u, 0x00000040u, 0x0004002bu, 0x00000006u, 0x00000042u, 0x00000014u, + 0x0004001cu, 0x00000043u, 0x00000041u, 0x00000042u, 0x00040020u, 0x00000044u, 0x00000004u, 0x00000043u, + 0x0004003bu, 0x00000044u, 0x00000045u, 0x00000004u, 0x00040020u, 0x00000048u, 0x00000004u, 0x00000009u, + 0x0004002bu, 0x00000006u, 0x00000057u, 0x00000001u, 0x0004002bu, 0x0000001eu, 0x00000062u, 0x00000000u, + 0x0004002bu, 0x0000001eu, 0x00000063u, 0x00000001u, 0x0004002bu, 0x0000001eu, 0x00000067u, 0x00000002u, + 0x0004002bu, 0x0000001eu, 0x0000006au, 0x00000003u, 0x0004002bu, 0x0000001eu, 0x00000070u, 0x00000005u, + 0x0005002cu, 0x0000001fu, 0x00000080u, 0x00000062u, 0x00000062u, 0x0005002cu, 0x0000001fu, 0x00000085u, + 0x00000063u, 0x00000063u, 0x0004001eu, 0x00000092u, 0x0000001fu, 0x00000009u, 0x00040020u, 0x00000093u, + 0x00000009u, 0x00000092u, 0x0004003bu, 0x00000093u, 0x00000094u, 0x00000009u, 0x00040020u, 0x00000095u, + 0x00000009u, 0x0000001fu, 0x00040020u, 0x000000a2u, 0x00000009u, 0x00000009u, 0x0004002bu, 0x00000006u, + 0x000000fcu, 0x00000002u, 0x00040017u, 0x0000013eu, 0x00000006u, 0x00000003u, 0x00040020u, 0x0000013fu, + 0x00000001u, 0x0000013eu, 0x0004003bu, 0x0000013fu, 0x00000140u, 0x00000001u, 0x00040017u, 0x00000141u, + 0x00000006u, 0x00000002u, 0x0004002bu, 0x0000001eu, 0x00000145u, 0x00000010u, 0x0005002cu, 0x0000001fu, + 0x00000146u, 0x00000145u, 0x00000145u, 0x00090019u, 0x00000157u, 0x00000008u, 0x00000001u, 0x00000000u, + 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, 0x0003001bu, 0x00000158u, 0x00000157u, 0x00040020u, + 0x00000159u, 0x00000000u, 0x00000158u, 0x0004003bu, 0x00000159u, 0x0000015au, 0x00000000u, 0x0004002bu, + 0x00000008u, 0x00000162u, 0x00000000u, 0x00040017u, 0x00000163u, 0x00000008u, 0x00000003u, 0x0003002au, + 0x00000016u, 0x0000016bu, 0x0004002bu, 0x00000008u, 0x00000171u, 0x40000000u, 0x0004002bu, 0x00000008u, + 0x0000017eu, 0x3f800000u, 0x0004002bu, 0x00000008u, 0x0000018bu, 0x40400000u, 0x0004002bu, 0x00000006u, + 0x0000019du, 0x00000010u, 0x0004002bu, 0x0000001eu, 0x000001aau, 0x00000014u, 0x0004002bu, 0x00000006u, + 0x00000234u, 0x00000108u, 0x0004002bu, 0x00000006u, 0x00000236u, 0x00000008u, 0x0004002bu, 0x00000006u, + 0x00000238u, 0x00000004u, 0x0004001cu, 0x00000262u, 0x00000009u, 0x0000019du, 0x00040020u, 0x00000263u, + 0x00000007u, 0x00000262u, 0x0004002bu, 0x00000008u, 0x00000268u, 0x3f9d7658u, 0x0004002bu, 0x00000008u, + 0x0000026eu, 0x3f5019c3u, 0x0004002bu, 0x0000001eu, 0x0000027au, 0x0000000fu, 0x0004002bu, 0x00000008u, + 0x0000027du, 0x3ee31355u, 0x0004002bu, 0x0000001eu, 0x00000295u, 0x0000000eu, 0x0004002bu, 0x00000008u, + 0x00000298u, 0x3f620676u, 0x0004002bu, 0x0000001eu, 0x000002aau, 0x00000004u, 0x0004002bu, 0x0000001eu, + 0x000002b1u, 0x0000000du, 0x0004002bu, 0x00000008u, 0x000002b4u, 0xbd5901aeu, 0x0004002bu, 0x0000001eu, + 0x000002ccu, 0x0000000cu, 0x0004002bu, 0x00000008u, 0x000002cfu, 0xbfcb0673u, 0x0004002bu, 0x0000001eu, + 0x000002e7u, 0x00000006u, 0x0004002bu, 0x00000006u, 0x00000353u, 0x0000000cu, 0x0004001cu, 0x00000354u, + 0x00000009u, 0x00000353u, 0x00040020u, 0x00000355u, 0x00000007u, 0x00000354u, 0x0004002bu, 0x0000001eu, + 0x0000036au, 0x0000000bu, 0x0004002bu, 0x0000001eu, 0x00000384u, 0x0000000au, 0x0004002bu, 0x0000001eu, + 0x0000039eu, 0x00000009u, 0x0004002bu, 0x0000001eu, 0x000003b8u, 0x00000008u, 0x00040020u, 0x0000040fu, + 0x00000001u, 0x00000006u, 0x0004003bu, 0x0000040fu, 0x00000410u, 0x00000001u, 0x0004002bu, 0x00000006u, + 0x00000415u, 0x00000020u, 0x0004002bu, 0x0000001eu, 0x00000432u, 0x00000020u, 0x00030031u, 0x00000016u, + 0x0000043cu, 0x0004002bu, 0x00000008u, 0x0000043fu, 0x3f000000u, 0x00090019u, 0x00000443u, 0x00000008u, + 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000002u, 0x00000000u, 0x00040020u, 0x00000444u, + 0x00000000u, 0x00000443u, 0x0004003bu, 0x00000444u, 0x00000445u, 0x00000000u, 0x0004002bu, 0x00000006u, + 0x00000466u, 0x00000040u, 0x0006002cu, 0x0000013eu, 0x00000467u, 0x00000466u, 0x00000057u, 0x00000057u, + 0x0005002cu, 0x0000001fu, 0x00000e98u, 0x00000067u, 0x00000067u, 0x0005002cu, 0x00000009u, 0x00000e9eu, + 0x0000043fu, 0x0000043fu, 0x0005002cu, 0x0000001fu, 0x00000e9fu, 0x00000432u, 0x00000432u, 0x00050036u, + 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, 0x00000263u, + 0x00000c92u, 0x00000007u, 0x0004003bu, 0x00000355u, 0x00000b95u, 0x00000007u, 0x0004003bu, 0x00000263u, + 0x00000aa1u, 0x00000007u, 0x0004003du, 0x00000006u, 0x00000411u, 0x00000410u, 0x0004003du, 0x0000013eu, + 0x000004a6u, 0x00000140u, 0x0007004fu, 0x00000141u, 0x000004a7u, 0x000004a6u, 0x000004a6u, 0x00000000u, + 0x00000001u, 0x0004007cu, 0x0000001fu, 0x000004a8u, 0x000004a7u, 0x00050084u, 0x0000001fu, 0x000004a9u, + 0x000004a8u, 0x00000146u, 0x00050082u, 0x0000001fu, 0x000004abu, 0x000004a9u, 0x00000e98u, 0x000600cbu, + 0x00000006u, 0x00000550u, 0x00000411u, 0x00000062u, 0x00000063u, 0x000600cbu, 0x00000006u, 0x00000552u, + 0x00000411u, 0x00000063u, 0x00000067u, 0x000600cbu, 0x00000006u, 0x00000554u, 0x00000411u, 0x0000006au, + 0x00000067u, 0x000500c4u, 0x00000006u, 0x00000555u, 0x00000554u, 0x00000063u, 0x000500c5u, 0x00000006u, + 0x00000557u, 0x00000550u, 0x00000555u, 0x000600cbu, 0x00000006u, 0x00000559u, 0x00000411u, 0x00000070u, + 0x00000063u, 0x000500c4u, 0x00000006u, 0x0000055au, 0x00000559u, 0x00000067u, 0x000500c5u, 0x00000006u, + 0x0000055cu, 0x00000552u, 0x0000055au, 0x0004007cu, 0x0000001eu, 0x0000055eu, 0x0000055cu, 0x0004007cu, + 0x0000001eu, 0x00000560u, 0x00000557u, 0x00050050u, 0x0000001fu, 0x00000561u, 0x0000055eu, 0x00000560u, + 0x00050084u, 0x0000001fu, 0x000004afu, 0x00000e98u, 0x00000561u, 0x00050080u, 0x0000001fu, 0x000004b2u, + 0x000004abu, 0x000004afu, 0x0004003du, 0x00000158u, 0x000004b3u, 0x0000015au, 0x000500b1u, 0x00000017u, + 0x0000056du, 0x000004b2u, 0x00000080u, 0x00050051u, 0x00000016u, 0x0000058eu, 0x0000056du, 0x00000000u, + 0x00050051u, 0x00000016u, 0x00000593u, 0x0000056du, 0x00000001u, 0x000600a9u, 0x0000001fu, 0x0000056fu, + 0x0000056du, 0x00000085u, 0x00000080u, 0x00050082u, 0x0000001fu, 0x00000571u, 0x000004b2u, 0x0000056fu, + 0x00050080u, 0x0000001fu, 0x00000574u, 0x00000571u, 0x00000085u, 0x0004006fu, 0x00000009u, 0x00000583u, + 0x00000574u, 0x00050041u, 0x000000a2u, 0x00000584u, 0x00000094u, 0x00000063u, 0x0004003du, 0x00000009u, + 0x00000585u, 0x00000584u, 0x00050085u, 0x00000009u, 0x00000586u, 0x00000583u, 0x00000585u, 0x00050051u, + 0x00000008u, 0x000004b6u, 0x00000586u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000004b7u, 0x00000586u, + 0x00000000u, 0x00060050u, 0x00000163u, 0x000004b8u, 0x000004b6u, 0x000004b7u, 0x00000162u, 0x00060060u, + 0x0000002cu, 0x000004b9u, 0x000004b3u, 0x000004b8u, 0x00000062u, 0x0004003du, 0x00000158u, 0x000004bbu, + 0x0000015au, 0x00050050u, 0x00000017u, 0x000005d6u, 0x0000016bu, 0x00000593u, 0x000600a9u, 0x0000001fu, + 0x000005b0u, 0x000005d6u, 0x00000085u, 0x00000080u, 0x00050082u, 0x0000001fu, 0x000005b2u, 0x000004b2u, + 0x000005b0u, 0x00050080u, 0x0000001fu, 0x000005b5u, 0x000005b2u, 0x00000085u, 0x00050041u, 0x00000095u, + 0x000005bcu, 0x00000094u, 0x00000062u, 0x0004003du, 0x0000001fu, 0x000005bdu, 0x000005bcu, 0x000500afu, + 0x00000017u, 0x000005beu, 0x000005b5u, 0x000005bdu, 0x00050051u, 0x00000016u, 0x000005dcu, 0x000005beu, + 0x00000000u, 0x00050050u, 0x00000017u, 0x000005e3u, 0x000005dcu, 0x0000016bu, 0x000600a9u, 0x0000001fu, + 0x000005c0u, 0x000005e3u, 0x00000085u, 0x00000080u, 0x00050080u, 0x0000001fu, 0x000005c2u, 0x000005b5u, + 0x000005c0u, 0x0004006fu, 0x00000009u, 0x000005c4u, 0x000005c2u, 0x00050085u, 0x00000009u, 0x000005c7u, + 0x000005c4u, 0x00000585u, 0x00050051u, 0x00000008u, 0x000004beu, 0x000005c7u, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000004bfu, 0x000005c7u, 0x00000000u, 0x00060050u, 0x00000163u, 0x000004c0u, 0x000004beu, + 0x000004bfu, 0x00000171u, 0x00060060u, 0x0000002cu, 0x000004c1u, 0x000004bbu, 0x000004c0u, 0x00000062u, + 0x0004003du, 0x00000158u, 0x000004c3u, 0x0000015au, 0x00050050u, 0x00000017u, 0x00000617u, 0x0000058eu, + 0x0000016bu, 0x000600a9u, 0x0000001fu, 0x000005f1u, 0x00000617u, 0x00000085u, 0x00000080u, 0x00050082u, + 0x0000001fu, 0x000005f3u, 0x000004b2u, 0x000005f1u, 0x00050080u, 0x0000001fu, 0x000005f6u, 0x000005f3u, + 0x00000085u, 0x000500afu, 0x00000017u, 0x000005ffu, 0x000005f6u, 0x000005bdu, 0x00050051u, 0x00000016u, + 0x00000622u, 0x000005ffu, 0x00000001u, 0x00050050u, 0x00000017u, 0x00000624u, 0x0000016bu, 0x00000622u, + 0x000600a9u, 0x0000001fu, 0x00000601u, 0x00000624u, 0x00000085u, 0x00000080u, 0x00050080u, 0x0000001fu, + 0x00000603u, 0x000005f6u, 0x00000601u, 0x0004006fu, 0x00000009u, 0x00000605u, 0x00000603u, 0x00050085u, + 0x00000009u, 0x00000608u, 0x00000605u, 0x00000585u, 0x00050051u, 0x00000008u, 0x000004c6u, 0x00000608u, + 0x00000001u, 0x00050051u, 0x00000008u, 0x000004c7u, 0x00000608u, 0x00000000u, 0x00060050u, 0x00000163u, + 0x000004c8u, 0x000004c6u, 0x000004c7u, 0x0000017eu, 0x00060060u, 0x0000002cu, 0x000004c9u, 0x000004c3u, + 0x000004c8u, 0x00000062u, 0x0004003du, 0x00000158u, 0x000004cbu, 0x0000015au, 0x00050080u, 0x0000001fu, + 0x00000637u, 0x000004b2u, 0x00000085u, 0x000500afu, 0x00000017u, 0x00000640u, 0x00000637u, 0x000005bdu, + 0x000600a9u, 0x0000001fu, 0x00000642u, 0x00000640u, 0x00000085u, 0x00000080u, 0x00050080u, 0x0000001fu, + 0x00000644u, 0x00000637u, 0x00000642u, 0x0004006fu, 0x00000009u, 0x00000646u, 0x00000644u, 0x00050085u, + 0x00000009u, 0x00000649u, 0x00000646u, 0x00000585u, 0x00050051u, 0x00000008u, 0x000004ceu, 0x00000649u, + 0x00000001u, 0x00050051u, 0x00000008u, 0x000004cfu, 0x00000649u, 0x00000000u, 0x00060050u, 0x00000163u, + 0x000004d0u, 0x000004ceu, 0x000004cfu, 0x0000018bu, 0x00060060u, 0x0000002cu, 0x000004d1u, 0x000004cbu, + 0x000004d0u, 0x00000062u, 0x00050051u, 0x0000001eu, 0x00000680u, 0x000004afu, 0x00000001u, 0x0004007cu, + 0x00000006u, 0x00000682u, 0x00000680u, 0x00050051u, 0x0000001eu, 0x00000684u, 0x000004afu, 0x00000000u, + 0x00050084u, 0x0000001eu, 0x00000685u, 0x00000067u, 0x00000684u, 0x0004007cu, 0x00000006u, 0x00000687u, + 0x00000685u, 0x00050051u, 0x00000008u, 0x00000689u, 0x000004b9u, 0x00000003u, 0x00050051u, 0x00000008u, + 0x0000068bu, 0x000004c9u, 0x00000003u, 0x00050050u, 0x00000009u, 0x0000068cu, 0x00000689u, 0x0000068bu, + 0x00060041u, 0x00000048u, 0x000006fbu, 0x00000045u, 0x00000682u, 0x00000687u, 0x0003003eu, 0x000006fbu, + 0x0000068cu, 0x00050080u, 0x0000001eu, 0x00000695u, 0x00000685u, 0x00000063u, 0x0004007cu, 0x00000006u, + 0x00000696u, 0x00000695u, 0x00050051u, 0x00000008u, 0x00000698u, 0x000004c1u, 0x00000003u, 0x00050051u, + 0x00000008u, 0x0000069au, 0x000004d1u, 0x00000003u, 0x00050050u, 0x00000009u, 0x0000069bu, 0x00000698u, + 0x0000069au, 0x00060041u, 0x00000048u, 0x00000700u, 0x00000045u, 0x00000682u, 0x00000696u, 0x0003003eu, + 0x00000700u, 0x0000069bu, 0x00050080u, 0x0000001eu, 0x000006a4u, 0x00000685u, 0x00000067u, 0x0004007cu, + 0x00000006u, 0x000006a5u, 0x000006a4u, 0x00050051u, 0x00000008u, 0x000006a7u, 0x000004b9u, 0x00000000u, + 0x00050051u, 0x00000008u, 0x000006a9u, 0x000004c9u, 0x00000000u, 0x00050050u, 0x00000009u, 0x000006aau, + 0x000006a7u, 0x000006a9u, 0x00060041u, 0x00000048u, 0x00000705u, 0x00000045u, 0x00000682u, 0x000006a5u, + 0x0003003eu, 0x00000705u, 0x000006aau, 0x00050080u, 0x0000001eu, 0x000006b3u, 0x00000685u, 0x0000006au, + 0x0004007cu, 0x00000006u, 0x000006b4u, 0x000006b3u, 0x00050051u, 0x00000008u, 0x000006b6u, 0x000004c1u, + 0x00000000u, 0x00050051u, 0x00000008u, 0x000006b8u, 0x000004d1u, 0x00000000u, 0x00050050u, 0x00000009u, + 0x000006b9u, 0x000006b6u, 0x000006b8u, 0x00060041u, 0x00000048u, 0x0000070au, 0x00000045u, 0x00000682u, + 0x000006b4u, 0x0003003eu, 0x0000070au, 0x000006b9u, 0x00050080u, 0x0000001eu, 0x000006bdu, 0x00000680u, + 0x00000063u, 0x0004007cu, 0x00000006u, 0x000006beu, 0x000006bdu, 0x00050051u, 0x00000008u, 0x000006c5u, + 0x000004b9u, 0x00000002u, 0x00050051u, 0x00000008u, 0x000006c7u, 0x000004c9u, 0x00000002u, 0x00050050u, + 0x00000009u, 0x000006c8u, 0x000006c5u, 0x000006c7u, 0x00060041u, 0x00000048u, 0x0000070fu, 0x00000045u, + 0x000006beu, 0x00000687u, 0x0003003eu, 0x0000070fu, 0x000006c8u, 0x00050051u, 0x00000008u, 0x000006d4u, + 0x000004c1u, 0x00000002u, 0x00050051u, 0x00000008u, 0x000006d6u, 0x000004d1u, 0x00000002u, 0x00050050u, + 0x00000009u, 0x000006d7u, 0x000006d4u, 0x000006d6u, 0x00060041u, 0x00000048u, 0x00000714u, 0x00000045u, + 0x000006beu, 0x00000696u, 0x0003003eu, 0x00000714u, 0x000006d7u, 0x00050051u, 0x00000008u, 0x000006e3u, + 0x000004b9u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000006e5u, 0x000004c9u, 0x00000001u, 0x00050050u, + 0x00000009u, 0x000006e6u, 0x000006e3u, 0x000006e5u, 0x00060041u, 0x00000048u, 0x00000719u, 0x00000045u, + 0x000006beu, 0x000006a5u, 0x0003003eu, 0x00000719u, 0x000006e6u, 0x00050051u, 0x00000008u, 0x000006f2u, + 0x000004c1u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000006f4u, 0x000004d1u, 0x00000001u, 0x00050050u, + 0x00000009u, 0x000006f5u, 0x000006f2u, 0x000006f4u, 0x00060041u, 0x00000048u, 0x0000071eu, 0x00000045u, + 0x000006beu, 0x000006b4u, 0x0003003eu, 0x0000071eu, 0x000006f5u, 0x00050089u, 0x00000006u, 0x000004dau, + 0x00000411u, 0x000000fcu, 0x00050084u, 0x00000006u, 0x000004dbu, 0x000000fcu, 0x000004dau, 0x00050080u, + 0x00000006u, 0x000004dcu, 0x0000019du, 0x000004dbu, 0x0004007cu, 0x0000001eu, 0x000004ddu, 0x000004dcu, + 0x00050086u, 0x00000006u, 0x000004dfu, 0x00000411u, 0x000000fcu, 0x00050084u, 0x00000006u, 0x000004e0u, + 0x000000fcu, 0x000004dfu, 0x0004007cu, 0x0000001eu, 0x000004e1u, 0x000004e0u, 0x00050050u, 0x0000001fu, + 0x000004e2u, 0x000004ddu, 0x000004e1u, 0x000500b1u, 0x00000016u, 0x000004e5u, 0x000004e1u, 0x000001aau, + 0x000300f7u, 0x00000515u, 0x00000000u, 0x000400fau, 0x000004e5u, 0x000004e6u, 0x00000515u, 0x000200f8u, + 0x000004e6u, 0x0004003du, 0x00000158u, 0x000004e7u, 0x0000015au, 0x00050080u, 0x0000001fu, 0x000004eau, + 0x000004abu, 0x000004e2u, 0x000500b1u, 0x00000017u, 0x0000072au, 0x000004eau, 0x00000080u, 0x00050051u, + 0x00000016u, 0x0000074bu, 0x0000072au, 0x00000000u, 0x00050051u, 0x00000016u, 0x00000750u, 0x0000072au, + 0x00000001u, 0x000600a9u, 0x0000001fu, 0x0000072cu, 0x0000072au, 0x00000085u, 0x00000080u, 0x00050082u, + 0x0000001fu, 0x0000072eu, 0x000004eau, 0x0000072cu, 0x00050080u, 0x0000001fu, 0x00000731u, 0x0000072eu, + 0x00000085u, 0x0004006fu, 0x00000009u, 0x00000740u, 0x00000731u, 0x00050085u, 0x00000009u, 0x00000743u, + 0x00000740u, 0x00000585u, 0x00050051u, 0x00000008u, 0x000004ecu, 0x00000743u, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000004edu, 0x00000743u, 0x00000000u, 0x00060050u, 0x00000163u, 0x000004eeu, 0x000004ecu, + 0x000004edu, 0x00000162u, 0x00060060u, 0x0000002cu, 0x000004efu, 0x000004e7u, 0x000004eeu, 0x00000062u, + 0x0004003du, 0x00000158u, 0x000004f1u, 0x0000015au, 0x00050050u, 0x00000017u, 0x00000793u, 0x0000016bu, + 0x00000750u, 0x000600a9u, 0x0000001fu, 0x0000076du, 0x00000793u, 0x00000085u, 0x00000080u, 0x00050082u, + 0x0000001fu, 0x0000076fu, 0x000004eau, 0x0000076du, 0x00050080u, 0x0000001fu, 0x00000772u, 0x0000076fu, + 0x00000085u, 0x000500afu, 0x00000017u, 0x0000077bu, 0x00000772u, 0x000005bdu, 0x00050051u, 0x00000016u, + 0x00000799u, 0x0000077bu, 0x00000000u, 0x00050050u, 0x00000017u, 0x000007a0u, 0x00000799u, 0x0000016bu, + 0x000600a9u, 0x0000001fu, 0x0000077du, 0x000007a0u, 0x00000085u, 0x00000080u, 0x00050080u, 0x0000001fu, + 0x0000077fu, 0x00000772u, 0x0000077du, 0x0004006fu, 0x00000009u, 0x00000781u, 0x0000077fu, 0x00050085u, + 0x00000009u, 0x00000784u, 0x00000781u, 0x00000585u, 0x00050051u, 0x00000008u, 0x000004f6u, 0x00000784u, + 0x00000001u, 0x00050051u, 0x00000008u, 0x000004f7u, 0x00000784u, 0x00000000u, 0x00060050u, 0x00000163u, + 0x000004f8u, 0x000004f6u, 0x000004f7u, 0x00000171u, 0x00060060u, 0x0000002cu, 0x000004f9u, 0x000004f1u, + 0x000004f8u, 0x00000062u, 0x0004003du, 0x00000158u, 0x000004fbu, 0x0000015au, 0x00050050u, 0x00000017u, + 0x000007d4u, 0x0000074bu, 0x0000016bu, 0x000600a9u, 0x0000001fu, 0x000007aeu, 0x000007d4u, 0x00000085u, + 0x00000080u, 0x00050082u, 0x0000001fu, 0x000007b0u, 0x000004eau, 0x000007aeu, 0x00050080u, 0x0000001fu, + 0x000007b3u, 0x000007b0u, 0x00000085u, 0x000500afu, 0x00000017u, 0x000007bcu, 0x000007b3u, 0x000005bdu, + 0x00050051u, 0x00000016u, 0x000007dfu, 0x000007bcu, 0x00000001u, 0x00050050u, 0x00000017u, 0x000007e1u, + 0x0000016bu, 0x000007dfu, 0x000600a9u, 0x0000001fu, 0x000007beu, 0x000007e1u, 0x00000085u, 0x00000080u, + 0x00050080u, 0x0000001fu, 0x000007c0u, 0x000007b3u, 0x000007beu, 0x0004006fu, 0x00000009u, 0x000007c2u, + 0x000007c0u, 0x00050085u, 0x00000009u, 0x000007c5u, 0x000007c2u, 0x00000585u, 0x00050051u, 0x00000008u, + 0x00000500u, 0x000007c5u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000501u, 0x000007c5u, 0x00000000u, + 0x00060050u, 0x00000163u, 0x00000502u, 0x00000500u, 0x00000501u, 0x0000017eu, 0x00060060u, 0x0000002cu, + 0x00000503u, 0x000004fbu, 0x00000502u, 0x00000062u, 0x0004003du, 0x00000158u, 0x00000505u, 0x0000015au, + 0x00050080u, 0x0000001fu, 0x000007f4u, 0x000004eau, 0x00000085u, 0x000500afu, 0x00000017u, 0x000007fdu, + 0x000007f4u, 0x000005bdu, 0x000600a9u, 0x0000001fu, 0x000007ffu, 0x000007fdu, 0x00000085u, 0x00000080u, + 0x00050080u, 0x0000001fu, 0x00000801u, 0x000007f4u, 0x000007ffu, 0x0004006fu, 0x00000009u, 0x00000803u, + 0x00000801u, 0x00050085u, 0x00000009u, 0x00000806u, 0x00000803u, 0x00000585u, 0x00050051u, 0x00000008u, + 0x0000050au, 0x00000806u, 0x00000001u, 0x00050051u, 0x00000008u, 0x0000050bu, 0x00000806u, 0x00000000u, + 0x00060050u, 0x00000163u, 0x0000050cu, 0x0000050au, 0x0000050bu, 0x0000018bu, 0x00060060u, 0x0000002cu, + 0x0000050du, 0x00000505u, 0x0000050cu, 0x00000062u, 0x00050084u, 0x0000001eu, 0x00000842u, 0x00000067u, + 0x000004ddu, 0x0004007cu, 0x00000006u, 0x00000844u, 0x00000842u, 0x00050051u, 0x00000008u, 0x00000846u, + 0x000004efu, 0x00000003u, 0x00050051u, 0x00000008u, 0x00000848u, 0x00000503u, 0x00000003u, 0x00050050u, + 0x00000009u, 0x00000849u, 0x00000846u, 0x00000848u, 0x00060041u, 0x00000048u, 0x000008b8u, 0x00000045u, + 0x000004e0u, 0x00000844u, 0x0003003eu, 0x000008b8u, 0x00000849u, 0x00050080u, 0x0000001eu, 0x00000852u, + 0x00000842u, 0x00000063u, 0x0004007cu, 0x00000006u, 0x00000853u, 0x00000852u, 0x00050051u, 0x00000008u, + 0x00000855u, 0x000004f9u, 0x00000003u, 0x00050051u, 0x00000008u, 0x00000857u, 0x0000050du, 0x00000003u, + 0x00050050u, 0x00000009u, 0x00000858u, 0x00000855u, 0x00000857u, 0x00060041u, 0x00000048u, 0x000008bdu, + 0x00000045u, 0x000004e0u, 0x00000853u, 0x0003003eu, 0x000008bdu, 0x00000858u, 0x00050080u, 0x0000001eu, + 0x00000861u, 0x00000842u, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000862u, 0x00000861u, 0x00050051u, + 0x00000008u, 0x00000864u, 0x000004efu, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000866u, 0x00000503u, + 0x00000000u, 0x00050050u, 0x00000009u, 0x00000867u, 0x00000864u, 0x00000866u, 0x00060041u, 0x00000048u, + 0x000008c2u, 0x00000045u, 0x000004e0u, 0x00000862u, 0x0003003eu, 0x000008c2u, 0x00000867u, 0x00050080u, + 0x0000001eu, 0x00000870u, 0x00000842u, 0x0000006au, 0x0004007cu, 0x00000006u, 0x00000871u, 0x00000870u, + 0x00050051u, 0x00000008u, 0x00000873u, 0x000004f9u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000875u, + 0x0000050du, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000876u, 0x00000873u, 0x00000875u, 0x00060041u, + 0x00000048u, 0x000008c7u, 0x00000045u, 0x000004e0u, 0x00000871u, 0x0003003eu, 0x000008c7u, 0x00000876u, + 0x00050080u, 0x0000001eu, 0x0000087au, 0x000004e1u, 0x00000063u, 0x0004007cu, 0x00000006u, 0x0000087bu, + 0x0000087au, 0x00050051u, 0x00000008u, 0x00000882u, 0x000004efu, 0x00000002u, 0x00050051u, 0x00000008u, + 0x00000884u, 0x00000503u, 0x00000002u, 0x00050050u, 0x00000009u, 0x00000885u, 0x00000882u, 0x00000884u, + 0x00060041u, 0x00000048u, 0x000008ccu, 0x00000045u, 0x0000087bu, 0x00000844u, 0x0003003eu, 0x000008ccu, + 0x00000885u, 0x00050051u, 0x00000008u, 0x00000891u, 0x000004f9u, 0x00000002u, 0x00050051u, 0x00000008u, + 0x00000893u, 0x0000050du, 0x00000002u, 0x00050050u, 0x00000009u, 0x00000894u, 0x00000891u, 0x00000893u, + 0x00060041u, 0x00000048u, 0x000008d1u, 0x00000045u, 0x0000087bu, 0x00000853u, 0x0003003eu, 0x000008d1u, + 0x00000894u, 0x00050051u, 0x00000008u, 0x000008a0u, 0x000004efu, 0x00000001u, 0x00050051u, 0x00000008u, + 0x000008a2u, 0x00000503u, 0x00000001u, 0x00050050u, 0x00000009u, 0x000008a3u, 0x000008a0u, 0x000008a2u, + 0x00060041u, 0x00000048u, 0x000008d6u, 0x00000045u, 0x0000087bu, 0x00000862u, 0x0003003eu, 0x000008d6u, + 0x000008a3u, 0x00050051u, 0x00000008u, 0x000008afu, 0x000004f9u, 0x00000001u, 0x00050051u, 0x00000008u, + 0x000008b1u, 0x0000050du, 0x00000001u, 0x00050050u, 0x00000009u, 0x000008b2u, 0x000008afu, 0x000008b1u, + 0x00060041u, 0x00000048u, 0x000008dbu, 0x00000045u, 0x0000087bu, 0x00000871u, 0x0003003eu, 0x000008dbu, + 0x000008b2u, 0x000200f9u, 0x00000515u, 0x000200f8u, 0x00000515u, 0x0007004fu, 0x0000001fu, 0x00000517u, + 0x000004e2u, 0x000004e2u, 0x00000001u, 0x00000000u, 0x000500b1u, 0x00000016u, 0x0000051au, 0x000004e1u, + 0x00000145u, 0x000300f7u, 0x0000054au, 0x00000000u, 0x000400fau, 0x0000051au, 0x0000051bu, 0x0000054au, + 0x000200f8u, 0x0000051bu, 0x0004003du, 0x00000158u, 0x0000051cu, 0x0000015au, 0x00050080u, 0x0000001fu, + 0x0000051fu, 0x000004abu, 0x00000517u, 0x000500b1u, 0x00000017u, 0x000008e7u, 0x0000051fu, 0x00000080u, + 0x00050051u, 0x00000016u, 0x00000908u, 0x000008e7u, 0x00000000u, 0x00050051u, 0x00000016u, 0x0000090du, + 0x000008e7u, 0x00000001u, 0x000600a9u, 0x0000001fu, 0x000008e9u, 0x000008e7u, 0x00000085u, 0x00000080u, + 0x00050082u, 0x0000001fu, 0x000008ebu, 0x0000051fu, 0x000008e9u, 0x00050080u, 0x0000001fu, 0x000008eeu, + 0x000008ebu, 0x00000085u, 0x0004006fu, 0x00000009u, 0x000008fdu, 0x000008eeu, 0x00050085u, 0x00000009u, + 0x00000900u, 0x000008fdu, 0x00000585u, 0x00050051u, 0x00000008u, 0x00000521u, 0x00000900u, 0x00000001u, + 0x00050051u, 0x00000008u, 0x00000522u, 0x00000900u, 0x00000000u, 0x00060050u, 0x00000163u, 0x00000523u, + 0x00000521u, 0x00000522u, 0x00000162u, 0x00060060u, 0x0000002cu, 0x00000524u, 0x0000051cu, 0x00000523u, + 0x00000062u, 0x0004003du, 0x00000158u, 0x00000526u, 0x0000015au, 0x00050050u, 0x00000017u, 0x00000950u, + 0x0000016bu, 0x0000090du, 0x000600a9u, 0x0000001fu, 0x0000092au, 0x00000950u, 0x00000085u, 0x00000080u, + 0x00050082u, 0x0000001fu, 0x0000092cu, 0x0000051fu, 0x0000092au, 0x00050080u, 0x0000001fu, 0x0000092fu, + 0x0000092cu, 0x00000085u, 0x000500afu, 0x00000017u, 0x00000938u, 0x0000092fu, 0x000005bdu, 0x00050051u, + 0x00000016u, 0x00000956u, 0x00000938u, 0x00000000u, 0x00050050u, 0x00000017u, 0x0000095du, 0x00000956u, + 0x0000016bu, 0x000600a9u, 0x0000001fu, 0x0000093au, 0x0000095du, 0x00000085u, 0x00000080u, 0x00050080u, + 0x0000001fu, 0x0000093cu, 0x0000092fu, 0x0000093au, 0x0004006fu, 0x00000009u, 0x0000093eu, 0x0000093cu, + 0x00050085u, 0x00000009u, 0x00000941u, 0x0000093eu, 0x00000585u, 0x00050051u, 0x00000008u, 0x0000052bu, + 0x00000941u, 0x00000001u, 0x00050051u, 0x00000008u, 0x0000052cu, 0x00000941u, 0x00000000u, 0x00060050u, + 0x00000163u, 0x0000052du, 0x0000052bu, 0x0000052cu, 0x00000171u, 0x00060060u, 0x0000002cu, 0x0000052eu, + 0x00000526u, 0x0000052du, 0x00000062u, 0x0004003du, 0x00000158u, 0x00000530u, 0x0000015au, 0x00050050u, + 0x00000017u, 0x00000991u, 0x00000908u, 0x0000016bu, 0x000600a9u, 0x0000001fu, 0x0000096bu, 0x00000991u, + 0x00000085u, 0x00000080u, 0x00050082u, 0x0000001fu, 0x0000096du, 0x0000051fu, 0x0000096bu, 0x00050080u, + 0x0000001fu, 0x00000970u, 0x0000096du, 0x00000085u, 0x000500afu, 0x00000017u, 0x00000979u, 0x00000970u, + 0x000005bdu, 0x00050051u, 0x00000016u, 0x0000099cu, 0x00000979u, 0x00000001u, 0x00050050u, 0x00000017u, + 0x0000099eu, 0x0000016bu, 0x0000099cu, 0x000600a9u, 0x0000001fu, 0x0000097bu, 0x0000099eu, 0x00000085u, + 0x00000080u, 0x00050080u, 0x0000001fu, 0x0000097du, 0x00000970u, 0x0000097bu, 0x0004006fu, 0x00000009u, + 0x0000097fu, 0x0000097du, 0x00050085u, 0x00000009u, 0x00000982u, 0x0000097fu, 0x00000585u, 0x00050051u, + 0x00000008u, 0x00000535u, 0x00000982u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000536u, 0x00000982u, + 0x00000000u, 0x00060050u, 0x00000163u, 0x00000537u, 0x00000535u, 0x00000536u, 0x0000017eu, 0x00060060u, + 0x0000002cu, 0x00000538u, 0x00000530u, 0x00000537u, 0x00000062u, 0x0004003du, 0x00000158u, 0x0000053au, + 0x0000015au, 0x00050080u, 0x0000001fu, 0x000009b1u, 0x0000051fu, 0x00000085u, 0x000500afu, 0x00000017u, + 0x000009bau, 0x000009b1u, 0x000005bdu, 0x000600a9u, 0x0000001fu, 0x000009bcu, 0x000009bau, 0x00000085u, + 0x00000080u, 0x00050080u, 0x0000001fu, 0x000009beu, 0x000009b1u, 0x000009bcu, 0x0004006fu, 0x00000009u, + 0x000009c0u, 0x000009beu, 0x00050085u, 0x00000009u, 0x000009c3u, 0x000009c0u, 0x00000585u, 0x00050051u, + 0x00000008u, 0x0000053fu, 0x000009c3u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000540u, 0x000009c3u, + 0x00000000u, 0x00060050u, 0x00000163u, 0x00000541u, 0x0000053fu, 0x00000540u, 0x0000018bu, 0x00060060u, + 0x0000002cu, 0x00000542u, 0x0000053au, 0x00000541u, 0x00000062u, 0x00050084u, 0x0000001eu, 0x000009ffu, + 0x00000067u, 0x000004e1u, 0x0004007cu, 0x00000006u, 0x00000a01u, 0x000009ffu, 0x00050051u, 0x00000008u, + 0x00000a03u, 0x00000524u, 0x00000003u, 0x00050051u, 0x00000008u, 0x00000a05u, 0x00000538u, 0x00000003u, + 0x00050050u, 0x00000009u, 0x00000a06u, 0x00000a03u, 0x00000a05u, 0x00060041u, 0x00000048u, 0x00000a75u, + 0x00000045u, 0x000004dcu, 0x00000a01u, 0x0003003eu, 0x00000a75u, 0x00000a06u, 0x00050080u, 0x0000001eu, + 0x00000a0fu, 0x000009ffu, 0x00000063u, 0x0004007cu, 0x00000006u, 0x00000a10u, 0x00000a0fu, 0x00050051u, + 0x00000008u, 0x00000a12u, 0x0000052eu, 0x00000003u, 0x00050051u, 0x00000008u, 0x00000a14u, 0x00000542u, + 0x00000003u, 0x00050050u, 0x00000009u, 0x00000a15u, 0x00000a12u, 0x00000a14u, 0x00060041u, 0x00000048u, + 0x00000a7au, 0x00000045u, 0x000004dcu, 0x00000a10u, 0x0003003eu, 0x00000a7au, 0x00000a15u, 0x00050080u, + 0x0000001eu, 0x00000a1eu, 0x000009ffu, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000a1fu, 0x00000a1eu, + 0x00050051u, 0x00000008u, 0x00000a21u, 0x00000524u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000a23u, + 0x00000538u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000a24u, 0x00000a21u, 0x00000a23u, 0x00060041u, + 0x00000048u, 0x00000a7fu, 0x00000045u, 0x000004dcu, 0x00000a1fu, 0x0003003eu, 0x00000a7fu, 0x00000a24u, + 0x00050080u, 0x0000001eu, 0x00000a2du, 0x000009ffu, 0x0000006au, 0x0004007cu, 0x00000006u, 0x00000a2eu, + 0x00000a2du, 0x00050051u, 0x00000008u, 0x00000a30u, 0x0000052eu, 0x00000000u, 0x00050051u, 0x00000008u, + 0x00000a32u, 0x00000542u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000a33u, 0x00000a30u, 0x00000a32u, + 0x00060041u, 0x00000048u, 0x00000a84u, 0x00000045u, 0x000004dcu, 0x00000a2eu, 0x0003003eu, 0x00000a84u, + 0x00000a33u, 0x00050080u, 0x0000001eu, 0x00000a37u, 0x000004ddu, 0x00000063u, 0x0004007cu, 0x00000006u, + 0x00000a38u, 0x00000a37u, 0x00050051u, 0x00000008u, 0x00000a3fu, 0x00000524u, 0x00000002u, 0x00050051u, + 0x00000008u, 0x00000a41u, 0x00000538u, 0x00000002u, 0x00050050u, 0x00000009u, 0x00000a42u, 0x00000a3fu, + 0x00000a41u, 0x00060041u, 0x00000048u, 0x00000a89u, 0x00000045u, 0x00000a38u, 0x00000a01u, 0x0003003eu, + 0x00000a89u, 0x00000a42u, 0x00050051u, 0x00000008u, 0x00000a4eu, 0x0000052eu, 0x00000002u, 0x00050051u, + 0x00000008u, 0x00000a50u, 0x00000542u, 0x00000002u, 0x00050050u, 0x00000009u, 0x00000a51u, 0x00000a4eu, + 0x00000a50u, 0x00060041u, 0x00000048u, 0x00000a8eu, 0x00000045u, 0x00000a38u, 0x00000a10u, 0x0003003eu, + 0x00000a8eu, 0x00000a51u, 0x00050051u, 0x00000008u, 0x00000a5du, 0x00000524u, 0x00000001u, 0x00050051u, + 0x00000008u, 0x00000a5fu, 0x00000538u, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000a60u, 0x00000a5du, + 0x00000a5fu, 0x00060041u, 0x00000048u, 0x00000a93u, 0x00000045u, 0x00000a38u, 0x00000a1fu, 0x0003003eu, + 0x00000a93u, 0x00000a60u, 0x00050051u, 0x00000008u, 0x00000a6cu, 0x0000052eu, 0x00000001u, 0x00050051u, + 0x00000008u, 0x00000a6eu, 0x00000542u, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000a6fu, 0x00000a6cu, + 0x00000a6eu, 0x00060041u, 0x00000048u, 0x00000a98u, 0x00000045u, 0x00000a38u, 0x00000a2eu, 0x0003003eu, + 0x00000a98u, 0x00000a6fu, 0x000200f9u, 0x0000054au, 0x000200f8u, 0x0000054au, 0x000400e0u, 0x000000fcu, + 0x000000fcu, 0x00000234u, 0x00050089u, 0x00000006u, 0x00000ab4u, 0x00000411u, 0x00000238u, 0x00050084u, + 0x00000006u, 0x00000ab5u, 0x00000236u, 0x00000ab4u, 0x0004007cu, 0x0000001eu, 0x00000ab6u, 0x00000ab5u, + 0x00050086u, 0x00000006u, 0x00000ab8u, 0x00000411u, 0x00000238u, 0x0004007cu, 0x0000001eu, 0x00000ab9u, + 0x00000ab8u, 0x000200f9u, 0x00000abbu, 0x000200f8u, 0x00000abbu, 0x000700f5u, 0x0000001eu, 0x00000e80u, + 0x00000062u, 0x0000054au, 0x00000ae0u, 0x00000abfu, 0x000500b1u, 0x00000016u, 0x00000abeu, 0x00000e80u, + 0x00000145u, 0x000400f6u, 0x00000ae1u, 0x00000abfu, 0x00000000u, 0x000400fau, 0x00000abeu, 0x00000abfu, + 0x00000ae1u, 0x000200f8u, 0x00000abfu, 0x00050080u, 0x0000001eu, 0x00000ac6u, 0x00000ab6u, 0x00000e80u, + 0x0004007cu, 0x00000006u, 0x00000ac8u, 0x00000ac6u, 0x00060041u, 0x00000048u, 0x00000b7bu, 0x00000045u, + 0x00000ab8u, 0x00000ac8u, 0x0004003du, 0x00000009u, 0x00000b7cu, 0x00000b7bu, 0x00050080u, 0x0000001eu, + 0x00000ad1u, 0x00000ac6u, 0x00000063u, 0x0004007cu, 0x00000006u, 0x00000ad2u, 0x00000ad1u, 0x00060041u, + 0x00000048u, 0x00000b81u, 0x00000045u, 0x00000ab8u, 0x00000ad2u, 0x0004003du, 0x00000009u, 0x00000b82u, + 0x00000b81u, 0x0005008eu, 0x00000009u, 0x00000ad7u, 0x00000b7cu, 0x00000268u, 0x00050041u, 0x0000000fu, + 0x00000ad8u, 0x00000aa1u, 0x00000e80u, 0x0003003eu, 0x00000ad8u, 0x00000ad7u, 0x00050080u, 0x0000001eu, + 0x00000adau, 0x00000e80u, 0x00000063u, 0x0005008eu, 0x00000009u, 0x00000adcu, 0x00000b82u, 0x0000026eu, + 0x00050041u, 0x0000000fu, 0x00000addu, 0x00000aa1u, 0x00000adau, 0x0003003eu, 0x00000addu, 0x00000adcu, + 0x00050080u, 0x0000001eu, 0x00000ae0u, 0x00000e80u, 0x00000067u, 0x000200f9u, 0x00000abbu, 0x000200f8u, + 0x00000ae1u, 0x000200f9u, 0x00000ae2u, 0x000200f8u, 0x00000ae2u, 0x000700f5u, 0x0000001eu, 0x00000e81u, + 0x00000067u, 0x00000ae1u, 0x00000af8u, 0x00000ae6u, 0x000500b1u, 0x00000016u, 0x00000ae5u, 0x00000e81u, + 0x0000027au, 0x000400f6u, 0x00000af9u, 0x00000ae6u, 0x00000000u, 0x000400fau, 0x00000ae5u, 0x00000ae6u, + 0x00000af9u, 0x000200f8u, 0x00000ae6u, 0x00050082u, 0x0000001eu, 0x00000ae9u, 0x00000e81u, 0x00000063u, + 0x00050041u, 0x0000000fu, 0x00000aeau, 0x00000aa1u, 0x00000ae9u, 0x0004003du, 0x00000009u, 0x00000aebu, + 0x00000aeau, 0x00050080u, 0x0000001eu, 0x00000aedu, 0x00000e81u, 0x00000063u, 0x00050041u, 0x0000000fu, + 0x00000aeeu, 0x00000aa1u, 0x00000aedu, 0x0004003du, 0x00000009u, 0x00000aefu, 0x00000aeeu, 0x00050081u, + 0x00000009u, 0x00000af0u, 0x00000aebu, 0x00000aefu, 0x0005008eu, 0x00000009u, 0x00000af1u, 0x00000af0u, + 0x0000027du, 0x00050041u, 0x0000000fu, 0x00000af2u, 0x00000aa1u, 0x00000e81u, 0x0004003du, 0x00000009u, + 0x00000af3u, 0x00000af2u, 0x00050083u, 0x00000009u, 0x00000af4u, 0x00000af3u, 0x00000af1u, 0x0003003eu, + 0x00000af2u, 0x00000af4u, 0x00050080u, 0x0000001eu, 0x00000af8u, 0x00000e81u, 0x00000067u, 0x000200f9u, + 0x00000ae2u, 0x000200f8u, 0x00000af9u, 0x000200f9u, 0x00000afau, 0x000200f8u, 0x00000afau, 0x000700f5u, + 0x0000001eu, 0x00000e82u, 0x0000006au, 0x00000af9u, 0x00000b10u, 0x00000afeu, 0x000500b1u, 0x00000016u, + 0x00000afdu, 0x00000e82u, 0x00000295u, 0x000400f6u, 0x00000b11u, 0x00000afeu, 0x00000000u, 0x000400fau, + 0x00000afdu, 0x00000afeu, 0x00000b11u, 0x000200f8u, 0x00000afeu, 0x00050082u, 0x0000001eu, 0x00000b01u, + 0x00000e82u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000b02u, 0x00000aa1u, 0x00000b01u, 0x0004003du, + 0x00000009u, 0x00000b03u, 0x00000b02u, 0x00050080u, 0x0000001eu, 0x00000b05u, 0x00000e82u, 0x00000063u, + 0x00050041u, 0x0000000fu, 0x00000b06u, 0x00000aa1u, 0x00000b05u, 0x0004003du, 0x00000009u, 0x00000b07u, + 0x00000b06u, 0x00050081u, 0x00000009u, 0x00000b08u, 0x00000b03u, 0x00000b07u, 0x0005008eu, 0x00000009u, + 0x00000b09u, 0x00000b08u, 0x00000298u, 0x00050041u, 0x0000000fu, 0x00000b0au, 0x00000aa1u, 0x00000e82u, + 0x0004003du, 0x00000009u, 0x00000b0bu, 0x00000b0au, 0x00050083u, 0x00000009u, 0x00000b0cu, 0x00000b0bu, + 0x00000b09u, 0x0003003eu, 0x00000b0au, 0x00000b0cu, 0x00050080u, 0x0000001eu, 0x00000b10u, 0x00000e82u, + 0x00000067u, 0x000200f9u, 0x00000afau, 0x000200f8u, 0x00000b11u, 0x000200f9u, 0x00000b12u, 0x000200f8u, + 0x00000b12u, 0x000700f5u, 0x0000001eu, 0x00000e83u, 0x000002aau, 0x00000b11u, 0x00000b28u, 0x00000b16u, + 0x000500b1u, 0x00000016u, 0x00000b15u, 0x00000e83u, 0x000002b1u, 0x000400f6u, 0x00000b29u, 0x00000b16u, + 0x00000000u, 0x000400fau, 0x00000b15u, 0x00000b16u, 0x00000b29u, 0x000200f8u, 0x00000b16u, 0x00050082u, + 0x0000001eu, 0x00000b19u, 0x00000e83u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000b1au, 0x00000aa1u, + 0x00000b19u, 0x0004003du, 0x00000009u, 0x00000b1bu, 0x00000b1au, 0x00050080u, 0x0000001eu, 0x00000b1du, + 0x00000e83u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000b1eu, 0x00000aa1u, 0x00000b1du, 0x0004003du, + 0x00000009u, 0x00000b1fu, 0x00000b1eu, 0x00050081u, 0x00000009u, 0x00000b20u, 0x00000b1bu, 0x00000b1fu, + 0x0005008eu, 0x00000009u, 0x00000b21u, 0x00000b20u, 0x000002b4u, 0x00050041u, 0x0000000fu, 0x00000b22u, + 0x00000aa1u, 0x00000e83u, 0x0004003du, 0x00000009u, 0x00000b23u, 0x00000b22u, 0x00050083u, 0x00000009u, + 0x00000b24u, 0x00000b23u, 0x00000b21u, 0x0003003eu, 0x00000b22u, 0x00000b24u, 0x00050080u, 0x0000001eu, + 0x00000b28u, 0x00000e83u, 0x00000067u, 0x000200f9u, 0x00000b12u, 0x000200f8u, 0x00000b29u, 0x000200f9u, + 0x00000b2au, 0x000200f8u, 0x00000b2au, 0x000700f5u, 0x0000001eu, 0x00000e84u, 0x00000070u, 0x00000b29u, + 0x00000b40u, 0x00000b2eu, 0x000500b1u, 0x00000016u, 0x00000b2du, 0x00000e84u, 0x000002ccu, 0x000400f6u, + 0x00000b41u, 0x00000b2eu, 0x00000000u, 0x000400fau, 0x00000b2du, 0x00000b2eu, 0x00000b41u, 0x000200f8u, + 0x00000b2eu, 0x00050082u, 0x0000001eu, 0x00000b31u, 0x00000e84u, 0x00000063u, 0x00050041u, 0x0000000fu, + 0x00000b32u, 0x00000aa1u, 0x00000b31u, 0x0004003du, 0x00000009u, 0x00000b33u, 0x00000b32u, 0x00050080u, + 0x0000001eu, 0x00000b35u, 0x00000e84u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000b36u, 0x00000aa1u, + 0x00000b35u, 0x0004003du, 0x00000009u, 0x00000b37u, 0x00000b36u, 0x00050081u, 0x00000009u, 0x00000b38u, + 0x00000b33u, 0x00000b37u, 0x0005008eu, 0x00000009u, 0x00000b39u, 0x00000b38u, 0x000002cfu, 0x00050041u, + 0x0000000fu, 0x00000b3au, 0x00000aa1u, 0x00000e84u, 0x0004003du, 0x00000009u, 0x00000b3bu, 0x00000b3au, + 0x00050083u, 0x00000009u, 0x00000b3cu, 0x00000b3bu, 0x00000b39u, 0x0003003eu, 0x00000b3au, 0x00000b3cu, + 0x00050080u, 0x0000001eu, 0x00000b40u, 0x00000e84u, 0x00000067u, 0x000200f9u, 0x00000b2au, 0x000200f8u, + 0x00000b41u, 0x000400e0u, 0x000000fcu, 0x000000fcu, 0x00000234u, 0x000200f9u, 0x00000b42u, 0x000200f8u, + 0x00000b42u, 0x000700f5u, 0x0000001eu, 0x00000e85u, 0x00000067u, 0x00000b41u, 0x00000b75u, 0x00000b46u, + 0x000500b1u, 0x00000016u, 0x00000b45u, 0x00000e85u, 0x000002e7u, 0x000400f6u, 0x00000b76u, 0x00000b46u, + 0x00000000u, 0x000400fau, 0x00000b45u, 0x00000b46u, 0x00000b76u, 0x000200f8u, 0x00000b46u, 0x00050084u, + 0x0000001eu, 0x00000b48u, 0x00000067u, 0x00000e85u, 0x00050041u, 0x0000000fu, 0x00000b4au, 0x00000aa1u, + 0x00000b48u, 0x0004003du, 0x00000009u, 0x00000b4bu, 0x00000b4au, 0x00050080u, 0x0000001eu, 0x00000b4eu, + 0x00000b48u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000b4fu, 0x00000aa1u, 0x00000b4eu, 0x0004003du, + 0x00000009u, 0x00000b50u, 0x00000b4fu, 0x00050051u, 0x00000008u, 0x00000b52u, 0x00000b4bu, 0x00000000u, + 0x00050051u, 0x00000008u, 0x00000b54u, 0x00000b50u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000b55u, + 0x00000b52u, 0x00000b54u, 0x00050051u, 0x00000008u, 0x00000b57u, 0x00000b4bu, 0x00000001u, 0x00050051u, + 0x00000008u, 0x00000b59u, 0x00000b50u, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000b5au, 0x00000b57u, + 0x00000b59u, 0x000500c3u, 0x0000001eu, 0x00000b5du, 0x00000ab6u, 0x00000063u, 0x00050082u, 0x0000001eu, + 0x00000b5fu, 0x00000e85u, 0x00000067u, 0x00050080u, 0x0000001eu, 0x00000b60u, 0x00000b5du, 0x00000b5fu, + 0x0004007cu, 0x00000006u, 0x00000b62u, 0x00000b60u, 0x00050084u, 0x0000001eu, 0x00000b65u, 0x00000067u, + 0x00000ab9u, 0x0004007cu, 0x00000006u, 0x00000b67u, 0x00000b65u, 0x00060041u, 0x00000048u, 0x00000b87u, + 0x00000045u, 0x00000b62u, 0x00000b67u, 0x0003003eu, 0x00000b87u, 0x00000b55u, 0x00050080u, 0x0000001eu, + 0x00000b6fu, 0x00000b65u, 0x00000063u, 0x0004007cu, 0x00000006u, 0x00000b70u, 0x00000b6fu, 0x00060041u, + 0x00000048u, 0x00000b8cu, 0x00000045u, 0x00000b62u, 0x00000b70u, 0x0003003eu, 0x00000b8cu, 0x00000b5au, + 0x00050080u, 0x0000001eu, 0x00000b75u, 0x00000e85u, 0x00000063u, 0x000200f9u, 0x00000b42u, 0x000200f8u, + 0x00000b76u, 0x000500b0u, 0x00000016u, 0x00000416u, 0x00000411u, 0x00000415u, 0x00050089u, 0x00000006u, + 0x00000ba8u, 0x00000411u, 0x00000236u, 0x00050084u, 0x00000006u, 0x00000ba9u, 0x00000238u, 0x00000ba8u, + 0x0004007cu, 0x0000001eu, 0x00000baau, 0x00000ba9u, 0x00050086u, 0x00000006u, 0x00000bacu, 0x00000411u, + 0x00000236u, 0x00050080u, 0x00000006u, 0x00000bafu, 0x00000bacu, 0x0000019du, 0x0004007cu, 0x0000001eu, + 0x00000bb0u, 0x00000bafu, 0x000300f7u, 0x00000c3bu, 0x00000000u, 0x000400fau, 0x00000416u, 0x00000bb3u, + 0x00000c3bu, 0x000200f8u, 0x00000bb3u, 0x000200f9u, 0x00000bb4u, 0x000200f8u, 0x00000bb4u, 0x000700f5u, + 0x0000001eu, 0x00000e86u, 0x00000062u, 0x00000bb3u, 0x00000bd9u, 0x00000bb8u, 0x000500b1u, 0x00000016u, + 0x00000bb7u, 0x00000e86u, 0x000002ccu, 0x000400f6u, 0x00000bdau, 0x00000bb8u, 0x00000000u, 0x000400fau, + 0x00000bb7u, 0x00000bb8u, 0x00000bdau, 0x000200f8u, 0x00000bb8u, 0x00050080u, 0x0000001eu, 0x00000bbfu, + 0x00000baau, 0x00000e86u, 0x0004007cu, 0x00000006u, 0x00000bc1u, 0x00000bbfu, 0x00060041u, 0x00000048u, + 0x00000c78u, 0x00000045u, 0x00000bafu, 0x00000bc1u, 0x0004003du, 0x00000009u, 0x00000c79u, 0x00000c78u, + 0x00050080u, 0x0000001eu, 0x00000bcau, 0x00000bbfu, 0x00000063u, 0x0004007cu, 0x00000006u, 0x00000bcbu, + 0x00000bcau, 0x00060041u, 0x00000048u, 0x00000c7eu, 0x00000045u, 0x00000bafu, 0x00000bcbu, 0x0004003du, + 0x00000009u, 0x00000c7fu, 0x00000c7eu, 0x0005008eu, 0x00000009u, 0x00000bd0u, 0x00000c79u, 0x00000268u, + 0x00050041u, 0x0000000fu, 0x00000bd1u, 0x00000b95u, 0x00000e86u, 0x0003003eu, 0x00000bd1u, 0x00000bd0u, + 0x00050080u, 0x0000001eu, 0x00000bd3u, 0x00000e86u, 0x00000063u, 0x0005008eu, 0x00000009u, 0x00000bd5u, + 0x00000c7fu, 0x0000026eu, 0x00050041u, 0x0000000fu, 0x00000bd6u, 0x00000b95u, 0x00000bd3u, 0x0003003eu, + 0x00000bd6u, 0x00000bd5u, 0x00050080u, 0x0000001eu, 0x00000bd9u, 0x00000e86u, 0x00000067u, 0x000200f9u, + 0x00000bb4u, 0x000200f8u, 0x00000bdau, 0x000200f9u, 0x00000bdbu, 0x000200f8u, 0x00000bdbu, 0x000700f5u, + 0x0000001eu, 0x00000e87u, 0x00000067u, 0x00000bdau, 0x00000bf1u, 0x00000bdfu, 0x000500b1u, 0x00000016u, + 0x00000bdeu, 0x00000e87u, 0x0000036au, 0x000400f6u, 0x00000bf2u, 0x00000bdfu, 0x00000000u, 0x000400fau, + 0x00000bdeu, 0x00000bdfu, 0x00000bf2u, 0x000200f8u, 0x00000bdfu, 0x00050082u, 0x0000001eu, 0x00000be2u, + 0x00000e87u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000be3u, 0x00000b95u, 0x00000be2u, 0x0004003du, + 0x00000009u, 0x00000be4u, 0x00000be3u, 0x00050080u, 0x0000001eu, 0x00000be6u, 0x00000e87u, 0x00000063u, + 0x00050041u, 0x0000000fu, 0x00000be7u, 0x00000b95u, 0x00000be6u, 0x0004003du, 0x00000009u, 0x00000be8u, + 0x00000be7u, 0x00050081u, 0x00000009u, 0x00000be9u, 0x00000be4u, 0x00000be8u, 0x0005008eu, 0x00000009u, + 0x00000beau, 0x00000be9u, 0x0000027du, 0x00050041u, 0x0000000fu, 0x00000bebu, 0x00000b95u, 0x00000e87u, + 0x0004003du, 0x00000009u, 0x00000becu, 0x00000bebu, 0x00050083u, 0x00000009u, 0x00000bedu, 0x00000becu, + 0x00000beau, 0x0003003eu, 0x00000bebu, 0x00000bedu, 0x00050080u, 0x0000001eu, 0x00000bf1u, 0x00000e87u, + 0x00000067u, 0x000200f9u, 0x00000bdbu, 0x000200f8u, 0x00000bf2u, 0x000200f9u, 0x00000bf3u, 0x000200f8u, + 0x00000bf3u, 0x000700f5u, 0x0000001eu, 0x00000e88u, 0x0000006au, 0x00000bf2u, 0x00000c09u, 0x00000bf7u, + 0x000500b1u, 0x00000016u, 0x00000bf6u, 0x00000e88u, 0x00000384u, 0x000400f6u, 0x00000c0au, 0x00000bf7u, + 0x00000000u, 0x000400fau, 0x00000bf6u, 0x00000bf7u, 0x00000c0au, 0x000200f8u, 0x00000bf7u, 0x00050082u, + 0x0000001eu, 0x00000bfau, 0x00000e88u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000bfbu, 0x00000b95u, + 0x00000bfau, 0x0004003du, 0x00000009u, 0x00000bfcu, 0x00000bfbu, 0x00050080u, 0x0000001eu, 0x00000bfeu, + 0x00000e88u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000bffu, 0x00000b95u, 0x00000bfeu, 0x0004003du, + 0x00000009u, 0x00000c00u, 0x00000bffu, 0x00050081u, 0x00000009u, 0x00000c01u, 0x00000bfcu, 0x00000c00u, + 0x0005008eu, 0x00000009u, 0x00000c02u, 0x00000c01u, 0x00000298u, 0x00050041u, 0x0000000fu, 0x00000c03u, + 0x00000b95u, 0x00000e88u, 0x0004003du, 0x00000009u, 0x00000c04u, 0x00000c03u, 0x00050083u, 0x00000009u, + 0x00000c05u, 0x00000c04u, 0x00000c02u, 0x0003003eu, 0x00000c03u, 0x00000c05u, 0x00050080u, 0x0000001eu, + 0x00000c09u, 0x00000e88u, 0x00000067u, 0x000200f9u, 0x00000bf3u, 0x000200f8u, 0x00000c0au, 0x000200f9u, + 0x00000c0bu, 0x000200f8u, 0x00000c0bu, 0x000700f5u, 0x0000001eu, 0x00000e89u, 0x000002aau, 0x00000c0au, + 0x00000c21u, 0x00000c0fu, 0x000500b1u, 0x00000016u, 0x00000c0eu, 0x00000e89u, 0x0000039eu, 0x000400f6u, + 0x00000c22u, 0x00000c0fu, 0x00000000u, 0x000400fau, 0x00000c0eu, 0x00000c0fu, 0x00000c22u, 0x000200f8u, + 0x00000c0fu, 0x00050082u, 0x0000001eu, 0x00000c12u, 0x00000e89u, 0x00000063u, 0x00050041u, 0x0000000fu, + 0x00000c13u, 0x00000b95u, 0x00000c12u, 0x0004003du, 0x00000009u, 0x00000c14u, 0x00000c13u, 0x00050080u, + 0x0000001eu, 0x00000c16u, 0x00000e89u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000c17u, 0x00000b95u, + 0x00000c16u, 0x0004003du, 0x00000009u, 0x00000c18u, 0x00000c17u, 0x00050081u, 0x00000009u, 0x00000c19u, + 0x00000c14u, 0x00000c18u, 0x0005008eu, 0x00000009u, 0x00000c1au, 0x00000c19u, 0x000002b4u, 0x00050041u, + 0x0000000fu, 0x00000c1bu, 0x00000b95u, 0x00000e89u, 0x0004003du, 0x00000009u, 0x00000c1cu, 0x00000c1bu, + 0x00050083u, 0x00000009u, 0x00000c1du, 0x00000c1cu, 0x00000c1au, 0x0003003eu, 0x00000c1bu, 0x00000c1du, + 0x00050080u, 0x0000001eu, 0x00000c21u, 0x00000e89u, 0x00000067u, 0x000200f9u, 0x00000c0bu, 0x000200f8u, + 0x00000c22u, 0x000200f9u, 0x00000c23u, 0x000200f8u, 0x00000c23u, 0x000700f5u, 0x0000001eu, 0x00000e8au, + 0x00000070u, 0x00000c22u, 0x00000c39u, 0x00000c27u, 0x000500b1u, 0x00000016u, 0x00000c26u, 0x00000e8au, + 0x000003b8u, 0x000400f6u, 0x00000c3au, 0x00000c27u, 0x00000000u, 0x000400fau, 0x00000c26u, 0x00000c27u, + 0x00000c3au, 0x000200f8u, 0x00000c27u, 0x00050082u, 0x0000001eu, 0x00000c2au, 0x00000e8au, 0x00000063u, + 0x00050041u, 0x0000000fu, 0x00000c2bu, 0x00000b95u, 0x00000c2au, 0x0004003du, 0x00000009u, 0x00000c2cu, + 0x00000c2bu, 0x00050080u, 0x0000001eu, 0x00000c2eu, 0x00000e8au, 0x00000063u, 0x00050041u, 0x0000000fu, + 0x00000c2fu, 0x00000b95u, 0x00000c2eu, 0x0004003du, 0x00000009u, 0x00000c30u, 0x00000c2fu, 0x00050081u, + 0x00000009u, 0x00000c31u, 0x00000c2cu, 0x00000c30u, 0x0005008eu, 0x00000009u, 0x00000c32u, 0x00000c31u, + 0x000002cfu, 0x00050041u, 0x0000000fu, 0x00000c33u, 0x00000b95u, 0x00000e8au, 0x0004003du, 0x00000009u, + 0x00000c34u, 0x00000c33u, 0x00050083u, 0x00000009u, 0x00000c35u, 0x00000c34u, 0x00000c32u, 0x0003003eu, + 0x00000c33u, 0x00000c35u, 0x00050080u, 0x0000001eu, 0x00000c39u, 0x00000e8au, 0x00000067u, 0x000200f9u, + 0x00000c23u, 0x000200f8u, 0x00000c3au, 0x000200f9u, 0x00000c3bu, 0x000200f8u, 0x00000c3bu, 0x000400e0u, + 0x000000fcu, 0x000000fcu, 0x00000234u, 0x000300f7u, 0x00000c73u, 0x00000000u, 0x000400fau, 0x00000416u, + 0x00000c3du, 0x00000c73u, 0x000200f8u, 0x00000c3du, 0x000200f9u, 0x00000c3eu, 0x000200f8u, 0x00000c3eu, + 0x000700f5u, 0x0000001eu, 0x00000e8bu, 0x00000067u, 0x00000c3du, 0x00000c71u, 0x00000c42u, 0x000500b1u, + 0x00000016u, 0x00000c41u, 0x00000e8bu, 0x000002aau, 0x000400f6u, 0x00000c72u, 0x00000c42u, 0x00000000u, + 0x000400fau, 0x00000c41u, 0x00000c42u, 0x00000c72u, 0x000200f8u, 0x00000c42u, 0x00050084u, 0x0000001eu, + 0x00000c44u, 0x00000067u, 0x00000e8bu, 0x00050041u, 0x0000000fu, 0x00000c46u, 0x00000b95u, 0x00000c44u, + 0x0004003du, 0x00000009u, 0x00000c47u, 0x00000c46u, 0x00050080u, 0x0000001eu, 0x00000c4au, 0x00000c44u, + 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000c4bu, 0x00000b95u, 0x00000c4au, 0x0004003du, 0x00000009u, + 0x00000c4cu, 0x00000c4bu, 0x00050051u, 0x00000008u, 0x00000c4eu, 0x00000c47u, 0x00000000u, 0x00050051u, + 0x00000008u, 0x00000c50u, 0x00000c4cu, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000c51u, 0x00000c4eu, + 0x00000c50u, 0x00050051u, 0x00000008u, 0x00000c53u, 0x00000c47u, 0x00000001u, 0x00050051u, 0x00000008u, + 0x00000c55u, 0x00000c4cu, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000c56u, 0x00000c53u, 0x00000c55u, + 0x000500c3u, 0x0000001eu, 0x00000c59u, 0x00000baau, 0x00000063u, 0x00050082u, 0x0000001eu, 0x00000c5bu, + 0x00000e8bu, 0x00000067u, 0x00050080u, 0x0000001eu, 0x00000c5cu, 0x00000c59u, 0x00000c5bu, 0x0004007cu, + 0x00000006u, 0x00000c5eu, 0x00000c5cu, 0x00050084u, 0x0000001eu, 0x00000c61u, 0x00000067u, 0x00000bb0u, + 0x0004007cu, 0x00000006u, 0x00000c63u, 0x00000c61u, 0x00060041u, 0x00000048u, 0x00000c84u, 0x00000045u, + 0x00000c5eu, 0x00000c63u, 0x0003003eu, 0x00000c84u, 0x00000c51u, 0x00050080u, 0x0000001eu, 0x00000c6bu, + 0x00000c61u, 0x00000063u, 0x0004007cu, 0x00000006u, 0x00000c6cu, 0x00000c6bu, 0x00060041u, 0x00000048u, + 0x00000c89u, 0x00000045u, 0x00000c5eu, 0x00000c6cu, 0x0003003eu, 0x00000c89u, 0x00000c56u, 0x00050080u, + 0x0000001eu, 0x00000c71u, 0x00000e8bu, 0x00000063u, 0x000200f9u, 0x00000c3eu, 0x000200f8u, 0x00000c72u, + 0x000200f9u, 0x00000c73u, 0x000200f8u, 0x00000c73u, 0x000400e0u, 0x000000fcu, 0x000000fcu, 0x00000234u, + 0x000200f9u, 0x00000cacu, 0x000200f8u, 0x00000cacu, 0x000700f5u, 0x0000001eu, 0x00000e8cu, 0x00000062u, + 0x00000c73u, 0x00000cd1u, 0x00000cb0u, 0x000500b1u, 0x00000016u, 0x00000cafu, 0x00000e8cu, 0x00000145u, + 0x000400f6u, 0x00000cd2u, 0x00000cb0u, 0x00000000u, 0x000400fau, 0x00000cafu, 0x00000cb0u, 0x00000cd2u, + 0x000200f8u, 0x00000cb0u, 0x00050080u, 0x0000001eu, 0x00000cb7u, 0x00000ab6u, 0x00000e8cu, 0x0004007cu, + 0x00000006u, 0x00000cb9u, 0x00000cb7u, 0x00060041u, 0x00000048u, 0x00000d6cu, 0x00000045u, 0x00000ab8u, + 0x00000cb9u, 0x0004003du, 0x00000009u, 0x00000d6du, 0x00000d6cu, 0x00050080u, 0x0000001eu, 0x00000cc2u, + 0x00000cb7u, 0x00000063u, 0x0004007cu, 0x00000006u, 0x00000cc3u, 0x00000cc2u, 0x00060041u, 0x00000048u, + 0x00000d72u, 0x00000045u, 0x00000ab8u, 0x00000cc3u, 0x0004003du, 0x00000009u, 0x00000d73u, 0x00000d72u, + 0x0005008eu, 0x00000009u, 0x00000cc8u, 0x00000d6du, 0x00000268u, 0x00050041u, 0x0000000fu, 0x00000cc9u, + 0x00000c92u, 0x00000e8cu, 0x0003003eu, 0x00000cc9u, 0x00000cc8u, 0x00050080u, 0x0000001eu, 0x00000ccbu, + 0x00000e8cu, 0x00000063u, 0x0005008eu, 0x00000009u, 0x00000ccdu, 0x00000d73u, 0x0000026eu, 0x00050041u, + 0x0000000fu, 0x00000cceu, 0x00000c92u, 0x00000ccbu, 0x0003003eu, 0x00000cceu, 0x00000ccdu, 0x00050080u, + 0x0000001eu, 0x00000cd1u, 0x00000e8cu, 0x00000067u, 0x000200f9u, 0x00000cacu, 0x000200f8u, 0x00000cd2u, + 0x000200f9u, 0x00000cd3u, 0x000200f8u, 0x00000cd3u, 0x000700f5u, 0x0000001eu, 0x00000e8du, 0x00000067u, + 0x00000cd2u, 0x00000ce9u, 0x00000cd7u, 0x000500b1u, 0x00000016u, 0x00000cd6u, 0x00000e8du, 0x0000027au, + 0x000400f6u, 0x00000ceau, 0x00000cd7u, 0x00000000u, 0x000400fau, 0x00000cd6u, 0x00000cd7u, 0x00000ceau, + 0x000200f8u, 0x00000cd7u, 0x00050082u, 0x0000001eu, 0x00000cdau, 0x00000e8du, 0x00000063u, 0x00050041u, + 0x0000000fu, 0x00000cdbu, 0x00000c92u, 0x00000cdau, 0x0004003du, 0x00000009u, 0x00000cdcu, 0x00000cdbu, + 0x00050080u, 0x0000001eu, 0x00000cdeu, 0x00000e8du, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000cdfu, + 0x00000c92u, 0x00000cdeu, 0x0004003du, 0x00000009u, 0x00000ce0u, 0x00000cdfu, 0x00050081u, 0x00000009u, + 0x00000ce1u, 0x00000cdcu, 0x00000ce0u, 0x0005008eu, 0x00000009u, 0x00000ce2u, 0x00000ce1u, 0x0000027du, + 0x00050041u, 0x0000000fu, 0x00000ce3u, 0x00000c92u, 0x00000e8du, 0x0004003du, 0x00000009u, 0x00000ce4u, + 0x00000ce3u, 0x00050083u, 0x00000009u, 0x00000ce5u, 0x00000ce4u, 0x00000ce2u, 0x0003003eu, 0x00000ce3u, + 0x00000ce5u, 0x00050080u, 0x0000001eu, 0x00000ce9u, 0x00000e8du, 0x00000067u, 0x000200f9u, 0x00000cd3u, + 0x000200f8u, 0x00000ceau, 0x000200f9u, 0x00000cebu, 0x000200f8u, 0x00000cebu, 0x000700f5u, 0x0000001eu, + 0x00000e8eu, 0x0000006au, 0x00000ceau, 0x00000d01u, 0x00000cefu, 0x000500b1u, 0x00000016u, 0x00000ceeu, + 0x00000e8eu, 0x00000295u, 0x000400f6u, 0x00000d02u, 0x00000cefu, 0x00000000u, 0x000400fau, 0x00000ceeu, + 0x00000cefu, 0x00000d02u, 0x000200f8u, 0x00000cefu, 0x00050082u, 0x0000001eu, 0x00000cf2u, 0x00000e8eu, + 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000cf3u, 0x00000c92u, 0x00000cf2u, 0x0004003du, 0x00000009u, + 0x00000cf4u, 0x00000cf3u, 0x00050080u, 0x0000001eu, 0x00000cf6u, 0x00000e8eu, 0x00000063u, 0x00050041u, + 0x0000000fu, 0x00000cf7u, 0x00000c92u, 0x00000cf6u, 0x0004003du, 0x00000009u, 0x00000cf8u, 0x00000cf7u, + 0x00050081u, 0x00000009u, 0x00000cf9u, 0x00000cf4u, 0x00000cf8u, 0x0005008eu, 0x00000009u, 0x00000cfau, + 0x00000cf9u, 0x00000298u, 0x00050041u, 0x0000000fu, 0x00000cfbu, 0x00000c92u, 0x00000e8eu, 0x0004003du, + 0x00000009u, 0x00000cfcu, 0x00000cfbu, 0x00050083u, 0x00000009u, 0x00000cfdu, 0x00000cfcu, 0x00000cfau, + 0x0003003eu, 0x00000cfbu, 0x00000cfdu, 0x00050080u, 0x0000001eu, 0x00000d01u, 0x00000e8eu, 0x00000067u, + 0x000200f9u, 0x00000cebu, 0x000200f8u, 0x00000d02u, 0x000200f9u, 0x00000d03u, 0x000200f8u, 0x00000d03u, + 0x000700f5u, 0x0000001eu, 0x00000e8fu, 0x000002aau, 0x00000d02u, 0x00000d19u, 0x00000d07u, 0x000500b1u, + 0x00000016u, 0x00000d06u, 0x00000e8fu, 0x000002b1u, 0x000400f6u, 0x00000d1au, 0x00000d07u, 0x00000000u, + 0x000400fau, 0x00000d06u, 0x00000d07u, 0x00000d1au, 0x000200f8u, 0x00000d07u, 0x00050082u, 0x0000001eu, + 0x00000d0au, 0x00000e8fu, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000d0bu, 0x00000c92u, 0x00000d0au, + 0x0004003du, 0x00000009u, 0x00000d0cu, 0x00000d0bu, 0x00050080u, 0x0000001eu, 0x00000d0eu, 0x00000e8fu, + 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000d0fu, 0x00000c92u, 0x00000d0eu, 0x0004003du, 0x00000009u, + 0x00000d10u, 0x00000d0fu, 0x00050081u, 0x00000009u, 0x00000d11u, 0x00000d0cu, 0x00000d10u, 0x0005008eu, + 0x00000009u, 0x00000d12u, 0x00000d11u, 0x000002b4u, 0x00050041u, 0x0000000fu, 0x00000d13u, 0x00000c92u, + 0x00000e8fu, 0x0004003du, 0x00000009u, 0x00000d14u, 0x00000d13u, 0x00050083u, 0x00000009u, 0x00000d15u, + 0x00000d14u, 0x00000d12u, 0x0003003eu, 0x00000d13u, 0x00000d15u, 0x00050080u, 0x0000001eu, 0x00000d19u, + 0x00000e8fu, 0x00000067u, 0x000200f9u, 0x00000d03u, 0x000200f8u, 0x00000d1au, 0x000200f9u, 0x00000d1bu, + 0x000200f8u, 0x00000d1bu, 0x000700f5u, 0x0000001eu, 0x00000e90u, 0x00000070u, 0x00000d1au, 0x00000d31u, + 0x00000d1fu, 0x000500b1u, 0x00000016u, 0x00000d1eu, 0x00000e90u, 0x000002ccu, 0x000400f6u, 0x00000d32u, + 0x00000d1fu, 0x00000000u, 0x000400fau, 0x00000d1eu, 0x00000d1fu, 0x00000d32u, 0x000200f8u, 0x00000d1fu, + 0x00050082u, 0x0000001eu, 0x00000d22u, 0x00000e90u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000d23u, + 0x00000c92u, 0x00000d22u, 0x0004003du, 0x00000009u, 0x00000d24u, 0x00000d23u, 0x00050080u, 0x0000001eu, + 0x00000d26u, 0x00000e90u, 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000d27u, 0x00000c92u, 0x00000d26u, + 0x0004003du, 0x00000009u, 0x00000d28u, 0x00000d27u, 0x00050081u, 0x00000009u, 0x00000d29u, 0x00000d24u, + 0x00000d28u, 0x0005008eu, 0x00000009u, 0x00000d2au, 0x00000d29u, 0x000002cfu, 0x00050041u, 0x0000000fu, + 0x00000d2bu, 0x00000c92u, 0x00000e90u, 0x0004003du, 0x00000009u, 0x00000d2cu, 0x00000d2bu, 0x00050083u, + 0x00000009u, 0x00000d2du, 0x00000d2cu, 0x00000d2au, 0x0003003eu, 0x00000d2bu, 0x00000d2du, 0x00050080u, + 0x0000001eu, 0x00000d31u, 0x00000e90u, 0x00000067u, 0x000200f9u, 0x00000d1bu, 0x000200f8u, 0x00000d32u, + 0x000400e0u, 0x000000fcu, 0x000000fcu, 0x00000234u, 0x000200f9u, 0x00000d33u, 0x000200f8u, 0x00000d33u, + 0x000700f5u, 0x0000001eu, 0x00000e91u, 0x00000067u, 0x00000d32u, 0x00000d66u, 0x00000d37u, 0x000500b1u, + 0x00000016u, 0x00000d36u, 0x00000e91u, 0x000002e7u, 0x000400f6u, 0x00000d67u, 0x00000d37u, 0x00000000u, + 0x000400fau, 0x00000d36u, 0x00000d37u, 0x00000d67u, 0x000200f8u, 0x00000d37u, 0x00050084u, 0x0000001eu, + 0x00000d39u, 0x00000067u, 0x00000e91u, 0x00050041u, 0x0000000fu, 0x00000d3bu, 0x00000c92u, 0x00000d39u, + 0x0004003du, 0x00000009u, 0x00000d3cu, 0x00000d3bu, 0x00050080u, 0x0000001eu, 0x00000d3fu, 0x00000d39u, + 0x00000063u, 0x00050041u, 0x0000000fu, 0x00000d40u, 0x00000c92u, 0x00000d3fu, 0x0004003du, 0x00000009u, + 0x00000d41u, 0x00000d40u, 0x00050051u, 0x00000008u, 0x00000d43u, 0x00000d3cu, 0x00000000u, 0x00050051u, + 0x00000008u, 0x00000d45u, 0x00000d41u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000d46u, 0x00000d43u, + 0x00000d45u, 0x00050051u, 0x00000008u, 0x00000d48u, 0x00000d3cu, 0x00000001u, 0x00050051u, 0x00000008u, + 0x00000d4au, 0x00000d41u, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000d4bu, 0x00000d48u, 0x00000d4au, + 0x000500c3u, 0x0000001eu, 0x00000d4eu, 0x00000ab6u, 0x00000063u, 0x00050082u, 0x0000001eu, 0x00000d50u, + 0x00000e91u, 0x00000067u, 0x00050080u, 0x0000001eu, 0x00000d51u, 0x00000d4eu, 0x00000d50u, 0x0004007cu, + 0x00000006u, 0x00000d53u, 0x00000d51u, 0x00050084u, 0x0000001eu, 0x00000d56u, 0x00000067u, 0x00000ab9u, + 0x0004007cu, 0x00000006u, 0x00000d58u, 0x00000d56u, 0x00060041u, 0x00000048u, 0x00000d78u, 0x00000045u, + 0x00000d53u, 0x00000d58u, 0x0003003eu, 0x00000d78u, 0x00000d46u, 0x00050080u, 0x0000001eu, 0x00000d60u, + 0x00000d56u, 0x00000063u, 0x0004007cu, 0x00000006u, 0x00000d61u, 0x00000d60u, 0x00060041u, 0x00000048u, + 0x00000d7du, 0x00000045u, 0x00000d53u, 0x00000d61u, 0x0003003eu, 0x00000d7du, 0x00000d4bu, 0x00050080u, + 0x0000001eu, 0x00000d66u, 0x00000e91u, 0x00000063u, 0x000200f9u, 0x00000d33u, 0x000200f8u, 0x00000d67u, + 0x000400e0u, 0x000000fcu, 0x000000fcu, 0x00000234u, 0x000200f9u, 0x00000422u, 0x000200f8u, 0x00000422u, + 0x000700f5u, 0x0000001eu, 0x00000e92u, 0x00000560u, 0x00000d67u, 0x00000465u, 0x00000425u, 0x000500b1u, + 0x00000016u, 0x00000428u, 0x00000e92u, 0x00000145u, 0x000400f6u, 0x00000424u, 0x00000425u, 0x00000000u, + 0x000400fau, 0x00000428u, 0x00000423u, 0x00000424u, 0x000200f8u, 0x00000423u, 0x000200f9u, 0x0000042cu, + 0x000200f8u, 0x0000042cu, 0x000700f5u, 0x0000001eu, 0x00000e93u, 0x0000055eu, 0x00000423u, 0x00000463u, + 0x0000042fu, 0x000500b1u, 0x00000016u, 0x00000433u, 0x00000e93u, 0x00000432u, 0x000400f6u, 0x0000042eu, + 0x0000042fu, 0x00000000u, 0x000400fau, 0x00000433u, 0x0000042du, 0x0000042eu, 0x000200f8u, 0x0000042du, + 0x0004007cu, 0x00000006u, 0x00000436u, 0x00000e92u, 0x0004007cu, 0x00000006u, 0x00000438u, 0x00000e93u, + 0x00060041u, 0x00000048u, 0x00000d99u, 0x00000045u, 0x00000436u, 0x00000438u, 0x0004003du, 0x00000009u, + 0x00000d9au, 0x00000d99u, 0x000300f7u, 0x0000043eu, 0x00000000u, 0x000400fau, 0x0000043cu, 0x0000043du, + 0x0000043eu, 0x000200f8u, 0x0000043du, 0x00050081u, 0x00000009u, 0x00000442u, 0x00000d9au, 0x00000e9eu, + 0x000200f9u, 0x0000043eu, 0x000200f8u, 0x0000043eu, 0x000700f5u, 0x00000009u, 0x00000e97u, 0x00000d9au, + 0x0000042du, 0x00000442u, 0x0000043du, 0x0004003du, 0x00000443u, 0x00000446u, 0x00000445u, 0x00050084u, + 0x0000001eu, 0x00000448u, 0x00000067u, 0x00000e92u, 0x00050050u, 0x0000001fu, 0x0000044bu, 0x00000448u, + 0x00000e93u, 0x0007004fu, 0x00000141u, 0x0000044du, 0x000004a6u, 0x000004a6u, 0x00000001u, 0x00000000u, + 0x0004007cu, 0x0000001fu, 0x0000044eu, 0x0000044du, 0x00050084u, 0x0000001fu, 0x00000450u, 0x00000e9fu, + 0x0000044eu, 0x00050080u, 0x0000001fu, 0x00000451u, 0x0000044bu, 0x00000450u, 0x0009004fu, 0x0000002cu, + 0x00000453u, 0x00000e97u, 0x00000e97u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00040063u, + 0x00000446u, 0x00000451u, 0x00000453u, 0x0004003du, 0x00000443u, 0x00000454u, 0x00000445u, 0x00050080u, + 0x0000001eu, 0x00000457u, 0x00000448u, 0x00000063u, 0x00050050u, 0x0000001fu, 0x00000459u, 0x00000457u, + 0x00000e93u, 0x00050080u, 0x0000001fu, 0x0000045fu, 0x00000459u, 0x00000450u, 0x0009004fu, 0x0000002cu, + 0x00000461u, 0x00000e97u, 0x00000e97u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00040063u, + 0x00000454u, 0x0000045fu, 0x00000461u, 0x000200f9u, 0x0000042fu, 0x000200f8u, 0x0000042fu, 0x00050080u, + 0x0000001eu, 0x00000463u, 0x00000e93u, 0x000003b8u, 0x000200f9u, 0x0000042cu, 0x000200f8u, 0x0000042eu, + 0x000200f9u, 0x00000425u, 0x000200f8u, 0x00000425u, 0x00050080u, 0x0000001eu, 0x00000465u, 0x00000e92u, + 0x000003b8u, 0x000200f9u, 0x00000422u, 0x000200f8u, 0x00000424u, 0x000100fdu, 0x00010038u, 0x07230203u, + 0x00010300u, 0x000d000bu, 0x00000ebeu, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, 0x00000009u, + 0x00020011u, 0x00000038u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, + 0x0003000eu, 0x00000000u, 0x00000001u, 0x0007000fu, 0x00000005u, 0x00000004u, 0x6e69616du, 0x00000000u, + 0x00000143u, 0x00000420u, 0x00060010u, 0x00000004u, 0x00000011u, 0x00000040u, 0x00000001u, 0x00000001u, + 0x00030047u, 0x00000094u, 0x00000002u, 0x00050048u, 0x00000094u, 0x00000000u, 0x00000023u, 0x00000000u, + 0x00050048u, 0x00000094u, 0x00000001u, 0x00000023u, 0x00000008u, 0x00040047u, 0x00000143u, 0x0000000bu, + 0x0000001au, 0x00030047u, 0x0000015du, 0x00000000u, 0x00040047u, 0x0000015du, 0x00000021u, 0x00000000u, + 0x00040047u, 0x0000015du, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000420u, 0x0000000bu, 0x0000001du, + 0x00040047u, 0x0000044cu, 0x00000001u, 0x00000000u, 0x00030047u, 0x00000455u, 0x00000000u, 0x00030047u, + 0x00000455u, 0x00000019u, 0x00040047u, 0x00000455u, 0x00000021u, 0x00000001u, 0x00040047u, 0x00000455u, + 0x00000022u, 0x00000000u, 0x00030047u, 0x00000456u, 0x00000000u, 0x00030047u, 0x00000465u, 0x00000000u, + 0x00040047u, 0x00000479u, 0x0000000bu, 0x00000019u, 0x00030047u, 0x000004c5u, 0x00000000u, 0x00030047u, + 0x000004cbu, 0x00000000u, 0x00030047u, 0x000004ceu, 0x00000000u, 0x00030047u, 0x000004d4u, 0x00000000u, + 0x00030047u, 0x000004d7u, 0x00000000u, 0x00030047u, 0x000004ddu, 0x00000000u, 0x00030047u, 0x000004e0u, + 0x00000000u, 0x00030047u, 0x000004e6u, 0x00000000u, 0x00030047u, 0x000004fdu, 0x00000000u, 0x00030047u, + 0x00000505u, 0x00000000u, 0x00030047u, 0x00000508u, 0x00000000u, 0x00030047u, 0x00000510u, 0x00000000u, + 0x00030047u, 0x00000513u, 0x00000000u, 0x00030047u, 0x0000051bu, 0x00000000u, 0x00030047u, 0x0000051eu, + 0x00000000u, 0x00030047u, 0x00000526u, 0x00000000u, 0x00030047u, 0x00000536u, 0x00000000u, 0x00030047u, + 0x0000053eu, 0x00000000u, 0x00030047u, 0x00000541u, 0x00000000u, 0x00030047u, 0x00000549u, 0x00000000u, + 0x00030047u, 0x0000054cu, 0x00000000u, 0x00030047u, 0x00000554u, 0x00000000u, 0x00030047u, 0x00000557u, + 0x00000000u, 0x00030047u, 0x0000055fu, 0x00000000u, 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, + 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, 0x00000000u, 0x00030016u, 0x00000008u, 0x00000010u, + 0x00040017u, 0x00000009u, 0x00000008u, 0x00000002u, 0x00040020u, 0x0000000fu, 0x00000007u, 0x00000009u, + 0x00020014u, 0x00000016u, 0x00040017u, 0x00000017u, 0x00000016u, 0x00000002u, 0x00040015u, 0x0000001eu, + 0x00000020u, 0x00000001u, 0x00040017u, 0x0000001fu, 0x0000001eu, 0x00000002u, 0x00030016u, 0x00000026u, + 0x00000020u, 0x00040017u, 0x00000027u, 0x00000026u, 0x00000002u, 0x00040017u, 0x0000002eu, 0x00000008u, + 0x00000004u, 0x0004002bu, 0x00000006u, 0x00000042u, 0x00000029u, 0x0004001cu, 0x00000043u, 0x00000009u, + 0x00000042u, 0x0004002bu, 0x00000006u, 0x00000044u, 0x00000014u, 0x0004001cu, 0x00000045u, 0x00000043u, + 0x00000044u, 0x00040020u, 0x00000046u, 0x00000004u, 0x00000045u, 0x0004003bu, 0x00000046u, 0x00000047u, + 0x00000004u, 0x00040020u, 0x0000004au, 0x00000004u, 0x00000009u, 0x0004002bu, 0x00000006u, 0x00000059u, + 0x00000001u, 0x0004002bu, 0x0000001eu, 0x00000064u, 0x00000000u, 0x0004002bu, 0x0000001eu, 0x00000065u, + 0x00000001u, 0x0004002bu, 0x0000001eu, 0x00000069u, 0x00000002u, 0x0004002bu, 0x0000001eu, 0x0000006cu, + 0x00000003u, 0x0004002bu, 0x0000001eu, 0x00000072u, 0x00000005u, 0x0005002cu, 0x0000001fu, 0x00000082u, + 0x00000064u, 0x00000064u, 0x0005002cu, 0x0000001fu, 0x00000087u, 0x00000065u, 0x00000065u, 0x0004001eu, + 0x00000094u, 0x0000001fu, 0x00000027u, 0x00040020u, 0x00000095u, 0x00000009u, 0x00000094u, 0x0004003bu, + 0x00000095u, 0x00000096u, 0x00000009u, 0x00040020u, 0x00000097u, 0x00000009u, 0x0000001fu, 0x00040020u, + 0x000000a5u, 0x00000009u, 0x00000027u, 0x0004002bu, 0x00000006u, 0x000000ffu, 0x00000002u, 0x00040017u, + 0x00000141u, 0x00000006u, 0x00000003u, 0x00040020u, 0x00000142u, 0x00000001u, 0x00000141u, 0x0004003bu, + 0x00000142u, 0x00000143u, 0x00000001u, 0x00040017u, 0x00000144u, 0x00000006u, 0x00000002u, 0x0004002bu, + 0x0000001eu, 0x00000148u, 0x00000010u, 0x0005002cu, 0x0000001fu, 0x00000149u, 0x00000148u, 0x00000148u, + 0x00090019u, 0x0000015au, 0x00000026u, 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000001u, + 0x00000000u, 0x0003001bu, 0x0000015bu, 0x0000015au, 0x00040020u, 0x0000015cu, 0x00000000u, 0x0000015bu, + 0x0004003bu, 0x0000015cu, 0x0000015du, 0x00000000u, 0x0004002bu, 0x00000026u, 0x00000165u, 0x00000000u, + 0x00040017u, 0x00000166u, 0x00000026u, 0x00000003u, 0x00040017u, 0x0000016au, 0x00000026u, 0x00000004u, + 0x0003002au, 0x00000016u, 0x00000170u, 0x0004002bu, 0x00000026u, 0x00000176u, 0x40000000u, 0x0004002bu, + 0x00000026u, 0x00000184u, 0x3f800000u, 0x0004002bu, 0x00000026u, 0x00000192u, 0x40400000u, 0x0004002bu, + 0x00000006u, 0x000001a5u, 0x00000010u, 0x0004002bu, 0x0000001eu, 0x000001b2u, 0x00000014u, 0x0004002bu, + 0x00000006u, 0x00000244u, 0x00000108u, 0x0004002bu, 0x00000006u, 0x00000246u, 0x00000008u, 0x0004002bu, + 0x00000006u, 0x00000248u, 0x00000004u, 0x0004001cu, 0x00000272u, 0x00000009u, 0x000001a5u, 0x00040020u, + 0x00000273u, 0x00000007u, 0x00000272u, 0x0004002bu, 0x00000008u, 0x00000278u, 0x00003cebu, 0x0004002bu, + 0x00000008u, 0x0000027eu, 0x00003a80u, 0x0004002bu, 0x0000001eu, 0x0000028au, 0x0000000fu, 0x0004002bu, + 0x00000008u, 0x0000028du, 0x00003718u, 0x0004002bu, 0x0000001eu, 0x000002a5u, 0x0000000eu, 0x0004002bu, + 0x00000008u, 0x000002a8u, 0x00003b10u, 0x0004002bu, 0x0000001eu, 0x000002bau, 0x00000004u, 0x0004002bu, + 0x0000001eu, 0x000002c1u, 0x0000000du, 0x0004002bu, 0x00000008u, 0x000002c4u, 0x0000aac8u, 0x0004002bu, + 0x0000001eu, 0x000002dcu, 0x0000000cu, 0x0004002bu, 0x00000008u, 0x000002dfu, 0x0000be58u, 0x0004002bu, + 0x0000001eu, 0x000002f7u, 0x00000006u, 0x0004002bu, 0x00000006u, 0x00000363u, 0x0000000cu, 0x0004001cu, + 0x00000364u, 0x00000009u, 0x00000363u, 0x00040020u, 0x00000365u, 0x00000007u, 0x00000364u, 0x0004002bu, + 0x0000001eu, 0x0000037au, 0x0000000bu, 0x0004002bu, 0x0000001eu, 0x00000394u, 0x0000000au, 0x0004002bu, + 0x0000001eu, 0x000003aeu, 0x00000009u, 0x0004002bu, 0x0000001eu, 0x000003c8u, 0x00000008u, 0x00040020u, + 0x0000041fu, 0x00000001u, 0x00000006u, 0x0004003bu, 0x0000041fu, 0x00000420u, 0x00000001u, 0x0004002bu, + 0x00000006u, 0x00000425u, 0x00000020u, 0x0004002bu, 0x0000001eu, 0x00000442u, 0x00000020u, 0x00030031u, + 0x00000016u, 0x0000044cu, 0x0004002bu, 0x00000008u, 0x0000044fu, 0x00003800u, 0x00090019u, 0x00000453u, + 0x00000026u, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000002u, 0x00000000u, 0x00040020u, + 0x00000454u, 0x00000000u, 0x00000453u, 0x0004003bu, 0x00000454u, 0x00000455u, 0x00000000u, 0x0004002bu, + 0x00000006u, 0x00000478u, 0x00000040u, 0x0006002cu, 0x00000141u, 0x00000479u, 0x00000478u, 0x00000059u, + 0x00000059u, 0x0005002cu, 0x0000001fu, 0x00000eb6u, 0x00000069u, 0x00000069u, 0x0005002cu, 0x00000009u, + 0x00000ebcu, 0x0000044fu, 0x0000044fu, 0x0005002cu, 0x0000001fu, 0x00000ebdu, 0x00000442u, 0x00000442u, + 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, + 0x00000273u, 0x00000cb0u, 0x00000007u, 0x0004003bu, 0x00000365u, 0x00000bb3u, 0x00000007u, 0x0004003bu, + 0x00000273u, 0x00000abfu, 0x00000007u, 0x0004003du, 0x00000006u, 0x00000421u, 0x00000420u, 0x0004003du, + 0x00000141u, 0x000004b8u, 0x00000143u, 0x0007004fu, 0x00000144u, 0x000004b9u, 0x000004b8u, 0x000004b8u, + 0x00000000u, 0x00000001u, 0x0004007cu, 0x0000001fu, 0x000004bau, 0x000004b9u, 0x00050084u, 0x0000001fu, + 0x000004bbu, 0x000004bau, 0x00000149u, 0x00050082u, 0x0000001fu, 0x000004bdu, 0x000004bbu, 0x00000eb6u, + 0x000600cbu, 0x00000006u, 0x0000056eu, 0x00000421u, 0x00000064u, 0x00000065u, 0x000600cbu, 0x00000006u, + 0x00000570u, 0x00000421u, 0x00000065u, 0x00000069u, 0x000600cbu, 0x00000006u, 0x00000572u, 0x00000421u, + 0x0000006cu, 0x00000069u, 0x000500c4u, 0x00000006u, 0x00000573u, 0x00000572u, 0x00000065u, 0x000500c5u, + 0x00000006u, 0x00000575u, 0x0000056eu, 0x00000573u, 0x000600cbu, 0x00000006u, 0x00000577u, 0x00000421u, + 0x00000072u, 0x00000065u, 0x000500c4u, 0x00000006u, 0x00000578u, 0x00000577u, 0x00000069u, 0x000500c5u, + 0x00000006u, 0x0000057au, 0x00000570u, 0x00000578u, 0x0004007cu, 0x0000001eu, 0x0000057cu, 0x0000057au, + 0x0004007cu, 0x0000001eu, 0x0000057eu, 0x00000575u, 0x00050050u, 0x0000001fu, 0x0000057fu, 0x0000057cu, + 0x0000057eu, 0x00050084u, 0x0000001fu, 0x000004c1u, 0x00000eb6u, 0x0000057fu, 0x00050080u, 0x0000001fu, + 0x000004c4u, 0x000004bdu, 0x000004c1u, 0x0004003du, 0x0000015bu, 0x000004c5u, 0x0000015du, 0x000500b1u, + 0x00000017u, 0x0000058bu, 0x000004c4u, 0x00000082u, 0x00050051u, 0x00000016u, 0x000005acu, 0x0000058bu, + 0x00000000u, 0x00050051u, 0x00000016u, 0x000005b1u, 0x0000058bu, 0x00000001u, 0x000600a9u, 0x0000001fu, + 0x0000058du, 0x0000058bu, 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, 0x0000058fu, 0x000004c4u, + 0x0000058du, 0x00050080u, 0x0000001fu, 0x00000592u, 0x0000058fu, 0x00000087u, 0x0004006fu, 0x00000027u, + 0x000005a1u, 0x00000592u, 0x00050041u, 0x000000a5u, 0x000005a2u, 0x00000096u, 0x00000065u, 0x0004003du, + 0x00000027u, 0x000005a3u, 0x000005a2u, 0x00050085u, 0x00000027u, 0x000005a4u, 0x000005a1u, 0x000005a3u, + 0x00050051u, 0x00000026u, 0x000004c8u, 0x000005a4u, 0x00000001u, 0x00050051u, 0x00000026u, 0x000004c9u, + 0x000005a4u, 0x00000000u, 0x00060050u, 0x00000166u, 0x000004cau, 0x000004c8u, 0x000004c9u, 0x00000165u, + 0x00060060u, 0x0000016au, 0x000004cbu, 0x000004c5u, 0x000004cau, 0x00000064u, 0x00040073u, 0x0000002eu, + 0x000004ccu, 0x000004cbu, 0x0004003du, 0x0000015bu, 0x000004ceu, 0x0000015du, 0x00050050u, 0x00000017u, + 0x000005f4u, 0x00000170u, 0x000005b1u, 0x000600a9u, 0x0000001fu, 0x000005ceu, 0x000005f4u, 0x00000087u, + 0x00000082u, 0x00050082u, 0x0000001fu, 0x000005d0u, 0x000004c4u, 0x000005ceu, 0x00050080u, 0x0000001fu, + 0x000005d3u, 0x000005d0u, 0x00000087u, 0x00050041u, 0x00000097u, 0x000005dau, 0x00000096u, 0x00000064u, + 0x0004003du, 0x0000001fu, 0x000005dbu, 0x000005dau, 0x000500afu, 0x00000017u, 0x000005dcu, 0x000005d3u, + 0x000005dbu, 0x00050051u, 0x00000016u, 0x000005fau, 0x000005dcu, 0x00000000u, 0x00050050u, 0x00000017u, + 0x00000601u, 0x000005fau, 0x00000170u, 0x000600a9u, 0x0000001fu, 0x000005deu, 0x00000601u, 0x00000087u, + 0x00000082u, 0x00050080u, 0x0000001fu, 0x000005e0u, 0x000005d3u, 0x000005deu, 0x0004006fu, 0x00000027u, + 0x000005e2u, 0x000005e0u, 0x00050085u, 0x00000027u, 0x000005e5u, 0x000005e2u, 0x000005a3u, 0x00050051u, + 0x00000026u, 0x000004d1u, 0x000005e5u, 0x00000001u, 0x00050051u, 0x00000026u, 0x000004d2u, 0x000005e5u, + 0x00000000u, 0x00060050u, 0x00000166u, 0x000004d3u, 0x000004d1u, 0x000004d2u, 0x00000176u, 0x00060060u, + 0x0000016au, 0x000004d4u, 0x000004ceu, 0x000004d3u, 0x00000064u, 0x00040073u, 0x0000002eu, 0x000004d5u, + 0x000004d4u, 0x0004003du, 0x0000015bu, 0x000004d7u, 0x0000015du, 0x00050050u, 0x00000017u, 0x00000635u, + 0x000005acu, 0x00000170u, 0x000600a9u, 0x0000001fu, 0x0000060fu, 0x00000635u, 0x00000087u, 0x00000082u, + 0x00050082u, 0x0000001fu, 0x00000611u, 0x000004c4u, 0x0000060fu, 0x00050080u, 0x0000001fu, 0x00000614u, + 0x00000611u, 0x00000087u, 0x000500afu, 0x00000017u, 0x0000061du, 0x00000614u, 0x000005dbu, 0x00050051u, + 0x00000016u, 0x00000640u, 0x0000061du, 0x00000001u, 0x00050050u, 0x00000017u, 0x00000642u, 0x00000170u, + 0x00000640u, 0x000600a9u, 0x0000001fu, 0x0000061fu, 0x00000642u, 0x00000087u, 0x00000082u, 0x00050080u, + 0x0000001fu, 0x00000621u, 0x00000614u, 0x0000061fu, 0x0004006fu, 0x00000027u, 0x00000623u, 0x00000621u, + 0x00050085u, 0x00000027u, 0x00000626u, 0x00000623u, 0x000005a3u, 0x00050051u, 0x00000026u, 0x000004dau, + 0x00000626u, 0x00000001u, 0x00050051u, 0x00000026u, 0x000004dbu, 0x00000626u, 0x00000000u, 0x00060050u, + 0x00000166u, 0x000004dcu, 0x000004dau, 0x000004dbu, 0x00000184u, 0x00060060u, 0x0000016au, 0x000004ddu, + 0x000004d7u, 0x000004dcu, 0x00000064u, 0x00040073u, 0x0000002eu, 0x000004deu, 0x000004ddu, 0x0004003du, + 0x0000015bu, 0x000004e0u, 0x0000015du, 0x00050080u, 0x0000001fu, 0x00000655u, 0x000004c4u, 0x00000087u, + 0x000500afu, 0x00000017u, 0x0000065eu, 0x00000655u, 0x000005dbu, 0x000600a9u, 0x0000001fu, 0x00000660u, + 0x0000065eu, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x00000662u, 0x00000655u, 0x00000660u, + 0x0004006fu, 0x00000027u, 0x00000664u, 0x00000662u, 0x00050085u, 0x00000027u, 0x00000667u, 0x00000664u, + 0x000005a3u, 0x00050051u, 0x00000026u, 0x000004e3u, 0x00000667u, 0x00000001u, 0x00050051u, 0x00000026u, + 0x000004e4u, 0x00000667u, 0x00000000u, 0x00060050u, 0x00000166u, 0x000004e5u, 0x000004e3u, 0x000004e4u, + 0x00000192u, 0x00060060u, 0x0000016au, 0x000004e6u, 0x000004e0u, 0x000004e5u, 0x00000064u, 0x00040073u, + 0x0000002eu, 0x000004e7u, 0x000004e6u, 0x00050051u, 0x0000001eu, 0x0000069eu, 0x000004c1u, 0x00000001u, + 0x0004007cu, 0x00000006u, 0x000006a0u, 0x0000069eu, 0x00050051u, 0x0000001eu, 0x000006a2u, 0x000004c1u, + 0x00000000u, 0x00050084u, 0x0000001eu, 0x000006a3u, 0x00000069u, 0x000006a2u, 0x0004007cu, 0x00000006u, + 0x000006a5u, 0x000006a3u, 0x00050051u, 0x00000008u, 0x000006a7u, 0x000004ccu, 0x00000003u, 0x00050051u, + 0x00000008u, 0x000006a9u, 0x000004deu, 0x00000003u, 0x00050050u, 0x00000009u, 0x000006aau, 0x000006a7u, + 0x000006a9u, 0x00060041u, 0x0000004au, 0x00000719u, 0x00000047u, 0x000006a0u, 0x000006a5u, 0x0003003eu, + 0x00000719u, 0x000006aau, 0x00050080u, 0x0000001eu, 0x000006b3u, 0x000006a3u, 0x00000065u, 0x0004007cu, + 0x00000006u, 0x000006b4u, 0x000006b3u, 0x00050051u, 0x00000008u, 0x000006b6u, 0x000004d5u, 0x00000003u, + 0x00050051u, 0x00000008u, 0x000006b8u, 0x000004e7u, 0x00000003u, 0x00050050u, 0x00000009u, 0x000006b9u, + 0x000006b6u, 0x000006b8u, 0x00060041u, 0x0000004au, 0x0000071eu, 0x00000047u, 0x000006a0u, 0x000006b4u, + 0x0003003eu, 0x0000071eu, 0x000006b9u, 0x00050080u, 0x0000001eu, 0x000006c2u, 0x000006a3u, 0x00000069u, + 0x0004007cu, 0x00000006u, 0x000006c3u, 0x000006c2u, 0x00050051u, 0x00000008u, 0x000006c5u, 0x000004ccu, + 0x00000000u, 0x00050051u, 0x00000008u, 0x000006c7u, 0x000004deu, 0x00000000u, 0x00050050u, 0x00000009u, + 0x000006c8u, 0x000006c5u, 0x000006c7u, 0x00060041u, 0x0000004au, 0x00000723u, 0x00000047u, 0x000006a0u, + 0x000006c3u, 0x0003003eu, 0x00000723u, 0x000006c8u, 0x00050080u, 0x0000001eu, 0x000006d1u, 0x000006a3u, + 0x0000006cu, 0x0004007cu, 0x00000006u, 0x000006d2u, 0x000006d1u, 0x00050051u, 0x00000008u, 0x000006d4u, + 0x000004d5u, 0x00000000u, 0x00050051u, 0x00000008u, 0x000006d6u, 0x000004e7u, 0x00000000u, 0x00050050u, + 0x00000009u, 0x000006d7u, 0x000006d4u, 0x000006d6u, 0x00060041u, 0x0000004au, 0x00000728u, 0x00000047u, + 0x000006a0u, 0x000006d2u, 0x0003003eu, 0x00000728u, 0x000006d7u, 0x00050080u, 0x0000001eu, 0x000006dbu, + 0x0000069eu, 0x00000065u, 0x0004007cu, 0x00000006u, 0x000006dcu, 0x000006dbu, 0x00050051u, 0x00000008u, + 0x000006e3u, 0x000004ccu, 0x00000002u, 0x00050051u, 0x00000008u, 0x000006e5u, 0x000004deu, 0x00000002u, + 0x00050050u, 0x00000009u, 0x000006e6u, 0x000006e3u, 0x000006e5u, 0x00060041u, 0x0000004au, 0x0000072du, + 0x00000047u, 0x000006dcu, 0x000006a5u, 0x0003003eu, 0x0000072du, 0x000006e6u, 0x00050051u, 0x00000008u, + 0x000006f2u, 0x000004d5u, 0x00000002u, 0x00050051u, 0x00000008u, 0x000006f4u, 0x000004e7u, 0x00000002u, + 0x00050050u, 0x00000009u, 0x000006f5u, 0x000006f2u, 0x000006f4u, 0x00060041u, 0x0000004au, 0x00000732u, + 0x00000047u, 0x000006dcu, 0x000006b4u, 0x0003003eu, 0x00000732u, 0x000006f5u, 0x00050051u, 0x00000008u, + 0x00000701u, 0x000004ccu, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000703u, 0x000004deu, 0x00000001u, + 0x00050050u, 0x00000009u, 0x00000704u, 0x00000701u, 0x00000703u, 0x00060041u, 0x0000004au, 0x00000737u, + 0x00000047u, 0x000006dcu, 0x000006c3u, 0x0003003eu, 0x00000737u, 0x00000704u, 0x00050051u, 0x00000008u, + 0x00000710u, 0x000004d5u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000712u, 0x000004e7u, 0x00000001u, + 0x00050050u, 0x00000009u, 0x00000713u, 0x00000710u, 0x00000712u, 0x00060041u, 0x0000004au, 0x0000073cu, + 0x00000047u, 0x000006dcu, 0x000006d2u, 0x0003003eu, 0x0000073cu, 0x00000713u, 0x00050089u, 0x00000006u, + 0x000004f0u, 0x00000421u, 0x000000ffu, 0x00050084u, 0x00000006u, 0x000004f1u, 0x000000ffu, 0x000004f0u, + 0x00050080u, 0x00000006u, 0x000004f2u, 0x000001a5u, 0x000004f1u, 0x0004007cu, 0x0000001eu, 0x000004f3u, + 0x000004f2u, 0x00050086u, 0x00000006u, 0x000004f5u, 0x00000421u, 0x000000ffu, 0x00050084u, 0x00000006u, + 0x000004f6u, 0x000000ffu, 0x000004f5u, 0x0004007cu, 0x0000001eu, 0x000004f7u, 0x000004f6u, 0x00050050u, + 0x0000001fu, 0x000004f8u, 0x000004f3u, 0x000004f7u, 0x000500b1u, 0x00000016u, 0x000004fbu, 0x000004f7u, + 0x000001b2u, 0x000300f7u, 0x0000052fu, 0x00000000u, 0x000400fau, 0x000004fbu, 0x000004fcu, 0x0000052fu, + 0x000200f8u, 0x000004fcu, 0x0004003du, 0x0000015bu, 0x000004fdu, 0x0000015du, 0x00050080u, 0x0000001fu, + 0x00000500u, 0x000004bdu, 0x000004f8u, 0x000500b1u, 0x00000017u, 0x00000748u, 0x00000500u, 0x00000082u, + 0x00050051u, 0x00000016u, 0x00000769u, 0x00000748u, 0x00000000u, 0x00050051u, 0x00000016u, 0x0000076eu, + 0x00000748u, 0x00000001u, 0x000600a9u, 0x0000001fu, 0x0000074au, 0x00000748u, 0x00000087u, 0x00000082u, + 0x00050082u, 0x0000001fu, 0x0000074cu, 0x00000500u, 0x0000074au, 0x00050080u, 0x0000001fu, 0x0000074fu, + 0x0000074cu, 0x00000087u, 0x0004006fu, 0x00000027u, 0x0000075eu, 0x0000074fu, 0x00050085u, 0x00000027u, + 0x00000761u, 0x0000075eu, 0x000005a3u, 0x00050051u, 0x00000026u, 0x00000502u, 0x00000761u, 0x00000001u, + 0x00050051u, 0x00000026u, 0x00000503u, 0x00000761u, 0x00000000u, 0x00060050u, 0x00000166u, 0x00000504u, + 0x00000502u, 0x00000503u, 0x00000165u, 0x00060060u, 0x0000016au, 0x00000505u, 0x000004fdu, 0x00000504u, + 0x00000064u, 0x00040073u, 0x0000002eu, 0x00000506u, 0x00000505u, 0x0004003du, 0x0000015bu, 0x00000508u, + 0x0000015du, 0x00050050u, 0x00000017u, 0x000007b1u, 0x00000170u, 0x0000076eu, 0x000600a9u, 0x0000001fu, + 0x0000078bu, 0x000007b1u, 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, 0x0000078du, 0x00000500u, + 0x0000078bu, 0x00050080u, 0x0000001fu, 0x00000790u, 0x0000078du, 0x00000087u, 0x000500afu, 0x00000017u, + 0x00000799u, 0x00000790u, 0x000005dbu, 0x00050051u, 0x00000016u, 0x000007b7u, 0x00000799u, 0x00000000u, + 0x00050050u, 0x00000017u, 0x000007beu, 0x000007b7u, 0x00000170u, 0x000600a9u, 0x0000001fu, 0x0000079bu, + 0x000007beu, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x0000079du, 0x00000790u, 0x0000079bu, + 0x0004006fu, 0x00000027u, 0x0000079fu, 0x0000079du, 0x00050085u, 0x00000027u, 0x000007a2u, 0x0000079fu, + 0x000005a3u, 0x00050051u, 0x00000026u, 0x0000050du, 0x000007a2u, 0x00000001u, 0x00050051u, 0x00000026u, + 0x0000050eu, 0x000007a2u, 0x00000000u, 0x00060050u, 0x00000166u, 0x0000050fu, 0x0000050du, 0x0000050eu, + 0x00000176u, 0x00060060u, 0x0000016au, 0x00000510u, 0x00000508u, 0x0000050fu, 0x00000064u, 0x00040073u, + 0x0000002eu, 0x00000511u, 0x00000510u, 0x0004003du, 0x0000015bu, 0x00000513u, 0x0000015du, 0x00050050u, + 0x00000017u, 0x000007f2u, 0x00000769u, 0x00000170u, 0x000600a9u, 0x0000001fu, 0x000007ccu, 0x000007f2u, + 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, 0x000007ceu, 0x00000500u, 0x000007ccu, 0x00050080u, + 0x0000001fu, 0x000007d1u, 0x000007ceu, 0x00000087u, 0x000500afu, 0x00000017u, 0x000007dau, 0x000007d1u, + 0x000005dbu, 0x00050051u, 0x00000016u, 0x000007fdu, 0x000007dau, 0x00000001u, 0x00050050u, 0x00000017u, + 0x000007ffu, 0x00000170u, 0x000007fdu, 0x000600a9u, 0x0000001fu, 0x000007dcu, 0x000007ffu, 0x00000087u, + 0x00000082u, 0x00050080u, 0x0000001fu, 0x000007deu, 0x000007d1u, 0x000007dcu, 0x0004006fu, 0x00000027u, + 0x000007e0u, 0x000007deu, 0x00050085u, 0x00000027u, 0x000007e3u, 0x000007e0u, 0x000005a3u, 0x00050051u, + 0x00000026u, 0x00000518u, 0x000007e3u, 0x00000001u, 0x00050051u, 0x00000026u, 0x00000519u, 0x000007e3u, + 0x00000000u, 0x00060050u, 0x00000166u, 0x0000051au, 0x00000518u, 0x00000519u, 0x00000184u, 0x00060060u, + 0x0000016au, 0x0000051bu, 0x00000513u, 0x0000051au, 0x00000064u, 0x00040073u, 0x0000002eu, 0x0000051cu, + 0x0000051bu, 0x0004003du, 0x0000015bu, 0x0000051eu, 0x0000015du, 0x00050080u, 0x0000001fu, 0x00000812u, + 0x00000500u, 0x00000087u, 0x000500afu, 0x00000017u, 0x0000081bu, 0x00000812u, 0x000005dbu, 0x000600a9u, + 0x0000001fu, 0x0000081du, 0x0000081bu, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x0000081fu, + 0x00000812u, 0x0000081du, 0x0004006fu, 0x00000027u, 0x00000821u, 0x0000081fu, 0x00050085u, 0x00000027u, + 0x00000824u, 0x00000821u, 0x000005a3u, 0x00050051u, 0x00000026u, 0x00000523u, 0x00000824u, 0x00000001u, + 0x00050051u, 0x00000026u, 0x00000524u, 0x00000824u, 0x00000000u, 0x00060050u, 0x00000166u, 0x00000525u, + 0x00000523u, 0x00000524u, 0x00000192u, 0x00060060u, 0x0000016au, 0x00000526u, 0x0000051eu, 0x00000525u, + 0x00000064u, 0x00040073u, 0x0000002eu, 0x00000527u, 0x00000526u, 0x00050084u, 0x0000001eu, 0x00000860u, + 0x00000069u, 0x000004f3u, 0x0004007cu, 0x00000006u, 0x00000862u, 0x00000860u, 0x00050051u, 0x00000008u, + 0x00000864u, 0x00000506u, 0x00000003u, 0x00050051u, 0x00000008u, 0x00000866u, 0x0000051cu, 0x00000003u, + 0x00050050u, 0x00000009u, 0x00000867u, 0x00000864u, 0x00000866u, 0x00060041u, 0x0000004au, 0x000008d6u, + 0x00000047u, 0x000004f6u, 0x00000862u, 0x0003003eu, 0x000008d6u, 0x00000867u, 0x00050080u, 0x0000001eu, + 0x00000870u, 0x00000860u, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000871u, 0x00000870u, 0x00050051u, + 0x00000008u, 0x00000873u, 0x00000511u, 0x00000003u, 0x00050051u, 0x00000008u, 0x00000875u, 0x00000527u, + 0x00000003u, 0x00050050u, 0x00000009u, 0x00000876u, 0x00000873u, 0x00000875u, 0x00060041u, 0x0000004au, + 0x000008dbu, 0x00000047u, 0x000004f6u, 0x00000871u, 0x0003003eu, 0x000008dbu, 0x00000876u, 0x00050080u, + 0x0000001eu, 0x0000087fu, 0x00000860u, 0x00000069u, 0x0004007cu, 0x00000006u, 0x00000880u, 0x0000087fu, + 0x00050051u, 0x00000008u, 0x00000882u, 0x00000506u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000884u, + 0x0000051cu, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000885u, 0x00000882u, 0x00000884u, 0x00060041u, + 0x0000004au, 0x000008e0u, 0x00000047u, 0x000004f6u, 0x00000880u, 0x0003003eu, 0x000008e0u, 0x00000885u, + 0x00050080u, 0x0000001eu, 0x0000088eu, 0x00000860u, 0x0000006cu, 0x0004007cu, 0x00000006u, 0x0000088fu, + 0x0000088eu, 0x00050051u, 0x00000008u, 0x00000891u, 0x00000511u, 0x00000000u, 0x00050051u, 0x00000008u, + 0x00000893u, 0x00000527u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000894u, 0x00000891u, 0x00000893u, + 0x00060041u, 0x0000004au, 0x000008e5u, 0x00000047u, 0x000004f6u, 0x0000088fu, 0x0003003eu, 0x000008e5u, + 0x00000894u, 0x00050080u, 0x0000001eu, 0x00000898u, 0x000004f7u, 0x00000065u, 0x0004007cu, 0x00000006u, + 0x00000899u, 0x00000898u, 0x00050051u, 0x00000008u, 0x000008a0u, 0x00000506u, 0x00000002u, 0x00050051u, + 0x00000008u, 0x000008a2u, 0x0000051cu, 0x00000002u, 0x00050050u, 0x00000009u, 0x000008a3u, 0x000008a0u, + 0x000008a2u, 0x00060041u, 0x0000004au, 0x000008eau, 0x00000047u, 0x00000899u, 0x00000862u, 0x0003003eu, + 0x000008eau, 0x000008a3u, 0x00050051u, 0x00000008u, 0x000008afu, 0x00000511u, 0x00000002u, 0x00050051u, + 0x00000008u, 0x000008b1u, 0x00000527u, 0x00000002u, 0x00050050u, 0x00000009u, 0x000008b2u, 0x000008afu, + 0x000008b1u, 0x00060041u, 0x0000004au, 0x000008efu, 0x00000047u, 0x00000899u, 0x00000871u, 0x0003003eu, + 0x000008efu, 0x000008b2u, 0x00050051u, 0x00000008u, 0x000008beu, 0x00000506u, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000008c0u, 0x0000051cu, 0x00000001u, 0x00050050u, 0x00000009u, 0x000008c1u, 0x000008beu, + 0x000008c0u, 0x00060041u, 0x0000004au, 0x000008f4u, 0x00000047u, 0x00000899u, 0x00000880u, 0x0003003eu, + 0x000008f4u, 0x000008c1u, 0x00050051u, 0x00000008u, 0x000008cdu, 0x00000511u, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000008cfu, 0x00000527u, 0x00000001u, 0x00050050u, 0x00000009u, 0x000008d0u, 0x000008cdu, + 0x000008cfu, 0x00060041u, 0x0000004au, 0x000008f9u, 0x00000047u, 0x00000899u, 0x0000088fu, 0x0003003eu, + 0x000008f9u, 0x000008d0u, 0x000200f9u, 0x0000052fu, 0x000200f8u, 0x0000052fu, 0x0007004fu, 0x0000001fu, + 0x00000531u, 0x000004f8u, 0x000004f8u, 0x00000001u, 0x00000000u, 0x000500b1u, 0x00000016u, 0x00000534u, + 0x000004f7u, 0x00000148u, 0x000300f7u, 0x00000568u, 0x00000000u, 0x000400fau, 0x00000534u, 0x00000535u, + 0x00000568u, 0x000200f8u, 0x00000535u, 0x0004003du, 0x0000015bu, 0x00000536u, 0x0000015du, 0x00050080u, + 0x0000001fu, 0x00000539u, 0x000004bdu, 0x00000531u, 0x000500b1u, 0x00000017u, 0x00000905u, 0x00000539u, + 0x00000082u, 0x00050051u, 0x00000016u, 0x00000926u, 0x00000905u, 0x00000000u, 0x00050051u, 0x00000016u, + 0x0000092bu, 0x00000905u, 0x00000001u, 0x000600a9u, 0x0000001fu, 0x00000907u, 0x00000905u, 0x00000087u, + 0x00000082u, 0x00050082u, 0x0000001fu, 0x00000909u, 0x00000539u, 0x00000907u, 0x00050080u, 0x0000001fu, + 0x0000090cu, 0x00000909u, 0x00000087u, 0x0004006fu, 0x00000027u, 0x0000091bu, 0x0000090cu, 0x00050085u, + 0x00000027u, 0x0000091eu, 0x0000091bu, 0x000005a3u, 0x00050051u, 0x00000026u, 0x0000053bu, 0x0000091eu, + 0x00000001u, 0x00050051u, 0x00000026u, 0x0000053cu, 0x0000091eu, 0x00000000u, 0x00060050u, 0x00000166u, + 0x0000053du, 0x0000053bu, 0x0000053cu, 0x00000165u, 0x00060060u, 0x0000016au, 0x0000053eu, 0x00000536u, + 0x0000053du, 0x00000064u, 0x00040073u, 0x0000002eu, 0x0000053fu, 0x0000053eu, 0x0004003du, 0x0000015bu, + 0x00000541u, 0x0000015du, 0x00050050u, 0x00000017u, 0x0000096eu, 0x00000170u, 0x0000092bu, 0x000600a9u, + 0x0000001fu, 0x00000948u, 0x0000096eu, 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, 0x0000094au, + 0x00000539u, 0x00000948u, 0x00050080u, 0x0000001fu, 0x0000094du, 0x0000094au, 0x00000087u, 0x000500afu, + 0x00000017u, 0x00000956u, 0x0000094du, 0x000005dbu, 0x00050051u, 0x00000016u, 0x00000974u, 0x00000956u, + 0x00000000u, 0x00050050u, 0x00000017u, 0x0000097bu, 0x00000974u, 0x00000170u, 0x000600a9u, 0x0000001fu, + 0x00000958u, 0x0000097bu, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x0000095au, 0x0000094du, + 0x00000958u, 0x0004006fu, 0x00000027u, 0x0000095cu, 0x0000095au, 0x00050085u, 0x00000027u, 0x0000095fu, + 0x0000095cu, 0x000005a3u, 0x00050051u, 0x00000026u, 0x00000546u, 0x0000095fu, 0x00000001u, 0x00050051u, + 0x00000026u, 0x00000547u, 0x0000095fu, 0x00000000u, 0x00060050u, 0x00000166u, 0x00000548u, 0x00000546u, + 0x00000547u, 0x00000176u, 0x00060060u, 0x0000016au, 0x00000549u, 0x00000541u, 0x00000548u, 0x00000064u, + 0x00040073u, 0x0000002eu, 0x0000054au, 0x00000549u, 0x0004003du, 0x0000015bu, 0x0000054cu, 0x0000015du, + 0x00050050u, 0x00000017u, 0x000009afu, 0x00000926u, 0x00000170u, 0x000600a9u, 0x0000001fu, 0x00000989u, + 0x000009afu, 0x00000087u, 0x00000082u, 0x00050082u, 0x0000001fu, 0x0000098bu, 0x00000539u, 0x00000989u, + 0x00050080u, 0x0000001fu, 0x0000098eu, 0x0000098bu, 0x00000087u, 0x000500afu, 0x00000017u, 0x00000997u, + 0x0000098eu, 0x000005dbu, 0x00050051u, 0x00000016u, 0x000009bau, 0x00000997u, 0x00000001u, 0x00050050u, + 0x00000017u, 0x000009bcu, 0x00000170u, 0x000009bau, 0x000600a9u, 0x0000001fu, 0x00000999u, 0x000009bcu, + 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, 0x0000099bu, 0x0000098eu, 0x00000999u, 0x0004006fu, + 0x00000027u, 0x0000099du, 0x0000099bu, 0x00050085u, 0x00000027u, 0x000009a0u, 0x0000099du, 0x000005a3u, + 0x00050051u, 0x00000026u, 0x00000551u, 0x000009a0u, 0x00000001u, 0x00050051u, 0x00000026u, 0x00000552u, + 0x000009a0u, 0x00000000u, 0x00060050u, 0x00000166u, 0x00000553u, 0x00000551u, 0x00000552u, 0x00000184u, + 0x00060060u, 0x0000016au, 0x00000554u, 0x0000054cu, 0x00000553u, 0x00000064u, 0x00040073u, 0x0000002eu, + 0x00000555u, 0x00000554u, 0x0004003du, 0x0000015bu, 0x00000557u, 0x0000015du, 0x00050080u, 0x0000001fu, + 0x000009cfu, 0x00000539u, 0x00000087u, 0x000500afu, 0x00000017u, 0x000009d8u, 0x000009cfu, 0x000005dbu, + 0x000600a9u, 0x0000001fu, 0x000009dau, 0x000009d8u, 0x00000087u, 0x00000082u, 0x00050080u, 0x0000001fu, + 0x000009dcu, 0x000009cfu, 0x000009dau, 0x0004006fu, 0x00000027u, 0x000009deu, 0x000009dcu, 0x00050085u, + 0x00000027u, 0x000009e1u, 0x000009deu, 0x000005a3u, 0x00050051u, 0x00000026u, 0x0000055cu, 0x000009e1u, + 0x00000001u, 0x00050051u, 0x00000026u, 0x0000055du, 0x000009e1u, 0x00000000u, 0x00060050u, 0x00000166u, + 0x0000055eu, 0x0000055cu, 0x0000055du, 0x00000192u, 0x00060060u, 0x0000016au, 0x0000055fu, 0x00000557u, + 0x0000055eu, 0x00000064u, 0x00040073u, 0x0000002eu, 0x00000560u, 0x0000055fu, 0x00050084u, 0x0000001eu, + 0x00000a1du, 0x00000069u, 0x000004f7u, 0x0004007cu, 0x00000006u, 0x00000a1fu, 0x00000a1du, 0x00050051u, + 0x00000008u, 0x00000a21u, 0x0000053fu, 0x00000003u, 0x00050051u, 0x00000008u, 0x00000a23u, 0x00000555u, + 0x00000003u, 0x00050050u, 0x00000009u, 0x00000a24u, 0x00000a21u, 0x00000a23u, 0x00060041u, 0x0000004au, + 0x00000a93u, 0x00000047u, 0x000004f2u, 0x00000a1fu, 0x0003003eu, 0x00000a93u, 0x00000a24u, 0x00050080u, + 0x0000001eu, 0x00000a2du, 0x00000a1du, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000a2eu, 0x00000a2du, + 0x00050051u, 0x00000008u, 0x00000a30u, 0x0000054au, 0x00000003u, 0x00050051u, 0x00000008u, 0x00000a32u, + 0x00000560u, 0x00000003u, 0x00050050u, 0x00000009u, 0x00000a33u, 0x00000a30u, 0x00000a32u, 0x00060041u, + 0x0000004au, 0x00000a98u, 0x00000047u, 0x000004f2u, 0x00000a2eu, 0x0003003eu, 0x00000a98u, 0x00000a33u, + 0x00050080u, 0x0000001eu, 0x00000a3cu, 0x00000a1du, 0x00000069u, 0x0004007cu, 0x00000006u, 0x00000a3du, + 0x00000a3cu, 0x00050051u, 0x00000008u, 0x00000a3fu, 0x0000053fu, 0x00000000u, 0x00050051u, 0x00000008u, + 0x00000a41u, 0x00000555u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000a42u, 0x00000a3fu, 0x00000a41u, + 0x00060041u, 0x0000004au, 0x00000a9du, 0x00000047u, 0x000004f2u, 0x00000a3du, 0x0003003eu, 0x00000a9du, + 0x00000a42u, 0x00050080u, 0x0000001eu, 0x00000a4bu, 0x00000a1du, 0x0000006cu, 0x0004007cu, 0x00000006u, + 0x00000a4cu, 0x00000a4bu, 0x00050051u, 0x00000008u, 0x00000a4eu, 0x0000054au, 0x00000000u, 0x00050051u, + 0x00000008u, 0x00000a50u, 0x00000560u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000a51u, 0x00000a4eu, + 0x00000a50u, 0x00060041u, 0x0000004au, 0x00000aa2u, 0x00000047u, 0x000004f2u, 0x00000a4cu, 0x0003003eu, + 0x00000aa2u, 0x00000a51u, 0x00050080u, 0x0000001eu, 0x00000a55u, 0x000004f3u, 0x00000065u, 0x0004007cu, + 0x00000006u, 0x00000a56u, 0x00000a55u, 0x00050051u, 0x00000008u, 0x00000a5du, 0x0000053fu, 0x00000002u, + 0x00050051u, 0x00000008u, 0x00000a5fu, 0x00000555u, 0x00000002u, 0x00050050u, 0x00000009u, 0x00000a60u, + 0x00000a5du, 0x00000a5fu, 0x00060041u, 0x0000004au, 0x00000aa7u, 0x00000047u, 0x00000a56u, 0x00000a1fu, + 0x0003003eu, 0x00000aa7u, 0x00000a60u, 0x00050051u, 0x00000008u, 0x00000a6cu, 0x0000054au, 0x00000002u, + 0x00050051u, 0x00000008u, 0x00000a6eu, 0x00000560u, 0x00000002u, 0x00050050u, 0x00000009u, 0x00000a6fu, + 0x00000a6cu, 0x00000a6eu, 0x00060041u, 0x0000004au, 0x00000aacu, 0x00000047u, 0x00000a56u, 0x00000a2eu, + 0x0003003eu, 0x00000aacu, 0x00000a6fu, 0x00050051u, 0x00000008u, 0x00000a7bu, 0x0000053fu, 0x00000001u, + 0x00050051u, 0x00000008u, 0x00000a7du, 0x00000555u, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000a7eu, + 0x00000a7bu, 0x00000a7du, 0x00060041u, 0x0000004au, 0x00000ab1u, 0x00000047u, 0x00000a56u, 0x00000a3du, + 0x0003003eu, 0x00000ab1u, 0x00000a7eu, 0x00050051u, 0x00000008u, 0x00000a8au, 0x0000054au, 0x00000001u, + 0x00050051u, 0x00000008u, 0x00000a8cu, 0x00000560u, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000a8du, + 0x00000a8au, 0x00000a8cu, 0x00060041u, 0x0000004au, 0x00000ab6u, 0x00000047u, 0x00000a56u, 0x00000a4cu, + 0x0003003eu, 0x00000ab6u, 0x00000a8du, 0x000200f9u, 0x00000568u, 0x000200f8u, 0x00000568u, 0x000400e0u, + 0x000000ffu, 0x000000ffu, 0x00000244u, 0x00050089u, 0x00000006u, 0x00000ad2u, 0x00000421u, 0x00000248u, + 0x00050084u, 0x00000006u, 0x00000ad3u, 0x00000246u, 0x00000ad2u, 0x0004007cu, 0x0000001eu, 0x00000ad4u, + 0x00000ad3u, 0x00050086u, 0x00000006u, 0x00000ad6u, 0x00000421u, 0x00000248u, 0x0004007cu, 0x0000001eu, + 0x00000ad7u, 0x00000ad6u, 0x000200f9u, 0x00000ad9u, 0x000200f8u, 0x00000ad9u, 0x000700f5u, 0x0000001eu, + 0x00000e9eu, 0x00000064u, 0x00000568u, 0x00000afeu, 0x00000addu, 0x000500b1u, 0x00000016u, 0x00000adcu, + 0x00000e9eu, 0x00000148u, 0x000400f6u, 0x00000affu, 0x00000addu, 0x00000000u, 0x000400fau, 0x00000adcu, + 0x00000addu, 0x00000affu, 0x000200f8u, 0x00000addu, 0x00050080u, 0x0000001eu, 0x00000ae4u, 0x00000ad4u, + 0x00000e9eu, 0x0004007cu, 0x00000006u, 0x00000ae6u, 0x00000ae4u, 0x00060041u, 0x0000004au, 0x00000b99u, + 0x00000047u, 0x00000ad6u, 0x00000ae6u, 0x0004003du, 0x00000009u, 0x00000b9au, 0x00000b99u, 0x00050080u, + 0x0000001eu, 0x00000aefu, 0x00000ae4u, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000af0u, 0x00000aefu, + 0x00060041u, 0x0000004au, 0x00000b9fu, 0x00000047u, 0x00000ad6u, 0x00000af0u, 0x0004003du, 0x00000009u, + 0x00000ba0u, 0x00000b9fu, 0x0005008eu, 0x00000009u, 0x00000af5u, 0x00000b9au, 0x00000278u, 0x00050041u, + 0x0000000fu, 0x00000af6u, 0x00000abfu, 0x00000e9eu, 0x0003003eu, 0x00000af6u, 0x00000af5u, 0x00050080u, + 0x0000001eu, 0x00000af8u, 0x00000e9eu, 0x00000065u, 0x0005008eu, 0x00000009u, 0x00000afau, 0x00000ba0u, + 0x0000027eu, 0x00050041u, 0x0000000fu, 0x00000afbu, 0x00000abfu, 0x00000af8u, 0x0003003eu, 0x00000afbu, + 0x00000afau, 0x00050080u, 0x0000001eu, 0x00000afeu, 0x00000e9eu, 0x00000069u, 0x000200f9u, 0x00000ad9u, + 0x000200f8u, 0x00000affu, 0x000200f9u, 0x00000b00u, 0x000200f8u, 0x00000b00u, 0x000700f5u, 0x0000001eu, + 0x00000e9fu, 0x00000069u, 0x00000affu, 0x00000b16u, 0x00000b04u, 0x000500b1u, 0x00000016u, 0x00000b03u, + 0x00000e9fu, 0x0000028au, 0x000400f6u, 0x00000b17u, 0x00000b04u, 0x00000000u, 0x000400fau, 0x00000b03u, + 0x00000b04u, 0x00000b17u, 0x000200f8u, 0x00000b04u, 0x00050082u, 0x0000001eu, 0x00000b07u, 0x00000e9fu, + 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b08u, 0x00000abfu, 0x00000b07u, 0x0004003du, 0x00000009u, + 0x00000b09u, 0x00000b08u, 0x00050080u, 0x0000001eu, 0x00000b0bu, 0x00000e9fu, 0x00000065u, 0x00050041u, + 0x0000000fu, 0x00000b0cu, 0x00000abfu, 0x00000b0bu, 0x0004003du, 0x00000009u, 0x00000b0du, 0x00000b0cu, + 0x00050081u, 0x00000009u, 0x00000b0eu, 0x00000b09u, 0x00000b0du, 0x0005008eu, 0x00000009u, 0x00000b0fu, + 0x00000b0eu, 0x0000028du, 0x00050041u, 0x0000000fu, 0x00000b10u, 0x00000abfu, 0x00000e9fu, 0x0004003du, + 0x00000009u, 0x00000b11u, 0x00000b10u, 0x00050083u, 0x00000009u, 0x00000b12u, 0x00000b11u, 0x00000b0fu, + 0x0003003eu, 0x00000b10u, 0x00000b12u, 0x00050080u, 0x0000001eu, 0x00000b16u, 0x00000e9fu, 0x00000069u, + 0x000200f9u, 0x00000b00u, 0x000200f8u, 0x00000b17u, 0x000200f9u, 0x00000b18u, 0x000200f8u, 0x00000b18u, + 0x000700f5u, 0x0000001eu, 0x00000ea0u, 0x0000006cu, 0x00000b17u, 0x00000b2eu, 0x00000b1cu, 0x000500b1u, + 0x00000016u, 0x00000b1bu, 0x00000ea0u, 0x000002a5u, 0x000400f6u, 0x00000b2fu, 0x00000b1cu, 0x00000000u, + 0x000400fau, 0x00000b1bu, 0x00000b1cu, 0x00000b2fu, 0x000200f8u, 0x00000b1cu, 0x00050082u, 0x0000001eu, + 0x00000b1fu, 0x00000ea0u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b20u, 0x00000abfu, 0x00000b1fu, + 0x0004003du, 0x00000009u, 0x00000b21u, 0x00000b20u, 0x00050080u, 0x0000001eu, 0x00000b23u, 0x00000ea0u, + 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b24u, 0x00000abfu, 0x00000b23u, 0x0004003du, 0x00000009u, + 0x00000b25u, 0x00000b24u, 0x00050081u, 0x00000009u, 0x00000b26u, 0x00000b21u, 0x00000b25u, 0x0005008eu, + 0x00000009u, 0x00000b27u, 0x00000b26u, 0x000002a8u, 0x00050041u, 0x0000000fu, 0x00000b28u, 0x00000abfu, + 0x00000ea0u, 0x0004003du, 0x00000009u, 0x00000b29u, 0x00000b28u, 0x00050083u, 0x00000009u, 0x00000b2au, + 0x00000b29u, 0x00000b27u, 0x0003003eu, 0x00000b28u, 0x00000b2au, 0x00050080u, 0x0000001eu, 0x00000b2eu, + 0x00000ea0u, 0x00000069u, 0x000200f9u, 0x00000b18u, 0x000200f8u, 0x00000b2fu, 0x000200f9u, 0x00000b30u, + 0x000200f8u, 0x00000b30u, 0x000700f5u, 0x0000001eu, 0x00000ea1u, 0x000002bau, 0x00000b2fu, 0x00000b46u, + 0x00000b34u, 0x000500b1u, 0x00000016u, 0x00000b33u, 0x00000ea1u, 0x000002c1u, 0x000400f6u, 0x00000b47u, + 0x00000b34u, 0x00000000u, 0x000400fau, 0x00000b33u, 0x00000b34u, 0x00000b47u, 0x000200f8u, 0x00000b34u, + 0x00050082u, 0x0000001eu, 0x00000b37u, 0x00000ea1u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b38u, + 0x00000abfu, 0x00000b37u, 0x0004003du, 0x00000009u, 0x00000b39u, 0x00000b38u, 0x00050080u, 0x0000001eu, + 0x00000b3bu, 0x00000ea1u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b3cu, 0x00000abfu, 0x00000b3bu, + 0x0004003du, 0x00000009u, 0x00000b3du, 0x00000b3cu, 0x00050081u, 0x00000009u, 0x00000b3eu, 0x00000b39u, + 0x00000b3du, 0x0005008eu, 0x00000009u, 0x00000b3fu, 0x00000b3eu, 0x000002c4u, 0x00050041u, 0x0000000fu, + 0x00000b40u, 0x00000abfu, 0x00000ea1u, 0x0004003du, 0x00000009u, 0x00000b41u, 0x00000b40u, 0x00050083u, + 0x00000009u, 0x00000b42u, 0x00000b41u, 0x00000b3fu, 0x0003003eu, 0x00000b40u, 0x00000b42u, 0x00050080u, + 0x0000001eu, 0x00000b46u, 0x00000ea1u, 0x00000069u, 0x000200f9u, 0x00000b30u, 0x000200f8u, 0x00000b47u, + 0x000200f9u, 0x00000b48u, 0x000200f8u, 0x00000b48u, 0x000700f5u, 0x0000001eu, 0x00000ea2u, 0x00000072u, + 0x00000b47u, 0x00000b5eu, 0x00000b4cu, 0x000500b1u, 0x00000016u, 0x00000b4bu, 0x00000ea2u, 0x000002dcu, + 0x000400f6u, 0x00000b5fu, 0x00000b4cu, 0x00000000u, 0x000400fau, 0x00000b4bu, 0x00000b4cu, 0x00000b5fu, + 0x000200f8u, 0x00000b4cu, 0x00050082u, 0x0000001eu, 0x00000b4fu, 0x00000ea2u, 0x00000065u, 0x00050041u, + 0x0000000fu, 0x00000b50u, 0x00000abfu, 0x00000b4fu, 0x0004003du, 0x00000009u, 0x00000b51u, 0x00000b50u, + 0x00050080u, 0x0000001eu, 0x00000b53u, 0x00000ea2u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b54u, + 0x00000abfu, 0x00000b53u, 0x0004003du, 0x00000009u, 0x00000b55u, 0x00000b54u, 0x00050081u, 0x00000009u, + 0x00000b56u, 0x00000b51u, 0x00000b55u, 0x0005008eu, 0x00000009u, 0x00000b57u, 0x00000b56u, 0x000002dfu, + 0x00050041u, 0x0000000fu, 0x00000b58u, 0x00000abfu, 0x00000ea2u, 0x0004003du, 0x00000009u, 0x00000b59u, + 0x00000b58u, 0x00050083u, 0x00000009u, 0x00000b5au, 0x00000b59u, 0x00000b57u, 0x0003003eu, 0x00000b58u, + 0x00000b5au, 0x00050080u, 0x0000001eu, 0x00000b5eu, 0x00000ea2u, 0x00000069u, 0x000200f9u, 0x00000b48u, + 0x000200f8u, 0x00000b5fu, 0x000400e0u, 0x000000ffu, 0x000000ffu, 0x00000244u, 0x000200f9u, 0x00000b60u, + 0x000200f8u, 0x00000b60u, 0x000700f5u, 0x0000001eu, 0x00000ea3u, 0x00000069u, 0x00000b5fu, 0x00000b93u, + 0x00000b64u, 0x000500b1u, 0x00000016u, 0x00000b63u, 0x00000ea3u, 0x000002f7u, 0x000400f6u, 0x00000b94u, + 0x00000b64u, 0x00000000u, 0x000400fau, 0x00000b63u, 0x00000b64u, 0x00000b94u, 0x000200f8u, 0x00000b64u, + 0x00050084u, 0x0000001eu, 0x00000b66u, 0x00000069u, 0x00000ea3u, 0x00050041u, 0x0000000fu, 0x00000b68u, + 0x00000abfu, 0x00000b66u, 0x0004003du, 0x00000009u, 0x00000b69u, 0x00000b68u, 0x00050080u, 0x0000001eu, + 0x00000b6cu, 0x00000b66u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000b6du, 0x00000abfu, 0x00000b6cu, + 0x0004003du, 0x00000009u, 0x00000b6eu, 0x00000b6du, 0x00050051u, 0x00000008u, 0x00000b70u, 0x00000b69u, + 0x00000000u, 0x00050051u, 0x00000008u, 0x00000b72u, 0x00000b6eu, 0x00000000u, 0x00050050u, 0x00000009u, + 0x00000b73u, 0x00000b70u, 0x00000b72u, 0x00050051u, 0x00000008u, 0x00000b75u, 0x00000b69u, 0x00000001u, + 0x00050051u, 0x00000008u, 0x00000b77u, 0x00000b6eu, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000b78u, + 0x00000b75u, 0x00000b77u, 0x000500c3u, 0x0000001eu, 0x00000b7bu, 0x00000ad4u, 0x00000065u, 0x00050082u, + 0x0000001eu, 0x00000b7du, 0x00000ea3u, 0x00000069u, 0x00050080u, 0x0000001eu, 0x00000b7eu, 0x00000b7bu, + 0x00000b7du, 0x0004007cu, 0x00000006u, 0x00000b80u, 0x00000b7eu, 0x00050084u, 0x0000001eu, 0x00000b83u, + 0x00000069u, 0x00000ad7u, 0x0004007cu, 0x00000006u, 0x00000b85u, 0x00000b83u, 0x00060041u, 0x0000004au, + 0x00000ba5u, 0x00000047u, 0x00000b80u, 0x00000b85u, 0x0003003eu, 0x00000ba5u, 0x00000b73u, 0x00050080u, + 0x0000001eu, 0x00000b8du, 0x00000b83u, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000b8eu, 0x00000b8du, + 0x00060041u, 0x0000004au, 0x00000baau, 0x00000047u, 0x00000b80u, 0x00000b8eu, 0x0003003eu, 0x00000baau, + 0x00000b78u, 0x00050080u, 0x0000001eu, 0x00000b93u, 0x00000ea3u, 0x00000065u, 0x000200f9u, 0x00000b60u, + 0x000200f8u, 0x00000b94u, 0x000500b0u, 0x00000016u, 0x00000426u, 0x00000421u, 0x00000425u, 0x00050089u, + 0x00000006u, 0x00000bc6u, 0x00000421u, 0x00000246u, 0x00050084u, 0x00000006u, 0x00000bc7u, 0x00000248u, + 0x00000bc6u, 0x0004007cu, 0x0000001eu, 0x00000bc8u, 0x00000bc7u, 0x00050086u, 0x00000006u, 0x00000bcau, + 0x00000421u, 0x00000246u, 0x00050080u, 0x00000006u, 0x00000bcdu, 0x00000bcau, 0x000001a5u, 0x0004007cu, + 0x0000001eu, 0x00000bceu, 0x00000bcdu, 0x000300f7u, 0x00000c59u, 0x00000000u, 0x000400fau, 0x00000426u, + 0x00000bd1u, 0x00000c59u, 0x000200f8u, 0x00000bd1u, 0x000200f9u, 0x00000bd2u, 0x000200f8u, 0x00000bd2u, + 0x000700f5u, 0x0000001eu, 0x00000ea4u, 0x00000064u, 0x00000bd1u, 0x00000bf7u, 0x00000bd6u, 0x000500b1u, + 0x00000016u, 0x00000bd5u, 0x00000ea4u, 0x000002dcu, 0x000400f6u, 0x00000bf8u, 0x00000bd6u, 0x00000000u, + 0x000400fau, 0x00000bd5u, 0x00000bd6u, 0x00000bf8u, 0x000200f8u, 0x00000bd6u, 0x00050080u, 0x0000001eu, + 0x00000bddu, 0x00000bc8u, 0x00000ea4u, 0x0004007cu, 0x00000006u, 0x00000bdfu, 0x00000bddu, 0x00060041u, + 0x0000004au, 0x00000c96u, 0x00000047u, 0x00000bcdu, 0x00000bdfu, 0x0004003du, 0x00000009u, 0x00000c97u, + 0x00000c96u, 0x00050080u, 0x0000001eu, 0x00000be8u, 0x00000bddu, 0x00000065u, 0x0004007cu, 0x00000006u, + 0x00000be9u, 0x00000be8u, 0x00060041u, 0x0000004au, 0x00000c9cu, 0x00000047u, 0x00000bcdu, 0x00000be9u, + 0x0004003du, 0x00000009u, 0x00000c9du, 0x00000c9cu, 0x0005008eu, 0x00000009u, 0x00000beeu, 0x00000c97u, + 0x00000278u, 0x00050041u, 0x0000000fu, 0x00000befu, 0x00000bb3u, 0x00000ea4u, 0x0003003eu, 0x00000befu, + 0x00000beeu, 0x00050080u, 0x0000001eu, 0x00000bf1u, 0x00000ea4u, 0x00000065u, 0x0005008eu, 0x00000009u, + 0x00000bf3u, 0x00000c9du, 0x0000027eu, 0x00050041u, 0x0000000fu, 0x00000bf4u, 0x00000bb3u, 0x00000bf1u, + 0x0003003eu, 0x00000bf4u, 0x00000bf3u, 0x00050080u, 0x0000001eu, 0x00000bf7u, 0x00000ea4u, 0x00000069u, + 0x000200f9u, 0x00000bd2u, 0x000200f8u, 0x00000bf8u, 0x000200f9u, 0x00000bf9u, 0x000200f8u, 0x00000bf9u, + 0x000700f5u, 0x0000001eu, 0x00000ea5u, 0x00000069u, 0x00000bf8u, 0x00000c0fu, 0x00000bfdu, 0x000500b1u, + 0x00000016u, 0x00000bfcu, 0x00000ea5u, 0x0000037au, 0x000400f6u, 0x00000c10u, 0x00000bfdu, 0x00000000u, + 0x000400fau, 0x00000bfcu, 0x00000bfdu, 0x00000c10u, 0x000200f8u, 0x00000bfdu, 0x00050082u, 0x0000001eu, + 0x00000c00u, 0x00000ea5u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c01u, 0x00000bb3u, 0x00000c00u, + 0x0004003du, 0x00000009u, 0x00000c02u, 0x00000c01u, 0x00050080u, 0x0000001eu, 0x00000c04u, 0x00000ea5u, + 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c05u, 0x00000bb3u, 0x00000c04u, 0x0004003du, 0x00000009u, + 0x00000c06u, 0x00000c05u, 0x00050081u, 0x00000009u, 0x00000c07u, 0x00000c02u, 0x00000c06u, 0x0005008eu, + 0x00000009u, 0x00000c08u, 0x00000c07u, 0x0000028du, 0x00050041u, 0x0000000fu, 0x00000c09u, 0x00000bb3u, + 0x00000ea5u, 0x0004003du, 0x00000009u, 0x00000c0au, 0x00000c09u, 0x00050083u, 0x00000009u, 0x00000c0bu, + 0x00000c0au, 0x00000c08u, 0x0003003eu, 0x00000c09u, 0x00000c0bu, 0x00050080u, 0x0000001eu, 0x00000c0fu, + 0x00000ea5u, 0x00000069u, 0x000200f9u, 0x00000bf9u, 0x000200f8u, 0x00000c10u, 0x000200f9u, 0x00000c11u, + 0x000200f8u, 0x00000c11u, 0x000700f5u, 0x0000001eu, 0x00000ea6u, 0x0000006cu, 0x00000c10u, 0x00000c27u, + 0x00000c15u, 0x000500b1u, 0x00000016u, 0x00000c14u, 0x00000ea6u, 0x00000394u, 0x000400f6u, 0x00000c28u, + 0x00000c15u, 0x00000000u, 0x000400fau, 0x00000c14u, 0x00000c15u, 0x00000c28u, 0x000200f8u, 0x00000c15u, + 0x00050082u, 0x0000001eu, 0x00000c18u, 0x00000ea6u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c19u, + 0x00000bb3u, 0x00000c18u, 0x0004003du, 0x00000009u, 0x00000c1au, 0x00000c19u, 0x00050080u, 0x0000001eu, + 0x00000c1cu, 0x00000ea6u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c1du, 0x00000bb3u, 0x00000c1cu, + 0x0004003du, 0x00000009u, 0x00000c1eu, 0x00000c1du, 0x00050081u, 0x00000009u, 0x00000c1fu, 0x00000c1au, + 0x00000c1eu, 0x0005008eu, 0x00000009u, 0x00000c20u, 0x00000c1fu, 0x000002a8u, 0x00050041u, 0x0000000fu, + 0x00000c21u, 0x00000bb3u, 0x00000ea6u, 0x0004003du, 0x00000009u, 0x00000c22u, 0x00000c21u, 0x00050083u, + 0x00000009u, 0x00000c23u, 0x00000c22u, 0x00000c20u, 0x0003003eu, 0x00000c21u, 0x00000c23u, 0x00050080u, + 0x0000001eu, 0x00000c27u, 0x00000ea6u, 0x00000069u, 0x000200f9u, 0x00000c11u, 0x000200f8u, 0x00000c28u, + 0x000200f9u, 0x00000c29u, 0x000200f8u, 0x00000c29u, 0x000700f5u, 0x0000001eu, 0x00000ea7u, 0x000002bau, + 0x00000c28u, 0x00000c3fu, 0x00000c2du, 0x000500b1u, 0x00000016u, 0x00000c2cu, 0x00000ea7u, 0x000003aeu, + 0x000400f6u, 0x00000c40u, 0x00000c2du, 0x00000000u, 0x000400fau, 0x00000c2cu, 0x00000c2du, 0x00000c40u, + 0x000200f8u, 0x00000c2du, 0x00050082u, 0x0000001eu, 0x00000c30u, 0x00000ea7u, 0x00000065u, 0x00050041u, + 0x0000000fu, 0x00000c31u, 0x00000bb3u, 0x00000c30u, 0x0004003du, 0x00000009u, 0x00000c32u, 0x00000c31u, + 0x00050080u, 0x0000001eu, 0x00000c34u, 0x00000ea7u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c35u, + 0x00000bb3u, 0x00000c34u, 0x0004003du, 0x00000009u, 0x00000c36u, 0x00000c35u, 0x00050081u, 0x00000009u, + 0x00000c37u, 0x00000c32u, 0x00000c36u, 0x0005008eu, 0x00000009u, 0x00000c38u, 0x00000c37u, 0x000002c4u, + 0x00050041u, 0x0000000fu, 0x00000c39u, 0x00000bb3u, 0x00000ea7u, 0x0004003du, 0x00000009u, 0x00000c3au, + 0x00000c39u, 0x00050083u, 0x00000009u, 0x00000c3bu, 0x00000c3au, 0x00000c38u, 0x0003003eu, 0x00000c39u, + 0x00000c3bu, 0x00050080u, 0x0000001eu, 0x00000c3fu, 0x00000ea7u, 0x00000069u, 0x000200f9u, 0x00000c29u, + 0x000200f8u, 0x00000c40u, 0x000200f9u, 0x00000c41u, 0x000200f8u, 0x00000c41u, 0x000700f5u, 0x0000001eu, + 0x00000ea8u, 0x00000072u, 0x00000c40u, 0x00000c57u, 0x00000c45u, 0x000500b1u, 0x00000016u, 0x00000c44u, + 0x00000ea8u, 0x000003c8u, 0x000400f6u, 0x00000c58u, 0x00000c45u, 0x00000000u, 0x000400fau, 0x00000c44u, + 0x00000c45u, 0x00000c58u, 0x000200f8u, 0x00000c45u, 0x00050082u, 0x0000001eu, 0x00000c48u, 0x00000ea8u, + 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c49u, 0x00000bb3u, 0x00000c48u, 0x0004003du, 0x00000009u, + 0x00000c4au, 0x00000c49u, 0x00050080u, 0x0000001eu, 0x00000c4cu, 0x00000ea8u, 0x00000065u, 0x00050041u, + 0x0000000fu, 0x00000c4du, 0x00000bb3u, 0x00000c4cu, 0x0004003du, 0x00000009u, 0x00000c4eu, 0x00000c4du, + 0x00050081u, 0x00000009u, 0x00000c4fu, 0x00000c4au, 0x00000c4eu, 0x0005008eu, 0x00000009u, 0x00000c50u, + 0x00000c4fu, 0x000002dfu, 0x00050041u, 0x0000000fu, 0x00000c51u, 0x00000bb3u, 0x00000ea8u, 0x0004003du, + 0x00000009u, 0x00000c52u, 0x00000c51u, 0x00050083u, 0x00000009u, 0x00000c53u, 0x00000c52u, 0x00000c50u, + 0x0003003eu, 0x00000c51u, 0x00000c53u, 0x00050080u, 0x0000001eu, 0x00000c57u, 0x00000ea8u, 0x00000069u, + 0x000200f9u, 0x00000c41u, 0x000200f8u, 0x00000c58u, 0x000200f9u, 0x00000c59u, 0x000200f8u, 0x00000c59u, + 0x000400e0u, 0x000000ffu, 0x000000ffu, 0x00000244u, 0x000300f7u, 0x00000c91u, 0x00000000u, 0x000400fau, + 0x00000426u, 0x00000c5bu, 0x00000c91u, 0x000200f8u, 0x00000c5bu, 0x000200f9u, 0x00000c5cu, 0x000200f8u, + 0x00000c5cu, 0x000700f5u, 0x0000001eu, 0x00000ea9u, 0x00000069u, 0x00000c5bu, 0x00000c8fu, 0x00000c60u, + 0x000500b1u, 0x00000016u, 0x00000c5fu, 0x00000ea9u, 0x000002bau, 0x000400f6u, 0x00000c90u, 0x00000c60u, + 0x00000000u, 0x000400fau, 0x00000c5fu, 0x00000c60u, 0x00000c90u, 0x000200f8u, 0x00000c60u, 0x00050084u, + 0x0000001eu, 0x00000c62u, 0x00000069u, 0x00000ea9u, 0x00050041u, 0x0000000fu, 0x00000c64u, 0x00000bb3u, + 0x00000c62u, 0x0004003du, 0x00000009u, 0x00000c65u, 0x00000c64u, 0x00050080u, 0x0000001eu, 0x00000c68u, + 0x00000c62u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000c69u, 0x00000bb3u, 0x00000c68u, 0x0004003du, + 0x00000009u, 0x00000c6au, 0x00000c69u, 0x00050051u, 0x00000008u, 0x00000c6cu, 0x00000c65u, 0x00000000u, + 0x00050051u, 0x00000008u, 0x00000c6eu, 0x00000c6au, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000c6fu, + 0x00000c6cu, 0x00000c6eu, 0x00050051u, 0x00000008u, 0x00000c71u, 0x00000c65u, 0x00000001u, 0x00050051u, + 0x00000008u, 0x00000c73u, 0x00000c6au, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000c74u, 0x00000c71u, + 0x00000c73u, 0x000500c3u, 0x0000001eu, 0x00000c77u, 0x00000bc8u, 0x00000065u, 0x00050082u, 0x0000001eu, + 0x00000c79u, 0x00000ea9u, 0x00000069u, 0x00050080u, 0x0000001eu, 0x00000c7au, 0x00000c77u, 0x00000c79u, + 0x0004007cu, 0x00000006u, 0x00000c7cu, 0x00000c7au, 0x00050084u, 0x0000001eu, 0x00000c7fu, 0x00000069u, + 0x00000bceu, 0x0004007cu, 0x00000006u, 0x00000c81u, 0x00000c7fu, 0x00060041u, 0x0000004au, 0x00000ca2u, + 0x00000047u, 0x00000c7cu, 0x00000c81u, 0x0003003eu, 0x00000ca2u, 0x00000c6fu, 0x00050080u, 0x0000001eu, + 0x00000c89u, 0x00000c7fu, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000c8au, 0x00000c89u, 0x00060041u, + 0x0000004au, 0x00000ca7u, 0x00000047u, 0x00000c7cu, 0x00000c8au, 0x0003003eu, 0x00000ca7u, 0x00000c74u, + 0x00050080u, 0x0000001eu, 0x00000c8fu, 0x00000ea9u, 0x00000065u, 0x000200f9u, 0x00000c5cu, 0x000200f8u, + 0x00000c90u, 0x000200f9u, 0x00000c91u, 0x000200f8u, 0x00000c91u, 0x000400e0u, 0x000000ffu, 0x000000ffu, + 0x00000244u, 0x000200f9u, 0x00000ccau, 0x000200f8u, 0x00000ccau, 0x000700f5u, 0x0000001eu, 0x00000eaau, + 0x00000064u, 0x00000c91u, 0x00000cefu, 0x00000cceu, 0x000500b1u, 0x00000016u, 0x00000ccdu, 0x00000eaau, + 0x00000148u, 0x000400f6u, 0x00000cf0u, 0x00000cceu, 0x00000000u, 0x000400fau, 0x00000ccdu, 0x00000cceu, + 0x00000cf0u, 0x000200f8u, 0x00000cceu, 0x00050080u, 0x0000001eu, 0x00000cd5u, 0x00000ad4u, 0x00000eaau, + 0x0004007cu, 0x00000006u, 0x00000cd7u, 0x00000cd5u, 0x00060041u, 0x0000004au, 0x00000d8au, 0x00000047u, + 0x00000ad6u, 0x00000cd7u, 0x0004003du, 0x00000009u, 0x00000d8bu, 0x00000d8au, 0x00050080u, 0x0000001eu, + 0x00000ce0u, 0x00000cd5u, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000ce1u, 0x00000ce0u, 0x00060041u, + 0x0000004au, 0x00000d90u, 0x00000047u, 0x00000ad6u, 0x00000ce1u, 0x0004003du, 0x00000009u, 0x00000d91u, + 0x00000d90u, 0x0005008eu, 0x00000009u, 0x00000ce6u, 0x00000d8bu, 0x00000278u, 0x00050041u, 0x0000000fu, + 0x00000ce7u, 0x00000cb0u, 0x00000eaau, 0x0003003eu, 0x00000ce7u, 0x00000ce6u, 0x00050080u, 0x0000001eu, + 0x00000ce9u, 0x00000eaau, 0x00000065u, 0x0005008eu, 0x00000009u, 0x00000cebu, 0x00000d91u, 0x0000027eu, + 0x00050041u, 0x0000000fu, 0x00000cecu, 0x00000cb0u, 0x00000ce9u, 0x0003003eu, 0x00000cecu, 0x00000cebu, + 0x00050080u, 0x0000001eu, 0x00000cefu, 0x00000eaau, 0x00000069u, 0x000200f9u, 0x00000ccau, 0x000200f8u, + 0x00000cf0u, 0x000200f9u, 0x00000cf1u, 0x000200f8u, 0x00000cf1u, 0x000700f5u, 0x0000001eu, 0x00000eabu, + 0x00000069u, 0x00000cf0u, 0x00000d07u, 0x00000cf5u, 0x000500b1u, 0x00000016u, 0x00000cf4u, 0x00000eabu, + 0x0000028au, 0x000400f6u, 0x00000d08u, 0x00000cf5u, 0x00000000u, 0x000400fau, 0x00000cf4u, 0x00000cf5u, + 0x00000d08u, 0x000200f8u, 0x00000cf5u, 0x00050082u, 0x0000001eu, 0x00000cf8u, 0x00000eabu, 0x00000065u, + 0x00050041u, 0x0000000fu, 0x00000cf9u, 0x00000cb0u, 0x00000cf8u, 0x0004003du, 0x00000009u, 0x00000cfau, + 0x00000cf9u, 0x00050080u, 0x0000001eu, 0x00000cfcu, 0x00000eabu, 0x00000065u, 0x00050041u, 0x0000000fu, + 0x00000cfdu, 0x00000cb0u, 0x00000cfcu, 0x0004003du, 0x00000009u, 0x00000cfeu, 0x00000cfdu, 0x00050081u, + 0x00000009u, 0x00000cffu, 0x00000cfau, 0x00000cfeu, 0x0005008eu, 0x00000009u, 0x00000d00u, 0x00000cffu, + 0x0000028du, 0x00050041u, 0x0000000fu, 0x00000d01u, 0x00000cb0u, 0x00000eabu, 0x0004003du, 0x00000009u, + 0x00000d02u, 0x00000d01u, 0x00050083u, 0x00000009u, 0x00000d03u, 0x00000d02u, 0x00000d00u, 0x0003003eu, + 0x00000d01u, 0x00000d03u, 0x00050080u, 0x0000001eu, 0x00000d07u, 0x00000eabu, 0x00000069u, 0x000200f9u, + 0x00000cf1u, 0x000200f8u, 0x00000d08u, 0x000200f9u, 0x00000d09u, 0x000200f8u, 0x00000d09u, 0x000700f5u, + 0x0000001eu, 0x00000eacu, 0x0000006cu, 0x00000d08u, 0x00000d1fu, 0x00000d0du, 0x000500b1u, 0x00000016u, + 0x00000d0cu, 0x00000eacu, 0x000002a5u, 0x000400f6u, 0x00000d20u, 0x00000d0du, 0x00000000u, 0x000400fau, + 0x00000d0cu, 0x00000d0du, 0x00000d20u, 0x000200f8u, 0x00000d0du, 0x00050082u, 0x0000001eu, 0x00000d10u, + 0x00000eacu, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d11u, 0x00000cb0u, 0x00000d10u, 0x0004003du, + 0x00000009u, 0x00000d12u, 0x00000d11u, 0x00050080u, 0x0000001eu, 0x00000d14u, 0x00000eacu, 0x00000065u, + 0x00050041u, 0x0000000fu, 0x00000d15u, 0x00000cb0u, 0x00000d14u, 0x0004003du, 0x00000009u, 0x00000d16u, + 0x00000d15u, 0x00050081u, 0x00000009u, 0x00000d17u, 0x00000d12u, 0x00000d16u, 0x0005008eu, 0x00000009u, + 0x00000d18u, 0x00000d17u, 0x000002a8u, 0x00050041u, 0x0000000fu, 0x00000d19u, 0x00000cb0u, 0x00000eacu, + 0x0004003du, 0x00000009u, 0x00000d1au, 0x00000d19u, 0x00050083u, 0x00000009u, 0x00000d1bu, 0x00000d1au, + 0x00000d18u, 0x0003003eu, 0x00000d19u, 0x00000d1bu, 0x00050080u, 0x0000001eu, 0x00000d1fu, 0x00000eacu, + 0x00000069u, 0x000200f9u, 0x00000d09u, 0x000200f8u, 0x00000d20u, 0x000200f9u, 0x00000d21u, 0x000200f8u, + 0x00000d21u, 0x000700f5u, 0x0000001eu, 0x00000eadu, 0x000002bau, 0x00000d20u, 0x00000d37u, 0x00000d25u, + 0x000500b1u, 0x00000016u, 0x00000d24u, 0x00000eadu, 0x000002c1u, 0x000400f6u, 0x00000d38u, 0x00000d25u, + 0x00000000u, 0x000400fau, 0x00000d24u, 0x00000d25u, 0x00000d38u, 0x000200f8u, 0x00000d25u, 0x00050082u, + 0x0000001eu, 0x00000d28u, 0x00000eadu, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d29u, 0x00000cb0u, + 0x00000d28u, 0x0004003du, 0x00000009u, 0x00000d2au, 0x00000d29u, 0x00050080u, 0x0000001eu, 0x00000d2cu, + 0x00000eadu, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d2du, 0x00000cb0u, 0x00000d2cu, 0x0004003du, + 0x00000009u, 0x00000d2eu, 0x00000d2du, 0x00050081u, 0x00000009u, 0x00000d2fu, 0x00000d2au, 0x00000d2eu, + 0x0005008eu, 0x00000009u, 0x00000d30u, 0x00000d2fu, 0x000002c4u, 0x00050041u, 0x0000000fu, 0x00000d31u, + 0x00000cb0u, 0x00000eadu, 0x0004003du, 0x00000009u, 0x00000d32u, 0x00000d31u, 0x00050083u, 0x00000009u, + 0x00000d33u, 0x00000d32u, 0x00000d30u, 0x0003003eu, 0x00000d31u, 0x00000d33u, 0x00050080u, 0x0000001eu, + 0x00000d37u, 0x00000eadu, 0x00000069u, 0x000200f9u, 0x00000d21u, 0x000200f8u, 0x00000d38u, 0x000200f9u, + 0x00000d39u, 0x000200f8u, 0x00000d39u, 0x000700f5u, 0x0000001eu, 0x00000eaeu, 0x00000072u, 0x00000d38u, + 0x00000d4fu, 0x00000d3du, 0x000500b1u, 0x00000016u, 0x00000d3cu, 0x00000eaeu, 0x000002dcu, 0x000400f6u, + 0x00000d50u, 0x00000d3du, 0x00000000u, 0x000400fau, 0x00000d3cu, 0x00000d3du, 0x00000d50u, 0x000200f8u, + 0x00000d3du, 0x00050082u, 0x0000001eu, 0x00000d40u, 0x00000eaeu, 0x00000065u, 0x00050041u, 0x0000000fu, + 0x00000d41u, 0x00000cb0u, 0x00000d40u, 0x0004003du, 0x00000009u, 0x00000d42u, 0x00000d41u, 0x00050080u, + 0x0000001eu, 0x00000d44u, 0x00000eaeu, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d45u, 0x00000cb0u, + 0x00000d44u, 0x0004003du, 0x00000009u, 0x00000d46u, 0x00000d45u, 0x00050081u, 0x00000009u, 0x00000d47u, + 0x00000d42u, 0x00000d46u, 0x0005008eu, 0x00000009u, 0x00000d48u, 0x00000d47u, 0x000002dfu, 0x00050041u, + 0x0000000fu, 0x00000d49u, 0x00000cb0u, 0x00000eaeu, 0x0004003du, 0x00000009u, 0x00000d4au, 0x00000d49u, + 0x00050083u, 0x00000009u, 0x00000d4bu, 0x00000d4au, 0x00000d48u, 0x0003003eu, 0x00000d49u, 0x00000d4bu, + 0x00050080u, 0x0000001eu, 0x00000d4fu, 0x00000eaeu, 0x00000069u, 0x000200f9u, 0x00000d39u, 0x000200f8u, + 0x00000d50u, 0x000400e0u, 0x000000ffu, 0x000000ffu, 0x00000244u, 0x000200f9u, 0x00000d51u, 0x000200f8u, + 0x00000d51u, 0x000700f5u, 0x0000001eu, 0x00000eafu, 0x00000069u, 0x00000d50u, 0x00000d84u, 0x00000d55u, + 0x000500b1u, 0x00000016u, 0x00000d54u, 0x00000eafu, 0x000002f7u, 0x000400f6u, 0x00000d85u, 0x00000d55u, + 0x00000000u, 0x000400fau, 0x00000d54u, 0x00000d55u, 0x00000d85u, 0x000200f8u, 0x00000d55u, 0x00050084u, + 0x0000001eu, 0x00000d57u, 0x00000069u, 0x00000eafu, 0x00050041u, 0x0000000fu, 0x00000d59u, 0x00000cb0u, + 0x00000d57u, 0x0004003du, 0x00000009u, 0x00000d5au, 0x00000d59u, 0x00050080u, 0x0000001eu, 0x00000d5du, + 0x00000d57u, 0x00000065u, 0x00050041u, 0x0000000fu, 0x00000d5eu, 0x00000cb0u, 0x00000d5du, 0x0004003du, + 0x00000009u, 0x00000d5fu, 0x00000d5eu, 0x00050051u, 0x00000008u, 0x00000d61u, 0x00000d5au, 0x00000000u, + 0x00050051u, 0x00000008u, 0x00000d63u, 0x00000d5fu, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000d64u, + 0x00000d61u, 0x00000d63u, 0x00050051u, 0x00000008u, 0x00000d66u, 0x00000d5au, 0x00000001u, 0x00050051u, + 0x00000008u, 0x00000d68u, 0x00000d5fu, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000d69u, 0x00000d66u, + 0x00000d68u, 0x000500c3u, 0x0000001eu, 0x00000d6cu, 0x00000ad4u, 0x00000065u, 0x00050082u, 0x0000001eu, + 0x00000d6eu, 0x00000eafu, 0x00000069u, 0x00050080u, 0x0000001eu, 0x00000d6fu, 0x00000d6cu, 0x00000d6eu, + 0x0004007cu, 0x00000006u, 0x00000d71u, 0x00000d6fu, 0x00050084u, 0x0000001eu, 0x00000d74u, 0x00000069u, + 0x00000ad7u, 0x0004007cu, 0x00000006u, 0x00000d76u, 0x00000d74u, 0x00060041u, 0x0000004au, 0x00000d96u, + 0x00000047u, 0x00000d71u, 0x00000d76u, 0x0003003eu, 0x00000d96u, 0x00000d64u, 0x00050080u, 0x0000001eu, + 0x00000d7eu, 0x00000d74u, 0x00000065u, 0x0004007cu, 0x00000006u, 0x00000d7fu, 0x00000d7eu, 0x00060041u, + 0x0000004au, 0x00000d9bu, 0x00000047u, 0x00000d71u, 0x00000d7fu, 0x0003003eu, 0x00000d9bu, 0x00000d69u, + 0x00050080u, 0x0000001eu, 0x00000d84u, 0x00000eafu, 0x00000065u, 0x000200f9u, 0x00000d51u, 0x000200f8u, + 0x00000d85u, 0x000400e0u, 0x000000ffu, 0x000000ffu, 0x00000244u, 0x000200f9u, 0x00000432u, 0x000200f8u, + 0x00000432u, 0x000700f5u, 0x0000001eu, 0x00000eb0u, 0x0000057eu, 0x00000d85u, 0x00000477u, 0x00000435u, + 0x000500b1u, 0x00000016u, 0x00000438u, 0x00000eb0u, 0x00000148u, 0x000400f6u, 0x00000434u, 0x00000435u, + 0x00000000u, 0x000400fau, 0x00000438u, 0x00000433u, 0x00000434u, 0x000200f8u, 0x00000433u, 0x000200f9u, + 0x0000043cu, 0x000200f8u, 0x0000043cu, 0x000700f5u, 0x0000001eu, 0x00000eb1u, 0x0000057cu, 0x00000433u, + 0x00000475u, 0x0000043fu, 0x000500b1u, 0x00000016u, 0x00000443u, 0x00000eb1u, 0x00000442u, 0x000400f6u, + 0x0000043eu, 0x0000043fu, 0x00000000u, 0x000400fau, 0x00000443u, 0x0000043du, 0x0000043eu, 0x000200f8u, + 0x0000043du, 0x0004007cu, 0x00000006u, 0x00000446u, 0x00000eb0u, 0x0004007cu, 0x00000006u, 0x00000448u, + 0x00000eb1u, 0x00060041u, 0x0000004au, 0x00000db7u, 0x00000047u, 0x00000446u, 0x00000448u, 0x0004003du, + 0x00000009u, 0x00000db8u, 0x00000db7u, 0x000300f7u, 0x0000044eu, 0x00000000u, 0x000400fau, 0x0000044cu, + 0x0000044du, 0x0000044eu, 0x000200f8u, 0x0000044du, 0x00050081u, 0x00000009u, 0x00000452u, 0x00000db8u, + 0x00000ebcu, 0x000200f9u, 0x0000044eu, 0x000200f8u, 0x0000044eu, 0x000700f5u, 0x00000009u, 0x00000eb5u, + 0x00000db8u, 0x0000043du, 0x00000452u, 0x0000044du, 0x0004003du, 0x00000453u, 0x00000456u, 0x00000455u, + 0x00050084u, 0x0000001eu, 0x00000458u, 0x00000069u, 0x00000eb0u, 0x00050050u, 0x0000001fu, 0x0000045bu, + 0x00000458u, 0x00000eb1u, 0x0007004fu, 0x00000144u, 0x0000045du, 0x000004b8u, 0x000004b8u, 0x00000001u, + 0x00000000u, 0x0004007cu, 0x0000001fu, 0x0000045eu, 0x0000045du, 0x00050084u, 0x0000001fu, 0x00000460u, + 0x00000ebdu, 0x0000045eu, 0x00050080u, 0x0000001fu, 0x00000461u, 0x0000045bu, 0x00000460u, 0x0009004fu, + 0x0000002eu, 0x00000463u, 0x00000eb5u, 0x00000eb5u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00040073u, 0x0000016au, 0x00000464u, 0x00000463u, 0x00040063u, 0x00000456u, 0x00000461u, 0x00000464u, + 0x0004003du, 0x00000453u, 0x00000465u, 0x00000455u, 0x00050080u, 0x0000001eu, 0x00000468u, 0x00000458u, + 0x00000065u, 0x00050050u, 0x0000001fu, 0x0000046au, 0x00000468u, 0x00000eb1u, 0x00050080u, 0x0000001fu, + 0x00000470u, 0x0000046au, 0x00000460u, 0x0009004fu, 0x0000002eu, 0x00000472u, 0x00000eb5u, 0x00000eb5u, + 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00040073u, 0x0000016au, 0x00000473u, 0x00000472u, + 0x00040063u, 0x00000465u, 0x00000470u, 0x00000473u, 0x000200f9u, 0x0000043fu, 0x000200f8u, 0x0000043fu, + 0x00050080u, 0x0000001eu, 0x00000475u, 0x00000eb1u, 0x000003c8u, 0x000200f9u, 0x0000043cu, 0x000200f8u, + 0x0000043eu, 0x000200f9u, 0x00000435u, 0x000200f8u, 0x00000435u, 0x00050080u, 0x0000001eu, 0x00000477u, + 0x00000eb0u, 0x000003c8u, 0x000200f9u, 0x00000432u, 0x000200f8u, 0x00000434u, 0x000100fdu, 0x00010038u, + 0x07230203u, 0x00010300u, 0x000d000bu, 0x00000ec9u, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, + 0x00000009u, 0x00020011u, 0x00000038u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, + 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0007000fu, 0x00000005u, 0x00000004u, 0x6e69616du, + 0x00000000u, 0x00000144u, 0x00000414u, 0x00060010u, 0x00000004u, 0x00000011u, 0x00000040u, 0x00000001u, + 0x00000001u, 0x00030047u, 0x00000096u, 0x00000002u, 0x00050048u, 0x00000096u, 0x00000000u, 0x00000023u, + 0x00000000u, 0x00050048u, 0x00000096u, 0x00000001u, 0x00000023u, 0x00000008u, 0x00040047u, 0x00000144u, + 0x0000000bu, 0x0000001au, 0x00030047u, 0x0000015eu, 0x00000000u, 0x00040047u, 0x0000015eu, 0x00000021u, + 0x00000000u, 0x00040047u, 0x0000015eu, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000414u, 0x0000000bu, + 0x0000001du, 0x00040047u, 0x00000440u, 0x00000001u, 0x00000000u, 0x00030047u, 0x00000449u, 0x00000000u, + 0x00030047u, 0x00000449u, 0x00000019u, 0x00040047u, 0x00000449u, 0x00000021u, 0x00000001u, 0x00040047u, + 0x00000449u, 0x00000022u, 0x00000000u, 0x00030047u, 0x0000044au, 0x00000000u, 0x00030047u, 0x00000458u, + 0x00000000u, 0x00040047u, 0x0000046bu, 0x0000000bu, 0x00000019u, 0x00030047u, 0x000004b7u, 0x00000000u, + 0x00030047u, 0x000004bdu, 0x00000000u, 0x00030047u, 0x000004bfu, 0x00000000u, 0x00030047u, 0x000004c5u, + 0x00000000u, 0x00030047u, 0x000004c7u, 0x00000000u, 0x00030047u, 0x000004cdu, 0x00000000u, 0x00030047u, + 0x000004cfu, 0x00000000u, 0x00030047u, 0x000004d5u, 0x00000000u, 0x00030047u, 0x000004ebu, 0x00000000u, + 0x00030047u, 0x000004f3u, 0x00000000u, 0x00030047u, 0x000004f5u, 0x00000000u, 0x00030047u, 0x000004fdu, + 0x00000000u, 0x00030047u, 0x000004ffu, 0x00000000u, 0x00030047u, 0x00000507u, 0x00000000u, 0x00030047u, + 0x00000509u, 0x00000000u, 0x00030047u, 0x00000511u, 0x00000000u, 0x00030047u, 0x00000520u, 0x00000000u, + 0x00030047u, 0x00000528u, 0x00000000u, 0x00030047u, 0x0000052au, 0x00000000u, 0x00030047u, 0x00000532u, + 0x00000000u, 0x00030047u, 0x00000534u, 0x00000000u, 0x00030047u, 0x0000053cu, 0x00000000u, 0x00030047u, + 0x0000053eu, 0x00000000u, 0x00030047u, 0x00000546u, 0x00000000u, 0x00020013u, 0x00000002u, 0x00030021u, + 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, 0x00000000u, 0x00030016u, 0x00000008u, + 0x00000020u, 0x00040017u, 0x00000009u, 0x00000008u, 0x00000002u, 0x00040020u, 0x0000000fu, 0x00000007u, + 0x00000009u, 0x00020014u, 0x00000016u, 0x00040017u, 0x00000017u, 0x00000016u, 0x00000002u, 0x00040015u, + 0x0000001eu, 0x00000020u, 0x00000001u, 0x00040017u, 0x0000001fu, 0x0000001eu, 0x00000002u, 0x00040017u, + 0x0000002cu, 0x00000008u, 0x00000004u, 0x00030016u, 0x00000040u, 0x00000010u, 0x00040017u, 0x00000041u, + 0x00000040u, 0x00000002u, 0x0004002bu, 0x00000006u, 0x00000042u, 0x00000029u, 0x0004001cu, 0x00000043u, + 0x00000041u, 0x00000042u, 0x0004002bu, 0x00000006u, 0x00000044u, 0x00000014u, 0x0004001cu, 0x00000045u, + 0x00000043u, 0x00000044u, 0x00040020u, 0x00000046u, 0x00000004u, 0x00000045u, 0x0004003bu, 0x00000046u, + 0x00000047u, 0x00000004u, 0x00040020u, 0x0000004au, 0x00000004u, 0x00000041u, 0x0004002bu, 0x00000006u, + 0x0000005bu, 0x00000001u, 0x0004002bu, 0x0000001eu, 0x00000066u, 0x00000000u, 0x0004002bu, 0x0000001eu, + 0x00000067u, 0x00000001u, 0x0004002bu, 0x0000001eu, 0x0000006bu, 0x00000002u, 0x0004002bu, 0x0000001eu, + 0x0000006eu, 0x00000003u, 0x0004002bu, 0x0000001eu, 0x00000074u, 0x00000005u, 0x0005002cu, 0x0000001fu, + 0x00000084u, 0x00000066u, 0x00000066u, 0x0005002cu, 0x0000001fu, 0x00000089u, 0x00000067u, 0x00000067u, + 0x0004001eu, 0x00000096u, 0x0000001fu, 0x00000009u, 0x00040020u, 0x00000097u, 0x00000009u, 0x00000096u, + 0x0004003bu, 0x00000097u, 0x00000098u, 0x00000009u, 0x00040020u, 0x00000099u, 0x00000009u, 0x0000001fu, + 0x00040020u, 0x000000a6u, 0x00000009u, 0x00000009u, 0x0004002bu, 0x00000006u, 0x00000100u, 0x00000002u, + 0x00040017u, 0x00000142u, 0x00000006u, 0x00000003u, 0x00040020u, 0x00000143u, 0x00000001u, 0x00000142u, + 0x0004003bu, 0x00000143u, 0x00000144u, 0x00000001u, 0x00040017u, 0x00000145u, 0x00000006u, 0x00000002u, + 0x0004002bu, 0x0000001eu, 0x00000149u, 0x00000010u, 0x0005002cu, 0x0000001fu, 0x0000014au, 0x00000149u, + 0x00000149u, 0x00090019u, 0x0000015bu, 0x00000008u, 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, + 0x00000001u, 0x00000000u, 0x0003001bu, 0x0000015cu, 0x0000015bu, 0x00040020u, 0x0000015du, 0x00000000u, + 0x0000015cu, 0x0004003bu, 0x0000015du, 0x0000015eu, 0x00000000u, 0x0004002bu, 0x00000008u, 0x00000166u, + 0x00000000u, 0x00040017u, 0x00000167u, 0x00000008u, 0x00000003u, 0x0003002au, 0x00000016u, 0x0000016fu, + 0x0004002bu, 0x00000008u, 0x00000175u, 0x40000000u, 0x0004002bu, 0x00000008u, 0x00000182u, 0x3f800000u, + 0x0004002bu, 0x00000008u, 0x0000018fu, 0x40400000u, 0x0004002bu, 0x00000006u, 0x000001a1u, 0x00000010u, + 0x0004002bu, 0x0000001eu, 0x000001aeu, 0x00000014u, 0x0004002bu, 0x00000006u, 0x00000238u, 0x00000108u, + 0x0004002bu, 0x00000006u, 0x0000023au, 0x00000008u, 0x0004002bu, 0x00000006u, 0x0000023cu, 0x00000004u, + 0x0004001cu, 0x00000266u, 0x00000009u, 0x000001a1u, 0x00040020u, 0x00000267u, 0x00000007u, 0x00000266u, + 0x0004002bu, 0x00000008u, 0x0000026cu, 0x3f9d7658u, 0x0004002bu, 0x00000008u, 0x00000272u, 0x3f5019c3u, + 0x0004002bu, 0x0000001eu, 0x0000027eu, 0x0000000fu, 0x0004002bu, 0x00000008u, 0x00000281u, 0x3ee31355u, + 0x0004002bu, 0x0000001eu, 0x00000299u, 0x0000000eu, 0x0004002bu, 0x00000008u, 0x0000029cu, 0x3f620676u, + 0x0004002bu, 0x0000001eu, 0x000002aeu, 0x00000004u, 0x0004002bu, 0x0000001eu, 0x000002b5u, 0x0000000du, + 0x0004002bu, 0x00000008u, 0x000002b8u, 0xbd5901aeu, 0x0004002bu, 0x0000001eu, 0x000002d0u, 0x0000000cu, + 0x0004002bu, 0x00000008u, 0x000002d3u, 0xbfcb0673u, 0x0004002bu, 0x0000001eu, 0x000002ebu, 0x00000006u, + 0x0004002bu, 0x00000006u, 0x00000357u, 0x0000000cu, 0x0004001cu, 0x00000358u, 0x00000009u, 0x00000357u, + 0x00040020u, 0x00000359u, 0x00000007u, 0x00000358u, 0x0004002bu, 0x0000001eu, 0x0000036eu, 0x0000000bu, + 0x0004002bu, 0x0000001eu, 0x00000388u, 0x0000000au, 0x0004002bu, 0x0000001eu, 0x000003a2u, 0x00000009u, + 0x0004002bu, 0x0000001eu, 0x000003bcu, 0x00000008u, 0x00040020u, 0x00000413u, 0x00000001u, 0x00000006u, + 0x0004003bu, 0x00000413u, 0x00000414u, 0x00000001u, 0x0004002bu, 0x00000006u, 0x00000419u, 0x00000020u, + 0x0004002bu, 0x0000001eu, 0x00000436u, 0x00000020u, 0x00030031u, 0x00000016u, 0x00000440u, 0x0004002bu, + 0x00000008u, 0x00000443u, 0x3f000000u, 0x00090019u, 0x00000447u, 0x00000008u, 0x00000001u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000002u, 0x00000000u, 0x00040020u, 0x00000448u, 0x00000000u, 0x00000447u, + 0x0004003bu, 0x00000448u, 0x00000449u, 0x00000000u, 0x0004002bu, 0x00000006u, 0x0000046au, 0x00000040u, + 0x0006002cu, 0x00000142u, 0x0000046bu, 0x0000046au, 0x0000005bu, 0x0000005bu, 0x0005002cu, 0x0000001fu, + 0x00000ec1u, 0x0000006bu, 0x0000006bu, 0x0005002cu, 0x00000009u, 0x00000ec7u, 0x00000443u, 0x00000443u, + 0x0005002cu, 0x0000001fu, 0x00000ec8u, 0x00000436u, 0x00000436u, 0x00050036u, 0x00000002u, 0x00000004u, + 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, 0x00000267u, 0x00000cb6u, 0x00000007u, + 0x0004003bu, 0x00000359u, 0x00000bb5u, 0x00000007u, 0x0004003bu, 0x00000267u, 0x00000abdu, 0x00000007u, + 0x0004003du, 0x00000006u, 0x00000415u, 0x00000414u, 0x0004003du, 0x00000142u, 0x000004aau, 0x00000144u, + 0x0007004fu, 0x00000145u, 0x000004abu, 0x000004aau, 0x000004aau, 0x00000000u, 0x00000001u, 0x0004007cu, + 0x0000001fu, 0x000004acu, 0x000004abu, 0x00050084u, 0x0000001fu, 0x000004adu, 0x000004acu, 0x0000014au, + 0x00050082u, 0x0000001fu, 0x000004afu, 0x000004adu, 0x00000ec1u, 0x000600cbu, 0x00000006u, 0x00000554u, + 0x00000415u, 0x00000066u, 0x00000067u, 0x000600cbu, 0x00000006u, 0x00000556u, 0x00000415u, 0x00000067u, + 0x0000006bu, 0x000600cbu, 0x00000006u, 0x00000558u, 0x00000415u, 0x0000006eu, 0x0000006bu, 0x000500c4u, + 0x00000006u, 0x00000559u, 0x00000558u, 0x00000067u, 0x000500c5u, 0x00000006u, 0x0000055bu, 0x00000554u, + 0x00000559u, 0x000600cbu, 0x00000006u, 0x0000055du, 0x00000415u, 0x00000074u, 0x00000067u, 0x000500c4u, + 0x00000006u, 0x0000055eu, 0x0000055du, 0x0000006bu, 0x000500c5u, 0x00000006u, 0x00000560u, 0x00000556u, + 0x0000055eu, 0x0004007cu, 0x0000001eu, 0x00000562u, 0x00000560u, 0x0004007cu, 0x0000001eu, 0x00000564u, + 0x0000055bu, 0x00050050u, 0x0000001fu, 0x00000565u, 0x00000562u, 0x00000564u, 0x00050084u, 0x0000001fu, + 0x000004b3u, 0x00000ec1u, 0x00000565u, 0x00050080u, 0x0000001fu, 0x000004b6u, 0x000004afu, 0x000004b3u, + 0x0004003du, 0x0000015cu, 0x000004b7u, 0x0000015eu, 0x000500b1u, 0x00000017u, 0x00000571u, 0x000004b6u, + 0x00000084u, 0x00050051u, 0x00000016u, 0x00000592u, 0x00000571u, 0x00000000u, 0x00050051u, 0x00000016u, + 0x00000597u, 0x00000571u, 0x00000001u, 0x000600a9u, 0x0000001fu, 0x00000573u, 0x00000571u, 0x00000089u, + 0x00000084u, 0x00050082u, 0x0000001fu, 0x00000575u, 0x000004b6u, 0x00000573u, 0x00050080u, 0x0000001fu, + 0x00000578u, 0x00000575u, 0x00000089u, 0x0004006fu, 0x00000009u, 0x00000587u, 0x00000578u, 0x00050041u, + 0x000000a6u, 0x00000588u, 0x00000098u, 0x00000067u, 0x0004003du, 0x00000009u, 0x00000589u, 0x00000588u, + 0x00050085u, 0x00000009u, 0x0000058au, 0x00000587u, 0x00000589u, 0x00050051u, 0x00000008u, 0x000004bau, + 0x0000058au, 0x00000001u, 0x00050051u, 0x00000008u, 0x000004bbu, 0x0000058au, 0x00000000u, 0x00060050u, + 0x00000167u, 0x000004bcu, 0x000004bau, 0x000004bbu, 0x00000166u, 0x00060060u, 0x0000002cu, 0x000004bdu, + 0x000004b7u, 0x000004bcu, 0x00000066u, 0x0004003du, 0x0000015cu, 0x000004bfu, 0x0000015eu, 0x00050050u, + 0x00000017u, 0x000005dau, 0x0000016fu, 0x00000597u, 0x000600a9u, 0x0000001fu, 0x000005b4u, 0x000005dau, + 0x00000089u, 0x00000084u, 0x00050082u, 0x0000001fu, 0x000005b6u, 0x000004b6u, 0x000005b4u, 0x00050080u, + 0x0000001fu, 0x000005b9u, 0x000005b6u, 0x00000089u, 0x00050041u, 0x00000099u, 0x000005c0u, 0x00000098u, + 0x00000066u, 0x0004003du, 0x0000001fu, 0x000005c1u, 0x000005c0u, 0x000500afu, 0x00000017u, 0x000005c2u, + 0x000005b9u, 0x000005c1u, 0x00050051u, 0x00000016u, 0x000005e0u, 0x000005c2u, 0x00000000u, 0x00050050u, + 0x00000017u, 0x000005e7u, 0x000005e0u, 0x0000016fu, 0x000600a9u, 0x0000001fu, 0x000005c4u, 0x000005e7u, + 0x00000089u, 0x00000084u, 0x00050080u, 0x0000001fu, 0x000005c6u, 0x000005b9u, 0x000005c4u, 0x0004006fu, + 0x00000009u, 0x000005c8u, 0x000005c6u, 0x00050085u, 0x00000009u, 0x000005cbu, 0x000005c8u, 0x00000589u, + 0x00050051u, 0x00000008u, 0x000004c2u, 0x000005cbu, 0x00000001u, 0x00050051u, 0x00000008u, 0x000004c3u, + 0x000005cbu, 0x00000000u, 0x00060050u, 0x00000167u, 0x000004c4u, 0x000004c2u, 0x000004c3u, 0x00000175u, + 0x00060060u, 0x0000002cu, 0x000004c5u, 0x000004bfu, 0x000004c4u, 0x00000066u, 0x0004003du, 0x0000015cu, + 0x000004c7u, 0x0000015eu, 0x00050050u, 0x00000017u, 0x0000061bu, 0x00000592u, 0x0000016fu, 0x000600a9u, + 0x0000001fu, 0x000005f5u, 0x0000061bu, 0x00000089u, 0x00000084u, 0x00050082u, 0x0000001fu, 0x000005f7u, + 0x000004b6u, 0x000005f5u, 0x00050080u, 0x0000001fu, 0x000005fau, 0x000005f7u, 0x00000089u, 0x000500afu, + 0x00000017u, 0x00000603u, 0x000005fau, 0x000005c1u, 0x00050051u, 0x00000016u, 0x00000626u, 0x00000603u, + 0x00000001u, 0x00050050u, 0x00000017u, 0x00000628u, 0x0000016fu, 0x00000626u, 0x000600a9u, 0x0000001fu, + 0x00000605u, 0x00000628u, 0x00000089u, 0x00000084u, 0x00050080u, 0x0000001fu, 0x00000607u, 0x000005fau, + 0x00000605u, 0x0004006fu, 0x00000009u, 0x00000609u, 0x00000607u, 0x00050085u, 0x00000009u, 0x0000060cu, + 0x00000609u, 0x00000589u, 0x00050051u, 0x00000008u, 0x000004cau, 0x0000060cu, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000004cbu, 0x0000060cu, 0x00000000u, 0x00060050u, 0x00000167u, 0x000004ccu, 0x000004cau, + 0x000004cbu, 0x00000182u, 0x00060060u, 0x0000002cu, 0x000004cdu, 0x000004c7u, 0x000004ccu, 0x00000066u, + 0x0004003du, 0x0000015cu, 0x000004cfu, 0x0000015eu, 0x00050080u, 0x0000001fu, 0x0000063bu, 0x000004b6u, + 0x00000089u, 0x000500afu, 0x00000017u, 0x00000644u, 0x0000063bu, 0x000005c1u, 0x000600a9u, 0x0000001fu, + 0x00000646u, 0x00000644u, 0x00000089u, 0x00000084u, 0x00050080u, 0x0000001fu, 0x00000648u, 0x0000063bu, + 0x00000646u, 0x0004006fu, 0x00000009u, 0x0000064au, 0x00000648u, 0x00050085u, 0x00000009u, 0x0000064du, + 0x0000064au, 0x00000589u, 0x00050051u, 0x00000008u, 0x000004d2u, 0x0000064du, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000004d3u, 0x0000064du, 0x00000000u, 0x00060050u, 0x00000167u, 0x000004d4u, 0x000004d2u, + 0x000004d3u, 0x0000018fu, 0x00060060u, 0x0000002cu, 0x000004d5u, 0x000004cfu, 0x000004d4u, 0x00000066u, + 0x00050051u, 0x0000001eu, 0x00000684u, 0x000004b3u, 0x00000001u, 0x0004007cu, 0x00000006u, 0x00000686u, + 0x00000684u, 0x00050051u, 0x0000001eu, 0x00000688u, 0x000004b3u, 0x00000000u, 0x00050084u, 0x0000001eu, + 0x00000689u, 0x0000006bu, 0x00000688u, 0x0004007cu, 0x00000006u, 0x0000068bu, 0x00000689u, 0x00050051u, + 0x00000008u, 0x0000068du, 0x000004bdu, 0x00000003u, 0x00050051u, 0x00000008u, 0x0000068fu, 0x000004cdu, + 0x00000003u, 0x00050050u, 0x00000009u, 0x00000690u, 0x0000068du, 0x0000068fu, 0x00040073u, 0x00000041u, + 0x000006ffu, 0x00000690u, 0x00060041u, 0x0000004au, 0x00000700u, 0x00000047u, 0x00000686u, 0x0000068bu, + 0x0003003eu, 0x00000700u, 0x000006ffu, 0x00050080u, 0x0000001eu, 0x00000699u, 0x00000689u, 0x00000067u, + 0x0004007cu, 0x00000006u, 0x0000069au, 0x00000699u, 0x00050051u, 0x00000008u, 0x0000069cu, 0x000004c5u, + 0x00000003u, 0x00050051u, 0x00000008u, 0x0000069eu, 0x000004d5u, 0x00000003u, 0x00050050u, 0x00000009u, + 0x0000069fu, 0x0000069cu, 0x0000069eu, 0x00040073u, 0x00000041u, 0x00000705u, 0x0000069fu, 0x00060041u, + 0x0000004au, 0x00000706u, 0x00000047u, 0x00000686u, 0x0000069au, 0x0003003eu, 0x00000706u, 0x00000705u, + 0x00050080u, 0x0000001eu, 0x000006a8u, 0x00000689u, 0x0000006bu, 0x0004007cu, 0x00000006u, 0x000006a9u, + 0x000006a8u, 0x00050051u, 0x00000008u, 0x000006abu, 0x000004bdu, 0x00000000u, 0x00050051u, 0x00000008u, + 0x000006adu, 0x000004cdu, 0x00000000u, 0x00050050u, 0x00000009u, 0x000006aeu, 0x000006abu, 0x000006adu, + 0x00040073u, 0x00000041u, 0x0000070bu, 0x000006aeu, 0x00060041u, 0x0000004au, 0x0000070cu, 0x00000047u, + 0x00000686u, 0x000006a9u, 0x0003003eu, 0x0000070cu, 0x0000070bu, 0x00050080u, 0x0000001eu, 0x000006b7u, + 0x00000689u, 0x0000006eu, 0x0004007cu, 0x00000006u, 0x000006b8u, 0x000006b7u, 0x00050051u, 0x00000008u, + 0x000006bau, 0x000004c5u, 0x00000000u, 0x00050051u, 0x00000008u, 0x000006bcu, 0x000004d5u, 0x00000000u, + 0x00050050u, 0x00000009u, 0x000006bdu, 0x000006bau, 0x000006bcu, 0x00040073u, 0x00000041u, 0x00000711u, + 0x000006bdu, 0x00060041u, 0x0000004au, 0x00000712u, 0x00000047u, 0x00000686u, 0x000006b8u, 0x0003003eu, + 0x00000712u, 0x00000711u, 0x00050080u, 0x0000001eu, 0x000006c1u, 0x00000684u, 0x00000067u, 0x0004007cu, + 0x00000006u, 0x000006c2u, 0x000006c1u, 0x00050051u, 0x00000008u, 0x000006c9u, 0x000004bdu, 0x00000002u, + 0x00050051u, 0x00000008u, 0x000006cbu, 0x000004cdu, 0x00000002u, 0x00050050u, 0x00000009u, 0x000006ccu, + 0x000006c9u, 0x000006cbu, 0x00040073u, 0x00000041u, 0x00000717u, 0x000006ccu, 0x00060041u, 0x0000004au, + 0x00000718u, 0x00000047u, 0x000006c2u, 0x0000068bu, 0x0003003eu, 0x00000718u, 0x00000717u, 0x00050051u, + 0x00000008u, 0x000006d8u, 0x000004c5u, 0x00000002u, 0x00050051u, 0x00000008u, 0x000006dau, 0x000004d5u, + 0x00000002u, 0x00050050u, 0x00000009u, 0x000006dbu, 0x000006d8u, 0x000006dau, 0x00040073u, 0x00000041u, + 0x0000071du, 0x000006dbu, 0x00060041u, 0x0000004au, 0x0000071eu, 0x00000047u, 0x000006c2u, 0x0000069au, + 0x0003003eu, 0x0000071eu, 0x0000071du, 0x00050051u, 0x00000008u, 0x000006e7u, 0x000004bdu, 0x00000001u, + 0x00050051u, 0x00000008u, 0x000006e9u, 0x000004cdu, 0x00000001u, 0x00050050u, 0x00000009u, 0x000006eau, + 0x000006e7u, 0x000006e9u, 0x00040073u, 0x00000041u, 0x00000723u, 0x000006eau, 0x00060041u, 0x0000004au, + 0x00000724u, 0x00000047u, 0x000006c2u, 0x000006a9u, 0x0003003eu, 0x00000724u, 0x00000723u, 0x00050051u, + 0x00000008u, 0x000006f6u, 0x000004c5u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000006f8u, 0x000004d5u, + 0x00000001u, 0x00050050u, 0x00000009u, 0x000006f9u, 0x000006f6u, 0x000006f8u, 0x00040073u, 0x00000041u, + 0x00000729u, 0x000006f9u, 0x00060041u, 0x0000004au, 0x0000072au, 0x00000047u, 0x000006c2u, 0x000006b8u, + 0x0003003eu, 0x0000072au, 0x00000729u, 0x00050089u, 0x00000006u, 0x000004deu, 0x00000415u, 0x00000100u, + 0x00050084u, 0x00000006u, 0x000004dfu, 0x00000100u, 0x000004deu, 0x00050080u, 0x00000006u, 0x000004e0u, + 0x000001a1u, 0x000004dfu, 0x0004007cu, 0x0000001eu, 0x000004e1u, 0x000004e0u, 0x00050086u, 0x00000006u, + 0x000004e3u, 0x00000415u, 0x00000100u, 0x00050084u, 0x00000006u, 0x000004e4u, 0x00000100u, 0x000004e3u, + 0x0004007cu, 0x0000001eu, 0x000004e5u, 0x000004e4u, 0x00050050u, 0x0000001fu, 0x000004e6u, 0x000004e1u, + 0x000004e5u, 0x000500b1u, 0x00000016u, 0x000004e9u, 0x000004e5u, 0x000001aeu, 0x000300f7u, 0x00000519u, + 0x00000000u, 0x000400fau, 0x000004e9u, 0x000004eau, 0x00000519u, 0x000200f8u, 0x000004eau, 0x0004003du, + 0x0000015cu, 0x000004ebu, 0x0000015eu, 0x00050080u, 0x0000001fu, 0x000004eeu, 0x000004afu, 0x000004e6u, + 0x000500b1u, 0x00000017u, 0x00000736u, 0x000004eeu, 0x00000084u, 0x00050051u, 0x00000016u, 0x00000757u, + 0x00000736u, 0x00000000u, 0x00050051u, 0x00000016u, 0x0000075cu, 0x00000736u, 0x00000001u, 0x000600a9u, + 0x0000001fu, 0x00000738u, 0x00000736u, 0x00000089u, 0x00000084u, 0x00050082u, 0x0000001fu, 0x0000073au, + 0x000004eeu, 0x00000738u, 0x00050080u, 0x0000001fu, 0x0000073du, 0x0000073au, 0x00000089u, 0x0004006fu, + 0x00000009u, 0x0000074cu, 0x0000073du, 0x00050085u, 0x00000009u, 0x0000074fu, 0x0000074cu, 0x00000589u, + 0x00050051u, 0x00000008u, 0x000004f0u, 0x0000074fu, 0x00000001u, 0x00050051u, 0x00000008u, 0x000004f1u, + 0x0000074fu, 0x00000000u, 0x00060050u, 0x00000167u, 0x000004f2u, 0x000004f0u, 0x000004f1u, 0x00000166u, + 0x00060060u, 0x0000002cu, 0x000004f3u, 0x000004ebu, 0x000004f2u, 0x00000066u, 0x0004003du, 0x0000015cu, + 0x000004f5u, 0x0000015eu, 0x00050050u, 0x00000017u, 0x0000079fu, 0x0000016fu, 0x0000075cu, 0x000600a9u, + 0x0000001fu, 0x00000779u, 0x0000079fu, 0x00000089u, 0x00000084u, 0x00050082u, 0x0000001fu, 0x0000077bu, + 0x000004eeu, 0x00000779u, 0x00050080u, 0x0000001fu, 0x0000077eu, 0x0000077bu, 0x00000089u, 0x000500afu, + 0x00000017u, 0x00000787u, 0x0000077eu, 0x000005c1u, 0x00050051u, 0x00000016u, 0x000007a5u, 0x00000787u, + 0x00000000u, 0x00050050u, 0x00000017u, 0x000007acu, 0x000007a5u, 0x0000016fu, 0x000600a9u, 0x0000001fu, + 0x00000789u, 0x000007acu, 0x00000089u, 0x00000084u, 0x00050080u, 0x0000001fu, 0x0000078bu, 0x0000077eu, + 0x00000789u, 0x0004006fu, 0x00000009u, 0x0000078du, 0x0000078bu, 0x00050085u, 0x00000009u, 0x00000790u, + 0x0000078du, 0x00000589u, 0x00050051u, 0x00000008u, 0x000004fau, 0x00000790u, 0x00000001u, 0x00050051u, + 0x00000008u, 0x000004fbu, 0x00000790u, 0x00000000u, 0x00060050u, 0x00000167u, 0x000004fcu, 0x000004fau, + 0x000004fbu, 0x00000175u, 0x00060060u, 0x0000002cu, 0x000004fdu, 0x000004f5u, 0x000004fcu, 0x00000066u, + 0x0004003du, 0x0000015cu, 0x000004ffu, 0x0000015eu, 0x00050050u, 0x00000017u, 0x000007e0u, 0x00000757u, + 0x0000016fu, 0x000600a9u, 0x0000001fu, 0x000007bau, 0x000007e0u, 0x00000089u, 0x00000084u, 0x00050082u, + 0x0000001fu, 0x000007bcu, 0x000004eeu, 0x000007bau, 0x00050080u, 0x0000001fu, 0x000007bfu, 0x000007bcu, + 0x00000089u, 0x000500afu, 0x00000017u, 0x000007c8u, 0x000007bfu, 0x000005c1u, 0x00050051u, 0x00000016u, + 0x000007ebu, 0x000007c8u, 0x00000001u, 0x00050050u, 0x00000017u, 0x000007edu, 0x0000016fu, 0x000007ebu, + 0x000600a9u, 0x0000001fu, 0x000007cau, 0x000007edu, 0x00000089u, 0x00000084u, 0x00050080u, 0x0000001fu, + 0x000007ccu, 0x000007bfu, 0x000007cau, 0x0004006fu, 0x00000009u, 0x000007ceu, 0x000007ccu, 0x00050085u, + 0x00000009u, 0x000007d1u, 0x000007ceu, 0x00000589u, 0x00050051u, 0x00000008u, 0x00000504u, 0x000007d1u, + 0x00000001u, 0x00050051u, 0x00000008u, 0x00000505u, 0x000007d1u, 0x00000000u, 0x00060050u, 0x00000167u, + 0x00000506u, 0x00000504u, 0x00000505u, 0x00000182u, 0x00060060u, 0x0000002cu, 0x00000507u, 0x000004ffu, + 0x00000506u, 0x00000066u, 0x0004003du, 0x0000015cu, 0x00000509u, 0x0000015eu, 0x00050080u, 0x0000001fu, + 0x00000800u, 0x000004eeu, 0x00000089u, 0x000500afu, 0x00000017u, 0x00000809u, 0x00000800u, 0x000005c1u, + 0x000600a9u, 0x0000001fu, 0x0000080bu, 0x00000809u, 0x00000089u, 0x00000084u, 0x00050080u, 0x0000001fu, + 0x0000080du, 0x00000800u, 0x0000080bu, 0x0004006fu, 0x00000009u, 0x0000080fu, 0x0000080du, 0x00050085u, + 0x00000009u, 0x00000812u, 0x0000080fu, 0x00000589u, 0x00050051u, 0x00000008u, 0x0000050eu, 0x00000812u, + 0x00000001u, 0x00050051u, 0x00000008u, 0x0000050fu, 0x00000812u, 0x00000000u, 0x00060050u, 0x00000167u, + 0x00000510u, 0x0000050eu, 0x0000050fu, 0x0000018fu, 0x00060060u, 0x0000002cu, 0x00000511u, 0x00000509u, + 0x00000510u, 0x00000066u, 0x00050084u, 0x0000001eu, 0x0000084eu, 0x0000006bu, 0x000004e1u, 0x0004007cu, + 0x00000006u, 0x00000850u, 0x0000084eu, 0x00050051u, 0x00000008u, 0x00000852u, 0x000004f3u, 0x00000003u, + 0x00050051u, 0x00000008u, 0x00000854u, 0x00000507u, 0x00000003u, 0x00050050u, 0x00000009u, 0x00000855u, + 0x00000852u, 0x00000854u, 0x00040073u, 0x00000041u, 0x000008c4u, 0x00000855u, 0x00060041u, 0x0000004au, + 0x000008c5u, 0x00000047u, 0x000004e4u, 0x00000850u, 0x0003003eu, 0x000008c5u, 0x000008c4u, 0x00050080u, + 0x0000001eu, 0x0000085eu, 0x0000084eu, 0x00000067u, 0x0004007cu, 0x00000006u, 0x0000085fu, 0x0000085eu, + 0x00050051u, 0x00000008u, 0x00000861u, 0x000004fdu, 0x00000003u, 0x00050051u, 0x00000008u, 0x00000863u, + 0x00000511u, 0x00000003u, 0x00050050u, 0x00000009u, 0x00000864u, 0x00000861u, 0x00000863u, 0x00040073u, + 0x00000041u, 0x000008cau, 0x00000864u, 0x00060041u, 0x0000004au, 0x000008cbu, 0x00000047u, 0x000004e4u, + 0x0000085fu, 0x0003003eu, 0x000008cbu, 0x000008cau, 0x00050080u, 0x0000001eu, 0x0000086du, 0x0000084eu, + 0x0000006bu, 0x0004007cu, 0x00000006u, 0x0000086eu, 0x0000086du, 0x00050051u, 0x00000008u, 0x00000870u, + 0x000004f3u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000872u, 0x00000507u, 0x00000000u, 0x00050050u, + 0x00000009u, 0x00000873u, 0x00000870u, 0x00000872u, 0x00040073u, 0x00000041u, 0x000008d0u, 0x00000873u, + 0x00060041u, 0x0000004au, 0x000008d1u, 0x00000047u, 0x000004e4u, 0x0000086eu, 0x0003003eu, 0x000008d1u, + 0x000008d0u, 0x00050080u, 0x0000001eu, 0x0000087cu, 0x0000084eu, 0x0000006eu, 0x0004007cu, 0x00000006u, + 0x0000087du, 0x0000087cu, 0x00050051u, 0x00000008u, 0x0000087fu, 0x000004fdu, 0x00000000u, 0x00050051u, + 0x00000008u, 0x00000881u, 0x00000511u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000882u, 0x0000087fu, + 0x00000881u, 0x00040073u, 0x00000041u, 0x000008d6u, 0x00000882u, 0x00060041u, 0x0000004au, 0x000008d7u, + 0x00000047u, 0x000004e4u, 0x0000087du, 0x0003003eu, 0x000008d7u, 0x000008d6u, 0x00050080u, 0x0000001eu, + 0x00000886u, 0x000004e5u, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000887u, 0x00000886u, 0x00050051u, + 0x00000008u, 0x0000088eu, 0x000004f3u, 0x00000002u, 0x00050051u, 0x00000008u, 0x00000890u, 0x00000507u, + 0x00000002u, 0x00050050u, 0x00000009u, 0x00000891u, 0x0000088eu, 0x00000890u, 0x00040073u, 0x00000041u, + 0x000008dcu, 0x00000891u, 0x00060041u, 0x0000004au, 0x000008ddu, 0x00000047u, 0x00000887u, 0x00000850u, + 0x0003003eu, 0x000008ddu, 0x000008dcu, 0x00050051u, 0x00000008u, 0x0000089du, 0x000004fdu, 0x00000002u, + 0x00050051u, 0x00000008u, 0x0000089fu, 0x00000511u, 0x00000002u, 0x00050050u, 0x00000009u, 0x000008a0u, + 0x0000089du, 0x0000089fu, 0x00040073u, 0x00000041u, 0x000008e2u, 0x000008a0u, 0x00060041u, 0x0000004au, + 0x000008e3u, 0x00000047u, 0x00000887u, 0x0000085fu, 0x0003003eu, 0x000008e3u, 0x000008e2u, 0x00050051u, + 0x00000008u, 0x000008acu, 0x000004f3u, 0x00000001u, 0x00050051u, 0x00000008u, 0x000008aeu, 0x00000507u, + 0x00000001u, 0x00050050u, 0x00000009u, 0x000008afu, 0x000008acu, 0x000008aeu, 0x00040073u, 0x00000041u, + 0x000008e8u, 0x000008afu, 0x00060041u, 0x0000004au, 0x000008e9u, 0x00000047u, 0x00000887u, 0x0000086eu, + 0x0003003eu, 0x000008e9u, 0x000008e8u, 0x00050051u, 0x00000008u, 0x000008bbu, 0x000004fdu, 0x00000001u, + 0x00050051u, 0x00000008u, 0x000008bdu, 0x00000511u, 0x00000001u, 0x00050050u, 0x00000009u, 0x000008beu, + 0x000008bbu, 0x000008bdu, 0x00040073u, 0x00000041u, 0x000008eeu, 0x000008beu, 0x00060041u, 0x0000004au, + 0x000008efu, 0x00000047u, 0x00000887u, 0x0000087du, 0x0003003eu, 0x000008efu, 0x000008eeu, 0x000200f9u, + 0x00000519u, 0x000200f8u, 0x00000519u, 0x0007004fu, 0x0000001fu, 0x0000051bu, 0x000004e6u, 0x000004e6u, + 0x00000001u, 0x00000000u, 0x000500b1u, 0x00000016u, 0x0000051eu, 0x000004e5u, 0x00000149u, 0x000300f7u, + 0x0000054eu, 0x00000000u, 0x000400fau, 0x0000051eu, 0x0000051fu, 0x0000054eu, 0x000200f8u, 0x0000051fu, + 0x0004003du, 0x0000015cu, 0x00000520u, 0x0000015eu, 0x00050080u, 0x0000001fu, 0x00000523u, 0x000004afu, + 0x0000051bu, 0x000500b1u, 0x00000017u, 0x000008fbu, 0x00000523u, 0x00000084u, 0x00050051u, 0x00000016u, + 0x0000091cu, 0x000008fbu, 0x00000000u, 0x00050051u, 0x00000016u, 0x00000921u, 0x000008fbu, 0x00000001u, + 0x000600a9u, 0x0000001fu, 0x000008fdu, 0x000008fbu, 0x00000089u, 0x00000084u, 0x00050082u, 0x0000001fu, + 0x000008ffu, 0x00000523u, 0x000008fdu, 0x00050080u, 0x0000001fu, 0x00000902u, 0x000008ffu, 0x00000089u, + 0x0004006fu, 0x00000009u, 0x00000911u, 0x00000902u, 0x00050085u, 0x00000009u, 0x00000914u, 0x00000911u, + 0x00000589u, 0x00050051u, 0x00000008u, 0x00000525u, 0x00000914u, 0x00000001u, 0x00050051u, 0x00000008u, + 0x00000526u, 0x00000914u, 0x00000000u, 0x00060050u, 0x00000167u, 0x00000527u, 0x00000525u, 0x00000526u, + 0x00000166u, 0x00060060u, 0x0000002cu, 0x00000528u, 0x00000520u, 0x00000527u, 0x00000066u, 0x0004003du, + 0x0000015cu, 0x0000052au, 0x0000015eu, 0x00050050u, 0x00000017u, 0x00000964u, 0x0000016fu, 0x00000921u, + 0x000600a9u, 0x0000001fu, 0x0000093eu, 0x00000964u, 0x00000089u, 0x00000084u, 0x00050082u, 0x0000001fu, + 0x00000940u, 0x00000523u, 0x0000093eu, 0x00050080u, 0x0000001fu, 0x00000943u, 0x00000940u, 0x00000089u, + 0x000500afu, 0x00000017u, 0x0000094cu, 0x00000943u, 0x000005c1u, 0x00050051u, 0x00000016u, 0x0000096au, + 0x0000094cu, 0x00000000u, 0x00050050u, 0x00000017u, 0x00000971u, 0x0000096au, 0x0000016fu, 0x000600a9u, + 0x0000001fu, 0x0000094eu, 0x00000971u, 0x00000089u, 0x00000084u, 0x00050080u, 0x0000001fu, 0x00000950u, + 0x00000943u, 0x0000094eu, 0x0004006fu, 0x00000009u, 0x00000952u, 0x00000950u, 0x00050085u, 0x00000009u, + 0x00000955u, 0x00000952u, 0x00000589u, 0x00050051u, 0x00000008u, 0x0000052fu, 0x00000955u, 0x00000001u, + 0x00050051u, 0x00000008u, 0x00000530u, 0x00000955u, 0x00000000u, 0x00060050u, 0x00000167u, 0x00000531u, + 0x0000052fu, 0x00000530u, 0x00000175u, 0x00060060u, 0x0000002cu, 0x00000532u, 0x0000052au, 0x00000531u, + 0x00000066u, 0x0004003du, 0x0000015cu, 0x00000534u, 0x0000015eu, 0x00050050u, 0x00000017u, 0x000009a5u, + 0x0000091cu, 0x0000016fu, 0x000600a9u, 0x0000001fu, 0x0000097fu, 0x000009a5u, 0x00000089u, 0x00000084u, + 0x00050082u, 0x0000001fu, 0x00000981u, 0x00000523u, 0x0000097fu, 0x00050080u, 0x0000001fu, 0x00000984u, + 0x00000981u, 0x00000089u, 0x000500afu, 0x00000017u, 0x0000098du, 0x00000984u, 0x000005c1u, 0x00050051u, + 0x00000016u, 0x000009b0u, 0x0000098du, 0x00000001u, 0x00050050u, 0x00000017u, 0x000009b2u, 0x0000016fu, + 0x000009b0u, 0x000600a9u, 0x0000001fu, 0x0000098fu, 0x000009b2u, 0x00000089u, 0x00000084u, 0x00050080u, + 0x0000001fu, 0x00000991u, 0x00000984u, 0x0000098fu, 0x0004006fu, 0x00000009u, 0x00000993u, 0x00000991u, + 0x00050085u, 0x00000009u, 0x00000996u, 0x00000993u, 0x00000589u, 0x00050051u, 0x00000008u, 0x00000539u, + 0x00000996u, 0x00000001u, 0x00050051u, 0x00000008u, 0x0000053au, 0x00000996u, 0x00000000u, 0x00060050u, + 0x00000167u, 0x0000053bu, 0x00000539u, 0x0000053au, 0x00000182u, 0x00060060u, 0x0000002cu, 0x0000053cu, + 0x00000534u, 0x0000053bu, 0x00000066u, 0x0004003du, 0x0000015cu, 0x0000053eu, 0x0000015eu, 0x00050080u, + 0x0000001fu, 0x000009c5u, 0x00000523u, 0x00000089u, 0x000500afu, 0x00000017u, 0x000009ceu, 0x000009c5u, + 0x000005c1u, 0x000600a9u, 0x0000001fu, 0x000009d0u, 0x000009ceu, 0x00000089u, 0x00000084u, 0x00050080u, + 0x0000001fu, 0x000009d2u, 0x000009c5u, 0x000009d0u, 0x0004006fu, 0x00000009u, 0x000009d4u, 0x000009d2u, + 0x00050085u, 0x00000009u, 0x000009d7u, 0x000009d4u, 0x00000589u, 0x00050051u, 0x00000008u, 0x00000543u, + 0x000009d7u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000544u, 0x000009d7u, 0x00000000u, 0x00060050u, + 0x00000167u, 0x00000545u, 0x00000543u, 0x00000544u, 0x0000018fu, 0x00060060u, 0x0000002cu, 0x00000546u, + 0x0000053eu, 0x00000545u, 0x00000066u, 0x00050084u, 0x0000001eu, 0x00000a13u, 0x0000006bu, 0x000004e5u, + 0x0004007cu, 0x00000006u, 0x00000a15u, 0x00000a13u, 0x00050051u, 0x00000008u, 0x00000a17u, 0x00000528u, + 0x00000003u, 0x00050051u, 0x00000008u, 0x00000a19u, 0x0000053cu, 0x00000003u, 0x00050050u, 0x00000009u, + 0x00000a1au, 0x00000a17u, 0x00000a19u, 0x00040073u, 0x00000041u, 0x00000a89u, 0x00000a1au, 0x00060041u, + 0x0000004au, 0x00000a8au, 0x00000047u, 0x000004e0u, 0x00000a15u, 0x0003003eu, 0x00000a8au, 0x00000a89u, + 0x00050080u, 0x0000001eu, 0x00000a23u, 0x00000a13u, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000a24u, + 0x00000a23u, 0x00050051u, 0x00000008u, 0x00000a26u, 0x00000532u, 0x00000003u, 0x00050051u, 0x00000008u, + 0x00000a28u, 0x00000546u, 0x00000003u, 0x00050050u, 0x00000009u, 0x00000a29u, 0x00000a26u, 0x00000a28u, + 0x00040073u, 0x00000041u, 0x00000a8fu, 0x00000a29u, 0x00060041u, 0x0000004au, 0x00000a90u, 0x00000047u, + 0x000004e0u, 0x00000a24u, 0x0003003eu, 0x00000a90u, 0x00000a8fu, 0x00050080u, 0x0000001eu, 0x00000a32u, + 0x00000a13u, 0x0000006bu, 0x0004007cu, 0x00000006u, 0x00000a33u, 0x00000a32u, 0x00050051u, 0x00000008u, + 0x00000a35u, 0x00000528u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000a37u, 0x0000053cu, 0x00000000u, + 0x00050050u, 0x00000009u, 0x00000a38u, 0x00000a35u, 0x00000a37u, 0x00040073u, 0x00000041u, 0x00000a95u, + 0x00000a38u, 0x00060041u, 0x0000004au, 0x00000a96u, 0x00000047u, 0x000004e0u, 0x00000a33u, 0x0003003eu, + 0x00000a96u, 0x00000a95u, 0x00050080u, 0x0000001eu, 0x00000a41u, 0x00000a13u, 0x0000006eu, 0x0004007cu, + 0x00000006u, 0x00000a42u, 0x00000a41u, 0x00050051u, 0x00000008u, 0x00000a44u, 0x00000532u, 0x00000000u, + 0x00050051u, 0x00000008u, 0x00000a46u, 0x00000546u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000a47u, + 0x00000a44u, 0x00000a46u, 0x00040073u, 0x00000041u, 0x00000a9bu, 0x00000a47u, 0x00060041u, 0x0000004au, + 0x00000a9cu, 0x00000047u, 0x000004e0u, 0x00000a42u, 0x0003003eu, 0x00000a9cu, 0x00000a9bu, 0x00050080u, + 0x0000001eu, 0x00000a4bu, 0x000004e1u, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000a4cu, 0x00000a4bu, + 0x00050051u, 0x00000008u, 0x00000a53u, 0x00000528u, 0x00000002u, 0x00050051u, 0x00000008u, 0x00000a55u, + 0x0000053cu, 0x00000002u, 0x00050050u, 0x00000009u, 0x00000a56u, 0x00000a53u, 0x00000a55u, 0x00040073u, + 0x00000041u, 0x00000aa1u, 0x00000a56u, 0x00060041u, 0x0000004au, 0x00000aa2u, 0x00000047u, 0x00000a4cu, + 0x00000a15u, 0x0003003eu, 0x00000aa2u, 0x00000aa1u, 0x00050051u, 0x00000008u, 0x00000a62u, 0x00000532u, + 0x00000002u, 0x00050051u, 0x00000008u, 0x00000a64u, 0x00000546u, 0x00000002u, 0x00050050u, 0x00000009u, + 0x00000a65u, 0x00000a62u, 0x00000a64u, 0x00040073u, 0x00000041u, 0x00000aa7u, 0x00000a65u, 0x00060041u, + 0x0000004au, 0x00000aa8u, 0x00000047u, 0x00000a4cu, 0x00000a24u, 0x0003003eu, 0x00000aa8u, 0x00000aa7u, + 0x00050051u, 0x00000008u, 0x00000a71u, 0x00000528u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000a73u, + 0x0000053cu, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000a74u, 0x00000a71u, 0x00000a73u, 0x00040073u, + 0x00000041u, 0x00000aadu, 0x00000a74u, 0x00060041u, 0x0000004au, 0x00000aaeu, 0x00000047u, 0x00000a4cu, + 0x00000a33u, 0x0003003eu, 0x00000aaeu, 0x00000aadu, 0x00050051u, 0x00000008u, 0x00000a80u, 0x00000532u, + 0x00000001u, 0x00050051u, 0x00000008u, 0x00000a82u, 0x00000546u, 0x00000001u, 0x00050050u, 0x00000009u, + 0x00000a83u, 0x00000a80u, 0x00000a82u, 0x00040073u, 0x00000041u, 0x00000ab3u, 0x00000a83u, 0x00060041u, + 0x0000004au, 0x00000ab4u, 0x00000047u, 0x00000a4cu, 0x00000a42u, 0x0003003eu, 0x00000ab4u, 0x00000ab3u, + 0x000200f9u, 0x0000054eu, 0x000200f8u, 0x0000054eu, 0x000400e0u, 0x00000100u, 0x00000100u, 0x00000238u, + 0x00050089u, 0x00000006u, 0x00000ad0u, 0x00000415u, 0x0000023cu, 0x00050084u, 0x00000006u, 0x00000ad1u, + 0x0000023au, 0x00000ad0u, 0x0004007cu, 0x0000001eu, 0x00000ad2u, 0x00000ad1u, 0x00050086u, 0x00000006u, + 0x00000ad4u, 0x00000415u, 0x0000023cu, 0x0004007cu, 0x0000001eu, 0x00000ad5u, 0x00000ad4u, 0x000200f9u, + 0x00000ad7u, 0x000200f8u, 0x00000ad7u, 0x000700f5u, 0x0000001eu, 0x00000ea9u, 0x00000066u, 0x0000054eu, + 0x00000afcu, 0x00000adbu, 0x000500b1u, 0x00000016u, 0x00000adau, 0x00000ea9u, 0x00000149u, 0x000400f6u, + 0x00000afdu, 0x00000adbu, 0x00000000u, 0x000400fau, 0x00000adau, 0x00000adbu, 0x00000afdu, 0x000200f8u, + 0x00000adbu, 0x00050080u, 0x0000001eu, 0x00000ae2u, 0x00000ad2u, 0x00000ea9u, 0x0004007cu, 0x00000006u, + 0x00000ae4u, 0x00000ae2u, 0x00060041u, 0x0000004au, 0x00000b97u, 0x00000047u, 0x00000ad4u, 0x00000ae4u, + 0x0004003du, 0x00000041u, 0x00000b98u, 0x00000b97u, 0x00040073u, 0x00000009u, 0x00000b99u, 0x00000b98u, + 0x00050080u, 0x0000001eu, 0x00000aedu, 0x00000ae2u, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000aeeu, + 0x00000aedu, 0x00060041u, 0x0000004au, 0x00000b9eu, 0x00000047u, 0x00000ad4u, 0x00000aeeu, 0x0004003du, + 0x00000041u, 0x00000b9fu, 0x00000b9eu, 0x00040073u, 0x00000009u, 0x00000ba0u, 0x00000b9fu, 0x0005008eu, + 0x00000009u, 0x00000af3u, 0x00000b99u, 0x0000026cu, 0x00050041u, 0x0000000fu, 0x00000af4u, 0x00000abdu, + 0x00000ea9u, 0x0003003eu, 0x00000af4u, 0x00000af3u, 0x00050080u, 0x0000001eu, 0x00000af6u, 0x00000ea9u, + 0x00000067u, 0x0005008eu, 0x00000009u, 0x00000af8u, 0x00000ba0u, 0x00000272u, 0x00050041u, 0x0000000fu, + 0x00000af9u, 0x00000abdu, 0x00000af6u, 0x0003003eu, 0x00000af9u, 0x00000af8u, 0x00050080u, 0x0000001eu, + 0x00000afcu, 0x00000ea9u, 0x0000006bu, 0x000200f9u, 0x00000ad7u, 0x000200f8u, 0x00000afdu, 0x000200f9u, + 0x00000afeu, 0x000200f8u, 0x00000afeu, 0x000700f5u, 0x0000001eu, 0x00000eaau, 0x0000006bu, 0x00000afdu, + 0x00000b14u, 0x00000b02u, 0x000500b1u, 0x00000016u, 0x00000b01u, 0x00000eaau, 0x0000027eu, 0x000400f6u, + 0x00000b15u, 0x00000b02u, 0x00000000u, 0x000400fau, 0x00000b01u, 0x00000b02u, 0x00000b15u, 0x000200f8u, + 0x00000b02u, 0x00050082u, 0x0000001eu, 0x00000b05u, 0x00000eaau, 0x00000067u, 0x00050041u, 0x0000000fu, + 0x00000b06u, 0x00000abdu, 0x00000b05u, 0x0004003du, 0x00000009u, 0x00000b07u, 0x00000b06u, 0x00050080u, + 0x0000001eu, 0x00000b09u, 0x00000eaau, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000b0au, 0x00000abdu, + 0x00000b09u, 0x0004003du, 0x00000009u, 0x00000b0bu, 0x00000b0au, 0x00050081u, 0x00000009u, 0x00000b0cu, + 0x00000b07u, 0x00000b0bu, 0x0005008eu, 0x00000009u, 0x00000b0du, 0x00000b0cu, 0x00000281u, 0x00050041u, + 0x0000000fu, 0x00000b0eu, 0x00000abdu, 0x00000eaau, 0x0004003du, 0x00000009u, 0x00000b0fu, 0x00000b0eu, + 0x00050083u, 0x00000009u, 0x00000b10u, 0x00000b0fu, 0x00000b0du, 0x0003003eu, 0x00000b0eu, 0x00000b10u, + 0x00050080u, 0x0000001eu, 0x00000b14u, 0x00000eaau, 0x0000006bu, 0x000200f9u, 0x00000afeu, 0x000200f8u, + 0x00000b15u, 0x000200f9u, 0x00000b16u, 0x000200f8u, 0x00000b16u, 0x000700f5u, 0x0000001eu, 0x00000eabu, + 0x0000006eu, 0x00000b15u, 0x00000b2cu, 0x00000b1au, 0x000500b1u, 0x00000016u, 0x00000b19u, 0x00000eabu, + 0x00000299u, 0x000400f6u, 0x00000b2du, 0x00000b1au, 0x00000000u, 0x000400fau, 0x00000b19u, 0x00000b1au, + 0x00000b2du, 0x000200f8u, 0x00000b1au, 0x00050082u, 0x0000001eu, 0x00000b1du, 0x00000eabu, 0x00000067u, + 0x00050041u, 0x0000000fu, 0x00000b1eu, 0x00000abdu, 0x00000b1du, 0x0004003du, 0x00000009u, 0x00000b1fu, + 0x00000b1eu, 0x00050080u, 0x0000001eu, 0x00000b21u, 0x00000eabu, 0x00000067u, 0x00050041u, 0x0000000fu, + 0x00000b22u, 0x00000abdu, 0x00000b21u, 0x0004003du, 0x00000009u, 0x00000b23u, 0x00000b22u, 0x00050081u, + 0x00000009u, 0x00000b24u, 0x00000b1fu, 0x00000b23u, 0x0005008eu, 0x00000009u, 0x00000b25u, 0x00000b24u, + 0x0000029cu, 0x00050041u, 0x0000000fu, 0x00000b26u, 0x00000abdu, 0x00000eabu, 0x0004003du, 0x00000009u, + 0x00000b27u, 0x00000b26u, 0x00050083u, 0x00000009u, 0x00000b28u, 0x00000b27u, 0x00000b25u, 0x0003003eu, + 0x00000b26u, 0x00000b28u, 0x00050080u, 0x0000001eu, 0x00000b2cu, 0x00000eabu, 0x0000006bu, 0x000200f9u, + 0x00000b16u, 0x000200f8u, 0x00000b2du, 0x000200f9u, 0x00000b2eu, 0x000200f8u, 0x00000b2eu, 0x000700f5u, + 0x0000001eu, 0x00000eacu, 0x000002aeu, 0x00000b2du, 0x00000b44u, 0x00000b32u, 0x000500b1u, 0x00000016u, + 0x00000b31u, 0x00000eacu, 0x000002b5u, 0x000400f6u, 0x00000b45u, 0x00000b32u, 0x00000000u, 0x000400fau, + 0x00000b31u, 0x00000b32u, 0x00000b45u, 0x000200f8u, 0x00000b32u, 0x00050082u, 0x0000001eu, 0x00000b35u, + 0x00000eacu, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000b36u, 0x00000abdu, 0x00000b35u, 0x0004003du, + 0x00000009u, 0x00000b37u, 0x00000b36u, 0x00050080u, 0x0000001eu, 0x00000b39u, 0x00000eacu, 0x00000067u, + 0x00050041u, 0x0000000fu, 0x00000b3au, 0x00000abdu, 0x00000b39u, 0x0004003du, 0x00000009u, 0x00000b3bu, + 0x00000b3au, 0x00050081u, 0x00000009u, 0x00000b3cu, 0x00000b37u, 0x00000b3bu, 0x0005008eu, 0x00000009u, + 0x00000b3du, 0x00000b3cu, 0x000002b8u, 0x00050041u, 0x0000000fu, 0x00000b3eu, 0x00000abdu, 0x00000eacu, + 0x0004003du, 0x00000009u, 0x00000b3fu, 0x00000b3eu, 0x00050083u, 0x00000009u, 0x00000b40u, 0x00000b3fu, + 0x00000b3du, 0x0003003eu, 0x00000b3eu, 0x00000b40u, 0x00050080u, 0x0000001eu, 0x00000b44u, 0x00000eacu, + 0x0000006bu, 0x000200f9u, 0x00000b2eu, 0x000200f8u, 0x00000b45u, 0x000200f9u, 0x00000b46u, 0x000200f8u, + 0x00000b46u, 0x000700f5u, 0x0000001eu, 0x00000eadu, 0x00000074u, 0x00000b45u, 0x00000b5cu, 0x00000b4au, + 0x000500b1u, 0x00000016u, 0x00000b49u, 0x00000eadu, 0x000002d0u, 0x000400f6u, 0x00000b5du, 0x00000b4au, + 0x00000000u, 0x000400fau, 0x00000b49u, 0x00000b4au, 0x00000b5du, 0x000200f8u, 0x00000b4au, 0x00050082u, + 0x0000001eu, 0x00000b4du, 0x00000eadu, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000b4eu, 0x00000abdu, + 0x00000b4du, 0x0004003du, 0x00000009u, 0x00000b4fu, 0x00000b4eu, 0x00050080u, 0x0000001eu, 0x00000b51u, + 0x00000eadu, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000b52u, 0x00000abdu, 0x00000b51u, 0x0004003du, + 0x00000009u, 0x00000b53u, 0x00000b52u, 0x00050081u, 0x00000009u, 0x00000b54u, 0x00000b4fu, 0x00000b53u, + 0x0005008eu, 0x00000009u, 0x00000b55u, 0x00000b54u, 0x000002d3u, 0x00050041u, 0x0000000fu, 0x00000b56u, + 0x00000abdu, 0x00000eadu, 0x0004003du, 0x00000009u, 0x00000b57u, 0x00000b56u, 0x00050083u, 0x00000009u, + 0x00000b58u, 0x00000b57u, 0x00000b55u, 0x0003003eu, 0x00000b56u, 0x00000b58u, 0x00050080u, 0x0000001eu, + 0x00000b5cu, 0x00000eadu, 0x0000006bu, 0x000200f9u, 0x00000b46u, 0x000200f8u, 0x00000b5du, 0x000400e0u, + 0x00000100u, 0x00000100u, 0x00000238u, 0x000200f9u, 0x00000b5eu, 0x000200f8u, 0x00000b5eu, 0x000700f5u, + 0x0000001eu, 0x00000eaeu, 0x0000006bu, 0x00000b5du, 0x00000b91u, 0x00000b62u, 0x000500b1u, 0x00000016u, + 0x00000b61u, 0x00000eaeu, 0x000002ebu, 0x000400f6u, 0x00000b92u, 0x00000b62u, 0x00000000u, 0x000400fau, + 0x00000b61u, 0x00000b62u, 0x00000b92u, 0x000200f8u, 0x00000b62u, 0x00050084u, 0x0000001eu, 0x00000b64u, + 0x0000006bu, 0x00000eaeu, 0x00050041u, 0x0000000fu, 0x00000b66u, 0x00000abdu, 0x00000b64u, 0x0004003du, + 0x00000009u, 0x00000b67u, 0x00000b66u, 0x00050080u, 0x0000001eu, 0x00000b6au, 0x00000b64u, 0x00000067u, + 0x00050041u, 0x0000000fu, 0x00000b6bu, 0x00000abdu, 0x00000b6au, 0x0004003du, 0x00000009u, 0x00000b6cu, + 0x00000b6bu, 0x00050051u, 0x00000008u, 0x00000b6eu, 0x00000b67u, 0x00000000u, 0x00050051u, 0x00000008u, + 0x00000b70u, 0x00000b6cu, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000b71u, 0x00000b6eu, 0x00000b70u, + 0x00050051u, 0x00000008u, 0x00000b73u, 0x00000b67u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000b75u, + 0x00000b6cu, 0x00000001u, 0x00050050u, 0x00000009u, 0x00000b76u, 0x00000b73u, 0x00000b75u, 0x000500c3u, + 0x0000001eu, 0x00000b79u, 0x00000ad2u, 0x00000067u, 0x00050082u, 0x0000001eu, 0x00000b7bu, 0x00000eaeu, + 0x0000006bu, 0x00050080u, 0x0000001eu, 0x00000b7cu, 0x00000b79u, 0x00000b7bu, 0x0004007cu, 0x00000006u, + 0x00000b7eu, 0x00000b7cu, 0x00050084u, 0x0000001eu, 0x00000b81u, 0x0000006bu, 0x00000ad5u, 0x0004007cu, + 0x00000006u, 0x00000b83u, 0x00000b81u, 0x00040073u, 0x00000041u, 0x00000ba5u, 0x00000b71u, 0x00060041u, + 0x0000004au, 0x00000ba6u, 0x00000047u, 0x00000b7eu, 0x00000b83u, 0x0003003eu, 0x00000ba6u, 0x00000ba5u, + 0x00050080u, 0x0000001eu, 0x00000b8bu, 0x00000b81u, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000b8cu, + 0x00000b8bu, 0x00040073u, 0x00000041u, 0x00000babu, 0x00000b76u, 0x00060041u, 0x0000004au, 0x00000bacu, + 0x00000047u, 0x00000b7eu, 0x00000b8cu, 0x0003003eu, 0x00000bacu, 0x00000babu, 0x00050080u, 0x0000001eu, + 0x00000b91u, 0x00000eaeu, 0x00000067u, 0x000200f9u, 0x00000b5eu, 0x000200f8u, 0x00000b92u, 0x000500b0u, + 0x00000016u, 0x0000041au, 0x00000415u, 0x00000419u, 0x00050089u, 0x00000006u, 0x00000bc8u, 0x00000415u, + 0x0000023au, 0x00050084u, 0x00000006u, 0x00000bc9u, 0x0000023cu, 0x00000bc8u, 0x0004007cu, 0x0000001eu, + 0x00000bcau, 0x00000bc9u, 0x00050086u, 0x00000006u, 0x00000bccu, 0x00000415u, 0x0000023au, 0x00050080u, + 0x00000006u, 0x00000bcfu, 0x00000bccu, 0x000001a1u, 0x0004007cu, 0x0000001eu, 0x00000bd0u, 0x00000bcfu, + 0x000300f7u, 0x00000c5bu, 0x00000000u, 0x000400fau, 0x0000041au, 0x00000bd3u, 0x00000c5bu, 0x000200f8u, + 0x00000bd3u, 0x000200f9u, 0x00000bd4u, 0x000200f8u, 0x00000bd4u, 0x000700f5u, 0x0000001eu, 0x00000eafu, + 0x00000066u, 0x00000bd3u, 0x00000bf9u, 0x00000bd8u, 0x000500b1u, 0x00000016u, 0x00000bd7u, 0x00000eafu, + 0x000002d0u, 0x000400f6u, 0x00000bfau, 0x00000bd8u, 0x00000000u, 0x000400fau, 0x00000bd7u, 0x00000bd8u, + 0x00000bfau, 0x000200f8u, 0x00000bd8u, 0x00050080u, 0x0000001eu, 0x00000bdfu, 0x00000bcau, 0x00000eafu, + 0x0004007cu, 0x00000006u, 0x00000be1u, 0x00000bdfu, 0x00060041u, 0x0000004au, 0x00000c98u, 0x00000047u, + 0x00000bcfu, 0x00000be1u, 0x0004003du, 0x00000041u, 0x00000c99u, 0x00000c98u, 0x00040073u, 0x00000009u, + 0x00000c9au, 0x00000c99u, 0x00050080u, 0x0000001eu, 0x00000beau, 0x00000bdfu, 0x00000067u, 0x0004007cu, + 0x00000006u, 0x00000bebu, 0x00000beau, 0x00060041u, 0x0000004au, 0x00000c9fu, 0x00000047u, 0x00000bcfu, + 0x00000bebu, 0x0004003du, 0x00000041u, 0x00000ca0u, 0x00000c9fu, 0x00040073u, 0x00000009u, 0x00000ca1u, + 0x00000ca0u, 0x0005008eu, 0x00000009u, 0x00000bf0u, 0x00000c9au, 0x0000026cu, 0x00050041u, 0x0000000fu, + 0x00000bf1u, 0x00000bb5u, 0x00000eafu, 0x0003003eu, 0x00000bf1u, 0x00000bf0u, 0x00050080u, 0x0000001eu, + 0x00000bf3u, 0x00000eafu, 0x00000067u, 0x0005008eu, 0x00000009u, 0x00000bf5u, 0x00000ca1u, 0x00000272u, + 0x00050041u, 0x0000000fu, 0x00000bf6u, 0x00000bb5u, 0x00000bf3u, 0x0003003eu, 0x00000bf6u, 0x00000bf5u, + 0x00050080u, 0x0000001eu, 0x00000bf9u, 0x00000eafu, 0x0000006bu, 0x000200f9u, 0x00000bd4u, 0x000200f8u, + 0x00000bfau, 0x000200f9u, 0x00000bfbu, 0x000200f8u, 0x00000bfbu, 0x000700f5u, 0x0000001eu, 0x00000eb0u, + 0x0000006bu, 0x00000bfau, 0x00000c11u, 0x00000bffu, 0x000500b1u, 0x00000016u, 0x00000bfeu, 0x00000eb0u, + 0x0000036eu, 0x000400f6u, 0x00000c12u, 0x00000bffu, 0x00000000u, 0x000400fau, 0x00000bfeu, 0x00000bffu, + 0x00000c12u, 0x000200f8u, 0x00000bffu, 0x00050082u, 0x0000001eu, 0x00000c02u, 0x00000eb0u, 0x00000067u, + 0x00050041u, 0x0000000fu, 0x00000c03u, 0x00000bb5u, 0x00000c02u, 0x0004003du, 0x00000009u, 0x00000c04u, + 0x00000c03u, 0x00050080u, 0x0000001eu, 0x00000c06u, 0x00000eb0u, 0x00000067u, 0x00050041u, 0x0000000fu, + 0x00000c07u, 0x00000bb5u, 0x00000c06u, 0x0004003du, 0x00000009u, 0x00000c08u, 0x00000c07u, 0x00050081u, + 0x00000009u, 0x00000c09u, 0x00000c04u, 0x00000c08u, 0x0005008eu, 0x00000009u, 0x00000c0au, 0x00000c09u, + 0x00000281u, 0x00050041u, 0x0000000fu, 0x00000c0bu, 0x00000bb5u, 0x00000eb0u, 0x0004003du, 0x00000009u, + 0x00000c0cu, 0x00000c0bu, 0x00050083u, 0x00000009u, 0x00000c0du, 0x00000c0cu, 0x00000c0au, 0x0003003eu, + 0x00000c0bu, 0x00000c0du, 0x00050080u, 0x0000001eu, 0x00000c11u, 0x00000eb0u, 0x0000006bu, 0x000200f9u, + 0x00000bfbu, 0x000200f8u, 0x00000c12u, 0x000200f9u, 0x00000c13u, 0x000200f8u, 0x00000c13u, 0x000700f5u, + 0x0000001eu, 0x00000eb1u, 0x0000006eu, 0x00000c12u, 0x00000c29u, 0x00000c17u, 0x000500b1u, 0x00000016u, + 0x00000c16u, 0x00000eb1u, 0x00000388u, 0x000400f6u, 0x00000c2au, 0x00000c17u, 0x00000000u, 0x000400fau, + 0x00000c16u, 0x00000c17u, 0x00000c2au, 0x000200f8u, 0x00000c17u, 0x00050082u, 0x0000001eu, 0x00000c1au, + 0x00000eb1u, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000c1bu, 0x00000bb5u, 0x00000c1au, 0x0004003du, + 0x00000009u, 0x00000c1cu, 0x00000c1bu, 0x00050080u, 0x0000001eu, 0x00000c1eu, 0x00000eb1u, 0x00000067u, + 0x00050041u, 0x0000000fu, 0x00000c1fu, 0x00000bb5u, 0x00000c1eu, 0x0004003du, 0x00000009u, 0x00000c20u, + 0x00000c1fu, 0x00050081u, 0x00000009u, 0x00000c21u, 0x00000c1cu, 0x00000c20u, 0x0005008eu, 0x00000009u, + 0x00000c22u, 0x00000c21u, 0x0000029cu, 0x00050041u, 0x0000000fu, 0x00000c23u, 0x00000bb5u, 0x00000eb1u, + 0x0004003du, 0x00000009u, 0x00000c24u, 0x00000c23u, 0x00050083u, 0x00000009u, 0x00000c25u, 0x00000c24u, + 0x00000c22u, 0x0003003eu, 0x00000c23u, 0x00000c25u, 0x00050080u, 0x0000001eu, 0x00000c29u, 0x00000eb1u, + 0x0000006bu, 0x000200f9u, 0x00000c13u, 0x000200f8u, 0x00000c2au, 0x000200f9u, 0x00000c2bu, 0x000200f8u, + 0x00000c2bu, 0x000700f5u, 0x0000001eu, 0x00000eb2u, 0x000002aeu, 0x00000c2au, 0x00000c41u, 0x00000c2fu, + 0x000500b1u, 0x00000016u, 0x00000c2eu, 0x00000eb2u, 0x000003a2u, 0x000400f6u, 0x00000c42u, 0x00000c2fu, + 0x00000000u, 0x000400fau, 0x00000c2eu, 0x00000c2fu, 0x00000c42u, 0x000200f8u, 0x00000c2fu, 0x00050082u, + 0x0000001eu, 0x00000c32u, 0x00000eb2u, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000c33u, 0x00000bb5u, + 0x00000c32u, 0x0004003du, 0x00000009u, 0x00000c34u, 0x00000c33u, 0x00050080u, 0x0000001eu, 0x00000c36u, + 0x00000eb2u, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000c37u, 0x00000bb5u, 0x00000c36u, 0x0004003du, + 0x00000009u, 0x00000c38u, 0x00000c37u, 0x00050081u, 0x00000009u, 0x00000c39u, 0x00000c34u, 0x00000c38u, + 0x0005008eu, 0x00000009u, 0x00000c3au, 0x00000c39u, 0x000002b8u, 0x00050041u, 0x0000000fu, 0x00000c3bu, + 0x00000bb5u, 0x00000eb2u, 0x0004003du, 0x00000009u, 0x00000c3cu, 0x00000c3bu, 0x00050083u, 0x00000009u, + 0x00000c3du, 0x00000c3cu, 0x00000c3au, 0x0003003eu, 0x00000c3bu, 0x00000c3du, 0x00050080u, 0x0000001eu, + 0x00000c41u, 0x00000eb2u, 0x0000006bu, 0x000200f9u, 0x00000c2bu, 0x000200f8u, 0x00000c42u, 0x000200f9u, + 0x00000c43u, 0x000200f8u, 0x00000c43u, 0x000700f5u, 0x0000001eu, 0x00000eb3u, 0x00000074u, 0x00000c42u, + 0x00000c59u, 0x00000c47u, 0x000500b1u, 0x00000016u, 0x00000c46u, 0x00000eb3u, 0x000003bcu, 0x000400f6u, + 0x00000c5au, 0x00000c47u, 0x00000000u, 0x000400fau, 0x00000c46u, 0x00000c47u, 0x00000c5au, 0x000200f8u, + 0x00000c47u, 0x00050082u, 0x0000001eu, 0x00000c4au, 0x00000eb3u, 0x00000067u, 0x00050041u, 0x0000000fu, + 0x00000c4bu, 0x00000bb5u, 0x00000c4au, 0x0004003du, 0x00000009u, 0x00000c4cu, 0x00000c4bu, 0x00050080u, + 0x0000001eu, 0x00000c4eu, 0x00000eb3u, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000c4fu, 0x00000bb5u, + 0x00000c4eu, 0x0004003du, 0x00000009u, 0x00000c50u, 0x00000c4fu, 0x00050081u, 0x00000009u, 0x00000c51u, + 0x00000c4cu, 0x00000c50u, 0x0005008eu, 0x00000009u, 0x00000c52u, 0x00000c51u, 0x000002d3u, 0x00050041u, + 0x0000000fu, 0x00000c53u, 0x00000bb5u, 0x00000eb3u, 0x0004003du, 0x00000009u, 0x00000c54u, 0x00000c53u, + 0x00050083u, 0x00000009u, 0x00000c55u, 0x00000c54u, 0x00000c52u, 0x0003003eu, 0x00000c53u, 0x00000c55u, + 0x00050080u, 0x0000001eu, 0x00000c59u, 0x00000eb3u, 0x0000006bu, 0x000200f9u, 0x00000c43u, 0x000200f8u, + 0x00000c5au, 0x000200f9u, 0x00000c5bu, 0x000200f8u, 0x00000c5bu, 0x000400e0u, 0x00000100u, 0x00000100u, + 0x00000238u, 0x000300f7u, 0x00000c93u, 0x00000000u, 0x000400fau, 0x0000041au, 0x00000c5du, 0x00000c93u, + 0x000200f8u, 0x00000c5du, 0x000200f9u, 0x00000c5eu, 0x000200f8u, 0x00000c5eu, 0x000700f5u, 0x0000001eu, + 0x00000eb4u, 0x0000006bu, 0x00000c5du, 0x00000c91u, 0x00000c62u, 0x000500b1u, 0x00000016u, 0x00000c61u, + 0x00000eb4u, 0x000002aeu, 0x000400f6u, 0x00000c92u, 0x00000c62u, 0x00000000u, 0x000400fau, 0x00000c61u, + 0x00000c62u, 0x00000c92u, 0x000200f8u, 0x00000c62u, 0x00050084u, 0x0000001eu, 0x00000c64u, 0x0000006bu, + 0x00000eb4u, 0x00050041u, 0x0000000fu, 0x00000c66u, 0x00000bb5u, 0x00000c64u, 0x0004003du, 0x00000009u, + 0x00000c67u, 0x00000c66u, 0x00050080u, 0x0000001eu, 0x00000c6au, 0x00000c64u, 0x00000067u, 0x00050041u, + 0x0000000fu, 0x00000c6bu, 0x00000bb5u, 0x00000c6au, 0x0004003du, 0x00000009u, 0x00000c6cu, 0x00000c6bu, + 0x00050051u, 0x00000008u, 0x00000c6eu, 0x00000c67u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000c70u, + 0x00000c6cu, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000c71u, 0x00000c6eu, 0x00000c70u, 0x00050051u, + 0x00000008u, 0x00000c73u, 0x00000c67u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000c75u, 0x00000c6cu, + 0x00000001u, 0x00050050u, 0x00000009u, 0x00000c76u, 0x00000c73u, 0x00000c75u, 0x000500c3u, 0x0000001eu, + 0x00000c79u, 0x00000bcau, 0x00000067u, 0x00050082u, 0x0000001eu, 0x00000c7bu, 0x00000eb4u, 0x0000006bu, + 0x00050080u, 0x0000001eu, 0x00000c7cu, 0x00000c79u, 0x00000c7bu, 0x0004007cu, 0x00000006u, 0x00000c7eu, + 0x00000c7cu, 0x00050084u, 0x0000001eu, 0x00000c81u, 0x0000006bu, 0x00000bd0u, 0x0004007cu, 0x00000006u, + 0x00000c83u, 0x00000c81u, 0x00040073u, 0x00000041u, 0x00000ca6u, 0x00000c71u, 0x00060041u, 0x0000004au, + 0x00000ca7u, 0x00000047u, 0x00000c7eu, 0x00000c83u, 0x0003003eu, 0x00000ca7u, 0x00000ca6u, 0x00050080u, + 0x0000001eu, 0x00000c8bu, 0x00000c81u, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000c8cu, 0x00000c8bu, + 0x00040073u, 0x00000041u, 0x00000cacu, 0x00000c76u, 0x00060041u, 0x0000004au, 0x00000cadu, 0x00000047u, + 0x00000c7eu, 0x00000c8cu, 0x0003003eu, 0x00000cadu, 0x00000cacu, 0x00050080u, 0x0000001eu, 0x00000c91u, + 0x00000eb4u, 0x00000067u, 0x000200f9u, 0x00000c5eu, 0x000200f8u, 0x00000c92u, 0x000200f9u, 0x00000c93u, + 0x000200f8u, 0x00000c93u, 0x000400e0u, 0x00000100u, 0x00000100u, 0x00000238u, 0x000200f9u, 0x00000cd0u, + 0x000200f8u, 0x00000cd0u, 0x000700f5u, 0x0000001eu, 0x00000eb5u, 0x00000066u, 0x00000c93u, 0x00000cf5u, + 0x00000cd4u, 0x000500b1u, 0x00000016u, 0x00000cd3u, 0x00000eb5u, 0x00000149u, 0x000400f6u, 0x00000cf6u, + 0x00000cd4u, 0x00000000u, 0x000400fau, 0x00000cd3u, 0x00000cd4u, 0x00000cf6u, 0x000200f8u, 0x00000cd4u, + 0x00050080u, 0x0000001eu, 0x00000cdbu, 0x00000ad2u, 0x00000eb5u, 0x0004007cu, 0x00000006u, 0x00000cddu, + 0x00000cdbu, 0x00060041u, 0x0000004au, 0x00000d90u, 0x00000047u, 0x00000ad4u, 0x00000cddu, 0x0004003du, + 0x00000041u, 0x00000d91u, 0x00000d90u, 0x00040073u, 0x00000009u, 0x00000d92u, 0x00000d91u, 0x00050080u, + 0x0000001eu, 0x00000ce6u, 0x00000cdbu, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000ce7u, 0x00000ce6u, + 0x00060041u, 0x0000004au, 0x00000d97u, 0x00000047u, 0x00000ad4u, 0x00000ce7u, 0x0004003du, 0x00000041u, + 0x00000d98u, 0x00000d97u, 0x00040073u, 0x00000009u, 0x00000d99u, 0x00000d98u, 0x0005008eu, 0x00000009u, + 0x00000cecu, 0x00000d92u, 0x0000026cu, 0x00050041u, 0x0000000fu, 0x00000cedu, 0x00000cb6u, 0x00000eb5u, + 0x0003003eu, 0x00000cedu, 0x00000cecu, 0x00050080u, 0x0000001eu, 0x00000cefu, 0x00000eb5u, 0x00000067u, + 0x0005008eu, 0x00000009u, 0x00000cf1u, 0x00000d99u, 0x00000272u, 0x00050041u, 0x0000000fu, 0x00000cf2u, + 0x00000cb6u, 0x00000cefu, 0x0003003eu, 0x00000cf2u, 0x00000cf1u, 0x00050080u, 0x0000001eu, 0x00000cf5u, + 0x00000eb5u, 0x0000006bu, 0x000200f9u, 0x00000cd0u, 0x000200f8u, 0x00000cf6u, 0x000200f9u, 0x00000cf7u, + 0x000200f8u, 0x00000cf7u, 0x000700f5u, 0x0000001eu, 0x00000eb6u, 0x0000006bu, 0x00000cf6u, 0x00000d0du, + 0x00000cfbu, 0x000500b1u, 0x00000016u, 0x00000cfau, 0x00000eb6u, 0x0000027eu, 0x000400f6u, 0x00000d0eu, + 0x00000cfbu, 0x00000000u, 0x000400fau, 0x00000cfau, 0x00000cfbu, 0x00000d0eu, 0x000200f8u, 0x00000cfbu, + 0x00050082u, 0x0000001eu, 0x00000cfeu, 0x00000eb6u, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000cffu, + 0x00000cb6u, 0x00000cfeu, 0x0004003du, 0x00000009u, 0x00000d00u, 0x00000cffu, 0x00050080u, 0x0000001eu, + 0x00000d02u, 0x00000eb6u, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000d03u, 0x00000cb6u, 0x00000d02u, + 0x0004003du, 0x00000009u, 0x00000d04u, 0x00000d03u, 0x00050081u, 0x00000009u, 0x00000d05u, 0x00000d00u, + 0x00000d04u, 0x0005008eu, 0x00000009u, 0x00000d06u, 0x00000d05u, 0x00000281u, 0x00050041u, 0x0000000fu, + 0x00000d07u, 0x00000cb6u, 0x00000eb6u, 0x0004003du, 0x00000009u, 0x00000d08u, 0x00000d07u, 0x00050083u, + 0x00000009u, 0x00000d09u, 0x00000d08u, 0x00000d06u, 0x0003003eu, 0x00000d07u, 0x00000d09u, 0x00050080u, + 0x0000001eu, 0x00000d0du, 0x00000eb6u, 0x0000006bu, 0x000200f9u, 0x00000cf7u, 0x000200f8u, 0x00000d0eu, + 0x000200f9u, 0x00000d0fu, 0x000200f8u, 0x00000d0fu, 0x000700f5u, 0x0000001eu, 0x00000eb7u, 0x0000006eu, + 0x00000d0eu, 0x00000d25u, 0x00000d13u, 0x000500b1u, 0x00000016u, 0x00000d12u, 0x00000eb7u, 0x00000299u, + 0x000400f6u, 0x00000d26u, 0x00000d13u, 0x00000000u, 0x000400fau, 0x00000d12u, 0x00000d13u, 0x00000d26u, + 0x000200f8u, 0x00000d13u, 0x00050082u, 0x0000001eu, 0x00000d16u, 0x00000eb7u, 0x00000067u, 0x00050041u, + 0x0000000fu, 0x00000d17u, 0x00000cb6u, 0x00000d16u, 0x0004003du, 0x00000009u, 0x00000d18u, 0x00000d17u, + 0x00050080u, 0x0000001eu, 0x00000d1au, 0x00000eb7u, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000d1bu, + 0x00000cb6u, 0x00000d1au, 0x0004003du, 0x00000009u, 0x00000d1cu, 0x00000d1bu, 0x00050081u, 0x00000009u, + 0x00000d1du, 0x00000d18u, 0x00000d1cu, 0x0005008eu, 0x00000009u, 0x00000d1eu, 0x00000d1du, 0x0000029cu, + 0x00050041u, 0x0000000fu, 0x00000d1fu, 0x00000cb6u, 0x00000eb7u, 0x0004003du, 0x00000009u, 0x00000d20u, + 0x00000d1fu, 0x00050083u, 0x00000009u, 0x00000d21u, 0x00000d20u, 0x00000d1eu, 0x0003003eu, 0x00000d1fu, + 0x00000d21u, 0x00050080u, 0x0000001eu, 0x00000d25u, 0x00000eb7u, 0x0000006bu, 0x000200f9u, 0x00000d0fu, + 0x000200f8u, 0x00000d26u, 0x000200f9u, 0x00000d27u, 0x000200f8u, 0x00000d27u, 0x000700f5u, 0x0000001eu, + 0x00000eb8u, 0x000002aeu, 0x00000d26u, 0x00000d3du, 0x00000d2bu, 0x000500b1u, 0x00000016u, 0x00000d2au, + 0x00000eb8u, 0x000002b5u, 0x000400f6u, 0x00000d3eu, 0x00000d2bu, 0x00000000u, 0x000400fau, 0x00000d2au, + 0x00000d2bu, 0x00000d3eu, 0x000200f8u, 0x00000d2bu, 0x00050082u, 0x0000001eu, 0x00000d2eu, 0x00000eb8u, + 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000d2fu, 0x00000cb6u, 0x00000d2eu, 0x0004003du, 0x00000009u, + 0x00000d30u, 0x00000d2fu, 0x00050080u, 0x0000001eu, 0x00000d32u, 0x00000eb8u, 0x00000067u, 0x00050041u, + 0x0000000fu, 0x00000d33u, 0x00000cb6u, 0x00000d32u, 0x0004003du, 0x00000009u, 0x00000d34u, 0x00000d33u, + 0x00050081u, 0x00000009u, 0x00000d35u, 0x00000d30u, 0x00000d34u, 0x0005008eu, 0x00000009u, 0x00000d36u, + 0x00000d35u, 0x000002b8u, 0x00050041u, 0x0000000fu, 0x00000d37u, 0x00000cb6u, 0x00000eb8u, 0x0004003du, + 0x00000009u, 0x00000d38u, 0x00000d37u, 0x00050083u, 0x00000009u, 0x00000d39u, 0x00000d38u, 0x00000d36u, + 0x0003003eu, 0x00000d37u, 0x00000d39u, 0x00050080u, 0x0000001eu, 0x00000d3du, 0x00000eb8u, 0x0000006bu, + 0x000200f9u, 0x00000d27u, 0x000200f8u, 0x00000d3eu, 0x000200f9u, 0x00000d3fu, 0x000200f8u, 0x00000d3fu, + 0x000700f5u, 0x0000001eu, 0x00000eb9u, 0x00000074u, 0x00000d3eu, 0x00000d55u, 0x00000d43u, 0x000500b1u, + 0x00000016u, 0x00000d42u, 0x00000eb9u, 0x000002d0u, 0x000400f6u, 0x00000d56u, 0x00000d43u, 0x00000000u, + 0x000400fau, 0x00000d42u, 0x00000d43u, 0x00000d56u, 0x000200f8u, 0x00000d43u, 0x00050082u, 0x0000001eu, + 0x00000d46u, 0x00000eb9u, 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000d47u, 0x00000cb6u, 0x00000d46u, + 0x0004003du, 0x00000009u, 0x00000d48u, 0x00000d47u, 0x00050080u, 0x0000001eu, 0x00000d4au, 0x00000eb9u, + 0x00000067u, 0x00050041u, 0x0000000fu, 0x00000d4bu, 0x00000cb6u, 0x00000d4au, 0x0004003du, 0x00000009u, + 0x00000d4cu, 0x00000d4bu, 0x00050081u, 0x00000009u, 0x00000d4du, 0x00000d48u, 0x00000d4cu, 0x0005008eu, + 0x00000009u, 0x00000d4eu, 0x00000d4du, 0x000002d3u, 0x00050041u, 0x0000000fu, 0x00000d4fu, 0x00000cb6u, + 0x00000eb9u, 0x0004003du, 0x00000009u, 0x00000d50u, 0x00000d4fu, 0x00050083u, 0x00000009u, 0x00000d51u, + 0x00000d50u, 0x00000d4eu, 0x0003003eu, 0x00000d4fu, 0x00000d51u, 0x00050080u, 0x0000001eu, 0x00000d55u, + 0x00000eb9u, 0x0000006bu, 0x000200f9u, 0x00000d3fu, 0x000200f8u, 0x00000d56u, 0x000400e0u, 0x00000100u, + 0x00000100u, 0x00000238u, 0x000200f9u, 0x00000d57u, 0x000200f8u, 0x00000d57u, 0x000700f5u, 0x0000001eu, + 0x00000ebau, 0x0000006bu, 0x00000d56u, 0x00000d8au, 0x00000d5bu, 0x000500b1u, 0x00000016u, 0x00000d5au, + 0x00000ebau, 0x000002ebu, 0x000400f6u, 0x00000d8bu, 0x00000d5bu, 0x00000000u, 0x000400fau, 0x00000d5au, + 0x00000d5bu, 0x00000d8bu, 0x000200f8u, 0x00000d5bu, 0x00050084u, 0x0000001eu, 0x00000d5du, 0x0000006bu, + 0x00000ebau, 0x00050041u, 0x0000000fu, 0x00000d5fu, 0x00000cb6u, 0x00000d5du, 0x0004003du, 0x00000009u, + 0x00000d60u, 0x00000d5fu, 0x00050080u, 0x0000001eu, 0x00000d63u, 0x00000d5du, 0x00000067u, 0x00050041u, + 0x0000000fu, 0x00000d64u, 0x00000cb6u, 0x00000d63u, 0x0004003du, 0x00000009u, 0x00000d65u, 0x00000d64u, + 0x00050051u, 0x00000008u, 0x00000d67u, 0x00000d60u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000d69u, + 0x00000d65u, 0x00000000u, 0x00050050u, 0x00000009u, 0x00000d6au, 0x00000d67u, 0x00000d69u, 0x00050051u, + 0x00000008u, 0x00000d6cu, 0x00000d60u, 0x00000001u, 0x00050051u, 0x00000008u, 0x00000d6eu, 0x00000d65u, + 0x00000001u, 0x00050050u, 0x00000009u, 0x00000d6fu, 0x00000d6cu, 0x00000d6eu, 0x000500c3u, 0x0000001eu, + 0x00000d72u, 0x00000ad2u, 0x00000067u, 0x00050082u, 0x0000001eu, 0x00000d74u, 0x00000ebau, 0x0000006bu, + 0x00050080u, 0x0000001eu, 0x00000d75u, 0x00000d72u, 0x00000d74u, 0x0004007cu, 0x00000006u, 0x00000d77u, + 0x00000d75u, 0x00050084u, 0x0000001eu, 0x00000d7au, 0x0000006bu, 0x00000ad5u, 0x0004007cu, 0x00000006u, + 0x00000d7cu, 0x00000d7au, 0x00040073u, 0x00000041u, 0x00000d9eu, 0x00000d6au, 0x00060041u, 0x0000004au, + 0x00000d9fu, 0x00000047u, 0x00000d77u, 0x00000d7cu, 0x0003003eu, 0x00000d9fu, 0x00000d9eu, 0x00050080u, + 0x0000001eu, 0x00000d84u, 0x00000d7au, 0x00000067u, 0x0004007cu, 0x00000006u, 0x00000d85u, 0x00000d84u, + 0x00040073u, 0x00000041u, 0x00000da4u, 0x00000d6fu, 0x00060041u, 0x0000004au, 0x00000da5u, 0x00000047u, + 0x00000d77u, 0x00000d85u, 0x0003003eu, 0x00000da5u, 0x00000da4u, 0x00050080u, 0x0000001eu, 0x00000d8au, + 0x00000ebau, 0x00000067u, 0x000200f9u, 0x00000d57u, 0x000200f8u, 0x00000d8bu, 0x000400e0u, 0x00000100u, + 0x00000100u, 0x00000238u, 0x000200f9u, 0x00000426u, 0x000200f8u, 0x00000426u, 0x000700f5u, 0x0000001eu, + 0x00000ebbu, 0x00000564u, 0x00000d8bu, 0x00000469u, 0x00000429u, 0x000500b1u, 0x00000016u, 0x0000042cu, + 0x00000ebbu, 0x00000149u, 0x000400f6u, 0x00000428u, 0x00000429u, 0x00000000u, 0x000400fau, 0x0000042cu, + 0x00000427u, 0x00000428u, 0x000200f8u, 0x00000427u, 0x000200f9u, 0x00000430u, 0x000200f8u, 0x00000430u, + 0x000700f5u, 0x0000001eu, 0x00000ebcu, 0x00000562u, 0x00000427u, 0x00000467u, 0x00000433u, 0x000500b1u, + 0x00000016u, 0x00000437u, 0x00000ebcu, 0x00000436u, 0x000400f6u, 0x00000432u, 0x00000433u, 0x00000000u, + 0x000400fau, 0x00000437u, 0x00000431u, 0x00000432u, 0x000200f8u, 0x00000431u, 0x0004007cu, 0x00000006u, + 0x0000043au, 0x00000ebbu, 0x0004007cu, 0x00000006u, 0x0000043cu, 0x00000ebcu, 0x00060041u, 0x0000004au, + 0x00000dc1u, 0x00000047u, 0x0000043au, 0x0000043cu, 0x0004003du, 0x00000041u, 0x00000dc2u, 0x00000dc1u, + 0x00040073u, 0x00000009u, 0x00000dc3u, 0x00000dc2u, 0x000300f7u, 0x00000442u, 0x00000000u, 0x000400fau, + 0x00000440u, 0x00000441u, 0x00000442u, 0x000200f8u, 0x00000441u, 0x00050081u, 0x00000009u, 0x00000446u, + 0x00000dc3u, 0x00000ec7u, 0x000200f9u, 0x00000442u, 0x000200f8u, 0x00000442u, 0x000700f5u, 0x00000009u, + 0x00000ec0u, 0x00000dc3u, 0x00000431u, 0x00000446u, 0x00000441u, 0x0004003du, 0x00000447u, 0x0000044au, + 0x00000449u, 0x00050084u, 0x0000001eu, 0x0000044cu, 0x0000006bu, 0x00000ebbu, 0x00050050u, 0x0000001fu, + 0x0000044fu, 0x0000044cu, 0x00000ebcu, 0x0007004fu, 0x00000145u, 0x00000451u, 0x000004aau, 0x000004aau, + 0x00000001u, 0x00000000u, 0x0004007cu, 0x0000001fu, 0x00000452u, 0x00000451u, 0x00050084u, 0x0000001fu, + 0x00000454u, 0x00000ec8u, 0x00000452u, 0x00050080u, 0x0000001fu, 0x00000455u, 0x0000044fu, 0x00000454u, + 0x0009004fu, 0x0000002cu, 0x00000457u, 0x00000ec0u, 0x00000ec0u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00040063u, 0x0000044au, 0x00000455u, 0x00000457u, 0x0004003du, 0x00000447u, 0x00000458u, + 0x00000449u, 0x00050080u, 0x0000001eu, 0x0000045bu, 0x0000044cu, 0x00000067u, 0x00050050u, 0x0000001fu, + 0x0000045du, 0x0000045bu, 0x00000ebcu, 0x00050080u, 0x0000001fu, 0x00000463u, 0x0000045du, 0x00000454u, + 0x0009004fu, 0x0000002cu, 0x00000465u, 0x00000ec0u, 0x00000ec0u, 0x00000001u, 0x00000001u, 0x00000001u, + 0x00000001u, 0x00040063u, 0x00000458u, 0x00000463u, 0x00000465u, 0x000200f9u, 0x00000433u, 0x000200f8u, + 0x00000433u, 0x00050080u, 0x0000001eu, 0x00000467u, 0x00000ebcu, 0x000003bcu, 0x000200f9u, 0x00000430u, + 0x000200f8u, 0x00000432u, 0x000200f9u, 0x00000429u, 0x000200f8u, 0x00000429u, 0x00050080u, 0x0000001eu, + 0x00000469u, 0x00000ebbu, 0x000003bcu, 0x000200f9u, 0x00000426u, 0x000200f8u, 0x00000428u, 0x000100fdu, + 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, 0x0000004cu, 0x00000000u, 0x00020011u, 0x00000001u, + 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, + 0x00000001u, 0x0009000fu, 0x00000000u, 0x00000004u, 0x6e69616du, 0x00000000u, 0x00000008u, 0x00000012u, + 0x00000025u, 0x00000034u, 0x00040047u, 0x00000008u, 0x0000000bu, 0x0000002au, 0x00040047u, 0x00000012u, + 0x0000001eu, 0x00000000u, 0x00030047u, 0x00000023u, 0x00000002u, 0x00050048u, 0x00000023u, 0x00000000u, + 0x0000000bu, 0x00000000u, 0x00050048u, 0x00000023u, 0x00000001u, 0x0000000bu, 0x00000001u, 0x00050048u, + 0x00000023u, 0x00000002u, 0x0000000bu, 0x00000003u, 0x00050048u, 0x00000023u, 0x00000003u, 0x0000000bu, + 0x00000004u, 0x00040047u, 0x00000030u, 0x00000001u, 0x00000000u, 0x00040047u, 0x00000034u, 0x0000001eu, + 0x00000000u, 0x00040047u, 0x00000034u, 0x0000001fu, 0x00000002u, 0x00030047u, 0x00000037u, 0x00000002u, + 0x00050048u, 0x00000037u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x00000037u, 0x00000001u, + 0x00000023u, 0x00000008u, 0x00050048u, 0x00000037u, 0x00000002u, 0x00000023u, 0x00000010u, 0x00020013u, + 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, 0x00000001u, + 0x00040020u, 0x00000007u, 0x00000001u, 0x00000006u, 0x0004003bu, 0x00000007u, 0x00000008u, 0x00000001u, + 0x0004002bu, 0x00000006u, 0x0000000au, 0x00000000u, 0x00020014u, 0x0000000bu, 0x00030016u, 0x0000000fu, + 0x00000020u, 0x00040017u, 0x00000010u, 0x0000000fu, 0x00000002u, 0x00040020u, 0x00000011u, 0x00000003u, + 0x00000010u, 0x0004003bu, 0x00000011u, 0x00000012u, 0x00000003u, 0x0004002bu, 0x0000000fu, 0x00000013u, + 0x00000000u, 0x0005002cu, 0x00000010u, 0x00000014u, 0x00000013u, 0x00000013u, 0x0004002bu, 0x00000006u, + 0x00000017u, 0x00000001u, 0x0004002bu, 0x0000000fu, 0x0000001bu, 0x40000000u, 0x0005002cu, 0x00000010u, + 0x0000001cu, 0x00000013u, 0x0000001bu, 0x0005002cu, 0x00000010u, 0x0000001eu, 0x0000001bu, 0x00000013u, + 0x00040017u, 0x0000001fu, 0x0000000fu, 0x00000004u, 0x00040015u, 0x00000020u, 0x00000020u, 0x00000000u, + 0x0004002bu, 0x00000020u, 0x00000021u, 0x00000001u, 0x0004001cu, 0x00000022u, 0x0000000fu, 0x00000021u, + 0x0006001eu, 0x00000023u, 0x0000001fu, 0x0000000fu, 0x00000022u, 0x00000022u, 0x00040020u, 0x00000024u, + 0x00000003u, 0x00000023u, 0x0004003bu, 0x00000024u, 0x00000025u, 0x00000003u, 0x0004002bu, 0x0000000fu, + 0x00000028u, 0x3f800000u, 0x00040020u, 0x0000002eu, 0x00000003u, 0x0000001fu, 0x00030031u, 0x0000000bu, + 0x00000030u, 0x00040020u, 0x00000033u, 0x00000003u, 0x0000000fu, 0x0004003bu, 0x00000033u, 0x00000034u, + 0x00000003u, 0x0005001eu, 0x00000037u, 0x00000010u, 0x00000010u, 0x0000000fu, 0x00040020u, 0x00000038u, + 0x00000009u, 0x00000037u, 0x0004003bu, 0x00000038u, 0x00000039u, 0x00000009u, 0x0004002bu, 0x00000006u, + 0x0000003au, 0x00000002u, 0x00040020u, 0x0000003bu, 0x00000009u, 0x0000000fu, 0x0004002bu, 0x00000020u, + 0x00000040u, 0x00000000u, 0x00040020u, 0x00000046u, 0x00000009u, 0x00000010u, 0x0005002cu, 0x00000010u, + 0x0000004bu, 0x00000028u, 0x00000028u, 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, + 0x000200f8u, 0x00000005u, 0x0004003du, 0x00000006u, 0x00000009u, 0x00000008u, 0x000500aau, 0x0000000bu, + 0x0000000cu, 0x00000009u, 0x0000000au, 0x000300f7u, 0x0000000eu, 0x00000000u, 0x000400fau, 0x0000000cu, + 0x0000000du, 0x00000015u, 0x000200f8u, 0x0000000du, 0x0003003eu, 0x00000012u, 0x00000014u, 0x000200f9u, + 0x0000000eu, 0x000200f8u, 0x00000015u, 0x000500aau, 0x0000000bu, 0x00000018u, 0x00000009u, 0x00000017u, + 0x000300f7u, 0x0000001au, 0x00000000u, 0x000400fau, 0x00000018u, 0x00000019u, 0x0000001du, 0x000200f8u, + 0x00000019u, 0x0003003eu, 0x00000012u, 0x0000001cu, 0x000200f9u, 0x0000001au, 0x000200f8u, 0x0000001du, + 0x0003003eu, 0x00000012u, 0x0000001eu, 0x000200f9u, 0x0000001au, 0x000200f8u, 0x0000001au, 0x000200f9u, + 0x0000000eu, 0x000200f8u, 0x0000000eu, 0x0004003du, 0x00000010u, 0x00000026u, 0x00000012u, 0x0005008eu, + 0x00000010u, 0x00000027u, 0x00000026u, 0x0000001bu, 0x00050083u, 0x00000010u, 0x0000002au, 0x00000027u, + 0x0000004bu, 0x00050051u, 0x0000000fu, 0x0000002bu, 0x0000002au, 0x00000000u, 0x00050051u, 0x0000000fu, + 0x0000002cu, 0x0000002au, 0x00000001u, 0x00070050u, 0x0000001fu, 0x0000002du, 0x0000002bu, 0x0000002cu, + 0x00000013u, 0x00000028u, 0x00050041u, 0x0000002eu, 0x0000002fu, 0x00000025u, 0x0000000au, 0x0003003eu, + 0x0000002fu, 0x0000002du, 0x000300f7u, 0x00000032u, 0x00000000u, 0x000400fau, 0x00000030u, 0x00000031u, + 0x0000003fu, 0x000200f8u, 0x00000031u, 0x00050041u, 0x00000033u, 0x00000035u, 0x00000012u, 0x00000021u, + 0x0004003du, 0x0000000fu, 0x00000036u, 0x00000035u, 0x00050041u, 0x0000003bu, 0x0000003cu, 0x00000039u, + 0x0000003au, 0x0004003du, 0x0000000fu, 0x0000003du, 0x0000003cu, 0x00050085u, 0x0000000fu, 0x0000003eu, + 0x00000036u, 0x0000003du, 0x0003003eu, 0x00000034u, 0x0000003eu, 0x000200f9u, 0x00000032u, 0x000200f8u, + 0x0000003fu, 0x00050041u, 0x00000033u, 0x00000041u, 0x00000012u, 0x00000040u, 0x0004003du, 0x0000000fu, + 0x00000042u, 0x00000041u, 0x00050041u, 0x0000003bu, 0x00000043u, 0x00000039u, 0x0000003au, 0x0004003du, + 0x0000000fu, 0x00000044u, 0x00000043u, 0x00050085u, 0x0000000fu, 0x00000045u, 0x00000042u, 0x00000044u, + 0x0003003eu, 0x00000034u, 0x00000045u, 0x000200f9u, 0x00000032u, 0x000200f8u, 0x00000032u, 0x00050041u, + 0x00000046u, 0x00000047u, 0x00000039u, 0x0000000au, 0x0004003du, 0x00000010u, 0x00000048u, 0x00000047u, + 0x0004003du, 0x00000010u, 0x00000049u, 0x00000012u, 0x00050081u, 0x00000010u, 0x0000004au, 0x00000049u, + 0x00000048u, 0x0003003eu, 0x00000012u, 0x0000004au, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, + 0x000d000bu, 0x000001f2u, 0x00000000u, 0x00020011u, 0x00000001u, 0x0006000bu, 0x00000001u, 0x4c534c47u, + 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0008000fu, 0x00000004u, + 0x00000004u, 0x6e69616du, 0x00000000u, 0x00000015u, 0x000000a8u, 0x00000131u, 0x00030010u, 0x00000004u, + 0x00000007u, 0x00040047u, 0x00000015u, 0x0000001eu, 0x00000000u, 0x00030047u, 0x00000018u, 0x00000002u, + 0x00050048u, 0x00000018u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x00000018u, 0x00000001u, + 0x00000023u, 0x00000008u, 0x00050048u, 0x00000018u, 0x00000002u, 0x00000023u, 0x00000010u, 0x00050048u, + 0x00000018u, 0x00000003u, 0x00000023u, 0x00000014u, 0x00040047u, 0x00000021u, 0x00000001u, 0x00000000u, + 0x00030047u, 0x00000028u, 0x00000000u, 0x00040047u, 0x00000028u, 0x00000021u, 0x00000002u, 0x00040047u, + 0x00000028u, 0x00000022u, 0x00000000u, 0x00040047u, 0x000000a8u, 0x0000001eu, 0x00000000u, 0x00040047u, + 0x000000a8u, 0x0000001fu, 0x00000002u, 0x00030047u, 0x000000aeu, 0x00000000u, 0x00040047u, 0x000000aeu, + 0x00000021u, 0x00000000u, 0x00040047u, 0x000000aeu, 0x00000022u, 0x00000000u, 0x00030047u, 0x000000afu, + 0x00000000u, 0x00040047u, 0x000000afu, 0x00000021u, 0x00000001u, 0x00040047u, 0x000000afu, 0x00000022u, + 0x00000000u, 0x00040047u, 0x000000b1u, 0x00000001u, 0x00000003u, 0x00030047u, 0x00000131u, 0x00000000u, + 0x00040047u, 0x00000131u, 0x0000001eu, 0x00000000u, 0x00040047u, 0x00000133u, 0x00000001u, 0x00000001u, + 0x00030047u, 0x00000137u, 0x00000000u, 0x00030047u, 0x00000138u, 0x00000000u, 0x00030047u, 0x00000149u, + 0x00000000u, 0x00030047u, 0x0000014au, 0x00000000u, 0x00030047u, 0x0000014fu, 0x00000000u, 0x00030047u, + 0x00000150u, 0x00000000u, 0x00030047u, 0x00000155u, 0x00000000u, 0x00030047u, 0x00000156u, 0x00000000u, + 0x00030047u, 0x0000015bu, 0x00000000u, 0x00030047u, 0x0000015cu, 0x00000000u, 0x00030047u, 0x00000162u, + 0x00000000u, 0x00030047u, 0x00000163u, 0x00000000u, 0x00030047u, 0x00000168u, 0x00000000u, 0x00030047u, + 0x00000169u, 0x00000000u, 0x00030047u, 0x0000016eu, 0x00000000u, 0x00030047u, 0x0000016fu, 0x00000000u, + 0x00030047u, 0x00000174u, 0x00000000u, 0x00030047u, 0x00000175u, 0x00000000u, 0x00030047u, 0x00000194u, + 0x00000000u, 0x00030047u, 0x00000195u, 0x00000000u, 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, + 0x00000002u, 0x00030016u, 0x00000006u, 0x00000020u, 0x00090019u, 0x00000007u, 0x00000006u, 0x00000001u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00040020u, 0x00000008u, 0x00000000u, + 0x00000007u, 0x00040017u, 0x00000011u, 0x00000006u, 0x00000002u, 0x00040020u, 0x00000014u, 0x00000001u, + 0x00000011u, 0x0004003bu, 0x00000014u, 0x00000015u, 0x00000001u, 0x00040015u, 0x00000017u, 0x00000020u, + 0x00000001u, 0x0006001eu, 0x00000018u, 0x00000011u, 0x00000011u, 0x00000006u, 0x00000017u, 0x00040020u, + 0x00000019u, 0x00000009u, 0x00000018u, 0x0004003bu, 0x00000019u, 0x0000001au, 0x00000009u, 0x0004002bu, + 0x00000017u, 0x0000001bu, 0x00000001u, 0x00040020u, 0x0000001cu, 0x00000009u, 0x00000011u, 0x00020014u, + 0x00000020u, 0x00030031u, 0x00000020u, 0x00000021u, 0x0002001au, 0x00000026u, 0x00040020u, 0x00000027u, + 0x00000000u, 0x00000026u, 0x0004003bu, 0x00000027u, 0x00000028u, 0x00000000u, 0x0003001bu, 0x0000002au, + 0x00000007u, 0x00040017u, 0x0000002du, 0x00000017u, 0x00000002u, 0x0004002bu, 0x00000017u, 0x0000002eu, + 0x00000000u, 0x0005002cu, 0x0000002du, 0x0000002fu, 0x0000002eu, 0x0000001bu, 0x0005002cu, 0x0000002du, + 0x00000030u, 0x0000001bu, 0x0000002eu, 0x00040017u, 0x00000031u, 0x00000020u, 0x00000002u, 0x00050033u, + 0x00000031u, 0x00000032u, 0x00000021u, 0x00000021u, 0x00070034u, 0x0000002du, 0x00000033u, 0x000000a9u, + 0x00000032u, 0x0000002fu, 0x00000030u, 0x00040017u, 0x00000034u, 0x00000006u, 0x00000004u, 0x0004002bu, + 0x00000017u, 0x0000003cu, 0x00000003u, 0x0005002cu, 0x0000002du, 0x0000003du, 0x0000002eu, 0x0000003cu, + 0x0005002cu, 0x0000002du, 0x0000003eu, 0x0000003cu, 0x0000002eu, 0x00050033u, 0x00000031u, 0x0000003fu, + 0x00000021u, 0x00000021u, 0x00070034u, 0x0000002du, 0x00000040u, 0x000000a9u, 0x0000003fu, 0x0000003du, + 0x0000003eu, 0x0005002cu, 0x0000002du, 0x00000048u, 0x0000002eu, 0x0000002eu, 0x00050033u, 0x00000031u, + 0x00000049u, 0x00000021u, 0x00000021u, 0x00070034u, 0x0000002du, 0x0000004au, 0x000000a9u, 0x00000049u, + 0x00000048u, 0x00000048u, 0x0004002bu, 0x00000017u, 0x00000052u, 0x00000002u, 0x0005002cu, 0x0000002du, + 0x00000053u, 0x0000002eu, 0x00000052u, 0x0005002cu, 0x0000002du, 0x00000054u, 0x00000052u, 0x0000002eu, + 0x00050033u, 0x00000031u, 0x00000055u, 0x00000021u, 0x00000021u, 0x00070034u, 0x0000002du, 0x00000056u, + 0x000000a9u, 0x00000055u, 0x00000053u, 0x00000054u, 0x0004002bu, 0x00000006u, 0x00000074u, 0x00000000u, + 0x0004002bu, 0x00000017u, 0x00000082u, 0x00000004u, 0x0005002cu, 0x0000002du, 0x0000009bu, 0x0000002eu, + 0x00000082u, 0x0005002cu, 0x0000002du, 0x0000009cu, 0x00000082u, 0x0000002eu, 0x00050033u, 0x00000031u, + 0x0000009du, 0x00000021u, 0x00000021u, 0x00070034u, 0x0000002du, 0x0000009eu, 0x000000a9u, 0x0000009du, + 0x0000009bu, 0x0000009cu, 0x00040020u, 0x000000a7u, 0x00000001u, 0x00000006u, 0x0004003bu, 0x000000a7u, + 0x000000a8u, 0x00000001u, 0x0004003bu, 0x00000008u, 0x000000aeu, 0x00000000u, 0x0004003bu, 0x00000008u, + 0x000000afu, 0x00000000u, 0x00040032u, 0x00000017u, 0x000000b1u, 0x00000000u, 0x00060034u, 0x00000020u, + 0x000000b2u, 0x000000b1u, 0x000000b1u, 0x0000002eu, 0x0004002bu, 0x00000006u, 0x000000b6u, 0x3f800000u, + 0x00060034u, 0x00000020u, 0x000000beu, 0x000000adu, 0x000000b1u, 0x0000002eu, 0x0004002bu, 0x00000006u, + 0x000000c2u, 0x40000000u, 0x00040020u, 0x000000c4u, 0x00000009u, 0x00000017u, 0x0004002bu, 0x00000006u, + 0x000000d3u, 0x40800000u, 0x0004002bu, 0x00000006u, 0x000000fdu, 0x3f1a5adeu, 0x0004002bu, 0x00000006u, + 0x000000ffu, 0x3f175d96u, 0x0004002bu, 0x00000006u, 0x00000101u, 0xbda03385u, 0x0004002bu, 0x00000006u, + 0x00000103u, 0xbdbaecb1u, 0x0004002bu, 0x00000006u, 0x00000105u, 0x3cdb2036u, 0x0004002bu, 0x00000006u, + 0x00000118u, 0x3f8ebb2cu, 0x0004002bu, 0x00000006u, 0x00000119u, 0xbe88a26au, 0x0004002bu, 0x00000006u, + 0x0000011au, 0xbd6bb2c3u, 0x0004002bu, 0x00000006u, 0x0000011bu, 0x3c8a269fu, 0x00040020u, 0x00000130u, + 0x00000003u, 0x00000006u, 0x0004003bu, 0x00000130u, 0x00000131u, 0x00000003u, 0x00030031u, 0x00000020u, + 0x00000133u, 0x0004002bu, 0x00000006u, 0x00000136u, 0x3f000000u, 0x00050036u, 0x00000002u, 0x00000004u, + 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003du, 0x00000006u, 0x000000a9u, 0x000000a8u, + 0x0004006eu, 0x00000017u, 0x000000aau, 0x000000a9u, 0x000500c7u, 0x00000017u, 0x000000abu, 0x000000aau, + 0x0000001bu, 0x000500abu, 0x00000020u, 0x000000acu, 0x000000abu, 0x0000002eu, 0x0004003du, 0x00000011u, + 0x00000144u, 0x00000015u, 0x00050041u, 0x0000001cu, 0x00000145u, 0x0000001au, 0x0000001bu, 0x0004003du, + 0x00000011u, 0x00000146u, 0x00000145u, 0x00050081u, 0x00000011u, 0x00000147u, 0x00000144u, 0x00000146u, + 0x000300f7u, 0x0000017au, 0x00000000u, 0x000400fau, 0x00000021u, 0x00000148u, 0x00000161u, 0x000200f8u, + 0x00000148u, 0x0004003du, 0x00000007u, 0x00000149u, 0x000000aeu, 0x0004003du, 0x00000026u, 0x0000014au, + 0x00000028u, 0x00050056u, 0x0000002au, 0x0000014bu, 0x00000149u, 0x0000014au, 0x00080060u, 0x00000034u, + 0x0000014du, 0x0000014bu, 0x00000147u, 0x0000002eu, 0x00000008u, 0x00000033u, 0x0007004fu, 0x00000011u, + 0x0000014eu, 0x0000014du, 0x0000014du, 0x00000003u, 0x00000000u, 0x0004003du, 0x00000007u, 0x0000014fu, + 0x000000aeu, 0x0004003du, 0x00000026u, 0x00000150u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000151u, + 0x0000014fu, 0x00000150u, 0x00080060u, 0x00000034u, 0x00000153u, 0x00000151u, 0x00000147u, 0x0000002eu, + 0x00000008u, 0x00000040u, 0x0007004fu, 0x00000011u, 0x00000154u, 0x00000153u, 0x00000153u, 0x00000003u, + 0x00000000u, 0x0004003du, 0x00000007u, 0x00000155u, 0x000000afu, 0x0004003du, 0x00000026u, 0x00000156u, + 0x00000028u, 0x00050056u, 0x0000002au, 0x00000157u, 0x00000155u, 0x00000156u, 0x00080060u, 0x00000034u, + 0x00000159u, 0x00000157u, 0x00000147u, 0x0000002eu, 0x00000008u, 0x0000004au, 0x0007004fu, 0x00000011u, + 0x0000015au, 0x00000159u, 0x00000159u, 0x00000003u, 0x00000000u, 0x0004003du, 0x00000007u, 0x0000015bu, + 0x000000afu, 0x0004003du, 0x00000026u, 0x0000015cu, 0x00000028u, 0x00050056u, 0x0000002au, 0x0000015du, + 0x0000015bu, 0x0000015cu, 0x00080060u, 0x00000034u, 0x0000015fu, 0x0000015du, 0x00000147u, 0x0000002eu, + 0x00000008u, 0x00000056u, 0x0007004fu, 0x00000011u, 0x00000160u, 0x0000015fu, 0x0000015fu, 0x00000003u, + 0x00000000u, 0x000200f9u, 0x0000017au, 0x000200f8u, 0x00000161u, 0x0004003du, 0x00000007u, 0x00000162u, + 0x000000aeu, 0x0004003du, 0x00000026u, 0x00000163u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000164u, + 0x00000162u, 0x00000163u, 0x00080060u, 0x00000034u, 0x00000166u, 0x00000164u, 0x00000147u, 0x0000002eu, + 0x00000008u, 0x00000033u, 0x0007004fu, 0x00000011u, 0x00000167u, 0x00000166u, 0x00000166u, 0x00000003u, + 0x00000002u, 0x0004003du, 0x00000007u, 0x00000168u, 0x000000aeu, 0x0004003du, 0x00000026u, 0x00000169u, + 0x00000028u, 0x00050056u, 0x0000002au, 0x0000016au, 0x00000168u, 0x00000169u, 0x00080060u, 0x00000034u, + 0x0000016cu, 0x0000016au, 0x00000147u, 0x0000002eu, 0x00000008u, 0x00000040u, 0x0007004fu, 0x00000011u, + 0x0000016du, 0x0000016cu, 0x0000016cu, 0x00000003u, 0x00000002u, 0x0004003du, 0x00000007u, 0x0000016eu, + 0x000000afu, 0x0004003du, 0x00000026u, 0x0000016fu, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000170u, + 0x0000016eu, 0x0000016fu, 0x00080060u, 0x00000034u, 0x00000172u, 0x00000170u, 0x00000147u, 0x0000002eu, + 0x00000008u, 0x0000004au, 0x0007004fu, 0x00000011u, 0x00000173u, 0x00000172u, 0x00000172u, 0x00000003u, + 0x00000002u, 0x0004003du, 0x00000007u, 0x00000174u, 0x000000afu, 0x0004003du, 0x00000026u, 0x00000175u, + 0x00000028u, 0x00050056u, 0x0000002au, 0x00000176u, 0x00000174u, 0x00000175u, 0x00080060u, 0x00000034u, + 0x00000178u, 0x00000176u, 0x00000147u, 0x0000002eu, 0x00000008u, 0x00000056u, 0x0007004fu, 0x00000011u, + 0x00000179u, 0x00000178u, 0x00000178u, 0x00000003u, 0x00000002u, 0x000200f9u, 0x0000017au, 0x000200f8u, + 0x0000017au, 0x000700f5u, 0x00000011u, 0x000001cfu, 0x00000154u, 0x00000148u, 0x0000016du, 0x00000161u, + 0x000700f5u, 0x00000011u, 0x000001ceu, 0x00000160u, 0x00000148u, 0x00000179u, 0x00000161u, 0x000700f5u, + 0x00000011u, 0x000001cdu, 0x0000014eu, 0x00000148u, 0x00000167u, 0x00000161u, 0x000700f5u, 0x00000011u, + 0x000001ccu, 0x0000015au, 0x00000148u, 0x00000173u, 0x00000161u, 0x00050051u, 0x00000006u, 0x0000017du, + 0x000001ccu, 0x00000000u, 0x00050051u, 0x00000006u, 0x00000180u, 0x000001cdu, 0x00000000u, 0x00050051u, + 0x00000006u, 0x00000183u, 0x000001ccu, 0x00000001u, 0x00050051u, 0x00000006u, 0x00000186u, 0x000001cdu, + 0x00000001u, 0x00050051u, 0x00000006u, 0x00000189u, 0x000001ceu, 0x00000000u, 0x00050051u, 0x00000006u, + 0x0000018cu, 0x000001cfu, 0x00000000u, 0x00050051u, 0x00000006u, 0x0000018fu, 0x000001ceu, 0x00000001u, + 0x00050051u, 0x00000006u, 0x00000192u, 0x000001cfu, 0x00000001u, 0x0004003du, 0x00000007u, 0x00000194u, + 0x000000afu, 0x0004003du, 0x00000026u, 0x00000195u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000196u, + 0x00000194u, 0x00000195u, 0x00080058u, 0x00000034u, 0x00000198u, 0x00000196u, 0x00000144u, 0x0000000au, + 0x00000074u, 0x0000009eu, 0x00050051u, 0x00000006u, 0x00000199u, 0x00000198u, 0x00000000u, 0x000300f7u, + 0x000000b4u, 0x00000000u, 0x000400fau, 0x000000b2u, 0x000000b3u, 0x000000bdu, 0x000200f8u, 0x000000b3u, + 0x000500b8u, 0x00000020u, 0x000000b7u, 0x000000a9u, 0x000000b6u, 0x000600a9u, 0x00000006u, 0x000001e9u, + 0x000000b7u, 0x0000018cu, 0x00000180u, 0x000200f9u, 0x000000b4u, 0x000200f8u, 0x000000bdu, 0x000300f7u, + 0x000000c0u, 0x00000000u, 0x000400fau, 0x000000beu, 0x000000bfu, 0x000000c0u, 0x000200f8u, 0x000000bfu, + 0x00050081u, 0x00000006u, 0x000000c3u, 0x000000a9u, 0x000000c2u, 0x00050041u, 0x000000c4u, 0x000000c5u, + 0x0000001au, 0x0000003cu, 0x0004003du, 0x00000017u, 0x000000c6u, 0x000000c5u, 0x0004006fu, 0x00000006u, + 0x000000c7u, 0x000000c6u, 0x000500bau, 0x00000020u, 0x000000c8u, 0x000000c3u, 0x000000c7u, 0x000300f7u, + 0x000000cau, 0x00000000u, 0x000400fau, 0x000000c8u, 0x000000c9u, 0x000000d1u, 0x000200f8u, 0x000000c9u, + 0x000200f9u, 0x000000cau, 0x000200f8u, 0x000000d1u, 0x00050081u, 0x00000006u, 0x000000d4u, 0x000000a9u, + 0x000000d3u, 0x000500beu, 0x00000020u, 0x000000d8u, 0x000000d4u, 0x000000c7u, 0x000600a9u, 0x00000006u, + 0x000001eau, 0x000000d8u, 0x00000189u, 0x00000199u, 0x000200f9u, 0x000000cau, 0x000200f8u, 0x000000cau, + 0x000700f5u, 0x00000006u, 0x000001ddu, 0x0000017du, 0x000000c9u, 0x000001eau, 0x000000d1u, 0x000600a9u, + 0x00000006u, 0x000001ebu, 0x000000c8u, 0x00000183u, 0x0000018fu, 0x000200f9u, 0x000000c0u, 0x000200f8u, + 0x000000c0u, 0x000700f5u, 0x00000006u, 0x000001dcu, 0x00000199u, 0x000000bdu, 0x000001ddu, 0x000000cau, + 0x000700f5u, 0x00000006u, 0x000001d7u, 0x0000018fu, 0x000000bdu, 0x000001ebu, 0x000000cau, 0x000200f9u, + 0x000000b4u, 0x000200f8u, 0x000000b4u, 0x000700f5u, 0x00000006u, 0x000001dau, 0x00000199u, 0x000000b3u, + 0x000001dcu, 0x000000c0u, 0x000700f5u, 0x00000006u, 0x000001d5u, 0x0000018fu, 0x000000b3u, 0x000001d7u, + 0x000000c0u, 0x000700f5u, 0x00000006u, 0x000001d0u, 0x000001e9u, 0x000000b3u, 0x00000180u, 0x000000c0u, + 0x000300f7u, 0x000000e0u, 0x00000000u, 0x000400fau, 0x000000acu, 0x000000dfu, 0x00000106u, 0x000200f8u, + 0x000000dfu, 0x00050081u, 0x00000006u, 0x000000e9u, 0x00000186u, 0x0000018cu, 0x00050081u, 0x00000006u, + 0x000000efu, 0x00000183u, 0x000001d5u, 0x00050081u, 0x00000006u, 0x000000f5u, 0x000001d0u, 0x00000192u, + 0x00050081u, 0x00000006u, 0x000000fbu, 0x0000017du, 0x000001dau, 0x000200f9u, 0x000000e0u, 0x000200f8u, + 0x00000106u, 0x00050081u, 0x00000006u, 0x0000010du, 0x00000183u, 0x00000189u, 0x00050081u, 0x00000006u, + 0x00000112u, 0x000001d0u, 0x0000018cu, 0x00050081u, 0x00000006u, 0x00000117u, 0x0000017du, 0x000001d5u, + 0x000200f9u, 0x000000e0u, 0x000200f8u, 0x000000e0u, 0x000700f5u, 0x00000006u, 0x000001e7u, 0x000000fbu, + 0x000000dfu, 0x00000074u, 0x00000106u, 0x000700f5u, 0x00000006u, 0x000001e5u, 0x000000f5u, 0x000000dfu, + 0x00000117u, 0x00000106u, 0x000700f5u, 0x00000006u, 0x000001e3u, 0x000000efu, 0x000000dfu, 0x00000112u, + 0x00000106u, 0x000700f5u, 0x00000006u, 0x000001e1u, 0x000000e9u, 0x000000dfu, 0x0000010du, 0x00000106u, + 0x000600a9u, 0x00000006u, 0x000001ecu, 0x000000acu, 0x00000105u, 0x00000074u, 0x000600a9u, 0x00000006u, + 0x000001edu, 0x000000acu, 0x00000103u, 0x0000011bu, 0x000600a9u, 0x00000006u, 0x000001eeu, 0x000000acu, + 0x00000101u, 0x0000011au, 0x000600a9u, 0x00000006u, 0x000001efu, 0x000000acu, 0x000000ffu, 0x00000119u, + 0x000600a9u, 0x00000006u, 0x000001f0u, 0x000000acu, 0x000000fdu, 0x00000118u, 0x000600a9u, 0x00000006u, + 0x000001f1u, 0x000000acu, 0x00000189u, 0x00000186u, 0x00050085u, 0x00000006u, 0x0000011fu, 0x000001f1u, + 0x000001f0u, 0x00050085u, 0x00000006u, 0x00000122u, 0x000001e1u, 0x000001efu, 0x00050081u, 0x00000006u, + 0x00000123u, 0x0000011fu, 0x00000122u, 0x00050085u, 0x00000006u, 0x00000126u, 0x000001e3u, 0x000001eeu, + 0x00050081u, 0x00000006u, 0x00000127u, 0x00000123u, 0x00000126u, 0x00050085u, 0x00000006u, 0x0000012au, + 0x000001e5u, 0x000001edu, 0x00050081u, 0x00000006u, 0x0000012bu, 0x00000127u, 0x0000012au, 0x00050085u, + 0x00000006u, 0x0000012eu, 0x000001e7u, 0x000001ecu, 0x00050081u, 0x00000006u, 0x0000012fu, 0x0000012bu, + 0x0000012eu, 0x0003003eu, 0x00000131u, 0x0000012fu, 0x000300f7u, 0x00000135u, 0x00000000u, 0x000400fau, + 0x00000133u, 0x00000134u, 0x00000135u, 0x000200f8u, 0x00000134u, 0x0004003du, 0x00000006u, 0x00000137u, + 0x00000131u, 0x00050081u, 0x00000006u, 0x00000138u, 0x00000137u, 0x00000136u, 0x0003003eu, 0x00000131u, + 0x00000138u, 0x000200f9u, 0x00000135u, 0x000200f8u, 0x00000135u, 0x000100fdu, 0x00010038u, 0x07230203u, + 0x00010300u, 0x000d000bu, 0x00000423u, 0x00000000u, 0x00020011u, 0x00000001u, 0x0006000bu, 0x00000001u, + 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0009000fu, + 0x00000004u, 0x00000004u, 0x6e69616du, 0x00000000u, 0x00000015u, 0x000000a8u, 0x000001a4u, 0x000001a8u, + 0x00030010u, 0x00000004u, 0x00000007u, 0x00040047u, 0x00000015u, 0x0000001eu, 0x00000000u, 0x00030047u, + 0x00000018u, 0x00000002u, 0x00050048u, 0x00000018u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, + 0x00000018u, 0x00000001u, 0x00000023u, 0x00000008u, 0x00050048u, 0x00000018u, 0x00000002u, 0x00000023u, + 0x00000010u, 0x00050048u, 0x00000018u, 0x00000003u, 0x00000023u, 0x00000014u, 0x00040047u, 0x00000021u, + 0x00000001u, 0x00000000u, 0x00030047u, 0x00000028u, 0x00000000u, 0x00040047u, 0x00000028u, 0x00000021u, + 0x00000002u, 0x00040047u, 0x00000028u, 0x00000022u, 0x00000000u, 0x00040047u, 0x000000a8u, 0x0000001eu, + 0x00000000u, 0x00040047u, 0x000000a8u, 0x0000001fu, 0x00000002u, 0x00030047u, 0x000000aeu, 0x00000000u, + 0x00040047u, 0x000000aeu, 0x00000021u, 0x00000000u, 0x00040047u, 0x000000aeu, 0x00000022u, 0x00000000u, + 0x00030047u, 0x000000afu, 0x00000000u, 0x00040047u, 0x000000afu, 0x00000021u, 0x00000001u, 0x00040047u, + 0x000000afu, 0x00000022u, 0x00000000u, 0x00030047u, 0x000000b2u, 0x00000000u, 0x00040047u, 0x000000b2u, + 0x00000021u, 0x00000003u, 0x00040047u, 0x000000b2u, 0x00000022u, 0x00000000u, 0x00030047u, 0x000000b3u, + 0x00000000u, 0x00040047u, 0x000000b3u, 0x00000021u, 0x00000004u, 0x00040047u, 0x000000b3u, 0x00000022u, + 0x00000000u, 0x00030047u, 0x000000b6u, 0x00000000u, 0x00040047u, 0x000000b6u, 0x00000021u, 0x00000005u, + 0x00040047u, 0x000000b6u, 0x00000022u, 0x00000000u, 0x00030047u, 0x000000b7u, 0x00000000u, 0x00040047u, + 0x000000b7u, 0x00000021u, 0x00000006u, 0x00040047u, 0x000000b7u, 0x00000022u, 0x00000000u, 0x00040047u, + 0x000000d1u, 0x00000001u, 0x00000003u, 0x00030047u, 0x000001a4u, 0x00000000u, 0x00040047u, 0x000001a4u, + 0x0000001eu, 0x00000000u, 0x00030047u, 0x000001a8u, 0x00000000u, 0x00040047u, 0x000001a8u, 0x0000001eu, + 0x00000001u, 0x00040047u, 0x000001abu, 0x00000001u, 0x00000001u, 0x00030047u, 0x000001afu, 0x00000000u, + 0x00030047u, 0x000001b0u, 0x00000000u, 0x00040047u, 0x000001b1u, 0x00000001u, 0x00000002u, 0x00030047u, + 0x000001b4u, 0x00000000u, 0x00030047u, 0x000001b6u, 0x00000000u, 0x00030047u, 0x000001c4u, 0x00000000u, + 0x00030047u, 0x000001c5u, 0x00000000u, 0x00030047u, 0x000001cau, 0x00000000u, 0x00030047u, 0x000001cbu, + 0x00000000u, 0x00030047u, 0x000001d0u, 0x00000000u, 0x00030047u, 0x000001d1u, 0x00000000u, 0x00030047u, + 0x000001d6u, 0x00000000u, 0x00030047u, 0x000001d7u, 0x00000000u, 0x00030047u, 0x000001ddu, 0x00000000u, + 0x00030047u, 0x000001deu, 0x00000000u, 0x00030047u, 0x000001e3u, 0x00000000u, 0x00030047u, 0x000001e4u, + 0x00000000u, 0x00030047u, 0x000001e9u, 0x00000000u, 0x00030047u, 0x000001eau, 0x00000000u, 0x00030047u, + 0x000001efu, 0x00000000u, 0x00030047u, 0x000001f0u, 0x00000000u, 0x00030047u, 0x0000020fu, 0x00000000u, + 0x00030047u, 0x00000210u, 0x00000000u, 0x00030047u, 0x00000224u, 0x00000000u, 0x00030047u, 0x00000225u, + 0x00000000u, 0x00030047u, 0x0000022au, 0x00000000u, 0x00030047u, 0x0000022bu, 0x00000000u, 0x00030047u, + 0x00000230u, 0x00000000u, 0x00030047u, 0x00000231u, 0x00000000u, 0x00030047u, 0x00000236u, 0x00000000u, + 0x00030047u, 0x00000237u, 0x00000000u, 0x00030047u, 0x0000023du, 0x00000000u, 0x00030047u, 0x0000023eu, + 0x00000000u, 0x00030047u, 0x00000243u, 0x00000000u, 0x00030047u, 0x00000244u, 0x00000000u, 0x00030047u, + 0x00000249u, 0x00000000u, 0x00030047u, 0x0000024au, 0x00000000u, 0x00030047u, 0x0000024fu, 0x00000000u, + 0x00030047u, 0x00000250u, 0x00000000u, 0x00030047u, 0x0000026fu, 0x00000000u, 0x00030047u, 0x00000270u, + 0x00000000u, 0x00030047u, 0x00000284u, 0x00000000u, 0x00030047u, 0x00000285u, 0x00000000u, 0x00030047u, + 0x0000028au, 0x00000000u, 0x00030047u, 0x0000028bu, 0x00000000u, 0x00030047u, 0x00000290u, 0x00000000u, + 0x00030047u, 0x00000291u, 0x00000000u, 0x00030047u, 0x00000296u, 0x00000000u, 0x00030047u, 0x00000297u, + 0x00000000u, 0x00030047u, 0x0000029du, 0x00000000u, 0x00030047u, 0x0000029eu, 0x00000000u, 0x00030047u, + 0x000002a3u, 0x00000000u, 0x00030047u, 0x000002a4u, 0x00000000u, 0x00030047u, 0x000002a9u, 0x00000000u, + 0x00030047u, 0x000002aau, 0x00000000u, 0x00030047u, 0x000002afu, 0x00000000u, 0x00030047u, 0x000002b0u, + 0x00000000u, 0x00030047u, 0x000002cfu, 0x00000000u, 0x00030047u, 0x000002d0u, 0x00000000u, 0x00020013u, + 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00030016u, 0x00000006u, 0x00000020u, 0x00090019u, + 0x00000007u, 0x00000006u, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, + 0x00040020u, 0x00000008u, 0x00000000u, 0x00000007u, 0x00040017u, 0x00000011u, 0x00000006u, 0x00000002u, + 0x00040020u, 0x00000014u, 0x00000001u, 0x00000011u, 0x0004003bu, 0x00000014u, 0x00000015u, 0x00000001u, + 0x00040015u, 0x00000017u, 0x00000020u, 0x00000001u, 0x0006001eu, 0x00000018u, 0x00000011u, 0x00000011u, + 0x00000006u, 0x00000017u, 0x00040020u, 0x00000019u, 0x00000009u, 0x00000018u, 0x0004003bu, 0x00000019u, + 0x0000001au, 0x00000009u, 0x0004002bu, 0x00000017u, 0x0000001bu, 0x00000001u, 0x00040020u, 0x0000001cu, + 0x00000009u, 0x00000011u, 0x00020014u, 0x00000020u, 0x00030031u, 0x00000020u, 0x00000021u, 0x0002001au, + 0x00000026u, 0x00040020u, 0x00000027u, 0x00000000u, 0x00000026u, 0x0004003bu, 0x00000027u, 0x00000028u, + 0x00000000u, 0x0003001bu, 0x0000002au, 0x00000007u, 0x00040017u, 0x0000002du, 0x00000017u, 0x00000002u, + 0x0004002bu, 0x00000017u, 0x0000002eu, 0x00000000u, 0x0005002cu, 0x0000002du, 0x0000002fu, 0x0000002eu, + 0x0000001bu, 0x0005002cu, 0x0000002du, 0x00000030u, 0x0000001bu, 0x0000002eu, 0x00040017u, 0x00000031u, + 0x00000020u, 0x00000002u, 0x00050033u, 0x00000031u, 0x00000032u, 0x00000021u, 0x00000021u, 0x00070034u, + 0x0000002du, 0x00000033u, 0x000000a9u, 0x00000032u, 0x0000002fu, 0x00000030u, 0x00040017u, 0x00000034u, + 0x00000006u, 0x00000004u, 0x0004002bu, 0x00000017u, 0x0000003cu, 0x00000003u, 0x0005002cu, 0x0000002du, + 0x0000003du, 0x0000002eu, 0x0000003cu, 0x0005002cu, 0x0000002du, 0x0000003eu, 0x0000003cu, 0x0000002eu, + 0x00050033u, 0x00000031u, 0x0000003fu, 0x00000021u, 0x00000021u, 0x00070034u, 0x0000002du, 0x00000040u, + 0x000000a9u, 0x0000003fu, 0x0000003du, 0x0000003eu, 0x0005002cu, 0x0000002du, 0x00000048u, 0x0000002eu, + 0x0000002eu, 0x00050033u, 0x00000031u, 0x00000049u, 0x00000021u, 0x00000021u, 0x00070034u, 0x0000002du, + 0x0000004au, 0x000000a9u, 0x00000049u, 0x00000048u, 0x00000048u, 0x0004002bu, 0x00000017u, 0x00000052u, + 0x00000002u, 0x0005002cu, 0x0000002du, 0x00000053u, 0x0000002eu, 0x00000052u, 0x0005002cu, 0x0000002du, + 0x00000054u, 0x00000052u, 0x0000002eu, 0x00050033u, 0x00000031u, 0x00000055u, 0x00000021u, 0x00000021u, + 0x00070034u, 0x0000002du, 0x00000056u, 0x000000a9u, 0x00000055u, 0x00000053u, 0x00000054u, 0x0004002bu, + 0x00000006u, 0x00000074u, 0x00000000u, 0x0004002bu, 0x00000017u, 0x00000082u, 0x00000004u, 0x0005002cu, + 0x0000002du, 0x0000009bu, 0x0000002eu, 0x00000082u, 0x0005002cu, 0x0000002du, 0x0000009cu, 0x00000082u, + 0x0000002eu, 0x00050033u, 0x00000031u, 0x0000009du, 0x00000021u, 0x00000021u, 0x00070034u, 0x0000002du, + 0x0000009eu, 0x000000a9u, 0x0000009du, 0x0000009bu, 0x0000009cu, 0x00040020u, 0x000000a7u, 0x00000001u, + 0x00000006u, 0x0004003bu, 0x000000a7u, 0x000000a8u, 0x00000001u, 0x0004003bu, 0x00000008u, 0x000000aeu, + 0x00000000u, 0x0004003bu, 0x00000008u, 0x000000afu, 0x00000000u, 0x0004003bu, 0x00000008u, 0x000000b2u, + 0x00000000u, 0x0004003bu, 0x00000008u, 0x000000b3u, 0x00000000u, 0x0004003bu, 0x00000008u, 0x000000b6u, + 0x00000000u, 0x0004003bu, 0x00000008u, 0x000000b7u, 0x00000000u, 0x00040032u, 0x00000017u, 0x000000d1u, + 0x00000000u, 0x00060034u, 0x00000020u, 0x000000d2u, 0x000000b1u, 0x000000d1u, 0x0000002eu, 0x0004002bu, + 0x00000006u, 0x000000d6u, 0x3f800000u, 0x00060034u, 0x00000020u, 0x000000deu, 0x000000adu, 0x000000d1u, + 0x0000002eu, 0x0004002bu, 0x00000006u, 0x000000e2u, 0x40000000u, 0x00040020u, 0x000000e4u, 0x00000009u, + 0x00000017u, 0x0004002bu, 0x00000006u, 0x000000f3u, 0x40800000u, 0x00040017u, 0x00000101u, 0x00000006u, + 0x00000003u, 0x0004002bu, 0x00000006u, 0x0000014cu, 0x3f1a5adeu, 0x0004002bu, 0x00000006u, 0x0000014eu, + 0x3f175d96u, 0x0004002bu, 0x00000006u, 0x00000150u, 0xbda03385u, 0x0004002bu, 0x00000006u, 0x00000152u, + 0xbdbaecb1u, 0x0004002bu, 0x00000006u, 0x00000154u, 0x3cdb2036u, 0x0006002cu, 0x00000101u, 0x0000018au, + 0x00000074u, 0x00000074u, 0x00000074u, 0x0004002bu, 0x00000006u, 0x0000018bu, 0x3f8ebb2cu, 0x0004002bu, + 0x00000006u, 0x0000018cu, 0xbe88a26au, 0x0004002bu, 0x00000006u, 0x0000018du, 0xbd6bb2c3u, 0x0004002bu, + 0x00000006u, 0x0000018eu, 0x3c8a269fu, 0x00040020u, 0x000001a3u, 0x00000003u, 0x00000006u, 0x0004003bu, + 0x000001a3u, 0x000001a4u, 0x00000003u, 0x00040020u, 0x000001a7u, 0x00000003u, 0x00000011u, 0x0004003bu, + 0x000001a7u, 0x000001a8u, 0x00000003u, 0x00030031u, 0x00000020u, 0x000001abu, 0x0004002bu, 0x00000006u, + 0x000001aeu, 0x3f000000u, 0x00030031u, 0x00000020u, 0x000001b1u, 0x0005002cu, 0x00000011u, 0x00000372u, + 0x000001aeu, 0x000001aeu, 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, + 0x00000005u, 0x0004003du, 0x00000006u, 0x000000a9u, 0x000000a8u, 0x0004006eu, 0x00000017u, 0x000000aau, + 0x000000a9u, 0x000500c7u, 0x00000017u, 0x000000abu, 0x000000aau, 0x0000001bu, 0x000500abu, 0x00000020u, + 0x000000acu, 0x000000abu, 0x0000002eu, 0x0004003du, 0x00000011u, 0x000001bfu, 0x00000015u, 0x00050041u, + 0x0000001cu, 0x000001c0u, 0x0000001au, 0x0000001bu, 0x0004003du, 0x00000011u, 0x000001c1u, 0x000001c0u, + 0x00050081u, 0x00000011u, 0x000001c2u, 0x000001bfu, 0x000001c1u, 0x000300f7u, 0x000001f5u, 0x00000000u, + 0x000400fau, 0x00000021u, 0x000001c3u, 0x000001dcu, 0x000200f8u, 0x000001c3u, 0x0004003du, 0x00000007u, + 0x000001c4u, 0x000000aeu, 0x0004003du, 0x00000026u, 0x000001c5u, 0x00000028u, 0x00050056u, 0x0000002au, + 0x000001c6u, 0x000001c4u, 0x000001c5u, 0x00080060u, 0x00000034u, 0x000001c8u, 0x000001c6u, 0x000001c2u, + 0x0000002eu, 0x00000008u, 0x00000033u, 0x0007004fu, 0x00000011u, 0x000001c9u, 0x000001c8u, 0x000001c8u, + 0x00000003u, 0x00000000u, 0x0004003du, 0x00000007u, 0x000001cau, 0x000000aeu, 0x0004003du, 0x00000026u, + 0x000001cbu, 0x00000028u, 0x00050056u, 0x0000002au, 0x000001ccu, 0x000001cau, 0x000001cbu, 0x00080060u, + 0x00000034u, 0x000001ceu, 0x000001ccu, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x00000040u, 0x0007004fu, + 0x00000011u, 0x000001cfu, 0x000001ceu, 0x000001ceu, 0x00000003u, 0x00000000u, 0x0004003du, 0x00000007u, + 0x000001d0u, 0x000000afu, 0x0004003du, 0x00000026u, 0x000001d1u, 0x00000028u, 0x00050056u, 0x0000002au, + 0x000001d2u, 0x000001d0u, 0x000001d1u, 0x00080060u, 0x00000034u, 0x000001d4u, 0x000001d2u, 0x000001c2u, + 0x0000002eu, 0x00000008u, 0x0000004au, 0x0007004fu, 0x00000011u, 0x000001d5u, 0x000001d4u, 0x000001d4u, + 0x00000003u, 0x00000000u, 0x0004003du, 0x00000007u, 0x000001d6u, 0x000000afu, 0x0004003du, 0x00000026u, + 0x000001d7u, 0x00000028u, 0x00050056u, 0x0000002au, 0x000001d8u, 0x000001d6u, 0x000001d7u, 0x00080060u, + 0x00000034u, 0x000001dau, 0x000001d8u, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x00000056u, 0x0007004fu, + 0x00000011u, 0x000001dbu, 0x000001dau, 0x000001dau, 0x00000003u, 0x00000000u, 0x000200f9u, 0x000001f5u, + 0x000200f8u, 0x000001dcu, 0x0004003du, 0x00000007u, 0x000001ddu, 0x000000aeu, 0x0004003du, 0x00000026u, + 0x000001deu, 0x00000028u, 0x00050056u, 0x0000002au, 0x000001dfu, 0x000001ddu, 0x000001deu, 0x00080060u, + 0x00000034u, 0x000001e1u, 0x000001dfu, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x00000033u, 0x0007004fu, + 0x00000011u, 0x000001e2u, 0x000001e1u, 0x000001e1u, 0x00000003u, 0x00000002u, 0x0004003du, 0x00000007u, + 0x000001e3u, 0x000000aeu, 0x0004003du, 0x00000026u, 0x000001e4u, 0x00000028u, 0x00050056u, 0x0000002au, + 0x000001e5u, 0x000001e3u, 0x000001e4u, 0x00080060u, 0x00000034u, 0x000001e7u, 0x000001e5u, 0x000001c2u, + 0x0000002eu, 0x00000008u, 0x00000040u, 0x0007004fu, 0x00000011u, 0x000001e8u, 0x000001e7u, 0x000001e7u, + 0x00000003u, 0x00000002u, 0x0004003du, 0x00000007u, 0x000001e9u, 0x000000afu, 0x0004003du, 0x00000026u, + 0x000001eau, 0x00000028u, 0x00050056u, 0x0000002au, 0x000001ebu, 0x000001e9u, 0x000001eau, 0x00080060u, + 0x00000034u, 0x000001edu, 0x000001ebu, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x0000004au, 0x0007004fu, + 0x00000011u, 0x000001eeu, 0x000001edu, 0x000001edu, 0x00000003u, 0x00000002u, 0x0004003du, 0x00000007u, + 0x000001efu, 0x000000afu, 0x0004003du, 0x00000026u, 0x000001f0u, 0x00000028u, 0x00050056u, 0x0000002au, + 0x000001f1u, 0x000001efu, 0x000001f0u, 0x00080060u, 0x00000034u, 0x000001f3u, 0x000001f1u, 0x000001c2u, + 0x0000002eu, 0x00000008u, 0x00000056u, 0x0007004fu, 0x00000011u, 0x000001f4u, 0x000001f3u, 0x000001f3u, + 0x00000003u, 0x00000002u, 0x000200f9u, 0x000001f5u, 0x000200f8u, 0x000001f5u, 0x000700f5u, 0x00000011u, + 0x00000345u, 0x000001cfu, 0x000001c3u, 0x000001e8u, 0x000001dcu, 0x000700f5u, 0x00000011u, 0x00000344u, + 0x000001dbu, 0x000001c3u, 0x000001f4u, 0x000001dcu, 0x000700f5u, 0x00000011u, 0x00000343u, 0x000001c9u, + 0x000001c3u, 0x000001e2u, 0x000001dcu, 0x000700f5u, 0x00000011u, 0x00000342u, 0x000001d5u, 0x000001c3u, + 0x000001eeu, 0x000001dcu, 0x00050051u, 0x00000006u, 0x000001f8u, 0x00000342u, 0x00000000u, 0x00050051u, + 0x00000006u, 0x000001fbu, 0x00000343u, 0x00000000u, 0x00050051u, 0x00000006u, 0x000001feu, 0x00000342u, + 0x00000001u, 0x00050051u, 0x00000006u, 0x00000201u, 0x00000343u, 0x00000001u, 0x00050051u, 0x00000006u, + 0x00000204u, 0x00000344u, 0x00000000u, 0x00050051u, 0x00000006u, 0x00000207u, 0x00000345u, 0x00000000u, + 0x00050051u, 0x00000006u, 0x0000020au, 0x00000344u, 0x00000001u, 0x00050051u, 0x00000006u, 0x0000020du, + 0x00000345u, 0x00000001u, 0x0004003du, 0x00000007u, 0x0000020fu, 0x000000afu, 0x0004003du, 0x00000026u, + 0x00000210u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000211u, 0x0000020fu, 0x00000210u, 0x00080058u, + 0x00000034u, 0x00000213u, 0x00000211u, 0x000001bfu, 0x0000000au, 0x00000074u, 0x0000009eu, 0x00050051u, + 0x00000006u, 0x00000214u, 0x00000213u, 0x00000000u, 0x000300f7u, 0x00000255u, 0x00000000u, 0x000400fau, + 0x00000021u, 0x00000223u, 0x0000023cu, 0x000200f8u, 0x00000223u, 0x0004003du, 0x00000007u, 0x00000224u, + 0x000000b2u, 0x0004003du, 0x00000026u, 0x00000225u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000226u, + 0x00000224u, 0x00000225u, 0x00080060u, 0x00000034u, 0x00000228u, 0x00000226u, 0x000001c2u, 0x0000002eu, + 0x00000008u, 0x00000033u, 0x0007004fu, 0x00000011u, 0x00000229u, 0x00000228u, 0x00000228u, 0x00000003u, + 0x00000000u, 0x0004003du, 0x00000007u, 0x0000022au, 0x000000b2u, 0x0004003du, 0x00000026u, 0x0000022bu, + 0x00000028u, 0x00050056u, 0x0000002au, 0x0000022cu, 0x0000022au, 0x0000022bu, 0x00080060u, 0x00000034u, + 0x0000022eu, 0x0000022cu, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x00000040u, 0x0007004fu, 0x00000011u, + 0x0000022fu, 0x0000022eu, 0x0000022eu, 0x00000003u, 0x00000000u, 0x0004003du, 0x00000007u, 0x00000230u, + 0x000000b3u, 0x0004003du, 0x00000026u, 0x00000231u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000232u, + 0x00000230u, 0x00000231u, 0x00080060u, 0x00000034u, 0x00000234u, 0x00000232u, 0x000001c2u, 0x0000002eu, + 0x00000008u, 0x0000004au, 0x0007004fu, 0x00000011u, 0x00000235u, 0x00000234u, 0x00000234u, 0x00000003u, + 0x00000000u, 0x0004003du, 0x00000007u, 0x00000236u, 0x000000b3u, 0x0004003du, 0x00000026u, 0x00000237u, + 0x00000028u, 0x00050056u, 0x0000002au, 0x00000238u, 0x00000236u, 0x00000237u, 0x00080060u, 0x00000034u, + 0x0000023au, 0x00000238u, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x00000056u, 0x0007004fu, 0x00000011u, + 0x0000023bu, 0x0000023au, 0x0000023au, 0x00000003u, 0x00000000u, 0x000200f9u, 0x00000255u, 0x000200f8u, + 0x0000023cu, 0x0004003du, 0x00000007u, 0x0000023du, 0x000000b2u, 0x0004003du, 0x00000026u, 0x0000023eu, + 0x00000028u, 0x00050056u, 0x0000002au, 0x0000023fu, 0x0000023du, 0x0000023eu, 0x00080060u, 0x00000034u, + 0x00000241u, 0x0000023fu, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x00000033u, 0x0007004fu, 0x00000011u, + 0x00000242u, 0x00000241u, 0x00000241u, 0x00000003u, 0x00000002u, 0x0004003du, 0x00000007u, 0x00000243u, + 0x000000b2u, 0x0004003du, 0x00000026u, 0x00000244u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000245u, + 0x00000243u, 0x00000244u, 0x00080060u, 0x00000034u, 0x00000247u, 0x00000245u, 0x000001c2u, 0x0000002eu, + 0x00000008u, 0x00000040u, 0x0007004fu, 0x00000011u, 0x00000248u, 0x00000247u, 0x00000247u, 0x00000003u, + 0x00000002u, 0x0004003du, 0x00000007u, 0x00000249u, 0x000000b3u, 0x0004003du, 0x00000026u, 0x0000024au, + 0x00000028u, 0x00050056u, 0x0000002au, 0x0000024bu, 0x00000249u, 0x0000024au, 0x00080060u, 0x00000034u, + 0x0000024du, 0x0000024bu, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x0000004au, 0x0007004fu, 0x00000011u, + 0x0000024eu, 0x0000024du, 0x0000024du, 0x00000003u, 0x00000002u, 0x0004003du, 0x00000007u, 0x0000024fu, + 0x000000b3u, 0x0004003du, 0x00000026u, 0x00000250u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000251u, + 0x0000024fu, 0x00000250u, 0x00080060u, 0x00000034u, 0x00000253u, 0x00000251u, 0x000001c2u, 0x0000002eu, + 0x00000008u, 0x00000056u, 0x0007004fu, 0x00000011u, 0x00000254u, 0x00000253u, 0x00000253u, 0x00000003u, + 0x00000002u, 0x000200f9u, 0x00000255u, 0x000200f8u, 0x00000255u, 0x000700f5u, 0x00000011u, 0x00000349u, + 0x0000022fu, 0x00000223u, 0x00000248u, 0x0000023cu, 0x000700f5u, 0x00000011u, 0x00000348u, 0x0000023bu, + 0x00000223u, 0x00000254u, 0x0000023cu, 0x000700f5u, 0x00000011u, 0x00000347u, 0x00000229u, 0x00000223u, + 0x00000242u, 0x0000023cu, 0x000700f5u, 0x00000011u, 0x00000346u, 0x00000235u, 0x00000223u, 0x0000024eu, + 0x0000023cu, 0x00050051u, 0x00000006u, 0x00000258u, 0x00000346u, 0x00000000u, 0x00050051u, 0x00000006u, + 0x0000025bu, 0x00000347u, 0x00000000u, 0x00050051u, 0x00000006u, 0x0000025eu, 0x00000346u, 0x00000001u, + 0x00050051u, 0x00000006u, 0x00000261u, 0x00000347u, 0x00000001u, 0x00050051u, 0x00000006u, 0x00000264u, + 0x00000348u, 0x00000000u, 0x00050051u, 0x00000006u, 0x00000267u, 0x00000349u, 0x00000000u, 0x00050051u, + 0x00000006u, 0x0000026au, 0x00000348u, 0x00000001u, 0x00050051u, 0x00000006u, 0x0000026du, 0x00000349u, + 0x00000001u, 0x0004003du, 0x00000007u, 0x0000026fu, 0x000000b3u, 0x0004003du, 0x00000026u, 0x00000270u, + 0x00000028u, 0x00050056u, 0x0000002au, 0x00000271u, 0x0000026fu, 0x00000270u, 0x00080058u, 0x00000034u, + 0x00000273u, 0x00000271u, 0x000001bfu, 0x0000000au, 0x00000074u, 0x0000009eu, 0x00050051u, 0x00000006u, + 0x00000274u, 0x00000273u, 0x00000000u, 0x000300f7u, 0x000002b5u, 0x00000000u, 0x000400fau, 0x00000021u, + 0x00000283u, 0x0000029cu, 0x000200f8u, 0x00000283u, 0x0004003du, 0x00000007u, 0x00000284u, 0x000000b6u, + 0x0004003du, 0x00000026u, 0x00000285u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000286u, 0x00000284u, + 0x00000285u, 0x00080060u, 0x00000034u, 0x00000288u, 0x00000286u, 0x000001c2u, 0x0000002eu, 0x00000008u, + 0x00000033u, 0x0007004fu, 0x00000011u, 0x00000289u, 0x00000288u, 0x00000288u, 0x00000003u, 0x00000000u, + 0x0004003du, 0x00000007u, 0x0000028au, 0x000000b6u, 0x0004003du, 0x00000026u, 0x0000028bu, 0x00000028u, + 0x00050056u, 0x0000002au, 0x0000028cu, 0x0000028au, 0x0000028bu, 0x00080060u, 0x00000034u, 0x0000028eu, + 0x0000028cu, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x00000040u, 0x0007004fu, 0x00000011u, 0x0000028fu, + 0x0000028eu, 0x0000028eu, 0x00000003u, 0x00000000u, 0x0004003du, 0x00000007u, 0x00000290u, 0x000000b7u, + 0x0004003du, 0x00000026u, 0x00000291u, 0x00000028u, 0x00050056u, 0x0000002au, 0x00000292u, 0x00000290u, + 0x00000291u, 0x00080060u, 0x00000034u, 0x00000294u, 0x00000292u, 0x000001c2u, 0x0000002eu, 0x00000008u, + 0x0000004au, 0x0007004fu, 0x00000011u, 0x00000295u, 0x00000294u, 0x00000294u, 0x00000003u, 0x00000000u, + 0x0004003du, 0x00000007u, 0x00000296u, 0x000000b7u, 0x0004003du, 0x00000026u, 0x00000297u, 0x00000028u, + 0x00050056u, 0x0000002au, 0x00000298u, 0x00000296u, 0x00000297u, 0x00080060u, 0x00000034u, 0x0000029au, + 0x00000298u, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x00000056u, 0x0007004fu, 0x00000011u, 0x0000029bu, + 0x0000029au, 0x0000029au, 0x00000003u, 0x00000000u, 0x000200f9u, 0x000002b5u, 0x000200f8u, 0x0000029cu, + 0x0004003du, 0x00000007u, 0x0000029du, 0x000000b6u, 0x0004003du, 0x00000026u, 0x0000029eu, 0x00000028u, + 0x00050056u, 0x0000002au, 0x0000029fu, 0x0000029du, 0x0000029eu, 0x00080060u, 0x00000034u, 0x000002a1u, + 0x0000029fu, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x00000033u, 0x0007004fu, 0x00000011u, 0x000002a2u, + 0x000002a1u, 0x000002a1u, 0x00000003u, 0x00000002u, 0x0004003du, 0x00000007u, 0x000002a3u, 0x000000b6u, + 0x0004003du, 0x00000026u, 0x000002a4u, 0x00000028u, 0x00050056u, 0x0000002au, 0x000002a5u, 0x000002a3u, + 0x000002a4u, 0x00080060u, 0x00000034u, 0x000002a7u, 0x000002a5u, 0x000001c2u, 0x0000002eu, 0x00000008u, + 0x00000040u, 0x0007004fu, 0x00000011u, 0x000002a8u, 0x000002a7u, 0x000002a7u, 0x00000003u, 0x00000002u, + 0x0004003du, 0x00000007u, 0x000002a9u, 0x000000b7u, 0x0004003du, 0x00000026u, 0x000002aau, 0x00000028u, + 0x00050056u, 0x0000002au, 0x000002abu, 0x000002a9u, 0x000002aau, 0x00080060u, 0x00000034u, 0x000002adu, + 0x000002abu, 0x000001c2u, 0x0000002eu, 0x00000008u, 0x0000004au, 0x0007004fu, 0x00000011u, 0x000002aeu, + 0x000002adu, 0x000002adu, 0x00000003u, 0x00000002u, 0x0004003du, 0x00000007u, 0x000002afu, 0x000000b7u, + 0x0004003du, 0x00000026u, 0x000002b0u, 0x00000028u, 0x00050056u, 0x0000002au, 0x000002b1u, 0x000002afu, + 0x000002b0u, 0x00080060u, 0x00000034u, 0x000002b3u, 0x000002b1u, 0x000001c2u, 0x0000002eu, 0x00000008u, + 0x00000056u, 0x0007004fu, 0x00000011u, 0x000002b4u, 0x000002b3u, 0x000002b3u, 0x00000003u, 0x00000002u, + 0x000200f9u, 0x000002b5u, 0x000200f8u, 0x000002b5u, 0x000700f5u, 0x00000011u, 0x0000034du, 0x0000028fu, + 0x00000283u, 0x000002a8u, 0x0000029cu, 0x000700f5u, 0x00000011u, 0x0000034cu, 0x0000029bu, 0x00000283u, + 0x000002b4u, 0x0000029cu, 0x000700f5u, 0x00000011u, 0x0000034bu, 0x00000289u, 0x00000283u, 0x000002a2u, + 0x0000029cu, 0x000700f5u, 0x00000011u, 0x0000034au, 0x00000295u, 0x00000283u, 0x000002aeu, 0x0000029cu, + 0x00050051u, 0x00000006u, 0x000002b8u, 0x0000034au, 0x00000000u, 0x00050051u, 0x00000006u, 0x000002bbu, + 0x0000034bu, 0x00000000u, 0x00050051u, 0x00000006u, 0x000002beu, 0x0000034au, 0x00000001u, 0x00050051u, + 0x00000006u, 0x000002c1u, 0x0000034bu, 0x00000001u, 0x00050051u, 0x00000006u, 0x000002c4u, 0x0000034cu, + 0x00000000u, 0x00050051u, 0x00000006u, 0x000002c7u, 0x0000034du, 0x00000000u, 0x00050051u, 0x00000006u, + 0x000002cau, 0x0000034cu, 0x00000001u, 0x00050051u, 0x00000006u, 0x000002cdu, 0x0000034du, 0x00000001u, + 0x0004003du, 0x00000007u, 0x000002cfu, 0x000000b7u, 0x0004003du, 0x00000026u, 0x000002d0u, 0x00000028u, + 0x00050056u, 0x0000002au, 0x000002d1u, 0x000002cfu, 0x000002d0u, 0x00080058u, 0x00000034u, 0x000002d3u, + 0x000002d1u, 0x000001bfu, 0x0000000au, 0x00000074u, 0x0000009eu, 0x00050051u, 0x00000006u, 0x000002d4u, + 0x000002d3u, 0x00000000u, 0x000300f7u, 0x000000d4u, 0x00000000u, 0x000400fau, 0x000000d2u, 0x000000d3u, + 0x000000ddu, 0x000200f8u, 0x000000d3u, 0x000500b8u, 0x00000020u, 0x000000d7u, 0x000000a9u, 0x000000d6u, + 0x000600a9u, 0x00000006u, 0x0000041bu, 0x000000d7u, 0x00000207u, 0x000001fbu, 0x000200f9u, 0x000000d4u, + 0x000200f8u, 0x000000ddu, 0x000300f7u, 0x000000e0u, 0x00000000u, 0x000400fau, 0x000000deu, 0x000000dfu, + 0x000000e0u, 0x000200f8u, 0x000000dfu, 0x00050081u, 0x00000006u, 0x000000e3u, 0x000000a9u, 0x000000e2u, + 0x00050041u, 0x000000e4u, 0x000000e5u, 0x0000001au, 0x0000003cu, 0x0004003du, 0x00000017u, 0x000000e6u, + 0x000000e5u, 0x0004006fu, 0x00000006u, 0x000000e7u, 0x000000e6u, 0x000500bau, 0x00000020u, 0x000000e8u, + 0x000000e3u, 0x000000e7u, 0x000300f7u, 0x000000eau, 0x00000000u, 0x000400fau, 0x000000e8u, 0x000000e9u, + 0x000000f1u, 0x000200f8u, 0x000000e9u, 0x000200f9u, 0x000000eau, 0x000200f8u, 0x000000f1u, 0x00050081u, + 0x00000006u, 0x000000f4u, 0x000000a9u, 0x000000f3u, 0x000500beu, 0x00000020u, 0x000000f8u, 0x000000f4u, + 0x000000e7u, 0x000600a9u, 0x00000006u, 0x0000041cu, 0x000000f8u, 0x00000204u, 0x00000214u, 0x000200f9u, + 0x000000eau, 0x000200f8u, 0x000000eau, 0x000700f5u, 0x00000006u, 0x00000365u, 0x000001f8u, 0x000000e9u, + 0x0000041cu, 0x000000f1u, 0x000600a9u, 0x00000006u, 0x0000041du, 0x000000e8u, 0x000001feu, 0x0000020au, + 0x000200f9u, 0x000000e0u, 0x000200f8u, 0x000000e0u, 0x000700f5u, 0x00000006u, 0x00000364u, 0x00000214u, + 0x000000ddu, 0x00000365u, 0x000000eau, 0x000700f5u, 0x00000006u, 0x0000035cu, 0x0000020au, 0x000000ddu, + 0x0000041du, 0x000000eau, 0x000200f9u, 0x000000d4u, 0x000200f8u, 0x000000d4u, 0x000700f5u, 0x00000006u, + 0x0000035fu, 0x00000214u, 0x000000d3u, 0x00000364u, 0x000000e0u, 0x000700f5u, 0x00000006u, 0x00000357u, + 0x0000020au, 0x000000d3u, 0x0000035cu, 0x000000e0u, 0x000700f5u, 0x00000006u, 0x0000034fu, 0x0000041bu, + 0x000000d3u, 0x000001fbu, 0x000000e0u, 0x000300f7u, 0x00000100u, 0x00000000u, 0x000400fau, 0x000000acu, + 0x000000ffu, 0x00000155u, 0x000200f8u, 0x000000ffu, 0x00060050u, 0x00000101u, 0x0000010au, 0x00000204u, + 0x00000264u, 0x000002c4u, 0x00060050u, 0x00000101u, 0x00000112u, 0x00000201u, 0x00000261u, 0x000002c1u, + 0x00060050u, 0x00000101u, 0x00000119u, 0x00000207u, 0x00000267u, 0x000002c7u, 0x00050081u, 0x00000101u, + 0x0000011au, 0x00000112u, 0x00000119u, 0x00060050u, 0x00000101u, 0x00000122u, 0x000001feu, 0x0000025eu, + 0x000002beu, 0x00060050u, 0x00000101u, 0x00000129u, 0x00000357u, 0x0000026au, 0x000002cau, 0x00050081u, + 0x00000101u, 0x0000012au, 0x00000122u, 0x00000129u, 0x00060050u, 0x00000101u, 0x00000132u, 0x0000034fu, + 0x0000025bu, 0x000002bbu, 0x00060050u, 0x00000101u, 0x00000139u, 0x0000020du, 0x0000026du, 0x000002cdu, + 0x00050081u, 0x00000101u, 0x0000013au, 0x00000132u, 0x00000139u, 0x00060050u, 0x00000101u, 0x00000142u, + 0x000001f8u, 0x00000258u, 0x000002b8u, 0x00060050u, 0x00000101u, 0x00000149u, 0x0000035fu, 0x00000274u, + 0x000002d4u, 0x00050081u, 0x00000101u, 0x0000014au, 0x00000142u, 0x00000149u, 0x000200f9u, 0x00000100u, + 0x000200f8u, 0x00000155u, 0x00060050u, 0x00000101u, 0x0000015cu, 0x00000201u, 0x00000261u, 0x000002c1u, + 0x00060050u, 0x00000101u, 0x00000163u, 0x000001feu, 0x0000025eu, 0x000002beu, 0x00060050u, 0x00000101u, + 0x0000016au, 0x00000204u, 0x00000264u, 0x000002c4u, 0x00050081u, 0x00000101u, 0x0000016bu, 0x00000163u, + 0x0000016au, 0x00060050u, 0x00000101u, 0x00000172u, 0x0000034fu, 0x0000025bu, 0x000002bbu, 0x00060050u, + 0x00000101u, 0x00000179u, 0x00000207u, 0x00000267u, 0x000002c7u, 0x00050081u, 0x00000101u, 0x0000017au, + 0x00000172u, 0x00000179u, 0x00060050u, 0x00000101u, 0x00000181u, 0x000001f8u, 0x00000258u, 0x000002b8u, + 0x00060050u, 0x00000101u, 0x00000188u, 0x00000357u, 0x0000026au, 0x000002cau, 0x00050081u, 0x00000101u, + 0x00000189u, 0x00000181u, 0x00000188u, 0x000200f9u, 0x00000100u, 0x000200f8u, 0x00000100u, 0x000700f5u, + 0x00000101u, 0x0000036fu, 0x0000014au, 0x000000ffu, 0x0000018au, 0x00000155u, 0x000700f5u, 0x00000101u, + 0x0000036du, 0x0000013au, 0x000000ffu, 0x00000189u, 0x00000155u, 0x000700f5u, 0x00000101u, 0x0000036bu, + 0x0000012au, 0x000000ffu, 0x0000017au, 0x00000155u, 0x000700f5u, 0x00000101u, 0x00000369u, 0x0000011au, + 0x000000ffu, 0x0000016bu, 0x00000155u, 0x000700f5u, 0x00000101u, 0x00000367u, 0x0000010au, 0x000000ffu, + 0x0000015cu, 0x00000155u, 0x000600a9u, 0x00000006u, 0x0000041eu, 0x000000acu, 0x00000154u, 0x00000074u, + 0x000600a9u, 0x00000006u, 0x0000041fu, 0x000000acu, 0x00000152u, 0x0000018eu, 0x000600a9u, 0x00000006u, + 0x00000420u, 0x000000acu, 0x00000150u, 0x0000018du, 0x000600a9u, 0x00000006u, 0x00000421u, 0x000000acu, + 0x0000014eu, 0x0000018cu, 0x000600a9u, 0x00000006u, 0x00000422u, 0x000000acu, 0x0000014cu, 0x0000018bu, + 0x0005008eu, 0x00000101u, 0x00000192u, 0x00000367u, 0x00000422u, 0x0005008eu, 0x00000101u, 0x00000195u, + 0x00000369u, 0x00000421u, 0x00050081u, 0x00000101u, 0x00000196u, 0x00000192u, 0x00000195u, 0x0005008eu, + 0x00000101u, 0x00000199u, 0x0000036bu, 0x00000420u, 0x00050081u, 0x00000101u, 0x0000019au, 0x00000196u, + 0x00000199u, 0x0005008eu, 0x00000101u, 0x0000019du, 0x0000036du, 0x0000041fu, 0x00050081u, 0x00000101u, + 0x0000019eu, 0x0000019au, 0x0000019du, 0x0005008eu, 0x00000101u, 0x000001a1u, 0x0000036fu, 0x0000041eu, + 0x00050081u, 0x00000101u, 0x000001a2u, 0x0000019eu, 0x000001a1u, 0x00050051u, 0x00000006u, 0x000001a6u, + 0x000001a2u, 0x00000000u, 0x0003003eu, 0x000001a4u, 0x000001a6u, 0x0007004fu, 0x00000011u, 0x000001aau, + 0x000001a2u, 0x000001a2u, 0x00000001u, 0x00000002u, 0x0003003eu, 0x000001a8u, 0x000001aau, 0x000300f7u, + 0x000001adu, 0x00000000u, 0x000400fau, 0x000001abu, 0x000001acu, 0x000001adu, 0x000200f8u, 0x000001acu, + 0x0004003du, 0x00000006u, 0x000001afu, 0x000001a4u, 0x00050081u, 0x00000006u, 0x000001b0u, 0x000001afu, + 0x000001aeu, 0x0003003eu, 0x000001a4u, 0x000001b0u, 0x000200f9u, 0x000001adu, 0x000200f8u, 0x000001adu, + 0x000300f7u, 0x000001b3u, 0x00000000u, 0x000400fau, 0x000001b1u, 0x000001b2u, 0x000001b3u, 0x000200f8u, + 0x000001b2u, 0x0004003du, 0x00000011u, 0x000001b4u, 0x000001a8u, 0x00050081u, 0x00000011u, 0x000001b6u, + 0x000001b4u, 0x00000372u, 0x0003003eu, 0x000001a8u, 0x000001b6u, 0x000200f9u, 0x000001b3u, 0x000200f8u, + 0x000001b3u, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, 0x0000030fu, 0x00000000u, + 0x00020011u, 0x00000001u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, + 0x0003000eu, 0x00000000u, 0x00000001u, 0x000a000fu, 0x00000004u, 0x00000004u, 0x6e69616du, 0x00000000u, + 0x0000001bu, 0x000000f4u, 0x000001d4u, 0x000001d7u, 0x000001dau, 0x00030010u, 0x00000004u, 0x00000007u, + 0x00040047u, 0x0000001bu, 0x0000001eu, 0x00000000u, 0x00030047u, 0x0000001eu, 0x00000002u, 0x00050048u, + 0x0000001eu, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x0000001eu, 0x00000001u, 0x00000023u, + 0x00000008u, 0x00050048u, 0x0000001eu, 0x00000002u, 0x00000023u, 0x00000010u, 0x00050048u, 0x0000001eu, + 0x00000003u, 0x00000023u, 0x00000014u, 0x00040047u, 0x00000027u, 0x00000001u, 0x00000000u, 0x00030047u, + 0x0000002eu, 0x00000000u, 0x00040047u, 0x0000002eu, 0x00000021u, 0x00000002u, 0x00040047u, 0x0000002eu, + 0x00000022u, 0x00000000u, 0x00040047u, 0x000000f4u, 0x0000001eu, 0x00000000u, 0x00040047u, 0x000000f4u, + 0x0000001fu, 0x00000002u, 0x00030047u, 0x000000fau, 0x00000000u, 0x00040047u, 0x000000fau, 0x00000021u, + 0x00000000u, 0x00040047u, 0x000000fau, 0x00000022u, 0x00000000u, 0x00030047u, 0x000000fbu, 0x00000000u, + 0x00040047u, 0x000000fbu, 0x00000021u, 0x00000001u, 0x00040047u, 0x000000fbu, 0x00000022u, 0x00000000u, + 0x00030047u, 0x000000feu, 0x00000000u, 0x00040047u, 0x000000feu, 0x00000021u, 0x00000003u, 0x00040047u, + 0x000000feu, 0x00000022u, 0x00000000u, 0x00030047u, 0x000000ffu, 0x00000000u, 0x00040047u, 0x000000ffu, + 0x00000021u, 0x00000004u, 0x00040047u, 0x000000ffu, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000101u, + 0x00000001u, 0x00000003u, 0x00030047u, 0x000001d4u, 0x00000000u, 0x00040047u, 0x000001d4u, 0x0000001eu, + 0x00000000u, 0x00030047u, 0x000001d7u, 0x00000000u, 0x00040047u, 0x000001d7u, 0x0000001eu, 0x00000001u, + 0x00030047u, 0x000001dau, 0x00000000u, 0x00040047u, 0x000001dau, 0x0000001eu, 0x00000002u, 0x00040047u, + 0x000001deu, 0x00000001u, 0x00000001u, 0x00030047u, 0x000001e2u, 0x00000000u, 0x00030047u, 0x000001e3u, + 0x00000000u, 0x00040047u, 0x000001e4u, 0x00000001u, 0x00000002u, 0x00030047u, 0x000001e7u, 0x00000000u, + 0x00030047u, 0x000001e8u, 0x00000000u, 0x00030047u, 0x000001e9u, 0x00000000u, 0x00030047u, 0x000001eau, + 0x00000000u, 0x00030047u, 0x000001f8u, 0x00000000u, 0x00030047u, 0x000001f9u, 0x00000000u, 0x00030047u, + 0x000001feu, 0x00000000u, 0x00030047u, 0x000001ffu, 0x00000000u, 0x00030047u, 0x00000204u, 0x00000000u, + 0x00030047u, 0x00000205u, 0x00000000u, 0x00030047u, 0x0000020au, 0x00000000u, 0x00030047u, 0x0000020bu, + 0x00000000u, 0x00030047u, 0x00000211u, 0x00000000u, 0x00030047u, 0x00000212u, 0x00000000u, 0x00030047u, + 0x00000217u, 0x00000000u, 0x00030047u, 0x00000218u, 0x00000000u, 0x00030047u, 0x0000021du, 0x00000000u, + 0x00030047u, 0x0000021eu, 0x00000000u, 0x00030047u, 0x00000223u, 0x00000000u, 0x00030047u, 0x00000224u, + 0x00000000u, 0x00030047u, 0x00000243u, 0x00000000u, 0x00030047u, 0x00000244u, 0x00000000u, 0x00030047u, + 0x0000024fu, 0x00000000u, 0x00030047u, 0x00000250u, 0x00000000u, 0x00030047u, 0x00000256u, 0x00000000u, + 0x00030047u, 0x00000257u, 0x00000000u, 0x00030047u, 0x0000025du, 0x00000000u, 0x00030047u, 0x0000025eu, + 0x00000000u, 0x00030047u, 0x00000264u, 0x00000000u, 0x00030047u, 0x00000265u, 0x00000000u, 0x00030047u, + 0x0000026bu, 0x00000000u, 0x00030047u, 0x0000026cu, 0x00000000u, 0x00030047u, 0x00000272u, 0x00000000u, + 0x00030047u, 0x00000273u, 0x00000000u, 0x00030047u, 0x00000279u, 0x00000000u, 0x00030047u, 0x0000027au, + 0x00000000u, 0x00030047u, 0x00000280u, 0x00000000u, 0x00030047u, 0x00000281u, 0x00000000u, 0x00030047u, + 0x00000287u, 0x00000000u, 0x00030047u, 0x00000288u, 0x00000000u, 0x00020013u, 0x00000002u, 0x00030021u, + 0x00000003u, 0x00000002u, 0x00030016u, 0x00000006u, 0x00000020u, 0x00090019u, 0x00000007u, 0x00000006u, + 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00040020u, 0x00000008u, + 0x00000000u, 0x00000007u, 0x00040017u, 0x00000011u, 0x00000006u, 0x00000002u, 0x00040020u, 0x0000001au, + 0x00000001u, 0x00000011u, 0x0004003bu, 0x0000001au, 0x0000001bu, 0x00000001u, 0x00040015u, 0x0000001du, + 0x00000020u, 0x00000001u, 0x0006001eu, 0x0000001eu, 0x00000011u, 0x00000011u, 0x00000006u, 0x0000001du, + 0x00040020u, 0x0000001fu, 0x00000009u, 0x0000001eu, 0x0004003bu, 0x0000001fu, 0x00000020u, 0x00000009u, + 0x0004002bu, 0x0000001du, 0x00000021u, 0x00000001u, 0x00040020u, 0x00000022u, 0x00000009u, 0x00000011u, + 0x00020014u, 0x00000026u, 0x00030031u, 0x00000026u, 0x00000027u, 0x0002001au, 0x0000002cu, 0x00040020u, + 0x0000002du, 0x00000000u, 0x0000002cu, 0x0004003bu, 0x0000002du, 0x0000002eu, 0x00000000u, 0x0003001bu, + 0x00000030u, 0x00000007u, 0x00040017u, 0x00000033u, 0x0000001du, 0x00000002u, 0x0004002bu, 0x0000001du, + 0x00000034u, 0x00000000u, 0x0005002cu, 0x00000033u, 0x00000035u, 0x00000034u, 0x00000021u, 0x0005002cu, + 0x00000033u, 0x00000036u, 0x00000021u, 0x00000034u, 0x00040017u, 0x00000037u, 0x00000026u, 0x00000002u, + 0x00050033u, 0x00000037u, 0x00000038u, 0x00000027u, 0x00000027u, 0x00070034u, 0x00000033u, 0x00000039u, + 0x000000a9u, 0x00000038u, 0x00000035u, 0x00000036u, 0x00040017u, 0x0000003au, 0x00000006u, 0x00000004u, + 0x0004002bu, 0x0000001du, 0x00000042u, 0x00000003u, 0x0005002cu, 0x00000033u, 0x00000043u, 0x00000034u, + 0x00000042u, 0x0005002cu, 0x00000033u, 0x00000044u, 0x00000042u, 0x00000034u, 0x00050033u, 0x00000037u, + 0x00000045u, 0x00000027u, 0x00000027u, 0x00070034u, 0x00000033u, 0x00000046u, 0x000000a9u, 0x00000045u, + 0x00000043u, 0x00000044u, 0x0005002cu, 0x00000033u, 0x0000004eu, 0x00000034u, 0x00000034u, 0x00050033u, + 0x00000037u, 0x0000004fu, 0x00000027u, 0x00000027u, 0x00070034u, 0x00000033u, 0x00000050u, 0x000000a9u, + 0x0000004fu, 0x0000004eu, 0x0000004eu, 0x0004002bu, 0x0000001du, 0x00000058u, 0x00000002u, 0x0005002cu, + 0x00000033u, 0x00000059u, 0x00000034u, 0x00000058u, 0x0005002cu, 0x00000033u, 0x0000005au, 0x00000058u, + 0x00000034u, 0x00050033u, 0x00000037u, 0x0000005bu, 0x00000027u, 0x00000027u, 0x00070034u, 0x00000033u, + 0x0000005cu, 0x000000a9u, 0x0000005bu, 0x00000059u, 0x0000005au, 0x0004002bu, 0x00000006u, 0x0000007au, + 0x00000000u, 0x0004002bu, 0x0000001du, 0x00000088u, 0x00000004u, 0x0005002cu, 0x00000033u, 0x000000a1u, + 0x00000034u, 0x00000088u, 0x0005002cu, 0x00000033u, 0x000000a2u, 0x00000088u, 0x00000034u, 0x00050033u, + 0x00000037u, 0x000000a3u, 0x00000027u, 0x00000027u, 0x00070034u, 0x00000033u, 0x000000a4u, 0x000000a9u, + 0x000000a3u, 0x000000a1u, 0x000000a2u, 0x00040020u, 0x000000f3u, 0x00000001u, 0x00000006u, 0x0004003bu, + 0x000000f3u, 0x000000f4u, 0x00000001u, 0x0004003bu, 0x00000008u, 0x000000fau, 0x00000000u, 0x0004003bu, + 0x00000008u, 0x000000fbu, 0x00000000u, 0x0004003bu, 0x00000008u, 0x000000feu, 0x00000000u, 0x0004003bu, + 0x00000008u, 0x000000ffu, 0x00000000u, 0x00040032u, 0x0000001du, 0x00000101u, 0x00000000u, 0x00060034u, + 0x00000026u, 0x00000102u, 0x000000b1u, 0x00000101u, 0x00000034u, 0x0004002bu, 0x00000006u, 0x00000106u, + 0x3f800000u, 0x00060034u, 0x00000026u, 0x0000010eu, 0x000000adu, 0x00000101u, 0x00000034u, 0x0004002bu, + 0x00000006u, 0x00000112u, 0x40000000u, 0x00040020u, 0x00000114u, 0x00000009u, 0x0000001du, 0x0004002bu, + 0x00000006u, 0x00000123u, 0x40800000u, 0x00040017u, 0x00000131u, 0x00000006u, 0x00000003u, 0x0004002bu, + 0x00000006u, 0x0000017cu, 0x3f1a5adeu, 0x0004002bu, 0x00000006u, 0x0000017eu, 0x3f175d96u, 0x0004002bu, + 0x00000006u, 0x00000180u, 0xbda03385u, 0x0004002bu, 0x00000006u, 0x00000182u, 0xbdbaecb1u, 0x0004002bu, + 0x00000006u, 0x00000184u, 0x3cdb2036u, 0x0006002cu, 0x00000131u, 0x000001bau, 0x0000007au, 0x0000007au, + 0x0000007au, 0x0004002bu, 0x00000006u, 0x000001bbu, 0x3f8ebb2cu, 0x0004002bu, 0x00000006u, 0x000001bcu, + 0xbe88a26au, 0x0004002bu, 0x00000006u, 0x000001bdu, 0xbd6bb2c3u, 0x0004002bu, 0x00000006u, 0x000001beu, + 0x3c8a269fu, 0x00040020u, 0x000001d3u, 0x00000003u, 0x00000006u, 0x0004003bu, 0x000001d3u, 0x000001d4u, + 0x00000003u, 0x0004003bu, 0x000001d3u, 0x000001d7u, 0x00000003u, 0x0004003bu, 0x000001d3u, 0x000001dau, + 0x00000003u, 0x00030031u, 0x00000026u, 0x000001deu, 0x0004002bu, 0x00000006u, 0x000001e1u, 0x3f000000u, + 0x00030031u, 0x00000026u, 0x000001e4u, 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, + 0x000200f8u, 0x00000005u, 0x0004003du, 0x00000006u, 0x000000f5u, 0x000000f4u, 0x0004006eu, 0x0000001du, + 0x000000f6u, 0x000000f5u, 0x000500c7u, 0x0000001du, 0x000000f7u, 0x000000f6u, 0x00000021u, 0x000500abu, + 0x00000026u, 0x000000f8u, 0x000000f7u, 0x00000034u, 0x0004003du, 0x00000011u, 0x000001f3u, 0x0000001bu, + 0x00050041u, 0x00000022u, 0x000001f4u, 0x00000020u, 0x00000021u, 0x0004003du, 0x00000011u, 0x000001f5u, + 0x000001f4u, 0x00050081u, 0x00000011u, 0x000001f6u, 0x000001f3u, 0x000001f5u, 0x000300f7u, 0x00000229u, + 0x00000000u, 0x000400fau, 0x00000027u, 0x000001f7u, 0x00000210u, 0x000200f8u, 0x000001f7u, 0x0004003du, + 0x00000007u, 0x000001f8u, 0x000000fau, 0x0004003du, 0x0000002cu, 0x000001f9u, 0x0000002eu, 0x00050056u, + 0x00000030u, 0x000001fau, 0x000001f8u, 0x000001f9u, 0x00080060u, 0x0000003au, 0x000001fcu, 0x000001fau, + 0x000001f6u, 0x00000034u, 0x00000008u, 0x00000039u, 0x0007004fu, 0x00000011u, 0x000001fdu, 0x000001fcu, + 0x000001fcu, 0x00000003u, 0x00000000u, 0x0004003du, 0x00000007u, 0x000001feu, 0x000000fau, 0x0004003du, + 0x0000002cu, 0x000001ffu, 0x0000002eu, 0x00050056u, 0x00000030u, 0x00000200u, 0x000001feu, 0x000001ffu, + 0x00080060u, 0x0000003au, 0x00000202u, 0x00000200u, 0x000001f6u, 0x00000034u, 0x00000008u, 0x00000046u, + 0x0007004fu, 0x00000011u, 0x00000203u, 0x00000202u, 0x00000202u, 0x00000003u, 0x00000000u, 0x0004003du, + 0x00000007u, 0x00000204u, 0x000000fbu, 0x0004003du, 0x0000002cu, 0x00000205u, 0x0000002eu, 0x00050056u, + 0x00000030u, 0x00000206u, 0x00000204u, 0x00000205u, 0x00080060u, 0x0000003au, 0x00000208u, 0x00000206u, + 0x000001f6u, 0x00000034u, 0x00000008u, 0x00000050u, 0x0007004fu, 0x00000011u, 0x00000209u, 0x00000208u, + 0x00000208u, 0x00000003u, 0x00000000u, 0x0004003du, 0x00000007u, 0x0000020au, 0x000000fbu, 0x0004003du, + 0x0000002cu, 0x0000020bu, 0x0000002eu, 0x00050056u, 0x00000030u, 0x0000020cu, 0x0000020au, 0x0000020bu, + 0x00080060u, 0x0000003au, 0x0000020eu, 0x0000020cu, 0x000001f6u, 0x00000034u, 0x00000008u, 0x0000005cu, + 0x0007004fu, 0x00000011u, 0x0000020fu, 0x0000020eu, 0x0000020eu, 0x00000003u, 0x00000000u, 0x000200f9u, + 0x00000229u, 0x000200f8u, 0x00000210u, 0x0004003du, 0x00000007u, 0x00000211u, 0x000000fau, 0x0004003du, + 0x0000002cu, 0x00000212u, 0x0000002eu, 0x00050056u, 0x00000030u, 0x00000213u, 0x00000211u, 0x00000212u, + 0x00080060u, 0x0000003au, 0x00000215u, 0x00000213u, 0x000001f6u, 0x00000034u, 0x00000008u, 0x00000039u, + 0x0007004fu, 0x00000011u, 0x00000216u, 0x00000215u, 0x00000215u, 0x00000003u, 0x00000002u, 0x0004003du, + 0x00000007u, 0x00000217u, 0x000000fau, 0x0004003du, 0x0000002cu, 0x00000218u, 0x0000002eu, 0x00050056u, + 0x00000030u, 0x00000219u, 0x00000217u, 0x00000218u, 0x00080060u, 0x0000003au, 0x0000021bu, 0x00000219u, + 0x000001f6u, 0x00000034u, 0x00000008u, 0x00000046u, 0x0007004fu, 0x00000011u, 0x0000021cu, 0x0000021bu, + 0x0000021bu, 0x00000003u, 0x00000002u, 0x0004003du, 0x00000007u, 0x0000021du, 0x000000fbu, 0x0004003du, + 0x0000002cu, 0x0000021eu, 0x0000002eu, 0x00050056u, 0x00000030u, 0x0000021fu, 0x0000021du, 0x0000021eu, + 0x00080060u, 0x0000003au, 0x00000221u, 0x0000021fu, 0x000001f6u, 0x00000034u, 0x00000008u, 0x00000050u, + 0x0007004fu, 0x00000011u, 0x00000222u, 0x00000221u, 0x00000221u, 0x00000003u, 0x00000002u, 0x0004003du, + 0x00000007u, 0x00000223u, 0x000000fbu, 0x0004003du, 0x0000002cu, 0x00000224u, 0x0000002eu, 0x00050056u, + 0x00000030u, 0x00000225u, 0x00000223u, 0x00000224u, 0x00080060u, 0x0000003au, 0x00000227u, 0x00000225u, + 0x000001f6u, 0x00000034u, 0x00000008u, 0x0000005cu, 0x0007004fu, 0x00000011u, 0x00000228u, 0x00000227u, + 0x00000227u, 0x00000003u, 0x00000002u, 0x000200f9u, 0x00000229u, 0x000200f8u, 0x00000229u, 0x000700f5u, + 0x00000011u, 0x000002edu, 0x00000203u, 0x000001f7u, 0x0000021cu, 0x00000210u, 0x000700f5u, 0x00000011u, + 0x000002ecu, 0x0000020fu, 0x000001f7u, 0x00000228u, 0x00000210u, 0x000700f5u, 0x00000011u, 0x000002ebu, + 0x000001fdu, 0x000001f7u, 0x00000216u, 0x00000210u, 0x000700f5u, 0x00000011u, 0x000002eau, 0x00000209u, + 0x000001f7u, 0x00000222u, 0x00000210u, 0x00050051u, 0x00000006u, 0x0000022cu, 0x000002eau, 0x00000000u, + 0x00050051u, 0x00000006u, 0x0000022fu, 0x000002ebu, 0x00000000u, 0x00050051u, 0x00000006u, 0x00000232u, + 0x000002eau, 0x00000001u, 0x00050051u, 0x00000006u, 0x00000235u, 0x000002ebu, 0x00000001u, 0x00050051u, + 0x00000006u, 0x00000238u, 0x000002ecu, 0x00000000u, 0x00050051u, 0x00000006u, 0x0000023bu, 0x000002edu, + 0x00000000u, 0x00050051u, 0x00000006u, 0x0000023eu, 0x000002ecu, 0x00000001u, 0x00050051u, 0x00000006u, + 0x00000241u, 0x000002edu, 0x00000001u, 0x0004003du, 0x00000007u, 0x00000243u, 0x000000fbu, 0x0004003du, + 0x0000002cu, 0x00000244u, 0x0000002eu, 0x00050056u, 0x00000030u, 0x00000245u, 0x00000243u, 0x00000244u, + 0x00080058u, 0x0000003au, 0x00000247u, 0x00000245u, 0x000001f3u, 0x0000000au, 0x0000007au, 0x000000a4u, + 0x00050051u, 0x00000006u, 0x00000248u, 0x00000247u, 0x00000000u, 0x0004003du, 0x00000007u, 0x0000024fu, + 0x000000ffu, 0x0004003du, 0x0000002cu, 0x00000250u, 0x0000002eu, 0x00050056u, 0x00000030u, 0x00000251u, + 0x0000024fu, 0x00000250u, 0x00080058u, 0x0000003au, 0x00000253u, 0x00000251u, 0x000001f3u, 0x0000000au, + 0x0000007au, 0x00000050u, 0x0004003du, 0x00000007u, 0x00000256u, 0x000000feu, 0x0004003du, 0x0000002cu, + 0x00000257u, 0x0000002eu, 0x00050056u, 0x00000030u, 0x00000258u, 0x00000256u, 0x00000257u, 0x00080058u, + 0x0000003au, 0x0000025au, 0x00000258u, 0x000001f3u, 0x0000000au, 0x0000007au, 0x00000039u, 0x0004003du, + 0x00000007u, 0x0000025du, 0x000000ffu, 0x0004003du, 0x0000002cu, 0x0000025eu, 0x0000002eu, 0x00050056u, + 0x00000030u, 0x0000025fu, 0x0000025du, 0x0000025eu, 0x00080058u, 0x0000003au, 0x00000261u, 0x0000025fu, + 0x000001f3u, 0x0000000au, 0x0000007au, 0x00000039u, 0x0004003du, 0x00000007u, 0x00000264u, 0x000000feu, + 0x0004003du, 0x0000002cu, 0x00000265u, 0x0000002eu, 0x00050056u, 0x00000030u, 0x00000266u, 0x00000264u, + 0x00000265u, 0x00080058u, 0x0000003au, 0x00000268u, 0x00000266u, 0x000001f3u, 0x0000000au, 0x0000007au, + 0x0000005cu, 0x0004003du, 0x00000007u, 0x0000026bu, 0x000000ffu, 0x0004003du, 0x0000002cu, 0x0000026cu, + 0x0000002eu, 0x00050056u, 0x00000030u, 0x0000026du, 0x0000026bu, 0x0000026cu, 0x00080058u, 0x0000003au, + 0x0000026fu, 0x0000026du, 0x000001f3u, 0x0000000au, 0x0000007au, 0x0000005cu, 0x0004003du, 0x00000007u, + 0x00000272u, 0x000000feu, 0x0004003du, 0x0000002cu, 0x00000273u, 0x0000002eu, 0x00050056u, 0x00000030u, + 0x00000274u, 0x00000272u, 0x00000273u, 0x00080058u, 0x0000003au, 0x00000276u, 0x00000274u, 0x000001f3u, + 0x0000000au, 0x0000007au, 0x00000046u, 0x0004003du, 0x00000007u, 0x00000279u, 0x000000ffu, 0x0004003du, + 0x0000002cu, 0x0000027au, 0x0000002eu, 0x00050056u, 0x00000030u, 0x0000027bu, 0x00000279u, 0x0000027au, + 0x00080058u, 0x0000003au, 0x0000027du, 0x0000027bu, 0x000001f3u, 0x0000000au, 0x0000007au, 0x00000046u, + 0x0004003du, 0x00000007u, 0x00000280u, 0x000000feu, 0x0004003du, 0x0000002cu, 0x00000281u, 0x0000002eu, + 0x00050056u, 0x00000030u, 0x00000282u, 0x00000280u, 0x00000281u, 0x00080058u, 0x0000003au, 0x00000284u, + 0x00000282u, 0x000001f3u, 0x0000000au, 0x0000007au, 0x000000a4u, 0x0004003du, 0x00000007u, 0x00000287u, + 0x000000ffu, 0x0004003du, 0x0000002cu, 0x00000288u, 0x0000002eu, 0x00050056u, 0x00000030u, 0x00000289u, + 0x00000287u, 0x00000288u, 0x00080058u, 0x0000003au, 0x0000028bu, 0x00000289u, 0x000001f3u, 0x0000000au, + 0x0000007au, 0x000000a4u, 0x000300f7u, 0x00000104u, 0x00000000u, 0x000400fau, 0x00000102u, 0x00000103u, + 0x0000010du, 0x000200f8u, 0x00000103u, 0x000500b8u, 0x00000026u, 0x00000107u, 0x000000f5u, 0x00000106u, + 0x000600a9u, 0x00000006u, 0x00000307u, 0x00000107u, 0x0000023bu, 0x0000022fu, 0x000200f9u, 0x00000104u, + 0x000200f8u, 0x0000010du, 0x000300f7u, 0x00000110u, 0x00000000u, 0x000400fau, 0x0000010eu, 0x0000010fu, + 0x00000110u, 0x000200f8u, 0x0000010fu, 0x00050081u, 0x00000006u, 0x00000113u, 0x000000f5u, 0x00000112u, + 0x00050041u, 0x00000114u, 0x00000115u, 0x00000020u, 0x00000042u, 0x0004003du, 0x0000001du, 0x00000116u, + 0x00000115u, 0x0004006fu, 0x00000006u, 0x00000117u, 0x00000116u, 0x000500bau, 0x00000026u, 0x00000118u, + 0x00000113u, 0x00000117u, 0x000300f7u, 0x0000011au, 0x00000000u, 0x000400fau, 0x00000118u, 0x00000119u, + 0x00000121u, 0x000200f8u, 0x00000119u, 0x000200f9u, 0x0000011au, 0x000200f8u, 0x00000121u, 0x00050081u, + 0x00000006u, 0x00000124u, 0x000000f5u, 0x00000123u, 0x000500beu, 0x00000026u, 0x00000128u, 0x00000124u, + 0x00000117u, 0x000600a9u, 0x00000006u, 0x00000308u, 0x00000128u, 0x00000238u, 0x00000248u, 0x000200f9u, + 0x0000011au, 0x000200f8u, 0x0000011au, 0x000700f5u, 0x00000006u, 0x000002fbu, 0x0000022cu, 0x00000119u, + 0x00000308u, 0x00000121u, 0x000600a9u, 0x00000006u, 0x00000309u, 0x00000118u, 0x00000232u, 0x0000023eu, + 0x000200f9u, 0x00000110u, 0x000200f8u, 0x00000110u, 0x000700f5u, 0x00000006u, 0x000002fau, 0x00000248u, + 0x0000010du, 0x000002fbu, 0x0000011au, 0x000700f5u, 0x00000006u, 0x000002f5u, 0x0000023eu, 0x0000010du, + 0x00000309u, 0x0000011au, 0x000200f9u, 0x00000104u, 0x000200f8u, 0x00000104u, 0x000700f5u, 0x00000006u, + 0x000002f8u, 0x00000248u, 0x00000103u, 0x000002fau, 0x00000110u, 0x000700f5u, 0x00000006u, 0x000002f3u, + 0x0000023eu, 0x00000103u, 0x000002f5u, 0x00000110u, 0x000700f5u, 0x00000006u, 0x000002eeu, 0x00000307u, + 0x00000103u, 0x0000022fu, 0x00000110u, 0x000300f7u, 0x00000130u, 0x00000000u, 0x000400fau, 0x000000f8u, + 0x0000012fu, 0x00000185u, 0x000200f8u, 0x0000012fu, 0x00050051u, 0x00000006u, 0x00000138u, 0x0000026fu, + 0x00000000u, 0x00050051u, 0x00000006u, 0x00000139u, 0x0000026fu, 0x00000001u, 0x00060050u, 0x00000131u, + 0x0000013au, 0x00000238u, 0x00000138u, 0x00000139u, 0x00050051u, 0x00000006u, 0x00000140u, 0x00000268u, + 0x00000000u, 0x00050051u, 0x00000006u, 0x00000141u, 0x00000268u, 0x00000001u, 0x00060050u, 0x00000131u, + 0x00000142u, 0x00000235u, 0x00000140u, 0x00000141u, 0x00050051u, 0x00000006u, 0x00000147u, 0x00000276u, + 0x00000000u, 0x00050051u, 0x00000006u, 0x00000148u, 0x00000276u, 0x00000001u, 0x00060050u, 0x00000131u, + 0x00000149u, 0x0000023bu, 0x00000147u, 0x00000148u, 0x00050081u, 0x00000131u, 0x0000014au, 0x00000142u, + 0x00000149u, 0x00050051u, 0x00000006u, 0x00000150u, 0x00000261u, 0x00000000u, 0x00050051u, 0x00000006u, + 0x00000151u, 0x00000261u, 0x00000001u, 0x00060050u, 0x00000131u, 0x00000152u, 0x00000232u, 0x00000150u, + 0x00000151u, 0x00050051u, 0x00000006u, 0x00000157u, 0x0000027du, 0x00000000u, 0x00050051u, 0x00000006u, + 0x00000158u, 0x0000027du, 0x00000001u, 0x00060050u, 0x00000131u, 0x00000159u, 0x000002f3u, 0x00000157u, + 0x00000158u, 0x00050081u, 0x00000131u, 0x0000015au, 0x00000152u, 0x00000159u, 0x00050051u, 0x00000006u, + 0x00000160u, 0x0000025au, 0x00000000u, 0x00050051u, 0x00000006u, 0x00000161u, 0x0000025au, 0x00000001u, + 0x00060050u, 0x00000131u, 0x00000162u, 0x000002eeu, 0x00000160u, 0x00000161u, 0x00050051u, 0x00000006u, + 0x00000167u, 0x00000284u, 0x00000000u, 0x00050051u, 0x00000006u, 0x00000168u, 0x00000284u, 0x00000001u, + 0x00060050u, 0x00000131u, 0x00000169u, 0x00000241u, 0x00000167u, 0x00000168u, 0x00050081u, 0x00000131u, + 0x0000016au, 0x00000162u, 0x00000169u, 0x00050051u, 0x00000006u, 0x00000170u, 0x00000253u, 0x00000000u, + 0x00050051u, 0x00000006u, 0x00000171u, 0x00000253u, 0x00000001u, 0x00060050u, 0x00000131u, 0x00000172u, + 0x0000022cu, 0x00000170u, 0x00000171u, 0x00050051u, 0x00000006u, 0x00000177u, 0x0000028bu, 0x00000000u, + 0x00050051u, 0x00000006u, 0x00000178u, 0x0000028bu, 0x00000001u, 0x00060050u, 0x00000131u, 0x00000179u, + 0x000002f8u, 0x00000177u, 0x00000178u, 0x00050081u, 0x00000131u, 0x0000017au, 0x00000172u, 0x00000179u, + 0x000200f9u, 0x00000130u, 0x000200f8u, 0x00000185u, 0x00050051u, 0x00000006u, 0x0000018au, 0x00000268u, + 0x00000000u, 0x00050051u, 0x00000006u, 0x0000018bu, 0x00000268u, 0x00000001u, 0x00060050u, 0x00000131u, + 0x0000018cu, 0x00000235u, 0x0000018au, 0x0000018bu, 0x00050051u, 0x00000006u, 0x00000191u, 0x00000261u, + 0x00000000u, 0x00050051u, 0x00000006u, 0x00000192u, 0x00000261u, 0x00000001u, 0x00060050u, 0x00000131u, + 0x00000193u, 0x00000232u, 0x00000191u, 0x00000192u, 0x00050051u, 0x00000006u, 0x00000198u, 0x0000026fu, + 0x00000000u, 0x00050051u, 0x00000006u, 0x00000199u, 0x0000026fu, 0x00000001u, 0x00060050u, 0x00000131u, + 0x0000019au, 0x00000238u, 0x00000198u, 0x00000199u, 0x00050081u, 0x00000131u, 0x0000019bu, 0x00000193u, + 0x0000019au, 0x00050051u, 0x00000006u, 0x000001a0u, 0x0000025au, 0x00000000u, 0x00050051u, 0x00000006u, + 0x000001a1u, 0x0000025au, 0x00000001u, 0x00060050u, 0x00000131u, 0x000001a2u, 0x000002eeu, 0x000001a0u, + 0x000001a1u, 0x00050051u, 0x00000006u, 0x000001a7u, 0x00000276u, 0x00000000u, 0x00050051u, 0x00000006u, + 0x000001a8u, 0x00000276u, 0x00000001u, 0x00060050u, 0x00000131u, 0x000001a9u, 0x0000023bu, 0x000001a7u, + 0x000001a8u, 0x00050081u, 0x00000131u, 0x000001aau, 0x000001a2u, 0x000001a9u, 0x00050051u, 0x00000006u, + 0x000001afu, 0x00000253u, 0x00000000u, 0x00050051u, 0x00000006u, 0x000001b0u, 0x00000253u, 0x00000001u, + 0x00060050u, 0x00000131u, 0x000001b1u, 0x0000022cu, 0x000001afu, 0x000001b0u, 0x00050051u, 0x00000006u, + 0x000001b6u, 0x0000027du, 0x00000000u, 0x00050051u, 0x00000006u, 0x000001b7u, 0x0000027du, 0x00000001u, + 0x00060050u, 0x00000131u, 0x000001b8u, 0x000002f3u, 0x000001b6u, 0x000001b7u, 0x00050081u, 0x00000131u, + 0x000001b9u, 0x000001b1u, 0x000001b8u, 0x000200f9u, 0x00000130u, 0x000200f8u, 0x00000130u, 0x000700f5u, + 0x00000131u, 0x00000305u, 0x0000017au, 0x0000012fu, 0x000001bau, 0x00000185u, 0x000700f5u, 0x00000131u, + 0x00000303u, 0x0000016au, 0x0000012fu, 0x000001b9u, 0x00000185u, 0x000700f5u, 0x00000131u, 0x00000301u, + 0x0000015au, 0x0000012fu, 0x000001aau, 0x00000185u, 0x000700f5u, 0x00000131u, 0x000002ffu, 0x0000014au, + 0x0000012fu, 0x0000019bu, 0x00000185u, 0x000700f5u, 0x00000131u, 0x000002fdu, 0x0000013au, 0x0000012fu, + 0x0000018cu, 0x00000185u, 0x000600a9u, 0x00000006u, 0x0000030au, 0x000000f8u, 0x00000184u, 0x0000007au, + 0x000600a9u, 0x00000006u, 0x0000030bu, 0x000000f8u, 0x00000182u, 0x000001beu, 0x000600a9u, 0x00000006u, + 0x0000030cu, 0x000000f8u, 0x00000180u, 0x000001bdu, 0x000600a9u, 0x00000006u, 0x0000030du, 0x000000f8u, + 0x0000017eu, 0x000001bcu, 0x000600a9u, 0x00000006u, 0x0000030eu, 0x000000f8u, 0x0000017cu, 0x000001bbu, + 0x0005008eu, 0x00000131u, 0x000001c2u, 0x000002fdu, 0x0000030eu, 0x0005008eu, 0x00000131u, 0x000001c5u, + 0x000002ffu, 0x0000030du, 0x00050081u, 0x00000131u, 0x000001c6u, 0x000001c2u, 0x000001c5u, 0x0005008eu, + 0x00000131u, 0x000001c9u, 0x00000301u, 0x0000030cu, 0x00050081u, 0x00000131u, 0x000001cau, 0x000001c6u, + 0x000001c9u, 0x0005008eu, 0x00000131u, 0x000001cdu, 0x00000303u, 0x0000030bu, 0x00050081u, 0x00000131u, + 0x000001ceu, 0x000001cau, 0x000001cdu, 0x0005008eu, 0x00000131u, 0x000001d1u, 0x00000305u, 0x0000030au, + 0x00050081u, 0x00000131u, 0x000001d2u, 0x000001ceu, 0x000001d1u, 0x00050051u, 0x00000006u, 0x000001d6u, + 0x000001d2u, 0x00000000u, 0x0003003eu, 0x000001d4u, 0x000001d6u, 0x00050051u, 0x00000006u, 0x000001d9u, + 0x000001d2u, 0x00000001u, 0x0003003eu, 0x000001d7u, 0x000001d9u, 0x00050051u, 0x00000006u, 0x000001ddu, + 0x000001d2u, 0x00000002u, 0x0003003eu, 0x000001dau, 0x000001ddu, 0x000300f7u, 0x000001e0u, 0x00000000u, + 0x000400fau, 0x000001deu, 0x000001dfu, 0x000001e0u, 0x000200f8u, 0x000001dfu, 0x0004003du, 0x00000006u, + 0x000001e2u, 0x000001d4u, 0x00050081u, 0x00000006u, 0x000001e3u, 0x000001e2u, 0x000001e1u, 0x0003003eu, + 0x000001d4u, 0x000001e3u, 0x000200f9u, 0x000001e0u, 0x000200f8u, 0x000001e0u, 0x000300f7u, 0x000001e6u, + 0x00000000u, 0x000400fau, 0x000001e4u, 0x000001e5u, 0x000001e6u, 0x000200f8u, 0x000001e5u, 0x0004003du, + 0x00000006u, 0x000001e7u, 0x000001d7u, 0x00050081u, 0x00000006u, 0x000001e8u, 0x000001e7u, 0x000001e1u, + 0x0003003eu, 0x000001d7u, 0x000001e8u, 0x0004003du, 0x00000006u, 0x000001e9u, 0x000001dau, 0x00050081u, + 0x00000006u, 0x000001eau, 0x000001e9u, 0x000001e1u, 0x0003003eu, 0x000001dau, 0x000001eau, 0x000200f9u, + 0x000001e6u, 0x000200f8u, 0x000001e6u, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, + 0x00000081u, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, 0x00000038u, 0x0006000bu, 0x00000001u, + 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0006000fu, + 0x00000005u, 0x00000004u, 0x6e69616du, 0x00000000u, 0x00000030u, 0x00060010u, 0x00000004u, 0x00000011u, + 0x00000008u, 0x00000008u, 0x00000001u, 0x00040047u, 0x00000030u, 0x0000000bu, 0x0000001cu, 0x00040047u, + 0x00000047u, 0x00000021u, 0x00000000u, 0x00040047u, 0x00000047u, 0x00000022u, 0x00000000u, 0x00030047u, + 0x00000061u, 0x00000019u, 0x00040047u, 0x00000061u, 0x00000021u, 0x00000001u, 0x00040047u, 0x00000061u, + 0x00000022u, 0x00000000u, 0x00040047u, 0x0000006cu, 0x0000000bu, 0x00000019u, 0x00020013u, 0x00000002u, + 0x00030021u, 0x00000003u, 0x00000002u, 0x00030016u, 0x00000006u, 0x00000020u, 0x0004002bu, 0x00000006u, + 0x00000012u, 0xc2c80000u, 0x0004002bu, 0x00000006u, 0x00000017u, 0x00000000u, 0x00040015u, 0x00000018u, + 0x00000020u, 0x00000001u, 0x0004002bu, 0x00000018u, 0x0000001bu, 0x00000000u, 0x0004002bu, 0x00000018u, + 0x00000022u, 0x00000008u, 0x00020014u, 0x00000023u, 0x00040015u, 0x0000002du, 0x00000020u, 0x00000000u, + 0x00040017u, 0x0000002eu, 0x0000002du, 0x00000003u, 0x00040020u, 0x0000002fu, 0x00000001u, 0x0000002eu, + 0x0004003bu, 0x0000002fu, 0x00000030u, 0x00000001u, 0x00040017u, 0x00000031u, 0x0000002du, 0x00000002u, + 0x00040017u, 0x00000034u, 0x00000018u, 0x00000002u, 0x00040017u, 0x00000038u, 0x00000018u, 0x00000004u, + 0x0007002cu, 0x00000038u, 0x0000003cu, 0x0000001bu, 0x0000001bu, 0x0000001bu, 0x0000001bu, 0x00040017u, + 0x0000003du, 0x00000023u, 0x00000004u, 0x00040017u, 0x00000042u, 0x00000006u, 0x00000002u, 0x00090019u, + 0x00000045u, 0x00000006u, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, + 0x00040020u, 0x00000046u, 0x00000000u, 0x00000045u, 0x0004003bu, 0x00000046u, 0x00000047u, 0x00000000u, + 0x00040017u, 0x00000052u, 0x00000006u, 0x00000004u, 0x0004002bu, 0x00000018u, 0x0000005bu, 0x00000001u, + 0x00090019u, 0x0000005fu, 0x00000006u, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000002u, + 0x00000000u, 0x00040020u, 0x00000060u, 0x00000000u, 0x0000005fu, 0x0004003bu, 0x00000060u, 0x00000061u, + 0x00000000u, 0x0004002bu, 0x0000002du, 0x0000006au, 0x00000008u, 0x0004002bu, 0x0000002du, 0x0000006bu, + 0x00000001u, 0x0006002cu, 0x0000002eu, 0x0000006cu, 0x0000006au, 0x0000006au, 0x0000006bu, 0x0005002cu, + 0x00000034u, 0x0000007du, 0x00000022u, 0x00000022u, 0x0004002bu, 0x00000006u, 0x00000080u, 0x4040a8c2u, + 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x000200f9u, + 0x0000001cu, 0x000200f8u, 0x0000001cu, 0x000700f5u, 0x00000006u, 0x00000075u, 0x00000017u, 0x00000005u, + 0x00000078u, 0x0000001fu, 0x000700f5u, 0x00000018u, 0x00000074u, 0x0000001bu, 0x00000005u, 0x0000005eu, + 0x0000001fu, 0x000500b1u, 0x00000023u, 0x00000024u, 0x00000074u, 0x00000022u, 0x000400f6u, 0x0000001eu, + 0x0000001fu, 0x00000000u, 0x000400fau, 0x00000024u, 0x0000001du, 0x0000001eu, 0x000200f8u, 0x0000001du, + 0x000200f9u, 0x00000026u, 0x000200f8u, 0x00000026u, 0x000700f5u, 0x00000006u, 0x00000078u, 0x00000075u, + 0x0000001du, 0x0000007bu, 0x00000029u, 0x000700f5u, 0x00000018u, 0x00000076u, 0x0000001bu, 0x0000001du, + 0x0000005cu, 0x00000029u, 0x000500b1u, 0x00000023u, 0x0000002cu, 0x00000076u, 0x00000022u, 0x000400f6u, + 0x00000028u, 0x00000029u, 0x00000000u, 0x000400fau, 0x0000002cu, 0x00000027u, 0x00000028u, 0x000200f8u, + 0x00000027u, 0x0004003du, 0x0000002eu, 0x00000032u, 0x00000030u, 0x0007004fu, 0x00000031u, 0x00000033u, + 0x00000032u, 0x00000032u, 0x00000000u, 0x00000001u, 0x0004007cu, 0x00000034u, 0x00000035u, 0x00000033u, + 0x00050051u, 0x00000018u, 0x00000039u, 0x00000035u, 0x00000000u, 0x00050051u, 0x00000018u, 0x0000003au, + 0x00000035u, 0x00000001u, 0x00070050u, 0x00000038u, 0x0000003bu, 0x00000039u, 0x0000003au, 0x00000076u, + 0x00000074u, 0x000500abu, 0x0000003du, 0x0000003eu, 0x0000003bu, 0x0000003cu, 0x0004009au, 0x00000023u, + 0x0000003fu, 0x0000003eu, 0x000300f7u, 0x00000041u, 0x00000000u, 0x000400fau, 0x0000003fu, 0x00000040u, + 0x00000041u, 0x000200f8u, 0x00000040u, 0x0004003du, 0x00000045u, 0x00000048u, 0x00000047u, 0x00050084u, + 0x00000034u, 0x0000004du, 0x00000035u, 0x0000007du, 0x00050050u, 0x00000034u, 0x00000050u, 0x00000076u, + 0x00000074u, 0x00050080u, 0x00000034u, 0x00000051u, 0x0000004du, 0x00000050u, 0x0007005fu, 0x00000052u, + 0x00000053u, 0x00000048u, 0x00000051u, 0x00000002u, 0x0000001bu, 0x0007004fu, 0x00000042u, 0x00000054u, + 0x00000053u, 0x00000053u, 0x00000000u, 0x00000001u, 0x00050094u, 0x00000006u, 0x00000057u, 0x00000054u, + 0x00000054u, 0x00050081u, 0x00000006u, 0x00000059u, 0x00000078u, 0x00000057u, 0x000200f9u, 0x00000041u, + 0x000200f8u, 0x00000041u, 0x000700f5u, 0x00000006u, 0x0000007bu, 0x00000078u, 0x00000027u, 0x00000059u, + 0x00000040u, 0x000200f9u, 0x00000029u, 0x000200f8u, 0x00000029u, 0x00050080u, 0x00000018u, 0x0000005cu, + 0x00000076u, 0x0000005bu, 0x000200f9u, 0x00000026u, 0x000200f8u, 0x00000028u, 0x000200f9u, 0x0000001fu, + 0x000200f8u, 0x0000001fu, 0x00050080u, 0x00000018u, 0x0000005eu, 0x00000074u, 0x0000005bu, 0x000200f9u, + 0x0000001cu, 0x000200f8u, 0x0000001eu, 0x0004003du, 0x0000005fu, 0x00000062u, 0x00000061u, 0x0004003du, + 0x0000002eu, 0x00000063u, 0x00000030u, 0x0007004fu, 0x00000031u, 0x00000064u, 0x00000063u, 0x00000063u, + 0x00000000u, 0x00000001u, 0x0004007cu, 0x00000034u, 0x00000065u, 0x00000064u, 0x0006000cu, 0x00000006u, + 0x00000070u, 0x00000001u, 0x0000001eu, 0x00000075u, 0x00050085u, 0x00000006u, 0x00000072u, 0x00000070u, + 0x00000080u, 0x0007000cu, 0x00000006u, 0x00000073u, 0x00000001u, 0x00000028u, 0x00000072u, 0x00000012u, + 0x00070050u, 0x00000052u, 0x00000069u, 0x00000073u, 0x00000073u, 0x00000073u, 0x00000073u, 0x00040063u, + 0x00000062u, 0x00000065u, 0x00000069u, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, + 0x00000290u, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, 0x00000009u, 0x00020011u, 0x00000016u, + 0x00020011u, 0x0000003du, 0x00020011u, 0x0000003fu, 0x00020011u, 0x00000041u, 0x00020011u, 0x00000042u, + 0x00020011u, 0x00001151u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, + 0x0003000eu, 0x00000000u, 0x00000001u, 0x0009000fu, 0x00000005u, 0x00000004u, 0x6e69616du, 0x00000000u, + 0x00000038u, 0x000000b6u, 0x000000fau, 0x000000fcu, 0x00060010u, 0x00000004u, 0x00000011u, 0x00000040u, + 0x00000001u, 0x00000001u, 0x00030047u, 0x00000038u, 0x00000000u, 0x00040047u, 0x00000038u, 0x0000000bu, + 0x00000029u, 0x00040047u, 0x00000094u, 0x00000006u, 0x00000004u, 0x00050048u, 0x00000095u, 0x00000000u, + 0x00000023u, 0x00000000u, 0x00050048u, 0x00000095u, 0x00000001u, 0x00000023u, 0x00000004u, 0x00040047u, + 0x00000096u, 0x00000006u, 0x00000008u, 0x00030047u, 0x00000097u, 0x00000002u, 0x00050048u, 0x00000097u, + 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x00000097u, 0x00000001u, 0x00000023u, 0x00000004u, + 0x00050048u, 0x00000097u, 0x00000002u, 0x00000023u, 0x00000040u, 0x00050048u, 0x00000097u, 0x00000003u, + 0x00000023u, 0x00002040u, 0x00040047u, 0x00000099u, 0x00000021u, 0x00000000u, 0x00040047u, 0x00000099u, + 0x00000022u, 0x00000000u, 0x00040047u, 0x000000b6u, 0x0000000bu, 0x0000001au, 0x00030047u, 0x000000bdu, + 0x00000002u, 0x00050048u, 0x000000bdu, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x000000bdu, + 0x00000001u, 0x00000023u, 0x00000008u, 0x00050048u, 0x000000bdu, 0x00000002u, 0x00000023u, 0x00000010u, + 0x00050048u, 0x000000bdu, 0x00000003u, 0x00000023u, 0x00000014u, 0x00050048u, 0x000000bdu, 0x00000004u, + 0x00000023u, 0x00000018u, 0x00050048u, 0x000000bdu, 0x00000005u, 0x00000023u, 0x0000001cu, 0x00050048u, + 0x000000bdu, 0x00000006u, 0x00000023u, 0x00000020u, 0x00050048u, 0x000000bdu, 0x00000007u, 0x00000023u, + 0x00000024u, 0x00050048u, 0x000000bdu, 0x00000008u, 0x00000023u, 0x00000028u, 0x00030047u, 0x000000f9u, + 0x00000000u, 0x00030047u, 0x000000fau, 0x00000000u, 0x00040047u, 0x000000fau, 0x0000000bu, 0x00000024u, + 0x00030047u, 0x000000fbu, 0x00000000u, 0x00040047u, 0x000000fcu, 0x0000000bu, 0x00000028u, 0x00050048u, + 0x0000012du, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x0000012du, 0x00000001u, 0x00000023u, + 0x00000002u, 0x00040047u, 0x0000012fu, 0x00000006u, 0x00000004u, 0x00050048u, 0x00000130u, 0x00000000u, + 0x00000023u, 0x00000000u, 0x00050048u, 0x00000130u, 0x00000001u, 0x00000023u, 0x00000004u, 0x00040047u, + 0x00000131u, 0x00000006u, 0x00000040u, 0x00030047u, 0x00000132u, 0x00000002u, 0x00040048u, 0x00000132u, + 0x00000000u, 0x00000018u, 0x00050048u, 0x00000132u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00030047u, + 0x00000134u, 0x00000018u, 0x00040047u, 0x00000134u, 0x00000021u, 0x00000001u, 0x00040047u, 0x00000134u, + 0x00000022u, 0x00000000u, 0x00040047u, 0x000001b0u, 0x0000000bu, 0x00000019u, 0x00030047u, 0x000001f5u, + 0x00000000u, 0x00030047u, 0x00000221u, 0x00000000u, 0x00030047u, 0x00000252u, 0x00000000u, 0x00020013u, + 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00030016u, 0x00000006u, 0x00000020u, 0x00040015u, + 0x00000008u, 0x00000020u, 0x00000000u, 0x00020014u, 0x00000019u, 0x0004002bu, 0x00000008u, 0x0000001du, + 0x00000000u, 0x0004002bu, 0x00000006u, 0x00000021u, 0x40000000u, 0x0004002bu, 0x00000006u, 0x00000025u, + 0x00000000u, 0x0004002bu, 0x00000008u, 0x00000036u, 0x00000070u, 0x00040020u, 0x00000037u, 0x00000001u, + 0x00000008u, 0x0004003bu, 0x00000037u, 0x00000038u, 0x00000001u, 0x0004002bu, 0x00000008u, 0x0000003du, + 0x00000001u, 0x0004002bu, 0x00000008u, 0x00000044u, 0x00000010u, 0x0004002bu, 0x00000008u, 0x00000049u, + 0x00000003u, 0x0004002bu, 0x00000008u, 0x00000054u, 0x00000002u, 0x0004001cu, 0x0000005fu, 0x00000008u, + 0x00000044u, 0x00040020u, 0x00000060u, 0x00000004u, 0x0000005fu, 0x0004003bu, 0x00000060u, 0x00000061u, + 0x00000004u, 0x00040020u, 0x00000063u, 0x00000004u, 0x00000008u, 0x0004001cu, 0x00000068u, 0x00000006u, + 0x00000044u, 0x00040020u, 0x00000069u, 0x00000004u, 0x00000068u, 0x0004003bu, 0x00000069u, 0x0000006au, + 0x00000004u, 0x00040020u, 0x0000006cu, 0x00000004u, 0x00000006u, 0x0004002bu, 0x00000006u, 0x00000074u, + 0x7149f2cau, 0x00040015u, 0x00000076u, 0x00000020u, 0x00000001u, 0x0004002bu, 0x00000076u, 0x00000077u, + 0x00000000u, 0x0004002bu, 0x00000008u, 0x00000093u, 0x00000800u, 0x0004001cu, 0x00000094u, 0x00000008u, + 0x00000093u, 0x0004001eu, 0x00000095u, 0x00000076u, 0x00000008u, 0x0003001du, 0x00000096u, 0x00000095u, + 0x0006001eu, 0x00000097u, 0x00000008u, 0x00000008u, 0x00000094u, 0x00000096u, 0x00040020u, 0x00000098u, + 0x0000000cu, 0x00000097u, 0x0004003bu, 0x00000098u, 0x00000099u, 0x0000000cu, 0x0004002bu, 0x00000076u, + 0x0000009au, 0x00000001u, 0x00040020u, 0x0000009bu, 0x0000000cu, 0x00000008u, 0x00040017u, 0x000000b1u, + 0x00000076u, 0x00000002u, 0x00040017u, 0x000000b4u, 0x00000008u, 0x00000003u, 0x00040020u, 0x000000b5u, + 0x00000001u, 0x000000b4u, 0x0004003bu, 0x000000b5u, 0x000000b6u, 0x00000001u, 0x00040017u, 0x000000b7u, + 0x00000008u, 0x00000002u, 0x000b001eu, 0x000000bdu, 0x000000b1u, 0x000000b1u, 0x00000076u, 0x00000076u, + 0x00000076u, 0x00000076u, 0x00000008u, 0x00000008u, 0x00000008u, 0x00040020u, 0x000000beu, 0x00000009u, + 0x000000bdu, 0x0004003bu, 0x000000beu, 0x000000bfu, 0x00000009u, 0x0004002bu, 0x00000076u, 0x000000c0u, + 0x00000004u, 0x00040020u, 0x000000c1u, 0x00000009u, 0x00000076u, 0x0004002bu, 0x00000076u, 0x000000c6u, + 0x00000005u, 0x0004002bu, 0x00000076u, 0x000000d0u, 0x00000008u, 0x00040020u, 0x000000d1u, 0x00000009u, + 0x00000008u, 0x0004002bu, 0x00000076u, 0x000000d6u, 0x00000002u, 0x0004002bu, 0x00000076u, 0x000000deu, + 0x00000003u, 0x0004002bu, 0x00000076u, 0x000000e2u, 0x00000007u, 0x0004002bu, 0x00000076u, 0x000000ecu, + 0x00000010u, 0x00040020u, 0x000000f4u, 0x0000000cu, 0x00000076u, 0x0004003bu, 0x00000037u, 0x000000fau, + 0x00000001u, 0x0004003bu, 0x00000037u, 0x000000fcu, 0x00000001u, 0x00040020u, 0x00000115u, 0x00000009u, + 0x000000b1u, 0x00040017u, 0x00000118u, 0x00000019u, 0x00000002u, 0x00030016u, 0x0000012bu, 0x00000010u, + 0x00040015u, 0x0000012cu, 0x00000010u, 0x00000000u, 0x0004001eu, 0x0000012du, 0x0000012bu, 0x0000012cu, + 0x0004002bu, 0x00000008u, 0x0000012eu, 0x0000000fu, 0x0004001cu, 0x0000012fu, 0x0000012du, 0x0000012eu, + 0x0004001eu, 0x00000130u, 0x00000008u, 0x0000012fu, 0x0003001du, 0x00000131u, 0x00000130u, 0x0003001eu, + 0x00000132u, 0x00000131u, 0x00040020u, 0x00000133u, 0x0000000cu, 0x00000132u, 0x0004003bu, 0x00000133u, + 0x00000134u, 0x0000000cu, 0x00040020u, 0x00000150u, 0x0000000cu, 0x0000012du, 0x0004002bu, 0x00000008u, + 0x00000163u, 0x00000018u, 0x0004002bu, 0x00000008u, 0x00000178u, 0x00000004u, 0x0004002bu, 0x00000008u, + 0x0000017du, 0x00000008u, 0x0004002bu, 0x00000008u, 0x0000019au, 0x00000040u, 0x0004002bu, 0x00000008u, + 0x0000019fu, 0x0000001fu, 0x0004002bu, 0x00000008u, 0x000001a8u, 0x00000108u, 0x0006002cu, 0x000000b4u, + 0x000001b0u, 0x0000019au, 0x0000003du, 0x0000003du, 0x00030001u, 0x00000008u, 0x00000279u, 0x0005002cu, + 0x000000b1u, 0x0000028cu, 0x000000c0u, 0x000000c0u, 0x0004002bu, 0x00000006u, 0x0000028eu, 0x42720000u, + 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003du, + 0x00000008u, 0x000000f9u, 0x00000038u, 0x0004003du, 0x00000008u, 0x000000fbu, 0x000000fau, 0x0004003du, + 0x00000008u, 0x000000fdu, 0x000000fcu, 0x00050084u, 0x00000008u, 0x000000feu, 0x000000fbu, 0x000000fdu, + 0x00050080u, 0x00000008u, 0x000000ffu, 0x000000f9u, 0x000000feu, 0x0004003du, 0x000000b4u, 0x00000101u, + 0x000000b6u, 0x0007004fu, 0x000000b7u, 0x00000102u, 0x00000101u, 0x00000101u, 0x00000000u, 0x00000001u, + 0x0004007cu, 0x000000b1u, 0x00000103u, 0x00000102u, 0x000600cbu, 0x00000008u, 0x00000106u, 0x000000ffu, + 0x00000077u, 0x000000d6u, 0x0004007cu, 0x00000076u, 0x00000107u, 0x00000106u, 0x000600cbu, 0x00000008u, + 0x00000109u, 0x000000ffu, 0x000000d6u, 0x000000d6u, 0x0004007cu, 0x00000076u, 0x0000010au, 0x00000109u, + 0x00050050u, 0x000000b1u, 0x0000010bu, 0x00000107u, 0x0000010au, 0x00050084u, 0x000000b1u, 0x0000010fu, + 0x0000028cu, 0x00000103u, 0x00050080u, 0x000000b1u, 0x00000111u, 0x0000010fu, 0x0000010bu, 0x00050041u, + 0x00000115u, 0x00000116u, 0x000000bfu, 0x0000009au, 0x0004003du, 0x000000b1u, 0x00000117u, 0x00000116u, + 0x000500b1u, 0x00000118u, 0x00000119u, 0x00000111u, 0x00000117u, 0x0004009bu, 0x00000019u, 0x0000011au, + 0x00000119u, 0x00050041u, 0x000000c1u, 0x0000011cu, 0x000000bfu, 0x000000d6u, 0x0004003du, 0x00000076u, + 0x0000011du, 0x0000011cu, 0x00050041u, 0x000000c1u, 0x0000011eu, 0x000000bfu, 0x000000deu, 0x0004003du, + 0x00000076u, 0x0000011fu, 0x0000011eu, 0x00050051u, 0x00000076u, 0x00000121u, 0x00000111u, 0x00000001u, + 0x00050084u, 0x00000076u, 0x00000122u, 0x0000011fu, 0x00000121u, 0x00050080u, 0x00000076u, 0x00000123u, + 0x0000011du, 0x00000122u, 0x00050051u, 0x00000076u, 0x00000125u, 0x00000111u, 0x00000000u, 0x00050080u, + 0x00000076u, 0x00000126u, 0x00000123u, 0x00000125u, 0x000300f7u, 0x00000129u, 0x00000000u, 0x000400fau, + 0x0000011au, 0x00000128u, 0x00000129u, 0x000200f8u, 0x00000128u, 0x00070041u, 0x0000009bu, 0x00000136u, + 0x00000134u, 0x00000077u, 0x00000126u, 0x00000077u, 0x0004003du, 0x00000008u, 0x00000137u, 0x00000136u, + 0x000200f9u, 0x00000129u, 0x000200f8u, 0x00000129u, 0x000700f5u, 0x00000008u, 0x00000278u, 0x00000279u, + 0x00000005u, 0x00000137u, 0x00000128u, 0x000500c2u, 0x00000008u, 0x0000013au, 0x000000ffu, 0x000000c0u, + 0x000200f9u, 0x0000013du, 0x000200f8u, 0x0000013du, 0x000700f5u, 0x00000008u, 0x00000270u, 0x0000013au, + 0x00000129u, 0x000001a7u, 0x00000140u, 0x000500b0u, 0x00000019u, 0x00000143u, 0x00000270u, 0x00000044u, + 0x000400f6u, 0x0000013fu, 0x00000140u, 0x00000000u, 0x000400fau, 0x00000143u, 0x0000013eu, 0x0000013fu, + 0x000200f8u, 0x0000013eu, 0x000300f7u, 0x00000148u, 0x00000000u, 0x000400fau, 0x0000011au, 0x00000147u, + 0x00000148u, 0x000200f8u, 0x00000147u, 0x0007000cu, 0x00000008u, 0x0000014fu, 0x00000001u, 0x00000026u, + 0x00000270u, 0x00000278u, 0x00080041u, 0x00000150u, 0x00000151u, 0x00000134u, 0x00000077u, 0x00000126u, + 0x0000009au, 0x0000014fu, 0x0004003du, 0x0000012du, 0x00000152u, 0x00000151u, 0x00050051u, 0x0000012bu, + 0x00000153u, 0x00000152u, 0x00000000u, 0x00050051u, 0x0000012cu, 0x00000156u, 0x00000152u, 0x00000001u, + 0x00040073u, 0x00000006u, 0x0000015bu, 0x00000153u, 0x00040071u, 0x00000008u, 0x0000015eu, 0x00000156u, + 0x000200f9u, 0x00000148u, 0x000200f8u, 0x00000148u, 0x000700f5u, 0x00000006u, 0x0000027du, 0x00000025u, + 0x0000013eu, 0x0000015bu, 0x00000147u, 0x000700f5u, 0x00000008u, 0x0000027au, 0x0000001du, 0x0000013eu, + 0x0000015eu, 0x00000147u, 0x000500abu, 0x00000019u, 0x00000160u, 0x0000027au, 0x0000001du, 0x000300f7u, + 0x00000162u, 0x00000000u, 0x000400fau, 0x00000160u, 0x00000161u, 0x00000162u, 0x000200f8u, 0x00000161u, + 0x00050080u, 0x00000008u, 0x00000165u, 0x0000027au, 0x00000163u, 0x000200f9u, 0x00000162u, 0x000200f8u, + 0x00000162u, 0x000700f5u, 0x00000008u, 0x0000027bu, 0x0000027au, 0x00000148u, 0x00000165u, 0x00000161u, + 0x000500aau, 0x00000019u, 0x00000167u, 0x000000fbu, 0x00000044u, 0x000300f7u, 0x00000169u, 0x00000000u, + 0x000400fau, 0x00000167u, 0x00000168u, 0x0000016eu, 0x000200f8u, 0x00000168u, 0x0006015du, 0x00000008u, + 0x0000016bu, 0x00000049u, 0x00000000u, 0x0000027bu, 0x0006015eu, 0x00000006u, 0x0000016du, 0x00000049u, + 0x00000000u, 0x0000027du, 0x000200f9u, 0x00000169u, 0x000200f8u, 0x0000016eu, 0x0006015au, 0x00000008u, + 0x00000170u, 0x00000049u, 0x0000027bu, 0x0000003du, 0x00050080u, 0x00000008u, 0x00000172u, 0x0000027bu, + 0x00000170u, 0x0006015au, 0x00000008u, 0x00000174u, 0x00000049u, 0x00000172u, 0x00000054u, 0x00050080u, + 0x00000008u, 0x00000176u, 0x00000172u, 0x00000174u, 0x0006015au, 0x00000008u, 0x00000179u, 0x00000049u, + 0x00000176u, 0x00000178u, 0x00050080u, 0x00000008u, 0x0000017bu, 0x00000176u, 0x00000179u, 0x0006015au, + 0x00000008u, 0x0000017eu, 0x00000049u, 0x0000017bu, 0x0000017du, 0x00050080u, 0x00000008u, 0x00000180u, + 0x0000017bu, 0x0000017eu, 0x0006015au, 0x00000006u, 0x00000182u, 0x00000049u, 0x0000027du, 0x0000003du, + 0x00050081u, 0x00000006u, 0x00000184u, 0x0000027du, 0x00000182u, 0x0006015au, 0x00000006u, 0x00000186u, + 0x00000049u, 0x00000184u, 0x00000054u, 0x00050081u, 0x00000006u, 0x00000188u, 0x00000184u, 0x00000186u, + 0x0006015au, 0x00000006u, 0x0000018au, 0x00000049u, 0x00000188u, 0x00000178u, 0x00050081u, 0x00000006u, + 0x0000018cu, 0x00000188u, 0x0000018au, 0x0006015au, 0x00000006u, 0x0000018eu, 0x00000049u, 0x0000018cu, + 0x0000017du, 0x00050081u, 0x00000006u, 0x00000190u, 0x0000018cu, 0x0000018eu, 0x000200f9u, 0x00000169u, + 0x000200f8u, 0x00000169u, 0x000700f5u, 0x00000006u, 0x00000285u, 0x0000016du, 0x00000168u, 0x00000190u, + 0x0000016eu, 0x000700f5u, 0x00000008u, 0x0000027eu, 0x0000016bu, 0x00000168u, 0x00000180u, 0x0000016eu, + 0x000500c7u, 0x00000008u, 0x00000192u, 0x000000ffu, 0x0000012eu, 0x000500aau, 0x00000019u, 0x00000193u, + 0x00000192u, 0x0000001du, 0x000300f7u, 0x00000195u, 0x00000000u, 0x000400fau, 0x00000193u, 0x00000194u, + 0x00000195u, 0x000200f8u, 0x00000194u, 0x000500abu, 0x00000019u, 0x00000197u, 0x0000027eu, 0x0000001du, + 0x000300f7u, 0x00000199u, 0x00000000u, 0x000400fau, 0x00000197u, 0x00000198u, 0x00000199u, 0x000200f8u, + 0x00000198u, 0x00050080u, 0x00000008u, 0x0000019cu, 0x0000027eu, 0x0000019au, 0x000200f9u, 0x00000199u, + 0x000200f8u, 0x00000199u, 0x000700f5u, 0x00000008u, 0x00000283u, 0x0000027eu, 0x00000194u, 0x0000019cu, + 0x00000198u, 0x00050080u, 0x00000008u, 0x000001a0u, 0x00000283u, 0x0000019fu, 0x000500c2u, 0x00000008u, + 0x000001a1u, 0x000001a0u, 0x000000c6u, 0x00050041u, 0x00000063u, 0x000001a2u, 0x00000061u, 0x00000270u, + 0x0003003eu, 0x000001a2u, 0x000001a1u, 0x00050041u, 0x0000006cu, 0x000001a5u, 0x0000006au, 0x00000270u, + 0x0003003eu, 0x000001a5u, 0x00000285u, 0x000200f9u, 0x00000195u, 0x000200f8u, 0x00000195u, 0x000200f9u, + 0x00000140u, 0x000200f8u, 0x00000140u, 0x00050080u, 0x00000008u, 0x000001a7u, 0x00000270u, 0x00000178u, + 0x000200f9u, 0x0000013du, 0x000200f8u, 0x0000013fu, 0x000400e0u, 0x00000054u, 0x00000054u, 0x000001a8u, + 0x000500aau, 0x00000019u, 0x000001aau, 0x000000fdu, 0x0000001du, 0x000300f7u, 0x000001acu, 0x00000000u, + 0x000400fau, 0x000001aau, 0x000001abu, 0x000001acu, 0x000200f8u, 0x000001abu, 0x000500b0u, 0x00000019u, + 0x000001cbu, 0x000000f9u, 0x00000044u, 0x000300f7u, 0x000001d9u, 0x00000000u, 0x000400fau, 0x000001cbu, + 0x000001ccu, 0x000001d4u, 0x000200f8u, 0x000001ccu, 0x00050041u, 0x00000063u, 0x000001ceu, 0x00000061u, + 0x000000f9u, 0x0004003du, 0x00000008u, 0x000001cfu, 0x000001ceu, 0x00040070u, 0x00000006u, 0x000001d0u, + 0x000001cfu, 0x00050041u, 0x0000006cu, 0x000001d2u, 0x0000006au, 0x000000f9u, 0x0004003du, 0x00000006u, + 0x000001d3u, 0x000001d2u, 0x000200f9u, 0x000001d9u, 0x000200f8u, 0x000001d4u, 0x00050041u, 0x00000063u, + 0x000001d6u, 0x00000061u, 0x000000f9u, 0x0004003du, 0x00000008u, 0x000001d7u, 0x000001d6u, 0x00040070u, + 0x00000006u, 0x000001d8u, 0x000001d7u, 0x000200f9u, 0x000001d9u, 0x000200f8u, 0x000001d9u, 0x000700f5u, + 0x00000006u, 0x00000272u, 0x000001d0u, 0x000001ccu, 0x000001d8u, 0x000001d4u, 0x000700f5u, 0x00000006u, + 0x00000271u, 0x000001d3u, 0x000001ccu, 0x00000074u, 0x000001d4u, 0x00050041u, 0x00000063u, 0x000001dau, + 0x00000061u, 0x00000077u, 0x0004003du, 0x00000008u, 0x000001dbu, 0x000001dau, 0x00040070u, 0x00000006u, + 0x000001dcu, 0x000001dbu, 0x00050041u, 0x0000006cu, 0x000001dfu, 0x0000006au, 0x00000077u, 0x0004003du, + 0x00000006u, 0x000001e0u, 0x000001dfu, 0x000300f7u, 0x0000024au, 0x00000000u, 0x000300fbu, 0x0000001du, + 0x00000235u, 0x000200f8u, 0x00000235u, 0x000500b4u, 0x00000019u, 0x00000238u, 0x00000272u, 0x000001dcu, + 0x000300f7u, 0x0000023au, 0x00000000u, 0x000400fau, 0x00000238u, 0x00000239u, 0x0000023au, 0x000200f8u, + 0x00000239u, 0x000200f9u, 0x0000024au, 0x000200f8u, 0x0000023au, 0x00050083u, 0x00000006u, 0x0000023du, + 0x00000271u, 0x000001e0u, 0x0007000cu, 0x00000006u, 0x0000023eu, 0x00000001u, 0x00000028u, 0x0000023du, + 0x00000025u, 0x00050083u, 0x00000006u, 0x00000241u, 0x000001dcu, 0x00000272u, 0x00050088u, 0x00000006u, + 0x00000242u, 0x0000023eu, 0x00000241u, 0x0006000cu, 0x00000006u, 0x00000243u, 0x00000001u, 0x0000001eu, + 0x00000242u, 0x00050085u, 0x00000006u, 0x00000244u, 0x00000021u, 0x00000243u, 0x00050081u, 0x00000006u, + 0x00000247u, 0x00000244u, 0x0000028eu, 0x0007000cu, 0x00000006u, 0x00000248u, 0x00000001u, 0x00000028u, + 0x00000247u, 0x00000025u, 0x0004006du, 0x00000008u, 0x00000249u, 0x00000248u, 0x000200f9u, 0x0000024au, + 0x000200f8u, 0x0000024au, 0x000700f5u, 0x00000008u, 0x00000273u, 0x0000001du, 0x00000239u, 0x00000249u, + 0x0000023au, 0x000500aau, 0x00000019u, 0x000001e3u, 0x000000f9u, 0x0000001du, 0x000600a9u, 0x00000008u, + 0x0000028fu, 0x000001e3u, 0x0000001du, 0x00000273u, 0x00050080u, 0x00000008u, 0x00000252u, 0x00000036u, + 0x000000f9u, 0x0007000cu, 0x00000008u, 0x00000253u, 0x00000001u, 0x00000026u, 0x0000028fu, 0x00000252u, + 0x000200f9u, 0x00000254u, 0x000200f8u, 0x00000254u, 0x000700f5u, 0x00000008u, 0x00000276u, 0x00000253u, + 0x0000024au, 0x00000264u, 0x00000258u, 0x000700f5u, 0x00000008u, 0x00000275u, 0x0000003du, 0x0000024au, + 0x00000267u, 0x00000258u, 0x000500b0u, 0x00000019u, 0x00000257u, 0x00000275u, 0x00000044u, 0x000400f6u, + 0x00000268u, 0x00000258u, 0x00000000u, 0x000400fau, 0x00000257u, 0x00000258u, 0x00000268u, 0x000200f8u, + 0x00000258u, 0x0006015bu, 0x00000008u, 0x0000025bu, 0x00000049u, 0x00000276u, 0x00000275u, 0x00050080u, + 0x00000008u, 0x0000025du, 0x0000025bu, 0x00000275u, 0x000500aeu, 0x00000019u, 0x00000261u, 0x000000f9u, + 0x00000275u, 0x000600a9u, 0x00000008u, 0x00000263u, 0x00000261u, 0x0000025du, 0x0000001du, 0x0007000cu, + 0x00000008u, 0x00000264u, 0x00000001u, 0x00000029u, 0x00000276u, 0x00000263u, 0x00050084u, 0x00000008u, + 0x00000267u, 0x00000275u, 0x00000054u, 0x000200f9u, 0x00000254u, 0x000200f8u, 0x00000268u, 0x000300f7u, + 0x0000022fu, 0x00000000u, 0x000400fau, 0x000001e3u, 0x000001eau, 0x000001f0u, 0x000200f8u, 0x000001eau, + 0x0004003du, 0x00000008u, 0x000001ecu, 0x000001dau, 0x00050041u, 0x0000009bu, 0x000001edu, 0x00000099u, + 0x0000009au, 0x000700eau, 0x00000008u, 0x000001efu, 0x000001edu, 0x0000003du, 0x0000001du, 0x000001ecu, + 0x000200f9u, 0x0000022fu, 0x000200f8u, 0x000001f0u, 0x000300f7u, 0x0000022eu, 0x00000000u, 0x000400fau, + 0x000001cbu, 0x000001f3u, 0x0000022eu, 0x000200f8u, 0x000001f3u, 0x00050082u, 0x00000008u, 0x000001f5u, + 0x000000f9u, 0x0000003du, 0x00050041u, 0x00000063u, 0x000001f6u, 0x00000061u, 0x000001f5u, 0x0004003du, + 0x00000008u, 0x000001f7u, 0x000001f6u, 0x00050041u, 0x00000063u, 0x000001f9u, 0x00000061u, 0x000000f9u, + 0x0004003du, 0x00000008u, 0x000001fau, 0x000001f9u, 0x00050082u, 0x00000008u, 0x000001fbu, 0x000001f7u, + 0x000001fau, 0x000500abu, 0x00000019u, 0x000001fdu, 0x000001fbu, 0x0000001du, 0x000300f7u, 0x0000022du, + 0x00000000u, 0x000400fau, 0x000001fdu, 0x000001feu, 0x0000022du, 0x000200f8u, 0x000001feu, 0x00050041u, + 0x000000c1u, 0x00000202u, 0x000000bfu, 0x000000c0u, 0x0004003du, 0x00000076u, 0x00000203u, 0x00000202u, + 0x00050051u, 0x00000076u, 0x00000205u, 0x00000103u, 0x00000001u, 0x00050041u, 0x000000c1u, 0x00000206u, + 0x000000bfu, 0x000000c6u, 0x0004003du, 0x00000076u, 0x00000207u, 0x00000206u, 0x00050084u, 0x00000076u, + 0x00000208u, 0x00000205u, 0x00000207u, 0x00050080u, 0x00000076u, 0x00000209u, 0x00000203u, 0x00000208u, + 0x00050051u, 0x00000076u, 0x0000020bu, 0x00000103u, 0x00000000u, 0x00050080u, 0x00000076u, 0x0000020cu, + 0x00000209u, 0x0000020bu, 0x00050041u, 0x000000d1u, 0x0000020eu, 0x000000bfu, 0x000000d0u, 0x0004003du, + 0x00000008u, 0x0000020fu, 0x0000020eu, 0x000500c3u, 0x00000076u, 0x00000210u, 0x0000020cu, 0x0000020fu, + 0x0004007cu, 0x00000008u, 0x00000211u, 0x00000210u, 0x00050084u, 0x00000008u, 0x00000213u, 0x00000276u, + 0x00000044u, 0x00050080u, 0x00000008u, 0x00000215u, 0x00000213u, 0x00000211u, 0x00060041u, 0x0000009bu, + 0x00000216u, 0x00000099u, 0x000000d6u, 0x00000215u, 0x000700eau, 0x00000008u, 0x00000218u, 0x00000216u, + 0x0000003du, 0x0000001du, 0x000001fbu, 0x0004007cu, 0x00000008u, 0x0000021au, 0x0000020cu, 0x00050041u, + 0x000000d1u, 0x0000021cu, 0x000000bfu, 0x000000e2u, 0x0004003du, 0x00000008u, 0x0000021du, 0x0000021cu, + 0x00050084u, 0x00000008u, 0x0000021eu, 0x00000276u, 0x0000021du, 0x00050080u, 0x00000008u, 0x0000021fu, + 0x0000021au, 0x0000021eu, 0x0004007cu, 0x00000076u, 0x00000221u, 0x000000f9u, 0x000500c4u, 0x00000008u, + 0x00000225u, 0x000001fbu, 0x000000ecu, 0x000500c5u, 0x00000008u, 0x00000226u, 0x0000021au, 0x00000225u, + 0x00070041u, 0x000000f4u, 0x0000022au, 0x00000099u, 0x000000deu, 0x0000021fu, 0x00000077u, 0x0003003eu, + 0x0000022au, 0x00000221u, 0x00070041u, 0x0000009bu, 0x0000022cu, 0x00000099u, 0x000000deu, 0x0000021fu, + 0x0000009au, 0x0003003eu, 0x0000022cu, 0x00000226u, 0x000200f9u, 0x0000022du, 0x000200f8u, 0x0000022du, + 0x000200f9u, 0x0000022eu, 0x000200f8u, 0x0000022eu, 0x000200f9u, 0x0000022fu, 0x000200f8u, 0x0000022fu, + 0x000200f9u, 0x000001acu, 0x000200f8u, 0x000001acu, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, + 0x000d000bu, 0x0000006du, 0x00000000u, 0x00020011u, 0x00000001u, 0x0006000bu, 0x00000001u, 0x4c534c47u, + 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0006000fu, 0x00000005u, + 0x00000004u, 0x6e69616du, 0x00000000u, 0x00000012u, 0x00060010u, 0x00000004u, 0x00000011u, 0x00000200u, + 0x00000001u, 0x00000001u, 0x00040047u, 0x0000000bu, 0x00000006u, 0x00000010u, 0x00030047u, 0x0000000cu, + 0x00000002u, 0x00050048u, 0x0000000cu, 0x00000000u, 0x00000023u, 0x00000040u, 0x00040047u, 0x0000000eu, + 0x00000021u, 0x00000000u, 0x00040047u, 0x0000000eu, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000012u, + 0x0000000bu, 0x0000001du, 0x00040047u, 0x0000005au, 0x0000000bu, 0x00000019u, 0x00020013u, 0x00000002u, + 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, 0x00000000u, 0x00040017u, + 0x00000007u, 0x00000006u, 0x00000004u, 0x0004002bu, 0x00000006u, 0x0000000au, 0x00000200u, 0x0004001cu, + 0x0000000bu, 0x00000007u, 0x0000000au, 0x0003001eu, 0x0000000cu, 0x0000000bu, 0x00040020u, 0x0000000du, + 0x0000000cu, 0x0000000cu, 0x0004003bu, 0x0000000du, 0x0000000eu, 0x0000000cu, 0x00040015u, 0x0000000fu, + 0x00000020u, 0x00000001u, 0x0004002bu, 0x0000000fu, 0x00000010u, 0x00000000u, 0x00040020u, 0x00000011u, + 0x00000001u, 0x00000006u, 0x0004003bu, 0x00000011u, 0x00000012u, 0x00000001u, 0x00040020u, 0x00000014u, + 0x0000000cu, 0x00000007u, 0x0004002bu, 0x00000006u, 0x00000017u, 0x00000000u, 0x0004002bu, 0x00000006u, + 0x0000001bu, 0x00000001u, 0x0004002bu, 0x00000006u, 0x00000022u, 0x00000002u, 0x0004001cu, 0x0000002eu, + 0x00000006u, 0x0000000au, 0x00040020u, 0x0000002fu, 0x00000004u, 0x0000002eu, 0x0004003bu, 0x0000002fu, + 0x00000030u, 0x00000004u, 0x00040020u, 0x00000034u, 0x00000004u, 0x00000006u, 0x0004002bu, 0x00000006u, + 0x00000036u, 0x00000108u, 0x0004002bu, 0x00000006u, 0x0000003eu, 0x00000100u, 0x00020014u, 0x0000003fu, + 0x00040017u, 0x00000059u, 0x00000006u, 0x00000003u, 0x0006002cu, 0x00000059u, 0x0000005au, 0x0000000au, + 0x0000001bu, 0x0000001bu, 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, + 0x00000005u, 0x0004003du, 0x00000006u, 0x00000013u, 0x00000012u, 0x00060041u, 0x00000014u, 0x00000015u, + 0x0000000eu, 0x00000010u, 0x00000013u, 0x0004003du, 0x00000007u, 0x00000016u, 0x00000015u, 0x00050051u, + 0x00000006u, 0x0000001au, 0x00000016u, 0x00000000u, 0x00050051u, 0x00000006u, 0x0000001du, 0x00000016u, + 0x00000001u, 0x00050080u, 0x00000006u, 0x0000001eu, 0x0000001du, 0x0000001au, 0x00060052u, 0x00000007u, + 0x0000005fu, 0x0000001eu, 0x00000016u, 0x00000001u, 0x00050051u, 0x00000006u, 0x00000024u, 0x00000016u, + 0x00000002u, 0x00050080u, 0x00000006u, 0x00000025u, 0x00000024u, 0x0000001eu, 0x00060052u, 0x00000007u, + 0x00000063u, 0x00000025u, 0x0000005fu, 0x00000002u, 0x00050051u, 0x00000006u, 0x0000002bu, 0x00000016u, + 0x00000003u, 0x00050080u, 0x00000006u, 0x0000002cu, 0x0000002bu, 0x00000025u, 0x00060052u, 0x00000007u, + 0x00000067u, 0x0000002cu, 0x00000063u, 0x00000003u, 0x00050041u, 0x00000034u, 0x00000035u, 0x00000030u, + 0x00000013u, 0x0003003eu, 0x00000035u, 0x0000002cu, 0x000400e0u, 0x00000022u, 0x00000022u, 0x00000036u, + 0x000200f9u, 0x00000038u, 0x000200f8u, 0x00000038u, 0x000700f5u, 0x00000007u, 0x0000006bu, 0x00000067u, + 0x00000005u, 0x0000004fu, 0x0000003bu, 0x000700f5u, 0x00000006u, 0x0000006au, 0x0000001bu, 0x00000005u, + 0x00000055u, 0x0000003bu, 0x000500b0u, 0x0000003fu, 0x00000040u, 0x0000006au, 0x0000003eu, 0x000400f6u, + 0x0000003au, 0x0000003bu, 0x00000000u, 0x000400fau, 0x00000040u, 0x00000039u, 0x0000003au, 0x000200f8u, + 0x00000039u, 0x000400e0u, 0x00000022u, 0x00000022u, 0x00000036u, 0x000500aeu, 0x0000003fu, 0x00000044u, + 0x00000013u, 0x0000006au, 0x000300f7u, 0x00000046u, 0x00000000u, 0x000400fau, 0x00000044u, 0x00000045u, + 0x00000046u, 0x000200f8u, 0x00000045u, 0x00050082u, 0x00000006u, 0x00000049u, 0x00000013u, 0x0000006au, + 0x00050041u, 0x00000034u, 0x0000004au, 0x00000030u, 0x00000049u, 0x0004003du, 0x00000006u, 0x0000004bu, + 0x0000004au, 0x000200f9u, 0x00000046u, 0x000200f8u, 0x00000046u, 0x000700f5u, 0x00000006u, 0x0000006cu, + 0x00000017u, 0x00000039u, 0x0000004bu, 0x00000045u, 0x000400e0u, 0x00000022u, 0x00000022u, 0x00000036u, + 0x00070050u, 0x00000007u, 0x0000004eu, 0x0000006cu, 0x0000006cu, 0x0000006cu, 0x0000006cu, 0x00050080u, + 0x00000007u, 0x0000004fu, 0x0000006bu, 0x0000004eu, 0x00050051u, 0x00000006u, 0x00000052u, 0x0000004fu, + 0x00000003u, 0x0003003eu, 0x00000035u, 0x00000052u, 0x000200f9u, 0x0000003bu, 0x000200f8u, 0x0000003bu, + 0x00050084u, 0x00000006u, 0x00000055u, 0x0000006au, 0x00000022u, 0x000200f9u, 0x00000038u, 0x000200f8u, + 0x0000003au, 0x0003003eu, 0x00000015u, 0x0000006bu, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, + 0x000d000bu, 0x000000c1u, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, 0x0000003du, 0x00020011u, + 0x0000003fu, 0x00020011u, 0x00000041u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, + 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0008000fu, 0x00000005u, 0x00000004u, 0x6e69616du, + 0x00000000u, 0x0000001fu, 0x00000062u, 0x000000a2u, 0x00060010u, 0x00000004u, 0x00000011u, 0x00000001u, + 0x00000001u, 0x00000001u, 0x00040047u, 0x0000000bu, 0x00000006u, 0x00000004u, 0x00050048u, 0x0000000cu, + 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x0000000cu, 0x00000001u, 0x00000023u, 0x00000004u, + 0x00040047u, 0x0000000du, 0x00000006u, 0x00000008u, 0x00030047u, 0x0000000eu, 0x00000002u, 0x00040048u, + 0x0000000eu, 0x00000000u, 0x00000018u, 0x00050048u, 0x0000000eu, 0x00000000u, 0x00000023u, 0x00000004u, + 0x00040048u, 0x0000000eu, 0x00000001u, 0x00000018u, 0x00050048u, 0x0000000eu, 0x00000001u, 0x00000023u, + 0x00000040u, 0x00040048u, 0x0000000eu, 0x00000002u, 0x00000018u, 0x00050048u, 0x0000000eu, 0x00000002u, + 0x00000023u, 0x00002040u, 0x00030047u, 0x00000010u, 0x00000018u, 0x00040047u, 0x00000010u, 0x00000021u, + 0x00000000u, 0x00040047u, 0x00000010u, 0x00000022u, 0x00000000u, 0x00030047u, 0x00000015u, 0x00000002u, + 0x00050048u, 0x00000015u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x00000015u, 0x00000001u, + 0x00000023u, 0x00000004u, 0x00040047u, 0x0000001fu, 0x0000000bu, 0x0000001au, 0x00030047u, 0x00000062u, + 0x00000000u, 0x00040047u, 0x00000062u, 0x0000000bu, 0x00000029u, 0x00030047u, 0x00000063u, 0x00000000u, + 0x00040047u, 0x00000098u, 0x00000006u, 0x00000004u, 0x00030047u, 0x00000099u, 0x00000002u, 0x00050048u, + 0x00000099u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00040047u, 0x0000009bu, 0x00000021u, 0x00000001u, + 0x00040047u, 0x0000009bu, 0x00000022u, 0x00000000u, 0x00030047u, 0x000000a2u, 0x00000000u, 0x00040047u, + 0x000000a2u, 0x0000000bu, 0x00000024u, 0x00030047u, 0x000000a3u, 0x00000000u, 0x00030047u, 0x000000a4u, + 0x00000000u, 0x00040047u, 0x000000abu, 0x00000001u, 0x00000000u, 0x00040047u, 0x000000acu, 0x0000000bu, + 0x00000019u, 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, + 0x00000020u, 0x00000001u, 0x00040015u, 0x00000009u, 0x00000020u, 0x00000000u, 0x0004002bu, 0x00000009u, + 0x0000000au, 0x00000800u, 0x0004001cu, 0x0000000bu, 0x00000006u, 0x0000000au, 0x0004001eu, 0x0000000cu, + 0x00000006u, 0x00000009u, 0x0003001du, 0x0000000du, 0x0000000cu, 0x0005001eu, 0x0000000eu, 0x00000006u, + 0x0000000bu, 0x0000000du, 0x00040020u, 0x0000000fu, 0x0000000cu, 0x0000000eu, 0x0004003bu, 0x0000000fu, + 0x00000010u, 0x0000000cu, 0x0004002bu, 0x00000006u, 0x00000011u, 0x00000000u, 0x00040020u, 0x00000012u, + 0x0000000cu, 0x00000006u, 0x0004001eu, 0x00000015u, 0x00000009u, 0x00000009u, 0x00040020u, 0x00000016u, + 0x00000009u, 0x00000015u, 0x0004003bu, 0x00000016u, 0x00000017u, 0x00000009u, 0x00040020u, 0x00000018u, + 0x00000009u, 0x00000009u, 0x00040017u, 0x0000001du, 0x00000009u, 0x00000003u, 0x00040020u, 0x0000001eu, + 0x00000001u, 0x0000001du, 0x0004003bu, 0x0000001eu, 0x0000001fu, 0x00000001u, 0x0004002bu, 0x00000009u, + 0x00000020u, 0x00000000u, 0x00040020u, 0x00000021u, 0x00000001u, 0x00000009u, 0x00020014u, 0x00000024u, + 0x0004002bu, 0x00000006u, 0x00000029u, 0x00000001u, 0x0004002bu, 0x00000009u, 0x0000002cu, 0x00000001u, + 0x0004003bu, 0x00000021u, 0x00000062u, 0x00000001u, 0x0004002bu, 0x00000006u, 0x0000006au, 0x00000002u, + 0x00040020u, 0x00000074u, 0x0000000cu, 0x0000000cu, 0x0004002bu, 0x00000006u, 0x0000007eu, 0x00000010u, + 0x0004002bu, 0x00000009u, 0x00000086u, 0x00000003u, 0x0003001du, 0x00000098u, 0x00000006u, 0x0003001eu, + 0x00000099u, 0x00000098u, 0x00040020u, 0x0000009au, 0x0000000cu, 0x00000099u, 0x0004003bu, 0x0000009au, + 0x0000009bu, 0x0000000cu, 0x0004003bu, 0x00000021u, 0x000000a2u, 0x00000001u, 0x00040032u, 0x00000009u, + 0x000000abu, 0x00000001u, 0x00060033u, 0x0000001du, 0x000000acu, 0x000000abu, 0x0000002cu, 0x0000002cu, + 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x000300f7u, + 0x000000adu, 0x00000000u, 0x000300fbu, 0x00000020u, 0x000000aeu, 0x000200f8u, 0x000000aeu, 0x00050041u, + 0x00000012u, 0x00000013u, 0x00000010u, 0x00000011u, 0x0004003du, 0x00000006u, 0x00000014u, 0x00000013u, + 0x00050041u, 0x00000018u, 0x00000019u, 0x00000017u, 0x00000011u, 0x0004003du, 0x00000009u, 0x0000001au, + 0x00000019u, 0x0004007cu, 0x00000006u, 0x0000001bu, 0x0000001au, 0x00050082u, 0x00000006u, 0x0000001cu, + 0x00000014u, 0x0000001bu, 0x00050041u, 0x00000021u, 0x00000022u, 0x0000001fu, 0x00000020u, 0x0004003du, + 0x00000009u, 0x00000023u, 0x00000022u, 0x000500abu, 0x00000024u, 0x00000025u, 0x00000023u, 0x00000020u, + 0x000300f7u, 0x00000027u, 0x00000000u, 0x000400fau, 0x00000025u, 0x00000026u, 0x0000003cu, 0x000200f8u, + 0x00000026u, 0x00050082u, 0x00000009u, 0x0000002du, 0x00000023u, 0x0000002cu, 0x00060041u, 0x00000012u, + 0x0000002eu, 0x00000010u, 0x00000029u, 0x0000002du, 0x0004003du, 0x00000006u, 0x0000002fu, 0x0000002eu, + 0x00060041u, 0x00000012u, 0x00000032u, 0x00000010u, 0x00000029u, 0x00000023u, 0x0004003du, 0x00000006u, + 0x00000033u, 0x00000032u, 0x000500aau, 0x00000024u, 0x00000035u, 0x00000033u, 0x0000002fu, 0x000300f7u, + 0x00000037u, 0x00000000u, 0x000400fau, 0x00000035u, 0x00000036u, 0x00000037u, 0x000200f8u, 0x00000036u, + 0x000200f9u, 0x000000adu, 0x000200f8u, 0x00000037u, 0x00050082u, 0x00000006u, 0x0000003bu, 0x0000001cu, + 0x0000002fu, 0x000200f9u, 0x00000027u, 0x000200f8u, 0x0000003cu, 0x00060041u, 0x00000012u, 0x0000003fu, + 0x00000010u, 0x00000029u, 0x00000023u, 0x0004003du, 0x00000006u, 0x00000040u, 0x0000003fu, 0x000500aau, + 0x00000024u, 0x00000041u, 0x00000040u, 0x00000011u, 0x000300f7u, 0x00000043u, 0x00000000u, 0x000400fau, + 0x00000041u, 0x00000042u, 0x00000043u, 0x000200f8u, 0x00000042u, 0x000200f9u, 0x000000adu, 0x000200f8u, + 0x00000043u, 0x000200f9u, 0x00000027u, 0x000200f8u, 0x00000027u, 0x000700f5u, 0x00000006u, 0x000000b6u, + 0x0000003bu, 0x00000037u, 0x0000001cu, 0x00000043u, 0x000500b3u, 0x00000024u, 0x00000046u, 0x000000b6u, + 0x00000011u, 0x000300f7u, 0x00000048u, 0x00000000u, 0x000400fau, 0x00000046u, 0x00000047u, 0x00000048u, + 0x000200f8u, 0x00000047u, 0x000200f9u, 0x000000adu, 0x000200f8u, 0x00000048u, 0x000200f9u, 0x0000004du, + 0x000200f8u, 0x0000004du, 0x000700f5u, 0x00000009u, 0x000000b8u, 0x00000020u, 0x00000048u, 0x000000a7u, + 0x00000050u, 0x000700f5u, 0x00000009u, 0x000000b7u, 0x00000020u, 0x00000048u, 0x000000aau, 0x00000050u, + 0x000400f6u, 0x0000004fu, 0x00000050u, 0x00000000u, 0x000200f9u, 0x00000051u, 0x000200f8u, 0x00000051u, + 0x00050041u, 0x00000018u, 0x00000053u, 0x00000017u, 0x00000029u, 0x0004003du, 0x00000009u, 0x00000054u, + 0x00000053u, 0x000500b0u, 0x00000024u, 0x00000055u, 0x000000b7u, 0x00000054u, 0x000300f7u, 0x00000057u, + 0x00000000u, 0x000400fau, 0x00000055u, 0x00000056u, 0x00000057u, 0x000200f8u, 0x00000056u, 0x0004007cu, + 0x00000009u, 0x0000005au, 0x000000b6u, 0x000500b0u, 0x00000024u, 0x0000005bu, 0x000000b8u, 0x0000005au, + 0x000200f9u, 0x00000057u, 0x000200f8u, 0x00000057u, 0x000700f5u, 0x00000024u, 0x0000005cu, 0x00000055u, + 0x00000051u, 0x0000005bu, 0x00000056u, 0x000400fau, 0x0000005cu, 0x0000004eu, 0x0000004fu, 0x000200f8u, + 0x0000004eu, 0x0004003du, 0x00000009u, 0x00000063u, 0x00000062u, 0x00050080u, 0x00000009u, 0x00000064u, + 0x000000b7u, 0x00000063u, 0x000500b0u, 0x00000024u, 0x00000067u, 0x00000064u, 0x00000054u, 0x000300f7u, + 0x00000069u, 0x00000000u, 0x000400fau, 0x00000067u, 0x00000068u, 0x00000069u, 0x000200f8u, 0x00000068u, + 0x00050084u, 0x00000009u, 0x0000006fu, 0x00000023u, 0x00000054u, 0x00050080u, 0x00000009u, 0x00000071u, + 0x0000006fu, 0x000000b7u, 0x00050080u, 0x00000009u, 0x00000073u, 0x00000071u, 0x00000063u, 0x00060041u, + 0x00000074u, 0x00000075u, 0x00000010u, 0x0000006au, 0x00000073u, 0x0004003du, 0x0000000cu, 0x00000076u, + 0x00000075u, 0x00050051u, 0x00000006u, 0x00000077u, 0x00000076u, 0x00000000u, 0x00050051u, 0x00000009u, + 0x00000079u, 0x00000076u, 0x00000001u, 0x000200f9u, 0x00000069u, 0x000200f8u, 0x00000069u, 0x000700f5u, + 0x00000006u, 0x000000c0u, 0x00000011u, 0x0000004eu, 0x00000077u, 0x00000068u, 0x000700f5u, 0x00000009u, + 0x000000bbu, 0x00000020u, 0x0000004eu, 0x00000079u, 0x00000068u, 0x000600cbu, 0x00000009u, 0x0000007fu, + 0x000000bbu, 0x0000007eu, 0x0000007eu, 0x000600cbu, 0x00000009u, 0x00000083u, 0x000000bbu, 0x00000011u, + 0x0000007eu, 0x0006015du, 0x00000009u, 0x00000087u, 0x00000086u, 0x00000001u, 0x0000007fu, 0x00050080u, + 0x00000009u, 0x0000008cu, 0x000000b8u, 0x00000087u, 0x00050082u, 0x00000009u, 0x0000008eu, 0x0000008cu, + 0x0000007fu, 0x0004007cu, 0x00000009u, 0x00000090u, 0x000000b6u, 0x000500b0u, 0x00000024u, 0x00000091u, + 0x0000008eu, 0x00000090u, 0x000500abu, 0x00000024u, 0x00000094u, 0x0000007fu, 0x00000020u, 0x000500a7u, + 0x00000024u, 0x00000095u, 0x00000091u, 0x00000094u, 0x000300f7u, 0x00000097u, 0x00000000u, 0x000400fau, + 0x00000095u, 0x00000096u, 0x00000097u, 0x000200f8u, 0x00000096u, 0x00060041u, 0x00000012u, 0x0000009du, + 0x0000009bu, 0x00000011u, 0x00000083u, 0x000700eeu, 0x00000006u, 0x000000a0u, 0x0000009du, 0x0000002cu, + 0x00000020u, 0x000000c0u, 0x000200f9u, 0x00000097u, 0x000200f8u, 0x00000097u, 0x0004003du, 0x00000009u, + 0x000000a3u, 0x000000a2u, 0x00050082u, 0x00000009u, 0x000000a4u, 0x000000a3u, 0x0000002cu, 0x00060159u, + 0x00000009u, 0x000000a5u, 0x00000086u, 0x00000087u, 0x000000a4u, 0x00050080u, 0x00000009u, 0x000000a7u, + 0x000000b8u, 0x000000a5u, 0x000200f9u, 0x00000050u, 0x000200f8u, 0x00000050u, 0x00050080u, 0x00000009u, + 0x000000aau, 0x000000b7u, 0x000000a3u, 0x000200f9u, 0x0000004du, 0x000200f8u, 0x0000004fu, 0x000200f9u, + 0x000000adu, 0x000200f8u, 0x000000adu, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, + 0x00000864u, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, 0x00000009u, 0x00020011u, 0x00000016u, + 0x00020011u, 0x0000003du, 0x00020011u, 0x00000041u, 0x00020011u, 0x00000042u, 0x00020011u, 0x00000043u, + 0x00020011u, 0x00001151u, 0x00020011u, 0x00001160u, 0x0007000au, 0x5f565053u, 0x5f52484bu, 0x74696238u, + 0x6f74735fu, 0x65676172u, 0x00000000u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, + 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x0009000fu, 0x00000005u, 0x00000004u, 0x6e69616du, + 0x00000000u, 0x0000008cu, 0x00000370u, 0x00000372u, 0x00000388u, 0x00060010u, 0x00000004u, 0x00000011u, + 0x00000080u, 0x00000001u, 0x00000001u, 0x00030047u, 0x0000008cu, 0x00000000u, 0x00040047u, 0x0000008cu, + 0x0000000bu, 0x00000029u, 0x00040047u, 0x0000009cu, 0x00000001u, 0x00000001u, 0x00030047u, 0x00000149u, + 0x00000002u, 0x00050048u, 0x00000149u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x00000149u, + 0x00000001u, 0x00000023u, 0x00000008u, 0x00050048u, 0x00000149u, 0x00000002u, 0x00000023u, 0x00000010u, + 0x00050048u, 0x00000149u, 0x00000003u, 0x00000023u, 0x00000018u, 0x00050048u, 0x00000149u, 0x00000004u, + 0x00000023u, 0x0000001cu, 0x00050048u, 0x00000149u, 0x00000005u, 0x00000023u, 0x00000020u, 0x00050048u, + 0x00000149u, 0x00000006u, 0x00000023u, 0x00000024u, 0x00050048u, 0x00000149u, 0x00000007u, 0x00000023u, + 0x00000028u, 0x00050048u, 0x000001eau, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x000001eau, + 0x00000001u, 0x00000023u, 0x00000004u, 0x00040047u, 0x000001ebu, 0x00000006u, 0x00000008u, 0x00030047u, + 0x000001ecu, 0x00000002u, 0x00040048u, 0x000001ecu, 0x00000000u, 0x00000019u, 0x00050048u, 0x000001ecu, + 0x00000000u, 0x00000023u, 0x00000000u, 0x00030047u, 0x000001eeu, 0x00000019u, 0x00040047u, 0x000001eeu, + 0x00000021u, 0x00000001u, 0x00040047u, 0x000001eeu, 0x00000022u, 0x00000000u, 0x00050048u, 0x000001fbu, + 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x000001fbu, 0x00000001u, 0x00000023u, 0x00000002u, + 0x00040047u, 0x000001fdu, 0x00000006u, 0x00000004u, 0x00050048u, 0x000001feu, 0x00000000u, 0x00000023u, + 0x00000000u, 0x00050048u, 0x000001feu, 0x00000001u, 0x00000023u, 0x00000004u, 0x00040047u, 0x000001ffu, + 0x00000006u, 0x00000040u, 0x00030047u, 0x00000200u, 0x00000002u, 0x00040048u, 0x00000200u, 0x00000000u, + 0x00000019u, 0x00050048u, 0x00000200u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00030047u, 0x00000202u, + 0x00000019u, 0x00040047u, 0x00000202u, 0x00000021u, 0x00000002u, 0x00040047u, 0x00000202u, 0x00000022u, + 0x00000000u, 0x00040047u, 0x0000022du, 0x00000006u, 0x00000001u, 0x00030047u, 0x0000022eu, 0x00000002u, + 0x00050048u, 0x0000022eu, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x0000022eu, 0x00000001u, + 0x00000023u, 0x00000008u, 0x00040047u, 0x00000230u, 0x00000021u, 0x00000003u, 0x00040047u, 0x00000230u, + 0x00000022u, 0x00000000u, 0x00040047u, 0x00000370u, 0x0000000bu, 0x00000028u, 0x00030047u, 0x00000372u, + 0x00000000u, 0x00040047u, 0x00000372u, 0x0000000bu, 0x00000024u, 0x00030047u, 0x00000373u, 0x00000000u, + 0x00030047u, 0x00000375u, 0x00000000u, 0x00040047u, 0x00000388u, 0x0000000bu, 0x0000001au, 0x00040047u, + 0x000003bau, 0x00000021u, 0x00000000u, 0x00040047u, 0x000003bau, 0x00000022u, 0x00000000u, 0x00030047u, + 0x000003cau, 0x0000002au, 0x00030047u, 0x000003cfu, 0x0000002au, 0x00040047u, 0x000003edu, 0x0000000bu, + 0x00000019u, 0x00030047u, 0x0000044du, 0x0000002au, 0x00030047u, 0x00000450u, 0x0000002au, 0x00030047u, + 0x00000453u, 0x0000002au, 0x00030047u, 0x00000479u, 0x00000000u, 0x00030047u, 0x00000497u, 0x00000000u, + 0x00030047u, 0x000004a1u, 0x00000000u, 0x00030047u, 0x000004b7u, 0x00000000u, 0x00030047u, 0x000006d3u, + 0x00000000u, 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, + 0x00000020u, 0x00000000u, 0x00030016u, 0x00000008u, 0x00000020u, 0x00040020u, 0x0000000du, 0x00000007u, + 0x00000008u, 0x00040015u, 0x00000012u, 0x00000020u, 0x00000001u, 0x00040017u, 0x00000013u, 0x00000012u, + 0x00000002u, 0x00040017u, 0x00000018u, 0x00000008u, 0x00000004u, 0x00040020u, 0x00000019u, 0x00000007u, + 0x00000018u, 0x00040018u, 0x00000029u, 0x00000018u, 0x00000002u, 0x00040020u, 0x0000002au, 0x00000007u, + 0x00000029u, 0x0004002bu, 0x00000008u, 0x00000042u, 0x41000000u, 0x0004002bu, 0x00000008u, 0x00000044u, + 0x3e800000u, 0x0004002bu, 0x00000012u, 0x00000051u, 0x00000000u, 0x0004002bu, 0x00000012u, 0x00000052u, + 0x00000001u, 0x0004002bu, 0x00000012u, 0x00000056u, 0x00000002u, 0x0004002bu, 0x00000012u, 0x00000059u, + 0x00000003u, 0x0004002bu, 0x00000012u, 0x0000005fu, 0x00000005u, 0x00040017u, 0x0000006bu, 0x00000008u, + 0x00000002u, 0x0004002bu, 0x00000006u, 0x00000073u, 0x00000000u, 0x0004002bu, 0x00000006u, 0x00000076u, + 0x00000001u, 0x0004002bu, 0x00000006u, 0x00000083u, 0x00000008u, 0x00020014u, 0x00000084u, 0x0004002bu, + 0x00000006u, 0x00000089u, 0x00000003u, 0x00040020u, 0x0000008bu, 0x00000001u, 0x00000006u, 0x0004003bu, + 0x0000008bu, 0x0000008cu, 0x00000001u, 0x0004002bu, 0x00000006u, 0x0000008eu, 0x00000007u, 0x0004002bu, + 0x00000006u, 0x00000096u, 0x00000002u, 0x00030031u, 0x00000084u, 0x0000009cu, 0x0004002bu, 0x00000008u, + 0x0000009eu, 0x3f800000u, 0x0004002bu, 0x00000006u, 0x000000a3u, 0x00000006u, 0x0004001eu, 0x000000a8u, + 0x00000008u, 0x00000012u, 0x0004002bu, 0x00000008u, 0x000000c2u, 0x00000000u, 0x00040017u, 0x000000d3u, + 0x00000012u, 0x00000004u, 0x0004002bu, 0x00000012u, 0x000000f8u, 0x00000004u, 0x0007002cu, 0x00000018u, + 0x00000107u, 0x000000c2u, 0x000000c2u, 0x000000c2u, 0x000000c2u, 0x0004002bu, 0x00000008u, 0x00000108u, + 0x3f000000u, 0x0007002cu, 0x00000018u, 0x00000109u, 0x00000108u, 0x00000108u, 0x00000108u, 0x00000108u, + 0x00040017u, 0x0000010cu, 0x00000084u, 0x00000004u, 0x000a001eu, 0x00000149u, 0x00000013u, 0x00000013u, + 0x0000006bu, 0x00000008u, 0x00000008u, 0x00000012u, 0x00000012u, 0x00000008u, 0x00040020u, 0x0000014au, + 0x00000009u, 0x00000149u, 0x0004003bu, 0x0000014au, 0x0000014bu, 0x00000009u, 0x0004002bu, 0x00000012u, + 0x0000014cu, 0x00000007u, 0x00040020u, 0x0000014du, 0x00000009u, 0x00000008u, 0x0004002bu, 0x00000012u, + 0x00000186u, 0x00000008u, 0x00040020u, 0x000001d3u, 0x00000009u, 0x00000012u, 0x0004002bu, 0x00000012u, + 0x000001d8u, 0x00000006u, 0x0004001eu, 0x000001eau, 0x00000006u, 0x00000006u, 0x0003001du, 0x000001ebu, + 0x000001eau, 0x0003001eu, 0x000001ecu, 0x000001ebu, 0x00040020u, 0x000001edu, 0x0000000cu, 0x000001ecu, + 0x0004003bu, 0x000001edu, 0x000001eeu, 0x0000000cu, 0x00040020u, 0x000001f5u, 0x0000000cu, 0x00000006u, + 0x00030016u, 0x000001f9u, 0x00000010u, 0x00040015u, 0x000001fau, 0x00000010u, 0x00000000u, 0x0004001eu, + 0x000001fbu, 0x000001f9u, 0x000001fau, 0x0004002bu, 0x00000006u, 0x000001fcu, 0x0000000fu, 0x0004001cu, + 0x000001fdu, 0x000001fbu, 0x000001fcu, 0x0004001eu, 0x000001feu, 0x00000006u, 0x000001fdu, 0x0003001du, + 0x000001ffu, 0x000001feu, 0x0003001eu, 0x00000200u, 0x000001ffu, 0x00040020u, 0x00000201u, 0x0000000cu, + 0x00000200u, 0x0004003bu, 0x00000201u, 0x00000202u, 0x0000000cu, 0x0004002bu, 0x000001f9u, 0x00000207u, + 0x00000000u, 0x0004002bu, 0x000001fau, 0x00000208u, 0x00000000u, 0x00040020u, 0x0000020du, 0x0000000cu, + 0x000001f9u, 0x00040020u, 0x00000210u, 0x0000000cu, 0x000001fau, 0x00040015u, 0x0000022cu, 0x00000008u, + 0x00000000u, 0x0003001du, 0x0000022du, 0x0000022cu, 0x0004001eu, 0x0000022eu, 0x00000006u, 0x0000022du, + 0x00040020u, 0x0000022fu, 0x0000000cu, 0x0000022eu, 0x0004003bu, 0x0000022fu, 0x00000230u, 0x0000000cu, + 0x0004002bu, 0x00000012u, 0x00000242u, 0x00000010u, 0x0004002bu, 0x00000012u, 0x00000247u, 0x00000014u, + 0x0004002bu, 0x00000006u, 0x0000025eu, 0x00000004u, 0x00040015u, 0x0000027bu, 0x00000010u, 0x00000001u, + 0x0004002bu, 0x00000008u, 0x000002a5u, 0x476a6000u, 0x00040017u, 0x000002e4u, 0x00000006u, 0x00000004u, + 0x0007002cu, 0x000002e4u, 0x000002eau, 0x00000073u, 0x00000073u, 0x00000073u, 0x00000073u, 0x0007002cu, + 0x000002e4u, 0x000002edu, 0x00000073u, 0x00000076u, 0x00000096u, 0x00000089u, 0x0004002bu, 0x00000006u, + 0x000002f4u, 0x00000005u, 0x0007002cu, 0x000002e4u, 0x000002f5u, 0x0000025eu, 0x000002f4u, 0x000000a3u, + 0x0000008eu, 0x00040020u, 0x00000313u, 0x0000000cu, 0x0000022cu, 0x0004003bu, 0x0000008bu, 0x00000370u, + 0x00000001u, 0x0004003bu, 0x0000008bu, 0x00000372u, 0x00000001u, 0x00040017u, 0x00000386u, 0x00000006u, + 0x00000003u, 0x00040020u, 0x00000387u, 0x00000001u, 0x00000386u, 0x0004003bu, 0x00000387u, 0x00000388u, + 0x00000001u, 0x00040017u, 0x00000389u, 0x00000006u, 0x00000002u, 0x0004002bu, 0x00000012u, 0x0000038du, + 0x00000020u, 0x00040017u, 0x000003a8u, 0x00000008u, 0x00000003u, 0x00040020u, 0x000003adu, 0x00000009u, + 0x0000006bu, 0x00090019u, 0x000003b7u, 0x00000008u, 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, + 0x00000001u, 0x00000000u, 0x0003001bu, 0x000003b8u, 0x000003b7u, 0x00040020u, 0x000003b9u, 0x00000000u, + 0x000003b8u, 0x0004003bu, 0x000003b9u, 0x000003bau, 0x00000000u, 0x0005002cu, 0x00000013u, 0x000003bdu, + 0x00000052u, 0x00000052u, 0x0005002cu, 0x00000013u, 0x000003c3u, 0x00000059u, 0x00000052u, 0x00040020u, + 0x000003d2u, 0x00000009u, 0x00000013u, 0x00040017u, 0x000003d5u, 0x00000084u, 0x00000002u, 0x0004002bu, + 0x00000006u, 0x000003ecu, 0x00000080u, 0x0006002cu, 0x00000386u, 0x000003edu, 0x000003ecu, 0x00000076u, + 0x00000076u, 0x0005002cu, 0x00000013u, 0x00000850u, 0x0000038du, 0x0000038du, 0x0005002cu, 0x00000013u, + 0x00000851u, 0x00000186u, 0x00000186u, 0x0005002cu, 0x00000013u, 0x00000852u, 0x000000f8u, 0x000000f8u, + 0x0007002cu, 0x000000d3u, 0x00000853u, 0x00000051u, 0x00000051u, 0x00000051u, 0x00000051u, 0x0004002bu, + 0x00000008u, 0x00000858u, 0x3e000000u, 0x0004002bu, 0x00000012u, 0x0000085au, 0xffffffffu, 0x0007002cu, + 0x000002e4u, 0x0000085du, 0x00000076u, 0x00000096u, 0x0000025eu, 0x00000083u, 0x0004002bu, 0x00000006u, + 0x00000860u, 0x00000010u, 0x0004002bu, 0x00000006u, 0x00000861u, 0x00000020u, 0x0004002bu, 0x00000006u, + 0x00000862u, 0x00000040u, 0x0007002cu, 0x000002e4u, 0x00000863u, 0x00000860u, 0x00000861u, 0x00000862u, + 0x000003ecu, 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, + 0x0004003bu, 0x0000002au, 0x0000071eu, 0x00000007u, 0x0004003bu, 0x0000002au, 0x0000063bu, 0x00000007u, + 0x0004003du, 0x00000006u, 0x00000371u, 0x00000370u, 0x0004003du, 0x00000006u, 0x00000373u, 0x00000372u, + 0x00050084u, 0x00000006u, 0x00000374u, 0x00000371u, 0x00000373u, 0x0004003du, 0x00000006u, 0x00000375u, + 0x0000008cu, 0x00050080u, 0x00000006u, 0x00000376u, 0x00000374u, 0x00000375u, 0x000600cbu, 0x00000006u, + 0x00000379u, 0x00000376u, 0x00000051u, 0x00000059u, 0x000600cbu, 0x00000006u, 0x0000037cu, 0x00000376u, + 0x00000059u, 0x00000056u, 0x000600cbu, 0x00000006u, 0x0000037fu, 0x00000376u, 0x0000005fu, 0x00000056u, + 0x000500c4u, 0x00000006u, 0x00000382u, 0x00000379u, 0x00000059u, 0x000600cbu, 0x00000006u, 0x000003f8u, + 0x00000382u, 0x00000051u, 0x00000052u, 0x000600cbu, 0x00000006u, 0x000003fau, 0x00000382u, 0x00000052u, + 0x00000056u, 0x000600cbu, 0x00000006u, 0x000003fcu, 0x00000382u, 0x00000059u, 0x00000056u, 0x000500c4u, + 0x00000006u, 0x000003fdu, 0x000003fcu, 0x00000052u, 0x000500c5u, 0x00000006u, 0x000003ffu, 0x000003f8u, + 0x000003fdu, 0x000600cbu, 0x00000006u, 0x00000401u, 0x00000382u, 0x0000005fu, 0x00000052u, 0x000500c4u, + 0x00000006u, 0x00000402u, 0x00000401u, 0x00000056u, 0x000500c5u, 0x00000006u, 0x00000404u, 0x000003fau, + 0x00000402u, 0x0004007cu, 0x00000012u, 0x00000406u, 0x00000404u, 0x0004007cu, 0x00000012u, 0x00000408u, + 0x000003ffu, 0x00050050u, 0x00000013u, 0x00000409u, 0x00000406u, 0x00000408u, 0x0004003du, 0x00000386u, + 0x0000038au, 0x00000388u, 0x0007004fu, 0x00000389u, 0x0000038bu, 0x0000038au, 0x0000038au, 0x00000000u, + 0x00000001u, 0x0004007cu, 0x00000013u, 0x0000038cu, 0x0000038bu, 0x00050084u, 0x00000013u, 0x0000038fu, + 0x0000038cu, 0x00000850u, 0x0004007cu, 0x00000012u, 0x00000391u, 0x0000037cu, 0x0004007cu, 0x00000012u, + 0x00000393u, 0x0000037fu, 0x00050050u, 0x00000013u, 0x00000394u, 0x00000391u, 0x00000393u, 0x00050084u, + 0x00000013u, 0x00000396u, 0x00000851u, 0x00000394u, 0x00050080u, 0x00000013u, 0x00000398u, 0x0000038fu, + 0x00000396u, 0x00050080u, 0x00000013u, 0x0000039bu, 0x00000398u, 0x00000409u, 0x00050084u, 0x00000013u, + 0x000003a1u, 0x00000852u, 0x0000038cu, 0x00050080u, 0x00000013u, 0x000003a7u, 0x000003a1u, 0x00000394u, + 0x0004006fu, 0x0000006bu, 0x000003acu, 0x0000039bu, 0x00050041u, 0x000003adu, 0x000003aeu, 0x0000014bu, + 0x00000056u, 0x0004003du, 0x0000006bu, 0x000003afu, 0x000003aeu, 0x00050085u, 0x0000006bu, 0x000003b0u, + 0x000003acu, 0x000003afu, 0x00050041u, 0x0000014du, 0x000003b1u, 0x0000014bu, 0x00000059u, 0x0004003du, + 0x00000008u, 0x000003b2u, 0x000003b1u, 0x00050051u, 0x00000008u, 0x000003b3u, 0x000003b0u, 0x00000000u, + 0x00050051u, 0x00000008u, 0x000003b4u, 0x000003b0u, 0x00000001u, 0x00060050u, 0x000003a8u, 0x000003b5u, + 0x000003b3u, 0x000003b4u, 0x000003b2u, 0x0004003du, 0x000003b8u, 0x000003bbu, 0x000003bau, 0x00080060u, + 0x00000018u, 0x000003beu, 0x000003bbu, 0x000003b5u, 0x00000051u, 0x00000008u, 0x000003bdu, 0x0009004fu, + 0x00000018u, 0x000003bfu, 0x000003beu, 0x000003beu, 0x00000003u, 0x00000000u, 0x00000002u, 0x00000001u, + 0x0004003du, 0x000003b8u, 0x000003c1u, 0x000003bau, 0x00080060u, 0x00000018u, 0x000003c4u, 0x000003c1u, + 0x000003b5u, 0x00000051u, 0x00000008u, 0x000003c3u, 0x0009004fu, 0x00000018u, 0x000003c5u, 0x000003c4u, + 0x000003c4u, 0x00000003u, 0x00000000u, 0x00000002u, 0x00000001u, 0x00050041u, 0x0000014du, 0x000003c8u, + 0x0000014bu, 0x000000f8u, 0x0004003du, 0x00000008u, 0x000003c9u, 0x000003c8u, 0x0005008eu, 0x00000018u, + 0x000003cau, 0x000003bfu, 0x000003c9u, 0x0005008eu, 0x00000018u, 0x000003cfu, 0x000003c5u, 0x000003c9u, + 0x00050041u, 0x000003d2u, 0x000003d3u, 0x0000014bu, 0x00000052u, 0x0004003du, 0x00000013u, 0x000003d4u, + 0x000003d3u, 0x000500b1u, 0x000003d5u, 0x000003d6u, 0x000003a7u, 0x000003d4u, 0x0004009bu, 0x00000084u, + 0x000003d7u, 0x000003d6u, 0x000300f7u, 0x000003dau, 0x00000000u, 0x000400fau, 0x000003d7u, 0x000003d9u, + 0x000003dau, 0x000200f8u, 0x000003d9u, 0x00050050u, 0x00000029u, 0x000003e7u, 0x000003cau, 0x000003cfu, + 0x000300f7u, 0x000005b7u, 0x00000000u, 0x000300fbu, 0x00000073u, 0x0000043bu, 0x000200f8u, 0x0000043bu, + 0x0006000cu, 0x00000018u, 0x0000043eu, 0x00000001u, 0x00000004u, 0x000003cau, 0x0007004fu, 0x0000006bu, + 0x000005bcu, 0x0000043eu, 0x0000043eu, 0x00000000u, 0x00000001u, 0x0007004fu, 0x0000006bu, 0x000005beu, + 0x0000043eu, 0x0000043eu, 0x00000002u, 0x00000003u, 0x0007000cu, 0x0000006bu, 0x000005bfu, 0x00000001u, + 0x00000028u, 0x000005bcu, 0x000005beu, 0x00050051u, 0x00000008u, 0x000005c1u, 0x000005bfu, 0x00000000u, + 0x00050051u, 0x00000008u, 0x000005c3u, 0x000005bfu, 0x00000001u, 0x0007000cu, 0x00000008u, 0x000005c4u, + 0x00000001u, 0x00000028u, 0x000005c1u, 0x000005c3u, 0x0006000cu, 0x00000018u, 0x00000442u, 0x00000001u, + 0x00000004u, 0x000003cfu, 0x0007004fu, 0x0000006bu, 0x000005c9u, 0x00000442u, 0x00000442u, 0x00000000u, + 0x00000001u, 0x0007004fu, 0x0000006bu, 0x000005cbu, 0x00000442u, 0x00000442u, 0x00000002u, 0x00000003u, + 0x0007000cu, 0x0000006bu, 0x000005ccu, 0x00000001u, 0x00000028u, 0x000005c9u, 0x000005cbu, 0x00050051u, + 0x00000008u, 0x000005ceu, 0x000005ccu, 0x00000000u, 0x00050051u, 0x00000008u, 0x000005d0u, 0x000005ccu, + 0x00000001u, 0x0007000cu, 0x00000008u, 0x000005d1u, 0x00000001u, 0x00000028u, 0x000005ceu, 0x000005d0u, + 0x0007000cu, 0x00000008u, 0x00000444u, 0x00000001u, 0x00000028u, 0x000005c4u, 0x000005d1u, 0x00070166u, + 0x00000008u, 0x00000446u, 0x00000089u, 0x00000003u, 0x00000444u, 0x00000083u, 0x000500b8u, 0x00000084u, + 0x000005d9u, 0x00000446u, 0x0000009eu, 0x000500a6u, 0x00000084u, 0x000005dau, 0x0000009cu, 0x000005d9u, + 0x000300f7u, 0x000005eeu, 0x00000000u, 0x000400fau, 0x000005dau, 0x000005dbu, 0x000005dcu, 0x000200f8u, + 0x000005dbu, 0x000200f9u, 0x000005eeu, 0x000200f8u, 0x000005dcu, 0x00050083u, 0x00000008u, 0x000005deu, + 0x00000446u, 0x00000044u, 0x0006000cu, 0x000000a8u, 0x000005dfu, 0x00000001u, 0x00000034u, 0x000005deu, + 0x00050051u, 0x00000012u, 0x000005e0u, 0x000005dfu, 0x00000001u, 0x000500c4u, 0x00000012u, 0x000005e3u, + 0x00000052u, 0x000005e0u, 0x0004006fu, 0x00000008u, 0x000005e4u, 0x000005e3u, 0x00050083u, 0x00000008u, + 0x000005e5u, 0x000005e4u, 0x00000044u, 0x00050088u, 0x00000008u, 0x000005e8u, 0x00000446u, 0x000005e5u, + 0x00050083u, 0x00000008u, 0x000005f2u, 0x000005e8u, 0x00000044u, 0x00050085u, 0x00000008u, 0x000005f3u, + 0x000005f2u, 0x00000042u, 0x0006000cu, 0x00000008u, 0x000005f4u, 0x00000001u, 0x00000009u, 0x000005f3u, + 0x0004006du, 0x00000006u, 0x000005f5u, 0x000005f4u, 0x00040070u, 0x00000008u, 0x000005f9u, 0x000005f5u, + 0x00050085u, 0x00000008u, 0x000005fau, 0x000005f9u, 0x00000858u, 0x00050081u, 0x00000008u, 0x000005fbu, + 0x000005fau, 0x00000044u, 0x00050088u, 0x00000008u, 0x000005edu, 0x0000009eu, 0x000005fbu, 0x000200f9u, + 0x000005eeu, 0x000200f8u, 0x000005eeu, 0x000700f5u, 0x00000008u, 0x00000806u, 0x0000009eu, 0x000005dbu, + 0x000005edu, 0x000005dcu, 0x000700f5u, 0x00000006u, 0x00000805u, 0x000000a3u, 0x000005dbu, 0x000005f5u, + 0x000005dcu, 0x0005008fu, 0x00000029u, 0x0000044du, 0x000003e7u, 0x00000806u, 0x00050085u, 0x00000008u, + 0x00000450u, 0x00000446u, 0x00000806u, 0x00050085u, 0x00000008u, 0x00000453u, 0x00000444u, 0x00000806u, + 0x00050085u, 0x00000008u, 0x00000457u, 0x000003c9u, 0x00000806u, 0x00050085u, 0x00000008u, 0x00000859u, + 0x00000457u, 0x00000457u, 0x00050088u, 0x00000008u, 0x0000045cu, 0x0000009eu, 0x00000859u, 0x00050051u, + 0x00000018u, 0x0000045eu, 0x0000044du, 0x00000000u, 0x0004006eu, 0x000000d3u, 0x0000045fu, 0x0000045eu, + 0x0006000cu, 0x000000d3u, 0x00000460u, 0x00000001u, 0x00000005u, 0x0000045fu, 0x00050051u, 0x00000018u, + 0x00000462u, 0x0000044du, 0x00000001u, 0x0004006eu, 0x000000d3u, 0x00000463u, 0x00000462u, 0x0006000cu, + 0x000000d3u, 0x00000464u, 0x00000001u, 0x00000005u, 0x00000463u, 0x0004006eu, 0x00000012u, 0x00000466u, + 0x00000450u, 0x0004006eu, 0x00000012u, 0x00000468u, 0x00000453u, 0x00050041u, 0x000001d3u, 0x00000469u, + 0x0000014bu, 0x0000005fu, 0x0004003du, 0x00000012u, 0x0000046au, 0x00000469u, 0x00050051u, 0x00000012u, + 0x0000046cu, 0x000003a7u, 0x00000001u, 0x00050041u, 0x000001d3u, 0x0000046du, 0x0000014bu, 0x000001d8u, + 0x0004003du, 0x00000012u, 0x0000046eu, 0x0000046du, 0x00050084u, 0x00000012u, 0x0000046fu, 0x0000046cu, + 0x0000046eu, 0x00050080u, 0x00000012u, 0x00000470u, 0x0000046au, 0x0000046fu, 0x00050051u, 0x00000012u, + 0x00000472u, 0x000003a7u, 0x00000000u, 0x00050080u, 0x00000012u, 0x00000473u, 0x00000470u, 0x00000472u, + 0x0004007cu, 0x00000006u, 0x00000474u, 0x00000473u, 0x000500aau, 0x00000084u, 0x00000476u, 0x00000466u, + 0x00000051u, 0x000300f7u, 0x0000048bu, 0x00000000u, 0x000400fau, 0x00000476u, 0x00000477u, 0x0000048bu, + 0x000200f8u, 0x00000477u, 0x000500c7u, 0x00000006u, 0x00000479u, 0x00000375u, 0x0000008eu, 0x000500aau, + 0x00000084u, 0x0000047au, 0x00000479u, 0x00000073u, 0x000300f7u, 0x0000048au, 0x00000000u, 0x000400fau, + 0x0000047au, 0x0000047bu, 0x0000048au, 0x000200f8u, 0x0000047bu, 0x00070041u, 0x000001f5u, 0x0000047fu, + 0x000001eeu, 0x00000051u, 0x00000474u, 0x00000051u, 0x0003003eu, 0x0000047fu, 0x00000073u, 0x00070041u, + 0x000001f5u, 0x00000481u, 0x000001eeu, 0x00000051u, 0x00000474u, 0x00000052u, 0x0003003eu, 0x00000481u, + 0x00000073u, 0x00070041u, 0x000001f5u, 0x00000483u, 0x00000202u, 0x00000051u, 0x00000474u, 0x00000051u, + 0x0003003eu, 0x00000483u, 0x00000073u, 0x00090041u, 0x0000020du, 0x00000487u, 0x00000202u, 0x00000051u, + 0x00000474u, 0x00000052u, 0x00000051u, 0x00000051u, 0x0003003eu, 0x00000487u, 0x00000207u, 0x00090041u, + 0x00000210u, 0x00000489u, 0x00000202u, 0x00000051u, 0x00000474u, 0x00000052u, 0x00000051u, 0x00000052u, + 0x0003003eu, 0x00000489u, 0x00000208u, 0x000200f9u, 0x0000048au, 0x000200f8u, 0x0000048au, 0x000200f9u, + 0x000005b7u, 0x000200f8u, 0x0000048bu, 0x0006000cu, 0x00000012u, 0x0000048du, 0x00000001u, 0x0000004au, + 0x00000466u, 0x0006000cu, 0x00000018u, 0x00000643u, 0x00000001u, 0x00000004u, 0x0000045eu, 0x0006000cu, + 0x00000018u, 0x00000646u, 0x00000001u, 0x00000004u, 0x00000462u, 0x0007000cu, 0x00000018u, 0x00000657u, + 0x00000001u, 0x00000035u, 0x00000643u, 0x00000853u, 0x0006000cu, 0x00000018u, 0x00000658u, 0x00000001u, + 0x00000008u, 0x00000657u, 0x0007000cu, 0x00000018u, 0x0000065eu, 0x00000001u, 0x00000035u, 0x00000646u, + 0x00000853u, 0x0006000cu, 0x00000018u, 0x0000065fu, 0x00000001u, 0x00000003u, 0x0000065eu, 0x00050050u, + 0x00000029u, 0x0000066au, 0x00000658u, 0x0000065fu, 0x0003003eu, 0x0000063bu, 0x0000066au, 0x000200f9u, + 0x0000066bu, 0x000200f8u, 0x0000066bu, 0x000700f5u, 0x00000006u, 0x0000080bu, 0x00000073u, 0x0000048bu, + 0x00000833u, 0x00000682u, 0x000700f5u, 0x00000012u, 0x0000080au, 0x00000051u, 0x0000048bu, 0x00000684u, + 0x00000682u, 0x000500b1u, 0x00000084u, 0x0000066eu, 0x0000080au, 0x00000056u, 0x000400f6u, 0x00000685u, + 0x00000682u, 0x00000000u, 0x000400fau, 0x0000066eu, 0x0000066fu, 0x00000685u, 0x000200f8u, 0x0000066fu, + 0x000200f9u, 0x00000670u, 0x000200f8u, 0x00000670u, 0x000700f5u, 0x00000006u, 0x00000833u, 0x0000080bu, + 0x0000066fu, 0x0000084fu, 0x0000067eu, 0x000700f5u, 0x00000012u, 0x00000831u, 0x00000051u, 0x0000066fu, + 0x00000680u, 0x0000067eu, 0x000500b1u, 0x00000084u, 0x00000673u, 0x00000831u, 0x000000f8u, 0x000400f6u, + 0x00000681u, 0x0000067eu, 0x00000000u, 0x000400fau, 0x00000673u, 0x00000674u, 0x00000681u, 0x000200f8u, + 0x00000674u, 0x00060041u, 0x0000000du, 0x00000677u, 0x0000063bu, 0x0000080au, 0x00000831u, 0x0004003du, + 0x00000008u, 0x00000678u, 0x00000677u, 0x000500b7u, 0x00000084u, 0x00000679u, 0x00000678u, 0x000000c2u, + 0x000300f7u, 0x0000067du, 0x00000000u, 0x000400fau, 0x00000679u, 0x0000067au, 0x0000067du, 0x000200f8u, + 0x0000067au, 0x00050080u, 0x00000006u, 0x0000067cu, 0x00000833u, 0x00000052u, 0x000200f9u, 0x0000067du, + 0x000200f8u, 0x0000067du, 0x000700f5u, 0x00000006u, 0x0000084fu, 0x00000833u, 0x00000674u, 0x0000067cu, + 0x0000067au, 0x000200f9u, 0x0000067eu, 0x000200f8u, 0x0000067eu, 0x00050080u, 0x00000012u, 0x00000680u, + 0x00000831u, 0x00000052u, 0x000200f9u, 0x00000670u, 0x000200f8u, 0x00000681u, 0x000200f9u, 0x00000682u, + 0x000200f8u, 0x00000682u, 0x00050080u, 0x00000012u, 0x00000684u, 0x0000080au, 0x00000052u, 0x000200f9u, + 0x0000066bu, 0x000200f8u, 0x00000685u, 0x00050041u, 0x00000019u, 0x00000686u, 0x0000063bu, 0x00000051u, + 0x0004003du, 0x00000018u, 0x00000687u, 0x00000686u, 0x000500b7u, 0x0000010cu, 0x00000688u, 0x00000687u, + 0x00000107u, 0x000600a9u, 0x00000018u, 0x00000689u, 0x00000688u, 0x00000109u, 0x00000107u, 0x0004003du, + 0x00000018u, 0x0000068bu, 0x00000686u, 0x00050081u, 0x00000018u, 0x0000068cu, 0x0000068bu, 0x00000689u, + 0x0003003eu, 0x00000686u, 0x0000068cu, 0x00050041u, 0x00000019u, 0x0000068eu, 0x0000063bu, 0x00000052u, + 0x0004003du, 0x00000018u, 0x0000068fu, 0x0000068eu, 0x000500b7u, 0x0000010cu, 0x00000690u, 0x0000068fu, + 0x00000107u, 0x000600a9u, 0x00000018u, 0x00000691u, 0x00000690u, 0x00000109u, 0x00000107u, 0x0004003du, + 0x00000018u, 0x00000693u, 0x0000068eu, 0x00050081u, 0x00000018u, 0x00000694u, 0x00000693u, 0x00000691u, + 0x0003003eu, 0x0000068eu, 0x00000694u, 0x0004003du, 0x00000018u, 0x00000697u, 0x00000686u, 0x0007000cu, + 0x00000018u, 0x0000069au, 0x00000001u, 0x00000035u, 0x00000697u, 0x00000853u, 0x0006000cu, 0x00000018u, + 0x0000069bu, 0x00000001u, 0x00000003u, 0x0000069au, 0x0004003du, 0x00000018u, 0x0000069du, 0x0000068eu, + 0x0007000cu, 0x00000018u, 0x000006a0u, 0x00000001u, 0x00000035u, 0x0000069du, 0x00000853u, 0x0006000cu, + 0x00000018u, 0x000006a1u, 0x00000001u, 0x00000003u, 0x000006a0u, 0x00050050u, 0x00000029u, 0x000006acu, + 0x0000069bu, 0x000006a1u, 0x0003003eu, 0x0000063bu, 0x000006acu, 0x0007015du, 0x00000006u, 0x000006b7u, + 0x00000089u, 0x00000003u, 0x0000080bu, 0x00000083u, 0x00050041u, 0x0000014du, 0x000006c3u, 0x0000014bu, + 0x0000014cu, 0x0004003du, 0x00000008u, 0x000006c4u, 0x000006c3u, 0x000500adu, 0x00000084u, 0x00000610u, + 0x00000468u, 0x00000051u, 0x000600a9u, 0x00000012u, 0x00000611u, 0x00000610u, 0x00000052u, 0x00000051u, + 0x000500afu, 0x00000084u, 0x00000618u, 0x0000048du, 0x00000059u, 0x000300f7u, 0x00000627u, 0x00000000u, + 0x000400fau, 0x00000618u, 0x00000619u, 0x00000627u, 0x000200f8u, 0x00000619u, 0x00050082u, 0x00000012u, + 0x0000061bu, 0x0000048du, 0x00000056u, 0x00050080u, 0x00000012u, 0x0000061fu, 0x0000048du, 0x0000085au, + 0x000500c3u, 0x00000012u, 0x00000625u, 0x00000468u, 0x0000061bu, 0x000200f9u, 0x00000627u, 0x000200f8u, + 0x00000627u, 0x000700f5u, 0x00000012u, 0x0000080fu, 0x00000051u, 0x00000685u, 0x0000061bu, 0x00000619u, + 0x000700f5u, 0x00000012u, 0x0000080eu, 0x00000611u, 0x00000685u, 0x0000061fu, 0x00000619u, 0x000700f5u, + 0x00000012u, 0x0000080du, 0x00000468u, 0x00000685u, 0x00000625u, 0x00000619u, 0x0006000cu, 0x00000012u, + 0x0000062au, 0x00000001u, 0x0000004au, 0x0000080du, 0x00050080u, 0x00000012u, 0x0000062bu, 0x0000062au, + 0x00000052u, 0x00050080u, 0x00000012u, 0x0000062eu, 0x0000080eu, 0x0000062bu, 0x00050082u, 0x00000012u, + 0x00000632u, 0x0000062eu, 0x00000052u, 0x0007000cu, 0x00000012u, 0x00000633u, 0x00000001u, 0x0000002au, + 0x00000632u, 0x00000051u, 0x0007015du, 0x00000012u, 0x00000634u, 0x00000089u, 0x00000003u, 0x00000633u, + 0x00000083u, 0x00050084u, 0x00000012u, 0x00000635u, 0x00000186u, 0x00000634u, 0x0004007cu, 0x00000012u, + 0x00000637u, 0x000006b7u, 0x00050080u, 0x00000012u, 0x00000638u, 0x00000635u, 0x00000637u, 0x000200f9u, + 0x000006cau, 0x000200f8u, 0x000006cau, 0x000700f5u, 0x00000012u, 0x00000811u, 0x0000062eu, 0x00000627u, + 0x000006d9u, 0x000006ceu, 0x000700f5u, 0x00000006u, 0x00000810u, 0x00000076u, 0x00000627u, 0x000006dcu, + 0x000006ceu, 0x000500b0u, 0x00000084u, 0x000006cdu, 0x00000810u, 0x00000083u, 0x000400f6u, 0x000006ddu, + 0x000006ceu, 0x00000000u, 0x000400fau, 0x000006cdu, 0x000006ceu, 0x000006ddu, 0x000200f8u, 0x000006ceu, + 0x0006015bu, 0x00000012u, 0x000006d1u, 0x00000089u, 0x00000811u, 0x00000810u, 0x000500c7u, 0x00000006u, + 0x000006d3u, 0x00000375u, 0x0000008eu, 0x000500aeu, 0x00000084u, 0x000006d5u, 0x000006d3u, 0x00000810u, + 0x000600a9u, 0x00000012u, 0x000006d7u, 0x000006d5u, 0x000006d1u, 0x00000051u, 0x00050080u, 0x00000012u, + 0x000006d9u, 0x00000811u, 0x000006d7u, 0x00050084u, 0x00000006u, 0x000006dcu, 0x00000810u, 0x00000096u, + 0x000200f9u, 0x000006cau, 0x000200f8u, 0x000006ddu, 0x000500c7u, 0x00000006u, 0x00000497u, 0x00000375u, + 0x0000008eu, 0x000500aau, 0x00000084u, 0x00000498u, 0x00000497u, 0x0000008eu, 0x000300f7u, 0x0000049eu, + 0x00000000u, 0x000400fau, 0x00000498u, 0x00000499u, 0x0000049eu, 0x000200f8u, 0x00000499u, 0x00050041u, + 0x000001f5u, 0x0000049au, 0x00000230u, 0x00000051u, 0x0004007cu, 0x00000006u, 0x0000049cu, 0x00000811u, + 0x000700eau, 0x00000006u, 0x0000049du, 0x0000049au, 0x00000076u, 0x00000073u, 0x0000049cu, 0x000200f9u, + 0x0000049eu, 0x000200f8u, 0x0000049eu, 0x000700f5u, 0x00000006u, 0x00000812u, 0x00000073u, 0x000006ddu, + 0x0000049du, 0x00000499u, 0x000500c5u, 0x00000006u, 0x000004a1u, 0x00000375u, 0x0000008eu, 0x00060159u, + 0x00000006u, 0x000004a2u, 0x00000089u, 0x00000812u, 0x000004a1u, 0x00050082u, 0x00000012u, 0x000004a6u, + 0x00000811u, 0x0000062eu, 0x000500c4u, 0x00000012u, 0x000004aau, 0x0000080fu, 0x00000242u, 0x0004007cu, + 0x00000006u, 0x000004abu, 0x000004aau, 0x000700c9u, 0x00000006u, 0x000004aeu, 0x000004abu, 0x00000805u, + 0x00000247u, 0x000000f8u, 0x0004007cu, 0x00000006u, 0x000004b3u, 0x0000062bu, 0x00050084u, 0x00000006u, + 0x000004b7u, 0x00000497u, 0x00000096u, 0x000500c4u, 0x00000006u, 0x000004b8u, 0x000004b3u, 0x000004b7u, + 0x0006015au, 0x00000006u, 0x000004bau, 0x00000089u, 0x000004b8u, 0x00000076u, 0x000500c5u, 0x00000006u, + 0x000004bcu, 0x000004b8u, 0x000004bau, 0x0006015au, 0x00000006u, 0x000004beu, 0x00000089u, 0x000004bcu, + 0x00000096u, 0x000500c5u, 0x00000006u, 0x000004c0u, 0x000004bcu, 0x000004beu, 0x0006015au, 0x00000006u, + 0x000004c2u, 0x00000089u, 0x000004c0u, 0x0000025eu, 0x000500c5u, 0x00000006u, 0x000004c4u, 0x000004c0u, + 0x000004c2u, 0x000500c5u, 0x00000006u, 0x000004c7u, 0x000004aeu, 0x000004c4u, 0x000500aau, 0x00000084u, + 0x000004cau, 0x00000497u, 0x00000073u, 0x000300f7u, 0x000004e5u, 0x00000000u, 0x000400fau, 0x000004cau, + 0x000004cbu, 0x000004e5u, 0x000200f8u, 0x000004cbu, 0x00070041u, 0x000001f5u, 0x000004d2u, 0x000001eeu, + 0x00000051u, 0x00000474u, 0x00000051u, 0x0003003eu, 0x000004d2u, 0x000004c7u, 0x00070041u, 0x000001f5u, + 0x000004d4u, 0x000001eeu, 0x00000051u, 0x00000474u, 0x00000052u, 0x0003003eu, 0x000004d4u, 0x000004a2u, + 0x00050080u, 0x00000012u, 0x000004d7u, 0x0000048du, 0x00000052u, 0x0004007cu, 0x00000006u, 0x000004d8u, + 0x000004d7u, 0x00070041u, 0x000001f5u, 0x000004d9u, 0x00000202u, 0x00000051u, 0x00000474u, 0x00000051u, + 0x0003003eu, 0x000004d9u, 0x000004d8u, 0x00040072u, 0x0000027bu, 0x000004ddu, 0x00000638u, 0x0004007cu, + 0x000001fau, 0x000004deu, 0x000004ddu, 0x00090041u, 0x0000020du, 0x000004e2u, 0x00000202u, 0x00000051u, + 0x00000474u, 0x00000052u, 0x00000051u, 0x00000051u, 0x0003003eu, 0x000004e2u, 0x00000207u, 0x00090041u, + 0x00000210u, 0x000004e4u, 0x00000202u, 0x00000051u, 0x00000474u, 0x00000052u, 0x00000051u, 0x00000052u, + 0x0003003eu, 0x000004e4u, 0x000004deu, 0x000200f9u, 0x000004e5u, 0x000200f8u, 0x000004e5u, 0x000200f9u, + 0x000004e6u, 0x000200f8u, 0x000004e6u, 0x000700f5u, 0x00000012u, 0x00000814u, 0x00000052u, 0x000004e5u, + 0x0000050bu, 0x00000509u, 0x000500b3u, 0x00000084u, 0x000004eau, 0x00000814u, 0x0000048du, 0x000400f6u, + 0x0000050cu, 0x00000509u, 0x00000000u, 0x000400fau, 0x000004eau, 0x000004ebu, 0x0000050cu, 0x000200f8u, + 0x000004ebu, 0x000500c3u, 0x00000012u, 0x000006e8u, 0x00000468u, 0x00000814u, 0x0004007eu, 0x00000012u, + 0x00000738u, 0x00000814u, 0x00070050u, 0x000000d3u, 0x00000739u, 0x00000738u, 0x00000738u, 0x00000738u, + 0x00000738u, 0x0007000cu, 0x00000018u, 0x0000073au, 0x00000001u, 0x00000035u, 0x00000643u, 0x00000739u, + 0x0006000cu, 0x00000018u, 0x0000073bu, 0x00000001u, 0x00000008u, 0x0000073au, 0x0007000cu, 0x00000018u, + 0x00000741u, 0x00000001u, 0x00000035u, 0x00000646u, 0x00000739u, 0x0006000cu, 0x00000018u, 0x00000742u, + 0x00000001u, 0x00000003u, 0x00000741u, 0x00050050u, 0x00000029u, 0x0000074du, 0x0000073bu, 0x00000742u, + 0x0003003eu, 0x0000071eu, 0x0000074du, 0x000200f9u, 0x0000074eu, 0x000200f8u, 0x0000074eu, 0x000700f5u, + 0x00000006u, 0x00000825u, 0x00000073u, 0x000004ebu, 0x0000082fu, 0x00000765u, 0x000700f5u, 0x00000012u, + 0x00000824u, 0x00000051u, 0x000004ebu, 0x00000767u, 0x00000765u, 0x000500b1u, 0x00000084u, 0x00000751u, + 0x00000824u, 0x00000056u, 0x000400f6u, 0x00000768u, 0x00000765u, 0x00000000u, 0x000400fau, 0x00000751u, + 0x00000752u, 0x00000768u, 0x000200f8u, 0x00000752u, 0x000200f9u, 0x00000753u, 0x000200f8u, 0x00000753u, + 0x000700f5u, 0x00000006u, 0x0000082fu, 0x00000825u, 0x00000752u, 0x0000084du, 0x00000761u, 0x000700f5u, + 0x00000012u, 0x0000082du, 0x00000051u, 0x00000752u, 0x00000763u, 0x00000761u, 0x000500b1u, 0x00000084u, + 0x00000756u, 0x0000082du, 0x000000f8u, 0x000400f6u, 0x00000764u, 0x00000761u, 0x00000000u, 0x000400fau, + 0x00000756u, 0x00000757u, 0x00000764u, 0x000200f8u, 0x00000757u, 0x00060041u, 0x0000000du, 0x0000075au, + 0x0000071eu, 0x00000824u, 0x0000082du, 0x0004003du, 0x00000008u, 0x0000075bu, 0x0000075au, 0x000500b7u, + 0x00000084u, 0x0000075cu, 0x0000075bu, 0x000000c2u, 0x000300f7u, 0x00000760u, 0x00000000u, 0x000400fau, + 0x0000075cu, 0x0000075du, 0x00000760u, 0x000200f8u, 0x0000075du, 0x00050080u, 0x00000006u, 0x0000075fu, + 0x0000082fu, 0x00000052u, 0x000200f9u, 0x00000760u, 0x000200f8u, 0x00000760u, 0x000700f5u, 0x00000006u, + 0x0000084du, 0x0000082fu, 0x00000757u, 0x0000075fu, 0x0000075du, 0x000200f9u, 0x00000761u, 0x000200f8u, + 0x00000761u, 0x00050080u, 0x00000012u, 0x00000763u, 0x0000082du, 0x00000052u, 0x000200f9u, 0x00000753u, + 0x000200f8u, 0x00000764u, 0x000200f9u, 0x00000765u, 0x000200f8u, 0x00000765u, 0x00050080u, 0x00000012u, + 0x00000767u, 0x00000824u, 0x00000052u, 0x000200f9u, 0x0000074eu, 0x000200f8u, 0x00000768u, 0x00050041u, + 0x00000019u, 0x00000769u, 0x0000071eu, 0x00000051u, 0x0004003du, 0x00000018u, 0x0000076au, 0x00000769u, + 0x000500b7u, 0x0000010cu, 0x0000076bu, 0x0000076au, 0x00000107u, 0x000600a9u, 0x00000018u, 0x0000076cu, + 0x0000076bu, 0x00000109u, 0x00000107u, 0x0004003du, 0x00000018u, 0x0000076eu, 0x00000769u, 0x00050081u, + 0x00000018u, 0x0000076fu, 0x0000076eu, 0x0000076cu, 0x0003003eu, 0x00000769u, 0x0000076fu, 0x00050041u, + 0x00000019u, 0x00000771u, 0x0000071eu, 0x00000052u, 0x0004003du, 0x00000018u, 0x00000772u, 0x00000771u, + 0x000500b7u, 0x0000010cu, 0x00000773u, 0x00000772u, 0x00000107u, 0x000600a9u, 0x00000018u, 0x00000774u, + 0x00000773u, 0x00000109u, 0x00000107u, 0x0004003du, 0x00000018u, 0x00000776u, 0x00000771u, 0x00050081u, + 0x00000018u, 0x00000777u, 0x00000776u, 0x00000774u, 0x0003003eu, 0x00000771u, 0x00000777u, 0x0004003du, + 0x00000018u, 0x0000077au, 0x00000769u, 0x00070050u, 0x000000d3u, 0x0000077cu, 0x00000814u, 0x00000814u, + 0x00000814u, 0x00000814u, 0x0007000cu, 0x00000018u, 0x0000077du, 0x00000001u, 0x00000035u, 0x0000077au, + 0x0000077cu, 0x0006000cu, 0x00000018u, 0x0000077eu, 0x00000001u, 0x00000003u, 0x0000077du, 0x0004003du, + 0x00000018u, 0x00000780u, 0x00000771u, 0x0007000cu, 0x00000018u, 0x00000783u, 0x00000001u, 0x00000035u, + 0x00000780u, 0x0000077cu, 0x0006000cu, 0x00000018u, 0x00000784u, 0x00000001u, 0x00000003u, 0x00000783u, + 0x00050050u, 0x00000029u, 0x0000078fu, 0x0000077eu, 0x00000784u, 0x0003003eu, 0x0000071eu, 0x0000078fu, + 0x00050083u, 0x00000018u, 0x00000794u, 0x00000643u, 0x0000077eu, 0x00050083u, 0x00000018u, 0x00000797u, + 0x00000646u, 0x00000784u, 0x0007015du, 0x00000006u, 0x0000079au, 0x00000089u, 0x00000003u, 0x00000825u, + 0x00000083u, 0x00050094u, 0x00000008u, 0x0000079fu, 0x00000794u, 0x00000794u, 0x00050094u, 0x00000008u, + 0x000007a4u, 0x00000797u, 0x00000797u, 0x00050081u, 0x00000008u, 0x000007a5u, 0x0000079fu, 0x000007a4u, + 0x00050085u, 0x00000008u, 0x000007a8u, 0x000007a5u, 0x000006c4u, 0x00050085u, 0x00000008u, 0x000006eeu, + 0x000007a8u, 0x0000045cu, 0x000500adu, 0x00000084u, 0x000006f3u, 0x000006e8u, 0x00000051u, 0x000600a9u, + 0x00000012u, 0x000006f4u, 0x000006f3u, 0x00000052u, 0x00000051u, 0x00050082u, 0x00000012u, 0x000006f8u, + 0x0000048du, 0x00000814u, 0x000500afu, 0x00000084u, 0x000006fbu, 0x000006f8u, 0x00000059u, 0x000300f7u, + 0x0000070au, 0x00000000u, 0x000400fau, 0x000006fbu, 0x000006fcu, 0x0000070au, 0x000200f8u, 0x000006fcu, + 0x00050082u, 0x00000012u, 0x000006feu, 0x000006f8u, 0x00000056u, 0x00050080u, 0x00000012u, 0x00000702u, + 0x000006f8u, 0x0000085au, 0x000500c3u, 0x00000012u, 0x00000708u, 0x000006e8u, 0x000006feu, 0x000200f9u, + 0x0000070au, 0x000200f8u, 0x0000070au, 0x000700f5u, 0x00000012u, 0x00000828u, 0x000006f4u, 0x00000768u, + 0x00000702u, 0x000006fcu, 0x000700f5u, 0x00000012u, 0x00000827u, 0x000006e8u, 0x00000768u, 0x00000708u, + 0x000006fcu, 0x0006000cu, 0x00000012u, 0x0000070du, 0x00000001u, 0x0000004au, 0x00000827u, 0x00050080u, + 0x00000012u, 0x0000070eu, 0x0000070du, 0x00000052u, 0x00050080u, 0x00000012u, 0x00000711u, 0x00000828u, + 0x0000070eu, 0x00050082u, 0x00000012u, 0x00000715u, 0x00000711u, 0x00000052u, 0x0007000cu, 0x00000012u, + 0x00000716u, 0x00000001u, 0x0000002au, 0x00000715u, 0x00000051u, 0x0007015du, 0x00000012u, 0x00000717u, + 0x00000089u, 0x00000003u, 0x00000716u, 0x00000083u, 0x00050084u, 0x00000012u, 0x00000718u, 0x00000186u, + 0x00000717u, 0x0004007cu, 0x00000012u, 0x0000071au, 0x0000079au, 0x00050080u, 0x00000012u, 0x0000071bu, + 0x00000718u, 0x0000071au, 0x0007015eu, 0x00000008u, 0x000004f4u, 0x00000089u, 0x00000003u, 0x000006eeu, + 0x00000083u, 0x000300f7u, 0x00000508u, 0x00000000u, 0x000400fau, 0x000004cau, 0x000004f8u, 0x00000508u, + 0x000200f8u, 0x000004f8u, 0x0007000cu, 0x00000008u, 0x000004fcu, 0x00000001u, 0x00000025u, 0x000004f4u, + 0x000002a5u, 0x00040073u, 0x000001f9u, 0x000004fdu, 0x000004fcu, 0x00040072u, 0x0000027bu, 0x00000500u, + 0x0000071bu, 0x0004007cu, 0x000001fau, 0x00000501u, 0x00000500u, 0x00090041u, 0x0000020du, 0x00000505u, + 0x00000202u, 0x00000051u, 0x00000474u, 0x00000052u, 0x00000814u, 0x00000051u, 0x0003003eu, 0x00000505u, + 0x000004fdu, 0x00090041u, 0x00000210u, 0x00000507u, 0x00000202u, 0x00000051u, 0x00000474u, 0x00000052u, + 0x00000814u, 0x00000052u, 0x0003003eu, 0x00000507u, 0x00000501u, 0x000200f9u, 0x00000508u, 0x000200f8u, + 0x00000508u, 0x000200f9u, 0x00000509u, 0x000200f8u, 0x00000509u, 0x00050080u, 0x00000012u, 0x0000050bu, + 0x00000814u, 0x00000052u, 0x000200f9u, 0x000004e6u, 0x000200f8u, 0x0000050cu, 0x00050094u, 0x00000008u, + 0x00000511u, 0x0000045eu, 0x0000045eu, 0x00050094u, 0x00000008u, 0x00000516u, 0x00000462u, 0x00000462u, + 0x00050081u, 0x00000008u, 0x00000517u, 0x00000511u, 0x00000516u, 0x00050085u, 0x00000008u, 0x00000519u, + 0x00000517u, 0x0000045cu, 0x0007015eu, 0x00000008u, 0x0000051au, 0x00000089u, 0x00000003u, 0x00000519u, + 0x00000083u, 0x000300f7u, 0x0000052bu, 0x00000000u, 0x000400fau, 0x000004cau, 0x0000051eu, 0x0000052bu, + 0x000200f8u, 0x0000051eu, 0x00050080u, 0x00000012u, 0x00000521u, 0x0000048du, 0x00000052u, 0x0007000cu, + 0x00000008u, 0x00000523u, 0x00000001u, 0x00000025u, 0x000002a5u, 0x0000051au, 0x00040073u, 0x000001f9u, + 0x00000524u, 0x00000523u, 0x00090041u, 0x0000020du, 0x00000528u, 0x00000202u, 0x00000051u, 0x00000474u, + 0x00000052u, 0x00000521u, 0x00000051u, 0x0003003eu, 0x00000528u, 0x00000524u, 0x00090041u, 0x00000210u, + 0x0000052au, 0x00000202u, 0x00000051u, 0x00000474u, 0x00000052u, 0x00000521u, 0x00000052u, 0x0003003eu, + 0x0000052au, 0x00000208u, 0x000200f9u, 0x0000052bu, 0x000200f8u, 0x0000052bu, 0x0004007cu, 0x00000006u, + 0x0000052du, 0x000004a6u, 0x00050080u, 0x00000006u, 0x0000052fu, 0x0000052du, 0x000004a2u, 0x000500abu, + 0x00000084u, 0x00000532u, 0x0000080du, 0x00000051u, 0x000500abu, 0x00000084u, 0x00000534u, 0x0000080fu, + 0x00000051u, 0x000500a6u, 0x00000084u, 0x00000535u, 0x00000532u, 0x00000534u, 0x000300f7u, 0x000005b6u, + 0x00000000u, 0x000400fau, 0x00000535u, 0x00000537u, 0x000005b6u, 0x000200f8u, 0x00000537u, 0x000500b8u, + 0x0000010cu, 0x0000053au, 0x0000045eu, 0x00000107u, 0x000600a9u, 0x000002e4u, 0x0000053cu, 0x0000053au, + 0x0000085du, 0x000002eau, 0x000500b8u, 0x0000010cu, 0x0000053fu, 0x00000462u, 0x00000107u, 0x000600a9u, + 0x000002e4u, 0x00000541u, 0x0000053fu, 0x00000863u, 0x000002eau, 0x00050051u, 0x00000006u, 0x00000543u, + 0x0000053cu, 0x00000000u, 0x00050051u, 0x00000006u, 0x00000545u, 0x0000053cu, 0x00000001u, 0x000500c5u, + 0x00000006u, 0x00000546u, 0x00000543u, 0x00000545u, 0x00050051u, 0x00000006u, 0x00000548u, 0x0000053cu, + 0x00000002u, 0x000500c5u, 0x00000006u, 0x00000549u, 0x00000546u, 0x00000548u, 0x00050051u, 0x00000006u, + 0x0000054bu, 0x0000053cu, 0x00000003u, 0x000500c5u, 0x00000006u, 0x0000054cu, 0x00000549u, 0x0000054bu, + 0x00050051u, 0x00000006u, 0x0000054eu, 0x00000541u, 0x00000000u, 0x000500c5u, 0x00000006u, 0x0000054fu, + 0x0000054cu, 0x0000054eu, 0x00050051u, 0x00000006u, 0x00000551u, 0x00000541u, 0x00000001u, 0x000500c5u, + 0x00000006u, 0x00000552u, 0x0000054fu, 0x00000551u, 0x00050051u, 0x00000006u, 0x00000554u, 0x00000541u, + 0x00000002u, 0x000500c5u, 0x00000006u, 0x00000555u, 0x00000552u, 0x00000554u, 0x00050051u, 0x00000006u, + 0x00000557u, 0x00000541u, 0x00000003u, 0x000500c5u, 0x00000006u, 0x00000558u, 0x00000555u, 0x00000557u, + 0x00050080u, 0x00000006u, 0x0000055au, 0x0000052fu, 0x00000052u, 0x00040071u, 0x0000022cu, 0x0000055cu, + 0x00000558u, 0x00060041u, 0x00000313u, 0x0000055du, 0x00000230u, 0x00000052u, 0x0000052fu, 0x0003003eu, + 0x0000055du, 0x0000055cu, 0x00050080u, 0x00000012u, 0x00000561u, 0x0000080fu, 0x0000062bu, 0x00050082u, + 0x00000012u, 0x00000563u, 0x00000561u, 0x00000052u, 0x000200f9u, 0x00000564u, 0x000200f8u, 0x00000564u, + 0x000700f5u, 0x00000006u, 0x00000823u, 0x0000055au, 0x00000537u, 0x000005acu, 0x00000564u, 0x000700f5u, + 0x00000012u, 0x00000822u, 0x00000563u, 0x00000537u, 0x000005b1u, 0x00000564u, 0x00050051u, 0x00000012u, + 0x00000567u, 0x00000460u, 0x00000000u, 0x0004007cu, 0x00000006u, 0x00000568u, 0x00000567u, 0x000600cbu, + 0x00000006u, 0x0000056au, 0x00000568u, 0x00000822u, 0x00000052u, 0x00050051u, 0x00000012u, 0x0000056cu, + 0x00000460u, 0x00000001u, 0x0004007cu, 0x00000006u, 0x0000056du, 0x0000056cu, 0x000600cbu, 0x00000006u, + 0x0000056fu, 0x0000056du, 0x00000822u, 0x00000052u, 0x00050051u, 0x00000012u, 0x00000571u, 0x00000460u, + 0x00000002u, 0x0004007cu, 0x00000006u, 0x00000572u, 0x00000571u, 0x000600cbu, 0x00000006u, 0x00000574u, + 0x00000572u, 0x00000822u, 0x00000052u, 0x00050051u, 0x00000012u, 0x00000576u, 0x00000460u, 0x00000003u, + 0x0004007cu, 0x00000006u, 0x00000577u, 0x00000576u, 0x000600cbu, 0x00000006u, 0x00000579u, 0x00000577u, + 0x00000822u, 0x00000052u, 0x00070050u, 0x000002e4u, 0x0000057au, 0x0000056au, 0x0000056fu, 0x00000574u, + 0x00000579u, 0x00050051u, 0x00000012u, 0x0000057cu, 0x00000464u, 0x00000000u, 0x0004007cu, 0x00000006u, + 0x0000057du, 0x0000057cu, 0x000600cbu, 0x00000006u, 0x0000057fu, 0x0000057du, 0x00000822u, 0x00000052u, + 0x00050051u, 0x00000012u, 0x00000581u, 0x00000464u, 0x00000001u, 0x0004007cu, 0x00000006u, 0x00000582u, + 0x00000581u, 0x000600cbu, 0x00000006u, 0x00000584u, 0x00000582u, 0x00000822u, 0x00000052u, 0x00050051u, + 0x00000012u, 0x00000586u, 0x00000464u, 0x00000002u, 0x0004007cu, 0x00000006u, 0x00000587u, 0x00000586u, + 0x000600cbu, 0x00000006u, 0x00000589u, 0x00000587u, 0x00000822u, 0x00000052u, 0x00050051u, 0x00000012u, + 0x0000058bu, 0x00000464u, 0x00000003u, 0x0004007cu, 0x00000006u, 0x0000058cu, 0x0000058bu, 0x000600cbu, + 0x00000006u, 0x0000058eu, 0x0000058cu, 0x00000822u, 0x00000052u, 0x00070050u, 0x000002e4u, 0x0000058fu, + 0x0000057fu, 0x00000584u, 0x00000589u, 0x0000058eu, 0x000500c4u, 0x000002e4u, 0x00000591u, 0x0000057au, + 0x000002edu, 0x000500c4u, 0x000002e4u, 0x00000593u, 0x0000058fu, 0x000002f5u, 0x00050051u, 0x00000006u, + 0x00000595u, 0x00000591u, 0x00000000u, 0x00050051u, 0x00000006u, 0x00000597u, 0x00000591u, 0x00000001u, + 0x000500c5u, 0x00000006u, 0x00000598u, 0x00000595u, 0x00000597u, 0x00050051u, 0x00000006u, 0x0000059au, + 0x00000591u, 0x00000002u, 0x000500c5u, 0x00000006u, 0x0000059bu, 0x00000598u, 0x0000059au, 0x00050051u, + 0x00000006u, 0x0000059du, 0x00000591u, 0x00000003u, 0x000500c5u, 0x00000006u, 0x0000059eu, 0x0000059bu, + 0x0000059du, 0x00050051u, 0x00000006u, 0x000005a0u, 0x00000593u, 0x00000000u, 0x000500c5u, 0x00000006u, + 0x000005a1u, 0x0000059eu, 0x000005a0u, 0x00050051u, 0x00000006u, 0x000005a3u, 0x00000593u, 0x00000001u, + 0x000500c5u, 0x00000006u, 0x000005a4u, 0x000005a1u, 0x000005a3u, 0x00050051u, 0x00000006u, 0x000005a6u, + 0x00000593u, 0x00000002u, 0x000500c5u, 0x00000006u, 0x000005a7u, 0x000005a4u, 0x000005a6u, 0x00050051u, + 0x00000006u, 0x000005a9u, 0x00000593u, 0x00000003u, 0x000500c5u, 0x00000006u, 0x000005aau, 0x000005a7u, + 0x000005a9u, 0x00050080u, 0x00000006u, 0x000005acu, 0x00000823u, 0x00000052u, 0x00040071u, 0x0000022cu, + 0x000005aeu, 0x000005aau, 0x00060041u, 0x00000313u, 0x000005afu, 0x00000230u, 0x00000052u, 0x00000823u, + 0x0003003eu, 0x000005afu, 0x000005aeu, 0x00050082u, 0x00000012u, 0x000005b1u, 0x00000822u, 0x00000052u, + 0x000500afu, 0x00000084u, 0x000005b4u, 0x000005b1u, 0x00000051u, 0x000400f6u, 0x000005b5u, 0x00000564u, + 0x00000000u, 0x000400fau, 0x000005b4u, 0x00000564u, 0x000005b5u, 0x000200f8u, 0x000005b5u, 0x000200f9u, + 0x000005b6u, 0x000200f8u, 0x000005b6u, 0x000200f9u, 0x000005b7u, 0x000200f8u, 0x000005b7u, 0x000200f9u, + 0x000003dau, 0x000200f8u, 0x000003dau, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, + 0x000004acu, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, 0x00000038u, 0x00020011u, 0x0000003du, + 0x00020011u, 0x0000003fu, 0x00020011u, 0x00000042u, 0x00020011u, 0x00001151u, 0x00020011u, 0x00001160u, + 0x0007000au, 0x5f565053u, 0x5f52484bu, 0x74696238u, 0x6f74735fu, 0x65676172u, 0x00000000u, 0x0006000bu, + 0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, + 0x000a000fu, 0x00000005u, 0x00000004u, 0x6e69616du, 0x00000000u, 0x0000010eu, 0x00000116u, 0x00000159u, + 0x0000015bu, 0x0000016au, 0x00060010u, 0x00000004u, 0x00000011u, 0x00000080u, 0x00000001u, 0x00000001u, + 0x00040047u, 0x0000007eu, 0x00000006u, 0x00000001u, 0x00030047u, 0x0000007fu, 0x00000002u, 0x00040048u, + 0x0000007fu, 0x00000000u, 0x00000018u, 0x00050048u, 0x0000007fu, 0x00000000u, 0x00000023u, 0x00000000u, + 0x00030047u, 0x00000081u, 0x00000018u, 0x00040047u, 0x00000081u, 0x00000021u, 0x00000002u, 0x00040047u, + 0x00000081u, 0x00000022u, 0x00000000u, 0x00040047u, 0x0000010eu, 0x0000000bu, 0x00000026u, 0x00030047u, + 0x00000116u, 0x00000000u, 0x00040047u, 0x00000116u, 0x0000000bu, 0x00000029u, 0x00040047u, 0x00000159u, + 0x0000000bu, 0x00000028u, 0x00030047u, 0x0000015bu, 0x00000000u, 0x00040047u, 0x0000015bu, 0x0000000bu, + 0x00000024u, 0x00030047u, 0x0000015cu, 0x00000000u, 0x00030047u, 0x0000015eu, 0x00000000u, 0x00030047u, + 0x00000161u, 0x00000002u, 0x00050048u, 0x00000161u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, + 0x00000161u, 0x00000001u, 0x00000023u, 0x00000008u, 0x00050048u, 0x00000161u, 0x00000002u, 0x00000023u, + 0x0000000cu, 0x00050048u, 0x00000161u, 0x00000003u, 0x00000023u, 0x00000010u, 0x00040047u, 0x0000016au, + 0x0000000bu, 0x0000001au, 0x00040047u, 0x000001a0u, 0x00000006u, 0x00000004u, 0x00030047u, 0x000001a1u, + 0x00000002u, 0x00040048u, 0x000001a1u, 0x00000000u, 0x00000018u, 0x00050048u, 0x000001a1u, 0x00000000u, + 0x00000023u, 0x00000000u, 0x00030047u, 0x000001a3u, 0x00000018u, 0x00040047u, 0x000001a3u, 0x00000021u, + 0x00000001u, 0x00040047u, 0x000001a3u, 0x00000022u, 0x00000000u, 0x00030047u, 0x000001bfu, 0x00000019u, + 0x00040047u, 0x000001bfu, 0x00000021u, 0x00000000u, 0x00040047u, 0x000001bfu, 0x00000022u, 0x00000000u, + 0x00040047u, 0x000001d2u, 0x00000006u, 0x00000004u, 0x00030047u, 0x000001d3u, 0x00000002u, 0x00040048u, + 0x000001d3u, 0x00000000u, 0x00000018u, 0x00050048u, 0x000001d3u, 0x00000000u, 0x00000023u, 0x00000000u, + 0x00030047u, 0x000001d5u, 0x00000018u, 0x00040047u, 0x000001d5u, 0x00000021u, 0x00000002u, 0x00040047u, + 0x000001d5u, 0x00000022u, 0x00000000u, 0x00040047u, 0x000001f8u, 0x00000006u, 0x00000002u, 0x00030047u, + 0x000001f9u, 0x00000002u, 0x00040048u, 0x000001f9u, 0x00000000u, 0x00000018u, 0x00050048u, 0x000001f9u, + 0x00000000u, 0x00000023u, 0x00000000u, 0x00030047u, 0x000001fbu, 0x00000018u, 0x00040047u, 0x000001fbu, + 0x00000021u, 0x00000002u, 0x00040047u, 0x000001fbu, 0x00000022u, 0x00000000u, 0x00030047u, 0x000002a8u, + 0x00000000u, 0x00040047u, 0x00000354u, 0x0000000bu, 0x00000019u, 0x00020013u, 0x00000002u, 0x00030021u, + 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, 0x00000000u, 0x00040015u, 0x00000008u, + 0x00000020u, 0x00000001u, 0x00040017u, 0x00000009u, 0x00000008u, 0x00000002u, 0x00030016u, 0x0000000eu, + 0x00000020u, 0x00040017u, 0x00000013u, 0x0000000eu, 0x00000004u, 0x00040018u, 0x00000014u, 0x00000013u, + 0x00000002u, 0x0004002bu, 0x00000008u, 0x00000029u, 0x00000000u, 0x0004002bu, 0x00000008u, 0x0000002au, + 0x00000001u, 0x0004002bu, 0x00000008u, 0x0000002eu, 0x00000002u, 0x0004002bu, 0x00000008u, 0x00000031u, + 0x00000003u, 0x0004002bu, 0x00000008u, 0x00000037u, 0x00000005u, 0x0004002bu, 0x0000000eu, 0x00000047u, + 0x3e800000u, 0x00020014u, 0x0000004bu, 0x0004002bu, 0x00000006u, 0x0000004fu, 0x00000000u, 0x0004002bu, + 0x0000000eu, 0x00000054u, 0x00000000u, 0x0007002cu, 0x00000013u, 0x00000055u, 0x00000054u, 0x00000054u, + 0x00000054u, 0x00000054u, 0x0005002cu, 0x00000014u, 0x00000056u, 0x00000055u, 0x00000055u, 0x00040020u, + 0x00000058u, 0x00000007u, 0x00000008u, 0x0004002bu, 0x00000006u, 0x0000005fu, 0x00005555u, 0x0004002bu, + 0x00000006u, 0x00000063u, 0x0000aaaau, 0x00040015u, 0x0000007du, 0x00000008u, 0x00000000u, 0x0003001du, + 0x0000007eu, 0x0000007du, 0x0003001eu, 0x0000007fu, 0x0000007eu, 0x00040020u, 0x00000080u, 0x0000000cu, + 0x0000007fu, 0x0004003bu, 0x00000080u, 0x00000081u, 0x0000000cu, 0x00040020u, 0x00000083u, 0x0000000cu, + 0x0000007du, 0x0004002bu, 0x00000006u, 0x0000008bu, 0x00000008u, 0x0004001cu, 0x0000008cu, 0x00000008u, + 0x0000008bu, 0x00040020u, 0x0000008du, 0x00000007u, 0x0000008cu, 0x000b002cu, 0x0000008cu, 0x0000008fu, + 0x00000029u, 0x00000029u, 0x00000029u, 0x00000029u, 0x00000029u, 0x00000029u, 0x00000029u, 0x00000029u, + 0x0004002bu, 0x00000008u, 0x000000a6u, 0x00000008u, 0x0004002bu, 0x00000008u, 0x000000c6u, 0x00000004u, + 0x00040020u, 0x000000d0u, 0x00000007u, 0x0000000eu, 0x0004002bu, 0x0000000eu, 0x000000ddu, 0x3f000000u, + 0x00040020u, 0x000000e0u, 0x00000007u, 0x00000014u, 0x0004002bu, 0x00000008u, 0x000000f5u, 0x00000007u, + 0x0004002bu, 0x0000000eu, 0x000000f8u, 0x34000000u, 0x0004002bu, 0x00000006u, 0x00000106u, 0x00000001u, + 0x00040020u, 0x0000010du, 0x00000001u, 0x00000006u, 0x0004003bu, 0x0000010du, 0x0000010eu, 0x00000001u, + 0x0004002bu, 0x00000006u, 0x00000114u, 0x00000003u, 0x0004003bu, 0x0000010du, 0x00000116u, 0x00000001u, + 0x0004002bu, 0x00000006u, 0x0000011eu, 0x00000002u, 0x0004002bu, 0x00000006u, 0x00000124u, 0x00000108u, + 0x0004002bu, 0x00000006u, 0x0000012du, 0x00000020u, 0x0004001cu, 0x0000012eu, 0x00000006u, 0x0000012du, + 0x00040020u, 0x0000012fu, 0x00000004u, 0x0000012eu, 0x0004003bu, 0x0000012fu, 0x00000130u, 0x00000004u, + 0x00040020u, 0x00000132u, 0x00000004u, 0x00000006u, 0x0004003bu, 0x0000010du, 0x00000159u, 0x00000001u, + 0x0004003bu, 0x0000010du, 0x0000015bu, 0x00000001u, 0x0006001eu, 0x00000161u, 0x00000009u, 0x00000008u, + 0x00000008u, 0x00000008u, 0x00040020u, 0x00000162u, 0x00000009u, 0x00000161u, 0x0004003bu, 0x00000162u, + 0x00000163u, 0x00000009u, 0x00040020u, 0x00000164u, 0x00000009u, 0x00000008u, 0x00040017u, 0x00000168u, + 0x00000006u, 0x00000003u, 0x00040020u, 0x00000169u, 0x00000001u, 0x00000168u, 0x0004003bu, 0x00000169u, + 0x0000016au, 0x00000001u, 0x0004002bu, 0x00000006u, 0x00000181u, 0x00000004u, 0x00040017u, 0x0000018cu, + 0x00000006u, 0x00000002u, 0x0004002bu, 0x00000008u, 0x00000190u, 0x00000020u, 0x0003001du, 0x000001a0u, + 0x00000006u, 0x0003001eu, 0x000001a1u, 0x000001a0u, 0x00040020u, 0x000001a2u, 0x0000000cu, 0x000001a1u, + 0x0004003bu, 0x000001a2u, 0x000001a3u, 0x0000000cu, 0x00040020u, 0x000001a5u, 0x0000000cu, 0x00000006u, + 0x0004002bu, 0x00000006u, 0x000001a9u, 0xffffffffu, 0x00090019u, 0x000001bdu, 0x0000000eu, 0x00000001u, + 0x00000000u, 0x00000001u, 0x00000000u, 0x00000002u, 0x00000000u, 0x00040020u, 0x000001beu, 0x00000000u, + 0x000001bdu, 0x0004003bu, 0x000001beu, 0x000001bfu, 0x00000000u, 0x00040017u, 0x000001c8u, 0x00000008u, + 0x00000003u, 0x0003001du, 0x000001d2u, 0x00000006u, 0x0003001eu, 0x000001d3u, 0x000001d2u, 0x00040020u, + 0x000001d4u, 0x0000000cu, 0x000001d3u, 0x0004003bu, 0x000001d4u, 0x000001d5u, 0x0000000cu, 0x0004002bu, + 0x00000006u, 0x000001d9u, 0x0000ffffu, 0x0004002bu, 0x00000006u, 0x000001e0u, 0x000000ffu, 0x0004002bu, + 0x00000006u, 0x000001e3u, 0x00000010u, 0x00040015u, 0x000001f7u, 0x00000010u, 0x00000000u, 0x0003001du, + 0x000001f8u, 0x000001f7u, 0x0003001eu, 0x000001f9u, 0x000001f8u, 0x00040020u, 0x000001fau, 0x0000000cu, + 0x000001f9u, 0x0004003bu, 0x000001fau, 0x000001fbu, 0x0000000cu, 0x00040020u, 0x00000201u, 0x0000000cu, + 0x000001f7u, 0x0004002bu, 0x00000006u, 0x00000212u, 0x0000000fu, 0x0004003bu, 0x00000132u, 0x0000023au, + 0x00000004u, 0x0004001cu, 0x0000023du, 0x00000006u, 0x000001e3u, 0x00040020u, 0x0000023eu, 0x00000004u, + 0x0000023du, 0x0004003bu, 0x0000023eu, 0x0000023fu, 0x00000004u, 0x0004002bu, 0x00000006u, 0x000002f4u, + 0x0000001fu, 0x0004002bu, 0x0000000eu, 0x0000031du, 0x3f800000u, 0x0004002bu, 0x0000000eu, 0x0000031eu, + 0x40000000u, 0x0004002bu, 0x00000006u, 0x00000353u, 0x00000080u, 0x0006002cu, 0x00000168u, 0x00000354u, + 0x00000353u, 0x00000106u, 0x00000106u, 0x0005002cu, 0x00000009u, 0x000004a6u, 0x00000190u, 0x00000190u, + 0x0005002cu, 0x00000009u, 0x000004a7u, 0x000000a6u, 0x000000a6u, 0x0004002bu, 0x00000008u, 0x000004aau, + 0x00000018u, 0x0004002bu, 0x0000000eu, 0x000004abu, 0x3e000000u, 0x00050036u, 0x00000002u, 0x00000004u, + 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, 0x0000008du, 0x00000382u, 0x00000007u, + 0x0004003bu, 0x000000e0u, 0x0000038au, 0x00000007u, 0x0004003bu, 0x000000e0u, 0x0000026au, 0x00000007u, + 0x000300f7u, 0x00000357u, 0x00000000u, 0x000300fbu, 0x0000004fu, 0x00000358u, 0x000200f8u, 0x00000358u, + 0x0004003du, 0x00000006u, 0x0000015au, 0x00000159u, 0x0004003du, 0x00000006u, 0x0000015cu, 0x0000015bu, + 0x00050084u, 0x00000006u, 0x0000015du, 0x0000015au, 0x0000015cu, 0x0004003du, 0x00000006u, 0x0000015eu, + 0x00000116u, 0x00050080u, 0x00000006u, 0x0000015fu, 0x0000015du, 0x0000015eu, 0x00050041u, 0x00000164u, + 0x00000165u, 0x00000163u, 0x0000002eu, 0x0004003du, 0x00000008u, 0x00000166u, 0x00000165u, 0x0004007cu, + 0x00000006u, 0x00000167u, 0x00000166u, 0x00050041u, 0x0000010du, 0x0000016bu, 0x0000016au, 0x00000106u, + 0x0004003du, 0x00000006u, 0x0000016cu, 0x0000016bu, 0x00050041u, 0x00000164u, 0x0000016du, 0x00000163u, + 0x00000031u, 0x0004003du, 0x00000008u, 0x0000016eu, 0x0000016du, 0x0004007cu, 0x00000006u, 0x0000016fu, + 0x0000016eu, 0x00050084u, 0x00000006u, 0x00000170u, 0x0000016cu, 0x0000016fu, 0x00050080u, 0x00000006u, + 0x00000171u, 0x00000167u, 0x00000170u, 0x00050041u, 0x0000010du, 0x00000172u, 0x0000016au, 0x0000004fu, + 0x0004003du, 0x00000006u, 0x00000173u, 0x00000172u, 0x00050080u, 0x00000006u, 0x00000174u, 0x00000171u, + 0x00000173u, 0x0004007cu, 0x00000008u, 0x00000175u, 0x00000174u, 0x000600cbu, 0x00000006u, 0x00000178u, + 0x0000015fu, 0x00000029u, 0x00000031u, 0x000600cbu, 0x00000006u, 0x0000017bu, 0x0000015fu, 0x00000031u, + 0x0000002eu, 0x000600cbu, 0x00000006u, 0x0000017eu, 0x0000015fu, 0x00000037u, 0x0000002eu, 0x00050084u, + 0x00000006u, 0x00000182u, 0x0000017eu, 0x00000181u, 0x00050080u, 0x00000006u, 0x00000184u, 0x00000182u, + 0x0000017bu, 0x000500c4u, 0x00000006u, 0x00000188u, 0x00000178u, 0x00000031u, 0x000600cbu, 0x00000006u, + 0x00000366u, 0x00000188u, 0x00000029u, 0x0000002au, 0x000600cbu, 0x00000006u, 0x00000368u, 0x00000188u, + 0x0000002au, 0x0000002eu, 0x000600cbu, 0x00000006u, 0x0000036au, 0x00000188u, 0x00000031u, 0x0000002eu, + 0x000500c4u, 0x00000006u, 0x0000036bu, 0x0000036au, 0x0000002au, 0x000500c5u, 0x00000006u, 0x0000036du, + 0x00000366u, 0x0000036bu, 0x000600cbu, 0x00000006u, 0x0000036fu, 0x00000188u, 0x00000037u, 0x0000002au, + 0x000500c4u, 0x00000006u, 0x00000370u, 0x0000036fu, 0x0000002eu, 0x000500c5u, 0x00000006u, 0x00000372u, + 0x00000368u, 0x00000370u, 0x0004007cu, 0x00000008u, 0x00000374u, 0x00000372u, 0x0004007cu, 0x00000008u, + 0x00000376u, 0x0000036du, 0x00050050u, 0x00000009u, 0x00000377u, 0x00000374u, 0x00000376u, 0x0004003du, + 0x00000168u, 0x0000018du, 0x0000016au, 0x0007004fu, 0x0000018cu, 0x0000018eu, 0x0000018du, 0x0000018du, + 0x00000000u, 0x00000001u, 0x0004007cu, 0x00000009u, 0x0000018fu, 0x0000018eu, 0x00050084u, 0x00000009u, + 0x00000192u, 0x0000018fu, 0x000004a6u, 0x0004007cu, 0x00000008u, 0x00000194u, 0x0000017bu, 0x0004007cu, + 0x00000008u, 0x00000196u, 0x0000017eu, 0x00050050u, 0x00000009u, 0x00000197u, 0x00000194u, 0x00000196u, + 0x00050084u, 0x00000009u, 0x00000199u, 0x000004a7u, 0x00000197u, 0x00050080u, 0x00000009u, 0x0000019bu, + 0x00000192u, 0x00000199u, 0x00050080u, 0x00000009u, 0x0000019eu, 0x0000019bu, 0x00000377u, 0x00060041u, + 0x000001a5u, 0x000001a6u, 0x000001a3u, 0x00000029u, 0x00000175u, 0x0004003du, 0x00000006u, 0x000001a7u, + 0x000001a6u, 0x000500aau, 0x0000004bu, 0x000001aau, 0x000001a7u, 0x000001a9u, 0x000300f7u, 0x000001acu, + 0x00000000u, 0x000400fau, 0x000001aau, 0x000001abu, 0x000001acu, 0x000200f8u, 0x000001abu, 0x000200f9u, + 0x000001aeu, 0x000200f8u, 0x000001aeu, 0x000700f5u, 0x00000008u, 0x0000049fu, 0x00000029u, 0x000001abu, + 0x000001cfu, 0x000001b1u, 0x000500b1u, 0x0000004bu, 0x000001b4u, 0x0000049fu, 0x0000002eu, 0x000400f6u, + 0x000001b0u, 0x000001b1u, 0x00000000u, 0x000400fau, 0x000001b4u, 0x000001afu, 0x000001b0u, 0x000200f8u, + 0x000001afu, 0x000200f9u, 0x000001b6u, 0x000200f8u, 0x000001b6u, 0x000700f5u, 0x00000008u, 0x000004a0u, + 0x00000029u, 0x000001afu, 0x000001cdu, 0x000001b7u, 0x000500b1u, 0x0000004bu, 0x000001bcu, 0x000004a0u, + 0x000000c6u, 0x000400f6u, 0x000001b8u, 0x000001b7u, 0x00000000u, 0x000400fau, 0x000001bcu, 0x000001b7u, + 0x000001b8u, 0x000200f8u, 0x000001b7u, 0x0004003du, 0x000001bdu, 0x000001c0u, 0x000001bfu, 0x00050050u, + 0x00000009u, 0x000001c4u, 0x000004a0u, 0x0000049fu, 0x00050080u, 0x00000009u, 0x000001c5u, 0x0000019eu, + 0x000001c4u, 0x00050041u, 0x00000164u, 0x000001c6u, 0x00000163u, 0x0000002au, 0x0004003du, 0x00000008u, + 0x000001c7u, 0x000001c6u, 0x00050051u, 0x00000008u, 0x000001c9u, 0x000001c5u, 0x00000000u, 0x00050051u, + 0x00000008u, 0x000001cau, 0x000001c5u, 0x00000001u, 0x00060050u, 0x000001c8u, 0x000001cbu, 0x000001c9u, + 0x000001cau, 0x000001c7u, 0x00040063u, 0x000001c0u, 0x000001cbu, 0x00000055u, 0x00050080u, 0x00000008u, + 0x000001cdu, 0x000004a0u, 0x0000002au, 0x000200f9u, 0x000001b6u, 0x000200f8u, 0x000001b8u, 0x000200f9u, + 0x000001b1u, 0x000200f8u, 0x000001b1u, 0x00050080u, 0x00000008u, 0x000001cfu, 0x0000049fu, 0x0000002au, + 0x000200f9u, 0x000001aeu, 0x000200f8u, 0x000001b0u, 0x000200f9u, 0x00000357u, 0x000200f8u, 0x000001acu, + 0x00060041u, 0x000001a5u, 0x000001d7u, 0x000001d5u, 0x00000029u, 0x000001a7u, 0x0004003du, 0x00000006u, + 0x000001d8u, 0x000001d7u, 0x000500c7u, 0x00000006u, 0x000001dau, 0x000001d8u, 0x000001d9u, 0x00050080u, + 0x00000006u, 0x000001ddu, 0x000001a7u, 0x00000106u, 0x00060041u, 0x000001a5u, 0x000001deu, 0x000001d5u, + 0x00000029u, 0x000001ddu, 0x0004003du, 0x00000006u, 0x000001dfu, 0x000001deu, 0x000500c7u, 0x00000006u, + 0x000001e1u, 0x000001dfu, 0x000001e0u, 0x000500b0u, 0x0000004bu, 0x000001e4u, 0x0000015fu, 0x000001e3u, + 0x000300f7u, 0x000001e6u, 0x00000000u, 0x000400fau, 0x000001e4u, 0x000001e5u, 0x000001e6u, 0x000200f8u, + 0x000001e5u, 0x0004007cu, 0x00000008u, 0x000001ebu, 0x0000015fu, 0x000600cbu, 0x00000006u, 0x000001ecu, + 0x000001dau, 0x000001ebu, 0x0000002au, 0x000500abu, 0x0000004bu, 0x000001edu, 0x000001ecu, 0x0000004fu, + 0x000300f7u, 0x000001efu, 0x00000000u, 0x000400fau, 0x000001edu, 0x000001eeu, 0x000001efu, 0x000200f8u, + 0x000001eeu, 0x000600cbu, 0x00000006u, 0x000001f4u, 0x000001dau, 0x00000029u, 0x000001ebu, 0x000400cdu, + 0x00000008u, 0x000001f5u, 0x000001f4u, 0x0004007cu, 0x00000006u, 0x000001f6u, 0x000001f5u, 0x00050084u, + 0x00000006u, 0x000001fdu, 0x000001a7u, 0x0000011eu, 0x00050080u, 0x00000006u, 0x000001feu, 0x000001fdu, + 0x00000181u, 0x00050080u, 0x00000006u, 0x00000200u, 0x000001feu, 0x000001f6u, 0x00060041u, 0x00000201u, + 0x00000202u, 0x000001fbu, 0x00000029u, 0x00000200u, 0x0004003du, 0x000001f7u, 0x00000203u, 0x00000202u, + 0x00040071u, 0x00000006u, 0x00000204u, 0x00000203u, 0x00050084u, 0x00000006u, 0x00000206u, 0x000001a7u, + 0x00000181u, 0x00050080u, 0x00000006u, 0x00000207u, 0x00000206u, 0x0000008bu, 0x000400cdu, 0x00000008u, + 0x00000209u, 0x000001dau, 0x00050084u, 0x00000008u, 0x0000020au, 0x00000209u, 0x0000002eu, 0x0004007cu, + 0x00000006u, 0x0000020bu, 0x0000020au, 0x00050080u, 0x00000006u, 0x0000020cu, 0x00000207u, 0x0000020bu, + 0x00050080u, 0x00000006u, 0x0000020eu, 0x0000020cu, 0x000001f6u, 0x00060041u, 0x00000083u, 0x0000020fu, + 0x00000081u, 0x00000029u, 0x0000020eu, 0x0004003du, 0x0000007du, 0x00000210u, 0x0000020fu, 0x00040071u, + 0x00000006u, 0x00000211u, 0x00000210u, 0x000500c7u, 0x00000006u, 0x00000213u, 0x00000211u, 0x00000212u, + 0x000200f9u, 0x000001efu, 0x000200f8u, 0x000001efu, 0x000700f5u, 0x00000006u, 0x0000046au, 0x0000004fu, + 0x000001e5u, 0x00000213u, 0x000001eeu, 0x000700f5u, 0x00000006u, 0x00000469u, 0x0000004fu, 0x000001e5u, + 0x00000204u, 0x000001eeu, 0x000500c7u, 0x00000006u, 0x00000216u, 0x00000469u, 0x0000005fu, 0x000500c7u, + 0x00000006u, 0x00000219u, 0x00000469u, 0x00000063u, 0x000500c2u, 0x00000006u, 0x0000021cu, 0x00000219u, + 0x0000002au, 0x000500c5u, 0x00000006u, 0x0000021fu, 0x00000219u, 0x0000021cu, 0x000400cdu, 0x00000008u, + 0x00000222u, 0x00000216u, 0x000400cdu, 0x00000008u, 0x00000224u, 0x0000021fu, 0x00050080u, 0x00000008u, + 0x00000225u, 0x00000222u, 0x00000224u, 0x0004007cu, 0x00000006u, 0x00000226u, 0x00000225u, 0x00050084u, + 0x00000006u, 0x00000228u, 0x0000046au, 0x0000008bu, 0x00050080u, 0x00000006u, 0x00000229u, 0x00000226u, + 0x00000228u, 0x00050084u, 0x00000006u, 0x0000022cu, 0x000001a7u, 0x00000181u, 0x00050080u, 0x00000006u, + 0x0000022du, 0x0000022cu, 0x0000008bu, 0x000400cdu, 0x00000008u, 0x0000022fu, 0x000001dau, 0x00050084u, + 0x00000008u, 0x00000230u, 0x00000031u, 0x0000022fu, 0x0004007cu, 0x00000006u, 0x00000231u, 0x00000230u, + 0x00050080u, 0x00000006u, 0x00000232u, 0x0000022du, 0x00000231u, 0x0006015du, 0x00000006u, 0x00000234u, + 0x00000114u, 0x00000001u, 0x00000229u, 0x00050080u, 0x00000006u, 0x00000235u, 0x00000232u, 0x00000234u, + 0x000500aau, 0x0000004bu, 0x00000237u, 0x0000015fu, 0x00000212u, 0x000300f7u, 0x00000239u, 0x00000000u, + 0x000400fau, 0x00000237u, 0x00000238u, 0x00000239u, 0x000200f8u, 0x00000238u, 0x00050084u, 0x00000006u, + 0x0000023cu, 0x0000008bu, 0x00000235u, 0x0003003eu, 0x0000023au, 0x0000023cu, 0x000200f9u, 0x00000239u, + 0x000200f8u, 0x00000239u, 0x00050082u, 0x00000006u, 0x00000243u, 0x00000235u, 0x00000229u, 0x00050041u, + 0x00000132u, 0x00000244u, 0x0000023fu, 0x0000015fu, 0x0003003eu, 0x00000244u, 0x00000243u, 0x000200f9u, + 0x000001e6u, 0x000200f8u, 0x000001e6u, 0x000400e0u, 0x0000011eu, 0x0000011eu, 0x00000124u, 0x0004007cu, + 0x00000008u, 0x00000247u, 0x00000184u, 0x000600cbu, 0x00000006u, 0x00000248u, 0x000001dau, 0x00000247u, + 0x0000002au, 0x000500abu, 0x0000004bu, 0x00000249u, 0x00000248u, 0x0000004fu, 0x000300f7u, 0x0000024bu, + 0x00000000u, 0x000400fau, 0x00000249u, 0x0000024au, 0x000002a2u, 0x000200f8u, 0x0000024au, 0x000600cbu, + 0x00000006u, 0x00000250u, 0x000001dau, 0x00000029u, 0x00000247u, 0x000400cdu, 0x00000008u, 0x00000251u, + 0x00000250u, 0x0004007cu, 0x00000006u, 0x00000252u, 0x00000251u, 0x00050084u, 0x00000006u, 0x00000255u, + 0x000001a7u, 0x0000011eu, 0x00050080u, 0x00000006u, 0x00000256u, 0x00000255u, 0x00000181u, 0x00050080u, + 0x00000006u, 0x00000258u, 0x00000256u, 0x00000252u, 0x00060041u, 0x00000201u, 0x00000259u, 0x000001fbu, + 0x00000029u, 0x00000258u, 0x0004003du, 0x000001f7u, 0x0000025au, 0x00000259u, 0x00040071u, 0x00000006u, + 0x0000025bu, 0x0000025au, 0x00050084u, 0x00000006u, 0x0000025eu, 0x000001a7u, 0x00000181u, 0x00050080u, + 0x00000006u, 0x0000025fu, 0x0000025eu, 0x0000008bu, 0x000400cdu, 0x00000008u, 0x00000261u, 0x000001dau, + 0x00050084u, 0x00000008u, 0x00000262u, 0x00000261u, 0x0000002eu, 0x0004007cu, 0x00000006u, 0x00000263u, + 0x00000262u, 0x00050080u, 0x00000006u, 0x00000264u, 0x0000025fu, 0x00000263u, 0x00050080u, 0x00000006u, + 0x00000266u, 0x00000264u, 0x00000252u, 0x00060041u, 0x00000083u, 0x00000267u, 0x00000081u, 0x00000029u, + 0x00000266u, 0x0004003du, 0x0000007du, 0x00000268u, 0x00000267u, 0x00040071u, 0x00000006u, 0x00000269u, + 0x00000268u, 0x000500c7u, 0x00000006u, 0x0000026cu, 0x00000269u, 0x00000212u, 0x00050041u, 0x00000132u, + 0x00000272u, 0x0000023fu, 0x00000184u, 0x0004003du, 0x00000006u, 0x00000273u, 0x00000272u, 0x000300f7u, + 0x00000404u, 0x00000000u, 0x000300fbu, 0x0000004fu, 0x0000038du, 0x000200f8u, 0x0000038du, 0x000500aau, + 0x0000004bu, 0x0000038fu, 0x0000025bu, 0x0000004fu, 0x000300f7u, 0x00000392u, 0x00000000u, 0x000400fau, + 0x0000038fu, 0x00000391u, 0x00000392u, 0x000200f8u, 0x00000391u, 0x000200f9u, 0x00000404u, 0x000200f8u, + 0x00000392u, 0x0004007cu, 0x00000008u, 0x00000394u, 0x00000178u, 0x00050084u, 0x00000008u, 0x00000395u, + 0x0000002eu, 0x00000394u, 0x000500c7u, 0x00000006u, 0x00000397u, 0x0000025bu, 0x0000005fu, 0x000500c7u, + 0x00000006u, 0x00000399u, 0x0000025bu, 0x00000063u, 0x000500c2u, 0x00000006u, 0x0000039bu, 0x00000399u, + 0x0000002au, 0x000500c5u, 0x00000006u, 0x0000039eu, 0x00000399u, 0x0000039bu, 0x000600cbu, 0x00000006u, + 0x000003a1u, 0x00000397u, 0x00000029u, 0x00000395u, 0x000400cdu, 0x00000008u, 0x000003a2u, 0x000003a1u, + 0x000600cbu, 0x00000006u, 0x000003a5u, 0x0000039eu, 0x00000029u, 0x00000395u, 0x000400cdu, 0x00000008u, + 0x000003a6u, 0x000003a5u, 0x00050080u, 0x00000008u, 0x000003a7u, 0x000003a2u, 0x000003a6u, 0x0004007cu, + 0x00000006u, 0x000003a8u, 0x000003a7u, 0x00050084u, 0x00000006u, 0x000003abu, 0x0000026cu, 0x00000178u, + 0x00050080u, 0x00000006u, 0x000003acu, 0x000003a8u, 0x000003abu, 0x00050080u, 0x00000006u, 0x000003aeu, + 0x000003acu, 0x00000273u, 0x00060041u, 0x00000083u, 0x000003b0u, 0x00000081u, 0x00000029u, 0x000003aeu, + 0x0004003du, 0x0000007du, 0x000003b1u, 0x000003b0u, 0x00040071u, 0x00000006u, 0x000003b2u, 0x000003b1u, + 0x000600cbu, 0x00000006u, 0x000003b5u, 0x0000025bu, 0x00000395u, 0x0000002eu, 0x0003003eu, 0x00000382u, + 0x0000008fu, 0x00050080u, 0x00000006u, 0x000003b8u, 0x0000026cu, 0x000003b5u, 0x0004007cu, 0x00000008u, + 0x000003b9u, 0x000003b8u, 0x00050082u, 0x00000008u, 0x000003bbu, 0x000003b9u, 0x0000002au, 0x000200f9u, + 0x000003bcu, 0x000200f8u, 0x000003bcu, 0x000700f5u, 0x00000006u, 0x00000474u, 0x000003aeu, 0x00000392u, + 0x000003d7u, 0x000003dcu, 0x000700f5u, 0x00000008u, 0x0000046bu, 0x000003bbu, 0x00000392u, 0x000003deu, + 0x000003dcu, 0x000700f5u, 0x00000006u, 0x00000477u, 0x000003b2u, 0x00000392u, 0x000003dbu, 0x000003dcu, + 0x000500afu, 0x0000004bu, 0x000003bfu, 0x0000046bu, 0x00000029u, 0x000400f6u, 0x000003dfu, 0x000003dcu, + 0x00000000u, 0x000400fau, 0x000003bfu, 0x000003c0u, 0x000003dfu, 0x000200f8u, 0x000003c0u, 0x000200f9u, + 0x000003c1u, 0x000200f8u, 0x000003c1u, 0x000700f5u, 0x00000008u, 0x00000472u, 0x00000029u, 0x000003c0u, + 0x000003d4u, 0x000003c5u, 0x000500b1u, 0x0000004bu, 0x000003c4u, 0x00000472u, 0x000000a6u, 0x000400f6u, + 0x000003d5u, 0x000003c5u, 0x00000000u, 0x000400fau, 0x000003c4u, 0x000003c5u, 0x000003d5u, 0x000200f8u, + 0x000003c5u, 0x000600cbu, 0x00000006u, 0x000003c8u, 0x00000477u, 0x00000472u, 0x0000002au, 0x0004007cu, + 0x00000008u, 0x000003c9u, 0x000003c8u, 0x00050041u, 0x00000058u, 0x000003ccu, 0x00000382u, 0x00000472u, + 0x0004003du, 0x00000008u, 0x000003cdu, 0x000003ccu, 0x000700c9u, 0x00000008u, 0x000003d0u, 0x000003cdu, + 0x000003c9u, 0x0000046bu, 0x0000002au, 0x0003003eu, 0x000003ccu, 0x000003d0u, 0x00050080u, 0x00000008u, + 0x000003d4u, 0x00000472u, 0x0000002au, 0x000200f9u, 0x000003c1u, 0x000200f8u, 0x000003d5u, 0x00050080u, + 0x00000006u, 0x000003d7u, 0x00000474u, 0x0000002au, 0x00060041u, 0x00000083u, 0x000003d9u, 0x00000081u, + 0x00000029u, 0x000003d7u, 0x0004003du, 0x0000007du, 0x000003dau, 0x000003d9u, 0x00040071u, 0x00000006u, + 0x000003dbu, 0x000003dau, 0x000200f9u, 0x000003dcu, 0x000200f8u, 0x000003dcu, 0x00050082u, 0x00000008u, + 0x000003deu, 0x0000046bu, 0x0000002au, 0x000200f9u, 0x000003bcu, 0x000200f8u, 0x000003dfu, 0x000200f9u, + 0x000003e0u, 0x000200f8u, 0x000003e0u, 0x000700f5u, 0x00000008u, 0x0000046cu, 0x00000029u, 0x000003dfu, + 0x00000401u, 0x000003ffu, 0x000500b1u, 0x0000004bu, 0x000003e3u, 0x0000046cu, 0x000000c6u, 0x000400f6u, + 0x00000402u, 0x000003ffu, 0x00000000u, 0x000400fau, 0x000003e3u, 0x000003e4u, 0x00000402u, 0x000200f8u, + 0x000003e4u, 0x000200f9u, 0x000003e5u, 0x000200f8u, 0x000003e5u, 0x000700f5u, 0x00000008u, 0x0000046du, + 0x00000029u, 0x000003e4u, 0x000003fdu, 0x000003fbu, 0x000500b1u, 0x0000004bu, 0x000003e8u, 0x0000046du, + 0x0000002eu, 0x000400f6u, 0x000003feu, 0x000003fbu, 0x00000000u, 0x000400fau, 0x000003e8u, 0x000003e9u, + 0x000003feu, 0x000200f8u, 0x000003e9u, 0x00050084u, 0x00000008u, 0x000003ebu, 0x0000046cu, 0x0000002eu, + 0x00050080u, 0x00000008u, 0x000003edu, 0x000003ebu, 0x0000046du, 0x00050041u, 0x00000058u, 0x000003eeu, + 0x00000382u, 0x000003edu, 0x0004003du, 0x00000008u, 0x000003efu, 0x000003eeu, 0x0004006fu, 0x0000000eu, + 0x000003f0u, 0x000003efu, 0x000500b7u, 0x0000004bu, 0x000003f2u, 0x000003f0u, 0x00000054u, 0x000300f7u, + 0x000003f6u, 0x00000000u, 0x000400fau, 0x000003f2u, 0x000003f3u, 0x000003f6u, 0x000200f8u, 0x000003f3u, + 0x00050081u, 0x0000000eu, 0x000003f5u, 0x000003f0u, 0x000000ddu, 0x000200f9u, 0x000003f6u, 0x000200f8u, + 0x000003f6u, 0x000700f5u, 0x0000000eu, 0x00000471u, 0x000003f0u, 0x000003e9u, 0x000003f5u, 0x000003f3u, + 0x00060041u, 0x000000d0u, 0x000003fau, 0x0000038au, 0x0000046du, 0x0000046cu, 0x0003003eu, 0x000003fau, + 0x00000471u, 0x000200f9u, 0x000003fbu, 0x000200f8u, 0x000003fbu, 0x00050080u, 0x00000008u, 0x000003fdu, + 0x0000046du, 0x0000002au, 0x000200f9u, 0x000003e5u, 0x000200f8u, 0x000003feu, 0x000200f9u, 0x000003ffu, + 0x000200f8u, 0x000003ffu, 0x00050080u, 0x00000008u, 0x00000401u, 0x0000046cu, 0x0000002au, 0x000200f9u, + 0x000003e0u, 0x000200f8u, 0x00000402u, 0x0004003du, 0x00000014u, 0x00000403u, 0x0000038au, 0x000200f9u, + 0x00000404u, 0x000200f8u, 0x00000404u, 0x000700f5u, 0x00000014u, 0x00000478u, 0x00000056u, 0x00000391u, + 0x00000403u, 0x00000402u, 0x0003003eu, 0x0000026au, 0x00000478u, 0x000200f9u, 0x00000279u, 0x000200f8u, + 0x00000279u, 0x000700f5u, 0x00000008u, 0x0000047bu, 0x00000029u, 0x00000404u, 0x0000049eu, 0x0000027cu, + 0x000700f5u, 0x00000008u, 0x00000479u, 0x00000029u, 0x00000404u, 0x00000293u, 0x0000027cu, 0x000500b1u, + 0x0000004bu, 0x0000027fu, 0x00000479u, 0x0000002eu, 0x000400f6u, 0x0000027bu, 0x0000027cu, 0x00000000u, + 0x000400fau, 0x0000027fu, 0x0000027au, 0x0000027bu, 0x000200f8u, 0x0000027au, 0x000200f9u, 0x00000281u, + 0x000200f8u, 0x00000281u, 0x000700f5u, 0x00000008u, 0x0000049eu, 0x0000047bu, 0x0000027au, 0x0000028fu, + 0x00000282u, 0x000700f5u, 0x00000008u, 0x0000049cu, 0x00000029u, 0x0000027au, 0x00000291u, 0x00000282u, + 0x000500b1u, 0x0000004bu, 0x00000287u, 0x0000049cu, 0x000000c6u, 0x000400f6u, 0x00000283u, 0x00000282u, + 0x00000000u, 0x000400fau, 0x00000287u, 0x00000282u, 0x00000283u, 0x000200f8u, 0x00000282u, 0x00060041u, + 0x000000d0u, 0x0000028au, 0x0000026au, 0x00000479u, 0x0000049cu, 0x0004003du, 0x0000000eu, 0x0000028bu, + 0x0000028au, 0x000500b7u, 0x0000004bu, 0x0000028cu, 0x0000028bu, 0x00000054u, 0x000600a9u, 0x00000008u, + 0x0000028du, 0x0000028cu, 0x0000002au, 0x00000029u, 0x00050080u, 0x00000008u, 0x0000028fu, 0x0000049eu, + 0x0000028du, 0x00050080u, 0x00000008u, 0x00000291u, 0x0000049cu, 0x0000002au, 0x000200f9u, 0x00000281u, + 0x000200f8u, 0x00000283u, 0x000200f9u, 0x0000027cu, 0x000200f8u, 0x0000027cu, 0x00050080u, 0x00000008u, + 0x00000293u, 0x00000479u, 0x0000002au, 0x000200f9u, 0x00000279u, 0x000200f8u, 0x0000027bu, 0x000500c2u, + 0x00000006u, 0x0000040cu, 0x000001e1u, 0x00000031u, 0x0004007cu, 0x00000008u, 0x0000040du, 0x0000040cu, + 0x0004007cu, 0x00000008u, 0x00000410u, 0x000001e1u, 0x000500c7u, 0x00000008u, 0x00000411u, 0x00000410u, + 0x000000f5u, 0x00050080u, 0x00000008u, 0x00000413u, 0x000000a6u, 0x00000411u, 0x00050082u, 0x00000008u, + 0x00000415u, 0x000004aau, 0x0000040du, 0x000500c4u, 0x00000008u, 0x00000416u, 0x0000002au, 0x00000415u, + 0x00050084u, 0x00000008u, 0x00000417u, 0x00000413u, 0x00000416u, 0x0004006fu, 0x0000000eu, 0x00000418u, + 0x00000417u, 0x00050085u, 0x0000000eu, 0x00000419u, 0x000000f8u, 0x00000418u, 0x000600cbu, 0x00000006u, + 0x0000029bu, 0x00000269u, 0x000000c6u, 0x000000c6u, 0x00040070u, 0x0000000eu, 0x0000041eu, 0x0000029bu, + 0x00050085u, 0x0000000eu, 0x0000041fu, 0x0000041eu, 0x000004abu, 0x00050081u, 0x0000000eu, 0x00000420u, + 0x0000041fu, 0x00000047u, 0x00050085u, 0x0000000eu, 0x0000029eu, 0x00000419u, 0x00000420u, 0x0004003du, + 0x00000014u, 0x000002a0u, 0x0000026au, 0x0005008fu, 0x00000014u, 0x000002a1u, 0x000002a0u, 0x0000029eu, + 0x0003003eu, 0x0000026au, 0x000002a1u, 0x000200f9u, 0x0000024bu, 0x000200f8u, 0x000002a2u, 0x0003003eu, + 0x0000026au, 0x00000056u, 0x000200f9u, 0x0000024bu, 0x000200f8u, 0x0000024bu, 0x000700f5u, 0x00000008u, + 0x0000047au, 0x0000047bu, 0x0000027bu, 0x00000029u, 0x000002a2u, 0x0006015du, 0x00000008u, 0x000002a5u, + 0x00000114u, 0x00000001u, 0x0000047au, 0x00050082u, 0x00000006u, 0x000002a8u, 0x0000015cu, 0x00000106u, + 0x000500aau, 0x0000004bu, 0x000002a9u, 0x0000015eu, 0x000002a8u, 0x000300f7u, 0x000002abu, 0x00000000u, + 0x000400fau, 0x000002a9u, 0x000002aau, 0x000002abu, 0x000200f8u, 0x000002aau, 0x0004007cu, 0x00000006u, + 0x000002aeu, 0x000002a5u, 0x00050041u, 0x00000132u, 0x000002afu, 0x00000130u, 0x0000015au, 0x0003003eu, + 0x000002afu, 0x000002aeu, 0x000200f9u, 0x000002abu, 0x000200f8u, 0x000002abu, 0x0004003du, 0x00000006u, + 0x000002b0u, 0x0000010eu, 0x000500b2u, 0x0000004bu, 0x000002b1u, 0x000002b0u, 0x0000008bu, 0x000300f7u, + 0x000002b3u, 0x00000000u, 0x000400fau, 0x000002b1u, 0x000002b2u, 0x000002d0u, 0x000200f8u, 0x000002b2u, + 0x000400e0u, 0x0000011eu, 0x0000011eu, 0x00000124u, 0x000500b2u, 0x0000004bu, 0x000002b5u, 0x0000015cu, + 0x0000012du, 0x000300f7u, 0x000002b7u, 0x00000000u, 0x000400fau, 0x000002b5u, 0x000002b6u, 0x000002c3u, + 0x000200f8u, 0x000002b6u, 0x000500b0u, 0x0000004bu, 0x000002bau, 0x0000015fu, 0x000002b0u, 0x000300f7u, + 0x000002bcu, 0x00000000u, 0x000400fau, 0x000002bau, 0x000002bbu, 0x000002bcu, 0x000200f8u, 0x000002bbu, + 0x00050041u, 0x00000132u, 0x000002bfu, 0x00000130u, 0x0000015fu, 0x0004003du, 0x00000006u, 0x000002c0u, + 0x000002bfu, 0x0006015du, 0x00000006u, 0x000002c1u, 0x00000114u, 0x00000001u, 0x000002c0u, 0x0003003eu, + 0x000002bfu, 0x000002c1u, 0x000200f9u, 0x000002bcu, 0x000200f8u, 0x000002bcu, 0x000200f9u, 0x000002b7u, + 0x000200f8u, 0x000002c3u, 0x000500b0u, 0x0000004bu, 0x000002c6u, 0x0000015fu, 0x000002b0u, 0x000300f7u, + 0x000002c8u, 0x00000000u, 0x000400fau, 0x000002c6u, 0x000002c7u, 0x000002c8u, 0x000200f8u, 0x000002c7u, + 0x00050041u, 0x00000132u, 0x000002ccu, 0x00000130u, 0x0000015fu, 0x0004003du, 0x00000006u, 0x000002cdu, + 0x000002ccu, 0x000200f9u, 0x00000425u, 0x000200f8u, 0x00000425u, 0x000700f5u, 0x00000006u, 0x00000484u, + 0x000002cdu, 0x000002c7u, 0x00000434u, 0x0000042au, 0x000700f5u, 0x00000006u, 0x00000483u, 0x00000106u, + 0x000002c7u, 0x00000437u, 0x0000042au, 0x000500b0u, 0x0000004bu, 0x00000429u, 0x00000483u, 0x000002b0u, + 0x000400f6u, 0x00000438u, 0x0000042au, 0x00000000u, 0x000400fau, 0x00000429u, 0x0000042au, 0x00000438u, + 0x000200f8u, 0x0000042au, 0x0006015bu, 0x00000006u, 0x0000042du, 0x00000114u, 0x00000484u, 0x00000483u, + 0x000500aeu, 0x0000004bu, 0x00000430u, 0x0000015eu, 0x00000483u, 0x000600a9u, 0x00000006u, 0x00000432u, + 0x00000430u, 0x0000042du, 0x0000004fu, 0x00050080u, 0x00000006u, 0x00000434u, 0x00000484u, 0x00000432u, + 0x00050084u, 0x00000006u, 0x00000437u, 0x00000483u, 0x0000011eu, 0x000200f9u, 0x00000425u, 0x000200f8u, + 0x00000438u, 0x0003003eu, 0x000002ccu, 0x00000484u, 0x000200f9u, 0x000002c8u, 0x000200f8u, 0x000002c8u, + 0x000200f9u, 0x000002b7u, 0x000200f8u, 0x000002b7u, 0x000400e0u, 0x0000011eu, 0x0000011eu, 0x00000124u, + 0x000200f9u, 0x000002b3u, 0x000200f8u, 0x000002d0u, 0x000400e0u, 0x0000011eu, 0x0000011eu, 0x00000124u, + 0x000500b0u, 0x0000004bu, 0x00000442u, 0x0000015fu, 0x000002b0u, 0x000300f7u, 0x00000448u, 0x00000000u, + 0x000400fau, 0x00000442u, 0x00000444u, 0x00000448u, 0x000200f8u, 0x00000444u, 0x00050041u, 0x00000132u, + 0x00000446u, 0x00000130u, 0x0000015fu, 0x0004003du, 0x00000006u, 0x00000447u, 0x00000446u, 0x000200f9u, + 0x00000448u, 0x000200f8u, 0x00000448u, 0x000700f5u, 0x00000006u, 0x00000480u, 0x0000004fu, 0x000002d0u, + 0x00000447u, 0x00000444u, 0x000200f9u, 0x00000449u, 0x000200f8u, 0x00000449u, 0x000700f5u, 0x00000006u, + 0x0000047fu, 0x00000480u, 0x00000448u, 0x000004a2u, 0x00000465u, 0x000700f5u, 0x00000006u, 0x0000047cu, + 0x00000106u, 0x00000448u, 0x00000467u, 0x00000465u, 0x000500b0u, 0x0000004bu, 0x0000044du, 0x0000047cu, + 0x000002b0u, 0x000400f6u, 0x00000468u, 0x00000465u, 0x00000000u, 0x000400fau, 0x0000044du, 0x0000044eu, + 0x00000468u, 0x000200f8u, 0x0000044eu, 0x000500aeu, 0x0000004bu, 0x00000451u, 0x0000015fu, 0x0000047cu, + 0x000500a7u, 0x0000004bu, 0x00000453u, 0x00000451u, 0x00000442u, 0x000300f7u, 0x0000045bu, 0x00000000u, + 0x000400fau, 0x00000453u, 0x00000455u, 0x0000045bu, 0x000200f8u, 0x00000455u, 0x00050082u, 0x00000006u, + 0x00000458u, 0x0000015fu, 0x0000047cu, 0x00050041u, 0x00000132u, 0x00000459u, 0x00000130u, 0x00000458u, + 0x0004003du, 0x00000006u, 0x0000045au, 0x00000459u, 0x000200f9u, 0x0000045bu, 0x000200f8u, 0x0000045bu, + 0x000700f5u, 0x00000006u, 0x0000047du, 0x0000004fu, 0x0000044eu, 0x0000045au, 0x00000455u, 0x000400e0u, + 0x0000011eu, 0x0000011eu, 0x00000124u, 0x000300f7u, 0x00000464u, 0x00000000u, 0x000400fau, 0x00000453u, + 0x0000045du, 0x00000464u, 0x000200f8u, 0x0000045du, 0x00050080u, 0x00000006u, 0x00000460u, 0x0000047fu, + 0x0000047du, 0x00050041u, 0x00000132u, 0x00000463u, 0x00000130u, 0x0000015fu, 0x0003003eu, 0x00000463u, + 0x00000460u, 0x000200f9u, 0x00000464u, 0x000200f8u, 0x00000464u, 0x000700f5u, 0x00000006u, 0x000004a2u, + 0x0000047fu, 0x0000045bu, 0x00000460u, 0x0000045du, 0x000400e0u, 0x0000011eu, 0x0000011eu, 0x00000124u, + 0x000200f9u, 0x00000465u, 0x000200f8u, 0x00000465u, 0x00050084u, 0x00000006u, 0x00000467u, 0x0000047cu, + 0x0000011eu, 0x000200f9u, 0x00000449u, 0x000200f8u, 0x00000468u, 0x000200f9u, 0x000002b3u, 0x000200f8u, + 0x000002b3u, 0x0004003du, 0x00000006u, 0x000002d5u, 0x0000023au, 0x0004007cu, 0x00000006u, 0x000002d7u, + 0x000002a5u, 0x00050080u, 0x00000006u, 0x000002d8u, 0x000002d5u, 0x000002d7u, 0x0004007cu, 0x00000006u, + 0x000002dau, 0x0000047au, 0x00050082u, 0x00000006u, 0x000002dbu, 0x000002d8u, 0x000002dau, 0x000500abu, + 0x0000004bu, 0x000002ddu, 0x0000015au, 0x0000004fu, 0x000300f7u, 0x000002dfu, 0x00000000u, 0x000400fau, + 0x000002ddu, 0x000002deu, 0x000002dfu, 0x000200f8u, 0x000002deu, 0x00050082u, 0x00000006u, 0x000002e1u, + 0x0000015au, 0x00000106u, 0x00050041u, 0x00000132u, 0x000002e2u, 0x00000130u, 0x000002e1u, 0x0004003du, + 0x00000006u, 0x000002e3u, 0x000002e2u, 0x00050080u, 0x00000006u, 0x000002e5u, 0x000002dbu, 0x000002e3u, + 0x000200f9u, 0x000002dfu, 0x000200f8u, 0x000002dfu, 0x000700f5u, 0x00000006u, 0x0000048fu, 0x000002dbu, + 0x000002b3u, 0x000002e5u, 0x000002deu, 0x00050086u, 0x00000006u, 0x000002e8u, 0x0000048fu, 0x0000012du, + 0x00060041u, 0x000001a5u, 0x000002eau, 0x000001d5u, 0x00000029u, 0x000002e8u, 0x0004003du, 0x00000006u, + 0x000002ebu, 0x000002eau, 0x00050080u, 0x00000006u, 0x000002efu, 0x000002e8u, 0x00000106u, 0x00060041u, + 0x000001a5u, 0x000002f0u, 0x000001d5u, 0x00000029u, 0x000002efu, 0x0004003du, 0x00000006u, 0x000002f1u, + 0x000002f0u, 0x000500c7u, 0x00000006u, 0x000002f5u, 0x0000048fu, 0x000002f4u, 0x000500abu, 0x0000004bu, + 0x000002f7u, 0x000002f5u, 0x0000004fu, 0x000300f7u, 0x000002f9u, 0x00000000u, 0x000400fau, 0x000002f7u, + 0x000002f8u, 0x000002f9u, 0x000200f8u, 0x000002f8u, 0x000500c2u, 0x00000006u, 0x000002fcu, 0x000002ebu, + 0x000002f5u, 0x00050082u, 0x00000006u, 0x000002ffu, 0x0000012du, 0x000002f5u, 0x000500c4u, 0x00000006u, + 0x00000300u, 0x000002f1u, 0x000002ffu, 0x000500c5u, 0x00000006u, 0x00000302u, 0x000002fcu, 0x00000300u, + 0x000200f9u, 0x000002f9u, 0x000200f8u, 0x000002f9u, 0x000700f5u, 0x00000006u, 0x00000498u, 0x000002ebu, + 0x000002dfu, 0x00000302u, 0x000002f8u, 0x000200f9u, 0x00000305u, 0x000200f8u, 0x00000305u, 0x000700f5u, + 0x00000008u, 0x00000490u, 0x00000029u, 0x000002f9u, 0x0000032eu, 0x00000308u, 0x000700f5u, 0x00000008u, + 0x0000049au, 0x00000029u, 0x000002f9u, 0x00000499u, 0x00000308u, 0x000500b1u, 0x0000004bu, 0x0000030bu, + 0x00000490u, 0x000000c6u, 0x000400f6u, 0x00000307u, 0x00000308u, 0x00000000u, 0x000400fau, 0x0000030bu, + 0x00000306u, 0x00000307u, 0x000200f8u, 0x00000306u, 0x000200f9u, 0x0000030du, 0x000200f8u, 0x0000030du, + 0x000700f5u, 0x00000008u, 0x00000499u, 0x0000049au, 0x00000306u, 0x000004a5u, 0x00000310u, 0x000700f5u, + 0x00000008u, 0x00000494u, 0x00000029u, 0x00000306u, 0x0000032cu, 0x00000310u, 0x000500b1u, 0x0000004bu, + 0x00000313u, 0x00000494u, 0x0000002eu, 0x000400f6u, 0x0000030fu, 0x00000310u, 0x00000000u, 0x000400fau, + 0x00000313u, 0x0000030eu, 0x0000030fu, 0x000200f8u, 0x0000030eu, 0x00060041u, 0x000000d0u, 0x00000316u, + 0x0000026au, 0x00000494u, 0x00000490u, 0x0004003du, 0x0000000eu, 0x00000317u, 0x00000316u, 0x000500b7u, + 0x0000004bu, 0x00000318u, 0x00000317u, 0x00000054u, 0x000300f7u, 0x0000031au, 0x00000000u, 0x000400fau, + 0x00000318u, 0x00000319u, 0x0000031au, 0x000200f8u, 0x00000319u, 0x000600cbu, 0x00000006u, 0x00000321u, + 0x00000498u, 0x00000499u, 0x0000002au, 0x00040070u, 0x0000000eu, 0x00000322u, 0x00000321u, 0x00050085u, + 0x0000000eu, 0x00000323u, 0x0000031eu, 0x00000322u, 0x00050083u, 0x0000000eu, 0x00000324u, 0x0000031du, + 0x00000323u, 0x0004003du, 0x0000000eu, 0x00000326u, 0x00000316u, 0x00050085u, 0x0000000eu, 0x00000327u, + 0x00000326u, 0x00000324u, 0x0003003eu, 0x00000316u, 0x00000327u, 0x00050080u, 0x00000008u, 0x0000032au, + 0x00000499u, 0x0000002au, 0x000200f9u, 0x0000031au, 0x000200f8u, 0x0000031au, 0x000700f5u, 0x00000008u, + 0x000004a5u, 0x00000499u, 0x0000030eu, 0x0000032au, 0x00000319u, 0x000200f9u, 0x00000310u, 0x000200f8u, + 0x00000310u, 0x00050080u, 0x00000008u, 0x0000032cu, 0x00000494u, 0x0000002au, 0x000200f9u, 0x0000030du, + 0x000200f8u, 0x0000030fu, 0x000200f9u, 0x00000308u, 0x000200f8u, 0x00000308u, 0x00050080u, 0x00000008u, + 0x0000032eu, 0x00000490u, 0x0000002au, 0x000200f9u, 0x00000305u, 0x000200f8u, 0x00000307u, 0x000200f9u, + 0x00000330u, 0x000200f8u, 0x00000330u, 0x000700f5u, 0x00000008u, 0x00000491u, 0x00000029u, 0x00000307u, + 0x00000352u, 0x00000333u, 0x000500b1u, 0x0000004bu, 0x00000336u, 0x00000491u, 0x0000002eu, 0x000400f6u, + 0x00000332u, 0x00000333u, 0x00000000u, 0x000400fau, 0x00000336u, 0x00000331u, 0x00000332u, 0x000200f8u, + 0x00000331u, 0x000200f9u, 0x00000338u, 0x000200f8u, 0x00000338u, 0x000700f5u, 0x00000008u, 0x00000492u, + 0x00000029u, 0x00000331u, 0x00000350u, 0x00000339u, 0x000500b1u, 0x0000004bu, 0x0000033eu, 0x00000492u, + 0x000000c6u, 0x000400f6u, 0x0000033au, 0x00000339u, 0x00000000u, 0x000400fau, 0x0000033eu, 0x00000339u, + 0x0000033au, 0x000200f8u, 0x00000339u, 0x0004003du, 0x000001bdu, 0x0000033fu, 0x000001bfu, 0x00050050u, + 0x00000009u, 0x00000343u, 0x00000492u, 0x00000491u, 0x00050080u, 0x00000009u, 0x00000344u, 0x0000019eu, + 0x00000343u, 0x00050041u, 0x00000164u, 0x00000345u, 0x00000163u, 0x0000002au, 0x0004003du, 0x00000008u, + 0x00000346u, 0x00000345u, 0x00050051u, 0x00000008u, 0x00000347u, 0x00000344u, 0x00000000u, 0x00050051u, + 0x00000008u, 0x00000348u, 0x00000344u, 0x00000001u, 0x00060050u, 0x000001c8u, 0x00000349u, 0x00000347u, + 0x00000348u, 0x00000346u, 0x00060041u, 0x000000d0u, 0x0000034cu, 0x0000026au, 0x00000491u, 0x00000492u, + 0x0004003du, 0x0000000eu, 0x0000034du, 0x0000034cu, 0x00070050u, 0x00000013u, 0x0000034eu, 0x0000034du, + 0x0000034du, 0x0000034du, 0x0000034du, 0x00040063u, 0x0000033fu, 0x00000349u, 0x0000034eu, 0x00050080u, + 0x00000008u, 0x00000350u, 0x00000492u, 0x0000002au, 0x000200f9u, 0x00000338u, 0x000200f8u, 0x0000033au, + 0x000200f9u, 0x00000333u, 0x000200f8u, 0x00000333u, 0x00050080u, 0x00000008u, 0x00000352u, 0x00000491u, + 0x0000002au, 0x000200f9u, 0x00000330u, 0x000200f8u, 0x00000332u, 0x000200f9u, 0x00000357u, 0x000200f8u, + 0x00000357u, 0x000100fdu, 0x00010038u, 0x07230203u, 0x00010300u, 0x000d000bu, 0x0000051eu, 0x00000000u, + 0x00020011u, 0x00000001u, 0x00020011u, 0x0000002eu, 0x00020011u, 0x00000038u, 0x00020011u, 0x0000003du, + 0x00020011u, 0x0000003fu, 0x00020011u, 0x00000042u, 0x0006000bu, 0x00000001u, 0x4c534c47u, 0x6474732eu, + 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x000a000fu, 0x00000005u, 0x00000004u, + 0x6e69616du, 0x00000000u, 0x00000132u, 0x0000013au, 0x0000017du, 0x0000017fu, 0x0000018eu, 0x00060010u, + 0x00000004u, 0x00000011u, 0x00000080u, 0x00000001u, 0x00000001u, 0x00030047u, 0x00000059u, 0x00000000u, + 0x00040047u, 0x00000059u, 0x00000021u, 0x00000004u, 0x00040047u, 0x00000059u, 0x00000022u, 0x00000000u, + 0x00030047u, 0x00000065u, 0x00000000u, 0x00040047u, 0x00000065u, 0x00000021u, 0x00000003u, 0x00040047u, + 0x00000065u, 0x00000022u, 0x00000000u, 0x00040047u, 0x0000006fu, 0x00000021u, 0x00000002u, 0x00040047u, + 0x0000006fu, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000132u, 0x0000000bu, 0x00000026u, 0x00030047u, + 0x0000013au, 0x00000000u, 0x00040047u, 0x0000013au, 0x0000000bu, 0x00000029u, 0x00040047u, 0x0000017du, + 0x0000000bu, 0x00000028u, 0x00030047u, 0x0000017fu, 0x00000000u, 0x00040047u, 0x0000017fu, 0x0000000bu, + 0x00000024u, 0x00030047u, 0x00000180u, 0x00000000u, 0x00030047u, 0x00000182u, 0x00000000u, 0x00030047u, + 0x00000185u, 0x00000002u, 0x00050048u, 0x00000185u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, + 0x00000185u, 0x00000001u, 0x00000023u, 0x00000008u, 0x00050048u, 0x00000185u, 0x00000002u, 0x00000023u, + 0x0000000cu, 0x00050048u, 0x00000185u, 0x00000003u, 0x00000023u, 0x00000010u, 0x00040047u, 0x0000018eu, + 0x0000000bu, 0x0000001au, 0x00040047u, 0x000001c4u, 0x00000006u, 0x00000004u, 0x00030047u, 0x000001c5u, + 0x00000002u, 0x00040048u, 0x000001c5u, 0x00000000u, 0x00000018u, 0x00050048u, 0x000001c5u, 0x00000000u, + 0x00000023u, 0x00000000u, 0x00030047u, 0x000001c7u, 0x00000018u, 0x00040047u, 0x000001c7u, 0x00000021u, + 0x00000001u, 0x00040047u, 0x000001c7u, 0x00000022u, 0x00000000u, 0x00030047u, 0x000001e3u, 0x00000019u, + 0x00040047u, 0x000001e3u, 0x00000021u, 0x00000000u, 0x00040047u, 0x000001e3u, 0x00000022u, 0x00000000u, + 0x00030047u, 0x000002c2u, 0x00000000u, 0x00040047u, 0x00000370u, 0x0000000bu, 0x00000019u, 0x00030047u, + 0x00000397u, 0x00000000u, 0x00030047u, 0x0000039au, 0x00000000u, 0x00030047u, 0x0000039bu, 0x00000000u, + 0x00030047u, 0x000003a0u, 0x00000000u, 0x00030047u, 0x000003a3u, 0x00000000u, 0x00030047u, 0x000003a4u, + 0x00000000u, 0x00030047u, 0x000003a9u, 0x00000000u, 0x00030047u, 0x000003acu, 0x00000000u, 0x00030047u, + 0x000003adu, 0x00000000u, 0x00030047u, 0x000003b2u, 0x00000000u, 0x00030047u, 0x000003b5u, 0x00000000u, + 0x00030047u, 0x000003b6u, 0x00000000u, 0x00030047u, 0x000003bbu, 0x00000000u, 0x00030047u, 0x000003beu, + 0x00000000u, 0x00030047u, 0x000003bfu, 0x00000000u, 0x00030047u, 0x000003c4u, 0x00000000u, 0x00030047u, + 0x000003c7u, 0x00000000u, 0x00030047u, 0x000003c8u, 0x00000000u, 0x00030047u, 0x0000045bu, 0x00000000u, + 0x00030047u, 0x0000045eu, 0x00000000u, 0x00030047u, 0x0000045fu, 0x00000000u, 0x00030047u, 0x00000464u, + 0x00000000u, 0x00030047u, 0x00000467u, 0x00000000u, 0x00030047u, 0x00000468u, 0x00000000u, 0x00020013u, + 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, 0x00000020u, 0x00000000u, + 0x00040015u, 0x00000008u, 0x00000020u, 0x00000001u, 0x00040017u, 0x00000009u, 0x00000008u, 0x00000002u, + 0x00030016u, 0x0000000eu, 0x00000020u, 0x00040020u, 0x00000013u, 0x00000007u, 0x00000008u, 0x00040017u, + 0x0000001eu, 0x0000000eu, 0x00000004u, 0x00040018u, 0x0000001fu, 0x0000001eu, 0x00000002u, 0x0004002bu, + 0x00000008u, 0x00000034u, 0x00000000u, 0x0004002bu, 0x00000008u, 0x00000035u, 0x00000001u, 0x0004002bu, + 0x00000008u, 0x00000039u, 0x00000002u, 0x0004002bu, 0x00000008u, 0x0000003cu, 0x00000003u, 0x0004002bu, + 0x00000008u, 0x00000042u, 0x00000005u, 0x0004002bu, 0x0000000eu, 0x00000052u, 0x3e800000u, 0x00090019u, + 0x00000056u, 0x00000006u, 0x00000005u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, + 0x0003001bu, 0x00000057u, 0x00000056u, 0x00040020u, 0x00000058u, 0x00000000u, 0x00000057u, 0x0004003bu, + 0x00000058u, 0x00000059u, 0x00000000u, 0x00040017u, 0x0000005du, 0x00000006u, 0x00000004u, 0x0004002bu, + 0x00000006u, 0x0000005fu, 0x00000000u, 0x0004003bu, 0x00000058u, 0x00000065u, 0x00000000u, 0x0004003bu, + 0x00000058u, 0x0000006fu, 0x00000000u, 0x00020014u, 0x00000077u, 0x0004002bu, 0x0000000eu, 0x0000007fu, + 0x00000000u, 0x0007002cu, 0x0000001eu, 0x00000080u, 0x0000007fu, 0x0000007fu, 0x0000007fu, 0x0000007fu, + 0x0005002cu, 0x0000001fu, 0x00000081u, 0x00000080u, 0x00000080u, 0x0004002bu, 0x00000006u, 0x00000089u, + 0x00005555u, 0x0004002bu, 0x00000006u, 0x0000008du, 0x0000aaaau, 0x0004002bu, 0x00000006u, 0x000000afu, + 0x00000008u, 0x0004001cu, 0x000000b0u, 0x00000008u, 0x000000afu, 0x00040020u, 0x000000b1u, 0x00000007u, + 0x000000b0u, 0x000b002cu, 0x000000b0u, 0x000000b3u, 0x00000034u, 0x00000034u, 0x00000034u, 0x00000034u, + 0x00000034u, 0x00000034u, 0x00000034u, 0x00000034u, 0x0004002bu, 0x00000008u, 0x000000cau, 0x00000008u, + 0x0004002bu, 0x00000008u, 0x000000eau, 0x00000004u, 0x00040020u, 0x000000f4u, 0x00000007u, 0x0000000eu, + 0x0004002bu, 0x0000000eu, 0x00000101u, 0x3f000000u, 0x00040020u, 0x00000104u, 0x00000007u, 0x0000001fu, + 0x0004002bu, 0x00000008u, 0x00000119u, 0x00000007u, 0x0004002bu, 0x0000000eu, 0x0000011cu, 0x34000000u, + 0x0004002bu, 0x00000006u, 0x0000012au, 0x00000001u, 0x00040020u, 0x00000131u, 0x00000001u, 0x00000006u, + 0x0004003bu, 0x00000131u, 0x00000132u, 0x00000001u, 0x0004002bu, 0x00000006u, 0x00000138u, 0x00000003u, + 0x0004003bu, 0x00000131u, 0x0000013au, 0x00000001u, 0x0004002bu, 0x00000006u, 0x00000142u, 0x00000002u, + 0x0004002bu, 0x00000006u, 0x00000148u, 0x00000108u, 0x0004002bu, 0x00000006u, 0x00000151u, 0x00000020u, + 0x0004001cu, 0x00000152u, 0x00000006u, 0x00000151u, 0x00040020u, 0x00000153u, 0x00000004u, 0x00000152u, + 0x0004003bu, 0x00000153u, 0x00000154u, 0x00000004u, 0x00040020u, 0x00000156u, 0x00000004u, 0x00000006u, + 0x0004003bu, 0x00000131u, 0x0000017du, 0x00000001u, 0x0004003bu, 0x00000131u, 0x0000017fu, 0x00000001u, + 0x0006001eu, 0x00000185u, 0x00000009u, 0x00000008u, 0x00000008u, 0x00000008u, 0x00040020u, 0x00000186u, + 0x00000009u, 0x00000185u, 0x0004003bu, 0x00000186u, 0x00000187u, 0x00000009u, 0x00040020u, 0x00000188u, + 0x00000009u, 0x00000008u, 0x00040017u, 0x0000018cu, 0x00000006u, 0x00000003u, 0x00040020u, 0x0000018du, + 0x00000001u, 0x0000018cu, 0x0004003bu, 0x0000018du, 0x0000018eu, 0x00000001u, 0x0004002bu, 0x00000006u, + 0x000001a5u, 0x00000004u, 0x00040017u, 0x000001b0u, 0x00000006u, 0x00000002u, 0x0004002bu, 0x00000008u, + 0x000001b4u, 0x00000020u, 0x0003001du, 0x000001c4u, 0x00000006u, 0x0003001eu, 0x000001c5u, 0x000001c4u, + 0x00040020u, 0x000001c6u, 0x0000000cu, 0x000001c5u, 0x0004003bu, 0x000001c6u, 0x000001c7u, 0x0000000cu, + 0x00040020u, 0x000001c9u, 0x0000000cu, 0x00000006u, 0x0004002bu, 0x00000006u, 0x000001cdu, 0xffffffffu, + 0x00090019u, 0x000001e1u, 0x0000000eu, 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000002u, + 0x00000000u, 0x00040020u, 0x000001e2u, 0x00000000u, 0x000001e1u, 0x0004003bu, 0x000001e2u, 0x000001e3u, + 0x00000000u, 0x00040017u, 0x000001ecu, 0x00000008u, 0x00000003u, 0x0004002bu, 0x00000006u, 0x00000203u, + 0x00000010u, 0x0004002bu, 0x00000006u, 0x0000022cu, 0x0000000fu, 0x0004003bu, 0x00000156u, 0x00000254u, + 0x00000004u, 0x0004001cu, 0x00000257u, 0x00000006u, 0x00000203u, 0x00040020u, 0x00000258u, 0x00000004u, + 0x00000257u, 0x0004003bu, 0x00000258u, 0x00000259u, 0x00000004u, 0x0004002bu, 0x00000006u, 0x00000310u, + 0x0000001fu, 0x0004002bu, 0x0000000eu, 0x00000339u, 0x3f800000u, 0x0004002bu, 0x0000000eu, 0x0000033au, + 0x40000000u, 0x0004002bu, 0x00000006u, 0x0000036fu, 0x00000080u, 0x0006002cu, 0x0000018cu, 0x00000370u, + 0x0000036fu, 0x0000012au, 0x0000012au, 0x0005002cu, 0x00000009u, 0x00000518u, 0x000001b4u, 0x000001b4u, + 0x0005002cu, 0x00000009u, 0x00000519u, 0x000000cau, 0x000000cau, 0x0004002bu, 0x00000008u, 0x0000051cu, + 0x00000018u, 0x0004002bu, 0x0000000eu, 0x0000051du, 0x3e000000u, 0x00050036u, 0x00000002u, 0x00000004u, + 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, 0x000000b1u, 0x000003d5u, 0x00000007u, + 0x0004003bu, 0x00000104u, 0x000003deu, 0x00000007u, 0x0004003bu, 0x00000104u, 0x00000284u, 0x00000007u, + 0x000300f7u, 0x00000373u, 0x00000000u, 0x000300fbu, 0x0000005fu, 0x00000374u, 0x000200f8u, 0x00000374u, + 0x0004003du, 0x00000006u, 0x0000017eu, 0x0000017du, 0x0004003du, 0x00000006u, 0x00000180u, 0x0000017fu, + 0x00050084u, 0x00000006u, 0x00000181u, 0x0000017eu, 0x00000180u, 0x0004003du, 0x00000006u, 0x00000182u, + 0x0000013au, 0x00050080u, 0x00000006u, 0x00000183u, 0x00000181u, 0x00000182u, 0x00050041u, 0x00000188u, + 0x00000189u, 0x00000187u, 0x00000039u, 0x0004003du, 0x00000008u, 0x0000018au, 0x00000189u, 0x0004007cu, + 0x00000006u, 0x0000018bu, 0x0000018au, 0x00050041u, 0x00000131u, 0x0000018fu, 0x0000018eu, 0x0000012au, + 0x0004003du, 0x00000006u, 0x00000190u, 0x0000018fu, 0x00050041u, 0x00000188u, 0x00000191u, 0x00000187u, + 0x0000003cu, 0x0004003du, 0x00000008u, 0x00000192u, 0x00000191u, 0x0004007cu, 0x00000006u, 0x00000193u, + 0x00000192u, 0x00050084u, 0x00000006u, 0x00000194u, 0x00000190u, 0x00000193u, 0x00050080u, 0x00000006u, + 0x00000195u, 0x0000018bu, 0x00000194u, 0x00050041u, 0x00000131u, 0x00000196u, 0x0000018eu, 0x0000005fu, + 0x0004003du, 0x00000006u, 0x00000197u, 0x00000196u, 0x00050080u, 0x00000006u, 0x00000198u, 0x00000195u, + 0x00000197u, 0x0004007cu, 0x00000008u, 0x00000199u, 0x00000198u, 0x000600cbu, 0x00000006u, 0x0000019cu, + 0x00000183u, 0x00000034u, 0x0000003cu, 0x000600cbu, 0x00000006u, 0x0000019fu, 0x00000183u, 0x0000003cu, + 0x00000039u, 0x000600cbu, 0x00000006u, 0x000001a2u, 0x00000183u, 0x00000042u, 0x00000039u, 0x00050084u, + 0x00000006u, 0x000001a6u, 0x000001a2u, 0x000001a5u, 0x00050080u, 0x00000006u, 0x000001a8u, 0x000001a6u, + 0x0000019fu, 0x000500c4u, 0x00000006u, 0x000001acu, 0x0000019cu, 0x0000003cu, 0x000600cbu, 0x00000006u, + 0x00000382u, 0x000001acu, 0x00000034u, 0x00000035u, 0x000600cbu, 0x00000006u, 0x00000384u, 0x000001acu, + 0x00000035u, 0x00000039u, 0x000600cbu, 0x00000006u, 0x00000386u, 0x000001acu, 0x0000003cu, 0x00000039u, + 0x000500c4u, 0x00000006u, 0x00000387u, 0x00000386u, 0x00000035u, 0x000500c5u, 0x00000006u, 0x00000389u, + 0x00000382u, 0x00000387u, 0x000600cbu, 0x00000006u, 0x0000038bu, 0x000001acu, 0x00000042u, 0x00000035u, + 0x000500c4u, 0x00000006u, 0x0000038cu, 0x0000038bu, 0x00000039u, 0x000500c5u, 0x00000006u, 0x0000038eu, + 0x00000384u, 0x0000038cu, 0x0004007cu, 0x00000008u, 0x00000390u, 0x0000038eu, 0x0004007cu, 0x00000008u, + 0x00000392u, 0x00000389u, 0x00050050u, 0x00000009u, 0x00000393u, 0x00000390u, 0x00000392u, 0x0004003du, + 0x0000018cu, 0x000001b1u, 0x0000018eu, 0x0007004fu, 0x000001b0u, 0x000001b2u, 0x000001b1u, 0x000001b1u, + 0x00000000u, 0x00000001u, 0x0004007cu, 0x00000009u, 0x000001b3u, 0x000001b2u, 0x00050084u, 0x00000009u, + 0x000001b6u, 0x000001b3u, 0x00000518u, 0x0004007cu, 0x00000008u, 0x000001b8u, 0x0000019fu, 0x0004007cu, + 0x00000008u, 0x000001bau, 0x000001a2u, 0x00050050u, 0x00000009u, 0x000001bbu, 0x000001b8u, 0x000001bau, + 0x00050084u, 0x00000009u, 0x000001bdu, 0x00000519u, 0x000001bbu, 0x00050080u, 0x00000009u, 0x000001bfu, + 0x000001b6u, 0x000001bdu, 0x00050080u, 0x00000009u, 0x000001c2u, 0x000001bfu, 0x00000393u, 0x00060041u, + 0x000001c9u, 0x000001cau, 0x000001c7u, 0x00000034u, 0x00000199u, 0x0004003du, 0x00000006u, 0x000001cbu, + 0x000001cau, 0x000500aau, 0x00000077u, 0x000001ceu, 0x000001cbu, 0x000001cdu, 0x000300f7u, 0x000001d0u, + 0x00000000u, 0x000400fau, 0x000001ceu, 0x000001cfu, 0x000001d0u, 0x000200f8u, 0x000001cfu, 0x000200f9u, + 0x000001d2u, 0x000200f8u, 0x000001d2u, 0x000700f5u, 0x00000008u, 0x00000511u, 0x00000034u, 0x000001cfu, + 0x000001f3u, 0x000001d5u, 0x000500b1u, 0x00000077u, 0x000001d8u, 0x00000511u, 0x00000039u, 0x000400f6u, + 0x000001d4u, 0x000001d5u, 0x00000000u, 0x000400fau, 0x000001d8u, 0x000001d3u, 0x000001d4u, 0x000200f8u, + 0x000001d3u, 0x000200f9u, 0x000001dau, 0x000200f8u, 0x000001dau, 0x000700f5u, 0x00000008u, 0x00000512u, + 0x00000034u, 0x000001d3u, 0x000001f1u, 0x000001dbu, 0x000500b1u, 0x00000077u, 0x000001e0u, 0x00000512u, + 0x000000eau, 0x000400f6u, 0x000001dcu, 0x000001dbu, 0x00000000u, 0x000400fau, 0x000001e0u, 0x000001dbu, + 0x000001dcu, 0x000200f8u, 0x000001dbu, 0x0004003du, 0x000001e1u, 0x000001e4u, 0x000001e3u, 0x00050050u, + 0x00000009u, 0x000001e8u, 0x00000512u, 0x00000511u, 0x00050080u, 0x00000009u, 0x000001e9u, 0x000001c2u, + 0x000001e8u, 0x00050041u, 0x00000188u, 0x000001eau, 0x00000187u, 0x00000035u, 0x0004003du, 0x00000008u, + 0x000001ebu, 0x000001eau, 0x00050051u, 0x00000008u, 0x000001edu, 0x000001e9u, 0x00000000u, 0x00050051u, + 0x00000008u, 0x000001eeu, 0x000001e9u, 0x00000001u, 0x00060050u, 0x000001ecu, 0x000001efu, 0x000001edu, + 0x000001eeu, 0x000001ebu, 0x00040063u, 0x000001e4u, 0x000001efu, 0x00000080u, 0x00050080u, 0x00000008u, + 0x000001f1u, 0x00000512u, 0x00000035u, 0x000200f9u, 0x000001dau, 0x000200f8u, 0x000001dcu, 0x000200f9u, + 0x000001d5u, 0x000200f8u, 0x000001d5u, 0x00050080u, 0x00000008u, 0x000001f3u, 0x00000511u, 0x00000035u, + 0x000200f9u, 0x000001d2u, 0x000200f8u, 0x000001d4u, 0x000200f9u, 0x00000373u, 0x000200f8u, 0x000001d0u, + 0x0004007cu, 0x00000008u, 0x000001f7u, 0x000001cbu, 0x00050084u, 0x00000008u, 0x000001f8u, 0x00000039u, + 0x000001f7u, 0x0004003du, 0x00000057u, 0x00000397u, 0x00000065u, 0x00040064u, 0x00000056u, 0x00000399u, + 0x00000397u, 0x0005005fu, 0x0000005du, 0x0000039au, 0x00000399u, 0x000001f8u, 0x00050051u, 0x00000006u, + 0x0000039bu, 0x0000039au, 0x00000000u, 0x00050084u, 0x00000008u, 0x000001feu, 0x000000eau, 0x000001f7u, + 0x00050080u, 0x00000008u, 0x000001ffu, 0x000001feu, 0x000000eau, 0x0004003du, 0x00000057u, 0x000003a0u, + 0x00000059u, 0x00040064u, 0x00000056u, 0x000003a2u, 0x000003a0u, 0x0005005fu, 0x0000005du, 0x000003a3u, + 0x000003a2u, 0x000001ffu, 0x00050051u, 0x00000006u, 0x000003a4u, 0x000003a3u, 0x00000000u, 0x000500b0u, + 0x00000077u, 0x00000204u, 0x00000183u, 0x00000203u, 0x000300f7u, 0x00000206u, 0x00000000u, 0x000400fau, + 0x00000204u, 0x00000205u, 0x00000206u, 0x000200f8u, 0x00000205u, 0x0004007cu, 0x00000008u, 0x0000020bu, + 0x00000183u, 0x000600cbu, 0x00000006u, 0x0000020cu, 0x0000039bu, 0x0000020bu, 0x00000035u, 0x000500abu, + 0x00000077u, 0x0000020du, 0x0000020cu, 0x0000005fu, 0x000300f7u, 0x0000020fu, 0x00000000u, 0x000400fau, + 0x0000020du, 0x0000020eu, 0x0000020fu, 0x000200f8u, 0x0000020eu, 0x000600cbu, 0x00000006u, 0x00000214u, + 0x0000039bu, 0x00000034u, 0x0000020bu, 0x000400cdu, 0x00000008u, 0x00000215u, 0x00000214u, 0x0004007cu, + 0x00000006u, 0x00000216u, 0x00000215u, 0x00050084u, 0x00000006u, 0x00000218u, 0x000001cbu, 0x00000142u, + 0x00050080u, 0x00000006u, 0x00000219u, 0x00000218u, 0x000001a5u, 0x00050080u, 0x00000006u, 0x0000021bu, + 0x00000219u, 0x00000216u, 0x0004007cu, 0x00000008u, 0x0000021cu, 0x0000021bu, 0x0004003du, 0x00000057u, + 0x000003a9u, 0x00000065u, 0x00040064u, 0x00000056u, 0x000003abu, 0x000003a9u, 0x0005005fu, 0x0000005du, + 0x000003acu, 0x000003abu, 0x0000021cu, 0x00050051u, 0x00000006u, 0x000003adu, 0x000003acu, 0x00000000u, + 0x00050084u, 0x00000006u, 0x00000220u, 0x000001cbu, 0x000001a5u, 0x00050080u, 0x00000006u, 0x00000221u, + 0x00000220u, 0x000000afu, 0x000400cdu, 0x00000008u, 0x00000223u, 0x0000039bu, 0x00050084u, 0x00000008u, + 0x00000224u, 0x00000223u, 0x00000039u, 0x0004007cu, 0x00000006u, 0x00000225u, 0x00000224u, 0x00050080u, + 0x00000006u, 0x00000226u, 0x00000221u, 0x00000225u, 0x00050080u, 0x00000006u, 0x00000228u, 0x00000226u, + 0x00000216u, 0x0004007cu, 0x00000008u, 0x00000229u, 0x00000228u, 0x0004003du, 0x00000057u, 0x000003b2u, + 0x00000059u, 0x00040064u, 0x00000056u, 0x000003b4u, 0x000003b2u, 0x0005005fu, 0x0000005du, 0x000003b5u, + 0x000003b4u, 0x00000229u, 0x00050051u, 0x00000006u, 0x000003b6u, 0x000003b5u, 0x00000000u, 0x000500c7u, + 0x00000006u, 0x0000022du, 0x000003b6u, 0x0000022cu, 0x000200f9u, 0x0000020fu, 0x000200f8u, 0x0000020fu, + 0x000700f5u, 0x00000006u, 0x000004dcu, 0x0000005fu, 0x00000205u, 0x0000022du, 0x0000020eu, 0x000700f5u, + 0x00000006u, 0x000004dbu, 0x0000005fu, 0x00000205u, 0x000003adu, 0x0000020eu, 0x000500c7u, 0x00000006u, + 0x00000230u, 0x000004dbu, 0x00000089u, 0x000500c7u, 0x00000006u, 0x00000233u, 0x000004dbu, 0x0000008du, + 0x000500c2u, 0x00000006u, 0x00000236u, 0x00000233u, 0x00000035u, 0x000500c5u, 0x00000006u, 0x00000239u, + 0x00000233u, 0x00000236u, 0x000400cdu, 0x00000008u, 0x0000023cu, 0x00000230u, 0x000400cdu, 0x00000008u, + 0x0000023eu, 0x00000239u, 0x00050080u, 0x00000008u, 0x0000023fu, 0x0000023cu, 0x0000023eu, 0x0004007cu, + 0x00000006u, 0x00000240u, 0x0000023fu, 0x00050084u, 0x00000006u, 0x00000242u, 0x000004dcu, 0x000000afu, + 0x00050080u, 0x00000006u, 0x00000243u, 0x00000240u, 0x00000242u, 0x00050084u, 0x00000006u, 0x00000246u, + 0x000001cbu, 0x000001a5u, 0x00050080u, 0x00000006u, 0x00000247u, 0x00000246u, 0x000000afu, 0x000400cdu, + 0x00000008u, 0x00000249u, 0x0000039bu, 0x00050084u, 0x00000008u, 0x0000024au, 0x0000003cu, 0x00000249u, + 0x0004007cu, 0x00000006u, 0x0000024bu, 0x0000024au, 0x00050080u, 0x00000006u, 0x0000024cu, 0x00000247u, + 0x0000024bu, 0x0006015du, 0x00000006u, 0x0000024eu, 0x00000138u, 0x00000001u, 0x00000243u, 0x00050080u, + 0x00000006u, 0x0000024fu, 0x0000024cu, 0x0000024eu, 0x000500aau, 0x00000077u, 0x00000251u, 0x00000183u, + 0x0000022cu, 0x000300f7u, 0x00000253u, 0x00000000u, 0x000400fau, 0x00000251u, 0x00000252u, 0x00000253u, + 0x000200f8u, 0x00000252u, 0x00050084u, 0x00000006u, 0x00000256u, 0x000000afu, 0x0000024fu, 0x0003003eu, + 0x00000254u, 0x00000256u, 0x000200f9u, 0x00000253u, 0x000200f8u, 0x00000253u, 0x00050082u, 0x00000006u, + 0x0000025du, 0x0000024fu, 0x00000243u, 0x00050041u, 0x00000156u, 0x0000025eu, 0x00000259u, 0x00000183u, + 0x0003003eu, 0x0000025eu, 0x0000025du, 0x000200f9u, 0x00000206u, 0x000200f8u, 0x00000206u, 0x000400e0u, + 0x00000142u, 0x00000142u, 0x00000148u, 0x0004007cu, 0x00000008u, 0x00000261u, 0x000001a8u, 0x000600cbu, + 0x00000006u, 0x00000262u, 0x0000039bu, 0x00000261u, 0x00000035u, 0x000500abu, 0x00000077u, 0x00000263u, + 0x00000262u, 0x0000005fu, 0x000300f7u, 0x00000265u, 0x00000000u, 0x000400fau, 0x00000263u, 0x00000264u, + 0x000002bcu, 0x000200f8u, 0x00000264u, 0x000600cbu, 0x00000006u, 0x0000026au, 0x0000039bu, 0x00000034u, + 0x00000261u, 0x000400cdu, 0x00000008u, 0x0000026bu, 0x0000026au, 0x0004007cu, 0x00000006u, 0x0000026cu, + 0x0000026bu, 0x00050084u, 0x00000006u, 0x0000026fu, 0x000001cbu, 0x00000142u, 0x00050080u, 0x00000006u, + 0x00000270u, 0x0000026fu, 0x000001a5u, 0x00050080u, 0x00000006u, 0x00000272u, 0x00000270u, 0x0000026cu, + 0x0004007cu, 0x00000008u, 0x00000273u, 0x00000272u, 0x0004003du, 0x00000057u, 0x000003bbu, 0x00000065u, + 0x00040064u, 0x00000056u, 0x000003bdu, 0x000003bbu, 0x0005005fu, 0x0000005du, 0x000003beu, 0x000003bdu, + 0x00000273u, 0x00050051u, 0x00000006u, 0x000003bfu, 0x000003beu, 0x00000000u, 0x00050084u, 0x00000006u, + 0x00000278u, 0x000001cbu, 0x000001a5u, 0x00050080u, 0x00000006u, 0x00000279u, 0x00000278u, 0x000000afu, + 0x000400cdu, 0x00000008u, 0x0000027bu, 0x0000039bu, 0x00050084u, 0x00000008u, 0x0000027cu, 0x0000027bu, + 0x00000039u, 0x0004007cu, 0x00000006u, 0x0000027du, 0x0000027cu, 0x00050080u, 0x00000006u, 0x0000027eu, + 0x00000279u, 0x0000027du, 0x00050080u, 0x00000006u, 0x00000280u, 0x0000027eu, 0x0000026cu, 0x0004007cu, + 0x00000008u, 0x00000281u, 0x00000280u, 0x0004003du, 0x00000057u, 0x000003c4u, 0x00000059u, 0x00040064u, + 0x00000056u, 0x000003c6u, 0x000003c4u, 0x0005005fu, 0x0000005du, 0x000003c7u, 0x000003c6u, 0x00000281u, + 0x00050051u, 0x00000006u, 0x000003c8u, 0x000003c7u, 0x00000000u, 0x000500c7u, 0x00000006u, 0x00000286u, + 0x000003c8u, 0x0000022cu, 0x00050041u, 0x00000156u, 0x0000028cu, 0x00000259u, 0x000001a8u, 0x0004003du, + 0x00000006u, 0x0000028du, 0x0000028cu, 0x000300f7u, 0x00000456u, 0x00000000u, 0x000300fbu, 0x0000005fu, + 0x000003e1u, 0x000200f8u, 0x000003e1u, 0x000500aau, 0x00000077u, 0x000003e3u, 0x000003bfu, 0x0000005fu, + 0x000300f7u, 0x000003e6u, 0x00000000u, 0x000400fau, 0x000003e3u, 0x000003e5u, 0x000003e6u, 0x000200f8u, + 0x000003e5u, 0x000200f9u, 0x00000456u, 0x000200f8u, 0x000003e6u, 0x0004007cu, 0x00000008u, 0x000003e8u, + 0x0000019cu, 0x00050084u, 0x00000008u, 0x000003e9u, 0x00000039u, 0x000003e8u, 0x000500c7u, 0x00000006u, + 0x000003ebu, 0x000003bfu, 0x00000089u, 0x000500c7u, 0x00000006u, 0x000003edu, 0x000003bfu, 0x0000008du, + 0x000500c2u, 0x00000006u, 0x000003efu, 0x000003edu, 0x00000035u, 0x000500c5u, 0x00000006u, 0x000003f2u, + 0x000003edu, 0x000003efu, 0x000600cbu, 0x00000006u, 0x000003f5u, 0x000003ebu, 0x00000034u, 0x000003e9u, + 0x000400cdu, 0x00000008u, 0x000003f6u, 0x000003f5u, 0x000600cbu, 0x00000006u, 0x000003f9u, 0x000003f2u, + 0x00000034u, 0x000003e9u, 0x000400cdu, 0x00000008u, 0x000003fau, 0x000003f9u, 0x00050080u, 0x00000008u, + 0x000003fbu, 0x000003f6u, 0x000003fau, 0x0004007cu, 0x00000006u, 0x000003fcu, 0x000003fbu, 0x00050084u, + 0x00000006u, 0x000003ffu, 0x00000286u, 0x0000019cu, 0x00050080u, 0x00000006u, 0x00000400u, 0x000003fcu, + 0x000003ffu, 0x00050080u, 0x00000006u, 0x00000402u, 0x00000400u, 0x0000028du, 0x0004007cu, 0x00000008u, + 0x00000404u, 0x00000402u, 0x0004003du, 0x00000057u, 0x0000045bu, 0x00000059u, 0x00040064u, 0x00000056u, + 0x0000045du, 0x0000045bu, 0x0005005fu, 0x0000005du, 0x0000045eu, 0x0000045du, 0x00000404u, 0x00050051u, + 0x00000006u, 0x0000045fu, 0x0000045eu, 0x00000000u, 0x000600cbu, 0x00000006u, 0x00000408u, 0x000003bfu, + 0x000003e9u, 0x00000039u, 0x0003003eu, 0x000003d5u, 0x000000b3u, 0x00050080u, 0x00000006u, 0x0000040bu, + 0x00000286u, 0x00000408u, 0x0004007cu, 0x00000008u, 0x0000040cu, 0x0000040bu, 0x00050082u, 0x00000008u, + 0x0000040eu, 0x0000040cu, 0x00000035u, 0x000200f9u, 0x0000040fu, 0x000200f8u, 0x0000040fu, 0x000700f5u, + 0x00000006u, 0x000004e6u, 0x00000402u, 0x000003e6u, 0x0000042au, 0x0000042eu, 0x000700f5u, 0x00000008u, + 0x000004ddu, 0x0000040eu, 0x000003e6u, 0x00000430u, 0x0000042eu, 0x000700f5u, 0x00000006u, 0x000004e9u, + 0x0000045fu, 0x000003e6u, 0x00000468u, 0x0000042eu, 0x000500afu, 0x00000077u, 0x00000412u, 0x000004ddu, + 0x00000034u, 0x000400f6u, 0x00000431u, 0x0000042eu, 0x00000000u, 0x000400fau, 0x00000412u, 0x00000413u, + 0x00000431u, 0x000200f8u, 0x00000413u, 0x000200f9u, 0x00000414u, 0x000200f8u, 0x00000414u, 0x000700f5u, + 0x00000008u, 0x000004e4u, 0x00000034u, 0x00000413u, 0x00000427u, 0x00000418u, 0x000500b1u, 0x00000077u, + 0x00000417u, 0x000004e4u, 0x000000cau, 0x000400f6u, 0x00000428u, 0x00000418u, 0x00000000u, 0x000400fau, + 0x00000417u, 0x00000418u, 0x00000428u, 0x000200f8u, 0x00000418u, 0x000600cbu, 0x00000006u, 0x0000041bu, + 0x000004e9u, 0x000004e4u, 0x00000035u, 0x0004007cu, 0x00000008u, 0x0000041cu, 0x0000041bu, 0x00050041u, + 0x00000013u, 0x0000041fu, 0x000003d5u, 0x000004e4u, 0x0004003du, 0x00000008u, 0x00000420u, 0x0000041fu, + 0x000700c9u, 0x00000008u, 0x00000423u, 0x00000420u, 0x0000041cu, 0x000004ddu, 0x00000035u, 0x0003003eu, + 0x0000041fu, 0x00000423u, 0x00050080u, 0x00000008u, 0x00000427u, 0x000004e4u, 0x00000035u, 0x000200f9u, + 0x00000414u, 0x000200f8u, 0x00000428u, 0x00050080u, 0x00000006u, 0x0000042au, 0x000004e6u, 0x00000035u, + 0x0004007cu, 0x00000008u, 0x0000042cu, 0x0000042au, 0x0004003du, 0x00000057u, 0x00000464u, 0x00000059u, + 0x00040064u, 0x00000056u, 0x00000466u, 0x00000464u, 0x0005005fu, 0x0000005du, 0x00000467u, 0x00000466u, + 0x0000042cu, 0x00050051u, 0x00000006u, 0x00000468u, 0x00000467u, 0x00000000u, 0x000200f9u, 0x0000042eu, + 0x000200f8u, 0x0000042eu, 0x00050082u, 0x00000008u, 0x00000430u, 0x000004ddu, 0x00000035u, 0x000200f9u, + 0x0000040fu, 0x000200f8u, 0x00000431u, 0x000200f9u, 0x00000432u, 0x000200f8u, 0x00000432u, 0x000700f5u, + 0x00000008u, 0x000004deu, 0x00000034u, 0x00000431u, 0x00000453u, 0x00000451u, 0x000500b1u, 0x00000077u, + 0x00000435u, 0x000004deu, 0x000000eau, 0x000400f6u, 0x00000454u, 0x00000451u, 0x00000000u, 0x000400fau, + 0x00000435u, 0x00000436u, 0x00000454u, 0x000200f8u, 0x00000436u, 0x000200f9u, 0x00000437u, 0x000200f8u, + 0x00000437u, 0x000700f5u, 0x00000008u, 0x000004dfu, 0x00000034u, 0x00000436u, 0x0000044fu, 0x0000044du, + 0x000500b1u, 0x00000077u, 0x0000043au, 0x000004dfu, 0x00000039u, 0x000400f6u, 0x00000450u, 0x0000044du, + 0x00000000u, 0x000400fau, 0x0000043au, 0x0000043bu, 0x00000450u, 0x000200f8u, 0x0000043bu, 0x00050084u, + 0x00000008u, 0x0000043du, 0x000004deu, 0x00000039u, 0x00050080u, 0x00000008u, 0x0000043fu, 0x0000043du, + 0x000004dfu, 0x00050041u, 0x00000013u, 0x00000440u, 0x000003d5u, 0x0000043fu, 0x0004003du, 0x00000008u, + 0x00000441u, 0x00000440u, 0x0004006fu, 0x0000000eu, 0x00000442u, 0x00000441u, 0x000500b7u, 0x00000077u, + 0x00000444u, 0x00000442u, 0x0000007fu, 0x000300f7u, 0x00000448u, 0x00000000u, 0x000400fau, 0x00000444u, + 0x00000445u, 0x00000448u, 0x000200f8u, 0x00000445u, 0x00050081u, 0x0000000eu, 0x00000447u, 0x00000442u, + 0x00000101u, 0x000200f9u, 0x00000448u, 0x000200f8u, 0x00000448u, 0x000700f5u, 0x0000000eu, 0x000004e3u, + 0x00000442u, 0x0000043bu, 0x00000447u, 0x00000445u, 0x00060041u, 0x000000f4u, 0x0000044cu, 0x000003deu, + 0x000004dfu, 0x000004deu, 0x0003003eu, 0x0000044cu, 0x000004e3u, 0x000200f9u, 0x0000044du, 0x000200f8u, + 0x0000044du, 0x00050080u, 0x00000008u, 0x0000044fu, 0x000004dfu, 0x00000035u, 0x000200f9u, 0x00000437u, + 0x000200f8u, 0x00000450u, 0x000200f9u, 0x00000451u, 0x000200f8u, 0x00000451u, 0x00050080u, 0x00000008u, + 0x00000453u, 0x000004deu, 0x00000035u, 0x000200f9u, 0x00000432u, 0x000200f8u, 0x00000454u, 0x0004003du, + 0x0000001fu, 0x00000455u, 0x000003deu, 0x000200f9u, 0x00000456u, 0x000200f8u, 0x00000456u, 0x000700f5u, + 0x0000001fu, 0x000004eau, 0x00000081u, 0x000003e5u, 0x00000455u, 0x00000454u, 0x0003003eu, 0x00000284u, + 0x000004eau, 0x000200f9u, 0x00000293u, 0x000200f8u, 0x00000293u, 0x000700f5u, 0x00000008u, 0x000004edu, + 0x00000034u, 0x00000456u, 0x00000510u, 0x00000296u, 0x000700f5u, 0x00000008u, 0x000004ebu, 0x00000034u, + 0x00000456u, 0x000002adu, 0x00000296u, 0x000500b1u, 0x00000077u, 0x00000299u, 0x000004ebu, 0x00000039u, + 0x000400f6u, 0x00000295u, 0x00000296u, 0x00000000u, 0x000400fau, 0x00000299u, 0x00000294u, 0x00000295u, + 0x000200f8u, 0x00000294u, 0x000200f9u, 0x0000029bu, 0x000200f8u, 0x0000029bu, 0x000700f5u, 0x00000008u, + 0x00000510u, 0x000004edu, 0x00000294u, 0x000002a9u, 0x0000029cu, 0x000700f5u, 0x00000008u, 0x0000050eu, + 0x00000034u, 0x00000294u, 0x000002abu, 0x0000029cu, 0x000500b1u, 0x00000077u, 0x000002a1u, 0x0000050eu, + 0x000000eau, 0x000400f6u, 0x0000029du, 0x0000029cu, 0x00000000u, 0x000400fau, 0x000002a1u, 0x0000029cu, + 0x0000029du, 0x000200f8u, 0x0000029cu, 0x00060041u, 0x000000f4u, 0x000002a4u, 0x00000284u, 0x000004ebu, + 0x0000050eu, 0x0004003du, 0x0000000eu, 0x000002a5u, 0x000002a4u, 0x000500b7u, 0x00000077u, 0x000002a6u, + 0x000002a5u, 0x0000007fu, 0x000600a9u, 0x00000008u, 0x000002a7u, 0x000002a6u, 0x00000035u, 0x00000034u, + 0x00050080u, 0x00000008u, 0x000002a9u, 0x00000510u, 0x000002a7u, 0x00050080u, 0x00000008u, 0x000002abu, + 0x0000050eu, 0x00000035u, 0x000200f9u, 0x0000029bu, 0x000200f8u, 0x0000029du, 0x000200f9u, 0x00000296u, + 0x000200f8u, 0x00000296u, 0x00050080u, 0x00000008u, 0x000002adu, 0x000004ebu, 0x00000035u, 0x000200f9u, + 0x00000293u, 0x000200f8u, 0x00000295u, 0x000500c2u, 0x00000006u, 0x00000470u, 0x000003a4u, 0x0000003cu, + 0x0004007cu, 0x00000008u, 0x00000471u, 0x00000470u, 0x0004007cu, 0x00000008u, 0x00000474u, 0x000003a4u, + 0x000500c7u, 0x00000008u, 0x00000475u, 0x00000474u, 0x00000119u, 0x00050080u, 0x00000008u, 0x00000477u, + 0x000000cau, 0x00000475u, 0x00050082u, 0x00000008u, 0x00000479u, 0x0000051cu, 0x00000471u, 0x000500c4u, + 0x00000008u, 0x0000047au, 0x00000035u, 0x00000479u, 0x00050084u, 0x00000008u, 0x0000047bu, 0x00000477u, + 0x0000047au, 0x0004006fu, 0x0000000eu, 0x0000047cu, 0x0000047bu, 0x00050085u, 0x0000000eu, 0x0000047du, + 0x0000011cu, 0x0000047cu, 0x000600cbu, 0x00000006u, 0x000002b5u, 0x000003c8u, 0x000000eau, 0x000000eau, + 0x00040070u, 0x0000000eu, 0x00000482u, 0x000002b5u, 0x00050085u, 0x0000000eu, 0x00000483u, 0x00000482u, + 0x0000051du, 0x00050081u, 0x0000000eu, 0x00000484u, 0x00000483u, 0x00000052u, 0x00050085u, 0x0000000eu, + 0x000002b8u, 0x0000047du, 0x00000484u, 0x0004003du, 0x0000001fu, 0x000002bau, 0x00000284u, 0x0005008fu, + 0x0000001fu, 0x000002bbu, 0x000002bau, 0x000002b8u, 0x0003003eu, 0x00000284u, 0x000002bbu, 0x000200f9u, + 0x00000265u, 0x000200f8u, 0x000002bcu, 0x0003003eu, 0x00000284u, 0x00000081u, 0x000200f9u, 0x00000265u, + 0x000200f8u, 0x00000265u, 0x000700f5u, 0x00000008u, 0x000004ecu, 0x000004edu, 0x00000295u, 0x00000034u, + 0x000002bcu, 0x0006015du, 0x00000008u, 0x000002bfu, 0x00000138u, 0x00000001u, 0x000004ecu, 0x00050082u, + 0x00000006u, 0x000002c2u, 0x00000180u, 0x0000012au, 0x000500aau, 0x00000077u, 0x000002c3u, 0x00000182u, + 0x000002c2u, 0x000300f7u, 0x000002c5u, 0x00000000u, 0x000400fau, 0x000002c3u, 0x000002c4u, 0x000002c5u, + 0x000200f8u, 0x000002c4u, 0x0004007cu, 0x00000006u, 0x000002c8u, 0x000002bfu, 0x00050041u, 0x00000156u, + 0x000002c9u, 0x00000154u, 0x0000017eu, 0x0003003eu, 0x000002c9u, 0x000002c8u, 0x000200f9u, 0x000002c5u, + 0x000200f8u, 0x000002c5u, 0x0004003du, 0x00000006u, 0x000002cau, 0x00000132u, 0x000500b2u, 0x00000077u, + 0x000002cbu, 0x000002cau, 0x000000afu, 0x000300f7u, 0x000002cdu, 0x00000000u, 0x000400fau, 0x000002cbu, + 0x000002ccu, 0x000002eau, 0x000200f8u, 0x000002ccu, 0x000400e0u, 0x00000142u, 0x00000142u, 0x00000148u, + 0x000500b2u, 0x00000077u, 0x000002cfu, 0x00000180u, 0x00000151u, 0x000300f7u, 0x000002d1u, 0x00000000u, + 0x000400fau, 0x000002cfu, 0x000002d0u, 0x000002ddu, 0x000200f8u, 0x000002d0u, 0x000500b0u, 0x00000077u, + 0x000002d4u, 0x00000183u, 0x000002cau, 0x000300f7u, 0x000002d6u, 0x00000000u, 0x000400fau, 0x000002d4u, + 0x000002d5u, 0x000002d6u, 0x000200f8u, 0x000002d5u, 0x00050041u, 0x00000156u, 0x000002d9u, 0x00000154u, + 0x00000183u, 0x0004003du, 0x00000006u, 0x000002dau, 0x000002d9u, 0x0006015du, 0x00000006u, 0x000002dbu, + 0x00000138u, 0x00000001u, 0x000002dau, 0x0003003eu, 0x000002d9u, 0x000002dbu, 0x000200f9u, 0x000002d6u, + 0x000200f8u, 0x000002d6u, 0x000200f9u, 0x000002d1u, 0x000200f8u, 0x000002ddu, 0x000500b0u, 0x00000077u, + 0x000002e0u, 0x00000183u, 0x000002cau, 0x000300f7u, 0x000002e2u, 0x00000000u, 0x000400fau, 0x000002e0u, + 0x000002e1u, 0x000002e2u, 0x000200f8u, 0x000002e1u, 0x00050041u, 0x00000156u, 0x000002e6u, 0x00000154u, + 0x00000183u, 0x0004003du, 0x00000006u, 0x000002e7u, 0x000002e6u, 0x000200f9u, 0x00000489u, 0x000200f8u, + 0x00000489u, 0x000700f5u, 0x00000006u, 0x000004f6u, 0x000002e7u, 0x000002e1u, 0x00000498u, 0x0000048eu, + 0x000700f5u, 0x00000006u, 0x000004f5u, 0x0000012au, 0x000002e1u, 0x0000049bu, 0x0000048eu, 0x000500b0u, + 0x00000077u, 0x0000048du, 0x000004f5u, 0x000002cau, 0x000400f6u, 0x0000049cu, 0x0000048eu, 0x00000000u, + 0x000400fau, 0x0000048du, 0x0000048eu, 0x0000049cu, 0x000200f8u, 0x0000048eu, 0x0006015bu, 0x00000006u, + 0x00000491u, 0x00000138u, 0x000004f6u, 0x000004f5u, 0x000500aeu, 0x00000077u, 0x00000494u, 0x00000182u, + 0x000004f5u, 0x000600a9u, 0x00000006u, 0x00000496u, 0x00000494u, 0x00000491u, 0x0000005fu, 0x00050080u, + 0x00000006u, 0x00000498u, 0x000004f6u, 0x00000496u, 0x00050084u, 0x00000006u, 0x0000049bu, 0x000004f5u, + 0x00000142u, 0x000200f9u, 0x00000489u, 0x000200f8u, 0x0000049cu, 0x0003003eu, 0x000002e6u, 0x000004f6u, + 0x000200f9u, 0x000002e2u, 0x000200f8u, 0x000002e2u, 0x000200f9u, 0x000002d1u, 0x000200f8u, 0x000002d1u, + 0x000400e0u, 0x00000142u, 0x00000142u, 0x00000148u, 0x000200f9u, 0x000002cdu, 0x000200f8u, 0x000002eau, + 0x000400e0u, 0x00000142u, 0x00000142u, 0x00000148u, 0x000500b0u, 0x00000077u, 0x000004a6u, 0x00000183u, + 0x000002cau, 0x000300f7u, 0x000004acu, 0x00000000u, 0x000400fau, 0x000004a6u, 0x000004a8u, 0x000004acu, + 0x000200f8u, 0x000004a8u, 0x00050041u, 0x00000156u, 0x000004aau, 0x00000154u, 0x00000183u, 0x0004003du, + 0x00000006u, 0x000004abu, 0x000004aau, 0x000200f9u, 0x000004acu, 0x000200f8u, 0x000004acu, 0x000700f5u, + 0x00000006u, 0x000004f2u, 0x0000005fu, 0x000002eau, 0x000004abu, 0x000004a8u, 0x000200f9u, 0x000004adu, + 0x000200f8u, 0x000004adu, 0x000700f5u, 0x00000006u, 0x000004f1u, 0x000004f2u, 0x000004acu, 0x00000514u, + 0x000004c9u, 0x000700f5u, 0x00000006u, 0x000004eeu, 0x0000012au, 0x000004acu, 0x000004cbu, 0x000004c9u, + 0x000500b0u, 0x00000077u, 0x000004b1u, 0x000004eeu, 0x000002cau, 0x000400f6u, 0x000004ccu, 0x000004c9u, + 0x00000000u, 0x000400fau, 0x000004b1u, 0x000004b2u, 0x000004ccu, 0x000200f8u, 0x000004b2u, 0x000500aeu, + 0x00000077u, 0x000004b5u, 0x00000183u, 0x000004eeu, 0x000500a7u, 0x00000077u, 0x000004b7u, 0x000004b5u, + 0x000004a6u, 0x000300f7u, 0x000004bfu, 0x00000000u, 0x000400fau, 0x000004b7u, 0x000004b9u, 0x000004bfu, + 0x000200f8u, 0x000004b9u, 0x00050082u, 0x00000006u, 0x000004bcu, 0x00000183u, 0x000004eeu, 0x00050041u, + 0x00000156u, 0x000004bdu, 0x00000154u, 0x000004bcu, 0x0004003du, 0x00000006u, 0x000004beu, 0x000004bdu, + 0x000200f9u, 0x000004bfu, 0x000200f8u, 0x000004bfu, 0x000700f5u, 0x00000006u, 0x000004efu, 0x0000005fu, + 0x000004b2u, 0x000004beu, 0x000004b9u, 0x000400e0u, 0x00000142u, 0x00000142u, 0x00000148u, 0x000300f7u, + 0x000004c8u, 0x00000000u, 0x000400fau, 0x000004b7u, 0x000004c1u, 0x000004c8u, 0x000200f8u, 0x000004c1u, + 0x00050080u, 0x00000006u, 0x000004c4u, 0x000004f1u, 0x000004efu, 0x00050041u, 0x00000156u, 0x000004c7u, + 0x00000154u, 0x00000183u, 0x0003003eu, 0x000004c7u, 0x000004c4u, 0x000200f9u, 0x000004c8u, 0x000200f8u, + 0x000004c8u, 0x000700f5u, 0x00000006u, 0x00000514u, 0x000004f1u, 0x000004bfu, 0x000004c4u, 0x000004c1u, + 0x000400e0u, 0x00000142u, 0x00000142u, 0x00000148u, 0x000200f9u, 0x000004c9u, 0x000200f8u, 0x000004c9u, + 0x00050084u, 0x00000006u, 0x000004cbu, 0x000004eeu, 0x00000142u, 0x000200f9u, 0x000004adu, 0x000200f8u, + 0x000004ccu, 0x000200f9u, 0x000002cdu, 0x000200f8u, 0x000002cdu, 0x0004003du, 0x00000006u, 0x000002efu, + 0x00000254u, 0x0004007cu, 0x00000006u, 0x000002f1u, 0x000002bfu, 0x00050080u, 0x00000006u, 0x000002f2u, + 0x000002efu, 0x000002f1u, 0x0004007cu, 0x00000006u, 0x000002f4u, 0x000004ecu, 0x00050082u, 0x00000006u, + 0x000002f5u, 0x000002f2u, 0x000002f4u, 0x000500abu, 0x00000077u, 0x000002f7u, 0x0000017eu, 0x0000005fu, + 0x000300f7u, 0x000002f9u, 0x00000000u, 0x000400fau, 0x000002f7u, 0x000002f8u, 0x000002f9u, 0x000200f8u, + 0x000002f8u, 0x00050082u, 0x00000006u, 0x000002fbu, 0x0000017eu, 0x0000012au, 0x00050041u, 0x00000156u, + 0x000002fcu, 0x00000154u, 0x000002fbu, 0x0004003du, 0x00000006u, 0x000002fdu, 0x000002fcu, 0x00050080u, + 0x00000006u, 0x000002ffu, 0x000002f5u, 0x000002fdu, 0x000200f9u, 0x000002f9u, 0x000200f8u, 0x000002f9u, + 0x000700f5u, 0x00000006u, 0x00000501u, 0x000002f5u, 0x000002cdu, 0x000002ffu, 0x000002f8u, 0x00050086u, + 0x00000006u, 0x00000302u, 0x00000501u, 0x00000151u, 0x0004007cu, 0x00000008u, 0x00000304u, 0x00000302u, + 0x0004003du, 0x00000057u, 0x000004cfu, 0x0000006fu, 0x00040064u, 0x00000056u, 0x000004d1u, 0x000004cfu, + 0x0005005fu, 0x0000005du, 0x000004d2u, 0x000004d1u, 0x00000304u, 0x00050051u, 0x00000006u, 0x000004d3u, + 0x000004d2u, 0x00000000u, 0x00050080u, 0x00000006u, 0x0000030au, 0x00000302u, 0x0000012au, 0x0004007cu, + 0x00000008u, 0x0000030bu, 0x0000030au, 0x0004003du, 0x00000057u, 0x000004d6u, 0x0000006fu, 0x00040064u, + 0x00000056u, 0x000004d8u, 0x000004d6u, 0x0005005fu, 0x0000005du, 0x000004d9u, 0x000004d8u, 0x0000030bu, + 0x00050051u, 0x00000006u, 0x000004dau, 0x000004d9u, 0x00000000u, 0x000500c7u, 0x00000006u, 0x00000311u, + 0x00000501u, 0x00000310u, 0x000500abu, 0x00000077u, 0x00000313u, 0x00000311u, 0x0000005fu, 0x000300f7u, + 0x00000315u, 0x00000000u, 0x000400fau, 0x00000313u, 0x00000314u, 0x00000315u, 0x000200f8u, 0x00000314u, + 0x000500c2u, 0x00000006u, 0x00000318u, 0x000004d3u, 0x00000311u, 0x00050082u, 0x00000006u, 0x0000031bu, + 0x00000151u, 0x00000311u, 0x000500c4u, 0x00000006u, 0x0000031cu, 0x000004dau, 0x0000031bu, 0x000500c5u, + 0x00000006u, 0x0000031eu, 0x00000318u, 0x0000031cu, 0x000200f9u, 0x00000315u, 0x000200f8u, 0x00000315u, + 0x000700f5u, 0x00000006u, 0x0000050au, 0x000004d3u, 0x000002f9u, 0x0000031eu, 0x00000314u, 0x000200f9u, + 0x00000321u, 0x000200f8u, 0x00000321u, 0x000700f5u, 0x00000008u, 0x00000502u, 0x00000034u, 0x00000315u, + 0x0000034au, 0x00000324u, 0x000700f5u, 0x00000008u, 0x0000050cu, 0x00000034u, 0x00000315u, 0x0000050bu, + 0x00000324u, 0x000500b1u, 0x00000077u, 0x00000327u, 0x00000502u, 0x000000eau, 0x000400f6u, 0x00000323u, + 0x00000324u, 0x00000000u, 0x000400fau, 0x00000327u, 0x00000322u, 0x00000323u, 0x000200f8u, 0x00000322u, + 0x000200f9u, 0x00000329u, 0x000200f8u, 0x00000329u, 0x000700f5u, 0x00000008u, 0x0000050bu, 0x0000050cu, + 0x00000322u, 0x00000517u, 0x0000032cu, 0x000700f5u, 0x00000008u, 0x00000506u, 0x00000034u, 0x00000322u, + 0x00000348u, 0x0000032cu, 0x000500b1u, 0x00000077u, 0x0000032fu, 0x00000506u, 0x00000039u, 0x000400f6u, + 0x0000032bu, 0x0000032cu, 0x00000000u, 0x000400fau, 0x0000032fu, 0x0000032au, 0x0000032bu, 0x000200f8u, + 0x0000032au, 0x00060041u, 0x000000f4u, 0x00000332u, 0x00000284u, 0x00000506u, 0x00000502u, 0x0004003du, + 0x0000000eu, 0x00000333u, 0x00000332u, 0x000500b7u, 0x00000077u, 0x00000334u, 0x00000333u, 0x0000007fu, + 0x000300f7u, 0x00000336u, 0x00000000u, 0x000400fau, 0x00000334u, 0x00000335u, 0x00000336u, 0x000200f8u, + 0x00000335u, 0x000600cbu, 0x00000006u, 0x0000033du, 0x0000050au, 0x0000050bu, 0x00000035u, 0x00040070u, + 0x0000000eu, 0x0000033eu, 0x0000033du, 0x00050085u, 0x0000000eu, 0x0000033fu, 0x0000033au, 0x0000033eu, + 0x00050083u, 0x0000000eu, 0x00000340u, 0x00000339u, 0x0000033fu, 0x0004003du, 0x0000000eu, 0x00000342u, + 0x00000332u, 0x00050085u, 0x0000000eu, 0x00000343u, 0x00000342u, 0x00000340u, 0x0003003eu, 0x00000332u, + 0x00000343u, 0x00050080u, 0x00000008u, 0x00000346u, 0x0000050bu, 0x00000035u, 0x000200f9u, 0x00000336u, + 0x000200f8u, 0x00000336u, 0x000700f5u, 0x00000008u, 0x00000517u, 0x0000050bu, 0x0000032au, 0x00000346u, + 0x00000335u, 0x000200f9u, 0x0000032cu, 0x000200f8u, 0x0000032cu, 0x00050080u, 0x00000008u, 0x00000348u, + 0x00000506u, 0x00000035u, 0x000200f9u, 0x00000329u, 0x000200f8u, 0x0000032bu, 0x000200f9u, 0x00000324u, + 0x000200f8u, 0x00000324u, 0x00050080u, 0x00000008u, 0x0000034au, 0x00000502u, 0x00000035u, 0x000200f9u, + 0x00000321u, 0x000200f8u, 0x00000323u, 0x000200f9u, 0x0000034cu, 0x000200f8u, 0x0000034cu, 0x000700f5u, + 0x00000008u, 0x00000503u, 0x00000034u, 0x00000323u, 0x0000036eu, 0x0000034fu, 0x000500b1u, 0x00000077u, + 0x00000352u, 0x00000503u, 0x00000039u, 0x000400f6u, 0x0000034eu, 0x0000034fu, 0x00000000u, 0x000400fau, + 0x00000352u, 0x0000034du, 0x0000034eu, 0x000200f8u, 0x0000034du, 0x000200f9u, 0x00000354u, 0x000200f8u, + 0x00000354u, 0x000700f5u, 0x00000008u, 0x00000504u, 0x00000034u, 0x0000034du, 0x0000036cu, 0x00000355u, + 0x000500b1u, 0x00000077u, 0x0000035au, 0x00000504u, 0x000000eau, 0x000400f6u, 0x00000356u, 0x00000355u, + 0x00000000u, 0x000400fau, 0x0000035au, 0x00000355u, 0x00000356u, 0x000200f8u, 0x00000355u, 0x0004003du, + 0x000001e1u, 0x0000035bu, 0x000001e3u, 0x00050050u, 0x00000009u, 0x0000035fu, 0x00000504u, 0x00000503u, + 0x00050080u, 0x00000009u, 0x00000360u, 0x000001c2u, 0x0000035fu, 0x00050041u, 0x00000188u, 0x00000361u, + 0x00000187u, 0x00000035u, 0x0004003du, 0x00000008u, 0x00000362u, 0x00000361u, 0x00050051u, 0x00000008u, + 0x00000363u, 0x00000360u, 0x00000000u, 0x00050051u, 0x00000008u, 0x00000364u, 0x00000360u, 0x00000001u, + 0x00060050u, 0x000001ecu, 0x00000365u, 0x00000363u, 0x00000364u, 0x00000362u, 0x00060041u, 0x000000f4u, + 0x00000368u, 0x00000284u, 0x00000503u, 0x00000504u, 0x0004003du, 0x0000000eu, 0x00000369u, 0x00000368u, + 0x00070050u, 0x0000001eu, 0x0000036au, 0x00000369u, 0x00000369u, 0x00000369u, 0x00000369u, 0x00040063u, + 0x0000035bu, 0x00000365u, 0x0000036au, 0x00050080u, 0x00000008u, 0x0000036cu, 0x00000504u, 0x00000035u, + 0x000200f9u, 0x00000354u, 0x000200f8u, 0x00000356u, 0x000200f9u, 0x0000034fu, 0x000200f8u, 0x0000034fu, + 0x00050080u, 0x00000008u, 0x0000036eu, 0x00000503u, 0x00000035u, 0x000200f9u, 0x0000034cu, 0x000200f8u, + 0x0000034eu, 0x000200f9u, 0x00000373u, 0x000200f8u, 0x00000373u, 0x000100fdu, 0x00010038u, 0x07230203u, + 0x00010300u, 0x000d000bu, 0x000005a2u, 0x00000000u, 0x00020011u, 0x00000001u, 0x00020011u, 0x00000038u, + 0x00020011u, 0x0000003du, 0x00020011u, 0x0000003fu, 0x00020011u, 0x00000042u, 0x0006000bu, 0x00000001u, + 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u, 0x000a000fu, + 0x00000005u, 0x00000004u, 0x6e69616du, 0x00000000u, 0x00000152u, 0x0000015au, 0x0000019du, 0x0000019fu, + 0x000001aeu, 0x00060010u, 0x00000004u, 0x00000011u, 0x00000080u, 0x00000001u, 0x00000001u, 0x00030047u, + 0x0000005eu, 0x00000000u, 0x00040047u, 0x0000005eu, 0x00000021u, 0x00000004u, 0x00040047u, 0x0000005eu, + 0x00000022u, 0x00000000u, 0x00030047u, 0x00000075u, 0x00000000u, 0x00040047u, 0x00000075u, 0x00000021u, + 0x00000003u, 0x00040047u, 0x00000075u, 0x00000022u, 0x00000000u, 0x00040047u, 0x0000008au, 0x00000021u, + 0x00000002u, 0x00040047u, 0x0000008au, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000152u, 0x0000000bu, + 0x00000026u, 0x00030047u, 0x0000015au, 0x00000000u, 0x00040047u, 0x0000015au, 0x0000000bu, 0x00000029u, + 0x00040047u, 0x0000019du, 0x0000000bu, 0x00000028u, 0x00030047u, 0x0000019fu, 0x00000000u, 0x00040047u, + 0x0000019fu, 0x0000000bu, 0x00000024u, 0x00030047u, 0x000001a0u, 0x00000000u, 0x00030047u, 0x000001a2u, + 0x00000000u, 0x00030047u, 0x000001a5u, 0x00000002u, 0x00050048u, 0x000001a5u, 0x00000000u, 0x00000023u, + 0x00000000u, 0x00050048u, 0x000001a5u, 0x00000001u, 0x00000023u, 0x00000008u, 0x00050048u, 0x000001a5u, + 0x00000002u, 0x00000023u, 0x0000000cu, 0x00050048u, 0x000001a5u, 0x00000003u, 0x00000023u, 0x00000010u, + 0x00040047u, 0x000001aeu, 0x0000000bu, 0x0000001au, 0x00040047u, 0x000001e4u, 0x00000006u, 0x00000004u, + 0x00030047u, 0x000001e5u, 0x00000002u, 0x00040048u, 0x000001e5u, 0x00000000u, 0x00000018u, 0x00050048u, + 0x000001e5u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00030047u, 0x000001e7u, 0x00000018u, 0x00040047u, + 0x000001e7u, 0x00000021u, 0x00000001u, 0x00040047u, 0x000001e7u, 0x00000022u, 0x00000000u, 0x00030047u, + 0x00000203u, 0x00000019u, 0x00040047u, 0x00000203u, 0x00000021u, 0x00000000u, 0x00040047u, 0x00000203u, + 0x00000022u, 0x00000000u, 0x00030047u, 0x000002e8u, 0x00000000u, 0x00040047u, 0x00000398u, 0x0000000bu, + 0x00000019u, 0x00030047u, 0x000003c5u, 0x00000000u, 0x00030047u, 0x000003cbu, 0x00000000u, 0x00030047u, + 0x000003ccu, 0x00000000u, 0x00030047u, 0x000003d7u, 0x00000000u, 0x00030047u, 0x000003ddu, 0x00000000u, + 0x00030047u, 0x000003deu, 0x00000000u, 0x00030047u, 0x000003e9u, 0x00000000u, 0x00030047u, 0x000003efu, + 0x00000000u, 0x00030047u, 0x000003f0u, 0x00000000u, 0x00030047u, 0x000003fbu, 0x00000000u, 0x00030047u, + 0x00000401u, 0x00000000u, 0x00030047u, 0x00000402u, 0x00000000u, 0x00030047u, 0x0000040du, 0x00000000u, + 0x00030047u, 0x00000413u, 0x00000000u, 0x00030047u, 0x00000414u, 0x00000000u, 0x00030047u, 0x0000041fu, + 0x00000000u, 0x00030047u, 0x00000425u, 0x00000000u, 0x00030047u, 0x00000426u, 0x00000000u, 0x00030047u, + 0x000004c1u, 0x00000000u, 0x00030047u, 0x000004c7u, 0x00000000u, 0x00030047u, 0x000004c8u, 0x00000000u, + 0x00030047u, 0x000004d3u, 0x00000000u, 0x00030047u, 0x000004d9u, 0x00000000u, 0x00030047u, 0x000004dau, + 0x00000000u, 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00040015u, 0x00000006u, + 0x00000020u, 0x00000000u, 0x00040015u, 0x00000008u, 0x00000020u, 0x00000001u, 0x00040017u, 0x00000009u, + 0x00000008u, 0x00000002u, 0x00030016u, 0x0000000eu, 0x00000020u, 0x00040017u, 0x0000001du, 0x0000000eu, + 0x00000004u, 0x00040018u, 0x0000001eu, 0x0000001du, 0x00000002u, 0x0004002bu, 0x00000008u, 0x00000032u, + 0x00000000u, 0x0004002bu, 0x00000008u, 0x00000033u, 0x00000001u, 0x0004002bu, 0x00000008u, 0x00000037u, + 0x00000002u, 0x0004002bu, 0x00000008u, 0x0000003au, 0x00000003u, 0x0004002bu, 0x00000008u, 0x00000040u, + 0x00000005u, 0x0004002bu, 0x0000000eu, 0x00000050u, 0x3e800000u, 0x0004002bu, 0x00000008u, 0x00000056u, + 0x0000000cu, 0x0004002bu, 0x00000008u, 0x0000005au, 0x00000014u, 0x00090019u, 0x0000005cu, 0x00000006u, + 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00040020u, 0x0000005du, + 0x00000000u, 0x0000005cu, 0x0004003bu, 0x0000005du, 0x0000005eu, 0x00000000u, 0x00040017u, 0x00000065u, + 0x00000006u, 0x00000004u, 0x0004002bu, 0x00000006u, 0x00000067u, 0x00000000u, 0x0004002bu, 0x00000008u, + 0x0000006fu, 0x0000000bu, 0x0004002bu, 0x00000008u, 0x00000073u, 0x00000015u, 0x0004003bu, 0x0000005du, + 0x00000075u, 0x00000000u, 0x0004002bu, 0x00000008u, 0x00000084u, 0x0000000au, 0x0004002bu, 0x00000008u, + 0x00000088u, 0x00000016u, 0x0004003bu, 0x0000005du, 0x0000008au, 0x00000000u, 0x00020014u, 0x00000095u, + 0x0004002bu, 0x0000000eu, 0x0000009du, 0x00000000u, 0x0007002cu, 0x0000001du, 0x0000009eu, 0x0000009du, + 0x0000009du, 0x0000009du, 0x0000009du, 0x0005002cu, 0x0000001eu, 0x0000009fu, 0x0000009eu, 0x0000009eu, + 0x00040020u, 0x000000a1u, 0x00000007u, 0x00000008u, 0x0004002bu, 0x00000006u, 0x000000a8u, 0x00005555u, + 0x0004002bu, 0x00000006u, 0x000000acu, 0x0000aaaau, 0x0004002bu, 0x00000006u, 0x000000cfu, 0x00000008u, + 0x0004001cu, 0x000000d0u, 0x00000008u, 0x000000cfu, 0x00040020u, 0x000000d1u, 0x00000007u, 0x000000d0u, + 0x000b002cu, 0x000000d0u, 0x000000d3u, 0x00000032u, 0x00000032u, 0x00000032u, 0x00000032u, 0x00000032u, + 0x00000032u, 0x00000032u, 0x00000032u, 0x0004002bu, 0x00000008u, 0x000000eau, 0x00000008u, 0x0004002bu, + 0x00000008u, 0x0000010bu, 0x00000004u, 0x00040020u, 0x00000115u, 0x00000007u, 0x0000000eu, 0x0004002bu, + 0x0000000eu, 0x00000122u, 0x3f000000u, 0x00040020u, 0x00000125u, 0x00000007u, 0x0000001eu, 0x0004002bu, + 0x00000008u, 0x0000013au, 0x00000007u, 0x0004002bu, 0x0000000eu, 0x0000013du, 0x34000000u, 0x0004002bu, + 0x00000006u, 0x0000014au, 0x00000001u, 0x00040020u, 0x00000151u, 0x00000001u, 0x00000006u, 0x0004003bu, + 0x00000151u, 0x00000152u, 0x00000001u, 0x0004002bu, 0x00000006u, 0x00000158u, 0x00000003u, 0x0004003bu, + 0x00000151u, 0x0000015au, 0x00000001u, 0x0004002bu, 0x00000006u, 0x00000162u, 0x00000002u, 0x0004002bu, + 0x00000006u, 0x00000168u, 0x00000108u, 0x0004002bu, 0x00000006u, 0x00000171u, 0x00000020u, 0x0004001cu, + 0x00000172u, 0x00000006u, 0x00000171u, 0x00040020u, 0x00000173u, 0x00000004u, 0x00000172u, 0x0004003bu, + 0x00000173u, 0x00000174u, 0x00000004u, 0x00040020u, 0x00000176u, 0x00000004u, 0x00000006u, 0x0004003bu, + 0x00000151u, 0x0000019du, 0x00000001u, 0x0004003bu, 0x00000151u, 0x0000019fu, 0x00000001u, 0x0006001eu, + 0x000001a5u, 0x00000009u, 0x00000008u, 0x00000008u, 0x00000008u, 0x00040020u, 0x000001a6u, 0x00000009u, + 0x000001a5u, 0x0004003bu, 0x000001a6u, 0x000001a7u, 0x00000009u, 0x00040020u, 0x000001a8u, 0x00000009u, + 0x00000008u, 0x00040017u, 0x000001acu, 0x00000006u, 0x00000003u, 0x00040020u, 0x000001adu, 0x00000001u, + 0x000001acu, 0x0004003bu, 0x000001adu, 0x000001aeu, 0x00000001u, 0x0004002bu, 0x00000006u, 0x000001c5u, + 0x00000004u, 0x00040017u, 0x000001d0u, 0x00000006u, 0x00000002u, 0x0004002bu, 0x00000008u, 0x000001d4u, + 0x00000020u, 0x0003001du, 0x000001e4u, 0x00000006u, 0x0003001eu, 0x000001e5u, 0x000001e4u, 0x00040020u, + 0x000001e6u, 0x0000000cu, 0x000001e5u, 0x0004003bu, 0x000001e6u, 0x000001e7u, 0x0000000cu, 0x00040020u, + 0x000001e9u, 0x0000000cu, 0x00000006u, 0x0004002bu, 0x00000006u, 0x000001edu, 0xffffffffu, 0x00090019u, + 0x00000201u, 0x0000000eu, 0x00000001u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000002u, 0x00000000u, + 0x00040020u, 0x00000202u, 0x00000000u, 0x00000201u, 0x0004003bu, 0x00000202u, 0x00000203u, 0x00000000u, + 0x00040017u, 0x0000020cu, 0x00000008u, 0x00000003u, 0x0004002bu, 0x00000006u, 0x00000225u, 0x00000010u, + 0x0004002bu, 0x00000006u, 0x00000250u, 0x0000000fu, 0x0004003bu, 0x00000176u, 0x00000278u, 0x00000004u, + 0x0004001cu, 0x0000027bu, 0x00000006u, 0x00000225u, 0x00040020u, 0x0000027cu, 0x00000004u, 0x0000027bu, + 0x0004003bu, 0x0000027cu, 0x0000027du, 0x00000004u, 0x0004002bu, 0x00000006u, 0x00000338u, 0x0000001fu, + 0x0004002bu, 0x0000000eu, 0x00000361u, 0x3f800000u, 0x0004002bu, 0x0000000eu, 0x00000362u, 0x40000000u, + 0x0004002bu, 0x00000006u, 0x00000397u, 0x00000080u, 0x0006002cu, 0x000001acu, 0x00000398u, 0x00000397u, + 0x0000014au, 0x0000014au, 0x0005002cu, 0x00000009u, 0x0000059cu, 0x000001d4u, 0x000001d4u, 0x0005002cu, + 0x00000009u, 0x0000059du, 0x000000eau, 0x000000eau, 0x0004002bu, 0x00000008u, 0x000005a0u, 0x00000018u, + 0x0004002bu, 0x0000000eu, 0x000005a1u, 0x3e000000u, 0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, + 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, 0x000000d1u, 0x00000433u, 0x00000007u, 0x0004003bu, + 0x00000125u, 0x0000043cu, 0x00000007u, 0x0004003bu, 0x00000125u, 0x000002aau, 0x00000007u, 0x000300f7u, + 0x0000039bu, 0x00000000u, 0x000300fbu, 0x00000067u, 0x0000039cu, 0x000200f8u, 0x0000039cu, 0x0004003du, + 0x00000006u, 0x0000019eu, 0x0000019du, 0x0004003du, 0x00000006u, 0x000001a0u, 0x0000019fu, 0x00050084u, + 0x00000006u, 0x000001a1u, 0x0000019eu, 0x000001a0u, 0x0004003du, 0x00000006u, 0x000001a2u, 0x0000015au, + 0x00050080u, 0x00000006u, 0x000001a3u, 0x000001a1u, 0x000001a2u, 0x00050041u, 0x000001a8u, 0x000001a9u, + 0x000001a7u, 0x00000037u, 0x0004003du, 0x00000008u, 0x000001aau, 0x000001a9u, 0x0004007cu, 0x00000006u, + 0x000001abu, 0x000001aau, 0x00050041u, 0x00000151u, 0x000001afu, 0x000001aeu, 0x0000014au, 0x0004003du, + 0x00000006u, 0x000001b0u, 0x000001afu, 0x00050041u, 0x000001a8u, 0x000001b1u, 0x000001a7u, 0x0000003au, + 0x0004003du, 0x00000008u, 0x000001b2u, 0x000001b1u, 0x0004007cu, 0x00000006u, 0x000001b3u, 0x000001b2u, + 0x00050084u, 0x00000006u, 0x000001b4u, 0x000001b0u, 0x000001b3u, 0x00050080u, 0x00000006u, 0x000001b5u, + 0x000001abu, 0x000001b4u, 0x00050041u, 0x00000151u, 0x000001b6u, 0x000001aeu, 0x00000067u, 0x0004003du, + 0x00000006u, 0x000001b7u, 0x000001b6u, 0x00050080u, 0x00000006u, 0x000001b8u, 0x000001b5u, 0x000001b7u, + 0x0004007cu, 0x00000008u, 0x000001b9u, 0x000001b8u, 0x000600cbu, 0x00000006u, 0x000001bcu, 0x000001a3u, + 0x00000032u, 0x0000003au, 0x000600cbu, 0x00000006u, 0x000001bfu, 0x000001a3u, 0x0000003au, 0x00000037u, + 0x000600cbu, 0x00000006u, 0x000001c2u, 0x000001a3u, 0x00000040u, 0x00000037u, 0x00050084u, 0x00000006u, + 0x000001c6u, 0x000001c2u, 0x000001c5u, 0x00050080u, 0x00000006u, 0x000001c8u, 0x000001c6u, 0x000001bfu, + 0x000500c4u, 0x00000006u, 0x000001ccu, 0x000001bcu, 0x0000003au, 0x000600cbu, 0x00000006u, 0x000003aau, + 0x000001ccu, 0x00000032u, 0x00000033u, 0x000600cbu, 0x00000006u, 0x000003acu, 0x000001ccu, 0x00000033u, + 0x00000037u, 0x000600cbu, 0x00000006u, 0x000003aeu, 0x000001ccu, 0x0000003au, 0x00000037u, 0x000500c4u, + 0x00000006u, 0x000003afu, 0x000003aeu, 0x00000033u, 0x000500c5u, 0x00000006u, 0x000003b1u, 0x000003aau, + 0x000003afu, 0x000600cbu, 0x00000006u, 0x000003b3u, 0x000001ccu, 0x00000040u, 0x00000033u, 0x000500c4u, + 0x00000006u, 0x000003b4u, 0x000003b3u, 0x00000037u, 0x000500c5u, 0x00000006u, 0x000003b6u, 0x000003acu, + 0x000003b4u, 0x0004007cu, 0x00000008u, 0x000003b8u, 0x000003b6u, 0x0004007cu, 0x00000008u, 0x000003bau, + 0x000003b1u, 0x00050050u, 0x00000009u, 0x000003bbu, 0x000003b8u, 0x000003bau, 0x0004003du, 0x000001acu, + 0x000001d1u, 0x000001aeu, 0x0007004fu, 0x000001d0u, 0x000001d2u, 0x000001d1u, 0x000001d1u, 0x00000000u, + 0x00000001u, 0x0004007cu, 0x00000009u, 0x000001d3u, 0x000001d2u, 0x00050084u, 0x00000009u, 0x000001d6u, + 0x000001d3u, 0x0000059cu, 0x0004007cu, 0x00000008u, 0x000001d8u, 0x000001bfu, 0x0004007cu, 0x00000008u, + 0x000001dau, 0x000001c2u, 0x00050050u, 0x00000009u, 0x000001dbu, 0x000001d8u, 0x000001dau, 0x00050084u, + 0x00000009u, 0x000001ddu, 0x0000059du, 0x000001dbu, 0x00050080u, 0x00000009u, 0x000001dfu, 0x000001d6u, + 0x000001ddu, 0x00050080u, 0x00000009u, 0x000001e2u, 0x000001dfu, 0x000003bbu, 0x00060041u, 0x000001e9u, + 0x000001eau, 0x000001e7u, 0x00000032u, 0x000001b9u, 0x0004003du, 0x00000006u, 0x000001ebu, 0x000001eau, + 0x000500aau, 0x00000095u, 0x000001eeu, 0x000001ebu, 0x000001edu, 0x000300f7u, 0x000001f0u, 0x00000000u, + 0x000400fau, 0x000001eeu, 0x000001efu, 0x000001f0u, 0x000200f8u, 0x000001efu, 0x000200f9u, 0x000001f2u, + 0x000200f8u, 0x000001f2u, 0x000700f5u, 0x00000008u, 0x00000595u, 0x00000032u, 0x000001efu, 0x00000213u, + 0x000001f5u, 0x000500b1u, 0x00000095u, 0x000001f8u, 0x00000595u, 0x00000037u, 0x000400f6u, 0x000001f4u, + 0x000001f5u, 0x00000000u, 0x000400fau, 0x000001f8u, 0x000001f3u, 0x000001f4u, 0x000200f8u, 0x000001f3u, + 0x000200f9u, 0x000001fau, 0x000200f8u, 0x000001fau, 0x000700f5u, 0x00000008u, 0x00000596u, 0x00000032u, + 0x000001f3u, 0x00000211u, 0x000001fbu, 0x000500b1u, 0x00000095u, 0x00000200u, 0x00000596u, 0x0000010bu, + 0x000400f6u, 0x000001fcu, 0x000001fbu, 0x00000000u, 0x000400fau, 0x00000200u, 0x000001fbu, 0x000001fcu, + 0x000200f8u, 0x000001fbu, 0x0004003du, 0x00000201u, 0x00000204u, 0x00000203u, 0x00050050u, 0x00000009u, + 0x00000208u, 0x00000596u, 0x00000595u, 0x00050080u, 0x00000009u, 0x00000209u, 0x000001e2u, 0x00000208u, + 0x00050041u, 0x000001a8u, 0x0000020au, 0x000001a7u, 0x00000033u, 0x0004003du, 0x00000008u, 0x0000020bu, + 0x0000020au, 0x00050051u, 0x00000008u, 0x0000020du, 0x00000209u, 0x00000000u, 0x00050051u, 0x00000008u, + 0x0000020eu, 0x00000209u, 0x00000001u, 0x00060050u, 0x0000020cu, 0x0000020fu, 0x0000020du, 0x0000020eu, + 0x0000020bu, 0x00040063u, 0x00000204u, 0x0000020fu, 0x0000009eu, 0x00050080u, 0x00000008u, 0x00000211u, + 0x00000596u, 0x00000033u, 0x000200f9u, 0x000001fau, 0x000200f8u, 0x000001fcu, 0x000200f9u, 0x000001f5u, + 0x000200f8u, 0x000001f5u, 0x00050080u, 0x00000008u, 0x00000213u, 0x00000595u, 0x00000033u, 0x000200f9u, + 0x000001f2u, 0x000200f8u, 0x000001f4u, 0x000200f9u, 0x0000039bu, 0x000200f8u, 0x000001f0u, 0x0004007cu, + 0x00000008u, 0x00000217u, 0x000001ebu, 0x00050084u, 0x00000008u, 0x00000218u, 0x00000037u, 0x00000217u, + 0x0004007cu, 0x00000006u, 0x00000219u, 0x00000218u, 0x000600cbu, 0x00000006u, 0x000003c2u, 0x00000219u, + 0x00000032u, 0x0000006fu, 0x000600cbu, 0x00000006u, 0x000003c4u, 0x00000219u, 0x0000006fu, 0x00000073u, + 0x0004003du, 0x0000005cu, 0x000003c5u, 0x00000075u, 0x0004007cu, 0x00000008u, 0x000003c7u, 0x000003c2u, + 0x0004007cu, 0x00000008u, 0x000003c9u, 0x000003c4u, 0x00050050u, 0x00000009u, 0x000003cau, 0x000003c7u, + 0x000003c9u, 0x0007005fu, 0x00000065u, 0x000003cbu, 0x000003c5u, 0x000003cau, 0x00000002u, 0x00000032u, + 0x00050051u, 0x00000006u, 0x000003ccu, 0x000003cbu, 0x00000000u, 0x00050084u, 0x00000008u, 0x0000021fu, + 0x0000010bu, 0x00000217u, 0x00050080u, 0x00000008u, 0x00000220u, 0x0000021fu, 0x0000010bu, 0x0004007cu, + 0x00000006u, 0x00000221u, 0x00000220u, 0x000600cbu, 0x00000006u, 0x000003d4u, 0x00000221u, 0x00000032u, + 0x00000056u, 0x000600cbu, 0x00000006u, 0x000003d6u, 0x00000221u, 0x00000056u, 0x0000005au, 0x0004003du, + 0x0000005cu, 0x000003d7u, 0x0000005eu, 0x0004007cu, 0x00000008u, 0x000003d9u, 0x000003d4u, 0x0004007cu, + 0x00000008u, 0x000003dbu, 0x000003d6u, 0x00050050u, 0x00000009u, 0x000003dcu, 0x000003d9u, 0x000003dbu, + 0x0007005fu, 0x00000065u, 0x000003ddu, 0x000003d7u, 0x000003dcu, 0x00000002u, 0x00000032u, 0x00050051u, + 0x00000006u, 0x000003deu, 0x000003ddu, 0x00000000u, 0x000500b0u, 0x00000095u, 0x00000226u, 0x000001a3u, + 0x00000225u, 0x000300f7u, 0x00000228u, 0x00000000u, 0x000400fau, 0x00000226u, 0x00000227u, 0x00000228u, + 0x000200f8u, 0x00000227u, 0x0004007cu, 0x00000008u, 0x0000022du, 0x000001a3u, 0x000600cbu, 0x00000006u, + 0x0000022eu, 0x000003ccu, 0x0000022du, 0x00000033u, 0x000500abu, 0x00000095u, 0x0000022fu, 0x0000022eu, + 0x00000067u, 0x000300f7u, 0x00000231u, 0x00000000u, 0x000400fau, 0x0000022fu, 0x00000230u, 0x00000231u, + 0x000200f8u, 0x00000230u, 0x000600cbu, 0x00000006u, 0x00000236u, 0x000003ccu, 0x00000032u, 0x0000022du, + 0x000400cdu, 0x00000008u, 0x00000237u, 0x00000236u, 0x0004007cu, 0x00000006u, 0x00000238u, 0x00000237u, + 0x00050084u, 0x00000006u, 0x0000023au, 0x000001ebu, 0x00000162u, 0x00050080u, 0x00000006u, 0x0000023bu, + 0x0000023au, 0x000001c5u, 0x00050080u, 0x00000006u, 0x0000023du, 0x0000023bu, 0x00000238u, 0x000600cbu, + 0x00000006u, 0x000003e6u, 0x0000023du, 0x00000032u, 0x0000006fu, 0x000600cbu, 0x00000006u, 0x000003e8u, + 0x0000023du, 0x0000006fu, 0x00000073u, 0x0004003du, 0x0000005cu, 0x000003e9u, 0x00000075u, 0x0004007cu, + 0x00000008u, 0x000003ebu, 0x000003e6u, 0x0004007cu, 0x00000008u, 0x000003edu, 0x000003e8u, 0x00050050u, + 0x00000009u, 0x000003eeu, 0x000003ebu, 0x000003edu, 0x0007005fu, 0x00000065u, 0x000003efu, 0x000003e9u, + 0x000003eeu, 0x00000002u, 0x00000032u, 0x00050051u, 0x00000006u, 0x000003f0u, 0x000003efu, 0x00000000u, + 0x00050084u, 0x00000006u, 0x00000243u, 0x000001ebu, 0x000001c5u, 0x00050080u, 0x00000006u, 0x00000244u, + 0x00000243u, 0x000000cfu, 0x000400cdu, 0x00000008u, 0x00000246u, 0x000003ccu, 0x00050084u, 0x00000008u, + 0x00000247u, 0x00000246u, 0x00000037u, 0x0004007cu, 0x00000006u, 0x00000248u, 0x00000247u, 0x00050080u, + 0x00000006u, 0x00000249u, 0x00000244u, 0x00000248u, 0x00050080u, 0x00000006u, 0x0000024bu, 0x00000249u, + 0x00000238u, 0x000600cbu, 0x00000006u, 0x000003f8u, 0x0000024bu, 0x00000032u, 0x00000056u, 0x000600cbu, + 0x00000006u, 0x000003fau, 0x0000024bu, 0x00000056u, 0x0000005au, 0x0004003du, 0x0000005cu, 0x000003fbu, + 0x0000005eu, 0x0004007cu, 0x00000008u, 0x000003fdu, 0x000003f8u, 0x0004007cu, 0x00000008u, 0x000003ffu, + 0x000003fau, 0x00050050u, 0x00000009u, 0x00000400u, 0x000003fdu, 0x000003ffu, 0x0007005fu, 0x00000065u, + 0x00000401u, 0x000003fbu, 0x00000400u, 0x00000002u, 0x00000032u, 0x00050051u, 0x00000006u, 0x00000402u, + 0x00000401u, 0x00000000u, 0x000500c7u, 0x00000006u, 0x00000251u, 0x00000402u, 0x00000250u, 0x000200f9u, + 0x00000231u, 0x000200f8u, 0x00000231u, 0x000700f5u, 0x00000006u, 0x00000560u, 0x00000067u, 0x00000227u, + 0x00000251u, 0x00000230u, 0x000700f5u, 0x00000006u, 0x0000055fu, 0x00000067u, 0x00000227u, 0x000003f0u, + 0x00000230u, 0x000500c7u, 0x00000006u, 0x00000254u, 0x0000055fu, 0x000000a8u, 0x000500c7u, 0x00000006u, + 0x00000257u, 0x0000055fu, 0x000000acu, 0x000500c2u, 0x00000006u, 0x0000025au, 0x00000257u, 0x00000033u, + 0x000500c5u, 0x00000006u, 0x0000025du, 0x00000257u, 0x0000025au, 0x000400cdu, 0x00000008u, 0x00000260u, + 0x00000254u, 0x000400cdu, 0x00000008u, 0x00000262u, 0x0000025du, 0x00050080u, 0x00000008u, 0x00000263u, + 0x00000260u, 0x00000262u, 0x0004007cu, 0x00000006u, 0x00000264u, 0x00000263u, 0x00050084u, 0x00000006u, + 0x00000266u, 0x00000560u, 0x000000cfu, 0x00050080u, 0x00000006u, 0x00000267u, 0x00000264u, 0x00000266u, + 0x00050084u, 0x00000006u, 0x0000026au, 0x000001ebu, 0x000001c5u, 0x00050080u, 0x00000006u, 0x0000026bu, + 0x0000026au, 0x000000cfu, 0x000400cdu, 0x00000008u, 0x0000026du, 0x000003ccu, 0x00050084u, 0x00000008u, + 0x0000026eu, 0x0000003au, 0x0000026du, 0x0004007cu, 0x00000006u, 0x0000026fu, 0x0000026eu, 0x00050080u, + 0x00000006u, 0x00000270u, 0x0000026bu, 0x0000026fu, 0x0006015du, 0x00000006u, 0x00000272u, 0x00000158u, + 0x00000001u, 0x00000267u, 0x00050080u, 0x00000006u, 0x00000273u, 0x00000270u, 0x00000272u, 0x000500aau, + 0x00000095u, 0x00000275u, 0x000001a3u, 0x00000250u, 0x000300f7u, 0x00000277u, 0x00000000u, 0x000400fau, + 0x00000275u, 0x00000276u, 0x00000277u, 0x000200f8u, 0x00000276u, 0x00050084u, 0x00000006u, 0x0000027au, + 0x000000cfu, 0x00000273u, 0x0003003eu, 0x00000278u, 0x0000027au, 0x000200f9u, 0x00000277u, 0x000200f8u, + 0x00000277u, 0x00050082u, 0x00000006u, 0x00000281u, 0x00000273u, 0x00000267u, 0x00050041u, 0x00000176u, + 0x00000282u, 0x0000027du, 0x000001a3u, 0x0003003eu, 0x00000282u, 0x00000281u, 0x000200f9u, 0x00000228u, + 0x000200f8u, 0x00000228u, 0x000400e0u, 0x00000162u, 0x00000162u, 0x00000168u, 0x0004007cu, 0x00000008u, + 0x00000285u, 0x000001c8u, 0x000600cbu, 0x00000006u, 0x00000286u, 0x000003ccu, 0x00000285u, 0x00000033u, + 0x000500abu, 0x00000095u, 0x00000287u, 0x00000286u, 0x00000067u, 0x000300f7u, 0x00000289u, 0x00000000u, + 0x000400fau, 0x00000287u, 0x00000288u, 0x000002e2u, 0x000200f8u, 0x00000288u, 0x000600cbu, 0x00000006u, + 0x0000028eu, 0x000003ccu, 0x00000032u, 0x00000285u, 0x000400cdu, 0x00000008u, 0x0000028fu, 0x0000028eu, + 0x0004007cu, 0x00000006u, 0x00000290u, 0x0000028fu, 0x00050084u, 0x00000006u, 0x00000293u, 0x000001ebu, + 0x00000162u, 0x00050080u, 0x00000006u, 0x00000294u, 0x00000293u, 0x000001c5u, 0x00050080u, 0x00000006u, + 0x00000296u, 0x00000294u, 0x00000290u, 0x000600cbu, 0x00000006u, 0x0000040au, 0x00000296u, 0x00000032u, + 0x0000006fu, 0x000600cbu, 0x00000006u, 0x0000040cu, 0x00000296u, 0x0000006fu, 0x00000073u, 0x0004003du, + 0x0000005cu, 0x0000040du, 0x00000075u, 0x0004007cu, 0x00000008u, 0x0000040fu, 0x0000040au, 0x0004007cu, + 0x00000008u, 0x00000411u, 0x0000040cu, 0x00050050u, 0x00000009u, 0x00000412u, 0x0000040fu, 0x00000411u, + 0x0007005fu, 0x00000065u, 0x00000413u, 0x0000040du, 0x00000412u, 0x00000002u, 0x00000032u, 0x00050051u, + 0x00000006u, 0x00000414u, 0x00000413u, 0x00000000u, 0x00050084u, 0x00000006u, 0x0000029du, 0x000001ebu, + 0x000001c5u, 0x00050080u, 0x00000006u, 0x0000029eu, 0x0000029du, 0x000000cfu, 0x000400cdu, 0x00000008u, + 0x000002a0u, 0x000003ccu, 0x00050084u, 0x00000008u, 0x000002a1u, 0x000002a0u, 0x00000037u, 0x0004007cu, + 0x00000006u, 0x000002a2u, 0x000002a1u, 0x00050080u, 0x00000006u, 0x000002a3u, 0x0000029eu, 0x000002a2u, + 0x00050080u, 0x00000006u, 0x000002a5u, 0x000002a3u, 0x00000290u, 0x000600cbu, 0x00000006u, 0x0000041cu, + 0x000002a5u, 0x00000032u, 0x00000056u, 0x000600cbu, 0x00000006u, 0x0000041eu, 0x000002a5u, 0x00000056u, + 0x0000005au, 0x0004003du, 0x0000005cu, 0x0000041fu, 0x0000005eu, 0x0004007cu, 0x00000008u, 0x00000421u, + 0x0000041cu, 0x0004007cu, 0x00000008u, 0x00000423u, 0x0000041eu, 0x00050050u, 0x00000009u, 0x00000424u, + 0x00000421u, 0x00000423u, 0x0007005fu, 0x00000065u, 0x00000425u, 0x0000041fu, 0x00000424u, 0x00000002u, + 0x00000032u, 0x00050051u, 0x00000006u, 0x00000426u, 0x00000425u, 0x00000000u, 0x000500c7u, 0x00000006u, + 0x000002acu, 0x00000426u, 0x00000250u, 0x00050041u, 0x00000176u, 0x000002b2u, 0x0000027du, 0x000001c8u, + 0x0004003du, 0x00000006u, 0x000002b3u, 0x000002b2u, 0x000300f7u, 0x000004b6u, 0x00000000u, 0x000300fbu, + 0x00000067u, 0x0000043fu, 0x000200f8u, 0x0000043fu, 0x000500aau, 0x00000095u, 0x00000441u, 0x00000414u, + 0x00000067u, 0x000300f7u, 0x00000444u, 0x00000000u, 0x000400fau, 0x00000441u, 0x00000443u, 0x00000444u, + 0x000200f8u, 0x00000443u, 0x000200f9u, 0x000004b6u, 0x000200f8u, 0x00000444u, 0x0004007cu, 0x00000008u, + 0x00000446u, 0x000001bcu, 0x00050084u, 0x00000008u, 0x00000447u, 0x00000037u, 0x00000446u, 0x000500c7u, + 0x00000006u, 0x00000449u, 0x00000414u, 0x000000a8u, 0x000500c7u, 0x00000006u, 0x0000044bu, 0x00000414u, + 0x000000acu, 0x000500c2u, 0x00000006u, 0x0000044du, 0x0000044bu, 0x00000033u, 0x000500c5u, 0x00000006u, + 0x00000450u, 0x0000044bu, 0x0000044du, 0x000600cbu, 0x00000006u, 0x00000453u, 0x00000449u, 0x00000032u, + 0x00000447u, 0x000400cdu, 0x00000008u, 0x00000454u, 0x00000453u, 0x000600cbu, 0x00000006u, 0x00000457u, + 0x00000450u, 0x00000032u, 0x00000447u, 0x000400cdu, 0x00000008u, 0x00000458u, 0x00000457u, 0x00050080u, + 0x00000008u, 0x00000459u, 0x00000454u, 0x00000458u, 0x0004007cu, 0x00000006u, 0x0000045au, 0x00000459u, + 0x00050084u, 0x00000006u, 0x0000045du, 0x000002acu, 0x000001bcu, 0x00050080u, 0x00000006u, 0x0000045eu, + 0x0000045au, 0x0000045du, 0x00050080u, 0x00000006u, 0x00000460u, 0x0000045eu, 0x000002b3u, 0x000600cbu, + 0x00000006u, 0x000004beu, 0x00000460u, 0x00000032u, 0x00000056u, 0x000600cbu, 0x00000006u, 0x000004c0u, + 0x00000460u, 0x00000056u, 0x0000005au, 0x0004003du, 0x0000005cu, 0x000004c1u, 0x0000005eu, 0x0004007cu, + 0x00000008u, 0x000004c3u, 0x000004beu, 0x0004007cu, 0x00000008u, 0x000004c5u, 0x000004c0u, 0x00050050u, + 0x00000009u, 0x000004c6u, 0x000004c3u, 0x000004c5u, 0x0007005fu, 0x00000065u, 0x000004c7u, 0x000004c1u, + 0x000004c6u, 0x00000002u, 0x00000032u, 0x00050051u, 0x00000006u, 0x000004c8u, 0x000004c7u, 0x00000000u, + 0x000600cbu, 0x00000006u, 0x00000467u, 0x00000414u, 0x00000447u, 0x00000037u, 0x0003003eu, 0x00000433u, + 0x000000d3u, 0x00050080u, 0x00000006u, 0x0000046au, 0x000002acu, 0x00000467u, 0x0004007cu, 0x00000008u, + 0x0000046bu, 0x0000046au, 0x00050082u, 0x00000008u, 0x0000046du, 0x0000046bu, 0x00000033u, 0x000200f9u, + 0x0000046eu, 0x000200f8u, 0x0000046eu, 0x000700f5u, 0x00000006u, 0x0000056au, 0x00000460u, 0x00000444u, + 0x00000489u, 0x0000048eu, 0x000700f5u, 0x00000008u, 0x00000561u, 0x0000046du, 0x00000444u, 0x00000490u, + 0x0000048eu, 0x000700f5u, 0x00000006u, 0x0000056du, 0x000004c8u, 0x00000444u, 0x000004dau, 0x0000048eu, + 0x000500afu, 0x00000095u, 0x00000471u, 0x00000561u, 0x00000032u, 0x000400f6u, 0x00000491u, 0x0000048eu, + 0x00000000u, 0x000400fau, 0x00000471u, 0x00000472u, 0x00000491u, 0x000200f8u, 0x00000472u, 0x000200f9u, + 0x00000473u, 0x000200f8u, 0x00000473u, 0x000700f5u, 0x00000008u, 0x00000568u, 0x00000032u, 0x00000472u, + 0x00000486u, 0x00000477u, 0x000500b1u, 0x00000095u, 0x00000476u, 0x00000568u, 0x000000eau, 0x000400f6u, + 0x00000487u, 0x00000477u, 0x00000000u, 0x000400fau, 0x00000476u, 0x00000477u, 0x00000487u, 0x000200f8u, + 0x00000477u, 0x000600cbu, 0x00000006u, 0x0000047au, 0x0000056du, 0x00000568u, 0x00000033u, 0x0004007cu, + 0x00000008u, 0x0000047bu, 0x0000047au, 0x00050041u, 0x000000a1u, 0x0000047eu, 0x00000433u, 0x00000568u, + 0x0004003du, 0x00000008u, 0x0000047fu, 0x0000047eu, 0x000700c9u, 0x00000008u, 0x00000482u, 0x0000047fu, + 0x0000047bu, 0x00000561u, 0x00000033u, 0x0003003eu, 0x0000047eu, 0x00000482u, 0x00050080u, 0x00000008u, + 0x00000486u, 0x00000568u, 0x00000033u, 0x000200f9u, 0x00000473u, 0x000200f8u, 0x00000487u, 0x00050080u, + 0x00000006u, 0x00000489u, 0x0000056au, 0x00000033u, 0x000600cbu, 0x00000006u, 0x000004d0u, 0x00000489u, + 0x00000032u, 0x00000056u, 0x000600cbu, 0x00000006u, 0x000004d2u, 0x00000489u, 0x00000056u, 0x0000005au, + 0x0004003du, 0x0000005cu, 0x000004d3u, 0x0000005eu, 0x0004007cu, 0x00000008u, 0x000004d5u, 0x000004d0u, + 0x0004007cu, 0x00000008u, 0x000004d7u, 0x000004d2u, 0x00050050u, 0x00000009u, 0x000004d8u, 0x000004d5u, + 0x000004d7u, 0x0007005fu, 0x00000065u, 0x000004d9u, 0x000004d3u, 0x000004d8u, 0x00000002u, 0x00000032u, + 0x00050051u, 0x00000006u, 0x000004dau, 0x000004d9u, 0x00000000u, 0x000200f9u, 0x0000048eu, 0x000200f8u, + 0x0000048eu, 0x00050082u, 0x00000008u, 0x00000490u, 0x00000561u, 0x00000033u, 0x000200f9u, 0x0000046eu, + 0x000200f8u, 0x00000491u, 0x000200f9u, 0x00000492u, 0x000200f8u, 0x00000492u, 0x000700f5u, 0x00000008u, + 0x00000562u, 0x00000032u, 0x00000491u, 0x000004b3u, 0x000004b1u, 0x000500b1u, 0x00000095u, 0x00000495u, + 0x00000562u, 0x0000010bu, 0x000400f6u, 0x000004b4u, 0x000004b1u, 0x00000000u, 0x000400fau, 0x00000495u, + 0x00000496u, 0x000004b4u, 0x000200f8u, 0x00000496u, 0x000200f9u, 0x00000497u, 0x000200f8u, 0x00000497u, + 0x000700f5u, 0x00000008u, 0x00000563u, 0x00000032u, 0x00000496u, 0x000004afu, 0x000004adu, 0x000500b1u, + 0x00000095u, 0x0000049au, 0x00000563u, 0x00000037u, 0x000400f6u, 0x000004b0u, 0x000004adu, 0x00000000u, + 0x000400fau, 0x0000049au, 0x0000049bu, 0x000004b0u, 0x000200f8u, 0x0000049bu, 0x00050084u, 0x00000008u, + 0x0000049du, 0x00000562u, 0x00000037u, 0x00050080u, 0x00000008u, 0x0000049fu, 0x0000049du, 0x00000563u, + 0x00050041u, 0x000000a1u, 0x000004a0u, 0x00000433u, 0x0000049fu, 0x0004003du, 0x00000008u, 0x000004a1u, + 0x000004a0u, 0x0004006fu, 0x0000000eu, 0x000004a2u, 0x000004a1u, 0x000500b7u, 0x00000095u, 0x000004a4u, + 0x000004a2u, 0x0000009du, 0x000300f7u, 0x000004a8u, 0x00000000u, 0x000400fau, 0x000004a4u, 0x000004a5u, + 0x000004a8u, 0x000200f8u, 0x000004a5u, 0x00050081u, 0x0000000eu, 0x000004a7u, 0x000004a2u, 0x00000122u, + 0x000200f9u, 0x000004a8u, 0x000200f8u, 0x000004a8u, 0x000700f5u, 0x0000000eu, 0x00000567u, 0x000004a2u, + 0x0000049bu, 0x000004a7u, 0x000004a5u, 0x00060041u, 0x00000115u, 0x000004acu, 0x0000043cu, 0x00000563u, + 0x00000562u, 0x0003003eu, 0x000004acu, 0x00000567u, 0x000200f9u, 0x000004adu, 0x000200f8u, 0x000004adu, + 0x00050080u, 0x00000008u, 0x000004afu, 0x00000563u, 0x00000033u, 0x000200f9u, 0x00000497u, 0x000200f8u, + 0x000004b0u, 0x000200f9u, 0x000004b1u, 0x000200f8u, 0x000004b1u, 0x00050080u, 0x00000008u, 0x000004b3u, + 0x00000562u, 0x00000033u, 0x000200f9u, 0x00000492u, 0x000200f8u, 0x000004b4u, 0x0004003du, 0x0000001eu, + 0x000004b5u, 0x0000043cu, 0x000200f9u, 0x000004b6u, 0x000200f8u, 0x000004b6u, 0x000700f5u, 0x0000001eu, + 0x0000056eu, 0x0000009fu, 0x00000443u, 0x000004b5u, 0x000004b4u, 0x0003003eu, 0x000002aau, 0x0000056eu, + 0x000200f9u, 0x000002b9u, 0x000200f8u, 0x000002b9u, 0x000700f5u, 0x00000008u, 0x00000571u, 0x00000032u, + 0x000004b6u, 0x00000594u, 0x000002bcu, 0x000700f5u, 0x00000008u, 0x0000056fu, 0x00000032u, 0x000004b6u, + 0x000002d3u, 0x000002bcu, 0x000500b1u, 0x00000095u, 0x000002bfu, 0x0000056fu, 0x00000037u, 0x000400f6u, + 0x000002bbu, 0x000002bcu, 0x00000000u, 0x000400fau, 0x000002bfu, 0x000002bau, 0x000002bbu, 0x000200f8u, + 0x000002bau, 0x000200f9u, 0x000002c1u, 0x000200f8u, 0x000002c1u, 0x000700f5u, 0x00000008u, 0x00000594u, + 0x00000571u, 0x000002bau, 0x000002cfu, 0x000002c2u, 0x000700f5u, 0x00000008u, 0x00000592u, 0x00000032u, + 0x000002bau, 0x000002d1u, 0x000002c2u, 0x000500b1u, 0x00000095u, 0x000002c7u, 0x00000592u, 0x0000010bu, + 0x000400f6u, 0x000002c3u, 0x000002c2u, 0x00000000u, 0x000400fau, 0x000002c7u, 0x000002c2u, 0x000002c3u, + 0x000200f8u, 0x000002c2u, 0x00060041u, 0x00000115u, 0x000002cau, 0x000002aau, 0x0000056fu, 0x00000592u, + 0x0004003du, 0x0000000eu, 0x000002cbu, 0x000002cau, 0x000500b7u, 0x00000095u, 0x000002ccu, 0x000002cbu, + 0x0000009du, 0x000600a9u, 0x00000008u, 0x000002cdu, 0x000002ccu, 0x00000033u, 0x00000032u, 0x00050080u, + 0x00000008u, 0x000002cfu, 0x00000594u, 0x000002cdu, 0x00050080u, 0x00000008u, 0x000002d1u, 0x00000592u, + 0x00000033u, 0x000200f9u, 0x000002c1u, 0x000200f8u, 0x000002c3u, 0x000200f9u, 0x000002bcu, 0x000200f8u, + 0x000002bcu, 0x00050080u, 0x00000008u, 0x000002d3u, 0x0000056fu, 0x00000033u, 0x000200f9u, 0x000002b9u, + 0x000200f8u, 0x000002bbu, 0x000500c2u, 0x00000006u, 0x000004e2u, 0x000003deu, 0x0000003au, 0x0004007cu, + 0x00000008u, 0x000004e3u, 0x000004e2u, 0x0004007cu, 0x00000008u, 0x000004e6u, 0x000003deu, 0x000500c7u, + 0x00000008u, 0x000004e7u, 0x000004e6u, 0x0000013au, 0x00050080u, 0x00000008u, 0x000004e9u, 0x000000eau, + 0x000004e7u, 0x00050082u, 0x00000008u, 0x000004ebu, 0x000005a0u, 0x000004e3u, 0x000500c4u, 0x00000008u, + 0x000004ecu, 0x00000033u, 0x000004ebu, 0x00050084u, 0x00000008u, 0x000004edu, 0x000004e9u, 0x000004ecu, + 0x0004006fu, 0x0000000eu, 0x000004eeu, 0x000004edu, 0x00050085u, 0x0000000eu, 0x000004efu, 0x0000013du, + 0x000004eeu, 0x000600cbu, 0x00000006u, 0x000002dbu, 0x00000426u, 0x0000010bu, 0x0000010bu, 0x00040070u, + 0x0000000eu, 0x000004f4u, 0x000002dbu, 0x00050085u, 0x0000000eu, 0x000004f5u, 0x000004f4u, 0x000005a1u, + 0x00050081u, 0x0000000eu, 0x000004f6u, 0x000004f5u, 0x00000050u, 0x00050085u, 0x0000000eu, 0x000002deu, + 0x000004efu, 0x000004f6u, 0x0004003du, 0x0000001eu, 0x000002e0u, 0x000002aau, 0x0005008fu, 0x0000001eu, + 0x000002e1u, 0x000002e0u, 0x000002deu, 0x0003003eu, 0x000002aau, 0x000002e1u, 0x000200f9u, 0x00000289u, + 0x000200f8u, 0x000002e2u, 0x0003003eu, 0x000002aau, 0x0000009fu, 0x000200f9u, 0x00000289u, 0x000200f8u, + 0x00000289u, 0x000700f5u, 0x00000008u, 0x00000570u, 0x00000571u, 0x000002bbu, 0x00000032u, 0x000002e2u, + 0x0006015du, 0x00000008u, 0x000002e5u, 0x00000158u, 0x00000001u, 0x00000570u, 0x00050082u, 0x00000006u, + 0x000002e8u, 0x000001a0u, 0x0000014au, 0x000500aau, 0x00000095u, 0x000002e9u, 0x000001a2u, 0x000002e8u, + 0x000300f7u, 0x000002ebu, 0x00000000u, 0x000400fau, 0x000002e9u, 0x000002eau, 0x000002ebu, 0x000200f8u, + 0x000002eau, 0x0004007cu, 0x00000006u, 0x000002eeu, 0x000002e5u, 0x00050041u, 0x00000176u, 0x000002efu, + 0x00000174u, 0x0000019eu, 0x0003003eu, 0x000002efu, 0x000002eeu, 0x000200f9u, 0x000002ebu, 0x000200f8u, + 0x000002ebu, 0x0004003du, 0x00000006u, 0x000002f0u, 0x00000152u, 0x000500b2u, 0x00000095u, 0x000002f1u, + 0x000002f0u, 0x000000cfu, 0x000300f7u, 0x000002f3u, 0x00000000u, 0x000400fau, 0x000002f1u, 0x000002f2u, + 0x00000310u, 0x000200f8u, 0x000002f2u, 0x000400e0u, 0x00000162u, 0x00000162u, 0x00000168u, 0x000500b2u, + 0x00000095u, 0x000002f5u, 0x000001a0u, 0x00000171u, 0x000300f7u, 0x000002f7u, 0x00000000u, 0x000400fau, + 0x000002f5u, 0x000002f6u, 0x00000303u, 0x000200f8u, 0x000002f6u, 0x000500b0u, 0x00000095u, 0x000002fau, + 0x000001a3u, 0x000002f0u, 0x000300f7u, 0x000002fcu, 0x00000000u, 0x000400fau, 0x000002fau, 0x000002fbu, + 0x000002fcu, 0x000200f8u, 0x000002fbu, 0x00050041u, 0x00000176u, 0x000002ffu, 0x00000174u, 0x000001a3u, + 0x0004003du, 0x00000006u, 0x00000300u, 0x000002ffu, 0x0006015du, 0x00000006u, 0x00000301u, 0x00000158u, + 0x00000001u, 0x00000300u, 0x0003003eu, 0x000002ffu, 0x00000301u, 0x000200f9u, 0x000002fcu, 0x000200f8u, + 0x000002fcu, 0x000200f9u, 0x000002f7u, 0x000200f8u, 0x00000303u, 0x000500b0u, 0x00000095u, 0x00000306u, + 0x000001a3u, 0x000002f0u, 0x000300f7u, 0x00000308u, 0x00000000u, 0x000400fau, 0x00000306u, 0x00000307u, + 0x00000308u, 0x000200f8u, 0x00000307u, 0x00050041u, 0x00000176u, 0x0000030cu, 0x00000174u, 0x000001a3u, + 0x0004003du, 0x00000006u, 0x0000030du, 0x0000030cu, 0x000200f9u, 0x000004fbu, 0x000200f8u, 0x000004fbu, + 0x000700f5u, 0x00000006u, 0x0000057au, 0x0000030du, 0x00000307u, 0x0000050au, 0x00000500u, 0x000700f5u, + 0x00000006u, 0x00000579u, 0x0000014au, 0x00000307u, 0x0000050du, 0x00000500u, 0x000500b0u, 0x00000095u, + 0x000004ffu, 0x00000579u, 0x000002f0u, 0x000400f6u, 0x0000050eu, 0x00000500u, 0x00000000u, 0x000400fau, + 0x000004ffu, 0x00000500u, 0x0000050eu, 0x000200f8u, 0x00000500u, 0x0006015bu, 0x00000006u, 0x00000503u, + 0x00000158u, 0x0000057au, 0x00000579u, 0x000500aeu, 0x00000095u, 0x00000506u, 0x000001a2u, 0x00000579u, + 0x000600a9u, 0x00000006u, 0x00000508u, 0x00000506u, 0x00000503u, 0x00000067u, 0x00050080u, 0x00000006u, + 0x0000050au, 0x0000057au, 0x00000508u, 0x00050084u, 0x00000006u, 0x0000050du, 0x00000579u, 0x00000162u, + 0x000200f9u, 0x000004fbu, 0x000200f8u, 0x0000050eu, 0x0003003eu, 0x0000030cu, 0x0000057au, 0x000200f9u, + 0x00000308u, 0x000200f8u, 0x00000308u, 0x000200f9u, 0x000002f7u, 0x000200f8u, 0x000002f7u, 0x000400e0u, + 0x00000162u, 0x00000162u, 0x00000168u, 0x000200f9u, 0x000002f3u, 0x000200f8u, 0x00000310u, 0x000400e0u, + 0x00000162u, 0x00000162u, 0x00000168u, 0x000500b0u, 0x00000095u, 0x00000518u, 0x000001a3u, 0x000002f0u, + 0x000300f7u, 0x0000051eu, 0x00000000u, 0x000400fau, 0x00000518u, 0x0000051au, 0x0000051eu, 0x000200f8u, + 0x0000051au, 0x00050041u, 0x00000176u, 0x0000051cu, 0x00000174u, 0x000001a3u, 0x0004003du, 0x00000006u, + 0x0000051du, 0x0000051cu, 0x000200f9u, 0x0000051eu, 0x000200f8u, 0x0000051eu, 0x000700f5u, 0x00000006u, + 0x00000576u, 0x00000067u, 0x00000310u, 0x0000051du, 0x0000051au, 0x000200f9u, 0x0000051fu, 0x000200f8u, + 0x0000051fu, 0x000700f5u, 0x00000006u, 0x00000575u, 0x00000576u, 0x0000051eu, 0x00000598u, 0x0000053bu, + 0x000700f5u, 0x00000006u, 0x00000572u, 0x0000014au, 0x0000051eu, 0x0000053du, 0x0000053bu, 0x000500b0u, + 0x00000095u, 0x00000523u, 0x00000572u, 0x000002f0u, 0x000400f6u, 0x0000053eu, 0x0000053bu, 0x00000000u, + 0x000400fau, 0x00000523u, 0x00000524u, 0x0000053eu, 0x000200f8u, 0x00000524u, 0x000500aeu, 0x00000095u, + 0x00000527u, 0x000001a3u, 0x00000572u, 0x000500a7u, 0x00000095u, 0x00000529u, 0x00000527u, 0x00000518u, + 0x000300f7u, 0x00000531u, 0x00000000u, 0x000400fau, 0x00000529u, 0x0000052bu, 0x00000531u, 0x000200f8u, + 0x0000052bu, 0x00050082u, 0x00000006u, 0x0000052eu, 0x000001a3u, 0x00000572u, 0x00050041u, 0x00000176u, + 0x0000052fu, 0x00000174u, 0x0000052eu, 0x0004003du, 0x00000006u, 0x00000530u, 0x0000052fu, 0x000200f9u, + 0x00000531u, 0x000200f8u, 0x00000531u, 0x000700f5u, 0x00000006u, 0x00000573u, 0x00000067u, 0x00000524u, + 0x00000530u, 0x0000052bu, 0x000400e0u, 0x00000162u, 0x00000162u, 0x00000168u, 0x000300f7u, 0x0000053au, + 0x00000000u, 0x000400fau, 0x00000529u, 0x00000533u, 0x0000053au, 0x000200f8u, 0x00000533u, 0x00050080u, + 0x00000006u, 0x00000536u, 0x00000575u, 0x00000573u, 0x00050041u, 0x00000176u, 0x00000539u, 0x00000174u, + 0x000001a3u, 0x0003003eu, 0x00000539u, 0x00000536u, 0x000200f9u, 0x0000053au, 0x000200f8u, 0x0000053au, + 0x000700f5u, 0x00000006u, 0x00000598u, 0x00000575u, 0x00000531u, 0x00000536u, 0x00000533u, 0x000400e0u, + 0x00000162u, 0x00000162u, 0x00000168u, 0x000200f9u, 0x0000053bu, 0x000200f8u, 0x0000053bu, 0x00050084u, + 0x00000006u, 0x0000053du, 0x00000572u, 0x00000162u, 0x000200f9u, 0x0000051fu, 0x000200f8u, 0x0000053eu, + 0x000200f9u, 0x000002f3u, 0x000200f8u, 0x000002f3u, 0x0004003du, 0x00000006u, 0x00000315u, 0x00000278u, + 0x0004007cu, 0x00000006u, 0x00000317u, 0x000002e5u, 0x00050080u, 0x00000006u, 0x00000318u, 0x00000315u, + 0x00000317u, 0x0004007cu, 0x00000006u, 0x0000031au, 0x00000570u, 0x00050082u, 0x00000006u, 0x0000031bu, + 0x00000318u, 0x0000031au, 0x000500abu, 0x00000095u, 0x0000031du, 0x0000019eu, 0x00000067u, 0x000300f7u, + 0x0000031fu, 0x00000000u, 0x000400fau, 0x0000031du, 0x0000031eu, 0x0000031fu, 0x000200f8u, 0x0000031eu, + 0x00050082u, 0x00000006u, 0x00000321u, 0x0000019eu, 0x0000014au, 0x00050041u, 0x00000176u, 0x00000322u, + 0x00000174u, 0x00000321u, 0x0004003du, 0x00000006u, 0x00000323u, 0x00000322u, 0x00050080u, 0x00000006u, + 0x00000325u, 0x0000031bu, 0x00000323u, 0x000200f9u, 0x0000031fu, 0x000200f8u, 0x0000031fu, 0x000700f5u, + 0x00000006u, 0x00000585u, 0x0000031bu, 0x000002f3u, 0x00000325u, 0x0000031eu, 0x00050086u, 0x00000006u, + 0x00000328u, 0x00000585u, 0x00000171u, 0x000600cbu, 0x00000006u, 0x00000544u, 0x00000328u, 0x00000032u, + 0x00000084u, 0x000600cbu, 0x00000006u, 0x00000546u, 0x00000328u, 0x00000084u, 0x00000088u, 0x0004003du, + 0x0000005cu, 0x00000547u, 0x0000008au, 0x0004007cu, 0x00000008u, 0x00000549u, 0x00000544u, 0x0004007cu, + 0x00000008u, 0x0000054bu, 0x00000546u, 0x00050050u, 0x00000009u, 0x0000054cu, 0x00000549u, 0x0000054bu, + 0x0007005fu, 0x00000065u, 0x0000054du, 0x00000547u, 0x0000054cu, 0x00000002u, 0x00000032u, 0x00050051u, + 0x00000006u, 0x0000054eu, 0x0000054du, 0x00000000u, 0x00050080u, 0x00000006u, 0x00000331u, 0x00000328u, + 0x0000014au, 0x000600cbu, 0x00000006u, 0x00000554u, 0x00000331u, 0x00000032u, 0x00000084u, 0x000600cbu, + 0x00000006u, 0x00000556u, 0x00000331u, 0x00000084u, 0x00000088u, 0x0004003du, 0x0000005cu, 0x00000557u, + 0x0000008au, 0x0004007cu, 0x00000008u, 0x00000559u, 0x00000554u, 0x0004007cu, 0x00000008u, 0x0000055bu, + 0x00000556u, 0x00050050u, 0x00000009u, 0x0000055cu, 0x00000559u, 0x0000055bu, 0x0007005fu, 0x00000065u, + 0x0000055du, 0x00000557u, 0x0000055cu, 0x00000002u, 0x00000032u, 0x00050051u, 0x00000006u, 0x0000055eu, + 0x0000055du, 0x00000000u, 0x000500c7u, 0x00000006u, 0x00000339u, 0x00000585u, 0x00000338u, 0x000500abu, + 0x00000095u, 0x0000033bu, 0x00000339u, 0x00000067u, 0x000300f7u, 0x0000033du, 0x00000000u, 0x000400fau, + 0x0000033bu, 0x0000033cu, 0x0000033du, 0x000200f8u, 0x0000033cu, 0x000500c2u, 0x00000006u, 0x00000340u, + 0x0000054eu, 0x00000339u, 0x00050082u, 0x00000006u, 0x00000343u, 0x00000171u, 0x00000339u, 0x000500c4u, + 0x00000006u, 0x00000344u, 0x0000055eu, 0x00000343u, 0x000500c5u, 0x00000006u, 0x00000346u, 0x00000340u, + 0x00000344u, 0x000200f9u, 0x0000033du, 0x000200f8u, 0x0000033du, 0x000700f5u, 0x00000006u, 0x0000058eu, + 0x0000054eu, 0x0000031fu, 0x00000346u, 0x0000033cu, 0x000200f9u, 0x00000349u, 0x000200f8u, 0x00000349u, + 0x000700f5u, 0x00000008u, 0x00000586u, 0x00000032u, 0x0000033du, 0x00000372u, 0x0000034cu, 0x000700f5u, + 0x00000008u, 0x00000590u, 0x00000032u, 0x0000033du, 0x0000058fu, 0x0000034cu, 0x000500b1u, 0x00000095u, + 0x0000034fu, 0x00000586u, 0x0000010bu, 0x000400f6u, 0x0000034bu, 0x0000034cu, 0x00000000u, 0x000400fau, + 0x0000034fu, 0x0000034au, 0x0000034bu, 0x000200f8u, 0x0000034au, 0x000200f9u, 0x00000351u, 0x000200f8u, + 0x00000351u, 0x000700f5u, 0x00000008u, 0x0000058fu, 0x00000590u, 0x0000034au, 0x0000059bu, 0x00000354u, + 0x000700f5u, 0x00000008u, 0x0000058au, 0x00000032u, 0x0000034au, 0x00000370u, 0x00000354u, 0x000500b1u, + 0x00000095u, 0x00000357u, 0x0000058au, 0x00000037u, 0x000400f6u, 0x00000353u, 0x00000354u, 0x00000000u, + 0x000400fau, 0x00000357u, 0x00000352u, 0x00000353u, 0x000200f8u, 0x00000352u, 0x00060041u, 0x00000115u, + 0x0000035au, 0x000002aau, 0x0000058au, 0x00000586u, 0x0004003du, 0x0000000eu, 0x0000035bu, 0x0000035au, + 0x000500b7u, 0x00000095u, 0x0000035cu, 0x0000035bu, 0x0000009du, 0x000300f7u, 0x0000035eu, 0x00000000u, + 0x000400fau, 0x0000035cu, 0x0000035du, 0x0000035eu, 0x000200f8u, 0x0000035du, 0x000600cbu, 0x00000006u, + 0x00000365u, 0x0000058eu, 0x0000058fu, 0x00000033u, 0x00040070u, 0x0000000eu, 0x00000366u, 0x00000365u, + 0x00050085u, 0x0000000eu, 0x00000367u, 0x00000362u, 0x00000366u, 0x00050083u, 0x0000000eu, 0x00000368u, + 0x00000361u, 0x00000367u, 0x0004003du, 0x0000000eu, 0x0000036au, 0x0000035au, 0x00050085u, 0x0000000eu, + 0x0000036bu, 0x0000036au, 0x00000368u, 0x0003003eu, 0x0000035au, 0x0000036bu, 0x00050080u, 0x00000008u, + 0x0000036eu, 0x0000058fu, 0x00000033u, 0x000200f9u, 0x0000035eu, 0x000200f8u, 0x0000035eu, 0x000700f5u, + 0x00000008u, 0x0000059bu, 0x0000058fu, 0x00000352u, 0x0000036eu, 0x0000035du, 0x000200f9u, 0x00000354u, + 0x000200f8u, 0x00000354u, 0x00050080u, 0x00000008u, 0x00000370u, 0x0000058au, 0x00000033u, 0x000200f9u, + 0x00000351u, 0x000200f8u, 0x00000353u, 0x000200f9u, 0x0000034cu, 0x000200f8u, 0x0000034cu, 0x00050080u, + 0x00000008u, 0x00000372u, 0x00000586u, 0x00000033u, 0x000200f9u, 0x00000349u, 0x000200f8u, 0x0000034bu, + 0x000200f9u, 0x00000374u, 0x000200f8u, 0x00000374u, 0x000700f5u, 0x00000008u, 0x00000587u, 0x00000032u, + 0x0000034bu, 0x00000396u, 0x00000377u, 0x000500b1u, 0x00000095u, 0x0000037au, 0x00000587u, 0x00000037u, + 0x000400f6u, 0x00000376u, 0x00000377u, 0x00000000u, 0x000400fau, 0x0000037au, 0x00000375u, 0x00000376u, + 0x000200f8u, 0x00000375u, 0x000200f9u, 0x0000037cu, 0x000200f8u, 0x0000037cu, 0x000700f5u, 0x00000008u, + 0x00000588u, 0x00000032u, 0x00000375u, 0x00000394u, 0x0000037du, 0x000500b1u, 0x00000095u, 0x00000382u, + 0x00000588u, 0x0000010bu, 0x000400f6u, 0x0000037eu, 0x0000037du, 0x00000000u, 0x000400fau, 0x00000382u, + 0x0000037du, 0x0000037eu, 0x000200f8u, 0x0000037du, 0x0004003du, 0x00000201u, 0x00000383u, 0x00000203u, + 0x00050050u, 0x00000009u, 0x00000387u, 0x00000588u, 0x00000587u, 0x00050080u, 0x00000009u, 0x00000388u, + 0x000001e2u, 0x00000387u, 0x00050041u, 0x000001a8u, 0x00000389u, 0x000001a7u, 0x00000033u, 0x0004003du, + 0x00000008u, 0x0000038au, 0x00000389u, 0x00050051u, 0x00000008u, 0x0000038bu, 0x00000388u, 0x00000000u, + 0x00050051u, 0x00000008u, 0x0000038cu, 0x00000388u, 0x00000001u, 0x00060050u, 0x0000020cu, 0x0000038du, + 0x0000038bu, 0x0000038cu, 0x0000038au, 0x00060041u, 0x00000115u, 0x00000390u, 0x000002aau, 0x00000587u, + 0x00000588u, 0x0004003du, 0x0000000eu, 0x00000391u, 0x00000390u, 0x00070050u, 0x0000001du, 0x00000392u, + 0x00000391u, 0x00000391u, 0x00000391u, 0x00000391u, 0x00040063u, 0x00000383u, 0x0000038du, 0x00000392u, + 0x00050080u, 0x00000008u, 0x00000394u, 0x00000588u, 0x00000033u, 0x000200f9u, 0x0000037cu, 0x000200f8u, + 0x0000037eu, 0x000200f9u, 0x00000377u, 0x000200f8u, 0x00000377u, 0x00050080u, 0x00000008u, 0x00000396u, + 0x00000587u, 0x00000033u, 0x000200f9u, 0x00000374u, 0x000200f8u, 0x00000376u, 0x000200f9u, 0x0000039bu, + 0x000200f8u, 0x0000039bu, 0x000100fdu, 0x00010038u, +}; + +static const uint8_t reflection_bank[] = +{ + 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, + 0x41, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, + 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x7b, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, + 0x41, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x52, 0x00, 0x41, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +template +template +Shaders::Shaders(Device &device, Layout &layout, const Resolver &resolver) +{ + (void)resolver; + if (resolver("dwt", "FP16") == 0) + { + layout.unserialize(reflection_bank + 0, 348); + this->dwt[0] = device.request_program(spirv_bank + 0, 16332, &layout); + } + if (resolver("dwt", "FP16") == 0) + { + layout.unserialize(reflection_bank + 0, 348); + this->dwt[1] = device.request_program(spirv_bank + 0, 16332, &layout); + } + if (resolver("dwt", "FP16") == 0) + { + layout.unserialize(reflection_bank + 348, 348); + this->dwt[2] = device.request_program(spirv_bank + 4083, 15732, &layout); + } + if (resolver("dwt", "FP16") == 1) + { + layout.unserialize(reflection_bank + 696, 348); + this->dwt[0] = device.request_program(spirv_bank + 8016, 15960, &layout); + } + if (resolver("dwt", "FP16") == 1) + { + layout.unserialize(reflection_bank + 1044, 348); + this->dwt[1] = device.request_program(spirv_bank + 12006, 16168, &layout); + } + if (resolver("dwt", "FP16") == 1) + { + layout.unserialize(reflection_bank + 348, 348); + this->dwt[2] = device.request_program(spirv_bank + 4083, 15732, &layout); + } + layout.unserialize(reflection_bank + 1392, 348); + this->block_packing = device.request_program(spirv_bank + 16048, 11972, &layout); + if (resolver("idwt", "FP16") == 0) + { + layout.unserialize(reflection_bank + 1740, 348); + this->idwt[0] = device.request_program(spirv_bank + 19041, 18792, &layout); + } + if (resolver("idwt", "FP16") == 0) + { + layout.unserialize(reflection_bank + 1740, 348); + this->idwt[1] = device.request_program(spirv_bank + 19041, 18792, &layout); + } + if (resolver("idwt", "FP16") == 0) + { + layout.unserialize(reflection_bank + 2088, 348); + this->idwt[2] = device.request_program(spirv_bank + 23739, 17904, &layout); + } + if (resolver("idwt", "FP16") == 1) + { + layout.unserialize(reflection_bank + 2436, 348); + this->idwt[0] = device.request_program(spirv_bank + 28215, 18180, &layout); + } + if (resolver("idwt", "FP16") == 1) + { + layout.unserialize(reflection_bank + 2784, 348); + this->idwt[1] = device.request_program(spirv_bank + 32760, 18532, &layout); + } + if (resolver("idwt", "FP16") == 1) + { + layout.unserialize(reflection_bank + 2088, 348); + this->idwt[2] = device.request_program(spirv_bank + 23739, 17904, &layout); + } + layout.unserialize(reflection_bank + 3132, 348); + this->idwt_vs = device.request_shader(spirv_bank + 37393, 1716, &layout); + layout.unserialize(reflection_bank + 3480, 348); + this->idwt_fs[0] = device.request_shader(spirv_bank + 37822, 4804, &layout); + layout.unserialize(reflection_bank + 3828, 348); + this->idwt_fs[1] = device.request_shader(spirv_bank + 39023, 8880, &layout); + layout.unserialize(reflection_bank + 4176, 348); + this->idwt_fs[2] = device.request_shader(spirv_bank + 41243, 7368, &layout); + layout.unserialize(reflection_bank + 4524, 348); + this->power_to_db = device.request_program(spirv_bank + 43085, 1792, &layout); + layout.unserialize(reflection_bank + 4872, 348); + this->analyze_rate_control = device.request_program(spirv_bank + 43533, 6404, &layout); + layout.unserialize(reflection_bank + 5220, 348); + this->analyze_rate_control_finalize = device.request_program(spirv_bank + 45134, 1440, &layout); + layout.unserialize(reflection_bank + 5568, 348); + this->resolve_rate_control = device.request_program(spirv_bank + 45494, 2972, &layout); + layout.unserialize(reflection_bank + 5916, 348); + this->wavelet_quant = device.request_program(spirv_bank + 46237, 13184, &layout); + layout.unserialize(reflection_bank + 6264, 348); + this->wavelet_dequant[0] = device.request_program(spirv_bank + 49533, 11896, &layout); + layout.unserialize(reflection_bank + 6612, 348); + this->wavelet_dequant[1] = device.request_program(spirv_bank + 52507, 12176, &layout); + layout.unserialize(reflection_bank + 6960, 348); + this->wavelet_dequant[2] = device.request_program(spirv_bank + 55551, 13076, &layout); +} +} +#endif diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/slangmosh.json b/crates/pyrowave-sys/vendor/pyrowave/shaders/slangmosh.json new file mode 100644 index 00000000..da294ffc --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/slangmosh.json @@ -0,0 +1,71 @@ +{ + "shaders": [ + { + "name": "dwt", + "compute": true, + "path": "dwt.comp", + "variants": [ + { "define": "PRECISION", "count": 3, "resolve": false }, + { "define": "FP16", "count": 2, "resolve": true } + ] + }, + { + "name": "block_packing", + "compute": true, + "path": "block_packing.comp" + }, + { + "name": "idwt", + "compute": true, + "path": "idwt.comp", + "variants": [ + { "define": "PRECISION", "count": 3, "resolve": false }, + { "define": "FP16", "count": 2, "resolve": true } + ] + }, + { + "name": "idwt_vs", + "path": "idwt.vert" + }, + { + "name": "idwt_fs", + "path": "idwt.frag", + "variants": [ + { "define": "CHROMA_CONFIG", "count": 3 } + ] + }, + { + "name": "power_to_db", + "compute": true, + "path": "power_to_db.comp" + }, + { + "name": "analyze_rate_control", + "compute": true, + "path": "analyze_rate_control.comp" + }, + { + "name": "analyze_rate_control_finalize", + "compute": true, + "path": "analyze_rate_control_finalize.comp" + }, + { + "name": "resolve_rate_control", + "compute": true, + "path": "resolve_rate_control.comp" + }, + { + "name": "wavelet_quant", + "compute": true, + "path": "wavelet_quant.comp" + }, + { + "name": "wavelet_dequant", + "compute": true, + "path": "wavelet_dequant.comp", + "variants": [ + { "define": "STORAGE_MODE", "count" : 3 } + ] + } + ] +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/wavelet_dequant.comp b/crates/pyrowave-sys/vendor/pyrowave/shaders/wavelet_dequant.comp new file mode 100644 index 00000000..ebce6047 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/wavelet_dequant.comp @@ -0,0 +1,391 @@ +#version 450 +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#extension GL_KHR_shader_subgroup_basic : require +#extension GL_KHR_shader_subgroup_ballot : require +#extension GL_KHR_shader_subgroup_vote : require +#extension GL_KHR_shader_subgroup_arithmetic : require +#extension GL_KHR_shader_subgroup_shuffle_relative : require +#extension GL_EXT_samplerless_texture_functions : require + +#if STORAGE_MODE == 0 +#extension GL_EXT_shader_8bit_storage : require +#extension GL_EXT_shader_16bit_storage : require +#endif + +layout(local_size_x = 128) in; + +layout(set = 0, binding = 0) writeonly uniform image2DArray uDequantImg; + +layout(set = 0, binding = 1) readonly buffer PayloadOffsets +{ + uint data[]; +} payload_offsets; + +#if STORAGE_MODE == 0 +layout(set = 0, binding = 2) readonly buffer Payloads +{ + uint data[]; +} payload_data_u32; + +layout(set = 0, binding = 2) readonly buffer Payloads16 +{ + uint16_t data[]; +} payload_data_u16; + +layout(set = 0, binding = 2) readonly buffer Payloads8 +{ + uint8_t data[]; +} payload_data_u8; +#elif STORAGE_MODE == 1 +layout(set = 0, binding = 2) uniform usamplerBuffer PayloadU32; +layout(set = 0, binding = 3) uniform mediump usamplerBuffer PayloadU16; +layout(set = 0, binding = 4) uniform mediump usamplerBuffer PayloadU8; +#else +layout(set = 0, binding = 2) uniform utexture2D PayloadU32; +layout(set = 0, binding = 3) uniform mediump utexture2D PayloadU16; +layout(set = 0, binding = 4) uniform mediump utexture2D PayloadU8; +#endif + +#include "dwt_swizzle.h" +#include "dwt_quant_scale.h" +#include "constants.h" + +layout(push_constant) uniform Registers +{ + ivec2 resolution; + int output_layer; + int block_offset_32x32; + int block_stride_32x32; +} registers; + +#if STORAGE_MODE == 1 +uint read_payload_u8(int coord) +{ + return texelFetch(PayloadU8, coord).x; +} + +uint read_payload_u16(int coord) +{ + return texelFetch(PayloadU16, coord).x; +} + +uint read_payload_u32(int coord) +{ + return texelFetch(PayloadU32, coord).x; +} +#elif STORAGE_MODE == 2 +uint read_payload_u8(uint coord) +{ + uint x = bitfieldExtract(coord, 0, 12); + uint y = bitfieldExtract(coord, 12, 20); + return texelFetch(PayloadU8, ivec2(x, y), 0).x; +} + +uint read_payload_u16(uint coord) +{ + uint x = bitfieldExtract(coord, 0, 11); + uint y = bitfieldExtract(coord, 11, 21); + return texelFetch(PayloadU16, ivec2(x, y), 0).x; +} + +uint read_payload_u32(uint coord) +{ + uint x = bitfieldExtract(coord, 0, 10); + uint y = bitfieldExtract(coord, 10, 22); + return texelFetch(PayloadU32, ivec2(x, y), 0).x; +} +#endif + +mat2x4 decode_payload(uint code_word, uint q_bits, uint offset, uint block_index) +{ + bool empty_block = code_word == 0; + if (empty_block) + return mat2x4(vec4(0.0), vec4(0.0)); + + int bit_offset = 2 * int(block_index); + + // First, we need to compute the offset that our 4x2 block starts on. + uint lsbs = code_word & 0x5555u; + uint msbs = code_word & 0xaaaau; + uint msbs_shift = msbs >> 1; + msbs |= msbs_shift; + + uint byte_offset = + bitCount(bitfieldExtract(lsbs, 0, bit_offset)) + + bitCount(bitfieldExtract(msbs, 0, bit_offset)) + + q_bits * block_index + offset; + +#if STORAGE_MODE == 0 + // Eagerly load the data to keep latency down. + // Also forces the descriptor to be loaded early. + uint payload = uint(payload_data_u8.data[byte_offset]); +#else + uint payload = read_payload_u8(int(byte_offset)); +#endif + + uint local_control_word = bitfieldExtract(code_word, bit_offset, 2); + int decoded_abs[8] = int[8](0, 0, 0, 0, 0, 0, 0, 0); + int plane_iterations = int(q_bits + local_control_word); + + for (int q = plane_iterations - 1; q >= 0; q--) + { + for (int b = 0; b < 8; b++) + { + int decoded = int(bitfieldExtract(payload, b, 1)); + decoded_abs[b] = bitfieldInsert(decoded_abs[b], decoded, q, 1); + } + byte_offset++; +#if STORAGE_MODE == 0 + payload = uint(payload_data_u8.data[byte_offset]); +#else + payload = read_payload_u8(int(byte_offset)); +#endif + } + + mat2x4 m; + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 2; j++) + { + float v = float(decoded_abs[i * 2 + j]); + if (v != 0.0) + v += 0.5; + m[j][i] = v; + } + } + + return m; +} + +shared uint shared_sign_offset; +shared uint shared_plane_byte_offsets[16]; +shared uint shared_sign_scan[128 / 4]; + +const int MaxScaleExp = 4; + +float decode_quant(uint quant_code) +{ + // Custom FP formulation for numbers in (0, 16) range. + int e = MaxScaleExp - int(quant_code >> 3); + int m = int(quant_code) & 0x7; + float inv_quant = (1.0 / (8.0 * 1024.0 * 1024.0)) * float((8 + m) * (1 << (20 + e))); + return inv_quant; +} + +uint scan_subgroups(uint v) +{ + for (uint i = 1; i < gl_NumSubgroups; i *= 2) + { + uint up = subgroupShuffleUp(v, i); + v += gl_SubgroupInvocationID >= i ? up : 0; + } + + return v; +} + +void scan_subgroups_fallback(uint local_index) +{ + barrier(); + + // Slow LDS fallback for devices with wave size smaller than 16. + bool active_lane = local_index < gl_NumSubgroups; + + uint v = 0; + if (active_lane) + v = shared_sign_scan[local_index]; + + for (uint i = 1; i < gl_NumSubgroups; i *= 2) + { + uint up = 0; + bool do_work = local_index >= i && active_lane; + if (do_work) + up = shared_sign_scan[local_index - i]; + + // Resolve write-after-read hazard. + barrier(); + + if (do_work) + { + v += up; + shared_sign_scan[local_index] = v; + } + + barrier(); + } +} + + +void main() +{ + uint local_index = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID; + + int block_index_32x32 = int(registers.block_offset_32x32 + + gl_WorkGroupID.y * registers.block_stride_32x32 + + gl_WorkGroupID.x); + + uint block_local_index = bitfieldExtract(local_index, 0, 3); + uint block_x = bitfieldExtract(local_index, 3, 2); + uint block_y = bitfieldExtract(local_index, 5, 2); + uint linear_block = block_y * 4 + block_x; + + // Each thread individually decodes 8 values. + ivec2 local_coord = unswizzle8x8(block_local_index << 3); + + ivec2 coord = ivec2(gl_WorkGroupID.xy) * 32; + coord += 8 * ivec2(block_x, block_y); + coord += local_coord; + + uint offset_u32 = payload_offsets.data[block_index_32x32]; + + if (offset_u32 == ~0u) + { + for (int j = 0; j < 2; j++) + for (int i = 0; i < 4; i++) + imageStore(uDequantImg, ivec3(coord + ivec2(i, j), registers.output_layer), vec4(0.0)); + return; + } + +#if STORAGE_MODE == 0 + uint ballot = payload_data_u32.data[offset_u32] & 0xffff; + uint q_code = payload_data_u32.data[offset_u32 + 1] & 0xff; +#else + uint ballot = read_payload_u16(2 * int(offset_u32)); + uint q_code = read_payload_u8(4 * int(offset_u32) + 4); +#endif + + if (local_index < 16) + { + uint control_word = 0; + uint q_bits = 0; + + if (bitfieldExtract(ballot, int(local_index), 1) != 0) + { + uint local_code_offset = bitCount(bitfieldExtract(ballot, 0, int(local_index))); +#if STORAGE_MODE == 0 + control_word = uint(payload_data_u16.data[offset_u32 * 2 + 4 + local_code_offset]); + q_bits = uint(payload_data_u8.data[offset_u32 * 4 + 8 + bitCount(ballot) * 2 + local_code_offset]) & 0xfu; +#else + control_word = read_payload_u16(int(offset_u32 * 2 + 4 + local_code_offset)); + q_bits = read_payload_u8(int(offset_u32 * 4 + 8 + bitCount(ballot) * 2 + local_code_offset)) & 0xfu; +#endif + } + + uint lsbs = control_word & 0x5555u; + uint msbs = control_word & 0xaaaau; + uint msbs_shift = msbs >> 1; + msbs |= msbs_shift; + uint byte_cost = bitCount(lsbs) + bitCount(msbs) + q_bits * 8; + + uint byte_scan = offset_u32 * 4 + 8 + 3 * bitCount(ballot) + subgroupInclusiveAdd(byte_cost); + if (local_index == 15) + shared_sign_offset = 8 * byte_scan; + shared_plane_byte_offsets[local_index] = byte_scan - byte_cost; + } + + barrier(); + + mat2x4 v; + int significant_count; + + if (bitfieldExtract(ballot, int(linear_block), 1) != 0) + { + uint local_code_offset = bitCount(bitfieldExtract(ballot, 0, int(linear_block))); + +#if STORAGE_MODE == 0 + uint control_word = uint(payload_data_u16.data[offset_u32 * 2 + 4 + local_code_offset]); + uint control_word2 = uint(payload_data_u8.data[offset_u32 * 4 + 8 + bitCount(ballot) * 2 + local_code_offset]); +#else + uint control_word = read_payload_u16(int(offset_u32 * 2 + 4 + local_code_offset)); + uint control_word2 = read_payload_u8(int(offset_u32 * 4 + 8 + bitCount(ballot) * 2 + local_code_offset)); +#endif + + v = decode_payload(control_word, control_word2 & 0xfu, + shared_plane_byte_offsets[linear_block], block_local_index); + + significant_count = 0; + for (int j = 0; j < 2; j++) + for (int i = 0; i < 4; i++) + significant_count += int(v[j][i] != 0.0); + + float q = decode_quant(q_code); + float inv_scale = q * decode_quant_scale(bitfieldExtract(control_word2, QUANT_SCALE_OFFSET - 16, QUANT_SCALE_BITS)); + + v *= inv_scale; + } + else + { + v = mat2x4(vec4(0.0), vec4(0.0)); + significant_count = 0; + } + + // Figure out how many significant coefficients we have. + int significant_scan = subgroupInclusiveAdd(significant_count); + if (gl_SubgroupInvocationID == gl_SubgroupSize - 1) + shared_sign_scan[gl_SubgroupID] = significant_scan; + + if (gl_NumSubgroups <= 8) + { + barrier(); + if (gl_SubgroupSize <= 32) + { + // Should be more robust since not all compilers properly understand the shuffle up pattern. + // AMD is known to understand it well. + if (local_index < gl_NumSubgroups) + shared_sign_scan[local_index] = subgroupInclusiveAdd(shared_sign_scan[local_index]); + } + else + { + if (local_index < gl_NumSubgroups) + shared_sign_scan[local_index] = scan_subgroups(shared_sign_scan[local_index]); + } + barrier(); + } + else + { + scan_subgroups_fallback(local_index); + } + + // Compute where we need to start reading sign bits from. + uint sign_offset = shared_sign_offset + significant_scan - significant_count; + if (gl_SubgroupID != 0) + sign_offset += shared_sign_scan[gl_SubgroupID - 1]; + + // Read out all sign bits we could possibly access per thread. + // On AMD at least, this 64-bit load should be vectorizable. +#if STORAGE_MODE == 0 + uint sign_word = payload_data_u32.data[sign_offset / 32 + 0]; + uint sign_word_upper = payload_data_u32.data[sign_offset / 32 + 1]; +#else + uint sign_word = read_payload_u32(int(sign_offset / 32 + 0)); + uint sign_word_upper = read_payload_u32(int(sign_offset / 32 + 1)); +#endif + + uint masked_sign_offset = sign_offset & 31u; + if (masked_sign_offset != 0) + { + sign_word >>= masked_sign_offset; + sign_word |= sign_word_upper << (32 - masked_sign_offset); + } + + int sign_counter = 0; + + // Clock out the sign bits as needed. + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 2; j++) + { + if (v[j][i] != 0.0) + { + v[j][i] *= 1.0 - 2.0 * float(bitfieldExtract(sign_word, sign_counter, 1)); + sign_counter++; + } + } + } + + // Write output. + for (int j = 0; j < 2; j++) + for (int i = 0; i < 4; i++) + imageStore(uDequantImg, ivec3(coord + ivec2(i, j), registers.output_layer), vec4(v[j][i])); +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/wavelet_quant.comp b/crates/pyrowave-sys/vendor/pyrowave/shaders/wavelet_quant.comp new file mode 100644 index 00000000..70794e75 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/wavelet_quant.comp @@ -0,0 +1,316 @@ +#version 450 +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#extension GL_KHR_shader_subgroup_basic : require +#extension GL_KHR_shader_subgroup_arithmetic : require +#extension GL_KHR_shader_subgroup_ballot : require +#extension GL_KHR_shader_subgroup_shuffle : require +#extension GL_KHR_shader_subgroup_vote : require +#extension GL_KHR_shader_subgroup_shuffle_relative : require +#extension GL_KHR_shader_subgroup_clustered : require +#extension GL_EXT_shader_8bit_storage : require +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require + +#include "dwt_quant_scale.h" +#include "constants.h" + +layout(local_size_x = 128) in; +layout(constant_id = 1) const bool SkipQuantScale = false; + +layout(set = 0, binding = 0) uniform sampler2DArray uTexture; + +struct QuantStats +{ + float16_t square_error; + uint16_t payload_cost; +}; + +struct BlockMeta +{ + uint code_word; + uint offset; +}; + +// Fit into 64 bytes. +struct BlockStats +{ + uint num_planes; + QuantStats errors[15]; +}; + +layout(set = 0, binding = 1) writeonly buffer SSBOMeta +{ + BlockMeta meta[]; +} block_meta; + +layout(set = 0, binding = 2) writeonly buffer SSBOBlockStats +{ + BlockStats stats[]; +} block_stats; + +layout(set = 0, binding = 3) buffer Payloads +{ + layout(offset = 0) uint counter; + layout(offset = 8) uint8_t data[]; +} payload_data; + +#include "dwt_swizzle.h" + +layout(push_constant) uniform Registers +{ + ivec2 resolution; + ivec2 resolution_8x8_blocks; + vec2 inv_resolution; + float input_layer; + float quant_resolution; + int block_offset; + int block_stride; + float rdo_distortion_scale; +} registers; + +float max4(vec4 v) +{ + vec2 v2 = max(v.xy, v.zw); + return max(v2.x, v2.y); +} + +int max4(ivec4 v) +{ + ivec2 v2 = max(v.xy, v.zw); + return max(v2.x, v2.y); +} + +int scan_clustered8(int v) +{ + for (uint i = 1; i < 8; i *= 2) + { + int up = subgroupShuffleUp(v, i); + v += (gl_SubgroupInvocationID & 7u) >= i ? up : 0; + } + + return v; +} + +void compute_quant_scale(float max_wave_texels, out uint quant_code, out float quant_scale) +{ + if (SkipQuantScale || max_wave_texels < 1.0) + { + quant_code = ENCODE_QUANT_IDENTITY; + quant_scale = 1.0; + } + else + { + int e; + frexp(max_wave_texels - 0.25, e); + float target_max = float(1 << e) - 0.25; + float inv_scale = max_wave_texels / target_max; + quant_code = encode_quant_scale(inv_scale); + quant_scale = 1.0 / decode_quant_scale(quant_code); + } +} + +float compute_square_error(mat2x4 v, int q, out uint num_significant_values) +{ + v = mat2x4(abs(v[0]), abs(v[1])); + mat2x4 iv = mat2x4(floor(ldexp(v[0], ivec4(-q))), trunc(ldexp(v[1], ivec4(-q)))); + num_significant_values = 0; + for (int j = 0; j < 2; j++) + for (int i = 0; i < 4; i++) + if (iv[j][i] != 0.0) + num_significant_values++; + iv[0] += mix(vec4(0.0), vec4(0.5), notEqual(iv[0], vec4(0.0))); + iv[1] += mix(vec4(0.0), vec4(0.5), notEqual(iv[1], vec4(0.0))); + iv = mat2x4(trunc(ldexp(iv[0], ivec4(q))), trunc(ldexp(iv[1], ivec4(q)))); + mat2x4 err = v - iv; + num_significant_values = subgroupClusteredAdd(num_significant_values, 8); + return (dot(err[0], err[0]) + dot(err[1], err[1])) * registers.rdo_distortion_scale; +} + +struct QuantResult +{ + float square_error; + int encode_cost_early; + int block4x2_shifted; + int encode_cost_late_bits; + int quality_planes; +}; + +QuantResult compute_quant_stats(mat2x4 v, int q, int msb, int block4x2_max, float inv_quant_squared) +{ + block4x2_max >>= q; + + uint wave8_num_significants; + QuantResult result; + + result.square_error = compute_square_error(v, q, wave8_num_significants) * inv_quant_squared; + result.block4x2_shifted = block4x2_max; + + result.encode_cost_early = block4x2_max > 0 ? 1 : 0; + msb -= q; + + result.quality_planes = 0; + + if (msb >= 3) + { + result.quality_planes = msb - 2; + // Must encode the sign plane if we have quality planes. + result.encode_cost_early = result.quality_planes + 1; + result.block4x2_shifted >>= result.quality_planes; + } + + result.encode_cost_early += findMSB(result.block4x2_shifted) + 1; + result.encode_cost_late_bits = 8 * subgroupClusteredAdd(max(result.encode_cost_early - 1, 0), 8) + int(wave8_num_significants); + return result; +} + +float square(float v) +{ + return v * v; +} + +void encode_payload(ivec2 block_index_8x8, mat2x4 texels) +{ + precise float max_subblock_texel = max(max4(abs(texels[0])), max4(abs(texels[1]))); + precise float max_wave_texels = subgroupClusteredMax(max_subblock_texel, 8); + float quant_scale; + uint quant_code; + compute_quant_scale(max_wave_texels, quant_code, quant_scale); + texels *= quant_scale; + max_wave_texels *= quant_scale; + max_subblock_texel *= quant_scale; + + float overall_quant_scale = registers.quant_resolution * quant_scale; + float inv_quant = 1.0 / overall_quant_scale; + float inv_quant_squared = inv_quant * inv_quant; + ivec4 abs_quant_texels0 = abs(ivec4(texels[0])); + ivec4 abs_quant_texels1 = abs(ivec4(texels[1])); + int max_absolute_value = int(max_wave_texels); + int block4x2_max = int(max_subblock_texel); + + uint block_index = registers.block_offset + block_index_8x8.y * registers.block_stride + block_index_8x8.x; + + // The entire block quantizes to zero. + if (max_absolute_value == 0) + { + if ((gl_SubgroupInvocationID & 7) == 0) + { + block_meta.meta[block_index] = BlockMeta(0, 0); + block_stats.stats[block_index].num_planes = 0; + block_stats.stats[block_index].errors[0] = QuantStats(float16_t(0.0), uint16_t(0)); + } + return; + } + + int msb = findMSB(max_absolute_value); + + QuantResult result = compute_quant_stats(texels, 0, msb, block4x2_max, inv_quant_squared); + int scan = scan_clustered8(result.encode_cost_early); + + uint global_offset = 0; + + // For feedback, and allocation of payload. + if ((gl_SubgroupInvocationID & 7u) == 7u) + global_offset = atomicAdd(payload_data.counter, scan); + global_offset = subgroupShuffle(global_offset, gl_SubgroupInvocationID | 7u); + + scan -= result.encode_cost_early; + + // First, encode the code word. + int quality_planes = result.quality_planes; + uint code_word = quality_planes << Q_PLANES_OFFSET; + code_word = bitfieldInsert(code_word, quant_code, QUANT_SCALE_OFFSET, QUANT_SCALE_BITS); + uint plane_code = findMSB(result.block4x2_shifted) + 1; + + uint merged_plane_code = plane_code << ((gl_SubgroupInvocationID & 7u) * 2u); + merged_plane_code |= subgroupShuffleXor(merged_plane_code, 1u); + merged_plane_code |= subgroupShuffleXor(merged_plane_code, 2u); + merged_plane_code |= subgroupShuffleXor(merged_plane_code, 4u); + code_word |= merged_plane_code; + + if ((gl_SubgroupInvocationID & 7u) == 0u) + { + block_meta.meta[block_index] = BlockMeta(code_word, global_offset); + block_stats.stats[block_index].num_planes = msb + 1; + block_stats.stats[block_index].errors[0] = QuantStats( + float16_t(0.0), // We don't care about distortion from 0 quant since we've already made that decision. + uint16_t(result.encode_cost_late_bits)); + } + + for (int q = 1; q <= msb; q++) + { + QuantResult quant_result = compute_quant_stats(texels, q, msb, block4x2_max, inv_quant_squared); + float square_error = subgroupClusteredAdd(quant_result.square_error, 8); + + if ((gl_SubgroupInvocationID & 7u) == 0) + { + block_stats.stats[block_index].errors[q] = QuantStats( + float16_t(min(square_error, 60000.0)), + uint16_t(quant_result.encode_cost_late_bits)); + } + } + + // Record distortion for throwing away everything. + float square_error = subgroupClusteredAdd((dot(texels[0], texels[0]) + dot(texels[1], texels[1])) * inv_quant_squared, 8); + if ((gl_SubgroupInvocationID & 7u) == 0) + block_stats.stats[block_index].errors[msb + 1] = QuantStats(float16_t(min(60000.0, square_error)), uint16_t(0)); + + uint byte_offset = scan + global_offset; + bool need_sign = result.block4x2_shifted != 0 || quality_planes != 0; + + // Don't pack the sign plane until final pass, since we don't know how we quantize yet. + if (need_sign) + { + uvec4 s0 = uvec4(lessThan(texels[0], vec4(0.0))) << uvec4(0, 1, 2, 3); + uvec4 s1 = uvec4(lessThan(texels[1], vec4(0.0))) << uvec4(4, 5, 6, 7); + uint s = s0.x | s0.y | s0.z | s0.w | s1.x | s1.y | s1.z | s1.w; + payload_data.data[byte_offset++] = uint8_t(s); + + int plane_iterations = quality_planes + int(plane_code); + int q = plane_iterations - 1; + do + { + s0 = uvec4( + bitfieldExtract(uint(abs_quant_texels0.x), q, 1), + bitfieldExtract(uint(abs_quant_texels0.y), q, 1), + bitfieldExtract(uint(abs_quant_texels0.z), q, 1), + bitfieldExtract(uint(abs_quant_texels0.w), q, 1)); + s1 = uvec4( + bitfieldExtract(uint(abs_quant_texels1.x), q, 1), + bitfieldExtract(uint(abs_quant_texels1.y), q, 1), + bitfieldExtract(uint(abs_quant_texels1.z), q, 1), + bitfieldExtract(uint(abs_quant_texels1.w), q, 1)); + s0 <<= uvec4(0, 1, 2, 3); + s1 <<= uvec4(4, 5, 6, 7); + s = s0.x | s0.y | s0.z | s0.w | s1.x | s1.y | s1.z | s1.w; + payload_data.data[byte_offset++] = uint8_t(s); + q--; + } while (q >= 0); + } +} + +void main() +{ + uint local_index = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID; + uint block_local_index = bitfieldExtract(local_index, 0, 3); + uint block_x = bitfieldExtract(local_index, 3, 2); + uint block_y = bitfieldExtract(local_index, 5, 2); + + // Each thread individually encodes 8 values. + ivec2 local_coord = unswizzle8x8(block_local_index << 3); + + ivec2 coord = ivec2(gl_WorkGroupID.xy) * 32; + coord += 8 * ivec2(block_x, block_y); + coord += local_coord; + + ivec2 block_index = 4 * ivec2(gl_WorkGroupID.xy) + ivec2(block_x, block_y); + + vec3 uv = vec3(vec2(coord) * registers.inv_resolution, registers.input_layer); + vec4 texels0 = textureGatherOffset(uTexture, uv, ivec2(1, 1)).wxzy; + vec4 texels1 = textureGatherOffset(uTexture, uv, ivec2(3, 1)).wxzy; + precise vec4 scaled_texels0 = texels0 * registers.quant_resolution; + precise vec4 scaled_texels1 = texels1 * registers.quant_resolution; + bool in_bounds = all(lessThan(block_index, registers.resolution_8x8_blocks)); + if (in_bounds) + encode_payload(block_index, mat2x4(scaled_texels0, scaled_texels1)); +} \ No newline at end of file diff --git a/crates/pyrowave-sys/vendor/pyrowave/shaders/yuv2rgb.frag b/crates/pyrowave-sys/vendor/pyrowave/shaders/yuv2rgb.frag new file mode 100644 index 00000000..363d8f18 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/shaders/yuv2rgb.frag @@ -0,0 +1,60 @@ +#version 450 + +#if DELTA +layout(set = 0, binding = 0) uniform texture2D Y0; +layout(set = 0, binding = 1) uniform texture2D Y1; +#else +layout(set = 0, binding = 0) uniform texture2D Y; +layout(set = 0, binding = 1) uniform texture2D Cb; +layout(set = 0, binding = 2) uniform texture2D Cr; +#endif +layout(set = 0, binding = 3) uniform sampler Samp; + +layout(location = 0) out vec3 FragColor; +layout(location = 0) in vec2 vUV; + +layout(constant_id = 0) const bool BT2020 = false; +layout(constant_id = 1) const bool FullRange = false; + +const mat3 yuv2rgb_bt709 = mat3( + vec3(1.0, 1.0, 1.0), + vec3(0.0, -0.13397432 / 0.7152, 1.8556), + vec3(1.5748, -0.33480248 / 0.7152, 0.0)); + +const mat3 yuv2rgb_bt2020 = mat3( + vec3(1.0, 1.0, 1.0), + vec3(0.0, -0.202008 / 0.587, 1.772), + vec3(1.402, -0.419198 / 0.587, 0.0)); + +void main() +{ +#if DELTA + float y0 = textureLod(sampler2D(Y0, Samp), vUV, 0.0).x; + float y1 = textureLod(sampler2D(Y1, Samp), vUV, 0.0).x; + FragColor = vec3(abs(y0 - y1) * 10.0); +#else + float y = textureLod(sampler2D(Y, Samp), vUV, 0.0).x; + float cb = textureLod(sampler2D(Cb, Samp), vUV, 0.0).x; + float cr = textureLod(sampler2D(Cr, Samp), vUV, 0.0).x; + + cb -= 0.5; + cr -= 0.5; + + if (!FullRange) + { + y -= 16.0 / 255.0; + y *= 255.0 / 219.0; + const float ChromaScale = 255.0 / 224.0; + cb *= ChromaScale; + cr *= ChromaScale; + y = clamp(y, 0.0, 1.0); + cb = clamp(cb, -0.5, 0.5); + cr = clamp(cr, -0.5, 0.5); + } + + if (BT2020) + FragColor = yuv2rgb_bt2020 * vec3(y, cb, cr); + else + FragColor = yuv2rgb_bt709 * vec3(y, cb, cr); +#endif +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/slangmosh.sh b/crates/pyrowave-sys/vendor/pyrowave/slangmosh.sh new file mode 100644 index 00000000..6d2f0c7f --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/slangmosh.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +slangmosh --output shaders/slangmosh.hpp shaders/slangmosh.json --namespace PyroWave -O --strip diff --git a/crates/pyrowave-sys/vendor/pyrowave/viewer.cpp b/crates/pyrowave-sys/vendor/pyrowave/viewer.cpp new file mode 100644 index 00000000..5316c7fb --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/viewer.cpp @@ -0,0 +1,567 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT + +#include "application.hpp" +#include "command_buffer.hpp" +#include "device.hpp" +#include "os_filesystem.hpp" +#include "muglm/muglm_impl.hpp" +#include "pyrowave_encoder.hpp" +#include "pyrowave_decoder.hpp" +#include "yuv4mpeg.hpp" +#include "pyrowave_common.hpp" +#include "flat_renderer.hpp" +#include "ui_manager.hpp" +#include +#include + +using namespace Granite; +using namespace Vulkan; + +struct YCbCrImages +{ + Vulkan::ImageHandle images[3]; + PyroWave::ViewBuffers views; +}; + +static bool device_should_use_fragment_path(Device &device) +{ + return PyroWave::Decoder::device_prefers_fragment_path(device); +} + +static YCbCrImages create_ycbcr_images(Device &device, int width, int height, VkFormat fmt, PyroWave::ChromaSubsampling chroma) +{ + YCbCrImages images; + auto info = ImageCreateInfo::immutable_2d_image(width, height, fmt); + info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; + info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + if (device_should_use_fragment_path(device)) + info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + else + info.usage |= VK_IMAGE_USAGE_STORAGE_BIT; + + images.images[0] = device.create_image(info); + device.set_name(*images.images[0], "Y"); + + if (chroma == PyroWave::ChromaSubsampling::Chroma420) + { + info.width >>= 1; + info.height >>= 1; + } + + images.images[1] = device.create_image(info); + device.set_name(*images.images[1], "Cb"); + + images.images[2] = device.create_image(info); + device.set_name(*images.images[2], "Cr"); + + for (int i = 0; i < 3; i++) + images.views.planes[i] = &images.images[i]->get_view(); + + return images; +} + +struct ViewerApplication : Granite::Application, Granite::EventHandler +{ + explicit ViewerApplication(const char *path_) + : path(path_) + { + if (!file.open_read(path)) + { + rawfile.reset(fopen(path, "rb")); + if (!rawfile) + throw std::runtime_error("Failed to open."); + char magic[9] = {}; + if (fread(magic, 1, 8, rawfile.get()) != 8 || strcmp(magic, "PYROWAVE") != 0) + throw std::runtime_error("Failed to open."); + if (fread(&rawparam, sizeof(rawparam), 1, rawfile.get()) != 1) + throw std::runtime_error("Failed to open."); + } + + get_wsi().set_backbuffer_format(BackbufferFormat::UNORM); + EVENT_MANAGER_REGISTER_LATCH(ViewerApplication, on_device_created, on_device_destroyed, DeviceCreatedEvent); + EVENT_MANAGER_REGISTER(ViewerApplication, on_key_press, KeyboardEvent); + EVENT_MANAGER_REGISTER(ViewerApplication, on_mouse, MouseMoveEvent); + EVENT_MANAGER_REGISTER(ViewerApplication, on_mouse_event, MouseButtonEvent); + + x_slide = file.get_width() / 2; + } + + bool is_mouse_active = false; + bool paused = false; + + enum class Mode + { + Slide, + Flicker, + Delta + }; + Mode mode = Mode::Slide; + + bool on_mouse(const MouseMoveEvent &e) + { + if (is_mouse_active) + x_slide = int(e.get_abs_x()); + return true; + } + + bool on_mouse_event(const MouseButtonEvent &e) + { + is_mouse_active = e.get_pressed(); + return true; + } + + bool on_key_press(const KeyboardEvent &e) + { + if (e.get_key_state() != KeyState::Released) + { + if (e.get_key() == Key::Up) + bit_rate_mbit += 10; + else if (e.get_key() == Key::Down && bit_rate_mbit > 20) + bit_rate_mbit -= 10; + else if (e.get_key() == Key::F) + mode = Mode::Flicker; + else if (e.get_key() == Key::D) + mode = Mode::Delta; + else if (e.get_key() == Key::S) + mode = Mode::Slide; + else if (e.get_key() == Key::P) + { + get_wsi().set_backbuffer_format( + get_wsi().get_backbuffer_format() == BackbufferFormat::HDR10 ? + BackbufferFormat::UNORM : BackbufferFormat::HDR10); + } + } + + if (e.get_key_state() == KeyState::Pressed && e.get_key() == Key::Space) + paused = !paused; + + return true; + } + + void on_device_created(const DeviceCreatedEvent &e) + { + if (rawfile) + { + auto format = YUV4MPEGFile::format_to_bytes_per_component(rawparam.format) == 2 ? + VK_FORMAT_R16_UNORM : VK_FORMAT_R8_UNORM; + auto chroma = YUV4MPEGFile::format_has_subsampling(rawparam.format) ? + PyroWave::ChromaSubsampling::Chroma420 : + PyroWave::ChromaSubsampling::Chroma444; + + out_images = create_ycbcr_images(e.get_device(), rawparam.width, rawparam.height, format, chroma); + dec.init(&e.get_device(), rawparam.width, rawparam.height, chroma, device_should_use_fragment_path(e.get_device())); + } + else + { + auto format = YUV4MPEGFile::format_to_bytes_per_component(file.get_format()) == 2 ? VK_FORMAT_R16_UNORM + : VK_FORMAT_R8_UNORM; + auto chroma = YUV4MPEGFile::format_has_subsampling(file.get_format()) + ? PyroWave::ChromaSubsampling::Chroma420 : PyroWave::ChromaSubsampling::Chroma444; + in_images = create_ycbcr_images(e.get_device(), file.get_width(), file.get_height(), format, chroma); + out_images = create_ycbcr_images(e.get_device(), file.get_width(), file.get_height(), format, chroma); + enc.init(&e.get_device(), file.get_width(), file.get_height(), chroma); + dec.init(&e.get_device(), file.get_width(), file.get_height(), chroma, device_should_use_fragment_path(e.get_device())); + } + } + + void on_device_destroyed(const DeviceCreatedEvent &) + { + in_images = {}; + out_images = {}; + } + + std::vector packetized_data; + + bool read_raw_payload() + { + uint32_t u32_size; + + for (;;) + { + if (fread(&u32_size, sizeof(u32_size), 1, rawfile.get()) != 1) + return false; + packetized_data.resize(u32_size); + if (fread(packetized_data.data(), 1, u32_size, rawfile.get()) != u32_size) + return false; + + if (!dec.push_packet(packetized_data.data(), packetized_data.size())) + return false; + + if (dec.decode_is_ready(false)) + return true; + } + } + + void render_frame(double, double elapsed_time) override + { + auto &device = get_wsi().get_device(); + auto cmd = device.request_command_buffer(); + + if (!paused) + { + if (rawfile) + { + if (!read_raw_payload()) + { + fseek(rawfile.get(), strlen("PYROWAVE") + sizeof(rawparam), SEEK_SET); + dec.clear(); + if (!read_raw_payload()) + { + request_shutdown(); + return; + } + } + } + else if (!file.begin_frame()) + { + file = {}; + if (!file.open_read(path) || !file.begin_frame()) + { + request_shutdown(); + return; + } + } + + if (!rawfile) + { + for (int i = 0; i < 3; i++) + { + cmd->image_barrier(*in_images.images[i], VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 0, 0, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT); + } + + for (int i = 0; i < 3; i++) + { + auto *y = cmd->update_image(*in_images.images[i]); + if (!file.read(y, in_images.images[i]->get_width() * in_images.images[i]->get_height() * + YUV4MPEGFile::format_to_bytes_per_component(file.get_format()))) + { + LOGE("Failed to read plane.\n"); + device.submit_discard(cmd); + request_shutdown(); + return; + } + } + + for (int i = 0; i < 3; i++) + { + if (device_should_use_fragment_path(device)) + { + cmd->image_barrier(*in_images.images[i], + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + else + { + cmd->image_barrier(*in_images.images[i], + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + } + } + } + + unsigned bitstream_size = bit_rate_mbit * 1000000ull / (60 * 8); + + if (!rawfile) + { + bitstream_size &= ~3u; + + BufferCreateInfo buffer_info = {}; + buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + buffer_info.size = enc.get_meta_required_size(); + buffer_info.domain = BufferDomain::Device; + auto meta = device.create_buffer(buffer_info); + buffer_info.domain = BufferDomain::CachedHost; + auto meta_host = device.create_buffer(buffer_info); + + buffer_info.size = bitstream_size + 2 * enc.get_meta_required_size(); + buffer_info.domain = BufferDomain::Device; + auto bitstream = device.create_buffer(buffer_info); + buffer_info.domain = BufferDomain::CachedHost; + auto bitstream_host = device.create_buffer(buffer_info); + + PyroWave::Encoder::BitstreamBuffers buffers = {}; + buffers.meta.buffer = meta.get(); + buffers.meta.size = meta->get_create_info().size; + buffers.bitstream.buffer = bitstream.get(); + buffers.bitstream.size = bitstream->get_create_info().size; + buffers.target_size = bitstream_size; + + enc.encode(*cmd, in_images.views, buffers); + cmd->copy_buffer(*bitstream_host, *bitstream); + cmd->copy_buffer(*meta_host, *meta); + cmd->barrier(VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_HOST_BIT, VK_ACCESS_HOST_READ_BIT); + + Fence fence; + device.submit(cmd, &fence); + fence->wait(); + + auto *mapped_meta = static_cast( + device.map_host_buffer(*meta_host, MEMORY_ACCESS_READ_BIT)); + auto *mapped_bits = static_cast( + device.map_host_buffer(*bitstream_host, MEMORY_ACCESS_READ_BIT)); + + std::vector reordered_packet_buffer(bitstream_size * 2); + size_t num_packets = enc.compute_num_packets(mapped_meta, 8 * 1024); + std::vector packets(num_packets); + size_t out_packets = enc.packetize(packets.data(), 8 * 1024, + reordered_packet_buffer.data(), + reordered_packet_buffer.size(), + mapped_meta, mapped_bits); + (void) out_packets; + + size_t encoded_size = 0; + for (auto &p: packets) + encoded_size += p.size; + + LOGI("Total encoded size: %zu\n", encoded_size); + + if (encoded_size > bitstream_size) + { + LOGE("Broken rate control\n"); + return; + } + + assert(out_packets == num_packets); + + for (auto &p: packets) + if (!dec.push_packet(reordered_packet_buffer.data() + p.offset, p.size)) + return; + + cmd = device.request_command_buffer(); + } + + for (int i = 0; i < 3; i++) + { + if (device_should_use_fragment_path(device)) + { + cmd->image_barrier(*out_images.images[i], + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT); + } + else + { + cmd->image_barrier(*out_images.images[i], + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT); + } + } + + dec.decode(*cmd, out_images.views); + + for (int i = 0; i < 3; i++) + { + if (device_should_use_fragment_path(device)) + { + cmd->image_barrier(*out_images.images[i], + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + else + { + cmd->image_barrier(*out_images.images[i], + VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_SAMPLED_READ_BIT); + } + } + + cmd->begin_render_pass(device.get_swapchain_render_pass(SwapchainRenderPass::ColorOnly)); + cmd->set_sampler(0, 3, StockSampler::LinearClamp); + + auto fmt = rawfile ? rawparam.format : file.get_format(); + + cmd->set_specialization_constant_mask(3); + cmd->set_specialization_constant(0, fmt == YUV4MPEGFile::Format::YUV420P16 || fmt == YUV4MPEGFile::Format::YUV444P16); + cmd->set_specialization_constant(1, rawfile ? bool(rawparam.is_full_range) : file.is_full_range()); + + CommandBufferUtil::setup_fullscreen_quad(*cmd, "builtin://shaders/quad.vert", "assets://yuv2rgb.frag", + {{ "DELTA", mode == Mode::Delta ? 1 : 0 }}); + + x_slide = clamp(x_slide, 50, int(cmd->get_viewport().width) - 50); + + const float full_color = get_wsi().get_backbuffer_format() == BackbufferFormat::HDR10 ? 0.75f : 1.0f; + + if (mode == Mode::Flicker && !rawfile) + { + if (muglm::fract(elapsed_time * 10.0) < 0.5) + { + cmd->set_texture(0, 0, *in_images.views.planes[0]); + cmd->set_texture(0, 1, *in_images.views.planes[1]); + cmd->set_texture(0, 2, *in_images.views.planes[2]); + } + else + { + cmd->set_texture(0, 0, *out_images.views.planes[0]); + cmd->set_texture(0, 1, *out_images.views.planes[1]); + cmd->set_texture(0, 2, *out_images.views.planes[2]); + } + + cmd->draw(3); + flat_renderer.begin(); + char text[64]; + snprintf(text, sizeof(text), "FLICKER %u mbits | %.3f bpp @ 60 fps%s", + bit_rate_mbit, + double(bitstream_size * 8) / double(file.get_width() * file.get_height()), + paused ? " (paused)" : ""); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Large), + text, vec3(20, 20, 0), vec2(400, 200), vec4(full_color, full_color, 0.0f, 1.0f), + Font::Alignment::TopLeft); + flat_renderer.flush(*cmd, vec3(0), vec3(cmd->get_viewport().width, cmd->get_viewport().height, 1)); + } + else if (mode == Mode::Slide || rawfile) + { + if (!rawfile) + { + cmd->set_texture(0, 0, *in_images.views.planes[0]); + cmd->set_texture(0, 1, *in_images.views.planes[1]); + cmd->set_texture(0, 2, *in_images.views.planes[2]); + cmd->set_scissor({{ 0, 0 }, + { uint32_t(x_slide), uint32_t(cmd->get_viewport().height) }}); + cmd->draw(3); + } + + cmd->set_texture(0, 0, *out_images.views.planes[0]); + cmd->set_texture(0, 1, *out_images.views.planes[1]); + cmd->set_texture(0, 2, *out_images.views.planes[2]); + if (!rawfile) + { + cmd->set_scissor({{ int32_t(x_slide), 0 }, + { uint32_t(cmd->get_viewport().width), uint32_t(cmd->get_viewport().height) }}); + } + cmd->draw(3); + + cmd->set_scissor({{ 0, 0 }, + { uint32_t(cmd->get_viewport().width), uint32_t(cmd->get_viewport().height) }}); + + if (!rawfile) + { + flat_renderer.begin(); + char text[64]; + snprintf(text, sizeof(text), "%u mbits | %.3f bpp @ 60 fps%s", bit_rate_mbit, + double(bitstream_size * 8) / double(file.get_width() * file.get_height()), + paused ? " (paused)" : ""); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Large), + text, vec3(20, 20, 0), vec2(400, 200), + vec4(full_color, full_color, 0.0f, 1.0f), + Font::Alignment::TopLeft); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Large), + text, vec3(18, 22, 0.5f), vec2(400, 200), vec4(0.0f, 0.0f, 0.0f, 1.0f), + Font::Alignment::TopLeft); + flat_renderer.render_quad(vec3(float(x_slide), 0.0f, 0.8f), + vec2(2.0f, cmd->get_viewport().height), + vec4(full_color, full_color, 0.0f, 1.0f)); + flat_renderer.flush(*cmd, vec3(0), vec3(cmd->get_viewport().width, cmd->get_viewport().height, 1)); + } + } + else + { + cmd->set_texture(0, 0, *in_images.views.planes[0]); + cmd->set_texture(0, 1, *out_images.views.planes[0]); + cmd->draw(3); + + flat_renderer.begin(); + char text[64]; + snprintf(text, sizeof(text), "DELTA %u mbits | %.3f bpp @ 60 fps%s", + bit_rate_mbit, + double(bitstream_size * 8) / double(file.get_width() * file.get_height()), + paused ? " (paused)" : ""); + flat_renderer.render_text(GRANITE_UI_MANAGER()->get_font(UI::FontSize::Large), + text, vec3(20, 20, 0), vec2(400, 200), + vec4(full_color, full_color, 0.0f, 1.0f), + Font::Alignment::TopLeft); + flat_renderer.flush(*cmd, vec3(0), vec3(cmd->get_viewport().width, cmd->get_viewport().height, 1)); + } + + cmd->end_render_pass(); + + device.submit(cmd); + } + + unsigned get_default_width() override + { + return rawfile ? rawparam.width : file.get_width(); + } + + unsigned get_default_height() override + { + return rawfile ? rawparam.height : file.get_height(); + } + + PyroWave::Encoder enc; + PyroWave::Decoder dec; + YCbCrImages in_images; + YCbCrImages out_images; + YUV4MPEGFile file; + const char *path; + unsigned bit_rate_mbit = 200; + FlatRenderer flat_renderer; + + struct RawParameters + { + int32_t width; + int32_t height; + YUV4MPEGFile::Format format; + PyroWave::ChromaSubsampling chroma; + uint32_t is_full_range; + int32_t frame_rate_num; + int32_t frame_rate_den; + uint32_t chroma_siting; + }; + static_assert(sizeof(RawParameters) == 32, "RawParameters size mismatch."); + struct FILEDeleter { void operator()(FILE *f) { if (f) fclose(f); } }; + + std::unique_ptr rawfile; + RawParameters rawparam = {}; + + int x_slide = 100; +}; + +namespace Granite +{ +Application *application_create(int argc, char **argv) +{ + GRANITE_APPLICATION_SETUP_FILESYSTEM(); + +#ifndef __ANDROID__ + if (argc != 2) + { + LOGE("Usage: pyrowave-viewer test.y4m\n"); + return nullptr; + } +#endif + + const char *path = nullptr; + if (argc >= 2) + path = argv[1]; + +#ifdef __ANDROID__ + if (!path) + path = "/data/local/tmp/test.wave"; +#endif + + try + { + auto *app = new ViewerApplication(path); + return app; + } + catch (const std::exception &e) + { + LOGE("application_create() threw exception: %s\n", e.what()); + return nullptr; + } +} +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/yuv4mpeg.cpp b/crates/pyrowave-sys/vendor/pyrowave/yuv4mpeg.cpp new file mode 100644 index 00000000..a54974fa --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/yuv4mpeg.cpp @@ -0,0 +1,265 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#include "yuv4mpeg.hpp" +#include +#include + +bool YUV4MPEGFile::open_read(const std::string &path) +{ + return open(path, Mode::Read); +} + +bool YUV4MPEGFile::open_write(const std::string &path, const std::string ¶ms_) +{ + params = params_; + return open(path, Mode::Write); +} + +int YUV4MPEGFile::format_to_bytes_per_component(Format format) +{ + switch (format) + { + case Format::YUV420P16: + case Format::YUV444P16: + return 2; + + default: + return 1; + } +} + +bool YUV4MPEGFile::format_has_subsampling(Format format) +{ + switch (format) + { + case Format::YUV420P: + case Format::YUV420P16: + return true; + + default: + return false; + } +} + +bool YUV4MPEGFile::open(const std::string &path, Mode mode_) +{ + mode = mode_; + file.reset(fopen(path.c_str(), mode == Mode::Read ? "rb" : "wb")); + if (!file) + { + fprintf(stderr, "Failed to open %s\n", path.c_str()); + return false; + } + + if (mode == Mode::Read) + { + char magic[11] = {}; + if (fread(magic, 1, sizeof(magic) - 1, file.get()) != sizeof(magic) - 1) + { + fprintf(stderr, "Failed to read magic.\n"); + return false; + } + + if (strcmp(magic, "YUV4MPEG2 ") != 0) + { + fprintf(stderr, "Invalid magic\n"); + return false; + } + + char c; + while (fread(&c, 1, 1, file.get()) == 1 && c != '\n') + params += c; + params += '\n'; + } + else + { + if (!write("YUV4MPEG2 ", 10)) + return false; + + if (!write(params.data(), params.size())) + return false; + } + + auto w_pos = params.find_first_of('W'); + if (w_pos == std::string::npos) + return false; + width = strtol(params.c_str() + w_pos + 1, nullptr, 0); + + auto h_pos = params.find_first_of('H'); + if (h_pos == std::string::npos) + return false; + height = strtol(params.c_str() + h_pos + 1, nullptr, 0); + + auto f_pos = params.find_first_of('F'); + if (f_pos != std::string::npos) + { + char *end_ptr; + frame_rate_num = strtol(params.c_str() + f_pos + 1, &end_ptr, 0); + if (*end_ptr == ':') + frame_rate_den = strtol(end_ptr + 1, nullptr, 0); + } + + if (params.find("C420p10") != std::string::npos) + { + // Crude up-convert. + format = Format::YUV420P16; + unorm_scale = float(1 << 10) - 1.0f; + } + else if (params.find("C420p12") != std::string::npos) + { + format = Format::YUV420P16; + unorm_scale = float(1 << 12) - 1.0f; + } + else if (params.find("C420p14") != std::string::npos) + { + format = Format::YUV420P16; + unorm_scale = float(1 << 14) - 1.0f; + } + else if (params.find("C420p16") != std::string::npos) + { + format = Format::YUV420P16; + unorm_scale = float(0xffff); + } + else if (params.find("C444p10") != std::string::npos) + { + format = Format::YUV444P16; + unorm_scale = float(1 << 10) - 1.0f; + } + else if (params.find("C444p12") != std::string::npos) + { + format = Format::YUV444P16; + unorm_scale = float(1 << 12) - 1.0f; + } + else if (params.find("C444p14") != std::string::npos) + { + format = Format::YUV444P16; + unorm_scale = float(1 << 14) - 1.0f; + } + else if (params.find("C444p16") != std::string::npos) + { + format = Format::YUV444P16; + unorm_scale = float(0xffff); + } + else if (params.find("C444") != std::string::npos) + { + format = Format::YUV444P; + } + else + { + // Fallback. + format = Format::YUV420P; + } + + if (params.find("XCOLORRANGE=LIMITED") != std::string::npos) + full_range = false; + else if (params.find("XCOLORRANGE=FULL") != std::string::npos) + full_range = true; + + return width > 0 && height > 0; +} + +bool YUV4MPEGFile::begin_frame() +{ + if (mode == Mode::Write) + { + return fwrite("FRAME\n", 1, 6, file.get()) == 6; + } + else + { + std::string line; + char c; + + while (fread(&c, 1, 1, file.get()) == 1 && c != '\n') + line += c; + + return line == "FRAME"; + } +} + +bool YUV4MPEGFile::read(void *pixels, size_t size) +{ + if (format == Format::YUV420P16) + { + // Recale to P016. + auto *out = static_cast(pixels); + uint16_t buffer[1024]; + size /= 2; + + while (size) + { + auto to_read = std::min(size, 1024); + if (fread(buffer, 2, to_read, file.get()) != to_read) + return false; + for (size_t i = 0; i < to_read; i++) + out[i] = uint16_t(std::min(1.0f, float(buffer[i]) / unorm_scale) * float(0xffff) + 0.5f); + + size -= to_read; + out += to_read; + } + + return true; + } + else + return fread(pixels, 1, size, file.get()) == size; +} + +bool YUV4MPEGFile::write(const void *pixels, size_t size) +{ + if (format == Format::YUV420P16) + { + auto *inputs = static_cast(pixels); + uint16_t buffer[1024]; + size /= 2; + + while (size) + { + auto to_write = std::min(size, 1024); + for (size_t i = 0; i < to_write; i++) + buffer[i] = uint16_t(unorm_scale * float(inputs[i]) / float(0xffff) + 0.5f); + if (fwrite(buffer, 2, to_write, file.get()) != to_write) + return false; + + size -= to_write; + inputs += to_write; + } + + return true; + } + else + return fwrite(pixels, 1, size, file.get()) == size; +} + +int YUV4MPEGFile::get_width() const +{ + return width; +} + +int YUV4MPEGFile::get_height() const +{ + return height; +} + +int YUV4MPEGFile::get_frame_rate_num() const +{ + return frame_rate_num; +} + +int YUV4MPEGFile::get_frame_rate_den() const +{ + return frame_rate_den; +} + +const std::string &YUV4MPEGFile::get_params() const +{ + return params; +} + +YUV4MPEGFile::Format YUV4MPEGFile::get_format() const +{ + return format; +} + +bool YUV4MPEGFile::is_full_range() const +{ + return full_range; +} diff --git a/crates/pyrowave-sys/vendor/pyrowave/yuv4mpeg.hpp b/crates/pyrowave-sys/vendor/pyrowave/yuv4mpeg.hpp new file mode 100644 index 00000000..6e40ea91 --- /dev/null +++ b/crates/pyrowave-sys/vendor/pyrowave/yuv4mpeg.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2025 Hans-Kristian Arntzen +// SPDX-License-Identifier: MIT +#pragma once + +#include +#include +#include +#include + +class YUV4MPEGFile +{ +public: + bool open_read(const std::string &path); + bool open_write(const std::string &path, const std::string ¶ms); + const std::string &get_params() const; + + int get_width() const; + int get_height() const; + + bool begin_frame(); + bool write(const void *pixels, size_t size); + bool read(void *pixels, size_t size); + + enum class Format + { + YUV420P, + YUV444P, + YUV420P16, + YUV444P16 + }; + + Format get_format() const; + bool is_full_range() const; + + static int format_to_bytes_per_component(Format format); + static bool format_has_subsampling(Format format); + + int get_frame_rate_num() const; + int get_frame_rate_den() const; + +private: + enum class Mode { Read, Write }; + bool open(const std::string &path, Mode mode); + struct FileDeleter { void operator()(FILE *f) { if (f) fclose(f); } }; + std::unique_ptr file; + int width = 0, height = 0; + int frame_rate_num = 60, frame_rate_den = 1; + std::string params; + Mode mode = {}; + Format format = {}; + bool full_range = false; + float unorm_scale = 1.0f; +}; diff --git a/crates/pyrowave-sys/wrapper.h b/crates/pyrowave-sys/wrapper.h new file mode 100644 index 00000000..0eaf3c7f --- /dev/null +++ b/crates/pyrowave-sys/wrapper.h @@ -0,0 +1,4 @@ +/* pyrowave.h requires the Vulkan headers to be included first (it refuses to + * compile otherwise); both come from the vendored tree. */ +#include +#include diff --git a/scripts/vendor-pyrowave.sh b/scripts/vendor-pyrowave.sh new file mode 100755 index 00000000..5d577722 --- /dev/null +++ b/scripts/vendor-pyrowave.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# Re-vendors PyroWave (+ the minimal Granite subset it builds against) into +# crates/pyrowave-sys/vendor/pyrowave. Network access required; run manually, +# never from CI or build.rs (the flatpak/CI builders are offline — that is the +# whole reason the tree is committed). +# +# ⚠️ Bumping PYROWAVE_COMMIT is a protocol-affecting change: the PyroWave +# bitstream has no version field, so the CODEC_PYROWAVE wire bit means +# "PyroWave bitstream as of this pin" (design/pyrowave-codec-plan.md §4.2). +# A bump that changes the bitstream must bump the punktfunk protocol version, +# and the Apple Metal hand-port (§4.7) must re-diff the two decode shaders + +# bitstream header structs. +set -euo pipefail + +PYROWAVE_COMMIT=509e4f887b585a3f97471fcc804e9de649f2c16f +# The Granite pin + submodule set come from upstream's checkout_granite.sh at +# that commit; recorded here for the vendor manifest only. + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +DEST="$REPO_ROOT/crates/pyrowave-sys/vendor/pyrowave" +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +git clone https://github.com/Themaister/pyrowave "$WORK/pyrowave" +git -C "$WORK/pyrowave" checkout "$PYROWAVE_COMMIT" +(cd "$WORK/pyrowave" && bash checkout_granite.sh) + +GRANITE_COMMIT="$(git -C "$WORK/pyrowave/Granite" rev-parse HEAD)" +VOLK_COMMIT="$(git -C "$WORK/pyrowave/Granite/third_party/volk" rev-parse HEAD)" +VKHDR_COMMIT="$(git -C "$WORK/pyrowave/Granite/third_party/khronos/vulkan-headers" rev-parse HEAD)" + +cd "$WORK/pyrowave" +rm -rf .git Granite/.git +rm -f Granite/third_party/volk/.git Granite/third_party/khronos/vulkan-headers/.git +# Upstream's own .gitignore files ignore the Granite checkout (`/Granite`) — +# fatal for a committed vendor tree; strip them all. +find . -name .gitignore -delete + +# Everything below is never entered by the standalone configure that +# crates/pyrowave-sys/CMakeLists.txt performs (GRANITE_SHIPPING=ON, +# GRANITE_RENDERER=OFF, GRANITE_PLATFORM=null, no PYROWAVE_DEVEL) — verified +# empirically: configure fails loudly if a needed dir goes missing. +# third_party/renderdoc stays: Granite adds it unconditionally. +rm -rf Granite/renderer Granite/ui Granite/scene-export Granite/video \ + Granite/audio Granite/physics Granite/tests Granite/tools \ + Granite/viewer Granite/assets Granite/slangmosh Granite/network \ + Granite/.github Granite/third_party/mikktspace +# vulkan-headers: the build needs the C headers + CMake package only. +rm -rf Granite/third_party/khronos/vulkan-headers/registry \ + Granite/third_party/khronos/vulkan-headers/tests +rm -f Granite/third_party/khronos/vulkan-headers/include/vulkan/*.hpp \ + Granite/third_party/khronos/vulkan-headers/include/vulkan/*.cppm + +mkdir -p "$(dirname "$DEST")" +rm -rf "$DEST" +cp -a "$WORK/pyrowave" "$DEST" + +cat > "$DEST/PUNKTFUNK-VENDOR.txt" <