From 3b65cdb8f555b6efee313112d665668290909dfe Mon Sep 17 00:00:00 2001 From: Peter Li Date: Fri, 11 Apr 2025 13:57:04 -0700 Subject: [PATCH] sdl3 hello world gpu working --- engine/{neonwood.zig => backlog.zig} | 282 +++--- lib/sdl3/SDL/include/SDL3/SDL_gpu.h | 2 +- lib/sdl3/src/events.zig | 118 +++ lib/sdl3/src/generators/gpu.py | 748 ++++++++------ lib/sdl3/src/generators/shared.py | 0 lib/sdl3/src/gpu.zig | 1183 ++++++++++++++++------- lib/sdl3/src/init.zig | 39 - lib/sdl3/src/samples/hello-triangle.zig | 138 ++- lib/sdl3/src/sdl3.zig | 47 +- 9 files changed, 1749 insertions(+), 808 deletions(-) rename engine/{neonwood.zig => backlog.zig} (97%) create mode 100644 lib/sdl3/src/events.zig create mode 100644 lib/sdl3/src/generators/shared.py diff --git a/engine/neonwood.zig b/engine/backlog.zig similarity index 97% rename from engine/neonwood.zig rename to engine/backlog.zig index f3e8b66..2d1f9dc 100644 --- a/engine/neonwood.zig +++ b/engine/backlog.zig @@ -1,141 +1,141 @@ -pub const core = @import("core"); -pub const platform = @import("platform"); -pub const assets = @import("assets"); -pub const audio = @import("audio"); -pub const graphics = @import("graphics"); -pub const vkImgui = @import("vkImgui"); -pub const ui = @import("ui"); -pub const papyrus = @import("papyrus"); -pub const physics = @import("physics"); - -const modulelist = @import("modulelist.zig").list; - -const std = @import("std"); - -pub const NwArgs = struct { - useGPA: bool = true, // slower zig based memory allocator, provides detailed tracking of leaks and memory violations - vulkanValidation: bool = true, - fastTest: bool = false, - dmt: bool = false, // detailed memory tracking, implements a timeline for tracking all memory allocations - fatDump: bool = false, // takes a full fat minidump on crash, very large files are produced -}; - -pub fn getArgs() !NwArgs { - const a = try core.ParseArgs(NwArgs); - - return a; -} - -// entry function for a backlog program -// when this function is called it will use the settings specified by the program spec -// to conditionally start up feature modules within the engine - -var shutdownList: std.ArrayListUnmanaged(*const fn (std.mem.Allocator) void) = .{}; - -pub fn start_modules(comptime programSpec: anytype, maybeArgs: ?NwArgs, allocator: std.mem.Allocator) !void { - const Backlog = @This(); - - inline for (modulelist) |feature| { - if (@hasDecl(Backlog, feature)) { - const Struct = @field(Backlog, feature); - if (comptime core.isModuleEnabled(Struct.Module, programSpec)) { - if (maybeArgs) |args| { - try Struct.start_module(programSpec, args, allocator); - } else { - try Struct.start_module(programSpec, NwArgs{}, allocator); - } - try shutdownList.append(allocator, Struct.shutdown_module); - core.engine_logs("module started >>>> " ++ feature ++ " <<<<"); - } - } - } -} - -pub fn shutdown_modules(allocator: std.mem.Allocator) void { - var i: isize = @intCast(shutdownList.items.len - 1); - while (i >= 0) : (i -= 1) { - shutdownList.items[@intCast(i)](allocator); - } - shutdownList.deinit(allocator); -} - -pub fn start_everything(comptime spec: anytype, allocator: std.mem.Allocator, maybeArgs: ?NwArgs) !void { - if (maybeArgs) |args| { - if (args.vulkanValidation) - graphics.setStartupSettings("vulkanValidation", true); - } - - try start_modules(spec, maybeArgs, allocator); -} - -pub fn shutdown_everything(allocator: std.mem.Allocator) void { - shutdown_modules(allocator); -} - -pub fn run_everything(comptime GameContext: type) !void { - var canTick: bool = false; - - if (@hasDecl(GameContext, "tick")) { - canTick = true; - } - - var gameContext = try core.createObject(GameContext, .{ .can_tick = canTick }); - - if (@hasDecl(GameContext, "prepare_game")) { - gameContext.prepare_game() catch @panic("Unable to run base level prepare script"); - } else if (@hasDecl(GameContext, "prepare")) { - gameContext.prepare() catch @panic("Unable to run base level prepare script"); - } - - try core.gEngine.run(); - - while (!core.gEngine.exitFinished()) { - const z = core.tracy.ZoneN(@src(), "shutdown poll"); - platform.getInstance().pollEvents(); - z.End(); - } -} - -pub fn initializeAndRunStandardProgram(comptime GameContext: type, comptime spec: anytype) !void { - const args = try getArgs(); - - var backingAllocator: std.mem.Allocator = std.heap.c_allocator; - var gpa: std.heap.GeneralPurposeAllocator(.{ - .stack_trace_frames = 20, - }) = .{}; - - defer { - const cleanupStatus = gpa.deinit(); - if (cleanupStatus == .leak) { - std.debug.print("gpa cleanup leaked memory\n", .{}); - } - } - - if (args.useGPA) { - backingAllocator = gpa.allocator(); - } - - const memory = core.MemoryTracker; - memory.MTSetup(backingAllocator, .{ .timeline = args.dmt }); - defer memory.MTShutdown(); - - var tracker = memory.MTGet().?; - const allocator = tracker.allocator(); - - if (args.vulkanValidation) { - core.engine_logs("Using vulkan validation"); - } - - graphics.setStartupSettings("vulkanValidation", args.vulkanValidation); - - if (@hasField(@TypeOf(spec), "windowName")) { - platform.setWindowSettings(.{ .windowName = spec.windowName }); - } else { - platform.setWindowSettings(.{ .windowName = spec.name }); - } - - try start_everything(spec, allocator, args); - defer shutdown_everything(allocator); - - try run_everything(GameContext); -} +pub const core = @import("core"); +pub const platform = @import("platform"); +pub const assets = @import("assets"); +pub const audio = @import("audio"); +pub const graphics = @import("graphics"); +pub const vkImgui = @import("vkImgui"); +pub const ui = @import("ui"); +pub const papyrus = @import("papyrus"); +pub const physics = @import("physics"); + +const modulelist = @import("modulelist.zig").list; + +const std = @import("std"); + +pub const NwArgs = struct { + useGPA: bool = true, // slower zig based memory allocator, provides detailed tracking of leaks and memory violations + vulkanValidation: bool = true, + fastTest: bool = false, + dmt: bool = false, // detailed memory tracking, implements a timeline for tracking all memory allocations + fatDump: bool = false, // takes a full fat minidump on crash, very large files are produced +}; + +pub fn getArgs() !NwArgs { + const a = try core.ParseArgs(NwArgs); + + return a; +} + +// entry function for a backlog program +// when this function is called it will use the settings specified by the program spec +// to conditionally start up feature modules within the engine + +var shutdownList: std.ArrayListUnmanaged(*const fn (std.mem.Allocator) void) = .{}; + +pub fn start_modules(comptime programSpec: anytype, maybeArgs: ?NwArgs, allocator: std.mem.Allocator) !void { + const Backlog = @This(); + + inline for (modulelist) |feature| { + if (@hasDecl(Backlog, feature)) { + const Struct = @field(Backlog, feature); + if (comptime core.isModuleEnabled(Struct.Module, programSpec)) { + if (maybeArgs) |args| { + try Struct.start_module(programSpec, args, allocator); + } else { + try Struct.start_module(programSpec, NwArgs{}, allocator); + } + try shutdownList.append(allocator, Struct.shutdown_module); + core.engine_logs("module started >>>> " ++ feature ++ " <<<<"); + } + } + } +} + +pub fn shutdown_modules(allocator: std.mem.Allocator) void { + var i: isize = @intCast(shutdownList.items.len - 1); + while (i >= 0) : (i -= 1) { + shutdownList.items[@intCast(i)](allocator); + } + shutdownList.deinit(allocator); +} + +pub fn start_everything(comptime spec: anytype, allocator: std.mem.Allocator, maybeArgs: ?NwArgs) !void { + if (maybeArgs) |args| { + if (args.vulkanValidation) + graphics.setStartupSettings("vulkanValidation", true); + } + + try start_modules(spec, maybeArgs, allocator); +} + +pub fn shutdown_everything(allocator: std.mem.Allocator) void { + shutdown_modules(allocator); +} + +pub fn run_everything(comptime GameContext: type) !void { + var canTick: bool = false; + + if (@hasDecl(GameContext, "tick")) { + canTick = true; + } + + var gameContext = try core.createObject(GameContext, .{ .can_tick = canTick }); + + if (@hasDecl(GameContext, "prepare_game")) { + gameContext.prepare_game() catch @panic("Unable to run base level prepare script"); + } else if (@hasDecl(GameContext, "prepare")) { + gameContext.prepare() catch @panic("Unable to run base level prepare script"); + } + + try core.gEngine.run(); + + while (!core.gEngine.exitFinished()) { + const z = core.tracy.ZoneN(@src(), "shutdown poll"); + platform.getInstance().pollEvents(); + z.End(); + } +} + +pub fn initializeAndRunStandardProgram(comptime GameContext: type, comptime spec: anytype) !void { + const args = try getArgs(); + + var backingAllocator: std.mem.Allocator = std.heap.c_allocator; + var gpa: std.heap.GeneralPurposeAllocator(.{ + .stack_trace_frames = 20, + }) = .{}; + + defer { + const cleanupStatus = gpa.deinit(); + if (cleanupStatus == .leak) { + std.debug.print("gpa cleanup leaked memory\n", .{}); + } + } + + if (args.useGPA) { + backingAllocator = gpa.allocator(); + } + + const memory = core.MemoryTracker; + memory.MTSetup(backingAllocator, .{ .timeline = args.dmt }); + defer memory.MTShutdown(); + + var tracker = memory.MTGet().?; + const allocator = tracker.allocator(); + + if (args.vulkanValidation) { + core.engine_logs("Using vulkan validation"); + } + + graphics.setStartupSettings("vulkanValidation", args.vulkanValidation); + + if (@hasField(@TypeOf(spec), "windowName")) { + platform.setWindowSettings(.{ .windowName = spec.windowName }); + } else { + platform.setWindowSettings(.{ .windowName = spec.name }); + } + + try start_everything(spec, allocator, args); + defer shutdown_everything(allocator); + + try run_everything(GameContext); +} diff --git a/lib/sdl3/SDL/include/SDL3/SDL_gpu.h b/lib/sdl3/SDL/include/SDL3/SDL_gpu.h index 9f516d7..ffddb80 100644 --- a/lib/sdl3/SDL/include/SDL3/SDL_gpu.h +++ b/lib/sdl3/SDL/include/SDL3/SDL_gpu.h @@ -2231,7 +2231,7 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGPUDriver(int index); /** * Returns the name of the backend used to create this GPU context. - * + * \param device a GPU context to query. * \returns the name of the device's driver, or NULL on error. * diff --git a/lib/sdl3/src/events.zig b/lib/sdl3/src/events.zig new file mode 100644 index 0000000..5d5cdcb --- /dev/null +++ b/lib/sdl3/src/events.zig @@ -0,0 +1,118 @@ +pub const first: u32 = 0; +pub const quit: u32 = 256; +pub const terminating: u32 = 257; +pub const low_memory: u32 = 258; +pub const will_enter_background: u32 = 259; +pub const did_enter_background: u32 = 260; +pub const will_enter_foreground: u32 = 261; +pub const did_enter_foreground: u32 = 262; +pub const locale_changed: u32 = 263; +pub const system_theme_changed: u32 = 264; +pub const display_orientation: u32 = 337; +pub const display_added: u32 = 338; +pub const display_removed: u32 = 339; +pub const display_moved: u32 = 340; +pub const display_desktop_mode_changed: u32 = 341; +pub const display_current_mode_changed: u32 = 342; +pub const display_content_scale_changed: u32 = 343; +pub const display_first: u32 = 337; +pub const display_last: u32 = 343; +pub const window_shown: u32 = 514; +pub const window_hidden: u32 = 515; +pub const window_exposed: u32 = 516; +pub const window_moved: u32 = 517; +pub const window_resized: u32 = 518; +pub const window_pixel_size_changed: u32 = 519; +pub const window_metal_view_resized: u32 = 520; +pub const window_minimized: u32 = 521; +pub const window_maximized: u32 = 522; +pub const window_restored: u32 = 523; +pub const window_mouse_enter: u32 = 524; +pub const window_mouse_leave: u32 = 525; +pub const window_focus_gained: u32 = 526; +pub const window_focus_lost: u32 = 527; +pub const window_close_requested: u32 = 528; +pub const window_hit_test: u32 = 529; +pub const window_iccprof_changed: u32 = 530; +pub const window_display_changed: u32 = 531; +pub const window_display_scale_changed: u32 = 532; +pub const window_safe_area_changed: u32 = 533; +pub const window_occluded: u32 = 534; +pub const window_enter_fullscreen: u32 = 535; +pub const window_leave_fullscreen: u32 = 536; +pub const window_destroyed: u32 = 537; +pub const window_hdr_state_changed: u32 = 538; +pub const window_first: u32 = 514; +pub const window_last: u32 = 538; +pub const key_down: u32 = 768; +pub const key_up: u32 = 769; +pub const text_editing: u32 = 770; +pub const text_input: u32 = 771; +pub const keymap_changed: u32 = 772; +pub const keyboard_added: u32 = 773; +pub const keyboard_removed: u32 = 774; +pub const text_editing_candidates: u32 = 775; +pub const mouse_motion: u32 = 1024; +pub const mouse_button_down: u32 = 1025; +pub const mouse_button_up: u32 = 1026; +pub const mouse_wheel: u32 = 1027; +pub const mouse_added: u32 = 1028; +pub const mouse_removed: u32 = 1029; +pub const joystick_axis_motion: u32 = 1536; +pub const joystick_ball_motion: u32 = 1537; +pub const joystick_hat_motion: u32 = 1538; +pub const joystick_button_down: u32 = 1539; +pub const joystick_button_up: u32 = 1540; +pub const joystick_added: u32 = 1541; +pub const joystick_removed: u32 = 1542; +pub const joystick_battery_updated: u32 = 1543; +pub const joystick_update_complete: u32 = 1544; +pub const gamepad_axis_motion: u32 = 1616; +pub const gamepad_button_down: u32 = 1617; +pub const gamepad_button_up: u32 = 1618; +pub const gamepad_added: u32 = 1619; +pub const gamepad_removed: u32 = 1620; +pub const gamepad_remapped: u32 = 1621; +pub const gamepad_touchpad_down: u32 = 1622; +pub const gamepad_touchpad_motion: u32 = 1623; +pub const gamepad_touchpad_up: u32 = 1624; +pub const gamepad_sensor_update: u32 = 1625; +pub const gamepad_update_complete: u32 = 1626; +pub const gamepad_steam_handle_updated: u32 = 1627; +pub const finger_down: u32 = 1792; +pub const finger_up: u32 = 1793; +pub const finger_motion: u32 = 1794; +pub const finger_canceled: u32 = 1795; +pub const clipboard_update: u32 = 2304; +pub const drop_file: u32 = 4096; +pub const drop_text: u32 = 4097; +pub const drop_begin: u32 = 4098; +pub const drop_complete: u32 = 4099; +pub const drop_position: u32 = 4100; +pub const audio_device_added: u32 = 4352; +pub const audio_device_removed: u32 = 4353; +pub const audio_device_format_changed: u32 = 4354; +pub const sensor_update: u32 = 4608; +pub const pen_proximity_in: u32 = 4864; +pub const pen_proximity_out: u32 = 4865; +pub const pen_down: u32 = 4866; +pub const pen_up: u32 = 4867; +pub const pen_button_down: u32 = 4868; +pub const pen_button_up: u32 = 4869; +pub const pen_motion: u32 = 4870; +pub const pen_axis: u32 = 4871; +pub const camera_device_added: u32 = 5120; +pub const camera_device_removed: u32 = 5121; +pub const camera_device_approved: u32 = 5122; +pub const camera_device_denied: u32 = 5123; +pub const render_targets_reset: u32 = 8192; +pub const render_device_reset: u32 = 8193; +pub const render_device_lost: u32 = 8194; +pub const private0: u32 = 16384; +pub const private1: u32 = 16385; +pub const private2: u32 = 16386; +pub const private3: u32 = 16387; +pub const poll_sentinel: u32 = 32512; +pub const user: u32 = 32768; +pub const last: u32 = 65535; +pub const enum_padding: u32 = 2147483647; diff --git a/lib/sdl3/src/generators/gpu.py b/lib/sdl3/src/generators/gpu.py index 748d382..8b1df8e 100644 --- a/lib/sdl3/src/generators/gpu.py +++ b/lib/sdl3/src/generators/gpu.py @@ -1,4 +1,5 @@ import os + import sys from pprint import pprint import math @@ -23,29 +24,47 @@ def convertCase(x): origDir = os.path.abspath(os.path.dirname(__file__)) os.chdir(origDir) -gpufile = "../../SDL/include/SDL3/SDL_gpu.h" +infile = "../../SDL/include/SDL3/SDL_gpu.h" +ofile = os.path.abspath(os.path.join(origDir, '../gpu.zig')) -mode_default = 0 -mode_collecting = 1 +SDL_files = [ + 'SDL_gpu.h', +] -typedefs_pod = [] -typedefs_opaque = [] -typedefs_enum = [] -typedefs_struct = [] -typedefs_unknown = [] -functions = [] +typeMap = { + 'Uint32': 'u32', 'float': 'f32', 'Sint32': 'i32', 'bool': 'bool', 'Uint8': 'u8', 'SDL_PropertiesID': 'PropertiesID','char': 'u8', + 'void': 'void', + 'int': 'c_int', + 'size_t': 'usize', + 'SDL_Window': 'Window', +} -defines = [] +typeMap_r = {} -lastList = None +def generateAll(infile, ofile): -with open(gpufile) as rf: - mode = mode_default - braceCount = 0 - f = rf.readlines() + mode_default = 0 + mode_collecting = 1 - x = [ y + '\n' for y in """ + typedefs_pod = [] + typedefs_opaque = [] + typedefs_enum = [] + typedefs_struct = [] + typedefs_unknown = [] + + functions = [] + + defines = [] + + lastList = None + + with open(infile) as rf: + mode = mode_default + braceCount = 0 + f = rf.readlines() + + x = [ y + '\n' for y in """ typedef struct SDL_FColor { float r; @@ -54,342 +73,527 @@ typedef struct SDL_FColor { float a; } SDL_FColor; +typedef struct SDL_Rect +{ + int x; + int y; + int w; + int h; +} SDL_Rect; + typedef enum SDL_FlipMode { SDL_FLIP_NONE, /**< Do not flip */ SDL_FLIP_HORIZONTAL, /**< flip horizontally */ SDL_FLIP_VERTICAL /**< flip vertically */ } SDL_FlipMode; - """.split('\n')] + """.split('\n')] - f += x + f += x - for l in f: - dropped = True - line = l.strip() - if mode == mode_default: - if line.startswith('typedef'): - if ";" in line and 'struct' in line: - typedefs_opaque.append(line) + for l in f: + dropped = True + line = l.strip() + if mode == mode_default: + if line.startswith('typedef'): + if ";" in line and 'struct' in line: + typedefs_opaque.append(line) + dropped = False + elif ';' in line: + typedefs_pod.append(line) + dropped = False + elif 'enum' in line: + lastList = typedefs_enum + typedefs_enum.append(line) + dropped = False + elif 'struct' in line: + lastList = typedefs_struct + typedefs_struct.append(line) + dropped = False + else: + lastList = typedefs_unknown + dropped = False + typedefs_unknown.append(line) + + elif line.startswith('extern SDL_DECLSPEC'): + lastList = functions dropped = False - elif ';' in line: - typedefs_pod.append(line) - dropped = False - elif 'enum' in line: - lastList = typedefs_enum - typedefs_enum.append(line) - dropped = False - elif 'struct' in line: - lastList = typedefs_struct - typedefs_struct.append(line) - dropped = False - else: - lastList = typedefs_unknown - dropped = False - typedefs_unknown.append(line) + functions.append(line) - elif line.startswith('extern SDL_DECLSPEC'): - lastList = functions - dropped = False - functions.append(line) + elif line.startswith('#define '): + lastList = defines + defines.append(line) - elif line.startswith('#define '): - lastList = defines - defines.append(line) + if ';' not in line and not dropped: + mode = mode_collecting + if "{" in l: + braceCount = 1 - if ';' not in line and not dropped: - mode = mode_collecting - if "{" in l: - braceCount = 1 + elif mode == mode_collecting: + lastList[-1] += l.replace('\n', '\n') - elif mode == mode_collecting: - lastList[-1] += l.replace('\n', '\n') + if "{" in line: + braceCount += 1 - if "{" in line: - braceCount += 1 + if "}" in line: + braceCount -= 1 - if "}" in line: - braceCount -= 1 + if ';' in line and braceCount == 0: + mode = mode_default - if ';' in line and braceCount == 0: - mode = mode_default + print_types = False + print_functions = False + print_defines= False -print_types = False -print_functions = False -print_defines= False + def plos(l): + for s in l: + print('> ', s, " < ") -def plos(l): - for s in l: - print('> ', s, " < ") - -print('struct') + print('struct') # plos(typedefs_struct) -print('pod') -plos(typedefs_pod) -if print_types: - print('opaque') - plos(typedefs_opaque) print('pod') plos(typedefs_pod) - print('enum') - plos(typedefs_enum) - print('unknown') - plos(typedefs_unknown) + if print_types: + print('opaque') + plos(typedefs_opaque) + print('pod') + plos(typedefs_pod) + print('enum') + plos(typedefs_enum) + print('unknown') + plos(typedefs_unknown) -if print_functions: - print('functions') - plos(functions) + if print_functions: + print('functions') + plos(functions) -if print_defines: - print('defines') - plos(defines) + if print_defines: + print('defines') + plos(defines) -print(f"\nfunctions: {len(functions)}, structs:{len(typedefs_struct)}, enums:{len(typedefs_enum)}\n") + print(f"\nfunctions: {len(functions)}, structs:{len(typedefs_struct)}, enums:{len(typedefs_enum)}\n") -ostring = 'pub const c = @import("c.zig").c;\n\npub const PropertiesID = u32;' + ostring = 'pub const c = @import("c.zig").c;\n\npub const PropertiesID = u32;\n pub const Window = c.SDL_Window;' # time to generate types... # first the opaques -ostring += '\n' + ostring += '\n' -typeMap = { - 'Uint32': 'u32', 'float': 'f32', 'Sint32': 'i32', 'bool': 'bool', 'Uint8': 'u8', 'SDL_PropertiesID': 'PropertiesID','char': 'i8', - 'size_t': 'usize', - 'SDL_FColor': 'FColor', - 'SDL_FlipMode': 'FlipMode' -} + opaques = {'Window': ''} + enums = {} -typeMap_r = {} + opaqueOrder = [] + + for t in typedefs_pod: + c_typename = t.strip().strip(';').split(' ')[-1] + typename = c_typename + + if typename.startswith("SDL_"): + typename = typename[4:] + + typeMap[c_typename] = typename + typeMap_r[typename] = c_typename + # todo generate packed flags for each one + + for t in typedefs_opaque: + c_typename = t.strip().strip(';').split(' ')[3] + typename = c_typename + + if typename.startswith("SDL_"): + typename = typename[4:] + + typeMap[c_typename] = typename + typeMap_r[typename] = c_typename + + brackets = "{}" + definition = f"pub const {typename} = opaque {{\n" + # ostring += definition + opaques[typename] = definition + opaqueOrder.append(typename) -for t in typedefs_pod: - c_typename = t.strip().strip(';').split(' ')[-1] - typename = c_typename + ostring += '\n' - if typename.startswith("SDL_"): - typename = typename[4:] + packedFlags = [ + ('SDL_GPUTextureUsageFlags', 'Uint32', [ + ('SDL_GPU_TEXTUREUSAGE_SAMPLER', 1 << 0), + ('SDL_GPU_TEXTUREUSAGE_COLOR_TARGET', 1 << 1), + ('SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET', 1 << 2), + ('SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ', 1 << 3), + ('SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ', 1 << 4), + ('SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE', 1 << 5), + ('SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE', 1 << 6), + ('rsvd', 1 << 31) + ]), + ('SDL_GPUBufferUsageFlags', 'Uint32', [ + ('SDL_GPU_BUFFERUSAGE_VERTEX', (1 << 0)), + ('SDL_GPU_BUFFERUSAGE_INDEX', (1 << 1)), + ('SDL_GPU_BUFFERUSAGE_INDIRECT', (1 << 2)), + ('SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ', (1 << 3)), + ('SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ', (1 << 4)), + ('SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE', (1 << 5)), + ('rsvd', 1 << 31) + ]), + ('SDL_GPUColorComponentFlags', 'Uint8', [ + ('SDL_GPU_COLORCOMPONENT_R', (1 << 0)), + ('SDL_GPU_COLORCOMPONENT_G', (1 << 1)), + ('SDL_GPU_COLORCOMPONENT_B', (1 << 2)), + ('SDL_GPU_COLORCOMPONENT_A', (1 << 3)), + ('rsvd', 1 << 7) + ]), + ('SDL_GPUShaderFormat', 'Uint32', [ + ('SDL_GPU_SHADERFORMAT_PRIVATE', (1 << 0)), + ('SDL_GPU_SHADERFORMAT_SPIRV', (1 << 1)), + ('SDL_GPU_SHADERFORMAT_DXBC', (1 << 2)), + ('SDL_GPU_SHADERFORMAT_DXIL', (1 << 3)), + ('SDL_GPU_SHADERFORMAT_MSL', (1 << 4)), + ('SDL_GPU_SHADERFORMAT_METALLIB', (1 << 5)), + ('rsvd', 1 << 31) + ], [('Invalid', '.{}')]), + ] - typeMap[c_typename] = typename - typeMap_r[typename] = c_typename - # todo generate packed flags for each one + def makePackedFlags(typename, backingtype, flagList, constants=None): + global typeMap + global typeMap_r -for t in typedefs_opaque: - c_typename = t.strip().strip(';').split(' ')[3] - typename = c_typename + c_typename = typename + if typename.startswith("SDL_"): + typename = typename[4:] - if typename.startswith("SDL_"): - typename = typename[4:] + typeMap[c_typename] = typename + typeMap_r[typename] = c_typename - typeMap[c_typename] = typename - typeMap_r[typename] = c_typename + rv = 'pub const ' + typename + ' = packed struct(' + typeMap[backingtype] + ') {\n' - brackets = "{}" - definition = f"pub const {typename} = opaque{brackets};\n" - ostring += definition + offset = 0 + padcount = 0 + for flag in flagList: + name = flag[0] + targetOffset = math.log2(flag[1]) -ostring += '\n' + if 'SDL_GPU_' in name: + name = name[8:] + name = convertCase(name) -packedFlags = [ - ('SDL_GPUTextureUsageFlags', 'Uint32', [ - ('SDL_GPU_TEXTUREUSAGE_SAMPLER', 1 << 0), - ('SDL_GPU_TEXTUREUSAGE_COLOR_TARGET', 1 << 1), - ('SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET', 1 << 2), - ('SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ', 1 << 3), - ('SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ', 1 << 4), - ('SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE', 1 << 5), - ('SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE', 1 << 6), - ]), - ('SDL_GPUBufferUsageFlags', 'Uint32', [ - ('SDL_GPU_BUFFERUSAGE_VERTEX', (1 << 0)), - ('SDL_GPU_BUFFERUSAGE_INDEX', (1 << 1)), - ('SDL_GPU_BUFFERUSAGE_INDIRECT', (1 << 2)), - ('SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ', (1 << 3)), - ('SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ', (1 << 4)), - ('SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE', (1 << 5)), - ]), - ('SDL_GPUColorComponentFlags', 'Uint8', [ - ('SDL_GPU_COLORCOMPONENT_R', (1 << 0)), - ('SDL_GPU_COLORCOMPONENT_G', (1 << 1)), - ('SDL_GPU_COLORCOMPONENT_B', (1 << 2)), - ('SDL_GPU_COLORCOMPONENT_A', (1 << 3)), - ]), - ('SDL_GPUShaderFormat', 'Uint32', [ - ('SDL_GPU_SHADERFORMAT_PRIVATE', (1 << 0)), - ('SDL_GPU_SHADERFORMAT_SPIRV', (1 << 1)), - ('SDL_GPU_SHADERFORMAT_DXBC', (1 << 2)), - ('SDL_GPU_SHADERFORMAT_DXIL', (1 << 3)), - ('SDL_GPU_SHADERFORMAT_MSL', (1 << 4)), - ('SDL_GPU_SHADERFORMAT_METALLIB', (1 << 5)), - ], [('Invalid', '.{}')]), -] + if targetOffset != offset: + diff = int(targetOffset - offset) + rv += ' ' + 'pad' + str(padcount) + ': u' + str(diff) + ' = 0,\n' + padcount += 1 + offset = targetOffset -def makePackedFlags(typename, backingtype, flagList, constants=None): - global typeMap - global typeMap_r + rv += ' ' + name + ': bool = false,\n' + offset += 1 - c_typename = typename - if typename.startswith("SDL_"): - typename = typename[4:] + if constants is not None: + for constant in constants: + rv += f' pub const {constant[0]}: @This() = {constant[1]};\n' - typeMap[c_typename] = typename - typeMap_r[typename] = c_typename + rv += '};\n' - rv = 'pub const ' + typename + ' = packed struct(' + typeMap[backingtype] + ') {\n' + return rv - offset = 0 - padcount = 0 - for flag in flagList: - name = flag[0] - targetOffset = math.log2(flag[1]) + ostring += '\n' - if 'SDL_GPU_' in name: - name = name[8:] - name = convertCase(name) + for p in packedFlags: + ostring += makePackedFlags(*p) - if targetOffset != offset: - diff = int(targetOffset - offset) - rv += ' ' + 'pad' + str(padcount) + ': u' + str(diff) + ' = 0,\n' - padcount += 1 - offset = targetOffset + for t in typedefs_enum: + typename = t.split("}")[1].strip('\n ;') + #print("E", typename, t) + c_typename = typename + if typename.startswith("SDL_"): + typename = typename[4:] - rv += ' ' + name + ': bool = false,\n' - offset += 1 + typeMap[c_typename] = typename + typeMap_r[typename] = c_typename + enums[typename] = "" - if constants is not None: - for constant in constants: - rv += f' pub const {constant[0]}: @This() = {constant[1]};\n' + # print(t) - rv += '};\n' + inners = t.strip().split('\n')[1:-1] + e = [] - return rv - -ostring += '\n' - -for p in packedFlags: - ostring += makePackedFlags(*p) - -for t in typedefs_enum: - typename = t.split("}")[1].strip('\n ;') - #print("E", typename, t) - c_typename = typename - if typename.startswith("SDL_"): - typename = typename[4:] - - typeMap[c_typename] = typename - typeMap_r[typename] = c_typename - - # print(t) - - inners = t.strip().split('\n')[1:-1] - e = [] - - for i in range(0, len(inners)): - line = inners[i] - if ',' in line or line == inners[-1]: - e.append(line.strip()) + for i in range(0, len(inners)): + line = inners[i] + if ',' in line or line == inners[-1]: + e.append(line.strip()) - for i in range(0, len(e)): - e[i] = e[i].replace('/*', '//') - e[i] = e[i].replace('SDL_GPU_', '') + for i in range(0, len(e)): + e[i] = e[i].replace('/*', '//') + e[i] = e[i].replace('SDL_GPU_', '') - if ',' not in e[i]: - count = 0 - for x in e[i]: - if x == ' ': - break - count += 1 + if ',' not in e[i]: + count = 0 + for x in e[i]: + if x == ' ': + break + count += 1 - e[i] = e[i][:count] + ',' + e[i][count:] + e[i] = e[i][:count] + ',' + e[i][count:] - r = e[i].split(',') + r = e[i].split(',') - r[0] = convertCase(r[0]) + r[0] = convertCase(r[0]) - e[i] = r[0] + ',' + r[1] - common = os.path.commonprefix(e) - #print(common) - #plos(e) + e[i] = r[0] + ',' + r[1] + common = os.path.commonprefix(e) + #print(common) + #plos(e) - ostring += 'pub const ' + typename + ' = ' + 'enum {\n' - for i in e: - ostring += ' ' + i + '\n' - ostring += '};\n\n' + ostring += 'pub const ' + typename + ' = ' + 'enum(c_int) {\n' + for i in e: + ostring += ' ' + i + '\n' + ostring += '};\n\n' -for t in typedefs_struct: - typename = t.split("}")[1].strip('\n ;') - c_typename = typename - if typename.startswith("SDL_"): - typename = typename[4:] + for t in typedefs_struct: + typename = t.split("}")[1].strip('\n ;') + c_typename = typename + if typename.startswith("SDL_"): + typename = typename[4:] - typeMap[c_typename] = typename - typeMap_r[typename] = c_typename + typeMap[c_typename] = typename + typeMap_r[typename] = c_typename -for t in typedefs_struct: + for t in typedefs_struct: - typename = t.split("}")[1].strip('\n ;') - c_typename = typename - if typename.startswith("SDL_"): - typename = typename[4:] + typename = t.split("}")[1].strip('\n ;') + c_typename = typename + if typename.startswith("SDL_"): + typename = typename[4:] - typeMap[c_typename] = typename - typeMap_r[typename] = c_typename + typeMap[c_typename] = typename + typeMap_r[typename] = c_typename - inner = t.strip("\n ").split('\n')[1:-1] + inner = t.strip("\n ").split('\n')[1:-1] - # print("----", typename) - for i in range(0, len(inner)): - inner[i] = inner[i].replace('/*', "//") - inner[i] = inner[i].replace('*<', "") - inner[i] = inner[i].replace('*/', "") + # print("----", typename) + for i in range(0, len(inner)): + inner[i] = inner[i].replace('/*', "//") + inner[i] = inner[i].replace('*<', "") + inner[i] = inner[i].replace('*/', "") - fields = [] + fields = [] - for txt in inner: - s = txt.split(';') - decl = s[0].strip() - comment = "" - if len(s) > 1: - comment = s[1].strip() + for txt in inner: + s = txt.split(';') + decl = s[0].strip() + comment = "" + if len(s) > 1: + comment = s[1].strip() - fieldType = " ".join(decl.split(' ')[:-1]) - name = decl.split(' ')[-1] - const = False - pointer = False + fieldType = " ".join(decl.split(' ')[:-1]) + name = decl.split(' ')[-1] + const = False + pointer = False - if fieldType.startswith('const'): - fieldType = fieldType[5:].strip() - const = True + if fieldType.startswith('const'): + fieldType = fieldType[5:].strip() + const = True - if name.startswith('*'): - pointer = True; - name = name.strip('*') + if name.startswith('*'): + pointer = True; + name = name.strip('*') - if fieldType != '' and name != '': - fields.append((fieldType, name, const, comment, pointer)) - # not implemented - if '[' in name: - assert False + if fieldType != '' and name != '': + fields.append((fieldType, name, const, comment, pointer)) - if '[' in fieldType: - assert False + # not implemented + if '[' in name: + assert False - tstr = "pub const " + typename + " = extern struct {\n" + if '[' in fieldType: + assert False - for field in fields: - tstr += ' ' + field[1] + ': ' + ('*' if field[4] else '') + ('const ' if field[2] else '') + typeMap[field[0]] + ', ' + field[3] + ' \n' + tstr = "pub const " + typename + " = extern struct {\n" - tstr += '};\n' + for field in fields: + typestring = typeMap[field[0]] + ptr = '[*c]' + if typestring in opaques: + ptr = '*' + tstr += ' ' + field[1] + ': ' + (ptr if field[4] else '') + ('const ' if field[2] else '') + typestring + ', ' + field[3] + ' \n' - ostring += tstr + "\n" + tstr += '};\n' -for t in functions: - print(t) + ostring += tstr + "\n" -# print (ostring) + for t in functions: + funcname = None -with open(os.path.abspath(os.path.join(origDir, '../gpu.zig')), 'w') as f: - f.write(ostring) + s = t[len("extern SDL_DECLSPEC "):].split('(') + label = s[0] + args = s[1].replace('\n', '') + + def findTypeFromLabel(label): + pointerCount = label.count('*') + + label = label.split(' ') + + typeStr = None + isConst = False + + + if label[0] == 'const': + isConst = True + + if isConst: + typeStr = 'const ' + typeMap[label[1]] + else: + typeStr = typeMap[label[0]] + + for i in range(0, pointerCount): + if typeStr.split(' ')[-1] in opaques: + typeStr = '*' + typeStr + else: + typeStr = '[*c]' + typeStr + + if typeStr == '*void': + typeStr = '*anyopaque' + + if typeStr == '*const u8': + return '[*c]const u8' + + return typeStr + + def getArgsListFromArgs(t, args): + rv = [] + + if args.strip(' );') == 'void': + return rv + + l = args.replace(')', '') + l = l.replace(';', '') + l = l.split(',') + + l2 = [] + for x in l: + l2.append(x.strip()) + + print(l2) + for i in l2: + x = findTypeFromLabel(i) + print("type: ", i, '>', x, '<') + + y = i.split(' ')[-1].replace('*', '') + + if y == 'type': + y = '_type' + + v = (x, y) + + rv.append(v) + print(v) + + return rv + + def findFuncFromLabel(label): + rv = '' + + rv = label.split(' ')[-1] + + if rv.startswith('SDL_'): + rv = rv[4:] + + if rv.startswith('GPU'): + rv = 'gpu' + rv[3:] + + if rv.startswith('GDK'): + rv = 'gdk' + rv[3:] + + rv = rv[0].lower() + rv[1:] + + return rv + + argsList = getArgsListFromArgs(t, args) + rtype = findTypeFromLabel(label) + funcLabel = findFuncFromLabel(label) + funcargs = '' + first = True + body = '' + for arg in argsList: + if first: + first = False + else: + funcargs += ', ' + funcargs += arg[1] + ': ' + arg[0] + # body += ' _ = ' + arg[1] + ';\n' + + cfunc = label.split(' ')[-1].strip() + funcstring = '// ' + label.split(' ')[-1] + '\n' + funcstring += 'pub inline fn ' + funcLabel + '('+ funcargs + ') ' + rtype + ' {\n' + bitCastRtype = False + ptrCastRtype = False + enumCastRtype = False + + if rtype is not None and rtype != 'void': + funcstring += ' return ' + if rtype == '[*c]const u8' or rtype.strip('*') in opaques: + ptrCastRtype = True + elif rtype in enums: + enumCastRtype = True + elif rtype != 'bool' and rtype != 'void': + print('rtype === ', rtype) + bitCastRtype = True + else: + funcstring += ' ' + + if ptrCastRtype: + funcstring += '@ptrCast(' + + if bitCastRtype: + funcstring += '@bitCast(' + + if enumCastRtype: + funcstring += '@enumFromInt(' + + funcstring += 'c.' + cfunc + '(' + first = True + + selfArg = None + for arg in argsList: + argType = arg[0] + argName = arg[1] + if first: + first = False + if argType.strip('*') in opaques: + selfArg = argType.strip('*') + else: + funcstring += ', ' + + if argType == 'bool' or argType == '[*c]const u8': + funcstring += argName + elif '*' in argType: + funcstring += '@ptrCast(' + argName + ')' + else: + funcstring += '@bitCast(' + argName + ')' + + if bitCastRtype or ptrCastRtype or enumCastRtype: + funcstring += ')' + + funcstring += ');\n' + + funcstring += body + funcstring += '}\n\n' + + if selfArg is not None: + opaques[selfArg] += funcstring + else: + ostring += funcstring + + for opaque in opaques: + opaques[opaque] += '};\n\n' + + for opaque in opaqueOrder: + ostring += opaques[opaque] + + with open(ofile, 'w') as f: + f.write(ostring) + + subprocess.run(['zig', 'fmt', ofile]) + + +generateAll(infile, ofile) diff --git a/lib/sdl3/src/generators/shared.py b/lib/sdl3/src/generators/shared.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/sdl3/src/gpu.zig b/lib/sdl3/src/gpu.zig index 7391f36..075bbeb 100644 --- a/lib/sdl3/src/gpu.zig +++ b/lib/sdl3/src/gpu.zig @@ -1,20 +1,7 @@ pub const c = @import("c.zig").c; pub const PropertiesID = u32; -pub const GPUDevice = opaque{}; -pub const GPUBuffer = opaque{}; -pub const GPUTransferBuffer = opaque{}; -pub const GPUTexture = opaque{}; -pub const GPUSampler = opaque{}; -pub const GPUShader = opaque{}; -pub const GPUComputePipeline = opaque{}; -pub const GPUGraphicsPipeline = opaque{}; -pub const GPUCommandBuffer = opaque{}; -pub const GPURenderPass = opaque{}; -pub const GPUComputePass = opaque{}; -pub const GPUCopyPass = opaque{}; -pub const GPUFence = opaque{}; - +pub const Window = c.SDL_Window; pub const GPUTextureUsageFlags = packed struct(u32) { textureusageSampler: bool = false, @@ -24,6 +11,8 @@ pub const GPUTextureUsageFlags = packed struct(u32) { textureusageComputeStorageRead: bool = false, textureusageComputeStorageWrite: bool = false, textureusageComputeStorageSimultaneousReadWrite: bool = false, + pad0: u24 = 0, + rsvd: bool = false, }; pub const GPUBufferUsageFlags = packed struct(u32) { bufferusageVertex: bool = false, @@ -32,12 +21,16 @@ pub const GPUBufferUsageFlags = packed struct(u32) { bufferusageGraphicsStorageRead: bool = false, bufferusageComputeStorageRead: bool = false, bufferusageComputeStorageWrite: bool = false, + pad0: u25 = 0, + rsvd: bool = false, }; pub const GPUColorComponentFlags = packed struct(u8) { colorcomponentR: bool = false, colorcomponentG: bool = false, colorcomponentB: bool = false, colorcomponentA: bool = false, + pad0: u3 = 0, + rsvd: bool = false, }; pub const GPUShaderFormat = packed struct(u32) { shaderformatPrivate: bool = false, @@ -46,35 +39,37 @@ pub const GPUShaderFormat = packed struct(u32) { shaderformatDxil: bool = false, shaderformatMsl: bool = false, shaderformatMetallib: bool = false, + pad0: u25 = 0, + rsvd: bool = false, pub const Invalid: @This() = .{}; }; -pub const GPUPrimitiveType = enum { - primitivetypeTrianglelist, //*< A series of separate triangles. */ +pub const GPUPrimitiveType = enum(c_int) { + primitivetypeTrianglelist, //*< A series of separate triangles. */ primitivetypeTrianglestrip, //*< A series of connected triangles. */ - primitivetypeLinelist, //*< A series of separate lines. */ - primitivetypeLinestrip, //*< A series of connected lines. */ - primitivetypePointlist, //*< A series of separate points. */ + primitivetypeLinelist, //*< A series of separate lines. */ + primitivetypeLinestrip, //*< A series of connected lines. */ + primitivetypePointlist, //*< A series of separate points. */ }; -pub const GPULoadOp = enum { - loadopLoad, //*< The previous contents of the texture will be preserved. */ - loadopClear, //*< The contents of the texture will be cleared to a color. */ - loadopDontCare, //*< The previous contents of the texture need not be preserved. The contents will be undefined. */ +pub const GPULoadOp = enum(c_int) { + loadopLoad, //*< The previous contents of the texture will be preserved. */ + loadopClear, //*< The contents of the texture will be cleared to a color. */ + loadopDontCare, //*< The previous contents of the texture need not be preserved. The contents will be undefined. */ }; -pub const GPUStoreOp = enum { - storeopStore, //*< The contents generated during the render pass will be written to memory. */ - storeopDontCare, //*< The contents generated during the render pass are not needed and may be discarded. The contents will be undefined. */ - storeopResolve, //*< The multisample contents generated during the render pass will be resolved to a non-multisample texture. The contents in the multisample texture may then be discarded and will be undefined. */ - storeopResolveAndStore, //*< The multisample contents generated during the render pass will be resolved to a non-multisample texture. The contents in the multisample texture will be written to memory. */ +pub const GPUStoreOp = enum(c_int) { + storeopStore, //*< The contents generated during the render pass will be written to memory. */ + storeopDontCare, //*< The contents generated during the render pass are not needed and may be discarded. The contents will be undefined. */ + storeopResolve, //*< The multisample contents generated during the render pass will be resolved to a non-multisample texture. The contents in the multisample texture may then be discarded and will be undefined. */ + storeopResolveAndStore, //*< The multisample contents generated during the render pass will be resolved to a non-multisample texture. The contents in the multisample texture will be written to memory. */ }; -pub const GPUIndexElementSize = enum { +pub const GPUIndexElementSize = enum(c_int) { indexelementsize16bit, //*< The index elements are 16-bit. */ - indexelementsize32bit, //*< The index elements are 32-bit. */ + indexelementsize32bit, //*< The index elements are 32-bit. */ }; -pub const GPUTextureFormat = enum { +pub const GPUTextureFormat = enum(c_int) { textureformatInvalid, textureformatA8Unorm, textureformatR8Unorm, @@ -182,22 +177,22 @@ pub const GPUTextureFormat = enum { textureformatAstc12x12Float, }; -pub const GPUTextureType = enum { - texturetype2d, //*< The texture is a 2-dimensional image. */ - texturetype2dArray, //*< The texture is a 2-dimensional array image. */ - texturetype3d, //*< The texture is a 3-dimensional image. */ - texturetypeCube, //*< The texture is a cube image. */ - texturetypeCubeArray, //*< The texture is a cube array image. */ +pub const GPUTextureType = enum(c_int) { + texturetype2d, //*< The texture is a 2-dimensional image. */ + texturetype2dArray, //*< The texture is a 2-dimensional array image. */ + texturetype3d, //*< The texture is a 3-dimensional image. */ + texturetypeCube, //*< The texture is a cube image. */ + texturetypeCubeArray, //*< The texture is a cube array image. */ }; -pub const GPUSampleCount = enum { - samplecount1, //*< No multisampling. */ - samplecount2, //*< MSAA 2x */ - samplecount4, //*< MSAA 4x */ - samplecount8, //*< MSAA 8x */ +pub const GPUSampleCount = enum(c_int) { + samplecount1, //*< No multisampling. */ + samplecount2, //*< MSAA 2x */ + samplecount4, //*< MSAA 4x */ + samplecount8, //*< MSAA 8x */ }; -pub const GPUCubeMapFace = enum { +pub const GPUCubeMapFace = enum(c_int) { cubemapfacePositivex, cubemapfaceNegativex, cubemapfacePositivey, @@ -206,17 +201,17 @@ pub const GPUCubeMapFace = enum { cubemapfaceNegativez, }; -pub const GPUTransferBufferUsage = enum { +pub const GPUTransferBufferUsage = enum(c_int) { transferbufferusageUpload, transferbufferusageDownload, }; -pub const GPUShaderStage = enum { +pub const GPUShaderStage = enum(c_int) { shaderstageVertex, shaderstageFragment, }; -pub const GPUVertexElementFormat = enum { +pub const GPUVertexElementFormat = enum(c_int) { vertexelementformatInvalid, vertexelementformatInt, vertexelementformatInt2, @@ -250,447 +245,949 @@ pub const GPUVertexElementFormat = enum { vertexelementformatHalf4, }; -pub const GPUVertexInputRate = enum { - vertexinputrateVertex, //*< Attribute addressing is a function of the vertex index. */ - vertexinputrateInstance, //*< Attribute addressing is a function of the instance index. */ +pub const GPUVertexInputRate = enum(c_int) { + vertexinputrateVertex, //*< Attribute addressing is a function of the vertex index. */ + vertexinputrateInstance, //*< Attribute addressing is a function of the instance index. */ }; -pub const GPUFillMode = enum { - fillmodeFill, //*< Polygons will be rendered via rasterization. */ - fillmodeLine, //*< Polygon edges will be drawn as line segments. */ +pub const GPUFillMode = enum(c_int) { + fillmodeFill, //*< Polygons will be rendered via rasterization. */ + fillmodeLine, //*< Polygon edges will be drawn as line segments. */ }; -pub const GPUCullMode = enum { - cullmodeNone, //*< No triangles are culled. */ - cullmodeFront, //*< Front-facing triangles are culled. */ - cullmodeBack, //*< Back-facing triangles are culled. */ +pub const GPUCullMode = enum(c_int) { + cullmodeNone, //*< No triangles are culled. */ + cullmodeFront, //*< Front-facing triangles are culled. */ + cullmodeBack, //*< Back-facing triangles are culled. */ }; -pub const GPUFrontFace = enum { - frontfaceCounterClockwise, //*< A triangle with counter-clockwise vertex winding will be considered front-facing. */ - frontfaceClockwise, //*< A triangle with clockwise vertex winding will be considered front-facing. */ +pub const GPUFrontFace = enum(c_int) { + frontfaceCounterClockwise, //*< A triangle with counter-clockwise vertex winding will be considered front-facing. */ + frontfaceClockwise, //*< A triangle with clockwise vertex winding will be considered front-facing. */ }; -pub const GPUCompareOp = enum { +pub const GPUCompareOp = enum(c_int) { compareopInvalid, - compareopNever, //*< The comparison always evaluates false. */ - compareopLess, //*< The comparison evaluates reference < test. */ - compareopEqual, //*< The comparison evaluates reference == test. */ - compareopLessOrEqual, //*< The comparison evaluates reference <= test. */ - compareopGreater, //*< The comparison evaluates reference > test. */ - compareopNotEqual, //*< The comparison evaluates reference != test. */ - compareopGreaterOrEqual, //*< The comparison evalutes reference >= test. */ - compareopAlways, //*< The comparison always evaluates true. */ + compareopNever, //*< The comparison always evaluates false. */ + compareopLess, //*< The comparison evaluates reference < test. */ + compareopEqual, //*< The comparison evaluates reference == test. */ + compareopLessOrEqual, //*< The comparison evaluates reference <= test. */ + compareopGreater, //*< The comparison evaluates reference > test. */ + compareopNotEqual, //*< The comparison evaluates reference != test. */ + compareopGreaterOrEqual, //*< The comparison evalutes reference >= test. */ + compareopAlways, //*< The comparison always evaluates true. */ }; -pub const GPUStencilOp = enum { +pub const GPUStencilOp = enum(c_int) { stencilopInvalid, - stencilopKeep, //*< Keeps the current value. */ - stencilopZero, //*< Sets the value to 0. */ - stencilopReplace, //*< Sets the value to reference. */ - stencilopIncrementAndClamp, //*< Increments the current value and clamps to the maximum value. */ - stencilopDecrementAndClamp, //*< Decrements the current value and clamps to 0. */ - stencilopInvert, //*< Bitwise-inverts the current value. */ - stencilopIncrementAndWrap, //*< Increments the current value and wraps back to 0. */ - stencilopDecrementAndWrap, //*< Decrements the current value and wraps to the maximum value. */ + stencilopKeep, //*< Keeps the current value. */ + stencilopZero, //*< Sets the value to 0. */ + stencilopReplace, //*< Sets the value to reference. */ + stencilopIncrementAndClamp, //*< Increments the current value and clamps to the maximum value. */ + stencilopDecrementAndClamp, //*< Decrements the current value and clamps to 0. */ + stencilopInvert, //*< Bitwise-inverts the current value. */ + stencilopIncrementAndWrap, //*< Increments the current value and wraps back to 0. */ + stencilopDecrementAndWrap, //*< Decrements the current value and wraps to the maximum value. */ }; -pub const GPUBlendOp = enum { +pub const GPUBlendOp = enum(c_int) { blendopInvalid, - blendopAdd, //*< (source * source_factor) + (destination * destination_factor) */ - blendopSubtract, //*< (source * source_factor) - (destination * destination_factor) */ - blendopReverseSubtract, //*< (destination * destination_factor) - (source * source_factor) */ - blendopMin, //*< min(source - blendopMax //*< max(source, destination) */ + blendopAdd, //*< (source * source_factor) + (destination * destination_factor) */ + blendopSubtract, //*< (source * source_factor) - (destination * destination_factor) */ + blendopReverseSubtract, //*< (destination * destination_factor) - (source * source_factor) */ + blendopMin, //*< min(source + blendopMax, //*< max(source, destination) */ }; -pub const GPUBlendFactor = enum { +pub const GPUBlendFactor = enum(c_int) { blendfactorInvalid, - blendfactorZero, //*< 0 */ - blendfactorOne, //*< 1 */ - blendfactorSrcColor, //*< source color */ - blendfactorOneMinusSrcColor, //*< 1 - source color */ - blendfactorDstColor, //*< destination color */ - blendfactorOneMinusDstColor, //*< 1 - destination color */ - blendfactorSrcAlpha, //*< source alpha */ - blendfactorOneMinusSrcAlpha, //*< 1 - source alpha */ - blendfactorDstAlpha, //*< destination alpha */ - blendfactorOneMinusDstAlpha, //*< 1 - destination alpha */ - blendfactorConstantColor, //*< blend constant */ - blendfactorOneMinusConstantColor, //*< 1 - blend constant */ - blendfactorSrcAlphaSaturate //*< min(source alpha, 1 - destination alpha) */ + blendfactorZero, //*< 0 */ + blendfactorOne, //*< 1 */ + blendfactorSrcColor, //*< source color */ + blendfactorOneMinusSrcColor, //*< 1 - source color */ + blendfactorDstColor, //*< destination color */ + blendfactorOneMinusDstColor, //*< 1 - destination color */ + blendfactorSrcAlpha, //*< source alpha */ + blendfactorOneMinusSrcAlpha, //*< 1 - source alpha */ + blendfactorDstAlpha, //*< destination alpha */ + blendfactorOneMinusDstAlpha, //*< 1 - destination alpha */ + blendfactorConstantColor, //*< blend constant */ + blendfactorOneMinusConstantColor, //*< 1 - blend constant */ + blendfactorSrcAlphaSaturate, //*< min(source alpha, 1 - destination alpha) */ }; -pub const GPUFilter = enum { - filterNearest, //*< Point filtering. */ - filterLinear, //*< Linear filtering. */ +pub const GPUFilter = enum(c_int) { + filterNearest, //*< Point filtering. */ + filterLinear, //*< Linear filtering. */ }; -pub const GPUSamplerMipmapMode = enum { - samplermipmapmodeNearest, //*< Point filtering. */ - samplermipmapmodeLinear, //*< Linear filtering. */ +pub const GPUSamplerMipmapMode = enum(c_int) { + samplermipmapmodeNearest, //*< Point filtering. */ + samplermipmapmodeLinear, //*< Linear filtering. */ }; -pub const GPUSamplerAddressMode = enum { - sampleraddressmodeRepeat, //*< Specifies that the coordinates will wrap around. */ - sampleraddressmodeMirroredRepeat, //*< Specifies that the coordinates will wrap around mirrored. */ - sampleraddressmodeClampToEdge, //*< Specifies that the coordinates will clamp to the 0-1 range. */ +pub const GPUSamplerAddressMode = enum(c_int) { + sampleraddressmodeRepeat, //*< Specifies that the coordinates will wrap around. */ + sampleraddressmodeMirroredRepeat, //*< Specifies that the coordinates will wrap around mirrored. */ + sampleraddressmodeClampToEdge, //*< Specifies that the coordinates will clamp to the 0-1 range. */ }; -pub const GPUPresentMode = enum { +pub const GPUPresentMode = enum(c_int) { presentmodeVsync, presentmodeImmediate, presentmodeMailbox, }; -pub const GPUSwapchainComposition = enum { +pub const GPUSwapchainComposition = enum(c_int) { swapchaincompositionSdr, swapchaincompositionSdrLinear, swapchaincompositionHdrExtendedLinear, swapchaincompositionHdr10St2084, }; -pub const FlipMode = enum { - sdlFlipNone, //*< Do not flip */ - sdlFlipHorizontal, //*< flip horizontally */ - sdlFlipVertical, //*< flip vertically */ +pub const FlipMode = enum(c_int) { + sdlFlipNone, //*< Do not flip */ + sdlFlipHorizontal, //*< flip horizontally */ + sdlFlipVertical, //*< flip vertically */ }; pub const GPUViewport = extern struct { - x: f32, // The left offset of the viewport. - y: f32, // The top offset of the viewport. - w: f32, // The width of the viewport. - h: f32, // The height of the viewport. - min_depth: f32, // The minimum depth of the viewport. - max_depth: f32, // The maximum depth of the viewport. + x: f32, // The left offset of the viewport. + y: f32, // The top offset of the viewport. + w: f32, // The width of the viewport. + h: f32, // The height of the viewport. + min_depth: f32, // The minimum depth of the viewport. + max_depth: f32, // The maximum depth of the viewport. }; pub const GPUTextureTransferInfo = extern struct { - transfer_buffer: *GPUTransferBuffer, // The transfer buffer used in the transfer operation. - offset: u32, // The starting byte of the image data in the transfer buffer. - pixels_per_row: u32, // The number of pixels from one row to the next. - rows_per_layer: u32, // The number of rows from one layer/depth-slice to the next. + transfer_buffer: *GPUTransferBuffer, // The transfer buffer used in the transfer operation. + offset: u32, // The starting byte of the image data in the transfer buffer. + pixels_per_row: u32, // The number of pixels from one row to the next. + rows_per_layer: u32, // The number of rows from one layer/depth-slice to the next. }; pub const GPUTransferBufferLocation = extern struct { - transfer_buffer: *GPUTransferBuffer, // The transfer buffer used in the transfer operation. - offset: u32, // The starting byte of the buffer data in the transfer buffer. + transfer_buffer: *GPUTransferBuffer, // The transfer buffer used in the transfer operation. + offset: u32, // The starting byte of the buffer data in the transfer buffer. }; pub const GPUTextureLocation = extern struct { - texture: *GPUTexture, // The texture used in the copy operation. - mip_level: u32, // The mip level index of the location. - layer: u32, // The layer index of the location. - x: u32, // The left offset of the location. - y: u32, // The top offset of the location. - z: u32, // The front offset of the location. + texture: *GPUTexture, // The texture used in the copy operation. + mip_level: u32, // The mip level index of the location. + layer: u32, // The layer index of the location. + x: u32, // The left offset of the location. + y: u32, // The top offset of the location. + z: u32, // The front offset of the location. }; pub const GPUTextureRegion = extern struct { - texture: *GPUTexture, // The texture used in the copy operation. - mip_level: u32, // The mip level index to transfer. - layer: u32, // The layer index to transfer. - x: u32, // The left offset of the region. - y: u32, // The top offset of the region. - z: u32, // The front offset of the region. - w: u32, // The width of the region. - h: u32, // The height of the region. - d: u32, // The depth of the region. + texture: *GPUTexture, // The texture used in the copy operation. + mip_level: u32, // The mip level index to transfer. + layer: u32, // The layer index to transfer. + x: u32, // The left offset of the region. + y: u32, // The top offset of the region. + z: u32, // The front offset of the region. + w: u32, // The width of the region. + h: u32, // The height of the region. + d: u32, // The depth of the region. }; pub const GPUBlitRegion = extern struct { - texture: *GPUTexture, // The texture. - mip_level: u32, // The mip level index of the region. - layer_or_depth_plane: u32, // The layer index or depth plane of the region. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures. - x: u32, // The left offset of the region. - y: u32, // The top offset of the region. - w: u32, // The width of the region. - h: u32, // The height of the region. + texture: *GPUTexture, // The texture. + mip_level: u32, // The mip level index of the region. + layer_or_depth_plane: u32, // The layer index or depth plane of the region. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures. + x: u32, // The left offset of the region. + y: u32, // The top offset of the region. + w: u32, // The width of the region. + h: u32, // The height of the region. }; pub const GPUBufferLocation = extern struct { - buffer: *GPUBuffer, // The buffer. - offset: u32, // The starting byte within the buffer. + buffer: *GPUBuffer, // The buffer. + offset: u32, // The starting byte within the buffer. }; pub const GPUBufferRegion = extern struct { - buffer: *GPUBuffer, // The buffer. - offset: u32, // The starting byte within the buffer. - size: u32, // The size in bytes of the region. + buffer: *GPUBuffer, // The buffer. + offset: u32, // The starting byte within the buffer. + size: u32, // The size in bytes of the region. }; pub const GPUIndirectDrawCommand = extern struct { - num_vertices: u32, // The number of vertices to draw. - num_instances: u32, // The number of instances to draw. - first_vertex: u32, // The index of the first vertex to draw. - first_instance: u32, // The ID of the first instance to draw. + num_vertices: u32, // The number of vertices to draw. + num_instances: u32, // The number of instances to draw. + first_vertex: u32, // The index of the first vertex to draw. + first_instance: u32, // The ID of the first instance to draw. }; pub const GPUIndexedIndirectDrawCommand = extern struct { - num_indices: u32, // The number of indices to draw per instance. - num_instances: u32, // The number of instances to draw. - first_index: u32, // The base index within the index buffer. - vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer. - first_instance: u32, // The ID of the first instance to draw. + num_indices: u32, // The number of indices to draw per instance. + num_instances: u32, // The number of instances to draw. + first_index: u32, // The base index within the index buffer. + vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer. + first_instance: u32, // The ID of the first instance to draw. }; pub const GPUIndirectDispatchCommand = extern struct { - groupcount_x: u32, // The number of local workgroups to dispatch in the X dimension. - groupcount_y: u32, // The number of local workgroups to dispatch in the Y dimension. - groupcount_z: u32, // The number of local workgroups to dispatch in the Z dimension. + groupcount_x: u32, // The number of local workgroups to dispatch in the X dimension. + groupcount_y: u32, // The number of local workgroups to dispatch in the Y dimension. + groupcount_z: u32, // The number of local workgroups to dispatch in the Z dimension. }; pub const GPUSamplerCreateInfo = extern struct { - min_filter: GPUFilter, // The minification filter to apply to lookups. - mag_filter: GPUFilter, // The magnification filter to apply to lookups. - mipmap_mode: GPUSamplerMipmapMode, // The mipmap filter to apply to lookups. - address_mode_u: GPUSamplerAddressMode, // The addressing mode for U coordinates outside [0, 1). - address_mode_v: GPUSamplerAddressMode, // The addressing mode for V coordinates outside [0, 1). - address_mode_w: GPUSamplerAddressMode, // The addressing mode for W coordinates outside [0, 1). - mip_lod_bias: f32, // The bias to be added to mipmap LOD calculation. - max_anisotropy: f32, // The anisotropy value clamp used by the sampler. If enable_anisotropy is false, this is ignored. - compare_op: GPUCompareOp, // The comparison operator to apply to fetched data before filtering. - min_lod: f32, // Clamps the minimum of the computed LOD value. - max_lod: f32, // Clamps the maximum of the computed LOD value. - enable_anisotropy: bool, // true to enable anisotropic filtering. - enable_compare: bool, // true to enable comparison against a reference value during lookups. - padding1: u8, - padding2: u8, - props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. + min_filter: GPUFilter, // The minification filter to apply to lookups. + mag_filter: GPUFilter, // The magnification filter to apply to lookups. + mipmap_mode: GPUSamplerMipmapMode, // The mipmap filter to apply to lookups. + address_mode_u: GPUSamplerAddressMode, // The addressing mode for U coordinates outside [0, 1). + address_mode_v: GPUSamplerAddressMode, // The addressing mode for V coordinates outside [0, 1). + address_mode_w: GPUSamplerAddressMode, // The addressing mode for W coordinates outside [0, 1). + mip_lod_bias: f32, // The bias to be added to mipmap LOD calculation. + max_anisotropy: f32, // The anisotropy value clamp used by the sampler. If enable_anisotropy is false, this is ignored. + compare_op: GPUCompareOp, // The comparison operator to apply to fetched data before filtering. + min_lod: f32, // Clamps the minimum of the computed LOD value. + max_lod: f32, // Clamps the maximum of the computed LOD value. + enable_anisotropy: bool, // true to enable anisotropic filtering. + enable_compare: bool, // true to enable comparison against a reference value during lookups. + padding1: u8, + padding2: u8, + props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. }; pub const GPUVertexBufferDescription = extern struct { - slot: u32, // The binding slot of the vertex buffer. - pitch: u32, // The byte pitch between consecutive elements of the vertex buffer. - input_rate: GPUVertexInputRate, // Whether attribute addressing is a function of the vertex index or instance index. - instance_step_rate: u32, // Reserved for future use. Must be set to 0. + slot: u32, // The binding slot of the vertex buffer. + pitch: u32, // The byte pitch between consecutive elements of the vertex buffer. + input_rate: GPUVertexInputRate, // Whether attribute addressing is a function of the vertex index or instance index. + instance_step_rate: u32, // Reserved for future use. Must be set to 0. }; pub const GPUVertexAttribute = extern struct { - location: u32, // The shader input location index. - buffer_slot: u32, // The binding slot of the associated vertex buffer. - format: GPUVertexElementFormat, // The size and type of the attribute data. - offset: u32, // The byte offset of this attribute relative to the start of the vertex element. + location: u32, // The shader input location index. + buffer_slot: u32, // The binding slot of the associated vertex buffer. + format: GPUVertexElementFormat, // The size and type of the attribute data. + offset: u32, // The byte offset of this attribute relative to the start of the vertex element. }; pub const GPUVertexInputState = extern struct { - vertex_buffer_descriptions: *const GPUVertexBufferDescription, // A pointer to an array of vertex buffer descriptions. - num_vertex_buffers: u32, // The number of vertex buffer descriptions in the above array. - vertex_attributes: *const GPUVertexAttribute, // A pointer to an array of vertex attribute descriptions. - num_vertex_attributes: u32, // The number of vertex attribute descriptions in the above array. + vertex_buffer_descriptions: [*c]const GPUVertexBufferDescription, // A pointer to an array of vertex buffer descriptions. + num_vertex_buffers: u32, // The number of vertex buffer descriptions in the above array. + vertex_attributes: [*c]const GPUVertexAttribute, // A pointer to an array of vertex attribute descriptions. + num_vertex_attributes: u32, // The number of vertex attribute descriptions in the above array. }; pub const GPUStencilOpState = extern struct { - fail_op: GPUStencilOp, // The action performed on samples that fail the stencil test. - pass_op: GPUStencilOp, // The action performed on samples that pass the depth and stencil tests. - depth_fail_op: GPUStencilOp, // The action performed on samples that pass the stencil test and fail the depth test. - compare_op: GPUCompareOp, // The comparison operator used in the stencil test. + fail_op: GPUStencilOp, // The action performed on samples that fail the stencil test. + pass_op: GPUStencilOp, // The action performed on samples that pass the depth and stencil tests. + depth_fail_op: GPUStencilOp, // The action performed on samples that pass the stencil test and fail the depth test. + compare_op: GPUCompareOp, // The comparison operator used in the stencil test. }; pub const GPUColorTargetBlendState = extern struct { - src_color_blendfactor: GPUBlendFactor, // The value to be multiplied by the source RGB value. - dst_color_blendfactor: GPUBlendFactor, // The value to be multiplied by the destination RGB value. - color_blend_op: GPUBlendOp, // The blend operation for the RGB components. - src_alpha_blendfactor: GPUBlendFactor, // The value to be multiplied by the source alpha. - dst_alpha_blendfactor: GPUBlendFactor, // The value to be multiplied by the destination alpha. - alpha_blend_op: GPUBlendOp, // The blend operation for the alpha component. - color_write_mask: GPUColorComponentFlags, // A bitmask specifying which of the RGBA components are enabled for writing. Writes to all channels if enable_color_write_mask is false. - enable_blend: bool, // Whether blending is enabled for the color target. - enable_color_write_mask: bool, // Whether the color write mask is enabled. - padding1: u8, - padding2: u8, + src_color_blendfactor: GPUBlendFactor, // The value to be multiplied by the source RGB value. + dst_color_blendfactor: GPUBlendFactor, // The value to be multiplied by the destination RGB value. + color_blend_op: GPUBlendOp, // The blend operation for the RGB components. + src_alpha_blendfactor: GPUBlendFactor, // The value to be multiplied by the source alpha. + dst_alpha_blendfactor: GPUBlendFactor, // The value to be multiplied by the destination alpha. + alpha_blend_op: GPUBlendOp, // The blend operation for the alpha component. + color_write_mask: GPUColorComponentFlags, // A bitmask specifying which of the RGBA components are enabled for writing. Writes to all channels if enable_color_write_mask is false. + enable_blend: bool, // Whether blending is enabled for the color target. + enable_color_write_mask: bool, // Whether the color write mask is enabled. + padding1: u8, + padding2: u8, }; pub const GPUShaderCreateInfo = extern struct { - code_size: usize, // The size in bytes of the code pointed to. - code: *const u8, // A pointer to shader code. - entrypoint: *const i8, // A pointer to a null-terminated UTF-8 string specifying the entry point function name for the shader. - format: GPUShaderFormat, // The format of the shader code. - stage: GPUShaderStage, // The stage the shader program corresponds to. - num_samplers: u32, // The number of samplers defined in the shader. - num_storage_textures: u32, // The number of storage textures defined in the shader. - num_storage_buffers: u32, // The number of storage buffers defined in the shader. - num_uniform_buffers: u32, // The number of uniform buffers defined in the shader. - props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. + code_size: usize, // The size in bytes of the code pointed to. + code: [*c]const u8, // A pointer to shader code. + entrypoint: [*c]const u8, // A pointer to a null-terminated UTF-8 string specifying the entry point function name for the shader. + format: GPUShaderFormat, // The format of the shader code. + stage: GPUShaderStage, // The stage the shader program corresponds to. + num_samplers: u32, // The number of samplers defined in the shader. + num_storage_textures: u32, // The number of storage textures defined in the shader. + num_storage_buffers: u32, // The number of storage buffers defined in the shader. + num_uniform_buffers: u32, // The number of uniform buffers defined in the shader. + props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. }; pub const GPUTextureCreateInfo = extern struct { - type: GPUTextureType, // The base dimensionality of the texture. - format: GPUTextureFormat, // The pixel format of the texture. - usage: GPUTextureUsageFlags, // How the texture is intended to be used by the client. - width: u32, // The width of the texture. - height: u32, // The height of the texture. - layer_count_or_depth: u32, // The layer count or depth of the texture. This value is treated as a layer count on 2D array textures, and as a depth value on 3D textures. - num_levels: u32, // The number of mip levels in the texture. - sample_count: GPUSampleCount, // The number of samples per texel. Only applies if the texture is used as a render target. - props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. + type: GPUTextureType, // The base dimensionality of the texture. + format: GPUTextureFormat, // The pixel format of the texture. + usage: GPUTextureUsageFlags, // How the texture is intended to be used by the client. + width: u32, // The width of the texture. + height: u32, // The height of the texture. + layer_count_or_depth: u32, // The layer count or depth of the texture. This value is treated as a layer count on 2D array textures, and as a depth value on 3D textures. + num_levels: u32, // The number of mip levels in the texture. + sample_count: GPUSampleCount, // The number of samples per texel. Only applies if the texture is used as a render target. + props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. }; pub const GPUBufferCreateInfo = extern struct { - usage: GPUBufferUsageFlags, // How the buffer is intended to be used by the client. - size: u32, // The size in bytes of the buffer. - props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. + usage: GPUBufferUsageFlags, // How the buffer is intended to be used by the client. + size: u32, // The size in bytes of the buffer. + props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. }; pub const GPUTransferBufferCreateInfo = extern struct { - usage: GPUTransferBufferUsage, // How the transfer buffer is intended to be used by the client. - size: u32, // The size in bytes of the transfer buffer. - props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. + usage: GPUTransferBufferUsage, // How the transfer buffer is intended to be used by the client. + size: u32, // The size in bytes of the transfer buffer. + props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. }; pub const GPURasterizerState = extern struct { - fill_mode: GPUFillMode, // Whether polygons will be filled in or drawn as lines. - cull_mode: GPUCullMode, // The facing direction in which triangles will be culled. - front_face: GPUFrontFace, // The vertex winding that will cause a triangle to be determined as front-facing. - depth_bias_constant_factor: f32, // A scalar factor controlling the depth value added to each fragment. - depth_bias_clamp: f32, // The maximum depth bias of a fragment. - depth_bias_slope_factor: f32, // A scalar factor applied to a fragment's slope in depth calculations. - enable_depth_bias: bool, // true to bias fragment depth values. - enable_depth_clip: bool, // true to enable depth clip, false to enable depth clamp. - padding1: u8, - padding2: u8, + fill_mode: GPUFillMode, // Whether polygons will be filled in or drawn as lines. + cull_mode: GPUCullMode, // The facing direction in which triangles will be culled. + front_face: GPUFrontFace, // The vertex winding that will cause a triangle to be determined as front-facing. + depth_bias_constant_factor: f32, // A scalar factor controlling the depth value added to each fragment. + depth_bias_clamp: f32, // The maximum depth bias of a fragment. + depth_bias_slope_factor: f32, // A scalar factor applied to a fragment's slope in depth calculations. + enable_depth_bias: bool, // true to bias fragment depth values. + enable_depth_clip: bool, // true to enable depth clip, false to enable depth clamp. + padding1: u8, + padding2: u8, }; pub const GPUMultisampleState = extern struct { - sample_count: GPUSampleCount, // The number of samples to be used in rasterization. - sample_mask: u32, // Reserved for future use. Must be set to 0. - enable_mask: bool, // Reserved for future use. Must be set to false. - padding1: u8, - padding2: u8, - padding3: u8, + sample_count: GPUSampleCount, // The number of samples to be used in rasterization. + sample_mask: u32, // Reserved for future use. Must be set to 0. + enable_mask: bool, // Reserved for future use. Must be set to false. + padding1: u8, + padding2: u8, + padding3: u8, }; pub const GPUDepthStencilState = extern struct { - compare_op: GPUCompareOp, // The comparison operator used for depth testing. - back_stencil_state: GPUStencilOpState, // The stencil op state for back-facing triangles. - front_stencil_state: GPUStencilOpState, // The stencil op state for front-facing triangles. - compare_mask: u8, // Selects the bits of the stencil values participating in the stencil test. - write_mask: u8, // Selects the bits of the stencil values updated by the stencil test. - enable_depth_test: bool, // true enables the depth test. - enable_depth_write: bool, // true enables depth writes. Depth writes are always disabled when enable_depth_test is false. - enable_stencil_test: bool, // true enables the stencil test. - padding1: u8, - padding2: u8, - padding3: u8, + compare_op: GPUCompareOp, // The comparison operator used for depth testing. + back_stencil_state: GPUStencilOpState, // The stencil op state for back-facing triangles. + front_stencil_state: GPUStencilOpState, // The stencil op state for front-facing triangles. + compare_mask: u8, // Selects the bits of the stencil values participating in the stencil test. + write_mask: u8, // Selects the bits of the stencil values updated by the stencil test. + enable_depth_test: bool, // true enables the depth test. + enable_depth_write: bool, // true enables depth writes. Depth writes are always disabled when enable_depth_test is false. + enable_stencil_test: bool, // true enables the stencil test. + padding1: u8, + padding2: u8, + padding3: u8, }; pub const GPUColorTargetDescription = extern struct { - format: GPUTextureFormat, // The pixel format of the texture to be used as a color target. - blend_state: GPUColorTargetBlendState, // The blend state to be used for the color target. + format: GPUTextureFormat, // The pixel format of the texture to be used as a color target. + blend_state: GPUColorTargetBlendState, // The blend state to be used for the color target. }; pub const GPUGraphicsPipelineTargetInfo = extern struct { - color_target_descriptions: *const GPUColorTargetDescription, // A pointer to an array of color target descriptions. - num_color_targets: u32, // The number of color target descriptions in the above array. - depth_stencil_format: GPUTextureFormat, // The pixel format of the depth-stencil target. Ignored if has_depth_stencil_target is false. - has_depth_stencil_target: bool, // true specifies that the pipeline uses a depth-stencil target. - padding1: u8, - padding2: u8, - padding3: u8, + color_target_descriptions: [*c]const GPUColorTargetDescription, // A pointer to an array of color target descriptions. + num_color_targets: u32, // The number of color target descriptions in the above array. + depth_stencil_format: GPUTextureFormat, // The pixel format of the depth-stencil target. Ignored if has_depth_stencil_target is false. + has_depth_stencil_target: bool, // true specifies that the pipeline uses a depth-stencil target. + padding1: u8, + padding2: u8, + padding3: u8, }; pub const GPUGraphicsPipelineCreateInfo = extern struct { - vertex_shader: *GPUShader, // The vertex shader used by the graphics pipeline. - fragment_shader: *GPUShader, // The fragment shader used by the graphics pipeline. - vertex_input_state: GPUVertexInputState, // The vertex layout of the graphics pipeline. - primitive_type: GPUPrimitiveType, // The primitive topology of the graphics pipeline. - rasterizer_state: GPURasterizerState, // The rasterizer state of the graphics pipeline. - multisample_state: GPUMultisampleState, // The multisample state of the graphics pipeline. - depth_stencil_state: GPUDepthStencilState, // The depth-stencil state of the graphics pipeline. - target_info: GPUGraphicsPipelineTargetInfo, // Formats and blend modes for the render targets of the graphics pipeline. - props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. + vertex_shader: *GPUShader, // The vertex shader used by the graphics pipeline. + fragment_shader: *GPUShader, // The fragment shader used by the graphics pipeline. + vertex_input_state: GPUVertexInputState, // The vertex layout of the graphics pipeline. + primitive_type: GPUPrimitiveType, // The primitive topology of the graphics pipeline. + rasterizer_state: GPURasterizerState, // The rasterizer state of the graphics pipeline. + multisample_state: GPUMultisampleState, // The multisample state of the graphics pipeline. + depth_stencil_state: GPUDepthStencilState, // The depth-stencil state of the graphics pipeline. + target_info: GPUGraphicsPipelineTargetInfo, // Formats and blend modes for the render targets of the graphics pipeline. + props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. }; pub const GPUComputePipelineCreateInfo = extern struct { - code_size: usize, // The size in bytes of the compute shader code pointed to. - code: *const u8, // A pointer to compute shader code. - entrypoint: *const i8, // A pointer to a null-terminated UTF-8 string specifying the entry point function name for the shader. - format: GPUShaderFormat, // The format of the compute shader code. - num_samplers: u32, // The number of samplers defined in the shader. - num_readonly_storage_textures: u32, // The number of readonly storage textures defined in the shader. - num_readonly_storage_buffers: u32, // The number of readonly storage buffers defined in the shader. - num_readwrite_storage_textures: u32, // The number of read-write storage textures defined in the shader. - num_readwrite_storage_buffers: u32, // The number of read-write storage buffers defined in the shader. - num_uniform_buffers: u32, // The number of uniform buffers defined in the shader. - threadcount_x: u32, // The number of threads in the X dimension. This should match the value in the shader. - threadcount_y: u32, // The number of threads in the Y dimension. This should match the value in the shader. - threadcount_z: u32, // The number of threads in the Z dimension. This should match the value in the shader. - props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. + code_size: usize, // The size in bytes of the compute shader code pointed to. + code: [*c]const u8, // A pointer to compute shader code. + entrypoint: [*c]const u8, // A pointer to a null-terminated UTF-8 string specifying the entry point function name for the shader. + format: GPUShaderFormat, // The format of the compute shader code. + num_samplers: u32, // The number of samplers defined in the shader. + num_readonly_storage_textures: u32, // The number of readonly storage textures defined in the shader. + num_readonly_storage_buffers: u32, // The number of readonly storage buffers defined in the shader. + num_readwrite_storage_textures: u32, // The number of read-write storage textures defined in the shader. + num_readwrite_storage_buffers: u32, // The number of read-write storage buffers defined in the shader. + num_uniform_buffers: u32, // The number of uniform buffers defined in the shader. + threadcount_x: u32, // The number of threads in the X dimension. This should match the value in the shader. + threadcount_y: u32, // The number of threads in the Y dimension. This should match the value in the shader. + threadcount_z: u32, // The number of threads in the Z dimension. This should match the value in the shader. + props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed. }; pub const GPUColorTargetInfo = extern struct { - texture: *GPUTexture, // The texture that will be used as a color target by a render pass. - mip_level: u32, // The mip level to use as a color target. - layer_or_depth_plane: u32, // The layer index or depth plane to use as a color target. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures. - clear_color: FColor, // The color to clear the color target to at the start of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used. - load_op: GPULoadOp, // What is done with the contents of the color target at the beginning of the render pass. - store_op: GPUStoreOp, // What is done with the results of the render pass. - resolve_texture: *GPUTexture, // The texture that will receive the results of a multisample resolve operation. Ignored if a RESOLVE* store_op is not used. - resolve_mip_level: u32, // The mip level of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used. - resolve_layer: u32, // The layer index of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used. - cycle: bool, // true cycles the texture if the texture is bound and load_op is not LOAD - cycle_resolve_texture: bool, // true cycles the resolve texture if the resolve texture is bound. Ignored if a RESOLVE* store_op is not used. - padding1: u8, - padding2: u8, + texture: *GPUTexture, // The texture that will be used as a color target by a render pass. + mip_level: u32, // The mip level to use as a color target. + layer_or_depth_plane: u32, // The layer index or depth plane to use as a color target. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures. + clear_color: FColor, // The color to clear the color target to at the start of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used. + load_op: GPULoadOp, // What is done with the contents of the color target at the beginning of the render pass. + store_op: GPUStoreOp, // What is done with the results of the render pass. + resolve_texture: *GPUTexture, // The texture that will receive the results of a multisample resolve operation. Ignored if a RESOLVE* store_op is not used. + resolve_mip_level: u32, // The mip level of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used. + resolve_layer: u32, // The layer index of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used. + cycle: bool, // true cycles the texture if the texture is bound and load_op is not LOAD + cycle_resolve_texture: bool, // true cycles the resolve texture if the resolve texture is bound. Ignored if a RESOLVE* store_op is not used. + padding1: u8, + padding2: u8, }; pub const GPUDepthStencilTargetInfo = extern struct { - texture: *GPUTexture, // The texture that will be used as the depth stencil target by the render pass. - clear_depth: f32, // The value to clear the depth component to at the beginning of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used. - load_op: GPULoadOp, // What is done with the depth contents at the beginning of the render pass. - store_op: GPUStoreOp, // What is done with the depth results of the render pass. - stencil_load_op: GPULoadOp, // What is done with the stencil contents at the beginning of the render pass. - stencil_store_op: GPUStoreOp, // What is done with the stencil results of the render pass. - cycle: bool, // true cycles the texture if the texture is bound and any load ops are not LOAD - clear_stencil: u8, // The value to clear the stencil component to at the beginning of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used. - padding1: u8, - padding2: u8, + texture: *GPUTexture, // The texture that will be used as the depth stencil target by the render pass. + clear_depth: f32, // The value to clear the depth component to at the beginning of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used. + load_op: GPULoadOp, // What is done with the depth contents at the beginning of the render pass. + store_op: GPUStoreOp, // What is done with the depth results of the render pass. + stencil_load_op: GPULoadOp, // What is done with the stencil contents at the beginning of the render pass. + stencil_store_op: GPUStoreOp, // What is done with the stencil results of the render pass. + cycle: bool, // true cycles the texture if the texture is bound and any load ops are not LOAD + clear_stencil: u8, // The value to clear the stencil component to at the beginning of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used. + padding1: u8, + padding2: u8, }; pub const GPUBlitInfo = extern struct { - destination: GPUBlitRegion, // The destination region for the blit. - load_op: GPULoadOp, // What is done with the contents of the destination before the blit. - clear_color: FColor, // The color to clear the destination region to before the blit. Ignored if load_op is not SDL_GPU_LOADOP_CLEAR. - flip_mode: FlipMode, // The flip mode for the source region. - filter: GPUFilter, // The filter mode used when blitting. - cycle: bool, // true cycles the destination texture if it is already bound. - padding1: u8, - padding2: u8, - padding3: u8, + destination: GPUBlitRegion, // The destination region for the blit. + load_op: GPULoadOp, // What is done with the contents of the destination before the blit. + clear_color: FColor, // The color to clear the destination region to before the blit. Ignored if load_op is not SDL_GPU_LOADOP_CLEAR. + flip_mode: FlipMode, // The flip mode for the source region. + filter: GPUFilter, // The filter mode used when blitting. + cycle: bool, // true cycles the destination texture if it is already bound. + padding1: u8, + padding2: u8, + padding3: u8, }; pub const GPUBufferBinding = extern struct { - buffer: *GPUBuffer, // The buffer to bind. Must have been created with SDL_GPU_BUFFERUSAGE_VERTEX for SDL_BindGPUVertexBuffers, or SDL_GPU_BUFFERUSAGE_INDEX for SDL_BindGPUIndexBuffer. - offset: u32, // The starting byte of the data to bind in the buffer. + buffer: *GPUBuffer, // The buffer to bind. Must have been created with SDL_GPU_BUFFERUSAGE_VERTEX for SDL_BindGPUVertexBuffers, or SDL_GPU_BUFFERUSAGE_INDEX for SDL_BindGPUIndexBuffer. + offset: u32, // The starting byte of the data to bind in the buffer. }; pub const GPUTextureSamplerBinding = extern struct { - texture: *GPUTexture, // The texture to bind. Must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER. - sampler: *GPUSampler, // The sampler to bind. + texture: *GPUTexture, // The texture to bind. Must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER. + sampler: *GPUSampler, // The sampler to bind. }; pub const GPUStorageBufferReadWriteBinding = extern struct { - buffer: *GPUBuffer, // The buffer to bind. Must have been created with SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE. - cycle: bool, // true cycles the buffer if it is already bound. - padding1: u8, - padding2: u8, - padding3: u8, + buffer: *GPUBuffer, // The buffer to bind. Must have been created with SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE. + cycle: bool, // true cycles the buffer if it is already bound. + padding1: u8, + padding2: u8, + padding3: u8, }; pub const GPUStorageTextureReadWriteBinding = extern struct { - texture: *GPUTexture, // The texture to bind. Must have been created with SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE or SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE. - mip_level: u32, // The mip level index to bind. - layer: u32, // The layer index to bind. - cycle: bool, // true cycles the texture if it is already bound. - padding1: u8, - padding2: u8, - padding3: u8, + texture: *GPUTexture, // The texture to bind. Must have been created with SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE or SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE. + mip_level: u32, // The mip level index to bind. + layer: u32, // The layer index to bind. + cycle: bool, // true cycles the texture if it is already bound. + padding1: u8, + padding2: u8, + padding3: u8, }; pub const FColor = extern struct { - r: f32, - g: f32, - b: f32, - a: f32, + r: f32, + g: f32, + b: f32, + a: f32, }; +pub const Rect = extern struct { + x: c_int, + y: c_int, + w: c_int, + h: c_int, +}; + +// SDL_GPUSupportsShaderFormats +pub inline fn gpuSupportsShaderFormats(format_flags: GPUShaderFormat, name: [*c]const u8) bool { + return c.SDL_GPUSupportsShaderFormats(@bitCast(format_flags), name); +} + +// SDL_GPUSupportsProperties +pub inline fn gpuSupportsProperties(props: PropertiesID) bool { + return c.SDL_GPUSupportsProperties(@bitCast(props)); +} + +// SDL_CreateGPUDevice +pub inline fn createGPUDevice(format_flags: GPUShaderFormat, debug_mode: bool, name: [*c]const u8) *GPUDevice { + return @ptrCast(c.SDL_CreateGPUDevice(@bitCast(format_flags), debug_mode, name)); +} + +// SDL_CreateGPUDeviceWithProperties +pub inline fn createGPUDeviceWithProperties(props: PropertiesID) *GPUDevice { + return @ptrCast(c.SDL_CreateGPUDeviceWithProperties(@bitCast(props))); +} + +// SDL_GetNumGPUDrivers +pub inline fn getNumGPUDrivers() c_int { + return @bitCast(c.SDL_GetNumGPUDrivers()); +} + +// SDL_GetGPUDriver +pub inline fn getGPUDriver(index: c_int) [*c]const u8 { + return @ptrCast(c.SDL_GetGPUDriver(@bitCast(index))); +} + +// SDL_GPUTextureFormatTexelBlockSize +pub inline fn gpuTextureFormatTexelBlockSize(format: GPUTextureFormat) u32 { + return @bitCast(c.SDL_GPUTextureFormatTexelBlockSize(@bitCast(format))); +} + +// SDL_CalculateGPUTextureFormatSize +pub inline fn calculateGPUTextureFormatSize(format: GPUTextureFormat, width: u32, height: u32, depth_or_layer_count: u32) u32 { + return @bitCast(c.SDL_CalculateGPUTextureFormatSize(@bitCast(format), @bitCast(width), @bitCast(height), @bitCast(depth_or_layer_count))); +} + +pub const GPUDevice = opaque { + // SDL_DestroyGPUDevice + pub inline fn destroyGPUDevice(device: *GPUDevice) void { + c.SDL_DestroyGPUDevice(@ptrCast(device)); + } + + // SDL_GetGPUDeviceDriver + pub inline fn getGPUDeviceDriver(device: *GPUDevice) [*c]const u8 { + return @ptrCast(c.SDL_GetGPUDeviceDriver(@ptrCast(device))); + } + + // SDL_GetGPUShaderFormats + pub inline fn getGPUShaderFormats(device: *GPUDevice) GPUShaderFormat { + return @bitCast(c.SDL_GetGPUShaderFormats(@ptrCast(device))); + } + + // SDL_CreateGPUComputePipeline + pub inline fn createGPUComputePipeline(device: *GPUDevice, createinfo: [*c]const GPUComputePipelineCreateInfo) *GPUComputePipeline { + return @ptrCast(c.SDL_CreateGPUComputePipeline(@ptrCast(device), @ptrCast(createinfo))); + } + + // SDL_CreateGPUGraphicsPipeline + pub inline fn createGPUGraphicsPipeline(device: *GPUDevice, createinfo: [*c]const GPUGraphicsPipelineCreateInfo) *GPUGraphicsPipeline { + return @ptrCast(c.SDL_CreateGPUGraphicsPipeline(@ptrCast(device), @ptrCast(createinfo))); + } + + // SDL_CreateGPUSampler + pub inline fn createGPUSampler(device: *GPUDevice, createinfo: [*c]const GPUSamplerCreateInfo) *GPUSampler { + return @ptrCast(c.SDL_CreateGPUSampler(@ptrCast(device), @ptrCast(createinfo))); + } + + // SDL_CreateGPUShader + pub inline fn createGPUShader(device: *GPUDevice, createinfo: [*c]const GPUShaderCreateInfo) *GPUShader { + return @ptrCast(c.SDL_CreateGPUShader(@ptrCast(device), @ptrCast(createinfo))); + } + + // SDL_CreateGPUTexture + pub inline fn createGPUTexture(device: *GPUDevice, createinfo: [*c]const GPUTextureCreateInfo) *GPUTexture { + return @ptrCast(c.SDL_CreateGPUTexture(@ptrCast(device), @ptrCast(createinfo))); + } + + // SDL_CreateGPUBuffer + pub inline fn createGPUBuffer(device: *GPUDevice, createinfo: [*c]const GPUBufferCreateInfo) *GPUBuffer { + return @ptrCast(c.SDL_CreateGPUBuffer(@ptrCast(device), @ptrCast(createinfo))); + } + + // SDL_CreateGPUTransferBuffer + pub inline fn createGPUTransferBuffer(device: *GPUDevice, createinfo: [*c]const GPUTransferBufferCreateInfo) *GPUTransferBuffer { + return @ptrCast(c.SDL_CreateGPUTransferBuffer(@ptrCast(device), @ptrCast(createinfo))); + } + + // SDL_SetGPUBufferName + pub inline fn setGPUBufferName(device: *GPUDevice, buffer: *GPUBuffer, text: [*c]const u8) void { + c.SDL_SetGPUBufferName(@ptrCast(device), @ptrCast(buffer), text); + } + + // SDL_SetGPUTextureName + pub inline fn setGPUTextureName(device: *GPUDevice, texture: *GPUTexture, text: [*c]const u8) void { + c.SDL_SetGPUTextureName(@ptrCast(device), @ptrCast(texture), text); + } + + // SDL_ReleaseGPUTexture + pub inline fn releaseGPUTexture(device: *GPUDevice, texture: *GPUTexture) void { + c.SDL_ReleaseGPUTexture(@ptrCast(device), @ptrCast(texture)); + } + + // SDL_ReleaseGPUSampler + pub inline fn releaseGPUSampler(device: *GPUDevice, sampler: *GPUSampler) void { + c.SDL_ReleaseGPUSampler(@ptrCast(device), @ptrCast(sampler)); + } + + // SDL_ReleaseGPUBuffer + pub inline fn releaseGPUBuffer(device: *GPUDevice, buffer: *GPUBuffer) void { + c.SDL_ReleaseGPUBuffer(@ptrCast(device), @ptrCast(buffer)); + } + + // SDL_ReleaseGPUTransferBuffer + pub inline fn releaseGPUTransferBuffer(device: *GPUDevice, transfer_buffer: *GPUTransferBuffer) void { + c.SDL_ReleaseGPUTransferBuffer(@ptrCast(device), @ptrCast(transfer_buffer)); + } + + // SDL_ReleaseGPUComputePipeline + pub inline fn releaseGPUComputePipeline(device: *GPUDevice, compute_pipeline: *GPUComputePipeline) void { + c.SDL_ReleaseGPUComputePipeline(@ptrCast(device), @ptrCast(compute_pipeline)); + } + + // SDL_ReleaseGPUShader + pub inline fn releaseGPUShader(device: *GPUDevice, shader: *GPUShader) void { + c.SDL_ReleaseGPUShader(@ptrCast(device), @ptrCast(shader)); + } + + // SDL_ReleaseGPUGraphicsPipeline + pub inline fn releaseGPUGraphicsPipeline(device: *GPUDevice, graphics_pipeline: *GPUGraphicsPipeline) void { + c.SDL_ReleaseGPUGraphicsPipeline(@ptrCast(device), @ptrCast(graphics_pipeline)); + } + + // SDL_AcquireGPUCommandBuffer + pub inline fn acquireGPUCommandBuffer(device: *GPUDevice) *GPUCommandBuffer { + return @ptrCast(c.SDL_AcquireGPUCommandBuffer(@ptrCast(device))); + } + + // SDL_MapGPUTransferBuffer + pub inline fn mapGPUTransferBuffer(device: *GPUDevice, transfer_buffer: *GPUTransferBuffer, cycle: bool) [*c]void { + return @bitCast(c.SDL_MapGPUTransferBuffer(@ptrCast(device), @ptrCast(transfer_buffer), cycle)); + } + + // SDL_UnmapGPUTransferBuffer + pub inline fn unmapGPUTransferBuffer(device: *GPUDevice, transfer_buffer: *GPUTransferBuffer) void { + c.SDL_UnmapGPUTransferBuffer(@ptrCast(device), @ptrCast(transfer_buffer)); + } + + // SDL_WindowSupportsGPUSwapchainComposition + pub inline fn windowSupportsGPUSwapchainComposition(device: *GPUDevice, window: *Window, swapchain_composition: GPUSwapchainComposition) bool { + return c.SDL_WindowSupportsGPUSwapchainComposition(@ptrCast(device), @ptrCast(window), @bitCast(swapchain_composition)); + } + + // SDL_WindowSupportsGPUPresentMode + pub inline fn windowSupportsGPUPresentMode(device: *GPUDevice, window: *Window, present_mode: GPUPresentMode) bool { + return c.SDL_WindowSupportsGPUPresentMode(@ptrCast(device), @ptrCast(window), @bitCast(present_mode)); + } + + // SDL_ClaimWindowForGPUDevice + pub inline fn claimWindowForGPUDevice(device: *GPUDevice, window: *Window) bool { + return c.SDL_ClaimWindowForGPUDevice(@ptrCast(device), @ptrCast(window)); + } + + // SDL_ReleaseWindowFromGPUDevice + pub inline fn releaseWindowFromGPUDevice(device: *GPUDevice, window: *Window) void { + c.SDL_ReleaseWindowFromGPUDevice(@ptrCast(device), @ptrCast(window)); + } + + // SDL_SetGPUSwapchainParameters + pub inline fn setGPUSwapchainParameters(device: *GPUDevice, window: *Window, swapchain_composition: GPUSwapchainComposition, present_mode: GPUPresentMode) bool { + return c.SDL_SetGPUSwapchainParameters(@ptrCast(device), @ptrCast(window), @bitCast(swapchain_composition), @bitCast(present_mode)); + } + + // SDL_SetGPUAllowedFramesInFlight + pub inline fn setGPUAllowedFramesInFlight(device: *GPUDevice, allowed_frames_in_flight: u32) bool { + return c.SDL_SetGPUAllowedFramesInFlight(@ptrCast(device), @bitCast(allowed_frames_in_flight)); + } + + // SDL_GetGPUSwapchainTextureFormat + pub inline fn getGPUSwapchainTextureFormat(device: *GPUDevice, window: *Window) GPUTextureFormat { + return @enumFromInt(c.SDL_GetGPUSwapchainTextureFormat(@ptrCast(device), @ptrCast(window))); + } + + // SDL_WaitForGPUSwapchain + pub inline fn waitForGPUSwapchain(device: *GPUDevice, window: *Window) bool { + return c.SDL_WaitForGPUSwapchain(@ptrCast(device), @ptrCast(window)); + } + + // SDL_WaitForGPUIdle + pub inline fn waitForGPUIdle(device: *GPUDevice) bool { + return c.SDL_WaitForGPUIdle(@ptrCast(device)); + } + + // SDL_WaitForGPUFences + pub inline fn waitForGPUFences(device: *GPUDevice, wait_all: bool, fences: [*c]*GPUFence, num_fences: u32) bool { + return c.SDL_WaitForGPUFences(@ptrCast(device), wait_all, @ptrCast(fences), @bitCast(num_fences)); + } + + // SDL_QueryGPUFence + pub inline fn queryGPUFence(device: *GPUDevice, fence: *GPUFence) bool { + return c.SDL_QueryGPUFence(@ptrCast(device), @ptrCast(fence)); + } + + // SDL_ReleaseGPUFence + pub inline fn releaseGPUFence(device: *GPUDevice, fence: *GPUFence) void { + c.SDL_ReleaseGPUFence(@ptrCast(device), @ptrCast(fence)); + } + + // SDL_GPUTextureSupportsFormat + pub inline fn gpuTextureSupportsFormat(device: *GPUDevice, format: GPUTextureFormat, _type: GPUTextureType, usage: GPUTextureUsageFlags) bool { + return c.SDL_GPUTextureSupportsFormat(@ptrCast(device), @bitCast(format), @bitCast(_type), @bitCast(usage)); + } + + // SDL_GPUTextureSupportsSampleCount + pub inline fn gpuTextureSupportsSampleCount(device: *GPUDevice, format: GPUTextureFormat, sample_count: GPUSampleCount) bool { + return c.SDL_GPUTextureSupportsSampleCount(@ptrCast(device), @bitCast(format), @bitCast(sample_count)); + } + + // SDL_GDKSuspendGPU + pub inline fn gdkSuspendGPU(device: *GPUDevice) void { + c.SDL_GDKSuspendGPU(@ptrCast(device)); + } + + // SDL_GDKResumeGPU + pub inline fn gdkResumeGPU(device: *GPUDevice) void { + c.SDL_GDKResumeGPU(@ptrCast(device)); + } +}; + +pub const GPUBuffer = opaque {}; + +pub const GPUTransferBuffer = opaque {}; + +pub const GPUTexture = opaque {}; + +pub const GPUSampler = opaque {}; + +pub const GPUShader = opaque {}; + +pub const GPUComputePipeline = opaque {}; + +pub const GPUGraphicsPipeline = opaque {}; + +pub const GPUCommandBuffer = opaque { + // SDL_InsertGPUDebugLabel + pub inline fn insertGPUDebugLabel(command_buffer: *GPUCommandBuffer, text: [*c]const u8) void { + c.SDL_InsertGPUDebugLabel(@ptrCast(command_buffer), text); + } + + // SDL_PushGPUDebugGroup + pub inline fn pushGPUDebugGroup(command_buffer: *GPUCommandBuffer, name: [*c]const u8) void { + c.SDL_PushGPUDebugGroup(@ptrCast(command_buffer), name); + } + + // SDL_PopGPUDebugGroup + pub inline fn popGPUDebugGroup(command_buffer: *GPUCommandBuffer) void { + c.SDL_PopGPUDebugGroup(@ptrCast(command_buffer)); + } + + // SDL_PushGPUVertexUniformData + pub inline fn pushGPUVertexUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: [*c]const void, length: u32) void { + c.SDL_PushGPUVertexUniformData(@ptrCast(command_buffer), @bitCast(slot_index), @ptrCast(data), @bitCast(length)); + } + + // SDL_PushGPUFragmentUniformData + pub inline fn pushGPUFragmentUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: [*c]const void, length: u32) void { + c.SDL_PushGPUFragmentUniformData(@ptrCast(command_buffer), @bitCast(slot_index), @ptrCast(data), @bitCast(length)); + } + + // SDL_PushGPUComputeUniformData + pub inline fn pushGPUComputeUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: [*c]const void, length: u32) void { + c.SDL_PushGPUComputeUniformData(@ptrCast(command_buffer), @bitCast(slot_index), @ptrCast(data), @bitCast(length)); + } + + // SDL_BeginGPURenderPass + pub inline fn beginGPURenderPass(command_buffer: *GPUCommandBuffer, color_target_infos: [*c]const GPUColorTargetInfo, num_color_targets: u32, depth_stencil_target_info: [*c]const GPUDepthStencilTargetInfo) *GPURenderPass { + return @ptrCast(c.SDL_BeginGPURenderPass(@ptrCast(command_buffer), @ptrCast(color_target_infos), @bitCast(num_color_targets), @ptrCast(depth_stencil_target_info))); + } + + // SDL_BeginGPUComputePass + pub inline fn beginGPUComputePass(command_buffer: *GPUCommandBuffer, storage_texture_bindings: [*c]const GPUStorageTextureReadWriteBinding, num_storage_texture_bindings: u32, storage_buffer_bindings: [*c]const GPUStorageBufferReadWriteBinding, num_storage_buffer_bindings: u32) *GPUComputePass { + return @ptrCast(c.SDL_BeginGPUComputePass(@ptrCast(command_buffer), @ptrCast(storage_texture_bindings), @bitCast(num_storage_texture_bindings), @ptrCast(storage_buffer_bindings), @bitCast(num_storage_buffer_bindings))); + } + + // SDL_BeginGPUCopyPass + pub inline fn beginGPUCopyPass(command_buffer: *GPUCommandBuffer) *GPUCopyPass { + return @ptrCast(c.SDL_BeginGPUCopyPass(@ptrCast(command_buffer))); + } + + // SDL_GenerateMipmapsForGPUTexture + pub inline fn generateMipmapsForGPUTexture(command_buffer: *GPUCommandBuffer, texture: *GPUTexture) void { + c.SDL_GenerateMipmapsForGPUTexture(@ptrCast(command_buffer), @ptrCast(texture)); + } + + // SDL_BlitGPUTexture + pub inline fn blitGPUTexture(command_buffer: *GPUCommandBuffer, info: [*c]const GPUBlitInfo) void { + c.SDL_BlitGPUTexture(@ptrCast(command_buffer), @ptrCast(info)); + } + + // SDL_AcquireGPUSwapchainTexture + pub inline fn acquireGPUSwapchainTexture(command_buffer: *GPUCommandBuffer, window: *Window, swapchain_texture: [*c]*GPUTexture, swapchain_texture_width: [*c]u32, swapchain_texture_height: [*c]u32) bool { + return c.SDL_AcquireGPUSwapchainTexture(@ptrCast(command_buffer), @ptrCast(window), @ptrCast(swapchain_texture), @ptrCast(swapchain_texture_width), @ptrCast(swapchain_texture_height)); + } + + // SDL_WaitAndAcquireGPUSwapchainTexture + pub inline fn waitAndAcquireGPUSwapchainTexture(command_buffer: *GPUCommandBuffer, window: *Window, swapchain_texture: [*c]*GPUTexture, swapchain_texture_width: [*c]u32, swapchain_texture_height: [*c]u32) bool { + return c.SDL_WaitAndAcquireGPUSwapchainTexture(@ptrCast(command_buffer), @ptrCast(window), @ptrCast(swapchain_texture), @ptrCast(swapchain_texture_width), @ptrCast(swapchain_texture_height)); + } + + // SDL_SubmitGPUCommandBuffer + pub inline fn submitGPUCommandBuffer(command_buffer: *GPUCommandBuffer) bool { + return c.SDL_SubmitGPUCommandBuffer(@ptrCast(command_buffer)); + } + + // SDL_SubmitGPUCommandBufferAndAcquireFence + pub inline fn submitGPUCommandBufferAndAcquireFence(command_buffer: *GPUCommandBuffer) *GPUFence { + return @ptrCast(c.SDL_SubmitGPUCommandBufferAndAcquireFence(@ptrCast(command_buffer))); + } + + // SDL_CancelGPUCommandBuffer + pub inline fn cancelGPUCommandBuffer(command_buffer: *GPUCommandBuffer) bool { + return c.SDL_CancelGPUCommandBuffer(@ptrCast(command_buffer)); + } +}; + +pub const GPURenderPass = opaque { + // SDL_BindGPUGraphicsPipeline + pub inline fn bindGPUGraphicsPipeline(render_pass: *GPURenderPass, graphics_pipeline: *GPUGraphicsPipeline) void { + c.SDL_BindGPUGraphicsPipeline(@ptrCast(render_pass), @ptrCast(graphics_pipeline)); + } + + // SDL_SetGPUViewport + pub inline fn setGPUViewport(render_pass: *GPURenderPass, viewport: [*c]const GPUViewport) void { + c.SDL_SetGPUViewport(@ptrCast(render_pass), @ptrCast(viewport)); + } + + // SDL_SetGPUScissor + pub inline fn setGPUScissor(render_pass: *GPURenderPass, scissor: [*c]const Rect) void { + c.SDL_SetGPUScissor(@ptrCast(render_pass), @ptrCast(scissor)); + } + + // SDL_SetGPUBlendConstants + pub inline fn setGPUBlendConstants(render_pass: *GPURenderPass, blend_constants: FColor) void { + c.SDL_SetGPUBlendConstants(@ptrCast(render_pass), @bitCast(blend_constants)); + } + + // SDL_SetGPUStencilReference + pub inline fn setGPUStencilReference(render_pass: *GPURenderPass, reference: u8) void { + c.SDL_SetGPUStencilReference(@ptrCast(render_pass), @bitCast(reference)); + } + + // SDL_BindGPUVertexBuffers + pub inline fn bindGPUVertexBuffers(render_pass: *GPURenderPass, first_slot: u32, bindings: [*c]const GPUBufferBinding, num_bindings: u32) void { + c.SDL_BindGPUVertexBuffers(@ptrCast(render_pass), @bitCast(first_slot), @ptrCast(bindings), @bitCast(num_bindings)); + } + + // SDL_BindGPUIndexBuffer + pub inline fn bindGPUIndexBuffer(render_pass: *GPURenderPass, binding: [*c]const GPUBufferBinding, index_element_size: GPUIndexElementSize) void { + c.SDL_BindGPUIndexBuffer(@ptrCast(render_pass), @ptrCast(binding), @bitCast(index_element_size)); + } + + // SDL_BindGPUVertexSamplers + pub inline fn bindGPUVertexSamplers(render_pass: *GPURenderPass, first_slot: u32, texture_sampler_bindings: [*c]const GPUTextureSamplerBinding, num_bindings: u32) void { + c.SDL_BindGPUVertexSamplers(@ptrCast(render_pass), @bitCast(first_slot), @ptrCast(texture_sampler_bindings), @bitCast(num_bindings)); + } + + // SDL_BindGPUVertexStorageTextures + pub inline fn bindGPUVertexStorageTextures(render_pass: *GPURenderPass, first_slot: u32, storage_textures: [*c]*GPUTexture, num_bindings: u32) void { + c.SDL_BindGPUVertexStorageTextures(@ptrCast(render_pass), @bitCast(first_slot), @ptrCast(storage_textures), @bitCast(num_bindings)); + } + + // SDL_BindGPUVertexStorageBuffers + pub inline fn bindGPUVertexStorageBuffers(render_pass: *GPURenderPass, first_slot: u32, storage_buffers: [*c]*GPUBuffer, num_bindings: u32) void { + c.SDL_BindGPUVertexStorageBuffers(@ptrCast(render_pass), @bitCast(first_slot), @ptrCast(storage_buffers), @bitCast(num_bindings)); + } + + // SDL_BindGPUFragmentSamplers + pub inline fn bindGPUFragmentSamplers(render_pass: *GPURenderPass, first_slot: u32, texture_sampler_bindings: [*c]const GPUTextureSamplerBinding, num_bindings: u32) void { + c.SDL_BindGPUFragmentSamplers(@ptrCast(render_pass), @bitCast(first_slot), @ptrCast(texture_sampler_bindings), @bitCast(num_bindings)); + } + + // SDL_BindGPUFragmentStorageTextures + pub inline fn bindGPUFragmentStorageTextures(render_pass: *GPURenderPass, first_slot: u32, storage_textures: [*c]*GPUTexture, num_bindings: u32) void { + c.SDL_BindGPUFragmentStorageTextures(@ptrCast(render_pass), @bitCast(first_slot), @ptrCast(storage_textures), @bitCast(num_bindings)); + } + + // SDL_BindGPUFragmentStorageBuffers + pub inline fn bindGPUFragmentStorageBuffers(render_pass: *GPURenderPass, first_slot: u32, storage_buffers: [*c]*GPUBuffer, num_bindings: u32) void { + c.SDL_BindGPUFragmentStorageBuffers(@ptrCast(render_pass), @bitCast(first_slot), @ptrCast(storage_buffers), @bitCast(num_bindings)); + } + + // SDL_DrawGPUIndexedPrimitives + pub inline fn drawGPUIndexedPrimitives(render_pass: *GPURenderPass, num_indices: u32, num_instances: u32, first_index: u32, vertex_offset: i32, first_instance: u32) void { + c.SDL_DrawGPUIndexedPrimitives(@ptrCast(render_pass), @bitCast(num_indices), @bitCast(num_instances), @bitCast(first_index), @bitCast(vertex_offset), @bitCast(first_instance)); + } + + // SDL_DrawGPUPrimitives + pub inline fn drawGPUPrimitives(render_pass: *GPURenderPass, num_vertices: u32, num_instances: u32, first_vertex: u32, first_instance: u32) void { + c.SDL_DrawGPUPrimitives(@ptrCast(render_pass), @bitCast(num_vertices), @bitCast(num_instances), @bitCast(first_vertex), @bitCast(first_instance)); + } + + // SDL_DrawGPUPrimitivesIndirect + pub inline fn drawGPUPrimitivesIndirect(render_pass: *GPURenderPass, buffer: *GPUBuffer, offset: u32, draw_count: u32) void { + c.SDL_DrawGPUPrimitivesIndirect(@ptrCast(render_pass), @ptrCast(buffer), @bitCast(offset), @bitCast(draw_count)); + } + + // SDL_DrawGPUIndexedPrimitivesIndirect + pub inline fn drawGPUIndexedPrimitivesIndirect(render_pass: *GPURenderPass, buffer: *GPUBuffer, offset: u32, draw_count: u32) void { + c.SDL_DrawGPUIndexedPrimitivesIndirect(@ptrCast(render_pass), @ptrCast(buffer), @bitCast(offset), @bitCast(draw_count)); + } + + // SDL_EndGPURenderPass + pub inline fn endGPURenderPass(render_pass: *GPURenderPass) void { + c.SDL_EndGPURenderPass(@ptrCast(render_pass)); + } +}; + +pub const GPUComputePass = opaque { + // SDL_BindGPUComputePipeline + pub inline fn bindGPUComputePipeline(compute_pass: *GPUComputePass, compute_pipeline: *GPUComputePipeline) void { + c.SDL_BindGPUComputePipeline(@ptrCast(compute_pass), @ptrCast(compute_pipeline)); + } + + // SDL_BindGPUComputeSamplers + pub inline fn bindGPUComputeSamplers(compute_pass: *GPUComputePass, first_slot: u32, texture_sampler_bindings: [*c]const GPUTextureSamplerBinding, num_bindings: u32) void { + c.SDL_BindGPUComputeSamplers(@ptrCast(compute_pass), @bitCast(first_slot), @ptrCast(texture_sampler_bindings), @bitCast(num_bindings)); + } + + // SDL_BindGPUComputeStorageTextures + pub inline fn bindGPUComputeStorageTextures(compute_pass: *GPUComputePass, first_slot: u32, storage_textures: [*c]*GPUTexture, num_bindings: u32) void { + c.SDL_BindGPUComputeStorageTextures(@ptrCast(compute_pass), @bitCast(first_slot), @ptrCast(storage_textures), @bitCast(num_bindings)); + } + + // SDL_BindGPUComputeStorageBuffers + pub inline fn bindGPUComputeStorageBuffers(compute_pass: *GPUComputePass, first_slot: u32, storage_buffers: [*c]*GPUBuffer, num_bindings: u32) void { + c.SDL_BindGPUComputeStorageBuffers(@ptrCast(compute_pass), @bitCast(first_slot), @ptrCast(storage_buffers), @bitCast(num_bindings)); + } + + // SDL_DispatchGPUCompute + pub inline fn dispatchGPUCompute(compute_pass: *GPUComputePass, groupcount_x: u32, groupcount_y: u32, groupcount_z: u32) void { + c.SDL_DispatchGPUCompute(@ptrCast(compute_pass), @bitCast(groupcount_x), @bitCast(groupcount_y), @bitCast(groupcount_z)); + } + + // SDL_DispatchGPUComputeIndirect + pub inline fn dispatchGPUComputeIndirect(compute_pass: *GPUComputePass, buffer: *GPUBuffer, offset: u32) void { + c.SDL_DispatchGPUComputeIndirect(@ptrCast(compute_pass), @ptrCast(buffer), @bitCast(offset)); + } + + // SDL_EndGPUComputePass + pub inline fn endGPUComputePass(compute_pass: *GPUComputePass) void { + c.SDL_EndGPUComputePass(@ptrCast(compute_pass)); + } +}; + +pub const GPUCopyPass = opaque { + // SDL_UploadToGPUTexture + pub inline fn uploadToGPUTexture(copy_pass: *GPUCopyPass, source: [*c]const GPUTextureTransferInfo, destination: [*c]const GPUTextureRegion, cycle: bool) void { + c.SDL_UploadToGPUTexture(@ptrCast(copy_pass), @ptrCast(source), @ptrCast(destination), cycle); + } + + // SDL_UploadToGPUBuffer + pub inline fn uploadToGPUBuffer(copy_pass: *GPUCopyPass, source: [*c]const GPUTransferBufferLocation, destination: [*c]const GPUBufferRegion, cycle: bool) void { + c.SDL_UploadToGPUBuffer(@ptrCast(copy_pass), @ptrCast(source), @ptrCast(destination), cycle); + } + + // SDL_CopyGPUTextureToTexture + pub inline fn copyGPUTextureToTexture(copy_pass: *GPUCopyPass, source: [*c]const GPUTextureLocation, destination: [*c]const GPUTextureLocation, w: u32, h: u32, d: u32, cycle: bool) void { + c.SDL_CopyGPUTextureToTexture(@ptrCast(copy_pass), @ptrCast(source), @ptrCast(destination), @bitCast(w), @bitCast(h), @bitCast(d), cycle); + } + + // SDL_CopyGPUBufferToBuffer + pub inline fn copyGPUBufferToBuffer(copy_pass: *GPUCopyPass, source: [*c]const GPUBufferLocation, destination: [*c]const GPUBufferLocation, size: u32, cycle: bool) void { + c.SDL_CopyGPUBufferToBuffer(@ptrCast(copy_pass), @ptrCast(source), @ptrCast(destination), @bitCast(size), cycle); + } + + // SDL_DownloadFromGPUTexture + pub inline fn downloadFromGPUTexture(copy_pass: *GPUCopyPass, source: [*c]const GPUTextureRegion, destination: [*c]const GPUTextureTransferInfo) void { + c.SDL_DownloadFromGPUTexture(@ptrCast(copy_pass), @ptrCast(source), @ptrCast(destination)); + } + + // SDL_DownloadFromGPUBuffer + pub inline fn downloadFromGPUBuffer(copy_pass: *GPUCopyPass, source: [*c]const GPUBufferRegion, destination: [*c]const GPUTransferBufferLocation) void { + c.SDL_DownloadFromGPUBuffer(@ptrCast(copy_pass), @ptrCast(source), @ptrCast(destination)); + } + + // SDL_EndGPUCopyPass + pub inline fn endGPUCopyPass(copy_pass: *GPUCopyPass) void { + c.SDL_EndGPUCopyPass(@ptrCast(copy_pass)); + } +}; + +pub const GPUFence = opaque {}; diff --git a/lib/sdl3/src/init.zig b/lib/sdl3/src/init.zig index 9d134d5..e69de29 100644 --- a/lib/sdl3/src/init.zig +++ b/lib/sdl3/src/init.zig @@ -1,39 +0,0 @@ -pub const c = @cImport({ // todo, should not be constant - @cInclude("SDL3/SDL.h"); -}); - -pub const InitOptions = packed struct(c_int) { - pad0: u4 = 0, // 0 - 3 - audio: bool = false, // 4 - video: bool = false, // 5 - pad1: u2 = 0, // 6-7 - pad2: u1 = 0, // 8 - joystick: bool = false, // 9 - pad3: u2 = 0, // 10-11 - haptic: bool = false, // 12 - gamepad: bool = false, - events: bool = false, - sensor: bool = false, - camera: bool = false, - pad4: u3 = 0, - pad5: u12 = 0, -}; - -pub const AppResult = enum{ - app_continue, - app_success, - app_failure, -}; - -pub const Window = opaque {}; - -pub fn createWindow() !*Window { - - return @ptrCast(); -} - -pub fn init(options: InitOptions) !void { - if (!c.SDL_Init(@bitCast(options))) { - return error.InitFailed; - } -} diff --git a/lib/sdl3/src/samples/hello-triangle.zig b/lib/sdl3/src/samples/hello-triangle.zig index c139852..d75d999 100644 --- a/lib/sdl3/src/samples/hello-triangle.zig +++ b/lib/sdl3/src/samples/hello-triangle.zig @@ -4,9 +4,17 @@ timer: std.time.Timer, // fillPipeline: *sdl3.GpuGraphicsPipeline = undefined, // linePipeline: *sdl3.GpuGraphicsPipeline = undefined, // viewport: sdl3.GpuViewport = undefined, -// scissor: sdl3.Rect = undefined, +scissor: gpu.Rect = .{ .x = 0, .y = 0, .w = 640, .h = 480 }, running: bool = true, +window: *sdl3.Window = undefined, +device: *gpu.GPUDevice = undefined, +shaderpath: []const u8 = undefined, +shadersuffix: []const u8 = undefined, +fragment: *gpu.GPUShader = undefined, +vertex: *gpu.GPUShader = undefined, +pipeline: *gpu.GPUGraphicsPipeline = undefined, +shaderformat: gpu.GPUShaderFormat = undefined, pub fn create(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); @@ -24,10 +32,92 @@ pub fn startContext(self: *@This()) !void { .gamepad = true, }); - const window = sdl3.c.SDL_CreateWindow("lmao your mom", 640, 480, 0); - _ = window; + self.window = sdl3.c.SDL_CreateWindow("hello-world", 640, 480, 0).?; + self.device = gpu.createGPUDevice(.{ + .shaderformatSpirv = true, + .shaderformatDxil = true, + .shaderformatMsl = true, + }, false, null); - _ = self; + if (!self.device.claimWindowForGPUDevice(self.window)) + return error.UnableToClaimGpu; + + const formats = self.device.getGPUShaderFormats(); + std.debug.print("SDL Context Loaded: {}\n", .{formats}); + if (formats.shaderformatSpirv) { + self.shaderpath = "./content/_cooked/spv"; // shaderformatSpirv + self.shadersuffix = ".spv"; + self.shaderformat = .{ .shaderformatSpirv = true }; + } else if (formats.shaderformatMsl) { + self.shaderpath = "./content/_cooked/msl"; // shaderformatSpirv + self.shadersuffix = ".msl"; + self.shaderformat = .{ .shaderformatMsl = true }; + } else if (formats.shaderformatDxil) { + self.shaderpath = "./content/_cooked/dxil"; // shaderformatSpirv + self.shadersuffix = ".dxil"; + self.shaderformat = .{ .shaderformatDxil = true }; + } + + self.fragment = try self.loadShader("hello-triangle.frag", .shaderstageFragment, 0, 0, 0, 0); + self.vertex = try self.loadShader("hello-triangle.vert", .shaderstageVertex, 0, 0, 0, 0); + + var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo); + pci.fragment_shader = self.fragment; + pci.vertex_shader = self.vertex; + + pci.target_info.num_color_targets = 1; + pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ + .{ + .format = self.device.getGPUSwapchainTextureFormat(self.window), + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, + }; + + pci.rasterizer_state.fill_mode = .fillmodeFill; + self.pipeline = self.device.createGPUGraphicsPipeline(&pci); +} + +pub fn loadFileAlloc(filename: []const u8, comptime alignment: usize, allocator: std.mem.Allocator) ![]u8 { + var file = try std.fs.cwd().openFile(filename, .{}); + defer file.close(); + const filesize = (try file.stat()).size + 1; // add null byte + const buffer: []align(alignment) u8 = try allocator.alignedAlloc(u8, alignment, filesize); + errdefer allocator.free(buffer); + try file.reader().readNoEof(buffer[0 .. buffer.len - 1]); + buffer[buffer.len - 1] = 0; + return buffer; +} + +pub fn loadShader( + self: *@This(), + shaderName: []const u8, + stage: gpu.GPUShaderStage, + num_samplers: u32, // The number of samplers defined in the shader. + num_storage_textures: u32, // The number of storage textures defined in the shader. + num_storage_buffers: u32, // The number of storage buffers defined in the shader. + num_uniform_buffers: u32, // The number of uniform buffers defined in the shader. +) !*gpu.GPUShader { + const spath = try std.fmt.allocPrintZ(self.allocator, "{s}/{s}{s}", .{ self.shaderpath, shaderName, self.shadersuffix }); + defer self.allocator.free(spath); + + std.debug.print("loading shader {s}\n", .{spath}); + + const fileContents = try loadFileAlloc(spath, 8, self.allocator); + defer self.allocator.free(fileContents); + const sci = gpu.GPUShaderCreateInfo{ + .code = @ptrCast(fileContents.ptr), + .entrypoint = "main", + .format = self.shaderformat, + .code_size = fileContents.len - 1, + .stage = stage, + .num_samplers = num_samplers, + .num_storage_textures = num_storage_textures, // The number of storage textures defined in the shader. + .num_storage_buffers = num_storage_buffers, // The number of storage buffers defined in the shader. + .num_uniform_buffers = num_uniform_buffers, // The number of uniform buffers defined in the shader. + .props = 0, + }; + + return self.device.createGPUShader(&sci); } pub fn loop(self: *@This()) !void { @@ -40,25 +130,53 @@ pub fn loop(self: *@This()) !void { } fn update(self: *@This(), dt: f64) void { - _ = dt; - while (sdl3.pollEvent()) |event| { - _ = event; - // std.debug.print("{any} \n", .{event}); + switch (event.type) { + sdl_event.quit => { + self.running = false; + }, + else => {}, + } + + self.draw(dt); } - self.running = true; +} +pub fn draw(self: *@This(), dt: f64) void { + _ = dt; + const cmd = self.device.acquireGPUCommandBuffer(); + var swapchain_texture: *gpu.GPUTexture = undefined; + if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, &swapchain_texture, null, null)) { + var targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroes(gpu.GPUColorTargetInfo); + targetInfo.texture = swapchain_texture; + targetInfo.clear_color = .{ .r = 0.1, .g = 0.1, .b = 0.1, .a = 1.0 }; + targetInfo.load_op = .loadopClear; + targetInfo.store_op = .storeopStore; + + const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, null); + renderpass.bindGPUGraphicsPipeline(self.pipeline); + renderpass.setGPUScissor(&self.scissor); + renderpass.drawGPUPrimitives(3, 1, 0, 0); + renderpass.endGPURenderPass(); + } + + _ = cmd.submitGPUCommandBuffer(); } pub fn destroy(self: *@This()) void { + sdl3.c.SDL_DestroyWindow(self.window); + self.device.releaseWindowFromGPUDevice(self.window); + self.allocator.destroy(self); } pub fn main() !void { - std.debug.print("creating context", .{}); + std.debug.print("hello world... n", .{}); const app = try create(std.heap.c_allocator); try app.loop(); defer app.destroy(); } const sdl3 = @import("sdl3"); +const gpu = sdl3.gpu; +const sdl_event = sdl3.events; const std = @import("std"); diff --git a/lib/sdl3/src/sdl3.zig b/lib/sdl3/src/sdl3.zig index e9d2a8e..cfdabfb 100644 --- a/lib/sdl3/src/sdl3.zig +++ b/lib/sdl3/src/sdl3.zig @@ -1,4 +1,47 @@ -const c = @import("c.zig").c; +pub const c = @import("c.zig").c; +pub const events = @import("events.zig"); + +pub const InitOptions = packed struct(c_int) { + pad0: u4 = 0, // 0 - 3 + audio: bool = false, // 4 + video: bool = false, // 5 + pad1: u2 = 0, // 6-7 + pad2: u1 = 0, // 8 + joystick: bool = false, // 9 + pad3: u2 = 0, // 10-11 + haptic: bool = false, // 12 + gamepad: bool = false, + events: bool = false, + sensor: bool = false, + camera: bool = false, + pad4: u3 = 0, + pad5: u12 = 0, +}; + +pub const AppResult = enum { + app_continue, + app_success, + app_failure, +}; + +pub const Window = c.SDL_Window; +pub const Event = c.SDL_Event; +pub const Rect = c.SDL_Rect; + +pub fn init(options: InitOptions) !void { + if (!c.SDL_Init(@bitCast(options))) { + return error.InitFailed; + } +} + +pub const EventType = events; + +var gLastEvent: Event = undefined; +pub fn pollEvent() ?*Event { + if (c.SDL_PollEvent(&gLastEvent)) { + return &gLastEvent; + } + return null; +} pub const gpu = @import("gpu.zig"); -pub const init = @import("init.zig");