#zig-sdl3: A Zig Wrapper For SDL3

1 messages · Page 2 of 1

shut tree
#

I think I did everything.

shut tree
#

@mellow sedge https://github.com/Gota7/zig-sdl3/pull/100

There seems to be no way to create a pull request for 'adding a branch'. This pull request is not supposed to be merged, instead a branch should be created from this pull request.

mellow sedge
#

will look at later, thnx

hard sparrow
shut tree
#

I will commit it once I get on my PC.

#

And, no, tests do not run the examples. But example run almost fine to me.

#

For some reason SDL isn't able to initialize if I run from any nix shell.

#

Did you try to use the flake by the way?

hard sparrow
hard sparrow
shut tree
#

Sure.

hard sparrow
hard sparrow
#

(Not saying it isn't needed I'm not sure myself)

shut tree
hard sparrow
shut tree
hard sparrow
shut tree
#

Though wait, it's no longer about the nix shell. Apparently it does not work from my normal shell, but works if I run it from VSCode?

#

That's cursed.

hard sparrow
shut tree
#

Why would it work in VSCode though 🤔

hard sparrow
#

It isn't isolated

#

Look at my flake I linked above and see the deps in my ld path and see which are needed, I haven't trimmed them down I took mine from another project of mine I had made it for earlier and just kept them all in

shut tree
#

I am not in the nix shell, not sure if this is related.

hard sparrow
#

Your flake actually needs to declare all the build dependencies which it is linking against

shut tree
#

Ooh, yeah, that makes sense.

#

Thank you. Going to try.

hard sparrow
#

I recommend using the template as it includes better logging

shut tree
#

Yeah, I know about it.

#

Oh, right, I also need to fix the template. Thank you for reminding.

hard sparrow
shut tree
#

I mean that's fine :)

#

I might just insert it as a quote.

#

Instead of a link.

hard sparrow
#

You shouldn't really need to refer to a Discord message, it might not exist forever you know
Someone looking might not have a Discord account either

shut tree
#

True...

hard sparrow
#

Out of curiosity gota you know how you added some nice logging to the template example, howcome you don't just have that nice logging be the default so people don't have to copy paste it in their projects? They also might not know they can do that, iirc not all the examples have the extra logging

shut tree
#

Because I didn't do anything. xD

hard sparrow
shut tree
#

Oh, sorry, I misread. Didn't notice the 'gota'.

hard sparrow
broken bluff
#

this is actually planned lol

#

where I'll probably put in an extras lib a built-in log function that can be easily used, as well as another log function that would forward to zig logs

#

I really don't want to force my defaults on anyone though and would rather just forward SDL and have any extras be opt-in/explicitly used (which is why the functions will be in an extras subsystem and you'd have to still call sdl3.log.setLogOutputFunction() and sdl3.errors.error_callback yourself

hard sparrow
#

I think the extra logging info tho is really useful

atomic girder
broken bluff
atomic girder
#

yeah, I figured it out the hard way already

broken bluff
#

I currently have 13 event structs left to wrap, after that it shouldn't take me long to wrap all of the SDL events properly

#

once events are done I'll work on some of the issues for 1.0.0 and 1.1.0 because I'd rather work on literally anything else than the hints subsystem

clever otter
#

What's so bad about hints?

broken bluff
#

I legit don't know if I can do this without doing some form of at least partial automation because of just the tediousness and size

hard sparrow
broken bluff
#

true lol

atomic girder
broken bluff
#

I mean sure do as many as the hints as you like lol

clever otter
#

I can try helping but I don't have a github account.

broken bluff
#

They're free

#

Also 2 event datatypes left, events will definitely be done tonight or sometime tomorrow but most likely tomorrow

#

I'd say the lack of events are the only real thing making using zig-sdl3 impractical so I'm happy about that

hard sparrow
#

What do you think you'll add next after your events and cleanup? Audio mixer or something?
(Just curious)

broken bluff
#

Idk if mixer for sdl3 is released yet

#

I was going to document image and probably look into shadercross outside of random issues

hard sparrow
broken bluff
#

oh neat

#

shadercross more of a priority though tbh bc most people care about GPU I think lol

hard sparrow
broken bluff
#

Yeah that part might be hard with the big deps

hard sparrow
thin prism
#

the SDL project loves having lots of big deps

broken bluff
#

Ooo nice that there is work on this already

mellow sedge
#

once zig 15 is released, it might be neat to wrap SDL's IO and async IO for zig using the new IO interface

shut tree
broken bluff
#

merged and added as dev

#

man this events thing is taking longer than expected

#

so close yet so far

hard sparrow
broken bluff
#

yeah

#

no more data1 and data2 nonsense

#

and proper tagged union

hard sparrow
#

that really sucks

broken bluff
#

yeah, the main insult is that I have 4 places I need to go through each event pretty much

#

1 for defining all the event types

#

1 for mapping event types to the proper struct

#

1 for converting the SDL event to the zig event for every event

#

and 1 for converting every zig event to SDL event for every event

broken bluff
#

I got 2 of the 4 places done at least

hard sparrow
broken bluff
#

ITS DONE

#

events is finally done

#

only hints remains

#

being able to see the suggestions for the tagged union is so satisfying

#

I'm happy recommending zig-sdl3 to people now

#

events was the main thing you really couldn't do and that's not great given most of SDL is event driven

#

the API may change a bit while I smooth some things out but other than that and potential bugs (and ofc unfinished extensions) it's basically done

#

a lot of the stuff remaining other than extension libs is polish

#

Honestly I'm just tempted to punt hints like sdl does. Don't have inline docs or type hints properly and just link you to the wiki

#

I think that's what I'll do bc I really don't want to do this. Someone else can if they want but unless I hear strong reasons why wrapping hints properly with inline docs is necessary I'll punt it like sdl does

#

I want this to come out faster and digging into hints rather than something people cares about seems like a waste of time

clever otter
#

For a subsystem that gets called 3~4 times per program, I think it's fair

shut tree
#

Events now on zig-master. No changes were needed, fortunately.

shut tree
#

Didn't even need to rebase, just cherry-picked it.

floral holly
#

I also always use Zig master, so I appreciate your effort!

#

Also congrats @broken bluff on finishing everything (except hints).

shut tree
floral holly
#

I haven't had a chance to try it yet. I'll let you know when I do.

broken bluff
#

Since I'm punting hints, all the subsystems will be done tonight!

#

0.1.0 is coming out this weekend :>

#

@shut tree for the zig-master branch could you delete the docs job and update the test job to use the correct zig version?

mellow sedge
#

epic, thnx

thin prism
#

honestly sometimes SDL feels like it was designed by aliens or something

broken bluff
#

Yeahhh the pro of making a wrapper api is you get to reinterpret some of the more... interesting design choices

#

I don't get it either they are using a tagged union anyways USE THE TAGGED UNION

thin prism
#

fr

broken bluff
#

And properties can go to hell

thin prism
#

i mean i guess properties are because "oh we need to add new fields without breaking ABI"

#

i hate dynamic linking.

broken bluff
#

Ah yeah true

thin prism
broken bluff
#

Yeah I'd rather they use pointers for all properties or something

#

And have an array of fixed size and an unused property for the future is just blank in the slot

#

Actually this doesn't do much

#

Hm

thin prism
#

what i would do is like
have the properties field be a pointer to a plain array of key/value pairs
or something like that
the point is it would be something you can declare inline using Designated Initializers

#

(this is one reason i like sokol better api-wise. floooh actually knows that designated initializers exist and the api is designed around that fact)

#

(and really if you're targeting anything older than c99 you're doing something wrong)

broken bluff
#

I think that's a good approach

shut tree
mellow sedge
#

looks good to me, you can merge it now if you want

#

(otherwise I'll merge when I get the chance)

broken bluff
#

so I just put the part of the hearder with all the defines in a text file and than ran this script I made on it, good enough :p

with open('hints.txt', 'r') as ins:
    with open('hints_out.txt', 'w') as outs:
        tags = []
        for line in ins:
            if line.startswith('#define'):
                parts = line.split(' ')
                tag = parts[1].replace('SDL_HINT_', '').lower()
                outs.write(f'{tag},\n')
                tags.append((tag, parts[1]))
        outs.write('\n/// Convert to an SDL value.\n')
        outs.write('pub fn toSdl(self: Type) [*c]const u8 {\n')
        outs.write('\treturn switch (self) {\n')
        for tag in tags:
            outs.write(f'\t\t.{tag[0]} => c.{tag[1]},\n')
        outs.write('\t};\n')
        outs.write('}\n')
#

just double checking all the other functions before I mark hints as done

#

THERE WE GO, LAST SUBSYSTEM DONE

broken bluff
#

now I'm documenting the image subsystem

shut tree
#

Will get on zig-master as soon as I can.

shut tree
#

Fixed that. I hope.

#

Got changes on zig-master.

broken bluff
#

Yeah ik I need to fix the templat and I have a fix for it just haven't been able to push

broken bluff
#

so close...

#

originally the frame rate capper wasn't planned for this but I already started work on it since it makes sense to use for examples so the CPU isn't constantly burning lol

#

unfortunately I'm not good at writing frame rate capper code it seems, mostly functional just have some things to iron out about it

broken bluff
#

I've been having so much trouble getting the custom allocator to work

#

these are my callbacks for SDL, and they look correct so I'm not sure what's wrong?

#
/// Custom allocator to use for `setMemoryFunctionsByAllocator()`.
var custom_allocator: std.mem.Allocator = undefined;

const Allocation = struct {
    size: usize,
};

fn allocationSize(request_size: usize) usize {
    var size: usize = request_size;
    if (size < 1)
        size = 1;
    while (size % @min(@sizeOf(@cImport(@cInclude("stddef.h")).max_align_t), @sizeOf(?*anyopaque) * 2) != 0) // TODO: Optimize this?
        size += 1;
    return size;
}

fn makeAllocation(total_size: usize, comptime memset: bool) ?*anyopaque {
    const total_buf = custom_allocator.alloc(u8, allocationSize(total_size) + @sizeOf(Allocation)) catch return null;
    if (memset)
        @memset(total_buf, 0);
    const allocation: *Allocation = @ptrCast(@alignCast(total_buf.ptr));
    allocation.size = total_buf.len;
    const data_ptr: *anyopaque = @ptrFromInt(@intFromPtr(total_buf.ptr) + @sizeOf(Allocation));
    // std.debug.print("MAKE PTR: {p}, {d}\n", .{ data_ptr, allocation.size });
    return data_ptr;
}

fn allocCalloc(num_members: usize, size: usize) callconv(.c) ?*anyopaque {
    return makeAllocation(num_members * size, true);
}

fn allocFree(mem: ?*anyopaque) callconv(.c) void {
    const raw_ptr = mem orelse return;
    const allocation: *Allocation = @ptrFromInt(@intFromPtr(mem) - @sizeOf(Allocation));
    // std.debug.print("CLEAR PTR: {p}, {d}\n", .{ raw_ptr, allocation.size });
    custom_allocator.free(@as([*]u8, @ptrCast(raw_ptr))[0..allocation.size]);
}

fn allocMalloc(size: usize) callconv(.c) ?*anyopaque {
    return makeAllocation(size, false);
}

fn allocRealloc(mem: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque {
    const raw_ptr = mem orelse return allocMalloc(size);
    // const allocation: *Allocation = @alignCast(@fieldParentPtr("buf", @as(*void, @ptrCast(raw_ptr))));
    allocFree(raw_ptr);
    return allocMalloc(size);
    // const total_buf = custom_allocator.realloc(@as([*]u8, @ptrCast(raw_ptr))[0..allocation.size], allocationSize(size) + @sizeOf(Allocation)) catch return null;
    // allocation = @ptrCast(@alignCast(total_buf.ptr));
    // allocation.size = total_buf.len;
    // return &allocation.buf;
}
#

what's especially funny is that if I try and use the C allocator I get this:

❯ zig build run -Dexample=custom_allocator -Dc_sdl_sanitize_c=full
MAKE PTR: anyopaque@2317a2a8, 24
MAKE PTR: anyopaque@2317a2c8, 72
MAKE PTR: anyopaque@2317a318, 104
MAKE PTR: anyopaque@2317a388, 56
MAKE PTR: anyopaque@2317a3c8, 56
MAKE PTR: anyopaque@2317a408, 40
MAKE PTR: anyopaque@2317a438, 1032
MAKE PTR: anyopaque@2317a848, 24
MAKE PTR: anyopaque@2317a868, 200
CLEAR PTR: anyopaque@2317a318, 104
free(): invalid pointer
run
└─ run custom_allocator failure
error: the following command terminated unexpectedly:
/home/gota/Documents/Zig/SDL3/zig-out/bin/custom_allocator
Build Summary: 28/30 steps succeeded; 1 failed
run transitive failure
└─ run custom_allocator failure
error: the following build command failed with exit code 1:
/home/gota/Documents/Zig/SDL3/.zig-cache/o/af9a13d54bdb3f5077ec3a908244d46a/build /home/gota/Apps/zig-x86_64-linux-0.14.1/zig /home/gota/Apps/zig-x86_64-linux-0.14.1/lib /home/gota/Documents/Zig/SDL3 /home/gota/Documents/Zig/SDL3/.zig-cache /home/gota/.cache/zig --seed 0x3729cd45 -Zb69b279c5beeb924 run -Dexample=custom_allocator -Dc_sdl_sanitize_c=full
#

we can see very clearly that the address being freed has been allocated perfectly fine

#

so who knows really

celest lion
broken bluff
#

holy shot was that really it

#

ok I'm closer, now I get this:

❯ zig build run -Dexample=custom_allocator -Dc_sdl_sanitize_c=full
Illegal instruction at address 0x160f73e
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c:1007:58: 0x160f73e in SDL_GetDisplayIndex (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c)
        if (displayID == _this->displays[display_index]->id) {
                                                         ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c:976:21: 0x160fc82 in SDL_GetVideoDisplay (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c)
    display_index = SDL_GetDisplayIndex(displayID);
                    ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c:1031:33: 0x160e692 in SDL_GetDisplayProperties_REAL (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c)
    SDL_VideoDisplay *display = SDL_GetVideoDisplay(displayID);
                                ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c:882:13: 0x160dfc2 in SDL_AddVideoDisplay (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c)
    props = SDL_GetDisplayProperties(id);
            ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/x11/SDL_x11modes.c:507:9: 0x1a6616f in X11_AddXRandRDisplay (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/x11/SDL_x11modes.c)
    if (SDL_AddVideoDisplay(&display, send_event) == 0) {
        ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/x11/SDL_x11modes.c:768:22: 0x1a60f75 in X11_InitModes_XRandR (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/x11/SDL_x11modes.c)
                if (!X11_AddXRandRDisplay(_this, dpy, screen, res->outputs[output], res, false)) {
                     ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/x11/SDL_x11modes.c:881:13: 0x1a6067f in X11_InitModes (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/x11/SDL_x11modes.c)
            X11_InitModes_XRandR(_this)) {
            ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/x11/SDL_x11video.c:406:10: 0x19fdd87 in X11_VideoInit (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/x11/SDL_x11video.c)
    if (!X11_InitModes(_this)) {
         ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c:700:10: 0x160a1a3 in SDL_VideoInit (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/video/SDL_video.c)
    if (!_this->VideoInit(_this)) {
         ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/SDL.c:357:18: 0x15e4cc6 in SDL_InitSubSystem_REAL (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/SDL.c)
            if (!SDL_VideoInit(NULL)) {
                 ^
/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/SDL.c:534:12: 0x15e5a02 in SDL_Init_REAL (/home/gota/.cache/zig/p/sdl-0.2.5+3.2.18-7uIn9FwZfwHKOwSubcg5_CiW4fXag5IIsiV_jnLdkpDM/src/SDL.c)
    return SDL_InitSubSystem(flags);
          ```
#

thnx though that was a really good catch idk how I missed that lol

broken bluff
#

it looks like I got the FPS capper working at least :>

#

has 2 modes, one for setting to a given FPS and one for just acting unlimited

#

the delay function in unlimited mode will essentially just give the dt, basically you have 3 options:

  1. Unlimited FPS (There really is never a good reason to do this except for "benchmarks" and that's a stretch)
  2. Unlimited FPS, but the renderer or GPU is vsync limited so this works well for getting dt and observed FPS
  3. Limited FPS (Good for having the user set the FPS, basically mandatory if vsync is not available)
#

I find it really strange that SDL by default has no good way of managing FPS? Getting the dt is one of the most important parts of any game loop

#

and unless you are explicitly going out of your way to enable vsync, or have an application that is event-driven rather than frame-driven, then by default you're running at unlimited FPS and maxing out your CPU which is definitely not great for beginners, even the official SDL3 examples just ignore this problem! The default SDL3 examples just have you burn CPU and battery!

#

https://examples.libsdl.org/SDL3/renderer/08-rotating-textures/ for example, this example here does per-frame updates but they don't even try to set vsync and how they spin the texture relative to the frame time is definitely more of a hack than what anyone would practically do when making an FPS-driven app or game

#

I think this is bad practice personally and I'll be using the FPS limiter extra for the renderer examples when I get to them, as you want a beginner to be doing the right thing by default. No one new to SDL is going to practically know about CPU time, and what if they never even heard of the concept of dt welp have fun explaining to them how to get it themselves and delay properly

#

I'll also update the template to have an FPS debug counter or something on the top right

#

(and yes vsync is disabled by default)

broken bluff
#

I wrote something in the SDL server about my concerns with the examples and frame limiting, I suppose I'll wait to hear back

harsh lagoon
#

The app callbacks aren't permanently running though

#

Its logic depends on the platform; on ios and android it uses the OS's own callbacks to decide when it's time to make a frame

#

so the battery usage is as good as possible

#

This is the logic for platforms that don't provide frame callbacks

broken bluff
#

you would think they would use this in the examples though

#

also on my PC callbacks by default do run as fast as possible on the CPU

harsh lagoon
#

it USED to

#

My bad

broken bluff
#

not great they removed functionality like that then out of nowhere 😬

#

SDL guys giving me shit saying I'm inventing a problem pfffffff

harsh lagoon
#

It'd probably better raise the issue on the actual github

#

Basically there are three possible solutions:

  • callbacks shouldn't run as fast as possible by default
  • vsync should be on by default
  • examples should require vsync
#

it's up to the devs to decide which solution is appropriate (or if they don't care about laptops)

winged forum
broken bluff
#

so far the responses have been along the lines of this lib isn't to cater to beginners, who's shipping a game that doesn't know about FPS caps

#

and that I'm overexaggerating the effects of just burning CPU lol as if handheld gaming isn't a big trend where idk you kinda want battery life???

#

I'll probably make an issue on the repo yeah

#

FPS counter and frame cap added to the template

clever otter
broken bluff
#

this is a nice article

clever otter
broken bluff
#

this is a neat thread

#

I didn't know there were so many different methods of frame rate...

#

I've just be using variable all my life

#

(except for fixed-framerate on retro consoles)

harsh lagoon
#

not people who think they are elite programmers because they use SDL

harsh lagoon
#

it's also possible that laptop OSes are assumed to force vsync anyway?

#

Either way yeah, raising a descriptive issue with the actual problem and what might be acceptable solutions and letting the devs share their thoughts is the way to go about it

hard sparrow
#

How are you supposed to save images with the sdl3 image wrapper?
I thought it'd just be this:

        const image_stream = try sdl3.io_stream.Stream.initFromFile(full_path, .read_binary);
        const image_surface = try sdl3.image.loadIo(image_stream, true);
        try sdl3.image.savePng(image_surface, OUTPUT_PATH);

But it gives me an thread 259477 panic: applying zero offset to null pointer

hard sparrow
#
thread 4567 panic: applying zero offset to null pointer
miniz.h:2619:39: 0x7f5ebf8fd6a5 in tdefl_compress_normal (IMG_png.c)
      const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
                                      ^
miniz.h:2782:10: 0x7f5ebf8fb751 in tdefl_compress (IMG_png.c)
    if (!tdefl_compress_normal(d))
         ^
miniz.h:2802:41: 0x7f5ebf8fa8bb in tdefl_compress_buffer (IMG_png.c)
  MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
                                        ^
miniz.h:2926:7: 0x7f5ebf8f752c in tdefl_write_image_to_png_file_in_memory_ex (IMG_png.c)
  if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
      ^
miniz.h:2967:10: 0x7f5ebf8f6e07 in tdefl_write_image_to_png_file_in_memory (IMG_png.c)
  return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, bpl, pLen_out, 6, MZ_FALSE);
         ^
IMG_png.c:759:15: 0x7f5ebf8f665b in IMG_SavePNG_IO_miniz (IMG_png.c)
        png = tdefl_write_image_to_png_file_in_memory(surface->pixels, surface->w, surface->h, SDL_BYTESPERPIXEL(surface->format), surface->pitch, &size);
              ^
IMG_png.c:808:18: 0x7f5ebf8f5ede in IMG_SavePNG_IO (IMG_png.c)
        result = IMG_SavePNG_IO_miniz(surface, dst);
                 ^
IMG_png.c:785:16: 0x7f5ebf8f5e4c in IMG_SavePNG (src/IMG_png.c)
        return IMG_SavePNG_IO(surface, dst, 1);
               ^
image.zig:1221:30: 0x10e6c4e in savePng (pppp)
    const ret = c.IMG_SavePNG(
                             ^
atlas_pack.zig:79:31: 0x10e76b5 in main (pppp)
        try sdl3.image.savePng(image_surface, OUTPUT_PATH);
                              ^
nimble stag
# hard sparrow How are you supposed to save images with the sdl3 image wrapper? I thought it'd ...

you're hitting an UBSan trap because it's adding 0 to a null pointer. in this code snippet is probably fine in practice but it's technically UB and therefore a bug in the miniz.h header

UBSan is enabled by default for Debug and ReleaseSafe builds, with how the zig-sdl3 build.zig is set up you can only disable it by building it in ReleaseFast/Small (i.e. pass .optimize = .ReleaseFast instead of optimize in your b.dependency("sdl3") call in your own build.zig)

#

a good contribution to zig-sdl3 would be to make it pass forward the c_sdl_sanitize_c option to the compile step that creates SDL_image

#

so that you can disable ubsan in debug builds

hard sparrow
#

Don't you want it on?

nimble stag
#

it's a "bug" because the C spec says that null + 0 is undefined and that a compiler is free to handle that however it wants, but in practice every compiler in the world is going to handle it the same way

#

ubsan is very pedantic and doesn't differentiate between dangerous, always-bad UB and silly things like this

hard sparrow
#

Wait so your saying the SDL_image code is fine but the problem is that zig-sdl3 doesn't turn off the sanitizing?

nimble stag
#

yes

hard sparrow
#

So SDL_image shouldn't be changed to avoid UB?

#

I see that's really counter intuitive for me lol, I haven't written C code before so not sure about how UB works

#

If I did turn ubsan off wouldn't I miss other actual problems?

nimble stag
#

fixing it in SDL_image would be good too. I've run into similar ubsan traps in the main SDL in the past and I usually contribute an upstream fix that rewrites the code to avoid invoking UB

#

if you turn it off it won't catch other actual problems, but SDL_image is a mature enough library that it's probably not a problem

#

that you're even running into this is just because most C projects use bad compiler defaults and don't build with important warning/sanitization enabled

#

zig cc tries to improve upon status quo with more sane defaults, at the cost of annoyances like this if the code wasn't written taking warnings/UB into consideration

hard sparrow
#

Is there a way to have them be warnings instead of errors?

#

Even if I contributed a fix it'd still take a while before the next release comes out and zig-sdl3 updates I assume

nimble stag
#

not from your own code, no. I haven't tested but it might be possible to log failures but not trap by passing -fsanitize=recover as a C flag when setting up SDL_image in zig-sdl3

#

but either way the most pragmatic fix for you right now is building zig-sdl3 in ReleaseFast, even in debug builds

hard sparrow
#

I'll try do that then soon

#

Thank you

#

I'm not sure I know how to rewrite this better, would it be worth me creating a GitHub issue or just posting in the Discord you reckon before I switch modes to ignore the problem?

nimble stag
#

I'd say ignore it. creating an issue in the SDL_image repo wouldn't hurt but if you're not familiar with compiling C it's probably difficult to reduce it down to a minimal repro for the maintainers without requiring them to use zig specifically. usually these are best handled by contributing a PR directly

hard sparrow
nimble stag
#

wrong place, you pass it to the b.dependency call for zig-sdl3

hard sparrow
#

Yeah no longer get the error anymore thanks!

broken bluff
#

2 issues left until 0.1.0

clever otter
#

Woo!

broken bluff
#

1 more

#

it's just the custom allocator example but it's not working at all and keeps crashing and I really can't figure this out :<

#

I might push that to 0.1.0

#

IT HAPPEND!

broken bluff
#

My next priority is getting shadercross and some hlsl examples working

#

Also some render examples would be good

shut tree
#

I need some networking for my game so I will work on #15.

shut tree
waxen vale
#

please ignore the mach engine. i mistook the game-dev in mach channel for this i ment to send it here.

hard sparrow
shut tree
#

You need to also write the wrapper in this case.

#

For example, SDL_ttf.h is 3000 lines of code and it's really painful to write a wrapper for it.

hard sparrow
shut tree
#

Yeah.

#

Because SDL_net.h is only 1300 lines.

hard sparrow
#

Nice that's cool

#

Out of curiosity have you automated transferring docs over or something or do you do that manually?

shut tree
#

I write a Python script to generate the initial thing and then just tweaked that.

#

Though I still don't understand how I get files smaller than the original header.

shut tree
#

ziggyyes Decided to also do SDL_ttf since I would probably need it too.

hard sparrow
#

Anyone know off any examples loading a 3d object?
Like from gltf or obj or something

broken bluff
#

@shut tree you're insane lol thnx I'll review when I can

#

At this rate we might just skip 1.0.0 and go straight to 1.1.0 lol

broken bluff
#

@hard sparrow do you know anything about this [Gota7/zig-sdl3] Issue opened: #106 nix-os SdlError: No available video device (maybe add system integration?)

#

Ok that didn't work

#

There we go

shut tree
broken bluff
#

Yeah probably

broken bluff
#

(You can make a pull request if you like, otherwise I'll do it when I get home)

hard sparrow
broken bluff
#

No worries

atomic girder
broken bluff
#

Thnx, I'll look into it

atomic girder
#

Glad to help!

shut tree
#

Also, I realized we need to install examples/data so ttf example can actually run. It was in my local zig-out all this time. You can do it now or I'll do it myself tomorrow, it's 11 PM for me here already.

broken bluff
#

passed back MR

waxen vale
atomic girder
waxen vale
atomic girder
#

Alright, glad I could help!

waxen vale
atomic girder
#

Thank you for your Android template, It really did safe me alot of time

#

(and alot of pain)

waxen vale
#

Do anyone have any ideas on how to use shaders with sdl renderer? or is it impossible as of now?

hard sparrow
#

That's what I've heard

celest lion
mellow sedge
#

I think for the extension libs, it'd be nice to have a bring your own lib for them too

#

bc for my own development purposes I'd like to be able to load .kra files as textures

#

which would require my own fork of SDL_image

#

so a way to specify the SDL_image to use rather than the one in the zon would be useful

#

(I do basically all my artwork with Krita)

clever otter
#

That's actually such a good idea

mellow sedge
#

it really does makes dev time faster

#

I added zip reading functionality in my old engine just for it

chilly palm
#

Are there any zig examples or tutorials for working with gpu?

#

I'm going through a regular sdl tutorial, but really new to zig so having something to reference would be nice

hard sparrow
#

The shaders are written with Zig though so I looked at the shaders from the regular tutorials and SDL3 code from here

#

I was wondering why you do all this pointer magic rather than just using memcpy?

    const transfer_buffer_mapped = @as(
        *@TypeOf(vertex_data),
        @alignCast(@ptrCast(try ctx.device.mapTransferBuffer(transfer_buffer, false))),
    );
    transfer_buffer_mapped.* = vertex_data;
    @as(*@TypeOf(index_data), @ptrFromInt(@intFromPtr(transfer_buffer_mapped) + vertex_data_size)).* = index_data;

https://github.com/Gota7/zig-sdl3-gpu-examples/blob/master/src/examples/textured_quad.zig#L189-L201

I tried to do something similar yesterday as you did and it worked when I hard coded the vertex and index buffers but as soon as I had them at runtime I started getting alignment errors (probably because the alignment of the vertices and indices are different ig, which doesn't seem to be a problem with memcpy with sliceAsBytes?)

What it looks like the other way:

    const vertex_index_transfer_buffer_mapped = try device.mapTransferBuffer(vertex_index_transfer_buffer, false);
    @memcpy(vertex_index_transfer_buffer_mapped, std.mem.sliceAsBytes(vertex_data));
    @memcpy(vertex_index_transfer_buffer_mapped + vertex_data_size, std.mem.sliceAsBytes(index_data));
#

@broken bluff

broken bluff
#

yeah that's cleaner I forgot std.mem.sliceAsBytes exists tbh

#

you can make an MR for it if you like

hard sparrow
hard sparrow
hard sparrow
#

Just wondering if you started on sdl-shadercross yet or nah gota?

broken bluff
#

Nothing substantial, someone else is free to do it. I'm taking a short break from sdl stuff in general

hard sparrow
#

If you got it built I can take a look and try work on bindings or something maybe, just not sure how to port the build to Zig myself

broken bluff
#

Nah I didn't get it built, I was copying some from someone else's port linked somewhere above in this thread

hard sparrow
broken bluff
#

I didn't build any yet didn't get that far

#

Just started porting one into the repo but only a small amount

hard sparrow
#

Oh you mean you hadn't actually started getting it running icic

#

How hard do you think it'd be for me to add one of those in?

broken bluff
#

Assuming the existing one works not to bad to copy it into the zig sdl3 build.zig

hard sparrow
clever otter
#

I heavily suggest to anyone who doesn't want to ship on Xbox to just disable DirectXShaderCompiler in SDL_shadercross. Then it becomes trivial to build. Just use the Vulkan backend on Windows

hard sparrow
#

Still will need to find a way to compile spirv cross iteslf though as SDL_shadercross depends on it

clever otter
#

It's still hard to build AFAIK but nowhere near the monstruosity that is DirectXShaderCompiler

clever otter
#

And for the record, if you don't plan to ship on Mac/iOS, you also don't need SDL_shadercross at all

hard sparrow
#

Oh what

#

Awesome so zero other deps?

clever otter
#

Pure SPIR-V works perfectly on Windows and Linux (and I think Android) thanks to Vulkan

#

You'd just need SPIR-V reflect if you want it to check all the bindings for you. But I'm pretty sure that one is extremely trivial to build

#

Now if you want to use HLSL and not GLSL, I think you need something like shaderc or glslc to compile it. But it doesn't have to be DirectXShaderCompiler

hard sparrow
#

Ahh

#

Those work out of the box with SDL_shadercross?

clever otter
#

SDL_shadercross is just a thin wrapper over DirectXShaderCompiler and SPIRV-Cross. It uses the former to compile HLSL to SPIR-V and then the latter to cross compile it to all the other GPU API formats

#

If you don't need the other formats, there is no use for SDL_shadercross. You can just compile your shader to SPIRV, use SPIRV-reflect (or just hardcode the bindings when creating the shader) and pass it to SDL GPU

hard sparrow
#

Wait so your saying I don't even need SDL_shadercross to compile SPIR-V?

#

What's the easiest way to compile it from HLSL? HLSL is what I see all the examples written in online so I thought that'd be the best one to use

clever otter
#

You don't need D3D12 unless shipping to Xbox because Vulkan works perfectly fine on Windows, and you don't need Metal if you don't want to ship to Mac/iOS.
If you only want Windows and Linux support, you can just compile your SPIR-V and use it normally and it will work

clever otter
hard sparrow
#

Or do you just recommend going with GLSL over HLSL?

#

What do you do?

clever otter
#

There's tons of HLSL-to-SPIR-V compilers, you can just pick the one you like more. I can't really tell you which one is better because I do just use GLSL and glslangValidator

hard sparrow
#

So if I did just want to write GLSL then I should just use SDL_shadercross that's the easiest way to go about with that or is something like glslang easier to get working/compiled with Zig?

clever otter
#

If you want to just write GLSL, just use glslang from the Vulkan SDK

#

Again SDL_shadercross is not needed at all unless you want to ship on consoles or Mac/iOS

hard sparrow
clever otter
#

Same

hard sparrow
#

Thank you so much I think you probably have saved me like a lot of time and effort haha

clever otter
#

No problem!

broken bluff
#

I mostly want shadercross for integrating with the zig build system tbh

#

Would rather not translate at runtime

hard sparrow
#

Apparently DXC or whatever is a fork of LLVM or Clang or something lol

broken bluff
#

Ah yeah with Microsoft bs

chilly palm
#

Are there any samples showing how send uniform data?

hard sparrow
#

At the start when you initialise a shader you tell it how many uniforms you want bound:

    const vert_shader = try device.createShader(.{
...
        .num_uniform_buffers = 1,
...
    });
#

Then in your render pass before your draw call upload the data:

        command_buffer.pushVertexUniformData(0, std.mem.sliceAsBytes(&model_matrix));
#

Much simpler than buffers or textures DoggoSmile

chilly palm
#

The docs say this: In practical terms this means you must ensure that vec3 and vec4 fields are 16-byte aligned.
The sdl tutorial I followed also uses a struct to hold a float value.
So how would you e.g. send two different floats?

hard sparrow
#

You can load a vector or matrix or whatever onto a uniform there is no problems with doing that btw

chilly palm
#

Does it need to be padded to be a multiple of 16 bytes?

hard sparrow
#

For example I have three matrices which I bind to a single uniform:

const Transforms = struct {
    model: zm.Mat,
    view: zm.Mat,
    projection: zm.Mat,
};
[[vk::binding(0, 1)]]
cbuffer Transforms {
  float4x4 model;
  float4x4 view;
  float4x4 projection;
}
#

I don't do anything fancy to upload them either:

        command_buffer.pushVertexUniformData(0, std.mem.asBytes(&transforms));
chilly palm
#

I'm just curious about the line that says std140 requires fields be 16-byte aligned

hard sparrow
chilly palm
#

ah ok

hard sparrow
#

If you have two separate variables which do not have the same alignment and are not in a struct (i.e. probably because they are not comptime known size) and you want to combine them together, then you'd need to manually calculate the padding or whatever to fix the alignment
But that sounds hard and I haven't had to do that yet

#

But I don't think that's even relevant to uniforms in particular, you'd have the same issue with a buffer or texture or anything I'm pretty sure

chilly palm
#

What's the difference betweenasBytes and sliceAsBytes?

hard sparrow
chilly palm
#

Sorry maybe I should have asked in game-dev, this isn't really zigsdl3 specific anymore

hard sparrow
chilly palm
#

I suppose not

chilly palm
#

Possibly you're not setting something up or not calling something you should be

#

do you have code that can be run to test?

hard sparrow
#

Is there a reason why the swapchain texture struct is declared inline?

pub fn waitAndAcquireSwapchainTexture(
        self: CommandBuffer,
        window: video.Window,
    ) !struct { texture: ?Texture, width: u32, height: u32 }
broken bluff
#

I mean it's just easier to do that for functions that return multiple things essentially

#

Could make a struct for everything but is there a reason to?

hard sparrow
broken bluff
#

In worst case you could use the type info to get that struct, not the cleanest but it works

hard sparrow
#

My only thing was it would've had ! error type

clever otter
#

How are you supposed to handle errors with this wrapper?

chilly palm
boreal tulip
#

Don't use vector or packed struct instead of extern here, they both have very weird alignment/impl stuffs that will definitely bite you

broken bluff
chilly palm
#

So it should be extern struct instead?
I'll be honest I don't really understand either of these keywords.

hard sparrow
#

Unless you need to call it from C code?

boreal tulip
#

packed really means bitpacked and puts all your fields in bits with no alignment into an integer while extern forces the struct to use the C abi
Vector is a SIMD primitive and has basically no implementation guarantees

boreal tulip
hard sparrow
chilly palm
#

So if not vector, []f32, or individual f32 fields instead?

#

Also the examples use packed and Vector for the vertex data. Is that also a problem?

boreal tulip
#

Use [N]f32

#

I think it's fine in the shaders because they are then SPIR-V vectors but idk

shut tree
#

@broken bluff , sorry for being inactive, I am back. First I'll get stuff on master then I'll try to finish the PR.

chilly palm
#

So can anyone clarify something on how uniform data works?
Basically I set up some uniforms for the fragment shader and pushed it using pushFragmentUniformData.
Then later also added the same uniform data to the vertex shader, but didn't add a corresponding pushVertexUniformData
And yet it still worked.

broken bluff
hard sparrow
#

When you copy a matrix [4][4]f32 with Zig onto GPU is it row or column major?

stark elk
#

column major

broken bluff
#

Now that I'm back from vacation I'll look at that big MR again and start working on some 1.0.0 stuff

left umbra
#

Saw https://poniesandlight.co.uk/reflect/debug_print_text/ in #game-dev a few months ago, decided to see if I could get it to work with SDL3 and HLSL+shadercross as a project to test this wrap and try SDL3. Worked beautifully, vert buffer is a bit chunky but not having to pre-render letters is nice.

minor hemlock
#

Is v0.1.0 only compatible with 0.14.0, or also 0.14.1?

#

for the gpu stuff, everything else works fine

boreal tulip
minor hemlock
#

Hmm, is there anything obviously wrong in here?
https://zigbin.io/795197
I just grabbed the template from the main sdl3-zig repo and then swapped out some of the window and renderer creation stuff from one of the gpu examples, I was hoping to just get a window up and running.

limpid widget
#

Do zig shaders work with SDL shadercross?

atomic girder
glacial smelt
#

but eventualy it will work 😄

stark elk
glacial smelt
#

huh mb I should do that too

#

thx

stark elk
clever otter
#

I don't think so. I think at this stage it's way better to just use GLSL shaders...

novel monolith
stark elk
#

aww rip, okay

broken bluff
novel monolith
#

hf

novel cloud
#

I have a strange issue with RenderDoc and the sdl3 gpu API. When running through renderdoc the device creation fails. I get no vulkan validation errors or anything. When running the exe manually I have no issues at all. I use the callback template and create a device with debug enabled and spirv. Anyone else ran into this? Good to mention I'm on ubuntu.

mellow sedge
#

never ran into that before

#

I suppose it's time to upgrade the master branch to zig 15 now, luckily that shouldn't take too long thnx to the helpful @ oh they are gone

celest lion
novel cloud
waxen vale
#

Also there is this issue on android platform. the gpu api with the wrapper, app crashes all the time in when sent to background. but it doesn't happen with raw c api that often why is that?

novel cloud
# waxen vale Also there is this issue on android platform. the gpu api with the wrapper, app ...

Hmm not sure, you would need to check the wrapper code, but I don't think it does anything else but calling the c api. I got renderdoc working using x11. So it seems wayland is not yet fully supported when using vulkan, see the following open issue on renderdoc: https://github.com/baldurk/renderdoc/issues/853

GitHub

Many Unix-like platforms are in the process of adopting the more modern Wayland protocol in place of X11, so it would be great to have native Wayland support in the RenderDoc in-application API. Cu...

mellow sedge
#

update to 0.15.1 coming this weekend

#

had basically 0 zig time this weekend lol so assuming I get my college stuff done tonight I have a lot of stuff I want to work on for zig-sdl3

broken bluff
#

ok so just merging the zig-master branch into the master branch has a bunch of merge conflicts and I'm not sure what to do

#

are there any git masters here that would know the best course of action for getting zig-sdl3 to 0.15.1 while taking advantage of the changes done in the zig-master branch

#

once this is updated to use 0.15.1 and I fix some bugs I'll release a 0.1.1

#

maybe cherry-picking

#

yeah I can do that

broken bluff
#

done!

#

tagged v0.1.1

stark elk
#

nice i will switch from the zig-master branch to 0.1.1 then :D

royal crow
#

switched to 0.1.1 all gucci. thanks @broken bluff

broken bluff
#

Ye np

broken bluff
#

working on wrapping shadercross rn

#

once I finish wrapping it, I'll get started on porting GPU examples

#

each example will be a standalone file and executable

#

though the build script will build all of them and optionally run a target example

#

each shader will have an HLSL, GLSL, and zig equivalent

#

in addition to that, there will probably be another GPU example folder and build script exclusively for zig shaders using some tricks I learned for compile time reflection to verify CPU<->Vertex Shader<->Fragment Shader code and binding compatiblity

#

but the "normal GPU examples folder" would have zig shaders that just do exactly what the GLSL and HLSL ones do with not much else

broken bluff
#

I wrapped shadercross, now just need to get it built lol

scarlet cloud
#

So much looking forward to it 😃

broken bluff
#

alright, I think I got shadercross linked? I got the clear screen example working on the shadercross branch

clever otter
#

Woo!

broken bluff
#

and yeah each example is stand-alone copy-paste using callbacks

broken bluff
#

huh apparently I need to compile shadercross with DXC in order to get HLSL to SPIRV? Interesting

empty oyster
#

It's my first time using Github to make a PR so hopefully I did it correctly. It seems right.

broken bluff
#

dang how did I miss this thanks

broken bluff
#

welp, shadercross reflecting for getting the SPIRV metadata is not appreciating the zig compiled SPIRV binary :p

novel monolith
#

spirv-tools suck ass on a whole. sorry

broken bluff
#

I wonder if I do an optimization pass on the SPIRV would fix it

#

as I need to do that anyways

#

very annoying that spirv-tools just gives up the second something is wrong though, just parse the thing

#

ah well

broken bluff
#

so make my own implementation of the shadercross get SPIRV metadata?

#

I suppose that would be the only alternate option other than hardcoding some values if spirv-opt doesn't magically fix it

broken bluff
#

h u h

#

wait I'm sorry what

#

are you really not allowing me to optimize

novel monolith
#

old spirv-opt

broken bluff
#

because your tool doesn't expect zig to exist

#

w h y

#

what kind of future proofing is that

#

yeah ik I need to update my version but still like what

novel monolith
#

k h r o n o s

broken bluff
#

how is this a problem that can be encountered, isn't the purpose of SPIRV to be language agnostic???

novel monolith
#

i suppose they expect you to put 0 (Unknown) in that case

broken bluff
#

just give me a warning don't error and abort everything :p

#

guess it's time how to figure out how to update these tools then

#

unfortunately I'm on debian 12

novel monolith
#

rip

broken bluff
#

ok if I update to trixie I'll get a 2025 version

#

I do want to upgrade my debian install but not sure if I have enough time atm to back everything up properly

broken bluff
#

I decided to upgrade to debian 13 anyways

#

luckily, debian is so good and reliable that it just worked without issues. I had a weird bug where the KDE apps list wouldn't show any of my apps but there was a single command I had to run and then it was fine

#

so yeah now spirv-opt seems to be doing its thing but unfortunately I still get that alignment error from reflection...

broken bluff
#

at least I know this is just a shadercross thing at runtime

#

bc compiling GLSL to SPV results in the same thing :p

#

setup is always the hard part, once I have the basic triangle example working for GLSL, HLSL, and zig with shadercross behaving properly, then the rest of the examples should be fairly straightforward

#

the zig shaders in this are also standalone files unlike my other examples where they are a bunch of comptime stuff, I want these GPU examples to be as standalone as possible

broken bluff
#

added a log and error shim

#

has options for both using zig log and debug prints

broken bluff
#

I updated the version of spirv-cross but still no luck hm

broken bluff
#

OH OK ITS AN UBSAN THING

#

it ✨ just works ✨ in ReleaseFast

#

I'll force SPIRV-cross to be ReleaseFast for now

#

wanted to be smart and switch between ReleaseSmall and ReleaseFast but it's not comptime-able? So idk

broken bluff
#

so far, all the shader formats are working on linux except for HLSL

#

added warning for spirv-opt not being found

#

I rely on spirv-opt for zig shaders to be optimized properly, but it is not technically necessary

#

also added a nice panic message for when glslang is missing

scarlet cloud
#

this is so cool!
I am super excited to try out the examples as soon as you are in the "triangle working" state 🙂

broken bluff
#

There is a shadercross branch on my zig-sdl3 repo with everything so far

scarlet cloud
broken bluff
#

I'll see what happens if I disable the int64 spirv extension later

novel monolith
broken bluff
#

Epic

#

Perfect then

#

Checklist for shadercross branch to be done:

  1. HLSL support
  2. Verify all 3 shader formats work on linux, windows, and mac
  3. Finish all the GPU examples
  4. Make a dedicated example project showing watching for an HLSL file change and recompiling the shader at runtime for a shader-toy like program
  5. Zig shader GPU project using compile time reflection to generate CPU vertex buffer types and ensure vertex and fragment shader compatibility
broken bluff
#

alright I think I fixed zig shaders on Mac

#

friend can't test until tomorrow though

scarlet cloud
#

I might give it a shot later today 🙂

broken bluff
#

Thnx :>

broken bluff
#

windows really just said no lol

#

I'll try GLSL and see if that works at least

#

though I'm pretty sure this is a known issue with Windows

#

At least my Mac friend zig and glsl shaders worked for him

royal crow
#

why is stuff always broken on windows... so annoying to have to struggle getting shit working just because I'm not a linux nerd

broken bluff
#

Found the issue

#

Windows is just harder to develop for tbh

#

Having used both for a while I vastly prefer the unix like command utilities and filesystem

royal crow
#

I agree, when it comes to the amount of bullshit that MS puts into the OS and API and such

#

This is why I'm doing fun stuff in zig as an antidote for all the bullshit from my day job lol

broken bluff
#

When using the windows 10 vm to try and compile I clicked the system environment variables start menu entry too fast and I had to right click and hit open in order for anything to happen

#

I couldn't left click anymore even closing and reopening the start menu, but just for that entry

#

How does that even happen

#

There is a pr to fix the windows issue but it looks dead :<

broken bluff
#

alright GLSL borked too

#

ughh

#

oh ok it's not GLSL

#

it's just every GPU example crashing on WIndows for no discernable reason

#

NO idea what is going on

#

maybe it's something to do with shadercross?

#

the regular SDL3 examples are working perfectly fine

#

or maybe it's my VM

#

or maybe something with GPU in general

#

I have no idea no error messages just the program exiting unsuccessfully, and not sure how to debug this

#

if there are any zig Windows experts that can figure out what the issue is please let me know, it'll help greatly in getting this out faster

empty oyster
#

I cannot say I'm an "expert", but I am using Zig on Windows and can see what output I get

#

Is this on the shadercross branch?

broken bluff
#

Yep

#

So it works for you @empty oyster? Might just be a vm thing then

#

Thanks for testing :>

scarlet cloud
#

@broken bluff basic triangle works perfectly on my Mac 🙂
Only one feedback, the error message is not very clear when glslang is not installed

broken bluff
# scarlet cloud 🥳

Eyyy nice. Do zig shaders work too? I also tried doing a custom panic message for glslang I'm not sure what else I can do unfortunately

mellow sedge
# scarlet cloud

also this looks like you're trying to compile zig shaders and using an outdated version of my shadercross branch?

scarlet cloud
mellow sedge
#

oh huh

#

I thought I disabled 64-bit ints for zig shaders

#

I'm not sure why zig shaders are not working on runtime...

empty oyster
#

It was technically on Windows 11 but I doubt that matters

broken bluff
#

Probably not, good to know that :>

#

This also means while I can't compile zig shaders on windows they'd probably run if precompiled from a different os

broken bluff
#

Basic triangle and basic vertex buffer examples done

broken bluff
#

cull mode example done

#

5/32 GPU examples completed

stark elk
stark elk
#

this looks a lot cleaner than the old gpu examples :D

#

looking forward to a uniform buffer example ;) (for my zig-sdl3 and zig shader exploration project)

broken bluff
#

Thnx :> I've been trying to make everything look cleaner and self-contained. Hopefully I have time to complete all the examples soon

novel cloud
#

I have some strange issue with surface creation before and after claimWindow call. running it before claimWindow seems to work, after not. Anyone else run into this? I did see a possible related issue: https://github.com/Gota7/zig-sdl3/issues/123 added some samples there.

GitHub

I am trying to load images with SDL_Image and upload the to the GPU using SDL_GPU. But if I call IMG_Load between claiming the window to the device and creating the texture, the entire program cras...

#

I would assume claimWindow and image.loadFile should be totally unrelated as loadFile is not a gpu operation as far as I know.

mellow sedge
#

yeah, I have no idea what the problem is

broken bluff
#

ok the vertex buffer example I made on my laptop just crashes on my PC

#

what

#

cull mode works fine though

#

huh

broken bluff
#

it looks like the renderer in VULKAN_submit is just null

novel cloud
#

@broken bluff I've investigated into my issue some more and it results in to almost the same error as you have above:
The interesting thing is that this time I rewrote it in c using the zig build system. I've added the c code to the open issue: https://github.com/Gota7/zig-sdl3/issues/123

GitHub

I am trying to load images with SDL_Image and upload the to the GPU using SDL_GPU. But if I call IMG_Load between claiming the window to the device and creating the texture, the entire program cras...

novel cloud
#

Building SDL from source, and building the SDL_gpu_examples from source than I don't have this issue.

broken bluff
#

oh huh

#

wonder what's going on with the build system

#

undefined behavior somewhere maybe?

#

OK I THINK IT WAS FIXED UPSTREAM

#

I updated SDL3 and it seemed to work

#

making a PR now

#

mostly waiting for CI to pass

#

ok @novel cloud try now

#

using the latest master of zig-sdl3

novel cloud
#

Nice! this seems to work indeed

broken bluff
#

eyyy nice

#

I'll just comment on the issue and then close it then

novel cloud
#

still strange issue though. curious to see what the underlying issue was.

#

Anyways thnx for checking and for the awesome library!

novel cloud
#

Yeah that looks like a winner

broken bluff
#

7/32 GPU examples done

broken bluff
#

8/32 GPU examples done

#

I just did the textured quad one :>

#

next example will be to animate the texture quad with a matrix, let's see how that goes lol

broken bluff
#

9/32 GPU examples done

#

textured animated quads working

#

zig shader too

#
const std = @import("std");

extern var uniforms: extern struct {
    transform: Mat4,
} addrspace(.uniform);

extern var position_in: @Vector(3, f32) addrspace(.input);
extern var tex_coord_in: @Vector(2, f32) addrspace(.input);

extern var tex_coord_out: @Vector(2, f32) addrspace(.output);

const Mat4 = extern struct {
    c0: @Vector(4, f32),
    c1: @Vector(4, f32),
    c2: @Vector(4, f32),
    c3: @Vector(4, f32),

    pub fn mulVec(a: Mat4, b: @Vector(4, f32)) @Vector(4, f32) {
        const ar0 = a.row(0);
        const ar1 = a.row(1);
        const ar2 = a.row(2);
        const ar3 = a.row(3);
        return .{ @reduce(.Add, ar0 * b), @reduce(.Add, ar1 * b), @reduce(.Add, ar2 * b), @reduce(.Add, ar3 * b) };
    }

    pub fn row(mat: Mat4, ind: comptime_int) @Vector(4, f32) {
        return switch (ind) {
            0 => .{ mat.c0[0], mat.c1[0], mat.c2[0], mat.c3[0] },
            1 => .{ mat.c0[1], mat.c1[1], mat.c2[1], mat.c3[1] },
            2 => .{ mat.c0[2], mat.c1[2], mat.c2[2], mat.c3[2] },
            3 => .{ mat.c0[3], mat.c1[3], mat.c2[3], mat.c3[3] },
            else => @compileError("Invalid row number"),
        };
    }
};

export fn main() callconv(.spirv_vertex) void {
    std.gpu.binding(&uniforms, 1, 0);

    std.gpu.location(&position_in, 0);
    std.gpu.location(&tex_coord_in, 1);

    std.gpu.location(&tex_coord_out, 0);

    std.gpu.position_out.* = uniforms.transform.mulVec(.{ position_in[0], position_in[1], position_in[2], 1 });
    tex_coord_out = tex_coord_in;
}
#

this is what the shader looks like for those that are curious

scarlet cloud
broken bluff
#

that would be nice

#

I am working on a generic math lib, but it uses packed structs which is not possible for extern vars in GPU to use

#

10/32 examples done

#

about to do the basic compute example next, I'm excited for this one

scarlet cloud
broken bluff
#

so far I got the GLSL program working

#

just working out some of the last bugs in the zig inline assembly

#

I'm currently getting this which is very unhelpful lol

#

oh

#

turns out I need to use a u32 vec not i32 vec

scarlet cloud
broken bluff
#

not yet

#

it will be once the zig part is done which should hopefully be sometime today

#
const std = @import("std");

fn store2d(
    comptime set: u32,
    comptime bind: u32,
    uv: @Vector(2, u32),
    pixel: @Vector(4, f32),
) void {
    asm volatile (
        \\%float          = OpTypeFloat 32
        \\%v4float        = OpTypeVector %float 4
        \\%img_type       = OpTypeImage %float 2D 0 0 0 2 Rgba32f
        \\%img_ptr        = OpTypePointer UniformConstant %img_type
        \\%img            = OpVariable %img_ptr UniformConstant
        \\                  OpDecorate %img DescriptorSet $set
        \\                  OpDecorate %img Binding $bind
        \\%loaded_image   = OpLoad %img_type %img
        \\                  OpImageWrite %loaded_image %uv %pixel
        :
        : [uv] "" (uv),
          [pixel] "" (pixel),
          [set] "c" (set),
          [bind] "c" (bind),
    );
}

export fn main() callconv(.spirv_kernel) void {
    std.gpu.executionMode(main, .{ .local_size = .{ .x = 8, .y = 8, .z = 1 } });

    store2d(1, 0, .{ std.gpu.global_invocation_id[0], std.gpu.global_invocation_id[1] }, .{ 1, 1, 0, 1 });
}
#

@novel monolith this is my zig shader for a compute kernel, though I get this error:

scarlet cloud
#

Sweet 😃

broken bluff
#

am I setting the execution mode wrong?

#

(unfortunately my program crashes entirely if I just do not set the execution mode so it is probably important?)

novel monolith
#

hey sorry about that i removed execution mode from assembler with no replacement

#

there's an open PR to use callconv tho which is the intended way

broken bluff
#

ah ok

#

that's unfortunate, I guess compute with zig shaders is not possible in the meantime then?

novel monolith
broken bluff
#

:<

#

the new changes look good, but I must ask why remove valid SPIR-V assembly instructions? I know using the language is the correct way in most scenarios, but I can write x86 assembly code that does the same thing zig code does if I wanted to

#

ok an interesting idea I have, I have no way of doing what I want in zig to get the inline assembly working. But what if I link code that does the inline assembly I need?

novel monolith
novel monolith
broken bluff
#

ah

#

yeah in that case I have no ideas outside of binary hacking, and I really don't think appending an instruction to a compiled binary is really practical lol

empty oyster
broken bluff
#

probably?

empty oyster
#

Probably to which?

broken bluff
#

I just prefer using vectors more, and in practice you would probably be using a math library and wouldn't be seeing underlying operations like @reduce anyways

#

as in [4]f32 would probably compile the same

empty oyster
#

Yeah, agreed. I haven't read up on the SPIRV backend at all so wasn't sure if maybe you had to use the Vector built-in to get the equivalent of vec4 in glsl, for example

broken bluff
#

also in general vector operations would be more optimal (assuming the spirv-opt tool doesn't promote to vectors already)

empty oyster
#

I would think they'd be the same, but this is out of my wheelhouse. GPUs are SIMD machines so I'd hope it'd be able to deduce that [4]f32 is just a vec4

broken bluff
#

hopefully, would be interesting to compare at some point

#

11/32 GPU examples done, the compute one is up

#

unfortunately zig shaders for compute will have to be added in the future and for now I just have all compute shaders for zig use the GLSL versions which is kinda gross as now you need glslang installed to run any of the examples using zig or GLSL

novel monolith
novel monolith
empty oyster
novel monolith
#

i don't know what glsl compilers generate but that sounds about right

mellow sedge
#

does the compute-uniform example crash for anyone else?

#

for me the compute pipeline just dies a few frames in causing a crash

#

with GPU debug mode on it says something about the piepline handle not being valid

mellow sedge
#

it turns out I made a dumb mistake

#

I used defer instead of errdefer

#

so the pipeline in init gets freed a few frames in

#

bc of how long it takes Vulkan to free the pipeline handle

broken bluff
#

12/32 GPU examples done

coarse hamlet
#

I'm trying to move my project from Zig 14 to 15 but I'm having some issues, before it worked just fine now it crashes as soon as it opens a window, I included my logs for both running and debugging it in sdlvk.txt

spiral granite
#

That's actually nice: in debug mode it inserts a breakpoint so if you run under a debugger, you'll stop at that point and be able to examine memory and see what the issue is. Just a couple lines above line 689 in posix.zig will show the condition where it decides to break/exit.

coarse hamlet
#
debug.zig
70        pub fn castToNull() noreturn {
71                    @branchHint(.cold);
72                    call("cast causes pointer to be null", @returnAddress());
73        }
main_callbacks.zig
182        pub export fn SDL_AppEvent(
183            app_state: ?*anyopaque,
184            event: *c.SDL_Event,
185        ) callconv(.c) c.SDL_AppResult {
186            if (@hasDecl(root, "event")) {
187                const ret = root.event(@alignCast(@ptrCast(app_state)), events.Event.fromSdl(event.*)) catch |err| {
188                    std.log.err("{s}", .{@errorName(err)});
189                    if (@errorReturnTrace()) |trace| {
190                        std.debug.dumpStackTrace(trace.*);
191                    }
192                    return c.SDL_APP_FAILURE;
193                };
194                return @intFromEnum(ret);
195            } else return c.SDL_APP_CONTINUE;
196        }
#

looks like its some kind of alignment issue

azure stream
#

I'm trying to use HLSL for my shaders, but having trouble getting them to build on macOS. I thought it was something I goofed but trying the gpu_examples with zig build run -Dexample=compute-uniforms -Dshader_format=hlsl results in the same error: SDL3: [Error:General] Shadercross was not built with DXC support, cannot compile using DXC! error.

Is HLSL not supported on macOS?

empty oyster
#

HLSL is made for DirectX so possibly not

broken bluff
broken bluff
coarse hamlet
broken bluff
#

ok, I'll have to see if I can reproduce it later

coarse hamlet
#

I rewrote a part of my project without main callbacks and its working, so the problem seems to be something with main callbacks. My guess is its some weird function pointer aligning/casting inconsistency on windows, I might try to booting up one of my linux machines and seeing if my project works any different on there

#

also idk if anyone else has tried using this library with snektron's vulkan binding but they work together pretty well

empty oyster
coarse hamlet
#

Its a theme lol

broken bluff
#

the tonemapping example is surprisingly in depth there's a lot of shaders and I need a way to load an HDR texture

#

I could just add stb image like the C code does but should I

#

also why doesn't SDL image support HDR lol

empty oyster
#

I'm having a strange behavior and wondering if others have encountered the same before. Each time I build my app it crashes at the same time the first time I run the program and then it stops after that. Anyone encounter something similar before?

Illegal instruction at address 0x7ff67b197acf
C:\Users\user\AppData\Local\zig\p\sdl-0.2.6+3.2.20-7uIn9NgjfwHH5a6HhyLHat2nHU3OP5B05QHhKJKuxEex\src\gpu\SDL_gpu.c:3223:0: 0x7ff67aef9b9d in SDL_SubmitGPUCommandBuffer_REAL (SDL3.lib)
    return COMMAND_BUFFER_DEVICE->Submit(

C:\Users\user\AppData\Local\zig\p\sdl-0.2.6+3.2.20-7uIn9NgjfwHH5a6HhyLHat2nHU3OP5B05QHhKJKuxEex\src\dynapi\SDL_dynapi_procs.h:957:0: 0x7ff67ae4de53 in SDL_SubmitGPUCommandBuffer (SDL3.lib)
SDL_DYNAPI_PROC(bool,SDL_SubmitGPUCommandBuffer,(SDL_GPUCommandBuffer *a),(a),return)

C:\Users\user\AppData\Local\zig\p\sdl3-0.1.1-NmT1QwTgIADixpCS2g5pBBON5AEfnjOox94dU0dtT-tq\src\gpu.zig:964:64: 0x7ff67ae23285 in submit (sdl3_zig_zcu.obj)
        return errors.wrapCallBool(c.SDL_SubmitGPUCommandBuffer(self.value));
                                                               ^
C:\Users\user\src\sdl3-zig\src\main.zig:273:30: 0x7ff67ae251b9 in init (sdl3_zig_zcu.obj)
    try command_buffer.submit();
                             ^
... (omitted to stay in Discord limits)
                           ^
C:\Users\user\AppData\Local\Zigup\zig\0.15.1\files\lib\libc\mingw\crt\crtexe.c:259:0: 0x7ff67ae321bb in __tmainCRTStartup (crt2.obj)
    mainret = _tmain (argc, argv, envp);

C:\Users\user\AppData\Local\Zigup\zig\0.15.1\files\lib\libc\mingw\crt\crtexe.c:179:0: 0x7ff67ae3221b in mainCRTStartup (crt2.obj)
  ret = __tmainCRTStartup ();

???:?:?: 0x7ffbdbbee8d6 in ??? (KERNEL32.DLL)
???:?:?: 0x7ffbddd28d9b in ??? (ntdll.dll)
#

Oh, it's actually happening in two different spots. Might be something I'm doing then. Still seems weird it's only happening on the very first run after each rebuild.

mellow sedge
#

I don't know sure what's happening exactly, but it looks like some issue with SDL's dynamic linker thing

#

basically SDL even when statically linked will still search for DLLs

#

if I had to take a guess for some reason that table isn't being populated correctly

nimble stag
empty oyster
empty oyster
nimble stag
empty oyster
#

zig fetch --save git+https://github.com/Gota7/zig-sdl3#v0.1.1 (from the README) resolves to the same commit that I already have in bulid.zig.zon

GitHub

Zig wrapper for SDL3. Contribute to Gota7/zig-sdl3 development by creating an account on GitHub.

#

Should I go with zig fetch --save git+https://github.com/Gota7/zig-sdl3#zig-master and make whatever changes necessary with the API changes in zig-sdl3

hazy marsh
#

ìs it possible to use @sqrt with zig shaders?
error: TODO (SPIR-V): implement unary operation 'sqrt' for vulkan os

#

Was trying something with the gpu examples

stark elk
#

you can do an approximation

#

something like:

inline fn sqrt(x: f32) f32 {
  //TODO check and handle x <= 0
  //TODO check and handle x == 0
  var s = x;//initial guess
  inline for (0..3) |_| {
    s = (s + x/s) * 0.5;
  }
  return s;
}
#

adjust the amount of iterations depending on what you use as initial guess, the range of given x and the required precision

stark elk
hazy marsh
#

i feel like adding sqrt to the vulkan spirv should be trivial

hazy marsh
#

is it just the 0.5?

stark elk
#

i will check when i get home

stark elk
# hazy marsh does a similar approximation exist for cbrt?
/// returns the next approximation of x := base^(1/q)
pub fn iterateRoot(F: type, base: F, q: usize, x: F) F {
    switch (q) {
        0 => unreachable,
        1 => return base,
        else => {
            const w = 1.0 / @as(F, @floatFromInt(q));
            return (1 - w) * x + w * base / naturalPower(F, x, q - 1);
        },
    }
}

i think that weights like this will be ideal, however the convergence gets worse quickly for higher values of q.
There are probably other approximations that converge faster, but i would have to look those up

mellow sedge
#

I did update SDL3 since the last tagged release, and zig-master I don't think is maintained anymore?

empty oyster
#

That worked, though, by the way

kind hazel
#

has anyone done dear imgui with zig-sdl3?

mellow sedge
#

oh wait

empty oyster
#

Sounds good, I'll abandon the PR

mellow sedge
#

you mean to remove the zig-master

empty oyster
#

Oh

mellow sedge
#

sorry I misread the PR

#

yeah I'll merge it

royal crow
royal crow
royal crow
#

One thing I don't like about it is the additional SDL3 dependency in the project (i.e. needing both castholm/SDL and Gota7/zig-sdl3), when zig-sdl3 already depends on SDL. I couldn't find a way to set the include path of the ImGui source to point to the SDL source that is inside zig-sdl3. Does anyone know if it's possible?

stark elk
#

@mellow sedge i wrote some little helper functions that lets me write shaders like this:

const gpu = @import("gpu.zig");

pub const vertex_index = gpu.ptr(u32, .input, "vertex_index");
pub const uv = gpu.ptr(@Vector(2, f32), .output, "uv");
pub const position = gpu.ptr(@Vector(2, f32), .output, "position");

fn main() void {
    gpu.location(uv, 0);

    position.* = switch (vertex_index.*) {
        0 => .{ -1, -1 },
        1, 4 => .{ 1, -1 },
        2, 3 => .{ -1, 1 },
        5 => .{ 1, 1 },
        else => unreachable,
    };
    uv.* = position.*;
}

comptime {
    gpu.main(main, .vertex);
}
``` this compiles to spirv target with the correct callconv and addrspace. But it can also be imported when compiling for the cpu. So one could do comptime pipeline checks like this:
```rs
const std = @import("std");
const expect = std.testing.expect;
const gpu = @import("shaders/gpu.zig");

const Canvas = @import("shaders/canvas.vert.zig");

test Canvas {
    try expect(@typeInfo(Canvas).@"struct".decls.len == 3);
    try expect(gpu.AddressSpace.from(Canvas.vertex_index) == .input);
    try expect(gpu.AddressSpace.from(Canvas.uv) == .output);
    try expect(gpu.AddressSpace.from(Canvas.position) == .output);
}
#

I now your were looking into comptime pipeline checks in the past. Did you find a satisfying solution?

#

Might this be of help to you?

broken bluff
#

@stark elk I did end up finding a solution in the old repo, but this appears to be a lot cleaner assuming I can generate the gpu.ptrs with comptime schenanigans

stark elk
#

points i am still looking into, with what i currently got

  • gpu.ptr to not need a name
  • automate gpu.location calls
broken bluff
#

I was able to kinda automate the location calls

#

For comptime checking with shaders I'll probably have you use a function to call another function with the inputs as parameters and outputs as a struct and do some magic on how I call the function

stark elk
#

i would try to require vertex outputs and fragment inputs to be in the same order. That way one can just iterate over the decls and compare if the count and types match 🤔

#

i will try that today and report back 👍

broken bluff
#

That'll be cool

stark elk
#

i didnt quite get to the prototype yet. i got side tracked by a couple of simplifications :)

stark elk
#

prototype vertex/fragment compatibility check:

pub fn checkVertexFragment(Vertex: type, Fragment: type) !void {
    const outputs = decls(Vertex, .output);
    const inputs = decls(Fragment, .input);
    if (outputs.len != inputs.len) @compileError("vertex outputs must match fragment inputs");
    inline for (outputs, inputs) |o, i| {
        if (o != i) @compileError("vertex outputs must match fragment inputs");
    }
}
mellow sedge
#

I really need to extend the template to support Android and Emscripten

#

I think that'll be my next goal after the GPU examples

#

haven't had much time or the motivation to work on the GPU examples much lately bc I ran into the tonemap example

#

which is surprisingly involved

#

I might just skip it for now

#

save it for last

broken bluff
#

13/32 GPU examples done

broken bluff
#

14/32 GPU examples done

#

almost halfway

#

also added a new shader format to the examples, .hsl_runtime

#

now normal .hlsl will just compile the HLSL shaders to SPIR-V using glslang

#

as I imagine there is probably an audience for people who want their shaders procompiled but still written in HLSL

scarlet cloud
#

This is so awesome!
In your experience is there any obvious benefit of hlsl over glsl? So far I only used the latter 😃
Also are you planning for an example for a compute shader?

broken bluff
# scarlet cloud This is so awesome! In your experience is there any obvious benefit of hlsl over...

from my experience I think it's just personal taste looking at the shader code I ported from HLSL to GLSL and zig, I like GLSL the most. I'm used to it more, nothing scientific. Though I really like how HLSL has explicit inputs and outputs. There are compute shaders on the shadercross branch working already, just not zig variants as they are not currenly possible due to compiler breaking support for compute shaders

#

though when it comes to personal projects I'll use zig for everything as having reflection for checking and having all code in the same language is nice

left umbra
#

ButtonFlags in mouse.zig needs all the enum instances (c.SDL_BUTTON_LEFT etc) wrapped with c.SDL_BUTTON_MASK(...) in toSdl() and fromSdl(), the enum is 1,2,3,... and the mask fn handles the shifting to 2,4,8,...

#

can make GH issue in 12h if you want it there instead of a random discord message

broken bluff
#

Yeah pls make an issue

#

Thnx for the heads up

left umbra
mellow sedge
#

I really want to get this done before the end of the year to keep up with my own goals for personal projects, so here is what I want to do:

  • September - Finish porting GPU examples from SDL
  • October - Finish shadercross, runtime HLSL example, and zig shader reflection example. Update the template project to work for Android and Web
  • November - Release 1.0.0
  • December - Release 1.1.0 + 1.2.0
glacial smelt
#

this isnt to do much with SDL3 but you guys are definently they right people to ask, when making a spirv shader do I need just a function like

pub fn vert() callconv(.spirv_vertex) void {}

Or do I need to make an entire module in the build system?

mellow sedge
glacial smelt
#

thx

#

I see

#

one thing why are you using allocPrint you can use b.fmt

mellow sedge
#

I didn't know it existed'

#

I will note that for the future

glacial smelt
#

👌

mellow sedge
#

I found out I started this project August last year man it went by so quick I didn't know I worked on this for over a year 😿

low lantern
#

I just found this project. looks really cool! I am relatively new to zig. I struggle a little with translating the build.zig line:

lib.root_module.addImport("sdl3", sdl3.module("sdl3"));

...into something working in an init zig project. The screenshot shows how I attempted to do it and the error. But I miss some basic concept understanding of the whole build.zig file.

Can anyone pinpoint how I can fix this?

The main.zig file has this as the very first line which is what seems to break:

const sdl3 = @import("sdl3");
boreal tulip
#

Add the import to exe.root_module if you want to use it from main.zig, mod applies to root.zig and its subfiles, but not main.zig

low lantern
#

wow, thanks! window is now showing!🙏

broken bluff
#

15/32 GPU examples done

broken bluff
#

16/32 GPU examples done

#

finally halfway there

ancient crow
#

does anyone have any examples of build.zig for the master branch of zig?

low lantern
# broken bluff finally halfway there

thank you for doing all this work! I am a total rookie in zig as well as c and sdl and I find it hard to follow c examples as I simply don't have enough knowledge in this area. making a zig version really lowers the bar for ppl like me

broken bluff
#

np

#

I'm currently 17/32 examples done

#

each zig example file is standalone too, so assuming you have the shaders and build system in place it's just copy paste

#

better alternative than a mega-executable with all the examples

low lantern
#

I have nothing in place - but I would like to learn about shaders so all this sounds really nice

hidden marsh
#

Nice project @broken bluff
I have a doubt,
In C we have SDL_GetPointerProperty
This function returns a property pointer,
In C, we can then override and we can then set the callback, How to set the pointer callback in zig? Can we just do it through property.pointer.callback = ? will this be fine?

broken bluff
#

what function are you talking about?

hidden marsh
#

Can I use setPointerPropertyWithCleanup?

#

Like, is this used to set a callback as well?

hidden marsh
broken bluff
#
fn testPropertiesCleanupCb(user_data: ?*void, value: *std.array_list.Managed(u32)) void {
    _ = user_data;
    value.deinit();
}

...
    try group.set("a", Property{ .number = 5 });
    try group.set("b", Property{ .boolean = false });
    var arr = std.array_list.Managed(u32).init(std.testing.allocator);
    try arr.append(8); // Ensure no memory leakage.
    try group.setPointerPropertyWithCleanup("c", std.array_list.Managed(u32), &arr, void, testPropertiesCleanupCb, null);
...
#

an example @hidden marsh

#

and when you get a property in zig, it will return a tagged union

broken bluff
#

ye np

#

18/32 examples done

#

just finished the MSAA one which I imagine will be useful

#

Done (25/32):

  • Clear Screen
  • Clear Screen Multi-Window
  • Basic Triangle
  • Basic Vertex Buffer
  • Cull Mode
  • Basic Stencil
  • Instanced Indexed
  • Textured Quad
  • Textured Animated Quad
  • Clear 3D Slice
  • Basic Compute
  • Compute Uniforms
  • Draw Indirect
  • Compute Sampler
  • Copy And Readback
  • Copy Consistency
  • Texture 2d Array
  • Triangle MSAA
  • Cubemap
  • Window Resize
  • Blit 2d Array
  • Blit Cube
  • Blit Mirror
  • Generate Mipmaps
  • Latency

Not Done:

  • Tone Mapping
  • Custom Sampling
  • Depth Sampler
  • Compute Sprite Batch
  • Pull Sprite Batch
  • Texture Type Test
  • Compressed Textures
hidden marsh
#

Do we have a SDL_SetStringProperty implementation?

hidden marsh
broken bluff
#

yes, you have .set

hidden marsh
#

but, it takes property as a value?

broken bluff
#

yeah, you give it the tagged union you want

#
    try group.set("trial", Property{ .string = "Hello World!" });
hidden marsh
#

Also, SDL_itoa?

broken bluff
#

don't use that

hidden marsh
#

ok, thanks

broken bluff
#

in zig you should just use format strings and printing instead

broken bluff
#

aw man, one of my hacky tricks doesn't work when going through the optimizer :<

#

since you can't hold opaque types, to sample twice I just have you call the function twice

#

unfortunately that falls apart if you put it through the optimizer...

broken bluff
#

I can't have you do all the samples at once in the function for N amounts bc idk how to have a programmatic number of contraints...

#

So unfortunately I'd have to have one big inline block that does all the sampling

#

Or just not use the optimizer for this one

#

If only the UVs were not runtime only known and different from each other, then I could build the assembly string

#

Wait what if I type the uvs in inline assembly as a pointer to vec2's

#

Then in select the proper index based on the count maybe in a loop or something

#

That could work

#

Or just an array or something

stark elk
#

could you just have the inline definions once at the start of each shader? to avoid that error? (i dont really know what i am talking about though 🙊 )

mellow sedge
#

unfortunately you can't declare variables in one inline assembly block and then use them in another, I tried it

#

and since these are SPIR-V specific opaque types I can't really save an "OpTypeImage" to a zig variable to use later

#

so in order to be valid SPIR-V and zig code, all the sampling must be done in the same inline block as "OpTypeImage"

#

I wonder if there is a flag I can pass to the optimizer though that would make it less pedantic, but I doubt it

#

OH actually, I can do --remove-duplicates to "Removes duplicate types, decorations, capabilities and extension instructions" and --validate-after-all to "Validate the module after each pass is performed." I might also need to add --skip-validation to not validate the SPIR-V before optimizing. It warns I should use this option with caution but I think I know what I'm doing

#

basically I'm thinking I can be clever and run a pass of the optimizer tool to remove the duplicate types, then run another pass of the optimizer to properly optimize

#

so my silly sampling function might be practical to use after all

stark elk
#

another idea would be to make the inline assembly variable names depend on bind and set. Or maybe even pass @src() to every call like with dvui. 🤔

mellow sedge
#

that wouldn't work

#

the problem isn't the names, in fact the names are per each inline assembly call and get turned in to IDs

stark elk
#

oh i see >.<

mellow sedge
#

the problem is that you can't declare the same type twice

#

while the SPIRV does work and indeed I tried it, I guess it's against spec

stark elk
#

oh that is annoying

#

those 2 rules kinda force you to write a single custom asm block. >.<
(if it werent for the 🪄 you found)

mellow sedge
#

yeah, I'll definitely try it when I'm at my PC tonight I got worried that I would have to mandate some ugly inline assembly...

#

I'd rather just have me write some ugly assembly once and then anyone could copy-paste the function

broken bluff
#

yep that works :>

broken bluff
#

noooo

#

@novel monolith is there a work around for now?

#

oh it looks like I can just do OpCapability ImageQuery in SPIR-V assmbly directly for now, epic

broken bluff
#

man

#

unfortunately the depth cube sampler won't work properly in zig :<

#

unfortunately, since I need to write to the fragment depth I need to set the execution mode, which is currently impossible...

#

evil idea, what if using SPIRV tools disassemble the SPIRV, replace the execution mode, then reassemble it

#

hmmmmmmmmm

#

that way I could also do compute shaders in zig too

broken bluff
#

there we go, I did it with black magic

novel monolith
#

nice

broken bluff
#

just pushed it up now

#

it is so cursed

#

I run the output SPIRV into a disassembler, then run a custom build tool on it that adds the execution mode, then assembles the SPIRV back and then optimizes it

#

later I'll try seeing if I can use this method to get compute kernels working on the current zig version

#

as far actual practicality goes for a project on this method, idk I feel like it's perfectly viable. Definitely a hacky workaround, but if you're dealing with zig shaders you should have spirv-tools installed anyways for optimizing so ensuring you have the disassembler and assembler tool just sitting around isn't too far fetched

#

I don't recommend using zig for shaders really, however I am the stubborn I want zig to run on everything including my GPU, and love the compile time stuff that can be done

#

my goal with these examples is to prove that using zig shaders for real graphics dev is viable, even if not really practical or clean

novel monolith
#

yeah the state is unfortunate rn. i'll try to rebase that PR (as soon as im free) and bug mlugg again to review it

broken bluff
#

thnx, I really hope it is in the next release

#

I'm just glad I found a workaround even though it's really hacky

#

now I can probably do compute kernels too

#

which I'm excited about

scarlet cloud
hidden marsh
#

How does SDL_PeepEvents work, is it sdl3.events.peep? But it only takes 3 arguments?

broken bluff
broken bluff
#

HA GOT ZIG COMPUTE KERNELS WORKING LET'S GO

broken bluff
#

got the gradient example working too with some more inline assembly help

#

luckily the extension inline assembly just worked, I'm happy about that

broken bluff
#

there we go, pushed

#

now all the examples that are finished that involved compute kernels now have zig versions of the compute kernels as well

#

I'm just happy all of this is possible I didn't expect this to work at all lol

broken bluff
#

I'm sorry, am I getting a miscompilation????

#

YEP

#

it works fine in release fast

#

it's a miscompilation

broken bluff
#

another subtle bug

#

this is not correct behavior

#

almost done with this zig shader though, once I finish this example I'll submit these bugs to the zig issue thing

polar sigil
broken bluff
#

sorry I still need to review I should probably do that I keep forgetting

potent fern
#

I tried getting SDL_cross working yesterday, using bits and pieces stolen from your WIP branch, and the DXG stuff was causing me huge pains. Is that at all in progress now, or is it todo, or did I just rip off your code the wrong way? 😄

#

(I'm not making a competing spirv cross. I just looked at your code and jiggled it a bit and stuck it in my own local project to try to get some of the code sample stuff working. so "stole" is a joke)

broken bluff
#

no worries

#

I haven't done the DXC stuff yet

#

as a personal opinion you don't need runtime HLSL source support (which is what DXC is for) unless you want to support hot-reload shaders

#

I don't know any other reason where it wouldn't be advantageous to pre-compile your shaders to SPIR-V

#

and if hot reload is for development purposes, then you could just have the reload run your system's shader compiler anyways

potent fern
#

what do you use instead? glsl?

broken bluff
#

nah you can still use HLSL, just put it through glslang or something

potent fern
#

I was attempting to get my shaders to recompile at build time with zig build, without using any stuff installed on the OS.

broken bluff
#

ah I see yeah I definitely should make a GPU template that has a shader compiler build tool using shadercross

#

this is a legit use

potent fern
#

Also, I was starting with what was in the SDL gpu examples project, and they start with HLSL, and cross compile to support all targets (SPIRV, Metal, and DXIL I think?) so I was seeing if that was possible with zig build.

#

I think DXC is the big blocker for that on your shader cross build implementation? Is that correct?

TBH I would be happy with any textual shader format that supported all features. So GLSL would be fine as an input. I am much more used to GLSL than HLSL anyway.

For some reason, the hacky SDL_Cross cli implementation I threw together (with some of your code bits for help) still complained it couldn't take GLSL as an input. I only managed to get it working with SPRIV input.

I didn't end up pulling in the vulkan headers tho. Maybe that + some preprocessor define was required to get the SDL_Shadercross cli to accept GLSL inputs, and they just have bad error messages when everything isn't linked and enabled.

broken bluff
broken bluff
#

v0.1.3 has been released

#

Updated sdl3 and some bugfixes and improvements

broken bluff
#

If anyone wants to contribute pls help me figure out why custom allocators do not work I am so confused KettuCry

nimble stag
broken bluff
#

WAIT REALLY

#

that was my mistake?? holy shot thanks

#

I never would of caught that

#

you don't know how long I've been staring at these

nimble stag
#

on master it also seems to cause the compiler to hang, possibly because of the while loop used to calculate size and alignment

#

I rewrote it like this and now it works, it also makes use of remap. I think it's correct but I can't promise for sure, either way you're completely free to steal and adapt it however you'd like

#
const Allocation = extern struct {
    size: usize,
    data: void align(@alignOf(std.c.max_align_t)),
};

fn makeAllocation(size: usize, zero_init: bool) ?[*]u8 {
    const bytes = custom_allocator.allocWithOptions(u8, @sizeOf(Allocation) + size, .of(Allocation), null) catch return null;
    if (zero_init) @memset(bytes, 0);
    const allocation: *Allocation = @ptrCast(@alignCast(bytes.ptr));
    allocation.size = bytes.len;
    const mem: [*]u8 = @ptrCast(&allocation.data);
    return mem;
}

fn allocMalloc(size: usize) ?[*]u8 {
    return makeAllocation(size, false);
}

fn allocCalloc(nmemb: usize, size: usize) ?[*]u8 {
    return makeAllocation(nmemb * size, true);
}

fn allocRealloc(mem: ?[*]u8, size: usize) ?[*]u8 {
    const old_mem = mem orelse return allocMalloc(size);
    const old_data: *align(@alignOf(std.c.max_align_t)) void = @ptrCast(@alignCast(old_mem));
    const old_allocation: *Allocation = @fieldParentPtr("data", old_data);
    const old_bytes_ptr: [*]align(@alignOf(Allocation)) u8 = @ptrCast(old_allocation);
    const old_bytes = old_bytes_ptr[0..old_allocation.size];
    if (custom_allocator.remap(old_bytes, @sizeOf(Allocation) + size)) |new_bytes| {
        const new_allocation: *Allocation = @ptrCast(@alignCast(new_bytes.ptr));
        new_allocation.size = new_bytes.len;
        const new_mem: [*]u8 = @ptrCast(&new_allocation.data);
        return new_mem;
    }
    const new_mem = makeAllocation(size, false) orelse return null;
    @memcpy(new_mem[0..size], old_mem[0..size]);
    custom_allocator.free(old_bytes);
    return new_mem;
}

fn allocFree(mem: [*]u8) void {
    const data: *align(@alignOf(std.c.max_align_t)) void = @ptrCast(@alignCast(mem));
    const allocation: *Allocation = @fieldParentPtr("data", data);
    const bytes_ptr: [*]align(@alignOf(Allocation)) u8 = @ptrCast(allocation);
    const bytes = bytes_ptr[0..allocation.size];
    custom_allocator.free(bytes);
}
broken bluff
#

thank you, I will copy this and make an example showcasing the allocator

nimble stag
# broken bluff you don't know how long I've been staring at these

btw, a tip if you didn't already realize: if you build with -Dc_sdl_sanitize_c=full you will get slightly more useful messages from ubsan. in this case with a debug allocator it will say

member access within misaligned address 0xaaaaaaaaaaaaaaaa for type 'SDL_VideoDisplay' (aka 'struct SDL_VideoDisplay'), which requires 8 byte alignment
which makes it a bit easier to see that something is not getting initialized

broken bluff
#

good to know thnx, I forgot that flag existed somehow 😵‍💫

broken bluff
#

tagged a new version v0.1.4 with this custom allocator functionality

broken bluff
#

I decided that even though I want things to be one file when possible, it only makes sense to make the inline assembly stuff for zig GPU code common

#

the textured quad fragment shader now looks like:

const common = @import("common.zig");
const std = @import("std");

const tex0 = common.Sampler2d(2, 0);

extern var tex_coord_in: @Vector(2, f32) addrspace(.input);

extern var color_out: @Vector(4, f32) addrspace(.output);

export fn main() callconv(.spirv_fragment) void {
    std.gpu.location(&tex_coord_in, 0);

    std.gpu.location(&color_out, 0);

    color_out = tex0.texture(tex_coord_in);
}
#

here's a file with all the common shader code atm

scarlet cloud
broken bluff
#

Thnx :>

quartz summit
#

Oh that looks sweet

broken bluff
#

Maybe after all this zig-sdl3 stuff I'll make it full featured and PR to std.gpu

#

But given that invalid bitcode is produced in most cases I'm hesitant that it would be accepted

#

Regardless having a fully featured wrapper would be great and prevent people from needing to learn SPIR-V assembly to do anything

broken bluff
#

thanks to @atomic girder, the template now supports building for web! zig build -Dtarget=wasm32-emscripten to build

#

hopefully it works well for everyone else though :>

broken bluff
#

Android support next on the list

mellow sedge
#

GPU examples are tedious and I want to work on the other parts of GPU so I can get the shadercross branch merged as soon as possible. I could then just make issues for the unfinished GPU examples. Here is my TODO list for the rest of the month:

  • Template android support
  • GPU template that uses shadercross at build time rather than at runtime
  • GPU template that uses zig shaders and comptime checking
  • GPU runtime HLSL example (shader-toy like program with hot-reload)
  • Finish GPU examples
#

this is a lot, let's see if I can do it lol

#

though tbh the GPU template projects really are not that bad

broken bluff
#

v0.1.5 released

#

made it so many functions return tuples rather than structs

#

this is the most notable example

quartz summit
#

Cool, I've only read about doing that so far. Any observations about it?

mellow sedge
#

I think this is a lot nicer than the return structure for variables that are distinct enough and you would access frequently

broken bluff
#

GPU template work is... going lol

#

it's bc the dependency is named sdl not sdl3 I feel dumb lol

broken bluff
#

got it to run shadercross as part of the build process for the template

#

ofc I still need to work out the whole DXC thing for the build step but at least building shadercross is working surprisingly well so far, the zig build system is really cool in how you can just build a build tool and use it perfectly fine

broken bluff
#

hm any ways to build dxcompiler in zig have not been updated to 0.15.1...

#

now what

#

I could update it myself but rahhhh

broken bluff
#

Been trying to update Mach's dxcompiler to 0.15.1 but having to deal with changes to http and zstd decompression

#

Ugh

broken bluff
#

Been working on the zig shader reflection template

#

Once that's in a good state might try cleaning things up to merge into master

#

Then just make issues for things that are not fully done but seems like kinda cop out since I want everything in master to work lol

#

Could always take parts out of the pull to master I suppose

mellow sedge
#

ok what if I just make you have to have DXC installed on your system and I just use the system library

#

you should only be using DXC for dev anyways

#

plus I don't want building examples to take 10 billion years

#

plus if you want to ship something with DXC compiled into it you're doing something wrong

#

(unless what you are shipping happens to be a shader toy thing)

scarlet cloud
#

If I am only interested in glsl I do not need dxc, correct?
If so, could you make it configurable so that dxc is not a requirement when one does not use hlsl ?

broken bluff
#

yeah, it'll be configurable

#

you only need DXC for HLSL input that isn't precompiled to SPIRV

random sedge
#

Probably not specific to your project, but I find the biggest barrier to using the lib is not having lsp jump/completes into the project. I'm using zig fetch, and I'm new enough that I don't know if this is universal/fault of lsp or something else.

Any ideas on how to fix that?

left umbra
# random sedge Probably not specific to your project, but I find the biggest barrier to using t...

First is making sure your ZLS version corresponds to your Zig version, since Zig moves fast and breaks stuff often, ZLS has to move just as fast. If you go to https://zigtools.org/zls/install/ it will let you enter your zig version string and give you a download for that exact matching ZLS version. If you are using VSCode, set it up settings for the zig ext to use your copy of Zig and the version of ZLS that you downloaded instead of copies the ext manages. One other thing making it not work could be missing trys on instance creation, the lib has a lot of falliable fns and ZLS typically won't pop up suggestions on results that haven't been error-unwrapped.

broken bluff
#

Yeah lsp works fine for me

broken bluff
#

Putting this project on hold bc I'm running out of motivation and burning out

#

Has been over a year of working on this after all :p

thin prism
broken bluff
#

thnx :> I will return will just be some time

celest lion
#

@mellow sedge just wondering if you still need a build of dxc? I took a crack at porting latest dxc version and it seems to be working

mellow sedge
#

YOU GOT IT???

#

yeah that would be most helpful, if possible would you like to PR to the shadercross branch to add DXC support to shadercross? If not just just having DXC live in its own repo is great too, or some combo of both