diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index ee0d357e4..bec452007 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -285,6 +285,9 @@ simd_reduce_xor :: proc(a: #simd[N]T) -> T where type_is_integer(T) || t simd_reduce_any :: proc(a: #simd[N]T) -> T where type_is_boolean(T) --- simd_reduce_all :: proc(a: #simd[N]T) -> T where type_is_boolean(T) --- +simd_extract_lsbs :: proc(a: #simd[N]T) -> bit_set[0.. bit_set[0.. #simd[N]T where type_is_integer(U) || type_is_boolean(U) --- simd_scatter :: proc(ptr: #simd[N]rawptr, val: #simd[N]T, mask: #simd[N]U) where type_is_integer(U) || type_is_boolean(U) --- diff --git a/base/runtime/core.odin b/base/runtime/core.odin index e47f3ecbc..cd7d35540 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -239,47 +239,6 @@ Type_Info :: struct { }, } -// NOTE(bill): This must match the compiler's -Typeid_Kind :: enum u8 { - Invalid, - Integer, - Rune, - Float, - Complex, - Quaternion, - String, - Boolean, - Any, - Type_Id, - Pointer, - Multi_Pointer, - Procedure, - Array, - Enumerated_Array, - Dynamic_Array, - Slice, - Tuple, - Struct, - Union, - Enum, - Map, - Bit_Set, - Simd_Vector, - Matrix, - Soa_Pointer, - Bit_Field, -} -#assert(len(Typeid_Kind) < 32) - -Typeid_Bit_Field :: bit_field uintptr { - index: uintptr | 8*size_of(uintptr) - 8, - kind: Typeid_Kind | 5, // Typeid_Kind - named: bool | 1, - special: bool | 1, // signed, cstring, etc - reserved: bool | 1, -} -#assert(size_of(Typeid_Bit_Field) == size_of(uintptr)) - // NOTE(bill): only the ones that are needed (not all types) // This will be set by the compiler type_table: []^Type_Info @@ -483,10 +442,14 @@ Raw_Any :: struct { data: rawptr, id: typeid, } +when !ODIN_NO_RTTI { + #assert(size_of(Raw_Any) == size_of(any)) +} Raw_Cstring :: struct { data: [^]byte, } +#assert(size_of(Raw_Cstring) == size_of(cstring)) Raw_Soa_Pointer :: struct { data: rawptr, @@ -686,13 +649,16 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { type_info_base_without_enum :: type_info_core __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check { - MASK :: 1<<(8*size_of(typeid) - 8) - 1 - data := transmute(uintptr)id - n := int(data & MASK) - if n < 0 || n >= len(type_table) { - n = 0 + n := u64(len(type_table)) + i := transmute(u64)id % n + for _ in 0.. Random_Generator { return { procedure = default_random_generator_proc, diff --git a/core/dynlib/lib.odin b/core/dynlib/lib.odin index cd9eed5f8..e6b39be4b 100644 --- a/core/dynlib/lib.odin +++ b/core/dynlib/lib.odin @@ -145,6 +145,11 @@ initialize_symbols :: proc( } } + // No field for it in the struct. + if handle == nil { + handle = load_library(library_path) or_return + } + // Buffer to concatenate the prefix + symbol name. prefixed_symbol_buf: [2048]u8 = --- diff --git a/core/flags/util.odin b/core/flags/util.odin index f1bd60e75..c182289be 100644 --- a/core/flags/util.odin +++ b/core/flags/util.odin @@ -36,7 +36,7 @@ parse_or_exit :: proc( args = program_args[1:] } - error := parse(model, args, style) + error := parse(model, args, style, true, true, allocator, loc) if error != nil { stderr := os.stream_from_handle(os.stderr) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 51e70f6b7..b7b42ffa4 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -613,6 +613,10 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true, newline : i += 1 width_index, _, index_ok := _arg_number(fmt, &i, len(args)) + if !index_ok { + width_index, index_ok = error_check_arg(fi, false, unused_args^) + } + if index_ok { unused_args^ -= {width_index} @@ -638,6 +642,10 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true, newline : i += 1 precision_index, _, index_ok := _arg_number(fmt, &i, len(args)) + if !index_ok { + precision_index, index_ok = error_check_arg(fi, false, unused_args^) + } + if index_ok { unused_args^ -= {precision_index} fi.prec, _, fi.prec_set = int_from_arg(args, precision_index) @@ -1289,7 +1297,7 @@ fmt_rune :: proc(fi: ^Info, r: rune, verb: rune) { case 'q', 'w': fi.n += io.write_quoted_rune(fi.writer, r) case: - fmt_int(fi, u64(r), false, 32, verb) + fmt_int(fi, u64(u32(r)), false, 32, verb) } } // Formats an integer value according to the specified formatting verb. diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 3082a0afc..537256d32 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -19,7 +19,6 @@ default_random_generator :: runtime.default_random_generator @(require_results) create :: proc(seed: u64) -> (state: Default_Random_State) { seed := seed - runtime.default_random_generator(&state) runtime.default_random_generator_proc(&state, .Reset, ([^]byte)(&seed)[:size_of(seed)]) return } diff --git a/core/mem/doc.odin b/core/mem/doc.odin index 98755d797..580b08c96 100644 --- a/core/mem/doc.odin +++ b/core/mem/doc.odin @@ -16,8 +16,8 @@ a multipointer can be indexed, but does not have a definite length. A slice is a pointer that points to multiple objects equipped with the length, specifying the amount of objects a slice points to. -When object's values are read through a pointer, that operation is called a -*load* operation. When memory is read through a pointer, that operation is +When an object's values are read through a pointer, that operation is called a +*load* operation. When memory is written to through a pointer, that operation is called a *store* operation. Both of these operations can be called a *memory access operation*. diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 5191505cf..42f0054c2 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -341,7 +341,9 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, new_end := start + size if start < old_end && old_end == block.used && new_end <= block.reserved { // grow data in-place, adjusting next allocation + prev_used := block.used _ = alloc_from_memory_block(block, new_end - old_end, 1, default_commit_size=arena.default_commit_size) or_return + arena.total_used += block.used - prev_used data = block.base[start:new_end] return } diff --git a/core/net/dns.odin b/core/net/dns.odin index 9febc8b34..7eb543db3 100644 --- a/core/net/dns.odin +++ b/core/net/dns.odin @@ -7,10 +7,11 @@ package net */ /* - Copyright 2022 Tetralux - Copyright 2022 Colin Davidson - Copyright 2022 Jeroen van Rijn . - Copyright 2024 Feoramund . + Copyright 2022 Tetralux + Copyright 2022 Colin Davidson + Copyright 2022 Jeroen van Rijn . + Copyright 2024 Feoramund . + Copyright 2025 Christiano Haesbaert . Made available under Odin's BSD-3 license. List of contributors: @@ -18,12 +19,14 @@ package net Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver Jeroen van Rijn: Cross platform unification, code style, documentation Feoramund: FreeBSD platform code + Haesbaert: Security fixes */ import "core:mem" import "core:strings" import "core:time" import "core:os" +import "core:math/rand" /* Default configuration for DNS resolution. */ @@ -227,7 +230,7 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type } hdr := DNS_Header{ - id = 0, + id = u16be(rand.uint32()), is_response = false, opcode = 0, is_authoritative = false, @@ -272,17 +275,23 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type return nil, .Connection_Error } - recv_sz, _ := recv_udp(conn, dns_response_buf[:]) or_continue + recv_sz, src := recv_udp(conn, dns_response_buf[:]) or_continue if recv_sz == 0 { continue } + if src != name_server { + continue + } dns_response = dns_response_buf[:recv_sz] - rsp, _ok := parse_response(dns_response, type) + rsp, xid, _ok := parse_response(dns_response, type) if !_ok { return nil, .Server_Error } + if id != xid { + continue + } if len(rsp) == 0 { continue @@ -803,7 +812,7 @@ parse_record :: proc(packet: []u8, cur_off: ^int, filter: DNS_Record_Type = nil) - Data[] */ -parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator := context.allocator) -> (records: []DNS_Record, ok: bool) { +parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator := context.allocator) -> (records: []DNS_Record, xid: u16be, ok: bool) { context.allocator = allocator HEADER_SIZE_BYTES :: 12 @@ -816,11 +825,13 @@ parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator dns_hdr_chunks := mem.slice_data_cast([]u16be, response[:HEADER_SIZE_BYTES]) hdr := unpack_dns_header(dns_hdr_chunks[0], dns_hdr_chunks[1]) if !hdr.is_response { + delete(_records) return } question_count := int(dns_hdr_chunks[2]) if question_count != 1 { + delete(_records) return } answer_count := int(dns_hdr_chunks[3]) @@ -872,6 +883,7 @@ parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator append(&_records, rec) } } + xid = hdr.id - return _records[:], true + return _records[:], xid, true } diff --git a/core/net/socket_windows.odin b/core/net/socket_windows.odin index 747d5cab3..f19be536a 100644 --- a/core/net/socket_windows.odin +++ b/core/net/socket_windows.odin @@ -80,8 +80,9 @@ _dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_optio sockaddr := _endpoint_to_sockaddr(endpoint) res := win.connect(win.SOCKET(socket), &sockaddr, size_of(sockaddr)) if res < 0 { + err = Dial_Error(win.WSAGetLastError()) close(socket) - return {}, Dial_Error(win.WSAGetLastError()) + return {}, err } if options.no_delay { diff --git a/core/os/os2/dir.odin b/core/os/os2/dir.odin index a41ef68f9..4a7762ded 100644 --- a/core/os/os2/dir.odin +++ b/core/os/os2/dir.odin @@ -20,7 +20,7 @@ read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files TEMP_ALLOCATOR_GUARD() - it := read_directory_iterator_create(f) or_return + it := read_directory_iterator_create(f) defer _read_directory_iterator_destroy(&it) dfi := make([dynamic]File_Info, 0, size, temp_allocator()) @@ -34,9 +34,14 @@ read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files if n > 0 && index == n { break } + + _ = read_directory_iterator_error(&it) or_break + append(&dfi, file_info_clone(fi, allocator) or_return) } + _ = read_directory_iterator_error(&it) or_return + return slice.clone(dfi[:], allocator) } @@ -61,22 +66,129 @@ read_all_directory_by_path :: proc(path: string, allocator: runtime.Allocator) - Read_Directory_Iterator :: struct { - f: ^File, + f: ^File, + err: struct { + err: Error, + path: [dynamic]byte, + }, + index: int, impl: Read_Directory_Iterator_Impl, } +/* +Creates a directory iterator with the given directory. -@(require_results) -read_directory_iterator_create :: proc(f: ^File) -> (Read_Directory_Iterator, Error) { - return _read_directory_iterator_create(f) +For an example on how to use the iterator, see `read_directory_iterator`. +*/ +read_directory_iterator_create :: proc(f: ^File) -> (it: Read_Directory_Iterator) { + read_directory_iterator_init(&it, f) + return } +/* +Initialize a directory iterator with the given directory. + +This procedure may be called on an existing iterator to reuse it for another directory. + +For an example on how to use the iterator, see `read_directory_iterator`. +*/ +read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { + it.err.err = nil + it.err.path.allocator = file_allocator() + clear(&it.err.path) + + it.f = f + it.index = 0 + + _read_directory_iterator_init(it, f) +} + +/* +Destroys a directory iterator. +*/ read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) { + if it == nil { + return + } + + delete(it.err.path) + _read_directory_iterator_destroy(it) } -// NOTE(bill): `File_Info` does not need to deleted on each iteration. Any copies must be manually copied with `file_info_clone` +/* +Retrieve the last error that happened during iteration. +*/ +@(require_results) +read_directory_iterator_error :: proc(it: ^Read_Directory_Iterator) -> (path: string, err: Error) { + return string(it.err.path[:]), it.err.err +} + +@(private) +read_directory_iterator_set_error :: proc(it: ^Read_Directory_Iterator, path: string, err: Error) { + if err == nil { + return + } + + resize(&it.err.path, len(path)) + copy(it.err.path[:], path) + + it.err.err = err +} + +/* +Returns the next file info entry for the iterator's directory. + +The given `File_Info` is reused in subsequent calls so a copy (`file_info_clone`) has to be made to +extend its lifetime. + +Example: + package main + + import "core:fmt" + import os "core:os/os2" + + main :: proc() { + f, oerr := os.open("core") + ensure(oerr == nil) + defer os.close(f) + + it := os.read_directory_iterator_create(f) + defer os.read_directory_iterator_destroy(&it) + + for info in os.read_directory_iterator(&it) { + // Optionally break on the first error: + // Supports not doing this, and keeping it going with remaining items. + // _ = os.read_directory_iterator_error(&it) or_break + + // Handle error as we go: + // Again, no need to do this as it will keep going with remaining items. + if path, err := os.read_directory_iterator_error(&it); err != nil { + fmt.eprintfln("failed reading %s: %s", path, err) + continue + } + + // Or, do not handle errors during iteration, and just check the error at the end. + + + fmt.printfln("%#v", info) + } + + // Handle error if one happened during iteration at the end: + if path, err := os.read_directory_iterator_error(&it); err != nil { + fmt.eprintfln("read directory failed at %s: %s", path, err) + } + } +*/ @(require_results) read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) { + if it.f == nil { + return + } + + if it.index == 0 && it.err.err != nil { + return + } + return _read_directory_iterator(it) } diff --git a/core/os/os2/dir_linux.odin b/core/os/os2/dir_linux.odin index f7723936b..a868a02c4 100644 --- a/core/os/os2/dir_linux.odin +++ b/core/os/os2/dir_linux.odin @@ -8,12 +8,11 @@ Read_Directory_Iterator_Impl :: struct { dirent_backing: []u8, dirent_buflen: int, dirent_off: int, - index: int, } @(require_results) _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) { - scan_entries :: proc(dfd: linux.Fd, entries: []u8, offset: ^int) -> (fd: linux.Fd, file_name: string) { + scan_entries :: proc(it: ^Read_Directory_Iterator, dfd: linux.Fd, entries: []u8, offset: ^int) -> (fd: linux.Fd, file_name: string) { for d in linux.dirent_iterate_buf(entries, offset) { file_name = linux.dirent_name(d) if file_name == "." || file_name == ".." { @@ -24,18 +23,21 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info entry_fd, errno := linux.openat(dfd, file_name_cstr, {.NOFOLLOW, .PATH}) if errno == .NONE { return entry_fd, file_name + } else { + read_directory_iterator_set_error(it, file_name, _get_platform_error(errno)) } } + return -1, "" } - index = it.impl.index - it.impl.index += 1 + index = it.index + it.index += 1 dfd := linux.Fd(_fd(it.f)) entries := it.impl.dirent_backing[:it.impl.dirent_buflen] - entry_fd, file_name := scan_entries(dfd, entries, &it.impl.dirent_off) + entry_fd, file_name := scan_entries(it, dfd, entries, &it.impl.dirent_off) for entry_fd == -1 { if len(it.impl.dirent_backing) == 0 { @@ -58,44 +60,60 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info it.impl.dirent_buflen = buflen entries = it.impl.dirent_backing[:buflen] break loop - case: // error + case: + read_directory_iterator_set_error(it, name(it.f), _get_platform_error(errno)) return } } - entry_fd, file_name = scan_entries(dfd, entries, &it.impl.dirent_off) + entry_fd, file_name = scan_entries(it, dfd, entries, &it.impl.dirent_off) } defer linux.close(entry_fd) + // PERF: reuse the fullpath string like on posix and wasi. file_info_delete(it.impl.prev_fi, file_allocator()) - fi, _ = _fstat_internal(entry_fd, file_allocator()) + + err: Error + fi, err = _fstat_internal(entry_fd, file_allocator()) it.impl.prev_fi = fi + if err != nil { + path, _ := _get_full_path(entry_fd, temp_allocator()) + read_directory_iterator_set_error(it, path, err) + } + ok = true return } -@(require_results) -_read_directory_iterator_create :: proc(f: ^File) -> (Read_Directory_Iterator, Error) { +_read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { + // NOTE: Allow calling `init` to target a new directory with the same iterator. + it.impl.dirent_buflen = 0 + it.impl.dirent_off = 0 + if f == nil || f.impl == nil { - return {}, .Invalid_File + read_directory_iterator_set_error(it, "", .Invalid_File) + return } stat: linux.Stat errno := linux.fstat(linux.Fd(fd(f)), &stat) if errno != .NONE { - return {}, _get_platform_error(errno) + read_directory_iterator_set_error(it, name(f), _get_platform_error(errno)) + return } + if (stat.mode & linux.S_IFMT) != linux.S_IFDIR { - return {}, .Invalid_Dir + read_directory_iterator_set_error(it, name(f), .Invalid_Dir) + return } - return {f = f}, nil } _read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) { if it == nil { return } + delete(it.impl.dirent_backing, file_allocator()) file_info_delete(it.impl.prev_fi, file_allocator()) } diff --git a/core/os/os2/dir_posix.odin b/core/os/os2/dir_posix.odin index 36cac2597..d9fa16f8d 100644 --- a/core/os/os2/dir_posix.odin +++ b/core/os/os2/dir_posix.odin @@ -6,7 +6,6 @@ import "core:sys/posix" Read_Directory_Iterator_Impl :: struct { dir: posix.DIR, - idx: int, fullpath: [dynamic]byte, } @@ -14,14 +13,16 @@ Read_Directory_Iterator_Impl :: struct { _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) { fimpl := (^File_Impl)(it.f.impl) - index = it.impl.idx - it.impl.idx += 1 + index = it.index + it.index += 1 for { + posix.set_errno(nil) entry := posix.readdir(it.impl.dir) if entry == nil { - // NOTE(laytan): would be good to have an `error` field on the `Read_Directory_Iterator` - // There isn't a way to now know if it failed or if we are at the end. + if errno := posix.errno(); errno != nil { + read_directory_iterator_set_error(it, name(it.f), _get_platform_error(errno)) + } return } @@ -31,54 +32,62 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info } sname := string(cname) - stat: posix.stat_t - if posix.fstatat(posix.dirfd(it.impl.dir), cname, &stat, { .SYMLINK_NOFOLLOW }) != .OK { - // NOTE(laytan): would be good to have an `error` field on the `Read_Directory_Iterator` - // There isn't a way to now know if it failed or if we are at the end. - return - } - n := len(fimpl.name)+1 if err := non_zero_resize(&it.impl.fullpath, n+len(sname)); err != nil { - // Can't really tell caller we had an error, sad. + read_directory_iterator_set_error(it, sname, err) + ok = true return } copy(it.impl.fullpath[n:], sname) + stat: posix.stat_t + if posix.fstatat(posix.dirfd(it.impl.dir), cname, &stat, { .SYMLINK_NOFOLLOW }) != .OK { + read_directory_iterator_set_error(it, string(it.impl.fullpath[:]), _get_platform_error()) + ok = true + return + } + fi = internal_stat(stat, string(it.impl.fullpath[:])) ok = true return } } -@(require_results) -_read_directory_iterator_create :: proc(f: ^File) -> (iter: Read_Directory_Iterator, err: Error) { +_read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { if f == nil || f.impl == nil { - err = .Invalid_File + read_directory_iterator_set_error(it, "", .Invalid_File) return } impl := (^File_Impl)(f.impl) - iter.f = f - iter.impl.idx = 0 + // NOTE: Allow calling `init` to target a new directory with the same iterator. + it.impl.fullpath.allocator = file_allocator() + clear(&it.impl.fullpath) + if err := reserve(&it.impl.fullpath, len(impl.name)+128); err != nil { + read_directory_iterator_set_error(it, name(f), err) + return + } - iter.impl.fullpath = make([dynamic]byte, 0, len(impl.name)+128, file_allocator()) or_return - append(&iter.impl.fullpath, impl.name) - append(&iter.impl.fullpath, "/") - defer if err != nil { delete(iter.impl.fullpath) } + append(&it.impl.fullpath, impl.name) + append(&it.impl.fullpath, "/") // `fdopendir` consumes the file descriptor so we need to `dup` it. dupfd := posix.dup(impl.fd) if dupfd == -1 { - err = _get_platform_error() + read_directory_iterator_set_error(it, name(f), _get_platform_error()) return } - defer if err != nil { posix.close(dupfd) } + defer if it.err.err != nil { posix.close(dupfd) } - iter.impl.dir = posix.fdopendir(dupfd) - if iter.impl.dir == nil { - err = _get_platform_error() + // NOTE: Allow calling `init` to target a new directory with the same iterator. + if it.impl.dir != nil { + posix.closedir(it.impl.dir) + } + + it.impl.dir = posix.fdopendir(dupfd) + if it.impl.dir == nil { + read_directory_iterator_set_error(it, name(f), _get_platform_error()) return } @@ -86,7 +95,7 @@ _read_directory_iterator_create :: proc(f: ^File) -> (iter: Read_Directory_Itera } _read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) { - if it == nil || it.impl.dir == nil { + if it.impl.dir == nil { return } diff --git a/core/os/os2/dir_walker.odin b/core/os/os2/dir_walker.odin new file mode 100644 index 000000000..0af751f31 --- /dev/null +++ b/core/os/os2/dir_walker.odin @@ -0,0 +1,230 @@ +package os2 + +import "core:container/queue" + +/* +A recursive directory walker. + +Note that none of the fields should be accessed directly. +*/ +Walker :: struct { + todo: queue.Queue(string), + skip_dir: bool, + err: struct { + path: [dynamic]byte, + err: Error, + }, + iter: Read_Directory_Iterator, +} + +walker_init_path :: proc(w: ^Walker, path: string) { + cloned_path, err := clone_string(path, file_allocator()) + if err != nil { + walker_set_error(w, path, err) + return + } + + walker_clear(w) + + if _, err = queue.push(&w.todo, cloned_path); err != nil { + walker_set_error(w, cloned_path, err) + return + } +} + +walker_init_file :: proc(w: ^Walker, f: ^File) { + handle, err := clone(f) + if err != nil { + path, _ := clone_string(name(f), file_allocator()) + walker_set_error(w, path, err) + return + } + + walker_clear(w) + + read_directory_iterator_init(&w.iter, handle) +} + +/* +Initializes a walker, either using a path or a file pointer to a directory the walker will start at. + +You are allowed to repeatedly call this to reuse it for later walks. + +For an example on how to use the walker, see `walker_walk`. +*/ +walker_init :: proc { + walker_init_path, + walker_init_file, +} + +@(require_results) +walker_create_path :: proc(path: string) -> (w: Walker) { + walker_init_path(&w, path) + return +} + +@(require_results) +walker_create_file :: proc(f: ^File) -> (w: Walker) { + walker_init_file(&w, f) + return +} + +/* +Creates a walker, either using a path or a file pointer to a directory the walker will start at. + +For an example on how to use the walker, see `walker_walk`. +*/ +walker_create :: proc { + walker_create_path, + walker_create_file, +} + +/* +Returns the last error that occurred during the walker's operations. + +Can be called while iterating, or only at the end to check if anything failed. +*/ +@(require_results) +walker_error :: proc(w: ^Walker) -> (path: string, err: Error) { + return string(w.err.path[:]), w.err.err +} + +@(private) +walker_set_error :: proc(w: ^Walker, path: string, err: Error) { + if err == nil { + return + } + + resize(&w.err.path, len(path)) + copy(w.err.path[:], path) + + w.err.err = err +} + +@(private) +walker_clear :: proc(w: ^Walker) { + w.iter.f = nil + w.skip_dir = false + + w.err.path.allocator = file_allocator() + clear(&w.err.path) + + w.todo.data.allocator = file_allocator() + for path in queue.pop_front_safe(&w.todo) { + delete(path, file_allocator()) + } +} + +walker_destroy :: proc(w: ^Walker) { + walker_clear(w) + queue.destroy(&w.todo) + delete(w.err.path) + read_directory_iterator_destroy(&w.iter) +} + +// Marks the current directory to be skipped (not entered into). +walker_skip_dir :: proc(w: ^Walker) { + w.skip_dir = true +} + +/* +Returns the next file info in the iterator, files are iterated in breadth-first order. + +If an error occurred opening a directory, you may get zero'd info struct and +`walker_error` will return the error. + +Example: + package main + + import "core:fmt" + import "core:strings" + import os "core:os/os2" + + main :: proc() { + w := os.walker_create("core") + defer os.walker_destroy(&w) + + for info in os.walker_walk(&w) { + // Optionally break on the first error: + // _ = walker_error(&w) or_break + + // Or, handle error as we go: + if path, err := os.walker_error(&w); err != nil { + fmt.eprintfln("failed walking %s: %s", path, err) + continue + } + + // Or, do not handle errors during iteration, and just check the error at the end. + + + + // Skip a directory: + if strings.has_suffix(info.fullpath, ".git") { + os.walker_skip_dir(&w) + continue + } + + fmt.printfln("%#v", info) + } + + // Handle error if one happened during iteration at the end: + if path, err := os.walker_error(&w); err != nil { + fmt.eprintfln("failed walking %s: %v", path, err) + } + } +*/ +@(require_results) +walker_walk :: proc(w: ^Walker) -> (fi: File_Info, ok: bool) { + if w.skip_dir { + w.skip_dir = false + if skip, sok := queue.pop_back_safe(&w.todo); sok { + delete(skip, file_allocator()) + } + } + + if w.iter.f == nil { + if queue.len(w.todo) == 0 { + return + } + + next := queue.pop_front(&w.todo) + + handle, err := open(next) + if err != nil { + walker_set_error(w, next, err) + return {}, true + } + + read_directory_iterator_init(&w.iter, handle) + + delete(next, file_allocator()) + } + + info, _, iter_ok := read_directory_iterator(&w.iter) + + if path, err := read_directory_iterator_error(&w.iter); err != nil { + walker_set_error(w, path, err) + } + + if !iter_ok { + close(w.iter.f) + w.iter.f = nil + return walker_walk(w) + } + + if info.type == .Directory { + path, err := clone_string(info.fullpath, file_allocator()) + if err != nil { + walker_set_error(w, "", err) + return + } + + _, err = queue.push_back(&w.todo, path) + if err != nil { + walker_set_error(w, path, err) + return + } + } + + return info, iter_ok +} diff --git a/core/os/os2/dir_wasi.odin b/core/os/os2/dir_wasi.odin index e4349069a..61c005674 100644 --- a/core/os/os2/dir_wasi.odin +++ b/core/os/os2/dir_wasi.odin @@ -1,6 +1,8 @@ #+private package os2 +import "base:runtime" +import "core:slice" import "base:intrinsics" import "core:sys/wasm/wasi" @@ -8,7 +10,6 @@ Read_Directory_Iterator_Impl :: struct { fullpath: [dynamic]byte, buf: []byte, off: int, - idx: int, } @(require_results) @@ -17,8 +18,8 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info buf := it.impl.buf[it.impl.off:] - index = it.impl.idx - it.impl.idx += 1 + index = it.index + it.index += 1 for { if len(buf) < size_of(wasi.dirent_t) { @@ -28,10 +29,7 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info entry := intrinsics.unaligned_load((^wasi.dirent_t)(raw_data(buf))) buf = buf[size_of(wasi.dirent_t):] - if len(buf) < int(entry.d_namlen) { - // shouldn't be possible. - return - } + assert(len(buf) < int(entry.d_namlen)) name := string(buf[:entry.d_namlen]) buf = buf[entry.d_namlen:] @@ -43,7 +41,8 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info n := len(fimpl.name)+1 if alloc_err := non_zero_resize(&it.impl.fullpath, n+len(name)); alloc_err != nil { - // Can't really tell caller we had an error, sad. + read_directory_iterator_set_error(it, name, alloc_err) + ok = true return } copy(it.impl.fullpath[n:], name) @@ -55,6 +54,7 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info ino = entry.d_ino, filetype = entry.d_type, } + read_directory_iterator_set_error(it, string(it.impl.fullpath[:]), _get_platform_error(err)) } fi = internal_stat(stat, string(it.impl.fullpath[:])) @@ -63,27 +63,35 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info } } -@(require_results) -_read_directory_iterator_create :: proc(f: ^File) -> (iter: Read_Directory_Iterator, err: Error) { +_read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { + // NOTE: Allow calling `init` to target a new directory with the same iterator. + it.impl.off = 0 + if f == nil || f.impl == nil { - err = .Invalid_File + read_directory_iterator_set_error(it, "", .Invalid_File) return } impl := (^File_Impl)(f.impl) - iter.f = f buf: [dynamic]byte + // NOTE: Allow calling `init` to target a new directory with the same iterator. + if it.impl.buf != nil { + buf = slice.into_dynamic(it.impl.buf) + } buf.allocator = file_allocator() - defer if err != nil { delete(buf) } - // NOTE: this is very grug. + defer if it.err.err != nil { delete(buf) } + for { - non_zero_resize(&buf, 512 if len(buf) == 0 else len(buf)*2) or_return + if err := non_zero_resize(&buf, 512 if len(buf) == 0 else len(buf)*2); err != nil { + read_directory_iterator_set_error(it, name(f), err) + return + } - n, _err := wasi.fd_readdir(__fd(f), buf[:], 0) - if _err != nil { - err = _get_platform_error(_err) + n, err := wasi.fd_readdir(__fd(f), buf[:], 0) + if err != nil { + read_directory_iterator_set_error(it, name(f), _get_platform_error(err)) return } @@ -94,11 +102,18 @@ _read_directory_iterator_create :: proc(f: ^File) -> (iter: Read_Directory_Itera assert(n == len(buf)) } - iter.impl.buf = buf[:] + it.impl.buf = buf[:] - iter.impl.fullpath = make([dynamic]byte, 0, len(impl.name)+128, file_allocator()) or_return - append(&iter.impl.fullpath, impl.name) - append(&iter.impl.fullpath, "/") + // NOTE: Allow calling `init` to target a new directory with the same iterator. + it.impl.fullpath.allocator = file_allocator() + clear(&it.impl.fullpath) + if err := reserve(&it.impl.fullpath, len(impl.name)+128); err != nil { + read_directory_iterator_set_error(it, name(f), err) + return + } + + append(&it.impl.fullpath, impl.name) + append(&it.impl.fullpath, "/") return } @@ -106,5 +121,4 @@ _read_directory_iterator_create :: proc(f: ^File) -> (iter: Read_Directory_Itera _read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) { delete(it.impl.buf, file_allocator()) delete(it.impl.fullpath) - it^ = {} } diff --git a/core/os/os2/dir_windows.odin b/core/os/os2/dir_windows.odin index f71e7e763..d592e8036 100644 --- a/core/os/os2/dir_windows.odin +++ b/core/os/os2/dir_windows.odin @@ -44,16 +44,11 @@ Read_Directory_Iterator_Impl :: struct { path: string, prev_fi: File_Info, no_more_files: bool, - index: int, } @(require_results) _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) { - if it.f == nil { - return - } - TEMP_ALLOCATOR_GUARD() for !it.impl.no_more_files { @@ -63,19 +58,21 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info fi, err = find_data_to_file_info(it.impl.path, &it.impl.find_data, file_allocator()) if err != nil { + read_directory_iterator_set_error(it, it.impl.path, err) return } + if fi.name != "" { it.impl.prev_fi = fi ok = true - index = it.impl.index - it.impl.index += 1 + index = it.index + it.index += 1 } if !win32.FindNextFileW(it.impl.find_handle, &it.impl.find_data) { e := _get_platform_error() - if pe, _ := is_platform_error(e); pe == i32(win32.ERROR_NO_MORE_FILES) { - it.impl.no_more_files = true + if pe, _ := is_platform_error(e); pe != i32(win32.ERROR_NO_MORE_FILES) { + read_directory_iterator_set_error(it, it.impl.path, e) } it.impl.no_more_files = true } @@ -86,16 +83,27 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info return } -@(require_results) -_read_directory_iterator_create :: proc(f: ^File) -> (it: Read_Directory_Iterator, err: Error) { - if f == nil { +_read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { + it.impl.no_more_files = false + + if f == nil || f.impl == nil { + read_directory_iterator_set_error(it, "", .Invalid_File) return } + it.f = f impl := (^File_Impl)(f.impl) + // NOTE: Allow calling `init` to target a new directory with the same iterator - reset idx. + if it.impl.find_handle != nil { + win32.FindClose(it.impl.find_handle) + } + if it.impl.path != "" { + delete(it.impl.path, file_allocator()) + } + if !is_directory(impl.name) { - err = .Invalid_Dir + read_directory_iterator_set_error(it, impl.name, .Invalid_Dir) return } @@ -118,14 +126,19 @@ _read_directory_iterator_create :: proc(f: ^File) -> (it: Read_Directory_Iterato it.impl.find_handle = win32.FindFirstFileW(raw_data(wpath_search), &it.impl.find_data) if it.impl.find_handle == win32.INVALID_HANDLE_VALUE { - err = _get_platform_error() + read_directory_iterator_set_error(it, impl.name, _get_platform_error()) return } - defer if err != nil { + defer if it.err.err != nil { win32.FindClose(it.impl.find_handle) } - it.impl.path = _cleanpath_from_buf(wpath, file_allocator()) or_return + err: Error + it.impl.path, err = _cleanpath_from_buf(wpath, file_allocator()) + if err != nil { + read_directory_iterator_set_error(it, impl.name, err) + } + return } diff --git a/core/os/os2/env.odin b/core/os/os2/env.odin index c8d39b270..13c107f3c 100644 --- a/core/os/os2/env.odin +++ b/core/os/os2/env.odin @@ -22,8 +22,8 @@ lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, } // set_env sets the value of the environment variable named by the key -// Returns true on success, false on failure -set_env :: proc(key, value: string) -> bool { +// Returns Error on failure +set_env :: proc(key, value: string) -> Error { return _set_env(key, value) } @@ -41,7 +41,7 @@ clear_env :: proc() { // environ returns a copy of strings representing the environment, in the form "key=value" // NOTE: the slice of strings and the strings with be allocated using the supplied allocator @(require_results) -environ :: proc(allocator: runtime.Allocator) -> []string { +environ :: proc(allocator: runtime.Allocator) -> ([]string, Error) { return _environ(allocator) } diff --git a/core/os/os2/env_linux.odin b/core/os/os2/env_linux.odin index e0ef06010..2ed43dd91 100644 --- a/core/os/os2/env_linux.odin +++ b/core/os/os2/env_linux.odin @@ -20,19 +20,18 @@ NOT_FOUND :: -1 // the environment is a 0 delimited list of = strings _env: [dynamic]string -_env_mutex: sync.Mutex +_env_mutex: sync.Recursive_Mutex // We need to be able to figure out if the environment variable // is contained in the original environment or not. This also // serves as a flag to determine if we have built _env. -_org_env_begin: uintptr -_org_env_end: uintptr +_org_env_begin: uintptr // atomic +_org_env_end: uintptr // guarded by _env_mutex // Returns value + index location into _env // or -1 if not found _lookup :: proc(key: string) -> (value: string, idx: int) { - sync.mutex_lock(&_env_mutex) - defer sync.mutex_unlock(&_env_mutex) + sync.guard(&_env_mutex) for entry, i in _env { if k, v := _kv_from_entry(entry); k == key { @@ -43,7 +42,7 @@ _lookup :: proc(key: string) -> (value: string, idx: int) { } _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { - if _org_env_begin == 0 { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { _build_env() } @@ -54,19 +53,18 @@ _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string return } -_set_env :: proc(key, v_new: string) -> bool { - if _org_env_begin == 0 { +_set_env :: proc(key, v_new: string) -> Error { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { _build_env() } + sync.guard(&_env_mutex) // all key values are stored as "key=value\x00" kv_size := len(key) + len(v_new) + 2 if v_curr, idx := _lookup(key); idx != NOT_FOUND { if v_curr == v_new { - return true + return nil } - sync.mutex_lock(&_env_mutex) - defer sync.mutex_unlock(&_env_mutex) unordered_remove(&_env, idx) @@ -78,7 +76,7 @@ _set_env :: proc(key, v_new: string) -> bool { if len(v_new) > len(v_curr) { k_addr = ([^]u8)(runtime.heap_resize(k_addr, kv_size)) if k_addr == nil { - return false + return .Out_Of_Memory } v_addr = &k_addr[len(key) + 1] } @@ -86,13 +84,13 @@ _set_env :: proc(key, v_new: string) -> bool { v_addr[len(v_new)] = 0 append(&_env, string(k_addr[:kv_size])) - return true + return nil } } k_addr := ([^]u8)(runtime.heap_alloc(kv_size)) if k_addr == nil { - return false + return .Out_Of_Memory } intrinsics.mem_copy_non_overlapping(k_addr, raw_data(key), len(key)) k_addr[len(key)] = '=' @@ -101,16 +99,15 @@ _set_env :: proc(key, v_new: string) -> bool { intrinsics.mem_copy_non_overlapping(&val_slice[0], raw_data(v_new), len(v_new)) val_slice[len(v_new)] = 0 - sync.mutex_lock(&_env_mutex) append(&_env, string(k_addr[:kv_size - 1])) - sync.mutex_unlock(&_env_mutex) - return true + return nil } _unset_env :: proc(key: string) -> bool { - if _org_env_begin == 0 { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { _build_env() } + sync.guard(&_env_mutex) v: string i: int @@ -118,15 +115,13 @@ _unset_env :: proc(key: string) -> bool { return false } - sync.mutex_lock(&_env_mutex) unordered_remove(&_env, i) - sync.mutex_unlock(&_env_mutex) if _is_in_org_env(v) { return true } - // if we got this far, the envrionment variable + // if we got this far, the environment variable // existed AND was allocated by us. k_addr, _ := _kv_addr_from_val(v, key) runtime.heap_free(k_addr) @@ -134,8 +129,7 @@ _unset_env :: proc(key: string) -> bool { } _clear_env :: proc() { - sync.mutex_lock(&_env_mutex) - defer sync.mutex_unlock(&_env_mutex) + sync.guard(&_env_mutex) for kv in _env { if !_is_in_org_env(kv) { @@ -145,28 +139,36 @@ _clear_env :: proc() { clear(&_env) // nothing resides in the original environment either - _org_env_begin = ~uintptr(0) + intrinsics.atomic_store_explicit(&_org_env_begin, ~uintptr(0), .Release) _org_env_end = ~uintptr(0) } -_environ :: proc(allocator: runtime.Allocator) -> []string { - if _org_env_begin == 0 { +_environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { _build_env() } - env := make([]string, len(_env), allocator) + sync.guard(&_env_mutex) - sync.mutex_lock(&_env_mutex) - defer sync.mutex_unlock(&_env_mutex) - for entry, i in _env { - env[i], _ = clone_string(entry, allocator) + env := make([dynamic]string, 0, len(_env), allocator) or_return + defer if err != nil { + for e in env { + delete(e, allocator) + } + delete(env) } - return env + + for entry in _env { + s := clone_string(entry, allocator) or_return + append(&env, s) + } + environ = env[:] + return } // The entire environment is stored as 0 terminated strings, // so there is no need to clone/free individual variables export_cstring_environment :: proc(allocator: runtime.Allocator) -> []cstring { - if _org_env_begin == 0 { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { // The environment has not been modified, so we can just // send the original environment org_env := _get_original_env() @@ -174,12 +176,11 @@ export_cstring_environment :: proc(allocator: runtime.Allocator) -> []cstring { for ; org_env[n] != nil; n += 1 {} return slice.clone(org_env[:n + 1], allocator) } + sync.guard(&_env_mutex) // NOTE: already terminated by nil pointer via + 1 env := make([]cstring, len(_env) + 1, allocator) - sync.mutex_lock(&_env_mutex) - defer sync.mutex_unlock(&_env_mutex) for entry, i in _env { env[i] = cstring(raw_data(entry)) } @@ -187,15 +188,14 @@ export_cstring_environment :: proc(allocator: runtime.Allocator) -> []cstring { } _build_env :: proc() { - sync.mutex_lock(&_env_mutex) - defer sync.mutex_unlock(&_env_mutex) - if _org_env_begin != 0 { + sync.guard(&_env_mutex) + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) != 0 { return } _env = make(type_of(_env), runtime.heap_allocator()) cstring_env := _get_original_env() - _org_env_begin = uintptr(rawptr(cstring_env[0])) + intrinsics.atomic_store_explicit(&_org_env_begin, uintptr(rawptr(cstring_env[0])), .Release) for i := 0; cstring_env[i] != nil; i += 1 { bytes := ([^]u8)(cstring_env[i]) n := len(cstring_env[i]) @@ -227,5 +227,5 @@ _kv_addr_from_val :: #force_inline proc(val: string, key: string) -> ([^]u8, [^] _is_in_org_env :: #force_inline proc(env_data: string) -> bool { addr := uintptr(raw_data(env_data)) - return addr >= _org_env_begin && addr < _org_env_end + return addr >= intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) && addr < _org_env_end } diff --git a/core/os/os2/env_posix.odin b/core/os/os2/env_posix.odin index e2080485d..9661768b4 100644 --- a/core/os/os2/env_posix.odin +++ b/core/os/os2/env_posix.odin @@ -26,13 +26,15 @@ _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string return } -_set_env :: proc(key, value: string) -> (ok: bool) { +_set_env :: proc(key, value: string) -> (err: Error) { TEMP_ALLOCATOR_GUARD() - ckey := strings.clone_to_cstring(key, temp_allocator()) - cval := strings.clone_to_cstring(key, temp_allocator()) + ckey := strings.clone_to_cstring(key, temp_allocator()) or_return + cval := strings.clone_to_cstring(key, temp_allocator()) or_return - ok = posix.setenv(ckey, cval, true) == .OK + if posix.setenv(ckey, cval, true) != nil { + err = _get_platform_error_from_errno() + } return } @@ -54,23 +56,23 @@ _clear_env :: proc() { } } -_environ :: proc(allocator: runtime.Allocator) -> (environ: []string) { - n := 0 +_environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) { + n := 0 for entry := posix.environ[0]; entry != nil; n, entry = n+1, posix.environ[n] {} - err: runtime.Allocator_Error - if environ, err = make([]string, n, allocator); err != nil { - // NOTE(laytan): is the environment empty or did allocation fail, how does the user know? - return + r := make([dynamic]string, 0, n, allocator) or_return + defer if err != nil { + for e in r { + delete(e, allocator) + } + delete(r) } for i, entry := 0, posix.environ[0]; entry != nil; i, entry = i+1, posix.environ[i] { - if environ[i], err = strings.clone(string(entry), allocator); err != nil { - // NOTE(laytan): is the entire environment returned or did allocation fail, how does the user know? - return - } + append(&r, strings.clone(string(entry), allocator) or_return) } + environ = r[:] return } diff --git a/core/os/os2/env_wasi.odin b/core/os/os2/env_wasi.odin index 8bf4eff38..305192c92 100644 --- a/core/os/os2/env_wasi.odin +++ b/core/os/os2/env_wasi.odin @@ -80,46 +80,30 @@ _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string } @(require_results) -_set_env :: proc(key, value: string) -> bool { - if err := build_env(); err != nil { - return false - } +_set_env :: proc(key, value: string) -> (err: Error) { + build_env() or_return sync.guard(&g_env_mutex) - key_ptr, value_ptr, just_inserted, err := map_entry(&g_env, key) - if err != nil { - return false + defer if err != nil { + delete_key(&g_env, key) } - alloc_err: runtime.Allocator_Error + key_ptr, value_ptr, just_inserted := map_entry(&g_env, key) or_return if just_inserted { - key_ptr^, alloc_err = clone_string(key, file_allocator()) - if alloc_err != nil { - delete_key(&g_env, key) - return false - } - - value_ptr^, alloc_err = clone_string(value, file_allocator()) - if alloc_err != nil { - delete_key(&g_env, key) + key_ptr^ = clone_string(key, file_allocator()) or_return + defer if err != nil { delete(key_ptr^, file_allocator()) - return false } - - return true + value_ptr^ = clone_string(value, file_allocator()) or_return + return } delete_string_if_not_original(value_ptr^) - value_ptr^, alloc_err = clone_string(value, file_allocator()) - if alloc_err != nil { - delete_key(&g_env, key) - return false - } - - return true + value_ptr^ = clone_string(value, file_allocator()) or_return + return } @(require_results) @@ -153,34 +137,23 @@ _clear_env :: proc() { } @(require_results) -_environ :: proc(allocator: runtime.Allocator) -> []string { - if err := build_env(); err != nil { - return nil - } +_environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) { + build_env() or_return sync.shared_guard(&g_env_mutex) - envs, alloc_err := make([]string, len(g_env), allocator) - if alloc_err != nil { - return nil - } - - defer if alloc_err != nil { + envs := make([dynamic]string, 0, len(g_env), allocator) or_return + defer if err != nil { for env in envs { delete(env, allocator) } - delete(envs, allocator) + delete(envs) } - i: int for k, v in g_env { - defer i += 1 - - envs[i], alloc_err = concatenate({k, "=", v}, allocator) - if alloc_err != nil { - return nil - } + append(&envs, concatenate({k, "=", v}, allocator) or_return) } - return envs + environ = envs[:] + return } diff --git a/core/os/os2/env_windows.odin b/core/os/os2/env_windows.odin index a1e8c969d..3ac26a261 100644 --- a/core/os/os2/env_windows.odin +++ b/core/os/os2/env_windows.odin @@ -36,12 +36,15 @@ _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string return } -_set_env :: proc(key, value: string) -> bool { +_set_env :: proc(key, value: string) -> Error { TEMP_ALLOCATOR_GUARD() - k, _ := win32_utf8_to_wstring(key, temp_allocator()) - v, _ := win32_utf8_to_wstring(value, temp_allocator()) + k := win32_utf8_to_wstring(key, temp_allocator()) or_return + v := win32_utf8_to_wstring(value, temp_allocator()) or_return - return bool(win32.SetEnvironmentVariableW(k, v)) + if !win32.SetEnvironmentVariableW(k, v) { + return _get_platform_error() + } + return nil } _unset_env :: proc(key: string) -> bool { @@ -52,7 +55,7 @@ _unset_env :: proc(key: string) -> bool { _clear_env :: proc() { TEMP_ALLOCATOR_GUARD() - envs := environ(temp_allocator()) + envs, _ := environ(temp_allocator()) for env in envs { for j in 1..>= 4 + } } - i -= 1 - buf[i] = digits[u % b] - return string(buf[i:]) + return string(buf) } diff --git a/core/os/os2/path_openbsd.odin b/core/os/os2/path_openbsd.odin index f56c1a61b..37b5de927 100644 --- a/core/os/os2/path_openbsd.odin +++ b/core/os/os2/path_openbsd.odin @@ -46,7 +46,7 @@ _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err strings.write_string(&buf, "/") strings.write_string(&buf, sarg) - cpath := strings.to_cstring(&buf) + cpath := strings.to_cstring(&buf) or_return if posix.access(cpath, {.X_OK}) == .OK { return real(cpath, allocator) } diff --git a/core/os/os2/path_wasi.odin b/core/os/os2/path_wasi.odin index 2f8a3c8c6..1c4fafa17 100644 --- a/core/os/os2/path_wasi.odin +++ b/core/os/os2/path_wasi.odin @@ -60,16 +60,20 @@ _remove_all :: proc(path: string) -> (err: Error) { dir := open(path) or_return defer close(dir) - iter := read_directory_iterator_create(dir) or_return + iter := read_directory_iterator_create(dir) defer read_directory_iterator_destroy(&iter) for fi in read_directory_iterator(&iter) { + _ = read_directory_iterator_error(&iter) or_break + if fi.type == .Directory { _remove_all(fi.fullpath) or_return } else { remove(fi.fullpath) or_return } } + + _ = read_directory_iterator_error(&iter) or_return } return remove(path) diff --git a/core/os/os2/pipe_posix.odin b/core/os/os2/pipe_posix.odin index edead2ab3..7c07bc068 100644 --- a/core/os/os2/pipe_posix.odin +++ b/core/os/os2/pipe_posix.odin @@ -29,7 +29,7 @@ _pipe :: proc() -> (r, w: ^File, err: Error) { strings.write_string(&rname, "/dev/fd/") strings.write_int(&rname, int(fds[0])) ri.name = strings.to_string(rname) - ri.cname = strings.to_cstring(&rname) + ri.cname = strings.to_cstring(&rname) or_return w = __new_file(fds[1], file_allocator()) wi := (^File_Impl)(w.impl) @@ -39,7 +39,7 @@ _pipe :: proc() -> (r, w: ^File, err: Error) { strings.write_string(&wname, "/dev/fd/") strings.write_int(&wname, int(fds[1])) wi.name = strings.to_string(wname) - wi.cname = strings.to_cstring(&wname) + wi.cname = strings.to_cstring(&wname) or_return return } diff --git a/core/os/os2/process_linux.odin b/core/os/os2/process_linux.odin index 09fd8c255..632bde6ba 100644 --- a/core/os/os2/process_linux.odin +++ b/core/os/os2/process_linux.odin @@ -111,7 +111,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator strings.write_string(&path_builder, "/proc/") strings.write_int(&path_builder, pid) - proc_fd, errno := linux.open(strings.to_cstring(&path_builder), _OPENDIR_FLAGS) + proc_fd, errno := linux.open(strings.to_cstring(&path_builder) or_return, _OPENDIR_FLAGS) if errno != .NONE { err = _get_platform_error(errno) return @@ -169,7 +169,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator strings.write_int(&path_builder, pid) strings.write_string(&path_builder, "/cmdline") - cmdline_bytes, cmdline_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder), temp_allocator()) + cmdline_bytes, cmdline_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder) or_return, temp_allocator()) if cmdline_err != nil || len(cmdline_bytes) == 0 { err = cmdline_err break cmdline_if @@ -190,7 +190,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator strings.write_int(&path_builder, pid) strings.write_string(&path_builder, "/cwd") - cwd, cwd_err = _read_link_cstr(strings.to_cstring(&path_builder), temp_allocator()) // allowed to fail + cwd, cwd_err = _read_link_cstr(strings.to_cstring(&path_builder) or_return, temp_allocator()) // allowed to fail if cwd_err == nil && .Working_Dir in selection { info.working_dir = strings.clone(cwd, allocator) or_return info.fields += {.Working_Dir} @@ -258,7 +258,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator strings.write_int(&path_builder, pid) strings.write_string(&path_builder, "/stat") - proc_stat_bytes, stat_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder), temp_allocator()) + proc_stat_bytes, stat_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder) or_return, temp_allocator()) if stat_err != nil { err = stat_err break stat_if @@ -330,7 +330,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator strings.write_int(&path_builder, pid) strings.write_string(&path_builder, "/environ") - if env_bytes, env_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder), temp_allocator()); env_err == nil { + if env_bytes, env_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder) or_return, temp_allocator()); env_err == nil { env := string(env_bytes) env_list := make([dynamic]string, allocator) or_return @@ -418,7 +418,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { strings.write_byte(&exe_builder, '/') strings.write_string(&exe_builder, executable_name) - exe_path = strings.to_cstring(&exe_builder) + exe_path = strings.to_cstring(&exe_builder) or_return if linux.access(exe_path, linux.X_OK) == .NONE { found = true break @@ -430,7 +430,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { strings.write_string(&exe_builder, "./") strings.write_string(&exe_builder, executable_name) - exe_path = strings.to_cstring(&exe_builder) + exe_path = strings.to_cstring(&exe_builder) or_return if linux.access(exe_path, linux.X_OK) != .NONE { return process, .Not_Exist } @@ -594,7 +594,7 @@ _process_state_update_times :: proc(state: ^Process_State) -> (err: Error) { strings.write_string(&path_builder, "/stat") stat_buf: []u8 - stat_buf, err = _read_entire_pseudo_file(strings.to_cstring(&path_builder), temp_allocator()) + stat_buf, err = _read_entire_pseudo_file(strings.to_cstring(&path_builder) or_return, temp_allocator()) if err != nil { return } diff --git a/core/os/os2/process_posix.odin b/core/os/os2/process_posix.odin index b54374cec..3fa429cbe 100644 --- a/core/os/os2/process_posix.odin +++ b/core/os/os2/process_posix.odin @@ -71,7 +71,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { strings.write_byte(&exe_builder, '/') strings.write_string(&exe_builder, exe_name) - if exe_fd := posix.open(strings.to_cstring(&exe_builder), {.CLOEXEC, .EXEC}); exe_fd == -1 { + if exe_fd := posix.open(strings.to_cstring(&exe_builder) or_return, {.CLOEXEC, .EXEC}); exe_fd == -1 { continue } else { posix.close(exe_fd) @@ -91,7 +91,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { // "hello/./world" is fine right? - if exe_fd := posix.open(strings.to_cstring(&exe_builder), {.CLOEXEC, .EXEC}); exe_fd == -1 { + if exe_fd := posix.open(strings.to_cstring(&exe_builder) or_return, {.CLOEXEC, .EXEC}); exe_fd == -1 { err = .Not_Exist return } else { @@ -102,7 +102,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { strings.builder_reset(&exe_builder) strings.write_string(&exe_builder, exe_name) - if exe_fd := posix.open(strings.to_cstring(&exe_builder), {.CLOEXEC, .EXEC}); exe_fd == -1 { + if exe_fd := posix.open(strings.to_cstring(&exe_builder) or_return, {.CLOEXEC, .EXEC}); exe_fd == -1 { err = .Not_Exist return } else { @@ -181,7 +181,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { if posix.chdir(cwd) != .OK { abort(pipe[WRITE]) } } - res := posix.execve(strings.to_cstring(&exe_builder), raw_data(cmd), env) + res := posix.execve(strings.to_cstring(&exe_builder) or_return, raw_data(cmd), env) assert(res == -1) abort(pipe[WRITE]) diff --git a/core/os/os2/process_windows.odin b/core/os/os2/process_windows.odin index 1984cbfdf..536930ee1 100644 --- a/core/os/os2/process_windows.odin +++ b/core/os/os2/process_windows.odin @@ -427,7 +427,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { command_line_w := win32_utf8_to_wstring(command_line, temp_allocator()) or_return environment := desc.env if desc.env == nil { - environment = environ(temp_allocator()) + environment = environ(temp_allocator()) or_return } environment_block := _build_environment_block(environment, temp_allocator()) environment_block_w := win32_utf8_to_utf16(environment_block, temp_allocator()) or_return diff --git a/core/os/os2/stat.odin b/core/os/os2/stat.odin index b53ebb3ab..d0a5a659d 100644 --- a/core/os/os2/stat.odin +++ b/core/os/os2/stat.odin @@ -24,7 +24,7 @@ File_Info :: struct { @(require_results) file_info_clone :: proc(fi: File_Info, allocator: runtime.Allocator) -> (cloned: File_Info, err: runtime.Allocator_Error) { cloned = fi - cloned.fullpath = strings.clone(fi.fullpath) or_return + cloned.fullpath = strings.clone(fi.fullpath, allocator) or_return cloned.name = filepath.base(cloned.fullpath) return } diff --git a/core/os/os2/temp_file.odin b/core/os/os2/temp_file.odin index 5ca4e1453..e93117f02 100644 --- a/core/os/os2/temp_file.odin +++ b/core/os/os2/temp_file.odin @@ -20,7 +20,7 @@ create_temp_file :: proc(dir, pattern: string) -> (f: ^File, err: Error) { prefix, suffix := _prefix_and_suffix(pattern) or_return prefix = temp_join_path(dir, prefix) or_return - rand_buf: [32]byte + rand_buf: [10]byte name_buf := make([]byte, len(prefix)+len(rand_buf)+len(suffix), temp_allocator()) attempts := 0 @@ -52,7 +52,7 @@ make_directory_temp :: proc(dir, pattern: string, allocator: runtime.Allocator) prefix, suffix := _prefix_and_suffix(pattern) or_return prefix = temp_join_path(dir, prefix) or_return - rand_buf: [32]byte + rand_buf: [10]byte name_buf := make([]byte, len(prefix)+len(rand_buf)+len(suffix), temp_allocator()) attempts := 0 diff --git a/core/os/os2/user.odin b/core/os/os2/user.odin index a0a7a839d..7fcc87bf8 100644 --- a/core/os/os2/user.odin +++ b/core/os/os2/user.odin @@ -49,7 +49,7 @@ user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Erro dir = concatenate({dir, "/.config"}, allocator) or_return } case: // All other UNIX systems - dir = get_env("XDG_CACHE_HOME", allocator) + dir = get_env("XDG_CONFIG_HOME", allocator) if dir == "" { dir = get_env("HOME", temp_allocator()) if dir == "" { diff --git a/core/simd/simd.odin b/core/simd/simd.odin index 01d11dfbe..0bce4e16a 100644 --- a/core/simd/simd.odin +++ b/core/simd/simd.odin @@ -1,182 +1,2366 @@ +/* +The SIMD support package. + +SIMD (Single Instruction Multiple Data), is a CPU hardware feature that +introduce special registers and instructions which operate on multiple units +of data at the same time, which enables faster data processing for +applications with heavy computational workloads. + +In Odin SIMD is exposed via a special kinds of arrays, called the *SIMD +vectors*. The types of SIMD vectors is written as `#simd [N]T`, where N is a +power of two, and T could be any basic type (integers, floats, etc.). The +documentation of this package will call *SIMD vectors* just *vectors*. + +SIMD vectors consist of elements, called *scalar values*, or +*scalars*, each occupying a *lane* of the SIMD vector. In the type declaration, +`N` specifies the amount of lanes, or values, that a vector stores. + +This package implements procedures for working with vectors. +*/ package simd import "base:builtin" import "base:intrinsics" -// IS_EMULATED is true iff the compile-time target lacks hardware support -// for at least 128-bit SIMD. +/* +Check if SIMD is software-emulated on a target platform. + +This value is `false`, when the compile-time target has the hardware support for +at 128-bit (or wider) SIMD. If the compile-time target lacks the hardware support +for 128-bit SIMD, this value is `true`, and all SIMD operations will likely be +emulated. +*/ IS_EMULATED :: true when (ODIN_ARCH == .amd64 || ODIN_ARCH == .i386) && !intrinsics.has_target_feature("sse2") else true when (ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32) && !intrinsics.has_target_feature("neon") else true when (ODIN_ARCH == .wasm64p32 || ODIN_ARCH == .wasm32) && !intrinsics.has_target_feature("simd128") else true when (ODIN_ARCH == .riscv64) && !intrinsics.has_target_feature("v") else false -// 128-bit vector aliases +/* +Vector of 16 `u8` lanes (128 bits). +*/ u8x16 :: #simd[16]u8 + +/* +Vector of 16 `i8` lanes (128 bits). +*/ i8x16 :: #simd[16]i8 + +/* +Vector of 8 `u16` lanes (128 bits). +*/ u16x8 :: #simd[8]u16 + +/* +Vector of 8 `i16` lanes (128 bits). +*/ i16x8 :: #simd[8]i16 + +/* +Vector of 4 `u32` lanes (128 bits). +*/ u32x4 :: #simd[4]u32 + +/* +Vector of 4 `i32` lanes (128 bits). +*/ i32x4 :: #simd[4]i32 + +/* +Vector of 2 `u64` lanes (128 bits). +*/ u64x2 :: #simd[2]u64 + +/* +Vector of 2 `i64` lanes (128 bits). +*/ i64x2 :: #simd[2]i64 + +/* +Vector of 4 `f32` lanes (128 bits). +*/ f32x4 :: #simd[4]f32 + +/* +Vector of 2 `f64` lanes (128 bits). +*/ f64x2 :: #simd[2]f64 +/* +Vector of 16 `bool` lanes (128 bits). +*/ boolx16 :: #simd[16]bool + +/* +Vector of 16 `b8` lanes (128 bits). +*/ b8x16 :: #simd[16]b8 + +/* +Vector of 8 `b16` lanes (128 bits). +*/ b16x8 :: #simd[8]b16 + +/* +Vector of 4 `b32` lanes (128 bits). +*/ b32x4 :: #simd[4]b32 + +/* +Vector of 2 `b64` lanes (128 bits). +*/ b64x2 :: #simd[2]b64 -// 256-bit vector aliases +/* +Vector of 32 `u8` lanes (256 bits). +*/ u8x32 :: #simd[32]u8 + +/* +Vector of 32 `i8` lanes (256 bits). +*/ i8x32 :: #simd[32]i8 + +/* +Vector of 16 `u16` lanes (256 bits). +*/ u16x16 :: #simd[16]u16 + +/* +Vector of 16 `i16` lanes (256 bits). +*/ i16x16 :: #simd[16]i16 + +/* +Vector of 8 `u32` lanes (256 bits). +*/ u32x8 :: #simd[8]u32 + +/* +Vector of 8 `i32` lanes (256 bits). +*/ i32x8 :: #simd[8]i32 + +/* +Vector of 4 `u64` lanes (256 bits). +*/ u64x4 :: #simd[4]u64 + +/* +Vector of 4 `i64` lanes (256 bits). +*/ i64x4 :: #simd[4]i64 + +/* +Vector of 8 `f32` lanes (256 bits). +*/ f32x8 :: #simd[8]f32 + +/* +Vector of 4 `f64` lanes (256 bits). +*/ f64x4 :: #simd[4]f64 +/* +Vector of 32 `bool` lanes (256 bits). +*/ boolx32 :: #simd[32]bool + +/* +Vector of 32 `b8` lanes (256 bits). +*/ b8x32 :: #simd[32]b8 + +/* +Vector of 16 `b16` lanes (256 bits). +*/ b16x16 :: #simd[16]b16 + +/* +Vector of 8 `b32` lanes (256 bits). +*/ b32x8 :: #simd[8]b32 + +/* +Vector of 4 `b64` lanes (256 bits). +*/ b64x4 :: #simd[4]b64 -// 512-bit vector aliases +/* +Vector of 64 `u8` lanes (512 bits). +*/ u8x64 :: #simd[64]u8 + +/* +Vector of 64 `i8` lanes (512 bits). +*/ i8x64 :: #simd[64]i8 + +/* +Vector of 32 `u16` lanes (512 bits). +*/ u16x32 :: #simd[32]u16 + +/* +Vector of 32 `i16` lanes (512 bits). +*/ i16x32 :: #simd[32]i16 + +/* +Vector of 16 `u32` lanes (512 bits). +*/ u32x16 :: #simd[16]u32 + +/* +Vector of 16 `i32` lanes (512 bits). +*/ i32x16 :: #simd[16]i32 + +/* +Vector of 8 `u64` lanes (512 bits). +*/ u64x8 :: #simd[8]u64 + +/* +Vector of 8 `i64` lanes (512 bits). +*/ i64x8 :: #simd[8]i64 + +/* +Vector of 16 `f32` lanes (512 bits). +*/ f32x16 :: #simd[16]f32 + +/* +Vector of 8 `f64` lanes (512 bits). +*/ f64x8 :: #simd[8]f64 +/* +Vector of 64 `bool` lanes (512 bits). +*/ boolx64 :: #simd[64]bool + +/* +Vector of 64 `b8` lanes (512 bits). +*/ b8x64 :: #simd[64]b8 + +/* +Vector of 32 `b16` lanes (512 bits). +*/ b16x32 :: #simd[32]b16 + +/* +Vector of 16 `b32` lanes (512 bits). +*/ b32x16 :: #simd[16]b32 + +/* +Vector of 8 `b64` lanes (512 bits). +*/ b64x8 :: #simd[8]b64 +/* +Add SIMD vectors. +This procedure returns a vector, where each lane holds the sum of the +corresponding `a` and `b` vectors' lanes. + +Inputs: +- `a`: An integer or a float vector. +- `b`: An integer or a float vector. + +Returns: +- A vector that is the sum of two input vectors. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = a[i] + b[i] + } + return res + +Example: + + +-----+-----+-----+-----+ + a: | 0 | 1 | 2 | 3 | + +-----+-----+-----+-----+ + +-----+-----+-----+-----+ + b: | 0 | 1 | 2 | -1 | + +-----+-----+-----+-----+ + res: + +-----+-----+-----+-----+ + | 0 | 2 | 4 | 2 | + +-----+-----+-----+-----+ +*/ add :: intrinsics.simd_add -sub :: intrinsics.simd_sub -mul :: intrinsics.simd_mul -div :: intrinsics.simd_div // floats only -// Keeps Odin's Behaviour -// (x << y) if y <= mask else 0 +/* +Subtract SIMD vectors. + +This procedure returns a vector, where each lane holds the difference between +the corresponding lanes of the vectors `a` and `b`. The lanes from the vector +`b` are subtracted from the corresponding lanes of the vector `a`. + +Inputs: +- `a`: An integer or a float vector to subtract from. +- `b`: An integer or a float vector. + +Returns: +- A vector that is the difference of two vectors, `a` - `b`. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = a[i] - b[i] + } + return res + +Example: + + +-----+-----+-----+-----+ + a: | 2 | 2 | 2 | 2 | + +-----+-----+-----+-----+ + +-----+-----+-----+-----+ + b: | 0 | 1 | 2 | 3 | + +-----+-----+-----+-----+ + res: + +-----+-----+-----+-----+ + | 2 | 1 | 0 | -1 | + +-----+-----+-----+-----+ +*/ +sub :: intrinsics.simd_sub + +/* +Multiply (component-wise) SIMD vectors. + +This procedure returns a vector, where each lane holds the product of the +corresponding lanes of the vectors `a` and `b`. + +Inputs: +- `a`: An integer or a float vector. +- `b`: An integer or a float vector. + +Returns: +- A vector that is the product of two vectors. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = a[i] * b[i] + } + return res + +Example: + + +-----+-----+-----+-----+ + a: | 2 | 2 | 2 | 2 | + +-----+-----+-----+-----+ + +-----+-----+-----+-----+ + b: | 0 | -1 | 2 | -3 | + +-----+-----+-----+-----+ + res: + +-----+-----+-----+-----+ + | 0 | -2 | 4 | -6 | + +-----+-----+-----+-----+ +*/ +mul :: intrinsics.simd_mul + +/* +Divide SIMD vectors. + +This procedure returns a vector, where each lane holds the quotient (result +of division) between the corresponding lanes of the vectors `a` and `b`. Each +lane of the vector `a` is divided by the corresponding lane of the vector `b`. + +This operation performs a standard floating-point division for each lane. + +Inputs: +- `a`: A float vector. +- `b`: A float vector to divide by. + +Returns: +- A vector that is the quotient of two vectors, `a` / `b`. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = a[i] / b[i] + } + return res + +Example: + + +-----+-----+-----+-----+ + a: | 2 | 2 | 2 | 2 | + +-----+-----+-----+-----+ + +-----+-----+-----+-----+ + b: | 0 | -1 | 2 | -3 | + +-----+-----+-----+-----+ + res: + +-----+-----+-----+------+ + | +∞ | -2 | 1 | -2/3 | + +-----+-----+-----+------+ +*/ +div :: intrinsics.simd_div + +/* +Shift left lanes of a vector. + +This procedure returns a vector, such that each lane holds the result of a +shift-left (aka shift-up) operation of the corresponding lane from vector `a` by the shift +amount from the corresponding lane of the vector `b`. + +If the shift amount is greater than the bit-width of a lane, the result is `0` +in the corresponding positions of the result. + +Inputs: +- `a`: An integer vector of values to shift. +- `b`: An unsigned integer vector of the shift amounts. + +Result: +- A vector, where each lane is the lane from `a` shifted left by the amount +specified in the corresponding lane of the vector `b`. + +**Operation**: + + for i in 0 ..< len(res) { + if b[i] < 8*size_of(a[i]) { + res[i] = a[i] << b[i] + } else { + res[i] = 0 + } + } + return res + +Example: + + // An example for a 4-lane 8-bit signed integer vector `a`. + + +-------+-------+-------+-------+ + a: | 0x11 | 0x55 | 0x03 | 0xff | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 2 | 1 | 33 | 1 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+--------+ + | 0x44 | 0xaa | 0 | 0xfe | + +-------+-------+-------+--------+ +*/ shl :: intrinsics.simd_shl + +/* +Shift right lanes of a vector. + +This procedure returns a vector, such that each lane holds the result of a +shift-right (aka shift-down) operation, of lane from the vector `a` by the shift +amount from the corresponding lane of the vector `b`. + +If the shift amount is greater than the bit-width of a lane, the result is `0` +in the corresponding positions of the result. + +If the first vector is a vector of signed integers, the arithmetic shift +operation is performed. Otherwise, if the first vector is a vector of unsigned +integers, a logical shift is performed. + +Inputs: +- `a`: An integer vector of values to shift. +- `b`: An unsigned integer vector of the shift amounts. + +Result: +- A vector, where each lane is the lane from `a` shifted right by the amount +specified in the corresponding lane of the vector `b`. + +**Operation**: + + for i in 0 ..< len(res) { + if b[i] < 8*size_of(a[i]) { + res[i] = a[i] >> b[i] + } else { + res[i] = 0 + } + } + return res + +Example: + + // An example for a 4-lane 8-bit signed integer vector `a`. + + +-------+-------+-------+-------+ + a: | 0x11 | 0x55 | 0x03 | 0xff | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 2 | 1 | 33 | 1 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+--------+ + | 0x04 | 0x2a | 0 | 0xff | + +-------+-------+-------+--------+ +*/ shr :: intrinsics.simd_shr -// Similar to C's Behaviour -// x << (y & mask) +/* +Shift left lanes of a vector (masked). + +This procedure returns a vector, such that each lane holds the result of a +shift-left (aka shift-up) operation, of lane from the vector `a` by the shift +amount from the corresponding lane of the vector `b`. + +The shift amount is wrapped (masked) to the bit-width of the lane. + +Inputs: +- `a`: An integer vector of values to shift. +- `b`: An unsigned integer vector of the shift amounts. + +Result: +- A vector, where each lane is the lane from `a` shifted left by the amount +specified in the corresponding lane of the vector `b`. + +**Operation**: + + for i in 0 ..< len(res) { + mask := 8*size_of(a[i]) - 1 + res[i] = a[i] << (b[i] & mask) + } + return res + +Example: + + // An example for a 4-lane vector `a` of 8-bit signed integers. + + +-------+-------+-------+-------+ + a: | 0x11 | 0x55 | 0x03 | 0xff | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 2 | 1 | 33 | 1 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+--------+ + | 0x44 | 0xaa | 0x06 | 0xfe | + +-------+-------+-------+--------+ +*/ shl_masked :: intrinsics.simd_shl_masked + +/* +Shift right lanes of a vector (masked). + +This procedure returns a vector, such that each lane holds the result of a +shift-right (aka shift-down) operation, of lane from the vector `a` by the shift +amount from the corresponding lane of the vector `b`. + +The shift amount is wrapped (masked) to the bit-width of the lane. + +If the first vector is a vector of signed integers, the arithmetic shift +operation is performed. Otherwise, if the first vector is a vector of unsigned +integers, a logical shift is performed. + +Inputs: +- `a`: An integer vector of values to shift. +- `b`: An unsigned integer vector of the shift amounts. + +Result: +- A vector, where each lane is the lane from `a` shifted right by the amount +specified in the corresponding lane of the vector `b`. + +**Operation**: + + for i in 0 ..< len(res) { + mask := 8*size_of(a[i]) - 1 + res[i] = a[i] >> (b[i] & mask) + } + return res + +Example: + + // An example for a 4-lane vector `a` of 8-bit signed integers. + + +-------+-------+-------+-------+ + a: | 0x11 | 0x55 | 0x03 | 0xff | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 2 | 1 | 33 | 1 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+--------+ + | 0x04 | 0x2a | 0x01 | 0xff | + +-------+-------+-------+--------+ +*/ shr_masked :: intrinsics.simd_shr_masked -// Saturation Arithmetic +/* +Saturated addition of SIMD vectors. + +The *saturated sum* is a just like a normal sum, except the treatment of the +result upon overflow or underflow is different. In saturated operations, the +result is not wrapped to the bit-width of the lane, and instead is kept clamped +between the minimum and the maximum values of the lane type. + +This procedure returns a vector where each lane is the saturated sum of the +corresponding lanes of vectors `a` and `b`. + +Inputs: +- `a`: An integer vector. +- `b`: An integer vector. + +Returns: +- The saturated sum of the two vectors. + +**Operation**: + + for i in 0 ..< len(res) { + switch { + case b[i] >= max(type_of(a[i])) - a[i]: // (overflow of a[i]) + res[i] = max(type_of(a[i])) + case b[i] <= min(type_of(a[i])) - a[i]: // (underflow of a[i]) + res[i] = min(type_of(a[i])) + } else { + res[i] = a[i] + b[i] + } + } + return res + +Example: + + // An example for a 4-lane vector `a` of 8-bit signed integers. + + +-----+-----+-----+-----+ + a: | 0 | 255 | 2 | 3 | + +-----+-----+-----+-----+ + +-----+-----+-----+-----+ + b: | 1 | 3 | 2 | -1 | + +-----+-----+-----+-----+ + res: + +-----+-----+-----+-----+ + | 1 | 255 | 4 | 2 | + +-----+-----+-----+-----+ +*/ saturating_add :: intrinsics.simd_saturating_add + +/* +Saturated subtraction of 2 lanes of vectors. + +The *saturated difference* is a just like a normal difference, except the treatment of the +result upon overflow or underflow is different. In saturated operations, the +result is not wrapped to the bit-width of the lane, and instead is kept clamped +between the minimum and the maximum values of the lane type. + +This procedure returns a vector where each lane is the saturated difference of +the corresponding lanes of vectors `a` and `b`. + +Inputs: +- `a`: An integer vector to subtract from. +- `b`: An integer vector. + +Returns: +- The saturated difference of the two vectors. + +**Operation**: + + for i in 0 ..< len(res) { + switch { + case b[i] >= max(type_of(a[i])) + a[i]: // (overflow of a[i]) + res[i] = max(type_of(a[i])) + case b[i] <= min(type_of(a[i])) + a[i]: // (underflow of a[i]) + res[i] = min(type_of(a[i])) + } else { + res[i] = a[i] - b[i] + } + } + return res + +Example: + + // An example for a 4-lane vector `a` of 8-bit signed integers. + + +-----+-----+-----+-----+ + a: | 0 | 255 | 2 | 3 | + +-----+-----+-----+-----+ + +-----+-----+-----+-----+ + b: | 3 | 3 | 2 | -1 | + +-----+-----+-----+-----+ + res: + +-----+-----+-----+-----+ + | 0 | 252 | 0 | 4 | + +-----+-----+-----+-----+ +*/ saturating_sub :: intrinsics.simd_saturating_sub +/* +Bitwise AND of vectors. + +This procedure returns a vector, such that each lane has the result of a bitwise +AND operation between the corresponding lanes of the vectors `a` and `b`. + +Inputs: +- `a`: An integer or a boolean vector. +- `b`: An integer or a boolean vector. + +Returns: +- A vector that is the result of the bitwise AND operation between two vectors. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = a[i] & b[i] + } + return res + +Example: + + +------+------+------+------+ + a: | 0x11 | 0x33 | 0x55 | 0xaa | + +------+------+------+------+ + +------+------+------+------+ + b: | 0xff | 0xf0 | 0x0f | 0x00 | + +------+------+------+------+ + res: + +------+------+------+------+ + | 0x11 | 0x30 | 0x05 | 0x00 | + +------+------+------+------+ +*/ bit_and :: intrinsics.simd_bit_and + +/* +Bitwise OR of vectors. + +This procedure returns a vector, such that each lane has the result of a bitwise +OR operation between the corresponding lanes of the vectors `a` and `b`. + +Inputs: +- `a`: An integer or a boolean vector. +- `b`: An integer or a boolean vector. + +Returns: +- A vector that is the result of the bitwise OR operation between two vectors. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = a[i] | b[i] + } + return res + +Example: + + +------+------+------+------+ + a: | 0x11 | 0x33 | 0x55 | 0xaa | + +------+------+------+------+ + +------+------+------+------+ + b: | 0xff | 0xf0 | 0x0f | 0x00 | + +------+------+------+------+ + res: + +------+------+------+------+ + | 0xff | 0xf3 | 0x5f | 0xaa | + +------+------+------+------+ +*/ bit_or :: intrinsics.simd_bit_or + +/* +Bitwise XOR of vectors. + +This procedure returns a vector, such that each lane has the result of a bitwise +XOR operation between the corresponding lanes of the vectors `a` and `b`. + +Inputs: +- `a`: An integer or a boolean vector. +- `b`: An integer or a boolean vector. + +Returns: +- A vector that is the result of the bitwise XOR operation between two vectors. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = a[i] ~ b[i] + } + return res + +Example: + + +------+------+------+------+ + a: | 0x11 | 0x33 | 0x55 | 0xaa | + +------+------+------+------+ + +------+------+------+------+ + b: | 0xff | 0xf0 | 0x0f | 0x00 | + +------+------+------+------+ + res: + +------+------+------+------+ + | 0xee | 0xc3 | 0x5a | 0xaa | + +------+------+------+------+ +*/ bit_xor :: intrinsics.simd_bit_xor + +/* +Bitwise AND NOT of vectors. + +This procedure returns a vector, such that each lane has the result of a bitwise +AND NOT operation between the corresponding lanes of the vectors `a` and `b`. + +Inputs: +- `a`: An integer or a boolean vector. +- `b`: An integer or a boolean vector. + +Returns: +- A vector that is the result of the bitwise AND NOT operation between two vectors. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = a[i] &~ b[i] + } + return res + +Example: + + +------+------+------+------+ + a: | 0x11 | 0x33 | 0x55 | 0xaa | + +------+------+------+------+ + +------+------+------+------+ + b: | 0xff | 0xf0 | 0x0f | 0x00 | + +------+------+------+------+ + res: + +------+------+------+------+ + | 0x00 | 0x03 | 0x50 | 0xaa | + +------+------+------+------+ +*/ bit_and_not :: intrinsics.simd_bit_and_not +/* +Negation of a SIMD vector. + +This procedure returns a vector where each lane is the negation of the +corresponding lane in the vector `a`. + +Inputs: +- `a`: An integer or a float vector to negate. + +Returns: +- The negated version of the vector `a`. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = -a[i] + } + return res + +Example: + + +------+------+------+------+ + a: | 0 | 1 | 2 | 3 | + +------+------+------+------+ + res: + +------+------+------+------+ + | 0 | -1 | -2 | -3 | + +------+------+------+------+ +*/ neg :: intrinsics.simd_neg +/* +Absolute value of a SIMD vector. + +This procedure returns a vector where each lane has the absolute value of the +corresponding lane in the vector `a`. + +Inputs: +- `a`: An integer or a float vector to negate + +Returns: +- The absolute value of a vector. + +**Operation**: + + for i in 0 ..< len(res) { + switch { + case a[i] < 0: res[i] = -a[i] + case a[i] > 0: res[i] = a[i] + case a[i] == 0: res[i] = 0 + } + } + return res + +Example: + + +------+------+------+------+ + a: | 0 | -1 | 2 | -3 | + +------+------+------+------+ + res: + +------+------+------+------+ + | 0 | 1 | 2 | 3 | + +------+------+------+------+ +*/ abs :: intrinsics.simd_abs +/* +Minimum of each lane of vectors. + +This procedure returns a vector, such that each lane has the minimum value +between the corresponding lanes in vectors `a` and `b`. + +Inputs: +- `a`: An integer or a float vector. +- `b`: An integer or a float vector. + +Returns: +- A vector containing with minimum values from corresponding lanes of `a` and `b`. + +**Operation**: + + for i in 0 ..< len(res) { + if a[i] < b[i] { + res[i] = a[i] + } else { + res[i] = b[i] + } + } + return res + +Example: + + +-----+-----+-----+-----+ + a: | 0 | 1 | 2 | 3 | + +-----+-----+-----+-----+ + +-----+-----+-----+-----+ + b: | 0 | 2 | 1 | -1 | + +-----+-----+-----+-----+ + res: + +-----+-----+-----+-----+ + | 0 | 1 | 1 | -1 | + +-----+-----+-----+-----+ +*/ min :: intrinsics.simd_min + +/* +Maximum of each lane of vectors. + +This procedure returns a vector, such that each lane has the maximum value +between the corresponding lanes in vectors `a` and `b`. + +Inputs: +- `a`: An integer or a float vector. +- `b`: An integer or a float vector. + +Returns: +- A vector containing with maximum values from corresponding lanes of `a` and `b`. + +**Operation**: + + for i in 0 ..< len(res) { + if a[i] > b[i] { + res[i] = a[i] + } else { + res[i] = b[i] + } + } + return res + +Example: + + +-----+-----+-----+-----+ + a: | 0 | 1 | 2 | 3 | + +-----+-----+-----+-----+ + +-----+-----+-----+-----+ + b: | 0 | 2 | 1 | -1 | + +-----+-----+-----+-----+ + res: + +-----+-----+-----+-----+ + | 0 | 2 | 2 | 3 | + +-----+-----+-----+-----+ +*/ max :: intrinsics.simd_max + +/* +Clamp lanes of vector. + +This procedure returns a vector, where each lane is the result of the +clamping of the lane from the vector `v` between the values in the corresponding +lanes of vectors `min` and `max`. + +Inputs: +- `v`: An integer or a float vector with values to be clamped. +- `min`: An integer or a float vector with minimum bounds. +- `max`: An integer or a float vectoe with maximum bounds. + +Returns: +- A vector containing clamped values in each lane. + +**Operation**: + + for i in 0 ..< len(res) { + val := v[i] + switch { + case val < min: val = min + case val > max: val = max + } + res[i] = val + } + return res + +Example: + + +-------+-------+-------+-------+ + v: | -1 | 0.3 | 1.2 | 1 | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + min: | 0 | 0 | 0 | 0 | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + max: | 1 | 1 | 1 | 1 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+-------+ + | 0 | 0.3 | 1 | 1 | + +-------+-------+-------+-------+ +*/ clamp :: intrinsics.simd_clamp -// Return an unsigned integer of the same size as the input type -// NOT A BOOLEAN -// element-wise: -// false => 0x00...00 -// true => 0xff...ff +/* +Check if lanes of vectors are equal. + +This procedure checks each pair of lanes from vectors `a` and `b` for whether +they are equal, and if they are, the corresponding lane of the result vector +will have a value with all bits set (`0xff..ff`). Otherwise the lane of the +result vector will have the value `0`. + +Inputs: +- `a`: An integer, a float or a boolean vector. +- `b`: An integer, a float or a boolean vector. + +Returns: +- A vector of unsigned integers of the same size as the input vector's lanes, +containing the comparison results for each lane. + +**Operation**: + + for i in 0 ..< len(res) { + if a[i] == b[i] { + res[i] = max(T) + } else { + res[i] = 0 + } + } + return res + +Example: + + +-------+-------+-------+-------+ + a: | 0 | 1 | 2 | 3 | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 0 | 2 | 2 | 2 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+-------+ + | 0xff | 0x00 | 0xff | 0x00 | + +-------+-------+-------+-------+ +*/ lanes_eq :: intrinsics.simd_lanes_eq + +/* +Check if lanes of vectors are not equal. + +This procedure checks each pair of lanes from vectors `a` and `b` for whether +they are not equal, and if they are, the corresponding lane of the result +vector will have a value with all bits set (`0xff..ff`). Otherwise the lane of +the result vector will have the value `0`. + +Inputs: +- `a`: An integer, a float or a boolean vector. +- `b`: An integer, a float or a boolean vector. + +Returns: +- A vector of unsigned integers of the same size as the input vector's lanes, +containing the comparison results for each lane. + +**Operation**: + + for i in 0 ..< len(res) { + if a[i] != b[i] { + res[i] = unsigned(-1) + } else { + res[i] = 0 + } + } + return res + +Example: + + +-------+-------+-------+-------+ + a: | 0 | 1 | 2 | 3 | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 0 | 2 | 2 | 2 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+-------+ + | 0x00 | 0xff | 0x00 | 0xff | + +-------+-------+-------+-------+ +*/ lanes_ne :: intrinsics.simd_lanes_ne + +/* +Check if lanes of a vector are less than another. + +This procedure checks each pair of lanes from vectors `a` and `b` for whether +the lane of `a` is less than the lane of `b`, and if so, the corresponding lane +of the result vector will have a value with all bits set (`0xff..ff`). Otherwise +the lane of the result vector will have the value `0`. + +Inputs: +- `a`: An integer or a float vector. +- `b`: An integer or a float vector. + +Returns: +- A vector of unsigned integers of the same size as the input vector's lanes, +containing the comparison results for each lane. + +**Operation**: + + for i in 0 ..< len(res) { + if a[i] < b[i] { + res[i] = unsigned(-1) + } else { + res[i] = 0 + } + } + return res + +Example: + + +-------+-------+-------+-------+ + a: | 0 | 1 | 2 | 3 | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 0 | 2 | 2 | 2 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+-------+ + r: | 0x00 | 0xff | 0x00 | 0x00 | + +-------+-------+-------+-------+ +*/ lanes_lt :: intrinsics.simd_lanes_lt + +/* +Check if lanes of a vector are less than or equal than another. +SIMD vector. + +This procedure checks each pair of lanes from vectors `a` and `b` for whether the +lane of `a` is less than or equal to the lane of `b`, and if so, the +corresponding lane of the result vector will have a value with all bits set +(`0xff..ff`). Otherwise the lane of the result vector will have the value `0`. + +Inputs: +- `a`: An integer or a float vector. +- `b`: An integer or a float vector. + +Returns: +- A vector of unsigned integers of the same size as the input vector's lanes, +containing the comparison results for each lane. + +**Operation**: + + for i in 0 ..< len(res) { + if a[i] <= b[i] { + res[i] = unsigned(-1) + } else { + res[i] = 0 + } + } + return res + +Example: + + +-------+-------+-------+-------+ + a: | 0 | 1 | 2 | 3 | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 0 | 2 | 2 | 2 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+-------+ + | 0xff | 0xff | 0xff | 0x00 | + +-------+-------+-------+-------+ +*/ lanes_le :: intrinsics.simd_lanes_le + +/* +Check if lanes of a vector are greater than another. +vector. + +This procedure checks each pair of lanes from vectors `a` and `b` for whether the +lane of `a` is greater than to the lane of `b`, and if so, the corresponding +lane of the result vector will have a value with all bits set (`0xff..ff`). +Otherwise the lane of the result vector will have the value `0`. + +Inputs: +- `a`: An integer or a float vector. +- `b`: An integer or a float vector. + +Returns: +- A vector of unsigned integers of the same size as the input vector's lanes, +containing the comparison results for each lane. + +**Operation**: + + for i in 0 ..< len(res) { + if a[i] > b[i] { + res[i] = unsigned(-1) + } else { + res[i] = 0 + } + } + return res + +Example: + + +-------+-------+-------+-------+ + a: | 0 | 1 | 2 | 3 | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 0 | 2 | 2 | 2 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+-------+ + | 0x00 | 0x00 | 0x00 | 0xff | + +-------+-------+-------+-------+ +*/ lanes_gt :: intrinsics.simd_lanes_gt + +/* +Check if lanes of a vector are greater than or equal than another. +SIMD vector. + +This procedure checks each pair of lanes from vectors `a` and `b` for whether the +lane of `a` is greater than or equal to the lane of `b`, and if so, the +corresponding lane of the result vector will have a value with all bits set +(`0xff..ff`). Otherwise the lane of the result vector will have the value `0`. + +Inputs: +- `a`: An integer or a float vector. +- `b`: An integer or a float vector. + +Returns: +- A vector of unsigned integers of the same size as the input vector's lanes, +containing the comparison results for each lane. + +**Operation**: + + for i in 0 ..< len(res) { + if a[i] >= b[i] { + res[i] = unsigned(-1) + } else { + res[i] = 0 + } + } + return res + +Example: + + +-------+-------+-------+-------+ + a: | 0 | 1 | 2 | 3 | + +-------+-------+-------+-------+ + +-------+-------+-------+-------+ + b: | 0 | 2 | 2 | 2 | + +-------+-------+-------+-------+ + res: + +-------+-------+-------+-------+ + | 0xff | 0x00 | 0xff | 0xff | + +-------+-------+-------+-------+ +*/ lanes_ge :: intrinsics.simd_lanes_ge +/* +Perform a gather load into a vector. -// Gather and Scatter intrinsics +A *gather* operation is memory load operation, that loads values from an vector +of addresses into a single value vector. This can be used to achieve the +following results: + +- Accessing every N'th element of an array (strided access) +- Access of elements according to some computed offsets (indexed access). +- Access of elements in a different order (shuffling access). + +When used alongside other SIMD procedures in order to compute the offsets +for the `ptr` and `mask` parameters. + +Inputs: +- `ptr`: A vector of memory locations. Each pointer points to a single value, + of a SIMD vector's lane type that will be loaded into the vector. Pointer + in this vector can be `nil` or any other invalid value, if the corresponding + value in the `mask` parameter is zero. +- `val`: A vector of values that will be used at corresponding positions + of the result vector, if the corresponding memory location has been + masked out. +- `mask`: A vector of booleans or unsigned integers that determines which memory + locations to read from. If the value at an index has the value true + (lowest bit set), the value at that index will be loaded into the result + vector from the corresponding memory location in the `ptr` vector. Otherwise + the value will be loaded from the `val` vector. + +Returns: +- A vector with all values from unmasked indices +loaded from the pointer vector `ptr`, and all values from masked indices loaded +from the value vector `val`. + +**Operation**: + + for i in 0 ..< len(res) { + if mask[i]&1 == 1 { + res[i] = ptr[i]^ + } else { + res[i] = val[i] + } + } + return res + +Example: + + // Example below loads 2 lanes of values from 2 lanes of float vectors, `v1` and + // `v2`. From each of these vectors we're loading the second value, into the first + // and the third position of the result vector. + + // Therefore the `ptrs` argument is initialized such that the first and the third + // value are the addresses of the values that we want to load into the result + // vector, and we'll fill in `nil` for the rest of them. To prevent CPU from + // dereferencing those `nil` addresses we provide the mask that only allows us + // to load valid positions of the `ptrs` array, and the array of defaults which + // will have `127` in each position as the default value. + + v1 := [4] f32 {1, 2, 3, 4}; + v2 := [4] f32 {9, 10,11,12}; + ptrs := #simd [4]rawptr { &v1[1], nil, &v2[1], nil } + mask := #simd [4]bool { true, false, true, false } + defaults := #simd [4]f32 { 0x7f, 0x7f, 0x7f, 0x7f } + res := simd.gather(ptrs, defaults, mask) + fmt.println(res) + +Output: + + <2, 127, 10, 127> + +The first and the third positions came from the `ptrs` array, and the other +2 lanes of from the default vector. The graphic below shows how the values of +the result are decided based on the mask: + + +-------------------------------+ + mask: | 1 | 0 | 1 | 0 | + +-------------------------------+ + | | | `----------------------------. + | | | | + | `---- | ------------------------. | + v v v v + +-------------------------------+ +-------------------+ + ptrs: | &m0 | nil | &m2 | nil | vals: | d0 | d1 | d2 | d3 | + +-------------------------------+ +-------------------+ + | | | | + | .--- | -------------------------' | + | | | ,-------------------------' + v v v v + +-------------------------------+ + result: | m0 | d1 | m2 | d3 | + +-------------------------------+ +*/ gather :: intrinsics.simd_gather + +/* +Perform a scatter store from a vector. + +A *scatter* operation is a memory store operation that stores values from a +vector into multiple memory locations. This operation is effectively the +opposite of the *gather* operation. + +Inputs: +- `ptr`: A vector of memory locations. Each masked location will be written + to with a value from the `val` vector. Pointers in this vector can be `nil` + or any other invalid value if the corresponding value in the `mask` + parameter is zero. +- `val`: A vector of values to write to the memory locations. +- `mask`: A vector of booleans or unsigned integers that decides which lanes + get written to memory. If the value of the mask is `true` (the lowest bit + set), the corresponding lane is written into memory. Otherwise it's not + written into memory. + +**Operation**: + + for i in 0 ..< len(ptr) { + if mask[i]&1 == 1 { + ptr[i]^ = val[i] + } + } + +Example: + + // Example below writes value `127` to the second element of two different + // vectors. The addresses of store destinations are written to the first and the + // third argument of the `ptr` vector, and the `mask` is set accordingly. + + v1 := [4] f32 {1, 2, 3, 4}; + v2 := [4] f32 {5, 6, 7, 8}; + ptrs := #simd [4]rawptr { &v1[1], nil, &v2[1], nil } + mask := #simd [4]bool { true, false, true, false } + vals := #simd [4]f32 { 0x7f, 0x7f, 0x7f, 0x7f } + simd.scatter(ptrs, vals, mask) + fmt.println(v1) + fmt.println(v2) + +Output: + + [1, 127, 3, 4] + [5, 127, 7, 8] + +The graphic below shows how the data gets written into memory. + + + +-------------------+ + mask: | 1 | 0 | 1 | 0 | + +-------------------+ + | | | | + v X v X + +-------------------+ + vals: | d0 | d1 | d2 | d3 | + +-------------------+ + | \ + v v + +-----------------------+ + ptrs: | &m0 | nil | &m2 | nil | + +-----------------------+ +*/ scatter :: intrinsics.simd_scatter + +/* +Perform a masked load into the vector. + +This procedure performs a masked load from memory, into the vector. The `ptr` +argument specifies the base address from which the values of the vector +will be loaded. The mask selects the source for the result vector's lanes. If +the mask for the corresponding lane has the value `true` (lowest bit set), the +result lane is loaded from memory. Otherwise the result lane is loaded from the +corresponding lane of the `val` vector. + +Inputs: +- `ptr`: The address of the vector values to load. Masked-off values are not + accessed. +- `val`: The vector of values that will be loaded into the masked slots of the + result vector. +- `mask`: The mask that selects where to load the values from. + +Returns: +- The loaded vector. The lanes for which the mask was set are loaded from +memory, and the other lanes are loaded from the `val` vector. + +**Operation**: + + for i in 0 ..< len(res) { + if mask[i]&1 == 1 { + res[i] = ptr[i] + } else { + res[i] = vals[i] + } + } + return res + +Example: + + // The following code loads two values from the `src` vector, the first and the + // third value (selected by the mask). The masked-off values are given the value + // of 127 (`0x7f`). + + src := [4] f32 {1, 2, 3, 4}; + mask := #simd [4]bool { true, false, true, false } + vals := #simd [4]f32 { 0x7f, 0x7f, 0x7f, 0x7f } + res := simd.masked_load(&src, vals, mask) + fmt.println(res) + +Output: + + <1, 127, 3, 127> + +The graphic below demonstrates the flow of lanes. + + +-------------------------------+ + mask: | 1 | 0 | 1 | 0 | + +-------------------------------+ + | | | `----------------------------. + | | | | + | `---- | ------------------------. | + ptr v v v v + +---->+-------------------------------+ +-------------------+ + | v1 | v2 | v3 | v4 | vals: | d0 | d1 | d2 | d3 | + +-------------------------------+ +-------------------+ + | | | | + | .--- | -------------------------' | + | | | ,-------------------------' + v v v v + +-------------------------------+ + result: | v1 | d1 | v3 | d3 | + +-------------------------------+ +*/ masked_load :: intrinsics.simd_masked_load + +/* +Perform a masked store to memory. + +This procedure performs a masked store from a vector `val`, into memory at +address `ptr`, with the `mask` deciding which lanes are going to be stored, +and which aren't. If the mask at a corresponding lane has the value `true` +(lowest bit set), the lane is stored into memory. Otherwise the lane is not +stored into memory. + +Inputs: +- `ptr`: The base address of the store. +- `val`: The vector to store. +- `mask`: The mask, selecting which lanes of the vector to store into memory. + +**Operation**: + + for i in 0 ..< len(val) { + if mask[i]&1 == 1 { + ptr[i] = val + } + } + +Example: + + // Example below stores the value 127 into the first and the third slot of the + // vector `v`. + + v := [4] f32 {1, 2, 3, 4}; + mask := #simd [4]bool { true, false, true, false } + vals := #simd [4]f32 { 0x7f, 0x7f, 0x7f, 0x7f } + simd.masked_store(&v, vals, mask) + fmt.println(v) + +Output: + + [127, 2, 127, 4] + +The graphic below shows the flow of lanes: + + +-------------------+ + mask: | 1 | 0 | 1 | 0 | + +-------------------+ + | | | | + v X v X + +-------------------+ + vals: | v0 | v1 | v2 | v3 | + +-------------------+ + | \ + ptr v v + +--->+-----------------------+ + | v0 | ... | v2 | ... | + +-----------------------+ +*/ masked_store :: intrinsics.simd_masked_store + +/* +Load consecutive scalar values and expand into a vector. + +This procedure loads a number of consecutive scalar values from an address, +specified by the `ptr` parameter, and stores them in a result vector, according +to the mask. The number of values read from memory is the number of set bits +in the mask. The lanes for which the mask has the value `true` get the next +consecutive value from memory, otherwise if the mask is `false` for the +lane, its value is filled from the corresponding lane of the `val` parameter. + +This procedure acts like `masked_store`, except the values from memory are +read consecutively, and not according to the lanes. The memory values are read +and assigned to the result vector's masked lanes in order of increasing +addresses. + +Inputs: +- `ptr`: The pointer to the memory to read from. +- `vals`: The default values for masked-off entries. +- `mask`: The mask that determines which lanes get consecutive memory values. + +Returns: +- The result vector, holding masked memory values unmasked default values. + +**Operation**: + + mem_idx := 0 + for i in 0 ..< len(mask) { + if mask[i]&1 == 1 { + res[i] = ptr[mem_idx] + mem_idx += 1 + } else { + res[i] = val[i] + } + } + return res + +Example: + + // The example below loads two values from memory of the vector `v`. Two values in + // the mask are set to `true`, meaning only two memory items will be loaded into + // the result vector. The mask is set to `true` in the first and the third + // position, which specifies that the first memory item will be read into the + // first lane of the result vector, and the second memory item will be read into + // the third lane of the result vector. All the other lanes of the result vector + // will be initialized to the default value `127`. + + v := [2] f64 {1, 2}; + mask := #simd [4]bool { true, false, true, false } + vals := #simd [4]f64 { 0x7f, 0x7f, 0x7f, 0x7f } + res := simd.masked_expand_load(&v, vals, mask) + fmt.println(res) + +Output: + + <1, 127, 2, 127> + +Graphical representation of the operation: + + + ptr --->+-----------+----- + | m0 | m1 | ... + +-----------+----- + | `--. + v v + +-------------------+ +-------------------+ + mask: | 1 | 0 | 1 | 0 | vals: | v0 | v1 | v2 | v3 | + +-------------------+ +-------------------+ + | | | | + | .-- | -----------------------' | + | | | ,----------------------------' + v v v v + +-------------------+ + result: | m0 | v1 | m1 | v3 | + +-------------------+ +*/ masked_expand_load :: intrinsics.simd_masked_expand_load + +/* +Store masked values to consecutive memory locations. + +This procedure stores values from masked lanes of a vector `val` consecutively +into memory. This operation is the opposite of `masked_expand_load`. The number +of items stored into memory is the number of set bits in the mask. If the value +in a lane of a mask is `true`, that lane is stored into memory. Otherwise +nothing is stored. + +Inputs: +- `ptr`: The pointer to the memory of a store. +- `val`: The vector to store into memory. +- `mask`: The mask that selects which values to store into memory. + +**Operation**: + + mem_idx := 0 + for i in 0 ..< len(mask) { + if mask[i]&1 == 1 { + ptr[mem_idx] = val[i] + mem_idx += 1 + } + } + +Example: + + // The code below fills the vector `v` with two values from a 4-element SIMD + // vector, the first and the third value. The items in the mask are set to `true` + // in those lanes. + + v := [2] f64 { }; + mask := #simd [4]bool { true, false, true, false } + vals := #simd [4]f64 { 1, 2, 3, 4 } + simd.masked_compress_store(&v, vals, mask) + fmt.println(v) + +Output: + + [1, 3] + +Graphical representation of the operation: + + +-------------------+ + mask: | 1 | 0 | 1 | 0 | + +-------------------+ + | | + v v + +-------------------+ + vals: | v0 | v1 | v2 | v3 | + +-------------------+ + | ,--' + ptr v v + +--->+----------------- + | v0 | v2 | ... + +----------------- +*/ masked_compress_store :: intrinsics.simd_masked_compress_store -// extract :: proc(a: #simd[N]T, idx: uint) -> T +/* +Extract scalar from a vector's lane. + +This procedure returns the scalar from the lane at the specified index of the +vector. + +Inputs: +- `a`: The vector to extract from. +- `idx`: The lane index. + +Returns: +- The value of the lane at the specified index. + +**Operation**: + + return a[idx] +*/ extract :: intrinsics.simd_extract -// replace :: proc(a: #simd[N]T, idx: uint, elem: T) -> #simd[N]T + +/* +Replace the value in a vector's lane. + +This procedure places a scalar value at the lane corresponding to the given index of +the vector. + +Inputs: +- `a`: The vector to replace a lane in. +- `idx`: The lane index. +- `elem`: The scalar to place. + +Returns: +- Vector with the specified lane replaced. + +**Operation**: + + a[idx] = elem +*/ replace :: intrinsics.simd_replace +/* +Reduce a vector to a scalar by adding up all the lanes. + +This procedure returns a scalar that is the ordered sum of all lanes. The +ordered sum may be important for accounting for precision errors in +floating-point computation, as floating-point addition is not associative, +that is `(a+b)+c` may not be equal to `a+(b+c)`. + +Inputs: +- `a`: The vector to reduce. + +Result: +- Sum of all lanes, as a scalar. + +**Operation**: + + res := 0 + for i in 0 ..< len(a) { + res += a[i] + } +*/ reduce_add_ordered :: intrinsics.simd_reduce_add_ordered + +/* +Reduce a vector to a scalar by multiplying all the lanes. + +This procedure returns a scalar that is the ordered product of all lanes. +The ordered product may be important for accounting for precision errors in +floating-point computation, as floating-point multiplication is not associative, +that is `(a*b)*c` may not be equal to `a*(b*c)`. + +Inputs: +- `a`: The vector to reduce. + +Result: +- Product of all lanes, as a scalar. + +**Operation**: + + res := 1 + for i in 0 ..< len(a) { + res *= a[i] + } +*/ reduce_mul_ordered :: intrinsics.simd_reduce_mul_ordered -reduce_min :: intrinsics.simd_reduce_min -reduce_max :: intrinsics.simd_reduce_max -reduce_and :: intrinsics.simd_reduce_and -reduce_or :: intrinsics.simd_reduce_or -reduce_xor :: intrinsics.simd_reduce_xor -reduce_any :: intrinsics.simd_reduce_any -reduce_all :: intrinsics.simd_reduce_all +/* +Reduce a vector to a scalar by finding the minimum value between all of the lanes. -// swizzle :: proc(a: #simd[N]T, indices: ..int) -> #simd[len(indices)]T +This procedure returns a scalar that is the minimum value of all the lanes +in a vector. + +Inputs: +- `a`: The vector to reduce. + +Result: +- Minimum value of all lanes, as a scalar. + +**Operation**: + + res := 0 + for i in 0 ..< len(a) { + res = min(res, a[i]) + } +*/ +reduce_min :: intrinsics.simd_reduce_min + +/* +Reduce a vector to a scalar by finding the maximum value between all of the lanes. + +This procedure returns a scalar that is the maximum value of all the lanes +in a vector. + +Inputs: +- `a`: The vector to reduce. + +Result: +- Maximum value of all lanes, as a scalar. + +**Operation**: + + res := 0 + for i in 0 ..< len(a) { + res = max(res, a[i]) + } +*/ +reduce_max :: intrinsics.simd_reduce_max + +/* +Reduce a vector to a scalar by performing bitwise AND of all of the lanes. + +This procedure returns a scalar that is the result of the bitwise AND operation +between all of the lanes in a vector. + +Inputs: +- `a`: The vector to reduce. + +Result: +- Bitwise AND of all lanes, as a scalar. + +**Operation**: + + res := 0 + for i in 0 ..< len(a) { + res &= a[i] + } +*/ +reduce_and :: intrinsics.simd_reduce_and + +/* +Reduce a vector to a scalar by performing bitwise OR of all of the lanes. + +This procedure returns a scalar that is the result of the bitwise OR operation +between all of the lanes in a vector. + +Inputs: +- `a`: The vector to reduce. + +Result: +- Bitwise OR of all lanes, as a scalar. + +**Operation**: + + res := 0 + for i in 0 ..< len(a) { + res |= a[i] + } +*/ +reduce_or :: intrinsics.simd_reduce_or + +/* +Reduce SIMD vector to a scalar by performing bitwise XOR of all of the lanes. + +This procedure returns a scalar that is the result of the bitwise XOR operation +between all of the lanes in a vector. + +Inputs: +- `a`: The vector to reduce. + +Result: +- Bitwise XOR of all lanes, as a scalar. + +**Operation**: + + res := 0 + for i in 0 ..< len(a) { + res ~= a[i] + } +*/ +reduce_xor :: intrinsics.simd_reduce_xor + +/* +Reduce SIMD vector to a scalar by performing bitwise OR of all of the lanes. + +This procedure returns a scalar that is the result of the bitwise OR operation +between all of the lanes in a vector. + +Inputs: +- `a`: The vector to reduce. + +Result: +- Bitwise OR of all lanes, as a scalar. + +**Operation**: + + res := 0 + for i in 0 ..< len(a) { + res |= a[i] + } +*/ +reduce_any :: intrinsics.simd_reduce_any + +/* +Reduce SIMD vector to a scalar by performing bitwise AND of all of the lanes. + +This procedure returns a scalar that is the result of the bitwise AND operation +between all of the lanes in a vector. + +Inputs: +- `a`: The vector to reduce. + +Result: +- Bitwise AND of all lanes, as a scalar. + +**Operation**: + + res := 0 + for i in 0 ..< len(a) { + res &= a[i] + } +*/ +reduce_all :: intrinsics.simd_reduce_all + +/* +Reorder the lanes of a SIMD vector. + +This procedure reorders the lanes of a vector, according to the provided +indices. The number of indices correspond to the number of lanes in the +result vector and must be the same as the number of lanes of the input vector. +Each index specifies, the lane of the scalar from the input vector, which +will be written at the corresponding position of the result vector. + +Inputs: +- `x`: The input vector. +- `indices`: The indices of lanes to write to the result vector. + +Result: +- Swizzled input vector. + +**Operation**: + + res = {} + for i in 0 ..< len(indices) { + res[i] = x[indices[i]] + } + return res + +Example: + + // The example below shows how the indices are used to determine which lanes of the + // input vector get written into the result vector. + + x := #simd [4]f32 { 1.5, 2.5, 3.5, 4.5 } + res := simd.swizzle(x, 0, 3, 1, 1) + fmt.println("res") + +Output: + + [ 1.5, 3.5, 2.5, 2.5 ] + +The graphical representation of the operation is as follows. The `idx` vector in +the picture represents the `indices` parameter: + + 0 1 2 3 + +-----+-----+-----+-----+ + x: | 1.5 | 2.5 | 3.5 | 4.5 | + +-----+-----+-----+-----+ + ^ ^ ^ + | | | + | '----. | + | .---- | ---' + | | | + | | +------. + +-----+-----+-----+-----+ + idx: | 0 | 3 | 1 | 1 | + +-----+-----+-----+-----+ + ^ ^ ^ ^ + | | | | + +-----+-----+-----+-----+ + res: | 1.5 | 3.5 | 2.5 | 2.5 | + +-----+-----+-----+-----+ +*/ swizzle :: builtin.swizzle -// shuffle :: proc(a, b: #simd[N]T, indices: #simd[max 2*N]u32) -> #simd[len(indices)]T +/* +Extract the set of most-significant bits of a SIMD vector. + +This procedure checks the the most-significant bit (MSB) for each lane of vector +and returns the numbers of lanes with the most-significant bit set. This procedure +can be used in conjuction with `lanes_eq` (and other similar procedures) to +count the number of matched lanes by computing the cardinality of the resulting +set. + +Inputs: +- `a`: An input vector. + +Result: +- A bitset of integers, corresponding to the indexes of the lanes, whose MSBs + are set. + +**Operation**: + + bits_per_lane = 8*size_of(a[0]) + res = bit_set {} + for i in 0 ..< len(a) { + if a[i] & 1<<(bits_per_lane-1) != 0 { + res |= i + } + } + return res + +Example: + + // Since lanes 0, 1, 4, 7 contain negative numbers, the most significant + // bits for them will be set. + v := #simd [8]i32 { -1, -2, +3, +4, -5, +6, +7, -8 } + fmt.println(simd.extract_msbs(v)) + +Output: + + bit_set[0..=7]{0, 1, 4, 7} +*/ +extract_msbs :: intrinsics.simd_extract_msbs + +/* +Extract the set of least-significant bits of a SIMD vector. + +This procedure checks the the least-significant bit (LSB) for each lane of vector +and returns the numbers of lanes with the least-significant bit set. This procedure +can be used in conjuction with `lanes_eq` (and other similar procedures) to +count the number of matched lanes by computing the cardinality of the resulting +set. + +Inputs: +- `a`: An input vector. + +Result: +- A bitset of integers, corresponding to the indexes of the lanes, whose LSBs + are set. + +**Operation**: + + res = bit_set {} + for i in 0 ..< len(a) { + if a[i] & 1 != 0 { + res |= i + } + } + return res + +Example: + + // Since lanes 0, 2, 4, 6 contain odd integers, the least significant bits + // for these lanes are set. + v := #simd [8]i32 { -1, -2, +3, +4, -5, +6, +7, -8 } + fmt.println(simd.extract_lsbs(v)) + +Output: + + bit_set[0..=7]{0, 2, 4, 6} +*/ +extract_lsbs :: intrinsics.simd_extract_lsbs + +/* +Reorder the lanes of two SIMD vectors. + +This procedure returns a vector, containing the scalars from the lanes of two +vectors, according to the provided indices vector. Each index in the indices +vector specifies, the lane of the scalar from one of the two input vectors, +which will be written at the corresponding position of the result vector. If +the index is within bounds 0 ..< len(A), it corresponds to the indices of the +first input vector. Otherwise the index corresponds to the indices of the second +input vector. + +Inputs: +- `a`: The first input vector. +- `b`: The second input vector. +- `indices`: The indices. + +Result: +- Input vectors, shuffled according to the indices. + +**Operation**: + + res = {} + for i in 0 ..< len(indices) { + idx = indices[i]; + if idx < len(a) { + res[i] = a[idx] + } else { + res[i] = b[idx] + } + } + return res + +Example: + + // The example below shows how the indices are used to determine lanes of the + // input vector that are shuffled into the result vector. + + a := #simd [4]f32 { 1, 2, 3, 4 } + b := #simd [4]f32 { 5, 6, 7, 8 } + res := simd.shuffle(a, b, 0, 4, 2, 5) + fmt.println("res") + +Output: + + [ 1, 5, 3, 6 ] + +The graphical representation of the operation is as follows. The `idx` vector in +the picture represents the `indices` parameter: + + 0 1 2 3 4 5 6 7 + +-----+-----+-----+-----+ +-----+-----+-----+-----+ + a: | 1 | 2 | 3 | 4 | b: | 5 | 6 | 7 | 8 | + +-----+-----+-----+-----+ +-----+-----+-----+-----+ + ^ ^ ^ ^ + | | | | + | | | | + | .--- | ----------------' | + | | | .-----------------' + +-----+-----+-----+-----+ + idx: | 0 | 4 | 2 | 5 | + +-----+-----+-----+-----+ + ^ ^ ^ ^ + | | | | + +-----+-----+-----+-----+ + res: | 1 | 5 | 3 | 6 | + +-----+-----+-----+-----+ +*/ shuffle :: intrinsics.simd_shuffle -// select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T +/* +Select values from one of the two vectors. + +This procedure returns a vector, which has, on each lane a value from one of the +corresponding lanes in one of the two input vectors based on the `cond` +parameter. On each lane, if the value of the `cond` parameter is `true` (or +non-zero), the result lane will have a value from the `true` input vector, +otherwise the result lane will have a value from the `false` input vector. + +Inputs: +- `cond`: The condition vector. +- `true`: The first input vector. +- `false`: The second input vector. + +Result: +- The result of selecting values from the two input vectors. + +**Operation**: + + res = {} + for i in 0 ..< len(cond) { + if cond[i] { + res[i] = true[i] + } else { + res[i] = false[i] + } + } + return res + +Example: + + // The following example selects values from the two input vectors, `a` and `b` + // into a single vector. + a := #simd [4] f64 { 1,2,3,4 } + b := #simd [4] f64 { 5,6,7,8 } + cond := #simd[4] int { 1, 0, 1, 0 } + fmt.println(simd.select(cond,a,b)) + +Output: + + [ 1, 6, 3, 8 ] + +Graphically, the operation looks as follows. The `t` and `f` represent the +`true` and `false` vectors respectively: + + 0 1 2 3 0 1 2 3 + +-----+-----+-----+-----+ +-----+-----+-----+-----+ + t: | 1 | 2 | 3 | 4 | f: | 5 | 6 | 7 | 8 | + +-----+-----+-----+-----+ +-----+-----+-----+-----+ + ^ ^ ^ ^ + | | | | + | | | | + | .--- | ----------------------' | + | | | .-----------------------------' + +-----+-----+-----+-----+ + cond: | 1 | 0 | 1 | 0 | + +-----+-----+-----+-----+ + ^ ^ ^ ^ + | | | | + +-----+-----+-----+-----+ + res: | 1 | 5 | 3 | 6 | + +-----+-----+-----+-----+ +*/ select :: intrinsics.simd_select - +/* +Compute the square root of each lane in a SIMD vector. +*/ sqrt :: intrinsics.sqrt + +/* +Ceil each lane in a SIMD vector. +*/ ceil :: intrinsics.simd_ceil + +/* +Floor each lane in a SIMD vector. +*/ floor :: intrinsics.simd_floor + +/* +Truncate each lane in a SIMD vector. +*/ trunc :: intrinsics.simd_trunc + +/* +Compute the nearest integer of each lane in a SIMD vector. +*/ nearest :: intrinsics.simd_nearest +/* +Transmute a SIMD vector into an integer vector. +*/ to_bits :: intrinsics.simd_to_bits +/* +Reverse the lanes of a SIMD vector. + +This procedure reverses the lanes of a vector, putting last lane in the +first spot, etc. This procedure is equivalent to the following call (for +4-element vectors): + + swizzle(a, 3, 2, 1, 0) +*/ lanes_reverse :: intrinsics.simd_lanes_reverse -lanes_rotate_left :: intrinsics.simd_lanes_rotate_left +/* +Rotate the lanes of a SIMD vector left. + +This procedure rotates the lanes of a vector, putting the first lane of the +last spot, second lane in the first spot, third lane in the second spot, etc. +For 4-element vectors, this procedure is equvalent to the following: + + swizzle(a, 1, 2, 3, 0) +*/ +lanes_rotate_left :: intrinsics.simd_lanes_rotate_left + +/* +Rotate the lanes of a SIMD vector right. + +This procedure rotates the lanes of a SIMD vector, putting the first lane of the +second spot, second lane in the third spot, etc. For 4-element vectors, this +procedure is equvalent to the following: + + swizzle(a, 3, 0, 1, 2) +*/ lanes_rotate_right :: intrinsics.simd_lanes_rotate_right -count_ones :: intrinsics.count_ones -count_zeros :: intrinsics.count_zeros +/* +Count the number of set bits in each lane of a SIMD vector. +*/ +count_ones :: intrinsics.count_ones + +/* +Count the number of unset bits in each lane of a SIMD vector. +*/ +count_zeros :: intrinsics.count_zeros + +/* +Count the number of trailing unset bits in each lane of a SIMD vector. +*/ count_trailing_zeros :: intrinsics.count_trailing_zeros -count_leading_zeros :: intrinsics.count_leading_zeros -reverse_bits :: intrinsics.reverse_bits +/* +Count the number of leading unset bits in each lane of a SIMD vector. +*/ +count_leading_zeros :: intrinsics.count_leading_zeros + +/* +Reverse the bit pattern of a SIMD vector. +*/ +reverse_bits :: intrinsics.reverse_bits + +/* +Perform a FMA (Fused multiply-add) operation on each lane of SIMD vectors. + +A fused multiply-add is a ternary operation that for three operands, `a`, `b` +and `c` performs the operation `a*b+c`. This operation is a hardware feature +that allows to minimize floating-point error and allow for faster computation. + +This procedure performs a FMA operation on each lane of the SIMD vectors. + +Inputs: +- `a`: The multiplier +- `b`: The multiplicand +- `c`: The addend + +Returns: +- `a*b+c` + +**Operation** + + res := 0 + for i in 0 ..< len(a) { + res[i] = fma(a[i], b[i], c[i]) + } + return res +*/ fused_mul_add :: intrinsics.fused_mul_add -fma :: intrinsics.fused_mul_add +/* +Perform a FMA (Fused multiply-add) operation on each lane of SIMD vectors. + +A fused multiply-add is a ternary operation that for three operands, `a`, `b` +and `c` performs the operation `a*b+c`. This operation is a hardware feature +that allows to minimize floating-point error and allow for faster computation. + +This procedure performs a FMA operation on each lane of the SIMD vectors. + +Inputs: +- `a`: The multiplier. +- `b`: The multiplicand. +- `c`: The addend. + +Returns: +- `a*b+c` + +**Operation** + + res := 0 + for i in 0 ..< len(a) { + res[i] = fma(a[i], b[i], c[i]) + } + return res +*/ +fma :: intrinsics.fused_mul_add + +/* +Convert pointer to SIMD vector to an array pointer. +*/ to_array_ptr :: #force_inline proc "contextless" (v: ^#simd[$LANES]$E) -> ^[LANES]E { return (^[LANES]E)(v) } + +/* +Convert SIMD vector to an array. +*/ to_array :: #force_inline proc "contextless" (v: #simd[$LANES]$E) -> [LANES]E { return transmute([LANES]E)(v) } + +/* +Convert array to SIMD vector. +*/ from_array :: #force_inline proc "contextless" (v: $A/[$LANES]$E) -> #simd[LANES]E { return transmute(#simd[LANES]E)v } +/* +Convert slice to SIMD vector. +*/ from_slice :: proc($T: typeid/#simd[$LANES]$E, slice: []E) -> T { assert(len(slice) >= LANES, "slice length must be a least the number of lanes") array: [LANES]E @@ -186,10 +2370,36 @@ from_slice :: proc($T: typeid/#simd[$LANES]$E, slice: []E) -> T { return transmute(T)array } +/* +Perform binary not operation on a SIMD vector. + +This procedure returns a vector where each lane is the result of the binary +NOT operation of the corresponding lane in the vector `a`. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = ~a[i] + } + return res + +Example: + + +------+------+------+------+ + a: | 0x00 | 0x50 | 0x80 | 0xff | + +------+------+------+------+ + res: + +------+------+------+------+ + | 0xff | 0xaf | 0x7f | 0x00 | + +------+------+------+------+ +*/ bit_not :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) { return xor(v, T(~E(0))) } +/* +Copy the signs from lanes of one SIMD vector into another SIMD vector. +*/ copysign :: #force_inline proc "contextless" (v, sign: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) { neg_zero := to_bits(T(-0.0)) sign_bit := to_bits(sign) & neg_zero @@ -197,11 +2407,48 @@ copysign :: #force_inline proc "contextless" (v, sign: $T/#simd[$LANES]$E) -> T return transmute(T)(sign_bit|magnitude) } +/* +Return signs of SIMD lanes. + +This procedure returns a vector, each lane of which contains either +1.0 or +-1.0 depending on the sign of the value in the corresponding lane of the +input vector. If the lane of the input vector has NaN, then the result vector +will contain this NaN value as-is. +*/ signum :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) { is_nan := lanes_ne(v, v) return select(is_nan, v, copysign(T(1), v)) } +/* +Calculate reciprocals of SIMD lanes. + +This procedure returns a vector where each lane is the reciprocal of the +corresponding lane in the vector `a`. + +Inputs: +- `a`: An integer or a float vector to negate. + +Returns: +- Negated vector. + +**Operation**: + + for i in 0 ..< len(res) { + res[i] = 1.0 / a[i] + } + return res + +Example: + + +------+------+------+------+ + a: | 2 | 1 | 3 | 5 | + +------+------+------+------+ + res: + +------+------+------+------+ + | 0.5 | 1 | 0.33 | 0.2 | + +------+------+------+------+ +*/ recip :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) { return T(1) / v } diff --git a/core/slice/slice.odin b/core/slice/slice.odin index 66166bddb..c328fd267 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -898,8 +898,7 @@ bitset_to_enum_slice_with_buffer :: proc(buf: []$E, bs: $T) -> (slice: []E) wher // sl := slice.bitset_to_enum_slice(bs) @(require_results) bitset_to_enum_slice_with_make :: proc(bs: $T, $E: typeid, allocator := context.allocator) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { - ones := intrinsics.count_ones(transmute(E)bs) - buf := make([]E, int(ones), allocator) + buf := make([]E, card(bs), allocator) return bitset_to_enum_slice(buf, bs) } diff --git a/core/strings/builder.odin b/core/strings/builder.odin index 97a615990..e5a88527a 100644 --- a/core/strings/builder.odin +++ b/core/strings/builder.odin @@ -288,18 +288,41 @@ to_string :: proc(b: Builder) -> (res: string) { /* Appends a trailing null byte after the end of the current Builder byte buffer and then casts it to a cstring +NOTE: This procedure will not check if the backing buffer has enough space to include the extra null byte. + Inputs: - b: A pointer to builder Returns: - res: A cstring of the Builder's buffer */ -to_cstring :: proc(b: ^Builder) -> (res: cstring) { +unsafe_to_cstring :: proc(b: ^Builder) -> (res: cstring) { append(&b.buf, 0) pop(&b.buf) return cstring(raw_data(b.buf)) } /* +Appends a trailing null byte after the end of the current Builder byte buffer and then casts it to a cstring + +Inputs: +- b: A pointer to builder + +Returns: +- res: A cstring of the Builder's buffer upon success +- err: An optional allocator error if one occured, `nil` otherwise +*/ +to_cstring :: proc(b: ^Builder) -> (res: cstring, err: mem.Allocator_Error) { + n := append(&b.buf, 0) or_return + if n != 1 { + return nil, .Out_Of_Memory + } + pop(&b.buf) + #no_bounds_check { + assert(b.buf[len(b.buf)] == 0) + } + return cstring(raw_data(b.buf)), nil +} +/* Returns the length of the Builder's buffer, in bytes Inputs: diff --git a/core/strings/strings.odin b/core/strings/strings.odin index e99a1bfb4..52230f572 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -25,7 +25,7 @@ Returns: clone :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { c := make([]byte, len(s), allocator, loc) or_return copy(c, s) - return string(c[:len(s)]), nil + return string(c), nil } /* Clones a string safely (returns early with an allocation error on failure) diff --git a/core/sys/darwin/Foundation/NSSavePanel.odin b/core/sys/darwin/Foundation/NSSavePanel.odin index f026b482d..d40b3ecd5 100644 --- a/core/sys/darwin/Foundation/NSSavePanel.odin +++ b/core/sys/darwin/Foundation/NSSavePanel.odin @@ -14,6 +14,6 @@ SavePanel_savePanel :: proc "c" () -> ^SavePanel { } @(objc_type=SavePanel, objc_name="URL") -SavePanel_URL :: proc "c" (self: ^SavePanel) -> ^Array { - return msgSend(^Array, self, "URL") +SavePanel_URL :: proc "c" (self: ^SavePanel) -> ^URL { + return msgSend(^URL, self, "URL") } diff --git a/core/sys/orca/macros.odin b/core/sys/orca/macros.odin index d6a1a0f82..12adfdb91 100644 --- a/core/sys/orca/macros.odin +++ b/core/sys/orca/macros.odin @@ -37,12 +37,7 @@ log_info :: proc "contextless" (msg: cstring, loc := #caller_location) { } abort :: proc "contextless" (msg: cstring, loc := #caller_location) { - abort_ext( - cstring(raw_data(loc.procedure)), - cstring(raw_data(loc.file_path)), - loc.line, - msg, - ) + abort_ext(cstring(raw_data(loc.procedure)), cstring(raw_data(loc.file_path)), loc.line, msg) } //////////////////////////////////////////////////////////////////////////////// @@ -55,7 +50,12 @@ list_entry :: proc "contextless" (elt: ^list_elt, $T: typeid, $member: string) - } // Get the next entry in a list. -list_next_entry :: proc "contextless" (list: ^list, elt: ^list_elt, $T: typeid, $member: string) -> ^T { +list_next_entry :: proc "contextless" ( + list: ^list, + elt: ^list_elt, + $T: typeid, + $member: string, +) -> ^T { if elt.next != list.last { return list_entry(elt.next, T, member) } @@ -64,7 +64,12 @@ list_next_entry :: proc "contextless" (list: ^list, elt: ^list_elt, $T: typeid, } // Get the previous entry in a list. -list_prev_entry :: proc "contextless" (list: ^list, elt: ^list_elt, $T: typeid, $member: string) -> ^T { +list_prev_entry :: proc "contextless" ( + list: ^list, + elt: ^list_elt, + $T: typeid, + $member: string, +) -> ^T { if elt.prev != list.last { return list_entry(elt.prev, T, member) } @@ -94,9 +99,23 @@ list_last_entry :: proc "contextless" (list: ^list, $T: typeid, $member: string) // _elt: ^list_elt // for elt in oc.list_for(list, &_elt, int, "elt") { // } -list_for :: proc "contextless" (list: ^list, elt: ^^list_elt, $T: typeid, $member: string) -> (^T, bool) { +list_for :: proc "contextless" ( + list: ^list, + elt: ^^list_elt, + $T: typeid, + $member: string, +) -> ( + ^T, + bool, +) { if elt == nil { - assert_fail(#file, #procedure, #line, "elt != nil", "misuse of `list_for`, expected `elt` to not be nil") + assert_fail( + #file, + #procedure, + #line, + "elt != nil", + "misuse of `list_for`, expected `elt` to not be nil", + ) } if elt^ == nil { @@ -112,7 +131,15 @@ list_for :: proc "contextless" (list: ^list, elt: ^^list_elt, $T: typeid, $membe list_iter :: list_for -list_for_reverse :: proc "contextless" (list: ^list, elt: ^^list_elt, $T: typeid, $member: string) -> (^T, bool) { +list_for_reverse :: proc "contextless" ( + list: ^list, + elt: ^^list_elt, + $T: typeid, + $member: string, +) -> ( + ^T, + bool, +) { if elt^ == nil { elt^ = list.last entry := list_checked_entry(elt^, T, member) @@ -226,27 +253,17 @@ str32_list_for :: proc "contextless" (list: ^str32_list, elt: ^^list_elt) -> (^s return list_for(&list.list, elt, str32_elt, "listElt") } -@(deferred_none=ui_box_end) -ui_container :: proc "contextless" (name: string, flags: ui_flags = {}) -> ^ui_box { - return ui_box_begin_str8(name, flags) +@(deferred_none = ui_box_end) +ui_container :: proc "contextless" (name: string) -> ^ui_box { + return ui_box_begin_str8(name) } -@(deferred_none=ui_end_frame) -ui_frame :: proc "contextless" (frame_size: [2]f32, style: ui_style, mask: ui_style_mask) { - ui_begin_frame(frame_size, style, mask) +@(deferred_none = ui_menu_end) +ui_menu :: proc "contextless" (key, name: string) { + ui_menu_begin_str8(key, name) } -@(deferred_none=ui_panel_end) -ui_panel :: proc "contextless" (name: cstring, flags: ui_flags) { - ui_panel_begin(name, flags) -} - -@(deferred_none=ui_menu_end) -ui_menu :: proc "contextless" (name: cstring) { - ui_menu_begin(name) -} - -@(deferred_none=ui_menu_bar_end) -ui_menu_bar :: proc "contextless" (name: cstring) { - ui_menu_bar_begin(name) +@(deferred_none = ui_menu_bar_end) +ui_menu_bar :: proc "contextless" (key: string) { + ui_menu_bar_begin_str8(key) } diff --git a/core/sys/orca/odin.odin b/core/sys/orca/odin.odin index 5c3e3e4d9..c59b990cf 100644 --- a/core/sys/orca/odin.odin +++ b/core/sys/orca/odin.odin @@ -8,15 +8,25 @@ create_odin_logger :: proc(lowest := runtime.Logger_Level.Debug, ident := "") -> return runtime.Logger{odin_logger_proc, nil, lowest, {}} } +log_typed :: proc "contextless" (level: log_level, msg: cstring, loc := #caller_location) { + log_ext( + level, + cstring(raw_data(loc.procedure)), + cstring(raw_data(loc.file_path)), + loc.line, + msg, + ) +} + odin_logger_proc :: proc(logger_data: rawptr, level: runtime.Logger_Level, text: string, options: runtime.Logger_Options, location := #caller_location) { cbuf := make([]byte, len(text)+1, context.temp_allocator) copy(cbuf, text) ctext := cstring(raw_data(cbuf)) switch level { - case .Debug, .Info: log_info(ctext, location) - case .Warning: log_warning(ctext, location) + case .Debug, .Info: log_typed(.INFO, ctext, location) + case .Warning: log_typed(.WARNING, ctext, location) case: fallthrough - case .Error, .Fatal: log_error(ctext, location) + case .Error, .Fatal: log_typed(.ERROR, ctext, location) } } diff --git a/core/sys/orca/orca.odin b/core/sys/orca/orca.odin index d1e7dbf66..abcf42fe2 100644 --- a/core/sys/orca/orca.odin +++ b/core/sys/orca/orca.odin @@ -14,27 +14,6 @@ pool :: struct { blockSize: u64, } -@(link_prefix="OC_") -foreign { - UI_DARK_THEME: ui_theme - UI_LIGHT_THEME: ui_theme - - UI_DARK_PALETTE: ui_palette - UI_LIGHT_PALETTE: ui_palette -} - - -SYS_MAX_ERROR :: 1024 - -sys_err_def :: struct { - msg: [SYS_MAX_ERROR]u8 `fmt:"s,0"`, - code: i32, -} - -@(link_prefix="oc_") -foreign { - sys_error: sys_err_def -} UNICODE_BASIC_LATIN :: unicode_range { 0x0000, 127 } UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT :: unicode_range { 0x0080, 127 } UNICODE_LATIN_EXTENDED_A :: unicode_range { 0x0100, 127 } @@ -178,43 +157,6 @@ file_write_slice :: proc(file: file, slice: []char) -> u64 { file_read_slice :: proc(file: file, slice: []char) -> u64 { return file_read(file, u64(len(slice)), raw_data(slice)) } - -style_enum :: enum { - SIZE_WIDTH = 1, - SIZE_HEIGHT, - - LAYOUT_AXIS, - LAYOUT_ALIGN_X, - LAYOUT_ALIGN_Y, - LAYOUT_SPACING, - LAYOUT_MARGIN_X, - LAYOUT_MARGIN_Y, - - FLOAT_X, - FLOAT_Y, - - COLOR, - BG_COLOR, - BORDER_COLOR, - BORDER_SIZE, - ROUNDNESS, - - FONT, - FONT_SIZE, - - ANIMATION_TIME, - ANIMATION_MASK, -} - -ui_style_mask :: bit_set[style_enum; u64] - -// Masks like the C version that can be used as common combinations -SIZE :: ui_style_mask { .SIZE_WIDTH, .SIZE_HEIGHT } -LAYOUT_MARGINS :: ui_style_mask { .LAYOUT_MARGIN_X, .LAYOUT_MARGIN_Y } -LAYOUT :: ui_style_mask { .LAYOUT_AXIS, .LAYOUT_ALIGN_X, .LAYOUT_ALIGN_Y, .LAYOUT_SPACING, .LAYOUT_MARGIN_X, .LAYOUT_MARGIN_Y } -FLOAT :: ui_style_mask { .FLOAT_X, .FLOAT_Y } -MASK_INHERITED :: ui_style_mask { .COLOR, .FONT, .FONT_SIZE, .ANIMATION_TIME, .ANIMATION_MASK } - //////////////////////////////////////////////////////////////////////////////// // Utility data structures and helpers used throughout the Orca API. //////////////////////////////////////////////////////////////////////////////// @@ -578,8 +520,28 @@ foreign { // A unicode codepoint. utf32 :: rune +// This enum declares the possible return status of UTF8 decoding/encoding operations. +utf8_status :: enum u32 { + // The operation was successful. + OK = 0, + // The operation unexpectedly encountered the end of the utf8 sequence. + OUT_OF_BOUNDS = 1, + // A continuation byte was encountered where a leading byte was expected. + UNEXPECTED_CONTINUATION_BYTE = 3, + // A leading byte was encountered in the middle of the encoding of utf8 codepoint. + UNEXPECTED_LEADING_BYTE = 4, + // The utf8 sequence contains an invalid byte. + INVALID_BYTE = 5, + // The operation encountered an invalid utf8 codepoint. + INVALID_CODEPOINT = 6, + // The utf8 sequence contains an overlong encoding of a utf8 codepoint. + OVERLONG_ENCODING = 7, +} + // A type representing the result of decoding of utf8-encoded codepoint. utf8_dec :: struct { + // The status of the decoding operation. If not `OC_UTF8_OK`, it describes the error that was encountered during decoding. + status: utf8_status, // The decoded codepoint. codepoint: utf32, // The size of the utf8 sequence encoding that codepoint. @@ -1033,7 +995,7 @@ file_dialog_kind :: enum u32 { // File dialog flags. file_dialog_flag :: enum u32 { // This dialog allows selecting files. - FILES = 1, + FILES = 0, // This dialog allows selecting directories. DIRECTORIES, // This dialog allows selecting multiple items. @@ -1180,7 +1142,7 @@ io_req :: struct { unused: u64, }, using _: struct #raw_union { - open: struct { + using open: struct { // The access permissions requested on the file to open. rights: file_access, // The options to use when opening the file. @@ -1390,181 +1352,333 @@ foreign { // A 2D Vector Graphics API. //////////////////////////////////////////////////////////////////////////////// +// An opaque handle to a graphics surface. surface :: distinct u64 +// An opaque handle representing a rendering engine for the canvas API. canvas_renderer :: distinct u64 +// An opaque handle to a canvas context. Canvas contexts are used to hold contextual state about drawing commands, such as the current color or the current line width, and to record drawing commands. Once commands have been recorded, they can be rendered to a surface using `oc_canvas_render()`. canvas_context :: distinct u64 +// An opaque font handle. font :: distinct u64 +// An opaque image handle. image :: distinct u64 +// This enum describes possible blending modes for color gradient. gradient_blend_space :: enum u32 { + // The gradient colors are interpolated in linear space. LINEAR = 0, + // The gradient colors are interpolated in sRGB space. SRGB = 1, } +// An enum identifying possible color spaces. color_space :: enum u32 { + // A linear RGB color space. RGB = 0, + // An sRGB color space. SRGB = 1, } +// A struct representing a color. color :: struct { using c: [4]f32, colorSpace: color_space } +// Stroke joint types. joint_type :: enum u32 { + // Miter joint. MITER = 0, + // Bevel joint. BEVEL = 1, + // Don't join path segments. NONE = 2, } +// Cap types. cap_type :: enum u32 { + // Don't draw caps. NONE = 0, + // Square caps. SQUARE = 1, } +// A struct describing the metrics of a font. font_metrics :: struct { + // The ascent from the baseline to the top of the line (a positive value means the top line is above the baseline). ascent: f32, + // The descent from the baseline to the bottom line (a positive value means the bottom line is below the baseline). descent: f32, + // The gap between two lines of text. lineGap: f32, + // The height of the lowercase character 'x'. xHeight: f32, + // The height of capital letters. capHeight: f32, + // The maximum character width. width: f32, } +// A struct describing the metrics of a single glyph. glyph_metrics :: struct { ink: rect, + // The default amount from which to advance the cursor after drawing this glyph. advance: vec2, } +// A struct describing the metrics of a run of glyphs. text_metrics :: struct { + // The bounding box of the inked portion of the text. ink: rect, + // The logical bounding box of the text (including ascents, descents, and line gaps). logical: rect, + // The amount from which to advance the cursor after drawing the text. advance: vec2, } +// An opaque struct representing a rectangle atlas. This is used to allocate rectangular regions of an image to make texture atlases. rect_atlas :: struct {} +// A struct describing a rectangular sub-region of an image. image_region :: struct { + // The image handle. image: image, + // The rectangular region of the image. rect: rect, } @(default_calling_convention="c", link_prefix="oc_") foreign { + // Returns a `nil` surface handle. surface_nil :: proc() -> surface --- + // Check if a surface handle is `nil`. surface_is_nil :: proc(surface: surface) -> bool --- + // Destroy a graphics surface. surface_destroy :: proc(surface: surface) --- + /* + Get a surface's size. + + The size is returned in device-independent "points". To get the size in pixels, multiply the size in points by the scaling factor returned by `oc_surface_contents_scaling()`. + */ surface_get_size :: proc(surface: surface) -> vec2 --- + // Get the scaling factor of a surface. surface_contents_scaling :: proc(surface: surface) -> vec2 --- + // Bring a surface to the foreground, rendering it on top of other surfaces. surface_bring_to_front :: proc(surface: surface) --- + // Send a surface to the background, rendering it below other surfaces. surface_send_to_back :: proc(surface: surface) --- + // Checks if a surface is hidden. surface_get_hidden :: proc(surface: surface) -> bool --- + // Set the hidden status of a surface. surface_set_hidden :: proc(surface: surface, hidden: bool) --- + // Create a color using RGBA values. color_rgba :: proc(r: f32, g: f32, b: f32, a: f32) -> color --- + // Create a current color using sRGBA values. color_srgba :: proc(r: f32, g: f32, b: f32, a: f32) -> color --- + // Convert a color from one color space to another. color_convert :: proc(_color: color, colorSpace: color_space) -> color --- + // Returns a `nil` canvas renderer handle. canvas_renderer_nil :: proc() -> canvas_renderer --- + // Checks if a canvas renderer handle is `nil`. canvas_renderer_is_nil :: proc(renderer: canvas_renderer) -> bool --- + // Create a canvas renderer. canvas_renderer_create :: proc() -> canvas_renderer --- + // Destroy a canvas renderer. canvas_renderer_destroy :: proc(renderer: canvas_renderer) --- + // Render canvas commands onto a surface. canvas_render :: proc(renderer: canvas_renderer, _context: canvas_context, surface: surface) --- + // Present a canvas surface to the display. canvas_present :: proc(renderer: canvas_renderer, surface: surface) --- + // Create a surface for rendering vector graphics. canvas_surface_create :: proc(renderer: canvas_renderer) -> surface --- - canvas_surface_swap_interval :: proc(surface: surface, swap: i32) --- + // Returns a `nil` canvas context handle. canvas_context_nil :: proc() -> canvas_context --- + // Checks if a canvas context handle is `nil`. canvas_context_is_nil :: proc(_context: canvas_context) -> bool --- + // Create a canvas context. canvas_context_create :: proc() -> canvas_context --- + // Destroy a canvas context canvas_context_destroy :: proc(_context: canvas_context) --- + // Make a canvas context current in the calling thread. Subsequent canvas commands will refer to this context until another context is made current. canvas_context_select :: proc(_context: canvas_context) -> canvas_context --- + // Set the multisample anti-aliasing sample count for the commands of a context. canvas_context_set_msaa_sample_count :: proc(_context: canvas_context, sampleCount: u32) --- + // Return a `nil` font handle. font_nil :: proc() -> font --- + // Check if a font handle is `nil`. font_is_nil :: proc(font: font) -> bool --- + // Create a font from in-memory TrueType data. font_create_from_memory :: proc(mem: str8, rangeCount: u32, ranges: ^unicode_range) -> font --- + // Create a font from a TrueType font file. font_create_from_file :: proc(file: file, rangeCount: u32, ranges: ^unicode_range) -> font --- + // Create a font from a TrueType font file path. font_create_from_path :: proc(path: str8, rangeCount: u32, ranges: ^unicode_range) -> font --- + // Destroy a font. font_destroy :: proc(font: font) --- + // Get the glyph indices of a run of unicode code points in a given font. font_get_glyph_indices :: proc(font: font, codePoints: str32, backing: str32) -> str32 --- + // Get the glyph indices of a run of unicode code points in a given font and push them on an arena. font_push_glyph_indices :: proc(arena: ^arena, font: font, codePoints: str32) -> str32 --- + // Get the glyp index of a single codepoint in a given font. font_get_glyph_index :: proc(font: font, codePoint: utf32) -> u32 --- + // Get a font's metrics for a given font size. font_get_metrics :: proc(font: font, emSize: f32) -> font_metrics --- + // Get a font's unscaled metrics. font_get_metrics_unscaled :: proc(font: font) -> font_metrics --- + // Get a scale factor to apply to unscaled font metrics to obtain a given 'm' size. font_get_scale_for_em_pixels :: proc(font: font, emSize: f32) -> f32 --- + // Get text metrics for a run of unicode code points. font_text_metrics_utf32 :: proc(font: font, fontSize: f32, codepoints: str32) -> text_metrics --- + // Get the text metrics for a utf8 string. font_text_metrics :: proc(font: font, fontSize: f32, text: str8) -> text_metrics --- + // Returns a `nil` image handle. image_nil :: proc() -> image --- + // Check if an image handle is `nil`. image_is_nil :: proc(a: image) -> bool --- + // Create an uninitialized image. image_create :: proc(renderer: canvas_renderer, width: u32, height: u32) -> image --- + // Create an image from an array of 8 bit per channel rgba values. image_create_from_rgba8 :: proc(renderer: canvas_renderer, width: u32, height: u32, pixels: [^]u8) -> image --- + // Create an image from in-memory png, jpeg or bmp data. image_create_from_memory :: proc(renderer: canvas_renderer, mem: str8, flip: bool) -> image --- + // Create an image from an image file. Supported formats are: png, jpeg or bmp. image_create_from_file :: proc(renderer: canvas_renderer, file: file, flip: bool) -> image --- + // Create an image from an image file path. Supported formats are: png, jpeg or bmp. image_create_from_path :: proc(renderer: canvas_renderer, path: str8, flip: bool) -> image --- + // Destroy an image. image_destroy :: proc(image: image) --- + // Upload pixels to an image. image_upload_region_rgba8 :: proc(image: image, region: rect, pixels: [^]u8) --- + // Get the size of an image. image_size :: proc(image: image) -> vec2 --- + // Create a rectangle atlas. rect_atlas_create :: proc(arena: ^arena, width: i32, height: i32) -> ^rect_atlas --- + // Allocate a rectangular region from an atlas. rect_atlas_alloc :: proc(atlas: ^rect_atlas, width: i32, height: i32) -> rect --- + // Recycle a rectangular region that was previously allocated from an atlas. rect_atlas_recycle :: proc(atlas: ^rect_atlas, rect: rect) --- + // Allocate an image region from an atlas and upload pixels to that region. image_atlas_alloc_from_rgba8 :: proc(atlas: ^rect_atlas, backingImage: image, width: u32, height: u32, pixels: [^]u8) -> image_region --- + // Allocate an image region from an atlas and upload an image to it. image_atlas_alloc_from_memory :: proc(atlas: ^rect_atlas, backingImage: image, mem: str8, flip: bool) -> image_region --- + // Allocate an image region from an atlas and upload an image to it. image_atlas_alloc_from_file :: proc(atlas: ^rect_atlas, backingImage: image, file: file, flip: bool) -> image_region --- + // Allocate an image region from an atlas and upload an image to it. image_atlas_alloc_from_path :: proc(atlas: ^rect_atlas, backingImage: image, path: str8, flip: bool) -> image_region --- + // Recycle an image region allocated from an atlas. image_atlas_recycle :: proc(atlas: ^rect_atlas, imageRgn: image_region) --- + // Push a matrix on the transform stack. matrix_push :: proc(_matrix: mat2x3) --- + // Multiply a matrix with the top of the transform stack, and push the result on the top of the stack. matrix_multiply_push :: proc(_matrix: mat2x3) --- + // Pop a matrix from the transform stack. matrix_pop :: proc() --- + // Get the top matrix of the transform stack. matrix_top :: proc() -> mat2x3 --- + // Push a clip rectangle to the clip stack. clip_push :: proc(x: f32, y: f32, w: f32, h: f32) --- + // Pop from the clip stack. clip_pop :: proc() --- + // Get the clip rectangle from the top of the clip stack. clip_top :: proc() -> rect --- + // Set the current color. set_color :: proc(_color: color) --- + // Set the current color using linear RGBA values. set_color_rgba :: proc(r: f32, g: f32, b: f32, a: f32) --- + // Set the current color using sRGBA values. set_color_srgba :: proc(r: f32, g: f32, b: f32, a: f32) --- + // Set the current color gradient. set_gradient :: proc(blendSpace: gradient_blend_space, bottomLeft: color, bottomRight: color, topRight: color, topLeft: color) --- + // Set the current line width. set_width :: proc(width: f32) --- + // Set the current tolerance for the line width. Bigger values increase performance but allow more inconsistent stroke widths along a path. set_tolerance :: proc(tolerance: f32) --- + // Set the current joint style. set_joint :: proc(joint: joint_type) --- + // Set the maximum joint excursion. If a joint would extend past this threshold, the renderer falls back to a bevel joint. set_max_joint_excursion :: proc(maxJointExcursion: f32) --- + // Set the current cap style. set_cap :: proc(cap: cap_type) --- + // The the current font. set_font :: proc(font: font) --- + // Set the current font size. set_font_size :: proc(size: f32) --- + // Set the current text flip value. `true` flips the y-axis of text rendering commands. set_text_flip :: proc(flip: bool) --- + // Set the current source image. set_image :: proc(image: image) --- + // Set the current source image region. set_image_source_region :: proc(region: rect) --- + // Get the current color get_color :: proc() -> color --- + // Get the current line width. get_width :: proc() -> f32 --- + // Get the current line width tolerance. get_tolerance :: proc() -> f32 --- + // Get the current joint style. get_joint :: proc() -> joint_type --- + // Get the current max joint excursion. get_max_joint_excursion :: proc() -> f32 --- + // Get the current cap style. get_cap :: proc() -> cap_type --- + // Get the current font. get_font :: proc() -> font --- + // Get the current font size. get_font_size :: proc() -> f32 --- + // Get the current text flip value. get_text_flip :: proc() -> bool --- + // Get the current source image. get_image :: proc() -> image --- + // Get the current image source region. get_image_source_region :: proc() -> rect --- + // Get the current cursor position. get_position :: proc() -> vec2 --- + // Move the cursor to a given position. move_to :: proc(x: f32, y: f32) --- + // Add a line to the path from the current position to a new one. line_to :: proc(x: f32, y: f32) --- + // Add a quadratic Bézier curve to the path from the current position to a new one. quadratic_to :: proc(x1: f32, y1: f32, x2: f32, y2: f32) --- + // Add a cubic Bézier curve to the path from the current position to a new one. cubic_to :: proc(x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) --- + // Close the current path with a line. close_path :: proc() --- + // Add the outlines of a glyph run to the path, using glyph indices. glyph_outlines :: proc(glyphIndices: str32) -> rect --- + // Add the outlines of a glyph run to the path, using unicode codepoints. codepoints_outlines :: proc(string: str32) --- + // Add the outlines of a glyph run to the path, using a utf8 string. text_outlines :: proc(string: str8) --- + // Clear the canvas to the current color. clear :: proc() --- + // Fill the current path. fill :: proc() --- + // Stroke the current path. stroke :: proc() --- + // Draw a filled rectangle. rectangle_fill :: proc(x: f32, y: f32, w: f32, h: f32) --- + // Draw a stroked rectangle. rectangle_stroke :: proc(x: f32, y: f32, w: f32, h: f32) --- + // Draw a filled rounded rectangle. rounded_rectangle_fill :: proc(x: f32, y: f32, w: f32, h: f32, r: f32) --- + // Draw a stroked rounded rectangle. rounded_rectangle_stroke :: proc(x: f32, y: f32, w: f32, h: f32, r: f32) --- + // Draw a filled ellipse. ellipse_fill :: proc(x: f32, y: f32, rx: f32, ry: f32) --- + // Draw a stroked ellipse. ellipse_stroke :: proc(x: f32, y: f32, rx: f32, ry: f32) --- + // Draw a filled circle. circle_fill :: proc(x: f32, y: f32, r: f32) --- + // Draw a stroked circle. circle_stroke :: proc(x: f32, y: f32, r: f32) --- + // Add an arc to the path. arc :: proc(x: f32, y: f32, r: f32, arcAngle: f32, startAngle: f32) --- + // Draw a text line. text_fill :: proc(x: f32, y: f32, text: str8) --- + // Draw an image. image_draw :: proc(image: image, rect: rect) --- + // Draw a sub-region of an image. image_draw_region :: proc(image: image, srcRegion: rect, dstRegion: rect) --- } @@ -1574,9 +1688,11 @@ foreign { @(default_calling_convention="c", link_prefix="oc_") foreign { + // Create a graphics surface for GLES rendering. gles_surface_create :: proc() -> surface --- + // Make the GL context of the surface current. gles_surface_make_current :: proc(surface: surface) --- - gles_surface_swap_interval :: proc(surface: surface, interval: i32) --- + // Swap the buffers of a GLES surface. gles_surface_swap_buffers :: proc(surface: surface) --- } @@ -1638,463 +1754,6 @@ input_state :: struct { clipboard: clipboard_state, } -ui_key :: struct { - hash: u64, -} - -ui_axis :: enum u32 { - X = 0, - Y = 1, - COUNT = 2, -} - -ui_align :: enum u32 { - START = 0, - END = 1, - CENTER = 2, -} - -ui_layout_align :: [2]ui_align - -ui_layout :: struct { - axis: ui_axis, - spacing: f32, - margin: [2]f32, - align: ui_layout_align, -} - -ui_size_kind :: enum u32 { - TEXT = 0, - PIXELS = 1, - CHILDREN = 2, - PARENT = 3, - PARENT_MINUS_PIXELS = 4, -} - -ui_size :: struct { - kind: ui_size_kind, - value: f32, - relax: f32, - minSize: f32, -} - -ui_box_size :: [2]ui_size - -ui_box_floating :: [2]bool - -ui_style :: struct { - size: ui_box_size, - layout: ui_layout, - floating: ui_box_floating, - floatTarget: vec2, - _color: color, - bgColor: color, - borderColor: color, - font: font, - fontSize: f32, - borderSize: f32, - roundness: f32, - animationTime: f32, - animationMask: ui_style_mask, -} - -ui_palette :: struct { - red0: color, - red1: color, - red2: color, - red3: color, - red4: color, - red5: color, - red6: color, - red7: color, - red8: color, - red9: color, - orange0: color, - orange1: color, - orange2: color, - orange3: color, - orange4: color, - orange5: color, - orange6: color, - orange7: color, - orange8: color, - orange9: color, - amber0: color, - amber1: color, - amber2: color, - amber3: color, - amber4: color, - amber5: color, - amber6: color, - amber7: color, - amber8: color, - amber9: color, - yellow0: color, - yellow1: color, - yellow2: color, - yellow3: color, - yellow4: color, - yellow5: color, - yellow6: color, - yellow7: color, - yellow8: color, - yellow9: color, - lime0: color, - lime1: color, - lime2: color, - lime3: color, - lime4: color, - lime5: color, - lime6: color, - lime7: color, - lime8: color, - lime9: color, - lightGreen0: color, - lightGreen1: color, - lightGreen2: color, - lightGreen3: color, - lightGreen4: color, - lightGreen5: color, - lightGreen6: color, - lightGreen7: color, - lightGreen8: color, - lightGreen9: color, - green0: color, - green1: color, - green2: color, - green3: color, - green4: color, - green5: color, - green6: color, - green7: color, - green8: color, - green9: color, - teal0: color, - teal1: color, - teal2: color, - teal3: color, - teal4: color, - teal5: color, - teal6: color, - teal7: color, - teal8: color, - teal9: color, - cyan0: color, - cyan1: color, - cyan2: color, - cyan3: color, - cyan4: color, - cyan5: color, - cyan6: color, - cyan7: color, - cyan8: color, - cyan9: color, - lightBlue0: color, - lightBlue1: color, - lightBlue2: color, - lightBlue3: color, - lightBlue4: color, - lightBlue5: color, - lightBlue6: color, - lightBlue7: color, - lightBlue8: color, - lightBlue9: color, - blue0: color, - blue1: color, - blue2: color, - blue3: color, - blue4: color, - blue5: color, - blue6: color, - blue7: color, - blue8: color, - blue9: color, - indigo0: color, - indigo1: color, - indigo2: color, - indigo3: color, - indigo4: color, - indigo5: color, - indigo6: color, - indigo7: color, - indigo8: color, - indigo9: color, - violet0: color, - violet1: color, - violet2: color, - violet3: color, - violet4: color, - violet5: color, - violet6: color, - violet7: color, - violet8: color, - violet9: color, - purple0: color, - purple1: color, - purple2: color, - purple3: color, - purple4: color, - purple5: color, - purple6: color, - purple7: color, - purple8: color, - purple9: color, - pink0: color, - pink1: color, - pink2: color, - pink3: color, - pink4: color, - pink5: color, - pink6: color, - pink7: color, - pink8: color, - pink9: color, - grey0: color, - grey1: color, - grey2: color, - grey3: color, - grey4: color, - grey5: color, - grey6: color, - grey7: color, - grey8: color, - grey9: color, - black: color, - white: color, -} - -ui_theme :: struct { - white: color, - primary: color, - primaryHover: color, - primaryActive: color, - border: color, - fill0: color, - fill1: color, - fill2: color, - bg0: color, - bg1: color, - bg2: color, - bg3: color, - bg4: color, - text0: color, - text1: color, - text2: color, - text3: color, - sliderThumbBorder: color, - elevatedBorder: color, - roundnessSmall: f32, - roundnessMedium: f32, - roundnessLarge: f32, - palette: ^ui_palette, -} - -ui_tag :: struct { - hash: u64, -} - -ui_selector_kind :: enum u32 { - ANY = 0, - OWNER = 1, - TEXT = 2, - TAG = 3, - STATUS = 4, - KEY = 5, -} - -ui_status_flag :: enum u8 { - HOVER = 1, - HOT, - ACTIVE, - DRAGGING, -} -ui_status :: bit_set[ui_status_flag; u8] - -ui_selector_op :: enum u32 { - DESCENDANT = 0, - AND = 1, -} - -ui_selector :: struct { - listElt: list_elt, - kind: ui_selector_kind, - op: ui_selector_op, - using _: struct #raw_union { - text: str8, - key: ui_key, - tag: ui_tag, - status: ui_status, - }, -} - -ui_pattern :: struct { - l: list, -} - -ui_box :: struct { - listElt: list_elt, - children: list, - parent: ^ui_box, - overlayElt: list_elt, - bucketElt: list_elt, - key: ui_key, - frameCounter: u64, - flags: ui_flags, - string: str8, - tags: list, - drawProc: ui_box_draw_proc, - drawData: rawptr, - beforeRules: list, - afterRules: list, - targetStyle: ^ui_style, - style: ui_style, - z: u32, - floatPos: vec2, - childrenSum: [2]f32, - spacing: [2]f32, - minSize: [2]f32, - rect: rect, - sig: ^ui_sig, - fresh: bool, - closed: bool, - parentClosed: bool, - dragging: bool, - hot: bool, - active: bool, - scroll: vec2, - pressedMouse: vec2, - hotTransition: f32, - activeTransition: f32, -} - -ui_style_rule :: struct { - boxElt: list_elt, - buildElt: list_elt, - tmpElt: list_elt, - owner: ^ui_box, - pattern: ui_pattern, - mask: ui_style_mask, - style: ^ui_style, -} - -ui_sig :: struct { - box: ^ui_box, - mouse: vec2, - delta: vec2, - wheel: vec2, - pressed: bool, - released: bool, - clicked: bool, - doubleClicked: bool, - tripleClicked: bool, - rightPressed: bool, - dragging: bool, - hovering: bool, - pasted: bool, -} - -ui_box_draw_proc :: proc "c" (arg0: ^ui_box, arg1: rawptr) - -ui_flag :: enum u32 { - CLICKABLE = 0, - SCROLL_WHEEL_X, - SCROLL_WHEEL_Y, - BLOCK_MOUSE, - HOT_ANIMATION, - ACTIVE_ANIMATION, - OVERFLOW_ALLOW_X, - OVERFLOW_ALLOW_Y, - CLIP, - DRAW_BACKGROUND, - DRAW_FOREGROUND, - DRAW_BORDER, - DRAW_TEXT, - DRAW_PROC, - OVERLAY, -} -ui_flags :: bit_set[ui_flag; u32] - -MAX_INPUT_CHAR_PER_FRAME :: 64 - -ui_input_text :: struct { - count: u8 `fmt:"-"`, - codePoints: [64]utf32 `fmt:"s,count"`, -} - -ui_stack_elt :: struct { - parent: ^ui_stack_elt, - using _: struct #raw_union { - box: ^ui_box, - size: ui_size, - clip: rect, - }, -} - -ui_tag_elt :: struct { - listElt: list_elt, - tag: ui_tag, -} - -BOX_MAP_BUCKET_COUNT :: 1024 - -ui_edit_move :: enum u32 { - NONE = 0, - CHAR = 1, - WORD = 2, - LINE = 3, -} - -ui_context :: struct { - init: bool, - input: input_state, - frameCounter: u64, - frameTime: f64, - lastFrameDuration: f64, - frameArena: arena, - boxPool: pool, - boxMap: [1024]list, - root: ^ui_box, - overlay: ^ui_box, - overlayList: list, - boxStack: ^ui_stack_elt, - clipStack: ^ui_stack_elt, - nextBoxBeforeRules: list, - nextBoxAfterRules: list, - nextBoxTags: list, - z: u32, - hovered: ^ui_box, - focus: ^ui_box, - editCursor: i32, - editMark: i32, - editFirstDisplayedChar: i32, - editCursorBlinkStart: f64, - editSelectionMode: ui_edit_move, - editWordSelectionInitialCursor: i32, - editWordSelectionInitialMark: i32, - theme: ^ui_theme, -} - -ui_text_box_result :: struct { - changed: bool, - accepted: bool, - text: str8, -} - -ui_select_popup_info :: struct { - changed: bool, - selectedIndex: i32, - optionCount: i32 `fmt:"-"`, - options: [^]str8 `fmt:"s,optionCount"`, - placeholder: str8, -} - -ui_radio_group_info :: struct { - changed: bool, - selectedIndex: i32, - optionCount: i32 `fmt:"-"`, - options: [^]str8 `fmt:"s,optionCount"`, -} - @(default_calling_convention="c", link_prefix="oc_") foreign { input_process_event :: proc(arena: ^arena, state: ^input_state, event: ^event) --- @@ -2120,59 +1779,364 @@ foreign { clipboard_pasted :: proc(state: ^input_state) -> bool --- clipboard_pasted_text :: proc(state: ^input_state) -> str8 --- key_mods :: proc(state: ^input_state) -> keymod_flags --- - ui_init :: proc(_context: ^ui_context) --- +} + +//////////////////////////////////////////////////////////////////////////////// +// Graphical User Interface Core API. +//////////////////////////////////////////////////////////////////////////////// + +ui_axis :: enum u32 { + X = 0, + Y = 1, + COUNT = 2, +} + +ui_align :: enum u32 { + START = 0, + END = 1, + CENTER = 2, +} + +ui_size_kind :: enum u32 { + CHILDREN = 0, + TEXT = 1, + PIXELS = 2, + PARENT = 3, + PARENT_MINUS_PIXELS = 4, +} + +ui_size :: struct { + kind: ui_size_kind, + value: f32, + relax: f32, + minSize: f32, +} + +ui_overflow :: enum u32 { + CLIP = 0, + ALLOW = 1, + SCROLL = 2, +} + +ui_attribute :: enum u32 { + WIDTH = 0, + HEIGHT = 1, + AXIS = 2, + MARGIN_X = 3, + MARGIN_Y = 4, + SPACING = 5, + ALIGN_X = 6, + ALIGN_Y = 7, + FLOATING_X = 8, + FLOATING_Y = 9, + FLOAT_TARGET_X = 10, + FLOAT_TARGET_Y = 11, + OVERFLOW_X = 12, + OVERFLOW_Y = 13, + CONSTRAIN_X = 14, + CONSTRAIN_Y = 15, + COLOR = 16, + BG_COLOR = 17, + BORDER_COLOR = 18, + FONT = 19, + TEXT_SIZE = 20, + BORDER_SIZE = 21, + ROUNDNESS = 22, + DRAW_MASK = 23, + ANIMATION_TIME = 24, + ANIMATION_MASK = 25, + CLICK_THROUGH = 26, + ATTRIBUTE_COUNT = 27, +} + +ui_attribute_mask :: enum u32 { + NONE = 0, + SIZE_WIDTH = 1, + SIZE_HEIGHT = 2, + LAYOUT_AXIS = 4, + LAYOUT_ALIGN_X = 64, + LAYOUT_ALIGN_Y = 128, + LAYOUT_SPACING = 32, + LAYOUT_MARGIN_X = 8, + LAYOUT_MARGIN_Y = 16, + FLOATING_X = 256, + FLOATING_Y = 512, + FLOAT_TARGET_X = 1024, + FLOAT_TARGET_Y = 2048, + OVERFLOW_X = 4096, + OVERFLOW_Y = 8192, + CONSTRAIN_X = 16384, + CONSTRAIN_Y = 32768, + COLOR = 65536, + BG_COLOR = 131072, + BORDER_COLOR = 262144, + BORDER_SIZE = 2097152, + ROUNDNESS = 4194304, + FONT = 524288, + FONT_SIZE = 1048576, + DRAW_MASK = 8388608, + ANIMATION_TIME = 16777216, + ANIMATION_MASK = 33554432, + CLICK_THROUGH = 67108864, +} + +ui_layout_align :: [2]ui_align + +ui_layout :: struct { + axis: ui_axis, + spacing: f32, + margin: [2]f32, + align: ui_layout_align, + overflow: [2]ui_overflow, + constrain: [2]bool, +} + +ui_box_size :: [2]ui_size + +ui_box_floating :: [2]bool + +ui_draw_mask :: enum u32 { + BACKGROUND = 1, + BORDER = 2, + TEXT = 4, + PROC = 8, +} + +ui_style :: struct { + size: ui_box_size, + layout: ui_layout, + floating: ui_box_floating, + floatTarget: vec2, + _color: color, + bgColor: color, + borderColor: color, + font: font, + fontSize: f32, + borderSize: f32, + roundness: f32, + drawMask: u32, + animationTime: f32, + animationMask: ui_attribute_mask, + clickThrough: bool, +} + +ui_context :: struct {} + +ui_sig :: struct { + box: ^ui_box, + mouse: vec2, + delta: vec2, + wheel: vec2, + lastPressedMouse: vec2, + pressed: bool, + released: bool, + clicked: bool, + doubleClicked: bool, + tripleClicked: bool, + rightPressed: bool, + closed: bool, + active: bool, + hover: bool, + focus: bool, + pasted: bool, +} + +ui_box_draw_proc :: proc "c" (arg0: ^ui_box, arg1: rawptr) + +ui_key :: struct { + hash: u64, +} + +ui_box :: struct { + listElt: list_elt, + children: list, + parent: ^ui_box, + overlayElt: list_elt, + overlay: bool, + bucketElt: list_elt, + key: ui_key, + frameCounter: u64, + keyString: str8, + text: str8, + tags: list, + drawProc: ui_box_draw_proc, + drawData: rawptr, + rules: list, + targetStyle: ^ui_style, + style: ui_style, + z: u32, + floatPos: vec2, + childrenSum: [2]f32, + spacing: [2]f32, + minSize: [2]f32, + rect: rect, + styleVariables: list, + sig: ui_sig, + fresh: bool, + closed: bool, + parentClosed: bool, + dragging: bool, + hot: bool, + active: bool, + scroll: vec2, + pressedMouse: vec2, + hotTransition: f32, + activeTransition: f32, +} + +@(default_calling_convention="c", link_prefix="oc_") +foreign { + ui_context_create :: proc(defaultFont: font) -> ^ui_context --- + ui_context_destroy :: proc(_context: ^ui_context) --- ui_get_context :: proc() -> ^ui_context --- ui_set_context :: proc(_context: ^ui_context) --- ui_process_event :: proc(event: ^event) --- - ui_begin_frame :: proc(size: vec2, #by_ptr defaultStyle: ui_style, mask: ui_style_mask) --- - ui_end_frame :: proc() --- + ui_frame_begin :: proc(size: vec2) --- + ui_frame_end :: proc() --- ui_draw :: proc() --- - ui_set_theme :: proc(theme: ^ui_theme) --- - ui_key_make_str8 :: proc(string: str8) -> ui_key --- - ui_key_make_path :: proc(path: str8_list) -> ui_key --- - ui_box_make_str8 :: proc(string: str8, flags: ui_flags) -> ^ui_box --- - ui_box_begin_str8 :: proc(string: str8, flags: ui_flags) -> ^ui_box --- + ui_input :: proc() -> ^input_state --- + ui_frame_arena :: proc() -> ^arena --- + ui_frame_time :: proc() -> f64 --- + ui_box_begin_str8 :: proc(string: str8) -> ^ui_box --- ui_box_end :: proc() -> ^ui_box --- - ui_box_push :: proc(box: ^ui_box) --- - ui_box_pop :: proc() --- - ui_box_top :: proc() -> ^ui_box --- - ui_box_lookup_key :: proc(key: ui_key) -> ^ui_box --- - ui_box_lookup_str8 :: proc(string: str8) -> ^ui_box --- ui_box_set_draw_proc :: proc(box: ^ui_box, _proc: ui_box_draw_proc, data: rawptr) --- - ui_box_closed :: proc(box: ^ui_box) -> bool --- + ui_box_set_text :: proc(box: ^ui_box, text: str8) --- + ui_box_set_overlay :: proc(box: ^ui_box, overlay: bool) --- ui_box_set_closed :: proc(box: ^ui_box, closed: bool) --- - ui_box_active :: proc(box: ^ui_box) -> bool --- - ui_box_activate :: proc(box: ^ui_box) --- - ui_box_deactivate :: proc(box: ^ui_box) --- - ui_box_hot :: proc(box: ^ui_box) -> bool --- - ui_box_set_hot :: proc(box: ^ui_box, hot: bool) --- - ui_box_sig :: proc(box: ^ui_box) -> ui_sig --- - ui_tag_make_str8 :: proc(string: str8) -> ui_tag --- - ui_tag_box_str8 :: proc(box: ^ui_box, string: str8) --- + ui_box_user_data_get :: proc(box: ^ui_box) -> cstring --- + ui_box_user_data_push :: proc(box: ^ui_box, size: u64) -> cstring --- + ui_box_request_focus :: proc(box: ^ui_box) --- + ui_box_release_focus :: proc(box: ^ui_box) --- + ui_box_get_sig :: proc(box: ^ui_box) -> ui_sig --- + ui_set_draw_proc :: proc(_proc: ui_box_draw_proc, data: rawptr) --- + ui_set_text :: proc(text: str8) --- + ui_set_overlay :: proc(overlay: bool) --- + ui_set_closed :: proc(closed: bool) --- + ui_user_data_get :: proc() -> cstring --- + ui_user_data_push :: proc(size: u64) -> cstring --- + ui_request_focus :: proc() --- + ui_release_focus :: proc() --- + ui_get_sig :: proc() -> ui_sig --- + ui_box_tag_str8 :: proc(box: ^ui_box, string: str8) --- + ui_tag_str8 :: proc(string: str8) --- ui_tag_next_str8 :: proc(string: str8) --- - ui_apply_style_with_mask :: proc(dst: ^ui_style, src: ^ui_style, mask: ui_style_mask) --- - ui_pattern_push :: proc(arena: ^arena, pattern: ^ui_pattern, selector: ui_selector) --- - ui_pattern_all :: proc() -> ui_pattern --- - ui_pattern_owner :: proc() -> ui_pattern --- - ui_style_next :: proc(#by_ptr style: ui_style, mask: ui_style_mask) --- - ui_style_match_before :: proc(pattern: ui_pattern, #by_ptr style: ui_style, mask: ui_style_mask) --- - ui_style_match_after :: proc(pattern: ui_pattern, #by_ptr style: ui_style, mask: ui_style_mask) --- - ui_label :: proc(label: cstring) -> ui_sig --- - ui_label_str8 :: proc(label: str8) -> ui_sig --- - ui_button :: proc(label: cstring) -> ui_sig --- - ui_checkbox :: proc(name: cstring, checked: ^bool) -> ui_sig --- - ui_slider :: proc(name: cstring, value: ^f32) -> ^ui_box --- - ui_scrollbar :: proc(name: cstring, thumbRatio: f32, scrollValue: ^f32) -> ^ui_box --- - ui_tooltip :: proc(label: cstring) --- - ui_panel_begin :: proc(name: cstring, flags: ui_flags) --- - ui_panel_end :: proc() --- - ui_menu_bar_begin :: proc(name: cstring) --- - ui_menu_bar_end :: proc() --- - ui_menu_begin :: proc(label: cstring) --- - ui_menu_end :: proc() --- - ui_menu_button :: proc(label: cstring) -> ui_sig --- - ui_text_box :: proc(name: cstring, arena: ^arena, text: str8) -> ui_text_box_result --- - ui_select_popup :: proc(name: cstring, info: ^ui_select_popup_info) -> ui_select_popup_info --- - ui_radio_group :: proc(name: cstring, info: ^ui_radio_group_info) -> ui_radio_group_info --- + ui_style_rule_begin :: proc(pattern: str8) --- + ui_style_rule_end :: proc() --- + ui_style_set_i32 :: proc(attr: ui_attribute, i: i32) --- + ui_style_set_f32 :: proc(attr: ui_attribute, f: f32) --- + ui_style_set_color :: proc(attr: ui_attribute, _color: color) --- + ui_style_set_font :: proc(attr: ui_attribute, font: font) --- + ui_style_set_size :: proc(attr: ui_attribute, size: ui_size) --- + ui_style_set_var_str8 :: proc(attr: ui_attribute, var: str8) --- + ui_style_set_var :: proc(attr: ui_attribute, var: cstring) --- + ui_var_default_i32_str8 :: proc(name: str8, i: i32) --- + ui_var_default_f32_str8 :: proc(name: str8, f: f32) --- + ui_var_default_size_str8 :: proc(name: str8, size: ui_size) --- + ui_var_default_color_str8 :: proc(name: str8, _color: color) --- + ui_var_default_font_str8 :: proc(name: str8, font: font) --- + ui_var_default_str8 :: proc(name: str8, src: str8) --- + ui_var_default_i32 :: proc(name: cstring, i: i32) --- + ui_var_default_f32 :: proc(name: cstring, f: f32) --- + ui_var_default_size :: proc(name: cstring, size: ui_size) --- + ui_var_default_color :: proc(name: cstring, _color: color) --- + ui_var_default_font :: proc(name: cstring, font: font) --- + ui_var_default :: proc(name: cstring, src: cstring) --- + ui_var_set_i32_str8 :: proc(name: str8, i: i32) --- + ui_var_set_f32_str8 :: proc(name: str8, f: f32) --- + ui_var_set_size_str8 :: proc(name: str8, size: ui_size) --- + ui_var_set_color_str8 :: proc(name: str8, _color: color) --- + ui_var_set_font_str8 :: proc(name: str8, font: font) --- + ui_var_set_str8 :: proc(name: str8, src: str8) --- + ui_var_set_i32 :: proc(name: cstring, i: i32) --- + ui_var_set_f32 :: proc(name: cstring, f: f32) --- + ui_var_set_size :: proc(name: cstring, size: ui_size) --- + ui_var_set_color :: proc(name: cstring, _color: color) --- + ui_var_set_font :: proc(name: cstring, font: font) --- + ui_var_set :: proc(name: cstring, src: cstring) --- + ui_var_get_i32_str8 :: proc(name: str8) -> i32 --- + ui_var_get_f32_str8 :: proc(name: str8) -> f32 --- + ui_var_get_size_str8 :: proc(name: str8) -> ui_size --- + ui_var_get_color_str8 :: proc(name: str8) -> color --- + ui_var_get_font_str8 :: proc(name: str8) -> font --- + ui_var_get_i32 :: proc(name: cstring) -> i32 --- + ui_var_get_f32 :: proc(name: cstring) -> f32 --- + ui_var_get_size :: proc(name: cstring) -> ui_size --- + ui_var_get_color :: proc(name: cstring) -> color --- + ui_var_get_font :: proc(name: cstring) -> font --- + ui_theme_dark :: proc() --- + ui_theme_light :: proc() --- +} + +//////////////////////////////////////////////////////////////////////////////// +// Graphical User Interface Widgets. +//////////////////////////////////////////////////////////////////////////////// + +ui_text_box_result :: struct { + changed: bool, + accepted: bool, + text: str8, + box: ^ui_box, +} + +ui_edit_move :: enum u32 { + NONE = 0, + CHAR = 1, + WORD = 2, + LINE = 3, +} + +ui_text_box_info :: struct { + text: str8, + defaultText: str8, + cursor: i32, + mark: i32, + selectionMode: ui_edit_move, + wordSelectionInitialCursor: i32, + wordSelectionInitialMark: i32, + firstDisplayedChar: i32, + cursorBlinkStart: f64, +} + +ui_select_popup_info :: struct { + changed: bool, + selectedIndex: i32, + optionCount: i32 `fmt:"-"`, + options: [^]str8 `fmt:"s,optionCount"`, + placeholder: str8, +} + +ui_radio_group_info :: struct { + changed: bool, + selectedIndex: i32, + optionCount: i32 `fmt:"-"`, + options: [^]str8 `fmt:"s,optionCount"`, +} + +@(default_calling_convention="c", link_prefix="oc_") +foreign { + ui_label :: proc(key: cstring, label: cstring) -> ui_sig --- + ui_label_str8 :: proc(key: str8, label: str8) -> ui_sig --- + ui_button :: proc(key: cstring, text: cstring) -> ui_sig --- + ui_button_str8 :: proc(key: str8, text: str8) -> ui_sig --- + ui_checkbox :: proc(key: cstring, checked: ^bool) -> ui_sig --- + ui_checkbox_str8 :: proc(key: str8, checked: ^bool) -> ui_sig --- + ui_slider :: proc(name: cstring, value: ^f32) -> ^ui_box --- + ui_slider_str8 :: proc(name: str8, value: ^f32) -> ^ui_box --- + ui_tooltip :: proc(key: cstring, text: cstring) --- + ui_tooltip_str8 :: proc(key: str8, text: str8) --- + ui_menu_bar_begin :: proc(key: cstring) --- + ui_menu_bar_begin_str8 :: proc(key: str8) --- + ui_menu_bar_end :: proc() --- + ui_menu_begin :: proc(key: cstring, name: cstring) --- + ui_menu_begin_str8 :: proc(key: str8, name: str8) --- + ui_menu_end :: proc() --- + ui_menu_button :: proc(key: cstring, text: cstring) -> ui_sig --- + ui_menu_button_str8 :: proc(key: str8, text: str8) -> ui_sig --- + ui_text_box :: proc(key: cstring, arena: ^arena, info: ^ui_text_box_info) -> ui_text_box_result --- + ui_text_box_str8 :: proc(key: str8, arena: ^arena, info: ^ui_text_box_info) -> ui_text_box_result --- + ui_select_popup :: proc(key: cstring, info: ^ui_select_popup_info) -> ui_select_popup_info --- + ui_select_popup_str8 :: proc(key: str8, info: ^ui_select_popup_info) -> ui_select_popup_info --- + ui_radio_group :: proc(key: cstring, info: ^ui_radio_group_info) -> ui_radio_group_info --- + ui_radio_group_str8 :: proc(key: str8, info: ^ui_radio_group_info) -> ui_radio_group_info --- } diff --git a/core/sys/windows/dwmapi.odin b/core/sys/windows/dwmapi.odin index 11a46f53a..e86730660 100644 --- a/core/sys/windows/dwmapi.odin +++ b/core/sys/windows/dwmapi.odin @@ -38,6 +38,13 @@ DWMNCRENDERINGPOLICY :: enum { DWMNCRP_LAST, } +DWM_WINDOW_CORNER_PREFERENCE :: enum c_int { + DEFAULT, + DONOTROUND, + ROUND, + ROUNDSMALL, +} + @(default_calling_convention="system") foreign dwmapi { DwmFlush :: proc() -> HRESULT --- diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 82b047103..c559d4771 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -2185,7 +2185,7 @@ or_break_and_or_continue_operators :: proc() { // The concept of 'or_break' and 'or_continue' is very similar to that of 'or_return'. // The difference is that unlike 'or_return', the value does not get returned from // the current procedure but rather discarded if it is 'false' or not 'nil', and then - // the specified branch (i.e. break or_continue). + // the specified branch (i.e. break or continue). // The or branch expression can be labelled if a specific statement needs to be used. Error :: enum { @@ -2337,7 +2337,7 @@ matrix_type :: proc() { // There is no support for booleans, quaternions, or any compound type. // Indexing a matrix can be used with the matrix indexing syntax - // This mirrors othe type usages: type on the left, usage on the right + // This mirrors other type usages: type on the left, usage on the right elem := m[1, 2] // row 1, column 2 assert(elem == -6) @@ -2599,6 +2599,7 @@ main :: proc() { using_statement() implicit_context_system() parametric_polymorphism() + threading_example() array_programming() map_type() implicit_selector_expression() @@ -2614,7 +2615,6 @@ main :: proc() { ranged_fields_for_array_compound_literals() deprecated_attribute() range_statements_with_multiple_return_values() - threading_example() soa_struct_layout() constant_literal_expressions() union_maybe() diff --git a/misc/featuregen/featuregen.py b/misc/featuregen/featuregen.py index ecc47f70c..534934b87 100644 --- a/misc/featuregen/featuregen.py +++ b/misc/featuregen/featuregen.py @@ -21,7 +21,7 @@ with tempfile.NamedTemporaryFile(suffix=".odin", delete=True) as temp_file: temp_file.write(b"package main\n") for arch, target, triple, cpus, features in archs: - cmd = ["odin", "build", temp_file.name, "-file", "-build-mode:llvm", "-out:temp", "-target-features:\"help\"", f"-target:\"{target}\""] + cmd = ["odin", "build", temp_file.name, "-file", "-use-single-module", "-build-mode:asm", "-out:temp", "-target-features:\"help\"", f"-target:\"{target}\""] process = subprocess.Popen(cmd, stderr=subprocess.PIPE, text=True) state = SEEKING_CPUS @@ -59,7 +59,7 @@ with tempfile.NamedTemporaryFile(suffix=".odin", delete=True) as temp_file: print(f"odin build returned with non-zero exit code {process.returncode}") sys.exit(1) - os.remove("temp.ll") + os.remove("temp.S") def print_default_features(triple, microarch): cmd = ["./featuregen", triple, microarch] diff --git a/odin.rdi b/odin.rdi deleted file mode 100644 index 851ee3578..000000000 Binary files a/odin.rdi and /dev/null differ diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 1826b07c7..d9b04e35f 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -888,6 +888,39 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } + case BuiltinProc_simd_extract_lsbs: + case BuiltinProc_simd_extract_msbs: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; + + if (!is_type_simd_vector(x.type)) { + gbString xs = type_to_string(x.type); + error(x.expr, "'%.*s' expected a simd vector type, got '%s'", LIT(builtin_name), xs); + gb_string_free(xs); + return false; + } + + Type *elem = base_array_type(x.type); + if (!is_type_integer_like(elem)) { + gbString xs = type_to_string(x.type); + error(x.expr, "'%.*s' expected a #simd type with integer or boolean elements, got '%s'", LIT(builtin_name), xs); + gb_string_free(xs); + return false; + } + + i64 num_elems = get_array_type_count(x.type); + + Type *result_type = alloc_type_bit_set(); + result_type->BitSet.elem = t_int; + result_type->BitSet.lower = 0; + result_type->BitSet.upper = num_elems - 1; + + operand->mode = Addressing_Value; + operand->type = result_type; + return true; + } + case BuiltinProc_simd_shuffle: { diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 9084f15f0..5607ea725 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1742,8 +1742,8 @@ gb_internal void add_deps_from_child_to_parent(DeclInfo *decl) { rw_mutex_shared_lock(&decl->type_info_deps_mutex); rw_mutex_lock(&decl->parent->type_info_deps_mutex); - for (Type *t : decl->type_info_deps) { - ptr_set_add(&decl->parent->type_info_deps, t); + for (auto const &tt : decl->type_info_deps) { + type_set_add(&decl->parent->type_info_deps, tt); } rw_mutex_unlock(&decl->parent->type_info_deps_mutex); @@ -1784,6 +1784,10 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de ctx->curr_proc_sig = type; ctx->curr_proc_calling_convention = type->Proc.calling_convention; + if (decl->parent && decl->entity && decl->parent->entity) { + decl->entity->parent_proc_decl = decl->parent; + } + if (ctx->pkg->name != "runtime") { switch (type->Proc.calling_convention) { case ProcCC_None: @@ -1873,6 +1877,8 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de check_open_scope(ctx, body); { + ctx->scope->decl_info = decl; + for (auto const &entry : using_entities) { Entity *uvar = entry.uvar; Entity *prev = scope_insert(ctx->scope, uvar); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index aa176c2b7..6b090af99 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -345,7 +345,7 @@ gb_internal void check_scope_decls(CheckerContext *c, Slice const &nodes, check_collect_entities(c, nodes); for (auto const &entry : s->elements) { - Entity *e = entry.value; + Entity *e = entry.value;\ switch (e->kind) { case Entity_Constant: case Entity_TypeName: @@ -2599,9 +2599,8 @@ gb_internal ExactValue exact_bit_set_all_set_mask(Type *type) { continue; } - BigInt shift_amount = f->Constant.value.value_integer; - big_int_sub_eq(&shift_amount, &b_lower_base); - + BigInt shift_amount = {}; + big_int_sub(&shift_amount, &f->Constant.value.value_integer, &b_lower_base); BigInt value = {}; big_int_shl(&value, &one, &shift_amount); @@ -5509,6 +5508,11 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod case Addressing_SwizzleVariable: operand->mode = Addressing_SwizzleVariable; break; + case Addressing_Value: + if (is_type_pointer(original_type)) { + operand->mode = Addressing_SwizzleVariable; + } + break; } if (array_type->kind == Type_SimdVector) { diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 1708f7c81..e81996566 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1446,8 +1446,8 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ Ast *nil_seen = nullptr; - PtrSet seen = {}; - defer (ptr_set_destroy(&seen)); + TypeSet seen = {}; + defer (type_set_destroy(&seen)); for (Ast *stmt : bs->stmts) { if (stmt->kind != Ast_CaseClause) { @@ -1515,7 +1515,7 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ GB_PANIC("Unknown type to type switch statement"); } - if (type_ptr_set_update(&seen, y.type)) { + if (type_set_update(&seen, y.type)) { TokenPos pos = cc->token.pos; gbString expr_str = expr_to_string(y.expr); error(y.expr, @@ -1569,7 +1569,7 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ auto unhandled = array_make(temporary_allocator(), 0, variants.count); for (Type *t : variants) { - if (!type_ptr_set_exists(&seen, t)) { + if (!type_set_exists(&seen, t)) { array_add(&unhandled, t); } } diff --git a/src/check_type.cpp b/src/check_type.cpp index 4d9101c6c..9d4defbb2 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2859,15 +2859,23 @@ gb_internal void check_matrix_type(CheckerContext *ctx, Type **type, Ast *node) } if (generic_row == nullptr && row_count < MATRIX_ELEMENT_COUNT_MIN) { - gbString s = expr_to_string(row.expr); - error(row.expr, "Invalid matrix row count, expected %d+ rows, got %s", MATRIX_ELEMENT_COUNT_MIN, s); - gb_string_free(s); + if (row.expr == nullptr) { + error(node, "Invalid matrix row count, got nothing"); + } else { + gbString s = expr_to_string(row.expr); + error(row.expr, "Invalid matrix row count, expected %d+ rows, got %s", MATRIX_ELEMENT_COUNT_MIN, s); + gb_string_free(s); + } } if (generic_column == nullptr && column_count < MATRIX_ELEMENT_COUNT_MIN) { - gbString s = expr_to_string(column.expr); - error(column.expr, "Invalid matrix column count, expected %d+ rows, got %s", MATRIX_ELEMENT_COUNT_MIN, s); - gb_string_free(s); + if (column.expr == nullptr) { + error(node, "Invalid matrix column count, got nothing"); + } else { + gbString s = expr_to_string(column.expr); + error(column.expr, "Invalid matrix column count, expected %d+ rows, got %s", MATRIX_ELEMENT_COUNT_MIN, s); + gb_string_free(s); + } } if ((generic_row == nullptr && generic_column == nullptr) && row_count*column_count > MATRIX_ELEMENT_COUNT_MAX) { diff --git a/src/checker.cpp b/src/checker.cpp index bfcabe4fa..bee3f1efe 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3,7 +3,10 @@ #include "entity.cpp" #include "types.cpp" -String get_final_microarchitecture(); + +gb_internal u64 type_hash_canonical_type(Type *type); + +gb_internal String get_final_microarchitecture(); gb_internal void check_expr(CheckerContext *c, Operand *operand, Ast *expression); gb_internal void check_expr_or_type(CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint=nullptr); @@ -170,7 +173,7 @@ gb_internal void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) { d->parent = parent; d->scope = scope; ptr_set_init(&d->deps, 0); - ptr_set_init(&d->type_info_deps, 0); + type_set_init(&d->type_info_deps, 0); d->labels.allocator = heap_allocator(); d->variadic_reuses.allocator = heap_allocator(); d->variadic_reuse_max_bytes = 0; @@ -355,6 +358,10 @@ gb_internal void check_open_scope(CheckerContext *c, Ast *node) { scope->flags |= ScopeFlag_Type; break; } + if (c->decl && c->decl->proc_lit) { + // Number the scopes within a procedure body depth-first + scope->index = c->decl->scope_index++; + } c->scope = scope; c->state_flags |= StateFlag_bounds_check; } @@ -825,11 +832,17 @@ gb_internal void add_dependency(CheckerInfo *info, DeclInfo *d, Entity *e) { rw_mutex_unlock(&d->deps_mutex); } gb_internal void add_type_info_dependency(CheckerInfo *info, DeclInfo *d, Type *type) { - if (d == nullptr) { + if (d == nullptr || type == nullptr) { return; } + if (type->kind == Type_Named) { + Entity *e = type->Named.type_name; + if (e->TypeName.is_type_alias) { + type = type->Named.base; + } + } rw_mutex_lock(&d->type_info_deps_mutex); - ptr_set_add(&d->type_info_deps, type); + type_set_add(&d->type_info_deps, type); rw_mutex_unlock(&d->type_info_deps_mutex); } @@ -1358,8 +1371,11 @@ gb_internal void init_checker_info(CheckerInfo *i) { string_map_init(&i->foreigns); // map_init(&i->gen_procs); map_init(&i->gen_types); - array_init(&i->type_info_types, a); - map_init(&i->type_info_map); + + type_set_init(&i->min_dep_type_info_set); + map_init(&i->min_dep_type_info_index_map); + + // map_init(&i->type_info_map); string_map_init(&i->files); string_map_init(&i->packages); array_init(&i->variable_init_order, a); @@ -1392,8 +1408,10 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { string_map_destroy(&i->foreigns); // map_destroy(&i->gen_procs); map_destroy(&i->gen_types); - array_free(&i->type_info_types); - map_destroy(&i->type_info_map); + + type_set_destroy(&i->min_dep_type_info_set); + map_destroy(&i->min_dep_type_info_index_map); + string_map_destroy(&i->files); string_map_destroy(&i->packages); array_free(&i->variable_init_order); @@ -1627,6 +1645,23 @@ gb_internal void check_remove_expr_info(CheckerContext *c, Ast *e) { } } +gb_internal isize type_info_index(CheckerInfo *info, TypeInfoPair pair, bool error_on_failure) { + mutex_lock(&info->minimum_dependency_type_info_mutex); + + isize entry_index = -1; + u64 hash = pair.hash; + isize *found_entry_index = map_get(&info->min_dep_type_info_index_map, hash); + if (found_entry_index) { + entry_index = *found_entry_index; + } + mutex_unlock(&info->minimum_dependency_type_info_mutex); + + if (error_on_failure && entry_index < 0) { + compiler_error("Type_Info for '%s' could not be found", type_to_string(pair.type)); + } + return entry_index; +} + gb_internal isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) { type = default_type(type); @@ -1634,34 +1669,12 @@ gb_internal isize type_info_index(CheckerInfo *info, Type *type, bool error_on_f type = t_bool; } - mutex_lock(&info->type_info_mutex); - - isize entry_index = -1; - isize *found_entry_index = map_get(&info->type_info_map, type); - if (found_entry_index) { - entry_index = *found_entry_index; - } - if (entry_index < 0) { - // NOTE(bill): Do manual linear search - for (auto const &e : info->type_info_map) { - if (are_types_identical_unique_tuples(e.key, type)) { - entry_index = e.value; - // NOTE(bill): Add it to the search map - map_set(&info->type_info_map, type, entry_index); - break; - } - } - } - - mutex_unlock(&info->type_info_mutex); - - if (error_on_failure && entry_index < 0) { - compiler_error("Type_Info for '%s' could not be found", type_to_string(type)); - } - return entry_index; + u64 hash = type_hash_canonical_type(type); + return type_info_index(info, {type, hash}, error_on_failure); } + gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode, Type *type, ExactValue const &value) { if (expr == nullptr) { return; @@ -2013,8 +2026,12 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { } add_type_info_dependency(c->info, c->decl, t); - +#if 0 MUTEX_GUARD_BLOCK(&c->info->type_info_mutex) { + if (type_set_update(&c->info->type_info_set, t)) { + // return; + } + auto found = map_get(&c->info->type_info_map, t); if (found != nullptr) { // Types have already been added @@ -2037,7 +2054,8 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { // Unique entry // NOTE(bill): map entries grow linearly and in order ti_index = c->info->type_info_types.count; - array_add(&c->info->type_info_types, t); + TypeInfoPair tt = {t, type_hash_canonical_type(t)}; + array_add(&c->info->type_info_types, tt); } map_set(&c->checker->info.type_info_map, t, ti_index); @@ -2232,6 +2250,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind); break; } +#endif } @@ -2289,19 +2308,7 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { return; } - auto *set = &c->info.minimum_dependency_type_info_set; - - isize ti_index = type_info_index(&c->info, t, false); - if (ti_index < 0) { - add_type_info_type(&c->builtin_ctx, t); // Missing the type information - ti_index = type_info_index(&c->info, t, false); - } - GB_ASSERT(ti_index >= 0); - // IMPORTANT NOTE(bill): this must be copied as `map_set` takes a const ref - // and effectively assigns the `+1` of the value - isize const count = set->count; - if (map_set_if_not_previously_exists(set, ti_index+1, count)) { - // Type already exists; + if (type_set_update(&c->info.min_dep_type_info_set, t)) { return; } @@ -2501,8 +2508,8 @@ gb_internal void add_dependency_to_set(Checker *c, Entity *entity) { if (decl == nullptr) { return; } - for (Type *t : decl->type_info_deps) { - add_min_dep_type_info(c, t); + for (TypeInfoPair const tt : decl->type_info_deps) { + add_min_dep_type_info(c, tt.type); } for (Entity *e : decl->deps) { @@ -2702,7 +2709,6 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { isize min_dep_set_cap = next_pow2_isize(entity_count*4); // empirically determined factor ptr_set_init(&c->info.minimum_dependency_set, min_dep_set_cap); - map_init(&c->info.minimum_dependency_type_info_set); #define FORCE_ADD_RUNTIME_ENTITIES(condition, ...) do { \ if (condition) { \ @@ -3894,6 +3900,7 @@ gb_internal DECL_ATTRIBUTE_PROC(type_decl_attribute) { #include "check_expr.cpp" #include "check_builtin.cpp" #include "check_type.cpp" +#include "name_canonicalization.cpp" #include "check_decl.cpp" #include "check_stmt.cpp" @@ -6724,6 +6731,58 @@ gb_internal void check_parsed_files(Checker *c) { add_type_and_value(&c->builtin_ctx, u.expr, u.info->mode, u.info->type, u.info->value); } + TIME_SECTION("initialize and check for collisions in type info array"); + { + Array type_info_types; // sorted after filled + array_init(&type_info_types, heap_allocator()); + defer (array_free(&type_info_types)); + + for (auto const &tt : c->info.min_dep_type_info_set) { + array_add(&type_info_types, tt); + } + array_sort(type_info_types, type_info_pair_cmp); + + array_init(&c->info.type_info_types_hash_map, heap_allocator(), type_info_types.count*2 + 1); + map_reserve(&c->info.min_dep_type_info_index_map, type_info_types.count); + + isize hash_map_len = c->info.type_info_types_hash_map.count; + for (auto const &tt : type_info_types) { + isize index = tt.hash % hash_map_len; + // NOTE(bill): no need for a sanity check since there + // will always be enough space for the entries + for (;;) { + if (index == 0 || c->info.type_info_types_hash_map[index].hash != 0) { + index = (index+1) % hash_map_len; + continue; + } + break; + } + c->info.type_info_types_hash_map[index] = tt; + + bool exists = map_set_if_not_previously_exists(&c->info.min_dep_type_info_index_map, tt.hash, index); + if (exists) { + for (auto const &entry : c->info.min_dep_type_info_index_map) { + if (entry.key != tt.hash) { + continue; + } + auto const &other = type_info_types[entry.value]; + if (are_types_identical_unique_tuples(tt.type, other.type)) { + continue; + } + gbString t = temp_canonical_string(tt.type); + gbString o = temp_canonical_string(other.type); + GB_PANIC("%s (%s) %llu vs %s (%s) %llu", + type_to_string(tt.type, false), t, cast(unsigned long long)tt.hash, + type_to_string(other.type, false), o, cast(unsigned long long)other.hash); + } + } + } + + + GB_ASSERT(c->info.min_dep_type_info_index_map.count <= type_info_types.count); + } + + TIME_SECTION("sort init and fini procedures"); check_sort_init_and_fini_procedures(c); diff --git a/src/checker.hpp b/src/checker.hpp index 4634047c0..d3b2d7d89 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -167,6 +167,7 @@ typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc); gb_internal void check_decl_attributes(CheckerContext *c, Array const &attributes, DeclAttributeProc *proc, AttributeContext *ac); +#include "name_canonicalization.hpp" enum ProcCheckedState : u8 { ProcCheckedState_Unchecked, @@ -221,13 +222,15 @@ struct DeclInfo { RwMutex deps_mutex; PtrSet deps; - RwMutex type_info_deps_mutex; - PtrSet type_info_deps; + RwMutex type_info_deps_mutex; + TypeSet type_info_deps; BlockingMutex type_and_value_mutex; Array labels; + i32 scope_index; + Array variadic_reuses; i64 variadic_reuse_max_bytes; i64 variadic_reuse_max_align; @@ -272,10 +275,14 @@ struct Scope { std::atomic next; std::atomic head_child; + i32 index; // within a procedure + RwMutex mutex; StringMap elements; PtrSet imported; + DeclInfo *decl_info; + i32 flags; // ScopeFlag union { AstPackage *pkg; @@ -421,8 +428,10 @@ struct CheckerInfo { Scope * init_scope; Entity * entry_point; PtrSet minimum_dependency_set; - PtrMap minimum_dependency_type_info_set; - + BlockingMutex minimum_dependency_type_info_mutex; + PtrMap min_dep_type_info_index_map; + TypeSet min_dep_type_info_set; + Array type_info_types_hash_map; // 2 * type_info_types.count Array testing_procedures; @@ -450,9 +459,10 @@ struct CheckerInfo { BlockingMutex gen_types_mutex; PtrMap gen_types; - BlockingMutex type_info_mutex; // NOT recursive - Array type_info_types; - PtrMap type_info_map; + // BlockingMutex type_info_mutex; // NOT recursive + // Array type_info_types; + // PtrMap type_info_map; + // TypeSet type_info_set; BlockingMutex foreign_mutex; // NOT recursive StringMap foreigns; @@ -571,6 +581,7 @@ gb_internal DeclInfo * decl_info_of_entity (Entity * e); gb_internal AstFile * ast_file_of_filename (CheckerInfo *i, String filename); // IMPORTANT: Only to use once checking is done gb_internal isize type_info_index (CheckerInfo *i, Type *type, bool error_on_failure); +gb_internal isize type_info_index (CheckerInfo *info, TypeInfoPair pair, bool error_on_failure); // Will return nullptr if not found gb_internal Entity *entity_of_node(Ast *expr); diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 2dfd570e4..40dde8240 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -181,6 +181,9 @@ BuiltinProc__simd_begin, BuiltinProc_simd_reduce_any, BuiltinProc_simd_reduce_all, + BuiltinProc_simd_extract_lsbs, + BuiltinProc_simd_extract_msbs, + BuiltinProc_simd_shuffle, BuiltinProc_simd_select, @@ -523,6 +526,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("simd_reduce_any"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_reduce_all"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_extract_lsbs"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_extract_msbs"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_shuffle"), 2, true, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_select"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/common.cpp b/src/common.cpp index 0ef39bd10..ad1e5a851 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -134,9 +134,9 @@ gb_internal u32 fnv32a(void const *data, isize len) { return h; } -gb_internal u64 fnv64a(void const *data, isize len) { +gb_internal u64 fnv64a(void const *data, isize len, u64 seed=0xcbf29ce484222325ull) { u8 const *bytes = cast(u8 const *)data; - u64 h = 0xcbf29ce484222325ull; + u64 h = seed; for (; len >= 8; len -= 8, bytes += 8) { h = (h ^ bytes[0]) * 0x100000001b3ull; diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 341b3fa6b..a92ffc7ad 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -16,6 +16,8 @@ gb_global char const* OdinDocWriterState_strings[] { "writing ", }; +gb_global std::atomic g_in_doc_writer; + struct OdinDocWriter { CheckerInfo *info; OdinDocWriterState state; @@ -26,11 +28,10 @@ struct OdinDocWriter { StringMap string_cache; - OrderedInsertPtrMap file_cache; - OrderedInsertPtrMap pkg_cache; - OrderedInsertPtrMap entity_cache; - OrderedInsertPtrMap type_cache; - OrderedInsertPtrMap stable_type_cache; + OrderedInsertPtrMap file_cache; + OrderedInsertPtrMap pkg_cache; + OrderedInsertPtrMap entity_cache; + OrderedInsertPtrMap type_cache; OdinDocWriterItemTracker files; OdinDocWriterItemTracker pkgs; @@ -61,7 +62,6 @@ gb_internal void odin_doc_writer_prepare(OdinDocWriter *w) { map_init(&w->pkg_cache, 1<<10); map_init(&w->entity_cache, 1<<18); map_init(&w->type_cache, 1<<18); - map_init(&w->stable_type_cache, 1<<18); odin_doc_writer_item_tracker_init(&w->files, 1); odin_doc_writer_item_tracker_init(&w->pkgs, 1); @@ -81,7 +81,6 @@ gb_internal void odin_doc_writer_destroy(OdinDocWriter *w) { map_destroy(&w->pkg_cache); map_destroy(&w->entity_cache); map_destroy(&w->type_cache); - map_destroy(&w->stable_type_cache); } @@ -492,55 +491,18 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { } } - // Type **mapped_type = map_get(&w->stable_type_cache, type); // may map to itself - // if (mapped_type && *mapped_type) { - // type = *mapped_type; - // } - - OdinDocTypeIndex *found = map_get(&w->type_cache, type); + u64 type_hash = type_hash_canonical_type(type); + OdinDocTypeIndex *found = map_get(&w->type_cache, type_hash); if (found) { return *found; } - for (auto const &entry : w->type_cache) { - // NOTE(bill): THIS IS SLOW - Type *x = type; - Type *y = entry.key; - - if (x == y) { - goto do_set; - } - - if (!x | !y) { - continue; - } - if (y->kind == Type_Named) { - Entity *e = y->Named.type_name; - if (e->TypeName.is_type_alias) { - y = y->Named.base; - } - } - if (x->kind != y->kind) { - continue; - } - - if (!are_types_identical_internal(x, y, true)) { - continue; - } - - do_set: - OdinDocTypeIndex index = entry.value; - map_set(&w->type_cache, type, index); - map_set(&w->stable_type_cache, type, entry.key); - return index; - } OdinDocType *dst = nullptr; OdinDocType doc_type = {}; OdinDocTypeIndex type_index = 0; type_index = odin_doc_write_item(w, &w->types, &doc_type, &dst); - map_set(&w->type_cache, type, type_index); - map_set(&w->stable_type_cache, type, type); + map_set(&w->type_cache, type_hash, type_index); switch (type->kind) { case Type_Basic: @@ -1177,6 +1139,8 @@ gb_internal void odin_doc_write_to_file(OdinDocWriter *w, char const *filename) } gb_internal void odin_doc_write(CheckerInfo *info, char const *filename) { + g_in_doc_writer.store(true); + OdinDocWriter w_ = {}; OdinDocWriter *w = &w_; defer (odin_doc_writer_destroy(w)); @@ -1192,4 +1156,11 @@ gb_internal void odin_doc_write(CheckerInfo *info, char const *filename) { odin_doc_writer_end_writing(w); odin_doc_write_to_file(w, filename); + + g_in_doc_writer.store(false); } + + +gb_internal bool is_in_doc_writer(void) { + return g_in_doc_writer.load(); +} \ No newline at end of file diff --git a/src/entity.cpp b/src/entity.cpp index d137a8674..b2148aa7b 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -257,6 +257,7 @@ struct Entity { bool has_instrumentation : 1; bool is_memcpy_like : 1; bool uses_branch_location : 1; + bool is_anonymous : 1; } Procedure; struct { Array entities; diff --git a/src/gb/gb.h b/src/gb/gb.h index 59611ceb6..98c362e93 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -5856,7 +5856,7 @@ gb_inline isize gb_fprintf_va(struct gbFile *f, char const *fmt, va_list va) { gb_inline char *gb_bprintf_va(char const *fmt, va_list va) { - gb_local_persist char buffer[4096]; + gb_thread_local gb_local_persist char buffer[4096]; gb_snprintf_va(buffer, gb_size_of(buffer), fmt, va); return buffer; } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 0896ea8c7..88e099930 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -24,7 +24,7 @@ #include "llvm_backend_stmt.cpp" #include "llvm_backend_proc.cpp" -String get_default_microarchitecture() { +gb_internal String get_default_microarchitecture() { String default_march = str_lit("generic"); if (build_context.metrics.arch == TargetArch_amd64) { // NOTE(bill): x86-64-v2 is more than enough for everyone @@ -47,7 +47,7 @@ String get_default_microarchitecture() { return default_march; } -String get_final_microarchitecture() { +gb_internal String get_final_microarchitecture() { BuildContext *bc = &build_context; String microarch = bc->microarch; @@ -169,7 +169,7 @@ gb_internal void lb_correct_entity_linkage(lbGenerator *gen) { other_global = LLVMGetNamedGlobal(ec.other_module->mod, ec.cname); if (other_global) { LLVMSetLinkage(other_global, LLVMWeakAnyLinkage); - if (!ec.e->Variable.is_export) { + if (!ec.e->Variable.is_export && !ec.e->Variable.is_foreign) { LLVMSetVisibility(other_global, LLVMHiddenVisibility); } } @@ -177,7 +177,7 @@ gb_internal void lb_correct_entity_linkage(lbGenerator *gen) { other_global = LLVMGetNamedFunction(ec.other_module->mod, ec.cname); if (other_global) { LLVMSetLinkage(other_global, LLVMWeakAnyLinkage); - if (!ec.e->Procedure.is_export) { + if (!ec.e->Procedure.is_export && !ec.e->Procedure.is_foreign) { LLVMSetVisibility(other_global, LLVMHiddenVisibility); } } @@ -233,6 +233,16 @@ gb_internal lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx } +gb_internal String lb_internal_gen_name_from_type(char const *prefix, Type *type) { + gbString str = gb_string_make(permanent_allocator(), prefix); + u64 hash = type_hash_canonical_type(type); + str = gb_string_appendc(str, "-"); + str = gb_string_append_fmt(str, "%llu", cast(unsigned long long)hash); + String proc_name = make_string(cast(u8 const *)str, gb_string_length(str)); + return proc_name; +} + + gb_internal lbValue lb_equal_proc_for_type(lbModule *m, Type *type) { type = base_type(type); GB_ASSERT(is_type_comparable(type)); @@ -240,7 +250,8 @@ gb_internal lbValue lb_equal_proc_for_type(lbModule *m, Type *type) { Type *pt = alloc_type_pointer(type); LLVMTypeRef ptr_type = lb_type(m, pt); - lbProcedure **found = map_get(&m->equal_procs, type); + String proc_name = lb_internal_gen_name_from_type("__$equal", type); + lbProcedure **found = string_map_get(&m->gen_procs, proc_name); lbProcedure *compare_proc = nullptr; if (found) { compare_proc = *found; @@ -248,17 +259,12 @@ gb_internal lbValue lb_equal_proc_for_type(lbModule *m, Type *type) { return {compare_proc->value, compare_proc->type}; } - static std::atomic proc_index; - - char buf[32] = {}; - isize n = gb_snprintf(buf, 32, "__$equal%u", 1+proc_index.fetch_add(1)); - char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); - String proc_name = make_string_c(str); lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_equal_proc); - map_set(&m->equal_procs, type, p); + string_map_set(&m->gen_procs, proc_name, p); lb_begin_procedure_body(p); + LLVMSetLinkage(p->value, LLVMInternalLinkage); // lb_add_attribute_to_proc(m, p->value, "readonly"); lb_add_attribute_to_proc(m, p->value, "nounwind"); @@ -410,24 +416,19 @@ gb_internal lbValue lb_hasher_proc_for_type(lbModule *m, Type *type) { Type *pt = alloc_type_pointer(type); - lbProcedure **found = map_get(&m->hasher_procs, type); + String proc_name = lb_internal_gen_name_from_type("__$hasher", type); + lbProcedure **found = string_map_get(&m->gen_procs, proc_name); if (found) { GB_ASSERT(*found != nullptr); return {(*found)->value, (*found)->type}; } - static std::atomic proc_index; - - char buf[32] = {}; - isize n = gb_snprintf(buf, 32, "__$hasher%u", 1+proc_index.fetch_add(1)); - char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); - String proc_name = make_string_c(str); - lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_hasher_proc); - map_set(&m->hasher_procs, type, p); + string_map_set(&m->gen_procs, proc_name, p); lb_begin_procedure_body(p); defer (lb_end_procedure_body(p)); + LLVMSetLinkage(p->value, LLVMInternalLinkage); // lb_add_attribute_to_proc(m, p->value, "readonly"); lb_add_attribute_to_proc(m, p->value, "nounwind"); @@ -577,21 +578,15 @@ gb_internal lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) { type = base_type(type); GB_ASSERT(type->kind == Type_Map); - - lbProcedure **found = map_get(&m->map_get_procs, type); + String proc_name = lb_internal_gen_name_from_type("__$map_get", type); + lbProcedure **found = string_map_get(&m->gen_procs, proc_name); if (found) { GB_ASSERT(*found != nullptr); return {(*found)->value, (*found)->type}; } - static std::atomic proc_index; - - char buf[32] = {}; - isize n = gb_snprintf(buf, 32, "__$map_get-%u", 1+proc_index.fetch_add(1)); - char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); - String proc_name = make_string_c(str); lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_map_get_proc); - map_set(&m->map_get_procs, type, p); + string_map_set(&m->gen_procs, proc_name, p); lb_begin_procedure_body(p); defer (lb_end_procedure_body(p)); @@ -758,21 +753,15 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) { type = base_type(type); GB_ASSERT(type->kind == Type_Map); - - lbProcedure **found = map_get(&m->map_set_procs, type); + String proc_name = lb_internal_gen_name_from_type("__$map_set", type); + lbProcedure **found = string_map_get(&m->gen_procs, proc_name); if (found) { GB_ASSERT(*found != nullptr); return {(*found)->value, (*found)->type}; } - static std::atomic proc_index; - - char buf[32] = {}; - isize n = gb_snprintf(buf, 32, "__$map_set-%u", 1+proc_index.fetch_add(1)); - char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); - String proc_name = make_string_c(str); lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_map_set_proc); - map_set(&m->map_set_procs, type, p); + string_map_set(&m->gen_procs, proc_name, p); lb_begin_procedure_body(p); defer (lb_end_procedure_body(p)); @@ -917,7 +906,7 @@ gb_internal lbValue lb_gen_map_cell_info_ptr(lbModule *m, Type *type) { LLVMValueRef llvm_res = llvm_const_named_struct(m, t_map_cell_info, const_values, gb_count_of(const_values)); lbValue res = {llvm_res, t_map_cell_info}; - lbAddr addr = lb_add_global_generated(m, t_map_cell_info, res, nullptr); + lbAddr addr = lb_add_global_generated_with_name(m, t_map_cell_info, res, lb_internal_gen_name_from_type("ggv$map_cell_info", type)); lb_make_global_private_const(addr); map_set(&m->map_cell_info_map, type, addr); @@ -948,7 +937,7 @@ gb_internal lbValue lb_gen_map_info_ptr(lbModule *m, Type *map_type) { LLVMValueRef llvm_res = llvm_const_named_struct(m, t_map_info, const_values, gb_count_of(const_values)); lbValue res = {llvm_res, t_map_info}; - lbAddr addr = lb_add_global_generated(m, t_map_info, res, nullptr); + lbAddr addr = lb_add_global_generated_with_name(m, t_map_info, res, lb_internal_gen_name_from_type("ggv$map_info", map_type)); lb_make_global_private_const(addr); map_set(&m->map_info_map, map_type, addr); @@ -1284,7 +1273,10 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc if (is_type_any(t)) { // NOTE(bill): Edge case for 'any' type Type *var_type = default_type(var.init.type); - lbAddr g = lb_add_global_generated(main_module, var_type, var.init); + gbString var_name = gb_string_make(permanent_allocator(), "__$global_any::"); + gbString e_str = string_canonical_entity_name(temporary_allocator(), e); + var_name = gb_string_append_length(var_name, e_str, gb_strlen(e_str)); + lbAddr g = lb_add_global_generated_with_name(main_module, var_type, var.init, make_string_c(var_name)); lb_addr_store(p, g, var.init); lbValue gp = lb_addr_get_ptr(p, g); @@ -1563,21 +1555,13 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { } } - for (auto const &entry : m->equal_procs) { + for (auto const &entry : m->gen_procs) { lbProcedure *p = entry.value; - lb_llvm_function_pass_per_function_internal(m, p); - } - for (auto const &entry : m->hasher_procs) { - lbProcedure *p = entry.value; - lb_llvm_function_pass_per_function_internal(m, p); - } - for (auto const &entry : m->map_get_procs) { - lbProcedure *p = entry.value; - lb_llvm_function_pass_per_function_internal(m, p, lbFunctionPassManager_none); - } - for (auto const &entry : m->map_set_procs) { - lbProcedure *p = entry.value; - lb_llvm_function_pass_per_function_internal(m, p, lbFunctionPassManager_none); + if (string_starts_with(p->name, str_lit("__$map"))) { + lb_llvm_function_pass_per_function_internal(m, p, lbFunctionPassManager_none); + } else { + lb_llvm_function_pass_per_function_internal(m, p); + } } return 0; @@ -2575,17 +2559,16 @@ gb_internal String lb_filepath_ll_for_module(lbModule *m) { build_context.build_paths[BuildPath_Output].name ); - if (m->file) { - char buf[32] = {}; - isize n = gb_snprintf(buf, gb_size_of(buf), "-%u", m->file->id); - String suffix = make_string((u8 *)buf, n-1); - path = concatenate_strings(permanent_allocator(), path, suffix); - } else if (m->pkg) { - path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name); - } else if (USE_SEPARATE_MODULES) { - path = concatenate_strings(permanent_allocator(), path, STR_LIT("-builtin")); + GB_ASSERT(m->module_name != nullptr); + String s = make_string_c(m->module_name); + String prefix = str_lit("odin_package-"); + if (string_starts_with(s, prefix)) { + s.text += prefix.len; + s.len -= prefix.len; } - path = concatenate_strings(permanent_allocator(), path, STR_LIT(".ll")); + + path = concatenate_strings(permanent_allocator(), path, s); + path = concatenate_strings(permanent_allocator(), s, STR_LIT(".ll")); return path; } @@ -2608,17 +2591,21 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { path = gb_string_appendc(path, "/"); path = gb_string_append_length(path, name.text, name.len); - if (m->file) { - char buf[32] = {}; - isize n = gb_snprintf(buf, gb_size_of(buf), "-%u", m->file->id); - String suffix = make_string((u8 *)buf, n-1); - path = gb_string_append_length(path, suffix.text, suffix.len); - } else if (m->pkg) { - path = gb_string_appendc(path, "-"); - path = gb_string_append_length(path, m->pkg->name.text, m->pkg->name.len); + { + + GB_ASSERT(m->module_name != nullptr); + String s = make_string_c(m->module_name); + String prefix = str_lit("odin_package"); + if (string_starts_with(s, prefix)) { + s.text += prefix.len; + s.len -= prefix.len; + } + + path = gb_string_append_length(path, s.text, s.len); } if (use_temporary_directory) { + // NOTE(bill): this must be suffixed to ensure it is not conflicting with anything else in the temporary directory path = gb_string_append_fmt(path, "-%p", m); } @@ -2825,7 +2812,7 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test")); Type *array_type = alloc_type_array(t_Internal_Test, m->info->testing_procedures.count); Type *slice_type = alloc_type_slice(t_Internal_Test); - lbAddr all_tests_array_addr = lb_add_global_generated(p->module, array_type, {}); + lbAddr all_tests_array_addr = lb_add_global_generated_with_name(p->module, array_type, {}, str_lit("__$all_tests_array")); lbValue all_tests_array = lb_addr_get_ptr(p, all_tests_array_addr); LLVMValueRef indices[2] = {}; @@ -3154,7 +3141,10 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { lbModule *m = default_module; { // Add type info data - isize max_type_info_count = info->minimum_dependency_type_info_set.count+1; + // GB_ASSERT_MSG(info->minimum_dependency_type_info_index_map.count == info->type_info_types.count, "%tu vs %tu", info->minimum_dependency_type_info_index_map.count, info->type_info_types.count); + + // isize max_type_info_count = info->minimum_dependency_type_info_index_map.count+1; + isize max_type_info_count = info->type_info_types_hash_map.count; Type *t = alloc_type_array(t_type_info_ptr, max_type_info_count); // IMPORTANT NOTE(bill): As LLVM does not have a union type, an array of unions cannot be initialized @@ -3166,7 +3156,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMValueRef g = LLVMAddGlobal(m->mod, internal_llvm_type, LB_TYPE_INFO_DATA_NAME); LLVMSetInitializer(g, LLVMConstNull(internal_llvm_type)); LLVMSetLinkage(g, USE_SEPARATE_MODULES ? LLVMExternalLinkage : LLVMInternalLinkage); - LLVMSetUnnamedAddress(g, LLVMGlobalUnnamedAddr); + // LLVMSetUnnamedAddress(g, LLVMGlobalUnnamedAddr); LLVMSetGlobalConstant(g, true); lbValue value = {}; @@ -3182,7 +3172,11 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { isize count = 0; isize offsets_extra = 0; - for (Type *t : m->info->type_info_types) { + for (auto const &tt : m->info->type_info_types_hash_map) { + Type *t = tt.type; + if (t == nullptr) { + continue; + } isize index = lb_type_info_index(m->info, t, false); if (index < 0) { continue; diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index a0775ac3b..4fd1b8d1a 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -160,15 +160,17 @@ struct lbModule { AstFile *file; // possibly associated char const *module_name; - PtrMap types; // mutex: types_mutex + PtrMap types; // mutex: types_mutex PtrMap struct_field_remapping; // Key: LLVMTypeRef or Type *, mutex: types_mutex - PtrMap func_raw_types; // mutex: func_raw_types_mutex - RecursiveMutex types_mutex; - RecursiveMutex func_raw_types_mutex; + PtrMap func_raw_types; // mutex: func_raw_types_mutex + RecursiveMutex types_mutex; + RecursiveMutex func_raw_types_mutex; i32 internal_type_level; RwMutex values_mutex; + std::atomic global_array_index; + PtrMap values; PtrMap soa_values; StringMap members; @@ -178,14 +180,9 @@ struct lbModule { StringMap const_strings; - PtrMap function_type_map; + PtrMap function_type_map; - PtrMap equal_procs; - PtrMap hasher_procs; - PtrMap map_get_procs; - PtrMap map_set_procs; - - std::atomic nested_type_name_guid; + StringMap gen_procs; // key is the canonicalized name Array procedures_to_generate; Array global_procedures_to_create; @@ -204,8 +201,8 @@ struct lbModule { StringMap objc_classes; StringMap objc_selectors; - PtrMap map_cell_info_map; // address of runtime.Map_Info - PtrMap map_info_map; // address of runtime.Map_Cell_Info + PtrMap map_cell_info_map; // address of runtime.Map_Info + PtrMap map_info_map; // address of runtime.Map_Cell_Info PtrMap exact_value_compound_literal_addr_map; // Key: Ast_CompoundLit @@ -231,9 +228,6 @@ struct lbGenerator : LinkerData { RecursiveMutex anonymous_proc_lits_mutex; PtrMap anonymous_proc_lits; - std::atomic global_array_index; - std::atomic global_generated_index; - isize used_module_count; lbProcedure *startup_runtime; @@ -364,6 +358,8 @@ struct lbProcedure { bool in_multi_assignment; Array raw_input_parameters; + u32 global_generated_index; + bool uses_branch_location; TokenPos branch_location_pos; TokenPos curr_token_pos; @@ -399,7 +395,7 @@ struct lbProcedure { gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c); gb_internal String lb_mangle_name(Entity *e); -gb_internal String lb_get_entity_name(lbModule *m, Entity *e, String name = {}); +gb_internal String lb_get_entity_name(lbModule *m, Entity *e); gb_internal LLVMAttributeRef lb_create_enum_attribute(LLVMContextRef ctx, char const *name, u64 value=0); gb_internal LLVMAttributeRef lb_create_enum_attribute_with_type(LLVMContextRef ctx, char const *name, LLVMTypeRef type); @@ -473,7 +469,8 @@ gb_internal lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx gb_internal lbContextData *lb_push_context_onto_stack_from_implicit_parameter(lbProcedure *p); -gb_internal lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value={}, Entity **entity_=nullptr); +gb_internal lbAddr lb_add_global_generated_from_procedure(lbProcedure *p, Type *type, lbValue value={}); +gb_internal lbAddr lb_add_global_generated_with_name(lbModule *m, Type *type, lbValue value, String name, Entity **entity_=nullptr); gb_internal lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e=nullptr, bool zero_init=true, bool force_no_init=false); gb_internal void lb_add_foreign_library_path(lbModule *m, Entity *e); @@ -610,6 +607,9 @@ gb_internal LLVMTypeRef llvm_array_type(LLVMTypeRef ElementType, uint64_t Elemen } +gb_internal String lb_internal_gen_name_from_type(char const *prefix, Type *type); + + gb_internal void lb_set_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name, u64 value); gb_internal u64 lb_get_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name); diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 754bbfca2..b916c0017 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -330,31 +330,57 @@ gb_internal lbValue lb_emit_source_code_location_const(lbProcedure *p, Ast *node return lb_emit_source_code_location_const(p, proc_name, pos); } +gb_internal String lb_source_code_location_gen_name(String const &procedure, TokenPos const &pos) { + gbString s = gb_string_make(permanent_allocator(), "scl$["); + + s = gb_string_append_length(s, procedure.text, procedure.len); + if (pos.offset != 0) { + s = gb_string_append_fmt(s, "%d", pos.offset); + } else { + s = gb_string_append_fmt(s, "%d_%d", pos.line, pos.column); + } + s = gb_string_appendc(s, "]"); + + return make_string(cast(u8 const *)s, gb_string_length(s)); +} + +gb_internal String lb_source_code_location_gen_name(lbProcedure *p, Ast *node) { + String proc_name = {}; + if (p->entity) { + proc_name = p->entity->token.string; + } + TokenPos pos = {}; + if (node) { + pos = ast_token(node).pos; + } + return lb_source_code_location_gen_name(proc_name, pos); +} + + gb_internal lbValue lb_emit_source_code_location_as_global_ptr(lbProcedure *p, String const &procedure, TokenPos const &pos) { lbValue loc = lb_emit_source_code_location_const(p, procedure, pos); - lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr); + lbAddr addr = lb_add_global_generated_with_name(p->module, loc.type, loc, lb_source_code_location_gen_name(procedure, pos)); lb_make_global_private_const(addr); return addr.addr; } gb_internal lbValue lb_const_source_code_location_as_global_ptr(lbModule *m, String const &procedure, TokenPos const &pos) { lbValue loc = lb_const_source_code_location_const(m, procedure, pos); - lbAddr addr = lb_add_global_generated(m, loc.type, loc, nullptr); + lbAddr addr = lb_add_global_generated_with_name(m, loc.type, loc, lb_source_code_location_gen_name(procedure, pos)); lb_make_global_private_const(addr); return addr.addr; } - - - gb_internal lbValue lb_emit_source_code_location_as_global_ptr(lbProcedure *p, Ast *node) { lbValue loc = lb_emit_source_code_location_const(p, node); - lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr); + lbAddr addr = lb_add_global_generated_with_name(p->module, loc.type, loc, lb_source_code_location_gen_name(p, node)); lb_make_global_private_const(addr); return addr.addr; } + + gb_internal lbValue lb_emit_source_code_location_as_global(lbProcedure *p, String const &procedure, TokenPos const &pos) { return lb_emit_load(p, lb_emit_source_code_location_as_global_ptr(p, procedure, pos)); } @@ -562,12 +588,12 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo return lb_addr_load(p, slice); } } else { - isize max_len = 7+8+1; - char *str = gb_alloc_array(permanent_allocator(), char, max_len); - u32 id = m->gen->global_array_index.fetch_add(1); - isize len = gb_snprintf(str, max_len, "csba$%x", id); + u32 id = m->global_array_index.fetch_add(1); + gbString str = gb_string_make(temporary_allocator(), "csba$"); + str = gb_string_appendc(str, m->module_name); + str = gb_string_append_fmt(str, "$%x", id); - String name = make_string(cast(u8 *)str, len-1); + String name = make_string(cast(u8 const *)str, gb_string_length(str)); Entity *e = alloc_entity_constant(nullptr, make_token_ident(name), t, value); array_data = LLVMAddGlobal(m->mod, lb_type(m, t), str); diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index fbb25960a..067004bc1 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -843,7 +843,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { 8*cast(unsigned)type_align_of(type), lb_debug_type(m, type->EnumeratedArray.elem), subscripts, gb_count_of(subscripts)); - gbString name = type_to_string(type, temporary_allocator()); + gbString name = temp_canonical_string(type); return LLVMDIBuilderCreateTypedef(m->debug_builder, array_type, name, gb_string_length(name), nullptr, 0, nullptr, cast(u32)(8*type_align_of(type))); } @@ -852,16 +852,16 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { Type *bt = base_type(type->Map.debug_metadata_type); GB_ASSERT(bt->kind == Type_Struct); - return lb_debug_struct(m, type, bt, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); + return lb_debug_struct(m, type, bt, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); } - case Type_Struct: return lb_debug_struct( m, type, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); - case Type_Slice: return lb_debug_slice( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); - case Type_DynamicArray: return lb_debug_dynamic_array(m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); - case Type_Union: return lb_debug_union( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); - case Type_BitSet: return lb_debug_bitset( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); - case Type_Enum: return lb_debug_enum( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); - case Type_BitField: return lb_debug_bitfield( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); + case Type_Struct: return lb_debug_struct( m, type, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); + case Type_Slice: return lb_debug_slice( m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); + case Type_DynamicArray: return lb_debug_dynamic_array(m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); + case Type_Union: return lb_debug_union( m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); + case Type_BitSet: return lb_debug_bitset( m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); + case Type_Enum: return lb_debug_enum( m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); + case Type_BitField: return lb_debug_bitfield( m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); case Type_Tuple: if (type->Tuple.variables.count == 1) { @@ -904,7 +904,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { { LLVMMetadataRef proc_underlying_type = lb_debug_type_internal_proc(m, type); LLVMMetadataRef pointer_type = LLVMDIBuilderCreatePointerType(m->debug_builder, proc_underlying_type, ptr_bits, ptr_bits, 0, nullptr, 0); - gbString name = type_to_string(type, temporary_allocator()); + gbString name = temp_canonical_string(type); return LLVMDIBuilderCreateTypedef(m->debug_builder, pointer_type, name, gb_string_length(name), nullptr, 0, nullptr, cast(u32)(8*type_align_of(type))); } break; @@ -987,10 +987,7 @@ gb_internal LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) { line = cast(unsigned)e->token.pos.line; } - String name = type->Named.name; - if (type->Named.type_name && type->Named.type_name->pkg && type->Named.type_name->pkg->name.len != 0) { - name = concatenate3_strings(temporary_allocator(), type->Named.type_name->pkg->name, str_lit("."), type->Named.name); - } + String name = type_to_canonical_string(temporary_allocator(), type); Type *bt = base_type(type->Named.base); @@ -1187,8 +1184,8 @@ gb_internal void lb_add_debug_context_variable(lbProcedure *p, lbAddr const &ctx gb_internal String debug_info_mangle_constant_name(Entity *e, gbAllocator const &allocator, bool *did_allocate_) { String name = e->token.string; if (e->pkg && e->pkg->name.len > 0) { - // NOTE(bill): C++ NONSENSE FOR DEBUG SHITE! - name = concatenate3_strings(allocator, e->pkg->name, str_lit("::"), name); + gbString s = string_canonical_entity_name(allocator, e); + name = make_string(cast(u8 const *)s, gb_string_length(s)); if (did_allocate_) *did_allocate_ = true; } return name; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 693f2e225..56c7b45ec 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1554,7 +1554,7 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { lbValue cmp = lb_emit_comp_against_nil(p, be->op.kind, right); Type *type = default_type(tv.type); return lb_emit_conv(p, cmp, type); - } else if (lb_is_empty_string_constant(be->right)) { + } else if (lb_is_empty_string_constant(be->right) && !is_type_union(be->left->tav.type)) { // `x == ""` or `x != ""` lbValue s = lb_build_expr(p, be->left); s = lb_emit_conv(p, s, t_string); @@ -1562,7 +1562,7 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { lbValue cmp = lb_emit_comp(p, be->op.kind, len, lb_const_int(p->module, t_int, 0)); Type *type = default_type(tv.type); return lb_emit_conv(p, cmp, type); - } else if (lb_is_empty_string_constant(be->left)) { + } else if (lb_is_empty_string_constant(be->left) && !is_type_union(be->right->tav.type)) { // `"" == x` or `"" != x` lbValue s = lb_build_expr(p, be->right); s = lb_emit_conv(p, s, t_string); @@ -2312,9 +2312,9 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { lbValue array_const_value = {}; array_const_value.type = t; array_const_value.value = LLVMConstArray(lb_type(m, elem), values, cast(unsigned)index_count); - v = lb_add_global_generated(m, t, array_const_value); + v = lb_add_global_generated_from_procedure(p, t, array_const_value); } else { - v = lb_add_global_generated(m, t); + v = lb_add_global_generated_from_procedure(p, t); } lb_make_global_private_const(v); @@ -3004,7 +3004,16 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left LLVMTypeRef mask_int_type = LLVMIntTypeInContext(p->module->ctx, cast(unsigned)(8*type_size_of(a))); LLVMValueRef mask_int = LLVMBuildBitCast(p->builder, mask, mask_int_type, ""); - res.value = LLVMBuildICmp(p->builder, LLVMIntNE, mask_int, LLVMConstNull(LLVMTypeOf(mask_int)), ""); + + switch (op_kind) { + case Token_CmpEq: + res.value = LLVMBuildICmp(p->builder, LLVMIntEQ, mask_int, LLVMConstInt(mask_int_type, U64_MAX, true), ""); + break; + case Token_NotEq: + res.value = LLVMBuildICmp(p->builder, LLVMIntNE, mask_int, LLVMConstNull(mask_int_type), ""); + break; + } + return res; } else { @@ -3255,7 +3264,7 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { Type *type = v.type; lbAddr addr = {}; if (p->is_startup) { - addr = lb_add_global_generated(p->module, type, v); + addr = lb_add_global_generated_from_procedure(p, type, v); } else { addr = lb_add_local_generated(p, type, false); } @@ -3842,7 +3851,7 @@ gb_internal lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *exp Type *t = default_type(type_of_expr(expr)); lbValue v = lb_const_value(p->module, t, e->Constant.value); if (LLVMIsConstant(v.value)) { - lbAddr g = lb_add_global_generated(p->module, t, v); + lbAddr g = lb_add_global_generated_from_procedure(p, t, v); return g; } GB_ASSERT(LLVMIsALoadInst(v.value)); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 7425b9fd7..71d368ec9 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -18,17 +18,36 @@ gb_global isize lb_global_type_info_member_tags_index = 0; gb_internal void lb_init_module(lbModule *m, Checker *c) { m->info = &c->info; - gbString module_name = gb_string_make(heap_allocator(), "odin_package"); - if (m->file) { - module_name = gb_string_append_fmt(module_name, "-%u", m->file->id+1); + + String name = build_context.build_paths[BuildPath_Output].name; + gbString module_name = gb_string_make(heap_allocator(), ""); + module_name = gb_string_append_length(module_name, name.text, name.len); + + if (!USE_SEPARATE_MODULES) { + // ignore suffixes + } else if (m->file) { + if (gb_string_length(module_name)) { + module_name = gb_string_appendc(module_name, "-"); + } + if (m->pkg) { + module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len); + module_name = gb_string_appendc(module_name, "-"); + } + String filename = filename_from_path(m->file->filename); + module_name = gb_string_append_length(module_name, filename.text, filename.len); } else if (m->pkg) { - module_name = gb_string_appendc(module_name, "-"); + if (gb_string_length(module_name)) { + module_name = gb_string_appendc(module_name, "-"); + } module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len); - } else if (USE_SEPARATE_MODULES) { - module_name = gb_string_appendc(module_name, "-builtin"); + } else { + if (gb_string_length(module_name)) { + module_name = gb_string_appendc(module_name, "-"); + } + module_name = gb_string_appendc(module_name, "builtin"); } - m->module_name = module_name ? module_name : "odin_package"; + m->module_name = module_name; m->ctx = LLVMContextCreate(); m->mod = LLVMModuleCreateWithNameInContext(m->module_name, m->ctx); // m->debug_builder = nullptr; @@ -67,10 +86,7 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { string_map_init(&m->procedures); string_map_init(&m->const_strings); map_init(&m->function_type_map); - map_init(&m->equal_procs); - map_init(&m->hasher_procs); - map_init(&m->map_get_procs); - map_init(&m->map_set_procs); + string_map_init(&m->gen_procs); if (USE_SEPARATE_MODULES) { array_init(&m->procedures_to_generate, a, 0, 1<<10); map_init(&m->procedure_values, 1<<11); @@ -218,7 +234,7 @@ gb_internal void lb_loop_end(lbProcedure *p, lbLoopData const &data) { gb_internal void lb_make_global_private_const(LLVMValueRef global_data) { LLVMSetLinkage(global_data, LLVMLinkerPrivateLinkage); - LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr); + // LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr); LLVMSetGlobalConstant(global_data, true); } gb_internal void lb_make_global_private_const(lbAddr const &addr) { @@ -1010,7 +1026,7 @@ gb_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) { LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); return; } else if (LLVMIsConstant(value.value)) { - lbAddr addr = lb_add_global_generated(p->module, value.type, value, nullptr); + lbAddr addr = lb_add_global_generated_from_procedure(p, value.type, value); lb_make_global_private_const(addr); LLVMValueRef dst_ptr = ptr.value; @@ -1443,148 +1459,30 @@ gb_internal void lb_clone_struct_type(LLVMTypeRef dst, LLVMTypeRef src) { LLVMStructSetBody(dst, fields, field_count, LLVMIsPackedStruct(src)); } -gb_internal String lb_mangle_name(Entity *e) { - String name = e->token.string; - - AstPackage *pkg = e->pkg; - GB_ASSERT_MSG(pkg != nullptr, "Missing package for '%.*s'", LIT(name)); - String pkgn = pkg->name; - GB_ASSERT(!rune_is_digit(pkgn[0])); - if (pkgn == "llvm") { - pkgn = str_lit("llvm$"); - } - - isize max_len = pkgn.len + 1 + name.len + 1; - bool require_suffix_id = is_type_polymorphic(e->type, true); - - if ((e->scope->flags & (ScopeFlag_File | ScopeFlag_Pkg)) == 0) { - require_suffix_id = true; - } else if (is_blank_ident(e->token)) { - require_suffix_id = true; - }if (e->flags & EntityFlag_NotExported) { - require_suffix_id = true; - } - - if (require_suffix_id) { - max_len += 21; - } - - char *new_name = gb_alloc_array(permanent_allocator(), char, max_len); - isize new_name_len = gb_snprintf( - new_name, max_len, - "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s", LIT(pkgn), LIT(name) - ); - if (require_suffix_id) { - char *str = new_name + new_name_len-1; - isize len = max_len-new_name_len; - isize extra = gb_snprintf(str, len, "-%llu", cast(unsigned long long)e->id); - new_name_len += extra-1; - } - - String mangled_name = make_string((u8 const *)new_name, new_name_len-1); - return mangled_name; -} - -gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedure *p, lbModule *module) { - // NOTE(bill, 2020-03-08): A polymorphic procedure may take a nested type declaration - // and as a result, the declaration does not have time to determine what it should be - - GB_ASSERT(e != nullptr && e->kind == Entity_TypeName); - if (e->TypeName.ir_mangled_name.len != 0) { - return e->TypeName.ir_mangled_name; - } - GB_ASSERT((e->scope->flags & ScopeFlag_File) == 0); - - if (p == nullptr) { - Entity *proc = nullptr; - if (e->parent_proc_decl != nullptr) { - proc = e->parent_proc_decl->entity; - } else { - Scope *scope = e->scope; - while (scope != nullptr && (scope->flags & ScopeFlag_Proc) == 0) { - scope = scope->parent; - } - GB_ASSERT(scope != nullptr); - GB_ASSERT(scope->flags & ScopeFlag_Proc); - proc = scope->procedure_entity; - } - if (proc != nullptr) { - GB_ASSERT(proc->kind == Entity_Procedure); - if (proc->code_gen_procedure != nullptr) { - p = proc->code_gen_procedure; - } - } - } - - // NOTE(bill): Generate a new name - // parent_proc.name-guid - String ts_name = e->token.string; - - if (p != nullptr) { - isize name_len = p->name.len + 1 + ts_name.len + 1 + 10 + 1; - char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); - u32 guid = 1+p->module->nested_type_name_guid.fetch_add(1); - name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(p->name), LIT(ts_name), guid); - - String name = make_string(cast(u8 *)name_text, name_len-1); - e->TypeName.ir_mangled_name = name; - return name; - } else { - // NOTE(bill): a nested type be required before its parameter procedure exists. Just give it a temp name for now - isize name_len = 9 + 1 + ts_name.len + 1 + 10 + 1; - char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); - static std::atomic guid; - name_len = gb_snprintf(name_text, name_len, "_internal" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(ts_name), 1+guid.fetch_add(1)); - - String name = make_string(cast(u8 *)name_text, name_len-1); - e->TypeName.ir_mangled_name = name; - return name; - } -} - -gb_internal String lb_get_entity_name(lbModule *m, Entity *e, String default_name) { +gb_internal String lb_get_entity_name(lbModule *m, Entity *e) { GB_ASSERT(m != nullptr); - if (e != nullptr && e->kind == Entity_TypeName && e->TypeName.ir_mangled_name.len != 0) { - return e->TypeName.ir_mangled_name; - } GB_ASSERT(e != nullptr); + if (e->kind == Entity_TypeName && e->TypeName.ir_mangled_name.len != 0) { + return e->TypeName.ir_mangled_name; + } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len != 0) { + return e->Procedure.link_name; + } if (e->pkg == nullptr) { return e->token.string; } - if (e->kind == Entity_TypeName && (e->scope->flags & ScopeFlag_File) == 0) { - return lb_set_nested_type_name_ir_mangled_name(e, nullptr, m); - } + gbString w = string_canonical_entity_name(heap_allocator(), e); + defer (gb_string_free(w)); - String name = {}; - - bool no_name_mangle = false; - - if (e->kind == Entity_Variable) { - bool is_foreign = e->Variable.is_foreign; - bool is_export = e->Variable.is_export; - no_name_mangle = e->Variable.link_name.len > 0 || is_foreign || is_export; - if (e->Variable.link_name.len > 0) { - return e->Variable.link_name; - } - } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) { - return e->Procedure.link_name; - } else if (e->kind == Entity_Procedure && e->Procedure.is_export) { - no_name_mangle = true; - } - - if (!no_name_mangle) { - name = lb_mangle_name(e); - } - if (name.len == 0) { - name = e->token.string; - } + String name = copy_string(permanent_allocator(), make_string(cast(u8 const *)w, gb_string_length(w))); if (e->kind == Entity_TypeName) { e->TypeName.ir_mangled_name = name; } else if (e->kind == Entity_Procedure) { e->Procedure.link_name = name; + } else if (e->kind == Entity_Variable) { + e->Variable.link_name = name; } return name; @@ -1902,15 +1800,24 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return type; } type = LLVMStructCreateNamed(ctx, name); - LLVMTypeRef fields[2] = { - lb_type(m, t_rawptr), - lb_type(m, t_typeid), - }; - LLVMStructSetBody(type, fields, 2, false); + if (build_context.ptr_size == 4) { + LLVMTypeRef fields[3] = { + lb_type(m, t_rawptr), + lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size), // padding + lb_type(m, t_typeid), + }; + LLVMStructSetBody(type, fields, 3, false); + } else { + LLVMTypeRef fields[2] = { + lb_type(m, t_rawptr), + lb_type(m, t_typeid), + }; + LLVMStructSetBody(type, fields, 2, false); + } return type; } - case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 8*cast(unsigned)build_context.ptr_size); + case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 64); // Endian Specific Types case Basic_i16le: return LLVMInt16TypeInContext(ctx); @@ -2088,26 +1995,26 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { case Type_Struct: { type_set_offsets(type); - + i64 full_type_size = type_size_of(type); i64 full_type_align = type_align_of(type); GB_ASSERT(full_type_size % full_type_align == 0); - + if (type->Struct.is_raw_union) { - + lbStructFieldRemapping field_remapping = {}; slice_init(&field_remapping, permanent_allocator(), 1); - + LLVMTypeRef fields[1] = {}; fields[0] = lb_type_padding_filler(m, full_type_size, full_type_align); field_remapping[0] = 0; - + LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false); map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping); map_set(&m->struct_field_remapping, cast(void *)type, field_remapping); return struct_type; } - + lbStructFieldRemapping field_remapping = {}; slice_init(&field_remapping, permanent_allocator(), type->Struct.fields.count); @@ -2120,7 +2027,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMTypeRef padding_type = lb_type_padding_filler(m, 0, type_align_of(type)); array_add(&fields, padding_type); } - + i64 prev_offset = 0; bool requires_packing = type->Struct.is_packed; for (i32 field_index : struct_fields_index_by_increasing_offset(temporary_allocator(), type)) { @@ -2151,7 +2058,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { prev_offset = offset + type_size_of(field->type); } - + i64 end_padding = full_type_size-prev_offset; if (end_padding > 0) { array_add(&fields, lb_type_padding_filler(m, end_padding, 1)); @@ -2160,14 +2067,14 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { for_array(i, fields) { GB_ASSERT(fields[i] != nullptr); } - + LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing); map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping); - map_set(&m->struct_field_remapping, cast(void *)type, field_remapping); + map_set(&m->struct_field_remapping, cast(void *)type, field_remapping); #if 0 - GB_ASSERT_MSG(lb_sizeof(struct_type) == full_type_size, - "(%lld) %s vs (%lld) %s", - cast(long long)lb_sizeof(struct_type), LLVMPrintTypeToString(struct_type), + GB_ASSERT_MSG(lb_sizeof(struct_type) == full_type_size, + "(%lld) %s vs (%lld) %s", + cast(long long)lb_sizeof(struct_type), LLVMPrintTypeToString(struct_type), cast(long long)full_type_size, type_to_string(type)); #endif return struct_type; @@ -2196,8 +2103,22 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMTypeRef variant = lb_type(m, type->Union.variants[0]); array_add(&fields, variant); } else { - LLVMTypeRef block_type = lb_type_padding_filler(m, block_size, align); - LLVMTypeRef tag_type = lb_type(m, union_tag_type(type)); + LLVMTypeRef block_type = nullptr; + + bool all_pointers = align == build_context.ptr_size; + for (isize i = 0; all_pointers && i < type->Union.variants.count; i++) { + Type *t = type->Union.variants[i]; + if (!is_type_internally_pointer_like(t)) { + all_pointers = false; + } + } + if (all_pointers) { + block_type = lb_type(m, t_rawptr); + } else { + block_type = lb_type_padding_filler(m, block_size, align); + } + + LLVMTypeRef tag_type = lb_type(m, union_tag_type(type)); array_add(&fields, block_type); array_add(&fields, tag_type); i64 used_size = lb_sizeof(block_type) + lb_sizeof(tag_type); @@ -2633,12 +2554,10 @@ gb_internal LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String co false); - isize max_len = 7+8+1; - char *name = gb_alloc_array(permanent_allocator(), char, max_len); - - u32 id = m->gen->global_array_index.fetch_add(1); - isize len = gb_snprintf(name, max_len, "csbs$%x", id); - len -= 1; + u32 id = m->global_array_index.fetch_add(1); + gbString name = gb_string_make(temporary_allocator(), "csbs$"); + name = gb_string_appendc(name, m->module_name); + name = gb_string_append_fmt(name, "$%x", id); LLVMTypeRef type = LLVMTypeOf(data); LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); @@ -2676,14 +2595,11 @@ gb_internal lbValue lb_find_or_add_entity_string_byte_slice_with_type(lbModule * false); - char *name = nullptr; - { - isize max_len = 7+8+1; - name = gb_alloc_array(permanent_allocator(), char, max_len); - u32 id = m->gen->global_array_index.fetch_add(1); - isize len = gb_snprintf(name, max_len, "csbs$%x", id); - len -= 1; - } + u32 id = m->global_array_index.fetch_add(1); + gbString name = gb_string_make(temporary_allocator(), "csba$"); + name = gb_string_appendc(name, m->module_name); + name = gb_string_append_fmt(name, "$%x", id); + LLVMTypeRef type = LLVMTypeOf(data); LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); LLVMSetInitializer(global_data, data); @@ -2869,6 +2785,8 @@ gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &pr pl->decl->code_gen_module = m; e->decl_info = pl->decl; pl->decl->entity = e; + e->parent_proc_decl = pl->decl->parent; + e->Procedure.is_anonymous = true; e->flags |= EntityFlag_ProcBodyChecked; lbProcedure *p = lb_create_procedure(m, e); @@ -2889,17 +2807,14 @@ gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &pr } -gb_internal lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value, Entity **entity_) { +gb_internal lbAddr lb_add_global_generated_with_name(lbModule *m, Type *type, lbValue value, String name, Entity **entity_) { + GB_ASSERT(name.len != 0); GB_ASSERT(type != nullptr); type = default_type(type); - isize max_len = 7+8+1; - u8 *str = cast(u8 *)gb_alloc_array(permanent_allocator(), u8, max_len); - - u32 id = m->gen->global_generated_index.fetch_add(1); - - isize len = gb_snprintf(cast(char *)str, max_len, "ggv$%x", id); - String name = make_string(str, len-1); + u8 *str = cast(u8 *)gb_alloc_array(temporary_allocator(), u8, name.len); + memcpy(str, name.text, name.len); + str[name.len] = 0; Scope *scope = nullptr; Entity *e = alloc_entity_variable(scope, make_token_ident(name), type); @@ -2921,6 +2836,25 @@ gb_internal lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue valu return lb_addr(g); } + +gb_internal lbAddr lb_add_global_generated_from_procedure(lbProcedure *p, Type *type, lbValue value) { + GB_ASSERT(type != nullptr); + type = default_type(type); + + u32 index = ++p->global_generated_index; + + gbString s = gb_string_make(temporary_allocator(), "ggv$"); + // s = gb_string_appendc(s, p->module->module_name); + // s = gb_string_appendc(s, "$"); + s = gb_string_append_length(s, p->name.text, p->name.len); + s = gb_string_append_fmt(s, "$%u", index); + + String name = make_string(cast(u8 const *)s, gb_string_length(s)); + return lb_add_global_generated_with_name(p->module, type, value, name); +} + + + gb_internal lbValue lb_find_runtime_value(lbModule *m, String const &name) { AstPackage *p = m->info->runtime_package; Entity *e = scope_lookup_current(p->scope, name); @@ -3028,7 +2962,7 @@ gb_internal lbValue lb_generate_global_array(lbModule *m, Type *elem_type, i64 c g.type = alloc_type_pointer(t); LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g.value, LLVMPrivateLinkage); - LLVMSetUnnamedAddress(g.value, LLVMGlobalUnnamedAddr); + // LLVMSetUnnamedAddress(g.value, LLVMGlobalUnnamedAddr); string_map_set(&m->members, s, g); return g; } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index e5c04852c..a835ae2c8 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1119,7 +1119,7 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c if (LLVMIsConstant(x.value)) { // NOTE(bill): if the value is already constant, then just it as a global variable // and pass it by pointer - lbAddr addr = lb_add_global_generated(p->module, original_type, x); + lbAddr addr = lb_add_global_generated_from_procedure(p, original_type, x); lb_make_global_private_const(addr); ptr = addr.addr; } else { @@ -1564,6 +1564,34 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } + case BuiltinProc_simd_extract_lsbs: + case BuiltinProc_simd_extract_msbs: + { + Type *vt = arg0.type; + GB_ASSERT(vt->kind == Type_SimdVector); + + i64 elem_bits = 8*type_size_of(elem); + i64 num_elems = get_array_type_count(vt); + + LLVMValueRef broadcast_value = arg0.value; + if (builtin_id == BuiltinProc_simd_extract_msbs) { + LLVMTypeRef word_type = lb_type(m, elem); + LLVMValueRef shift_value = llvm_splat_int(num_elems, word_type, elem_bits - 1); + broadcast_value = LLVMBuildAShr(p->builder, broadcast_value, shift_value, ""); + } + + LLVMTypeRef bitvec_type = LLVMVectorType(LLVMInt1TypeInContext(m->ctx), (unsigned)num_elems); + LLVMValueRef bitvec_value = LLVMBuildTrunc(p->builder, broadcast_value, bitvec_type, ""); + + LLVMTypeRef mask_type = LLVMIntTypeInContext(m->ctx, (unsigned)num_elems); + LLVMValueRef mask_value = LLVMBuildBitCast(p->builder, bitvec_value, mask_type, ""); + + LLVMTypeRef result_type = lb_type(m, res.type); + res.value = LLVMBuildZExtOrBitCast(p->builder, mask_value, result_type, ""); + + return res; + } + case BuiltinProc_simd_shuffle: { @@ -1846,7 +1874,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu LLVMValueRef backing_array = llvm_const_array(lb_type(m, t_load_directory_file), elements, count); Type *array_type = alloc_type_array(t_load_directory_file, count); - lbAddr backing_array_addr = lb_add_global_generated(m, array_type, {backing_array, array_type}, nullptr); + lbAddr backing_array_addr = lb_add_global_generated_from_procedure(p, array_type, {backing_array, array_type}); lb_make_global_private_const(backing_array_addr); LLVMValueRef backing_array_ptr = backing_array_addr.addr.value; @@ -1854,7 +1882,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu LLVMValueRef const_slice = llvm_const_slice_internal(m, backing_array_ptr, LLVMConstInt(lb_type(m, t_int), count, false)); - lbAddr addr = lb_add_global_generated(p->module, tv.type, {const_slice, t_load_directory_file_slice}, nullptr); + lbAddr addr = lb_add_global_generated_from_procedure(p, tv.type, {const_slice, t_load_directory_file_slice}); lb_make_global_private_const(addr); return lb_addr_load(p, addr); @@ -2548,8 +2576,8 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } case BuiltinProc_ptr_sub: { - Type *elem0 = type_deref(type_of_expr(ce->args[0])); - Type *elem1 = type_deref(type_of_expr(ce->args[1])); + Type *elem0 = type_deref(type_of_expr(ce->args[0]), true); + Type *elem1 = type_deref(type_of_expr(ce->args[1]), true); GB_ASSERT(are_types_identical(elem0, elem1)); Type *elem = elem0; @@ -3280,13 +3308,14 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu { isize max_len = 7+8+1; name = gb_alloc_array(permanent_allocator(), char, max_len); - u32 id = m->gen->global_array_index.fetch_add(1); + u32 id = m->global_array_index.fetch_add(1); isize len = gb_snprintf(name, max_len, "csbs$%x", id); len -= 1; } LLVMTypeRef type = LLVMTypeOf(array); LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); LLVMSetInitializer(global_data, array); + LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr); LLVMSetLinkage(global_data, LLVMInternalLinkage); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 56ccb6819..5cbd16807 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -5,8 +5,6 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) auto *min_dep_set = &p->module->info->minimum_dependency_set; - static i32 global_guid = 0; - for (Ast *ident : vd->names) { GB_ASSERT(ident->kind == Ast_Ident); Entity *e = entity_of_node(ident); @@ -32,7 +30,8 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) continue; } - lb_set_nested_type_name_ir_mangled_name(e, p, p->module); + String name = lb_get_entity_name(p->module, e); + gb_unused(name); } for_array(i, vd->names) { @@ -1115,62 +1114,43 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc } Type *elem = et->BitSet.elem; - if (is_type_enum(elem)) { - i64 enum_count = 0; - lbValue values = lb_enum_values_slice(p, elem, &enum_count); - lbValue values_data = lb_slice_elem(p, values); - lbValue max_count = lb_const_int(m, t_int, enum_count); + Type *mask = bit_set_to_int(et); - lbAddr offset_ = lb_add_local_generated(p, t_int, false); - lb_addr_store(p, offset_, lb_const_int(m, t_int, 0)); + lbValue all_mask = lb_const_value(p->module, mask, exact_bit_set_all_set_mask(et)); + lbValue initial_mask = lb_emit_arith(p, Token_And, the_set, all_mask, mask); - loop = lb_create_block(p, "for.bit_set.enum.loop"); - lb_emit_jump(p, loop); - lb_start_block(p, loop); - - lbBlock *body_check = lb_create_block(p, "for.bit_set.enum.body-check"); - lbBlock *body = lb_create_block(p, "for.bit_set.enum.body"); - done = lb_create_block(p, "for.bit_set.enum.done"); - - lbValue offset = lb_addr_load(p, offset_); - lbValue cond = lb_emit_comp(p, Token_Lt, offset, max_count); - lb_emit_if(p, cond, body_check, done); - lb_start_block(p, body_check); - - lbValue val_ptr = lb_emit_ptr_offset(p, values_data, offset); - lb_emit_increment(p, offset_.addr); - val = lb_emit_load(p, val_ptr); - val = lb_emit_conv(p, val, elem); - - lbValue check = lb_build_binary_in(p, val, the_set, Token_in); - lb_emit_if(p, check, body, loop); - lb_start_block(p, body); - } else { - lbAddr offset_ = lb_add_local_generated(p, t_int, false); - lb_addr_store(p, offset_, lb_const_int(m, t_int, et->BitSet.lower)); - - lbValue max_count = lb_const_int(m, t_int, et->BitSet.upper); - - loop = lb_create_block(p, "for.bit_set.range.loop"); - lb_emit_jump(p, loop); - lb_start_block(p, loop); - - lbBlock *body_check = lb_create_block(p, "for.bit_set.range.body-check"); - lbBlock *body = lb_create_block(p, "for.bit_set.range.body"); - done = lb_create_block(p, "for.bit_set.range.done"); - - lbValue offset = lb_addr_load(p, offset_); - lbValue cond = lb_emit_comp(p, Token_LtEq, offset, max_count); - lb_emit_if(p, cond, body_check, done); - lb_start_block(p, body_check); - - val = lb_emit_conv(p, offset, elem); - lb_emit_increment(p, offset_.addr); - - lbValue check = lb_build_binary_in(p, val, the_set, Token_in); - lb_emit_if(p, check, body, loop); - lb_start_block(p, body); + if (rs->reverse) { + initial_mask = lb_emit_reverse_bits(p, initial_mask, mask); } + + lbAddr remaining = lb_add_local_generated(p, mask, false); + lb_addr_store(p, remaining, initial_mask); + + loop = lb_create_block(p, "for.bit_set.loop"); + lbBlock *body = lb_create_block(p, "for.bit_set.body"); + done = lb_create_block(p, "for.bit_set.done"); + + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbValue remaining_val = lb_addr_load(p, remaining); + lbValue cond = lb_emit_comp(p, Token_NotEq, remaining_val, lb_zero(m, mask)); + lb_emit_if(p, cond, body, done); + + lb_start_block(p, body); + val = lb_emit_count_trailing_zeros(p, remaining_val, mask); + val = lb_emit_conv(p, val, elem); + + if (rs->reverse) { + val = lb_emit_arith(p, Token_Sub, lb_const_int(m, elem, et->BitSet.lower + 8*type_size_of(mask) - 1), val, elem); + } else { + val = lb_emit_arith(p, Token_Add, val, lb_const_int(m, elem, et->BitSet.lower), elem); + } + + lbValue reduce_val = lb_emit_arith(p, Token_Sub, remaining_val, lb_const_int(m, mask, 1), mask); + remaining_val = lb_emit_arith(p, Token_And, remaining_val, reduce_val, mask); + lb_addr_store(p, remaining, remaining_val); + break; } default: diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 6c12b37be..ad4250f3c 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -1,24 +1,24 @@ -gb_internal isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=true) { - auto *set = &info->minimum_dependency_type_info_set; - isize index = type_info_index(info, type, err_on_not_found); + +gb_internal isize lb_type_info_index(CheckerInfo *info, TypeInfoPair pair, bool err_on_not_found=true) { + isize index = type_info_index(info, pair, err_on_not_found); if (index >= 0) { - auto *found = map_get(set, index+1); - if (found) { - GB_ASSERT(*found >= 0); - return *found + 1; - } + return index; } if (err_on_not_found) { - gb_printf_err("NOT FOUND lb_type_info_index:\n\t%s\n\t@ index %td\n\tmax count: %u\nFound:\n", type_to_string(type), index, set->count); - for (auto const &entry : *set) { + gb_printf_err("NOT FOUND lb_type_info_index:\n\t%s\n\t@ index %td\n\tmax count: %u\nFound:\n", type_to_string(pair.type), index, info->min_dep_type_info_index_map.count); + for (auto const &entry : info->min_dep_type_info_index_map) { isize type_info_index = entry.key; - gb_printf_err("\t%s\n", type_to_string(info->type_info_types[type_info_index])); + gb_printf_err("\t%s\n", type_to_string(info->type_info_types_hash_map[type_info_index].type)); } GB_PANIC("NOT FOUND"); } return -1; } +gb_internal isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=true) { + return lb_type_info_index(info, {type, type_hash_canonical_type(type)}, err_on_not_found); +} + gb_internal u64 lb_typeid_kind(lbModule *m, Type *type, u64 id=0) { GB_ASSERT(!build_context.no_rtti); @@ -73,37 +73,8 @@ gb_internal lbValue lb_typeid(lbModule *m, Type *type) { type = default_type(type); - u64 id = cast(u64)lb_type_info_index(m->info, type); - GB_ASSERT(id >= 0); - - u64 kind = lb_typeid_kind(m, type, id); - u64 named = is_type_named(type) && type->kind != Type_Basic; - u64 special = 0; - u64 reserved = 0; - - if (is_type_cstring(type)) { - special = 1; - } else if (is_type_integer(type) && !is_type_unsigned(type)) { - special = 1; - } - - u64 data = 0; - if (build_context.ptr_size == 4) { - GB_ASSERT(id <= (1u<<24u)); - data |= (id &~ (1u<<24)) << 0u; // index - data |= (kind &~ (1u<<5)) << 24u; // kind - data |= (named &~ (1u<<1)) << 29u; // named - data |= (special &~ (1u<<1)) << 30u; // special - data |= (reserved &~ (1u<<1)) << 31u; // reserved - } else { - GB_ASSERT(build_context.ptr_size == 8); - GB_ASSERT(id <= (1ull<<56u)); - data |= (id &~ (1ull<<56)) << 0ul; // index - data |= (kind &~ (1ull<<5)) << 56ull; // kind - data |= (named &~ (1ull<<1)) << 61ull; // named - data |= (special &~ (1ull<<1)) << 62ull; // special - data |= (reserved &~ (1ull<<1)) << 63ull; // reserved - } + u64 data = type_hash_canonical_type(type); + GB_ASSERT(data != 0); lbValue res = {}; res.value = LLVMConstInt(lb_type(m, t_typeid), data, false); @@ -279,13 +250,14 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ LLVMTypeRef *modified_types = lb_setup_modified_types_for_type_info(m, global_type_info_data_entity_count); defer (gb_free(heap_allocator(), modified_types)); - for_array(type_info_type_index, info->type_info_types) { - Type *t = info->type_info_types[type_info_type_index]; + for_array(type_info_type_index, info->type_info_types_hash_map) { + auto const &tt = info->type_info_types_hash_map[type_info_type_index]; + Type *t = tt.type; if (t == nullptr || t == t_invalid) { continue; } - isize entry_index = lb_type_info_index(info, t, false); + isize entry_index = lb_type_info_index(info, tt, false); if (entry_index <= 0) { continue; } @@ -342,8 +314,8 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ return giant_const_values[index]; }; - for_array(type_info_type_index, info->type_info_types) { - Type *t = info->type_info_types[type_info_type_index]; + for_array(type_info_type_index, info->type_info_types_hash_map) { + Type *t = info->type_info_types_hash_map[type_info_type_index].type; if (t == nullptr || t == t_invalid) { continue; } @@ -1071,7 +1043,12 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ LLVMSetInitializer(giant_const_values[entry_index], LLVMConstNamedStruct(stype, small_const_values, variant_index+1)); } for (isize i = 0; i < global_type_info_data_entity_count; i++) { - giant_const_values[i] = LLVMConstPointerCast(giant_const_values[i], lb_type(m, t_type_info_ptr)); + auto *ptr = &giant_const_values[i]; + if (*ptr != nullptr) { + *ptr = LLVMConstPointerCast(*ptr, lb_type(m, t_type_info_ptr)); + } else { + *ptr = LLVMConstNull(lb_type(m, t_type_info_ptr)); + } } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index aa425a9d5..c876169f3 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -971,6 +971,13 @@ gb_internal i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) { if (t->kind == Type_Struct) { auto field_remapping = lb_get_struct_remapping(m, t); return field_remapping[index]; + } else if (is_type_any(t) && build_context.ptr_size == 4) { + GB_ASSERT(t->kind == Type_Basic); + GB_ASSERT(t->Basic.kind == Basic_any); + switch (index) { + case 0: return 0; // data + case 1: return 2; // id + } } else if (build_context.ptr_size != build_context.int_size) { switch (t->kind) { case Type_Basic: @@ -2105,7 +2112,13 @@ gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, Stri } if (!entity) { - lbAddr default_addr = lb_add_global_generated(default_module, t_objc_SEL, {}, &entity); + gbString global_name = gb_string_make(temporary_allocator(), "__$objc_SEL$"); + global_name = gb_string_append_length(global_name, name.text, name.len); + + lbAddr default_addr = lb_add_global_generated_with_name( + default_module, t_objc_SEL, {}, + make_string(cast(u8 const *)global_name, gb_string_length(global_name)), + &entity); string_map_set(&default_module->objc_selectors, name, lbObjcRef{entity, default_addr}); } @@ -2162,7 +2175,12 @@ gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String } if (!entity) { - lbAddr default_addr = lb_add_global_generated(default_module, t_objc_Class, {}, &entity); + gbString global_name = gb_string_make(temporary_allocator(), "__$objc_Class$"); + global_name = gb_string_append_length(global_name, name.text, name.len); + + lbAddr default_addr = lb_add_global_generated_with_name(default_module, t_objc_Class, {}, + make_string(cast(u8 const *)global_name, gb_string_length(global_name)), + &entity); string_map_set(&default_module->objc_classes, name, lbObjcRef{entity, default_addr}); } diff --git a/src/main.cpp b/src/main.cpp index e8336b292..0a24d64a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3593,10 +3593,15 @@ int main(int arg_count, char const **arg_ptr) { } if (build_context.generate_docs) { + MAIN_TIME_SECTION("generate documentation"); if (global_error_collector.count != 0) { return 1; } generate_documentation(checker); + + if (build_context.show_timings) { + show_timings(checker, &global_timings); + } return 0; } diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp new file mode 100644 index 000000000..a80dc1996 --- /dev/null +++ b/src/name_canonicalization.cpp @@ -0,0 +1,752 @@ +gb_internal GB_COMPARE_PROC(type_info_pair_cmp) { + TypeInfoPair *x = cast(TypeInfoPair *)a; + TypeInfoPair *y = cast(TypeInfoPair *)b; + if (x->hash == y->hash) { + return 0; + } + return x->hash < y->hash ? -1 : +1; +} + + +gb_internal gbAllocator type_set_allocator(void) { + return heap_allocator(); +} + +gb_internal TypeSetIterator begin(TypeSet &set) noexcept { + usize index = 0; + while (index < set.capacity) { + TypeInfoPair key = set.keys[index]; + if (key.hash != 0 && key.hash != TYPE_SET_TOMBSTONE) { + break; + } + index++; + } + return TypeSetIterator{&set, index}; +} +gb_internal TypeSetIterator end(TypeSet &set) noexcept { + return TypeSetIterator{&set, set.capacity}; +} + + +gb_internal void type_set_init(TypeSet *s, isize capacity) { + GB_ASSERT(s->keys == nullptr); + if (capacity != 0) { + capacity = next_pow2_isize(gb_max(16, capacity)); + s->keys = gb_alloc_array(type_set_allocator(), TypeInfoPair, capacity); + // This memory will be zeroed, no need to explicitly zero it + } + s->count = 0; + s->capacity = capacity; +} + +gb_internal void type_set_destroy(TypeSet *s) { + gb_free(type_set_allocator(), s->keys); + s->keys = nullptr; + s->count = 0; + s->capacity = 0; +} + + +gb_internal isize type_set__find(TypeSet *s, TypeInfoPair pair) { + GB_ASSERT(pair.type != nullptr); + GB_ASSERT(pair.hash != 0); + if (s->count != 0) { + usize hash = pair.hash; + usize mask = s->capacity-1; + usize hash_index = cast(usize)hash & mask; + for (usize i = 0; i < s->capacity; i++) { + Type *key = s->keys[hash_index].type; + if (are_types_identical_unique_tuples(key, pair.type)) { + return hash_index; + } else if (key == 0) { + return -1; + } + hash_index = (hash_index+1)&mask; + } + } + return -1; +} +gb_internal isize type_set__find(TypeSet *s, Type *ptr) { + GB_ASSERT(ptr != 0); + if (s->count != 0) { + usize hash = cast(usize)type_hash_canonical_type(ptr); + usize mask = s->capacity-1; + usize hash_index = cast(usize)hash & mask; + for (usize i = 0; i < s->capacity; i++) { + Type *key = s->keys[hash_index].type; + if (are_types_identical_unique_tuples(key, ptr)) { + return hash_index; + } else if (key == 0) { + return -1; + } + hash_index = (hash_index+1)&mask; + } + } + return -1; +} + +gb_internal bool type_set__full(TypeSet *s) { + return 0.75f * s->capacity <= s->count; +} + +gb_internal gb_inline void type_set_grow(TypeSet *old_set) { + if (old_set->capacity == 0) { + type_set_init(old_set); + return; + } + + TypeSet new_set = {}; + type_set_init(&new_set, gb_max(old_set->capacity<<1, 16)); + + for (TypeInfoPair const &set : *old_set) { + bool was_new = type_set_update(&new_set, set); + GB_ASSERT(!was_new); + } + GB_ASSERT(old_set->count == new_set.count); + + type_set_destroy(old_set); + + *old_set = new_set; +} + + +gb_internal gb_inline bool type_set_exists(TypeSet *s, Type *ptr) { + return type_set__find(s, ptr) >= 0; +} +gb_internal gb_inline bool type_set_exists(TypeSet *s, TypeInfoPair pair) { + return type_set__find(s, pair) >= 0; +} +gb_internal gb_inline TypeInfoPair *type_set_retrieve(TypeSet *s, Type *type) { + isize index = type_set__find(s, type); + if (index >= 0) { + return &s->keys[index]; + } + return nullptr; +} + + +gb_internal bool type_set_update(TypeSet *s, TypeInfoPair pair) { // returns true if it previously existsed + if (type_set_exists(s, pair)) { + return true; + } + + if (s->keys == nullptr) { + type_set_init(s); + } else if (type_set__full(s)) { + type_set_grow(s); + } + GB_ASSERT(s->count < s->capacity); + GB_ASSERT(s->capacity >= 0); + + usize mask = s->capacity-1; + usize hash = cast(usize)pair.hash; + usize hash_index = (cast(usize)hash) & mask; + GB_ASSERT(hash_index < s->capacity); + for (usize i = 0; i < s->capacity; i++) { + TypeInfoPair *key = &s->keys[hash_index]; + GB_ASSERT(!are_types_identical_unique_tuples(key->type, pair.type)); + if (key->hash == TYPE_SET_TOMBSTONE || key->hash == 0) { + *key = pair; + s->count++; + return false; + } + hash_index = (hash_index+1)&mask; + } + + GB_PANIC("ptr set out of memory"); + return false; +} + +gb_internal bool type_set_update(TypeSet *s, Type *ptr) { // returns true if it previously existsed + TypeInfoPair pair = {ptr, type_hash_canonical_type(ptr)}; + return type_set_update(s, pair); +} + + +gb_internal Type *type_set_add(TypeSet *s, Type *ptr) { + type_set_update(s, ptr); + return ptr; +} + +gb_internal Type *type_set_add(TypeSet *s, TypeInfoPair pair) { + type_set_update(s, pair); + return pair.type; +} + + + +gb_internal void type_set_remove(TypeSet *s, Type *ptr) { + isize index = type_set__find(s, ptr); + if (index >= 0) { + GB_ASSERT(s->count > 0); + s->keys[index].type = nullptr; + s->keys[index].hash = TYPE_SET_TOMBSTONE; + s->count--; + } +} + +gb_internal gb_inline void type_set_clear(TypeSet *s) { + s->count = 0; + gb_zero_size(s->keys, s->capacity*gb_size_of(*s->keys)); +} + + +#define TYPE_WRITER_PROC(name) bool name(TypeWriter *w, void const *ptr, isize len) +typedef TYPE_WRITER_PROC(TypeWriterProc); + + +struct TypeWriter { + TypeWriterProc *proc; + void *user_data; +}; + +bool type_writer_append(TypeWriter *w, void const *ptr, isize len) { + return w->proc(w, ptr, len); +} + +bool type_writer_appendb(TypeWriter *w, char b) { + return w->proc(w, &b, 1); +} + +bool type_writer_appendc(TypeWriter *w, char const *str) { + isize len = gb_strlen(str); + return w->proc(w, str, len); +} + +bool type_writer_append_fmt(TypeWriter *w, char const *fmt, ...) { + va_list va; + char *str; + va_start(va, fmt); + str = gb_bprintf_va(fmt, va); + va_end(va); + + return type_writer_appendc(w, str); +} + + + +TYPE_WRITER_PROC(type_writer_string_writer_proc) { + gbString *s = cast(gbString *)&w->user_data; + *s = gb_string_append_length(*s, ptr, len); + return true; +} + +void type_writer_make_string(TypeWriter *w, gbAllocator allocator) { + w->user_data = gb_string_make(allocator, ""); + w->proc = type_writer_string_writer_proc; +} + +void type_writer_destroy_string(TypeWriter *w) { + gb_string_free(cast(gbString)w->user_data); +} + + +TYPE_WRITER_PROC(type_writer_hasher_writer_proc) { + u64 *seed = cast(u64 *)w->user_data; + *seed = fnv64a(ptr, len, *seed); + return true; +} + +void type_writer_make_hasher(TypeWriter *w, u64 *hash) { + w->user_data = hash; + w->proc = type_writer_hasher_writer_proc; +} + + + + +gb_internal void write_canonical_params(TypeWriter *w, Type *params) { + type_writer_appendc(w, "("); + defer (type_writer_appendc(w, ")")); + + if (params == nullptr) { + return; + } + GB_ASSERT(params->kind == Type_Tuple); + for_array(i, params->Tuple.variables) { + Entity *v = params->Tuple.variables[i]; + if (i > 0) { + type_writer_appendc(w, CANONICAL_PARAM_SEPARATOR); + } + type_writer_append(w, v->token.string.text, v->token.string.len); + type_writer_appendc(w, CANONICAL_TYPE_SEPARATOR); + + switch (v->kind) { + case Entity_Variable: + if (v->flags&EntityFlag_CVarArg) { + type_writer_appendc(w, CANONICAL_PARAM_C_VARARG); + } + if (v->flags&EntityFlag_Ellipsis) { + Type *slice = base_type(v->type); + type_writer_appendc(w, CANONICAL_PARAM_VARARG); + GB_ASSERT(v->type->kind == Type_Slice); + write_type_to_canonical_string(w, slice->Slice.elem); + } else { + write_type_to_canonical_string(w, v->type); + } + break; + case Entity_TypeName: + type_writer_appendc(w, CANONICAL_PARAM_TYPEID); + write_type_to_canonical_string(w, v->type); + break; + case Entity_Constant: + { + type_writer_appendc(w, CANONICAL_PARAM_CONST); + gbString s = exact_value_to_string(v->Constant.value, 1<<16); + type_writer_append(w, s, gb_string_length(s)); + gb_string_free(s); + } + break; + default: + GB_PANIC("TODO(bill): handle non type/const parapoly parameter values"); + break; + } + } + return; +} + +gb_internal u64 type_hash_canonical_type(Type *type) { + if (type == nullptr) { + return 0; + } + u64 hash = fnv64a(nullptr, 0); + TypeWriter w = {}; + type_writer_make_hasher(&w, &hash); + write_type_to_canonical_string(&w, type); + + return hash ? hash : 1; +} + +gb_internal String type_to_canonical_string(gbAllocator allocator, Type *type) { + TypeWriter w = {}; + type_writer_make_string(&w, allocator); + write_type_to_canonical_string(&w, type); + + gbString s = cast(gbString)w.user_data; + return make_string(cast(u8 const *)s, gb_string_length(s)); +} + +gb_internal gbString temp_canonical_string(Type *type) { + TypeWriter w = {}; + type_writer_make_string(&w, temporary_allocator()); + write_type_to_canonical_string(&w, type); + + return cast(gbString)w.user_data; +} + +gb_internal gbString string_canonical_entity_name(gbAllocator allocator, Entity *e) { + TypeWriter w = {}; + type_writer_make_string(&w, allocator); + write_canonical_entity_name(&w, e); + return cast(gbString)w.user_data; +} + + + +gb_internal void write_canonical_parent_prefix(TypeWriter *w, Entity *e) { + GB_ASSERT(e != nullptr); + if (e->kind == Entity_Procedure || e->kind == Entity_TypeName) { + if (e->kind == Entity_Procedure && (e->Procedure.is_export || e->Procedure.is_foreign)) { + // no prefix + return; + } + if (e->parent_proc_decl) { + Entity *p = e->parent_proc_decl->entity; + write_canonical_parent_prefix(w, p); + type_writer_append(w, p->token.string.text, p->token.string.len); + if (is_type_polymorphic(p->type)) { + type_writer_appendc(w, CANONICAL_TYPE_SEPARATOR); + write_type_to_canonical_string(w, p->type); + } + type_writer_appendc(w, CANONICAL_NAME_SEPARATOR); + + } else if (e->pkg && (scope_lookup_current(e->pkg->scope, e->token.string) == e)) { + type_writer_append(w, e->pkg->name.text, e->pkg->name.len); + if (e->pkg->name == "llvm") { + type_writer_appendc(w, "$"); + } + type_writer_appendc(w, CANONICAL_NAME_SEPARATOR); + } else { + String file_name = filename_without_directory(e->file->fullpath); + type_writer_append(w, e->pkg->name.text, e->pkg->name.len); + if (e->pkg->name == "llvm") { + type_writer_appendc(w, "$"); + } + type_writer_append_fmt(w, CANONICAL_NAME_SEPARATOR "%.*s" CANONICAL_NAME_SEPARATOR, LIT(file_name)); + } + } else { + GB_PANIC("TODO(bill): handle entity kind: %d", e->kind); + } + if (e->kind == Entity_Procedure && e->Procedure.is_anonymous) { + String file_name = filename_without_directory(e->file->fullpath); + type_writer_append_fmt(w, CANONICAL_ANON_PREFIX "_%.*s:%d", LIT(file_name), e->token.pos.offset); + } else { + type_writer_append(w, e->token.string.text, e->token.string.len); + } + + if (is_type_polymorphic(e->type)) { + type_writer_appendc(w, CANONICAL_TYPE_SEPARATOR); + write_type_to_canonical_string(w, e->type); + } + type_writer_appendc(w, CANONICAL_NAME_SEPARATOR); + + return; +} + +gb_internal void write_canonical_entity_name(TypeWriter *w, Entity *e) { + GB_ASSERT(e != nullptr); + + if (e->token.string == "_") { + GB_PANIC("_ string"); + } + if (e->token.string.len == 0) { + GB_PANIC("empty string"); + } + + if (e->kind == Entity_Variable) { + bool is_foreign = e->Variable.is_foreign; + bool is_export = e->Variable.is_export; + if (e->Variable.link_name.len > 0) { + type_writer_append(w, e->Variable.link_name.text, e->Variable.link_name.len); + return; + } else if (is_foreign || is_export) { + type_writer_append(w, e->token.string.text, e->token.string.len); + return; + } + } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) { + type_writer_append(w, e->Procedure.link_name.text, e->Procedure.link_name.len); + return; + } else if (e->kind == Entity_Procedure && e->Procedure.is_export) { + type_writer_append(w, e->token.string.text, e->token.string.len); + return; + } + + bool write_scope_index_suffix = false; + + if (e->scope->flags & (ScopeFlag_Builtin)) { + goto write_base_name; + } else if ((e->scope->flags & (ScopeFlag_File | ScopeFlag_Pkg)) == 0 || + e->flags & EntityFlag_NotExported) { + Scope *s = e->scope; + + while ((s->flags & (ScopeFlag_Proc|ScopeFlag_File)) == 0 && s->decl_info == nullptr) { + if (s->parent == nullptr) { + break; + } + s = s->parent; + } + + if (s->decl_info != nullptr && s->decl_info->entity) { + Entity *parent = s->decl_info->entity; + write_canonical_parent_prefix(w, parent); + if (e->scope->index > 0) { + write_scope_index_suffix = true; + } + + goto write_base_name; + } else if ((s->flags & ScopeFlag_File) && s->file != nullptr) { + String file_name = filename_without_directory(s->file->fullpath); + type_writer_append(w, e->pkg->name.text, e->pkg->name.len); + if (e->pkg->name == "llvm") { + type_writer_appendc(w, "$"); + } + type_writer_appendc(w, gb_bprintf(CANONICAL_NAME_SEPARATOR "[%.*s]" CANONICAL_NAME_SEPARATOR, LIT(file_name))); + goto write_base_name; + } else if (s->flags & (ScopeFlag_Builtin)) { + goto write_base_name; + } + gb_printf_err("%s WEIRD ENTITY TYPE %s %u %p\n", token_pos_to_string(e->token.pos), type_to_string(e->type), s->flags, s->decl_info); + + auto const print_scope_flags = [](Scope *s) { + if (s->flags & ScopeFlag_Pkg) gb_printf_err("Pkg "); + if (s->flags & ScopeFlag_Builtin) gb_printf_err("Builtin "); + if (s->flags & ScopeFlag_Global) gb_printf_err("Global "); + if (s->flags & ScopeFlag_File) gb_printf_err("File "); + if (s->flags & ScopeFlag_Init) gb_printf_err("Init "); + if (s->flags & ScopeFlag_Proc) gb_printf_err("Proc "); + if (s->flags & ScopeFlag_Type) gb_printf_err("Type "); + if (s->flags & ScopeFlag_HasBeenImported) gb_printf_err("HasBeenImported "); + if (s->flags & ScopeFlag_ContextDefined) gb_printf_err("ContextDefined "); + gb_printf_err("\n"); + }; + + print_scope_flags(s); + GB_PANIC("weird entity %.*s", LIT(e->token.string)); + } + if (e->pkg != nullptr) { + type_writer_append(w, e->pkg->name.text, e->pkg->name.len); + type_writer_appendc(w, CANONICAL_NAME_SEPARATOR); + } + +write_base_name: + + switch (e->kind) { + case Entity_TypeName: + { + + Type *params = nullptr; + Entity *parent = type_get_polymorphic_parent(e->type, ¶ms); + if (parent && (parent->token.string == e->token.string)) { + type_writer_append(w, parent->token.string.text, parent->token.string.len); + write_canonical_params(w, params); + } else { + type_writer_append(w, e->token.string.text, e->token.string.len); + } + } + break; + + case Entity_Constant: + // For debug symbols only + /*fallthrough*/ + case Entity_Procedure: + case Entity_Variable: + type_writer_append(w, e->token.string.text, e->token.string.len); + if (is_type_polymorphic(e->type)) { + type_writer_appendc(w, CANONICAL_TYPE_SEPARATOR); + write_type_to_canonical_string(w, e->type); + } + break; + + default: + GB_PANIC("TODO(bill): entity kind %d", e->kind); + break; + } + + if (write_scope_index_suffix) { + GB_ASSERT(e != nullptr && e->scope != nullptr); + type_writer_append_fmt(w, CANONICAL_NAME_SEPARATOR "$%d", e->scope->index); + } + + return; +} + +gb_internal bool is_in_doc_writer(void); + +// NOTE(bill): This exists so that we deterministically hash a type by serializing it to a canonical string +gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { + if (type == nullptr) { + type_writer_appendc(w, CANONICAL_NONE_TYPE); // none/void type + return; + } + + type = default_type(type); + GB_ASSERT(!is_type_untyped(type)); + + switch (type->kind) { + case Type_Basic: + type_writer_append(w, type->Basic.name.text, type->Basic.name.len); + return; + case Type_Pointer: + type_writer_appendb(w, '^'); + write_type_to_canonical_string(w, type->Pointer.elem); + return; + case Type_MultiPointer: + type_writer_appendc(w, "[^]"); + write_type_to_canonical_string(w, type->Pointer.elem); + return; + case Type_SoaPointer: + type_writer_appendc(w, "#soa^"); + write_type_to_canonical_string(w, type->Pointer.elem); + return; + case Type_EnumeratedArray: + if (type->EnumeratedArray.is_sparse) { + type_writer_appendc(w, "#sparse"); + } + type_writer_appendb(w, '['); + write_type_to_canonical_string(w, type->EnumeratedArray.index); + type_writer_appendb(w, ']'); + write_type_to_canonical_string(w, type->EnumeratedArray.elem); + return; + case Type_Array: + type_writer_append_fmt(w, "[%lld]", cast(long long)type->Array.count); + write_type_to_canonical_string(w, type->Array.elem); + return; + case Type_Slice: + type_writer_appendc(w, "[]"); + write_type_to_canonical_string(w, type->Array.elem); + return; + case Type_DynamicArray: + type_writer_appendc(w, "[dynamic]"); + write_type_to_canonical_string(w, type->DynamicArray.elem); + return; + case Type_SimdVector: + type_writer_append_fmt(w, "#simd[%lld]", cast(long long)type->SimdVector.count); + write_type_to_canonical_string(w, type->SimdVector.elem); + return; + case Type_Matrix: + if (type->Matrix.is_row_major) { + type_writer_appendc(w, "#row_major "); + } + type_writer_append_fmt(w, "matrix[%lld, %lld]", cast(long long)type->Matrix.row_count, cast(long long)type->Matrix.column_count); + write_type_to_canonical_string(w, type->Matrix.elem); + return; + case Type_Map: + type_writer_appendc(w, "map["); + write_type_to_canonical_string(w, type->Map.key); + type_writer_appendc(w, "]"); + write_type_to_canonical_string(w, type->Map.value); + return; + + case Type_Enum: + type_writer_appendc(w, "enum"); + if (type->Enum.base_type != nullptr) { + type_writer_appendb(w, ' '); + write_type_to_canonical_string(w, type->Enum.base_type); + type_writer_appendb(w, ' '); + } + type_writer_appendb(w, '{'); + for_array(i, type->Enum.fields) { + Entity *f = type->Enum.fields[i]; + GB_ASSERT(f->kind == Entity_Constant); + if (i > 0) { + type_writer_appendc(w, CANONICAL_FIELD_SEPARATOR); + } + type_writer_append(w, f->token.string.text, f->token.string.len); + type_writer_appendc(w, "="); + + gbString s = exact_value_to_string(f->Constant.value, 1<<16); + type_writer_append(w, s, gb_string_length(s)); + gb_string_free(s); + } + type_writer_appendb(w, '}'); + return; + case Type_BitSet: + type_writer_appendc(w, "bit_set["); + if (type->BitSet.elem == nullptr) { + type_writer_appendc(w, CANONICAL_NONE_TYPE); + } else if (is_type_enum(type->BitSet.elem)) { + write_type_to_canonical_string(w, type->BitSet.elem); + } else { + type_writer_append_fmt(w, "%lld", type->BitSet.lower); + type_writer_append_fmt(w, CANONICAL_RANGE_OPERATOR); + type_writer_append_fmt(w, "%lld", type->BitSet.upper); + } + if (type->BitSet.underlying != nullptr) { + type_writer_appendc(w, ";"); + write_type_to_canonical_string(w, type->BitSet.underlying); + } + type_writer_appendc(w, "]"); + return; + + case Type_Union: + type_writer_appendc(w, "union"); + + switch (type->Union.kind) { + case UnionType_no_nil: type_writer_appendc(w, "#no_nil"); break; + case UnionType_shared_nil: type_writer_appendc(w, "#shared_nil"); break; + } + if (type->Union.custom_align != 0) { + type_writer_append_fmt(w, "#align(%lld)", cast(long long)type->Union.custom_align); + } + type_writer_appendc(w, "{"); + for_array(i, type->Union.variants) { + Type *t = type->Union.variants[i]; + if (i > 0) type_writer_appendc(w, CANONICAL_FIELD_SEPARATOR); + write_type_to_canonical_string(w, t); + } + type_writer_appendc(w, "}"); + return; + case Type_Struct: + if (type->Struct.soa_kind != StructSoa_None) { + switch (type->Struct.soa_kind) { + case StructSoa_Fixed: type_writer_append_fmt(w, "#soa[%lld]", cast(long long)type->Struct.soa_count); break; + case StructSoa_Slice: type_writer_appendc(w, "#soa[]"); break; + case StructSoa_Dynamic: type_writer_appendc(w, "#soa[dynamic]"); break; + default: GB_PANIC("Unknown StructSoaKind"); break; + } + return write_type_to_canonical_string(w, type->Struct.soa_elem); + } + + type_writer_appendc(w, "struct"); + if (type->Struct.is_packed) type_writer_appendc(w, "#packed"); + if (type->Struct.is_raw_union) type_writer_appendc(w, "#raw_union"); + if (type->Struct.is_no_copy) type_writer_appendc(w, "#no_copy"); + if (type->Struct.custom_min_field_align != 0) type_writer_append_fmt(w, "#min_field_align(%lld)", cast(long long)type->Struct.custom_min_field_align); + if (type->Struct.custom_max_field_align != 0) type_writer_append_fmt(w, "#max_field_align(%lld)", cast(long long)type->Struct.custom_max_field_align); + if (type->Struct.custom_align != 0) type_writer_append_fmt(w, "#align(%lld)", cast(long long)type->Struct.custom_align); + type_writer_appendb(w, '{'); + for_array(i, type->Struct.fields) { + Entity *f = type->Struct.fields[i]; + GB_ASSERT(f->kind == Entity_Variable); + if (i > 0) { + type_writer_appendc(w, CANONICAL_FIELD_SEPARATOR); + } + type_writer_append(w, f->token.string.text, f->token.string.len); + type_writer_appendc(w, CANONICAL_TYPE_SEPARATOR); + write_type_to_canonical_string(w, f->type); + String tag = {}; + if (type->Struct.tags != nullptr) { + tag = type->Struct.tags[i]; + } + if (tag.len != 0) { + String s = quote_to_ascii(heap_allocator(), tag); + type_writer_append(w, s.text, s.len); + gb_free(heap_allocator(), s.text); + } + } + type_writer_appendb(w, '}'); + return; + + case Type_BitField: + type_writer_appendc(w, "bit_field"); + write_type_to_canonical_string(w, type->BitField.backing_type); + type_writer_appendc(w, " {"); + for (isize i = 0; i < type->BitField.fields.count; i++) { + Entity *f = type->BitField.fields[i]; + if (i > 0) { + type_writer_appendc(w, CANONICAL_FIELD_SEPARATOR); + } + type_writer_append(w, f->token.string.text, f->token.string.len); + type_writer_appendc(w, CANONICAL_TYPE_SEPARATOR); + write_type_to_canonical_string(w, f->type); + type_writer_appendc(w, CANONICAL_BIT_FIELD_SEPARATOR); + type_writer_append_fmt(w, "%u", type->BitField.bit_sizes[i]); + } + type_writer_appendc(w, " }"); + return; + + case Type_Proc: + type_writer_appendc(w, "proc"); + if (default_calling_convention() != type->Proc.calling_convention) { + type_writer_appendc(w, "\""); + type_writer_appendc(w, proc_calling_convention_strings[type->Proc.calling_convention]); + type_writer_appendc(w, "\""); + } + + write_canonical_params(w, type->Proc.params); + if (type->Proc.result_count > 0) { + type_writer_appendc(w, "->"); + write_canonical_params(w, type->Proc.results); + } + return; + + case Type_Generic: + if (is_in_doc_writer()) { + type_writer_appendc(w, "$"); + type_writer_append(w, type->Generic.name.text, type->Generic.name.len); + type_writer_append_fmt(w, "%lld", cast(long long)type->Generic.id); + } else { + GB_PANIC("Type_Generic should never be hit"); + } + return; + + case Type_Named: + if (type->Named.type_name != nullptr) { + write_canonical_entity_name(w, type->Named.type_name); + return; + } else { + type_writer_append(w, type->Named.name.text, type->Named.name.len); + } + return; + + case Type_Tuple: + type_writer_appendc(w, "params"); + write_canonical_params(w, type); + return; + default: + GB_PANIC("unknown type kind %d %.*s", type->kind, LIT(type_strings[type->kind])); + break; + } + + return; +} \ No newline at end of file diff --git a/src/name_canonicalization.hpp b/src/name_canonicalization.hpp new file mode 100644 index 000000000..304aff42e --- /dev/null +++ b/src/name_canonicalization.hpp @@ -0,0 +1,128 @@ +/* + General Rules for canonical name mangling + + * No spaces between any values + + * normal declarations - pkg::name + * builtin names - just their normal name e.g. `i32` or `string` + * nested (zero level) - pkg::parent1::parent2::name + * nested (more scopes) - pkg::parent1::parent2::name[4] + * [4] indicates the 4th scope within a procedure numbered in depth-first order + * file private - pkg::[file_name]::name + * Example: `pkg::[file.odin]::Type` + * polymorphic procedure/type - pkg::foo:TYPE + * naming convention for parameters + * type + * $typeid_based_name + * $$constant_parameter + * Example: `foo::to_thing:proc(u64)->([]u8)` + * nested decl in polymorphic procedure - pkg::foo:TYPE::name + * anonymous procedures - pkg::foo::$anon[file.odin:123] + * 123 is the file offset in bytes +*/ + +#define CANONICAL_TYPE_SEPARATOR ":" +#define CANONICAL_NAME_SEPARATOR "::" +// #define CANONICAL_NAME_SEPARATOR "·" + +#define CANONICAL_BIT_FIELD_SEPARATOR "|" + +#define CANONICAL_PARAM_SEPARATOR "," + +#define CANONICAL_PARAM_TYPEID "$" +#define CANONICAL_PARAM_CONST "$$" + +#define CANONICAL_PARAM_C_VARARG "#c_vararg" +#define CANONICAL_PARAM_VARARG ".." + +#define CANONICAL_FIELD_SEPARATOR "," + +#define CANONICAL_ANON_PREFIX "$anon" + +#define CANONICAL_NONE_TYPE "<>" + +#define CANONICAL_RANGE_OPERATOR "..=" + +struct TypeWriter; + +gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type); +gb_internal void write_canonical_entity_name(TypeWriter *w, Entity *e); +gb_internal u64 type_hash_canonical_type(Type *type); +gb_internal String type_to_canonical_string(gbAllocator allocator, Type *type); +gb_internal gbString temp_canonical_string(Type *type); + + +gb_internal GB_COMPARE_PROC(type_info_pair_cmp); + + +struct TypeInfoPair { + Type *type; + u64 hash; // see: type_hash_canonical_type +}; + +struct TypeSet { + TypeInfoPair *keys; + usize count; + usize capacity; +}; + +static constexpr u64 TYPE_SET_TOMBSTONE = ~(u64)(0ull); + +struct TypeSetIterator { + TypeSet *set; + usize index; + + TypeSetIterator &operator++() noexcept { + for (;;) { + ++index; + if (set->capacity == index) { + return *this; + } + TypeInfoPair key = set->keys[index]; + if (key.hash != 0 && key.hash != TYPE_SET_TOMBSTONE) { + return *this; + } + } + } + + bool operator==(TypeSetIterator const &other) const noexcept { + return this->set == other.set && this->index == other.index; + } + + + operator TypeInfoPair *() const { + return &set->keys[index]; + } +}; + + +gb_internal void type_set_init (TypeSet *s, isize capacity = 16); +gb_internal void type_set_destroy(TypeSet *s); +gb_internal Type *type_set_add (TypeSet *s, Type *ptr); +gb_internal Type *type_set_add (TypeSet *s, TypeInfoPair pair); +gb_internal bool type_set_update (TypeSet *s, Type *ptr); // returns true if it previously existed +gb_internal bool type_set_update (TypeSet *s, TypeInfoPair pair); // returns true if it previously existed +gb_internal bool type_set_exists (TypeSet *s, Type *ptr); +gb_internal void type_set_remove (TypeSet *s, Type *ptr); +gb_internal void type_set_clear (TypeSet *s); +gb_internal TypeInfoPair *type_set_retrieve(TypeSet *s, Type *ptr); + +gb_internal TypeSetIterator begin(TypeSet &set) noexcept; +gb_internal TypeSetIterator end(TypeSet &set) noexcept; + + +template +gb_internal gb_inline V *map_get(PtrMap *h, Type *key) { + return map_get(h, type_hash_canonical_type(key)); +} +template +gb_internal gb_inline void map_set(PtrMap *h, Type *key, V const &value) { + map_set(h, type_hash_canonical_type(key), value); +} + +template +gb_internal gb_inline V &map_must_get(PtrMap *h, Type *key) { + V *ptr = map_get(h, type_hash_canonical_type(key)); + GB_ASSERT(ptr != nullptr); + return *ptr; +} \ No newline at end of file diff --git a/src/parser.cpp b/src/parser.cpp index 33b493900..df0ad87f8 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3016,9 +3016,10 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { syntax_error(token, "Expected a type or range, got nothing"); } - if (allow_token(f, Token_Semicolon)) { + if (f->curr_token.kind == Token_Semicolon && f->curr_token.string == ";") { + expect_token(f, Token_Semicolon); underlying = parse_type(f); - } else if (allow_token(f, Token_Comma)) { + } else if (allow_token(f, Token_Comma) || allow_token(f, Token_Semicolon)) { String p = token_to_string(f->prev_token); syntax_error(token_end_of_line(f, f->prev_token), "Expected a semicolon, got a %.*s", LIT(p)); @@ -4342,30 +4343,132 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl } - if (f->curr_token.kind == Token_Colon) { - Array names = convert_to_ident_list(f, list, true, allow_poly_names); // Copy for semantic reasons + if (f->curr_token.kind != Token_Colon) { + // NOTE(bill): proc(Type, Type, Type) + for (AstAndFlags const &item : list) { + Ast *type = item.node; + Token token = blank_token; + if (allowed_flags&FieldFlag_Results) { + // NOTE(bill): Make this nothing and not `_` + token.string = str_lit(""); + } + + auto names = array_make(ast_allocator(f), 1); + token.pos = ast_token(type).pos; + names[0] = ast_ident(f, token); + u32 flags = check_field_prefixes(f, list.count, allowed_flags, item.flags); + Token tag = {}; + Ast *param = ast_field(f, names, item.node, nullptr, flags, tag, docs, f->line_comment); + array_add(¶ms, param); + } + + if (name_count_) *name_count_ = total_name_count; + return ast_field_list(f, start_token, params); + } + + // NOTE(bill): proc(ident, ident, ident: Type) + + if (f->prev_token.kind == Token_Comma) { + syntax_error(f->prev_token, "Trailing comma before a colon is not allowed"); + } + Array names = convert_to_ident_list(f, list, true, allow_poly_names); // Copy for semantic reasons + if (names.count == 0) { + syntax_error(f->curr_token, "Empty field declaration"); + } + bool any_polymorphic_names = check_procedure_name_list(names); + u32 set_flags = 0; + if (list.count > 0) { + set_flags = list[0].flags; + } + set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags); + total_name_count += names.count; + + Ast *type = nullptr; + Ast *default_value = nullptr; + Token tag = {}; + + expect_token_after(f, Token_Colon, "field list"); + if (f->curr_token.kind != Token_Eq) { + type = parse_var_type(f, allow_ellipsis, allow_typeid_token); + Ast *tt = unparen_expr(type); + if (tt == nullptr) { + syntax_error(f->prev_token, "Invalid type expression in field list"); + } else if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { + syntax_error(type, "Specialization of typeid is not allowed without polymorphic names"); + } + } + + if (allow_token(f, Token_Eq)) { + default_value = parse_expr(f, false); + if (!allow_default_parameters) { + syntax_error(f->curr_token, "Default parameters are only allowed for procedures"); + default_value = nullptr; + } + } + + if (default_value != nullptr && names.count > 1) { + syntax_error(f->curr_token, "Default parameters can only be applied to single values"); + } + + if (allowed_flags == FieldFlag_Struct && default_value != nullptr) { + syntax_error(default_value, "Default parameters are not allowed for structs"); + default_value = nullptr; + } + + if (type != nullptr && type->kind == Ast_Ellipsis) { + if (seen_ellipsis) syntax_error(type, "Extra variadic parameter after ellipsis"); + seen_ellipsis = true; + if (names.count != 1) { + syntax_error(type, "Variadic parameters can only have one field name"); + } + } else if (seen_ellipsis && default_value == nullptr) { + syntax_error(f->curr_token, "Extra parameter after ellipsis without a default value"); + } + + if (type != nullptr && default_value == nullptr) { + if (f->curr_token.kind == Token_String) { + tag = expect_token(f, Token_String); + if ((allowed_flags & FieldFlag_Tags) == 0) { + syntax_error(tag, "Field tags are only allowed within structures"); + } + } + } + + bool more_fields = allow_field_separator(f); + Ast *param = ast_field(f, names, type, default_value, set_flags, tag, docs, f->line_comment); + array_add(¶ms, param); + + if (!more_fields) { + if (name_count_) *name_count_ = total_name_count; + return ast_field_list(f, start_token, params); + } + + while (f->curr_token.kind != follow && + f->curr_token.kind != Token_EOF && + f->curr_token.kind != Token_Semicolon) { + CommentGroup *docs = f->lead_comment; + + if (!is_signature) parse_enforce_tabs(f); + u32 set_flags = parse_field_prefixes(f); + Token tag = {}; + Array names = parse_ident_list(f, allow_poly_names); if (names.count == 0) { syntax_error(f->curr_token, "Empty field declaration"); + break; } bool any_polymorphic_names = check_procedure_name_list(names); - u32 set_flags = 0; - if (list.count > 0) { - set_flags = list[0].flags; - } set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags); total_name_count += names.count; Ast *type = nullptr; Ast *default_value = nullptr; - Token tag = {}; - expect_token_after(f, Token_Colon, "field list"); if (f->curr_token.kind != Token_Eq) { type = parse_var_type(f, allow_ellipsis, allow_typeid_token); Ast *tt = unparen_expr(type); - if (tt == nullptr) { - syntax_error(f->prev_token, "Invalid type expression in field list"); - } else if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { + if (is_signature && !any_polymorphic_names && + tt != nullptr && + tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { syntax_error(type, "Specialization of typeid is not allowed without polymorphic names"); } } @@ -4382,11 +4485,6 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl syntax_error(f->curr_token, "Default parameters can only be applied to single values"); } - if (allowed_flags == FieldFlag_Struct && default_value != nullptr) { - syntax_error(default_value, "Default parameters are not allowed for structs"); - default_value = nullptr; - } - if (type != nullptr && type->kind == Ast_Ellipsis) { if (seen_ellipsis) syntax_error(type, "Extra variadic parameter after ellipsis"); seen_ellipsis = true; @@ -4406,105 +4504,14 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl } } - bool more_fields = allow_field_separator(f); + + bool ok = allow_field_separator(f); Ast *param = ast_field(f, names, type, default_value, set_flags, tag, docs, f->line_comment); array_add(¶ms, param); - if (!more_fields) { - if (name_count_) *name_count_ = total_name_count; - return ast_field_list(f, start_token, params); + if (!ok) { + break; } - - while (f->curr_token.kind != follow && - f->curr_token.kind != Token_EOF && - f->curr_token.kind != Token_Semicolon) { - CommentGroup *docs = f->lead_comment; - - if (!is_signature) parse_enforce_tabs(f); - u32 set_flags = parse_field_prefixes(f); - Token tag = {}; - Array names = parse_ident_list(f, allow_poly_names); - if (names.count == 0) { - syntax_error(f->curr_token, "Empty field declaration"); - break; - } - bool any_polymorphic_names = check_procedure_name_list(names); - set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags); - total_name_count += names.count; - - Ast *type = nullptr; - Ast *default_value = nullptr; - expect_token_after(f, Token_Colon, "field list"); - if (f->curr_token.kind != Token_Eq) { - type = parse_var_type(f, allow_ellipsis, allow_typeid_token); - Ast *tt = unparen_expr(type); - if (is_signature && !any_polymorphic_names && - tt != nullptr && - tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { - syntax_error(type, "Specialization of typeid is not allowed without polymorphic names"); - } - } - - if (allow_token(f, Token_Eq)) { - default_value = parse_expr(f, false); - if (!allow_default_parameters) { - syntax_error(f->curr_token, "Default parameters are only allowed for procedures"); - default_value = nullptr; - } - } - - if (default_value != nullptr && names.count > 1) { - syntax_error(f->curr_token, "Default parameters can only be applied to single values"); - } - - if (type != nullptr && type->kind == Ast_Ellipsis) { - if (seen_ellipsis) syntax_error(type, "Extra variadic parameter after ellipsis"); - seen_ellipsis = true; - if (names.count != 1) { - syntax_error(type, "Variadic parameters can only have one field name"); - } - } else if (seen_ellipsis && default_value == nullptr) { - syntax_error(f->curr_token, "Extra parameter after ellipsis without a default value"); - } - - if (type != nullptr && default_value == nullptr) { - if (f->curr_token.kind == Token_String) { - tag = expect_token(f, Token_String); - if ((allowed_flags & FieldFlag_Tags) == 0) { - syntax_error(tag, "Field tags are only allowed within structures"); - } - } - } - - - bool ok = allow_field_separator(f); - Ast *param = ast_field(f, names, type, default_value, set_flags, tag, docs, f->line_comment); - array_add(¶ms, param); - - if (!ok) { - break; - } - } - - if (name_count_) *name_count_ = total_name_count; - return ast_field_list(f, start_token, params); - } - - for (AstAndFlags const &item : list) { - Ast *type = item.node; - Token token = blank_token; - if (allowed_flags&FieldFlag_Results) { - // NOTE(bill): Make this nothing and not `_` - token.string = str_lit(""); - } - - auto names = array_make(ast_allocator(f), 1); - token.pos = ast_token(type).pos; - names[0] = ast_ident(f, token); - u32 flags = check_field_prefixes(f, list.count, allowed_flags, item.flags); - Token tag = {}; - Ast *param = ast_field(f, names, item.node, nullptr, flags, tag, docs, f->line_comment); - array_add(¶ms, param); } if (name_count_) *name_count_ = total_name_count; @@ -4572,6 +4579,9 @@ gb_internal Ast *parse_do_body(AstFile *f, Token const &token, char const *msg) gb_internal bool parse_control_statement_semicolon_separator(AstFile *f) { Token tok = peek_token(f); if (tok.kind != Token_OpenBrace) { + if (f->curr_token.kind == Token_Semicolon && f->curr_token.string != ";") { + syntax_error(token_end_of_line(f, f->prev_token), "Expected ';', got newline"); + } return allow_token(f, Token_Semicolon); } if (f->curr_token.string == ";") { diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index ff4befc37..5097e2bb6 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -42,7 +42,7 @@ gb_internal void ptr_set_destroy(PtrSet *s) { template gb_internal isize ptr_set__find(PtrSet *s, T ptr) { - GB_ASSERT(ptr != nullptr); + GB_ASSERT(ptr != 0); if (s->count != 0) { #if 0 for (usize i = 0; i < s->capacity; i++) { @@ -58,7 +58,7 @@ gb_internal isize ptr_set__find(PtrSet *s, T ptr) { T key = s->keys[hash_index]; if (key == ptr) { return hash_index; - } else if (key == nullptr) { + } else if (key == 0) { return -1; } hash_index = (hash_index+1)&mask; @@ -122,7 +122,7 @@ gb_internal bool ptr_set_update(PtrSet *s, T ptr) { // returns true if it pre for (usize i = 0; i < s->capacity; i++) { T *key = &s->keys[hash_index]; GB_ASSERT(*key != ptr); - if (*key == (T)PtrSet::TOMBSTONE || *key == nullptr) { + if (*key == (T)PtrSet::TOMBSTONE || *key == 0) { *key = ptr; s->count++; return false; @@ -169,7 +169,7 @@ struct PtrSetIterator { return *this; } T key = set->keys[index]; - if (key != nullptr && key != (T)PtrSet::TOMBSTONE) { + if (key != 0 && key != (T)PtrSet::TOMBSTONE) { return *this; } } @@ -191,7 +191,7 @@ gb_internal PtrSetIterator begin(PtrSet &set) noexcept { usize index = 0; while (index < set.capacity) { T key = set.keys[index]; - if (key != nullptr && key != (T)PtrSet::TOMBSTONE) { + if (key != 0 && key != (T)PtrSet::TOMBSTONE) { break; } index++; diff --git a/src/types.cpp b/src/types.cpp index 412448cbc..43fe625f2 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1,5 +1,5 @@ -struct Scope; struct Ast; +struct Scope; struct Entity; enum BasicKind { @@ -161,10 +161,10 @@ struct TypeStruct { struct TypeUnion { Slice variants; - + Ast * node; Scope * scope; - + i64 variant_block_size; i64 custom_align; Type * polymorphic_params; // Type_Tuple @@ -503,9 +503,9 @@ gb_global Type basic_types[] = { {Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}}, {Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}}, {Type_Basic, {Basic_cstring, BasicFlag_String, -1, STR_LIT("cstring")}}, - {Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}}, + {Type_Basic, {Basic_any, 0, 16, STR_LIT("any")}}, - {Type_Basic, {Basic_typeid, 0, -1, STR_LIT("typeid")}}, + {Type_Basic, {Basic_typeid, 0, 8, STR_LIT("typeid")}}, // Endian {Type_Basic, {Basic_i16le, BasicFlag_Integer | BasicFlag_EndianLittle, 2, STR_LIT("i16le")}}, @@ -856,40 +856,6 @@ gb_internal void type_path_pop(TypePath *tp) { #define FAILURE_SIZE 0 #define FAILURE_ALIGNMENT 0 -gb_internal bool type_ptr_set_exists(PtrSet *s, Type *t); - -gb_internal bool type_ptr_set_update(PtrSet *s, Type *t) { - if (t == nullptr) { - return true; - } - if (type_ptr_set_exists(s, t)) { - return true; - } - ptr_set_add(s, t); - return false; -} - -gb_internal bool type_ptr_set_exists(PtrSet *s, Type *t) { - if (t == nullptr) { - return true; - } - - if (ptr_set_exists(s, t)) { - return true; - } - - // TODO(bill, 2019-10-05): This is very slow and it's probably a lot - // faster to cache types correctly - for (Type *f : *s) { - if (are_types_identical(t, f)) { - ptr_set_add(s, t); - return true; - } - } - - return false; -} - gb_internal Type *base_type(Type *t) { for (;;) { if (t == nullptr) { @@ -1438,7 +1404,7 @@ gb_internal bool is_type_matrix(Type *t) { gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) { t = base_type(t); GB_ASSERT(t->kind == Type_Matrix); - + Type *elem = t->Matrix.elem; i64 row_count = gb_max(t->Matrix.row_count, 1); i64 column_count = gb_max(t->Matrix.column_count, 1); @@ -1450,15 +1416,15 @@ gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) { i64 elem_align = type_align_of_internal(elem, tp); if (pop) type_path_pop(tp); - + i64 elem_size = type_size_of(elem); - + // NOTE(bill, 2021-10-25): The alignment strategy here is to have zero padding // It would be better for performance to pad each column so that each column // could be maximally aligned but as a compromise, having no padding will be // beneficial to third libraries that assume no padding - + i64 total_expected_size = row_count*column_count*elem_size; // i64 min_alignment = prev_pow2(elem_align * row_count); i64 min_alignment = prev_pow2(total_expected_size); @@ -1466,7 +1432,7 @@ gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) { min_alignment >>= 1; } min_alignment = gb_max(min_alignment, elem_align); - + i64 align = gb_min(min_alignment, build_context.max_simd_align); return align; } @@ -1480,7 +1446,7 @@ gb_internal i64 matrix_type_stride_in_bytes(Type *t, struct TypePath *tp) { } else if (t->Matrix.row_count == 0) { return 0; } - + i64 elem_size; if (tp != nullptr) { elem_size = type_size_of_internal(t->Matrix.elem, tp); @@ -1489,7 +1455,7 @@ gb_internal i64 matrix_type_stride_in_bytes(Type *t, struct TypePath *tp) { } i64 stride_in_bytes = 0; - + // NOTE(bill, 2021-10-25): The alignment strategy here is to have zero padding // It would be better for performance to pad each column/row so that each column/row // could be maximally aligned but as a compromise, having no padding will be @@ -1545,7 +1511,7 @@ gb_internal i64 matrix_row_major_index_to_offset(Type *t, i64 index) { gb_internal i64 matrix_column_major_index_to_offset(Type *t, i64 index) { t = base_type(t); GB_ASSERT(t->kind == Type_Matrix); - + i64 row_index = index%t->Matrix.row_count; i64 column_index = index/t->Matrix.row_count; return matrix_indices_to_offset(t, row_index, column_index); @@ -1566,7 +1532,7 @@ gb_internal bool is_type_valid_for_matrix_elems(Type *t) { return true; } else if (is_type_complex(t)) { return true; - } + } if (t->kind == Type_Generic) { return true; } @@ -2119,6 +2085,26 @@ gb_internal bool is_type_sliceable(Type *t) { return false; } +gb_internal Entity *type_get_polymorphic_parent(Type *t, Type **params_) { + t = base_type(t); + if (t == nullptr) { + return nullptr; + } + Type *parent = nullptr; + if (t->kind == Type_Struct) { + parent = t->Struct.polymorphic_parent; + if (params_) *params_ = t->Struct.polymorphic_params; + } else if (t->kind == Type_Union) { + parent = t->Union.polymorphic_parent; + if (params_) *params_ = t->Union.polymorphic_params; + } + if (parent != nullptr) { + GB_ASSERT(parent->kind == Type_Named); + + return parent->Named.type_name; + } + return nullptr; +} gb_internal bool is_type_polymorphic_record(Type *t) { t = base_type(t); @@ -2485,7 +2471,7 @@ gb_internal bool is_type_simple_compare(Type *t) { case Type_Proc: case Type_BitSet: return true; - + case Type_Matrix: return is_type_simple_compare(t->Matrix.elem); @@ -2732,7 +2718,7 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple case Type_Array: return (x->Array.count == y->Array.count) && are_types_identical(x->Array.elem, y->Array.elem); - + case Type_Matrix: return x->Matrix.row_count == y->Matrix.row_count && x->Matrix.column_count == y->Matrix.column_count && @@ -2757,7 +2743,37 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple case Type_Enum: - return x == y; // NOTE(bill): All enums are unique + if (x == y) { + return true; + } + if (x->Enum.fields.count != y->Enum.fields.count) { + return false; + } + if (!are_types_identical(x->Enum.base_type, y->Enum.base_type)) { + return false; + } + if (x->Enum.min_value_index != y->Enum.min_value_index) { + return false; + } + if (x->Enum.max_value_index != y->Enum.max_value_index) { + return false; + } + + for (isize i = 0; i < x->Enum.fields.count; i++) { + Entity *a = x->Enum.fields[i]; + Entity *b = y->Enum.fields[i]; + if (a->token.string != b->token.string) { + return false; + } + GB_ASSERT(a->kind == b->kind); + GB_ASSERT(a->kind == Entity_Constant); + bool same = compare_exact_values(Token_CmpEq, a->Constant.value, b->Constant.value); + if (!same) { + return false; + } + } + + return true; case Type_Union: if (x->Union.variants.count == y->Union.variants.count && @@ -2815,7 +2831,9 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple return false; } } - return are_types_identical(x->Struct.polymorphic_params, y->Struct.polymorphic_params); + // TODO(bill): Which is the correct logic here? + // return are_types_identical(x->Struct.polymorphic_params, y->Struct.polymorphic_params); + return true; } break; @@ -3592,7 +3610,7 @@ gb_internal bool are_struct_fields_reordered(Type *type) { return false; } GB_ASSERT(type->Struct.offsets != nullptr); - + i64 prev_offset = 0; for_array(i, type->Struct.fields) { i64 offset = type->Struct.offsets[i]; @@ -3613,9 +3631,9 @@ gb_internal Slice struct_fields_index_by_increasing_offset(gbAllocator allo return {}; } GB_ASSERT(type->Struct.offsets != nullptr); - + auto indices = slice_make(allocator, type->Struct.fields.count); - + i64 prev_offset = 0; bool is_ordered = true; for_array(i, indices) { @@ -3630,14 +3648,14 @@ gb_internal Slice struct_fields_index_by_increasing_offset(gbAllocator allo isize n = indices.count; for (isize i = 1; i < n; i++) { isize j = i; - + while (j > 0 && type->Struct.offsets[indices[j-1]] > type->Struct.offsets[indices[j]]) { gb_swap(i32, indices[j-1], indices[j]); j -= 1; - } + } } } - + return indices; } @@ -3685,8 +3703,8 @@ gb_internal i64 type_size_of(Type *t) { switch (t->Basic.kind) { case Basic_string: size = 2*build_context.int_size; break; case Basic_cstring: size = build_context.ptr_size; break; - case Basic_any: size = 2*build_context.ptr_size; break; - case Basic_typeid: size = build_context.ptr_size; break; + case Basic_any: size = 16; break; + case Basic_typeid: size = 8; break; case Basic_int: case Basic_uint: size = build_context.int_size; @@ -3748,8 +3766,8 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { switch (t->Basic.kind) { case Basic_string: return build_context.int_size; case Basic_cstring: return build_context.ptr_size; - case Basic_any: return build_context.ptr_size; - case Basic_typeid: return build_context.ptr_size; + case Basic_any: return 8; + case Basic_typeid: return 8; case Basic_int: case Basic_uint: return build_context.int_size; @@ -3887,8 +3905,8 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { // IMPORTANT TODO(bill): Figure out the alignment of vector types return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.max_simd_align*2); } - - case Type_Matrix: + + case Type_Matrix: return matrix_align_of(t, path); case Type_SoaPointer: @@ -3999,8 +4017,8 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { switch (kind) { case Basic_string: return 2*build_context.int_size; case Basic_cstring: return build_context.ptr_size; - case Basic_any: return 2*build_context.ptr_size; - case Basic_typeid: return build_context.ptr_size; + case Basic_any: return 16; + case Basic_typeid: return 8; case Basic_int: case Basic_uint: return build_context.int_size; @@ -4175,7 +4193,7 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { Type *elem = t->SimdVector.elem; return count * type_size_of_internal(elem, path); } - + case Type_Matrix: { i64 stride_in_bytes = matrix_type_stride_in_bytes(t, path); if (t->Matrix.is_row_major) { @@ -4236,7 +4254,7 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) { return 0; // data case 1: if (field_type_) *field_type_ = t_typeid; - return build_context.ptr_size; // id + return 8; // id } } break; @@ -4307,8 +4325,8 @@ gb_internal i64 type_offset_of_from_selection(Type *type, Selection sel) { } } else if (t->Basic.kind == Basic_any) { switch (index) { - case 0: t = t_type_info_ptr; break; - case 1: t = t_rawptr; break; + case 0: t = t_rawptr; break; + case 1: t = t_typeid; break; } } break; @@ -4580,7 +4598,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha break; case Type_Array: - str = gb_string_appendc(str, gb_bprintf("[%d]", cast(int)type->Array.count)); + str = gb_string_appendc(str, gb_bprintf("[%lld]", cast(long long)type->Array.count)); str = write_type_to_string(str, type->Array.elem); break; @@ -4753,10 +4771,10 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha } break; case ProcCC_CDecl: - str = gb_string_appendc(str, " \"cdecl\" "); + str = gb_string_appendc(str, " \"c\" "); break; case ProcCC_StdCall: - str = gb_string_appendc(str, " \"stdcall\" "); + str = gb_string_appendc(str, " \"std\" "); break; case ProcCC_FastCall: str = gb_string_appendc(str, " \"fastcall\" "); @@ -4814,7 +4832,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha str = gb_string_append_fmt(str, "#simd[%d]", cast(int)type->SimdVector.count); str = write_type_to_string(str, type->SimdVector.elem); break; - + case Type_Matrix: if (type->Matrix.is_row_major) { str = gb_string_appendc(str, "#row_major "); @@ -4855,6 +4873,3 @@ gb_internal gbString type_to_string(Type *type, bool shorthand) { gb_internal gbString type_to_string_shorthand(Type *type) { return type_to_string(type, true); } - - - diff --git a/tests/core/os/os2/dir.odin b/tests/core/os/os2/dir.odin index 5bb5c9820..7077e9ae2 100644 --- a/tests/core/os/os2/dir.odin +++ b/tests/core/os/os2/dir.odin @@ -5,6 +5,7 @@ import "core:log" import "core:path/filepath" import "core:slice" import "core:testing" +import "core:strings" @(test) test_read_dir :: proc(t: ^testing.T) { @@ -30,3 +31,76 @@ test_read_dir :: proc(t: ^testing.T) { testing.expect_value(t, fis[1].name, "sub") testing.expect_value(t, fis[1].type, os.File_Type.Directory) } + +@(test) +test_walker :: proc(t: ^testing.T) { + path := filepath.join({#directory, "../dir"}) + defer delete(path) + + w := os.walker_create(path) + defer os.walker_destroy(&w) + + test_walker_internal(t, &w) +} + +@(test) +test_walker_file :: proc(t: ^testing.T) { + path := filepath.join({#directory, "../dir"}) + defer delete(path) + + f, err := os.open(path) + testing.expect_value(t, err, nil) + defer os.close(f) + + w := os.walker_create(f) + defer os.walker_destroy(&w) + + test_walker_internal(t, &w) +} + +test_walker_internal :: proc(t: ^testing.T, w: ^os.Walker) { + Seen :: struct { + type: os.File_Type, + path: string, + } + + expected := [?]Seen{ + {.Regular, filepath.join({"dir", "b.txt"})}, + {.Directory, filepath.join({"dir", "sub"})}, + {.Regular, filepath.join({"dir", "sub", ".gitkeep"})}, + } + + seen: [dynamic]Seen + defer delete(seen) + + for info in os.walker_walk(w) { + + errpath, err := os.walker_error(w) + testing.expectf(t, err == nil, "walker error for %q: %v", errpath, err) + + append(&seen, Seen{ + info.type, + strings.clone(info.fullpath), + }) + } + + if _, err := os.walker_error(w); err == .Unsupported { + log.warn("os2 directory functionality is unsupported, skipping test") + return + } + + testing.expect_value(t, len(seen), len(expected)) + + for expectation in expected { + found: bool + for entry in seen { + if strings.has_suffix(entry.path, expectation.path) { + found = true + testing.expect_value(t, entry.type, expectation.type) + delete(entry.path) + } + } + testing.expectf(t, found, "%q not found in %v", expectation, seen) + delete(expectation.path) + } +} diff --git a/tests/core/os/os2/file.odin b/tests/core/os/os2/file.odin new file mode 100644 index 000000000..c4df74f4a --- /dev/null +++ b/tests/core/os/os2/file.odin @@ -0,0 +1,31 @@ +package tests_core_os_os2 + +import os "core:os/os2" +import "core:testing" +import "core:path/filepath" + +@(test) +test_clone :: proc(t: ^testing.T) { + f, err := os.open(filepath.join({#directory, "file.odin"}, context.temp_allocator)) + testing.expect_value(t, err, nil) + testing.expect(t, f != nil) + + clone: ^os.File + clone, err = os.clone(f) + testing.expect_value(t, err, nil) + testing.expect(t, clone != nil) + + testing.expect_value(t, os.name(clone), os.name(f)) + testing.expect(t, os.fd(clone) != os.fd(f)) + + os.close(f) + + buf: [128]byte + n: int + n, err = os.read(clone, buf[:]) + testing.expect_value(t, err, nil) + testing.expect(t, n > 13) + testing.expect_value(t, string(buf[:13]), "package tests") + + os.close(clone) +} diff --git a/tests/core/strings/test_core_strings.odin b/tests/core/strings/test_core_strings.odin index 44c79ce73..7b5f7fbb4 100644 --- a/tests/core/strings/test_core_strings.odin +++ b/tests/core/strings/test_core_strings.odin @@ -1,5 +1,6 @@ package test_core_strings +import "core:mem" import "core:strings" import "core:testing" import "base:runtime" @@ -175,3 +176,45 @@ test_substring :: proc(t: ^testing.T) { testing.expectf(t, sub == tc.sub, "expected %v[%v:%v] to return sub: %v, got: %v", tc.s, tc.start, tc.end, tc.sub, sub) } } + +@test +test_builder_to_cstring_with_nil_allocator :: proc(t: ^testing.T) { + b := strings.builder_make_none(mem.nil_allocator()) + + cstr, err := strings.to_cstring(&b) + testing.expect_value(t, cstr, nil) + testing.expect_value(t, err, mem.Allocator_Error.Out_Of_Memory) +} + +@test +test_builder_to_cstring :: proc(t: ^testing.T) { + buf: [8]byte + a: mem.Arena + mem.arena_init(&a, buf[:]) + + b := strings.builder_make_none(mem.arena_allocator(&a)) + + { + cstr, err := strings.to_cstring(&b) + testing.expectf(t, cstr != nil, "expected cstr to not be nil, got %v", cstr) + testing.expect_value(t, err, nil) + } + + n := strings.write_byte(&b, 'a') + testing.expect(t, n == 1) + + { + cstr, err := strings.to_cstring(&b) + testing.expectf(t, cstr != nil, "expected cstr to not be nil, got %v", cstr) + testing.expect_value(t, err, nil) + } + + n = strings.write_string(&b, "aaaaaaa") + testing.expect(t, n == 7) + + { + cstr, err := strings.to_cstring(&b) + testing.expect(t, cstr == nil) + testing.expect(t, err == .Out_Of_Memory) + } +} diff --git a/vendor/cgltf/README.md b/vendor/cgltf/README.md index 334b6a1e7..9ae236d85 100644 --- a/vendor/cgltf/README.md +++ b/vendor/cgltf/README.md @@ -67,7 +67,7 @@ main :: proc() { ``` Writing to memory: -```c +```odin package main import "vendor:cgltf" diff --git a/vendor/directx/d3d11/d3d11.odin b/vendor/directx/d3d11/d3d11.odin index 3c41d1597..bb91e87ce 100644 --- a/vendor/directx/d3d11/d3d11.odin +++ b/vendor/directx/d3d11/d3d11.odin @@ -19,6 +19,8 @@ BOOL :: dxgi.BOOL UINT :: dxgi.UINT INT :: dxgi.INT +LPCWSTR :: [^]u16 + RECT :: dxgi.RECT SIZE :: dxgi.SIZE @@ -3281,7 +3283,19 @@ IVideoContext_VTable :: struct { VideoProcessorGetStreamRotation: proc "system" (this: ^IVideoContext, pVideoProcessor: ^IVideoProcessor, StreamIndex: u32, pEnable: ^BOOL, pRotation: ^VIDEO_PROCESSOR_ROTATION), } - +IUserDefinedAnnotation_UUID_STRING :: "B2DAAD8B-03D4-4DBF-95EB-32AB4B63D0AB" +IUserDefinedAnnotation_UUID := &IID{0xB2DAAD8B, 0x03D4, 0x4DBF, {0x95, 0xEB, 0x32, 0xAB, 0x4B, 0x63, 0xD0, 0xAB}} +IUserDefinedAnnotation :: struct #raw_union { + #subtype iunknown: IUnknown, + using id3d11userdefinedannotation_vtable: ^IUserDefinedAnnotation_VTable, +} +IUserDefinedAnnotation_VTable :: struct { + using iunknown_vtable : IUnknown_VTable, + BeginEvent: proc "system" (this: ^IUserDefinedAnnotation, Name: LPCWSTR) -> i32, + EndEvent: proc "system" (this: ^IUserDefinedAnnotation) -> i32, + GetStatus: proc "system" (this: ^IUserDefinedAnnotation) -> i32, + SetMarker: proc "system" (this: ^IUserDefinedAnnotation, Name: LPCWSTR), +} IVideoDevice_UUID_STRING :: "10EC4D5B-975A-4689-B9E4-D0AAC30FE333" IVideoDevice_UUID := &IID{0x10EC4D5B, 0x975A, 0x4689, {0xB9, 0xE4, 0xD0, 0xAA, 0xC3, 0x0F, 0xE3, 0x33}} diff --git a/vendor/sdl3/image/LICENSE.aom.txt b/vendor/sdl3/image/LICENSE.aom.txt new file mode 100644 index 000000000..fc340c376 --- /dev/null +++ b/vendor/sdl3/image/LICENSE.aom.txt @@ -0,0 +1,27 @@ +Copyright (c) 2016, Alliance for Open Media. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/sdl3/image/LICENSE.avif.txt b/vendor/sdl3/image/LICENSE.avif.txt new file mode 100644 index 000000000..734b2b602 --- /dev/null +++ b/vendor/sdl3/image/LICENSE.avif.txt @@ -0,0 +1,353 @@ +Copyright 2019 Joe Drago. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------ + +Files: src/obu.c + +Copyright © 2018-2019, VideoLAN and dav1d authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------ + +Files: apps/shared/iccjpeg.* + +In plain English: + +1. We don't promise that this software works. (But if you find any bugs, + please let us know!) +2. You can use this software for whatever you want. You don't have to pay us. +3. You may not pretend that you wrote this software. If you use it in a + program, you must acknowledge somewhere in your documentation that + you've used the IJG code. + +In legalese: + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-2013, Thomas G. Lane, Guido Vollbeding. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + + +The Unix configuration script "configure" was produced with GNU Autoconf. +It is copyright by the Free Software Foundation but is freely distributable. +The same holds for its supporting scripts (config.guess, config.sub, +ltmain.sh). Another support script, install-sh, is copyright by X Consortium +but is also freely distributable. + +The IJG distribution formerly included code to read and write GIF files. +To avoid entanglement with the Unisys LZW patent, GIF reading support has +been removed altogether, and the GIF writer has been simplified to produce +"uncompressed GIFs". This technique does not use the LZW algorithm; the +resulting GIF files are larger than usual, but are readable by all standard +GIF decoders. + +We are required to state that + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + +------------------------------------------------------------------------------ + +Files: contrib/gdk-pixbuf/* + +Copyright 2020 Emmanuel Gil Peyrot. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------ + +Files: android_jni/gradlew* + + + 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/vendor/sdl3/image/LICENSE.dav1d.txt b/vendor/sdl3/image/LICENSE.dav1d.txt new file mode 100644 index 000000000..875b138ec --- /dev/null +++ b/vendor/sdl3/image/LICENSE.dav1d.txt @@ -0,0 +1,23 @@ +Copyright © 2018-2019, VideoLAN and dav1d authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sdl3/image/LICENSE.tiff.txt b/vendor/sdl3/image/LICENSE.tiff.txt new file mode 100644 index 000000000..828218615 --- /dev/null +++ b/vendor/sdl3/image/LICENSE.tiff.txt @@ -0,0 +1,21 @@ +Copyright (c) 1988-1997 Sam Leffler +Copyright (c) 1991-1997 Silicon Graphics, Inc. + +Permission to use, copy, modify, distribute, and sell this software and +its documentation for any purpose is hereby granted without fee, provided +that (i) the above copyright notices and this permission notice appear in +all copies of the software and related documentation, and (ii) the names of +Sam Leffler and Silicon Graphics may not be used in any advertising or +publicity relating to the software without the specific, prior written +permission of Sam Leffler and Silicon Graphics. + +THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR +ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF +LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THIS SOFTWARE. diff --git a/vendor/sdl3/image/LICENSE.txt b/vendor/sdl3/image/LICENSE.txt new file mode 100644 index 000000000..52d0ed38b --- /dev/null +++ b/vendor/sdl3/image/LICENSE.txt @@ -0,0 +1,17 @@ +Copyright (C) 1997-2025 Sam Lantinga + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/vendor/sdl3/image/LICENSE.webp.txt b/vendor/sdl3/image/LICENSE.webp.txt new file mode 100644 index 000000000..7a6f99547 --- /dev/null +++ b/vendor/sdl3/image/LICENSE.webp.txt @@ -0,0 +1,30 @@ +Copyright (c) 2010, Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/sdl3/image/SDL3_image.dll b/vendor/sdl3/image/SDL3_image.dll new file mode 100644 index 000000000..a45e44530 Binary files /dev/null and b/vendor/sdl3/image/SDL3_image.dll differ diff --git a/vendor/sdl3/image/SDL3_image.lib b/vendor/sdl3/image/SDL3_image.lib new file mode 100644 index 000000000..4e9913b4c Binary files /dev/null and b/vendor/sdl3/image/SDL3_image.lib differ diff --git a/vendor/sdl3/image/include/SDL_image.h b/vendor/sdl3/image/include/SDL_image.h new file mode 100644 index 000000000..9775ee616 --- /dev/null +++ b/vendor/sdl3/image/include/SDL_image.h @@ -0,0 +1,2110 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* WIKI CATEGORY: SDLImage */ + +/** + * # CategorySDLImage + * + * Header file for SDL_image library + * + * A simple library to load images of various formats as SDL surfaces + */ + +#ifndef SDL_IMAGE_H_ +#define SDL_IMAGE_H_ + +#include +#include + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Printable format: "%d.%d.%d", MAJOR, MINOR, MICRO + */ +#define SDL_IMAGE_MAJOR_VERSION 3 +#define SDL_IMAGE_MINOR_VERSION 2 +#define SDL_IMAGE_MICRO_VERSION 0 + +/** + * This is the version number macro for the current SDL_image version. + */ +#define SDL_IMAGE_VERSION \ + SDL_VERSIONNUM(SDL_IMAGE_MAJOR_VERSION, SDL_IMAGE_MINOR_VERSION, SDL_IMAGE_MICRO_VERSION) + +/** + * This macro will evaluate to true if compiled with SDL_image at least X.Y.Z. + */ +#define SDL_IMAGE_VERSION_ATLEAST(X, Y, Z) \ + ((SDL_IMAGE_MAJOR_VERSION >= X) && \ + (SDL_IMAGE_MAJOR_VERSION > X || SDL_IMAGE_MINOR_VERSION >= Y) && \ + (SDL_IMAGE_MAJOR_VERSION > X || SDL_IMAGE_MINOR_VERSION > Y || SDL_IMAGE_MICRO_VERSION >= Z)) + +/** + * This function gets the version of the dynamically linked SDL_image library. + * + * \returns SDL_image version. + * + * \since This function is available since SDL_image 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL IMG_Version(void); + +/** + * Load an image from an SDL data source into a software surface. + * + * An SDL_Surface is a buffer of pixels in memory accessible by the CPU. Use + * this if you plan to hand the data to something else or manipulate it + * further in code. + * + * There are no guarantees about what format the new SDL_Surface data will be; + * in many cases, SDL_image will attempt to supply a surface that exactly + * matches the provided image, but in others it might have to convert (either + * because the image is in a format that SDL doesn't directly support or + * because it's compressed data that could reasonably uncompress to various + * formats and SDL_image had to pick one). You can inspect an SDL_Surface for + * its specifics, and use SDL_ConvertSurface to then migrate to any supported + * format. + * + * If the image format supports a transparent pixel, SDL will set the colorkey + * for the surface. You can enable RLE acceleration on the surface afterwards + * by calling: SDL_SetSurfaceColorKey(image, SDL_RLEACCEL, + * image->format->colorkey); + * + * If `closeio` is true, `src` will be closed before returning, whether this + * function succeeds or not. SDL_image reads everything it needs from `src` + * during this call in any case. + * + * Even though this function accepts a file type, SDL_image may still try + * other decoders that are capable of detecting file type from the contents of + * the image data, but may rely on the caller-provided type string for formats + * that it cannot autodetect. If `type` is NULL, SDL_image will rely solely on + * its ability to guess the format. + * + * There is a separate function to read files from disk without having to deal + * with SDL_IOStream: `IMG_Load("filename.jpg")` will call this function and + * manage those details for you, determining the file type from the filename's + * extension. + * + * There is also IMG_Load_IO(), which is equivalent to this function except + * that it will rely on SDL_image to determine what type of data it is + * loading, much like passing a NULL for type. + * + * If you are using SDL's 2D rendering API, there is an equivalent call to + * load images directly into an SDL_Texture for use by the GPU without using a + * software surface: call IMG_LoadTextureTyped_IO() instead. + * + * When done with the returned surface, the app should dispose of it with a + * call to SDL_DestroySurface(). + * + * \param src an SDL_IOStream that data will be read from. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param type a filename extension that represent this data ("BMP", "GIF", + * "PNG", etc). + * \returns a new SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_Load + * \sa IMG_Load_IO + * \sa SDL_DestroySurface + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadTyped_IO(SDL_IOStream *src, bool closeio, const char *type); + +/** + * Load an image from a filesystem path into a software surface. + * + * An SDL_Surface is a buffer of pixels in memory accessible by the CPU. Use + * this if you plan to hand the data to something else or manipulate it + * further in code. + * + * There are no guarantees about what format the new SDL_Surface data will be; + * in many cases, SDL_image will attempt to supply a surface that exactly + * matches the provided image, but in others it might have to convert (either + * because the image is in a format that SDL doesn't directly support or + * because it's compressed data that could reasonably uncompress to various + * formats and SDL_image had to pick one). You can inspect an SDL_Surface for + * its specifics, and use SDL_ConvertSurface to then migrate to any supported + * format. + * + * If the image format supports a transparent pixel, SDL will set the colorkey + * for the surface. You can enable RLE acceleration on the surface afterwards + * by calling: SDL_SetSurfaceColorKey(image, SDL_RLEACCEL, + * image->format->colorkey); + * + * There is a separate function to read files from an SDL_IOStream, if you + * need an i/o abstraction to provide data from anywhere instead of a simple + * filesystem read; that function is IMG_Load_IO(). + * + * If you are using SDL's 2D rendering API, there is an equivalent call to + * load images directly into an SDL_Texture for use by the GPU without using a + * software surface: call IMG_LoadTexture() instead. + * + * When done with the returned surface, the app should dispose of it with a + * call to + * [SDL_DestroySurface](https://wiki.libsdl.org/SDL3/SDL_DestroySurface) + * (). + * + * \param file a path on the filesystem to load an image from. + * \returns a new SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadTyped_IO + * \sa IMG_Load_IO + * \sa SDL_DestroySurface + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load(const char *file); + +/** + * Load an image from an SDL data source into a software surface. + * + * An SDL_Surface is a buffer of pixels in memory accessible by the CPU. Use + * this if you plan to hand the data to something else or manipulate it + * further in code. + * + * There are no guarantees about what format the new SDL_Surface data will be; + * in many cases, SDL_image will attempt to supply a surface that exactly + * matches the provided image, but in others it might have to convert (either + * because the image is in a format that SDL doesn't directly support or + * because it's compressed data that could reasonably uncompress to various + * formats and SDL_image had to pick one). You can inspect an SDL_Surface for + * its specifics, and use SDL_ConvertSurface to then migrate to any supported + * format. + * + * If the image format supports a transparent pixel, SDL will set the colorkey + * for the surface. You can enable RLE acceleration on the surface afterwards + * by calling: SDL_SetSurfaceColorKey(image, SDL_RLEACCEL, + * image->format->colorkey); + * + * If `closeio` is true, `src` will be closed before returning, whether this + * function succeeds or not. SDL_image reads everything it needs from `src` + * during this call in any case. + * + * There is a separate function to read files from disk without having to deal + * with SDL_IOStream: `IMG_Load("filename.jpg")` will call this function and + * manage those details for you, determining the file type from the filename's + * extension. + * + * There is also IMG_LoadTyped_IO(), which is equivalent to this function + * except a file extension (like "BMP", "JPG", etc) can be specified, in case + * SDL_image cannot autodetect the file format. + * + * If you are using SDL's 2D rendering API, there is an equivalent call to + * load images directly into an SDL_Texture for use by the GPU without using a + * software surface: call IMG_LoadTexture_IO() instead. + * + * When done with the returned surface, the app should dispose of it with a + * call to SDL_DestroySurface(). + * + * \param src an SDL_IOStream that data will be read from. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns a new SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_Load + * \sa IMG_LoadTyped_IO + * \sa SDL_DestroySurface + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load_IO(SDL_IOStream *src, bool closeio); + +/** + * Load an image from a filesystem path into a GPU texture. + * + * An SDL_Texture represents an image in GPU memory, usable by SDL's 2D Render + * API. This can be significantly more efficient than using a CPU-bound + * SDL_Surface if you don't need to manipulate the image directly after + * loading it. + * + * If the loaded image has transparency or a colorkey, a texture with an alpha + * channel will be created. Otherwise, SDL_image will attempt to create an + * SDL_Texture in the most format that most reasonably represents the image + * data (but in many cases, this will just end up being 32-bit RGB or 32-bit + * RGBA). + * + * There is a separate function to read files from an SDL_IOStream, if you + * need an i/o abstraction to provide data from anywhere instead of a simple + * filesystem read; that function is IMG_LoadTexture_IO(). + * + * If you would rather decode an image to an SDL_Surface (a buffer of pixels + * in CPU memory), call IMG_Load() instead. + * + * When done with the returned texture, the app should dispose of it with a + * call to SDL_DestroyTexture(). + * + * \param renderer the SDL_Renderer to use to create the GPU texture. + * \param file a path on the filesystem to load an image from. + * \returns a new texture, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadTextureTyped_IO + * \sa IMG_LoadTexture_IO + */ +extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture(SDL_Renderer *renderer, const char *file); + +/** + * Load an image from an SDL data source into a GPU texture. + * + * An SDL_Texture represents an image in GPU memory, usable by SDL's 2D Render + * API. This can be significantly more efficient than using a CPU-bound + * SDL_Surface if you don't need to manipulate the image directly after + * loading it. + * + * If the loaded image has transparency or a colorkey, a texture with an alpha + * channel will be created. Otherwise, SDL_image will attempt to create an + * SDL_Texture in the most format that most reasonably represents the image + * data (but in many cases, this will just end up being 32-bit RGB or 32-bit + * RGBA). + * + * If `closeio` is true, `src` will be closed before returning, whether this + * function succeeds or not. SDL_image reads everything it needs from `src` + * during this call in any case. + * + * There is a separate function to read files from disk without having to deal + * with SDL_IOStream: `IMG_LoadTexture(renderer, "filename.jpg")` will call + * this function and manage those details for you, determining the file type + * from the filename's extension. + * + * There is also IMG_LoadTextureTyped_IO(), which is equivalent to this + * function except a file extension (like "BMP", "JPG", etc) can be specified, + * in case SDL_image cannot autodetect the file format. + * + * If you would rather decode an image to an SDL_Surface (a buffer of pixels + * in CPU memory), call IMG_Load() instead. + * + * When done with the returned texture, the app should dispose of it with a + * call to SDL_DestroyTexture(). + * + * \param renderer the SDL_Renderer to use to create the GPU texture. + * \param src an SDL_IOStream that data will be read from. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns a new texture, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadTexture + * \sa IMG_LoadTextureTyped_IO + * \sa SDL_DestroyTexture + */ +extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture_IO(SDL_Renderer *renderer, SDL_IOStream *src, bool closeio); + +/** + * Load an image from an SDL data source into a GPU texture. + * + * An SDL_Texture represents an image in GPU memory, usable by SDL's 2D Render + * API. This can be significantly more efficient than using a CPU-bound + * SDL_Surface if you don't need to manipulate the image directly after + * loading it. + * + * If the loaded image has transparency or a colorkey, a texture with an alpha + * channel will be created. Otherwise, SDL_image will attempt to create an + * SDL_Texture in the most format that most reasonably represents the image + * data (but in many cases, this will just end up being 32-bit RGB or 32-bit + * RGBA). + * + * If `closeio` is true, `src` will be closed before returning, whether this + * function succeeds or not. SDL_image reads everything it needs from `src` + * during this call in any case. + * + * Even though this function accepts a file type, SDL_image may still try + * other decoders that are capable of detecting file type from the contents of + * the image data, but may rely on the caller-provided type string for formats + * that it cannot autodetect. If `type` is NULL, SDL_image will rely solely on + * its ability to guess the format. + * + * There is a separate function to read files from disk without having to deal + * with SDL_IOStream: `IMG_LoadTexture("filename.jpg")` will call this + * function and manage those details for you, determining the file type from + * the filename's extension. + * + * There is also IMG_LoadTexture_IO(), which is equivalent to this function + * except that it will rely on SDL_image to determine what type of data it is + * loading, much like passing a NULL for type. + * + * If you would rather decode an image to an SDL_Surface (a buffer of pixels + * in CPU memory), call IMG_LoadTyped_IO() instead. + * + * When done with the returned texture, the app should dispose of it with a + * call to SDL_DestroyTexture(). + * + * \param renderer the SDL_Renderer to use to create the GPU texture. + * \param src an SDL_IOStream that data will be read from. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param type a filename extension that represent this data ("BMP", "GIF", + * "PNG", etc). + * \returns a new texture, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadTexture + * \sa IMG_LoadTexture_IO + * \sa SDL_DestroyTexture + */ +extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTextureTyped_IO(SDL_Renderer *renderer, SDL_IOStream *src, bool closeio, const char *type); + +/** + * Detect AVIF image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is AVIF data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isAVIF(SDL_IOStream *src); + +/** + * Detect ICO image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is ICO data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isICO(SDL_IOStream *src); + +/** + * Detect CUR image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is CUR data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isCUR(SDL_IOStream *src); + +/** + * Detect BMP image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is BMP data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isBMP(SDL_IOStream *src); + +/** + * Detect GIF image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is GIF data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isGIF(SDL_IOStream *src); + +/** + * Detect JPG image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is JPG data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isJPG(SDL_IOStream *src); + +/** + * Detect JXL image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is JXL data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isJXL(SDL_IOStream *src); + +/** + * Detect LBM image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is LBM data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isLBM(SDL_IOStream *src); + +/** + * Detect PCX image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is PCX data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isPCX(SDL_IOStream *src); + +/** + * Detect PNG image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is PNG data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isPNG(SDL_IOStream *src); + +/** + * Detect PNM image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is PNM data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isPNM(SDL_IOStream *src); + +/** + * Detect SVG image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is SVG data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isSVG(SDL_IOStream *src); + +/** + * Detect QOI image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is QOI data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isQOI(SDL_IOStream *src); + +/** + * Detect TIFF image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is TIFF data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isTIF(SDL_IOStream *src); + +/** + * Detect XCF image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is XCF data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXPM + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isXCF(SDL_IOStream *src); + +/** + * Detect XPM image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is XPM data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXV + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isXPM(SDL_IOStream *src); + +/** + * Detect XV image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is XV data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isXV(SDL_IOStream *src); + +/** + * Detect WEBP image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns non-zero if this is WEBP data, zero otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isICO + * \sa IMG_isCUR + * \sa IMG_isBMP + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isSVG + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isWEBP(SDL_IOStream *src); + +/** + * Load a AVIF image directly. + * + * If you know you definitely have a AVIF image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadAVIF_IO(SDL_IOStream *src); + +/** + * Load a ICO image directly. + * + * If you know you definitely have a ICO image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadICO_IO(SDL_IOStream *src); + +/** + * Load a CUR image directly. + * + * If you know you definitely have a CUR image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadCUR_IO(SDL_IOStream *src); + +/** + * Load a BMP image directly. + * + * If you know you definitely have a BMP image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadBMP_IO(SDL_IOStream *src); + +/** + * Load a GIF image directly. + * + * If you know you definitely have a GIF image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadGIF_IO(SDL_IOStream *src); + +/** + * Load a JPG image directly. + * + * If you know you definitely have a JPG image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadJPG_IO(SDL_IOStream *src); + +/** + * Load a JXL image directly. + * + * If you know you definitely have a JXL image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadJXL_IO(SDL_IOStream *src); + +/** + * Load a LBM image directly. + * + * If you know you definitely have a LBM image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadLBM_IO(SDL_IOStream *src); + +/** + * Load a PCX image directly. + * + * If you know you definitely have a PCX image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPCX_IO(SDL_IOStream *src); + +/** + * Load a PNG image directly. + * + * If you know you definitely have a PNG image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNG_IO(SDL_IOStream *src); + +/** + * Load a PNM image directly. + * + * If you know you definitely have a PNM image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNM_IO(SDL_IOStream *src); + +/** + * Load a SVG image directly. + * + * If you know you definitely have a SVG image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadSVG_IO(SDL_IOStream *src); + +/** + * Load a QOI image directly. + * + * If you know you definitely have a QOI image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadQOI_IO(SDL_IOStream *src); + +/** + * Load a TGA image directly. + * + * If you know you definitely have a TGA image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadTGA_IO(SDL_IOStream *src); + +/** + * Load a TIFF image directly. + * + * If you know you definitely have a TIFF image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadTIF_IO(SDL_IOStream *src); + +/** + * Load a XCF image directly. + * + * If you know you definitely have a XCF image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadXCF_IO(SDL_IOStream *src); + +/** + * Load a XPM image directly. + * + * If you know you definitely have a XPM image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXV_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadXPM_IO(SDL_IOStream *src); + +/** + * Load a XV image directly. + * + * If you know you definitely have a XV image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadWEBP_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadXV_IO(SDL_IOStream *src); + +/** + * Load a WEBP image directly. + * + * If you know you definitely have a WEBP image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadWEBP_IO(SDL_IOStream *src); + +/** + * Load an SVG image, scaled to a specific size. + * + * Since SVG files are resolution-independent, you specify the size you would + * like the output image to be and it will be generated at those dimensions. + * + * Either width or height may be 0 and the image will be auto-sized to + * preserve aspect ratio. + * + * When done with the returned surface, the app should dispose of it with a + * call to SDL_DestroySurface(). + * + * \param src an SDL_IOStream to load SVG data from. + * \param width desired width of the generated surface, in pixels. + * \param height desired height of the generated surface, in pixels. + * \returns a new SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadSizedSVG_IO(SDL_IOStream *src, int width, int height); + +/** + * Load an XPM image from a memory array. + * + * The returned surface will be an 8bpp indexed surface, if possible, + * otherwise it will be 32bpp. If you always want 32-bit data, use + * IMG_ReadXPMFromArrayToRGB888() instead. + * + * When done with the returned surface, the app should dispose of it with a + * call to SDL_DestroySurface(). + * + * \param xpm a null-terminated array of strings that comprise XPM data. + * \returns a new SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_ReadXPMFromArrayToRGB888 + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArray(char **xpm); + +/** + * Load an XPM image from a memory array. + * + * The returned surface will always be a 32-bit RGB surface. If you want 8-bit + * indexed colors (and the XPM data allows it), use IMG_ReadXPMFromArray() + * instead. + * + * When done with the returned surface, the app should dispose of it with a + * call to SDL_DestroySurface(). + * + * \param xpm a null-terminated array of strings that comprise XPM data. + * \returns a new SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_ReadXPMFromArray + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArrayToRGB888(char **xpm); + +/** + * Save an SDL_Surface into a AVIF image file. + * + * If the file already exists, it will be overwritten. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write new file to. + * \param quality the desired quality, ranging between 0 (lowest) and 100 + * (highest). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_SaveAVIF_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveAVIF(SDL_Surface *surface, const char *file, int quality); + +/** + * Save an SDL_Surface into AVIF image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SaveAVIF() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param quality the desired quality, ranging between 0 (lowest) and 100 + * (highest). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_SaveAVIF + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveAVIF_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio, int quality); + +/** + * Save an SDL_Surface into a PNG image file. + * + * If the file already exists, it will be overwritten. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write new file to. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_SavePNG_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SavePNG(SDL_Surface *surface, const char *file); + +/** + * Save an SDL_Surface into PNG image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SavePNG() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_SavePNG + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); + +/** + * Save an SDL_Surface into a JPEG image file. + * + * If the file already exists, it will be overwritten. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write new file to. + * \param quality [0; 33] is Lowest quality, [34; 66] is Middle quality, [67; + * 100] is Highest quality. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_SaveJPG_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveJPG(SDL_Surface *surface, const char *file, int quality); + +/** + * Save an SDL_Surface into JPEG image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SaveJPG() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param quality [0; 33] is Lowest quality, [34; 66] is Middle quality, [67; + * 100] is Highest quality. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_SaveJPG + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveJPG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio, int quality); + +/** + * Animated image support + * + * Currently only animated GIFs and WEBP images are supported. + */ +typedef struct IMG_Animation +{ + int w, h; + int count; + SDL_Surface **frames; + int *delays; +} IMG_Animation; + +/** + * Load an animation from a file. + * + * When done with the returned animation, the app should dispose of it with a + * call to IMG_FreeAnimation(). + * + * \param file path on the filesystem containing an animated image. + * \returns a new IMG_Animation, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_FreeAnimation + */ +extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadAnimation(const char *file); + +/** + * Load an animation from an SDL_IOStream. + * + * If `closeio` is true, `src` will be closed before returning, whether this + * function succeeds or not. SDL_image reads everything it needs from `src` + * during this call in any case. + * + * When done with the returned animation, the app should dispose of it with a + * call to IMG_FreeAnimation(). + * + * \param src an SDL_IOStream that data will be read from. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns a new IMG_Animation, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_FreeAnimation + */ +extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadAnimation_IO(SDL_IOStream *src, bool closeio); + +/** + * Load an animation from an SDL datasource + * + * Even though this function accepts a file type, SDL_image may still try + * other decoders that are capable of detecting file type from the contents of + * the image data, but may rely on the caller-provided type string for formats + * that it cannot autodetect. If `type` is NULL, SDL_image will rely solely on + * its ability to guess the format. + * + * If `closeio` is true, `src` will be closed before returning, whether this + * function succeeds or not. SDL_image reads everything it needs from `src` + * during this call in any case. + * + * When done with the returned animation, the app should dispose of it with a + * call to IMG_FreeAnimation(). + * + * \param src an SDL_IOStream that data will be read from. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param type a filename extension that represent this data ("GIF", etc). + * \returns a new IMG_Animation, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAnimation + * \sa IMG_LoadAnimation_IO + * \sa IMG_FreeAnimation + */ +extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadAnimationTyped_IO(SDL_IOStream *src, bool closeio, const char *type); + +/** + * Dispose of an IMG_Animation and free its resources. + * + * The provided `anim` pointer is not valid once this call returns. + * + * \param anim IMG_Animation to dispose of. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAnimation + * \sa IMG_LoadAnimation_IO + * \sa IMG_LoadAnimationTyped_IO + */ +extern SDL_DECLSPEC void SDLCALL IMG_FreeAnimation(IMG_Animation *anim); + +/** + * Load a GIF animation directly. + * + * If you know you definitely have a GIF image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream that data will be read from. + * \returns a new IMG_Animation, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAnimation + * \sa IMG_LoadAnimation_IO + * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_FreeAnimation + */ +extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadGIFAnimation_IO(SDL_IOStream *src); + +/** + * Load a WEBP animation directly. + * + * If you know you definitely have a WEBP image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream that data will be read from. + * \returns a new IMG_Animation, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAnimation + * \sa IMG_LoadAnimation_IO + * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_FreeAnimation + */ +extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadWEBPAnimation_IO(SDL_IOStream *src); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_IMAGE_H_ */ diff --git a/vendor/sdl3/image/libavif-16.dll b/vendor/sdl3/image/libavif-16.dll new file mode 100644 index 000000000..7fef6232a Binary files /dev/null and b/vendor/sdl3/image/libavif-16.dll differ diff --git a/vendor/sdl3/image/libtiff-6.dll b/vendor/sdl3/image/libtiff-6.dll new file mode 100644 index 000000000..645e446b8 Binary files /dev/null and b/vendor/sdl3/image/libtiff-6.dll differ diff --git a/vendor/sdl3/image/libwebp-7.dll b/vendor/sdl3/image/libwebp-7.dll new file mode 100644 index 000000000..fe41f5652 Binary files /dev/null and b/vendor/sdl3/image/libwebp-7.dll differ diff --git a/vendor/sdl3/image/libwebpdemux-2.dll b/vendor/sdl3/image/libwebpdemux-2.dll new file mode 100644 index 000000000..6d012f01c Binary files /dev/null and b/vendor/sdl3/image/libwebpdemux-2.dll differ diff --git a/vendor/sdl3/image/sdl_image.odin b/vendor/sdl3/image/sdl_image.odin new file mode 100644 index 000000000..4712c7f3c --- /dev/null +++ b/vendor/sdl3/image/sdl_image.odin @@ -0,0 +1,107 @@ +package sdl3_image + +import "core:c" +import SDL "vendor:sdl3" + +when ODIN_OS == .Windows { + foreign import lib "SDL3_image.lib" +} else { + foreign import lib "system:SDL3_image" +} + +MAJOR_VERSION :: 3 +MINOR_VERSION :: 2 +PATCHLEVEL :: 0 + +Animation :: struct { + w, h: c.int, + count: c.int, + frames: [^]^SDL.Surface, + delays: [^]c.int, +} + +@(default_calling_convention="c", link_prefix="IMG_") +foreign lib { + Version :: proc() -> c.int --- + + /* Load an image from an SDL data source. + The 'type' may be one of: "BMP", "GIF", "PNG", etc. + If the image format supports a transparent pixel, SDL will set the + colorkey for the surface. You can enable RLE acceleration on the + surface afterwards by calling: + SDL_SetColorKey(image, SDL_RLEACCEL, image->format->colorkey); + */ + LoadTyped_IO :: proc(src: ^SDL.IOStream, closeio: bool, type: cstring) -> ^SDL.Surface --- + + /* Convenience functions */ + Load :: proc(file: cstring) -> ^SDL.Surface --- + Load_IO :: proc(src: ^SDL.IOStream, closeio: bool) -> ^SDL.Surface --- + + /* Load an image directly into a render texture. */ + LoadTexture :: proc(renderer: ^SDL.Renderer, file: cstring) -> ^SDL.Texture --- + LoadTexture_IO :: proc(renderer: ^SDL.Renderer, src: ^SDL.IOStream, closeio: bool) -> ^SDL.Texture --- + LoadTextureTyped_IO :: proc(renderer: ^SDL.Renderer, src: ^SDL.IOStream, closeio: bool, type: cstring) -> ^SDL.Texture --- + + /* Functions to detect a file type, given a seekable source */ + isAVIF :: proc(src: ^SDL.IOStream) -> bool --- + isICO :: proc(src: ^SDL.IOStream) -> bool --- + isCUR :: proc(src: ^SDL.IOStream) -> bool --- + isBMP :: proc(src: ^SDL.IOStream) -> bool --- + isGIF :: proc(src: ^SDL.IOStream) -> bool --- + isJPG :: proc(src: ^SDL.IOStream) -> bool --- + isJXL :: proc(src: ^SDL.IOStream) -> bool --- + isLBM :: proc(src: ^SDL.IOStream) -> bool --- + isPCX :: proc(src: ^SDL.IOStream) -> bool --- + isPNG :: proc(src: ^SDL.IOStream) -> bool --- + isPNM :: proc(src: ^SDL.IOStream) -> bool --- + isSVG :: proc(src: ^SDL.IOStream) -> bool --- + isQOI :: proc(src: ^SDL.IOStream) -> bool --- + isTIF :: proc(src: ^SDL.IOStream) -> bool --- + isXCF :: proc(src: ^SDL.IOStream) -> bool --- + isXPM :: proc(src: ^SDL.IOStream) -> bool --- + isXV :: proc(src: ^SDL.IOStream) -> bool --- + isWEBP :: proc(src: ^SDL.IOStream) -> bool --- + + /* Individual loading functions */ + LoadAVIF_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadICO_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadCUR_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadBMP_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadGIF_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadJPG_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadJXL_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadLBM_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadPCX_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadPNG_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadPNM_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadSVG_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadQOI_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadTGA_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadTIF_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadXCF_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadXPM_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadXV_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + LoadWEBP_IO :: proc(src: ^SDL.IOStream) -> ^SDL.Surface --- + + LoadSizedSVG_IO :: proc(src: ^SDL.IOStream, width, height: c.int) -> ^SDL.Surface --- + + ReadXPMFromArray :: proc(xpm: [^]cstring) -> ^SDL.Surface --- + ReadXPMFromArrayToRGB888 :: proc(xpm: [^]cstring) -> ^SDL.Surface --- + + /* Individual saving functions */ + SaveAVIF :: proc(surface: ^SDL.Surface, file: cstring, quality: c.int) -> c.int --- + SaveAVIF_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool, quality: c.int) -> c.int --- + SavePNG :: proc(surface: ^SDL.Surface, file: cstring) -> c.int --- + SavePNG_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool) -> c.int --- + SaveJPG :: proc(surface: ^SDL.Surface, file: cstring, quality: c.int) -> c.int --- + SaveJPG_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool, quality: c.int) -> c.int --- + + LoadAnimation :: proc(file: cstring) -> ^Animation --- + LoadAnimation_IO :: proc(src: ^SDL.IOStream, closeio: bool) -> ^Animation --- + LoadAnimationTyped_IO :: proc(src: ^SDL.IOStream, closeio: bool, type: cstring) -> ^Animation --- + FreeAnimation :: proc(anim: ^Animation) --- + + /* Individual loading functions */ + LoadGIFAnimation_IO :: proc(src: ^SDL.IOStream) -> ^Animation --- + LoadWEBPAnimation_IO :: proc(src: ^SDL.IOStream) -> ^Animation --- +} diff --git a/vendor/sdl3/sdl3_keyboard.odin b/vendor/sdl3/sdl3_keyboard.odin index b2faea04d..a27826354 100644 --- a/vendor/sdl3/sdl3_keyboard.odin +++ b/vendor/sdl3/sdl3_keyboard.odin @@ -52,7 +52,7 @@ foreign lib { TextInputActive :: proc(window: ^Window) -> bool --- StopTextInput :: proc(window: ^Window) -> bool --- ClearComposition :: proc(window: ^Window) -> bool --- - SetTextInputArea :: proc(window: ^Window, #by_ptr rect: Rect, cursor: c.int) -> bool --- + SetTextInputArea :: proc(window: ^Window, rect: Maybe(^Rect), cursor: c.int) -> bool --- GetTextInputArea :: proc(window: ^Window, rect: ^Rect, cursor: ^c.int) -> bool --- HasScreenKeyboardSupport :: proc() -> bool --- ScreenKeyboardShown :: proc(window: ^Window) -> bool --- diff --git a/vendor/sdl3/sdl3_render.odin b/vendor/sdl3/sdl3_render.odin index dc74cdd71..5af4bb055 100644 --- a/vendor/sdl3/sdl3_render.odin +++ b/vendor/sdl3/sdl3_render.odin @@ -183,10 +183,10 @@ foreign lib { RenderCoordinatesFromWindow :: proc(renderer: ^Renderer, window_x, window_y: f32, x, y: ^f32) -> bool --- RenderCoordinatesToWindow :: proc(renderer: ^Renderer, x, y: f32, window_x, window_y: ^f32) -> bool --- ConvertEventToRenderCoordinates :: proc(renderer: ^Renderer, event: ^Event) -> bool --- - SetRenderViewport :: proc(renderer: ^Renderer, #by_ptr rect: Rect) -> bool --- + SetRenderViewport :: proc(renderer: ^Renderer, rect: Maybe(^Rect)) -> bool --- GetRenderViewport :: proc(renderer: ^Renderer, rect: ^Rect) -> bool --- GetRenderSafeArea :: proc(renderer: ^Renderer, rect: ^Rect) -> bool --- - SetRenderClipRect :: proc(renderer: ^Renderer, #by_ptr rect: Rect) -> bool --- + SetRenderClipRect :: proc(renderer: ^Renderer, rect: Maybe(^Rect)) -> bool --- GetRenderClipRect :: proc(renderer: ^Renderer, rect: ^Rect) -> bool --- SetRenderScale :: proc(renderer: ^Renderer, scaleX, scaleY: f32) -> bool --- GetRenderScale :: proc(renderer: ^Renderer, scaleX, scaleY: ^f32) -> bool --- @@ -203,9 +203,9 @@ foreign lib { RenderPoints :: proc(renderer: ^Renderer, points: [^]FPoint, count: c.int) -> bool --- RenderLine :: proc(renderer: ^Renderer, x1, y1, x2, y2: f32) -> bool --- RenderLines :: proc(renderer: ^Renderer, points: [^]FPoint, count: c.int) -> bool --- - RenderRect :: proc(renderer: ^Renderer, #by_ptr rect: FRect) -> bool --- + RenderRect :: proc(renderer: ^Renderer, rect: Maybe(^FRect)) -> bool --- RenderRects :: proc(renderer: ^Renderer, rects: [^]FRect, count: c.int) -> bool --- - RenderFillRect :: proc(renderer: ^Renderer, #by_ptr rect: FRect) -> bool --- + RenderFillRect :: proc(renderer: ^Renderer, rect: Maybe(^FRect)) -> bool --- RenderFillRects :: proc(renderer: ^Renderer, rects: [^]FRect, count: c.int) -> bool --- RenderTexture :: proc(renderer: ^Renderer, texture: ^Texture, srcrect, dstrect: Maybe(^FRect)) -> bool --- RenderTextureRotated :: proc(renderer: ^Renderer, texture: ^Texture, srcrect, dstrect: Maybe(^FRect), angle: f64, #by_ptr center: FPoint, flip: FlipMode) -> bool --- diff --git a/vendor/sdl3/sdl3_surface.odin b/vendor/sdl3/sdl3_surface.odin index 10466adff..7abbd4ab5 100644 --- a/vendor/sdl3/sdl3_surface.odin +++ b/vendor/sdl3/sdl3_surface.odin @@ -78,7 +78,7 @@ foreign lib { GetSurfaceAlphaMod :: proc(surface: ^Surface, alpha: ^Uint8) -> bool --- SetSurfaceBlendMode :: proc(surface: ^Surface, blendMode: BlendMode) -> bool --- GetSurfaceBlendMode :: proc(surface: ^Surface, blendMode: ^BlendMode) -> bool --- - SetSurfaceClipRect :: proc(surface: ^Surface, #by_ptr rect: Rect) -> bool --- + SetSurfaceClipRect :: proc(surface: ^Surface, rect: Maybe(^Rect)) -> bool --- GetSurfaceClipRect :: proc(surface: ^Surface, rect: ^Rect) -> bool --- FlipSurface :: proc(surface: ^Surface, flip: FlipMode) -> bool --- DuplicateSurface :: proc(surface: ^Surface) -> ^Surface --- @@ -90,15 +90,15 @@ foreign lib { PremultiplyAlpha :: proc(width, height: c.int, src_format: PixelFormat, src: rawptr, src_pitch: c.int, dst_format: PixelFormat, dst: rawptr, dst_pitch: c.int, linear: bool) -> bool --- PremultiplySurfaceAlpha :: proc(surface: ^Surface, linear: bool) -> bool --- ClearSurface :: proc(surface: ^Surface, r, g, b, a: f32) -> bool --- - FillSurfaceRect :: proc(dst: ^Surface, #by_ptr rect: Rect, color: Uint32) -> bool --- + FillSurfaceRect :: proc(dst: ^Surface, rect: Maybe(^Rect), color: Uint32) -> bool --- FillSurfaceRects :: proc(dst: ^Surface, rects: [^]Rect, count: c.int, color: Uint32) -> bool --- - BlitSurface :: proc(src: ^Surface, #by_ptr srcrect: Rect, dst: ^Surface, #by_ptr dstrect: Rect) -> bool --- - BlitSurfaceUnchecked :: proc(src: ^Surface, #by_ptr srcrect: Rect, dst: ^Surface, #by_ptr dstrect: Rect) -> bool --- - BlitSurfaceScaled :: proc(src: ^Surface, #by_ptr srcrect: Rect, dst: ^Surface, #by_ptr dstrect: Rect, scaleMode: ScaleMode) -> bool --- - BlitSurfaceUncheckedScaled :: proc(src: ^Surface, #by_ptr srcrect: Rect, dst: ^Surface, #by_ptr dstrect: Rect, scaleMode: ScaleMode) -> bool --- - BlitSurfaceTiled :: proc(src: ^Surface, #by_ptr srcrect: Rect, dst: ^Surface, #by_ptr dstrect: Rect) -> bool --- - BlitSurfaceTiledWithScale :: proc(src: ^Surface, #by_ptr srcrect: Rect, scale: f32, scaleMode: ScaleMode, dst: ^Surface, #by_ptr dstrect: Rect) -> bool --- - BlitSurface9Grid :: proc(src: ^Surface, #by_ptr srcrect: Rect, left_width, right_width, top_height, bottom_height: c.int, scale: f32, scaleMode: ScaleMode, dst: ^Surface, #by_ptr dstrect: Rect) -> bool --- + BlitSurface :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect)) -> bool --- + BlitSurfaceUnchecked :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect)) -> bool --- + BlitSurfaceScaled :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect), scaleMode: ScaleMode) -> bool --- + BlitSurfaceUncheckedScaled :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect), scaleMode: ScaleMode) -> bool --- + BlitSurfaceTiled :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect)) -> bool --- + BlitSurfaceTiledWithScale :: proc(src: ^Surface, srcrect: Maybe(^Rect), scale: f32, scaleMode: ScaleMode, dst: ^Surface, dstrect: Maybe(^Rect)) -> bool --- + BlitSurface9Grid :: proc(src: ^Surface, srcrect: Maybe(^Rect), left_width, right_width, top_height, bottom_height: c.int, scale: f32, scaleMode: ScaleMode, dst: ^Surface, dstrect: Maybe(^Rect)) -> bool --- MapSurfaceRGB :: proc(surface: ^Surface, r, g, b: Uint8) -> Uint32 --- MapSurfaceRGBA :: proc(surface: ^Surface, r, g, b, a: Uint8) -> Uint32 --- ReadSurfacePixel :: proc(surface: ^Surface, x, y: c.int, r, g, b, a: ^Uint8) -> bool --- diff --git a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py index 407e6371c..9da3ee239 100644 --- a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py +++ b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py @@ -18,6 +18,7 @@ file_and_urls = [ ("vulkan_wayland.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_wayland.h', False), ("vulkan_xlib.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_xlib.h', False), ("vulkan_xcb.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_xcb.h', False), + ("vulkan_beta.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_beta.h', False), # Vulkan Video ("vulkan_video_codec_av1std.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_av1std.h', False), ("vulkan_video_codec_av1std_decode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_av1std_decode.h', False), @@ -338,7 +339,6 @@ def parse_enums(f): generated_flags.add(flags_name) f.write("{} :: distinct bit_set[{}; Flags]\n".format(flags_name, enum_name)) - if is_flag_bit: f.write("{} :: enum Flags {{\n".format(name.replace("FlagBits", "Flag"))) else: @@ -537,80 +537,164 @@ def parse_fake_enums(f): f.write("}\n\n") +class BitfieldError(ValueError): + pass + +def bitfield_type_to_size(type_): + if type_ == 'u8': + return 8 + if type_ == 'u16': + return 16 + if type_ == 'u32': + return 32 + if type_ == 'u64': + return 64 + if 'Flags' in type_: + return 32 + else: + raise BitfieldError(f"Invalid type for bitfield: {type_}") + +def bitfield_size_to_type(size): + if size == 8: + return 'u8' + if size == 16: + return 'u16' + if size == 32: + return 'u32' + if size == 64: + return 'u64' + else: + raise BitfieldError(f"Invalid size for bitfield: {size}") + + +class Bitfield: + class Field: + def __init__(self, name, type_, bitsize): + self.name = name + self.type = type_ + self.bitsize = bitsize + + def __init__(self, type_): + self.bitsize = bitfield_type_to_size(type_) + self.type = bitfield_size_to_type(self.bitsize) + self.fields_bitsize = 0 + self.fields = [] + + def add_field(self, name, type_, bitsize): + self.fields.append(Bitfield.Field(name, type_, bitsize)) + self.fields_bitsize += bitsize + + def write(self, f, name=None, indent=0, justify=True): + max_name = 1 if not justify else max([len(f.name) for f in self.fields], default=0) + max_type = 1 if not justify else max([len(f.type) for f in self.fields], default=0) + is_bit_set = all([f.bitsize == 1 or f.name == "reserved" for f in self.fields]) + if is_bit_set and name is None: + raise BitfieldError(f"bit_set can not be anonymous") + + if is_bit_set: + if not name.endswith("Flags"): + raise BitfieldError(f"bit_set name should end with 'Flags': {name}") + enum_name = re.sub('Flags$', 'Flag', name) + f.write("{}{} :: distinct bit_set[{}; {}]\n".format('\t' * indent, name, enum_name, self.type)) + f.write("{}{} :: enum {} {{\n".format('\t' * indent, enum_name, self.type)) + for field in self.fields: + if field.name != "reserved": + f.write("{}{},\n".format('\t' * (indent + 1), field.name)) + f.write(('\t' * indent) + "}\n") + + else: + f.write("{}{} bit_field {} {{\n".format('\t' * indent, name + ' ::' if name else 'using _:', self.type)) + for field in self.fields: + type_ = field.type.replace("Flags", "Flag") + f.write("{}{} {} | {},\n".format( + '\t' * (indent + 1), + (field.name + ":").ljust(max_name + 1), + type_.ljust(max_type), + field.bitsize)) + f.write(('\t' * indent) + "}" + ("," if name is None else "") + "\n") + def parse_structs(f): data = re.findall(r"typedef (struct|union) Vk(\w+?) {(.+?)} \w+?;", src, re.S) data += re.findall(r"typedef (struct|union) Std(\w+?) {(.+?)} \w+?;", src, re.S) - for _type, name, fields in data: + for _type, struct_name, fields in data: fields = re.findall(r"\s+(.+?)[\s:]+([_a-zA-Z0-9[\]]+);", fields) - f.write("{} :: struct ".format(name)) - if _type == "union": - f.write("#raw_union ") - f.write("{\n") - prev_name = "" ffields = [] + bitfield = None for type_, fname in fields: - # If the field name only has a number in it, then it is a C bit field. + # We will collect all the bit fields and then create either a bit_field or a bit_set. if is_int(fname): - comment = None - bit_field = type_.split(' ') + bf_field = type_.split(' ') # Get rid of empty spaces - bit_field = list(filter(bool, bit_field)) + bf_field = list(filter(bool, bf_field)) # [type, fieldname] - assert len(bit_field) == 2, "Failed to parse the bit field!" + assert len(bf_field) == 2, "Failed to parse the bit field!" + field_type = do_type(bf_field[0]) + bitsize = int(fname) + # Close the set because the field size is greater than the bitfield type + if bitfield and (bitfield.fields_bitsize + bitsize) > bitfield_type_to_size(field_type): + ffields.append(tuple([None, bitfield])) + bitfield = None - bit_field_type = "" - # Right now there are only two ways that C bit fields exist in - # the header files. + # Raise an error if the field type size is greater than the bitfield type size + if bitfield is not None and bitfield_type_to_size(bitfield.type) < bitfield_type_to_size(field_type): + raise BitfieldError(f"field will not fit in the bitfield: {bitfield.type} < {field_type}") - # First one uses the 8 MOST significant bits for one field, and - # 24 bits for the other field. - # In the bindings these two fields are merged into one u32. - if int(fname) == 24: - prev_name = bit_field[1] - continue - - elif prev_name: - bit_field_type = do_type("uint32_t") - bit_field_name = prev_name + "And" + bit_field[1].capitalize() - comment = " // Most significant byte is {}".format(bit_field[1]) - ffields.append(tuple([bit_field_name, bit_field_type, comment])) - prev_name = "" - continue - - # The second way has many fields that are each 1 bit - elif int(fname) == 1: - bit_field_type = do_type(bit_field[0], prev_name, fname) - ffields.append(tuple(["bitfield", bit_field_type, comment])) - break + # Create a new bitfield if we don't have one + if not bitfield: + bitfield = Bitfield(field_type) + # Add the field to the bitfield + bitfield.add_field(bf_field[1], field_type, bitsize) + continue + # Close the bitfield because this is not a field + elif bitfield: + ffields.append(tuple([None, bitfield])) + bitfield = None if '[' in fname: fname, type_ = parse_array(fname, type_) - comment = None n = fix_arg(fname) if "Flag_Bits" in type_: - comment = " // only single bit set" + # comment = " // only single bit set" + raise BitfieldError("only single bit set") t = do_type(type_, prev_name, fname) if n == "matrix": n = "mat" - ffields.append(tuple([n, t, comment])) + ffields.append(tuple([n, t])) prev_name = fname - max_len = max([len(n) for n, _, _ in ffields], default=0) + # Close the bitfield because we have no more fields + if bitfield: + ffields.append(tuple([None, bitfield])) - for n, t, comment in ffields: - k = max_len-len(n)+len(t) - f.write("\t{}: {},{}\n".format(n, t.rjust(k), comment or "")) + # Write the struct as a bitfield if it only has bit fields + if len(ffields) == 1 and ffields[0][0] is None: + ffields[0][1].write(f, struct_name, 0, True) + f.write("\n") - - f.write("}\n\n") + # Write as a normal struct (or union) if it has other fields + # and inject anonymous bitfields into the struct if there are any + else: + has_anon_bitfield = any(name is None for name, _ in ffields) + max_len = max([0 if n is None else len(n) for n, _ in ffields], default=0) + f.write("{} :: struct ".format(struct_name)) + if _type == "union": + f.write("#raw_union ") + f.write("{\n") + for name, type_ in ffields: + if name is None: + # Inject an anonymous bitfield into the struct + type_.write(f, None, indent=1, justify=True) + else: + f.write("\t{} {},\n".format((name + ":").ljust(max_len + 1), type_)) + f.write("}\n\n") f.write("// Opaque structs\n") f.write(OPAQUE_STRUCTS) diff --git a/vendor/vulkan/_gen/vk_platform.h b/vendor/vulkan/_gen/vk_platform.h index 0ecd4f647..18e5ca34c 100644 --- a/vendor/vulkan/_gen/vk_platform.h +++ b/vendor/vulkan/_gen/vk_platform.h @@ -2,7 +2,7 @@ // File: vk_platform.h // /* -** Copyright 2014-2024 The Khronos Group Inc. +** Copyright 2014-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_beta.h b/vendor/vulkan/_gen/vulkan_beta.h new file mode 100644 index 000000000..867483d08 --- /dev/null +++ b/vendor/vulkan/_gen/vulkan_beta.h @@ -0,0 +1,226 @@ +#ifndef VULKAN_BETA_H_ +#define VULKAN_BETA_H_ 1 + +/* +** Copyright 2015-2025 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 +VKAPI_ATTR VkResult VKAPI_CALL vkCreateExecutionGraphPipelinesAMDX( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineScratchSizeAMDX( + VkDevice device, + VkPipeline executionGraph, + VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineNodeIndexAMDX( + VkDevice device, + VkPipeline executionGraph, + const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, + uint32_t* pNodeIndex); + +VKAPI_ATTR void VKAPI_CALL vkCmdInitializeGraphScratchMemoryAMDX( + VkCommandBuffer commandBuffer, + VkPipeline executionGraph, + VkDeviceAddress scratch, + VkDeviceSize scratchSize); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceSize scratchSize, + const VkDispatchGraphCountInfoAMDX* pCountInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceSize scratchSize, + const VkDispatchGraphCountInfoAMDX* pCountInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectCountAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceSize scratchSize, + VkDeviceAddress countInfo); +#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; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/vulkan/_gen/vulkan_core.h b/vendor/vulkan/_gen/vulkan_core.h index 4e716da03..26e53459b 100644 --- a/vendor/vulkan/_gen/vulkan_core.h +++ b/vendor/vulkan/_gen/vulkan_core.h @@ -2,7 +2,7 @@ #define VULKAN_CORE_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -69,7 +69,7 @@ extern "C" { #define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 303 +#define VK_HEADER_VERSION 309 // Complete version of this file #define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 4, VK_HEADER_VERSION) @@ -1008,7 +1008,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = 1000421000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RENDER_PASS_STRIPED_FEATURES_ARM = 1000424000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RENDER_PASS_STRIPED_PROPERTIES_ARM = 1000424001, @@ -1025,6 +1024,9 @@ typedef enum VkStructureType { 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, @@ -1082,6 +1084,10 @@ typedef enum VkStructureType { 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, @@ -1171,6 +1177,20 @@ typedef enum VkStructureType { 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_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, @@ -1185,17 +1205,34 @@ typedef enum VkStructureType { 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_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_DEPTH_CLAMP_CONTROL_FEATURES_EXT = 1000582000, VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLAMP_CONTROL_CREATE_INFO_EXT = 1000582001, + 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_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_VERTEX_ATTRIBUTE_ROBUSTNESS_FEATURES_EXT = 1000608000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_SET_PRESENT_CONFIG_NV = 1000613000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_METERING_FEATURES_NV = 1000613001, +#endif 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 deprecated alias @@ -1405,6 +1442,7 @@ typedef enum VkStructureType { 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_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, @@ -2260,6 +2298,7 @@ typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000, VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001, 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 @@ -2716,6 +2755,7 @@ 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; @@ -2906,6 +2946,7 @@ typedef enum VkDependencyFlagBits { 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_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 @@ -5171,6 +5212,9 @@ typedef enum VkExternalMemoryHandleTypeFlagBits { 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_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, @@ -5954,7 +5998,7 @@ typedef enum VkDriverId { VK_DRIVER_ID_MESA_NVK = 24, VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA = 25, VK_DRIVER_ID_MESA_HONEYKRISP = 26, - VK_DRIVER_ID_RESERVED_27 = 27, + VK_DRIVER_ID_VULKAN_SC_EMULATION_ON_VULKAN = 27, 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, @@ -6795,6 +6839,7 @@ static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE 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; typedef VkFlags64 VkAccessFlags2; @@ -6958,6 +7003,7 @@ static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_ 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; @@ -7805,6 +7851,8 @@ static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONL #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_RAY_TRACING_SKIP_BUILT_IN_PRIMITIVES_BIT_KHR = 0x00001000ULL; +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; @@ -7837,6 +7885,7 @@ static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_ static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT_EXT = 0x40000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000ULL; 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_CAPTURE_DATA_BIT_KHR = 0x80000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT = 0x4000000000ULL; @@ -8941,6 +8990,7 @@ typedef enum VkVideoSessionCreateFlagBitsKHR { 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; @@ -12127,6 +12177,10 @@ typedef enum VkComponentTypeKHR { VK_COMPONENT_TYPE_UINT16_KHR = 8, VK_COMPONENT_TYPE_UINT32_KHR = 9, VK_COMPONENT_TYPE_UINT64_KHR = 10, + VK_COMPONENT_TYPE_SINT8_PACKED_NV = 1000491000, + VK_COMPONENT_TYPE_UINT8_PACKED_NV = 1000491001, + VK_COMPONENT_TYPE_FLOAT_E4M3_NV = 1000491002, + VK_COMPONENT_TYPE_FLOAT_E5M2_NV = 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, @@ -12782,6 +12836,76 @@ typedef struct VkPhysicalDeviceLayeredApiVulkanPropertiesKHR { +// 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 VkPhysicalDeviceMaintenance8FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance8; +} VkPhysicalDeviceMaintenance8FeaturesKHR; + +typedef struct VkMemoryBarrierAccessFlags3KHR { + VkStructureType sType; + const void* pNext; + VkAccessFlags3KHR srcAccessMask3; + VkAccessFlags3KHR dstAccessMask3; +} VkMemoryBarrierAccessFlags3KHR; + + + +// 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_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) @@ -14644,6 +14768,8 @@ 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, 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 @@ -18253,6 +18379,7 @@ typedef enum VkOpacityMicromapSpecialIndexEXT { VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT = -2, VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT = -3, VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT = -4, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_CLUSTER_GEOMETRY_DISABLE_OPACITY_MICROMAP_NV = -5, VK_OPACITY_MICROMAP_SPECIAL_INDEX_MAX_ENUM_EXT = 0x7FFFFFFF } VkOpacityMicromapSpecialIndexEXT; @@ -18684,11 +18811,7 @@ VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetHostMappingVALVE( #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 struct VkPhysicalDeviceDepthClampZeroOneFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 depthClampZeroOne; -} VkPhysicalDeviceDepthClampZeroOneFeaturesEXT; +typedef VkPhysicalDeviceDepthClampZeroOneFeaturesKHR VkPhysicalDeviceDepthClampZeroOneFeaturesEXT; @@ -18920,6 +19043,61 @@ VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetPipelineIndirectDeviceAddressNV( #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 @@ -19816,6 +19994,83 @@ typedef struct 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 +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeVectorPropertiesNV( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkCooperativeVectorPropertiesNV* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkConvertCooperativeVectorMatrixNV( + VkDevice device, + const VkConvertCooperativeVectorMatrixInfoNV* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdConvertCooperativeVectorMatrixNV( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkConvertCooperativeVectorMatrixInfoNV* pInfos); +#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 @@ -20330,6 +20585,359 @@ typedef struct 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 2 +#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_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_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 VkAccelerationStructureBuildSizesInfoKHR { + VkStructureType sType; + const 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 +VKAPI_ATTR void VKAPI_CALL vkGetClusterAccelerationStructureBuildSizesNV( + VkDevice device, + const VkClusterAccelerationStructureInputInfoNV* pInfo, + VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildClusterAccelerationStructureIndirectNV( + VkCommandBuffer commandBuffer, + const VkClusterAccelerationStructureCommandsInfoNV* pCommandInfos); +#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 +VKAPI_ATTR void VKAPI_CALL vkGetPartitionedAccelerationStructuresBuildSizesNV( + VkDevice device, + const VkPartitionedAccelerationStructureInstancesInputNV* pInfo, + VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildPartitionedAccelerationStructuresNV( + VkCommandBuffer commandBuffer, + const VkBuildPartitionedAccelerationStructureInfoNV* pBuildInfo); +#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) @@ -20721,6 +21329,18 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixFlexibleDimen #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_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 @@ -20733,6 +21353,25 @@ typedef struct VkPhysicalDeviceVertexAttributeRobustnessFeaturesEXT { +// 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_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 @@ -20889,14 +21528,6 @@ typedef struct VkCopyAccelerationStructureInfoKHR { VkCopyAccelerationStructureModeKHR mode; } VkCopyAccelerationStructureInfoKHR; -typedef struct VkAccelerationStructureBuildSizesInfoKHR { - VkStructureType sType; - const void* pNext; - VkDeviceSize accelerationStructureSize; - VkDeviceSize updateScratchSize; - VkDeviceSize buildScratchSize; -} VkAccelerationStructureBuildSizesInfoKHR; - 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); @@ -21079,12 +21710,6 @@ typedef struct VkPhysicalDeviceRayTracingPipelinePropertiesKHR { uint32_t maxRayHitAttributeSize; } VkPhysicalDeviceRayTracingPipelinePropertiesKHR; -typedef struct VkStridedDeviceAddressRegionKHR { - VkDeviceAddress deviceAddress; - VkDeviceSize stride; - VkDeviceSize size; -} VkStridedDeviceAddressRegionKHR; - typedef struct VkTraceRaysIndirectCommandKHR { uint32_t width; uint32_t height; diff --git a/vendor/vulkan/_gen/vulkan_ios.h b/vendor/vulkan/_gen/vulkan_ios.h index 22ed2c039..a705dc600 100644 --- a/vendor/vulkan/_gen/vulkan_ios.h +++ b/vendor/vulkan/_gen/vulkan_ios.h @@ -2,7 +2,7 @@ #define VULKAN_IOS_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_macos.h b/vendor/vulkan/_gen/vulkan_macos.h index a7f5613a0..8d5dd05a7 100644 --- a/vendor/vulkan/_gen/vulkan_macos.h +++ b/vendor/vulkan/_gen/vulkan_macos.h @@ -2,7 +2,7 @@ #define VULKAN_MACOS_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_metal.h b/vendor/vulkan/_gen/vulkan_metal.h index 89a557490..7e44f54cb 100644 --- a/vendor/vulkan/_gen/vulkan_metal.h +++ b/vendor/vulkan/_gen/vulkan_metal.h @@ -2,7 +2,7 @@ #define VULKAN_METAL_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -188,6 +188,47 @@ VKAPI_ATTR void VKAPI_CALL vkExportMetalObjectsEXT( VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); #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 +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryMetalHandleEXT( + VkDevice device, + const VkMemoryGetMetalHandleInfoEXT* pGetMetalHandleInfo, + void** pHandle); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryMetalHandlePropertiesEXT( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + const void* pHandle, + VkMemoryMetalHandlePropertiesEXT* pMemoryMetalHandleProperties); +#endif + #ifdef __cplusplus } #endif diff --git a/vendor/vulkan/_gen/vulkan_video_codec_av1std.h b/vendor/vulkan/_gen/vulkan_video_codec_av1std.h index 4fdced78e..347e0d2ae 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_av1std.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_av1std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_AV1STD_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_av1std_decode.h b/vendor/vulkan/_gen/vulkan_video_codec_av1std_decode.h index 6b8130cd9..522628e86 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_av1std_decode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_av1std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_AV1STD_DECODE_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_av1std_encode.h b/vendor/vulkan/_gen/vulkan_video_codec_av1std_encode.h index 87fc093b5..ca5f6f474 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_av1std_encode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_av1std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_AV1STD_ENCODE_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h264std.h b/vendor/vulkan/_gen/vulkan_video_codec_h264std.h index 6d27af37b..6fd381066 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h264std.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h264std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h264std_decode.h b/vendor/vulkan/_gen/vulkan_video_codec_h264std_decode.h index 439cb885e..d6a90b498 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h264std_decode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h264std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h264std_encode.h b/vendor/vulkan/_gen/vulkan_video_codec_h264std_encode.h index 9e24aa5d9..410b1b254 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h264std_encode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h264std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h265std.h b/vendor/vulkan/_gen/vulkan_video_codec_h265std.h index d0a1bacbe..3eecd6011 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h265std.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h265std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h265std_decode.h b/vendor/vulkan/_gen/vulkan_video_codec_h265std_decode.h index 0178793e5..a9e1a0964 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h265std_decode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h265std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h265std_encode.h b/vendor/vulkan/_gen/vulkan_video_codec_h265std_encode.h index ee34491f4..fe2f28d57 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h265std_encode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h265std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_wayland.h b/vendor/vulkan/_gen/vulkan_wayland.h index 5d18518f6..5a2dcb5f0 100644 --- a/vendor/vulkan/_gen/vulkan_wayland.h +++ b/vendor/vulkan/_gen/vulkan_wayland.h @@ -2,7 +2,7 @@ #define VULKAN_WAYLAND_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_win32.h b/vendor/vulkan/_gen/vulkan_win32.h index d7a0b2bab..e66ed1fcd 100644 --- a/vendor/vulkan/_gen/vulkan_win32.h +++ b/vendor/vulkan/_gen/vulkan_win32.h @@ -2,7 +2,7 @@ #define VULKAN_WIN32_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_xcb.h b/vendor/vulkan/_gen/vulkan_xcb.h index cdf6b5269..4e0627559 100644 --- a/vendor/vulkan/_gen/vulkan_xcb.h +++ b/vendor/vulkan/_gen/vulkan_xcb.h @@ -2,7 +2,7 @@ #define VULKAN_XCB_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_xlib.h b/vendor/vulkan/_gen/vulkan_xlib.h index b3c3e27d7..b581779c1 100644 --- a/vendor/vulkan/_gen/vulkan_xlib.h +++ b/vendor/vulkan/_gen/vulkan_xlib.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_H_ 1 /* -** Copyright 2015-2024 The Khronos Group Inc. +** Copyright 2015-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/core.odin b/vendor/vulkan/core.odin index f90b65008..b258bc85a 100644 --- a/vendor/vulkan/core.odin +++ b/vendor/vulkan/core.odin @@ -71,7 +71,7 @@ VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION :: VULKAN_VIDEO_CODEC_H265_ENCODE_AP MAKE_VIDEO_STD_VERSION :: MAKE_VERSION // General Constants -HEADER_VERSION :: 303 +HEADER_VERSION :: 309 MAX_DRIVER_NAME_SIZE :: 256 MAX_DRIVER_INFO_SIZE :: 256 @@ -481,6 +481,15 @@ KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME :: "VK_KHR_shader_rela KHR_maintenance7 :: 1 KHR_MAINTENANCE_7_SPEC_VERSION :: 1 KHR_MAINTENANCE_7_EXTENSION_NAME :: "VK_KHR_maintenance7" +KHR_maintenance8 :: 1 +KHR_MAINTENANCE_8_SPEC_VERSION :: 1 +KHR_MAINTENANCE_8_EXTENSION_NAME :: "VK_KHR_maintenance8" +KHR_video_maintenance2 :: 1 +KHR_VIDEO_MAINTENANCE_2_SPEC_VERSION :: 1 +KHR_VIDEO_MAINTENANCE_2_EXTENSION_NAME :: "VK_KHR_video_maintenance2" +KHR_depth_clamp_zero_one :: 1 +KHR_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION :: 1 +KHR_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME :: "VK_KHR_depth_clamp_zero_one" EXT_debug_report :: 1 EXT_DEBUG_REPORT_SPEC_VERSION :: 10 EXT_DEBUG_REPORT_EXTENSION_NAME :: "VK_EXT_debug_report" @@ -1008,6 +1017,9 @@ NV_MEMORY_DECOMPRESSION_EXTENSION_NAME :: "VK_NV_memory_decom NV_device_generated_commands_compute :: 1 NV_DEVICE_GENERATED_COMMANDS_COMPUTE_SPEC_VERSION :: 2 NV_DEVICE_GENERATED_COMMANDS_COMPUTE_EXTENSION_NAME :: "VK_NV_device_generated_commands_compute" +NV_ray_tracing_linear_swept_spheres :: 1 +NV_RAY_TRACING_LINEAR_SWEPT_SPHERES_SPEC_VERSION :: 1 +NV_RAY_TRACING_LINEAR_SWEPT_SPHERES_EXTENSION_NAME :: "VK_NV_ray_tracing_linear_swept_spheres" NV_linear_color_attachment :: 1 NV_LINEAR_COLOR_ATTACHMENT_SPEC_VERSION :: 1 NV_LINEAR_COLOR_ATTACHMENT_EXTENSION_NAME :: "VK_NV_linear_color_attachment" @@ -1053,6 +1065,9 @@ EXT_SHADER_OBJECT_EXTENSION_NAME :: "VK_EXT_shader_obje NV_ray_tracing_invocation_reorder :: 1 NV_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION :: 1 NV_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME :: "VK_NV_ray_tracing_invocation_reorder" +NV_cooperative_vector :: 1 +NV_COOPERATIVE_VECTOR_SPEC_VERSION :: 4 +NV_COOPERATIVE_VECTOR_EXTENSION_NAME :: "VK_NV_cooperative_vector" NV_extended_sparse_address_space :: 1 NV_EXTENDED_SPARSE_ADDRESS_SPACE_SPEC_VERSION :: 1 NV_EXTENDED_SPARSE_ADDRESS_SPACE_EXTENSION_NAME :: "VK_NV_extended_sparse_address_space" @@ -1101,6 +1116,12 @@ EXT_SHADER_REPLICATED_COMPOSITES_EXTENSION_NAME :: "VK_EXT_shader_repl NV_ray_tracing_validation :: 1 NV_RAY_TRACING_VALIDATION_SPEC_VERSION :: 1 NV_RAY_TRACING_VALIDATION_EXTENSION_NAME :: "VK_NV_ray_tracing_validation" +NV_cluster_acceleration_structure :: 1 +NV_CLUSTER_ACCELERATION_STRUCTURE_SPEC_VERSION :: 2 +NV_CLUSTER_ACCELERATION_STRUCTURE_EXTENSION_NAME :: "VK_NV_cluster_acceleration_structure" +NV_partitioned_acceleration_structure :: 1 +NV_PARTITIONED_ACCELERATION_STRUCTURE_SPEC_VERSION :: 1 +NV_PARTITIONED_ACCELERATION_STRUCTURE_EXTENSION_NAME :: "VK_NV_partitioned_acceleration_structure" EXT_device_generated_commands :: 1 EXT_DEVICE_GENERATED_COMMANDS_SPEC_VERSION :: 1 EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME :: "VK_EXT_device_generated_commands" @@ -1113,6 +1134,9 @@ NV_COOPERATIVE_MATRIX_2_EXTENSION_NAME :: "VK_NV_cooperative_ EXT_vertex_attribute_robustness :: 1 EXT_VERTEX_ATTRIBUTE_ROBUSTNESS_SPEC_VERSION :: 1 EXT_VERTEX_ATTRIBUTE_ROBUSTNESS_EXTENSION_NAME :: "VK_EXT_vertex_attribute_robustness" +NV_present_metering :: 1 +NV_PRESENT_METERING_SPEC_VERSION :: 1 +NV_PRESENT_METERING_EXTENSION_NAME :: "VK_NV_present_metering" KHR_acceleration_structure :: 1 KHR_ACCELERATION_STRUCTURE_SPEC_VERSION :: 13 KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME :: "VK_KHR_acceleration_structure" @@ -1158,6 +1182,9 @@ EXT_METAL_SURFACE_EXTENSION_NAME :: "VK_EXT_metal_surfa EXT_metal_objects :: 1 EXT_METAL_OBJECTS_SPEC_VERSION :: 2 EXT_METAL_OBJECTS_EXTENSION_NAME :: "VK_EXT_metal_objects" +EXT_external_memory_metal :: 1 +EXT_EXTERNAL_MEMORY_METAL_SPEC_VERSION :: 1 +EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME :: "VK_EXT_external_memory_metal" KHR_wayland_surface :: 1 KHR_WAYLAND_SURFACE_SPEC_VERSION :: 6 KHR_WAYLAND_SURFACE_EXTENSION_NAME :: "VK_KHR_wayland_surface" @@ -1167,6 +1194,15 @@ KHR_XLIB_SURFACE_EXTENSION_NAME :: "VK_KHR_xlib_surfac KHR_xcb_surface :: 1 KHR_XCB_SURFACE_SPEC_VERSION :: 6 KHR_XCB_SURFACE_EXTENSION_NAME :: "VK_KHR_xcb_surface" +KHR_portability_subset :: 1 +KHR_PORTABILITY_SUBSET_SPEC_VERSION :: 1 +KHR_PORTABILITY_SUBSET_EXTENSION_NAME :: "VK_KHR_portability_subset" +AMDX_shader_enqueue :: 1 +AMDX_SHADER_ENQUEUE_SPEC_VERSION :: 2 +AMDX_SHADER_ENQUEUE_EXTENSION_NAME :: "VK_AMDX_shader_enqueue" +NV_displacement_micromap :: 1 +NV_DISPLACEMENT_MICROMAP_SPEC_VERSION :: 2 +NV_DISPLACEMENT_MICROMAP_EXTENSION_NAME :: "VK_NV_displacement_micromap" // Handles types Instance :: distinct Handle diff --git a/vendor/vulkan/enums.odin b/vendor/vulkan/enums.odin index a55ba9e58..418c7c8b1 100644 --- a/vendor/vulkan/enums.odin +++ b/vendor/vulkan/enums.odin @@ -304,6 +304,55 @@ ChromaLocation :: enum c.int { MIDPOINT_KHR = MIDPOINT, } +ClusterAccelerationStructureAddressResolutionFlagsNV :: distinct bit_set[ClusterAccelerationStructureAddressResolutionFlagNV; Flags] +ClusterAccelerationStructureAddressResolutionFlagNV :: enum Flags { + INDIRECTED_DST_IMPLICIT_DATA = 0, + INDIRECTED_SCRATCH_DATA = 1, + INDIRECTED_DST_ADDRESS_ARRAY = 2, + INDIRECTED_DST_SIZES_ARRAY = 3, + INDIRECTED_SRC_INFOS_ARRAY = 4, + INDIRECTED_SRC_INFOS_COUNT = 5, +} + +ClusterAccelerationStructureClusterFlagsNV :: distinct bit_set[ClusterAccelerationStructureClusterFlagNV; Flags] +ClusterAccelerationStructureClusterFlagNV :: enum Flags { + ALLOW_DISABLE_OPACITY_MICROMAPS = 0, +} + +ClusterAccelerationStructureGeometryFlagsNV :: distinct bit_set[ClusterAccelerationStructureGeometryFlagNV; Flags] +ClusterAccelerationStructureGeometryFlagNV :: enum Flags { + CULL_DISABLE = 0, + NO_DUPLICATE_ANYHIT_INVOCATION = 1, + OPAQUE = 2, +} + +ClusterAccelerationStructureIndexFormatFlagsNV :: distinct bit_set[ClusterAccelerationStructureIndexFormatFlagNV; Flags] +ClusterAccelerationStructureIndexFormatFlagNV :: enum Flags { + _8BIT = 0, + _16BIT = 1, + _32BIT = 2, +} + +ClusterAccelerationStructureOpModeNV :: enum c.int { + IMPLICIT_DESTINATIONS = 0, + EXPLICIT_DESTINATIONS = 1, + COMPUTE_SIZES = 2, +} + +ClusterAccelerationStructureOpTypeNV :: enum c.int { + MOVE_OBJECTS = 0, + BUILD_CLUSTERS_BOTTOM_LEVEL = 1, + BUILD_TRIANGLE_CLUSTER = 2, + BUILD_TRIANGLE_CLUSTER_TEMPLATE = 3, + INSTANTIATE_TRIANGLE_CLUSTER = 4, +} + +ClusterAccelerationStructureTypeNV :: enum c.int { + CLUSTERS_BOTTOM_LEVEL = 0, + TRIANGLE_CLUSTER = 1, + TRIANGLE_CLUSTER_TEMPLATE = 2, +} + CoarseSampleOrderTypeNV :: enum c.int { DEFAULT = 0, CUSTOM = 1, @@ -391,28 +440,32 @@ ComponentSwizzle :: enum c.int { } ComponentTypeKHR :: enum c.int { - FLOAT16 = 0, - FLOAT32 = 1, - FLOAT64 = 2, - SINT8 = 3, - SINT16 = 4, - SINT32 = 5, - SINT64 = 6, - UINT8 = 7, - UINT16 = 8, - UINT32 = 9, - UINT64 = 10, - FLOAT16_NV = FLOAT16, - FLOAT32_NV = FLOAT32, - FLOAT64_NV = FLOAT64, - SINT8_NV = SINT8, - SINT16_NV = SINT16, - SINT32_NV = SINT32, - SINT64_NV = SINT64, - UINT8_NV = UINT8, - UINT16_NV = UINT16, - UINT32_NV = UINT32, - UINT64_NV = UINT64, + FLOAT16 = 0, + FLOAT32 = 1, + FLOAT64 = 2, + SINT8 = 3, + SINT16 = 4, + SINT32 = 5, + SINT64 = 6, + UINT8 = 7, + UINT16 = 8, + UINT32 = 9, + UINT64 = 10, + SINT8_PACKED_NV = 1000491000, + UINT8_PACKED_NV = 1000491001, + FLOAT_E4M3_NV = 1000491002, + FLOAT_E5M2_NV = 1000491003, + FLOAT16_NV = FLOAT16, + FLOAT32_NV = FLOAT32, + FLOAT64_NV = FLOAT64, + SINT8_NV = SINT8, + SINT16_NV = SINT16, + SINT32_NV = SINT32, + SINT64_NV = SINT64, + UINT8_NV = UINT8, + UINT16_NV = UINT16, + UINT32_NV = UINT32, + UINT64_NV = UINT64, } CompositeAlphaFlagsKHR :: distinct bit_set[CompositeAlphaFlagKHR; Flags] @@ -434,6 +487,13 @@ ConservativeRasterizationModeEXT :: enum c.int { UNDERESTIMATE = 2, } +CooperativeVectorMatrixLayoutNV :: enum c.int { + ROW_MAJOR = 0, + COLUMN_MAJOR = 1, + INFERENCING_OPTIMAL = 2, + TRAINING_OPTIMAL = 3, +} + CopyAccelerationStructureModeKHR :: enum c.int { CLONE = 0, COMPACT = 1, @@ -554,12 +614,13 @@ DebugUtilsMessageTypeFlagEXT :: enum Flags { DependencyFlags :: distinct bit_set[DependencyFlag; Flags] DependencyFlag :: enum Flags { - BY_REGION = 0, - DEVICE_GROUP = 2, - VIEW_LOCAL = 1, - FEEDBACK_LOOP_EXT = 3, - VIEW_LOCAL_KHR = VIEW_LOCAL, - DEVICE_GROUP_KHR = DEVICE_GROUP, + BY_REGION = 0, + DEVICE_GROUP = 2, + VIEW_LOCAL = 1, + FEEDBACK_LOOP_EXT = 3, + QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_KHR = 5, + VIEW_LOCAL_KHR = VIEW_LOCAL, + DEVICE_GROUP_KHR = DEVICE_GROUP, } DepthBiasRepresentationEXT :: enum c.int { @@ -611,25 +672,26 @@ DescriptorSetLayoutCreateFlag :: enum Flags { } DescriptorType :: enum c.int { - SAMPLER = 0, - COMBINED_IMAGE_SAMPLER = 1, - SAMPLED_IMAGE = 2, - STORAGE_IMAGE = 3, - UNIFORM_TEXEL_BUFFER = 4, - STORAGE_TEXEL_BUFFER = 5, - UNIFORM_BUFFER = 6, - STORAGE_BUFFER = 7, - UNIFORM_BUFFER_DYNAMIC = 8, - STORAGE_BUFFER_DYNAMIC = 9, - INPUT_ATTACHMENT = 10, - INLINE_UNIFORM_BLOCK = 1000138000, - ACCELERATION_STRUCTURE_KHR = 1000150000, - ACCELERATION_STRUCTURE_NV = 1000165000, - SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000, - BLOCK_MATCH_IMAGE_QCOM = 1000440001, - MUTABLE_EXT = 1000351000, - INLINE_UNIFORM_BLOCK_EXT = INLINE_UNIFORM_BLOCK, - MUTABLE_VALVE = MUTABLE_EXT, + SAMPLER = 0, + COMBINED_IMAGE_SAMPLER = 1, + SAMPLED_IMAGE = 2, + STORAGE_IMAGE = 3, + UNIFORM_TEXEL_BUFFER = 4, + STORAGE_TEXEL_BUFFER = 5, + UNIFORM_BUFFER = 6, + STORAGE_BUFFER = 7, + UNIFORM_BUFFER_DYNAMIC = 8, + STORAGE_BUFFER_DYNAMIC = 9, + INPUT_ATTACHMENT = 10, + INLINE_UNIFORM_BLOCK = 1000138000, + ACCELERATION_STRUCTURE_KHR = 1000150000, + ACCELERATION_STRUCTURE_NV = 1000165000, + SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000, + BLOCK_MATCH_IMAGE_QCOM = 1000440001, + MUTABLE_EXT = 1000351000, + PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570000, + INLINE_UNIFORM_BLOCK_EXT = INLINE_UNIFORM_BLOCK, + MUTABLE_VALVE = MUTABLE_EXT, } DescriptorUpdateTemplateType :: enum c.int { @@ -706,6 +768,12 @@ DiscardRectangleModeEXT :: enum c.int { EXCLUSIVE = 1, } +DisplacementMicromapFormatNV :: enum c.int { + _64_TRIANGLES_64_BYTES = 1, + _256_TRIANGLES_128_BYTES = 2, + _1024_TRIANGLES_128_BYTES = 3, +} + DisplayEventTypeEXT :: enum c.int { FIRST_PIXEL_OUT = 0, } @@ -758,7 +826,7 @@ DriverId :: enum c.int { MESA_NVK = 24, IMAGINATION_OPEN_SOURCE_MESA = 25, MESA_HONEYKRISP = 26, - RESERVED_27 = 27, + VULKAN_SC_EMULATION_ON_VULKAN = 27, AMD_PROPRIETARY_KHR = AMD_PROPRIETARY, AMD_OPEN_SOURCE_KHR = AMD_OPEN_SOURCE, MESA_RADV_KHR = MESA_RADV, @@ -935,6 +1003,9 @@ ExternalMemoryHandleTypeFlag :: enum Flags { ZIRCON_VMO_FUCHSIA = 11, RDMA_ADDRESS_NV = 12, SCREEN_BUFFER_QNX = 14, + MTLBUFFER_EXT = 16, + MTLTEXTURE_EXT = 17, + MTLHEAP_EXT = 18, OPAQUE_FD_KHR = OPAQUE_FD, OPAQUE_WIN32_KHR = OPAQUE_WIN32, OPAQUE_WIN32_KMT_KHR = OPAQUE_WIN32_KMT, @@ -1425,11 +1496,13 @@ GeometryInstanceFlagKHR :: enum Flags { } GeometryTypeKHR :: enum c.int { - TRIANGLES = 0, - AABBS = 1, - INSTANCES = 2, - TRIANGLES_NV = TRIANGLES, - AABBS_NV = AABBS, + TRIANGLES = 0, + AABBS = 1, + INSTANCES = 2, + SPHERES_NV = 1000429004, + LINEAR_SWEPT_SPHERES_NV = 1000429005, + TRIANGLES_NV = TRIANGLES, + AABBS_NV = AABBS, } GraphicsPipelineLibraryFlagsEXT :: distinct bit_set[GraphicsPipelineLibraryFlagEXT; Flags] @@ -1906,10 +1979,11 @@ OpacityMicromapFormatEXT :: enum c.int { } OpacityMicromapSpecialIndexEXT :: enum c.int { - FULLY_TRANSPARENT = -1, - FULLY_OPAQUE = -2, - FULLY_UNKNOWN_TRANSPARENT = -3, - FULLY_UNKNOWN_OPAQUE = -4, + FULLY_TRANSPARENT = -1, + FULLY_OPAQUE = -2, + FULLY_UNKNOWN_TRANSPARENT = -3, + FULLY_UNKNOWN_OPAQUE = -4, + CLUSTER_GEOMETRY_DISABLE_OPACITY_MICROMAP_NV = -5, } OpticalFlowExecuteFlagsNV :: distinct bit_set[OpticalFlowExecuteFlagNV; Flags] @@ -1973,6 +2047,21 @@ OutOfBandQueueTypeNV :: enum c.int { PRESENT = 1, } +PartitionedAccelerationStructureInstanceFlagsNV :: distinct bit_set[PartitionedAccelerationStructureInstanceFlagNV; Flags] +PartitionedAccelerationStructureInstanceFlagNV :: enum Flags { + FLAG_TRIANGLE_FACING_CULL_DISABLE = 0, + FLAG_TRIANGLE_FLIP_FACING = 1, + FLAG_FORCE_OPAQUE = 2, + FLAG_FORCE_NO_OPAQUE = 3, + FLAG_ENABLE_EXPLICIT_BOUNDING_BOX = 4, +} + +PartitionedAccelerationStructureOpTypeNV :: enum c.int { + WRITE_INSTANCE = 0, + UPDATE_INSTANCE = 1, + WRITE_PARTITION_TRANSLATION = 2, +} + PeerMemoryFeatureFlags :: distinct bit_set[PeerMemoryFeatureFlag; Flags] PeerMemoryFeatureFlag :: enum Flags { COPY_SRC = 0, @@ -2072,8 +2161,9 @@ PipelineBindPoint :: enum c.int { PipelineCacheCreateFlags :: distinct bit_set[PipelineCacheCreateFlag; Flags] PipelineCacheCreateFlag :: enum Flags { - EXTERNALLY_SYNCHRONIZED = 0, - EXTERNALLY_SYNCHRONIZED_EXT = EXTERNALLY_SYNCHRONIZED, + EXTERNALLY_SYNCHRONIZED = 0, + INTERNALLY_SYNCHRONIZED_MERGE_KHR = 3, + EXTERNALLY_SYNCHRONIZED_EXT = EXTERNALLY_SYNCHRONIZED, } PipelineCacheHeaderVersion :: enum c.int { @@ -2389,6 +2479,16 @@ RayTracingInvocationReorderModeNV :: enum c.int { REORDER = 1, } +RayTracingLssIndexingModeNV :: enum c.int { + LIST = 0, + SUCCESSIVE = 1, +} + +RayTracingLssPrimitiveEndCapsModeNV :: enum c.int { + NONE = 0, + CHAINED = 1, +} + RayTracingShaderGroupTypeKHR :: enum c.int { GENERAL = 0, TRIANGLES_HIT_GROUP = 1, @@ -3498,7 +3598,6 @@ StructureType :: enum c.int { PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000, DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001, DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002, - PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = 1000421000, PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000, PHYSICAL_DEVICE_RENDER_PASS_STRIPED_FEATURES_ARM = 1000424000, PHYSICAL_DEVICE_RENDER_PASS_STRIPED_PROPERTIES_ARM = 1000424001, @@ -3515,6 +3614,9 @@ StructureType :: enum c.int { PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV = 1000428000, COMPUTE_PIPELINE_INDIRECT_BUFFER_INFO_NV = 1000428001, PIPELINE_INDIRECT_DEVICE_ADDRESS_INFO_NV = 1000428002, + PHYSICAL_DEVICE_RAY_TRACING_LINEAR_SWEPT_SPHERES_FEATURES_NV = 1000429008, + ACCELERATION_STRUCTURE_GEOMETRY_LINEAR_SWEPT_SPHERES_DATA_NV = 1000429009, + ACCELERATION_STRUCTURE_GEOMETRY_SPHERES_DATA_NV = 1000429010, PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV = 1000430000, PHYSICAL_DEVICE_SHADER_MAXIMAL_RECONVERGENCE_FEATURES_KHR = 1000434000, PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT = 1000437000, @@ -3572,6 +3674,10 @@ StructureType :: enum c.int { PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM = 1000488000, PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV = 1000490000, PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV = 1000490001, + PHYSICAL_DEVICE_COOPERATIVE_VECTOR_FEATURES_NV = 1000491000, + PHYSICAL_DEVICE_COOPERATIVE_VECTOR_PROPERTIES_NV = 1000491001, + COOPERATIVE_VECTOR_PROPERTIES_NV = 1000491002, + CONVERT_COOPERATIVE_VECTOR_MATRIX_INFO_NV = 1000491004, PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV = 1000492000, PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV = 1000492001, PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT = 1000351000, @@ -3661,6 +3767,20 @@ StructureType :: enum c.int { PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT16_VECTOR_FEATURES_NV = 1000563000, PHYSICAL_DEVICE_SHADER_REPLICATED_COMPOSITES_FEATURES_EXT = 1000564000, PHYSICAL_DEVICE_RAY_TRACING_VALIDATION_FEATURES_NV = 1000568000, + PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_FEATURES_NV = 1000569000, + PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_PROPERTIES_NV = 1000569001, + CLUSTER_ACCELERATION_STRUCTURE_CLUSTERS_BOTTOM_LEVEL_INPUT_NV = 1000569002, + CLUSTER_ACCELERATION_STRUCTURE_TRIANGLE_CLUSTER_INPUT_NV = 1000569003, + CLUSTER_ACCELERATION_STRUCTURE_MOVE_OBJECTS_INPUT_NV = 1000569004, + CLUSTER_ACCELERATION_STRUCTURE_INPUT_INFO_NV = 1000569005, + CLUSTER_ACCELERATION_STRUCTURE_COMMANDS_INFO_NV = 1000569006, + RAY_TRACING_PIPELINE_CLUSTER_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000569007, + PHYSICAL_DEVICE_PARTITIONED_ACCELERATION_STRUCTURE_FEATURES_NV = 1000570000, + PHYSICAL_DEVICE_PARTITIONED_ACCELERATION_STRUCTURE_PROPERTIES_NV = 1000570001, + WRITE_DESCRIPTOR_SET_PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570002, + PARTITIONED_ACCELERATION_STRUCTURE_INSTANCES_INPUT_NV = 1000570003, + BUILD_PARTITIONED_ACCELERATION_STRUCTURE_INFO_NV = 1000570004, + PARTITIONED_ACCELERATION_STRUCTURE_FLAGS_NV = 1000570005, PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_EXT = 1000572000, PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_EXT = 1000572001, GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_EXT = 1000572002, @@ -3675,17 +3795,30 @@ StructureType :: enum c.int { INDIRECT_EXECUTION_SET_SHADER_LAYOUT_INFO_EXT = 1000572012, GENERATED_COMMANDS_PIPELINE_INFO_EXT = 1000572013, GENERATED_COMMANDS_SHADER_INFO_EXT = 1000572014, + PHYSICAL_DEVICE_MAINTENANCE_8_FEATURES_KHR = 1000574000, + MEMORY_BARRIER_ACCESS_FLAGS_3_KHR = 1000574002, PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_FEATURES_MESA = 1000575000, PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_PROPERTIES_MESA = 1000575001, IMAGE_ALIGNMENT_CONTROL_CREATE_INFO_MESA = 1000575002, PHYSICAL_DEVICE_DEPTH_CLAMP_CONTROL_FEATURES_EXT = 1000582000, PIPELINE_VIEWPORT_DEPTH_CLAMP_CONTROL_CREATE_INFO_EXT = 1000582001, + PHYSICAL_DEVICE_VIDEO_MAINTENANCE_2_FEATURES_KHR = 1000586000, + VIDEO_DECODE_H264_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586001, + VIDEO_DECODE_H265_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586002, + VIDEO_DECODE_AV1_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586003, PHYSICAL_DEVICE_HDR_VIVID_FEATURES_HUAWEI = 1000590000, HDR_VIVID_DYNAMIC_METADATA_HUAWEI = 1000590001, PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_FEATURES_NV = 1000593000, COOPERATIVE_MATRIX_FLEXIBLE_DIMENSIONS_PROPERTIES_NV = 1000593001, PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_PROPERTIES_NV = 1000593002, + PHYSICAL_DEVICE_PIPELINE_OPACITY_MICROMAP_FEATURES_ARM = 1000596000, + IMPORT_MEMORY_METAL_HANDLE_INFO_EXT = 1000602000, + MEMORY_METAL_HANDLE_PROPERTIES_EXT = 1000602001, + MEMORY_GET_METAL_HANDLE_INFO_EXT = 1000602002, + PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR = 1000421000, PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_ROBUSTNESS_FEATURES_EXT = 1000608000, + SET_PRESENT_CONFIG_NV = 1000613000, + PHYSICAL_DEVICE_PRESENT_METERING_FEATURES_NV = 1000613001, PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, DEBUG_REPORT_CREATE_INFO_EXT = DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, @@ -3892,6 +4025,7 @@ StructureType :: enum c.int { DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = DEVICE_BUFFER_MEMORY_REQUIREMENTS, DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = DEVICE_IMAGE_MEMORY_REQUIREMENTS, PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES, + PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR, PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES, PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR = PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES, PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR = PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES, @@ -4481,6 +4615,7 @@ VideoSessionCreateFlagKHR :: enum Flags { INLINE_QUERIES = 2, ALLOW_ENCODE_QUANTIZATION_DELTA_MAP = 3, ALLOW_ENCODE_EMPHASIS_MAP = 4, + INLINE_SESSION_PARAMETERS = 5, } VideoSessionParametersCreateFlagsKHR :: distinct bit_set[VideoSessionParametersCreateFlagKHR; Flags] @@ -4767,6 +4902,7 @@ FormatFeatureFlag2 :: enum Flags64 { SAMPLED_IMAGE_DEPTH_COMPARISON_KHR = 33, SAMPLED_IMAGE_FILTER_MINMAX_KHR = 16, SAMPLED_IMAGE_FILTER_CUBIC_EXT = 13, + ACCELERATION_STRUCTURE_RADIUS_BUFFER_NV = 51, LINEAR_COLOR_ATTACHMENT_NV = 38, WEIGHT_IMAGE_QCOM = 34, WEIGHT_SAMPLED_IMAGE_QCOM = 35, @@ -4781,50 +4917,53 @@ FormatFeatureFlag2 :: enum Flags64 { PipelineCreateFlags2 :: distinct bit_set[PipelineCreateFlag2; Flags64] PipelineCreateFlag2 :: enum Flags64 { - DISABLE_OPTIMIZATION = 0, - ALLOW_DERIVATIVES = 1, - DERIVATIVE = 2, - VIEW_INDEX_FROM_DEVICE_INDEX = 3, - DISPATCH_BASE = 4, - FAIL_ON_PIPELINE_COMPILE_REQUIRED = 8, - EARLY_RETURN_ON_FAILURE = 9, - NO_PROTECTED_ACCESS = 27, - PROTECTED_ACCESS_ONLY = 30, - EXECUTION_GRAPH_AMDX = 32, - ENABLE_LEGACY_DITHERING_EXT = 34, - DISABLE_OPTIMIZATION_KHR = 0, - ALLOW_DERIVATIVES_KHR = 1, - DERIVATIVE_KHR = 2, - VIEW_INDEX_FROM_DEVICE_INDEX_KHR = 3, - DISPATCH_BASE_KHR = 4, - DEFER_COMPILE_NV = 5, - CAPTURE_STATISTICS_KHR = 6, - CAPTURE_INTERNAL_REPRESENTATIONS_KHR = 7, - FAIL_ON_PIPELINE_COMPILE_REQUIRED_KHR = 8, - EARLY_RETURN_ON_FAILURE_KHR = 9, - LINK_TIME_OPTIMIZATION_EXT = 10, - RETAIN_LINK_TIME_OPTIMIZATION_INFO_EXT = 23, - LIBRARY_KHR = 11, - RAY_TRACING_SKIP_TRIANGLES_KHR = 12, - RAY_TRACING_SKIP_AABBS_KHR = 13, - RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_KHR = 14, - RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_KHR = 15, - RAY_TRACING_NO_NULL_MISS_SHADERS_KHR = 16, - RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_KHR = 17, - RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_KHR = 19, - INDIRECT_BINDABLE_NV = 18, - RAY_TRACING_ALLOW_MOTION_NV = 20, - RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_KHR = 21, - RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_EXT = 22, - RAY_TRACING_OPACITY_MICROMAP_EXT = 24, - COLOR_ATTACHMENT_FEEDBACK_LOOP_EXT = 25, - DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_EXT = 26, - NO_PROTECTED_ACCESS_EXT = 27, - PROTECTED_ACCESS_ONLY_EXT = 30, - RAY_TRACING_DISPLACEMENT_MICROMAP_NV = 28, - DESCRIPTOR_BUFFER_EXT = 29, - CAPTURE_DATA_KHR = 31, - INDIRECT_BINDABLE_EXT = 38, + DISABLE_OPTIMIZATION = 0, + ALLOW_DERIVATIVES = 1, + DERIVATIVE = 2, + VIEW_INDEX_FROM_DEVICE_INDEX = 3, + DISPATCH_BASE = 4, + FAIL_ON_PIPELINE_COMPILE_REQUIRED = 8, + EARLY_RETURN_ON_FAILURE = 9, + NO_PROTECTED_ACCESS = 27, + PROTECTED_ACCESS_ONLY = 30, + EXECUTION_GRAPH_AMDX = 32, + RAY_TRACING_SKIP_BUILT_IN_PRIMITIVES_KHR = 12, + RAY_TRACING_ALLOW_SPHERES_AND_LINEAR_SWEPT_SPHERES_NV = 33, + ENABLE_LEGACY_DITHERING_EXT = 34, + DISABLE_OPTIMIZATION_KHR = 0, + ALLOW_DERIVATIVES_KHR = 1, + DERIVATIVE_KHR = 2, + VIEW_INDEX_FROM_DEVICE_INDEX_KHR = 3, + DISPATCH_BASE_KHR = 4, + DEFER_COMPILE_NV = 5, + CAPTURE_STATISTICS_KHR = 6, + CAPTURE_INTERNAL_REPRESENTATIONS_KHR = 7, + FAIL_ON_PIPELINE_COMPILE_REQUIRED_KHR = 8, + EARLY_RETURN_ON_FAILURE_KHR = 9, + LINK_TIME_OPTIMIZATION_EXT = 10, + RETAIN_LINK_TIME_OPTIMIZATION_INFO_EXT = 23, + LIBRARY_KHR = 11, + RAY_TRACING_SKIP_TRIANGLES_KHR = 12, + RAY_TRACING_SKIP_AABBS_KHR = 13, + RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_KHR = 14, + RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_KHR = 15, + RAY_TRACING_NO_NULL_MISS_SHADERS_KHR = 16, + RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_KHR = 17, + RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_KHR = 19, + INDIRECT_BINDABLE_NV = 18, + RAY_TRACING_ALLOW_MOTION_NV = 20, + RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_KHR = 21, + RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_EXT = 22, + RAY_TRACING_OPACITY_MICROMAP_EXT = 24, + COLOR_ATTACHMENT_FEEDBACK_LOOP_EXT = 25, + DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_EXT = 26, + NO_PROTECTED_ACCESS_EXT = 27, + PROTECTED_ACCESS_ONLY_EXT = 30, + RAY_TRACING_DISPLACEMENT_MICROMAP_NV = 28, + DESCRIPTOR_BUFFER_EXT = 29, + DISALLOW_OPACITY_MICROMAP_ARM = 37, + CAPTURE_DATA_KHR = 31, + INDIRECT_BINDABLE_EXT = 38, } PipelineStageFlags2 :: distinct bit_set[PipelineStageFlag2; Flags64] @@ -4903,6 +5042,7 @@ PipelineStageFlag2 :: enum Flags64 { MICROMAP_BUILD_EXT = 30, CLUSTER_CULLING_SHADER_HUAWEI = 41, OPTICAL_FLOW_NV = 29, + CONVERT_COOPERATIVE_VECTOR_MATRIX_NV = 44, } diff --git a/vendor/vulkan/procedures.odin b/vendor/vulkan/procedures.odin index 19f70fc85..6a63c83d0 100644 --- a/vendor/vulkan/procedures.odin +++ b/vendor/vulkan/procedures.odin @@ -62,6 +62,7 @@ ProcGetPhysicalDeviceCalibrateableTimeDomainsKHR :: #type pr ProcGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeMatrixFlexibleDimensionsPropertiesNV) -> Result ProcGetPhysicalDeviceCooperativeMatrixPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeMatrixPropertiesKHR) -> Result ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeMatrixPropertiesNV) -> Result +ProcGetPhysicalDeviceCooperativeVectorPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeVectorPropertiesNV) -> Result ProcGetPhysicalDeviceDisplayPlaneProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayPlaneProperties2KHR) -> Result ProcGetPhysicalDeviceDisplayPlanePropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayPlanePropertiesKHR) -> Result ProcGetPhysicalDeviceDisplayProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayProperties2KHR) -> Result @@ -178,11 +179,14 @@ ProcCmdBlitImage2KHR :: #type proc "system ProcCmdBuildAccelerationStructureNV :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^AccelerationStructureInfoNV, instanceData: Buffer, instanceOffset: DeviceSize, update: b32, dst: AccelerationStructureNV, src: AccelerationStructureNV, scratch: Buffer, scratchOffset: DeviceSize) ProcCmdBuildAccelerationStructuresIndirectKHR :: #type proc "system" (commandBuffer: CommandBuffer, infoCount: u32, pInfos: [^]AccelerationStructureBuildGeometryInfoKHR, pIndirectDeviceAddresses: [^]DeviceAddress, pIndirectStrides: [^]u32, ppMaxPrimitiveCounts: ^[^]u32) ProcCmdBuildAccelerationStructuresKHR :: #type proc "system" (commandBuffer: CommandBuffer, infoCount: u32, pInfos: [^]AccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ^[^]AccelerationStructureBuildRangeInfoKHR) +ProcCmdBuildClusterAccelerationStructureIndirectNV :: #type proc "system" (commandBuffer: CommandBuffer, pCommandInfos: [^]ClusterAccelerationStructureCommandsInfoNV) ProcCmdBuildMicromapsEXT :: #type proc "system" (commandBuffer: CommandBuffer, infoCount: u32, pInfos: [^]MicromapBuildInfoEXT) +ProcCmdBuildPartitionedAccelerationStructuresNV :: #type proc "system" (commandBuffer: CommandBuffer, pBuildInfo: ^BuildPartitionedAccelerationStructureInfoNV) ProcCmdClearAttachments :: #type proc "system" (commandBuffer: CommandBuffer, attachmentCount: u32, pAttachments: [^]ClearAttachment, rectCount: u32, pRects: [^]ClearRect) ProcCmdClearColorImage :: #type proc "system" (commandBuffer: CommandBuffer, image: Image, imageLayout: ImageLayout, pColor: ^ClearColorValue, rangeCount: u32, pRanges: [^]ImageSubresourceRange) ProcCmdClearDepthStencilImage :: #type proc "system" (commandBuffer: CommandBuffer, image: Image, imageLayout: ImageLayout, pDepthStencil: ^ClearDepthStencilValue, rangeCount: u32, pRanges: [^]ImageSubresourceRange) ProcCmdControlVideoCodingKHR :: #type proc "system" (commandBuffer: CommandBuffer, pCodingControlInfo: ^VideoCodingControlInfoKHR) +ProcCmdConvertCooperativeVectorMatrixNV :: #type proc "system" (commandBuffer: CommandBuffer, infoCount: u32, pInfos: [^]ConvertCooperativeVectorMatrixInfoNV) ProcCmdCopyAccelerationStructureKHR :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^CopyAccelerationStructureInfoKHR) ProcCmdCopyAccelerationStructureNV :: #type proc "system" (commandBuffer: CommandBuffer, dst: AccelerationStructureNV, src: AccelerationStructureNV, mode: CopyAccelerationStructureModeKHR) ProcCmdCopyAccelerationStructureToMemoryKHR :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^CopyAccelerationStructureToMemoryInfoKHR) @@ -216,6 +220,9 @@ ProcCmdDecompressMemoryNV :: #type proc "system ProcCmdDispatch :: #type proc "system" (commandBuffer: CommandBuffer, groupCountX: u32, groupCountY: u32, groupCountZ: u32) ProcCmdDispatchBase :: #type proc "system" (commandBuffer: CommandBuffer, baseGroupX: u32, baseGroupY: u32, baseGroupZ: u32, groupCountX: u32, groupCountY: u32, groupCountZ: u32) ProcCmdDispatchBaseKHR :: #type proc "system" (commandBuffer: CommandBuffer, baseGroupX: u32, baseGroupY: u32, baseGroupZ: u32, groupCountX: u32, groupCountY: u32, groupCountZ: u32) +ProcCmdDispatchGraphAMDX :: #type proc "system" (commandBuffer: CommandBuffer, scratch: DeviceAddress, scratchSize: DeviceSize, pCountInfo: ^DispatchGraphCountInfoAMDX) +ProcCmdDispatchGraphIndirectAMDX :: #type proc "system" (commandBuffer: CommandBuffer, scratch: DeviceAddress, scratchSize: DeviceSize, pCountInfo: ^DispatchGraphCountInfoAMDX) +ProcCmdDispatchGraphIndirectCountAMDX :: #type proc "system" (commandBuffer: CommandBuffer, scratch: DeviceAddress, scratchSize: DeviceSize, countInfo: DeviceAddress) ProcCmdDispatchIndirect :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize) ProcCmdDraw :: #type proc "system" (commandBuffer: CommandBuffer, vertexCount: u32, instanceCount: u32, firstVertex: u32, firstInstance: u32) ProcCmdDrawClusterHUAWEI :: #type proc "system" (commandBuffer: CommandBuffer, groupCountX: u32, groupCountY: u32, groupCountZ: u32) @@ -254,6 +261,7 @@ ProcCmdExecuteCommands :: #type proc "system ProcCmdExecuteGeneratedCommandsEXT :: #type proc "system" (commandBuffer: CommandBuffer, isPreprocessed: b32, pGeneratedCommandsInfo: ^GeneratedCommandsInfoEXT) ProcCmdExecuteGeneratedCommandsNV :: #type proc "system" (commandBuffer: CommandBuffer, isPreprocessed: b32, pGeneratedCommandsInfo: ^GeneratedCommandsInfoNV) ProcCmdFillBuffer :: #type proc "system" (commandBuffer: CommandBuffer, dstBuffer: Buffer, dstOffset: DeviceSize, size: DeviceSize, data: u32) +ProcCmdInitializeGraphScratchMemoryAMDX :: #type proc "system" (commandBuffer: CommandBuffer, executionGraph: Pipeline, scratch: DeviceAddress, scratchSize: DeviceSize) ProcCmdInsertDebugUtilsLabelEXT :: #type proc "system" (commandBuffer: CommandBuffer, pLabelInfo: ^DebugUtilsLabelEXT) ProcCmdNextSubpass :: #type proc "system" (commandBuffer: CommandBuffer, contents: SubpassContents) ProcCmdNextSubpass2 :: #type proc "system" (commandBuffer: CommandBuffer, pSubpassBeginInfo: ^SubpassBeginInfo, pSubpassEndInfo: ^SubpassEndInfo) @@ -405,6 +413,7 @@ ProcCmdWriteTimestamp :: #type proc "system ProcCmdWriteTimestamp2 :: #type proc "system" (commandBuffer: CommandBuffer, stage: PipelineStageFlags2, queryPool: QueryPool, query: u32) ProcCmdWriteTimestamp2KHR :: #type proc "system" (commandBuffer: CommandBuffer, stage: PipelineStageFlags2, queryPool: QueryPool, query: u32) ProcCompileDeferredNV :: #type proc "system" (device: Device, pipeline: Pipeline, shader: u32) -> Result +ProcConvertCooperativeVectorMatrixNV :: #type proc "system" (device: Device, pInfo: ^ConvertCooperativeVectorMatrixInfoNV) -> Result ProcCopyAccelerationStructureKHR :: #type proc "system" (device: Device, deferredOperation: DeferredOperationKHR, pInfo: ^CopyAccelerationStructureInfoKHR) -> Result ProcCopyAccelerationStructureToMemoryKHR :: #type proc "system" (device: Device, deferredOperation: DeferredOperationKHR, pInfo: ^CopyAccelerationStructureToMemoryInfoKHR) -> Result ProcCopyImageToImage :: #type proc "system" (device: Device, pCopyImageToImageInfo: ^CopyImageToImageInfo) -> Result @@ -433,6 +442,7 @@ ProcCreateDescriptorSetLayout :: #type proc "system ProcCreateDescriptorUpdateTemplate :: #type proc "system" (device: Device, pCreateInfo: ^DescriptorUpdateTemplateCreateInfo, pAllocator: ^AllocationCallbacks, pDescriptorUpdateTemplate: ^DescriptorUpdateTemplate) -> Result ProcCreateDescriptorUpdateTemplateKHR :: #type proc "system" (device: Device, pCreateInfo: ^DescriptorUpdateTemplateCreateInfo, pAllocator: ^AllocationCallbacks, pDescriptorUpdateTemplate: ^DescriptorUpdateTemplate) -> Result ProcCreateEvent :: #type proc "system" (device: Device, pCreateInfo: ^EventCreateInfo, pAllocator: ^AllocationCallbacks, pEvent: ^Event) -> Result +ProcCreateExecutionGraphPipelinesAMDX :: #type proc "system" (device: Device, pipelineCache: PipelineCache, createInfoCount: u32, pCreateInfos: [^]ExecutionGraphPipelineCreateInfoAMDX, pAllocator: ^AllocationCallbacks, pPipelines: [^]Pipeline) -> Result ProcCreateFence :: #type proc "system" (device: Device, pCreateInfo: ^FenceCreateInfo, pAllocator: ^AllocationCallbacks, pFence: ^Fence) -> Result ProcCreateFramebuffer :: #type proc "system" (device: Device, pCreateInfo: ^FramebufferCreateInfo, pAllocator: ^AllocationCallbacks, pFramebuffer: ^Framebuffer) -> Result ProcCreateGraphicsPipelines :: #type proc "system" (device: Device, pipelineCache: PipelineCache, createInfoCount: u32, pCreateInfos: [^]GraphicsPipelineCreateInfo, pAllocator: ^AllocationCallbacks, pPipelines: [^]Pipeline) -> Result @@ -535,6 +545,7 @@ ProcGetBufferOpaqueCaptureAddressKHR :: #type proc "system ProcGetBufferOpaqueCaptureDescriptorDataEXT :: #type proc "system" (device: Device, pInfo: ^BufferCaptureDescriptorDataInfoEXT, pData: rawptr) -> Result ProcGetCalibratedTimestampsEXT :: #type proc "system" (device: Device, timestampCount: u32, pTimestampInfos: [^]CalibratedTimestampInfoKHR, pTimestamps: [^]u64, pMaxDeviation: ^u64) -> Result ProcGetCalibratedTimestampsKHR :: #type proc "system" (device: Device, timestampCount: u32, pTimestampInfos: [^]CalibratedTimestampInfoKHR, pTimestamps: [^]u64, pMaxDeviation: ^u64) -> Result +ProcGetClusterAccelerationStructureBuildSizesNV :: #type proc "system" (device: Device, pInfo: ^ClusterAccelerationStructureInputInfoNV, pSizeInfo: ^AccelerationStructureBuildSizesInfoKHR) ProcGetCudaModuleCacheNV :: #type proc "system" (device: Device, module: CudaModuleNV, pCacheSize: ^int, pCacheData: rawptr) -> Result ProcGetDeferredOperationMaxConcurrencyKHR :: #type proc "system" (device: Device, operation: DeferredOperationKHR) -> u32 ProcGetDeferredOperationResultKHR :: #type proc "system" (device: Device, operation: DeferredOperationKHR) -> Result @@ -571,6 +582,8 @@ ProcGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI :: #type proc "system ProcGetDynamicRenderingTilePropertiesQCOM :: #type proc "system" (device: Device, pRenderingInfo: ^RenderingInfo, pProperties: [^]TilePropertiesQCOM) -> Result ProcGetEncodedVideoSessionParametersKHR :: #type proc "system" (device: Device, pVideoSessionParametersInfo: ^VideoEncodeSessionParametersGetInfoKHR, pFeedbackInfo: ^VideoEncodeSessionParametersFeedbackInfoKHR, pDataSize: ^int, pData: rawptr) -> Result ProcGetEventStatus :: #type proc "system" (device: Device, event: Event) -> Result +ProcGetExecutionGraphPipelineNodeIndexAMDX :: #type proc "system" (device: Device, executionGraph: Pipeline, pNodeInfo: ^PipelineShaderStageNodeCreateInfoAMDX, pNodeIndex: ^u32) -> Result +ProcGetExecutionGraphPipelineScratchSizeAMDX :: #type proc "system" (device: Device, executionGraph: Pipeline, pSizeInfo: ^ExecutionGraphPipelineScratchSizeAMDX) -> Result ProcGetFenceFdKHR :: #type proc "system" (device: Device, pGetFdInfo: ^FenceGetFdInfoKHR, pFd: ^c.int) -> Result ProcGetFenceStatus :: #type proc "system" (device: Device, fence: Fence) -> Result ProcGetFenceWin32HandleKHR :: #type proc "system" (device: Device, pGetWin32HandleInfo: ^FenceGetWin32HandleInfoKHR, pHandle: ^HANDLE) -> Result @@ -597,11 +610,14 @@ ProcGetLatencyTimingsNV :: #type proc "system ProcGetMemoryFdKHR :: #type proc "system" (device: Device, pGetFdInfo: ^MemoryGetFdInfoKHR, pFd: ^c.int) -> Result ProcGetMemoryFdPropertiesKHR :: #type proc "system" (device: Device, handleType: ExternalMemoryHandleTypeFlags, fd: c.int, pMemoryFdProperties: [^]MemoryFdPropertiesKHR) -> Result ProcGetMemoryHostPointerPropertiesEXT :: #type proc "system" (device: Device, handleType: ExternalMemoryHandleTypeFlags, pHostPointer: rawptr, pMemoryHostPointerProperties: [^]MemoryHostPointerPropertiesEXT) -> Result +ProcGetMemoryMetalHandleEXT :: #type proc "system" (device: Device, pGetMetalHandleInfo: ^MemoryGetMetalHandleInfoEXT, pHandle: ^rawptr) -> Result +ProcGetMemoryMetalHandlePropertiesEXT :: #type proc "system" (device: Device, handleType: ExternalMemoryHandleTypeFlags, pHandle: rawptr, pMemoryMetalHandleProperties: [^]MemoryMetalHandlePropertiesEXT) -> Result ProcGetMemoryRemoteAddressNV :: #type proc "system" (device: Device, pMemoryGetRemoteAddressInfo: ^MemoryGetRemoteAddressInfoNV, pAddress: [^]RemoteAddressNV) -> Result ProcGetMemoryWin32HandleKHR :: #type proc "system" (device: Device, pGetWin32HandleInfo: ^MemoryGetWin32HandleInfoKHR, pHandle: ^HANDLE) -> Result ProcGetMemoryWin32HandleNV :: #type proc "system" (device: Device, memory: DeviceMemory, handleType: ExternalMemoryHandleTypeFlagsNV, pHandle: ^HANDLE) -> Result ProcGetMemoryWin32HandlePropertiesKHR :: #type proc "system" (device: Device, handleType: ExternalMemoryHandleTypeFlags, handle: HANDLE, pMemoryWin32HandleProperties: [^]MemoryWin32HandlePropertiesKHR) -> Result ProcGetMicromapBuildSizesEXT :: #type proc "system" (device: Device, buildType: AccelerationStructureBuildTypeKHR, pBuildInfo: ^MicromapBuildInfoEXT, pSizeInfo: ^MicromapBuildSizesInfoEXT) +ProcGetPartitionedAccelerationStructuresBuildSizesNV :: #type proc "system" (device: Device, pInfo: ^PartitionedAccelerationStructureInstancesInputNV, pSizeInfo: ^AccelerationStructureBuildSizesInfoKHR) ProcGetPastPresentationTimingGOOGLE :: #type proc "system" (device: Device, swapchain: SwapchainKHR, pPresentationTimingCount: ^u32, pPresentationTimings: [^]PastPresentationTimingGOOGLE) -> Result ProcGetPerformanceParameterINTEL :: #type proc "system" (device: Device, parameter: PerformanceParameterTypeINTEL, pValue: ^PerformanceValueINTEL) -> Result ProcGetPipelineBinaryDataKHR :: #type proc "system" (device: Device, pInfo: ^PipelineBinaryDataInfoKHR, pPipelineBinaryKey: ^PipelineBinaryKeyKHR, pPipelineBinaryDataSize: ^int, pPipelineBinaryData: rawptr) -> Result @@ -759,6 +775,7 @@ GetPhysicalDeviceCalibrateableTimeDomainsKHR: ProcGetPhysica GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV GetPhysicalDeviceCooperativeMatrixPropertiesKHR: ProcGetPhysicalDeviceCooperativeMatrixPropertiesKHR GetPhysicalDeviceCooperativeMatrixPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV +GetPhysicalDeviceCooperativeVectorPropertiesNV: ProcGetPhysicalDeviceCooperativeVectorPropertiesNV GetPhysicalDeviceDisplayPlaneProperties2KHR: ProcGetPhysicalDeviceDisplayPlaneProperties2KHR GetPhysicalDeviceDisplayPlanePropertiesKHR: ProcGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayProperties2KHR: ProcGetPhysicalDeviceDisplayProperties2KHR @@ -875,11 +892,14 @@ CmdBlitImage2KHR: ProcCmdBlitImage2KHR CmdBuildAccelerationStructureNV: ProcCmdBuildAccelerationStructureNV CmdBuildAccelerationStructuresIndirectKHR: ProcCmdBuildAccelerationStructuresIndirectKHR CmdBuildAccelerationStructuresKHR: ProcCmdBuildAccelerationStructuresKHR +CmdBuildClusterAccelerationStructureIndirectNV: ProcCmdBuildClusterAccelerationStructureIndirectNV CmdBuildMicromapsEXT: ProcCmdBuildMicromapsEXT +CmdBuildPartitionedAccelerationStructuresNV: ProcCmdBuildPartitionedAccelerationStructuresNV CmdClearAttachments: ProcCmdClearAttachments CmdClearColorImage: ProcCmdClearColorImage CmdClearDepthStencilImage: ProcCmdClearDepthStencilImage CmdControlVideoCodingKHR: ProcCmdControlVideoCodingKHR +CmdConvertCooperativeVectorMatrixNV: ProcCmdConvertCooperativeVectorMatrixNV CmdCopyAccelerationStructureKHR: ProcCmdCopyAccelerationStructureKHR CmdCopyAccelerationStructureNV: ProcCmdCopyAccelerationStructureNV CmdCopyAccelerationStructureToMemoryKHR: ProcCmdCopyAccelerationStructureToMemoryKHR @@ -913,6 +933,9 @@ CmdDecompressMemoryNV: ProcCmdDecompressMemoryN CmdDispatch: ProcCmdDispatch CmdDispatchBase: ProcCmdDispatchBase CmdDispatchBaseKHR: ProcCmdDispatchBaseKHR +CmdDispatchGraphAMDX: ProcCmdDispatchGraphAMDX +CmdDispatchGraphIndirectAMDX: ProcCmdDispatchGraphIndirectAMDX +CmdDispatchGraphIndirectCountAMDX: ProcCmdDispatchGraphIndirectCountAMDX CmdDispatchIndirect: ProcCmdDispatchIndirect CmdDraw: ProcCmdDraw CmdDrawClusterHUAWEI: ProcCmdDrawClusterHUAWEI @@ -951,6 +974,7 @@ CmdExecuteCommands: ProcCmdExecuteCommands CmdExecuteGeneratedCommandsEXT: ProcCmdExecuteGeneratedCommandsEXT CmdExecuteGeneratedCommandsNV: ProcCmdExecuteGeneratedCommandsNV CmdFillBuffer: ProcCmdFillBuffer +CmdInitializeGraphScratchMemoryAMDX: ProcCmdInitializeGraphScratchMemoryAMDX CmdInsertDebugUtilsLabelEXT: ProcCmdInsertDebugUtilsLabelEXT CmdNextSubpass: ProcCmdNextSubpass CmdNextSubpass2: ProcCmdNextSubpass2 @@ -1102,6 +1126,7 @@ CmdWriteTimestamp: ProcCmdWriteTimestamp CmdWriteTimestamp2: ProcCmdWriteTimestamp2 CmdWriteTimestamp2KHR: ProcCmdWriteTimestamp2KHR CompileDeferredNV: ProcCompileDeferredNV +ConvertCooperativeVectorMatrixNV: ProcConvertCooperativeVectorMatrixNV CopyAccelerationStructureKHR: ProcCopyAccelerationStructureKHR CopyAccelerationStructureToMemoryKHR: ProcCopyAccelerationStructureToMemoryKHR CopyImageToImage: ProcCopyImageToImage @@ -1130,6 +1155,7 @@ CreateDescriptorSetLayout: ProcCreateDescriptorSetL CreateDescriptorUpdateTemplate: ProcCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplateKHR: ProcCreateDescriptorUpdateTemplateKHR CreateEvent: ProcCreateEvent +CreateExecutionGraphPipelinesAMDX: ProcCreateExecutionGraphPipelinesAMDX CreateFence: ProcCreateFence CreateFramebuffer: ProcCreateFramebuffer CreateGraphicsPipelines: ProcCreateGraphicsPipelines @@ -1232,6 +1258,7 @@ GetBufferOpaqueCaptureAddressKHR: ProcGetBufferOpaqueCaptu GetBufferOpaqueCaptureDescriptorDataEXT: ProcGetBufferOpaqueCaptureDescriptorDataEXT GetCalibratedTimestampsEXT: ProcGetCalibratedTimestampsEXT GetCalibratedTimestampsKHR: ProcGetCalibratedTimestampsKHR +GetClusterAccelerationStructureBuildSizesNV: ProcGetClusterAccelerationStructureBuildSizesNV GetCudaModuleCacheNV: ProcGetCudaModuleCacheNV GetDeferredOperationMaxConcurrencyKHR: ProcGetDeferredOperationMaxConcurrencyKHR GetDeferredOperationResultKHR: ProcGetDeferredOperationResultKHR @@ -1268,6 +1295,8 @@ GetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI: ProcGetDeviceSubpassShad GetDynamicRenderingTilePropertiesQCOM: ProcGetDynamicRenderingTilePropertiesQCOM GetEncodedVideoSessionParametersKHR: ProcGetEncodedVideoSessionParametersKHR GetEventStatus: ProcGetEventStatus +GetExecutionGraphPipelineNodeIndexAMDX: ProcGetExecutionGraphPipelineNodeIndexAMDX +GetExecutionGraphPipelineScratchSizeAMDX: ProcGetExecutionGraphPipelineScratchSizeAMDX GetFenceFdKHR: ProcGetFenceFdKHR GetFenceStatus: ProcGetFenceStatus GetFenceWin32HandleKHR: ProcGetFenceWin32HandleKHR @@ -1294,11 +1323,14 @@ GetLatencyTimingsNV: ProcGetLatencyTimingsNV GetMemoryFdKHR: ProcGetMemoryFdKHR GetMemoryFdPropertiesKHR: ProcGetMemoryFdPropertiesKHR GetMemoryHostPointerPropertiesEXT: ProcGetMemoryHostPointerPropertiesEXT +GetMemoryMetalHandleEXT: ProcGetMemoryMetalHandleEXT +GetMemoryMetalHandlePropertiesEXT: ProcGetMemoryMetalHandlePropertiesEXT GetMemoryRemoteAddressNV: ProcGetMemoryRemoteAddressNV GetMemoryWin32HandleKHR: ProcGetMemoryWin32HandleKHR GetMemoryWin32HandleNV: ProcGetMemoryWin32HandleNV GetMemoryWin32HandlePropertiesKHR: ProcGetMemoryWin32HandlePropertiesKHR GetMicromapBuildSizesEXT: ProcGetMicromapBuildSizesEXT +GetPartitionedAccelerationStructuresBuildSizesNV: ProcGetPartitionedAccelerationStructuresBuildSizesNV GetPastPresentationTimingGOOGLE: ProcGetPastPresentationTimingGOOGLE GetPerformanceParameterINTEL: ProcGetPerformanceParameterINTEL GetPipelineBinaryDataKHR: ProcGetPipelineBinaryDataKHR @@ -1456,6 +1488,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV") set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesKHR, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR") set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") + set_proc_address(&GetPhysicalDeviceCooperativeVectorPropertiesNV, "vkGetPhysicalDeviceCooperativeVectorPropertiesNV") set_proc_address(&GetPhysicalDeviceDisplayPlaneProperties2KHR, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") set_proc_address(&GetPhysicalDeviceDisplayPlanePropertiesKHR, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR") set_proc_address(&GetPhysicalDeviceDisplayProperties2KHR, "vkGetPhysicalDeviceDisplayProperties2KHR") @@ -1572,11 +1605,14 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdBuildAccelerationStructureNV, "vkCmdBuildAccelerationStructureNV") set_proc_address(&CmdBuildAccelerationStructuresIndirectKHR, "vkCmdBuildAccelerationStructuresIndirectKHR") set_proc_address(&CmdBuildAccelerationStructuresKHR, "vkCmdBuildAccelerationStructuresKHR") + set_proc_address(&CmdBuildClusterAccelerationStructureIndirectNV, "vkCmdBuildClusterAccelerationStructureIndirectNV") set_proc_address(&CmdBuildMicromapsEXT, "vkCmdBuildMicromapsEXT") + set_proc_address(&CmdBuildPartitionedAccelerationStructuresNV, "vkCmdBuildPartitionedAccelerationStructuresNV") set_proc_address(&CmdClearAttachments, "vkCmdClearAttachments") set_proc_address(&CmdClearColorImage, "vkCmdClearColorImage") set_proc_address(&CmdClearDepthStencilImage, "vkCmdClearDepthStencilImage") set_proc_address(&CmdControlVideoCodingKHR, "vkCmdControlVideoCodingKHR") + set_proc_address(&CmdConvertCooperativeVectorMatrixNV, "vkCmdConvertCooperativeVectorMatrixNV") set_proc_address(&CmdCopyAccelerationStructureKHR, "vkCmdCopyAccelerationStructureKHR") set_proc_address(&CmdCopyAccelerationStructureNV, "vkCmdCopyAccelerationStructureNV") set_proc_address(&CmdCopyAccelerationStructureToMemoryKHR, "vkCmdCopyAccelerationStructureToMemoryKHR") @@ -1610,6 +1646,9 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdDispatch, "vkCmdDispatch") set_proc_address(&CmdDispatchBase, "vkCmdDispatchBase") set_proc_address(&CmdDispatchBaseKHR, "vkCmdDispatchBaseKHR") + set_proc_address(&CmdDispatchGraphAMDX, "vkCmdDispatchGraphAMDX") + set_proc_address(&CmdDispatchGraphIndirectAMDX, "vkCmdDispatchGraphIndirectAMDX") + set_proc_address(&CmdDispatchGraphIndirectCountAMDX, "vkCmdDispatchGraphIndirectCountAMDX") set_proc_address(&CmdDispatchIndirect, "vkCmdDispatchIndirect") set_proc_address(&CmdDraw, "vkCmdDraw") set_proc_address(&CmdDrawClusterHUAWEI, "vkCmdDrawClusterHUAWEI") @@ -1648,6 +1687,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdExecuteGeneratedCommandsEXT, "vkCmdExecuteGeneratedCommandsEXT") set_proc_address(&CmdExecuteGeneratedCommandsNV, "vkCmdExecuteGeneratedCommandsNV") set_proc_address(&CmdFillBuffer, "vkCmdFillBuffer") + set_proc_address(&CmdInitializeGraphScratchMemoryAMDX, "vkCmdInitializeGraphScratchMemoryAMDX") set_proc_address(&CmdInsertDebugUtilsLabelEXT, "vkCmdInsertDebugUtilsLabelEXT") set_proc_address(&CmdNextSubpass, "vkCmdNextSubpass") set_proc_address(&CmdNextSubpass2, "vkCmdNextSubpass2") @@ -1799,6 +1839,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdWriteTimestamp2, "vkCmdWriteTimestamp2") set_proc_address(&CmdWriteTimestamp2KHR, "vkCmdWriteTimestamp2KHR") set_proc_address(&CompileDeferredNV, "vkCompileDeferredNV") + set_proc_address(&ConvertCooperativeVectorMatrixNV, "vkConvertCooperativeVectorMatrixNV") set_proc_address(&CopyAccelerationStructureKHR, "vkCopyAccelerationStructureKHR") set_proc_address(&CopyAccelerationStructureToMemoryKHR, "vkCopyAccelerationStructureToMemoryKHR") set_proc_address(&CopyImageToImage, "vkCopyImageToImage") @@ -1827,6 +1868,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CreateDescriptorUpdateTemplate, "vkCreateDescriptorUpdateTemplate") set_proc_address(&CreateDescriptorUpdateTemplateKHR, "vkCreateDescriptorUpdateTemplateKHR") set_proc_address(&CreateEvent, "vkCreateEvent") + set_proc_address(&CreateExecutionGraphPipelinesAMDX, "vkCreateExecutionGraphPipelinesAMDX") set_proc_address(&CreateFence, "vkCreateFence") set_proc_address(&CreateFramebuffer, "vkCreateFramebuffer") set_proc_address(&CreateGraphicsPipelines, "vkCreateGraphicsPipelines") @@ -1929,6 +1971,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetBufferOpaqueCaptureDescriptorDataEXT, "vkGetBufferOpaqueCaptureDescriptorDataEXT") set_proc_address(&GetCalibratedTimestampsEXT, "vkGetCalibratedTimestampsEXT") set_proc_address(&GetCalibratedTimestampsKHR, "vkGetCalibratedTimestampsKHR") + set_proc_address(&GetClusterAccelerationStructureBuildSizesNV, "vkGetClusterAccelerationStructureBuildSizesNV") set_proc_address(&GetCudaModuleCacheNV, "vkGetCudaModuleCacheNV") set_proc_address(&GetDeferredOperationMaxConcurrencyKHR, "vkGetDeferredOperationMaxConcurrencyKHR") set_proc_address(&GetDeferredOperationResultKHR, "vkGetDeferredOperationResultKHR") @@ -1965,6 +2008,8 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetDynamicRenderingTilePropertiesQCOM, "vkGetDynamicRenderingTilePropertiesQCOM") set_proc_address(&GetEncodedVideoSessionParametersKHR, "vkGetEncodedVideoSessionParametersKHR") set_proc_address(&GetEventStatus, "vkGetEventStatus") + set_proc_address(&GetExecutionGraphPipelineNodeIndexAMDX, "vkGetExecutionGraphPipelineNodeIndexAMDX") + set_proc_address(&GetExecutionGraphPipelineScratchSizeAMDX, "vkGetExecutionGraphPipelineScratchSizeAMDX") set_proc_address(&GetFenceFdKHR, "vkGetFenceFdKHR") set_proc_address(&GetFenceStatus, "vkGetFenceStatus") set_proc_address(&GetFenceWin32HandleKHR, "vkGetFenceWin32HandleKHR") @@ -1991,11 +2036,14 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetMemoryFdKHR, "vkGetMemoryFdKHR") set_proc_address(&GetMemoryFdPropertiesKHR, "vkGetMemoryFdPropertiesKHR") set_proc_address(&GetMemoryHostPointerPropertiesEXT, "vkGetMemoryHostPointerPropertiesEXT") + set_proc_address(&GetMemoryMetalHandleEXT, "vkGetMemoryMetalHandleEXT") + set_proc_address(&GetMemoryMetalHandlePropertiesEXT, "vkGetMemoryMetalHandlePropertiesEXT") set_proc_address(&GetMemoryRemoteAddressNV, "vkGetMemoryRemoteAddressNV") set_proc_address(&GetMemoryWin32HandleKHR, "vkGetMemoryWin32HandleKHR") set_proc_address(&GetMemoryWin32HandleNV, "vkGetMemoryWin32HandleNV") set_proc_address(&GetMemoryWin32HandlePropertiesKHR, "vkGetMemoryWin32HandlePropertiesKHR") set_proc_address(&GetMicromapBuildSizesEXT, "vkGetMicromapBuildSizesEXT") + set_proc_address(&GetPartitionedAccelerationStructuresBuildSizesNV, "vkGetPartitionedAccelerationStructuresBuildSizesNV") set_proc_address(&GetPastPresentationTimingGOOGLE, "vkGetPastPresentationTimingGOOGLE") set_proc_address(&GetPerformanceParameterINTEL, "vkGetPerformanceParameterINTEL") set_proc_address(&GetPipelineBinaryDataKHR, "vkGetPipelineBinaryDataKHR") @@ -2164,11 +2212,14 @@ Device_VTable :: struct { CmdBuildAccelerationStructureNV: ProcCmdBuildAccelerationStructureNV, CmdBuildAccelerationStructuresIndirectKHR: ProcCmdBuildAccelerationStructuresIndirectKHR, CmdBuildAccelerationStructuresKHR: ProcCmdBuildAccelerationStructuresKHR, + CmdBuildClusterAccelerationStructureIndirectNV: ProcCmdBuildClusterAccelerationStructureIndirectNV, CmdBuildMicromapsEXT: ProcCmdBuildMicromapsEXT, + CmdBuildPartitionedAccelerationStructuresNV: ProcCmdBuildPartitionedAccelerationStructuresNV, CmdClearAttachments: ProcCmdClearAttachments, CmdClearColorImage: ProcCmdClearColorImage, CmdClearDepthStencilImage: ProcCmdClearDepthStencilImage, CmdControlVideoCodingKHR: ProcCmdControlVideoCodingKHR, + CmdConvertCooperativeVectorMatrixNV: ProcCmdConvertCooperativeVectorMatrixNV, CmdCopyAccelerationStructureKHR: ProcCmdCopyAccelerationStructureKHR, CmdCopyAccelerationStructureNV: ProcCmdCopyAccelerationStructureNV, CmdCopyAccelerationStructureToMemoryKHR: ProcCmdCopyAccelerationStructureToMemoryKHR, @@ -2202,6 +2253,9 @@ Device_VTable :: struct { CmdDispatch: ProcCmdDispatch, CmdDispatchBase: ProcCmdDispatchBase, CmdDispatchBaseKHR: ProcCmdDispatchBaseKHR, + CmdDispatchGraphAMDX: ProcCmdDispatchGraphAMDX, + CmdDispatchGraphIndirectAMDX: ProcCmdDispatchGraphIndirectAMDX, + CmdDispatchGraphIndirectCountAMDX: ProcCmdDispatchGraphIndirectCountAMDX, CmdDispatchIndirect: ProcCmdDispatchIndirect, CmdDraw: ProcCmdDraw, CmdDrawClusterHUAWEI: ProcCmdDrawClusterHUAWEI, @@ -2240,6 +2294,7 @@ Device_VTable :: struct { CmdExecuteGeneratedCommandsEXT: ProcCmdExecuteGeneratedCommandsEXT, CmdExecuteGeneratedCommandsNV: ProcCmdExecuteGeneratedCommandsNV, CmdFillBuffer: ProcCmdFillBuffer, + CmdInitializeGraphScratchMemoryAMDX: ProcCmdInitializeGraphScratchMemoryAMDX, CmdInsertDebugUtilsLabelEXT: ProcCmdInsertDebugUtilsLabelEXT, CmdNextSubpass: ProcCmdNextSubpass, CmdNextSubpass2: ProcCmdNextSubpass2, @@ -2391,6 +2446,7 @@ Device_VTable :: struct { CmdWriteTimestamp2: ProcCmdWriteTimestamp2, CmdWriteTimestamp2KHR: ProcCmdWriteTimestamp2KHR, CompileDeferredNV: ProcCompileDeferredNV, + ConvertCooperativeVectorMatrixNV: ProcConvertCooperativeVectorMatrixNV, CopyAccelerationStructureKHR: ProcCopyAccelerationStructureKHR, CopyAccelerationStructureToMemoryKHR: ProcCopyAccelerationStructureToMemoryKHR, CopyImageToImage: ProcCopyImageToImage, @@ -2419,6 +2475,7 @@ Device_VTable :: struct { CreateDescriptorUpdateTemplate: ProcCreateDescriptorUpdateTemplate, CreateDescriptorUpdateTemplateKHR: ProcCreateDescriptorUpdateTemplateKHR, CreateEvent: ProcCreateEvent, + CreateExecutionGraphPipelinesAMDX: ProcCreateExecutionGraphPipelinesAMDX, CreateFence: ProcCreateFence, CreateFramebuffer: ProcCreateFramebuffer, CreateGraphicsPipelines: ProcCreateGraphicsPipelines, @@ -2521,6 +2578,7 @@ Device_VTable :: struct { GetBufferOpaqueCaptureDescriptorDataEXT: ProcGetBufferOpaqueCaptureDescriptorDataEXT, GetCalibratedTimestampsEXT: ProcGetCalibratedTimestampsEXT, GetCalibratedTimestampsKHR: ProcGetCalibratedTimestampsKHR, + GetClusterAccelerationStructureBuildSizesNV: ProcGetClusterAccelerationStructureBuildSizesNV, GetCudaModuleCacheNV: ProcGetCudaModuleCacheNV, GetDeferredOperationMaxConcurrencyKHR: ProcGetDeferredOperationMaxConcurrencyKHR, GetDeferredOperationResultKHR: ProcGetDeferredOperationResultKHR, @@ -2557,6 +2615,8 @@ Device_VTable :: struct { GetDynamicRenderingTilePropertiesQCOM: ProcGetDynamicRenderingTilePropertiesQCOM, GetEncodedVideoSessionParametersKHR: ProcGetEncodedVideoSessionParametersKHR, GetEventStatus: ProcGetEventStatus, + GetExecutionGraphPipelineNodeIndexAMDX: ProcGetExecutionGraphPipelineNodeIndexAMDX, + GetExecutionGraphPipelineScratchSizeAMDX: ProcGetExecutionGraphPipelineScratchSizeAMDX, GetFenceFdKHR: ProcGetFenceFdKHR, GetFenceStatus: ProcGetFenceStatus, GetFenceWin32HandleKHR: ProcGetFenceWin32HandleKHR, @@ -2583,11 +2643,14 @@ Device_VTable :: struct { GetMemoryFdKHR: ProcGetMemoryFdKHR, GetMemoryFdPropertiesKHR: ProcGetMemoryFdPropertiesKHR, GetMemoryHostPointerPropertiesEXT: ProcGetMemoryHostPointerPropertiesEXT, + GetMemoryMetalHandleEXT: ProcGetMemoryMetalHandleEXT, + GetMemoryMetalHandlePropertiesEXT: ProcGetMemoryMetalHandlePropertiesEXT, GetMemoryRemoteAddressNV: ProcGetMemoryRemoteAddressNV, GetMemoryWin32HandleKHR: ProcGetMemoryWin32HandleKHR, GetMemoryWin32HandleNV: ProcGetMemoryWin32HandleNV, GetMemoryWin32HandlePropertiesKHR: ProcGetMemoryWin32HandlePropertiesKHR, GetMicromapBuildSizesEXT: ProcGetMicromapBuildSizesEXT, + GetPartitionedAccelerationStructuresBuildSizesNV: ProcGetPartitionedAccelerationStructuresBuildSizesNV, GetPastPresentationTimingGOOGLE: ProcGetPastPresentationTimingGOOGLE, GetPerformanceParameterINTEL: ProcGetPerformanceParameterINTEL, GetPipelineBinaryDataKHR: ProcGetPipelineBinaryDataKHR, @@ -2754,11 +2817,14 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdBuildAccelerationStructureNV = auto_cast GetDeviceProcAddr(device, "vkCmdBuildAccelerationStructureNV") vtable.CmdBuildAccelerationStructuresIndirectKHR = auto_cast GetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresIndirectKHR") vtable.CmdBuildAccelerationStructuresKHR = auto_cast GetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR") + vtable.CmdBuildClusterAccelerationStructureIndirectNV = auto_cast GetDeviceProcAddr(device, "vkCmdBuildClusterAccelerationStructureIndirectNV") vtable.CmdBuildMicromapsEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBuildMicromapsEXT") + vtable.CmdBuildPartitionedAccelerationStructuresNV = auto_cast GetDeviceProcAddr(device, "vkCmdBuildPartitionedAccelerationStructuresNV") vtable.CmdClearAttachments = auto_cast GetDeviceProcAddr(device, "vkCmdClearAttachments") vtable.CmdClearColorImage = auto_cast GetDeviceProcAddr(device, "vkCmdClearColorImage") vtable.CmdClearDepthStencilImage = auto_cast GetDeviceProcAddr(device, "vkCmdClearDepthStencilImage") vtable.CmdControlVideoCodingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdControlVideoCodingKHR") + vtable.CmdConvertCooperativeVectorMatrixNV = auto_cast GetDeviceProcAddr(device, "vkCmdConvertCooperativeVectorMatrixNV") vtable.CmdCopyAccelerationStructureKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyAccelerationStructureKHR") vtable.CmdCopyAccelerationStructureNV = auto_cast GetDeviceProcAddr(device, "vkCmdCopyAccelerationStructureNV") vtable.CmdCopyAccelerationStructureToMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyAccelerationStructureToMemoryKHR") @@ -2792,6 +2858,9 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdDispatch = auto_cast GetDeviceProcAddr(device, "vkCmdDispatch") vtable.CmdDispatchBase = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchBase") vtable.CmdDispatchBaseKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchBaseKHR") + vtable.CmdDispatchGraphAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphAMDX") + vtable.CmdDispatchGraphIndirectAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphIndirectAMDX") + vtable.CmdDispatchGraphIndirectCountAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphIndirectCountAMDX") vtable.CmdDispatchIndirect = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchIndirect") vtable.CmdDraw = auto_cast GetDeviceProcAddr(device, "vkCmdDraw") vtable.CmdDrawClusterHUAWEI = auto_cast GetDeviceProcAddr(device, "vkCmdDrawClusterHUAWEI") @@ -2830,6 +2899,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdExecuteGeneratedCommandsEXT = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteGeneratedCommandsEXT") vtable.CmdExecuteGeneratedCommandsNV = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteGeneratedCommandsNV") vtable.CmdFillBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdFillBuffer") + vtable.CmdInitializeGraphScratchMemoryAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdInitializeGraphScratchMemoryAMDX") vtable.CmdInsertDebugUtilsLabelEXT = auto_cast GetDeviceProcAddr(device, "vkCmdInsertDebugUtilsLabelEXT") vtable.CmdNextSubpass = auto_cast GetDeviceProcAddr(device, "vkCmdNextSubpass") vtable.CmdNextSubpass2 = auto_cast GetDeviceProcAddr(device, "vkCmdNextSubpass2") @@ -2981,6 +3051,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdWriteTimestamp2 = auto_cast GetDeviceProcAddr(device, "vkCmdWriteTimestamp2") vtable.CmdWriteTimestamp2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdWriteTimestamp2KHR") vtable.CompileDeferredNV = auto_cast GetDeviceProcAddr(device, "vkCompileDeferredNV") + vtable.ConvertCooperativeVectorMatrixNV = auto_cast GetDeviceProcAddr(device, "vkConvertCooperativeVectorMatrixNV") vtable.CopyAccelerationStructureKHR = auto_cast GetDeviceProcAddr(device, "vkCopyAccelerationStructureKHR") vtable.CopyAccelerationStructureToMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCopyAccelerationStructureToMemoryKHR") vtable.CopyImageToImage = auto_cast GetDeviceProcAddr(device, "vkCopyImageToImage") @@ -3009,6 +3080,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CreateDescriptorUpdateTemplate = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorUpdateTemplate") vtable.CreateDescriptorUpdateTemplateKHR = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorUpdateTemplateKHR") vtable.CreateEvent = auto_cast GetDeviceProcAddr(device, "vkCreateEvent") + vtable.CreateExecutionGraphPipelinesAMDX = auto_cast GetDeviceProcAddr(device, "vkCreateExecutionGraphPipelinesAMDX") vtable.CreateFence = auto_cast GetDeviceProcAddr(device, "vkCreateFence") vtable.CreateFramebuffer = auto_cast GetDeviceProcAddr(device, "vkCreateFramebuffer") vtable.CreateGraphicsPipelines = auto_cast GetDeviceProcAddr(device, "vkCreateGraphicsPipelines") @@ -3111,6 +3183,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.GetBufferOpaqueCaptureDescriptorDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetBufferOpaqueCaptureDescriptorDataEXT") vtable.GetCalibratedTimestampsEXT = auto_cast GetDeviceProcAddr(device, "vkGetCalibratedTimestampsEXT") vtable.GetCalibratedTimestampsKHR = auto_cast GetDeviceProcAddr(device, "vkGetCalibratedTimestampsKHR") + vtable.GetClusterAccelerationStructureBuildSizesNV = auto_cast GetDeviceProcAddr(device, "vkGetClusterAccelerationStructureBuildSizesNV") vtable.GetCudaModuleCacheNV = auto_cast GetDeviceProcAddr(device, "vkGetCudaModuleCacheNV") vtable.GetDeferredOperationMaxConcurrencyKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeferredOperationMaxConcurrencyKHR") vtable.GetDeferredOperationResultKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeferredOperationResultKHR") @@ -3147,6 +3220,8 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.GetDynamicRenderingTilePropertiesQCOM = auto_cast GetDeviceProcAddr(device, "vkGetDynamicRenderingTilePropertiesQCOM") vtable.GetEncodedVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkGetEncodedVideoSessionParametersKHR") vtable.GetEventStatus = auto_cast GetDeviceProcAddr(device, "vkGetEventStatus") + vtable.GetExecutionGraphPipelineNodeIndexAMDX = auto_cast GetDeviceProcAddr(device, "vkGetExecutionGraphPipelineNodeIndexAMDX") + vtable.GetExecutionGraphPipelineScratchSizeAMDX = auto_cast GetDeviceProcAddr(device, "vkGetExecutionGraphPipelineScratchSizeAMDX") vtable.GetFenceFdKHR = auto_cast GetDeviceProcAddr(device, "vkGetFenceFdKHR") vtable.GetFenceStatus = auto_cast GetDeviceProcAddr(device, "vkGetFenceStatus") vtable.GetFenceWin32HandleKHR = auto_cast GetDeviceProcAddr(device, "vkGetFenceWin32HandleKHR") @@ -3173,11 +3248,14 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.GetMemoryFdKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryFdKHR") vtable.GetMemoryFdPropertiesKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryFdPropertiesKHR") vtable.GetMemoryHostPointerPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetMemoryHostPointerPropertiesEXT") + vtable.GetMemoryMetalHandleEXT = auto_cast GetDeviceProcAddr(device, "vkGetMemoryMetalHandleEXT") + vtable.GetMemoryMetalHandlePropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetMemoryMetalHandlePropertiesEXT") vtable.GetMemoryRemoteAddressNV = auto_cast GetDeviceProcAddr(device, "vkGetMemoryRemoteAddressNV") vtable.GetMemoryWin32HandleKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryWin32HandleKHR") vtable.GetMemoryWin32HandleNV = auto_cast GetDeviceProcAddr(device, "vkGetMemoryWin32HandleNV") vtable.GetMemoryWin32HandlePropertiesKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryWin32HandlePropertiesKHR") vtable.GetMicromapBuildSizesEXT = auto_cast GetDeviceProcAddr(device, "vkGetMicromapBuildSizesEXT") + vtable.GetPartitionedAccelerationStructuresBuildSizesNV = auto_cast GetDeviceProcAddr(device, "vkGetPartitionedAccelerationStructuresBuildSizesNV") vtable.GetPastPresentationTimingGOOGLE = auto_cast GetDeviceProcAddr(device, "vkGetPastPresentationTimingGOOGLE") vtable.GetPerformanceParameterINTEL = auto_cast GetDeviceProcAddr(device, "vkGetPerformanceParameterINTEL") vtable.GetPipelineBinaryDataKHR = auto_cast GetDeviceProcAddr(device, "vkGetPipelineBinaryDataKHR") @@ -3344,11 +3422,14 @@ load_proc_addresses_device :: proc(device: Device) { CmdBuildAccelerationStructureNV = auto_cast GetDeviceProcAddr(device, "vkCmdBuildAccelerationStructureNV") CmdBuildAccelerationStructuresIndirectKHR = auto_cast GetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresIndirectKHR") CmdBuildAccelerationStructuresKHR = auto_cast GetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR") + CmdBuildClusterAccelerationStructureIndirectNV = auto_cast GetDeviceProcAddr(device, "vkCmdBuildClusterAccelerationStructureIndirectNV") CmdBuildMicromapsEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBuildMicromapsEXT") + CmdBuildPartitionedAccelerationStructuresNV = auto_cast GetDeviceProcAddr(device, "vkCmdBuildPartitionedAccelerationStructuresNV") CmdClearAttachments = auto_cast GetDeviceProcAddr(device, "vkCmdClearAttachments") CmdClearColorImage = auto_cast GetDeviceProcAddr(device, "vkCmdClearColorImage") CmdClearDepthStencilImage = auto_cast GetDeviceProcAddr(device, "vkCmdClearDepthStencilImage") CmdControlVideoCodingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdControlVideoCodingKHR") + CmdConvertCooperativeVectorMatrixNV = auto_cast GetDeviceProcAddr(device, "vkCmdConvertCooperativeVectorMatrixNV") CmdCopyAccelerationStructureKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyAccelerationStructureKHR") CmdCopyAccelerationStructureNV = auto_cast GetDeviceProcAddr(device, "vkCmdCopyAccelerationStructureNV") CmdCopyAccelerationStructureToMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyAccelerationStructureToMemoryKHR") @@ -3382,6 +3463,9 @@ load_proc_addresses_device :: proc(device: Device) { CmdDispatch = auto_cast GetDeviceProcAddr(device, "vkCmdDispatch") CmdDispatchBase = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchBase") CmdDispatchBaseKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchBaseKHR") + CmdDispatchGraphAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphAMDX") + CmdDispatchGraphIndirectAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphIndirectAMDX") + CmdDispatchGraphIndirectCountAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphIndirectCountAMDX") CmdDispatchIndirect = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchIndirect") CmdDraw = auto_cast GetDeviceProcAddr(device, "vkCmdDraw") CmdDrawClusterHUAWEI = auto_cast GetDeviceProcAddr(device, "vkCmdDrawClusterHUAWEI") @@ -3420,6 +3504,7 @@ load_proc_addresses_device :: proc(device: Device) { CmdExecuteGeneratedCommandsEXT = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteGeneratedCommandsEXT") CmdExecuteGeneratedCommandsNV = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteGeneratedCommandsNV") CmdFillBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdFillBuffer") + CmdInitializeGraphScratchMemoryAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdInitializeGraphScratchMemoryAMDX") CmdInsertDebugUtilsLabelEXT = auto_cast GetDeviceProcAddr(device, "vkCmdInsertDebugUtilsLabelEXT") CmdNextSubpass = auto_cast GetDeviceProcAddr(device, "vkCmdNextSubpass") CmdNextSubpass2 = auto_cast GetDeviceProcAddr(device, "vkCmdNextSubpass2") @@ -3571,6 +3656,7 @@ load_proc_addresses_device :: proc(device: Device) { CmdWriteTimestamp2 = auto_cast GetDeviceProcAddr(device, "vkCmdWriteTimestamp2") CmdWriteTimestamp2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdWriteTimestamp2KHR") CompileDeferredNV = auto_cast GetDeviceProcAddr(device, "vkCompileDeferredNV") + ConvertCooperativeVectorMatrixNV = auto_cast GetDeviceProcAddr(device, "vkConvertCooperativeVectorMatrixNV") CopyAccelerationStructureKHR = auto_cast GetDeviceProcAddr(device, "vkCopyAccelerationStructureKHR") CopyAccelerationStructureToMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCopyAccelerationStructureToMemoryKHR") CopyImageToImage = auto_cast GetDeviceProcAddr(device, "vkCopyImageToImage") @@ -3599,6 +3685,7 @@ load_proc_addresses_device :: proc(device: Device) { CreateDescriptorUpdateTemplate = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorUpdateTemplate") CreateDescriptorUpdateTemplateKHR = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorUpdateTemplateKHR") CreateEvent = auto_cast GetDeviceProcAddr(device, "vkCreateEvent") + CreateExecutionGraphPipelinesAMDX = auto_cast GetDeviceProcAddr(device, "vkCreateExecutionGraphPipelinesAMDX") CreateFence = auto_cast GetDeviceProcAddr(device, "vkCreateFence") CreateFramebuffer = auto_cast GetDeviceProcAddr(device, "vkCreateFramebuffer") CreateGraphicsPipelines = auto_cast GetDeviceProcAddr(device, "vkCreateGraphicsPipelines") @@ -3701,6 +3788,7 @@ load_proc_addresses_device :: proc(device: Device) { GetBufferOpaqueCaptureDescriptorDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetBufferOpaqueCaptureDescriptorDataEXT") GetCalibratedTimestampsEXT = auto_cast GetDeviceProcAddr(device, "vkGetCalibratedTimestampsEXT") GetCalibratedTimestampsKHR = auto_cast GetDeviceProcAddr(device, "vkGetCalibratedTimestampsKHR") + GetClusterAccelerationStructureBuildSizesNV = auto_cast GetDeviceProcAddr(device, "vkGetClusterAccelerationStructureBuildSizesNV") GetCudaModuleCacheNV = auto_cast GetDeviceProcAddr(device, "vkGetCudaModuleCacheNV") GetDeferredOperationMaxConcurrencyKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeferredOperationMaxConcurrencyKHR") GetDeferredOperationResultKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeferredOperationResultKHR") @@ -3737,6 +3825,8 @@ load_proc_addresses_device :: proc(device: Device) { GetDynamicRenderingTilePropertiesQCOM = auto_cast GetDeviceProcAddr(device, "vkGetDynamicRenderingTilePropertiesQCOM") GetEncodedVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkGetEncodedVideoSessionParametersKHR") GetEventStatus = auto_cast GetDeviceProcAddr(device, "vkGetEventStatus") + GetExecutionGraphPipelineNodeIndexAMDX = auto_cast GetDeviceProcAddr(device, "vkGetExecutionGraphPipelineNodeIndexAMDX") + GetExecutionGraphPipelineScratchSizeAMDX = auto_cast GetDeviceProcAddr(device, "vkGetExecutionGraphPipelineScratchSizeAMDX") GetFenceFdKHR = auto_cast GetDeviceProcAddr(device, "vkGetFenceFdKHR") GetFenceStatus = auto_cast GetDeviceProcAddr(device, "vkGetFenceStatus") GetFenceWin32HandleKHR = auto_cast GetDeviceProcAddr(device, "vkGetFenceWin32HandleKHR") @@ -3763,11 +3853,14 @@ load_proc_addresses_device :: proc(device: Device) { GetMemoryFdKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryFdKHR") GetMemoryFdPropertiesKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryFdPropertiesKHR") GetMemoryHostPointerPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetMemoryHostPointerPropertiesEXT") + GetMemoryMetalHandleEXT = auto_cast GetDeviceProcAddr(device, "vkGetMemoryMetalHandleEXT") + GetMemoryMetalHandlePropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetMemoryMetalHandlePropertiesEXT") GetMemoryRemoteAddressNV = auto_cast GetDeviceProcAddr(device, "vkGetMemoryRemoteAddressNV") GetMemoryWin32HandleKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryWin32HandleKHR") GetMemoryWin32HandleNV = auto_cast GetDeviceProcAddr(device, "vkGetMemoryWin32HandleNV") GetMemoryWin32HandlePropertiesKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryWin32HandlePropertiesKHR") GetMicromapBuildSizesEXT = auto_cast GetDeviceProcAddr(device, "vkGetMicromapBuildSizesEXT") + GetPartitionedAccelerationStructuresBuildSizesNV = auto_cast GetDeviceProcAddr(device, "vkGetPartitionedAccelerationStructuresBuildSizesNV") GetPastPresentationTimingGOOGLE = auto_cast GetDeviceProcAddr(device, "vkGetPastPresentationTimingGOOGLE") GetPerformanceParameterINTEL = auto_cast GetDeviceProcAddr(device, "vkGetPerformanceParameterINTEL") GetPipelineBinaryDataKHR = auto_cast GetDeviceProcAddr(device, "vkGetPipelineBinaryDataKHR") @@ -3916,6 +4009,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV") GetPhysicalDeviceCooperativeMatrixPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR") GetPhysicalDeviceCooperativeMatrixPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") + GetPhysicalDeviceCooperativeVectorPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeVectorPropertiesNV") GetPhysicalDeviceDisplayPlaneProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") GetPhysicalDeviceDisplayPlanePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR") GetPhysicalDeviceDisplayProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayProperties2KHR") @@ -4032,11 +4126,14 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdBuildAccelerationStructureNV = auto_cast GetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructureNV") CmdBuildAccelerationStructuresIndirectKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructuresIndirectKHR") CmdBuildAccelerationStructuresKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructuresKHR") + CmdBuildClusterAccelerationStructureIndirectNV = auto_cast GetInstanceProcAddr(instance, "vkCmdBuildClusterAccelerationStructureIndirectNV") CmdBuildMicromapsEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBuildMicromapsEXT") + CmdBuildPartitionedAccelerationStructuresNV = auto_cast GetInstanceProcAddr(instance, "vkCmdBuildPartitionedAccelerationStructuresNV") CmdClearAttachments = auto_cast GetInstanceProcAddr(instance, "vkCmdClearAttachments") CmdClearColorImage = auto_cast GetInstanceProcAddr(instance, "vkCmdClearColorImage") CmdClearDepthStencilImage = auto_cast GetInstanceProcAddr(instance, "vkCmdClearDepthStencilImage") CmdControlVideoCodingKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdControlVideoCodingKHR") + CmdConvertCooperativeVectorMatrixNV = auto_cast GetInstanceProcAddr(instance, "vkCmdConvertCooperativeVectorMatrixNV") CmdCopyAccelerationStructureKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyAccelerationStructureKHR") CmdCopyAccelerationStructureNV = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyAccelerationStructureNV") CmdCopyAccelerationStructureToMemoryKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyAccelerationStructureToMemoryKHR") @@ -4070,6 +4167,9 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdDispatch = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatch") CmdDispatchBase = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchBase") CmdDispatchBaseKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchBaseKHR") + CmdDispatchGraphAMDX = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchGraphAMDX") + CmdDispatchGraphIndirectAMDX = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchGraphIndirectAMDX") + CmdDispatchGraphIndirectCountAMDX = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchGraphIndirectCountAMDX") CmdDispatchIndirect = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchIndirect") CmdDraw = auto_cast GetInstanceProcAddr(instance, "vkCmdDraw") CmdDrawClusterHUAWEI = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawClusterHUAWEI") @@ -4108,6 +4208,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdExecuteGeneratedCommandsEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdExecuteGeneratedCommandsEXT") CmdExecuteGeneratedCommandsNV = auto_cast GetInstanceProcAddr(instance, "vkCmdExecuteGeneratedCommandsNV") CmdFillBuffer = auto_cast GetInstanceProcAddr(instance, "vkCmdFillBuffer") + CmdInitializeGraphScratchMemoryAMDX = auto_cast GetInstanceProcAddr(instance, "vkCmdInitializeGraphScratchMemoryAMDX") CmdInsertDebugUtilsLabelEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdInsertDebugUtilsLabelEXT") CmdNextSubpass = auto_cast GetInstanceProcAddr(instance, "vkCmdNextSubpass") CmdNextSubpass2 = auto_cast GetInstanceProcAddr(instance, "vkCmdNextSubpass2") @@ -4259,6 +4360,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdWriteTimestamp2 = auto_cast GetInstanceProcAddr(instance, "vkCmdWriteTimestamp2") CmdWriteTimestamp2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdWriteTimestamp2KHR") CompileDeferredNV = auto_cast GetInstanceProcAddr(instance, "vkCompileDeferredNV") + ConvertCooperativeVectorMatrixNV = auto_cast GetInstanceProcAddr(instance, "vkConvertCooperativeVectorMatrixNV") CopyAccelerationStructureKHR = auto_cast GetInstanceProcAddr(instance, "vkCopyAccelerationStructureKHR") CopyAccelerationStructureToMemoryKHR = auto_cast GetInstanceProcAddr(instance, "vkCopyAccelerationStructureToMemoryKHR") CopyImageToImage = auto_cast GetInstanceProcAddr(instance, "vkCopyImageToImage") @@ -4287,6 +4389,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { CreateDescriptorUpdateTemplate = auto_cast GetInstanceProcAddr(instance, "vkCreateDescriptorUpdateTemplate") CreateDescriptorUpdateTemplateKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateDescriptorUpdateTemplateKHR") CreateEvent = auto_cast GetInstanceProcAddr(instance, "vkCreateEvent") + CreateExecutionGraphPipelinesAMDX = auto_cast GetInstanceProcAddr(instance, "vkCreateExecutionGraphPipelinesAMDX") CreateFence = auto_cast GetInstanceProcAddr(instance, "vkCreateFence") CreateFramebuffer = auto_cast GetInstanceProcAddr(instance, "vkCreateFramebuffer") CreateGraphicsPipelines = auto_cast GetInstanceProcAddr(instance, "vkCreateGraphicsPipelines") @@ -4389,6 +4492,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetBufferOpaqueCaptureDescriptorDataEXT = auto_cast GetInstanceProcAddr(instance, "vkGetBufferOpaqueCaptureDescriptorDataEXT") GetCalibratedTimestampsEXT = auto_cast GetInstanceProcAddr(instance, "vkGetCalibratedTimestampsEXT") GetCalibratedTimestampsKHR = auto_cast GetInstanceProcAddr(instance, "vkGetCalibratedTimestampsKHR") + GetClusterAccelerationStructureBuildSizesNV = auto_cast GetInstanceProcAddr(instance, "vkGetClusterAccelerationStructureBuildSizesNV") GetCudaModuleCacheNV = auto_cast GetInstanceProcAddr(instance, "vkGetCudaModuleCacheNV") GetDeferredOperationMaxConcurrencyKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeferredOperationMaxConcurrencyKHR") GetDeferredOperationResultKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeferredOperationResultKHR") @@ -4425,6 +4529,8 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetDynamicRenderingTilePropertiesQCOM = auto_cast GetInstanceProcAddr(instance, "vkGetDynamicRenderingTilePropertiesQCOM") GetEncodedVideoSessionParametersKHR = auto_cast GetInstanceProcAddr(instance, "vkGetEncodedVideoSessionParametersKHR") GetEventStatus = auto_cast GetInstanceProcAddr(instance, "vkGetEventStatus") + GetExecutionGraphPipelineNodeIndexAMDX = auto_cast GetInstanceProcAddr(instance, "vkGetExecutionGraphPipelineNodeIndexAMDX") + GetExecutionGraphPipelineScratchSizeAMDX = auto_cast GetInstanceProcAddr(instance, "vkGetExecutionGraphPipelineScratchSizeAMDX") GetFenceFdKHR = auto_cast GetInstanceProcAddr(instance, "vkGetFenceFdKHR") GetFenceStatus = auto_cast GetInstanceProcAddr(instance, "vkGetFenceStatus") GetFenceWin32HandleKHR = auto_cast GetInstanceProcAddr(instance, "vkGetFenceWin32HandleKHR") @@ -4451,11 +4557,14 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetMemoryFdKHR = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryFdKHR") GetMemoryFdPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryFdPropertiesKHR") GetMemoryHostPointerPropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryHostPointerPropertiesEXT") + GetMemoryMetalHandleEXT = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryMetalHandleEXT") + GetMemoryMetalHandlePropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryMetalHandlePropertiesEXT") GetMemoryRemoteAddressNV = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryRemoteAddressNV") GetMemoryWin32HandleKHR = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryWin32HandleKHR") GetMemoryWin32HandleNV = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryWin32HandleNV") GetMemoryWin32HandlePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryWin32HandlePropertiesKHR") GetMicromapBuildSizesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetMicromapBuildSizesEXT") + GetPartitionedAccelerationStructuresBuildSizesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPartitionedAccelerationStructuresBuildSizesNV") GetPastPresentationTimingGOOGLE = auto_cast GetInstanceProcAddr(instance, "vkGetPastPresentationTimingGOOGLE") GetPerformanceParameterINTEL = auto_cast GetInstanceProcAddr(instance, "vkGetPerformanceParameterINTEL") GetPipelineBinaryDataKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPipelineBinaryDataKHR") diff --git a/vendor/vulkan/structs.odin b/vendor/vulkan/structs.odin index 611a99ed7..7ceac8c82 100644 --- a/vendor/vulkan/structs.odin +++ b/vendor/vulkan/structs.odin @@ -4809,6 +4809,52 @@ PhysicalDeviceLayeredApiVulkanPropertiesKHR :: struct { properties: PhysicalDeviceProperties2, } +PhysicalDeviceMaintenance8FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maintenance8: b32, +} + +MemoryBarrierAccessFlags3KHR :: struct { + sType: StructureType, + pNext: rawptr, + srcAccessMask3: AccessFlags3KHR, + dstAccessMask3: AccessFlags3KHR, +} + +PhysicalDeviceVideoMaintenance2FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + videoMaintenance2: b32, +} + +VideoDecodeH264InlineSessionParametersInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + pStdSPS: ^VideoH264SequenceParameterSet, + pStdPPS: ^VideoH264PictureParameterSet, +} + +VideoDecodeH265InlineSessionParametersInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + pStdVPS: ^VideoH265VideoParameterSet, + pStdSPS: ^VideoH265SequenceParameterSet, + pStdPPS: ^VideoH265PictureParameterSet, +} + +VideoDecodeAV1InlineSessionParametersInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + pStdSequenceHeader: ^VideoAV1SequenceHeader, +} + +PhysicalDeviceDepthClampZeroOneFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + depthClampZeroOne: b32, +} + DebugReportCallbackCreateInfoEXT :: struct { sType: StructureType, pNext: rawptr, @@ -5635,10 +5681,16 @@ AabbPositionsKHR :: struct { } AccelerationStructureInstanceKHR :: struct { - transform: TransformMatrixKHR, - instanceCustomIndexAndMask: u32, // Most significant byte is mask - instanceShaderBindingTableRecordOffsetAndFlags: u32, // Most significant byte is flags - accelerationStructureReference: u64, + transform: TransformMatrixKHR, + using _: bit_field u32 { + instanceCustomIndex: u32 | 24, + mask: u32 | 8, + }, + using _: bit_field u32 { + instanceShaderBindingTableRecordOffset: u32 | 24, + flags: GeometryInstanceFlagKHR | 8, + }, + accelerationStructureReference: u64, } PhysicalDeviceRepresentativeFragmentTestFeaturesNV :: struct { @@ -6700,11 +6752,17 @@ AccelerationStructureMotionInfoNV :: struct { } AccelerationStructureMatrixMotionInstanceNV :: struct { - transformT0: TransformMatrixKHR, - transformT1: TransformMatrixKHR, - instanceCustomIndexAndMask: u32, // Most significant byte is mask - instanceShaderBindingTableRecordOffsetAndFlags: u32, // Most significant byte is flags - accelerationStructureReference: u64, + transformT0: TransformMatrixKHR, + transformT1: TransformMatrixKHR, + using _: bit_field u32 { + instanceCustomIndex: u32 | 24, + mask: u32 | 8, + }, + using _: bit_field u32 { + instanceShaderBindingTableRecordOffset: u32 | 24, + flags: GeometryInstanceFlagKHR | 8, + }, + accelerationStructureReference: u64, } SRTDataNV :: struct { @@ -6727,11 +6785,17 @@ SRTDataNV :: struct { } AccelerationStructureSRTMotionInstanceNV :: struct { - transformT0: SRTDataNV, - transformT1: SRTDataNV, - instanceCustomIndexAndMask: u32, // Most significant byte is mask - instanceShaderBindingTableRecordOffsetAndFlags: u32, // Most significant byte is flags - accelerationStructureReference: u64, + transformT0: SRTDataNV, + transformT1: SRTDataNV, + using _: bit_field u32 { + instanceCustomIndex: u32 | 24, + mask: u32 | 8, + }, + using _: bit_field u32 { + instanceShaderBindingTableRecordOffset: u32 | 24, + flags: GeometryInstanceFlagKHR | 8, + }, + accelerationStructureReference: u64, } AccelerationStructureMotionInstanceDataNV :: struct #raw_union { @@ -7358,12 +7422,6 @@ DescriptorSetLayoutHostMappingInfoVALVE :: struct { descriptorSize: u32, } -PhysicalDeviceDepthClampZeroOneFeaturesEXT :: struct { - sType: StructureType, - pNext: rawptr, - depthClampZeroOne: b32, -} - PhysicalDeviceNonSeamlessCubeMapFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -7497,6 +7555,43 @@ BindPipelineIndirectCommandNV :: struct { pipelineAddress: DeviceAddress, } +PhysicalDeviceRayTracingLinearSweptSpheresFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + spheres: b32, + linearSweptSpheres: b32, +} + +AccelerationStructureGeometryLinearSweptSpheresDataNV :: struct { + sType: StructureType, + pNext: rawptr, + vertexFormat: Format, + vertexData: DeviceOrHostAddressConstKHR, + vertexStride: DeviceSize, + radiusFormat: Format, + radiusData: DeviceOrHostAddressConstKHR, + radiusStride: DeviceSize, + indexType: IndexType, + indexData: DeviceOrHostAddressConstKHR, + indexStride: DeviceSize, + indexingMode: RayTracingLssIndexingModeNV, + endCapsMode: RayTracingLssPrimitiveEndCapsModeNV, +} + +AccelerationStructureGeometrySpheresDataNV :: struct { + sType: StructureType, + pNext: rawptr, + vertexFormat: Format, + vertexData: DeviceOrHostAddressConstKHR, + vertexStride: DeviceSize, + radiusFormat: Format, + radiusData: DeviceOrHostAddressConstKHR, + radiusStride: DeviceSize, + indexType: IndexType, + indexData: DeviceOrHostAddressConstKHR, + indexStride: DeviceSize, +} + PhysicalDeviceLinearColorAttachmentFeaturesNV :: struct { sType: StructureType, pNext: rawptr, @@ -7859,6 +7954,50 @@ PhysicalDeviceRayTracingInvocationReorderFeaturesNV :: struct { rayTracingInvocationReorder: b32, } +PhysicalDeviceCooperativeVectorPropertiesNV :: struct { + sType: StructureType, + pNext: rawptr, + cooperativeVectorSupportedStages: ShaderStageFlags, + cooperativeVectorTrainingFloat16Accumulation: b32, + cooperativeVectorTrainingFloat32Accumulation: b32, + maxCooperativeVectorComponents: u32, +} + +PhysicalDeviceCooperativeVectorFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + cooperativeVector: b32, + cooperativeVectorTraining: b32, +} + +CooperativeVectorPropertiesNV :: struct { + sType: StructureType, + pNext: rawptr, + inputType: ComponentTypeKHR, + inputInterpretation: ComponentTypeKHR, + matrixInterpretation: ComponentTypeKHR, + biasInterpretation: ComponentTypeKHR, + resultType: ComponentTypeKHR, + transpose: b32, +} + +ConvertCooperativeVectorMatrixInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + srcSize: int, + srcData: DeviceOrHostAddressConstKHR, + pDstSize: ^int, + dstData: DeviceOrHostAddressKHR, + srcComponentType: ComponentTypeKHR, + dstComponentType: ComponentTypeKHR, + numRows: u32, + numColumns: u32, + srcLayout: CooperativeVectorMatrixLayoutNV, + srcStride: int, + dstLayout: CooperativeVectorMatrixLayoutNV, + dstStride: int, +} + PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV :: struct { sType: StructureType, pNext: rawptr, @@ -8135,6 +8274,253 @@ PhysicalDeviceRayTracingValidationFeaturesNV :: struct { rayTracingValidation: b32, } +PhysicalDeviceClusterAccelerationStructureFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + clusterAccelerationStructure: b32, +} + +PhysicalDeviceClusterAccelerationStructurePropertiesNV :: struct { + sType: StructureType, + pNext: rawptr, + maxVerticesPerCluster: u32, + maxTrianglesPerCluster: u32, + clusterScratchByteAlignment: u32, + clusterByteAlignment: u32, + clusterTemplateByteAlignment: u32, + clusterBottomLevelByteAlignment: u32, + clusterTemplateBoundsByteAlignment: u32, + maxClusterGeometryIndex: u32, +} + +ClusterAccelerationStructureClustersBottomLevelInputNV :: struct { + sType: StructureType, + pNext: rawptr, + maxTotalClusterCount: u32, + maxClusterCountPerAccelerationStructure: u32, +} + +ClusterAccelerationStructureTriangleClusterInputNV :: struct { + sType: StructureType, + pNext: rawptr, + vertexFormat: Format, + maxGeometryIndexValue: u32, + maxClusterUniqueGeometryCount: u32, + maxClusterTriangleCount: u32, + maxClusterVertexCount: u32, + maxTotalTriangleCount: u32, + maxTotalVertexCount: u32, + minPositionTruncateBitCount: u32, +} + +ClusterAccelerationStructureMoveObjectsInputNV :: struct { + sType: StructureType, + pNext: rawptr, + type: ClusterAccelerationStructureTypeNV, + noMoveOverlap: b32, + maxMovedBytes: DeviceSize, +} + +ClusterAccelerationStructureOpInputNV :: struct #raw_union { + pClustersBottomLevel: ^ClusterAccelerationStructureClustersBottomLevelInputNV, + pTriangleClusters: [^]ClusterAccelerationStructureTriangleClusterInputNV, + pMoveObjects: [^]ClusterAccelerationStructureMoveObjectsInputNV, +} + +ClusterAccelerationStructureInputInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + maxAccelerationStructureCount: u32, + flags: BuildAccelerationStructureFlagsKHR, + opType: ClusterAccelerationStructureOpTypeNV, + opMode: ClusterAccelerationStructureOpModeNV, + opInput: ClusterAccelerationStructureOpInputNV, +} + +StridedDeviceAddressRegionKHR :: struct { + deviceAddress: DeviceAddress, + stride: DeviceSize, + size: DeviceSize, +} + +ClusterAccelerationStructureCommandsInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + input: ClusterAccelerationStructureInputInfoNV, + dstImplicitData: DeviceAddress, + scratchData: DeviceAddress, + dstAddressesArray: StridedDeviceAddressRegionKHR, + dstSizesArray: StridedDeviceAddressRegionKHR, + srcInfosArray: StridedDeviceAddressRegionKHR, + srcInfosCount: DeviceAddress, + addressResolutionFlags: ClusterAccelerationStructureAddressResolutionFlagsNV, +} + +StridedDeviceAddressNV :: struct { + startAddress: DeviceAddress, + strideInBytes: DeviceSize, +} + +ClusterAccelerationStructureGeometryIndexAndGeometryFlagsNV :: bit_field u32 { + geometryIndex: u32 | 24, + reserved: u32 | 5, + geometryFlags: u32 | 3, +} + +ClusterAccelerationStructureMoveObjectsInfoNV :: struct { + srcAccelerationStructure: DeviceAddress, +} + +ClusterAccelerationStructureBuildClustersBottomLevelInfoNV :: struct { + clusterReferencesCount: u32, + clusterReferencesStride: u32, + clusterReferences: DeviceAddress, +} + +ClusterAccelerationStructureBuildTriangleClusterInfoNV :: struct { + clusterID: u32, + clusterFlags: ClusterAccelerationStructureClusterFlagsNV, + using _: bit_field u32 { + triangleCount: u32 | 9, + vertexCount: u32 | 9, + positionTruncateBitCount: u32 | 6, + indexType: u32 | 4, + opacityMicromapIndexType: u32 | 4, + }, + baseGeometryIndexAndGeometryFlags: ClusterAccelerationStructureGeometryIndexAndGeometryFlagsNV, + indexBufferStride: u16, + vertexBufferStride: u16, + geometryIndexAndFlagsBufferStride: u16, + opacityMicromapIndexBufferStride: u16, + indexBuffer: DeviceAddress, + vertexBuffer: DeviceAddress, + geometryIndexAndFlagsBuffer: DeviceAddress, + opacityMicromapArray: DeviceAddress, + opacityMicromapIndexBuffer: DeviceAddress, +} + +ClusterAccelerationStructureBuildTriangleClusterTemplateInfoNV :: struct { + clusterID: u32, + clusterFlags: ClusterAccelerationStructureClusterFlagsNV, + using _: bit_field u32 { + triangleCount: u32 | 9, + vertexCount: u32 | 9, + positionTruncateBitCount: u32 | 6, + indexType: u32 | 4, + opacityMicromapIndexType: u32 | 4, + }, + baseGeometryIndexAndGeometryFlags: ClusterAccelerationStructureGeometryIndexAndGeometryFlagsNV, + indexBufferStride: u16, + vertexBufferStride: u16, + geometryIndexAndFlagsBufferStride: u16, + opacityMicromapIndexBufferStride: u16, + indexBuffer: DeviceAddress, + vertexBuffer: DeviceAddress, + geometryIndexAndFlagsBuffer: DeviceAddress, + opacityMicromapArray: DeviceAddress, + opacityMicromapIndexBuffer: DeviceAddress, + instantiationBoundingBoxLimit: DeviceAddress, +} + +ClusterAccelerationStructureInstantiateClusterInfoNV :: struct { + clusterIdOffset: u32, + using _: bit_field u32 { + geometryIndexOffset: u32 | 24, + reserved: u32 | 8, + }, + clusterTemplateAddress: DeviceAddress, + vertexBuffer: StridedDeviceAddressNV, +} + +AccelerationStructureBuildSizesInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + accelerationStructureSize: DeviceSize, + updateScratchSize: DeviceSize, + buildScratchSize: DeviceSize, +} + +RayTracingPipelineClusterAccelerationStructureCreateInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + allowClusterAccelerationStructure: b32, +} + +PhysicalDevicePartitionedAccelerationStructureFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + partitionedAccelerationStructure: b32, +} + +PhysicalDevicePartitionedAccelerationStructurePropertiesNV :: struct { + sType: StructureType, + pNext: rawptr, + maxPartitionCount: u32, +} + +PartitionedAccelerationStructureFlagsNV :: struct { + sType: StructureType, + pNext: rawptr, + enablePartitionTranslation: b32, +} + +BuildPartitionedAccelerationStructureIndirectCommandNV :: struct { + opType: PartitionedAccelerationStructureOpTypeNV, + argCount: u32, + argData: StridedDeviceAddressNV, +} + +PartitionedAccelerationStructureWriteInstanceDataNV :: struct { + transform: TransformMatrixKHR, + explicitAABB: [6]f32, + instanceID: u32, + instanceMask: u32, + instanceContributionToHitGroupIndex: u32, + instanceFlags: PartitionedAccelerationStructureInstanceFlagsNV, + instanceIndex: u32, + partitionIndex: u32, + accelerationStructure: DeviceAddress, +} + +PartitionedAccelerationStructureUpdateInstanceDataNV :: struct { + instanceIndex: u32, + instanceContributionToHitGroupIndex: u32, + accelerationStructure: DeviceAddress, +} + +PartitionedAccelerationStructureWritePartitionTranslationDataNV :: struct { + partitionIndex: u32, + partitionTranslation: [3]f32, +} + +WriteDescriptorSetPartitionedAccelerationStructureNV :: struct { + sType: StructureType, + pNext: rawptr, + accelerationStructureCount: u32, + pAccelerationStructures: [^]DeviceAddress, +} + +PartitionedAccelerationStructureInstancesInputNV :: struct { + sType: StructureType, + pNext: rawptr, + flags: BuildAccelerationStructureFlagsKHR, + instanceCount: u32, + maxInstancePerPartitionCount: u32, + partitionCount: u32, + maxInstanceInGlobalPartitionCount: u32, +} + +BuildPartitionedAccelerationStructureInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + input: PartitionedAccelerationStructureInstancesInputNV, + srcAccelerationStructureData: DeviceAddress, + dstAccelerationStructureData: DeviceAddress, + scratchData: DeviceAddress, + srcInfos: DeviceAddress, + srcInfosCount: DeviceAddress, +} + PhysicalDeviceDeviceGeneratedCommandsFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -8387,12 +8773,31 @@ PhysicalDeviceCooperativeMatrix2PropertiesNV :: struct { cooperativeMatrixWorkgroupScopeReservedSharedMemory: u32, } +PhysicalDevicePipelineOpacityMicromapFeaturesARM :: struct { + sType: StructureType, + pNext: rawptr, + pipelineOpacityMicromap: b32, +} + PhysicalDeviceVertexAttributeRobustnessFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, vertexAttributeRobustness: b32, } +SetPresentConfigNV :: struct { + sType: StructureType, + pNext: rawptr, + numFramesPerBatch: u32, + presentConfigFeedback: u32, +} + +PhysicalDevicePresentMeteringFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + presentMetering: b32, +} + AccelerationStructureBuildRangeInfoKHR :: struct { primitiveCount: u32, primitiveOffset: u32, @@ -8531,14 +8936,6 @@ CopyAccelerationStructureInfoKHR :: struct { mode: CopyAccelerationStructureModeKHR, } -AccelerationStructureBuildSizesInfoKHR :: struct { - sType: StructureType, - pNext: rawptr, - accelerationStructureSize: DeviceSize, - updateScratchSize: DeviceSize, - buildScratchSize: DeviceSize, -} - RayTracingShaderGroupCreateInfoKHR :: struct { sType: StructureType, pNext: rawptr, @@ -8597,12 +8994,6 @@ PhysicalDeviceRayTracingPipelinePropertiesKHR :: struct { maxRayHitAttributeSize: u32, } -StridedDeviceAddressRegionKHR :: struct { - deviceAddress: DeviceAddress, - stride: DeviceSize, - size: DeviceSize, -} - TraceRaysIndirectCommandKHR :: struct { width: u32, height: u32, @@ -8904,6 +9295,26 @@ ImportMetalSharedEventInfoEXT :: struct { mtlSharedEvent: MTLSharedEvent_id, } +ImportMemoryMetalHandleInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + handleType: ExternalMemoryHandleTypeFlags, + handle: rawptr, +} + +MemoryMetalHandlePropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + memoryTypeBits: u32, +} + +MemoryGetMetalHandleInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + memory: DeviceMemory, + handleType: ExternalMemoryHandleTypeFlags, +} + MacOSSurfaceCreateInfoMVK :: struct { sType: StructureType, pNext: rawptr, @@ -8942,8 +9353,135 @@ XcbSurfaceCreateInfoKHR :: struct { window: xcb_window_t, } -VideoAV1ColorConfigFlags :: struct { - bitfield: u32, +PhysicalDevicePortabilitySubsetFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + constantAlphaColorBlendFactors: b32, + events: b32, + imageViewFormatReinterpretation: b32, + imageViewFormatSwizzle: b32, + imageView2DOn3DImage: b32, + multisampleArrayImage: b32, + mutableComparisonSamplers: b32, + pointPolygons: b32, + samplerMipLodBias: b32, + separateStencilMaskRef: b32, + shaderSampleRateInterpolationFunctions: b32, + tessellationIsolines: b32, + tessellationPointMode: b32, + triangleFans: b32, + vertexAttributeAccessBeyondStride: b32, +} + +PhysicalDevicePortabilitySubsetPropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + minVertexInputBindingStrideAlignment: u32, +} + +PhysicalDeviceShaderEnqueueFeaturesAMDX :: struct { + sType: StructureType, + pNext: rawptr, + shaderEnqueue: b32, + shaderMeshEnqueue: b32, +} + +PhysicalDeviceShaderEnqueuePropertiesAMDX :: struct { + sType: StructureType, + pNext: rawptr, + maxExecutionGraphDepth: u32, + maxExecutionGraphShaderOutputNodes: u32, + maxExecutionGraphShaderPayloadSize: u32, + maxExecutionGraphShaderPayloadCount: u32, + executionGraphDispatchAddressAlignment: u32, + maxExecutionGraphWorkgroupCount: [3]u32, + maxExecutionGraphWorkgroups: u32, +} + +ExecutionGraphPipelineScratchSizeAMDX :: struct { + sType: StructureType, + pNext: rawptr, + minSize: DeviceSize, + maxSize: DeviceSize, + sizeGranularity: DeviceSize, +} + +ExecutionGraphPipelineCreateInfoAMDX :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineCreateFlags, + stageCount: u32, + pStages: [^]PipelineShaderStageCreateInfo, + pLibraryInfo: ^PipelineLibraryCreateInfoKHR, + layout: PipelineLayout, + basePipelineHandle: Pipeline, + basePipelineIndex: i32, +} + +DeviceOrHostAddressConstAMDX :: struct #raw_union { + deviceAddress: DeviceAddress, + hostAddress: rawptr, +} + +DispatchGraphInfoAMDX :: struct { + nodeIndex: u32, + payloadCount: u32, + payloads: DeviceOrHostAddressConstAMDX, + payloadStride: u64, +} + +DispatchGraphCountInfoAMDX :: struct { + count: u32, + infos: DeviceOrHostAddressConstAMDX, + stride: u64, +} + +PipelineShaderStageNodeCreateInfoAMDX :: struct { + sType: StructureType, + pNext: rawptr, + pName: cstring, + index: u32, +} + +PhysicalDeviceDisplacementMicromapFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + displacementMicromap: b32, +} + +PhysicalDeviceDisplacementMicromapPropertiesNV :: struct { + sType: StructureType, + pNext: rawptr, + maxDisplacementMicromapSubdivisionLevel: u32, +} + +AccelerationStructureTrianglesDisplacementMicromapNV :: struct { + sType: StructureType, + pNext: rawptr, + displacementBiasAndScaleFormat: Format, + displacementVectorFormat: Format, + displacementBiasAndScaleBuffer: DeviceOrHostAddressConstKHR, + displacementBiasAndScaleStride: DeviceSize, + displacementVectorBuffer: DeviceOrHostAddressConstKHR, + displacementVectorStride: DeviceSize, + displacedMicromapPrimitiveFlags: DeviceOrHostAddressConstKHR, + displacedMicromapPrimitiveFlagsStride: DeviceSize, + indexType: IndexType, + indexBuffer: DeviceOrHostAddressConstKHR, + indexStride: DeviceSize, + baseTriangle: u32, + usageCountsCount: u32, + pUsageCounts: [^]MicromapUsageEXT, + ppUsageCounts: ^[^]MicromapUsageEXT, + micromap: MicromapEXT, +} + +VideoAV1ColorConfigFlags :: distinct bit_set[VideoAV1ColorConfigFlag; u32] +VideoAV1ColorConfigFlag :: enum u32 { + mono_chrome, + color_range, + separate_uv_delta_q, + color_description_present_flag, } VideoAV1ColorConfig :: struct { @@ -8958,8 +9496,9 @@ VideoAV1ColorConfig :: struct { chroma_sample_position: VideoAV1ChromaSamplePosition, } -VideoAV1TimingInfoFlags :: struct { - bitfield: u32, +VideoAV1TimingInfoFlags :: distinct bit_set[VideoAV1TimingInfoFlag; u32] +VideoAV1TimingInfoFlag :: enum u32 { + equal_picture_interval, } VideoAV1TimingInfo :: struct { @@ -8969,8 +9508,10 @@ VideoAV1TimingInfo :: struct { num_ticks_per_picture_minus_1: u32, } -VideoAV1LoopFilterFlags :: struct { - bitfield: u32, +VideoAV1LoopFilterFlags :: distinct bit_set[VideoAV1LoopFilterFlag; u32] +VideoAV1LoopFilterFlag :: enum u32 { + loop_filter_delta_enabled, + loop_filter_delta_update, } VideoAV1LoopFilter :: struct { @@ -8983,8 +9524,10 @@ VideoAV1LoopFilter :: struct { loop_filter_mode_deltas: [VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS]i8, } -VideoAV1QuantizationFlags :: struct { - bitfield: u32, +VideoAV1QuantizationFlags :: distinct bit_set[VideoAV1QuantizationFlag; u32] +VideoAV1QuantizationFlag :: enum u32 { + using_qmatrix, + diff_uv_delta, } VideoAV1Quantization :: struct { @@ -9005,8 +9548,9 @@ VideoAV1Segmentation :: struct { FeatureData: [VIDEO_AV1_MAX_SEGMENTS][VIDEO_AV1_SEG_LVL_MAX]i16, } -VideoAV1TileInfoFlags :: struct { - bitfield: u32, +VideoAV1TileInfoFlags :: distinct bit_set[VideoAV1TileInfoFlag; u32] +VideoAV1TileInfoFlag :: enum u32 { + uniform_tile_spacing_flag, } VideoAV1TileInfo :: struct { @@ -9041,8 +9585,12 @@ VideoAV1GlobalMotion :: struct { gm_params: [VIDEO_AV1_NUM_REF_FRAMES][VIDEO_AV1_GLOBAL_MOTION_PARAMS]i32, } -VideoAV1FilmGrainFlags :: struct { - bitfield: u32, +VideoAV1FilmGrainFlags :: distinct bit_set[VideoAV1FilmGrainFlag; u32] +VideoAV1FilmGrainFlag :: enum u32 { + chroma_scaling_from_luma, + overlap_flag, + clip_to_restricted_range, + update_grain, } VideoAV1FilmGrain :: struct { @@ -9073,8 +9621,27 @@ VideoAV1FilmGrain :: struct { cr_offset: u16, } -VideoAV1SequenceHeaderFlags :: struct { - bitfield: u32, +VideoAV1SequenceHeaderFlags :: distinct bit_set[VideoAV1SequenceHeaderFlag; u32] +VideoAV1SequenceHeaderFlag :: enum u32 { + still_picture, + reduced_still_picture_header, + use_128x128_superblock, + enable_filter_intra, + enable_intra_edge_filter, + enable_interintra_compound, + enable_masked_compound, + enable_warped_motion, + enable_dual_filter, + enable_order_hint, + enable_jnt_comp, + enable_ref_frame_mvs, + frame_id_numbers_present_flag, + enable_superres, + enable_cdef, + enable_restoration, + film_grain_params_present, + timing_info_present_flag, + initial_display_delay_present_flag, } VideoAV1SequenceHeader :: struct { @@ -9094,8 +9661,37 @@ VideoAV1SequenceHeader :: struct { pTimingInfo: ^VideoAV1TimingInfo, } -VideoDecodeAV1PictureInfoFlags :: struct { - bitfield: u32, +VideoDecodeAV1PictureInfoFlags :: distinct bit_set[VideoDecodeAV1PictureInfoFlag; u32] +VideoDecodeAV1PictureInfoFlag :: enum u32 { + error_resilient_mode, + disable_cdf_update, + use_superres, + render_and_frame_size_different, + allow_screen_content_tools, + is_filter_switchable, + force_integer_mv, + frame_size_override_flag, + buffer_removal_time_present_flag, + allow_intrabc, + frame_refs_short_signaling, + allow_high_precision_mv, + is_motion_mode_switchable, + use_ref_frame_mvs, + disable_frame_end_update_cdf, + allow_warped_motion, + reduced_tx_set, + reference_select, + skip_mode_present, + delta_q_present, + delta_lf_present, + delta_lf_multi, + segmentation_enabled, + segmentation_update_map, + segmentation_temporal_update, + segmentation_update_data, + UsesLr, + usesChromaLr, + apply_grain, } VideoDecodeAV1PictureInfo :: struct { @@ -9125,8 +9721,10 @@ VideoDecodeAV1PictureInfo :: struct { pFilmGrain: ^VideoAV1FilmGrain, } -VideoDecodeAV1ReferenceInfoFlags :: struct { - bitfield: u32, +VideoDecodeAV1ReferenceInfoFlags :: distinct bit_set[VideoDecodeAV1ReferenceInfoFlag; u32] +VideoDecodeAV1ReferenceInfoFlag :: enum u32 { + disable_frame_end_update_cdf, + segmentation_enabled, } VideoDecodeAV1ReferenceInfo :: struct { @@ -9150,8 +9748,11 @@ VideoEncodeAV1ExtensionHeader :: struct { spatial_id: u8, } -VideoEncodeAV1OperatingPointInfoFlags :: struct { - bitfield: u32, +VideoEncodeAV1OperatingPointInfoFlags :: distinct bit_set[VideoEncodeAV1OperatingPointInfoFlag; u32] +VideoEncodeAV1OperatingPointInfoFlag :: enum u32 { + decoder_model_present_for_this_op, + low_delay_mode_flag, + initial_display_delay_present_for_this_op, } VideoEncodeAV1OperatingPointInfo :: struct { @@ -9164,8 +9765,37 @@ VideoEncodeAV1OperatingPointInfo :: struct { initial_display_delay_minus_1: u8, } -VideoEncodeAV1PictureInfoFlags :: struct { - bitfield: u32, +VideoEncodeAV1PictureInfoFlags :: distinct bit_set[VideoEncodeAV1PictureInfoFlag; u32] +VideoEncodeAV1PictureInfoFlag :: enum u32 { + error_resilient_mode, + disable_cdf_update, + use_superres, + render_and_frame_size_different, + allow_screen_content_tools, + is_filter_switchable, + force_integer_mv, + frame_size_override_flag, + buffer_removal_time_present_flag, + allow_intrabc, + frame_refs_short_signaling, + allow_high_precision_mv, + is_motion_mode_switchable, + use_ref_frame_mvs, + disable_frame_end_update_cdf, + allow_warped_motion, + reduced_tx_set, + skip_mode_present, + delta_q_present, + delta_lf_present, + delta_lf_multi, + segmentation_enabled, + segmentation_update_map, + segmentation_temporal_update, + segmentation_update_data, + UsesLr, + usesChromaLr, + show_frame, + showable_frame, } VideoEncodeAV1PictureInfo :: struct { @@ -9198,8 +9828,10 @@ VideoEncodeAV1PictureInfo :: struct { pBufferRemovalTimes: [^]u32, } -VideoEncodeAV1ReferenceInfoFlags :: struct { - bitfield: u32, +VideoEncodeAV1ReferenceInfoFlags :: distinct bit_set[VideoEncodeAV1ReferenceInfoFlag; u32] +VideoEncodeAV1ReferenceInfoFlag :: enum u32 { + disable_frame_end_update_cdf, + segmentation_enabled, } VideoEncodeAV1ReferenceInfo :: struct { @@ -9211,8 +9843,20 @@ VideoEncodeAV1ReferenceInfo :: struct { pExtensionHeader: ^VideoEncodeAV1ExtensionHeader, } -VideoH264SpsVuiFlags :: struct { - bitfield: u32, +VideoH264SpsVuiFlags :: distinct bit_set[VideoH264SpsVuiFlag; u32] +VideoH264SpsVuiFlag :: enum u32 { + aspect_ratio_info_present_flag, + overscan_info_present_flag, + overscan_appropriate_flag, + video_signal_type_present_flag, + video_full_range_flag, + color_description_present_flag, + chroma_loc_info_present_flag, + timing_info_present_flag, + fixed_frame_rate_flag, + bitstream_restriction_flag, + nal_hrd_parameters_present_flag, + vcl_hrd_parameters_present_flag, } VideoH264HrdParameters :: struct { @@ -9248,8 +9892,24 @@ VideoH264SequenceParameterSetVui :: struct { pHrdParameters: [^]VideoH264HrdParameters, } -VideoH264SpsFlags :: struct { - bitfield: u32, +VideoH264SpsFlags :: distinct bit_set[VideoH264SpsFlag; u32] +VideoH264SpsFlag :: enum u32 { + constraint_set0_flag, + constraint_set1_flag, + constraint_set2_flag, + constraint_set3_flag, + constraint_set4_flag, + constraint_set5_flag, + direct_8x8_inference_flag, + mb_adaptive_frame_field_flag, + frame_mbs_only_flag, + delta_pic_order_always_zero_flag, + separate_colour_plane_flag, + gaps_in_frame_num_value_allowed_flag, + qpprime_y_zero_transform_bypass_flag, + frame_cropping_flag, + seq_scaling_matrix_present_flag, + vui_parameters_present_flag, } VideoH264ScalingLists :: struct { @@ -9287,8 +9947,16 @@ VideoH264SequenceParameterSet :: struct { pSequenceParameterSetVui: ^VideoH264SequenceParameterSetVui, } -VideoH264PpsFlags :: struct { - bitfield: u32, +VideoH264PpsFlags :: distinct bit_set[VideoH264PpsFlag; u32] +VideoH264PpsFlag :: enum u32 { + transform_8x8_mode_flag, + redundant_pic_cnt_present_flag, + constrained_intra_pred_flag, + deblocking_filter_control_present_flag, + weighted_pred_flag, + bottom_field_pic_order_in_frame_present_flag, + entropy_coding_mode_flag, + pic_scaling_matrix_present_flag, } VideoH264PictureParameterSet :: struct { @@ -9305,8 +9973,14 @@ VideoH264PictureParameterSet :: struct { pScalingLists: [^]VideoH264ScalingLists, } -VideoDecodeH264PictureInfoFlags :: struct { - bitfield: u32, +VideoDecodeH264PictureInfoFlags :: distinct bit_set[VideoDecodeH264PictureInfoFlag; u32] +VideoDecodeH264PictureInfoFlag :: enum u32 { + field_pic_flag, + is_intra, + IdrPicFlag, + bottom_field_flag, + is_reference, + complementary_field_pair, } VideoDecodeH264PictureInfo :: struct { @@ -9320,8 +9994,12 @@ VideoDecodeH264PictureInfo :: struct { PicOrderCnt: [VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE]i32, } -VideoDecodeH264ReferenceInfoFlags :: struct { - bitfield: u32, +VideoDecodeH264ReferenceInfoFlags :: distinct bit_set[VideoDecodeH264ReferenceInfoFlag; u32] +VideoDecodeH264ReferenceInfoFlag :: enum u32 { + top_field_flag, + bottom_field_flag, + used_for_long_term_reference, + is_non_existing, } VideoDecodeH264ReferenceInfo :: struct { @@ -9352,20 +10030,30 @@ VideoEncodeH264WeightTable :: struct { chroma_offset_l1: [VIDEO_H264_MAX_NUM_LIST_REF][VIDEO_H264_MAX_CHROMA_PLANES]i8, } -VideoEncodeH264SliceHeaderFlags :: struct { - bitfield: u32, +VideoEncodeH264SliceHeaderFlags :: distinct bit_set[VideoEncodeH264SliceHeaderFlag; u32] +VideoEncodeH264SliceHeaderFlag :: enum u32 { + direct_spatial_mv_pred_flag, + num_ref_idx_active_override_flag, } -VideoEncodeH264PictureInfoFlags :: struct { - bitfield: u32, +VideoEncodeH264PictureInfoFlags :: distinct bit_set[VideoEncodeH264PictureInfoFlag; u32] +VideoEncodeH264PictureInfoFlag :: enum u32 { + IdrPicFlag, + is_reference, + no_output_of_prior_pics_flag, + long_term_reference_flag, + adaptive_ref_pic_marking_mode_flag, } -VideoEncodeH264ReferenceInfoFlags :: struct { - bitfield: u32, +VideoEncodeH264ReferenceInfoFlags :: distinct bit_set[VideoEncodeH264ReferenceInfoFlag; u32] +VideoEncodeH264ReferenceInfoFlag :: enum u32 { + used_for_long_term_reference, } -VideoEncodeH264ReferenceListsInfoFlags :: struct { - bitfield: u32, +VideoEncodeH264ReferenceListsInfoFlags :: distinct bit_set[VideoEncodeH264ReferenceListsInfoFlag; u32] +VideoEncodeH264ReferenceListsInfoFlag :: enum u32 { + ref_pic_list_modification_flag_l0, + ref_pic_list_modification_flag_l1, } VideoEncodeH264RefListModEntry :: struct { @@ -9447,8 +10135,14 @@ VideoH265SubLayerHrdParameters :: struct { cbr_flag: u32, } -VideoH265HrdFlags :: struct { - bitfield: u32, +VideoH265HrdFlags :: bit_field u32 { + nal_hrd_parameters_present_flag: u32 | 1, + vcl_hrd_parameters_present_flag: u32 | 1, + sub_pic_hrd_params_present_flag: u32 | 1, + sub_pic_cpb_params_in_pic_timing_sei_flag: u32 | 1, + fixed_pic_rate_general_flag: u32 | 8, + fixed_pic_rate_within_cvs_flag: u32 | 8, + low_delay_hrd_flag: u32 | 8, } VideoH265HrdParameters :: struct { @@ -9469,12 +10163,21 @@ VideoH265HrdParameters :: struct { pSubLayerHrdParametersVcl: ^VideoH265SubLayerHrdParameters, } -VideoH265VpsFlags :: struct { - bitfield: u32, +VideoH265VpsFlags :: distinct bit_set[VideoH265VpsFlag; u32] +VideoH265VpsFlag :: enum u32 { + vps_temporal_id_nesting_flag, + vps_sub_layer_ordering_info_present_flag, + vps_timing_info_present_flag, + vps_poc_proportional_to_timing_flag, } -VideoH265ProfileTierLevelFlags :: struct { - bitfield: u32, +VideoH265ProfileTierLevelFlags :: distinct bit_set[VideoH265ProfileTierLevelFlag; u32] +VideoH265ProfileTierLevelFlag :: enum u32 { + general_tier_flag, + general_progressive_source_flag, + general_interlaced_source_flag, + general_non_packed_constraint_flag, + general_frame_only_constraint_flag, } VideoH265ProfileTierLevel :: struct { @@ -9507,8 +10210,26 @@ VideoH265ScalingLists :: struct { ScalingListDCCoef32x32: [VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS]u8, } -VideoH265SpsVuiFlags :: struct { - bitfield: u32, +VideoH265SpsVuiFlags :: distinct bit_set[VideoH265SpsVuiFlag; u32] +VideoH265SpsVuiFlag :: enum u32 { + aspect_ratio_info_present_flag, + overscan_info_present_flag, + overscan_appropriate_flag, + video_signal_type_present_flag, + video_full_range_flag, + colour_description_present_flag, + chroma_loc_info_present_flag, + neutral_chroma_indication_flag, + field_seq_flag, + frame_field_info_present_flag, + default_display_window_flag, + vui_timing_info_present_flag, + vui_poc_proportional_to_timing_flag, + vui_hrd_parameters_present_flag, + bitstream_restriction_flag, + tiles_fixed_structure_flag, + motion_vectors_over_pic_boundaries_flag, + restricted_ref_pic_lists_flag, } VideoH265SequenceParameterSetVui :: struct { @@ -9544,12 +10265,44 @@ VideoH265PredictorPaletteEntries :: struct { PredictorPaletteEntries: [VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE][VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE]u16, } -VideoH265SpsFlags :: struct { - bitfield: u32, +VideoH265SpsFlags :: distinct bit_set[VideoH265SpsFlag; u32] +VideoH265SpsFlag :: enum u32 { + sps_temporal_id_nesting_flag, + separate_colour_plane_flag, + conformance_window_flag, + sps_sub_layer_ordering_info_present_flag, + scaling_list_enabled_flag, + sps_scaling_list_data_present_flag, + amp_enabled_flag, + sample_adaptive_offset_enabled_flag, + pcm_enabled_flag, + pcm_loop_filter_disabled_flag, + long_term_ref_pics_present_flag, + sps_temporal_mvp_enabled_flag, + strong_intra_smoothing_enabled_flag, + vui_parameters_present_flag, + sps_extension_present_flag, + sps_range_extension_flag, + transform_skip_rotation_enabled_flag, + transform_skip_context_enabled_flag, + implicit_rdpcm_enabled_flag, + explicit_rdpcm_enabled_flag, + extended_precision_processing_flag, + intra_smoothing_disabled_flag, + high_precision_offsets_enabled_flag, + persistent_rice_adaptation_enabled_flag, + cabac_bypass_alignment_enabled_flag, + sps_scc_extension_flag, + sps_curr_pic_ref_enabled_flag, + palette_mode_enabled_flag, + sps_palette_predictor_initializers_present_flag, + intra_boundary_filtering_disabled_flag, } -VideoH265ShortTermRefPicSetFlags :: struct { - bitfield: u32, +VideoH265ShortTermRefPicSetFlags :: distinct bit_set[VideoH265ShortTermRefPicSetFlag; u32] +VideoH265ShortTermRefPicSetFlag :: enum u32 { + inter_ref_pic_set_prediction_flag, + delta_rps_sign, } VideoH265ShortTermRefPicSet :: struct { @@ -9616,8 +10369,39 @@ VideoH265SequenceParameterSet :: struct { pPredictorPaletteEntries: [^]VideoH265PredictorPaletteEntries, } -VideoH265PpsFlags :: struct { - bitfield: u32, +VideoH265PpsFlags :: distinct bit_set[VideoH265PpsFlag; u32] +VideoH265PpsFlag :: enum u32 { + dependent_slice_segments_enabled_flag, + output_flag_present_flag, + sign_data_hiding_enabled_flag, + cabac_init_present_flag, + constrained_intra_pred_flag, + transform_skip_enabled_flag, + cu_qp_delta_enabled_flag, + pps_slice_chroma_qp_offsets_present_flag, + weighted_pred_flag, + weighted_bipred_flag, + transquant_bypass_enabled_flag, + tiles_enabled_flag, + entropy_coding_sync_enabled_flag, + uniform_spacing_flag, + loop_filter_across_tiles_enabled_flag, + pps_loop_filter_across_slices_enabled_flag, + deblocking_filter_control_present_flag, + deblocking_filter_override_enabled_flag, + pps_deblocking_filter_disabled_flag, + pps_scaling_list_data_present_flag, + lists_modification_present_flag, + slice_segment_header_extension_present_flag, + pps_extension_present_flag, + cross_component_prediction_enabled_flag, + chroma_qp_offset_list_enabled_flag, + pps_curr_pic_ref_enabled_flag, + residual_adaptive_colour_transform_enabled_flag, + pps_slice_act_qp_offsets_present_flag, + pps_palette_predictor_initializers_present_flag, + monochrome_palette_flag, + pps_range_extension_flag, } VideoH265PictureParameterSet :: struct { @@ -9659,8 +10443,12 @@ VideoH265PictureParameterSet :: struct { pPredictorPaletteEntries: [^]VideoH265PredictorPaletteEntries, } -VideoDecodeH265PictureInfoFlags :: struct { - bitfield: u32, +VideoDecodeH265PictureInfoFlags :: distinct bit_set[VideoDecodeH265PictureInfoFlag; u32] +VideoDecodeH265PictureInfoFlag :: enum u32 { + IrapPicFlag, + IdrPicFlag, + IsReference, + short_term_ref_pic_set_sps_flag, } VideoDecodeH265PictureInfo :: struct { @@ -9677,8 +10465,10 @@ VideoDecodeH265PictureInfo :: struct { RefPicSetLtCurr: [VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE]u8, } -VideoDecodeH265ReferenceInfoFlags :: struct { - bitfield: u32, +VideoDecodeH265ReferenceInfoFlags :: distinct bit_set[VideoDecodeH265ReferenceInfoFlag; u32] +VideoDecodeH265ReferenceInfoFlag :: enum u32 { + used_for_long_term_reference, + unused_for_reference, } VideoDecodeH265ReferenceInfo :: struct { @@ -9707,8 +10497,20 @@ VideoEncodeH265WeightTable :: struct { delta_chroma_offset_l1: [VIDEO_H265_MAX_NUM_LIST_REF][VIDEO_H265_MAX_CHROMA_PLANES]i8, } -VideoEncodeH265SliceSegmentHeaderFlags :: struct { - bitfield: u32, +VideoEncodeH265SliceSegmentHeaderFlags :: distinct bit_set[VideoEncodeH265SliceSegmentHeaderFlag; u32] +VideoEncodeH265SliceSegmentHeaderFlag :: enum u32 { + first_slice_segment_in_pic_flag, + dependent_slice_segment_flag, + slice_sao_luma_flag, + slice_sao_chroma_flag, + num_ref_idx_active_override_flag, + mvd_l1_zero_flag, + cabac_init_flag, + cu_chroma_qp_offset_enabled_flag, + deblocking_filter_override_flag, + slice_deblocking_filter_disabled_flag, + collocated_from_l0_flag, + slice_loop_filter_across_slices_enabled_flag, } VideoEncodeH265SliceSegmentHeader :: struct { @@ -9729,8 +10531,10 @@ VideoEncodeH265SliceSegmentHeader :: struct { pWeightTable: [^]VideoEncodeH265WeightTable, } -VideoEncodeH265ReferenceListsInfoFlags :: struct { - bitfield: u32, +VideoEncodeH265ReferenceListsInfoFlags :: distinct bit_set[VideoEncodeH265ReferenceListsInfoFlag; u32] +VideoEncodeH265ReferenceListsInfoFlag :: enum u32 { + ref_pic_list_modification_flag_l0, + ref_pic_list_modification_flag_l1, } VideoEncodeH265ReferenceListsInfo :: struct { @@ -9743,8 +10547,17 @@ VideoEncodeH265ReferenceListsInfo :: struct { list_entry_l1: [VIDEO_H265_MAX_NUM_LIST_REF]u8, } -VideoEncodeH265PictureInfoFlags :: struct { - bitfield: u32, +VideoEncodeH265PictureInfoFlags :: distinct bit_set[VideoEncodeH265PictureInfoFlag; u32] +VideoEncodeH265PictureInfoFlag :: enum u32 { + is_reference, + IrapPicFlag, + used_for_long_term_reference, + discardable_flag, + cross_layer_bla_flag, + pic_output_flag, + no_output_of_prior_pics_flag, + short_term_ref_pic_set_sps_flag, + slice_temporal_mvp_enabled_flag, } VideoEncodeH265LongTermRefPics :: struct { @@ -9772,8 +10585,10 @@ VideoEncodeH265PictureInfo :: struct { pLongTermRefPics: [^]VideoEncodeH265LongTermRefPics, } -VideoEncodeH265ReferenceInfoFlags :: struct { - bitfield: u32, +VideoEncodeH265ReferenceInfoFlags :: distinct bit_set[VideoEncodeH265ReferenceInfoFlag; u32] +VideoEncodeH265ReferenceInfoFlag :: enum u32 { + used_for_long_term_reference, + unused_for_reference, } VideoEncodeH265ReferenceInfo :: struct { @@ -10016,6 +10831,8 @@ BindDescriptorSetsInfoKHR :: BindDescriptorSet PushConstantsInfoKHR :: PushConstantsInfo PushDescriptorSetInfoKHR :: PushDescriptorSetInfo PushDescriptorSetWithTemplateInfoKHR :: PushDescriptorSetWithTemplateInfo +AccessFlags3KHR :: Flags64 +AccessFlag3KHR :: Flags64 PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT :: PhysicalDeviceTextureCompressionASTCHDRFeatures PipelineRobustnessBufferBehaviorEXT :: PipelineRobustnessBufferBehavior PipelineRobustnessImageBehaviorEXT :: PipelineRobustnessImageBehavior @@ -10114,6 +10931,7 @@ PhysicalDeviceGlobalPriorityQueryFeaturesEXT :: PhysicalDeviceGlo QueueFamilyGlobalPriorityPropertiesEXT :: QueueFamilyGlobalPriorityProperties PhysicalDeviceSchedulingControlsFlagsARM :: Flags64 PhysicalDeviceSchedulingControlsFlagARM :: Flags64 +PhysicalDeviceDepthClampZeroOneFeaturesEXT :: PhysicalDeviceDepthClampZeroOneFeaturesKHR MemoryDecompressionMethodFlagNV :: Flags64 MemoryDecompressionMethodFlagsNV :: Flags64 PhysicalDevicePipelineProtectedAccessFeaturesEXT :: PhysicalDevicePipelineProtectedAccessFeatures diff --git a/vendor/wgpu/.gitignore b/vendor/wgpu/.gitignore index 330d70755..80c337a4d 100644 --- a/vendor/wgpu/.gitignore +++ b/vendor/wgpu/.gitignore @@ -1,5 +1,5 @@ lib/* -!lib/.gitkeep +!lib/wgpu-windows-x86_64-msvc-release example/web/triangle.wasm example/web/wgpu.js example/web/runtime.js diff --git a/vendor/wgpu/README.md b/vendor/wgpu/doc.odin similarity index 68% rename from vendor/wgpu/README.md rename to vendor/wgpu/doc.odin index 1022e8541..a538c53c1 100644 --- a/vendor/wgpu/README.md +++ b/vendor/wgpu/doc.odin @@ -1,25 +1,26 @@ -# WGPU - +/* A cross-platform (and WASM) GPU API. WASM support is achieved by providing wrappers around the browser native WebGPU API -that are called instead of the [wgpu-native](https://github.com/gfx-rs/wgpu-native) library, +that are called instead of the [[wgpu-native; https://github.com/gfx-rs/wgpu-native]] library, the wgpu-native library provides support for all other targets. -Have a look at the `example/` directory for the rendering of a basic triangle. +**Examples** -## Getting the wgpu-native libraries +You can find a number of examples on [[Odin's official examples repository; https://github.com/odin-lang/examples/tree/master/wgpu]]. + +**Getting the wgpu-native libraries** For native support (not the browser), some libraries are required. Fortunately this is -extremely easy, just download them from the [releases on GitHub](https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1), -the bindings are for v22.1.0.1 at the moment. +extremely easy, just download them from the [[releases on GitHub; https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2]]. +the bindings are for v24.0.0.2 at the moment. These are expected in the `lib` folder under the same name as they are released (just unzipped). By default it will look for a static release version (`wgpu-OS-ARCH-release.a|lib`), you can set `-define:WGPU_DEBUG=true` for it to look for a debug version, and use `-define:WGPU_SHARED=true` to look for the shared libraries. -## WASM +**WASM** For WASM, the module has to be built with a function table to enable callbacks. You can do so using `-extra-linker-flags:"--export-table"`. @@ -29,12 +30,20 @@ Being able to allocate is also required (for some auxiliary APIs but also for ma You can set the context that is used for allocations by setting the global variable `wpgu.g_context`. It will default to the `runtime.default_context`. -Again, have a look at the `example/` and how it is set up, doing the `--import-memory` and the likes +Have a look at the [[example build file; https://github.com/odin-lang/examples/blob/master/wgpu/glfw-triangle/build_web.sh]] and [[html file; https://github.com/odin-lang/examples/blob/master/wgpu/glfw-triangle/web/index.html]] +to see how it looks when set up, doing the `--import-memory` and the likes is not strictly necessary but allows your app more memory than the minimal default. The bindings work on both `-target:js_wasm32` and `-target:js_wasm64p32`. -## GLFW Glue +**SDL Glue** + +There is an inner package `sdl2glue` (and `sdl3glue`) that can be used to glue together WGPU and SDL. +It exports one procedure `GetSurface(wgpu.Instance, ^SDL.Window) -> wgpu.Surface`. +The procedure will call the needed target specific procedures and return a surface configured +for the given window. + +**GLFW Glue** There is an inner package `glfwglue` that can be used to glue together WGPU and GLFW. It exports one procedure `GetSurface(wgpu.Instance, glfw.WindowHandle) -> wgpu.Surface`. @@ -44,14 +53,7 @@ for the given window. Do note that wgpu does not require GLFW, you can use native windows or another windowing library too. For that you can take inspiration from `glfwglue` on glueing them together. -## SDL2 Glue - -There is an inner package `sdl2glue` that can be used to glue together WGPU and SDL2. -It exports one procedure `GetSurface(wgpu.Instance, ^sdl2.Window) -> wgpu.Surface`. -The procedure will call the needed target specific procedures and return a surface configured -for the given window. - -### Wayland +**GLFW and Wayland** GLFW supports Wayland from version 3.4 onwards and only if it is compiled with `-DGLFW_EXPOSE_NATIVE_WAYLAND`. @@ -59,3 +61,5 @@ Odin links against your system's glfw library (probably installed through a pack If that version is lower than 3.4 or hasn't been compiled with the previously mentioned define, you will have to compile glfw from source yourself and adjust the `foreign import` declarations in `vendor:glfw/bindings` to point to it. +*/ +package wgpu diff --git a/vendor/wgpu/examples/glfw/Makefile b/vendor/wgpu/examples/glfw/Makefile deleted file mode 100644 index 022bfcbbc..000000000 --- a/vendor/wgpu/examples/glfw/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -FILES := $(wildcard *) - -# NOTE: changing this requires changing the same values in the `web/index.html`. -INITIAL_MEMORY_PAGES := 2000 -MAX_MEMORY_PAGES := 65536 - -PAGE_SIZE := 65536 -INITIAL_MEMORY_BYTES := $(shell expr $(INITIAL_MEMORY_PAGES) \* $(PAGE_SIZE)) -MAX_MEMORY_BYTES := $(shell expr $(MAX_MEMORY_PAGES) \* $(PAGE_SIZE)) - -web/triangle.wasm: $(FILES) ../../wgpu.js ../../../../core/sys/wasm/js/odin.js - odin build . \ - -target:js_wasm32 -out:web/triangle.wasm -o:size \ - -extra-linker-flags:"--export-table --import-memory --initial-memory=$(INITIAL_MEMORY_BYTES) --max-memory=$(MAX_MEMORY_BYTES)" - - cp ../../wgpu.js web/wgpu.js - cp ../../../../core/sys/wasm/js/odin.js web/odin.js diff --git a/vendor/wgpu/examples/glfw/build.bat b/vendor/wgpu/examples/glfw/build.bat deleted file mode 100644 index b71d4344a..000000000 --- a/vendor/wgpu/examples/glfw/build.bat +++ /dev/null @@ -1,12 +0,0 @@ -REM NOTE: changing this requires changing the same values in the `web/index.html`. -set INITIAL_MEMORY_PAGES=2000 -set MAX_MEMORY_PAGES=65536 - -set PAGE_SIZE=65536 -set /a INITIAL_MEMORY_BYTES=%INITIAL_MEMORY_PAGES% * %PAGE_SIZE% -set /a MAX_MEMORY_BYTES=%MAX_MEMORY_PAGES% * %PAGE_SIZE% - -call odin.exe build . -target:js_wasm32 -out:web/triangle.wasm -o:size -extra-linker-flags:"--export-table --import-memory --initial-memory=%INITIAL_MEMORY_BYTES% --max-memory=%MAX_MEMORY_BYTES%" - -copy "..\..\wgpu.js" "web\wgpu.js" -copy "..\..\..\..\core\sys\wasm\js\odin.js" "web\odin.js" diff --git a/vendor/wgpu/examples/glfw/main.odin b/vendor/wgpu/examples/glfw/main.odin deleted file mode 100644 index b57206371..000000000 --- a/vendor/wgpu/examples/glfw/main.odin +++ /dev/null @@ -1,189 +0,0 @@ -package vendor_wgpu_example_triangle - -import "base:runtime" - -import "core:fmt" - -import "vendor:wgpu" - -State :: struct { - ctx: runtime.Context, - os: OS, - - instance: wgpu.Instance, - surface: wgpu.Surface, - adapter: wgpu.Adapter, - device: wgpu.Device, - config: wgpu.SurfaceConfiguration, - queue: wgpu.Queue, - module: wgpu.ShaderModule, - pipeline_layout: wgpu.PipelineLayout, - pipeline: wgpu.RenderPipeline, -} - -@(private="file") -state: State - -main :: proc() { - state.ctx = context - - os_init(&state.os) - - state.instance = wgpu.CreateInstance(nil) - if state.instance == nil { - panic("WebGPU is not supported") - } - state.surface = os_get_surface(&state.os, state.instance) - - wgpu.InstanceRequestAdapter(state.instance, &{ compatibleSurface = state.surface }, on_adapter, nil) - - on_adapter :: proc "c" (status: wgpu.RequestAdapterStatus, adapter: wgpu.Adapter, message: cstring, userdata: rawptr) { - context = state.ctx - if status != .Success || adapter == nil { - fmt.panicf("request adapter failure: [%v] %s", status, message) - } - state.adapter = adapter - wgpu.AdapterRequestDevice(adapter, nil, on_device) - } - - on_device :: proc "c" (status: wgpu.RequestDeviceStatus, device: wgpu.Device, message: cstring, userdata: rawptr) { - context = state.ctx - if status != .Success || device == nil { - fmt.panicf("request device failure: [%v] %s", status, message) - } - state.device = device - - width, height := os_get_render_bounds(&state.os) - - state.config = wgpu.SurfaceConfiguration { - device = state.device, - usage = { .RenderAttachment }, - format = .BGRA8Unorm, - width = width, - height = height, - presentMode = .Fifo, - alphaMode = .Opaque, - } - wgpu.SurfaceConfigure(state.surface, &state.config) - - state.queue = wgpu.DeviceGetQueue(state.device) - - shader :: ` - @vertex - fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4 { - let x = f32(i32(in_vertex_index) - 1); - let y = f32(i32(in_vertex_index & 1u) * 2 - 1); - return vec4(x, y, 0.0, 1.0); - } - - @fragment - fn fs_main() -> @location(0) vec4 { - return vec4(1.0, 0.0, 0.0, 1.0); - }` - - state.module = wgpu.DeviceCreateShaderModule(state.device, &{ - nextInChain = &wgpu.ShaderModuleWGSLDescriptor{ - sType = .ShaderModuleWGSLDescriptor, - code = shader, - }, - }) - - state.pipeline_layout = wgpu.DeviceCreatePipelineLayout(state.device, &{}) - state.pipeline = wgpu.DeviceCreateRenderPipeline(state.device, &{ - layout = state.pipeline_layout, - vertex = { - module = state.module, - entryPoint = "vs_main", - }, - fragment = &{ - module = state.module, - entryPoint = "fs_main", - targetCount = 1, - targets = &wgpu.ColorTargetState{ - format = .BGRA8Unorm, - writeMask = wgpu.ColorWriteMaskFlags_All, - }, - }, - primitive = { - topology = .TriangleList, - - }, - multisample = { - count = 1, - mask = 0xFFFFFFFF, - }, - }) - - os_run(&state.os) - } -} - -resize :: proc "c" () { - context = state.ctx - - state.config.width, state.config.height = os_get_render_bounds(&state.os) - wgpu.SurfaceConfigure(state.surface, &state.config) -} - -frame :: proc "c" (dt: f32) { - context = state.ctx - - surface_texture := wgpu.SurfaceGetCurrentTexture(state.surface) - switch surface_texture.status { - case .Success: - // All good, could check for `surface_texture.suboptimal` here. - case .Timeout, .Outdated, .Lost: - // Skip this frame, and re-configure surface. - if surface_texture.texture != nil { - wgpu.TextureRelease(surface_texture.texture) - } - resize() - return - case .OutOfMemory, .DeviceLost: - // Fatal error - fmt.panicf("[triangle] get_current_texture status=%v", surface_texture.status) - } - defer wgpu.TextureRelease(surface_texture.texture) - - frame := wgpu.TextureCreateView(surface_texture.texture, nil) - defer wgpu.TextureViewRelease(frame) - - command_encoder := wgpu.DeviceCreateCommandEncoder(state.device, nil) - defer wgpu.CommandEncoderRelease(command_encoder) - - render_pass_encoder := wgpu.CommandEncoderBeginRenderPass( - command_encoder, &{ - colorAttachmentCount = 1, - colorAttachments = &wgpu.RenderPassColorAttachment{ - view = frame, - loadOp = .Clear, - storeOp = .Store, - depthSlice = wgpu.DEPTH_SLICE_UNDEFINED, - clearValue = { 0, 1, 0, 1 }, - }, - }, - ) - - wgpu.RenderPassEncoderSetPipeline(render_pass_encoder, state.pipeline) - wgpu.RenderPassEncoderDraw(render_pass_encoder, vertexCount=3, instanceCount=1, firstVertex=0, firstInstance=0) - - wgpu.RenderPassEncoderEnd(render_pass_encoder) - wgpu.RenderPassEncoderRelease(render_pass_encoder) - - command_buffer := wgpu.CommandEncoderFinish(command_encoder, nil) - defer wgpu.CommandBufferRelease(command_buffer) - - wgpu.QueueSubmit(state.queue, { command_buffer }) - wgpu.SurfacePresent(state.surface) -} - -finish :: proc() { - wgpu.RenderPipelineRelease(state.pipeline) - wgpu.PipelineLayoutRelease(state.pipeline_layout) - wgpu.ShaderModuleRelease(state.module) - wgpu.QueueRelease(state.queue) - wgpu.DeviceRelease(state.device) - wgpu.AdapterRelease(state.adapter) - wgpu.SurfaceRelease(state.surface) - wgpu.InstanceRelease(state.instance) -} diff --git a/vendor/wgpu/examples/glfw/os_glfw.odin b/vendor/wgpu/examples/glfw/os_glfw.odin deleted file mode 100644 index 211b1ce97..000000000 --- a/vendor/wgpu/examples/glfw/os_glfw.odin +++ /dev/null @@ -1,55 +0,0 @@ -#+build !js -package vendor_wgpu_example_triangle - -import "core:time" - -import "vendor:glfw" -import "vendor:wgpu" -import "vendor:wgpu/glfwglue" - -OS :: struct { - window: glfw.WindowHandle, -} - -os_init :: proc(os: ^OS) { - if !glfw.Init() { - panic("[glfw] init failure") - } - - glfw.WindowHint(glfw.CLIENT_API, glfw.NO_API) - os.window = glfw.CreateWindow(960, 540, "WGPU Native Triangle", nil, nil) - - glfw.SetFramebufferSizeCallback(os.window, size_callback) -} - -os_run :: proc(os: ^OS) { - dt: f32 - - for !glfw.WindowShouldClose(os.window) { - start := time.tick_now() - - glfw.PollEvents() - frame(dt) - - dt = f32(time.duration_seconds(time.tick_since(start))) - } - - finish() - - glfw.DestroyWindow(os.window) - glfw.Terminate() -} - -os_get_render_bounds :: proc(os: ^OS) -> (width, height: u32) { - iw, ih := glfw.GetWindowSize(os.window) - return u32(iw), u32(ih) -} - -os_get_surface :: proc(os: ^OS, instance: wgpu.Instance) -> wgpu.Surface { - return glfwglue.GetSurface(instance, os.window) -} - -@(private="file") -size_callback :: proc "c" (window: glfw.WindowHandle, width, height: i32) { - resize() -} diff --git a/vendor/wgpu/examples/glfw/os_js.odin b/vendor/wgpu/examples/glfw/os_js.odin deleted file mode 100644 index 68f9ef672..000000000 --- a/vendor/wgpu/examples/glfw/os_js.odin +++ /dev/null @@ -1,61 +0,0 @@ -package vendor_wgpu_example_triangle - -import "core:sys/wasm/js" - -import "vendor:wgpu" - -OS :: struct { - initialized: bool, -} - -@(private="file") -g_os: ^OS - -os_init :: proc(os: ^OS) { - g_os = os - assert(js.add_window_event_listener(.Resize, nil, size_callback)) -} - -// NOTE: frame loop is done by the runtime.js repeatedly calling `step`. -os_run :: proc(os: ^OS) { - os.initialized = true -} - -os_get_render_bounds :: proc(os: ^OS) -> (width, height: u32) { - rect := js.get_bounding_client_rect("body") - return u32(rect.width), u32(rect.height) -} - -os_get_surface :: proc(os: ^OS, instance: wgpu.Instance) -> wgpu.Surface { - return wgpu.InstanceCreateSurface( - instance, - &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromCanvasHTMLSelector{ - sType = .SurfaceDescriptorFromCanvasHTMLSelector, - selector = "#wgpu-canvas", - }, - }, - ) -} - -@(private="file", export) -step :: proc(dt: f32) -> bool { - if !g_os.initialized { - return true - } - - frame(dt) - return true -} - -@(private="file", fini) -os_fini :: proc() { - js.remove_window_event_listener(.Resize, nil, size_callback) - - finish() -} - -@(private="file") -size_callback :: proc(e: js.Event) { - resize() -} diff --git a/vendor/wgpu/examples/glfw/web/index.html b/vendor/wgpu/examples/glfw/web/index.html deleted file mode 100644 index a509cafbd..000000000 --- a/vendor/wgpu/examples/glfw/web/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - WGPU WASM Triangle - - - - - - - - - diff --git a/vendor/wgpu/examples/sdl2/Makefile b/vendor/wgpu/examples/sdl2/Makefile deleted file mode 100644 index 022bfcbbc..000000000 --- a/vendor/wgpu/examples/sdl2/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -FILES := $(wildcard *) - -# NOTE: changing this requires changing the same values in the `web/index.html`. -INITIAL_MEMORY_PAGES := 2000 -MAX_MEMORY_PAGES := 65536 - -PAGE_SIZE := 65536 -INITIAL_MEMORY_BYTES := $(shell expr $(INITIAL_MEMORY_PAGES) \* $(PAGE_SIZE)) -MAX_MEMORY_BYTES := $(shell expr $(MAX_MEMORY_PAGES) \* $(PAGE_SIZE)) - -web/triangle.wasm: $(FILES) ../../wgpu.js ../../../../core/sys/wasm/js/odin.js - odin build . \ - -target:js_wasm32 -out:web/triangle.wasm -o:size \ - -extra-linker-flags:"--export-table --import-memory --initial-memory=$(INITIAL_MEMORY_BYTES) --max-memory=$(MAX_MEMORY_BYTES)" - - cp ../../wgpu.js web/wgpu.js - cp ../../../../core/sys/wasm/js/odin.js web/odin.js diff --git a/vendor/wgpu/examples/sdl2/build.bat b/vendor/wgpu/examples/sdl2/build.bat deleted file mode 100644 index b71d4344a..000000000 --- a/vendor/wgpu/examples/sdl2/build.bat +++ /dev/null @@ -1,12 +0,0 @@ -REM NOTE: changing this requires changing the same values in the `web/index.html`. -set INITIAL_MEMORY_PAGES=2000 -set MAX_MEMORY_PAGES=65536 - -set PAGE_SIZE=65536 -set /a INITIAL_MEMORY_BYTES=%INITIAL_MEMORY_PAGES% * %PAGE_SIZE% -set /a MAX_MEMORY_BYTES=%MAX_MEMORY_PAGES% * %PAGE_SIZE% - -call odin.exe build . -target:js_wasm32 -out:web/triangle.wasm -o:size -extra-linker-flags:"--export-table --import-memory --initial-memory=%INITIAL_MEMORY_BYTES% --max-memory=%MAX_MEMORY_BYTES%" - -copy "..\..\wgpu.js" "web\wgpu.js" -copy "..\..\..\..\core\sys\wasm\js\odin.js" "web\odin.js" diff --git a/vendor/wgpu/examples/sdl2/main.odin b/vendor/wgpu/examples/sdl2/main.odin deleted file mode 100644 index 58e357f7a..000000000 --- a/vendor/wgpu/examples/sdl2/main.odin +++ /dev/null @@ -1,189 +0,0 @@ -package vendor_wgpu_example_triangle - -import "base:runtime" - -import "core:fmt" - -import "vendor:wgpu" - -State :: struct { - ctx: runtime.Context, - os: OS, - - instance: wgpu.Instance, - surface: wgpu.Surface, - adapter: wgpu.Adapter, - device: wgpu.Device, - config: wgpu.SurfaceConfiguration, - queue: wgpu.Queue, - module: wgpu.ShaderModule, - pipeline_layout: wgpu.PipelineLayout, - pipeline: wgpu.RenderPipeline, -} - -@(private="file") -state: State - -main :: proc() { - state.ctx = context - - os_init(&state.os) - - state.instance = wgpu.CreateInstance(nil) - if state.instance == nil { - panic("WebGPU is not supported") - } - state.surface = os_get_surface(&state.os, state.instance) - - wgpu.InstanceRequestAdapter(state.instance, &{ compatibleSurface = state.surface }, on_adapter, nil) - - on_adapter :: proc "c" (status: wgpu.RequestAdapterStatus, adapter: wgpu.Adapter, message: cstring, userdata: rawptr) { - context = state.ctx - if status != .Success || adapter == nil { - fmt.panicf("request adapter failure: [%v] %s", status, message) - } - state.adapter = adapter - wgpu.AdapterRequestDevice(adapter, nil, on_device) - } - - on_device :: proc "c" (status: wgpu.RequestDeviceStatus, device: wgpu.Device, message: cstring, userdata: rawptr) { - context = state.ctx - if status != .Success || device == nil { - fmt.panicf("request device failure: [%v] %s", status, message) - } - state.device = device - - width, height := os_get_render_bounds(&state.os) - - state.config = wgpu.SurfaceConfiguration { - device = state.device, - usage = { .RenderAttachment }, - format = .BGRA8Unorm, - width = width, - height = height, - presentMode = .Fifo, - alphaMode = .Opaque, - } - wgpu.SurfaceConfigure(state.surface, &state.config) - - state.queue = wgpu.DeviceGetQueue(state.device) - - shader :: ` - @vertex - fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4 { - let x = f32(i32(in_vertex_index) - 1); - let y = f32(i32(in_vertex_index & 1u) * 2 - 1); - return vec4(x, y, 0.0, 1.0); - } - - @fragment - fn fs_main() -> @location(0) vec4 { - return vec4(1.0, 0.0, 0.0, 1.0); - }` - - state.module = wgpu.DeviceCreateShaderModule(state.device, &{ - nextInChain = &wgpu.ShaderModuleWGSLDescriptor{ - sType = .ShaderModuleWGSLDescriptor, - code = shader, - }, - }) - - state.pipeline_layout = wgpu.DeviceCreatePipelineLayout(state.device, &{}) - state.pipeline = wgpu.DeviceCreateRenderPipeline(state.device, &{ - layout = state.pipeline_layout, - vertex = { - module = state.module, - entryPoint = "vs_main", - }, - fragment = &{ - module = state.module, - entryPoint = "fs_main", - targetCount = 1, - targets = &wgpu.ColorTargetState{ - format = .BGRA8Unorm, - writeMask = wgpu.ColorWriteMaskFlags_All, - }, - }, - primitive = { - topology = .TriangleList, - - }, - multisample = { - count = 1, - mask = 0xFFFFFFFF, - }, - }) - - os_run(&state.os) - } -} - -resize :: proc "c" () { - context = state.ctx - - state.config.width, state.config.height = os_get_render_bounds(&state.os) - wgpu.SurfaceConfigure(state.surface, &state.config) -} - -frame :: proc "c" (dt: f32) { - context = state.ctx - - surface_texture := wgpu.SurfaceGetCurrentTexture(state.surface) - switch surface_texture.status { - case .Success: - // All good, could check for `surface_texture.suboptimal` here. - case .Timeout, .Outdated, .Lost: - // Skip this frame, and re-configure surface. - if surface_texture.texture != nil { - wgpu.TextureRelease(surface_texture.texture) - } - resize() - return - case .OutOfMemory, .DeviceLost: - // Fatal error - fmt.panicf("[triangle] get_current_texture status=%v", surface_texture.status) - } - defer wgpu.TextureRelease(surface_texture.texture) - - frame := wgpu.TextureCreateView(surface_texture.texture, nil) - defer wgpu.TextureViewRelease(frame) - - command_encoder := wgpu.DeviceCreateCommandEncoder(state.device, nil) - defer wgpu.CommandEncoderRelease(command_encoder) - - render_pass_encoder := wgpu.CommandEncoderBeginRenderPass( - command_encoder, &{ - colorAttachmentCount = 1, - colorAttachments = &wgpu.RenderPassColorAttachment{ - view = frame, - loadOp = .Clear, - storeOp = .Store, - depthSlice = wgpu.DEPTH_SLICE_UNDEFINED, - clearValue = { 0, 1, 0, 1 }, - }, - }, - ) - - wgpu.RenderPassEncoderSetPipeline(render_pass_encoder, state.pipeline) - wgpu.RenderPassEncoderDraw(render_pass_encoder, vertexCount=3, instanceCount=1, firstVertex=0, firstInstance=0) - - wgpu.RenderPassEncoderEnd(render_pass_encoder) - wgpu.RenderPassEncoderRelease(render_pass_encoder) - - command_buffer := wgpu.CommandEncoderFinish(command_encoder, nil) - defer wgpu.CommandBufferRelease(command_buffer) - - wgpu.QueueSubmit(state.queue, { command_buffer }) - wgpu.SurfacePresent(state.surface) -} - -finish :: proc() { - wgpu.RenderPipelineRelease(state.pipeline) - wgpu.PipelineLayoutRelease(state.pipeline_layout) - wgpu.ShaderModuleRelease(state.module) - wgpu.QueueRelease(state.queue) - wgpu.DeviceRelease(state.device) - wgpu.AdapterRelease(state.adapter) - wgpu.SurfaceRelease(state.surface) - wgpu.InstanceRelease(state.instance) -} diff --git a/vendor/wgpu/examples/sdl2/os_js.odin b/vendor/wgpu/examples/sdl2/os_js.odin deleted file mode 100644 index 68f9ef672..000000000 --- a/vendor/wgpu/examples/sdl2/os_js.odin +++ /dev/null @@ -1,61 +0,0 @@ -package vendor_wgpu_example_triangle - -import "core:sys/wasm/js" - -import "vendor:wgpu" - -OS :: struct { - initialized: bool, -} - -@(private="file") -g_os: ^OS - -os_init :: proc(os: ^OS) { - g_os = os - assert(js.add_window_event_listener(.Resize, nil, size_callback)) -} - -// NOTE: frame loop is done by the runtime.js repeatedly calling `step`. -os_run :: proc(os: ^OS) { - os.initialized = true -} - -os_get_render_bounds :: proc(os: ^OS) -> (width, height: u32) { - rect := js.get_bounding_client_rect("body") - return u32(rect.width), u32(rect.height) -} - -os_get_surface :: proc(os: ^OS, instance: wgpu.Instance) -> wgpu.Surface { - return wgpu.InstanceCreateSurface( - instance, - &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromCanvasHTMLSelector{ - sType = .SurfaceDescriptorFromCanvasHTMLSelector, - selector = "#wgpu-canvas", - }, - }, - ) -} - -@(private="file", export) -step :: proc(dt: f32) -> bool { - if !g_os.initialized { - return true - } - - frame(dt) - return true -} - -@(private="file", fini) -os_fini :: proc() { - js.remove_window_event_listener(.Resize, nil, size_callback) - - finish() -} - -@(private="file") -size_callback :: proc(e: js.Event) { - resize() -} diff --git a/vendor/wgpu/examples/sdl2/os_sdl2.odin b/vendor/wgpu/examples/sdl2/os_sdl2.odin deleted file mode 100644 index 6ed70452f..000000000 --- a/vendor/wgpu/examples/sdl2/os_sdl2.odin +++ /dev/null @@ -1,85 +0,0 @@ -#+build !js -package vendor_wgpu_example_triangle - -import "core:c" -import "core:fmt" - -import "vendor:sdl2" -import "vendor:wgpu" -import "vendor:wgpu/sdl2glue" - -OS :: struct { - window: ^sdl2.Window, -} - -os_init :: proc(os: ^OS) { - sdl_flags := sdl2.InitFlags{.VIDEO, .JOYSTICK, .GAMECONTROLLER, .EVENTS} - if res := sdl2.Init(sdl_flags); res != 0 { - fmt.eprintfln("ERROR: Failed to initialize SDL: [%s]", sdl2.GetError()) - return - } - - window_flags: sdl2.WindowFlags = {.SHOWN, .ALLOW_HIGHDPI, .RESIZABLE} - os.window = sdl2.CreateWindow( - "WGPU Native Triangle", - sdl2.WINDOWPOS_CENTERED, - sdl2.WINDOWPOS_CENTERED, - 960, - 540, - window_flags, - ) - if os.window == nil { - fmt.eprintfln("ERROR: Failed to create the SDL Window: [%s]", sdl2.GetError()) - return - } - - sdl2.AddEventWatch(size_callback, nil) -} - -os_run :: proc(os: ^OS) { - now := sdl2.GetPerformanceCounter() - last : u64 - dt: f32 - main_loop: for { - last = now - now = sdl2.GetPerformanceCounter() - dt = f32((now - last) * 1000) / f32(sdl2.GetPerformanceFrequency()) - - e: sdl2.Event - - for sdl2.PollEvent(&e) { - #partial switch (e.type) { - case .QUIT: - break main_loop - } - } - - frame(dt) - } - - sdl2.DestroyWindow(os.window) - sdl2.Quit() - - finish() -} - - -os_get_render_bounds :: proc(os: ^OS) -> (width, height: u32) { - iw, ih: c.int - sdl2.GetWindowSize(os.window, &iw, &ih) - return u32(iw), u32(ih) -} - -os_get_surface :: proc(os: ^OS, instance: wgpu.Instance) -> wgpu.Surface { - return sdl2glue.GetSurface(instance, os.window) -} - -@(private="file") -size_callback :: proc "c" (userdata: rawptr, event: ^sdl2.Event) -> c.int { - if event.type == .WINDOWEVENT { - if event.window.event == .SIZE_CHANGED || event.window.event == .RESIZED { - resize() - } - } - return 0 -} diff --git a/vendor/wgpu/examples/sdl2/web/index.html b/vendor/wgpu/examples/sdl2/web/index.html deleted file mode 100644 index a509cafbd..000000000 --- a/vendor/wgpu/examples/sdl2/web/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - WGPU WASM Triangle - - - - - - - - - diff --git a/vendor/wgpu/glfwglue/glue_darwin.odin b/vendor/wgpu/glfwglue/glue_darwin.odin index c1477f4b0..fbf19e316 100644 --- a/vendor/wgpu/glfwglue/glue_darwin.odin +++ b/vendor/wgpu/glfwglue/glue_darwin.odin @@ -12,9 +12,9 @@ GetSurface :: proc(instance: wgpu.Instance, window: glfw.WindowHandle) -> wgpu.S return wgpu.InstanceCreateSurface( instance, &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromMetalLayer{ + nextInChain = &wgpu.SurfaceSourceMetalLayer{ chain = wgpu.ChainedStruct{ - sType = .SurfaceDescriptorFromMetalLayer, + sType = .SurfaceSourceMetalLayer, }, layer = rawptr(metal_layer), }, diff --git a/vendor/wgpu/glfwglue/glue_linux.odin b/vendor/wgpu/glfwglue/glue_linux.odin index 45d29a638..2b99d7970 100644 --- a/vendor/wgpu/glfwglue/glue_linux.odin +++ b/vendor/wgpu/glfwglue/glue_linux.odin @@ -11,9 +11,9 @@ GetSurface :: proc(instance: wgpu.Instance, window: glfw.WindowHandle) -> wgpu.S return wgpu.InstanceCreateSurface( instance, &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromWaylandSurface{ + nextInChain = &wgpu.SurfaceSourceWaylandSurface{ chain = { - sType = .SurfaceDescriptorFromWaylandSurface, + sType = .SurfaceSourceWaylandSurface, }, display = display, surface = surface, @@ -32,9 +32,9 @@ GetSurface :: proc(instance: wgpu.Instance, window: glfw.WindowHandle) -> wgpu.S return wgpu.InstanceCreateSurface( instance, &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromXlibWindow{ + nextInChain = &wgpu.SurfaceSourceXlibWindow{ chain = { - sType = .SurfaceDescriptorFromXlibWindow, + sType = .SurfaceSourceXlibWindow, }, display = display, window = u64(window), diff --git a/vendor/wgpu/glfwglue/glue_windows.odin b/vendor/wgpu/glfwglue/glue_windows.odin index 73a933f37..ade5ced61 100644 --- a/vendor/wgpu/glfwglue/glue_windows.odin +++ b/vendor/wgpu/glfwglue/glue_windows.odin @@ -11,9 +11,9 @@ GetSurface :: proc(instance: wgpu.Instance, window: glfw.WindowHandle) -> wgpu.S return wgpu.InstanceCreateSurface( instance, &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromWindowsHWND{ + nextInChain = &wgpu.SurfaceSourceWindowsHWND{ chain = wgpu.ChainedStruct{ - sType = .SurfaceDescriptorFromWindowsHWND, + sType = .SurfaceSourceWindowsHWND, }, hinstance = rawptr(hinstance), hwnd = rawptr(hwnd), diff --git a/vendor/wgpu/lib/.gitkeep b/vendor/wgpu/lib/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll new file mode 100644 index 000000000..7fa1c8398 Binary files /dev/null and b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll differ diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll.lib b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll.lib new file mode 100644 index 000000000..072c4b234 Binary files /dev/null and b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll.lib differ diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.lib b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib similarity index 72% rename from vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.lib rename to vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib index 7c9f95c33..787feaede 100644 Binary files a/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.lib and b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib differ diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.dll b/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.dll deleted file mode 100644 index b8f782a2f..000000000 Binary files a/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.dll and /dev/null differ diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.dll.lib b/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.dll.lib deleted file mode 100644 index 864b7eb53..000000000 Binary files a/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.dll.lib and /dev/null differ diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.pdb b/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.pdb deleted file mode 100644 index 52865e174..000000000 Binary files a/vendor/wgpu/lib/wgpu-windows-x86_64-release/wgpu_native.pdb and /dev/null differ diff --git a/vendor/wgpu/sdl2glue/glue_darwin.odin b/vendor/wgpu/sdl2glue/glue_darwin.odin index c48b8488c..9878c5602 100644 --- a/vendor/wgpu/sdl2glue/glue_darwin.odin +++ b/vendor/wgpu/sdl2glue/glue_darwin.odin @@ -14,9 +14,9 @@ GetSurface :: proc(instance: wgpu.Instance, window: ^sdl2.Window) -> wgpu.Surfac return wgpu.InstanceCreateSurface( instance, &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromMetalLayer{ + nextInChain = &wgpu.SurfaceSourceMetalLayer{ chain = wgpu.ChainedStruct{ - sType = .SurfaceDescriptorFromMetalLayer, + sType = .SurfaceSourceMetalLayer, }, layer = rawptr(metal_layer), }, diff --git a/vendor/wgpu/sdl2glue/glue_linux.odin b/vendor/wgpu/sdl2glue/glue_linux.odin index 58ec90499..689d16249 100644 --- a/vendor/wgpu/sdl2glue/glue_linux.odin +++ b/vendor/wgpu/sdl2glue/glue_linux.odin @@ -14,9 +14,9 @@ GetSurface :: proc(instance: wgpu.Instance, window: ^sdl2.Window) -> wgpu.Surfac return wgpu.InstanceCreateSurface( instance, &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromWaylandSurface{ + nextInChain = &wgpu.SurfaceSourceWaylandSurface{ chain = { - sType = .SurfaceDescriptorFromWaylandSurface, + sType = .SurfaceSourceWaylandSurface, }, display = display, surface = surface, @@ -29,9 +29,9 @@ GetSurface :: proc(instance: wgpu.Instance, window: ^sdl2.Window) -> wgpu.Surfac return wgpu.InstanceCreateSurface( instance, &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromXlibWindow{ + nextInChain = &wgpu.SurfaceSourceXlibWindow{ chain = { - sType = .SurfaceDescriptorFromXlibWindow, + sType = .SurfaceSourceXlibWindow, }, display = display, window = u64(window), diff --git a/vendor/wgpu/sdl2glue/glue_windows.odin b/vendor/wgpu/sdl2glue/glue_windows.odin index a2b1437ab..aaedc2779 100644 --- a/vendor/wgpu/sdl2glue/glue_windows.odin +++ b/vendor/wgpu/sdl2glue/glue_windows.odin @@ -13,9 +13,9 @@ GetSurface :: proc(instance: wgpu.Instance, window: ^sdl2.Window) -> wgpu.Surfac return wgpu.InstanceCreateSurface( instance, &wgpu.SurfaceDescriptor{ - nextInChain = &wgpu.SurfaceDescriptorFromWindowsHWND{ + nextInChain = &wgpu.SurfaceSourceWindowsHWND{ chain = wgpu.ChainedStruct{ - sType = .SurfaceDescriptorFromWindowsHWND, + sType = .SurfaceSourceWindowsHWND, }, hinstance = rawptr(hinstance), hwnd = rawptr(hwnd), diff --git a/vendor/wgpu/sdl3glue/glue.odin b/vendor/wgpu/sdl3glue/glue.odin new file mode 100644 index 000000000..4cc59614d --- /dev/null +++ b/vendor/wgpu/sdl3glue/glue.odin @@ -0,0 +1,6 @@ +#+build !linux +#+build !windows +#+build !darwin +package wgpu_sdl3_glue + +#panic("package wgpu/sdl3glue is not supported on the current target") diff --git a/vendor/wgpu/sdl3glue/glue_darwin.odin b/vendor/wgpu/sdl3glue/glue_darwin.odin new file mode 100644 index 000000000..b7c9a3b41 --- /dev/null +++ b/vendor/wgpu/sdl3glue/glue_darwin.odin @@ -0,0 +1,21 @@ +package wgpu_sdl3_glue + +import "vendor:sdl3" +import "vendor:wgpu" + +GetSurface :: proc(instance: wgpu.Instance, window: ^sdl3.Window) -> wgpu.Surface { + view := sdl3.Metal_CreateView(window) + layer := sdl3.Metal_GetLayer(view) + + return wgpu.InstanceCreateSurface( + instance, + &wgpu.SurfaceDescriptor{ + nextInChain = &wgpu.SurfaceSourceMetalLayer{ + chain = wgpu.ChainedStruct{ + sType = .SurfaceSourceMetalLayer, + }, + layer = layer, + }, + }, + ) +} diff --git a/vendor/wgpu/sdl3glue/glue_linux.odin b/vendor/wgpu/sdl3glue/glue_linux.odin new file mode 100644 index 000000000..8068ae7b4 --- /dev/null +++ b/vendor/wgpu/sdl3glue/glue_linux.odin @@ -0,0 +1,37 @@ +package wgpu_sdl3_glue + +import "vendor:sdl3" +import "vendor:wgpu" + +GetSurface :: proc(instance: wgpu.Instance, window: ^sdl3.Window) -> wgpu.Surface { + switch sdl3.GetCurrentVideoDriver() { + case "wayland": + return wgpu.InstanceCreateSurface( + instance, + &wgpu.SurfaceDescriptor{ + nextInChain = &wgpu.SurfaceSourceWaylandSurface{ + chain = { + sType = .SurfaceSourceWaylandSurface, + }, + display = sdl3.GetPointerProperty(sdl3.GetWindowProperties(window), sdl3.PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nil), + surface = sdl3.GetPointerProperty(sdl3.GetWindowProperties(window), sdl3.PROP_WINDOW_WAYLAND_SURFACE_POINTER, nil), + }, + }, + ) + case "x11": + return wgpu.InstanceCreateSurface( + instance, + &wgpu.SurfaceDescriptor{ + nextInChain = &wgpu.SurfaceSourceXlibWindow{ + chain = { + sType = .SurfaceSourceXlibWindow, + }, + display = sdl3.GetPointerProperty(sdl3.GetWindowProperties(window), sdl3.PROP_WINDOW_X11_DISPLAY_POINTER, nil), + window = cast(u64)sdl3.GetNumberProperty(sdl3.GetWindowProperties(window), sdl3.PROP_WINDOW_X11_WINDOW_NUMBER, 0), + }, + }, + ) + case: + panic("wgpu sdl3 glue: unsupported video driver, expected Wayland or X11") + } +} diff --git a/vendor/wgpu/sdl3glue/glue_windows.odin b/vendor/wgpu/sdl3glue/glue_windows.odin new file mode 100644 index 000000000..f5b5fd297 --- /dev/null +++ b/vendor/wgpu/sdl3glue/glue_windows.odin @@ -0,0 +1,19 @@ +package wgpu_sdl3_glue + +import "vendor:sdl3" +import "vendor:wgpu" + +GetSurface :: proc(instance: wgpu.Instance, window: ^sdl3.Window) -> wgpu.Surface { + return wgpu.InstanceCreateSurface( + instance, + &wgpu.SurfaceDescriptor{ + nextInChain = &wgpu.SurfaceSourceWindowsHWND{ + chain = wgpu.ChainedStruct{ + sType = .SurfaceSourceWindowsHWND, + }, + hinstance = sdl3.GetPointerProperty(sdl3.GetWindowProperties(window), sdl3.PROP_WINDOW_WIN32_INSTANCE_POINTER, nil), + hwnd = sdl3.GetPointerProperty(sdl3.GetWindowProperties(window), sdl3.PROP_WINDOW_WIN32_HWND_POINTER, nil), + }, + }, + ) +} diff --git a/vendor/wgpu/wgpu.js b/vendor/wgpu/wgpu.js index 5e0482b69..055f7abab 100644 --- a/vendor/wgpu/wgpu.js +++ b/vendor/wgpu/wgpu.js @@ -1,5 +1,55 @@ (function() { +const STATUS_SUCCESS = 1; +const STATUS_ERROR = 2; + +const ENUMS = { + FeatureName: [undefined, "depth-clip-control", "depth32float-stencil8", "timestamp-query", "texture-compression-bc", "texture-compression-bc-sliced-3d", "texture-compression-etc2", "texture-compression-astc", "texture-compression-astc-sliced-3d", "indirect-first-instance", "shader-f16", "rg11b10ufloat-renderable", "bgra8unorm-storage", "float32-filterable", "float32-blendable", "clip-distances", "dual-source-blending" ], + StoreOp: [undefined, "store", "discard", ], + LoadOp: [undefined, "load", "clear", ], + BufferBindingType: [null, undefined, "uniform", "storage", "read-only-storage", ], + SamplerBindingType: [null, undefined, "filtering", "non-filtering", "comparison", ], + TextureSampleType: [null, undefined, "float", "unfilterable-float", "depth", "sint", "uint", ], + TextureViewDimension: [undefined, "1d", "2d", "2d-array", "cube", "cube-array", "3d", ], + StorageTextureAccess: [null, undefined, "write-only", "read-only", "read-write", ], + TextureFormat: [undefined, "r8unorm", "r8snorm", "r8uint", "r8sint", "r16uint", "r16sint", "r16float", "rg8unorm", "rg8snorm", "rg8uint", "rg8sint", "r32float", "r32uint", "r32sint", "rg16uint", "rg16sint", "rg16float", "rgba8unorm", "rgba8unorm-srgb", "rgba8snorm", "rgba8uint", "rgba8sint", "bgra8unorm", "bgra8unorm-srgb", "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", "rgb9e5ufloat", "rg32float", "rg32uint", "rg32sint", "rgba16uint", "rgba16sint", "rgba16float", "rgba32float", "rgba32uint", "rgba32sint", "stencil8", "depth16unorm", "depth24plus", "depth24plus-stencil8", "depth32float", "depth32float-stencil8", "bc1-rgba-unorm", "bc1-rgba-unorm-srgb", "bc2-rgba-unorm", "bc2-rgba-unorm-srgb", "bc3-rgba-unorm", "bc3-rgba-unorm-srgb", "bc4-r-unorm", "bc4-r-snorm", "bc5-rg-unorm", "bc5-rg-snorm", "bc6h-rgb-ufloat", "bc6h-rgb-float", "bc7-rgba-unorm", "bc7-rgba-unorm-srgb", "etc2-rgb8unorm", "etc2-rgb8unorm-srgb", "etc2-rgb8a1unorm", "etc2-rgb8a1unorm-srgb", "etc2-rgba8unorm", "etc2-rgba8unorm-srgb", "eac-r11unorm", "eac-r11snorm", "eac-rg11unorm", "eac-rg11snorm", "astc-4x4-unorm", "astc-4x4-unorm-srgb", "astc-5x4-unorm", "astc-5x4-unorm-srgb", "astc-5x5-unorm", "astc-5x5-unorm-srgb", "astc-6x5-unorm", "astc-6x5-unorm-srgb", "astc-6x6-unorm", "astc-6x6-unorm-srgb", "astc-8x5-unorm", "astc-8x5-unorm-srgb", "astc-8x6-unorm", "astc-8x6-unorm-srgb", "astc-8x8-unorm", "astc-8x8-unorm-srgb", "astc-10x5-unorm", "astc-10x5-unorm-srgb", "astc-10x6-unorm", "astc-10x6-unorm-srgb", "astc-10x8-unorm", "astc-10x8-unorm-srgb", "astc-10x10-unorm", "astc-10x10-unorm-srgb", "astc-12x10-unorm", "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb", ], + QueryType: [undefined, "occlusion", "timestamp", ], + VertexStepMode: [null, undefined, "vertex", "instance", ], + VertexFormat: [undefined, "uint8", "uint8x2", "uint8x4", "sint8", "sint8x2", "sint8x4", "unorm8", "unorm8x2", "unorm8x4", "snorm8", "snorm8x2", "snorm8x4", "uint16", "uint16x2", "uint16x4", "sint16", "sint16x2", "sint16x4", "unorm16", "unorm16x2", "unorm16x4", "snorm16", "snorm16x2", "snorm16x4", "float16", "float16x2", "float16x4", "float32", "float32x2", "float32x3", "float32x4", "uint32", "uint32x2", "uint32x3", "uint32x4", "sint32", "sint32x2", "sint32x3", "sint32x4", "unorm10-10-2", "unorm8x4-bgra" ], + PrimitiveTopology: [undefined, "point-list", "line-list", "line-strip", "triangle-list", "triangle-strip", ], + IndexFormat: [undefined, "uint16", "uint32", ], + FrontFace: [undefined, "ccw", "cw", ], + CullMode: [undefined, "none", "front", "back", ], + AddressMode: [undefined, "clamp-to-edge", "repeat", "mirror-repeat", ], + FilterMode: [undefined, "nearest", "linear", ], + MipmapFilterMode: [undefined, "nearest", "linear", ], + CompareFunction: [undefined, "never", "less", "equal", "less-equal", "greater", "not-equal", "greater-equal", "always", ], + TextureDimension: [undefined, "1d", "2d", "3d", ], + ErrorType: [undefined, "no-error", "validation", "out-of-memory", "internal", "unknown", ], + WGSLLanguageFeatureName: [undefined, "readonly_and_readwrite_storage_textures", "packed_4x8_integer_dot_product", "unrestricted_pointer_parameters", "pointer_composite_access", ], + PowerPreference: [undefined, "low-power", "high-performance", ], + CompositeAlphaMode: ["auto", "opaque", "premultiplied", "unpremultiplied", "inherit", ], + StencilOperation: [undefined, "keep", "zero", "replace", "invert", "increment-clamp", "decrement-clamp", "increment-wrap", "decrement-wrap", ], + BlendOperation: ["add", "subtract", "reverse-subtract", "min", "max", ], + BlendFactor: [undefined, "zero", "one", "src", "one-minus-src", "src-alpha", "one-minus-src-alpha", "dst", "one-minus-dst", "dst-alpha", "one-minus-dst-alpha", "src-alpha-saturated", "constant", "one-minus-constant", "src1", "one-minus-src1", "src1-alpha", "one-minus-src1-alpha" ], + PresentMode: [undefined, "fifo", "fifo-relaxed", "immediate", "mailbox", ], + TextureAspect: [undefined, "all", "stencil-only", "depth-only"], + DeviceLostReason: [undefined, "unknown", "destroyed", "instance-dropped", "failed-creation"], + BufferMapState: [undefined, "unmapped", "pending", "mapped"], + OptionalBool: [false, true, undefined], + + // WARN: used with indexOf to pass to WASM, if we would pass to JS, this needs to use official naming convention (not like Odin enums) like the ones above. + BackendType: [undefined, null, "WebGPU", "D3D11", "D3D12", "Metal", "Vulkan", "OpenGL", "OpenGLES"], + AdapterType: [undefined, "DiscreteGPU", "IntegratedGPU", "CPU", "Unknown"], + RequestDeviceStatus: [undefined, "Success", "InstanceDropped", "Error", "Unknown"], + MapAsyncStatus: [undefined, "Success", "InstanceDropped", "Error", "Aborted", "Unknown"], + CreatePipelineAsyncStatus: [undefined, "Success", "InstanceDropped", "ValidationError", "InternalError", "Unknown"], + PopErrorScopeStatus: [undefined, "Success", "InstanceDropped", "EmptyStack"], + RequestAdapterStatus: [undefined, "Success", "InstanceDropped", "Unavailable", "Error", "Unknown"], + QueueWorkDoneStatus: [undefined, "Success", "InstanceDropped", "Error", "Unknown"], + CompilationInfoRequestStatus: [undefined, "Success", "InstanceDropped", "Error", "Unknown"], +}; + /** * Assumptions: * - Ability to allocate memory, set the context to allocate with using the global `wgpu.g_context` @@ -13,38 +63,33 @@ class WebGPUInterface { constructor(mem) { this.mem = mem; - this.enums = { - FeatureName: [undefined, "depth-clip-control", "depth32float-stencil8", "timestamp-query", "texture-compression-bc", "texture-compression-etc2", "texture-compression-astc", "indirect-first-instance", "shader-f16", "rg11b10ufloat-renderable", "bgra8unorm-storage", "float32-filterable", ], - StoreOp: [undefined, "store", "discard", ], - LoadOp: [undefined, "clear", "load", ], - BufferBindingType: [undefined, "uniform", "storage", "read-only-storage", ], - SamplerBindingType: [undefined, "filtering", "non-filtering", "comparison", ], - TextureSampleType: [undefined, "float", "unfilterable-float", "depth", "sint", "uint", ], - TextureViewDimension: [undefined, "1d", "2d", "2d-array", "cube", "cube-array", "3d", ], - StorageTextureAccess: [undefined, "write-only", "read-only", "read-write", ], - TextureFormat: [undefined, "r8unorm", "r8snorm", "r8uint", "r8sint", "r16uint", "r16sint", "r16float", "rg8unorm", "rg8snorm", "rg8uint", "rg8sint", "r32float", "r32uint", "r32sint", "rg16uint", "rg16sint", "rg16float", "rgba8unorm", "rgba8unorm-srgb", "rgba8snorm", "rgba8uint", "rgba8sint", "bgra8unorm", "bgra8unorm-srgb", "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", "rgb9e5ufloat", "rg32float", "rg32uint", "rg32sint", "rgba16uint", "rgba16sint", "rgba16float", "rgba32float", "rgba32uint", "rgba32sint", "stencil8", "depth16unorm", "depth24plus", "depth24plus-stencil8", "depth32float", "depth32float-stencil8", "bc1-rgba-unorm", "bc1-rgba-unorm-srgb", "bc2-rgba-unorm", "bc2-rgba-unorm-srgb", "bc3-rgba-unorm", "bc3-rgba-unorm-srgb", "bc4-r-unorm", "bc4-r-snorm", "bc5-rg-unorm", "bc5-rg-snorm", "bc6h-rgb-ufloat", "bc6h-rgb-float", "bc7-rgba-unorm", "bc7-rgba-unorm-srgb", "etc2-rgb8unorm", "etc2-rgb8unorm-srgb", "etc2-rgb8a1unorm", "etc2-rgb8a1unorm-srgb", "etc2-rgba8unorm", "etc2-rgba8unorm-srgb", "eac-r11unorm", "eac-r11snorm", "eac-rg11unorm", "eac-rg11snorm", "astc-4x4-unorm", "astc-4x4-unorm-srgb", "astc-5x4-unorm", "astc-5x4-unorm-srgb", "astc-5x5-unorm", "astc-5x5-unorm-srgb", "astc-6x5-unorm", "astc-6x5-unorm-srgb", "astc-6x6-unorm", "astc-6x6-unorm-srgb", "astc-8x5-unorm", "astc-8x5-unorm-srgb", "astc-8x6-unorm", "astc-8x6-unorm-srgb", "astc-8x8-unorm", "astc-8x8-unorm-srgb", "astc-10x5-unorm", "astc-10x5-unorm-srgb", "astc-10x6-unorm", "astc-10x6-unorm-srgb", "astc-10x8-unorm", "astc-10x8-unorm-srgb", "astc-10x10-unorm", "astc-10x10-unorm-srgb", "astc-12x10-unorm", "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb", ], - QueryType: ["occlusion", "timestamp", ], - VertexStepMode: ["vertex", "instance", "vertex-buffer-not-used", ], - VertexFormat: [undefined, "uint8x2", "uint8x4", "sint8x2", "sint8x4", "unorm8x2", "unorm8x4", "snorm8x2", "snorm8x4", "uint16x2", "uint16x4", "sint16x2", "sint16x4", "unorm16x2", "unorm16x4", "snorm16x2", "snorm16x4", "float16x2", "float16x4", "float32", "float32x2", "float32x3", "float32x4", "uint32", "uint32x2", "uint32x3", "uint32x4", "sint32", "sint32x2", "sint32x3", "sint32x4", ], - PrimitiveTopology: ["point-list", "line-list", "line-strip", "triangle-list", "triangle-strip", ], - IndexFormat: [undefined, "uint16", "uint32", ], - FrontFace: ["ccw", "cw", ], - CullMode: ["none", "front", "back", ], - AddressMode: ["repeat", "mirror-repeat", "clamp-to-edge", ], - FilterMode: ["nearest", "linear", ], - MipmapFilterMode: ["nearest", "linear", ], - CompareFunction: [undefined, "never", "less", "less-equal", "greater", "greater-equal", "equal", "not-equal", "always", ], - TextureDimension: ["1d", "2d", "3d", ], - ErrorType: ["no-error", "validation", "out-of-memory", "internal", "unknown", "device-lost", ], - WGSLFeatureName: [undefined, "readonly_and_readwrite_storage_textures", "packed_4x8_integer_dot_product", "unrestricted_pointer_parameters", "pointer_composite_access", ], - PowerPreference: [undefined, "low-power", "high-performance", ], - CompositeAlphaMode: ["auto", "opaque", "premultiplied", "unpremultiplied", "inherit", ], - StencilOperation: ["keep", "zero", "replace", "invert", "increment-clamp", "decrement-clamp", "increment-wrap", "decrement-wrap", ], - BlendOperation: ["add", "subtract", "reverse-subtract", "min", "max", ], - BlendFactor: ["zero", "one", "src", "one-minus-src", "src-alpha", "one-minus-src-alpha", "dst", "one-minus-dst", "dst-alpha", "one-minus-dst-alpha", "src-alpha-saturated", "constant", "one-minus-constant", ], - PresentMode: ["fifo", "fifo-relaxed", "immediate", "mailbox", ], - TextureAspect: ["all", "stencil-only", "depth-only"], - DeviceLostReason: [undefined, "unknown", "destroyed"], + this.sizes = { + Color: [32, 8], + BufferBindingLayout: [24, 8], + SamplerBindingLayout: [8, 4], + TextureBindingLayout: [16, 4], + StorageTextureBindingLayout: [16, 4], + StringView: [2*this.mem.intSize, this.mem.intSize], + ConstantEntry: [this.mem.intSize === 8 ? 32 : 24, 8], + ProgrammableStageDescriptor: [8 + this.mem.intSize*4, this.mem.intSize], + VertexBufferLayout: [16 + this.mem.intSize*2, 8], + VertexAttribute: [24, 8], + VertexState: [8 + this.mem.intSize*6, this.mem.intSize], + PrimitiveState: [24, 4], + MultisampleState: [16, 4], + StencilFaceState: [16, 4], + ColorTargetState: [24, 8], + BlendComponent: [12, 4], + TexelCopyBufferLayout: [16, 8], + Origin3D: [12, 4], + QueueDescriptor: [this.mem.intSize*3, this.mem.intSize], + CallbackInfo: [20, 4], + UncapturedErrorCallbackInfo: [16, 4], + RenderPassColorAttachment: [56, 8], + BindGroupEntry: [40, 8], + BindGroupLayoutEntry: [80, 8], + Extent3D: [12, 4], + CompilationMessage: [this.mem.intSize == 8 ? 64 : 48, 8], }; /** @type {WebGPUObjectManager<{}>} */ @@ -112,6 +157,29 @@ class WebGPUInterface { /** @type {WebGPUObjectManager} */ this.textureViews = new WebGPUObjectManager("TextureView", this.mem); + + this.zeroMessageAddr = 0; + } + + struct(start) { + let offset = start; + + return (size, alignment = null) => { + if (alignment === null) { + if (Array.isArray(size)) { + [size, alignment] = size; + } else { + alignment = size; + } + } + + // Align the offset to the required boundary + offset = Math.ceil(offset / alignment) * alignment; + let currentOffset = offset; + offset += size; + + return currentOffset; + }; } /** @@ -189,18 +257,18 @@ class WebGPUInterface { */ enumeration(name, ptr) { const int = this.mem.loadI32(ptr); - this.assert(this.enums[name], `Unknown enumeration "${name}"`); - return this.enums[name][int]; + return ENUMS[name][int]; } /** * @param {GPUSupportedFeatures} features * @param {number} ptr - * @returns {BigInt|number} */ - genericEnumerateFeatures(features, ptr) { + genericGetFeatures(features, ptr) { + this.assert(ptr != 0); + const availableFeatures = []; - this.enums.FeatureName.forEach((feature, value) => { + ENUMS.FeatureName.forEach((feature, value) => { if (!feature) { return; } @@ -210,57 +278,86 @@ class WebGPUInterface { } }); - if (ptr != 0) { - for (let i = 0; i < availableFeatures.length; i += 1) { - this.mem.storeI32(ptr + (i * 4), availableFeatures[i]); - } + if (availableFeatures.length === 0) { + return; } - return this.uint(availableFeatures.length); + const featuresAddr = this.mem.exports.wgpu_alloc(availableFeatures.length * 4); + this.assert(featuresAddr != 0); + + let off = this.struct(ptr); + this.mem.storeUint(off(this.mem.intSize), availableFeatures.length); + this.mem.storeI32(off(4), featuresAddr); + + off = this.struct(featuresAddr); + for (let i = 0; i < availableFeatures.length; i += 1) { + this.mem.storeI32(off(4), availableFeatures[i]); + } } /** * @param {GPUSupportedLimits} limits * @param {number} ptr + * @returns {number} */ genericGetLimits(limits, supportedLimitsPtr) { this.assert(supportedLimitsPtr != 0); - const limitsPtr = supportedLimitsPtr + 8; - this.mem.storeU32(limitsPtr + 0, limits.maxTextureDimension1D); - this.mem.storeU32(limitsPtr + 4, limits.maxTextureDimension2D); - this.mem.storeU32(limitsPtr + 8, limits.maxTextureDimension3D); - this.mem.storeU32(limitsPtr + 12, limits.maxTextureArrayLayers); - this.mem.storeU32(limitsPtr + 16, limits.maxBindGroups); - this.mem.storeU32(limitsPtr + 20, limits.maxBindGroupsPlusVertexBuffers); - this.mem.storeU32(limitsPtr + 24, limits.maxBindingsPerBindGroup); - this.mem.storeU32(limitsPtr + 28, limits.maxDynamicUniformBuffersPerPipelineLayout); - this.mem.storeU32(limitsPtr + 32, limits.maxDynamicStorageBuffersPerPipelineLayout); - this.mem.storeU32(limitsPtr + 36, limits.maxSampledTexturesPerShaderStage); - this.mem.storeU32(limitsPtr + 40, limits.maxSamplersPerShaderStage); - this.mem.storeU32(limitsPtr + 44, limits.maxStorageBuffersPerShaderStage); - this.mem.storeU32(limitsPtr + 48, limits.maxStorageTexturesPerShaderStage); - this.mem.storeU32(limitsPtr + 52, limits.maxUniformBuffersPerShaderStage); - this.mem.storeU64(limitsPtr + 56, limits.maxUniformBufferBindingSize); - this.mem.storeU64(limitsPtr + 64, limits.maxStorageBufferBindingSize); - this.mem.storeU32(limitsPtr + 72, limits.minUniformBufferOffsetAlignment); - this.mem.storeU32(limitsPtr + 76, limits.minStorageBufferOffsetAlignment); - this.mem.storeU32(limitsPtr + 80, limits.maxVertexBuffers); - this.mem.storeU64(limitsPtr + 88, limits.maxBufferSize); - this.mem.storeU32(limitsPtr + 96, limits.maxVertexAttributes); - this.mem.storeU32(limitsPtr + 100, limits.maxVertexBufferArrayStride); - this.mem.storeU32(limitsPtr + 104, limits.maxInterStageShaderComponents); - this.mem.storeU32(limitsPtr + 108, limits.maxInterStageShaderVariables); - this.mem.storeU32(limitsPtr + 112, limits.maxColorAttachments); - this.mem.storeU32(limitsPtr + 116, limits.maxColorAttachmentBytesPerSample); - this.mem.storeU32(limitsPtr + 120, limits.maxComputeWorkgroupStorageSize); - this.mem.storeU32(limitsPtr + 124, limits.maxComputeInvocationsPerWorkgroup); - this.mem.storeU32(limitsPtr + 128, limits.maxComputeWorkgroupSizeX); - this.mem.storeU32(limitsPtr + 132, limits.maxComputeWorkgroupSizeY); - this.mem.storeU32(limitsPtr + 136, limits.maxComputeWorkgroupSizeZ); - this.mem.storeU32(limitsPtr + 140, limits.maxComputeWorkgroupsPerDimension); + const off = this.struct(supportedLimitsPtr); + off(4); - return true; + this.mem.storeU32(off(4), limits.maxTextureDimension1D); + this.mem.storeU32(off(4), limits.maxTextureDimension2D); + this.mem.storeU32(off(4), limits.maxTextureDimension3D); + this.mem.storeU32(off(4), limits.maxTextureArrayLayers); + this.mem.storeU32(off(4), limits.maxBindGroups); + this.mem.storeU32(off(4), limits.maxBindGroupsPlusVertexBuffers); + this.mem.storeU32(off(4), limits.maxBindingsPerBindGroup); + this.mem.storeU32(off(4), limits.maxDynamicUniformBuffersPerPipelineLayout); + this.mem.storeU32(off(4), limits.maxDynamicStorageBuffersPerPipelineLayout); + this.mem.storeU32(off(4), limits.maxSampledTexturesPerShaderStage); + this.mem.storeU32(off(4), limits.maxSamplersPerShaderStage); + this.mem.storeU32(off(4), limits.maxStorageBuffersPerShaderStage); + this.mem.storeU32(off(4), limits.maxStorageTexturesPerShaderStage); + this.mem.storeU32(off(4), limits.maxUniformBuffersPerShaderStage); + this.mem.storeU64(off(8), limits.maxUniformBufferBindingSize); + this.mem.storeU64(off(8), limits.maxStorageBufferBindingSize); + this.mem.storeU32(off(4), limits.minUniformBufferOffsetAlignment); + this.mem.storeU32(off(4), limits.minStorageBufferOffsetAlignment); + this.mem.storeU32(off(4), limits.maxVertexBuffers); + this.mem.storeU64(off(8), limits.maxBufferSize); + this.mem.storeU32(off(4), limits.maxVertexAttributes); + this.mem.storeU32(off(4), limits.maxVertexBufferArrayStride); + this.mem.storeU32(off(4), limits.maxInterStageShaderVariables); + this.mem.storeU32(off(4), limits.maxColorAttachments); + this.mem.storeU32(off(4), limits.maxColorAttachmentBytesPerSample); + this.mem.storeU32(off(4), limits.maxComputeWorkgroupStorageSize); + this.mem.storeU32(off(4), limits.maxComputeInvocationsPerWorkgroup); + this.mem.storeU32(off(4), limits.maxComputeWorkgroupSizeX); + this.mem.storeU32(off(4), limits.maxComputeWorkgroupSizeY); + this.mem.storeU32(off(4), limits.maxComputeWorkgroupSizeZ); + this.mem.storeU32(off(4), limits.maxComputeWorkgroupsPerDimension); + + return STATUS_SUCCESS; + } + + genericAdapterInfo(infoPtr) { + this.assert(infoPtr != 0); + + const off = this.struct(infoPtr); + off(4); // nextInChain + off(this.sizes.StringView); // vendor + off(this.sizes.StringView); // architecture + off(this.sizes.StringView); // device + off(this.sizes.StringView); // description + + this.mem.storeI32(off(4), ENUMS.BackendType.indexOf("WebGPU")); + this.mem.storeI32(off(4), ENUMS.AdapterType.indexOf("Unknown")); + + // NOTE: I don't think getting the other fields in this struct is possible. + // `adapter.requestAdapterInfo` is deprecated. + + return STATUS_SUCCESS; } /** @@ -276,7 +373,7 @@ class WebGPUInterface { * @returns {GPUFeatureName} */ FeatureName(featureInt) { - return this.enums.FeatureName[featureInt]; + return ENUMS.FeatureName[featureInt]; } /** @@ -314,39 +411,41 @@ class WebGPUInterface { return undefined; }; + const off = this.struct(start); + off(4); + return { - maxTextureDimension1D: limitU32(start + 0), - maxTextureDimension2D: limitU32(start + 4), - maxTextureDimension3D: limitU32(start + 8), - maxTextureArrayLayers: limitU32(start + 12), - maxBindGroups: limitU32(start + 16), - maxBindGroupsPlusVertexBuffers: limitU32(start + 20), - maxBindingsPerBindGroup: limitU32(start + 24), - maxDynamicUniformBuffersPerPipelineLayout: limitU32(start + 28), - maxDynamicStorageBuffersPerPipelineLayout: limitU32(start + 32), - maxSampledTexturesPerShaderStage: limitU32(start + 36), - maxSamplersPerShaderStage: limitU32(start + 40), - maxStorageBuffersPerShaderStage: limitU32(start + 44), - maxStorageTexturesPerShaderStage: limitU32(start + 48), - maxUniformBuffersPerShaderStage: limitU32(start + 52), - maxUniformBufferBindingSize: limitU64(start + 56), - maxStorageBufferBindingSize: limitU64(start + 64), - minUniformBufferOffsetAlignment: limitU32(start + 72), - minStorageBufferOffsetAlignment: limitU32(start + 76), - maxVertexBuffers: limitU32(start + 80), - maxBufferSize: limitU64(start + 88), - maxVertexAttributes: limitU32(start + 96), - maxVertexBufferArrayStride: limitU32(start + 100), - maxInterStageShaderComponents: limitU32(start + 104), - maxInterStageShaderVariables: limitU32(start + 108), - maxColorAttachments: limitU32(start + 112), - maxColorAttachmentBytesPerSample: limitU32(start + 116), - maxComputeWorkgroupStorageSize: limitU32(start + 120), - maxComputeInvocationsPerWorkgroup: limitU32(start + 124), - maxComputeWorkgroupSizeX: limitU32(start + 128), - maxComputeWorkgroupSizeY: limitU32(start + 132), - maxComputeWorkgroupSizeZ: limitU32(start + 136), - maxComputeWorkgroupsPerDimension: limitU32(start + 140), + maxTextureDimension1D: limitU32(off(4)), + maxTextureDimension2D: limitU32(off(4)), + maxTextureDimension3D: limitU32(off(4)), + maxTextureArrayLayers: limitU32(off(4)), + maxBindGroups: limitU32(off(4)), + maxBindGroupsPlusVertexBuffers: limitU32(off(4)), + maxBindingsPerBindGroup: limitU32(off(4)), + maxDynamicUniformBuffersPerPipelineLayout: limitU32(off(4)), + maxDynamicStorageBuffersPerPipelineLayout: limitU32(off(4)), + maxSampledTexturesPerShaderStage: limitU32(off(4)), + maxSamplersPerShaderStage: limitU32(off(4)), + maxStorageBuffersPerShaderStage: limitU32(off(4)), + maxStorageTexturesPerShaderStage: limitU32(off(4)), + maxUniformBuffersPerShaderStage: limitU32(off(4)), + maxUniformBufferBindingSize: limitU64(off(8)), + maxStorageBufferBindingSize: limitU64(off(8)), + minUniformBufferOffsetAlignment: limitU32(off(4)), + minStorageBufferOffsetAlignment: limitU32(off(4)), + maxVertexBuffers: limitU32(off(4)), + maxBufferSize: limitU64(off(8)), + maxVertexAttributes: limitU32(off(4)), + maxVertexBufferArrayStride: limitU32(off(4)), + maxInterStageShaderVariables: limitU32(off(4)), + maxColorAttachments: limitU32(off(4)), + maxColorAttachmentBytesPerSample: limitU32(off(4)), + maxComputeWorkgroupStorageSize: limitU32(off(4)), + maxComputeInvocationsPerWorkgroup: limitU32(off(4)), + maxComputeWorkgroupSizeX: limitU32(off(4)), + maxComputeWorkgroupSizeY: limitU32(off(4)), + maxComputeWorkgroupSizeZ: limitU32(off(4)), + maxComputeWorkgroupsPerDimension: limitU32(off(4)), }; } @@ -356,7 +455,7 @@ class WebGPUInterface { */ QueueDescriptor(start) { return { - label: this.mem.loadCstring(start + 4), + label: this.StringView(start + 4), }; } @@ -370,10 +469,11 @@ class WebGPUInterface { return undefined; } + const off = this.struct(start); return { - querySet: this.querySets.get(this.mem.loadPtr(start + 0)), - beginningOfPassWriteIndex: this.mem.loadU32(start + 4), - endOfPassWriteIndex: this.mem.loadU32(start + 8), + querySet: this.querySets.get(this.mem.loadPtr(off(4))), + beginningOfPassWriteIndex: this.mem.loadU32(off(4)), + endOfPassWriteIndex: this.mem.loadU32(off(4)), }; } @@ -382,21 +482,25 @@ class WebGPUInterface { * @returns {GPURenderPassColorAttachment} */ RenderPassColorAttachment(start) { - const viewIdx = this.mem.loadPtr(start + 4); - const resolveTargetIdx = this.mem.loadPtr(start + 12); + const off = this.struct(start); + off(4); - let depthSlice = this.mem.loadU32(start + 8); + const viewIdx = this.mem.loadPtr(off(4)); + + let depthSlice = this.mem.loadU32(off(4)); if (depthSlice == 0xFFFFFFFF) { // DEPTH_SLICE_UNDEFINED. depthSlice = undefined; } + const resolveTargetIdx = this.mem.loadPtr(off(4)); + return { view: viewIdx > 0 ? this.textureViews.get(viewIdx) : undefined, resolveTarget: resolveTargetIdx > 0 ? this.textureViews.get(resolveTargetIdx) : undefined, depthSlice: depthSlice, - loadOp: this.enumeration("LoadOp", start + 16), - storeOp: this.enumeration("StoreOp", start + 20), - clearValue: this.Color(start + 24), + loadOp: this.enumeration("LoadOp", off(4)), + storeOp: this.enumeration("StoreOp", off(4)), + clearValue: this.Color(off(this.sizes.Color)), }; } @@ -405,11 +509,12 @@ class WebGPUInterface { * @returns {GPUColor} */ Color(start) { + const off = this.struct(start); return { - r: this.mem.loadF64(start + 0), - g: this.mem.loadF64(start + 8), - b: this.mem.loadF64(start + 16), - a: this.mem.loadF64(start + 24), + r: this.mem.loadF64(off(8)), + g: this.mem.loadF64(off(8)), + b: this.mem.loadF64(off(8)), + a: this.mem.loadF64(off(8)), }; } @@ -423,16 +528,18 @@ class WebGPUInterface { return undefined; } + const off = this.struct(ptr); + return { - view: this.textureViews.get(this.mem.loadPtr(start + 0)), - depthLoadOp: this.enumeration("LoadOp", start + 4), - depthStoreOp: this.enumeration("StoreOp", start + 8), - depthClearValue: this.mem.loadF32(start + 12), - depthReadOnly: this.mem.loadB32(start + 16), - stencilLoadOp: this.enumeration("LoadOp", start + 20), - stencilStoreOp: this.enumeration("StoreOp", start + 24), - stencilClearValue: this.mem.loadF32(start + 28), - stencilReadOnly: this.mem.loadB32(start + 32), + view: this.textureViews.get(this.mem.loadPtr(off(4))), + depthLoadOp: this.enumeration("LoadOp", off(4)), + depthStoreOp: this.enumeration("StoreOp", off(4)), + depthClearValue: this.mem.loadF32(off(4)), + depthReadOnly: this.mem.loadB32(off(4)), + stencilLoadOp: this.enumeration("LoadOp", off(4)), + stencilStoreOp: this.enumeration("StoreOp", off(4)), + stencilClearValue: this.mem.loadF32(off(4)), + stencilReadOnly: this.mem.loadB32(off(4)), }; } @@ -457,42 +564,6 @@ class WebGPUInterface { return this.ComputePassTimestampWritesPtr(ptr); } - /** - * @param {number} start - * @returns {GPUImageDataLayout} - */ - TextureDataLayout(start) { - return { - offset: this.mem.loadU64(start + 8), - bytesPerRow: this.mem.loadU32(start + 16), - rowsPerImage: this.mem.loadU32(start + 20), - }; - } - - /** - * @param {number} start - * @returns {GPUImageCopyBuffer} - */ - ImageCopyBuffer(start) { - return { - ...this.TextureDataLayout(start + 8), - buffer: this.buffers.get(this.mem.loadPtr(start + 32)).buffer, - }; - } - - /** - * @param {number} start - * @returns {GPUImageCopyTexture} - */ - ImageCopyTexture(start) { - return { - texture: this.textures.get(this.mem.loadPtr(start + 4)), - mipLevel: this.mem.loadU32(start + 8), - origin: this.Origin3D(start + 12), - aspect: this.enumeration("TextureAspect", start + 24), - }; - } - /** * @param {number} start * @returns {GPUOrigin3D} @@ -551,13 +622,16 @@ class WebGPUInterface { * @returns {GPUBindGroupLayoutEntry} */ BindGroupLayoutEntry(start) { + const off = this.struct(start); + off(4); + const entry = { - binding: this.mem.loadU32(start + 4), - visibility: this.mem.loadU32(start + 8), - buffer: this.BufferBindingLayout(start + 16), - sampler: this.SamplerBindingLayout(start + 40), - texture: this.TextureBindingLayout(start + 48), - storageTexture: this.StorageTextureBindingLayout(start + 64), + binding: this.mem.loadU32(off(4)), + visibility: this.mem.loadU64(off(8)), + buffer: this.BufferBindingLayout(off(this.sizes.BufferBindingLayout)), + sampler: this.SamplerBindingLayout(off(this.sizes.SamplerBindingLayout)), + texture: this.TextureBindingLayout(off(this.sizes.TextureBindingLayout)), + storageTexture: this.StorageTextureBindingLayout(off(this.sizes.StorageTextureBindingLayout)), }; if (!entry.buffer.type) { entry.buffer = undefined; @@ -625,15 +699,22 @@ class WebGPUInterface { * @returns {GPUProgrammableStage} */ ProgrammableStageDescriptor(start) { + const off = this.struct(start); + off(4); + + const shaderModule = this.shaderModules.get(this.mem.loadPtr(off(4))); + const entryPoint = this.StringView(off(this.sizes.StringView)); + const constantsArray = this.array( - this.mem.loadUint(start + 8 + this.mem.intSize), - this.mem.loadPtr(start + 8 + this.mem.intSize*2), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.ConstantEntry, - 16, + this.sizes.ConstantEntry[0], ); + return { - module: this.shaderModules.get(this.mem.loadPtr(start + 4)), - entryPoint: this.mem.loadCstring(start + 8), + module: shaderModule, + entryPoint: entryPoint, constants: constantsArray.reduce((prev, curr) => { prev[curr.key] = curr.value; return prev; @@ -646,9 +727,12 @@ class WebGPUInterface { * @returns {{ key: string, value: number }} */ ConstantEntry(start) { + const off = this.struct(start); + off(4); + return { - key: this.mem.loadCstring(start + 4), - value: this.mem.loadF64(start + 8), + key: this.StringView(off(this.sizes.StringView)), + value: this.mem.loadF64(off(8)), }; } @@ -657,11 +741,15 @@ class WebGPUInterface { * @returns {GPUComputePipelineDescriptor} */ ComputePipelineDescriptor(start) { - const layoutIdx = this.mem.loadPtr(start + 8) + const off = this.struct(start); + off(4); + + const label = this.StringView(off(this.sizes.StringView)); + const layoutIdx = this.mem.loadPtr(off(4)); return { - label: this.mem.loadCstring(start + 4), - layout: layoutIdx > 0 ? this.pipelineLayouts.get(layoutIdx) : undefined, - compute: this.ProgrammableStageDescriptor(start + 8 + this.mem.intSize), + label: label, + layout: layoutIdx > 0 ? this.pipelineLayouts.get(layoutIdx) : "auto", + compute: this.ProgrammableStageDescriptor(off(this.sizes.ProgrammableStageDescriptor)), }; } @@ -670,28 +758,31 @@ class WebGPUInterface { * @returns {GPUVertexState} */ VertexState(start) { - let off = 8 + this.mem.intSize; + const off = this.struct(start); + off(4); + + const shaderModuleIdx = this.mem.loadPtr(off(4)); + const entryPoint = this.StringView(off(this.sizes.StringView)); + const constantsArray = this.array( - this.mem.loadUint(start + off), - this.mem.loadPtr(start + off + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.ConstantEntry, - 16, + this.sizes.ConstantEntry[0], ); - off += this.mem.intSize * 2; - return { - module: this.shaderModules.get(this.mem.loadPtr(start + 4)), - entryPoint: this.mem.loadCstring(start + 8), + module: this.shaderModules.get(shaderModuleIdx), + entryPoint: entryPoint, constants: constantsArray.reduce((prev, curr) => { prev[curr.key] = curr.value; return prev; }, {}), buffers: this.array( - this.mem.loadUint(start + off), - this.mem.loadPtr(start + off + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.VertexBufferLayout, - this.mem.intSize == 8 ? 32 : 24, + this.sizes.VertexBufferLayout[0], ), }; } @@ -701,18 +792,21 @@ class WebGPUInterface { * @returns {?GPUVertexBufferLayout} */ VertexBufferLayout(start) { - const stepMode = this.enumeration("VertexStepMode", start + 8); - if (stepMode == "vertex-buffer-not-used") { + const off = this.struct(start); + + const stepMode = this.enumeration("VertexStepMode", off(4)); + if (stepMode == null) { return null; } + return { - arrayStride: this.mem.loadU64(start + 0), + arrayStride: this.mem.loadU64(off(8)), stepMode: stepMode, attributes: this.array( - this.mem.loadUint(start + 8 + this.mem.intSize), - this.mem.loadPtr(start + 8 + this.mem.intSize*2), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.VertexAttribute, - 24, + this.sizes.VertexAttribute[0], ), }; } @@ -722,10 +816,11 @@ class WebGPUInterface { * @returns {GPUVertexAttribute} */ VertexAttribute(start) { + const off = this.struct(start); return { - format: this.enumeration("VertexFormat", start + 0), - offset: this.mem.loadU64(start + 8), - shaderLocation: this.mem.loadU32(start + 16), + format: this.enumeration("VertexFormat", off(4)), + offset: this.mem.loadU64(off(8)), + shaderLocation: this.mem.loadU32(off(4)), }; } @@ -734,22 +829,15 @@ class WebGPUInterface { * @returns {GPUPrimitiveState} */ PrimitiveState(start) { - let unclippedDepth = undefined; - const nextInChain = this.mem.loadPtr(start); - if (nextInChain != 0) { - const nextInChainType = this.mem.loadI32(nextInChain + 4); - // PrimitiveDepthClipControl = 0x00000007, - if (nextInChainType == 7) { - unclippedDepth = this.mem.loadB32(nextInChain + 8); - } - } + const off = this.struct(start); + off(4); return { - topology: this.enumeration("PrimitiveTopology", start + 4), - stripIndexFormat: this.enumeration("IndexFormat", start + 8), - frontFace: this.enumeration("FrontFace", start + 12), - cullMode: this.enumeration("CullMode", start + 16), - unclippedDepth: unclippedDepth, + topology: this.enumeration("PrimitiveTopology", off(4)), + stripIndexFormat: this.enumeration("IndexFormat", off(4)), + frontFace: this.enumeration("FrontFace", off(4)), + cullMode: this.enumeration("CullMode", off(4)), + unclippedDepth: this.mem.loadB32(off(4)), }; } @@ -758,27 +846,19 @@ class WebGPUInterface { * @returns {GPURenderPipelineDescriptor} */ RenderPipelineDescriptor(start) { - const layoutIdx = this.mem.loadPtr(start + 8); - const offs = this.mem.intSize == 8 ? [64, 84, 88, 104] : [40, 60, 64, 80]; - return { - label: this.mem.loadCstring(start + 4), - layout: layoutIdx > 0 ? this.pipelineLayouts.get(layoutIdx) : undefined, - vertex: this.VertexState(start + 8 + this.mem.intSize), - primitive: this.PrimitiveState(start + offs[0]), - depthStencil: this.DepthStencilStatePtr(start + offs[1]), - multisample: this.MultisampleState(start + offs[2]), - fragment: this.FragmentStatePtr(start + offs[3]), - }; - } + const off = this.struct(start); + off(4); - /** - * @param {number} start - * @returns {GPUShaderModuleCompilationHint} - */ - ShaderModuleCompilationHint(start) { + const label = this.StringView(off(this.sizes.StringView)); + const layoutIdx = this.mem.loadPtr(off(4)); return { - entryPoint: this.mem.loadCstring(start + 4), - layout: this.pipelineLayouts.get(this.mem.loadPtr(start + 8)), + label: label, + layout: layoutIdx > 0 ? this.pipelineLayouts.get(layoutIdx) : "auto", + vertex: this.VertexState(off(this.sizes.VertexState)), + primitive: this.PrimitiveState(off(this.sizes.PrimitiveState)), + depthStencil: this.DepthStencilStatePtr(off(4)), + multisample: this.MultisampleState(off(this.sizes.MultisampleState)), + fragment: this.FragmentStatePtr(off(4)), }; } @@ -792,17 +872,20 @@ class WebGPUInterface { return undefined; } + const off = this.struct(start); + off(4); + return { - format: this.enumeration("TextureFormat", start + 4), - depthWriteEnabled: this.mem.loadB32(start + 8), - depthCompare: this.enumeration("CompareFunction", start + 12), - stencilFront: this.StencilFaceState(start + 16), - stencilBack: this.StencilFaceState(start + 32), - stencilReadMask: this.mem.loadU32(start + 48), - stencilWriteMask: this.mem.loadU32(start + 52), - depthBias: this.mem.loadI32(start + 56), - depthBiasSlopeScale: this.mem.loadF32(start + 60), - depthBiasClamp: this.mem.loadF32(start + 64), + format: this.enumeration("TextureFormat", off(4)), + depthWriteEnabled: this.enumeration("OptionalBool", off(4)), + depthCompare: this.enumeration("CompareFunction", off(4)), + stencilFront: this.StencilFaceState(off(this.sizes.StencilFaceState)), + stencilBack: this.StencilFaceState(off(this.sizes.StencilFaceState)), + stencilReadMask: this.mem.loadU32(off(4)), + stencilWriteMask: this.mem.loadU32(off(4)), + depthBias: this.mem.loadI32(off(4)), + depthBiasSlopeScale: this.mem.loadF32(off(4)), + depthBiasClamp: this.mem.loadF32(off(4)), }; } @@ -841,29 +924,31 @@ class WebGPUInterface { return undefined; } - let off = 8 + this.mem.intSize; + const off = this.struct(start); + off(4); + + const shaderModule = this.shaderModules.get(this.mem.loadPtr(off(4))); + const entryPoint = this.StringView(off(this.sizes.StringView)); const constantsArray = this.array( - this.mem.loadUint(start + off), - this.mem.loadPtr(start + off + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.ConstantEntry, - 16, + this.sizes.ConstantEntry[0], ); - off += this.mem.intSize * 2; - return { - module: this.shaderModules.get(this.mem.loadPtr(start + 4)), - entryPoint: this.mem.loadCstring(start + 8), + module: shaderModule, + entryPoint: entryPoint, constants: constantsArray.reduce((prev, curr) => { prev[curr.key] = curr.value; return prev; }, {}), targets: this.array( - this.mem.loadUint(start + off), - this.mem.loadPtr(start + off + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.ColorTargetState, - 16, + this.sizes.ColorTargetState[0], ), }; } @@ -873,10 +958,12 @@ class WebGPUInterface { * @returns {GPUColorTargetState} */ ColorTargetState(start) { + const off = this.struct(start); + off(4); return { - format: this.enumeration("TextureFormat", start + 4), - blend: this.BlendStatePtr(start + 8), - writeMask: this.mem.loadU32(start + 12), + format: this.enumeration("TextureFormat", off(4)), + blend: this.BlendStatePtr(off(4)), + writeMask: this.mem.loadU64(off(8)), }; } @@ -890,9 +977,11 @@ class WebGPUInterface { return undefined; } + const off = this.struct(start); + return { - color: this.BlendComponent(start + 0), - alpha: this.BlendComponent(start + 12), + color: this.BlendComponent(off(this.sizes.BlendComponent)), + alpha: this.BlendComponent(off(this.sizes.BlendComponent)), }; } @@ -908,6 +997,108 @@ class WebGPUInterface { }; } + TexelCopyBufferInfo(start) { + const off = this.struct(start); + const layout = this.TexelCopyBufferLayout(off(this.sizes.TexelCopyBufferLayout)); + const bufferIdx = this.mem.loadPtr(off(4)); + return { + buffer: this.buffers.get(bufferIdx).buffer, + offset: layout.offset, + bytesPerRow: layout.bytesPerRow, + rowsPerImage: layout.rowsPerImage, + }; + } + + TexelCopyBufferLayout(start) { + const off = this.struct(start); + return { + offset: this.mem.loadU64(off(8)), + bytesPerRow: this.mem.loadU32(off(4)), + rowsPerImage: this.mem.loadU32(off(4)), + }; + } + + TexelCopyTextureInfo(start) { + const off = this.struct(start); + return { + texture: this.textures.get(this.mem.loadPtr(off(4))), + mipLevel: this.mem.loadU32(off(4)), + origin: this.Origin3D(off(this.sizes.Origin3D)), + aspect: this.enumeration("TextureAspect", off(4)), + }; + } + + StringView(start) { + const data = this.mem.loadPtr(start); + return this.mem.loadString(data, this.mem.loadUint(start + this.mem.intSize)); + } + + CallbackInfoPtr(ptr) { + const start = this.mem.loadPtr(ptr); + if (start === 0) { + return null; + } + + return CallbackInfo(start); + } + + CallbackInfo(start) { + const off = this.struct(start); + off(4); + // TODO: callback mode? + off(4); + return { + callback: this.mem.exports.__indirect_function_table.get(this.mem.loadPtr(off(4))), + userdata1: this.mem.loadPtr(off(4)), + userdata2: this.mem.loadPtr(off(4)), + }; + } + + UncapturedErrorCallbackInfo(start) { + const off = this.struct(start); + off(4); + return { + callback: this.mem.exports.__indirect_function_table.get(this.mem.loadPtr(off(4))), + userdata1: this.mem.loadPtr(off(4)), + userdata2: this.mem.loadPtr(off(4)), + }; + } + + callCallback(callback, args) { + args.push(callback.userdata1); + args.push(callback.userdata2); + callback.callback(...args); + } + + zeroMessageArg() { + if (this.zeroMessageAddr > 0) { + return this.zeroMessageAddr; + } + + this.zeroMessageAddr = this.mem.exports.wgpu_alloc(this.sizes.StringView[0]); + return this.zeroMessageAddr; + } + + makeMessageArg(message) { + if (message.length == 0) { + return this.zeroMessageArg(); + } + + const messageLength = new TextEncoder().encode(message).length; + const stringSize = this.sizes.StringView[0]; + + const addr = this.mem.exports.wgpu_alloc(stringSize + messageLength); + + const messageAddr = addr + stringSize; + + this.mem.storeI32(addr, messageAddr); + this.mem.storeUint(addr + this.mem.intSize, messageLength); + + this.mem.storeString(messageAddr, message); + + return addr; + } + getInterface() { return { /** @@ -920,15 +1111,26 @@ class WebGPUInterface { return 0; } + // TODO: instance capabilities for futures? + return this.instances.create({}); }, /** - * @param {number} deviceIdx - * @param {number} procNamePtr + * @param {number} capabilitiesPtr * @returns {number} */ - wgpuGetProcAddress: (deviceIdx, procNamePtr) => { + wgpuGetInstanceCapabilities: (capabilitiesPtr) => { + // TODO: implement (futures). + return STATUS_ERROR; + }, + + /** + * @param {number} procNamePtr + * @param {number} procNameLen + * @returns {number} + */ + wgpuGetProcAddress: (procNamePtr, procNameLen) => { console.error(`unimplemented: wgpuGetProcAddress`); return 0; }, @@ -938,44 +1140,29 @@ class WebGPUInterface { /** * @param {number} adapterIdx * @param {number} featuresPtr - * @returns {number|BigInt} */ - wgpuAdapterEnumerateFeatures: (adapterIdx, featuresPtr) => { + wgpuAdapterGetFeatures: (adapterIdx, featuresPtr) => { const adapter = this.adapters.get(adapterIdx); - return this.genericEnumerateFeatures(adapter.features, featuresPtr); - }, - - /** - * @param {number} adapterIdx - * @param {number} supportedLimitsPtr - * @returns {boolean} - */ - wgpuAdapterGetLimits: (adapterIdx, supportedLimitsPtr) => { - const adapter = this.adapters.get(adapterIdx); - return this.genericGetLimits(adapter.limits, supportedLimitsPtr); + this.genericGetFeatures(adapter.features, featuresPtr); }, /** * @param {number} adapterIdx * @param {number} infoPtr + * @returns {number} */ wgpuAdapterGetInfo: (adapterIdx, infoPtr) => { - this.assert(infoPtr != 0); - - // WebGPU backend. - this.mem.storeI32(infoPtr + 20, 2); - // Unknown adapter. - this.mem.storeI32(infoPtr + 24, 3); - - // NOTE: I don't think getting the other fields in this struct is possible. - // `adapter.requestAdapterInfo` is deprecated. + return this.genericGetAdapterInfo(infoPtr); }, /** - * @param {number} infoPtr + * @param {number} adapterIdx + * @param {number} limitsPtr + * @returns {number} */ - wgpuAdapterInfoFreeMembers: (infoPtr) => { - // NOTE: nothing to free. + wgpuAdapterGetLimits: (adapterIdx, limitsPtr) => { + const adapter = this.adapters.get(adapterIdx); + return this.genericGetLimits(adapter.limits, limitsPtr); }, /** @@ -985,105 +1172,101 @@ class WebGPUInterface { */ wgpuAdapterHasFeature: (adapterIdx, featureInt) => { const adapter = this.adapters.get(adapterIdx); - return adapter.features.has(this.enums.FeatureName[featureInt]); + return adapter.features.has(ENUMS.FeatureName[featureInt]); }, /** * @param {number} adapterIdx * @param {0|number} descriptorPtr - * @param {number} callbackPtr - * @param {0|number} userdata + * @param {number} callbackInfoPtr + * @return {number} */ - wgpuAdapterRequestDevice: async (adapterIdx, descriptorPtr, callbackPtr, userdata) => { + wgpuAdapterRequestDevice: (adapterIdx, descriptorPtr, callbackInfoPtr) => { const adapter = this.adapters.get(adapterIdx); - const callback = this.mem.exports.__indirect_function_table.get(callbackPtr); + + const off = this.struct(descriptorPtr); + off(4); /** @type {GPUDeviceDescriptor} */ let descriptor; if (descriptorPtr != 0) { descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), + label: this.StringView(off(this.sizes.StringView)), requiredFeatures: this.array( - this.mem.loadUint(descriptorPtr + 8), - this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.FeatureNamePtr, 4, ), - requiredLimits: this.RequiredLimitsPtr(descriptorPtr + 8 + this.mem.intSize + 4), - defaultQueue: this.QueueDescriptor( descriptorPtr + 8 + this.mem.intSize + 4 + 4), + requiredLimits: this.RequiredLimitsPtr(off(4)), + defaultQueue: this.QueueDescriptor(off(this.sizes.QueueDescriptor)), }; } - let device; - let deviceIdx; - try { - device = await adapter.requestDevice(descriptor); - deviceIdx = this.devices.create(device); - // NOTE: don't callback here, any errors that happen later will then be caught by the catch here. - } catch (e) { - const messageLength = new TextEncoder().encode(e.message).length; - const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1); - this.mem.storeString(messageAddr, e.message); + const callbackInfo = this.CallbackInfo(callbackInfoPtr); - callback(1, null, messageAddr, userdata); - - this.mem.exports.wgpu_free(messageAddr); - } - - let callbacksPtr = descriptorPtr + 24 + this.mem.intSize; - - const deviceLostCallbackPtr = this.mem.loadPtr(callbacksPtr); - if (deviceLostCallbackPtr != 0) { - const deviceLostUserData = this.mem.loadPtr(callbacksPtr) + 4; - const deviceLostCallback = this.mem.exports.__indirect_function_table.get(deviceLostCallbackPtr); - - device.lost.then((info) => { - const reason = this.enums.DeviceLostReason.indexOf(info.reason); - - const messageLength = new TextEncoder().encode(info.message).length; - const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1); - this.mem.storeString(messageAddr, info.message); - - deviceLostCallback(reason, messageAddr, deviceLostUserData); + const deviceLostCallbackInfo = this.CallbackInfo(off(this.sizes.CallbackInfo)); + const uncapturedErrorCallbackInfo = this.UncapturedErrorCallbackInfo(off(this.sizes.UncapturedErrorCallbackInfo)); + adapter.requestDevice(descriptor) + .catch((e) => { + const messageAddr = this.makeMessageArg(e.message); + this.callCallback(callbackInfo, [ENUMS.RequestDeviceStatus.indexOf("Error"), messageAddr]); this.mem.exports.wgpu_free(messageAddr); - }); - } - callbacksPtr += 8; + }) + .then((device) => { + const deviceIdx = this.devices.create(device); - // Skip over `nextInChain`. - callbacksPtr += 4; + if (deviceLostCallbackInfo.callback !== null) { + device.lost.then((info) => { + const reason = ENUMS.DeviceLostReason.indexOf(info.reason); - const uncapturedErrorCallbackPtr = this.mem.loadPtr(callbacksPtr); - if (uncapturedErrorCallbackPtr != 0) { - const uncapturedErrorUserData = this.mem.loadPtr(callbacksPtr + 4); - const uncapturedErrorCallback = this.mem.exports.__indirect_function_table.get(uncapturedErrorCallbackPtr); + const devicePtr = this.mem.exports.wgpu_alloc(4); + this.mem.storeI32(devicePtr, deviceIdx); - device.onuncapturederror = (ev) => { - let status = 4; // Unknown - if (ev.error instanceof GPUValidationError) { - status = 1; // Validation - } else if (ev.error instanceof GPUOutOfMemoryError) { - status = 2; // OutOfMemory - } else if (ev.error instanceof GPUInternalError) { - status = 3; // Internal + const messageAddr = this.makeMessageArg(info.message); + this.callCallback(deviceLostCallbackInfo, [devicePtr, reason, messageAddr]); + + this.mem.exports.wgpu_free(devicePtr); + this.mem.exports.wgpu_free(messageAddr); + }); } - const messageLength = new TextEncoder().encode(ev.error.message).length; - const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1); - this.mem.storeString(messageAddr, ev.error.message); + if (uncapturedErrorCallbackInfo.callback !== null) { + device.onuncapturederror = (ev) => { + let status; + if (ev.error instanceof GPUValidationError) { + status = ENUMS.ErrorType.indexOf("validation"); + } else if (ev.error instanceof GPUOutOfMemoryError) { + status = ENUMS.ErrorType.indexOf("out-of-memory"); + } else if (ev.error instanceof GPUInternalError) { + status = ENUMS.ErrorType.indexOf("internal"); + } else { + status = ENUMS.ErrorType.indexOf("unknown"); + } - uncapturedErrorCallback(status, messageAddr, uncapturedErrorUserData); + const messageAddr = this.makeMessageArg(ev.error.message); + this.callCallback(uncapturedErrorCallbackInfo, [deviceIdx, status, messageAddr]); + this.mem.exports.wgpu_free(messageAddr); + }; + } - this.mem.exports.wgpu_free(messageAddr); - }; - } + this.callCallback(callbackInfo, [ENUMS.ErrorType.indexOf("no-error"), deviceIdx, this.zeroMessageArg()]); + }); - callback(0, deviceIdx, null, userdata); + // TODO: returning a future? WARN that requires refactor removing await + return BigInt(0); }, ...this.adapters.interface(), + /** + * @param {number} infoPtr + */ + wgpuAdapterInfoFreeMembers: (infoPtr) => { + // NOTE: nothing to free. + }, + /* ---------------------- BindGroup ---------------------- */ ...this.bindGroups.interface(true), @@ -1100,6 +1283,41 @@ class WebGPUInterface { buffer.buffer.destroy(); }, + /** + * @param {number} bufferIdx + * @param {number|BigInt} offset + * @param {number|BigInt} size + * @returns {number} + */ + wgpuBufferGetConstMappedRange: (bufferIdx, offset, size) => { + const buffer = this.buffers.get(bufferIdx); + offset = this.unwrapBigInt(offset); + size = this.unwrapBigInt(size); + + // TODO: does constMappedRange need to do something else? + + this.assert(!buffer.mapping, "buffer already mapped"); + + const range = buffer.buffer.getMappedRange(offset, size); + + const ptr = this.mem.exports.wgpu_alloc(range.byteLength); + + const mapping = new Uint8Array(this.mem.memory.buffer, ptr, size); + mapping.set(new Uint8Array(range)); + + buffer.mapping = { range: range, ptr: ptr, size: range.byteLength }; + return ptr; + }, + + /** + * @param {number} bufferIdx + * @return {number} + */ + wgpuBufferGetMapState: (bufferIdx) => { + const buffer = this.buffers.get(bufferIdx); + return ENUMS.BufferMapState.indexOf(buffer.mapState); + }, + /** * @param {number} bufferIdx * @param {number|BigInt} offset @@ -1117,6 +1335,9 @@ class WebGPUInterface { const ptr = this.mem.exports.wgpu_alloc(range.byteLength); + const mapping = new Uint8Array(this.mem.memory.buffer, ptr, size); + mapping.set(new Uint8Array(range)); + buffer.mapping = { range: range, ptr: ptr, size: range.byteLength }; return ptr; }, @@ -1144,44 +1365,38 @@ class WebGPUInterface { * @param {number} mode * @param {number|BigInt} offset * @param {number|BigInt} size - * @param {number} callbackPtr - * @param {0|number} userdata + * @param {number} callbackInfo + * @return {number} */ - wgpuBufferMapAsync: async (bufferIdx, mode, offset, size, callbackPtr, userdata) => { + wgpuBufferMapAsync: (bufferIdx, mode, offset, size, callbackInfoPtr) => { const buffer = this.buffers.get(bufferIdx); - const callback = this.mem.exports.__indirect_function_table.get(callbackPtr); + mode = this.unwrapBigInt(mode); offset = this.unwrapBigInt(offset); size = this.unwrapBigInt(size); - if (buffer.buffer.mapState == "pending") { - callback(this.enums.BufferMapAsyncStatus.MappingAlreadyPending, userdata); - } else { - let result; - try { - await buffer.buffer.mapAsync(mode, offset, size); - result = 0; // Success. - } catch(e) { - console.warn(e); - result = 2; // Unknown error. + const callbackInfo = this.CallbackInfo(callbackInfoPtr); + buffer.buffer.mapAsync(mode, offset, size) + .catch((e) => { + const messageAddr = this.makeMessageArg(e.message); + this.callCallback(callbackInfo, [ENUMS.MapAsyncStatus.indexOf("Error"), messageAddr]); + this.mem.exports.wgpu_free(messageAddr); + }) + .then(() => { + this.callCallback(callbackInfo, [ENUMS.MapAsyncStatus.indexOf("Success"), this.zeroMessageArg()]); + }); - if (e instanceof DomException) { - if (e.name == "OperationError") { - result = 1; // Validation error. - } - } - } - - callback(result, userdata); - } + // TODO: returning a future? WARN that requires refactor removing await + return BigInt(0); }, /** * @param {number} bufferIdx * @param {number} labelPtr + * @param {number} labelLen */ - wgpuBufferSetLabel: (bufferIdx, labelPtr) => { + wgpuBufferSetLabel: (bufferIdx, labelPtr, labelLen) => { const buffer = this.buffers.get(bufferIdx); - buffer.buffer.label = this.mem.loadCstringDirect(labelPtr); + buffer.buffer.label = this.mem.loadString(labelPtr, labelLen); }, /** @@ -1219,9 +1434,11 @@ class WebGPUInterface { /** @type {?GPUComputePassDescriptor} */ let descriptor; if (descriptorPtr != 0) { + const off = this.struct(descriptorPtr); + off(4); descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), - timestampWrites: this.ComputePassTimestampWritesPtr(descriptorPtr + 8), + label: this.StringView(off(this.sizes.StringView)), + timestampWrites: this.ComputePassTimestampWritesPtr(off(4)), }; } @@ -1238,28 +1455,30 @@ class WebGPUInterface { const commandEncoder = this.commandEncoders.get(commandEncoderIdx); this.assert(descriptorPtr != 0); + const off = this.struct(descriptorPtr); + let maxDrawCount = undefined; - const nextInChain = this.mem.loadPtr(descriptorPtr); + const nextInChain = this.mem.loadPtr(off(4)); if (nextInChain != 0) { const nextInChainType = this.mem.loadI32(nextInChain + 4); - // RenderPassDescriptorMaxDrawCount = 0x0000000F, - if (nextInChainType == 0x0000000F) { + // RenderPassMaxDrawCount = 0x00000003, + if (nextInChainType == 0x00000003) { maxDrawCount = this.mem.loadU64(nextInChain + 8); } } /** @type {GPURenderPassDescriptor} */ const descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), + label: this.StringView(off(this.sizes.StringView)), colorAttachments: this.array( - this.mem.loadUint(descriptorPtr + 8), - this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.RenderPassColorAttachment, - 56, + this.sizes.RenderPassColorAttachment[0], ), - depthStencilAttachment: this.RenderPassDepthStencilAttachmentPtr(descriptorPtr + 8 + this.mem.intSize + 4), - occlusionQuerySet: this.QuerySet(descriptorPtr + 8 + this.mem.intSize + 4 + 4), - timestampWrites: this.RenderPassTimestampWritesPtr(descriptorPtr + 8 + this.mem.intSize + 4 + 4), + depthStencilAttachment: this.RenderPassDepthStencilAttachmentPtr(off(4)), + occlusionQuerySet: this.QuerySet(off(4)), + timestampWrites: this.RenderPassTimestampWritesPtr(off(4)), maxDrawCount: maxDrawCount, }; @@ -1308,8 +1527,8 @@ class WebGPUInterface { wgpuCommandEncoderCopyBufferToTexture: (commandEncoderIdx, sourcePtr, destinationPtr, copySizePtr) => { const commandEncoder = this.commandEncoders.get(commandEncoderIdx); commandEncoder.copyBufferToTexture( - this.ImageCopyBuffer(sourcePtr), - this.ImageCopyTexture(destinationPtr), + this.TexelCopyBufferInfo(sourcePtr), + this.TexelCopyTextureInfo(destinationPtr), this.Extent3D(copySizePtr), ); }, @@ -1323,8 +1542,8 @@ class WebGPUInterface { wgpuCommandEncoderCopyTextureToBuffer: (commandEncoderIdx, sourcePtr, destinationPtr, copySizePtr) => { const commandEncoder = this.commandEncoders.get(commandEncoderIdx); commandEncoder.copyTextureToBuffer( - this.ImageCopyTexture(sourcePtr), - this.ImageCopyBuffer(destinationPtr), + this.TexelCopyTextureInfo(sourcePtr), + this.TexelCopyBufferInfo(destinationPtr), this.Extent3D(copySizePtr), ); }, @@ -1338,8 +1557,8 @@ class WebGPUInterface { wgpuCommandEncoderCopyTextureToTexture: (commandEncoderIdx, sourcePtr, destinationPtr, copySizePtr) => { const commandEncoder = this.commandEncoders.get(commandEncoderIdx); commandEncoder.copyTextureToTexture( - this.ImageCopyTexture(sourcePtr), - this.ImageCopyTexture(destinationPtr), + this.TexelCopyTextureInfo(sourcePtr), + this.TexelCopyTextureInfo(destinationPtr), this.Extent3D(copySizePtr), ); }, @@ -1356,7 +1575,7 @@ class WebGPUInterface { let descriptor; if (descriptorPtr != 0) { descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), + label: this.StringView(descriptorPtr + 4), }; } @@ -1367,10 +1586,11 @@ class WebGPUInterface { /** * @param {number} commandEncoderIdx * @param {number} markerLabelPtr + * @param {number} markerLabelLen */ - wgpuCommandEncoderInsertDebugMarker: (commandEncoderIdx, markerLabelPtr) => { + wgpuCommandEncoderInsertDebugMarker: (commandEncoderIdx, markerLabelPtr, markerLabelLen) => { const commandEncoder = this.commandEncoders.get(commandEncoderIdx); - commandEncoder.insertDebugMarker(this.mem.loadCstringDirect(markerLabelPtr)); + commandEncoder.insertDebugMarker(this.mem.loadString(markerLabelPtr, markerLabelLen)); }, /** @@ -1383,11 +1603,12 @@ class WebGPUInterface { /** * @param {number} commandEncoderIdx - * @param {number} markerLabelPtr + * @param {number} groupLabelPtr + * @param {number} groupLabelLen */ - wgpuCommandEncoderPushDebugGroup: (commandEncoderIdx, groupLabelPtr) => { + wgpuCommandEncoderPushDebugGroup: (commandEncoderIdx, groupLabelPtr, groupLabelLen) => { const commandEncoder = this.commandEncoders.get(commandEncoderIdx); - commandEncoder.pushDebugGroup(this.mem.loadCstringDirect(groupLabelPtr)); + commandEncoder.pushDebugGroup(this.mem.loadString(groupLabelPtr, groupLabelLen)); }, /** @@ -1456,10 +1677,11 @@ class WebGPUInterface { /** * @param {number} computePassEncoderIdx * @param {number} markerLabelPtr + * @param {number} markerLabelLen */ - wgpuComputePassEncoderInsertDebugMarker: (computePassEncoderIdx, markerLabelPtr) => { + wgpuComputePassEncoderInsertDebugMarker: (computePassEncoderIdx, markerLabelPtr, markerLabelLen) => { const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx); - computePassEncoder.insertDebugMarker(this.mem.loadCstringDirect(markerLabelPtr)); + computePassEncoder.insertDebugMarker(this.mem.loadString(markerLabelPtr, markerLabelLen)); }, /** @@ -1472,11 +1694,12 @@ class WebGPUInterface { /** * @param {number} computePassEncoderIdx - * @param {number} markerLabelPtr + * @param {number} groupLabelPtr + * @param {number} groupLabelLen */ - wgpuComputePassEncoderPushDebugGroup: (computePassEncoderIdx, groupLabelPtr) => { + wgpuComputePassEncoderPushDebugGroup: (computePassEncoderIdx, groupLabelPtr, groupLabelLen) => { const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx); - computePassEncoder.pushDebugGroup(this.mem.loadCstringDirect(groupLabelPtr)); + computePassEncoder.pushDebugGroup(this.mem.loadString(groupLabelPtr, groupLabelLen)); }, /** @@ -1542,15 +1765,18 @@ class WebGPUInterface { const device = this.devices.get(deviceIdx); this.assert(descriptorPtr != 0); + const off = this.struct(descriptorPtr); + off(4); + /** @type {GPUBindGroupDescriptor} */ const descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), - layout: this.bindGroupLayouts.get(this.mem.loadPtr(descriptorPtr + 8)), + label: this.StringView(off(this.sizes.StringView)), + layout: this.bindGroupLayouts.get(this.mem.loadPtr(off(4))), entries: this.array( - this.mem.loadUint(descriptorPtr + 8 + this.mem.intSize), - this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize * 2), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.BindGroupEntry, - 40, + this.sizes.BindGroupEntry[0], ), }; @@ -1567,14 +1793,17 @@ class WebGPUInterface { const device = this.devices.get(deviceIdx); this.assert(descriptorPtr != 0); + const off = this.struct(descriptorPtr); + off(4); + /** @type {GPUBindGroupLayoutDescriptor} */ const descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), + label: this.StringView(off(this.sizes.StringView)), entries: this.array( - this.mem.loadUint(descriptorPtr + 8), - this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.BindGroupLayoutEntry, - 80, + this.sizes.BindGroupLayoutEntry[0], ), }; @@ -1591,12 +1820,15 @@ class WebGPUInterface { const device = this.devices.get(deviceIdx); this.assert(descriptorPtr != 0); + const off = this.struct(descriptorPtr); + off(4); + /** @type {GPUBufferDescriptor} */ const descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), - usage: this.mem.loadU32(descriptorPtr + 8), - size: this.mem.loadU64(descriptorPtr + 16), - mappedAtCreation: this.mem.loadB32(descriptorPtr + 24), + label: this.StringView(off(this.sizes.StringView)), + usage: this.mem.loadU64(off(8)), + size: this.mem.loadU64(off(8)), + mappedAtCreation: this.mem.loadB32(off(4)), }; const buffer = device.createBuffer(descriptor); @@ -1615,7 +1847,7 @@ class WebGPUInterface { let descriptor; if (descriptor != 0) { descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), + label: this.StringView(descriptorPtr + 4), }; } @@ -1638,27 +1870,27 @@ class WebGPUInterface { /** * @param {number} deviceIdx * @param {number} descriptorPtr - * @param {number} callbackPtr - * @param {number} userdata + * @param {number} callbackInfo */ - wgpuDeviceCreateComputePipelineAsync: async (deviceIdx, descriptorPtr, callbackPtr, userdata) => { + wgpuDeviceCreateComputePipelineAsync: (deviceIdx, descriptorPtr, callbackInfoPtr) => { const device = this.devices.get(deviceIdx); - const callback = this.mem.exports.__indirect_function_table.get(callbackPtr); + this.assert(descriptorPtr != 0); - let result; - let resultIdx; - try { - const computePipeline = await device.createComputePipelineAsync(this.ComputePipelineDescriptor(descriptorPtr)); - resultIdx = this.computePipelines.create(computePipeline); - result = 0; /* Success */ - // NOTE: don't callback here, any errors that happen later will then be caught by the catch here. - } catch (e) { - console.warn(e); - result = 5; /* Unknown error */ - } + const callbackInfo = this.CallbackInfo(callbackInfoPtr); + device.createComputePipelineAsync(this.ComputePipelineDescriptor(descriptorPtr)) + .catch((e) => { + const messageAddr = this.makeMessageArg(e.message); + this.callCallback(callbackInfo, [ENUMS.CreatePipelineAsyncStatus.indexOf("Unknown"), 0, messageAddr]); + this.mem.exports.wgpu_free(messageAddr); + }) + .then((computePipeline) => { + const pipelineIdx = this.computePipelines.create(computePipeline); + this.callCallback(callbackInfo, [ENUMS.CreatePipelineAsyncStatus.indexOf("Success"), pipelineIdx, this.zeroMessageArg()]); + }); - callback(result, resultIdx, null, userdata); + // TODO: returning futures? + return BigInt(0); }, /** @@ -1670,12 +1902,15 @@ class WebGPUInterface { const device = this.devices.get(deviceIdx); this.assert(descriptorPtr != 0); + const off = this.struct(descriptorPtr); + off(4); + /** @type {GPUPipelineLayoutDescriptor} */ const descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), + label: this.StringView(off(this.sizes.StringView)), bindGroupLayouts: this.array( - this.mem.loadUint(descriptorPtr + 8), - this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), (ptr) => this.bindGroupLayouts.get(this.mem.loadPtr(ptr)), 4, ), @@ -1694,11 +1929,14 @@ class WebGPUInterface { const device = this.devices.get(deviceIdx); this.assert(descriptorPtr != 0); + const off = this.struct(descriptorPtr); + off(4); + /** @type {GPUQuerySetDescriptor} */ const descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), - type: this.QueryType(descriptorPtr + 8), - count: this.mem.loadU32(descriptorPtr + 12), + label: this.StringView(off(this.sizes.StringView)), + type: this.enumeration("QueryType", off(4)), + count: this.mem.loadU32(off(4)), }; const querySet = device.createQuerySet(descriptor); @@ -1714,19 +1952,22 @@ class WebGPUInterface { const device = this.devices.get(deviceIdx); this.assert(descriptorPtr != 0); + const off = this.struct(descriptorPtr); + off(4); + /** @type {GPURenderBundleEncoderDescriptor} */ const descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), + label: this.StringView(off(this.sizes.StringView)), colorFormats: this.array( - this.mem.loadUint(descriptorPtr + 8), - this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), this.TextureFormat, 4, ), - depthStencilFormat: this.enumeration("TextureFormat", descriptorPtr + 8 + this.mem.intSize + 4), - sampleCount: this.mem.loadU32(descriptorPtr + 8 + this.mem.intSize + 8), - depthReadOnly: this.mem.loadB32(descriptorPtr + 8 + this.mem.intSize + 12), - stencilReadOnly: this.mem.loadB32(descriptorPtr + 8 + this.mem.intSize + 16), + depthStencilFormat: this.enumeration("TextureFormat", off(4)), + sampleCount: this.mem.loadU32(off(4)), + depthReadOnly: this.mem.loadB32(off(4)), + stencilReadOnly: this.mem.loadB32(off(4)), }; const renderBundleEncoder = device.createRenderBundleEncoder(descriptor); @@ -1750,27 +1991,26 @@ class WebGPUInterface { /** * @param {number} deviceIdx * @param {number} descriptorPtr - * @param {number} callbackPtr - * @param {number} userdata + * @param {number} callbackInfo */ - wgpuDeviceCreateRenderPipelineAsync: async (deviceIdx, descriptorPtr, callbackPtr, userdata) => { + wgpuDeviceCreateRenderPipelineAsync: (deviceIdx, descriptorPtr, callbackInfoPtr) => { const device = this.devices.get(deviceIdx); - const callback = this.mem.exports.__indirect_function_table.get(callbackPtr); this.assert(descriptorPtr != 0); - let result; - let resultIdx; - try { - const renderPipeline = await device.createRenderPipelineAsync(this.RenderPipelineDescriptor(descriptorPtr)); - resultIdx = this.renderPipelines.create(renderPipeline); - result = 0; /* Success */ - // NOTE: don't callback here, any errors that happen later will then be caught by the catch here. - } catch (e) { - console.warn(e); - result = 5; /* Unknown error */ - } + const callbackInfo = this.CallbackInfo(callbackInfoPtr); + device.createRenderPipelineAsync(this.RenderPipelineDescriptor(descriptorPtr)) + .catch((e) => { + const messageAddr = this.makeMessageArg(e.message); + this.callCallback(callbackInfo, [ENUMS.CreatePipelineAsyncStatus.indexOf("Unknown"), 0, messageAddr]); + this.mem.exports.wgpu_free(messageAddr); + }) + .then((renderPipeline) => { + const renderPipelineIdx = this.renderPipelines.create(renderPipeline); + this.callCallback(callbackInfo, [ENUMS.CreatePipelineAsyncStatus.indexOf("Success"), renderPipelineIdx, this.zeroMessageArg()]); + }); - callback(result, resultIdx, null, userdata); + // TODO: returning futures? + return BigInt(0); }, /** @@ -1784,18 +2024,20 @@ class WebGPUInterface { /** @type {?GPUSamplerDescriptor} */ let descriptor; if (descriptorPtr != 0) { + const off = this.struct(descriptorPtr); + off(4); descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), - addressModeU: this.enumeration("AddressMode", descriptorPtr + 8), - addressModeV: this.enumeration("AddressMode", descriptorPtr + 12), - addressModeW: this.enumeration("AddressMode", descriptorPtr + 16), - magFilter: this.enumeration("FilterMode", descriptorPtr + 20), - minFilter: this.enumeration("FilterMode", descriptorPtr + 24), - mipMapFilter: this.enumeration("MipmapFilterMode", descriptorPtr + 28), - lodMinClamp: this.mem.loadF32(descriptorPtr + 32), - lodMaxClamp: this.mem.loadF32(descriptorPtr + 36), - compare: this.enumeration("CompareFunction", descriptorPtr + 40), - maxAnisotropy: this.mem.loadU16(descriptorPtr + 44), + label: this.StringView(off(this.sizes.StringView)), + addressModeU: this.enumeration("AddressMode", off(4)), + addressModeV: this.enumeration("AddressMode", off(4)), + addressModeW: this.enumeration("AddressMode", off(4)), + magFilter: this.enumeration("FilterMode", off(4)), + minFilter: this.enumeration("FilterMode", off(4)), + mipMapFilter: this.enumeration("MipmapFilterMode", off(4)), + lodMinClamp: this.mem.loadF32(off(4)), + lodMaxClamp: this.mem.loadF32(off(4)), + compare: this.enumeration("CompareFunction", off(4)), + maxAnisotropy: this.mem.loadU16(off(2)), }; } @@ -1812,24 +2054,24 @@ class WebGPUInterface { const device = this.devices.get(deviceIdx); this.assert(descriptorPtr != 0); - const nextInChain = this.mem.loadPtr(descriptorPtr); - const nextInChainType = this.mem.loadI32(nextInChain + 4); + const off = this.struct(descriptorPtr); - // ShaderModuleWGSLDescriptor = 0x00000006, - if (nextInChainType != 6) { - throw new TypeError(`Descriptor type should be 'ShaderModuleWGSLDescriptor', got ${nextInChainType}`); + const nextInChain = this.mem.loadPtr(off(4)); + + const chainOff = this.struct(nextInChain); + chainOff(4); + + const nextInChainType = this.mem.loadI32(chainOff(4)); + + // ShaderSourceWGSL = 0x00000002, + if (nextInChainType != 2) { + throw new TypeError(`Descriptor type should be 'ShaderSourceWGSL', got ${nextInChainType}`); } /** @type {GPUShaderModuleDescriptor} */ const descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), - code: this.mem.loadCstring(nextInChain + 8), - compilationHints: this.array( - this.mem.loadUint(descriptorPtr + 8), - this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize), - this.ShaderModuleCompilationHint, - 12, - ), + label: this.StringView(off(this.sizes.StringView)), + code: this.StringView(chainOff(this.sizes.StringView)), }; const shaderModule = device.createShaderModule(descriptor); @@ -1845,18 +2087,21 @@ class WebGPUInterface { const device = this.devices.get(deviceIdx); this.assert(descriptorPtr != 0); + const off = this.struct(descriptorPtr); + off(4); + /** @type {GPUTextureDescriptor} */ const descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), - usage: this.mem.loadU32(descriptorPtr + 8), - dimension: this.enumeration("TextureDimension", descriptorPtr + 12), - size: this.Extent3D(descriptorPtr + 16), - format: this.enumeration("TextureFormat", descriptorPtr + 28), - mipLevelCount: this.mem.loadU32(descriptorPtr + 32), - sampleCount: this.mem.loadU32(descriptorPtr + 36), + label: this.StringView(off(this.sizes.StringView)), + usage: this.mem.loadU64(off(8)), + dimension: this.enumeration("TextureDimension", off(4)), + size: this.Extent3D(off(this.sizes.Extent3D)), + format: this.enumeration("TextureFormat", off(4)), + mipLevelCount: this.mem.loadU32(off(4)), + sampleCount: this.mem.loadU32(off(4)), viewFormats: this.array( - this.mem.loadUint(descriptorPtr + 40), - this.mem.loadPtr(descriptorPtr + 40 + this.mem.intSize), + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), (ptr) => this.enumeration("TextureFormat", ptr), 4, ), @@ -1876,24 +2121,41 @@ class WebGPUInterface { /** * @param {number} deviceIdx - * @param {number} featuresPtr - * @returns {number|BigInt} + * @param {number} infoPtr + * @returns {number} */ - wgpuDeviceEnumerateFeatures: (deviceIdx, featuresPtr) => { + wgpuDeviceGetAdapterInfo: (deviceIdx, infoPtr) => { + return this.genericGetAdapterInfo(infoPtr); + }, + + /** + * @param {number} deviceIdx + * @param {number} featuresPtr + */ + wgpuDeviceGetFeatures: (deviceIdx, featuresPtr) => { const device = this.devices.get(deviceIdx); - return this.genericEnumerateFeatures(device.features, featuresPtr); + return this.genericGetFeatures(device.features, featuresPtr); }, /** * @param {number} deviceIdx * @param {number} limitsPtr - * @returns {boolean} + * @returns {number} */ wgpuDeviceGetLimits: (deviceIdx, limitsPtr) => { const device = this.devices.get(deviceIdx); return this.genericGetLimits(device.limits, limitsPtr); }, + /** + * @param {number} deviceIdx + * @returns {number} + */ + wgpuDeviceGetLostFuture: (deviceIdx) => { + // TODO: futures? + return BigInt(0); + }, + /** * @param {number} deviceIdx * @returns {number} @@ -1910,32 +2172,43 @@ class WebGPUInterface { */ wgpuDeviceHasFeature: (deviceIdx, featureInt) => { const device = this.devices.get(deviceIdx); - return device.features.has(this.enums.FeatureName[featureInt]); + return device.features.has(ENUMS.FeatureName[featureInt]); }, /** * @param {number} deviceIdx - * @param {number} callbackPtr - * @param {number} userdata + * @param {number} callbackInfo + * @returns {number} */ - wgpuDevicePopErrorScope: async (deviceIdx, callbackPtr, userdata) => { + wgpuDevicePopErrorScope: (deviceIdx, callbackInfoPtr) => { const device = this.devices.get(deviceIdx); - const callback = this.mem.exports.__indirect_function_table.get(callbackPtr); - const error = await device.popErrorScope(); - if (!error) { - callback(0, null, userdata); - return; - } - console.warn(error); - let status = 4; - if (error instanceof GPUValidationError) { - status = 1; - } else if (error instanceof GPUOutOfMemoryError) { - status = 2; - } else if (error instanceof GPUInternalError) { - status = 3; - } - callback(status, null, userdata); + + const callbackInfo = this.CallbackInfo(callbackInfoPtr); + device.popErrorScope() + .then((error) => { + if (!error) { + this.callCallback(callbackInfo, [ENUMS.PopErrorScopeStatus.indexOf("Success"), ENUMS.ErrorType.indexOf("no-error"), this.zeroMessageArg()]); + return; + } + + let status; + if (error instanceof GPUValidationError) { + status = ENUMS.ErrorType.indexOf("validation"); + } else if (error instanceof GPUOutOfMemoryError) { + status = ENUMS.ErrorType.indexOf("out-of-memory"); + } else if (error instanceof GPUInternalError) { + status = ENUMS.ErrorType.indexOf("internal"); + } else { + status = ENUMS.ErrorType.indexOf("unknown"); + } + + const messageAddr = error.message; + this.callCallback(callbackInfo, [ENUMS.PopErrorScopeStatus.indexOf("Success"), status, messageAddr]); + this.mem.exports.wgpu_free(messageAddr); + }); + + // TODO: futures? + return BigInt(0); }, /** @@ -1944,7 +2217,7 @@ class WebGPUInterface { */ wgpuDevicePushErrorScope: (deviceIdx, filterInt) => { const device = this.devices.get(deviceIdx); - device.pushErrorScope(this.enums.ErrorFilter[filterInt]); + device.pushErrorScope(ENUMS.ErrorFilter[filterInt]); }, ...this.devices.interface(true), @@ -1959,15 +2232,21 @@ class WebGPUInterface { this.assert(instanceIdx > 0); this.assert(descriptorPtr != 0); - const nextInChain = this.mem.loadPtr(descriptorPtr); - const nextInChainType = this.mem.loadI32(nextInChain + 4); + const off = this.struct(descriptorPtr); - // SurfaceDescriptorFromCanvasHTMLSelector = 0x00000004, - if (nextInChainType != 4) { - throw new TypeError(`Descriptor type should be 'SurfaceDescriptorFromCanvasHTMLSelector', got ${nextInChainType}`); + const nextInChain = this.mem.loadPtr(off(4)); + + const chainOff = this.struct(nextInChain); + chainOff(4); + + const nextInChainType = this.mem.loadI32(chainOff(4)); + + // SurfaceSourceCanvasHTMLSelector = 0x00040001, + if (nextInChainType != 0x00040001) { + throw new TypeError(`Descriptor type should be 'SurfaceSourceCanvasHTMLSelector', got ${nextInChainType}`); } - const selector = this.mem.loadCstring(nextInChain + 8); + const selector = this.StringView(chainOff(this.sizes.StringView)); const surface = document.querySelector(selector); if (!surface) { throw new Error(`Selector '${selector}' did not match any element`); @@ -1979,13 +2258,51 @@ class WebGPUInterface { return this.surfaces.create(surface); }, + /** + * @param {number} instanceIdx + * @param {number} featurePtr + * @returns {number} + */ + wgpuInstanceGetWGSLLanguageFeatures: (instanceIdx, featuresPtr) => { + this.assert(featuresPtr != 0); + + const availableFeatures = []; + ENUMS.WGSLLanguageFeatureName.forEach((feature, value) => { + if (!feature) { + return; + } + + if (navigator.gpu.wgslLanguageFeatures.has(feature)) { + availableFeatures.push(value); + } + }); + + if (availableFeatures.length === 0) { + return; + } + + const featuresAddr = this.mem.exports.wgpu_alloc(availableFeatures.length * 4); + this.assert(featuresAddr != 0); + + let off = this.struct(featuresPtr); + this.mem.storeUint(off(this.mem.intSize), availableFeatures.length); + this.mem.storeI32(off(4), featuresAddr); + + off = this.struct(featuresAddr); + for (let i = 0; i < availableFeatures.length; i += 1) { + this.mem.storeI32(off(4), availableFeatures[i]); + } + + return STATUS_SUCCESS; + }, + /** * @param {number} instanceIdx * @param {number} featureInt * @returns {boolean} */ wgpuInstanceHasWGSLLanguageFeature: (instanceIdx, featureInt) => { - return navigator.gpu.wgslLanguageFeatures.has(this.enums.WGSLFeatureName[featureInt]); + return navigator.gpu.wgslLanguageFeatures.has(ENUMS.WGSLLanguageFeatureName[featureInt]); }, /** @@ -1998,33 +2315,45 @@ class WebGPUInterface { /** * @param {number} instanceIdx * @param {0|number} optionsPtr - * @param {number} callbackPtr - * @param {number} userdata + * @param {number} callbackInfo + * @returns {number} */ - wgpuInstanceRequestAdapter: async (instanceIdx, optionsPtr, callbackPtr, userdata) => { + wgpuInstanceRequestAdapter: (instanceIdx, optionsPtr, callbackInfoPtr) => { this.assert(instanceIdx > 0); - const callback = this.mem.exports.__indirect_function_table.get(callbackPtr); /** @type {GPURequestAdapterOptions} */ let options; if (optionsPtr != 0) { + const off = this.struct(optionsPtr); + off(4); // nextInChain + off(4); // featureLevel options = { - powerPreference: this.enumeration("PowerPreference", optionsPtr + 8), - forceFallbackAdapter: this.mem.loadB32(optionsPtr + 16), + powerPreference: this.enumeration("PowerPreference", off(4)), + forceFallbackAdapter: this.mem.loadB32(off(4)), }; } - let adapterIdx; - try { - const adapter = await navigator.gpu.requestAdapter(options); - adapterIdx = this.adapters.create(adapter); - // NOTE: don't callback here, any errors that happen later will then be caught by the catch here. - } catch(e) { - console.warn(e); - callback(2, null, null, userdata); - } + const callbackInfo = this.CallbackInfo(callbackInfoPtr); + navigator.gpu.requestAdapter(options) + .catch((e) => { + const messageAddr = this.makeMessageArg(e.message); + this.callCallback(callbackInfo, [ENUMS.RequestAdapterStatus.indexOf("Error"), null, messageAddr]); + this.mem.exports.wgpu_free(messageAddr); + }) + .then((adapter) => { + const adapterIdx = this.adapters.create(adapter); - callback(0, adapterIdx, null, userdata); + this.callCallback(callbackInfo, [ENUMS.RequestAdapterStatus.indexOf("Success"), adapterIdx, this.zeroMessageArg()]); + }); + + // TODO: futures? + return BigInt(0); + }, + + wgpuInstanceWaitAny: (instanceIdx, futureCount, futuresPtr, timeoutNS) => { + // TODO: futures? + console.warn("unimplemented: wgpuInstanceProcessEvents"); + return BigInt(0); }, ...this.instances.interface(false), @@ -2058,7 +2387,7 @@ class WebGPUInterface { */ wgpuQuerySetGetType: (querySetIdx) => { const querySet = this.querySets.get(querySetIdx); - return this.enums.QueryType.indexOf(querySet.type); + return ENUMS.QueryType.indexOf(querySet.type); }, ...this.querySets.interface(true), @@ -2067,21 +2396,23 @@ class WebGPUInterface { /** * @param {number} queueIdx - * @param {number} callbackPtr - * @param {number} userdata + * @param {number} callbackInfo */ - wgpuQueueOnSubmittedWorkDone: async (queueIdx, callbackPtr, userdata) => { + wgpuQueueOnSubmittedWorkDone: (queueIdx, callbackInfoPtr) => { const queue = this.queues.get(queueIdx); - const callback = this.mem.exports.__indirect_function_table.get(callbackPtr); - let result; - try { - await queue.onSubmittedWorkDone(); - result = 0; - } catch(e) { - console.warn(e); - result = 1; - } - callback(result, userdata); + + const callbackInfo = this.CallbackInfo(callbackInfoPtr); + queue.onSubmittedWorkDone() + .catch((e) => { + console.warn(e); + this.callCallback(callbackInfo, [ENUMS.QueueWorkDoneStatus.indexOf("Error")]); + }) + .then(() => { + this.callCallback(callbackInfo, [ENUMS.QueueWorkDoneStatus.indexOf("Success")]); + }); + + // TODO: futures? + return BigInt(0); }, /** @@ -2125,9 +2456,9 @@ class WebGPUInterface { */ wgpuQueueWriteTexture: (queueIdx, destinationPtr, dataPtr, dataSize, dataLayoutPtr, writeSizePtr) => { const queue = this.queues.get(queueIdx); - const destination = this.ImageCopyTexture(destinationPtr); + const destination = this.TexelCopyTextureInfo(destinationPtr); dataSize = this.unwrapBigInt(dataSize); - const dataLayout = this.TextureDataLayout(dataLayoutPtr); + const dataLayout = this.TexelCopyBufferLayout(dataLayoutPtr); const writeSize = this.Extent3D(writeSizePtr); queue.writeTexture(destination, this.mem.loadBytes(dataPtr, dataSize), dataLayout, writeSize); }, @@ -2201,7 +2532,7 @@ class WebGPUInterface { let descriptor; if (descriptorPtr != 0) { descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), + label: this.StringView(descriptorPtr + 4), }; } @@ -2212,11 +2543,12 @@ class WebGPUInterface { /** * @param {number} renderBundleEncoderIdx * @param {number} markerLabelPtr + * @param {number} markerLabelLen */ - wgpuRenderBundleEncoderInsertDebugMarker: (renderBundleEncoderIdx, markerLabelPtr) => { + wgpuRenderBundleEncoderInsertDebugMarker: (renderBundleEncoderIdx, markerLabelPtr, markerLabelLen) => { const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx); this.assert(markerLabelPtr != 0); - const markerLabel = this.mem.loadCstringDirect(markerLabelPtr); + const markerLabel = this.mem.loadString(markerLabelPtr, markerLabelLen); renderBundleEncoder.insertDebugMarker(markerLabel); }, @@ -2231,11 +2563,12 @@ class WebGPUInterface { /** * @param {number} renderBundleEncoderIdx * @param {number} groupLabelPtr + * @param {number} grouplabelLen */ - wgpuRenderBundleEncoderPushDebugGroup: (renderBundleEncoderIdx, groupLabelPtr) => { + wgpuRenderBundleEncoderPushDebugGroup: (renderBundleEncoderIdx, groupLabelPtr, grouplabelLen) => { const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx); this.assert(groupLabelPtr!= 0); - const groupLabel = this.mem.loadCstringDirect(groupLabelPtr); + const groupLabel = this.mem.loadString(groupLabelPtr, groupLabelLen); renderBundleEncoder.pushDebugGroup(groupLabel); }, @@ -2270,7 +2603,7 @@ class WebGPUInterface { wgpuRenderBundleEncoderSetIndexBuffer: (renderBundleEncoderIdx, bufferIdx, formatInt, offset, size) => { const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx); const buffer = this.buffers.get(bufferIdx); - const format = this.enums.IndexFormat[formatInt]; + const format = ENUMS.IndexFormat[formatInt]; offset = this.unwrapBigInt(offset); size = this.unwrapBigInt(size); renderBundleEncoder.setIndexBuffer(buffer.buffer, format, offset, size); @@ -2404,10 +2737,11 @@ class WebGPUInterface { /** * @param {number} renderPassEncoderIdx * @param {number} markerLabelPtr + * @param {number} markerLabelLen */ - wgpuRenderPassEncoderInsertDebugMarker: (renderPassEncoderIdx, markerLabelPtr) => { + wgpuRenderPassEncoderInsertDebugMarker: (renderPassEncoderIdx, markerLabelPtr, markerLabelLen) => { const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx); - const markerLabel = this.mem.loadCstringDirect(markerLabelPtr); + const markerLabel = this.mem.loadString(markerLabelPtr, markerLabelLen); renderPassEncoder.insertDebugMarker(markerLabel); }, @@ -2422,10 +2756,11 @@ class WebGPUInterface { /** * @param {number} renderPassEncoderIdx * @param {number} groupLabelPtr + * @param {number} groupLabelLen */ - wgpuRenderPassEncoderPushDebugGroup: (renderPassEncoderIdx, groupLabelPtr) => { + wgpuRenderPassEncoderPushDebugGroup: (renderPassEncoderIdx, groupLabelPtr, groupLabelLen) => { const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx); - const groupLabel = this.mem.loadCstringDirect(groupLabelPtr); + const groupLabel = this.mem.loadString(groupLabelPtr, groupLabelLen); renderPassEncoder.pushDebugGroup(groupLabel); }, @@ -2470,7 +2805,7 @@ class WebGPUInterface { wgpuRenderPassEncoderSetIndexBuffer: (renderPassEncoderIdx, bufferIdx, formatInt, offset, size) => { const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx); const buffer = this.buffers.get(bufferIdx); - const format = this.enums.IndexFormat[formatInt]; + const format = ENUMS.IndexFormat[formatInt]; offset = this.unwrapBigInt(offset); size = this.unwrapBigInt(size); renderPassEncoder.setIndexBuffer(buffer.buffer, format, offset, size); @@ -2566,60 +2901,76 @@ class WebGPUInterface { /** * @param {number} shaderModuleIdx - * @param {number} callbackPtr - * @param {number} userdata + * @param {number} callbackInfo */ - wgpuShaderModuleGetCompilationInfo: async (shaderModuleIdx, callbackPtr, userdata) => { + wgpuShaderModuleGetCompilationInfo: (shaderModuleIdx, callbackInfoPtr) => { const shaderModule = this.shaderModules.get(shaderModuleIdx); - const callback = this.mem.exports.__indirect_function_table.get(callbackPtr); - let status = 0; - let retAddr = 0; + const callbackInfo = this.CallbackInfo(callbackInfoPtr); + shaderModule.getCompilationInfo() + .catch((e) => { + console.warn(e); + this.callCallback(callbackInfo, [ENUMS.CompilationInfoRequestStatus.indexOf("Error"), null]); + }) + .then((compilationInfo) => { + const ptrsToFree = []; - const ptrsToFree = []; + const compilationMessageSize = this.sizes.CompilationMessage[0]; - try { - const compilationInfo = await shaderModule.getCompilationInfo(); + const size = compilationInfo.messages.length * compilationMessageSize; - const size = compilationInfo.messages.length * 72; - const addr = this.mem.exports.wgpu_alloc(size); - ptrsToFree.push(addr); - compilationInfo.messages.forEach((message, i) => { - const messageLength = new TextEncoder().encode(message.message).length; - const messageAddr = this.mem.exports.wgpu_alloc(messageLength); - ptrsToFree.push(messageAddr); - this.mem.storeString(messageAddr, message.message); - this.mem.storeI32(addr + (i * size) + 4); + const addr = this.mem.exports.wgpu_alloc(size); + ptrsToFree.push(addr); - this.mem.storeI32(addr + (i * size) + 8, this.enums.CompilationMessageType.indexOf(message.type)); + compilationInfo.messages.forEach((message, i) => { + const messageLength = new TextEncoder().encode(message.message).length; + const messageAddr = this.mem.exports.wgpu_alloc(messageLength); + ptrsToFree.push(messageAddr); + this.mem.storeString(messageAddr, message.message); - this.mem.storeU64(addr + (i * size) + 16, message.lineNum); - this.mem.storeU64(addr + (i * size) + 24, message.linePos); - this.mem.storeU64(addr + (i * size) + 32, message.offset); - this.mem.storeU64(addr + (i * size) + 40, message.length); + const off = this.struct(addr + (i * compilationMessageSize)); + off(4); - // TODO: UTF16 units. - this.mem.storeU64(addr + (i * size) + 48, message.linePos); - this.mem.storeU64(addr + (i * size) + 56, message.offset); - this.mem.storeU64(addr + (i * size) + 64, message.length); + const messageStart = off(this.sizes.StringView); + this.mem.storeI32(messageStart, messageAddr); + this.mem.storeUint(messageStart + this.mem.intSize, messageLength); + + this.mem.storeI32(off(4), ENUMS.CompilationMessageType.indexOf(message.type)); + + this.mem.storeU64(off(8), message.lineNum); + this.mem.storeU64(off(8), message.linePos); + this.mem.storeU64(off(8), message.offset); + this.mem.storeU64(off(8), message.length); + }); + + const retAddr = this.mem.exports.wgpu_alloc(3*this.mem.intSize); + ptrsToFree.push(retAddr); + this.mem.storeUint(retAddr + this.mem.intSize, compilationInfo.messages.length); + this.mem.storeI32(retAddr + this.mem.intSize*2, addr); + + this.callCallback(callbackInfo, [ENUMS.CompilationInfoRequestStatus.indexOf("Success"), retAddr]); + + ptrsToFree.forEach(ptr => this.mem.exports.wgpu_free(ptr)); }); - retAddr = this.mem.exports.wgpu_alloc(3*this.mem.intSize); - ptrsToFree.push(retAddr); - this.mem.storeUint(retAddr + this.mem.intSize, compilationInfo.messages.length); - this.mem.storeI32(retAddr + this.mem.intSize*2, addr); - } catch (e) { - console.warn(e); - status = 1; - } - - callback(status, retAddr, userdata); - - ptrsToFree.forEach(ptr => this.mem.exports.wgpu_free(ptr)); + // TODO: futures? + return BigInt(0); }, ...this.shaderModules.interface(true), + /* ---------------------- SupportedFeatures ---------------------- */ + + wgpuSupportedFeaturesFreeMembers: (supportedFeaturesCount, supportedFeaturesPtr) => { + this.mem.exports.wgpu_free(supportedFeaturesPtr); + }, + + /* ---------------------- SupportedWGSLLanguageFeatures ---------------------- */ + + wgpuSupportedWGSLLanguageFeaturesFreeMembers: (supportedFeaturesCount, supportedFeaturesPtr) => { + this.mem.exports.wgpu_free(supportedFeaturesPtr); + }, + /* ---------------------- Surface ---------------------- */ /** @@ -2628,26 +2979,36 @@ class WebGPUInterface { */ wgpuSurfaceConfigure: (surfaceIdx, configPtr) => { const surface = this.surfaces.get(surfaceIdx); - const context = surface.getContext('webgpu'); + const context = surface.getContext("webgpu"); - const widthOff = 16 + this.mem.intSize + 8; - surface.width = this.mem.loadU32(configPtr + widthOff); - surface.height = this.mem.loadU32(configPtr + widthOff + 4); + const off = this.struct(configPtr); + off(4); + const device = this.devices.get(this.mem.loadPtr(off(4))); + const format = this.enumeration("TextureFormat", off(4)); + const usage = this.mem.loadU64(off(8)); + const width = this.mem.loadU32(off(4)); + const height = this.mem.loadU32(off(4)); + const viewFormats = this.array( + this.mem.loadUint(off(this.mem.intSize)), + this.mem.loadPtr(off(4)), + (ptr) => this.enumeration("TextureFormat", ptr), + 4, + ); + const alphaMode = this.enumeration("CompositeAlphaMode", off(4)); + // NOTE: present mode seems unused. + const presentMode = this.enumeration("PresentMode", off(4)); + + surface.width = width; + surface.height = height; /** @type {GPUCanvasConfiguration} */ const config = { - device: this.devices.get(this.mem.loadPtr(configPtr + 4)), - format: this.enumeration("TextureFormat", configPtr + 8), - usage: this.mem.loadU32(configPtr + 12), - viewFormats: this.array( - this.mem.loadUint(configPtr + 16), - this.mem.loadPtr(configPtr + 16 + this.mem.intSize), - (ptr) => this.enumeration("TextureFormat", ptr), - 4, - ), - alphaMode: this.enumeration("CompositeAlphaMode", configPtr + widthOff - 4), - // // NOTE: present mode seems unused. - presentMode: this.enumeration("PresentMode", configPtr + widthOff + 4), + device: device, + format: format, + usage: usage, + viewFormats: viewFormats, + alphaMode: alphaMode, + presentMode: presentMode, }; context.configure(config); @@ -2657,28 +3018,35 @@ class WebGPUInterface { * @param {number} surfaceIdx * @param {number} adapterIdx * @param {number} capabilitiesPtr + * @return {number} */ wgpuSurfaceGetCapabilities: (surfaceIdx, adapterIdx, capabilitiesPtr) => { - const formatStr = navigator.gpu.getPreferredCanvasFormat(); - const format = this.enums.TextureFormat.indexOf(formatStr); + const off = this.struct(capabilitiesPtr); + off(4); // nextInChain + off(8); // usages TODO: can we pass this? - this.mem.storeUint(capabilitiesPtr + 8, 1); + const formatStr = navigator.gpu.getPreferredCanvasFormat(); + const format = ENUMS.TextureFormat.indexOf(formatStr); + + this.mem.storeUint(off(this.mem.intSize), 1); const formatAddr = this.mem.exports.wgpu_alloc(4); this.mem.storeI32(formatAddr, format); - this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize, formatAddr); + this.mem.storeI32(off(4), formatAddr); // NOTE: present modes don't seem to actually do anything in JS, we can just give back a default FIFO though. - this.mem.storeUint(capabilitiesPtr + 8 + this.mem.intSize*2, 1); + this.mem.storeUint(off(this.mem.intSize), 1); const presentModesAddr = this.mem.exports.wgpu_alloc(4); - this.mem.storeI32(presentModesAddr, 0); - this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize*3, presentModesAddr); + this.mem.storeI32(presentModesAddr, ENUMS.PresentMode.indexOf("fifo")); + this.mem.storeI32(off(4), presentModesAddr); - // Browser seems to support opaque (1) and premultiplied (2). - this.mem.storeUint(capabilitiesPtr + 8 + this.mem.intSize*4, 2); + // Browser seems to support opaque and premultiplied. + this.mem.storeUint(off(this.mem.intSize), 2); const alphaModesAddr = this.mem.exports.wgpu_alloc(8); - this.mem.storeI32(alphaModesAddr + 0, 1); // Opaque. - this.mem.storeI32(alphaModesAddr + 4, 2); // premultiplied. - this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize*5, alphaModesAddr); + this.mem.storeI32(alphaModesAddr + 0, ENUMS.CompositeAlphaMode.indexOf("opaque")); + this.mem.storeI32(alphaModesAddr + 4, ENUMS.CompositeAlphaMode.indexOf("premultiplied")); + this.mem.storeI32(off(4), alphaModesAddr); + + return STATUS_SUCCESS; }, /** @@ -2691,7 +3059,7 @@ class WebGPUInterface { const texture = context.getCurrentTexture(); const textureIdx = this.textures.create(texture); - this.mem.storeI32(texturePtr, textureIdx); + this.mem.storeI32(texturePtr + 4, textureIdx); // TODO: determine suboptimal and/or status. }, @@ -2719,13 +3087,22 @@ class WebGPUInterface { * @param {number} surfaceCapabilitiesPtr */ wgpuSurfaceCapabilitiesFreeMembers: (surfaceCapabilitiesPtr) => { - const formatsAddr = this.mem.loadI32(surfaceCapabilitiesPtr + this.mem.intSize*2); + const off = this.struct(capabilitiesPtr); + off(4); // nextInChain + off(8); // usages + off(this.mem.intSize); // formatCount + + const formatsAddr = this.mem.loadPtr(off(4)); this.mem.exports.wgpu_free(formatsAddr); - const presentModesAddr = this.mem.loadI32(surfaceCapabilitiesPtr + this.mem.intSize*4); + off(this.mem.intSize); // presentModeCount + + const presentModesAddr = this.mem.loadPtr(off(4)); this.mem.exports.wgpu_free(presentModesAddr); - const alphaModesAddr = this.mem.loadI32(surfaceCapabilitiesPtr + this.mem.intSize*6); + off(this.mem.intSize); // alphaModeCount + + const alphaModesAddr = this.mem.loadPtr(off(4)); this.mem.exports.wgpu_free(alphaModesAddr); }, @@ -2742,15 +3119,18 @@ class WebGPUInterface { /** @type {?GPUTextureViewDescriptor} */ let descriptor; if (descriptorPtr != 0) { + const off = this.struct(descriptorPtr); + off(4); descriptor = { - label: this.mem.loadCstring(descriptorPtr + 4), - format: this.enumeration("TextureFormat", descriptorPtr + 8), - dimension: this.enumeration("TextureViewDimension", descriptorPtr + 12), - baseMipLevel: this.mem.loadU32(descriptorPtr + 16), - mipLevelCount: this.mem.loadU32(descriptorPtr + 20), - baseArrayLayer: this.mem.loadU32(descriptorPtr + 24), - arrayLayerCount: this.mem.loadU32(descriptorPtr + 28), - aspect: this.enumeration("TextureAspect", descriptorPtr + 32), + label: this.StringView(off(this.sizes.StringView)), + format: this.enumeration("TextureFormat", off(4)), + dimension: this.enumeration("TextureViewDimension", off(4)), + baseMipLevel: this.mem.loadU32(off(4)), + mipLevelCount: this.mem.loadU32(off(4)), + baseArrayLayer: this.mem.loadU32(off(4)), + arrayLayerCount: this.mem.loadU32(off(4)), + aspect: this.enumeration("TextureAspect", off(4)), + usage: this.mem.loadU64(off(8)), }; if (descriptor.arrayLayerCount == 0xFFFFFFFF) { descriptor.arrayLayerCount = undefined; @@ -2787,7 +3167,7 @@ class WebGPUInterface { */ wgpuTextureGetDimension: (textureIdx) => { const texture = this.textures.get(textureIdx); - return this.enums.TextureDimension.indexOf(texture.dimension); + return ENUMS.TextureDimension.indexOf(texture.dimension); }, /** @@ -2796,7 +3176,7 @@ class WebGPUInterface { */ wgpuTextureGetFormat: (textureIdx) => { const texture = this.textures.get(textureIdx); - return this.enums.TextureFormat.indexOf(texture.format); + return ENUMS.TextureFormat.indexOf(texture.format); }, /** @@ -2903,12 +3283,12 @@ class WebGPUObjectManager { interface(withLabelSetter = false) { const inter = {}; - inter[`wgpu${this.name}Reference`] = this.reference.bind(this); + inter[`wgpu${this.name}AddRef`] = this.reference.bind(this); inter[`wgpu${this.name}Release`] = this.release.bind(this); if (withLabelSetter) { - inter[`wgpu${this.name}SetLabel`] = (idx, labelPtr) => { + inter[`wgpu${this.name}SetLabel`] = (idx, labelPtr, labelLen) => { const obj = this.get(idx); - obj.label = this.mem.loadCstringDirect(labelPtr); + obj.label = this.mem.loadString(labelPtr, labelLen); }; } return inter; diff --git a/vendor/wgpu/wgpu.odin b/vendor/wgpu/wgpu.odin index 9854475a9..4bbe67d1f 100644 --- a/vendor/wgpu/wgpu.odin +++ b/vendor/wgpu/wgpu.odin @@ -10,12 +10,13 @@ WGPU_DEBUG :: #config(WGPU_DEBUG, false) when ODIN_OS == .Windows { @(private) ARCH :: "x86_64" when ODIN_ARCH == .amd64 else "x86_64" when ODIN_ARCH == .i386 else #panic("unsupported WGPU Native architecture") @(private) EXT :: ".dll.lib" when WGPU_SHARED else ".lib" - @(private) LIB :: "lib/wgpu-windows-" + ARCH + "-" + TYPE + "/wgpu_native" + EXT + @(private) LIB :: "lib/wgpu-windows-" + ARCH + "-msvc-" + TYPE + "/lib/wgpu_native" + EXT when !#exists(LIB) { - #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1, make sure to read the README at '" + #directory + "README.md'") + #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2, make sure to read the README at '" + #directory + "README.md'") } + @(export) foreign import libwgpu { LIB, "system:d3dcompiler.lib", @@ -29,16 +30,19 @@ when ODIN_OS == .Windows { "system:gdi32.lib", "system:ole32.lib", "system:oleaut32.lib", + "system:propsys.lib", + "system:runtimeobject.lib", } } else when ODIN_OS == .Darwin { @(private) ARCH :: "x86_64" when ODIN_ARCH == .amd64 else "aarch64" when ODIN_ARCH == .arm64 else #panic("unsupported WGPU Native architecture") @(private) EXT :: ".dylib" when WGPU_SHARED else ".a" - @(private) LIB :: "lib/wgpu-macos-" + ARCH + "-" + TYPE + "/libwgpu_native" + EXT + @(private) LIB :: "lib/wgpu-macos-" + ARCH + "-" + TYPE + "/lib/libwgpu_native" + EXT when !#exists(LIB) { - #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1, make sure to read the README at '" + #directory + "README.md'") + #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2, make sure to read the README at '" + #directory + "README.md'") } + @(export) foreign import libwgpu { LIB, "system:CoreFoundation.framework", @@ -48,18 +52,20 @@ when ODIN_OS == .Windows { } else when ODIN_OS == .Linux { @(private) ARCH :: "x86_64" when ODIN_ARCH == .amd64 else "aarch64" when ODIN_ARCH == .arm64 else #panic("unsupported WGPU Native architecture") @(private) EXT :: ".so" when WGPU_SHARED else ".a" - @(private) LIB :: "lib/wgpu-linux-" + ARCH + "-" + TYPE + "/libwgpu_native" + EXT + @(private) LIB :: "lib/wgpu-linux-" + ARCH + "-" + TYPE + "/lib/libwgpu_native" + EXT when !#exists(LIB) { - #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1, make sure to read the README at '" + #directory + "README.md'") + #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2, make sure to read the README at '" + #directory + "README.md'") } + @(export) foreign import libwgpu { LIB, "system:dl", "system:m", } } else when ODIN_OS == .JS { + @(export) foreign import libwgpu "wgpu" } @@ -73,7 +79,11 @@ QUERY_SET_INDEX_UNDEFINED :: max(u32) WHOLE_MAP_SIZE :: max(uint) WHOLE_SIZE :: max(u64) -Flags :: u32 +Flags :: u64 + +StringView :: string + +STRLEN :: transmute(int)(max(uint)) Adapter :: distinct rawptr BindGroup :: distinct rawptr @@ -99,16 +109,17 @@ Texture :: distinct rawptr TextureView :: distinct rawptr AdapterType :: enum i32 { - DiscreteGPU = 0x00000000, - IntegratedGPU = 0x00000001, - CPU = 0x00000002, - Unknown = 0x00000003, + DiscreteGPU = 0x00000001, + IntegratedGPU = 0x00000002, + CPU = 0x00000003, + Unknown = 0x00000004, } AddressMode :: enum i32 { - Repeat = 0x00000000, - MirrorRepeat = 0x00000001, - ClampToEdge = 0x00000002, + Undefined = 0x00000000, + ClampToEdge = 0x00000001, + Repeat = 0x00000002, + MirrorRepeat = 0x00000003, } BackendType :: enum i32 { @@ -124,19 +135,24 @@ BackendType :: enum i32 { } BlendFactor :: enum i32 { - Zero = 0x00000000, - One = 0x00000001, - Src = 0x00000002, - OneMinusSrc = 0x00000003, - SrcAlpha = 0x00000004, - OneMinusSrcAlpha = 0x00000005, - Dst = 0x00000006, - OneMinusDst = 0x00000007, - DstAlpha = 0x00000008, - OneMinusDstAlpha = 0x00000009, - SrcAlphaSaturated = 0x0000000A, - Constant = 0x0000000B, - OneMinusConstant = 0x0000000C, + Undefined = 0x00000000, + Zero = 0x00000001, + One = 0x00000002, + Src = 0x00000003, + OneMinusSrc = 0x00000004, + SrcAlpha = 0x00000005, + OneMinusSrcAlpha = 0x00000006, + Dst = 0x00000007, + OneMinusDst = 0x00000008, + DstAlpha = 0x00000009, + OneMinusDstAlpha = 0x0000000A, + SrcAlphaSaturated = 0x0000000B, + Constant = 0x0000000C, + OneMinusConstant = 0x0000000D, + Src1 = 0x0000000E, + OneMinusSrc1 = 0x0000000F, + Src1Alpha = 0x00000010, + OneMinusSrc1Alpha = 0x00000011, } BlendOperation :: enum i32 { @@ -148,53 +164,48 @@ BlendOperation :: enum i32 { } BufferBindingType :: enum i32 { - Undefined = 0x00000000, - Uniform = 0x00000001, - Storage = 0x00000002, - ReadOnlyStorage = 0x00000003, -} - -BufferMapAsyncStatus :: enum i32 { - Success = 0x00000000, - ValidationError = 0x00000001, - Unknown = 0x00000002, - DeviceLost = 0x00000003, - DestroyedBeforeCallback = 0x00000004, - UnmappedBeforeCallback = 0x00000005, - MappingAlreadyPending = 0x00000006, - OffsetOutOfRange = 0x00000007, - SizeOutOfRange = 0x00000008, + BindingNotUsed = 0x00000000, + Undefined = 0x00000001, + Uniform = 0x00000002, + Storage = 0x00000003, + ReadOnlyStorage = 0x00000004, } BufferMapState :: enum i32 { - Unmapped = 0x00000000, - Pending = 0x00000001, - Mapped = 0x00000002, + Unmapped = 0x00000001, + Pending = 0x00000002, + Mapped = 0x00000003, +} + +CallbackMode :: enum i32 { + WaitAnyOnly = 0x00000001, + AllowProcessEvents = 0x00000002, + AllowSpontaneos = 0x00000003, } CompareFunction :: enum i32 { Undefined = 0x00000000, Never = 0x00000001, Less = 0x00000002, - LessEqual = 0x00000003, - Greater = 0x00000004, - GreaterEqual = 0x00000005, - Equal = 0x00000006, - NotEqual = 0x00000007, + Equal = 0x00000003, + LessEqual = 0x00000004, + Greater = 0x00000005, + NotEqual = 0x00000006, + GreaterEqual = 0x00000007, Always = 0x00000008, } CompilationInfoRequestStatus :: enum i32 { - Success = 0x00000000, - Error = 0x00000001, - DeviceLost = 0x00000002, - Unknown = 0x00000003, + Success = 0x00000001, + InstanceDropped = 0x00000002, + Error = 0x00000003, + Unknown = 0x00000004, } CompilationMessageType :: enum i32 { - Error = 0x00000000, - Warning = 0x00000001, - Info = 0x00000002, + Error = 0x00000001, + Warning = 0x00000002, + Info = 0x00000003, } CompositeAlphaMode :: enum i32 { @@ -206,39 +217,45 @@ CompositeAlphaMode :: enum i32 { } CreatePipelineAsyncStatus :: enum i32 { - Success = 0x00000000, - ValidationError = 0x00000001, - InternalError = 0x00000002, - DeviceLost = 0x00000003, - DeviceDestroyed = 0x00000004, + Success = 0x00000001, + InstanceDropped = 0x00000002, + ValidationError = 0x00000003, + InternalError = 0x00000004, Unknown = 0x00000005, } CullMode :: enum i32 { - None = 0x00000000, - Front = 0x00000001, - Back = 0x00000002, + Undefined = 0x00000000, + None = 0x00000001, + Front = 0x00000002, + Back = 0x00000003, } DeviceLostReason :: enum i32 { Undefined = 0x00000000, Unknown = 0x00000001, Destroyed = 0x00000002, + InstanceDropped = 0x00000003, + FailedCreation = 0x00000004, } ErrorFilter :: enum i32 { - Validation = 0x00000000, - OutOfMemory = 0x00000001, - Internal = 0x00000002, -} - -ErrorType :: enum i32 { - NoError = 0x00000000, Validation = 0x00000001, OutOfMemory = 0x00000002, Internal = 0x00000003, - Unknown = 0x00000004, - DeviceLost = 0x00000005, +} + +ErrorType :: enum i32 { + NoError = 0x00000001, + Validation = 0x00000002, + OutOfMemory = 0x00000003, + Internal = 0x00000004, + Unknown = 0x00000005, +} + +FeatureLevel :: enum i32 { + Compatibility = 0x00000001, + Core = 0x00000002, } FeatureName :: enum i32 { @@ -248,13 +265,18 @@ FeatureName :: enum i32 { Depth32FloatStencil8 = 0x00000002, TimestampQuery = 0x00000003, TextureCompressionBC = 0x00000004, - TextureCompressionETC2 = 0x00000005, - TextureCompressionASTC = 0x00000006, - IndirectFirstInstance = 0x00000007, - ShaderF16 = 0x00000008, - RG11B10UfloatRenderable = 0x00000009, - BGRA8UnormStorage = 0x0000000A, - Float32Filterable = 0x0000000B, + TextureCompressionBCSliced3D = 0x00000005, + TextureCompressionETC2 = 0x00000006, + TextureCompressionASTC = 0x00000007, + TextureCompressionASTCSliced3D = 0x00000008, + IndirectFirstInstance = 0x00000009, + ShaderF16 = 0x0000000A, + RG11B10UfloatRenderable = 0x0000000B, + BGRA8UnormStorage = 0x0000000C, + Float32Filterable = 0x0000000D, + Float32Blendable = 0x0000000E, + ClipDistances = 0x0000000F, + DualSourceBlending = 0x00000010, // Native. PushConstants = 0x00030001, @@ -269,8 +291,6 @@ FeatureName :: enum i32 { PartiallyBoundBindingArray, TextureFormat16bitNorm, TextureCompressionAstcHdr, - // TODO: requires wgpu.h api change - // TimestampQueryInsidePasses, MappablePrimaryBuffers = 0x0003000E, BufferBindingArray, UniformBufferAndStorageTextureArrayNonUniformIndexing, @@ -281,7 +301,7 @@ FeatureName :: enum i32 { // PolygonModePoint, // ConservativeRasterization, // ClearTexture, - // SprivShaderPassThrough, + SpirvShaderPassthrough = 0x00030017, // MultiView, VertexAttribute64bit = 0x00030019, TextureFormatNv12, @@ -291,16 +311,23 @@ FeatureName :: enum i32 { ShaderI16, ShaderPrimitiveIndex, ShaderEarlyDepthTest, + Subgroup, + SubgroupVertex, + SubgroupBarrier, + TimestampQueryInsideEncoders, + TimestampQueryInsidePasses, } FilterMode :: enum i32 { - Nearest = 0x00000000, - Linear = 0x00000001, + Undefined = 0x00000000, + Nearest = 0x00000001, + Linear = 0x00000002, } FrontFace :: enum i32 { - CCW = 0x00000000, - CW = 0x00000001, + Undefined = 0x00000000, + CCW = 0x00000001, + CW = 0x00000002, } IndexFormat :: enum i32 { @@ -311,13 +338,34 @@ IndexFormat :: enum i32 { LoadOp :: enum i32 { Undefined = 0x00000000, - Clear = 0x00000001, - Load = 0x00000002, + Load = 0x00000001, + Clear = 0x00000002, +} + +MapAsyncStatus :: enum i32 { + Success = 0x00000001, + InstanceDropped = 0x00000002, + Error = 0x00000003, + Aborted = 0x00000004, + Unknown = 0x00000005, } MipmapFilterMode :: enum i32 { - Nearest = 0x00000000, - Linear = 0x00000001, + Undefined = 0x00000000, + Nearest = 0x00000001, + Linear = 0x00000002, +} + +OptionalBool :: enum i32 { + False = 0x00000000, + True = 0x00000001, + Undefined = 0x00000002, +} + +PopErrorScopeStatus :: enum i32 { + Success = 0x00000001, + InstanceDropped = 0x00000002, + EmptyStack = 0x00000003, } PowerPreference :: enum i32 { @@ -327,67 +375,68 @@ PowerPreference :: enum i32 { } PresentMode :: enum i32 { - Fifo = 0x00000000, - FifoRelaxed = 0x00000001, - Immediate = 0x00000002, - Mailbox = 0x00000003, + Undefined = 0x00000000, + Fifo = 0x00000001, + FifoRelaxed = 0x00000002, + Immediate = 0x00000003, + Mailbox = 0x00000004, } PrimitiveTopology :: enum i32 { - PointList = 0x00000000, - LineList = 0x00000001, - LineStrip = 0x00000002, - TriangleList = 0x00000003, - TriangleStrip = 0x00000004, + Undefined = 0x00000000, + PointList = 0x00000001, + LineList = 0x00000002, + LineStrip = 0x00000003, + TriangleList = 0x00000004, + TriangleStrip = 0x00000005, } QueryType :: enum i32 { // WebGPU. - Occlusion = 0x00000000, - Timestamp = 0x00000001, + Occlusion = 0x00000001, + Timestamp = 0x00000002, // Native. PipelineStatistics = 0x00030000, } QueueWorkDoneStatus :: enum i32 { - Success = 0x00000000, - Error = 0x00000001, - Unknown = 0x00000002, - DeviceLost = 0x00000003, + Success = 0x00000001, + InstanceDropped = 0x00000002, + Error = 0x00000003, + Unknown = 0x00000004, } RequestAdapterStatus :: enum i32 { - Success = 0x00000000, - Unavailable = 0x00000001, - Error = 0x00000002, - Unknown = 0x00000003, + Success = 0x00000001, + InstanceDropped = 0x00000002, + Unavailable = 0x00000003, + Error = 0x00000004, + Unknown = 0x00000005, } RequestDeviceStatus :: enum i32 { - Success = 0x00000000, - Error = 0x00000001, - Unknown = 0x00000002, + Success = 0x00000001, + InstanceDropped = 0x00000002, + Error = 0x00000003, + Unknown = 0x00000004, } SType :: enum i32 { // WebGPU. - Invalid = 0x00000000, - SurfaceDescriptorFromMetalLayer = 0x00000001, - SurfaceDescriptorFromWindowsHWND = 0x00000002, - SurfaceDescriptorFromXlibWindow = 0x00000003, - SurfaceDescriptorFromCanvasHTMLSelector = 0x00000004, - ShaderModuleSPIRVDescriptor = 0x00000005, - ShaderModuleWGSLDescriptor = 0x00000006, - PrimitiveDepthClipControl = 0x00000007, - SurfaceDescriptorFromWaylandSurface = 0x00000008, - SurfaceDescriptorFromAndroidNativeWindow = 0x00000009, - SurfaceDescriptorFromXcbWindow = 0x0000000A, - RenderPassDescriptorMaxDrawCount = 0x0000000F, + ShaderSourceSPIRV = 0x00000001, + ShaderSourceWGSL = 0x00000002, + RenderPassMaxDrawCount = 0x00000003, + SurfaceSourceMetalLayer = 0x00000004, + SurfaceSourceWindowsHWND = 0x00000005, + SurfaceSourceXlibWindow = 0x00000006, + SurfaceSourceWaylandSurface = 0x00000007, + SurfaceSourceAndroidNativeWindow = 0x00000008, + SurfaceSourceXCBWindow = 0x00000009, // Native. DeviceExtras = 0x00030001, - RequiredLimitsExtras, + NativeLimits, PipelineLayoutExtras, ShaderModuleGLSLDescriptor, SupportedLimitsExtras, @@ -396,31 +445,42 @@ SType :: enum i32 { BindGroupLayoutEntryExtras, QuerySetDescriptorExtras, SurfaceConfigurationExtras, + + // Odin. + SurfaceSourceCanvasHTMLSelector = 0x00040001, } SamplerBindingType :: enum i32 { - Undefined = 0x00000000, - Filtering = 0x00000001, - NonFiltering = 0x00000002, - Comparison = 0x00000003, + BindingNotUsed = 0x00000000, + Undefined = 0x00000001, + Filtering = 0x00000002, + NonFiltering = 0x00000003, + Comparison = 0x00000004, +} + +Status :: enum i32 { + Success = 0x00000001, + Error = 0x00000002, } StencilOperation :: enum i32 { - Keep = 0x00000000, - Zero = 0x00000001, - Replace = 0x00000002, - Invert = 0x00000003, - IncrementClamp = 0x00000004, - DecrementClamp = 0x00000005, - IncrementWrap = 0x00000006, - DecrementWrap = 0x00000007, + Undefined = 0x00000000, + Keep = 0x00000001, + Zero = 0x00000002, + Replace = 0x00000003, + Invert = 0x00000004, + IncrementClamp = 0x00000005, + DecrementClamp = 0x00000006, + IncrementWrap = 0x00000007, + DecrementWrap = 0x00000008, } StorageTextureAccess :: enum i32 { - Undefined = 0x00000000, - WriteOnly = 0x00000001, - ReadOnly = 0x00000002, - ReadWrite = 0x00000003, + BindingNotUsed = 0x00000000, + Undefined = 0x00000001, + WriteOnly = 0x00000002, + ReadOnly = 0x00000003, + ReadWrite = 0x00000004, } StoreOp :: enum i32 { @@ -430,24 +490,28 @@ StoreOp :: enum i32 { } SurfaceGetCurrentTextureStatus :: enum i32 { - Success = 0x00000000, - Timeout = 0x00000001, - Outdated = 0x00000002, - Lost = 0x00000003, - OutOfMemory = 0x00000004, - DeviceLost = 0x00000005, + SuccessOptimal = 0x00000001, + SuccessSuboptimal = 0x00000002, + Timeout = 0x00000003, + Outdated = 0x00000004, + Lost = 0x00000005, + OutOfMemory = 0x00000006, + DeviceLost = 0x00000007, + Error = 0x00000008, } TextureAspect :: enum i32 { - All = 0x00000000, - StencilOnly = 0x00000001, - DepthOnly = 0x00000002, + Undefined = 0x00000000, + All = 0x00000001, + StencilOnly = 0x00000002, + DepthOnly = 0x00000003, } TextureDimension :: enum i32 { - _1D = 0x00000000, - _2D = 0x00000001, - _3D = 0x00000002, + Undefined = 0x00000000, + _1D = 0x00000001, + _2D = 0x00000002, + _3D = 0x00000003, } TextureFormat :: enum i32 { @@ -562,12 +626,13 @@ TextureFormat :: enum i32 { } TextureSampleType :: enum i32 { - Undefined = 0x00000000, - Float = 0x00000001, - UnfilterableFloat = 0x00000002, - Depth = 0x00000003, - Sint = 0x00000004, - Uint = 0x00000005, + BindingNotUsed = 0x00000000, + Undefined = 0x00000001, + Float = 0x00000002, + UnfilterableFloat = 0x00000003, + Depth = 0x00000004, + Sint = 0x00000005, + Uint = 0x00000006, } TextureViewDimension :: enum i32 { @@ -581,53 +646,71 @@ TextureViewDimension :: enum i32 { } VertexFormat :: enum i32 { - Undefined = 0x00000000, - Uint8x2 = 0x00000001, - Uint8x4 = 0x00000002, - Sint8x2 = 0x00000003, - Sint8x4 = 0x00000004, - Unorm8x2 = 0x00000005, - Unorm8x4 = 0x00000006, - Snorm8x2 = 0x00000007, - Snorm8x4 = 0x00000008, - Uint16x2 = 0x00000009, - Uint16x4 = 0x0000000A, - Sint16x2 = 0x0000000B, - Sint16x4 = 0x0000000C, - Unorm16x2 = 0x0000000D, - Unorm16x4 = 0x0000000E, - Snorm16x2 = 0x0000000F, - Snorm16x4 = 0x00000010, - Float16x2 = 0x00000011, - Float16x4 = 0x00000012, - Float32 = 0x00000013, - Float32x2 = 0x00000014, - Float32x3 = 0x00000015, - Float32x4 = 0x00000016, - Uint32 = 0x00000017, - Uint32x2 = 0x00000018, - Uint32x3 = 0x00000019, - Uint32x4 = 0x0000001A, - Sint32 = 0x0000001B, - Sint32x2 = 0x0000001C, - Sint32x3 = 0x0000001D, - Sint32x4 = 0x0000001E, + Uint8 = 0x00000001, + Uint8x2 = 0x00000002, + Uint8x4 = 0x00000003, + Sint8 = 0x00000004, + Sint8x2 = 0x00000005, + Sint8x4 = 0x00000006, + Unorm8 = 0x00000007, + Unorm8x2 = 0x00000008, + Unorm8x4 = 0x00000009, + Snorm8 = 0x0000000A, + Snorm8x2 = 0x0000000B, + Snorm8x4 = 0x0000000C, + Uint16 = 0x0000000D, + Uint16x2 = 0x0000000E, + Uint16x4 = 0x0000000F, + Sint16 = 0x00000010, + Sint16x2 = 0x00000011, + Sint16x4 = 0x00000012, + Unorm16 = 0x00000013, + Unorm16x2 = 0x00000014, + Unorm16x4 = 0x00000015, + Snorm16 = 0x00000016, + Snorm16x2 = 0x00000017, + Snorm16x4 = 0x00000018, + Float16 = 0x00000019, + Float16x2 = 0x0000001A, + Float16x4 = 0x0000001B, + Float32 = 0x0000001C, + Float32x2 = 0x0000001D, + Float32x3 = 0x0000001E, + Float32x4 = 0x0000001F, + Uint32 = 0x00000020, + Uint32x2 = 0x00000021, + Uint32x3 = 0x00000022, + Uint32x4 = 0x00000023, + Sint32 = 0x00000024, + Sint32x2 = 0x00000025, + Sint32x3 = 0x00000026, + Sint32x4 = 0x00000027, + Unorm10_10_10_2 = 0x00000028, + Unorm8x4BGRA = 0x00000029, } VertexStepMode :: enum i32 { - Vertex = 0x00000000, - Instance = 0x00000001, - VertexBufferNotUsed = 0x00000002, + VertexBufferNotUsed = 0x00000000, + Undefined = 0x00000001, + Vertex = 0x00000002, + Instance = 0x00000003, } -WGSLFeatureName :: enum i32 { - Undefined = 0x00000000, +WGSLLanguageFeatureName :: enum i32 { ReadonlyAndReadwriteStorageTextures = 0x00000001, Packed4x8IntegerDotProduct = 0x00000002, UnrestrictedPointerParameters = 0x00000003, PointerCompositeAccess = 0x00000004, } +WaitStatus :: enum i32 { + Success = 0x00000001, + TimedOut = 0x00000002, + UnsupportedTimeout = 0x00000003, + UnsupportedCount = 0x00000004, + UnsupportedMixedSource = 0x00000005, +} + BufferUsage :: enum i32 { MapRead = 0x00000000, MapWrite = 0x00000001, @@ -675,45 +758,117 @@ TextureUsageFlags :: bit_set[TextureUsage; Flags] Proc :: distinct rawptr -DeviceLostCallback :: #type proc "c" (reason: DeviceLostReason, message: cstring, userdata: rawptr) -ErrorCallback :: #type proc "c" (type: ErrorType, message: cstring, userdata: rawptr) - -AdapterRequestDeviceCallback :: #type proc "c" (status: RequestDeviceStatus, device: Device, message: cstring, /* NULLABLE */ userdata: rawptr) -BufferMapAsyncCallback :: #type proc "c" (status: BufferMapAsyncStatus, /* NULLABLE */ userdata: rawptr) -DeviceCreateComputePipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: ComputePipeline, message: cstring, /* NULLABLE */ userdata: rawptr) -DeviceCreateRenderPipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: RenderPipeline, message: cstring, /* NULLABLE */ userdata: rawptr) -InstanceRequestAdapterCallback :: #type proc "c" (status: RequestAdapterStatus, adapter: Adapter, message: cstring, /* NULLABLE */ userdata: rawptr) -QueueOnSubmittedWorkDoneCallback :: #type proc "c" (status: QueueWorkDoneStatus, /* NULLABLE */ userdata: rawptr) -ShaderModuleGetCompilationInfoCallback :: #type proc "c" (status: CompilationInfoRequestStatus, compilationInfo: ^CompilationInfo, /* NULLABLE */ userdata: rawptr) +BufferMapCallback :: #type proc "c" (status: MapAsyncStatus, message: StringView, userdata1: rawptr, userdata2: rawptr) +CompilationInfoCallback :: #type proc "c" (status: CompilationInfoRequestStatus, compilationInfo: ^CompilationInfo, userdata1: rawptr, userdata2: rawptr) +CreateComputePipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: ComputePipeline, message: StringView, userdata1: rawptr, userdata2: rawptr) +CreateRenderPipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: RenderPipeline, message: StringView, userdata1: rawptr, userdata2: rawptr) +DeviceLostCallback :: #type proc "c" (device: ^Device, reason: DeviceLostReason, message: StringView, userdata1: rawptr, userdata2: rawptr) +PopErrorScopeCallback :: #type proc "c" (status: PopErrorScopeStatus, type: ErrorType, message: StringView, userdata1: rawptr, userdata2: rawptr) +QueueWorkDoneCallback :: #type proc "c" (status: QueueWorkDoneStatus, userdata1: rawptr, userdata2: rawptr) +RequestAdapterCallback :: #type proc "c" (status: RequestAdapterStatus, adapter: Adapter, message: StringView, userdata1: rawptr, userdata2: rawptr) +RequestDeviceCallback :: #type proc "c" (status: RequestDeviceStatus, adapter: Device, message: StringView, userdata1: rawptr, userdata2: rawptr) +UncapturedErrorCallback :: #type proc "c" (device: ^Device, type: ErrorType, message: StringView, userdata1: rawptr, userdata2: rawptr) ChainedStruct :: struct { - next: ^ChainedStruct, + next: ^ChainedStruct, sType: SType, } ChainedStructOut :: struct { - next: ^ChainedStructOut, + next: ^ChainedStructOut, sType: SType, } +BufferMapCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + mode: CallbackMode, + callback: BufferMapCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + +CompilationInfoCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + mode: CallbackMode, + callback: CompilationInfoCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + +CreateComputePipelineAsyncCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + mode: CallbackMode, + callback: CreateComputePipelineAsyncCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + +CreateRenderPipelineAsyncCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + mode: CallbackMode, + callback: CreateRenderPipelineAsyncCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + +DeviceLostCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + mode: CallbackMode, + callback: DeviceLostCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + +PopErrorScopeCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + mode: CallbackMode, + callback: PopErrorScopeCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + +QueueWorkDoneCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + mode: CallbackMode, + callback: QueueWorkDoneCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + +RequestAdapterCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + mode: CallbackMode, + callback: RequestAdapterCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + +RequestDeviceCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + mode: CallbackMode, + callback: RequestDeviceCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + +UncapturedErrorCallbackInfo :: struct { + nextInChain: /* const */ ^ChainedStruct, + callback: UncapturedErrorCallback, + userdata1: /* NULLABLE */ rawptr, + userdata2: /* NULLABLE */ rawptr, +} + AdapterInfo :: struct { nextInChain: ^ChainedStructOut, - vendor: cstring, - architecture: cstring, - device: cstring, - description: cstring, + vendor: StringView, + architecture: StringView, + device: StringView, + description: StringView, backendType: BackendType, adapterType: AdapterType, vendorID: u32, deviceID: u32, } -when ODIN_OS == .JS { - #assert(int(BackendType.WebGPU) == 2) - #assert(offset_of(AdapterInfo, backendType) == 20) - - #assert(int(AdapterType.Unknown) == 3) - #assert(offset_of(AdapterInfo, adapterType) == 24) -} BindGroupEntry :: struct { nextInChain: ^ChainedStruct, @@ -739,8 +894,8 @@ BufferBindingLayout :: struct { } BufferDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, usage: BufferUsageFlags, size: u64, mappedAtCreation: b32, @@ -749,26 +904,23 @@ BufferDescriptor :: struct { Color :: [4]f64 CommandBufferDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, } CommandEncoderDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, } CompilationMessage :: struct { nextInChain: ^ChainedStruct, - /* NULLABLE */ message: cstring, + message: StringView, type: CompilationMessageType, lineNum: u64, linePos: u64, offset: u64, length: u64, - utf16LinePos: u64, - utf16Offset: u64, - utf16Length: u64, } ComputePassTimestampWrites :: struct { @@ -778,8 +930,8 @@ ComputePassTimestampWrites :: struct { } ConstantEntry :: struct { - nextInChain: ^ChainedStruct, - key: cstring, + nextInChain: /* const */ ^ChainedStruct, + key: StringView, value: f64, } @@ -789,11 +941,18 @@ Extent3D :: struct { depthOrArrayLayers: u32, } -InstanceDescriptor :: struct { - nextInChain: ^ChainedStruct, +Future :: struct { + id: u64, +} + +InstanceCapabilities :: struct { + nextInChain: ^ChainedStructOut, + timedWaitAnyEnable: b32, + timedWaitAnyMaxCount: uint, } Limits :: struct { + nextInChain: ^ChainedStructOut, maxTextureDimension1D: u32, maxTextureDimension2D: u32, maxTextureDimension3D: u32, @@ -816,7 +975,6 @@ Limits :: struct { maxBufferSize: u64, maxVertexAttributes: u32, maxVertexBufferArrayStride: u32, - maxInterStageShaderComponents: u32, maxInterStageShaderVariables: u32, maxColorAttachments: u32, maxColorAttachmentBytesPerSample: u32, @@ -829,7 +987,7 @@ Limits :: struct { } MultisampleState :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, count: u32, mask: u32, alphaToCoverageEnabled: b32, @@ -842,47 +1000,43 @@ Origin3D :: struct { } PipelineLayoutDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, bindGroupLayoutCount: uint, bindGroupLayouts: [^]BindGroupLayout `fmt:"v,bindGroupLayoutCount"`, } -PrimitiveDepthClipControl :: struct { - using chain: ChainedStruct, - unclippedDepth: b32, -} - PrimitiveState :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, topology: PrimitiveTopology, stripIndexFormat: IndexFormat, frontFace: FrontFace, cullMode: CullMode, + unclippedDepth: b32, } QuerySetDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, type: QueryType, count: u32, } QueueDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, } RenderBundleDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, } RenderBundleEncoderDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, colorFormatCount: uint, - colorFormats: [^]TextureFormat `fmt:"v,colorFormatCount"`, + colorFormats: /* const */ [^]TextureFormat `fmt:"v,colorFormatCount"`, depthStencilFormat: TextureFormat, sampleCount: u32, depthReadOnly: b32, @@ -901,7 +1055,7 @@ RenderPassDepthStencilAttachment :: struct { stencilReadOnly: b32, } -RenderPassDescriptorMaxDrawCount :: struct { +RenderPassMaxDrawCount :: struct { using chain: ChainedStruct, maxDrawCount: u64, } @@ -913,21 +1067,22 @@ RenderPassTimestampWrites :: struct { } RequestAdapterOptions :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ compatibleSurface: Surface, + nextInChain: /* const */ ^ChainedStruct, + featureLevel: FeatureLevel, powerPreference: PowerPreference, - backendType: BackendType, forceFallbackAdapter: b32, + backendType: BackendType, + /* NULLABLE */ compatibleSurface: Surface, } SamplerBindingLayout :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, type: SamplerBindingType, } SamplerDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, addressModeU: AddressMode, addressModeV: AddressMode, addressModeW: AddressMode, @@ -940,21 +1095,20 @@ SamplerDescriptor :: struct { maxAnisotropy: u16, } -ShaderModuleCompilationHint :: struct { - nextInChain: ^ChainedStruct, - entryPoint: cstring, - layout: PipelineLayout, +ShaderModuleDescriptor :: struct { + nextInChain: /* const */ ^ChainedStruct, + label: StringView, } -ShaderModuleSPIRVDescriptor :: struct { +ShaderSourceSPIRV :: struct { using chain: ChainedStruct, codeSize: u32, code: /* const */ [^]u32 `fmt:"v,codeSize"`, } -ShaderModuleWGSLDescriptor :: struct { +ShaderSourceWGSL :: struct { using chain: ChainedStruct, - code: cstring, + code: StringView, } StencilFaceState :: struct { @@ -965,12 +1119,22 @@ StencilFaceState :: struct { } StorageTextureBindingLayout :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, access: StorageTextureAccess, format: TextureFormat, viewDimension: TextureViewDimension, } +SupportedFeatures :: struct { + featureCount: uint, + features: /* const */ [^]FeatureName `fmt:"v,featureCount"`, +} + +SupportedWGSLLanguageFeatures :: struct { + featureCount: uint, + features: /* const */ [^]WGSLLanguageFeatureName `fmt:"v,featureCount"`, +} + SurfaceCapabilities :: struct { nextInChain: ^ChainedStructOut, usages: TextureUsageFlags, @@ -981,97 +1145,86 @@ SurfaceCapabilities :: struct { alphaModeCount: uint, alphaModes: /* const */ [^]CompositeAlphaMode `fmt:"v,alphaModeCount"`, } -when ODIN_OS == .JS { - #assert(offset_of(SurfaceCapabilities, formatCount) == 8) - #assert(offset_of(SurfaceCapabilities, formats) == 8 + 1*size_of(int)) - - #assert(offset_of(SurfaceCapabilities, presentModeCount) == 8 + 2*size_of(int)) - #assert(offset_of(SurfaceCapabilities, presentModes) == 8 + 3*size_of(int)) - - #assert(offset_of(SurfaceCapabilities, alphaModeCount) == 8 + 4*size_of(int)) - #assert(offset_of(SurfaceCapabilities, alphaModes) == 8 + 5*size_of(int)) -} SurfaceConfiguration :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, device: Device, format: TextureFormat, usage: TextureUsageFlags, - viewFormatCount: uint, - viewFormats: [^]TextureFormat `fmt:"v,viewFormatCount"`, - alphaMode: CompositeAlphaMode, width: u32, height: u32, + viewFormatCount: uint, + viewFormats: /* const */ [^]TextureFormat `fmt:"v,viewFormatCount"`, + alphaMode: CompositeAlphaMode, presentMode: PresentMode, } SurfaceDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, } -SurfaceDescriptorFromAndroidNativeWindow :: struct { +SurfaceSourceAndroidNativeWindow :: struct { using chain: ChainedStruct, window: rawptr, } -SurfaceDescriptorFromCanvasHTMLSelector :: struct { +SurfaceSourceCanvasHTMLSelector :: struct { using chain: ChainedStruct, - selector: cstring, + selector: StringView, } -SurfaceDescriptorFromMetalLayer :: struct { +SurfaceSourceMetalLayer :: struct { using chain: ChainedStruct, layer: rawptr, } -SurfaceDescriptorFromWaylandSurface :: struct { +SurfaceSourceWaylandSurface :: struct { using chain: ChainedStruct, display: rawptr, surface: rawptr, } -SurfaceDescriptorFromWindowsHWND :: struct { +SurfaceSourceWindowsHWND :: struct { using chain: ChainedStruct, hinstance: rawptr, hwnd: rawptr, } -SurfaceDescriptorFromXcbWindow :: struct { +SurfaceSourceXcbWindow :: struct { using chain: ChainedStruct, connection: rawptr, window: u32, } -SurfaceDescriptorFromXlibWindow :: struct { +SurfaceSourceXlibWindow :: struct { using chain: ChainedStruct, display: rawptr, window: u64, } SurfaceTexture :: struct { + nextInChain: ^ChainedStructOut, texture: Texture, - suboptimal: b32, status: SurfaceGetCurrentTextureStatus, } -TextureBindingLayout :: struct { - nextInChain: ^ChainedStruct, - sampleType: TextureSampleType, - viewDimension: TextureViewDimension, - multisampled: b32, -} - -TextureDataLayout :: struct { - nextInChain: ^ChainedStruct, +TexelCopyBufferLayout :: struct { offset: u64, bytesPerRow: u32, rowsPerImage: u32, } +TextureBindingLayout :: struct { + nextInChain: /* const */ ^ChainedStruct, + sampleType: TextureSampleType, + viewDimension: TextureViewDimension, + multisampled: b32, +} + TextureViewDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, format: TextureFormat, dimension: TextureViewDimension, baseMipLevel: u32, @@ -1079,12 +1232,7 @@ TextureViewDescriptor :: struct { baseArrayLayer: u32, arrayLayerCount: u32, aspect: TextureAspect, -} - -UncapturedErrorCallbackInfo :: struct { - nextInChain: ^ChainedStruct, - callback: ErrorCallback, - userdata: rawptr, + usage: TextureUsageFlags, } VertexAttribute :: struct { @@ -1094,15 +1242,15 @@ VertexAttribute :: struct { } BindGroupDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, layout: BindGroupLayout, entryCount: uint, - entries: [^]BindGroupEntry `fmt:"v,entryCount"`, + entries: /* const */ [^]BindGroupEntry `fmt:"v,entryCount"`, } BindGroupLayoutEntry :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, binding: u32, visibility: ShaderStageFlags, buffer: BufferBindingLayout, @@ -1117,21 +1265,21 @@ BlendState :: struct { } CompilationInfo :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, messageCount: uint, - messages: [^]CompilationMessage `fmt:"v,messageCount"`, + messages: /* const */ [^]CompilationMessage `fmt:"v,messageCount"`, } ComputePassDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, /* NULLABLE */ timestampWrites: /* const */ ^ComputePassTimestampWrites, } DepthStencilState :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, format: TextureFormat, - depthWriteEnabled: b32, + depthWriteEnabled: OptionalBool, depthCompare: CompareFunction, stencilFront: StencilFaceState, stencilBack: StencilFaceState, @@ -1142,30 +1290,37 @@ DepthStencilState :: struct { depthBiasClamp: f32, } -ImageCopyBuffer :: struct { - nextInChain: ^ChainedStruct, - layout: TextureDataLayout, - buffer: Buffer, +DeviceDescriptor :: struct { + nextInChain: /* const */ ^ChainedStruct, + label: StringView, + requiredFeatureCount: uint, + requiredFeatures: /* const */ [^]FeatureName `fmt:"v,requiredFeatureCount"`, + /* NULLABLE */ requiredLimits: /* const */ ^Limits, + defaultQueue: QueueDescriptor, + deviceLostCallbackInfo: DeviceLostCallbackInfo, + uncapturedErrorCallbackInfo: UncapturedErrorCallbackInfo, } -ImageCopyTexture :: struct { - nextInChain: ^ChainedStruct, - texture: Texture, - mipLevel: u32, - origin: Origin3D, - aspect: TextureAspect, +FutureWaitInfo :: struct { + future: Future, + completed: b32, +} + +InstanceDescriptor :: struct { + nextInChain: /* const */ ^ChainedStruct, + features: InstanceCapabilities, } ProgrammableStageDescriptor :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, module: ShaderModule, - /* NULLABLE */ entryPoint: cstring, + entryPoint: StringView, constantCount: uint, constants: [^]ConstantEntry `fmt:"v,constantCount"`, } RenderPassColorAttachment :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, /* NULLABLE */ view: TextureView, depthSlice: u32, /* NULLABLE */ resolveTarget: TextureView, @@ -1173,36 +1328,22 @@ RenderPassColorAttachment :: struct { storeOp: StoreOp, clearValue: Color, } -when ODIN_OS == .JS { - #assert(size_of(RenderPassColorAttachment) == 56) - #assert(offset_of(RenderPassColorAttachment, view) == 4) - #assert(offset_of(RenderPassColorAttachment, depthSlice) == 8) - #assert(offset_of(RenderPassColorAttachment, resolveTarget) == 12) - #assert(offset_of(RenderPassColorAttachment, loadOp) == 16) - #assert(offset_of(RenderPassColorAttachment, storeOp) == 20) - #assert(offset_of(RenderPassColorAttachment, clearValue) == 24) + +TexelCopyBufferInfo :: struct { + layout: TexelCopyBufferLayout, + buffer: Buffer, } -RequiredLimits :: struct { - nextInChain: ^ChainedStruct, - limits: Limits, -} - -ShaderModuleDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, - hintCount: uint, - hints: [^]ShaderModuleCompilationHint `fmt:"v,hintCount"`, -} - -SupportedLimits :: struct { - nextInChain: ^ChainedStructOut, - limits: Limits, +TexelCopyTextureInfo :: struct { + texture: Texture, + mipLevel: u32, + origin: Origin3D, + aspect: TextureAspect, } TextureDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, usage: TextureUsageFlags, dimension: TextureDimension, size: Extent3D, @@ -1210,21 +1351,21 @@ TextureDescriptor :: struct { mipLevelCount: u32, sampleCount: u32, viewFormatCount: uint, - viewFormats: [^]TextureFormat `fmt:"v,viewFormatCount"`, + viewFormats: /* const */ [^]TextureFormat `fmt:"v,viewFormatCount"`, } VertexBufferLayout :: struct { - arrayStride: u64, stepMode: VertexStepMode, + arrayStride: u64, attributeCount: uint, - attributes: [^]VertexAttribute `fmt:"v,attributeCount"`, + attributes: /* const */ [^]VertexAttribute `fmt:"v,attributeCount"`, } BindGroupLayoutDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, entryCount: uint, - entries: [^]BindGroupLayoutEntry `fmt:"v,entryCount"`, + entries: /* const */ [^]BindGroupLayoutEntry `fmt:"v,entryCount"`, } ColorTargetState :: struct { @@ -1235,60 +1376,45 @@ ColorTargetState :: struct { } ComputePipelineDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, /* NULLABLE */ layout: PipelineLayout, compute: ProgrammableStageDescriptor, } -DeviceDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, - requiredFeatureCount: uint, - requiredFeatures: [^]FeatureName `fmt:"v,requiredFeatureCount"`, - /* NULLABLE */ requiredLimits: /* const */ ^RequiredLimits, - defaultQueue: QueueDescriptor, - deviceLostCallback: DeviceLostCallback, - deviceLostUserdata: rawptr, - uncapturedErrorCallbackInfo: UncapturedErrorCallbackInfo, -} -when ODIN_OS == .JS { - #assert(offset_of(DeviceDescriptor, deviceLostCallback) == 24 + size_of(int)) -} - RenderPassDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, colorAttachmentCount: uint, - colorAttachments: [^]RenderPassColorAttachment `fmt:"v,colorAttachmentCount"`, + colorAttachments: /* const */ [^]RenderPassColorAttachment `fmt:"v,colorAttachmentCount"`, /* NULLABLE */ depthStencilAttachment: /* const */ ^RenderPassDepthStencilAttachment, /* NULLABLE */ occlusionQuerySet: QuerySet, /* NULLABLE */ timestampWrites: /* const */ ^RenderPassTimestampWrites, } VertexState :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, module: ShaderModule, - /* NULLABLE */ entryPoint: cstring, + entryPoint: StringView, constantCount: uint, - constants: [^]ConstantEntry `fmt:"v,constantCount"`, + constants: /* const */ [^]ConstantEntry `fmt:"v,constantCount"`, bufferCount: uint, - buffers: [^]VertexBufferLayout `fmt:"v,bufferCount"`, + buffers: /* const */ [^]VertexBufferLayout `fmt:"v,bufferCount"`, } FragmentState :: struct { - nextInChain: ^ChainedStruct, + nextInChain: /* const */ ^ChainedStruct, module: ShaderModule, - /* NULLABLE */ entryPoint: cstring, + entryPoint: StringView, constantCount: uint, - constants: [^]ConstantEntry `fmt:"v,constantCount"`, + constants: /* const */ [^]ConstantEntry `fmt:"v,constantCount"`, targetCount: uint, - targets: [^]ColorTargetState `fmt:"v,targetCount"`, + targets: /* const */ [^]ColorTargetState `fmt:"v,targetCount"`, } RenderPipelineDescriptor :: struct { - nextInChain: ^ChainedStruct, - /* NULLABLE */ label: cstring, + nextInChain: /* const */ ^ChainedStruct, + label: StringView, /* NULLABLE */ layout: PipelineLayout, vertex: VertexState, primitive: PrimitiveState, @@ -1301,31 +1427,33 @@ RenderPipelineDescriptor :: struct { foreign libwgpu { @(link_name="wgpuCreateInstance") RawCreateInstance :: proc(/* NULLABLE */ descriptor: /* const */ ^InstanceDescriptor = nil) -> Instance --- - GetProcAddress :: proc(device: Device, procName: cstring) -> Proc --- + @(link_name="wgpuGetInstanceCapabilities") + RawGetInstanceCapabilities :: proc(capabilities: ^InstanceCapabilities) -> Status --- + GetProcAddress :: proc(procName: StringView) -> Proc --- // Methods of Adapter - @(link_name="wgpuAdapterEnumerateFeatures") - RawAdapterEnumerateFeatures :: proc(adapter: Adapter, features: [^]FeatureName) -> uint --- + @(link_name="wgpuAdapterGetFeatures") + RawAdapterGetFeatures :: proc(adapter: Adapter, features: ^SupportedFeatures) --- @(link_name="wgpuAdapterGetInfo") - RawAdapterGetInfo :: proc(adapter: Adapter, info: ^AdapterInfo) --- + RawAdapterGetInfo :: proc(adapter: Adapter, info: ^AdapterInfo) -> Status --- @(link_name="wgpuAdapterGetLimits") - RawAdapterGetLimits :: proc(adapter: Adapter, limits: ^SupportedLimits) -> b32 --- + RawAdapterGetLimits :: proc(adapter: Adapter, limits: ^Limits) -> Status --- AdapterHasFeature :: proc(adapter: Adapter, feature: FeatureName) -> b32 --- - AdapterRequestDevice :: proc(adapter: Adapter, /* NULLABLE */ descriptor: /* const */ ^DeviceDescriptor, callback: AdapterRequestDeviceCallback, /* NULLABLE */ userdata: rawptr = nil) --- - AdapterReference :: proc(adapter: Adapter) --- + AdapterRequestDevice :: proc(adapter: Adapter, /* NULLABLE */ descriptor: /* const */ ^DeviceDescriptor, callbackInfo: RequestDeviceCallbackInfo) -> Future --- + AdapterAddRef :: proc(adapter: Adapter) --- AdapterRelease :: proc(adapter: Adapter) --- // Procs of AdapterInfo AdapterInfoFreeMembers :: proc(adapterInfo: AdapterInfo) --- // Methods of BindGroup - BindGroupSetLabel :: proc(bindGroup: BindGroup, label: cstring) --- - BindGroupReference :: proc(bindGroup: BindGroup) --- + BindGroupSetLabel :: proc(bindGroup: BindGroup, label: StringView) --- + BindGroupAddRef :: proc(bindGroup: BindGroup) --- BindGroupRelease :: proc(bindGroup: BindGroup) --- // Methods of BindGroupLayout BindGroupLayoutSetLabel :: proc(bindGroupLayout: BindGroupLayout, label: cstring) --- - BindGroupLayoutReference :: proc(bindGroupLayout: BindGroupLayout) --- + BindGroupLayoutAddRef :: proc(bindGroupLayout: BindGroupLayout) --- BindGroupLayoutRelease :: proc(bindGroupLayout: BindGroupLayout) --- // Methods of Buffer @@ -1337,15 +1465,15 @@ foreign libwgpu { RawBufferGetMappedRange :: proc(buffer: Buffer, offset: uint, size: uint) -> rawptr --- BufferGetSize :: proc(buffer: Buffer) -> u64 --- BufferGetUsage :: proc(buffer: Buffer) -> BufferUsageFlags --- - BufferMapAsync :: proc(buffer: Buffer, mode: MapModeFlags, offset: uint, size: uint, callback: BufferMapAsyncCallback, /* NULLABLE */ userdata: rawptr = nil) --- - BufferSetLabel :: proc(buffer: Buffer, label: cstring) --- + BufferMapAsync :: proc(buffer: Buffer, mode: MapModeFlags, offset: uint, size: uint, callbackInfo: BufferMapCallbackInfo) -> Future --- + BufferSetLabel :: proc(buffer: Buffer, label: StringView) --- BufferUnmap :: proc(buffer: Buffer) --- - BufferReference :: proc(buffer: Buffer) --- + BufferAddRef :: proc(buffer: Buffer) --- BufferRelease :: proc(buffer: Buffer) --- // Methods of CommandBuffer - CommandBufferSetLabel :: proc(commandBuffer: CommandBuffer, label: cstring) --- - CommandBufferReference :: proc(commandBuffer: CommandBuffer) --- + CommandBufferSetLabel :: proc(commandBuffer: CommandBuffer, label: StringView) --- + CommandBufferAddRef :: proc(commandBuffer: CommandBuffer) --- CommandBufferRelease :: proc(commandBuffer: CommandBuffer) --- // Methods of CommandEncoder @@ -1353,37 +1481,37 @@ foreign libwgpu { CommandEncoderBeginRenderPass :: proc(commandEncoder: CommandEncoder, descriptor: /* const */ ^RenderPassDescriptor) -> RenderPassEncoder --- CommandEncoderClearBuffer :: proc(commandEncoder: CommandEncoder, buffer: Buffer, offset: u64, size: u64) --- CommandEncoderCopyBufferToBuffer :: proc(commandEncoder: CommandEncoder, source: Buffer, sourceOffset: u64, destination: Buffer, destinationOffset: u64, size: u64) --- - CommandEncoderCopyBufferToTexture :: proc(commandEncoder: CommandEncoder, source: /* const */ ^ImageCopyBuffer, destination: /* const */ ^ImageCopyTexture, copySize: /* const */ ^Extent3D) --- - CommandEncoderCopyTextureToBuffer :: proc(commandEncoder: CommandEncoder, source: /* const */ ^ImageCopyTexture, destination: /* const */ ^ImageCopyBuffer, copySize: /* const */ ^Extent3D) --- - CommandEncoderCopyTextureToTexture :: proc(commandEncoder: CommandEncoder, source: /* const */ ^ImageCopyTexture, destination: /* const */ ^ImageCopyTexture, copySize: /* const */ ^Extent3D) --- + CommandEncoderCopyBufferToTexture :: proc(commandEncoder: CommandEncoder, source: /* const */ ^TexelCopyBufferInfo, destination: /* const */ ^TexelCopyTextureInfo, copySize: /* const */ ^Extent3D) --- + CommandEncoderCopyTextureToBuffer :: proc(commandEncoder: CommandEncoder, source: /* const */ ^TexelCopyTextureInfo, destination: /* const */ ^TexelCopyBufferInfo, copySize: /* const */ ^Extent3D) --- + CommandEncoderCopyTextureToTexture :: proc(commandEncoder: CommandEncoder, source: /* const */ ^TexelCopyTextureInfo, destination: /* const */ ^TexelCopyTextureInfo, copySize: /* const */ ^Extent3D) --- CommandEncoderFinish :: proc(commandEncoder: CommandEncoder, /* NULLABLE */ descriptor: /* const */ ^CommandBufferDescriptor = nil) -> CommandBuffer --- - CommandEncoderInsertDebugMarker :: proc(commandEncoder: CommandEncoder, markerLabel: cstring) --- + CommandEncoderInsertDebugMarker :: proc(commandEncoder: CommandEncoder, markerLabel: StringView) --- CommandEncoderPopDebugGroup :: proc(commandEncoder: CommandEncoder) --- - CommandEncoderPushDebugGroup :: proc(commandEncoder: CommandEncoder, groupLabel: cstring) --- + CommandEncoderPushDebugGroup :: proc(commandEncoder: CommandEncoder, groupLabel: StringView) --- CommandEncoderResolveQuerySet :: proc(commandEncoder: CommandEncoder, querySet: QuerySet, firstQuery: u32, queryCount: u32, destination: Buffer, destinationOffset: u64) --- - CommandEncoderSetLabel :: proc(commandEncoder: CommandEncoder, label: cstring) --- + CommandEncoderSetLabel :: proc(commandEncoder: CommandEncoder, label: StringView) --- CommandEncoderWriteTimestamp :: proc(commandEncoder: CommandEncoder, querySet: QuerySet, queryIndex: u32) --- - CommandEncoderReference :: proc(commandEncoder: CommandEncoder) --- + CommandEncoderAddRef :: proc(commandEncoder: CommandEncoder) --- CommandEncoderRelease :: proc(commandEncoder: CommandEncoder) --- // Methods of ComputePassEncoder ComputePassEncoderDispatchWorkgroups :: proc(computePassEncoder: ComputePassEncoder, workgroupCountX: u32, workgroupCountY: u32, workgroupCountZ: u32) --- ComputePassEncoderDispatchWorkgroupsIndirect :: proc(computePassEncoder: ComputePassEncoder, indirectBuffer: Buffer, indirectOffset: u64) --- ComputePassEncoderEnd :: proc(computePassEncoder: ComputePassEncoder) --- - ComputePassEncoderInsertDebugMarker :: proc(computePassEncoder: ComputePassEncoder, markerLabel: cstring) --- + ComputePassEncoderInsertDebugMarker :: proc(computePassEncoder: ComputePassEncoder, markerLabel: StringView) --- ComputePassEncoderPopDebugGroup :: proc(computePassEncoder: ComputePassEncoder) --- - ComputePassEncoderPushDebugGroup :: proc(computePassEncoder: ComputePassEncoder, groupLabel: cstring) --- + ComputePassEncoderPushDebugGroup :: proc(computePassEncoder: ComputePassEncoder, groupLabel: StringView) --- @(link_name="wgpuComputePassEncoderSetBindGroup") - RawComputePassEncoderSetBindGroup :: proc(computePassEncoder: ComputePassEncoder, groupIndex: u32, /* NULLABLE */ group: BindGroup, dynamicOffsetCount: uint, dynamicOffsets: [^]u32) --- - ComputePassEncoderSetLabel :: proc(computePassEncoder: ComputePassEncoder, label: cstring) --- + RawComputePassEncoderSetBindGroup :: proc(computePassEncoder: ComputePassEncoder, groupIndex: u32, /* NULLABLE */ group: BindGroup, dynamicOffsetCount: uint, dynamicOffsets: /* const */ [^]u32) --- + ComputePassEncoderSetLabel :: proc(computePassEncoder: ComputePassEncoder, label: StringView) --- ComputePassEncoderSetPipeline :: proc(computePassEncoder: ComputePassEncoder, pipeline: ComputePipeline) --- - ComputePassEncoderReference :: proc(computePassEncoder: ComputePassEncoder) --- + ComputePassEncoderAddRef :: proc(computePassEncoder: ComputePassEncoder) --- ComputePassEncoderRelease :: proc(computePassEncoder: ComputePassEncoder) --- // Methods of ComputePipeline ComputePipelineGetBindGroupLayout :: proc(computePipeline: ComputePipeline, groupIndex: u32) -> BindGroupLayout --- - ComputePipelineSetLabel :: proc(computePipeline: ComputePipeline, label: cstring) --- - ComputePipelineReference :: proc(computePipeline: ComputePipeline) --- + ComputePipelineSetLabel :: proc(computePipeline: ComputePipeline, label: StringView) --- + ComputePipelineAddRef :: proc(computePipeline: ComputePipeline) --- ComputePipelineRelease :: proc(computePipeline: ComputePipeline) --- // Methods of Device @@ -1392,62 +1520,68 @@ foreign libwgpu { DeviceCreateBuffer :: proc(device: Device, descriptor: /* const */ ^BufferDescriptor) -> Buffer --- DeviceCreateCommandEncoder :: proc(device: Device, /* NULLABLE */ descriptor: /* const */ ^CommandEncoderDescriptor = nil) -> CommandEncoder --- DeviceCreateComputePipeline :: proc(device: Device, descriptor: /* const */ ^ComputePipelineDescriptor) -> ComputePipeline --- - DeviceCreateComputePipelineAsync :: proc(device: Device, descriptor: /* const */ ^ComputePipelineDescriptor, callback: DeviceCreateComputePipelineAsyncCallback, /* NULLABLE */ userdata: rawptr = nil) --- + DeviceCreateComputePipelineAsync :: proc(device: Device, descriptor: /* const */ ^ComputePipelineDescriptor, callbackInfo: CreateComputePipelineAsyncCallbackInfo) -> Future --- DeviceCreatePipelineLayout :: proc(device: Device, descriptor: /* const */ ^PipelineLayoutDescriptor) -> PipelineLayout --- DeviceCreateQuerySet :: proc(device: Device, descriptor: /* const */ ^QuerySetDescriptor) -> QuerySet --- DeviceCreateRenderBundleEncoder :: proc(device: Device, descriptor: /* const */ ^RenderBundleEncoderDescriptor) -> RenderBundleEncoder --- DeviceCreateRenderPipeline :: proc(device: Device, descriptor: /* const */ ^RenderPipelineDescriptor) -> RenderPipeline --- - DeviceCreateRenderPipelineAsync :: proc(device: Device, descriptor: /* const */ ^RenderPipelineDescriptor, callback: DeviceCreateRenderPipelineAsyncCallback, /* NULLABLE */ userdata: rawptr = nil) --- + DeviceCreateRenderPipelineAsync :: proc(device: Device, descriptor: /* const */ ^RenderPipelineDescriptor, callbackInfo: CreateRenderPipelineAsyncCallbackInfo) -> Future --- DeviceCreateSampler :: proc(device: Device, /* NULLABLE */ descriptor: /* const */ ^SamplerDescriptor = nil) -> Sampler --- DeviceCreateShaderModule :: proc(device: Device, descriptor: /* const */ ^ShaderModuleDescriptor) -> ShaderModule --- DeviceCreateTexture :: proc(device: Device, descriptor: /* const */ ^TextureDescriptor) -> Texture --- DeviceDestroy :: proc(device: Device) --- - @(link_name="wgpuDeviceEnumerateFeatures") - RawDeviceEnumerateFeatures :: proc(device: Device, features: ^FeatureName) -> uint --- + @(link_name="wgpuDeviceGetAdapterInfo") + RawDeviceGetAdapterInfo :: proc(device: Device, info: ^AdapterInfo) -> Status --- + @(link_name="wgpuDeviceGetFeatures") + RawDeviceGetFeatures :: proc(device: Device, features: ^SupportedFeatures) --- @(link_name="wgpuDeviceGetLimits") - RawDeviceGetLimits :: proc(device: Device, limits: ^SupportedLimits) -> b32 --- + RawDeviceGetLimits :: proc(device: Device, limits: ^Limits) -> Status --- + DeviceGetLostFuture :: proc(device: Device) -> Future --- DeviceGetQueue :: proc(device: Device) -> Queue --- DeviceHasFeature :: proc(device: Device, feature: FeatureName) -> b32 --- - DevicePopErrorScope :: proc(device: Device, callback: ErrorCallback, userdata: rawptr) --- + DevicePopErrorScope :: proc(device: Device, callbackInfo: PopErrorScopeCallbackInfo) -> Future --- DevicePushErrorScope :: proc(device: Device, filter: ErrorFilter) --- - DeviceSetLabel :: proc(device: Device, label: cstring) --- - DeviceReference :: proc(device: Device) --- + DeviceSetLabel :: proc(device: Device, label: StringView) --- + DeviceAddRef :: proc(device: Device) --- DeviceRelease :: proc(device: Device) --- // Methods of Instance InstanceCreateSurface :: proc(instance: Instance, descriptor: /* const */ ^SurfaceDescriptor) -> Surface --- - InstanceHasWGSLLanguageFeature :: proc(instance: Instance, feature: WGSLFeatureName) -> b32 --- + @(link_name="wgpuInstanceGetWGSLLanguageFeatures") + RawInstanceGetWGSLLanguageFeatures :: proc(instance: Instance, features: ^SupportedWGSLLanguageFeatures) -> Status --- + InstanceHasWGSLLanguageFeature :: proc(instance: Instance, feature: WGSLLanguageFeatureName) -> b32 --- InstanceProcessEvents :: proc(instance: Instance) --- - InstanceRequestAdapter :: proc(instance: Instance, /* NULLABLE */ options: /* const */ ^RequestAdapterOptions, callback: InstanceRequestAdapterCallback, /* NULLABLE */ userdata: rawptr = nil) --- - InstanceReference :: proc(instance: Instance) --- + InstanceRequestAdapter :: proc(instance: Instance, /* NULLABLE */ options: /* const */ ^RequestAdapterOptions, callbackInfo: RequestAdapterCallbackInfo) -> Future --- + InstanceWaitAny :: proc(instance: Instance, futureCount: uint, futures: [^]FutureWaitInfo, timeoutNS: u64) -> WaitStatus --- + InstanceAddRef :: proc(instance: Instance) --- InstanceRelease :: proc(instance: Instance) --- // Methods of PipelineLayout - PipelineLayoutSetLabel :: proc(pipelineLayout: PipelineLayout, label: cstring) --- - PipelineLayoutReference :: proc(pipelineLayout: PipelineLayout) --- + PipelineLayoutSetLabel :: proc(pipelineLayout: PipelineLayout, label: StringView) --- + PipelineLayoutAddRef :: proc(pipelineLayout: PipelineLayout) --- PipelineLayoutRelease :: proc(pipelineLayout: PipelineLayout) --- // Methods of QuerySet QuerySetDestroy :: proc(querySet: QuerySet) --- QuerySetGetCount :: proc(querySet: QuerySet) -> u32 --- QuerySetGetType :: proc(querySet: QuerySet) -> QueryType --- - QuerySetSetLabel :: proc(querySet: QuerySet, label: cstring) --- - QuerySetReference :: proc(querySet: QuerySet) --- + QuerySetSetLabel :: proc(querySet: QuerySet, label: StringView) --- + QuerySetAddRef :: proc(querySet: QuerySet) --- QuerySetRelease :: proc(querySet: QuerySet) --- // Methods of Queue - QueueOnSubmittedWorkDone :: proc(queue: Queue, callback: QueueOnSubmittedWorkDoneCallback, /* NULLABLE */ userdata: rawptr = nil) --- - QueueSetLabel :: proc(queue: Queue, label: cstring) --- + QueueOnSubmittedWorkDone :: proc(queue: Queue, callbackInfo: QueueWorkDoneCallbackInfo) -> Future --- + QueueSetLabel :: proc(queue: Queue, label: StringView) --- @(link_name="wgpuQueueSubmit") - RawQueueSubmit :: proc(queue: Queue, commandCount: uint, commands: [^]CommandBuffer) --- + RawQueueSubmit :: proc(queue: Queue, commandCount: uint, commands: /* const */ [^]CommandBuffer) --- QueueWriteBuffer :: proc(queue: Queue, buffer: Buffer, bufferOffset: u64, data: /* const */ rawptr, size: uint) --- - QueueWriteTexture :: proc(queue: Queue, destination: /* const */ ^ImageCopyTexture, data: /* const */ rawptr, dataSize: uint, dataLayout: /* const */ ^TextureDataLayout, writeSize: /* const */ ^Extent3D) --- - QueueReference :: proc(queue: Queue) --- + QueueWriteTexture :: proc(queue: Queue, destination: /* const */ ^TexelCopyTextureInfo, data: /* const */ rawptr, dataSize: uint, dataLayout: /* const */ ^TexelCopyBufferLayout, writeSize: /* const */ ^Extent3D) --- + QueueAddRef :: proc(queue: Queue) --- QueueRelease :: proc(queue: Queue) --- // Methods of RenderBundle - RenderBundleSetLabel :: proc(renderBundle: RenderBundle, label: cstring) --- - RenderBundleReference :: proc(renderBundle: RenderBundle) --- + RenderBundleSetLabel :: proc(renderBundle: RenderBundle, label: StringView) --- + RenderBundleAddRef :: proc(renderBundle: RenderBundle) --- RenderBundleRelease :: proc(renderBundle: RenderBundle) --- // Methods of RenderBundleEncoder @@ -1456,16 +1590,16 @@ foreign libwgpu { RenderBundleEncoderDrawIndexedIndirect :: proc(renderBundleEncoder: RenderBundleEncoder, indirectBuffer: Buffer, indirectOffset: u64) --- RenderBundleEncoderDrawIndirect :: proc(renderBundleEncoder: RenderBundleEncoder, indirectBuffer: Buffer, indirectOffset: u64) --- RenderBundleEncoderFinish :: proc(renderBundleEncoder: RenderBundleEncoder, /* NULLABLE */ descriptor: /* const */ ^RenderBundleDescriptor = nil) -> RenderBundle --- - RenderBundleEncoderInsertDebugMarker :: proc(renderBundleEncoder: RenderBundleEncoder, markerLabel: cstring) --- + RenderBundleEncoderInsertDebugMarker :: proc(renderBundleEncoder: RenderBundleEncoder, markerLabel: StringView) --- RenderBundleEncoderPopDebugGroup :: proc(renderBundleEncoder: RenderBundleEncoder) --- - RenderBundleEncoderPushDebugGroup :: proc(renderBundleEncoder: RenderBundleEncoder, groupLabel: cstring) --- + RenderBundleEncoderPushDebugGroup :: proc(renderBundleEncoder: RenderBundleEncoder, groupLabel: StringView) --- @(link_name="wgpuRenderBundleEncoderSetBindGroup") - RawRenderBundleEncoderSetBindGroup :: proc(renderBundleEncoder: RenderBundleEncoder, groupIndex: u32, /* NULLABLE */ group: BindGroup, dynamicOffsetCount: uint, dynamicOffsets: [^]u32) --- + RawRenderBundleEncoderSetBindGroup :: proc(renderBundleEncoder: RenderBundleEncoder, groupIndex: u32, /* NULLABLE */ group: BindGroup, dynamicOffsetCount: uint, dynamicOffsets: /* const */ [^]u32) --- RenderBundleEncoderSetIndexBuffer :: proc(renderBundleEncoder: RenderBundleEncoder, buffer: Buffer, format: IndexFormat, offset: u64, size: u64) --- - RenderBundleEncoderSetLabel :: proc(renderBundleEncoder: RenderBundleEncoder, label: cstring) --- + RenderBundleEncoderSetLabel :: proc(renderBundleEncoder: RenderBundleEncoder, label: StringView) --- RenderBundleEncoderSetPipeline :: proc(renderBundleEncoder: RenderBundleEncoder, pipeline: RenderPipeline) --- RenderBundleEncoderSetVertexBuffer :: proc(renderBundleEncoder: RenderBundleEncoder, slot: u32, /* NULLABLE */ buffer: Buffer, offset: u64, size: u64) --- - RenderBundleEncoderReference :: proc(renderBundleEncoder: RenderBundleEncoder) --- + RenderBundleEncoderAddRef :: proc(renderBundleEncoder: RenderBundleEncoder) --- RenderBundleEncoderRelease :: proc(renderBundleEncoder: RenderBundleEncoder) --- // Methods of RenderPassEncoder @@ -1477,50 +1611,56 @@ foreign libwgpu { RenderPassEncoderEnd :: proc(renderPassEncoder: RenderPassEncoder) --- RenderPassEncoderEndOcclusionQuery :: proc(renderPassEncoder: RenderPassEncoder) --- @(link_name="wgpuRenderPassEncoderExecuteBundles") - RawRenderPassEncoderExecuteBundles :: proc(renderPassEncoder: RenderPassEncoder, bundleCount: uint, bundles: [^]RenderBundle) --- - RenderPassEncoderInsertDebugMarker :: proc(renderPassEncoder: RenderPassEncoder, markerLabel: cstring) --- + RawRenderPassEncoderExecuteBundles :: proc(renderPassEncoder: RenderPassEncoder, bundleCount: uint, bundles: /* const */ [^]RenderBundle) --- + RenderPassEncoderInsertDebugMarker :: proc(renderPassEncoder: RenderPassEncoder, markerLabel: StringView) --- RenderPassEncoderPopDebugGroup :: proc(renderPassEncoder: RenderPassEncoder) --- - RenderPassEncoderPushDebugGroup :: proc(renderPassEncoder: RenderPassEncoder, groupLabel: cstring) --- + RenderPassEncoderPushDebugGroup :: proc(renderPassEncoder: RenderPassEncoder, groupLabel: StringView) --- @(link_name="wgpuRenderPassEncoderSetBindGroup") - RawRenderPassEncoderSetBindGroup :: proc(renderPassEncoder: RenderPassEncoder, groupIndex: u32, /* NULLABLE */ group: BindGroup, dynamicOffsetCount: uint, dynamicOffsets: [^]u32) --- + RawRenderPassEncoderSetBindGroup :: proc(renderPassEncoder: RenderPassEncoder, groupIndex: u32, /* NULLABLE */ group: BindGroup, dynamicOffsetCount: uint, dynamicOffsets: /* const */ [^]u32) --- RenderPassEncoderSetBlendConstant :: proc(renderPassEncoder: RenderPassEncoder, color: /* const */ ^Color) --- RenderPassEncoderSetIndexBuffer :: proc(renderPassEncoder: RenderPassEncoder, buffer: Buffer, format: IndexFormat, offset: u64, size: u64) --- - RenderPassEncoderSetLabel :: proc(renderPassEncoder: RenderPassEncoder, label: cstring) --- + RenderPassEncoderSetLabel :: proc(renderPassEncoder: RenderPassEncoder, label: StringView) --- RenderPassEncoderSetPipeline :: proc(renderPassEncoder: RenderPassEncoder, pipeline: RenderPipeline) --- RenderPassEncoderSetScissorRect :: proc(renderPassEncoder: RenderPassEncoder, x: u32, y: u32, width: u32, height: u32) --- RenderPassEncoderSetStencilReference :: proc(renderPassEncoder: RenderPassEncoder, reference: u32) --- RenderPassEncoderSetVertexBuffer :: proc(renderPassEncoder: RenderPassEncoder, slot: u32, /* NULLABLE */ buffer: Buffer, offset: u64, size: u64) --- RenderPassEncoderSetViewport :: proc(renderPassEncoder: RenderPassEncoder, x: f32, y: f32, width: f32, height: f32, minDepth: f32, maxDepth: f32) --- - RenderPassEncoderReference :: proc(renderPassEncoder: RenderPassEncoder) --- + RenderPassEncoderAddRef :: proc(renderPassEncoder: RenderPassEncoder) --- RenderPassEncoderRelease :: proc(renderPassEncoder: RenderPassEncoder) --- // Methods of RenderPipeline RenderPipelineGetBindGroupLayout :: proc(renderPipeline: RenderPipeline, groupIndex: u32) -> BindGroupLayout --- - RenderPipelineSetLabel :: proc(renderPipeline: RenderPipeline, label: cstring) --- - RenderPipelineReference :: proc(renderPipeline: RenderPipeline) --- + RenderPipelineSetLabel :: proc(renderPipeline: RenderPipeline, label: StringView) --- + RenderPipelineAddRef :: proc(renderPipeline: RenderPipeline) --- RenderPipelineRelease :: proc(renderPipeline: RenderPipeline) --- // Methods of Sampler - SamplerSetLabel :: proc(sampler: Sampler, label: cstring) --- - SamplerReference :: proc(sampler: Sampler) --- + SamplerSetLabel :: proc(sampler: Sampler, label: StringView) --- + SamplerAddRef :: proc(sampler: Sampler) --- SamplerRelease :: proc(sampler: Sampler) --- // Methods of ShaderModule - ShaderModuleGetCompilationInfo :: proc(shaderModule: ShaderModule, callback: ShaderModuleGetCompilationInfoCallback, /* NULLABLE */ userdata: rawptr = nil) --- - ShaderModuleSetLabel :: proc(shaderModule: ShaderModule, label: cstring) --- - ShaderModuleReference :: proc(shaderModule: ShaderModule) --- + ShaderModuleGetCompilationInfo :: proc(shaderModule: ShaderModule, callbackInfo: CompilationInfoCallbackInfo) -> Future --- + ShaderModuleSetLabel :: proc(shaderModule: ShaderModule, label: StringView) --- + ShaderModuleAddRef :: proc(shaderModule: ShaderModule) --- ShaderModuleRelease :: proc(shaderModule: ShaderModule) --- + // Methods of SupportedFeatures + SupportedFeaturesFreeMembers :: proc(supportedFeatures: SupportedFeatures) --- + + // Methods of SupportedWGSLLanguageFeatures + SupportedWGSLLanguageFeaturesFreeMembers :: proc(supportedWGSLLanguageFeatures: SupportedWGSLLanguageFeatures) --- + // Methods of Surface SurfaceConfigure :: proc(surface: Surface, config: /* const */ ^SurfaceConfiguration) --- @(link_name="wgpuSurfaceGetCapabilities") - RawSurfaceGetCapabilities :: proc(surface: Surface, adapter: Adapter, capabilities: ^SurfaceCapabilities) --- + RawSurfaceGetCapabilities :: proc(surface: Surface, adapter: Adapter, capabilities: ^SurfaceCapabilities) -> Status --- @(link_name="wgpuSurfaceGetCurrentTexture") RawSurfaceGetCurrentTexture :: proc(surface: Surface, surfaceTexture: ^SurfaceTexture) --- - SurfacePresent :: proc(surface: Surface) --- - SurfaceSetLabel :: proc(surface: Surface, label: cstring) --- + SurfacePresent :: proc(surface: Surface) -> Status --- + SurfaceSetLabel :: proc(surface: Surface, label: StringView) --- SurfaceUnconfigure :: proc(surface: Surface) --- - SurfaceReference :: proc(surface: Surface) --- + SurfaceAddRef :: proc(surface: Surface) --- SurfaceRelease :: proc(surface: Surface) --- // Methods of SurfaceCapabilities @@ -1537,13 +1677,13 @@ foreign libwgpu { TextureGetSampleCount :: proc(texture: Texture) -> u32 --- TextureGetUsage :: proc(texture: Texture) -> TextureUsageFlags --- TextureGetWidth :: proc(texture: Texture) -> u32 --- - TextureSetLabel :: proc(texture: Texture, label: cstring) --- - TextureReference :: proc(texture: Texture) --- + TextureSetLabel :: proc(texture: Texture, label: StringView) --- + TextureAddRef :: proc(texture: Texture) --- TextureRelease :: proc(texture: Texture) --- // Methods of TextureView - TextureViewSetLabel :: proc(textureView: TextureView, label: cstring) --- - TextureViewReference :: proc(textureView: TextureView) --- + TextureViewSetLabel :: proc(textureView: TextureView, label: StringView) --- + TextureViewAddRef :: proc(textureView: TextureView) --- TextureViewRelease :: proc(textureView: TextureView) --- } @@ -1551,28 +1691,45 @@ foreign libwgpu { CreateInstance :: proc "c" (/* NULLABLE */ descriptor: /* const */ ^InstanceDescriptor = nil) -> Instance { when ODIN_OS != .JS { - wgpu_native_version_check() + v := (transmute([4]u8)GetVersion()).wzyx + + if v.xyz != BINDINGS_VERSION.xyz { + buf: [1024]byte + n := copy(buf[:], "wgpu-native version mismatch: ") + n += copy(buf[n:], "bindings are for version ") + n += copy(buf[n:], BINDINGS_VERSION_STRING) + n += copy(buf[n:], ", but a different version is linked") + panic_contextless(string(buf[:n])) + } } return RawCreateInstance(descriptor) } -// Wrappers of Adapter - -AdapterEnumerateFeatures :: proc(adapter: Adapter, allocator := context.allocator) -> []FeatureName { - count := RawAdapterEnumerateFeatures(adapter, nil) - features := make([]FeatureName, count, allocator) - RawAdapterEnumerateFeatures(adapter, raw_data(features)) - return features -} - -AdapterGetLimits :: proc "c" (adapter: Adapter) -> (limits: SupportedLimits, ok: bool) { - ok = bool(RawAdapterGetLimits(adapter, &limits)) +GetInstanceCapabilities :: proc "c" () -> (capabilities: InstanceCapabilities, status: Status) { + status = RawGetInstanceCapabilities(&capabilities) return } -AdapterGetInfo :: proc "c" (adapter: Adapter) -> (info: AdapterInfo) { - RawAdapterGetInfo(adapter, &info) +InstanceGetWGSLLanguageFeatures :: proc "c" (instance: Instance) -> (features: SupportedWGSLLanguageFeatures, status: Status) { + status = RawInstanceGetWGSLLanguageFeatures(instance, &features) + return +} + +// Wrappers of Adapter + +AdapterGetLimits :: proc "c" (adapter: Adapter) -> (limits: Limits, status: Status) { + status = RawAdapterGetLimits(adapter, &limits) + return +} + +AdapterGetInfo :: proc "c" (adapter: Adapter) -> (info: AdapterInfo, status: Status) { + status = RawAdapterGetInfo(adapter, &info) + return +} + +AdapterGetFeatures :: proc "c" (adapter: Adapter) -> (features: SupportedFeatures) { + RawAdapterGetFeatures(adapter, &features) return } @@ -1614,20 +1771,23 @@ ComputePassEncoderSetBindGroup :: proc "c" (computePassEncoder: ComputePassEncod // Wrappers of Device -DeviceEnumerateFeatures :: proc(device: Device, allocator := context.allocator) -> []FeatureName { - count := RawDeviceEnumerateFeatures(device, nil) - features := make([]FeatureName, count, allocator) - RawDeviceEnumerateFeatures(device, raw_data(features)) - return features +DeviceGetLimits :: proc "c" (device: Device) -> (limits: Limits, status: Status) { + status = RawDeviceGetLimits(device, &limits) + return } -DeviceGetLimits :: proc "c" (device: Device) -> (limits: SupportedLimits, ok: bool) { - ok = bool(RawDeviceGetLimits(device, &limits)) +DeviceGetAdapterInfo :: proc "c" (device: Device) -> (info: AdapterInfo, status: Status) { + status = RawDeviceGetAdapterInfo(device, &info) + return +} + +DeviceGetFeatures :: proc "c" (device: Device) -> (features: SupportedFeatures) { + RawDeviceGetFeatures(device, &features) return } BufferWithDataDescriptor :: struct { - /* NULLABLE */ label: cstring, + /* NULLABLE */ label: StringView, usage: BufferUsageFlags, } @@ -1693,8 +1853,8 @@ RenderPassEncoderSetBindGroup :: proc "c" (renderPassEncoder: RenderPassEncoder, // Wrappers of Surface -SurfaceGetCapabilities :: proc "c" (surface: Surface, adapter: Adapter) -> (capabilities: SurfaceCapabilities) { - RawSurfaceGetCapabilities(surface, adapter, &capabilities) +SurfaceGetCapabilities :: proc "c" (surface: Surface, adapter: Adapter) -> (capabilities: SurfaceCapabilities, status: Status) { + status = RawSurfaceGetCapabilities(surface, adapter, &capabilities) return } @@ -1702,73 +1862,3 @@ SurfaceGetCurrentTexture :: proc "c" (surface: Surface) -> (surface_texture: Sur RawSurfaceGetCurrentTexture(surface, &surface_texture) return } - -// WGPU Native bindings - -BINDINGS_VERSION :: [4]u8{22, 1, 0, 1} -BINDINGS_VERSION_STRING :: "22.1.0.1" - -when ODIN_OS != .JS { - @(private="file") - wgpu_native_version_check :: proc "c" () { - v := (transmute([4]u8)GetVersion()).wzyx - - if v != BINDINGS_VERSION { - buf: [1024]byte - n := copy(buf[:], "wgpu-native version mismatch: ") - n += copy(buf[n:], "bindings are for version ") - n += copy(buf[n:], BINDINGS_VERSION_STRING) - n += copy(buf[n:], ", but a different version is linked") - panic_contextless(string(buf[:n])) - } - } - - @(link_prefix="wgpu") - foreign libwgpu { - @(link_name="wgpuGenerateReport") - RawGenerateReport :: proc(instance: Instance, report: ^GlobalReport) --- - @(link_name="wgpuInstanceEnumerateAdapters") - RawInstanceEnumerateAdapters :: proc(instance: Instance, /* NULLABLE */ options: /* const */ ^InstanceEnumerateAdapterOptions, adapters: [^]Adapter) -> uint --- - - @(link_name="wgpuQueueSubmitForIndex") - RawQueueSubmitForIndex :: proc(queue: Queue, commandCount: uint, commands: [^]CommandBuffer) -> SubmissionIndex --- - - // Returns true if the queue is empty, or false if there are more queue submissions still in flight. - DevicePoll :: proc(device: Device, wait: b32, /* NULLABLE */ wrappedSubmissionIndex: /* const */ ^WrappedSubmissionIndex = nil) -> b32 --- - - SetLogCallback :: proc(callback: LogCallback, userdata: rawptr) --- - - SetLogLevel :: proc(level: LogLevel) --- - - GetVersion :: proc() -> u32 --- - - RenderPassEncoderSetPushConstants :: proc(encoder: RenderPassEncoder, stages: ShaderStageFlags, offset: u32, sizeBytes: u32, data: rawptr) --- - - RenderPassEncoderMultiDrawIndirect :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count: u32) --- - RenderPassEncoderMultiDrawIndexedIndirect :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count: u32) --- - - RenderPassEncoderMultiDrawIndirectCount :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count_buffer: Buffer, count_buffer_offset: u64, max_count: u32) --- - RenderPassEncoderMultiDrawIndexedIndirectCount :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count_buffer: Buffer, count_buffer_offset: u64, max_count: u32) --- - - ComputePassEncoderBeginPipelineStatisticsQuery :: proc(computePassEncoder: ComputePassEncoder, querySet: QuerySet, queryIndex: u32) --- - ComputePassEncoderEndPipelineStatisticsQuery :: proc(computePassEncoder: ComputePassEncoder) --- - RenderPassEncoderBeginPipelineStatisticsQuery :: proc(renderPassEncoder: RenderPassEncoder, querySet: QuerySet, queryIndex: u32) --- - RenderPassEncoderEndPipelineStatisticsQuery :: proc(renderPassEncoder: RenderPassEncoder) --- - } - - GenerateReport :: proc "c" (instance: Instance) -> (report: GlobalReport) { - RawGenerateReport(instance, &report) - return - } - - InstanceEnumerateAdapters :: proc(instance: Instance, options: ^InstanceEnumerateAdapterOptions = nil, allocator := context.allocator) -> (adapters: []Adapter) { - count := RawInstanceEnumerateAdapters(instance, options, nil) - adapters = make([]Adapter, count, allocator) - RawInstanceEnumerateAdapters(instance, options, raw_data(adapters)) - return - } - - QueueSubmitForIndex :: proc "c" (queue: Queue, commands: []CommandBuffer) -> SubmissionIndex { - return RawQueueSubmitForIndex(queue, len(commands), raw_data(commands)) - } -} diff --git a/vendor/wgpu/wgpu_native.odin b/vendor/wgpu/wgpu_native.odin new file mode 100644 index 000000000..def095e07 --- /dev/null +++ b/vendor/wgpu/wgpu_native.odin @@ -0,0 +1,57 @@ +#+build !js +package wgpu + +@(link_prefix="wgpu") +foreign libwgpu { + @(link_name="wgpuGenerateReport") + RawGenerateReport :: proc(instance: Instance, report: ^GlobalReport) --- + @(link_name="wgpuInstanceEnumerateAdapters") + RawInstanceEnumerateAdapters :: proc(instance: Instance, /* NULLABLE */ options: /* const */ ^InstanceEnumerateAdapterOptions, adapters: [^]Adapter) -> uint --- + + @(link_name="wgpuQueueSubmitForIndex") + RawQueueSubmitForIndex :: proc(queue: Queue, commandCount: uint, commands: [^]CommandBuffer) -> SubmissionIndex --- + + // Returns true if the queue is empty, or false if there are more queue submissions still in flight. + DevicePoll :: proc(device: Device, wait: b32, /* NULLABLE */ wrappedSubmissionIndex: /* const */ ^SubmissionIndex = nil) -> b32 --- + DeviceCreateShaderModuleSpirV :: proc(device: Device, descriptor: ^ShaderModuleDescriptorSpirV) -> ShaderModule --- + + SetLogCallback :: proc(callback: LogCallback, userdata: rawptr) --- + + SetLogLevel :: proc(level: LogLevel) --- + + GetVersion :: proc() -> u32 --- + + RenderPassEncoderSetPushConstants :: proc(encoder: RenderPassEncoder, stages: ShaderStageFlags, offset: u32, sizeBytes: u32, data: rawptr) --- + ComputePassEncoderSetPushConstants :: proc(encoder: ComputePassEncoder, offset: u32, sizeBytes: u32, data: rawptr) --- + RenderBundleEncoderSetPushConstants :: proc(encoder: RenderBundleEncoder, stages: ShaderStageFlags, offset: u32, sizeBytes: u32, data: rawptr) --- + + RenderPassEncoderMultiDrawIndirect :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count: u32) --- + RenderPassEncoderMultiDrawIndexedIndirect :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count: u32) --- + + RenderPassEncoderMultiDrawIndirectCount :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count_buffer: Buffer, count_buffer_offset: u64, max_count: u32) --- + RenderPassEncoderMultiDrawIndexedIndirectCount :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count_buffer: Buffer, count_buffer_offset: u64, max_count: u32) --- + + ComputePassEncoderBeginPipelineStatisticsQuery :: proc(computePassEncoder: ComputePassEncoder, querySet: QuerySet, queryIndex: u32) --- + ComputePassEncoderEndPipelineStatisticsQuery :: proc(computePassEncoder: ComputePassEncoder) --- + RenderPassEncoderBeginPipelineStatisticsQuery :: proc(renderPassEncoder: RenderPassEncoder, querySet: QuerySet, queryIndex: u32) --- + RenderPassEncoderEndPipelineStatisticsQuery :: proc(renderPassEncoder: RenderPassEncoder) --- + + ComputePassEncoderWriteTimestamp :: proc(computePassEncoder: ComputePassEncoder, querySet: QuerySet, queryIndex: u32) --- + RenderPassEncoderWriteTimestamp :: proc(renderPassEncoder: RenderPassEncoder, querySet: QuerySet, queryIndex: u32) --- +} + +GenerateReport :: proc "c" (instance: Instance) -> (report: GlobalReport) { + RawGenerateReport(instance, &report) + return +} + +InstanceEnumerateAdapters :: proc(instance: Instance, options: ^InstanceEnumerateAdapterOptions = nil, allocator := context.allocator) -> (adapters: []Adapter) { + count := RawInstanceEnumerateAdapters(instance, options, nil) + adapters = make([]Adapter, count, allocator) + RawInstanceEnumerateAdapters(instance, options, raw_data(adapters)) + return +} + +QueueSubmitForIndex :: proc "c" (queue: Queue, commands: []CommandBuffer) -> SubmissionIndex { + return RawQueueSubmitForIndex(queue, len(commands), raw_data(commands)) +} diff --git a/vendor/wgpu/wgpu_native_types.odin b/vendor/wgpu/wgpu_native_types.odin index 2133fdd50..025004c0c 100644 --- a/vendor/wgpu/wgpu_native_types.odin +++ b/vendor/wgpu/wgpu_native_types.odin @@ -2,6 +2,9 @@ package wgpu import "base:runtime" +BINDINGS_VERSION :: [4]u8{24, 0, 0, 2} +BINDINGS_VERSION_STRING :: "24.0.0.2" + LogLevel :: enum i32 { Off, Error, @@ -59,30 +62,21 @@ InstanceExtras :: struct { flags: InstanceFlags, dx12ShaderCompiler: Dx12Compiler, gles3MinorVersion: Gles3MinorVersion, - dxilPath: cstring, - dxcPath: cstring, + dxilPath: StringView, + dxcPath: StringView, } DeviceExtras :: struct { using chain: ChainedStruct, - tracePath: cstring, + tracePath: StringView, } NativeLimits :: struct { + using chain: ChainedStructOut, maxPushConstantSize: u32, maxNonSamplerBindings: u32, } -RequiredLimitsExtras :: struct { - using chain: ChainedStruct, - limits: NativeLimits, -} - -SupportedLimitsExtras :: struct { - using chain: ChainedStructOut, - limits: NativeLimits, -} - PushConstantRange :: struct { stages: ShaderStageFlags, start: u32, @@ -97,29 +91,29 @@ PipelineLayoutExtras :: struct { SubmissionIndex :: distinct u64 -WrappedSubmissionIndex :: struct { - queue: Queue, - submissionIndex: SubmissionIndex, -} - ShaderDefine :: struct { - name: cstring, - value: cstring, + name: StringView, + value: StringView, } ShaderModuleGLSLDescriptor :: struct { using chain: ChainedStruct, stage: ShaderStage, - code: cstring, + code: StringView, defineCount: uint, - defines: [^]ShaderDefine `fmt:"v,defineCount"`, + defines: /* const */ [^]ShaderDefine `fmt:"v,defineCount"`, +} + +ShaderModuleDescriptorSpirV :: struct { + label: StringView, + sourceSize: u32, + source: /* const */ [^]u32 `fmt:"v,sourceSize"`, } RegistryReport :: struct { numAllocated: uint, numKeptFromUser: uint, numReleasedFromUser: uint, - numErrors: uint, elementSize: uint, } @@ -135,6 +129,7 @@ HubReport :: struct { renderBundles: RegistryReport, renderPipelines: RegistryReport, computePipelines: RegistryReport, + pipelineCaches: RegistryReport, querySets: RegistryReport, buffers: RegistryReport, textures: RegistryReport, @@ -144,11 +139,7 @@ HubReport :: struct { GlobalReport :: struct { surfaces: RegistryReport, - backendType: BackendType, - vulkan: HubReport, - metal: HubReport, - dx12: HubReport, - gl: HubReport, + hub: HubReport, } InstanceEnumerateAdapterOptions :: struct { @@ -179,10 +170,10 @@ QuerySetDescriptorExtras :: struct { SurfaceConfigurationExtras :: struct { using chain: ChainedStruct, - desiredMaximumFrameLatency: i32, + desiredMaximumFrameLatency: u32, } -LogCallback :: #type proc "c" (level: LogLevel, message: cstring, userdata: rawptr) +LogCallback :: #type proc "c" (level: LogLevel, message: StringView, userdata: rawptr) // Wrappers @@ -210,3 +201,4 @@ ConvertLogLevel :: proc { ConvertOdinToWGPULogLevel, ConvertWGPUToOdinLogLevel, } +