#genesis: a haxe rendering library

1 messages Β· Page 2 of 1

wicked elk
#

and what API are you using?

silk tapir
#

Haha my policy is that I'm focusing only on net/http for now, others can try it out on different libraries and see if it might work, but I want to get the most important library for my use case working correctly before I try out any others.

wicked elk
#

Okay so good news, I finally got conditionals to work after 2 days or so of headscratching

native igloo
#

πŸŽ‰

wicked elk
#

[showcase] I've finally gotten conditionals to work in the SPIR-V printer, this means that it is nearing completion! Only for and while loops need to be implemented. Everything else works :D

Other than the changes to support SPIR-V I've also spent some time into making MNSL more robust:

  • Made the main function require it has no parameters and returns void.
  • Made the input/uniform variables read-only.
  • A few other changes like the ones above that makes MNSL smarter regarding user error.
  • Added an array type instead of assuming arrayaccess on any type is valid.
  • Many bugfixes.
slender badge
#

wdym, and i'm using direct exchange apis. I've made an abstraction setup so I can mostly just map the exchange apis and use whatever exchange feed i want

#

main reason for my own app is there's nothing i've found that can do what i want x)

slender badge
#

Anything out there I want? No. Make it ourself!

wicked elk
wicked elk
#

XD

#

I love how that mindset is engrained in us haxe developers

#

lol

slender badge
#

the one i'm maining atm is bybit

#

will be the priority exchange, and will add an alternative at some point

#

don't particularly mind fees, care more about liquidity and likelyhood of exchange stability with a decent api

wicked elk
#

imagine the exchange goes down before you can place a sell order

#

and when it's back up

#

the stock has gone down 50%

#

that would be both sad and hilarious

slender badge
#

back in the day for crypto in particular, those kinds of things could happen often on popular exchanges

wicked elk
#

lol

#

i'd be so pissed

slender badge
#

they would get overloaded with traffic and didn't have the bandwidth or processing power to be able to handle the orders so your order would be placed in a queue

wicked elk
#

NOOOOOOOO

#

that is so baddd

slender badge
#

but your order could be invalid, so by the time it reached your order and it checked it. The order would get rejected because of some issue

wicked elk
#

that's dumb

#

if the queue is full, it should simply decline anyone's request and wait until the queue is fully empty again before starting to accept orders again

#

that is my opinion at least

slender badge
#

early days kind of thing

wicked elk
#

but it shouldn't even get overloaded in the first place

slender badge
#

most people who started crypto exchanges very early in the scene, are more like us. Relatively skilled people who has general knowledge but not much practical experience

wicked elk
#

that's quite literally the worst case scenario

wicked elk
#

i mean the behaviour is correct in most cases

#

on any website you would want a queue

#

but on a stock exchange?

#

the stock mutating while my order is waiting in a queue for an unspecified amount of time is asking for trouble really

slender badge
#

i didn't read up on why decisions were made, but i suspect it was more of a situation of the demand outgrew a working solution

#

and they likely didn't have the technical knowledge or team to sort it out for quite a while

wicked elk
#

i see

#

im currently waiting how one of my ideas will pan out

#

i've bought stocks in a bus company which almost filed for bankruptcy

#

they will deliver their busses this summer

slender badge
wicked elk
#

and their competition is closing down

#

so either it goes to shit or it goes very well

slender badge
wicked elk
#

as long as the "queue" is explicitly stated somewhere it's fine I guess

slender badge
#

ofc not

#

you had to find that out when market was going crazy πŸ˜„

wicked elk
#

xD of course

#

that's so dumb

#

but what do I expect

slender badge
#

early crypto scene is a lot like haxe scene

#

lots of potential

#

very little detail work

#

things are maturing, those kinds of issues rarely occur on the bigger exchanges

wicked elk
#

I'd hope so xD

slender badge
#

was fun though

wicked elk
#

i can believe so

silk tapir
#

did it ever work btw?

wicked elk
#

yes it did but the output structure changed a bit, so my search logic is broken

#

will have to probably add the --diagnostics flag

#

also, the codebase of scc didn't compile with go2hx due to an error regarding versions

#

one of the dependencies were too new for the go version that is used

wicked elk
#

conditionals and loops are now done and tested, SPIRV has reached completion! any sample should now be able to compile without any issues

silk tapir
wicked elk
#

there is no way for me to tell exactly what it is that the user requested to compile

#

I'd like to show what the files are for each library and some other info regarding times, issues, the cache, etc

#

I think it's best if there was some kind of API to easily submit these statistics to.

#

I think i'll be able to look at that flag tomorrow

silk tapir
wicked elk
nova forge
#

Lately I have been converting shaders from glsl to unity format. The weird thing regarding that is, I simply asked Claude to do the conversion, using my previously converted shaders as reference. And it works almost perfectly well. (I just had to fix one thing). The thing is: it only took, like, 10 minutes to do the shader conversion, so that makes me wonder how useful it is to actually do shader conversion with some specific script or spirv tools, when it's becoming that easy to ask some LLM to make the conversion

wicked elk
#

Sure, LLMs will be able to convert let's say 80% of shaders, but what if the shader is too large? What if there are multiple files? What if you have different kinds of shaders? What if the semantics between 2 languages are completely different? The mod operator does behave differently in some shader languages (from what I know)

The question is not "Can LLMs convert shaders", they totally can- But is it practical? You have practically no guarantees, changes need to be replicated across multiple files if they happen, loading shaders through a common API could become problematic. I could have decided to make separate shaders per graphics backend: it isn't that time consuming with LLMs but it is still an inconvenience.

#

for example: consider there are multiple vector types inside of ceramic, how would you feel if you had to replace Ceramic.Vec2() with Unity.Vec2()?

#

It's annoying but it could be a simple find & replace

#

The magic part of tooling (imo) is that things "just work"

#

If I write some code and suddenly it can run in my browser and on my phone, I will be happy.

#

Not saying that tooling is always the best solution, especially when you start layering tools over each other.

#

But, in the case of shaders, I think it is well worth it to include tools like these. Nobody should be required to depend on LLMs to convert their shaders in a reasonable time frame.

worthy badger
#

isnt this what Slang was kinda designed for-

wicked elk
#

All these projects are

#

SPIRV-Cross/Glslang

#

Slang

nova forge
# wicked elk But, in the case of shaders, I think it is well worth it to include tools like t...

Oh for sure it's always better to have reliable and automatic conversion by default, what I'm saying is that the existence of LLMs makes this less of a requirement in practice. Like, Claude can work with a lot of different files at the same time, it's totally able to convert the glsl-specific function to the hslsl equivalent, especially if you did give examples as reference. My mirror game lighting shader for Unity has been completely written by Claude from the GLSL one, except one attribute that wasn't converted properly, but something that can easily be addressed with a better prompt

#

I may still try to look at automated glsl to hlsl conversion anyway, just less useful in practice than I thought. More like a "nice to have" feature

native igloo
#

ceramic mnsl plugin when

nova forge
native igloo
#

🫑

wicked elk
#

if you only need to change shaders sometimes then marking shader cross-comp as a "nice to have" makes sense to me

wicked elk
nova forge
wicked elk
#

this is my todo

nova forge
#

Right now the minor problem I have with glsl shaders is that they are written in GLES2-style

nova forge
#

I think I should use a slightly more modern format as default version

#

I may use GLES 3.0 format as a default format (and rewrite all the default shaders in that format) at some point, and use that as a base for the conversion to HLSL (which is then embedded in some Unity-flavoured shader and so on)

#

Supporting MNSL with a Ceramic plugin is totally doable

#

I may only use the MNSL -> GLSL conversion though

#

Oh, but wait

#

it NEEDS syntax coloring in vscode (a tmLanguage file)

wicked elk
wicked elk
#

what is the default shader like?

nova forge
#

But it got some annotations to support multi-texture batching

#

But nothing that a LLM can't convert at this point

#

And Ceramic only uses vertex and fragment shaders, nothing fancy

#

You need to be able to pass uniforms, textures and attribute and that's about it

#
// ceramic: multiTexture

#ifdef GL_ES
precision mediump float;
#else
#define mediump
#endif

// ceramic: multiTexture/texture
uniform sampler2D tex0;

varying vec2 tcoord;
varying vec4 color;
// ceramic: multiTexture/textureId

void main() {
    vec4 texColor;
    // ceramic: multiTexture/if
    texColor = texture2D(tex0, tcoord);
    // ceramic: multiTexture/endif
    gl_FragColor = color * texColor;
}
wicked elk
#

yeah mnsl should have everything for that as-is

nova forge
#

Can it output GLSL #300 version ?

#

Aaannd… would it preserve comments?

wicked elk
#

first question: yes, second question: not yet

#
uniform sampler2D u_Texture;
in vec2 in_TexCoord;
in vec4 in_Colour;
out vec4 out_Colour;

void main() {
    vec4 TextureColour = texture(u_Texture, in_TexCoord);
    out_Colour = in_Colour * TextureColour;
}
// uniform
@uniform(Texture: Sampler)

// inputs
@input(TexCoord: Vec2)
@input(Colour: Vec4)

// output
@output(Colour: Vec4)

// functions
func main() {
    var TextureColour = texture(uniform.Texture, input.TexCoord);
    output.Colour = input.Colour * TextureColour;
}
#

in case you missed it, you can mess around with it here: https://mki.sh/mnsl.html (note that the uniforms/inputs/outputs you can use on the web demo are limited)

wicked elk
#

random question for anyone reading, for context I just added this:

func squared(x) -> x * x;

func main() {
    var a = squared(5);
    var b = squared(a);
}

what is your guys' opinion about arrow syntax in general (any language)?

native igloo
#

i don't really get the benefit of the arrow over the haxe style?

#

i.e why not just func squared(x) x * x;

wicked elk
#

that's a good point actually...

#

added that

#

lol

worthy badger
#

var squared = x->x*x; tro

wicked elk
#

i could add that in theory, but it would be way too evil

#
func main() {
  var someValue = 5;
  var multiply = x -> x * someValue;

  var x = multiply(5);
}

would look in the current scope when the closure is defined, check what vars are available, and then generate something like:

int __mnsl_closure_1(int someValue, int x) {
  return x * someValue;
}

void main() {
  int someValue = 5;
  int x = __mnsl_closure_1(someValue, x);
}
#

very hacky and very evil

#

i don't know if this is practical.

#

you wouldn't be able to pass the created function to another function

nova forge
wicked elk
#

yeahhh

#

i removed the arrow xd

#

now it's haxe style

#

func squared(x) x * x;

nova forge
#

You are this close to rename mnsl to hxsl

worthy badger
nova forge
worthy badger
wicked elk
wicked elk
#

was able to get spirv-dis to work in the web browser with emscripten

#

the way I did it is extremely hacky but it works

#

the highlighting is nice atleast :D

#

my favorite thing is still seeing how types get converted in real time

#

for example:

#

without:

#

just making changes and seeing how a whole bunch of systems work together to form something that is valid glsl is wild to me

#

and also how just one additional layer (the optimiser) largely changes how something behaves in the final result is also just so cooool

#

this is quite literally candy for my brain to just mess around with

silk tapir
#

Relatable

slender badge
#

what's this "estimated cost to develop" stat lol

wicked elk
#

it's based on https://en.wikipedia.org/wiki/COCOMO apparently.

The Constructive Cost Model (COCOMO) is a procedural software cost estimation model developed by Barry W. Boehm. The model parameters are derived from fitting a regression formula using data from historical projects (63 projects for COCOMO 81 and 163 projects for COCOMO II).

worthy badger
#

today i achieved something great

#

i wrote working cmake without consulting an AI

wicked elk
#

nice!

nova forge
wicked elk
#

for sure!

green palm
#

god damn it. and I thought cobalt was real πŸ˜”

worthy badger
wicked elk
#

CobaltAI, the newest release from Silicon Valley

queen thorn
wicked elk
#

Okay uhhh, small issue on the C++ target

#

so Std.isOfType is a bit weird

#

Star() is an MNSLToken

#

yet it passed the isOfType check against node?

#

wtf

#

????

queen thorn
#

does mnsltoken extend anythin

wicked elk
#

msnltoken is an enum, and so is the node

#

it's fine on hashlink

wicked elk
#

after a bit of messing around, matrices now have propper support

#

it's also smart enough to know that Mat4 * Vec3 is not valid and will cast Vec3 -> Vec4

#

and access has been changed quite a bit

#

here are some tests to get an idea of what is allowed

@uniform(matA: Mat3)
@uniform(matB: Mat3)
@uniform(arrA: Float[10])
@uniform(arrB: Vec3[10])
@uniform(arrC: Mat3[10])

// main function
func main() {
    var a0 = uniform.arrA;
    var a1 = a0[0];
    var a2 = uniform.arrB;

    var v0 = vec3(1.0, 2.0, 3.0);
    var v1 = v0.y;
    var v2 = v0[1];

    var m0 = uniform.matA;
    var mr0 = m0[0];
    var mrc0 = m0[0][0];

    var row = 1;
    var col = 2;
    var mrc1 = m0[row][col];

    var idx = 1;
    a0[idx] = 5.0;
    v0[0] = 5.0;
    m0[idx].x = 5.0;
    m0[idx].y = 6.0;
    m0[idx] = (1.0, 2.0, 3.0);
    m0[idx] = 5.0;
    a2[idx].x = 5.0;
    a2[idx][1] = 6.0;
    a2[idx] = 7.0;
    m0[idx][idx] = 4;

    var p0 = uniform.matA * uniform.matB;
    var p1 = uniform.matB * uniform.matA;
    var p2 = uniform.matA * 2.0;
    var p3 = 2.0 * uniform.matA;
    var p5 = uniform.matA * (1.0, 2.0, 3.0);
    var p6 = (1.0, 2.0, 3.0) * uniform.matA;
    var p7 = uniform.arrC[idx] * uniform.matA;
    var p8 = uniform.arrC[idx][idx] * uniform.matA;
    var p9 = uniform.arrC[idx][idx][idx] * uniform.matA;

    var m1 = mat3(
        1.0, 0.0, 0.0,
        0.0, 1.0, 0.0,
        0.0, 0.0, 1.0
    );

    var m2 = mat4(
        1.0, 0.0, 0.0, 0.0,
        0.0, 1.0, 0.0, 0.0,
        0.0, 0.0, 1.0, 0.0,
        0.0, 0.0, 0.0, 1.0
    );

    var m3: Mat3 = 6.0;
    var m4: Mat4 = 8.0;
}
#

VecN[idx] is valid too now, as long as idx is a constant

#

and yeah everything works

#

even accessing a specific row and column of a Mat3[10] as you can see

wicked elk
#
func multiply(x, y) -> x * y;
func squared(x) -> x * x;
func halfOf(x) -> x / 2;

func main() {
    var x = multiply(1, 2)->halfOf(_)->multiply(_, 3)->squared(_);
}

some people will love this, others will hate this.

#

note that haxe-like func squared(x) x * x; is also allowed

#

but the focus here is the chaining

#

very often i notice nested function calls in shaders, so this could help with readability

#

so this:

#

could be written as:

native igloo
#

i like pipe operators

queen thorn
wicked elk
#

i see

#

i also discovered that there are some things you can do that are unintentional

#

so mnsl allows pipe operators to work with any expression

#

add to that the fact you may initialize vectors with (1, 2)

#

and access them using array access

#

you get this

wicked elk
#
vec2 double_TVec2_TVec2(vec2 x) {
    return vec2(x * vec2(2));
}

float double_TFloat_TFloat(float x) {
    return float(x * float(2));
}

int double_TInt_TInt(int x) {
    return x * 2;
}

void main() {
    int x = double_TInt_TInt(5);
    float y = double_TFloat_TFloat(5.5);
    vec2 z = double_TVec2_TVec2(vec2(5));
}
#

before generics were only possible for internal functions, now they can be user-defined

#

still a bit experimental and it does need some more work (for example, in the TFloat_TFloat function is is casting to float twice, so there is something that the typer does not like)

#

but the basics work now

wicked elk
#

fixed the bugs :D

#

also works on spir-v (which isn't anything special considering that mnsl extracts separate functions out of generic functions)

#

what I also find really cool about this all is how in this example:

func double<T>(x: T): T -> x * 2;
func getX<T>(vec: T) -> vec.x;

func main() {
    var v = (5, 5) -> double(_) -> getX(_) -> double(_);
}

it gives a warning because of an implicit conversion from float->int at getX

#

it says that because it knows x * 2 will multiply TUnknown with TInt, likely resulting in TInt

#

that information is available when getX(_) is called, and just because it knows it will return a numerical value and that it will be multiplied by an int in the future, it will cast vec.x to an int beforehand

#

when doing x * 2.0 the warning magically goes away

wicked elk
#

[showcase] MNSL has gotten new language features :D

  • Pipe Operator: Code like someFunction(doSomething(1.0, 2.0), 3.0) can be rewritten as 1.0 -> doSomething(_, 2.0) -> someFunction(_, 3.0)
    The pipe operator works with any expression, so 1 + 2 -> _ + 4 is valid. You can even use vectors to chain using more than one value.
  • Support for matrices Matrices are now fully supported :D this includes initialization, assigning values and accessing values.
  • Generics MNSL now has support for user-defined generics, this helps a lot when you want to do the same operations on any data type or vector. (cool example of something the compiler can do: #1276627002022953000 message)
  • Alternative Function Syntax You can now define functions like this func squared(x) -> x * x; (or haxe-style like func squared(x) x * x)
  • Array access on vectors You can now use array access on vectors as long as the index is constant
  • Inline You can now hint the compiler to inline a function (inline func echo(x) -> x;)

Last but not least there have also been many bugfixes :D
I'd also like to thank Zanzlanz for helping me discover a bug regarding typing.

nova forge
#

I think I'm really not a fan of that pipe operator. Seems foreign, redundant and somewhat confusing to me, but I guess some will like it?

Generics are a good addition however!

wicked elk
#

It's almost like static extensions

#

it tries to solve the same problem

#

The main difference is that you can pick the argument it uses and that the operator is an arrow compared to a dot

nova forge
#

I mean, that's not the _ itself that I don't like. I just think the arrow chaining feels too foreign. My brains definitely doesn't want to read (5, 5) -> ... as a chained thing. At best it would think it's some closure syntax (which isn't the case here). someFunction(doSomething(1.0, 2.0), 3.0) is maybe theoretically less logical to read because of the inverted order of things, but it has been so common in so many programming languages that my brain prefers that. The fact that the language has two different syntaxes to mostly do the same thing is not really a good sign either imho. I'd rather have a language that sticks to a popular and common ground so that it feels natural enough for newcomers, and keep the more innovative syntax bits for things that can't be done with the regular syntax

wicked elk
#

I see what you mean

#

But a pipe operator isn't that uncommon

#

elixr, clojure, f# and many others

#

many languages have a concept which is the same without any specific operator

#

fluent interfaces specifically

#

JS devs do this alot

#

you have LINQ in c#

#

new Vec2(5, 5).multiply(2).getX()
compared to
(5, 5) -> multiply(_, 2) -> getX(_)

#

the main issue is that a dot is reserved to struct access. So this is the second best alternative IMO

#

I guess the main issue is the _ because I think if I were to just write (5, 5) -> multiply(2) -> getX() that it would already be more "acceptable" for people who are used to fluent interfaces

#

Also important to note is that there is no concept of classes, this makes fluent interfaces way harder

#

let's say i do .multiply(2)

#

that is just an int

#

Do you have any proposal to make this better?

nova forge
wicked elk
#

What If i made the underscore optional? I.e it would use the _ as the first argument if the expression isn't found anywhere?

nova forge
#

I think a more pragmatic approach could be to still use the dot syntax like LINQ, except that you give priority to vector fields if they exist

wicked elk
#

so (5, 5) -> multiply(2) -> getX()

nova forge
#

(anyway, there shouldn't be any ambiguity: if you read your Vec2().x, it's different than calling .x())

#

And your parser could recognize the difference

nova forge
wicked elk
#

in that case how would you handle var F = fresnelSchlick(max(dot(V, H), 0.0), F0);

nova forge
wicked elk
#

XD

#

oh well I'll give it a good thought

nova forge
#

I think removing the underscore and keeping the arrow could work though

wicked elk
#

Personally I want to avoid nesting

nova forge
#

It's just that the first argument, like a static extension, is always the previous expression

wicked elk
#

yeah

#

well it doesn't have to be

#

var x = (5, 5) -> double(_) -> add(5, _) -> multiply(_, _);

is also valid

#

in add it's the second argument, or in multiply it's both

#

but I guess if no _ is found I could default it to the first argument

nova forge
#

Yeah, I mean it's cool if you like that syntax. I guess that's really not my stuff

wicked elk
#

I see

nova forge
#

I'd rather either nest everything, or if that not readable enough, splitting into multiple lines and named variables is just fine to my book

wicked elk
nova forge
#

It's your language anyway, you don't have to convince me :D, you are the first and most important user of it

wicked elk
#

yeah defo, but trying to make something that is liked by more people is also an interesting challenge

nova forge
#

(that's the least one can have when designing their own language)

wicked elk
#

I am the primary user for sure, but, my goal is learning primarily

#

making something is one thing, but making something that is generally liked by people with different preferences is an even more valuable learning experience (for me personally)

#

Anyway, thank you for your input :D

wicked elk
#

[showcase] I've started a blog, feel free to read the first post here:

https://mki.sh/blog

warning: the writing style is probably pretty horrible πŸ˜… I hope to improve it, so any and all suggestions are welcome.

native igloo
wicked elk
#

oop

#

wtf

#

that is buggy

#

yeah i wrote this blogging system in like 1,5 hours

#

and the codebase is from 2023 i think

#

so i prob did not handle URL's correctly

#

will fix

wicked elk
#

fixed

native igloo
wicked elk
#

Heh

#

It does work in my instance of Firefox

#

I'll try to reproduce it

nova forge