[HN Gopher] Mach v0.1:  Cross-platform Zig graphics
       ___________________________________________________________________
        
       Mach v0.1:  Cross-platform Zig graphics
        
       Author : andreafeletto
       Score  : 153 points
       Date   : 2022-03-27 10:36 UTC (12 hours ago)
        
 (HTM) web link (devlog.hexops.com)
 (TXT) w3m dump (devlog.hexops.com)
        
       | Const-me wrote:
       | Good article, 1 comment, still.
       | 
       | > slugging through the depths of hell where only a footnote from
       | Raymond Chen himself will save you
       | 
       | The behavior is well documented: https://docs.microsoft.com/en-
       | us/cpp/build/x64-calling-conve...
       | 
       |  _the caller must allocate memory for the return value and pass a
       | pointer to it as the first argument. The remaining arguments are
       | then shifted one argument to the right. The same pointer must be
       | returned by the callee in RAX_
        
         | Andoryuuta wrote:
         | My memory on this specific issue is a bit fuzzy, but as far as
         | I remember the issue was regarding the definition/ABI
         | compatibility of C++ member functions. The doc you linked
         | aren't really clear what to do in the case of C++ member
         | functions, as they always take a hidden "this" class instance
         | pointer as the first argument (in MSVC). So which one is passed
         | first when you have both?
         | 
         | If you look at godbolt/or disassembly output of an MSVC
         | compiled binary, you can find that it is actually passing the
         | class pointer first, then the return value pointer. Which
         | definitely doesn't match the absolute "the caller must allocate
         | memory for the return value and pass a pointer to it as the
         | first argument" statement from their own docs.
         | 
         | Prior discussion about this at
         | https://news.ycombinator.com/item?id=29613640
        
         | Jasper_ wrote:
         | This is also fairly standard as a calling convention as well?
         | The Itanium C++ ABI (the standard for x64 on Linux) has the
         | same text: https://itanium-cxx-abi.github.io/cxx-
         | abi/abi.html#non-trivi...
         | 
         | So either there's some extra COM consideration I'm not aware
         | of, or there's a serious confusion in how calling conventions
         | work. If someone returns an aggregate, what option do you have
         | _other_ than a pointer? If it 's a callee-allocated pointer,
         | what are the lifetime rules and how do you free it? Passing
         | caller-allocated storage is the obvious answer and is far from
         | unusual, or undocumented.
         | 
         | The difference I can tell between the MSVC and Itanium C++ ABIs
         | is just that MSVC uses "this, ret" order for methods, and
         | Itanium uses "ret, this". There's probably some subtle
         | differences in what constitutes "non-trivial" between the two
         | ABIs as well.
        
           | Const-me wrote:
           | Apparently, the OP's issue was ABI incompatibility between
           | VC++ (also used by Windows SDK and everything built on top,
           | including Direct3D 12), and System V (used on Linux, also
           | MinGW on Windows).
           | 
           | VC++ documentation says structures are returned through a
           | caller-allocated pointer. Pretty sure modern VC++ optimizes
           | that thing when it can, especially with link time code
           | generation enabled, but for functions and COM methods
           | imported from DLLs that's not an option.
           | 
           | System V http://c9x.me/compile/doc/abi.html only classifies
           | values as MEMORY when they exceed 16 bytes. The
           | D3D12_CPU_DESCRIPTOR_HANDLE only has a single size_t field,
           | and therefore returned in RAX register in that convention.
           | Moreover, a structure of two size_t fields would be returned
           | in RAX + RDX registers.
        
             | Jasper_ wrote:
             | System V is only a C ABI, not a C++ ABI, so of course it
             | wouldn't cover C++-only details. What C++ ABI does MinGW
             | use on Windows?
        
               | Const-me wrote:
               | That thing is COM, which is a small subset of C++ ABI.
               | Technically it's about the same as on Windows, i.e. C ABI
               | with extra first argument for this pointer.
               | 
               | Once upon a time I made this library
               | https://github.com/const-me/comlightInterop/ The native
               | side of the interop is idiomatic C++, here's an example
               | https://github.com/Const-
               | me/ComLightInterop/blob/master/Demo... The C# side of the
               | interop is implemented through the built-in C interop,
               | here's the relevant part of the library
               | https://github.com/Const-
               | me/ComLightInterop/blob/master/ComL... I've tested Linux
               | version of that library on AMD64, ARMv7, and ARM64 CPUs,
               | but only with gcc compiler on the native side.
        
       | bsaul wrote:
       | i'm following zig's project from HN and i often see cross-
       | compilation and c/c++ mentionned.
       | 
       | Why is zig often mentionned in that context ? it seems that
       | cross-compilation and C can be achieved using llvm/clang without
       | a lot of problem ? What is zig accomplishing in that matter that
       | makes it so special ?
        
         | dralley wrote:
         | TL;DR the hardest part of cross compilation is usually getting
         | the tool gains set up to do so. Zig ships a bunch of libc's in
         | a lightweight compressed format which makes cross compilation
         | completely trivial, it handles most of the work behind the
         | scenes.
        
           | BiteCode_dev wrote:
           | How does it hande openssl ?
        
             | gpanders wrote:
             | What do you mean? It can link against OpenSSL just like any
             | other library. I don't know if OpenSSL supports static
             | builds, but if it does you can link it statically as well.
        
               | BiteCode_dev wrote:
               | For cross compilation with dynamic linking I mean.
               | 
               | Openssl is typically one you want to be kept up to date
               | with OS updates.
               | 
               | Like libc, it can be a pain.
        
         | ColonelPhantom wrote:
         | llvm/clang does not cross-compile "without a lot of problems".
         | See this post from Zig's creator:
         | https://andrewkelley.me/post/zig-cc-powerful-drop-in-replace...
         | 
         | zig cc uses clang under the hood, and Zig the language is also
         | mostly based on LLVM, but zig cc ships a lot of versions of
         | libc to ensure that it can properly compile to all platforms
         | without weird linker errors.
        
         | gpanders wrote:
         | Do you have experience cross compiling? If so, you're likely
         | familiar with the headache: getting the right tool chains,
         | sysroots, compiler flags, libraries, etc. There are entire
         | businesses and open source tools whose raison d'etre is
         | providing these tool chains and making the process simpler.
         | 
         | With Zig, that all goes away. It's as simple as saying `zig
         | build -Dtarget=aarch64-linux-gnu` or `zig build
         | -Dtarget=riscv32-freestanding-none` and it just works. It's
         | pretty incredible.
         | 
         | Zig has set the bar for how cross compilation should be done
         | and all other languages should be measured against it. Rust is
         | close but is still a headache. The only other language that
         | compares at the moment (IMO) is Go.
        
           | HowardStark wrote:
           | Huh. From what you said and then a quick peek at the docs Zig
           | does seem great in that regard, but in my own experience I've
           | definitely found Rust to be equally competent.
           | 
           | What about Zig would you say makes it better? Rust has `cargo
           | build --target <triple>`
        
             | mlindner wrote:
             | From what I've heard, for Rust the difficulty comes in when
             | you're using a Rust wrapper of a C/C++ library and you need
             | to crosscompile both into the binary.
        
             | gpanders wrote:
             | Admittedly I don't have as much experience cross compiling
             | with Rust, but my experience has not been so smooth. You
             | need to install each target toolchain manually with rustup,
             | and then some tool chains require different versions of
             | Rust (e.g. the ESP32 RISC-V toolchain requires nightly).
             | Another time I tried cross compiling on x86 Linux targeting
             | Linux on ARM64, and I kept getting linking errors (or it
             | couldn't find an acceptable linker).
             | 
             | I certainly agree that Rust is much better than C/C++, but
             | it's not quite at Zig level, at least in my (limited)
             | experience.
        
             | zRedShift wrote:
             | I use Zig and cargo-zigbuild to cross-compile my Rust
             | projects. It simply works, without Docker, if I want it to
             | use older GLIBC symbols for an embedded Linux target
             | running an ancient kernel/glibc version, or if I want to
             | cross-compile to an M1 Mac from Linux. Of course, you still
             | need to provide all the pkg-config/libraries/headers for
             | the target platform, but that's simple enough.
        
             | zamadatix wrote:
             | Cross compiling for the language itself is half of it,
             | albeit a half Rust does decently well too, but Zig will
             | also cross compile C/C++ for you just as easily. The latter
             | part combined with Zig's focus on making it as 0 effort as
             | possible to do either action is what results in it being
             | talked about so much.
        
         | defen wrote:
         | Here's the problem statement in a nutshell. Consider the
         | following trivial C program:                   #include
         | <stdio.h>         #include <sys/random.h>         int
         | main(void) {             unsigned char buf[10];
         | ssize_t ret;             ret = getrandom(buf, sizeof(buf), 0);
         | if (ret != sizeof(buf))                 fprintf(stderr,
         | "getrandom() failed\n");             else
         | fprintf(stderr, "getrandom() success\n");
         | return ret != sizeof(buf);         }
         | 
         | You have an x86_64 Linux machine running glibc 2.17. Your task
         | is to compile the above program into a dynamically linked
         | executable targeting glibc 2.28 on x86_64 Linux.
         | 
         | With Zig, it looks like this:
         | 
         | 1) Download zig
         | 
         | 2) `zig cc -target x86_64-linux-gnu.2.28 random.c`
         | 
         | What would those steps look like using llvm/clang?
         | 
         | Next, try doing it from Windows 8
        
         | fastball wrote:
         | Best place to read more is probably on the Zig project website,
         | specifically this section[1] on how/why Zig's compiler is also
         | a C compiler and the benefits that provides.
         | 
         | [1] https://ziglang.org/learn/overview/#zig-is-also-a-c-
         | compiler
        
           | einpoklum wrote:
           | So, I read that, and it is vague about whether the zig
           | compiler itself compiles C, or whether it launches a C
           | compiler (cc).
           | 
           | ---
           | 
           | I will resist making the obvious reference despite having
           | said both "launch" and "zig" in the same sentence.
        
             | kristoff_it wrote:
             | https://andrewkelley.me/post/zig-cc-powerful-drop-in-
             | replace...
        
       | modeless wrote:
       | This is awesome! I was hoping someone would take WebGPU/Dawn and
       | package it up in a form that is usable outside Chromium. Building
       | it yourself is nontrivial.
       | 
       | Portable graphics has always been a big issue. Back in the day
       | OpenGL was kinda sorta portable, but in practice that never
       | worked out very well. Drivers were buggy, platforms came with
       | different versions and different extensions, Windows didn't come
       | with GL drivers by default, mobile had OpenGL ES which was
       | different. And now Apple has deprecated OpenGL so the dream of
       | portable graphics at the OS level is truly dead.
       | 
       | WebGL is the most portable graphics API that exists today, and
       | it's actually possible to use it from native code if you want
       | (using the ANGLE library) but I don't think anyone does, and
       | that's understandable. WebGPU should be different. I think there
       | are a lot of good reasons that native apps should consider using
       | WebGPU.
        
       | jimbob45 wrote:
       | What's the value added in this over RayLib? Is it just building
       | GLFW from source to dodge the dependency issues? Granted, that's
       | a lot bigger deal than I'm making it seem.
        
         | slimsag wrote:
         | raylib is awesome and a great source of inspiration for me.
         | It's definitely way more complete & comprehensive today than
         | Mach is, too.
         | 
         | Longer term, I think you'll find raylib to be better for
         | simpler applications, and Mach looking a little more like an
         | Unreal/Unity/Godot & geared towards more complex applications.
         | All speculation, though, they're both improving rather quickly!
         | 
         | The other obvious difference would be language it's written in
         | (C vs. Zig)
        
           | nightowl_games wrote:
           | > Mach looking a little more like an Unreal/Unity/Godot
           | 
           | Right now, Mach is probably something more like Bevy,
           | Magnum.Graphics or BGFX. ie: a _framework_.
           | 
           | But your post alludes that that is not the goal. That Mach
           | seeks to build asset importing, animation tools, navigation
           | system, etc? ie: A FULL GAME ENGINE!?
        
             | ModernMech wrote:
             | I'm kind of new to game dev and I'm a little confused about
             | the terminology you're using. You called Bevy a framework
             | to differentiate it from an engine, but on the Bevy website
             | they call themselves an engine. What would you say is
             | differentiation between a framework and an engine?
        
               | syntheweave wrote:
               | While I've never seen it defined this way, I think the
               | distinction comes down to this:
               | 
               | An engine deals with assets in depth, and exposes runtime
               | abstractions to them.
               | 
               | A framework does what is necessary to expose I/O and load
               | the assets, but aims to be minimally opinionated about
               | how they integrate into the application.
               | 
               | For example, in an engine you might have abstractions for
               | applying collision, physics, and rendering techniques
               | onto an image asset, so that you can achieve a useful
               | result just by configuring the data correctly. A
               | framework would give you a way to load the image and
               | display it, but leave it to you to add more detailed
               | behaviors by writing new code.
               | 
               | In effect, engines are never totally done until you have
               | a feature-complete application. Often it works out that
               | you need a scripting layer to define a certain kind of
               | asset(e.g. dialogue tree logic), and then what you have
               | is an engine extension; if the asset is defined
               | independently of the scripting system, it can be made
               | portable to another engine.
        
               | slimsag wrote:
               | I think the key difference in most people's eyes is: am I
               | interacting with this mostly through code (framework), or
               | is there a substantial amount of graphical tooling that
               | aids me (engine)?
               | 
               | I'd say Bevy today is more akin to a framework, but they
               | intend to add tooling etc. to become closer to an engine
               | later on from what I understand.
               | 
               | framework <-> engine is more of a spectrum.
        
             | slimsag wrote:
             | Yes. I don't think we need more frameworks, there are
             | already great options there.
             | 
             | The interesting thing to work on in this space is tooling,
             | so that's where we're headed: full game engine.
        
       | slimsag wrote:
       | Author here, thanks for posting!
       | 
       | Happy to answer any questions about Mach (or my experience
       | working with Zig.)
        
         | modernerd wrote:
         | What do you think of Zig so far?
         | 
         | How do you recommend people get into it, especially those who
         | don't have systems programming experience? Should you learn C
         | first?
        
           | slimsag wrote:
           | I'm super productive in Zig, I really like the language.
           | 
           | Documentation is lacking, so you're going to be reading the
           | stdlib code. There are bugs. The current focus is on building
           | the new stage2 compiler (going from C++ -> Zig
           | implementation) so there are things that need attention that
           | don't get it, yet.
           | 
           | I would not suggest anyone learn C first if they don't have
           | systems programming experience. I'd go for Zig, Rust (or Go,
           | if you just want to dip your toes into the land of pointers)
           | and depending on how comfortable you feel. If you start with
           | one and find it super frustrating, try another, the
           | difference between them is huge. You might personally feel
           | more productive in one, leading to you learning more.
        
             | jedisct1 wrote:
             | Same here. As a compiled language, I find Zig super
             | productive.
             | 
             | There's neither "magic" nor an accumulation of abstraction
             | layers. As a result, when there's a bug in my code, I can
             | quickly understand what's going on and how to fix it. This
             | is very refreshing.
        
             | modernerd wrote:
             | Thanks, this is helpful!
             | 
             | Zig appeals to me for its philosophy, simplicity, community
             | and cross-platform build tools. The main reason I haven't
             | already adopted it is the lack of docs/educational material
             | that has made getting started pretty rough for a frontend
             | dev. A lot of the existing docs seem to start with the
             | assumption that you're a lifelong C hacker who is already
             | comfortable with manual memory management, libc,
             | allocators, linking and all the rest, and that you're
             | coming to Zig to gain quality of life improvements over C.
             | 
             | I've dabbled with Rust/Go and found the docs/books much
             | more accessible. But I didn't end up feeling an affinity
             | for either language quite the same as Zig. (For Rust it was
             | the complexity/readability and sluggish compile/dev loop;
             | for Go it was the feeling that it wasn't really empowering
             | me to do much that I couldn't already do quite comfortably
             | with TypeScript/Deno, or stretching me to understand lower-
             | level programming the way I'd hoped.)
             | 
             | Thank you for zigmonthly.org and for Mach! I just sponsored
             | you on GitHub. It's encouraging to hear buzz around Zig and
             | see it being used for fun things. I'm tempted to persevere
             | with Zig and write docs/guides pitched at those outside the
             | traditional systems programming realm as I gain confidence
             | with it.
        
               | slimsag wrote:
               | Super excited for Zig to make low-level coding more
               | accessible to people outside the usual group of lifelong
               | C hackers, as you said! That's one of the reasons I am
               | betting on it.
               | 
               | Check out https://zig.news too, it's where a ton of
               | people are writing learning material / little tutorials
               | on things.
        
         | qchris wrote:
         | > There are few things in life that I am more serious about
         | than this. I dedicate ~48 hours/week to my dayjob, and
         | ~50h/week to Zig building Mach and running zigmonthly.org.
         | After three years of aggressively pushing for progress in this
         | exact way, I have no plans to slow down anytime soon.
         | 
         | This is really awesome work, and if keeping this pace works for
         | you all the better. But I just wanted to encourage you to keep
         | any eye on that, and to make sure that you're not pushing
         | yourself beyond what you're able or willing to put into it. I
         | know many members of the open source community can struggle
         | with that balance, and that many of those people would also
         | rather you building stuff like this for _1 /5n_ hours a week
         | for the next 25 years than _n_ hours a week for 5 years and
         | burn out your interest or capacity. Thanks again for building
         | this project, really cool to see!
        
           | slimsag wrote:
           | Thanks :) I'm in this for the long haul and will keep this in
           | mind.
        
         | rudedogg wrote:
         | Just wanted to say I love the style of your blog (especially
         | the little diagrams), and am looking forward to future posts in
         | the ECS series.
         | 
         | Also, I've played around with the mach-glfw-vulkan-example
         | project (https://github.com/hexops/mach-glfw-vulkan-example)
         | and really enjoyed using it to learn about Vulkan, so thank you
         | for your part in that!
         | 
         | I think you make a good case for WebGPU, and am excited to look
         | through the resources you shared - and the future of mach!
        
       ___________________________________________________________________
       (page generated 2022-03-27 23:00 UTC)