Extent of the abstractions?

oli

New Member
Messages
3
Reaction score
1
Is anyone able to shed light on the extent of the abstractions?

Based on my first impression exploring the codebase, it appears that the majority of it consists of bindings. For example, if I were to implement a Vulkan renderer, it would essentially be 1:1 with if I was using direct bindings such as Silk.NET.Vulkan, and likewise with SDL3/GLFW for windowing. For context I'm used to frameworks such as FNA which provide things like a built in sprite batcher and methods for rendering primitives, as well as abstractions over the game's main logic update and render methods that mean you don't need to implement the loop manually.

My question is not really a criticism of BRUTAL's barebones-ness, but I do want to know what specifically this has to offer that I could not obtain by using a library such as Veldrid or the Silk.NET series of bindings, for example - as it would seem the same amount of effort would be required to build all the necessary abstractions to make a game on top of BRUTAL as it would with these libraries. It's rather hard to ascertain without much external documentation currently, so if any developer with more knowledge could give some pertinent examples I would greatly appreciate it.
 
The most visible point of difference between using the Brutal Framework and separate Vulkan and GLFW bindings is that we’ve curated a consistent experience across all our packages.

We apply the same coding standards and naming conventions, and use the same types whenever possible. For example, if two libraries both use 2D/3D vector types - you’ll notice they are they same Brutal.Numerics types and not a new set of vector types bespoke to each API (see: ImVec2).

Those same vector types mentioned are covered across all primitive types ranging from ushort to double in 2-4 components, with quaternions and matrix types in various sizes as well. These types should plug/play into your structures intuitively to make interop with graphics shaders simple as well.

We’ve created interfaces for all of our vector types that make implementing generics easier. We implement those interfaces using the latest .NET Core to make use of the latest improvements to C# and the .NET runtime.

We have new libraries on the way for high performance collections as well, one I’m personally excited for is a List type backed by custom allocators.

From here we will continue to push our interop performance to the absolute limit, while staying on the bleeding edge of .NET. And we are not afraid to break things to get the best results.
 
The most visible point of difference between using the Brutal Framework and separate Vulkan and GLFW bindings is that we’ve curated a consistent experience across all our packages.

We apply the same coding standards and naming conventions, and use the same types whenever possible. For example, if two libraries both use 2D/3D vector types - you’ll notice they are they same Brutal.Numerics types and not a new set of vector types bespoke to each API (see: ImVec2).

Those same vector types mentioned are covered across all primitive types ranging from ushort to double in 2-4 components, with quaternions and matrix types in various sizes as well. These types should plug/play into your structures intuitively to make interop with graphics shaders simple as well.

We’ve created interfaces for all of our vector types that make implementing generics easier. We implement those interfaces using the latest .NET Core to make use of the latest improvements to C# and the .NET runtime.

We have new libraries on the way for high performance collections as well, one I’m personally excited for is a List type backed by custom allocators.

From here we will continue to push our interop performance to the absolute limit, while staying on the bleeding edge of .NET. And we are not afraid to break things to get the best results.
I understand the benefit of unifying types and conventions across the bindings, but this doesn't exactly address my main point which is that the same is true in Silk.NET. For example:

Silk.NET.Maths (their roughly equivalent numerics library) types are used across all their graphics API bindings in order to unify it. As well as vectors it does cover the other important use cases you mentioned too like matrices, and integer vectors are covered by their Vector2D/3D/etc.<T>. Silk.NET targets .NET Standard instead of .NET 10, so this is maybe an avenue where BRUTAL could make improvements. Could you give some examples of modern .NET features BRUTAL takes advantage of that are of benefit?

Overall, it still seems evident that BRUTAL essentially serves exactly the same purpose as Silk.NET, which is to provide low-level bindings to native libraries as well as unifying types across all the bindings to make interop easier. I would be interested to see the high-performance collections library's feature set, but for now one of my greater concerns is the marketing. I mean, the announcement touts it as a ground-breaking step in game development, and I agree with many of Rocket's concerns about the games industry and modern engines highlighted in the Reddit post, but it seems a little dishonest for the studio to call BRUTAL a ground-breaking step in game development when the purpose it serves is one that has existed as an option to game developers for at least as long as Silk.NET 2.0 has been around.
 
Ah gotcha. To be honest, I don’t even want to compare cards with Silk 2.x because I’m sure they’re doing even better things in Silk 3 - likely on a more modern .NET as well. I try not to look closely at other people’s work because comparison is the thief of joy, and I certainly don’t want to steal other people’s ideas.

To confirm part of what you just said, perhaps we can agree that Silk.NET prioritizes compatibility; whereas I believe Brutal’s point of difference will be our hyper-focus on performance, and staying on the bleeding-edge of .NET (and in some cases push further).

We’ve seen improvements year-on-year in Brutal with the aggressive adoption of newer .NET versions ever since we started building Brutal for our projects on .NET 6. This includes the latest language features of C# that improve extensibility (instance and static extensions) or reduce allocations (automatic stack allocation or allocation-free params keywords), high-performance libraries and interfaces from .NET (improvements to ref structs like Span/ReadOnlySpan), and yearly improvements to source generators that give us the ability to build an interop layer with zero runtime marshaling.

Part of the reason we started Brutal is that we decided we wanted to own our tech stack all the way down to how the native binaries are built - and to not let anyone else set the pace for how quickly we move forward. That means we’re also okay with breaking things, which is part of why we haven’t open sourced up until now.
 
Ah gotcha. To be honest, I don’t even want to compare cards with Silk 2.x because I’m sure they’re doing even better things in Silk 3 - likely on a more modern .NET as well. I try not to look closely at other people’s work because comparison is the thief of joy, and I certainly don’t want to steal other people’s ideas.

To confirm part of what you just said, perhaps we can agree that Silk.NET prioritizes compatibility; whereas I believe Brutal’s point of difference will be our hyper-focus on performance, and staying on the bleeding-edge of .NET (and in some cases push further).

We’ve seen improvements year-on-year in Brutal with the aggressive adoption of newer .NET versions ever since we started building Brutal for our projects on .NET 6. This includes the latest language features of C# that improve extensibility (instance and static extensions) or reduce allocations (automatic stack allocation or allocation-free params keywords), high-performance libraries and interfaces from .NET (improvements to ref structs like Span/ReadOnlySpan), and yearly improvements to source generators that give us the ability to build an interop layer with zero runtime marshaling.

Part of the reason we started Brutal is that we decided we wanted to own our tech stack all the way down to how the native binaries are built - and to not let anyone else set the pace for how quickly we move forward. That means we’re also okay with breaking things, which is part of why we haven’t open sourced up until now.
Fair enough. I do agree that prioritising modern .NET is extremely important, and engines like Unity lose out on performance a lot by being stuck on legacy versions. As before I'm excited to see high-performance libraries tailored to game development, and potentially the emergence of people writing higher-level frameworks that use BRUTAL as a base, I hope.
 
Back
Top