diff --git a/base/runtime/core.odin b/base/runtime/core.odin index c62301c34..66099e787 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -273,14 +273,14 @@ Typeid_Kind :: enum u8 { } #assert(len(Typeid_Kind) < 32) -// Typeid_Bit_Field :: bit_field #align(align_of(uintptr)) { -// index: 8*size_of(uintptr) - 8, -// kind: 5, // Typeid_Kind -// named: 1, -// special: 1, // signed, cstring, etc -// reserved: 1, -// } -// #assert(size_of(Typeid_Bit_Field) == size_of(uintptr)); +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 diff --git a/core/fmt/doc.odin b/core/fmt/doc.odin index 597342e76..be666dcc4 100644 --- a/core/fmt/doc.odin +++ b/core/fmt/doc.odin @@ -1,5 +1,5 @@ /* -package fmt implemented formatted I/O with procedures similar to C's printf and Python's format. +package fmt implements formatted I/O with procedures similar to C's printf and Python's format. The format 'verbs' are derived from C's but simpler. Printing @@ -33,6 +33,8 @@ Floating-point, complex numbers, and quaternions: %E scientific notation, e.g. -1.23456E+78 %f decimal point but no exponent, e.g. 123.456 %F synonym for %f + %g synonym for %f with default maximum precision + %G synonym for %g %h hexadecimal (lower-case) representation with 0h prefix (0h01234abcd) %H hexadecimal (upper-case) representation with 0H prefix (0h01234ABCD) %m number of bytes in the best unit of measurement, e.g. 123.45mib @@ -61,9 +63,9 @@ For compound values, the elements are printed using these rules recursively; lai bit sets {key0 = elem0, key1 = elem1, ...} pointer to above: &{}, &[], &map[] -Width is specified by an optional decimal number immediately preceding the verb. +Width is specified by an optional decimal number immediately after the '%'. If not present, the width is whatever is necessary to represent the value. -Precision is specified after the (optional) width followed by a period followed by a decimal number. +Precision is specified after the (optional) width by a period followed by a decimal number. If no period is present, a default precision is used. A period with no following number specifies a precision of 0. @@ -75,7 +77,7 @@ Examples: %8.f width 8, precision 0 Width and precision are measured in units of Unicode code points (runes). -n.b. C's printf uses units of bytes +n.b. C's printf uses units of bytes. Other flags: @@ -92,7 +94,7 @@ Other flags: 0 pad with leading zeros rather than spaces -Flags are ignored by verbs that don't expect them +Flags are ignored by verbs that don't expect them. For each printf-like procedure, there is a print function that takes no @@ -105,19 +107,20 @@ Explicit argument indices: In printf-like procedures, the default behaviour is for each formatting verb to format successive arguments passed in the call. However, the notation [n] immediately before the verb indicates that the nth zero-index argument is to be formatted instead. -The same notation before an '*' for a width or precision selecting the argument index holding the value. -Python-like syntax with argument indices differs for the selecting the argument index: {N:v} +The same notation before an '*' for a width or precision specifier selects the argument index +holding the value. +Python-like syntax with argument indices differs for selecting the argument index: {n:v} Examples: - fmt.printf("%[1]d %[0]d\n", 13, 37); // C-like syntax - fmt.printf("{1:d} {0:d}\n", 13, 37); // Python-like syntax + fmt.printfln("%[1]d %[0]d", 13, 37) // C-like syntax + fmt.printfln("{1:d} {0:d}", 13, 37) // Python-like syntax prints "37 13", whilst: - fmt.printf("%[2]*.[1]*[0]f\n", 17.0, 2, 6); // C-like syntax - fmt.printf("%{0:[2]*.[1]*f}\n", 17.0, 2, 6); // Python-like syntax -equivalent to: - fmt.printf("%6.2f\n", 17.0, 2, 6); // C-like syntax - fmt.printf("{:6.2f}\n", 17.0, 2, 6); // Python-like syntax -prints "17.00" + fmt.printfln("%*[2].*[1][0]f", 17.0, 2, 6) // C-like syntax + fmt.printfln("{0:*[2].*[1]f}", 17.0, 2, 6) // Python-like syntax +is equivalent to: + fmt.printfln("%6.2f", 17.0) // C-like syntax + fmt.printfln("{:6.2f}", 17.0) // Python-like syntax +and prints "17.00". Format errors: diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 867257491..772d3dd9c 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -25,8 +25,6 @@ Info :: struct { prec: int, indent: int, - reordered: bool, - good_arg_index: bool, ignore_user_formatters: bool, in_bad: bool, @@ -527,13 +525,107 @@ wprintln :: proc(w: io.Writer, args: ..any, sep := " ", flush := true) -> int { // Returns: The number of bytes written // wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true, newline := false) -> int { + MAX_CHECKED_ARGS :: 64 + assert(len(args) <= MAX_CHECKED_ARGS, "number of args > 64 is unsupported") + + parse_options :: proc(fi: ^Info, fmt: string, index, end: int, unused_args: ^bit_set[0 ..< MAX_CHECKED_ARGS], args: ..any) -> int { + i := index + + // Prefix + prefix_loop: for ; i < end; i += 1 { + switch fmt[i] { + case '+': + fi.plus = true + case '-': + fi.minus = true + fi.zero = false + case ' ': + fi.space = true + case '#': + fi.hash = true + case '0': + fi.zero = !fi.minus + case: + break prefix_loop + } + } + + // Width + if i < end && fmt[i] == '*' { + i += 1 + width_index, _, index_ok := _arg_number(fmt, &i, len(args)) + + if index_ok { + unused_args^ -= {width_index} + + fi.width, _, fi.width_set = int_from_arg(args, width_index) + if !fi.width_set { + io.write_string(fi.writer, "%!(BAD WIDTH)", &fi.n) + } + + if fi.width < 0 { + fi.width = -fi.width + fi.minus = true + fi.zero = false + } + } + } else { + fi.width, i, fi.width_set = _parse_int(fmt, i) + } + + // Precision + if i < end && fmt[i] == '.' { + i += 1 + if i < end && fmt[i] == '*' { + i += 1 + precision_index, _, index_ok := _arg_number(fmt, &i, len(args)) + + if index_ok { + unused_args^ -= {precision_index} + fi.prec, _, fi.prec_set = int_from_arg(args, precision_index) + if fi.prec < 0 { + fi.prec = 0 + fi.prec_set = false + } + if !fi.prec_set { + io.write_string(fi.writer, "%!(BAD PRECISION)", &fi.n) + } + } + } else { + prev_i := i + fi.prec, i, fi.prec_set = _parse_int(fmt, i) + if i == prev_i { + fi.prec = 0 + fi.prec_set = true + } + } + } + + return i + } + + error_check_arg :: proc(fi: ^Info, arg_parsed: bool, unused_args: bit_set[0 ..< MAX_CHECKED_ARGS]) -> (int, bool) { + if !arg_parsed { + for index in unused_args { + return index, true + } + io.write_string(fi.writer, "%!(MISSING ARGUMENT)", &fi.n) + } else { + io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER)", &fi.n) + } + + return 0, false + } + fi: Info - arg_index: int = 0 end := len(fmt) - was_prev_index := false + unused_args: bit_set[0 ..< MAX_CHECKED_ARGS] + for i in 0 ..< len(args) { + unused_args += {i} + } loop: for i := 0; i < end; /**/ { - fi = Info{writer = w, good_arg_index = true, reordered = fi.reordered, n = fi.n} + fi = Info{writer = w, n = fi.n} prev_i := i for i < end && !(fmt[i] == '%' || fmt[i] == '{' || fmt[i] == '}') { @@ -567,191 +659,65 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true, newline : } if char == '%' { - prefix_loop: for ; i < end; i += 1 { - switch fmt[i] { - case '+': - fi.plus = true - case '-': - fi.minus = true - fi.zero = false - case ' ': - fi.space = true - case '#': - fi.hash = true - case '0': - fi.zero = !fi.minus - case: - break prefix_loop - } - } - - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) - - // Width - if i < end && fmt[i] == '*' { + if i < end && fmt[i] == '%' { + io.write_byte(fi.writer, '%', &fi.n) i += 1 - fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index) - if !fi.width_set { - io.write_string(w, "%!(BAD WIDTH)", &fi.n) - } - - if fi.width < 0 { - fi.width = -fi.width - fi.minus = true - fi.zero = false - } - was_prev_index = false - } else { - fi.width, i, fi.width_set = _parse_int(fmt, i) - if was_prev_index && fi.width_set { // %[6]2d - fi.good_arg_index = false - } + continue loop } - // Precision - if i < end && fmt[i] == '.' { - i += 1 - if was_prev_index { // %[6].2d - fi.good_arg_index = false - } - if i < end && fmt[i] == '*' { - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) - i += 1 - fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index) - if fi.prec < 0 { - fi.prec = 0 - fi.prec_set = false - } - if !fi.prec_set { - io.write_string(fi.writer, "%!(BAD PRECISION)", &fi.n) - } - was_prev_index = false - } else { - fi.prec, i, fi.prec_set = _parse_int(fmt, i) - } - } + i = parse_options(&fi, fmt, i, end, &unused_args, ..args) - if !was_prev_index { - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) + arg_index, arg_parsed, index_ok := _arg_number(fmt, &i, len(args)) + + if !index_ok { + arg_index, index_ok = error_check_arg(&fi, arg_parsed, unused_args) } if i >= end { io.write_string(fi.writer, "%!(NO VERB)", &fi.n) break loop + } else if fmt[i] == ' ' { + io.write_string(fi.writer, "%!(NO VERB)", &fi.n) + continue loop } verb, w := utf8.decode_rune_in_string(fmt[i:]) i += w - switch { - case verb == '%': - io.write_byte(fi.writer, '%', &fi.n) - case !fi.good_arg_index: - io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER)", &fi.n) - case arg_index >= len(args): - io.write_string(fi.writer, "%!(MISSING ARGUMENT)", &fi.n) - case: + if index_ok { + unused_args -= {arg_index} fmt_arg(&fi, args[arg_index], verb) - arg_index += 1 } } else if char == '{' { + arg_index: int + arg_parsed, index_ok: bool + if i < end && fmt[i] != '}' && fmt[i] != ':' { - new_arg_index, new_i, ok := _parse_int(fmt, i) - if ok { - fi.reordered = true - was_prev_index = true - arg_index = new_arg_index - i = new_i - } else { - io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER ", &fi.n) - // Skip over the bad argument - start_index := i - for i < end && fmt[i] != '}' && fmt[i] != ':' { - i += 1 - } - fmt_arg(&fi, fmt[start_index:i], 'v') - io.write_string(fi.writer, ")", &fi.n) + arg_index, i, arg_parsed = _parse_int(fmt, i) + if arg_parsed { + index_ok = 0 <= arg_index && arg_index < len(args) } } + if !index_ok { + arg_index, index_ok = error_check_arg(&fi, arg_parsed, unused_args) + } + verb: rune = 'v' if i < end && fmt[i] == ':' { i += 1 - prefix_loop_percent: for ; i < end; i += 1 { - switch fmt[i] { - case '+': - fi.plus = true - case '-': - fi.minus = true - fi.zero = false - case ' ': - fi.space = true - case '#': - fi.hash = true - case '0': - fi.zero = !fi.minus - case: - break prefix_loop_percent - } - } - - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) - - // Width - if i < end && fmt[i] == '*' { - i += 1 - fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index) - if !fi.width_set { - io.write_string(fi.writer, "%!(BAD WIDTH)", &fi.n) - } - - if fi.width < 0 { - fi.width = -fi.width - fi.minus = true - fi.zero = false - } - was_prev_index = false - } else { - fi.width, i, fi.width_set = _parse_int(fmt, i) - if was_prev_index && fi.width_set { // %[6]2d - fi.good_arg_index = false - } - } - - // Precision - if i < end && fmt[i] == '.' { - i += 1 - if was_prev_index { // %[6].2d - fi.good_arg_index = false - } - if i < end && fmt[i] == '*' { - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) - i += 1 - fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index) - if fi.prec < 0 { - fi.prec = 0 - fi.prec_set = false - } - if !fi.prec_set { - io.write_string(fi.writer, "%!(BAD PRECISION)", &fi.n) - } - was_prev_index = false - } else { - fi.prec, i, fi.prec_set = _parse_int(fmt, i) - } - } - - if !was_prev_index { - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) - } - + i = parse_options(&fi, fmt, i, end, &unused_args, ..args) if i >= end { io.write_string(fi.writer, "%!(NO VERB)", &fi.n) break loop + } else if fmt[i] == '}' { + i += 1 + io.write_string(fi.writer, "%!(NO VERB)", &fi.n) + continue } w: int = 1 @@ -770,31 +736,35 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true, newline : switch { case brace != '}': io.write_string(fi.writer, "%!(MISSING CLOSE BRACE)", &fi.n) - case !fi.good_arg_index: - io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER)", &fi.n) - case arg_index >= len(args): - io.write_string(fi.writer, "%!(MISSING ARGUMENT)", &fi.n) - case: + case index_ok: fmt_arg(&fi, args[arg_index], verb) - arg_index += 1 + unused_args -= {arg_index} } } } - if !fi.reordered && arg_index < len(args) { - io.write_string(fi.writer, "%!(EXTRA ", &fi.n) - for arg, index in args[arg_index:] { - if index > 0 { - io.write_string(fi.writer, ", ", &fi.n) + if unused_args != {} { + // Use default options when formatting extra arguments. + extra_fi := Info { writer = fi.writer, n = fi.n } + + io.write_string(extra_fi.writer, "%!(EXTRA ", &extra_fi.n) + first_printed := false + for index in unused_args { + if first_printed { + io.write_string(extra_fi.writer, ", ", &extra_fi.n) } + arg := args[index] if arg == nil { - io.write_string(fi.writer, "", &fi.n) + io.write_string(extra_fi.writer, "", &extra_fi.n) } else { - fmt_arg(&fi, args[index], 'v') + fmt_arg(&extra_fi, arg, 'v') } + first_printed = true } - io.write_string(fi.writer, ")", &fi.n) + io.write_byte(extra_fi.writer, ')', &extra_fi.n) + + fi.n = extra_fi.n } if newline { @@ -877,18 +847,16 @@ _parse_int :: proc(s: string, offset: int) -> (result: int, new_offset: int, ok: // Parses an argument number from a format string and determines if it's valid // // Inputs: -// - fi: A pointer to an Info structure -// - arg_index: The current argument index // - format: The format string to parse -// - offset: The current position in the format string +// - offset: A pointer to the current position in the format string // - arg_count: The total number of arguments // // Returns: // - index: The parsed argument index -// - new_offset: The new position in the format string -// - ok: A boolean indicating if the parsed argument number is valid +// - parsed: A boolean indicating if an argument number was parsed +// - ok: A boolean indicating if the parsed argument number is within arg_count // -_arg_number :: proc(fi: ^Info, arg_index: int, format: string, offset, arg_count: int) -> (index, new_offset: int, ok: bool) { +_arg_number :: proc(format: string, offset: ^int, arg_count: int) -> (index: int, parsed, ok: bool) { parse_arg_number :: proc(format: string) -> (int, int, bool) { if len(format) < 3 { return 0, 1, false @@ -896,30 +864,28 @@ _arg_number :: proc(fi: ^Info, arg_index: int, format: string, offset, arg_count for i in 1.. ^ast.Proc_Type { } expect_token(p, .Open_Paren) + p.expr_level += 1 params, _ := parse_field_list(p, .Close_Paren, ast.Field_Flags_Signature_Params) + p.expr_level -= 1 expect_closing_parentheses_of_field_list(p) results, diverging := parse_results(p) diff --git a/core/strconv/generic_float.odin b/core/strconv/generic_float.odin index 4ad42a647..6dc11c0be 100644 --- a/core/strconv/generic_float.odin +++ b/core/strconv/generic_float.odin @@ -104,8 +104,7 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, precision, bit_size: int) } else { switch fmt { case 'e', 'E': - prec += 1 - decimal.round(d, prec) + decimal.round(d, prec + 1) case 'f', 'F': decimal.round(d, d.decimal_point+prec) case 'g', 'G': diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index f998f33da..eba275522 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -429,6 +429,8 @@ foreign kernel32 { DisconnectNamedPipe :: proc(hNamedPipe: HANDLE) -> BOOL --- WaitNamedPipeW :: proc(lpNamedPipeName: LPCWSTR, nTimeOut: DWORD) -> BOOL --- + AllocConsole :: proc() -> BOOL --- + AttachConsole :: proc(dwProcessId: DWORD) -> BOOL --- SetConsoleCtrlHandler :: proc(HandlerRoutine: PHANDLER_ROUTINE, Add: BOOL) -> BOOL --- GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL --- FreeConsole :: proc() -> BOOL --- diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index cccbab4f6..c018077f9 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -161,8 +161,7 @@ gb_internal bool check_is_terminating_list(Slice const &stmts, String con } gb_internal bool check_has_break_list(Slice const &stmts, String const &label, bool implicit) { - for_array(i, stmts) { - Ast *stmt = stmts[i]; + for (Ast *stmt : stmts) { if (check_has_break(stmt, label, implicit)) { return true; } @@ -170,6 +169,14 @@ gb_internal bool check_has_break_list(Slice const &stmts, String const &l return false; } +gb_internal bool check_has_break_expr_list(Slice const &exprs, String const &label) { + for (Ast *expr : exprs) { + if (expr && expr->viral_state_flags & ViralStateFlag_ContainsOrBreak) { + return true; + } + } + return false; +} gb_internal bool check_has_break(Ast *stmt, String const &label, bool implicit) { switch (stmt->kind) { @@ -227,6 +234,20 @@ gb_internal bool check_has_break(Ast *stmt, String const &label, bool implicit) return true; } break; + + case Ast_ValueDecl: + if (stmt->ValueDecl.is_mutable && check_has_break_expr_list(stmt->ValueDecl.values, label)) { + return true; + } + break; + case Ast_AssignStmt: + if (check_has_break_expr_list(stmt->AssignStmt.lhs, label)) { + return true; + } + if (check_has_break_expr_list(stmt->AssignStmt.rhs, label)) { + return true; + } + break; } return false; @@ -250,6 +271,15 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { return check_is_terminating(unparen_expr(es->expr), label); case_end; + case_ast_node(vd, ValueDecl, node); + return check_has_break_expr_list(vd->values, label); + case_end; + + case_ast_node(as, AssignStmt, node); + return check_has_break_expr_list(as->lhs, label) || + check_has_break_expr_list(as->rhs, label); + case_end; + case_ast_node(bs, BranchStmt, node); return bs->token.kind == Token_fallthrough; case_end; diff --git a/src/parser.cpp b/src/parser.cpp index 6e859fe32..ee3c56daf 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3883,10 +3883,12 @@ gb_internal Ast *parse_proc_type(AstFile *f, Token proc_token) { expect_token(f, Token_OpenParen); + f->expr_level += 1; params = parse_field_list(f, nullptr, FieldFlag_Signature, Token_CloseParen, true, true); if (file_allow_newline(f)) { skip_possible_newline(f); } + f->expr_level -= 1; expect_token_after(f, Token_CloseParen, "parameter list"); results = parse_results(f, &diverging); diff --git a/tests/core/fmt/test_core_fmt.odin b/tests/core/fmt/test_core_fmt.odin index 4459af609..82d009ac6 100644 --- a/tests/core/fmt/test_core_fmt.odin +++ b/tests/core/fmt/test_core_fmt.odin @@ -29,6 +29,8 @@ when ODIN_TEST { main :: proc() { t := testing.T{} test_fmt_memory(&t) + test_fmt_doc_examples(&t) + test_fmt_options(&t) fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count) if TEST_fail > 0 { @@ -36,12 +38,13 @@ main :: proc() { } } -test_fmt_memory :: proc(t: ^testing.T) { - check :: proc(t: ^testing.T, exp: string, format: string, args: ..any, loc := #caller_location) { - got := fmt.tprintf(format, ..args) - expect(t, got == exp, fmt.tprintf("(%q, %v): %q != %q", format, args, got, exp), loc) - } +check :: proc(t: ^testing.T, exp: string, format: string, args: ..any, loc := #caller_location) { + got := fmt.tprintf(format, ..args) + expect(t, got == exp, fmt.tprintf("(%q, %v): %q != %q", format, args, got, exp), loc) +} +@(test) +test_fmt_memory :: proc(t: ^testing.T) { check(t, "5b", "%m", 5) check(t, "5B", "%M", 5) check(t, "-5B", "%M", -5) @@ -52,8 +55,129 @@ test_fmt_memory :: proc(t: ^testing.T) { check(t, "3.50 gib", "%#m", u32(mem.Gigabyte * 3.5)) check(t, "01tib", "%5.0m", mem.Terabyte) check(t, "-1tib", "%5.0m", -mem.Terabyte) - check(t, "2.50 pib", "%#5.m", uint(mem.Petabyte * 2.5)) + check(t, "2 pib", "%#5.m", uint(mem.Petabyte * 2.5)) check(t, "1.00 EiB", "%#M", mem.Exabyte) check(t, "255 B", "%#M", u8(255)) check(t, "0b", "%m", u8(0)) } + +@(test) +test_fmt_doc_examples :: proc(t: ^testing.T) { + // C-like syntax + check(t, "37 13", "%[1]d %[0]d", 13, 37) + check(t, "017.00", "%*[2].*[1][0]f", 17.0, 2, 6) + check(t, "017.00", "%6.2f", 17.0) + + // Python-like syntax + check(t, "37 13", "{1:d} {0:d}", 13, 37) + check(t, "017.00", "{0:*[2].*[1]f}", 17.0, 2, 6) + check(t, "017.00", "{:6.2f}", 17.0) +} + +@(test) +test_fmt_options :: proc(t: ^testing.T) { + // Escaping + check(t, "% { } 0 { } } {", "%% {{ }} {} {{ }} }} {{", 0 ) + + // Prefixes + check(t, "+3.000", "%+f", 3.0 ) + check(t, "0003", "%04i", 3 ) + check(t, "3 ", "% -4i", 3 ) + check(t, "+3", "%+i", 3 ) + check(t, "0b11", "%#b", 3 ) + check(t, "0xA", "%#X", 10 ) + + // Specific index formatting + check(t, "1 2 3", "%i %i %i", 1, 2, 3) + check(t, "1 2 3", "%[0]i %[1]i %[2]i", 1, 2, 3) + check(t, "3 2 1", "%[2]i %[1]i %[0]i", 1, 2, 3) + check(t, "3 1 2", "%[2]i %i %i", 1, 2, 3) + check(t, "1 2 3", "%i %[1]i %i", 1, 2, 3) + check(t, "1 3 2", "%i %[2]i %i", 1, 2, 3) + check(t, "1 1 1", "%[0]i %[0]i %[0]i", 1) + + // Width + check(t, "3.140", "%f", 3.14) + check(t, "3.140", "%4f", 3.14) + check(t, "3.140", "%5f", 3.14) + check(t, "03.140", "%6f", 3.14) + + // Precision + check(t, "3", "%.f", 3.14) + check(t, "3", "%.0f", 3.14) + check(t, "3.1", "%.1f", 3.14) + check(t, "3.140", "%.3f", 3.14) + check(t, "3.14000", "%.5f", 3.14) + + check(t, "3.1415", "%g", 3.1415) + + // Scientific notation + check(t, "3.000000e+00", "%e", 3.0) + + check(t, "3e+02", "%.e", 300.0) + check(t, "3e+02", "%.0e", 300.0) + check(t, "3.0e+02", "%.1e", 300.0) + check(t, "3.00e+02", "%.2e", 300.0) + check(t, "3.000e+02", "%.3e", 300.0) + + check(t, "3e+01", "%.e", 30.56) + check(t, "3e+01", "%.0e", 30.56) + check(t, "3.1e+01", "%.1e", 30.56) + check(t, "3.06e+01", "%.2e", 30.56) + check(t, "3.056e+01", "%.3e", 30.56) + + // Width and precision + check(t, "3.140", "%5.3f", 3.14) + check(t, "3.140", "%*[1].3f", 3.14, 5) + check(t, "3.140", "%*[1].*[2]f", 3.14, 5, 3) + check(t, "3.140", "%*[1].*[2][0]f", 3.14, 5, 3) + check(t, "3.140", "%*[2].*[1]f", 3.14, 3, 5) + check(t, "3.140", "%5.*[1]f", 3.14, 3) + + // Error checking + check(t, "%!(MISSING ARGUMENT)%!(NO VERB)", "%" ) + + check(t, "1%!(EXTRA 2, 3)", "%i", 1, 2, 3) + check(t, "2%!(EXTRA 1, 3)", "%[1]i", 1, 2, 3) + + check(t, "%!(BAD ARGUMENT NUMBER)%!(EXTRA 0)", "%[1]i", 0) + + check(t, "%!(MISSING ARGUMENT)", "%f") + check(t, "%!(BAD ARGUMENT NUMBER)%!(NO VERB)", "%[0]") + check(t, "%!(BAD ARGUMENT NUMBER)", "%[0]f") + + check(t, "%!(BAD ARGUMENT NUMBER)%!(NO VERB) %!(MISSING ARGUMENT)", "%[0] %i") + + check(t, "%!(NO VERB) 1%!(EXTRA 2)", "%[0] %i", 1, 2) + + check(t, "1 2 %!(MISSING ARGUMENT)", "%i %i %i", 1, 2) + check(t, "1 2 %!(BAD ARGUMENT NUMBER)", "%i %i %[2]i", 1, 2) + + check(t, "%!(BAD ARGUMENT NUMBER)%!(NO VERB)%!(EXTRA 0)", "%[1]", 0) + + check(t, "3.1%!(EXTRA 3.14)", "%.1f", 3.14, 3.14) + + // Python-like syntax + check(t, "1 2 3", "{} {} {}", 1, 2, 3) + check(t, "3 2 1", "{2} {1} {0}", 1, 2, 3) + check(t, "1 2 3", "{:i} {:i} {:i}", 1, 2, 3) + check(t, "1 2 3", "{0:i} {1:i} {2:i}", 1, 2, 3) + check(t, "3 2 1", "{2:i} {1:i} {0:i}", 1, 2, 3) + check(t, "3 1 2", "{2:i} {0:i} {1:i}", 1, 2, 3) + check(t, "1 2 3", "{:i} {1:i} {:i}", 1, 2, 3) + check(t, "1 3 2", "{:i} {2:i} {:i}", 1, 2, 3) + check(t, "1 1 1", "{0:i} {0:i} {0:i}", 1) + + check(t, "1 1%!(EXTRA 2)", "{} {0}", 1, 2) + check(t, "2 1", "{1} {}", 1, 2) + check(t, "%!(BAD ARGUMENT NUMBER) 1%!(EXTRA 2)", "{2} {}", 1, 2) + + check(t, "%!(BAD ARGUMENT NUMBER)", "{1}") + check(t, "%!(BAD ARGUMENT NUMBER)%!(NO VERB)", "{1:}") + check(t, "%!(BAD ARGUMENT NUMBER)%!(NO VERB)%!(EXTRA 0)", "{1:}", 0) + + check(t, "%!(MISSING ARGUMENT)", "{}" ) + check(t, "%!(MISSING ARGUMENT)%!(MISSING CLOSE BRACE)", "{" ) + check(t, "%!(MISSING CLOSE BRACE)%!(EXTRA 1)", "{", 1) + check(t, "%!(MISSING CLOSE BRACE)%!(EXTRA 1)", "{0", 1 ) +} diff --git a/vendor/directx/d3d12/d3d12.odin b/vendor/directx/d3d12/d3d12.odin index 7c4065d8b..e33845b73 100644 --- a/vendor/directx/d3d12/d3d12.odin +++ b/vendor/directx/d3d12/d3d12.odin @@ -82,6 +82,7 @@ FEATURE_LEVEL :: enum i32 { _11_1 = 45312, _12_0 = 49152, _12_1 = 49408, + _12_2 = 49664, } PRIMITIVE_TOPOLOGY :: enum i32 { @@ -833,6 +834,9 @@ FEATURE :: enum i32 { OPTIONS7 = 32, PROTECTED_RESOURCE_SESSION_TYPE_COUNT = 33, PROTECTED_RESOURCE_SESSION_TYPES = 34, + OPTIONS8 = 36, + OPTIONS9 = 37, + WAVE_MMA = 38, } SHADER_MIN_PRECISION_SUPPORT :: enum i32 { @@ -1017,6 +1021,7 @@ SHADER_MODEL :: enum i32 { _6_4 = 100, _6_5 = 101, _6_6 = 102, + _6_7 = 103, } FEATURE_DATA_SHADER_MODEL :: struct { @@ -1052,6 +1057,7 @@ SHADER_CACHE_SUPPORT_FLAG :: enum u32 { LIBRARY = 1, AUTOMATIC_INPROC_CACHE = 2, AUTOMATIC_DISK_CACHE = 3, + DRIVER_MANAGED_CACHE = 4, } FEATURE_DATA_SHADER_CACHE :: struct { @@ -1171,6 +1177,55 @@ FEATURE_DATA_QUERY_META_COMMAND :: struct { QueryOutputDataSizeInBytes: SIZE_T, } +FEATURE_DATA_OPTIONS8 :: struct { + UnalignedBlockTexturesSupported: BOOL, +} + +WAVE_MMA_TIER :: enum i32 { + NOT_SUPPORTED = 0, + _1_0 = 10, +} + +FEATURE_DATA_OPTIONS9 :: struct { + MeshShaderPipelineStatsSupported: BOOL, + MeshShaderSupportsFullRangeRenderTargetArrayIndex: BOOL, + AtomicInt64OnTypedResourceSupported: BOOL, + AtomicInt64OnGroupSharedSupported: BOOL, + DerivativesInMeshAndAmplificationShadersSupported: BOOL, + WaveMMATier: WAVE_MMA_TIER, +} + +WAVE_MMA_INPUT_DATATYPE :: enum i32 { + INVALID = 0, + BYTE = 1, + FLOAT16 = 2, + FLOAT = 3, +} + +WAVE_MMA_DIMENSION :: enum i32 { + INVALID = 0, + _16 = 1, + _64 = 2, +} + +WAVE_MMA_ACCUM_DATATYPE :: enum i32 { + NONE = 0, + INT32 = 1, + FLOAT16 = 2, + FLOAT = 4, +} + +FEATURE_DATA_WAVE_MMA :: struct { + InputDataType: WAVE_MMA_INPUT_DATATYPE, + M: WAVE_MMA_DIMENSION, + N: WAVE_MMA_DIMENSION, + Supported: BOOL, + K: u32, + AccumDataTypes: WAVE_MMA_ACCUM_DATATYPE, + RequiredWaveLaneCountMin: u32, + RequiredWaveLaneCountMax: u32, +} + RESOURCE_ALLOCATION_INFO :: struct { SizeInBytes: u64, Alignment: u64, @@ -1261,6 +1316,7 @@ RESOURCE_FLAG :: enum u32 { ALLOW_CROSS_ADAPTER = 4, ALLOW_SIMULTANEOUS_ACCESS = 5, VIDEO_DECODE_REFERENCE_ONLY = 6, + VIDEO_ENCODE_REFERENCE_ONLY = 7, } MIP_REGION :: struct { @@ -2140,6 +2196,7 @@ QUERY_HEAP_TYPE :: enum i32 { SO_STATISTICS = 3, VIDEO_DECODE_STATISTICS = 4, COPY_QUEUE_TIMESTAMP = 5, + PIPELINE_STATISTICS1 = 7, } QUERY_HEAP_DESC :: struct { @@ -2158,6 +2215,7 @@ QUERY_TYPE :: enum i32 { SO_STATISTICS_STREAM2 = 6, SO_STATISTICS_STREAM3 = 7, VIDEO_DECODE_STATISTICS = 8, + PIPELINE_STATISTICS1 = 10, } PREDICATION_OP :: enum i32 { @@ -2179,6 +2237,23 @@ QUERY_DATA_PIPELINE_STATISTICS :: struct { CSInvocations: u64, } +QUERY_DATA_PIPELINE_STATISTICS1 :: struct { + IAVertices: u64, + IAPrimitives: u64, + VSInvocations: u64, + GSInvocations: u64, + GSPrimitives: u64, + CInvocations: u64, + CPrimitives: u64, + PSInvocations: u64, + HSInvocations: u64, + DSInvocations: u64, + CSInvocations: u64, + ASInvocations: u64, + MSInvocations: u64, + MSPrimitives: u64, +} + QUERY_DATA_SO_STATISTICS :: struct { NumPrimitivesWritten: u64, PrimitivesStorageNeeded: u64, @@ -3244,6 +3319,8 @@ AUTO_BREADCRUMB_OP :: enum i32 { INITIALIZEEXTENSIONCOMMAND = 40, EXECUTEEXTENSIONCOMMAND = 41, DISPATCHMESH = 42, + ENCODEFRAME = 43, + RESOLVEENCODEROUTPUTMETADATA = 44, } AUTO_BREADCRUMB_NODE :: struct { @@ -3283,6 +3360,7 @@ DRED_VERSION :: enum i32 { _1_0 = 1, _1_1 = 2, _1_2 = 3, + _1_3 = 4, } DRED_FLAGS :: distinct bit_set[DRED_FLAG; u32] @@ -3329,6 +3407,8 @@ DRED_ALLOCATION_TYPE :: enum i32 { VIDEO_MOTION_ESTIMATOR = 45, VIDEO_MOTION_VECTOR_HEAP = 46, VIDEO_EXTENSION_COMMAND = 47, + VIDEO_ENCODER = 48, + VIDEO_ENCODER_HEAP = 49, INVALID = -1, } @@ -3367,6 +3447,24 @@ DRED_PAGE_FAULT_OUTPUT1 :: struct { pHeadRecentFreedAllocationNode: ^DRED_ALLOCATION_NODE1, } +DRED_PAGE_FAULT_FLAGS :: bit_set[DRED_PAGE_FAULT_FLAG;u32] +DRED_PAGE_FAULT_FLAG :: enum u32 { +} + +DRED_DEVICE_STATE :: enum i32 { + UNKNOWN = 0, + HUNG = 3, + FAULT = 6, + PAGEFAULT = 7, +} + +DRED_PAGE_FAULT_OUTPUT2 :: struct { + PageFaultVA: GPU_VIRTUAL_ADDRESS, + pHeadExistingAllocationNode: ^DRED_ALLOCATION_NODE1, + pHeadRecentFreedAllocationNode: ^DRED_ALLOCATION_NODE1, + PageFaultFlags: DRED_PAGE_FAULT_FLAGS, +} + DEVICE_REMOVED_EXTENDED_DATA1 :: struct { DeviceRemovedReason: HRESULT, AutoBreadcrumbsOutput: DRED_AUTO_BREADCRUMBS_OUTPUT, @@ -3379,12 +3477,20 @@ DEVICE_REMOVED_EXTENDED_DATA2 :: struct { PageFaultOutput: DRED_PAGE_FAULT_OUTPUT1, } +DEVICE_REMOVED_EXTENDED_DATA3 :: struct { + DeviceRemovedReason: HRESULT, + AutoBreadcrumbsOutput: DRED_AUTO_BREADCRUMBS_OUTPUT1, + PageFaultOutput: DRED_PAGE_FAULT_OUTPUT2, + DeviceState: DRED_DEVICE_STATE, +} + VERSIONED_DEVICE_REMOVED_EXTENDED_DATA :: struct { Version: DRED_VERSION, using _: struct #raw_union { Dred_1_0: DEVICE_REMOVED_EXTENDED_DATA, Dred_1_1: DEVICE_REMOVED_EXTENDED_DATA1, Dred_1_2: DEVICE_REMOVED_EXTENDED_DATA2, + Dred_1_3: DEVICE_REMOVED_EXTENDED_DATA3, }, } @@ -3440,6 +3546,18 @@ IDeviceRemovedExtendedData1_VTable :: struct { GetPageFaultAllocationOutput1: proc "system" (this: ^IDeviceRemovedExtendedData1, pOutput: ^DRED_PAGE_FAULT_OUTPUT1) -> HRESULT, } +IDeviceRemovedExtendedData2_UUID_STRING :: "67FC5816-E4CA-4915-BF18-42541272DA54" +IDeviceRemovedExtendedData2_UUID := &IID{0x67FC5816, 0xE4CA, 0x4915, {0xBF, 0x18, 0x42, 0x54, 0x12, 0x72, 0xDA, 0x54}} +IDeviceRemovedExtendedData2 :: struct #raw_union { + #subtype id3d12deviceremovedextendeddata1: IDeviceRemovedExtendedData1, + using id3d12deviceremovedextendeddata2_vtable: ^IDeviceRemovedExtendedData2_VTable, +} +IDeviceRemovedExtendedData2_VTable :: struct { + using id3d12deviceremovedextendeddata1_vtable: IDeviceRemovedExtendedData1_VTable, + GetPageFaultAllocationOutput2: proc "system" (this: ^IDeviceRemovedExtendedData2, pOutput: ^DRED_PAGE_FAULT_OUTPUT2) -> HRESULT, + GetDeviceState: proc "system" (this: ^IDeviceRemovedExtendedData2) -> DRED_DEVICE_STATE, +} + BACKGROUND_PROCESSING_MODE :: enum i32 { ALLOWED = 0, ALLOW_INTRUSIVE_MEASUREMENTS = 1, @@ -3686,6 +3804,71 @@ IGraphicsCommandList4_VTable :: struct { } +SHADER_CACHE_MODE :: enum i32 { + MEMORY = 0, + DISK = 1, +} + +SHADER_CACHE_FLAGS :: bit_set[SHADER_CACHE_FLAG;u32] +SHADER_CACHE_FLAG :: enum u32 { + DRIVER_VERSIONED = 0, + USE_WORKING_DIR = 1, +} + +SHADER_CACHE_SESSION_DESC :: struct { + Identifier: GUID, + Mode: SHADER_CACHE_MODE, + Flags: SHADER_CACHE_FLAGS, + MaximumInMemoryCacheSizeBytes: u32, + MaximumInMemoryCacheEntries: u32, + MaximumValueFileSizeBytes: u32, + Version: u64, +} + +IShaderCacheSession_UUID_STRING :: "28E2495D-0F64-4AE4-A6EC-129255DC49A8" +IShaderCacheSession_UUID := &IID{0x28E2495D, 0x0F64, 0x4AE4, {0xA6, 0xEC, 0x12, 0x92, 0x55, 0xDC, 0x49, 0xA8}} +IShaderCacheSession :: struct #raw_union { + #subtype idevicechild: IDeviceChild, + using id3d12shadercachesession_vtable: ^IShaderCacheSession_VTable, +} +IShaderCacheSession_VTable :: struct { + using idevicechild_vtable: IDeviceChild_VTable, + FindValue: proc "system" (this: ^IShaderCacheSession, pKey: rawptr, KeySize: u32, pValue: rawptr, pValueSize: ^u32) -> HRESULT, + StoreValue: proc "system" (this: ^IShaderCacheSession, pKey: rawptr, KeySize: u32, pValue: rawptr, ValueSize: u32) -> HRESULT, + SetDeleteOnDestroy: proc "system" (this: ^IShaderCacheSession), + GetDesc: proc "system" (this: ^IShaderCacheSession, pRetValue: ^SHADER_CACHE_SESSION_DESC) -> ^SHADER_CACHE_SESSION_DESC, +} + + +SHADER_CACHE_KIND_FLAGS :: bit_set[SHADER_CACHE_KIND_FLAG;u32] +SHADER_CACHE_KIND_FLAG :: enum u32 { + IMPLICIT_D3D_CACHE_FOR_DRIVER = 0, + IMPLICIT_D3D_CONVERSIONS = 1, + IMPLICIT_DRIVER_MANAGED = 2, + APPLICATION_MANAGED = 3, +} + +SHADER_CACHE_CONTROL_FLAGS :: bit_set[SHADER_CACHE_CONTROL_FLAG;u32] +SHADER_CACHE_CONTROL_FLAG :: enum u32 { + DISABLE = 0, + ENABLE = 1, + CLEAR = 2, +} + +IDevice9_UUID_STRING :: "4C80E962-F032-4F60-BC9E-EBC2CFA1D83C" +IDevice9_UUID := &IID{0x4C80E962, 0xF032, 0x4F60, {0xBC, 0x9E, 0xEB, 0xC2, 0xCF, 0xA1, 0xD8, 0x3C}} +IDevice9 :: struct #raw_union { + #subtype id3d12device8: IDevice8, + using id3d12device9_vtable: ^IDevice9_VTable, +} +IDevice9_VTable :: struct { + using id3d12device8_vtable: IDevice8_VTable, + CreateShaderCacheSession: proc "system" (this: ^IDevice9, pDesc: ^SHADER_CACHE_SESSION_DESC , riid: ^IID, ppvSession: ^rawptr) -> HRESULT, + ShaderCacheControl: proc "system" (this: ^IDevice9, Kinds: SHADER_CACHE_KIND_FLAGS, Control: SHADER_CACHE_CONTROL_FLAGS) -> HRESULT, + CreateCommandQueue1: proc "system" (this: ^IDevice9, pDesc: ^COMMAND_QUEUE_DESC, CreatorID: ^IID, riid: ^IID, ppCommandQueue: ^rawptr) -> HRESULT, +} + + ITools_UUID_STRING :: "7071e1f0-e84b-4b33-974f-12fa49de65c5" ITools_UUID := &IID{0x7071e1f0, 0xe84b, 0x4b33, {0x97, 0x4f, 0x12, 0xfa, 0x49, 0xde, 0x65, 0xc5}} ITools :: struct #raw_union { @@ -3766,6 +3949,30 @@ IDebug3_VTable :: struct { SetGPUBasedValidationFlags: proc "system" (this: ^IDebug3, Flags: GPU_BASED_VALIDATION_FLAGS), } + +IDebug4_UUID_STRING :: "014B816E-9EC5-4A2F-A845-FFBE441CE13A" +IDebug4_UUID := &IID{0x014B816E, 0x9EC5, 0x4A2F, {0xA8, 0x45, 0xFF, 0xBE, 0x44, 0x1C, 0xE1, 0x3A}} +IDebug4 :: struct #raw_union { + #subtype id3d12debug3: IDebug3, + using id3d12debug4_vtable: ^IDebug4_VTable, +} +IDebug4_VTable :: struct { + using id3d12debug3_vtable: IDebug3_VTable, + DisableDebugLayer: proc "system" (this: ^IDebug4), +} + + +IDebug5_UUID_STRING :: "548D6B12-09FA-40E0-9069-5DCD589A52C9" +IDebug5_UUID := &IID{0x548D6B12, 0x09FA, 0x40E0, {0x90, 0x69, 0x5D, 0xCD, 0x58, 0x9A, 0x52, 0xC9}} +IDebug5 :: struct #raw_union { + #subtype id3d12debug4: IDebug4, + using id3d12debug5_vtable: ^IDebug5_VTable, +} +IDebug5_VTable :: struct { + using id3d12debug4_vtable: IDebug4_VTable, + SetEnableAutoName: proc "system" (this: ^IDebug5, Enable: BOOL), +} + RLDO_FLAGS :: distinct bit_set[RLDO_FLAG; u32] RLDO_FLAG :: enum u32 { SUMMARY = 0, @@ -4890,6 +5097,19 @@ IInfoQueue1_VTable :: struct { UnregisterMessageCallback: proc "system" (this: ^IInfoQueue1, pCallbackCookie: u32) -> HRESULT, } + +ISDKConfiguration_UUID_STRING :: "E9EB5314-33AA-42B2-A718-D77F58B1F1C7" +ISDKConfiguration_UUID := &IID{0xE9EB5314, 0x33AA, 0x42B2, {0xA7, 0x18, 0xD7, 0x7F, 0x58, 0xB1, 0xF1, 0xC7}} +ISDKConfiguration :: struct #raw_union { + #subtype iunknown: IUnknown, + using id3d12sdkconfiguration_vtable: ^ISDKConfiguration_VTable, +} +ISDKConfiguration_VTable :: struct { + using iunknown_vtable: IUnknown_VTable, + SetSDKVersion: proc "system" (this: ^ISDKConfiguration, SDKVersion: u32, SDKPath: cstring) -> HRESULT, +} + + PFN_CREATE_DEVICE :: #type proc "c" (a0: ^IUnknown, a1: FEATURE_LEVEL, a2: ^IID, a3: ^rawptr) -> HRESULT PFN_GET_DEBUG_INTERFACE :: #type proc "c" (a0: ^IID, a1: ^rawptr) -> HRESULT diff --git a/vendor/directx/dxgi/dxgi.odin b/vendor/directx/dxgi/dxgi.odin index 5412747bc..235e07633 100644 --- a/vendor/directx/dxgi/dxgi.odin +++ b/vendor/directx/dxgi/dxgi.odin @@ -26,6 +26,8 @@ LONG :: win32.LONG RECT :: win32.RECT POINT :: win32.POINT SIZE :: win32.SIZE +WCHAR :: win32.WCHAR +DWORD :: win32.DWORD IUnknown :: struct { using _iunknown_vtable: ^IUnknown_VTable, @@ -38,10 +40,11 @@ IUnknown_VTable :: struct { @(default_calling_convention="system") foreign dxgi { - CreateDXGIFactory :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT --- - CreateDXGIFactory1 :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT --- - CreateDXGIFactory2 :: proc(Flags: CREATE_FACTORY, riid: ^IID, ppFactory: ^rawptr) -> HRESULT --- - DXGIGetDebugInterface1 :: proc(Flags: u32, riid: ^IID, pDebug: ^rawptr) -> HRESULT --- + CreateDXGIFactory :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT --- + CreateDXGIFactory1 :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT --- + CreateDXGIFactory2 :: proc(Flags: CREATE_FACTORY, riid: ^IID, ppFactory: ^rawptr) -> HRESULT --- + DXGIGetDebugInterface1 :: proc(Flags: u32, riid: ^IID, pDebug: ^rawptr) -> HRESULT --- + DeclareAdapterRemovalSupport :: proc() -> HRESULT --- } STANDARD_MULTISAMPLE_QUALITY_PATTERN :: 0xffffffff @@ -617,11 +620,11 @@ IDevice_VTable :: struct { SetGPUThreadPriority: proc "system" (this: ^IDevice, Priority: i32) -> HRESULT, GetGPUThreadPriority: proc "system" (this: ^IDevice, pPriority: ^i32) -> HRESULT, } -ADAPTER_FLAG :: enum u32 { // TODO: convert to bit_set - NONE = 0x0, - REMOTE = 0x1, - SOFTWARE = 0x2, - FORCE_DWORD = 0xffffffff, + +ADAPTER_FLAGS :: bit_set[ADAPTER_FLAG;u32] +ADAPTER_FLAG :: enum u32 { + REMOTE = 0, + SOFTWARE = 1, } ADAPTER_DESC1 :: struct { @@ -634,7 +637,7 @@ ADAPTER_DESC1 :: struct { DedicatedSystemMemory: SIZE_T, SharedSystemMemory: SIZE_T, AdapterLuid: LUID, - Flags: ADAPTER_FLAG, + Flags: ADAPTER_FLAGS, } DISPLAY_COLOR_SPACE :: struct { @@ -911,7 +914,7 @@ ADAPTER_DESC2 :: struct { DedicatedSystemMemory: SIZE_T, SharedSystemMemory: SIZE_T, AdapterLuid: LUID, - Flags: ADAPTER_FLAG, + Flags: ADAPTER_FLAGS, GraphicsPreemptionGranularity: GRAPHICS_PREEMPTION_GRANULARITY, ComputePreemptionGranularity: COMPUTE_PREEMPTION_GRANULARITY, } @@ -1165,6 +1168,199 @@ IAdapter3_VTable :: struct { UnregisterVideoMemoryBudgetChangeNotification: proc "system" (this: ^IAdapter3, dwCookie: u32), } +OUTDUPL_FLAG :: enum i32 { + COMPOSITED_UI_CAPTURE_ONLY = 1, +} + + +IOutput5_UUID_STRING :: "80A07424-AB52-42EB-833C-0C42FD282D98" +IOutput5_UUID := &IID{0x80A07424, 0xAB52, 0x42EB, {0x83, 0x3C, 0x0C, 0x42, 0xFD, 0x28, 0x2D, 0x98}} +IOutput5 :: struct #raw_union { + #subtype idxgioutput4: IOutput4, + using idxgioutput5_vtable: ^IOutput5_VTable, +} +IOutput5_VTable :: struct { + using idxgioutput4_vtable: IOutput4_VTable, + DuplicateOutput1: proc "system" (this: ^IOutput5, pDevice: ^IUnknown, Flags: u32, SupportedFormatsCount: u32, pSupportedFormats: ^FORMAT, ppOutputDuplication: ^^IOutputDuplication) -> HRESULT, +} + +HDR_METADATA_TYPE :: enum i32 { + NONE = 0, + HDR10 = 1, + HDR10PLUS = 2, +} + +HDR_METADATA_HDR10 :: struct { + RedPrimary: [2]u16, + GreenPrimary: [2]u16, + BluePrimary: [2]u16, + WhitePoint: [2]u16, + MaxMasteringLuminance: u32, + MinMasteringLuminance: u32, + MaxContentLightLevel: u16, + MaxFrameAverageLightLevel: u16, +} + +HDR_METADATA_HDR10PLUS :: struct { + Data: [72]byte, +} + + +ISwapChain4_UUID_STRING :: "3D585D5A-BD4A-489E-B1F4-3DBCB6452FFB" +ISwapChain4_UUID := &IID{0x3D585D5A, 0xBD4A, 0x489E, {0xB1, 0xF4, 0x3D, 0xBC, 0xB6, 0x45, 0x2F, 0xFB}} +ISwapChain4 :: struct #raw_union { + #subtype idxgiswapchain3: ISwapChain3, + using idxgiswapchain4_vtable: ^ISwapChain4_VTable, +} +ISwapChain4_VTable :: struct { + using idxgiswapchain3_vtable: ISwapChain3_VTable, + SetHDRMetaData: proc "system" (this: ^ISwapChain4, Type: HDR_METADATA_TYPE, Size: u32, pMetaData: rawptr) -> HRESULT, +} + +OFFER_RESOURCE_FLAGS :: bit_set[OFFER_RESOURCE_FLAG;u32] +OFFER_RESOURCE_FLAG :: enum u32 { + ALLOW_DECOMMIT = 0, +} + +RECLAIM_RESOURCE_RESULTS :: enum i32 { + OK = 0, + DISCARDED = 1, + NOT_COMMITTED = 2, +} + + +IDevice4_UUID_STRING :: "95B4F95F-D8DA-4CA4-9EE6-3B76D5968A10" +IDevice4_UUID := &IID{0x95B4F95F, 0xD8DA, 0x4CA4, {0x9E, 0xE6, 0x3B, 0x76, 0xD5, 0x96, 0x8A, 0x10}} +IDevice4 :: struct #raw_union { + #subtype idxgidevice3: IDevice3, + using idxgidevice4_vtable: ^IDevice4_VTable, +} +IDevice4_VTable :: struct { + using idxgidevice3_vtable: IDevice3_VTable, + OfferResources1: proc "system" (this: ^IDevice4, NumResources: u32, ppResources: ^^IResource, Priority: OFFER_RESOURCE_PRIORITY, Flags: OFFER_RESOURCE_FLAGS) -> HRESULT, + ReclaimResources1: proc "system" (this: ^IDevice4, NumResources: u32, ppResources: ^^IResource, pResults: ^RECLAIM_RESOURCE_RESULTS) -> HRESULT, +} + +FEATURE :: enum i32 { + PRESENT_ALLOW_TEARING = 0, +} + + +IFactory5_UUID_STRING :: "7632e1f5-ee65-4dca-87fd-84cd75f8838d" +IFactory5_UUID := &IID{0x7632e1f5, 0xee65, 0x4dca, {0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d}} +IFactory5 :: struct #raw_union { + #subtype idxgifactory4: IFactory4, + using idxgifactory5_vtable: ^IFactory5_VTable, +} +IFactory5_VTable :: struct { + using idxgifactory4_vtable: IFactory4_VTable, + CheckFeatureSupport: proc "system" (this: ^IFactory5, Feature: FEATURE, pFeatureSupportData: rawptr, FeatureSupportDataSize: u32) -> HRESULT, +} + +ADAPTER_FLAGS3 :: bit_set[ADAPTER_FLAG3;u32] +ADAPTER_FLAG3 :: enum u32 { + REMOTE = 0, + SOFTWARE = 1, + ACG_COMPATIBLE = 3, + SUPPORT_MONITORED_FENCES = 4, + SUPPORT_NON_MONITORED_FENCES = 5, + KEYED_MUTEX_CONFORMANCE = 6, +} + +ADAPTER_DESC3 :: struct { + Description: [128]WCHAR, + VendorId: u32, + DeviceId: u32, + SubSysId: u32, + Revision: u32, + DedicatedVideoMemory: u64, + DedicatedSystemMemory: u64, + SharedSystemMemory: u64, + AdapterLuid: LUID, + Flags: ADAPTER_FLAGS3, + GraphicsPreemptionGranularity: GRAPHICS_PREEMPTION_GRANULARITY, + ComputePreemptionGranularity: COMPUTE_PREEMPTION_GRANULARITY, +} + + +IAdapter4_UUID_STRING :: "3c8d99d1-4fbf-4181-a82c-af66bf7bd24e" +IAdapter4_UUID := &IID{0x3c8d99d1, 0x4fbf, 0x4181, {0xa8, 0x2c, 0xaf, 0x66, 0xbf, 0x7b, 0xd2, 0x4e}} +IAdapter4 :: struct #raw_union { + #subtype idxgiadapter3: IAdapter3, + using idxgiadapter4_vtable: ^IAdapter4_VTable, +} +IAdapter4_VTable :: struct { + using idxgiadapter3_vtable: IAdapter3_VTable, + GetDesc3: proc "system" (this: ^IAdapter4, pDesc: ^ADAPTER_DESC3) -> HRESULT, +} + +OUTPUT_DESC1 :: struct { + DeviceName: [32]WCHAR, + DesktopCoordinates: RECT, + AttachedToDesktop: BOOL, + Rotation: MODE_ROTATION, + Monitor: HMONITOR, + BitsPerColor: u32, + ColorSpace: COLOR_SPACE_TYPE, + RedPrimary: [2]f32, + GreenPrimary: [2]f32, + BluePrimary: [2]f32, + WhitePoint: [2]f32, + MinLuminance: f32, + MaxLuminance: f32, + MaxFullFrameLuminance: f32, +} + +HARDWARE_COMPOSITION_SUPPORT_FLAGS :: bit_set[HARDWARE_COMPOSITION_SUPPORT_FLAG;u32] +HARDWARE_COMPOSITION_SUPPORT_FLAG :: enum u32 { + FULLSCREEN = 0, + WINDOWED = 1, + CURSOR_STRETCHED = 2, +} + + +IOutput6_UUID_STRING :: "068346e8-aaec-4b84-add7-137f513f77a1" +IOutput6_UUID := &IID{0x068346e8, 0xaaec, 0x4b84, {0xad, 0xd7, 0x13, 0x7f, 0x51, 0x3f, 0x77, 0xa1}} +IOutput6 :: struct #raw_union { + #subtype idxgioutput5: IOutput5, + using idxgioutput6_vtable: ^IOutput6_VTable, +} +IOutput6_VTable :: struct { + using idxgioutput5_vtable: IOutput5_VTable, + GetDesc1: proc "system" (this: ^IOutput6, pDesc: ^OUTPUT_DESC1) -> HRESULT, + CheckHardwareCompositionSupport: proc "system" (this: ^IOutput6, pFlags: ^HARDWARE_COMPOSITION_SUPPORT_FLAGS) -> HRESULT, +} + +GPU_PREFERENCE :: enum i32 { + UNSPECIFIED = 0, + MINIMUM_POWER = 1, + HIGH_PERFORMANCE = 2, +} + + +IFactory6_UUID_STRING :: "c1b6694f-ff09-44a9-b03c-77900a0a1d17" +IFactory6_UUID := &IID{0xc1b6694f, 0xff09, 0x44a9, {0xb0, 0x3c, 0x77, 0x90, 0x0a, 0x0a, 0x1d, 0x17}} +IFactory6 :: struct #raw_union { + #subtype idxgifactory5: IFactory5, + using idxgifactory6_vtable: ^IFactory6_VTable, +} +IFactory6_VTable :: struct { + using idxgifactory5_vtable: IFactory5_VTable, + EnumAdapterByGpuPreference: proc "system" (this: ^IFactory6, Adapter: u32, GpuPreference: GPU_PREFERENCE, riid: ^IID, ppvAdapter: ^rawptr) -> HRESULT, +} + +IFactory7_UUID_STRING :: "a4966eed-76db-44da-84c1-ee9a7afb20a8" +IFactory7_UUID := &IID{0xa4966eed, 0x76db, 0x44da, {0x84, 0xc1, 0xee, 0x9a, 0x7a, 0xfb, 0x20, 0xa8}} +IFactory7 :: struct #raw_union { + #subtype idxgifactory6: IFactory6, + using idxgifactory7_vtable: ^IFactory7_VTable, +} +IFactory7_VTable :: struct { + using idxgifactory6_vtable: IFactory6_VTable, + RegisterAdaptersChangedEvent: proc "system" (this: ^IFactory7, hEvent: HANDLE, pdwCookie: ^DWORD) -> HRESULT, + UnregisterAdaptersChangedEvent: proc "system" (this: ^IFactory7, dwCookie: DWORD) -> HRESULT, +} + ERROR_ACCESS_DENIED :: HRESULT(-2005270485) //0x887A002B ERROR_ACCESS_LOST :: HRESULT(-2005270490) //0x887A0026 ERROR_ALREADY_EXISTS :: HRESULT(-2005270474) //0x887A0036 @@ -1192,4 +1388,4 @@ ERROR_WAS_STILL_DRAWING :: HRESULT(-2005270518) //0x887A000A STATUS_OCCLUDED :: HRESULT( 142213121) //0x087A0001 STATUS_MODE_CHANGED :: HRESULT( 142213127) //0x087A0007 -STATUS_MODE_CHANGE_IN_PROGRESS :: HRESULT( 142213128) //0x087A0008 \ No newline at end of file +STATUS_MODE_CHANGE_IN_PROGRESS :: HRESULT( 142213128) //0x087A0008