[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)