#DARE (Danny's Awesome Rendering Engine)

1 messages · Page 3 of 1

dawn wave
#

LMAOO

#

yes

devout mesa
#

epic

feral trellis
#

I just don't render my surfaces if normals are missing kek

dawn wave
#

based

feral trellis
#

Or any of the other attributes (position, uvs, tangents)

dawn wave
#

don't waste your precious cpu cycles on them

#

should i just blindly

#

believe that all my positions + normals will be vec3f32

#

and my texcoords uh

devout mesa
#

it is invalid by gltfspec

#

to have anything else

#

If your gltf has vec4 positions or vec2 positions, you can safely delete it

#

As it is invalid

dawn wave
#

understood

#

unsigned byte normalized huh

#

eh i'll ignore it and if it becomes an issue then i'll worry about it later

devout mesa
#

the only other accessor types that are accepted are for quantized meshes

#

for example you could have positions be a vec3 of integers or unsigned integers

#

but that doesn't matter right now

#

And it is an extension so

dawn wave
#

quantuized?

#

oh optimized

devout mesa
#

quantization means you take continuous values and discretize them to save space and compute

dawn wave
#

ohhh

devout mesa
#

so you take floats which are big 4 byte values

#

and you put them into unsigned shorts

dawn wave
#

yaa that makess sense

devout mesa
#

which are epic 2 byte values

dawn wave
#

so is that the main application of stuff like sparse accessors?

devout mesa
#

you lose some precision but you can gain it back with a transform

#

I don't know

dawn wave
#

hmm i see

devout mesa
#

Mesh quantization works with regular accessors

dawn wave
#

cool ill care about that feature one day...

devout mesa
#

but it is not important now ye

dawn wave
#

kekw another rewrite incoming

devout mesa
#

I'm not even sure RT supports quantization?

#

dunno

dawn wave
#

i don't think it does?

#

indices must be given in their original form

devout mesa
#

It wouldn't make much sense anyways

#

you need to be precise when tracing

dawn wave
#

yeah

#

heh so funny problemo #2

#

how am i supposed to indicate

#

the generated normal buffer is binded to the primitive

#

i refuse to do vertex struct mainly because i wanna have the later flexibility of being able to modify all of stuff en-masse

eager chasm
#

i never understood peopl who keep attributes in separate buffers : >

dawn wave
#

iirc some nvidia slide explaining

#

you should keep your attributes in seperate suballocations

devout mesa
#

you still make a vertex struct except now you put vectors instead of attributes

eager chasm
#

both ways have their pros and cons

devout mesa
#

and no, interleaved vs separate performance is meaningless

dawn wave
#

oh kekw i might to interleaved then since it's easier

devout mesa
#

AMD recommends separate yes, but I can guarantee you will never, ever see a difference in a profiler

dawn wave
#

but wouldn't that making modifying the buffer a bit harder however?

devout mesa
#

no and you usually don't modify vertex data

#

unless you're doing per vertex dynamic displacement or ridiculously fancy stuff like that

#

that would mean rebuilding your whole BLAS every time too

dawn wave
#

i just have a realization

#

revelation

#

How can I uh

#

know what my 2 next other vertices are gonna be?

#

Can I just assume they're the next 2 in the index buffer?

#

why the fuck am i asking this

#

ofc it is am i stupid

eager chasm
#

no worries, im also asking dumb things all the time

devout mesa
#

lol

#

hold on let me get my old message

#

#1090390868449558618 message

dawn wave
#
for v in vertices {
    v.n = vec3(0, 0, 0);
}

for t in triangles {
    n = normalize(cross(t.b - t.a, t.c - t.a));
    // add the normal to each vertex such that smooth normals are generated
    t.a.n += n;
    t.b.n += n;
    t.c.n += n;
}
for v in vertices {
    v.n = normalize(v.n);
}
devout mesa
#

I still think about this from time to time

#

I realized I was fucking dumb bleakekw

dawn wave
#

what

dawn wave
#

OH KEKW

#

huston

#

we are fucked

#

aka im stupid

#

abc refers to the point

#

ok

#

🗿

devout mesa
#

yeah see

#

this is what happens usually

#

to everyone

dawn wave
#

my brain shutted off i was wondering how we were filling up all the normals

devout mesa
#

when the
when tringle has 3 points

dawn wave
#

4 pointed triangle frog_think

devout mesa
#

If a 4th vertex lies on an edge of a tringle

#

is it still tringle?

dawn wave
#

tringle enough to me

#

hm

#

how to do images

#

guys

#

i might revert back bleakekw

#

i understand way more what i was doing

#

this feels like i'm fucking around

#

nah fuck that

#

ill find out

#

im him

#

im not him

#

NAH IM HIM. God the ability to modify the gltf document is so useful. I'm able to gaslight other parts of my program that things exist when they were just generated

dawn wave
#

also I think I know why the Sponza broke

#

I didn't add support for secondary texture coordinates

feral trellis
#

I don't have support for secondary texture coordinates and my sponza loads fine...

dawn wave
#

Nono i fucked up how I was selecting accessors @feral trellis

feral trellis
#

Ohh that's why

#

Ok makes sense

dawn wave
#

I didn't explicitly state 0 for the first set

#

So that is how I got into gambling there I think

#

theoretically i could reuse my old asset system

#

but it's a hot steaming pile of mess and I like the new one I made

#

combines what LVSTRI told me with some extra stuff he would scream at me for KEKW
I'm 100% certain it is bad practice to be modifying your gltf json variable, but it works so nicely as an intermediate between gltf -> asset loader

dawn wave
#

ASSET IMPORTING WORKS!!

#

i need to get materials working

#

then we're good

#

wait it's 1am? ill just do some clean up work then

#

bleakekw It doesn't feel okay so to
vertices.map(|x| {
x as u32
}).collect<Vec<u32>>();

tropic vigil
#

eh why not KEKW

#

though if you just want to reinterpret the bits bytemuck will do that for you

dawn wave
#

god i rewritten my entire asset loader within a day bleakekw

tropic vigil
#

certainly not the last time youll do that

dawn wave
#

i have an abstraction layer that lets me make "virtual" buffers which sounds dumb as fuck but useful if I need to gaslight my asset loaders into thinking a normal buffer does indeed exist

tropic vigil
dawn wave
#

Oh KEKW my asset system is very simple

#

I like mines a lot however. Everything is passed via handles

#

which makes it really easy to refactor

tropic vigil
#

Yeah, same here

#

But the asset system has no loading logic

#

Everything revolves around

#

pub trait Asset {
    type LoadInfo: Send + 'static;

    fn load(info: Self::LoadInfo, bus: EventBus<DI>) -> Result<Self>
    where
        Self: Sized;
}
#

This trait

dawn wave
#

i should use rust traits KEKW

tropic vigil
#

yes

#

theyre amazing

dawn wave
#

I have it very traditionally where you just select a file to load then it creates a scene struct

tropic vigil
#

"what if you had the concept of interfaces but not trash"

dawn wave
#

yeah im just not used to them yet

#

i'm mainly just confused how you deal with loading stuff mid way through

tropic vigil
#

my system just handles storage and accessing of assets

dawn wave
#

ohh i see

#

that's interesting

#

KEKW that would require me to rewrite my entire loader (again)

tropic vigil
#

as i said, not the last time

dawn wave
#

AHHHH fuck it

#

Okay excuse my stupiditiy

#

Oh ait

#

I can't asj how you load scenes as you just do terrain KEKW

tropic vigil
#

it'd work the same way though

dawn wave
#

I'd assume so a Scene struct then multiple scene loaders implenenting asset

tropic vigil
#

add a Scene asset with some LoadInfo, probably a json

#

Which checks the json or gltf or whatever

#

Splits it into primitives/meshes

#

Then kicks of a bunch of loads for Mesh assets

dawn wave
#

hmm i see

#

so I guess all the metadata about the mesh is already done

#

it's just waiting on it's associated buffer to load in

#

hmmm

#

that makes sense

#

but also requires me to rework it (again) so it works with indices rather than the raw data

tropic vigil
#

yea basically once you have the metadata (quick) you can kick of a bunch of tasks for the actual meshes

dawn wave
#

AHHH fuck it

#

i should probably split up my assets KEKW they're all in one mod.rs file

tropic vigil
#

maybe

dawn wave
#

Where should you put your traits

#

Wait what should LoadInfo even have? Path to the data itself?

tropic vigil
#

it could

#
pub enum TextureLoadInfo<F: TextureFormat> {
    FromPath {
        path: PathBuf,
        // Callback to do extra processing on the image data on the CPU.
        cpu_postprocess: Option<fn(u32, u32, &mut [F::Pixel]) -> Result<()>>,
        // Additional usage flags
        usage_flags: Option<vk::ImageUsageFlags>,
    },
    FromRawGpu {
        image: PairedImageView,
    },
}

This is my loadinfo for textures

dawn wave
#

cpu_postprocess? I assume this is for stuff like normalizing, changing types?

tropic vigil
#

yep

dawn wave
#

im yoinking that KEKW

tropic vigil
#

its not amazing but it works

dawn wave
#

eh good enough for most needs

#

ahh im overengineering this

tropic vigil
dawn wave
#

Maybe I add a second layer bleakekw

#

File loading + interpretation since gltf has a bit of Base64 stuff

devout mesa
#

I am already suing you

dawn wave
devout mesa
#

Right and why do you need that

#

Why not store the info into a vector

#

What kind of info are you storing

dawn wave
#

Because I would need to more or less recreate the exact same info the gltf_json struct is about

#

Buffer view offsets, stride, view length
Accessor format, offset

devout mesa
#

What exactly is the piece of code that requires you doing this

dawn wave
#

Get normals -> if normals don;t exist, generate -> push into scene normal vector -> create buffer view into normal

devout mesa
#

create buffer view into normal
why

dawn wave
#

Cuz my asset system works like that KEKW

devout mesa
#

give me a github link rn

dawn wave
#

It’s why I;m in the middle of a rework KEKW

#

I’m not using vertex structs 😭 I’m storing everything separately

#

Oh i haven’t pushed the new gltf loader yet @devout mesa

devout mesa
#

Well then

#

do so

#

I shall give you, hmmm let's see

#

5 seconds

dawn wave
#

WAISIA my pc is still booting up

devout mesa
#

time's up

dawn wave
#

So long brothers

#

Aw fucj

#

I forgor I was refractoring it KEKW

#

Turns out I am now moving everything into vecs

#

i can push it as is

#

@devout mesa Turns out you were right I didn't need to KEKW

devout mesa
#

good

dawn wave
#

maybe i lied

#

yeah okay i lied

#

turns out i do

devout mesa
#

make it so you don't need it then

dawn wave
#

but i kinda like it

#

:D

devout mesa
#

no

devout mesa
#

why do you like it

dawn wave
#

I'm not reinventing the wheel with my structs

devout mesa
#

Not that

#

I mean the thing where you modify your gltf file

dawn wave
#

I'm modifying the json document

#

that gets imported

devout mesa
#

Yeah

#

You said you store your normals in the json document?

dawn wave
#

yeah but it's not changed on the file system whatsoever

#
let mut document = document.into_json();

I'm mainly modifying that

devout mesa
#

Why not store them in a simple vector

#

what's wrong with that

dawn wave
#

So I can have indexing as well

#

so it can work with stuff gltf has already and anything I pre-generated

devout mesa
#

I don't understand

#

you can't index into a vector in rust?

dawn wave
#

yes you can KEKW it's just that

#

wait let me show you

#

hold on

devout mesa
#

awaiting

dawn wave
#

yea wait im trying to get this one refactor to work kek

#

@devout mesa

devout mesa
#

You will now be judged

#

Please await while the judgement processes

dawn wave
#

its broken + incompleted mainly the buffer bits

#

i got sponza loading using it however i can't render it as i don't have images rn

devout mesa
#

So

#

The judgement is complete

#

The only reason you modify the JSON document

#

is because you can use it in add_attribute_to_scene

#

Correct?

dawn wave
#

think so yeah

#

KEKW I forgor to add my mesh into my scene struct

devout mesa
#

I don't like it

#

But you can do whatever you want

dawn wave
#

KEKW What would you say I do then

devout mesa
#

You could've just sent a vector..

dawn wave
#

i could've

#

maybe i should

devout mesa
#

Do you have vectors or something

dawn wave
#

Yes KEKW

devout mesa
#

You seem to have some kind of adversity against them

dawn wave
#

i think this is left over when i had to use maps from the other gltf loader

#

so there was a tiny tiny chance there would somehow be a gap

#

so i just mapped it all

#

okok ill just past it by vecs instead KEKW

tropic vigil
#

you can index into vecs just fine

#

vec[0]

#

it just panics if the index doesnt exist

#

if you want an error you use .get()

#

Theres no point in writing .get().unwrap()

#

If youre going to unwrap immediately just use []

dawn wave
#

oh yeah i should kekw

#

AHHHHHH I'm still so lost on how to make the asset system

dawn wave
#

What the hell does blob stand for

#

there is no way mfs are calling generic data loaded in blob because of the word

eager chasm
#

Asset

#

AssetSystem

#

done

dawn wave
#

genius

eager chasm
#

inspired by deccer

#

im ok with that 😄

tropic vigil
#

its just

#

blob

dawn wave
#

blob :)

eager chasm
#

binary large o bject

devout mesa
#

I don't understand one thing

#

is it that hard to make something in Rust that just works, even if it's botched together

dawn wave
#

It is easy, but I'm stupid

devout mesa
#

Like my """asset system""" literally is just a collection of vectors

dawn wave
#

also I overthink things

devout mesa
#

I'd say Rust makes it harder to write dumb things and expects you to write prim and proper code, but is it actually this bad

dawn wave
#

No

#

I'm just stupid lmao and don't know how to engineer

#

ask Penguin, he is more experienced

devout mesa
#

Just do the thing and make it work

#

Do the simple thing first

#

Why complicate life

#

Make shrimple code

dawn wave
#

cuz why not

devout mesa
dawn wave
#

oh fuck

#

thanks for reminding me

devout mesa
#

Do you have pretty effects on screen

#

yeah

#

I wanna see you work solely on main.rchit

dawn wave
#

🤝 back to vectors we go

devout mesa
#

No rust

#

only GLSL

dawn wave
#

rust-gpu frog_think

devout mesa
#

no

#

only GLSL

dawn wave
feral trellis
feral trellis
dawn wave
#

yeah easy for everyone else

feral trellis
#

For me I have a vector that contains boxed trait objects of my Asset trait

#

Something like this

#

Vec<Box<dyn Asset>>

dawn wave
#

I'm still so lost wtf an asset trait does KEKW

feral trellis
#

Traits are implemented for rust types

dawn wave
#

eh if i can't think of a reason to use it i probably shouldn't ig

#

idk i can't think of a relevant trait and what it would have that would apply to all my assets.

#

eh whatever who cares

tropic vigil
#

but not poop

eager chasm
#

hows schbondsa coming along

dawn wave
#

its going

#

rewriting my asset system cuz KEKW

devout mesa
#

that's it

#

I'm calling China

dawn wave
#

oh fuck

#

(who is China)

eager chasm
#

😄

#

lustri has a point

devout mesa
#

If I don't see sponza

dawn wave
#

i too agree

devout mesa
#

within the next 5 minutes

dawn wave
eager chasm
#

ill give you 15

devout mesa
#

I will deport you

dawn wave
#

ok wait

eager chasm
#

without random texture selects

dawn wave
#

fuck

eager chasm
#

: >

#

i dont want to see the recycled skreenshot either

dawn wave
#

fuck

dawn wave
#

NO

#

STOP

#

I activate time reversal

devout mesa
#

where sponza

dawn wave
#

no

dawn wave
#

how to load images: don't

dawn wave
#

Should I just assume every texture is gonna be some variant of R8G8B8? plus or minus an A?

#

or should I go out of my way to ensure proper formatting, etc

#

A bit unsure how to go around materials? Ig just loop over the materials loop and assume each image referenced in it is unique

feral trellis
#

Since the material only contains like an index to whatever texture it's referencing

dawn wave
#

hmm alralr

#

Ahh the proper formatting piece is wasting so much cpu cycles bleakekw There has to be a faster way to normalized my types to 0-255

tropic vigil
#

I use rayon to parallelise it

dawn wave
#

rayon is magical

#

oh my god

#

omp if it was good

feral trellis
devout mesa
#

I am still waiting for sponza btw

dawn wave
#

lvstri is gonna hunt me down for sponza

devout mesa
#

I absolutely will and you can't hide

dawn wave
#

i am working on it pls wait

#

i have come to a brutal realization

#

materials provide you an index to your texture coordinate

#

that might be why my texture mapping was wacked

devout mesa
#

sponza has only one texture coordinate

dawn wave
#

wtf am i missing then

#

hmmm

#

texture transformations?

#

I haven't added support for that

devout mesa
#

Sponza has no texture transforms by default

dawn wave
#

that's it. im done. we're gonna make the first ever rng based gambling renderer
You keep rerunning it until your textures magically line up

#

99% of programmers stop before they hit it big

#

i geniunely have no clue why it is randomly selecting textures however bleakekw

devout mesa
#

Show me the shader

dawn wave
#

ik i f'd up the normal calculation for the world_normal if geom_normal is selected

#

but shhh

devout mesa
#

display material_resource.albedo_texture

dawn wave
#

wdym?

devout mesa
#

display a color for material_resource.albedo_texture

#

for each ID choose a different color

#

choose black for -1 or something

dawn wave
#

ohh ok uh any quick dirty algos to do it

#

KEKW eh just divide by like 10

devout mesa
#

many

devout mesa
#
vec3 hsv_to_rgb(in vec3 hsv) {
    const vec3 rgb = saturate(abs(mod(hsv.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0);
    return hsv.z * mix(vec3(1.0), rgb, hsv.y);
}```
#

You use the good old fract * GOLDEN_CONJ trick to generate random colors of a certain saturation

#

o_pixel = vec4(hsv_to_rgb(vec3(float(meshlet_instance_id) * M_GOLDEN_CONJ, 0.875, 0.85)), 1.0);```
#

Use it like this

dawn wave
#

M_GOLDEN_CONJ? Some built-in param into glsl?

devout mesa
#

just the conjugate of the golden ratio

#

0.618033988...

tropic vigil
#

Lol Ive never seen that

#

That’s cool

dawn wave
#

who will win

#

my cpu vs sponza

devout mesa
#

parallelizing slow code will not make fast code btw

#

it will just made slow code faster

#

which might seem like the same thing, but it's not

feral trellis
dawn wave
#

skill issue ig

feral trellis
#

Fair lol

devout mesa
#

no

dawn wave
#

just get faster hardware wdym you aren't using a 512 core supercomputer smh

devout mesa
#

I don't understand why you're keen on keeping your current architecture

#

which you know is too slow

#

it's not a skill issue

dawn wave
#

this is using my old stuff i made my new stuff faster

devout mesa
#

good

dawn wave
devout mesa
#

what happened to my function

dawn wave
#

murdered in cold blood

devout mesa
#

could you just use it

#

so I can understand and not burn my eyes with red KEKW

dawn wave
#

:AMD:

#

look at him

#

the wall + lion were f'd

#

the plants as well

devout mesa
#

now run again

#

does it change

#

if so, congratulations, you managed to invoke UB in Rust

dawn wave
#

let me see

devout mesa
dawn wave
#

UB in rust goes wild

#

could be ub

#

just as equially the shit architecture

#

cuz i had to fix another instance of randomly selected textures cuz i said "fuck gltf's very reasonable standard of storing everything in vectors"

devout mesa
#

imagine using vectors

#

skill issue ngl

#

I store everything in spatio temporal 4D data structures

feral trellis
#

temporal
bleakekw

devout mesa
#

yes

feral trellis
#

(I have a burning hatred for temporal effects)

devout mesa
#

and there is no temporal or spatial stability

dawn wave
feral trellis
#

(I'm looking at you TAA)

devout mesa
#

TAA's great wym

dawn wave
#

look same-ish so it's clearly a skill issue for me then

devout mesa
#

no it's different

#

look at the curtain bottom right

dawn wave
#

holy shit

devout mesa
#

congratulations you managed to invoke UB in rust

dawn wave
#

wait no that current works fine

devout mesa
#

truly one of the achievements of all time

dawn wave
#

wdym

devout mesa
#

it's purple in the first image, orange in the second

dawn wave
#

yeah ik

#

but when rendering that renders perfectly fine

#

it is the walls, pots, and lion that is fucked

#

OHH cuz i store everything in a dictionary so it's randomized that is why

devout mesa
#

Someone should erase your right to hash maps

dawn wave
#

actually

devout mesa
#

I will pass a new international law I swear

dawn wave
#

please

devout mesa
#

(joking of course)

#

Explain, why do you think it does this

dawn wave
#

hashmaps aren't ordered

devout mesa
#

it doesn't really matter the fact that it renders fine even if the ID is different tbh

#

The very thing that an ID is different from run to run is baaad

dawn wave
#

yeah ill change that KEKW

feral trellis
#

I mean hashmaps are fine

#

Idk what danny's doing that are giving him randomzied results

dawn wave
#

nodle you don't get how wack in a mole it is

feral trellis
#

Lol

dawn wave
#

okay let me explain how stupid this is

#

. > "Wow gltf stores everything in a vector!"
. > converts into hashmap
. > subsequently needs to make a lookup table as I sometimes may skip loading stuff so there is gonna be gaps (blud forgor Option<T> exists 💀)

tropic vigil
#

At least its not webdev

dawn wave
#

so to access anything i need to do:
asset_scene.meshes[lookup_table.mesh[gltf_index]]

tropic vigil
#

I spent 30 minutes centering a checkbox label today and it still doesn’t work

devout mesa
#

penguin

feral trellis
devout mesa
#

learn display flex

#

trust me

#

best decision I ever made

tropic vigil
#

It doesn’t work I swear

devout mesa
#

display flex?

tropic vigil
#

I copied every SO post I could find bleakekw

#

It does not center the damn thing

devout mesa
#

use display flex

#

it's super easy

feral trellis
#

Also @tropic vigil if you don't mind me I'm going to copy most of your settings from your blog post for mine

tropic vigil
#

Ill look into it tomorrow, not gonna do that without getting paid for it bleakekw

devout mesa
#
body {
    position: relative;
    width: 100vw;
    height: 100vh;
    display: flex;
}

body > div {
    position: relative;
    display: flex;
    flex: 1 0 auto;
    align-items: center;
    justify-content: center;
}```
#

Now all the things in DIVs children to body are centered

#

they must all be display flex though

tropic vigil
#

Hmm

#

I have a little container with some content

#

I just want a list of checkboxes inside the container with the labels nicely aligned

devout mesa
#

put labels in a div

#

make div display flex and disable auto grow

#

center the div (with align-items, justify-content)

tropic vigil
#

Alr

dawn wave
#

wtf mozilla added ai to their docs KEKW

#

i mean useful as a glorified search engine

#

wooh

#

new gltf loader

#

lets see if this worked

#

it borked

dawn wave
#

oh i know why

dawn wave
#

OH MY GOD

#

rewrite #2

dawn wave
#

Dammit

#
pub enum ImageLoadInfo<'a> {
    FromFile {
        name: Option<String>,
        source: DataSource,
        view: DataViewInfo<u64>,
    },
    FromBuffer {
        context: &'a mut crate::app::Context,
        name: Option<String>,
        source: Box<dyn assets::buffer::Buffer>,
        view: DataViewInfo<u64>,
    },
}
#

So this struct has a lifetime yeah?

#

I wanna put this apart of my trait implentation

#

but that's not possible 💀

impl<'a> assets::loader::LoadableAsset for Image {
    type LoadInfo = ImageLoadInfo<'a>;
}
feral trellis
#

In your LoadableAsset definition you have to do something like this then

trait LoadableAsset {
  type LoadInfo<'a>;
  
  ... your old code
}
#

@dawn wave

dawn wave
#

hmmm i see alright

#

that does make sense KEKW

feral trellis
#

It's what I have for my current asset system

#

I have a Context<'a> and Settings<'a> for each asset

dawn wave
#

tbfh would rather give image a lifetime but can't figure out where it would go but tbf I don't think image needs one

#

wdym Context<'a>?

feral trellis
#

Just fancy settings (since some of my assets need full references to the world and such)

dawn wave
#

ahh okok

feral trellis
#

No need to restrict the lifetime of a single struct just because one of it's constructor arguments needs a lifetime

#

So going with the LoadInfo<'a> method seems most appropriate

dawn wave
#

man i realized how bad static lifetimes were

#

was about to turn it all into 'static bleakekw

feral trellis
#

I mean tbh it depends on the situation

#

For example

#

&'static str

dawn wave
#

Yeah but why would you need a String that would last for the entire program

feral trellis
#

It saves you a heap allocation compared to String

#

So say I have just a simple string constants I would rather (and rust actually forces you) to use &'static str

dawn wave
#

ohhh so 'static is mainly used for constants

feral trellis
#

Mainly* yea

dawn wave
#

KEKW good enough for me

feral trellis
#

Or if you have a multitude of strings that you know will never get modified throughout their lifetimes

dawn wave
#

ohh yeah

#

Ahh I really don't like this bleakekw
Some of my structs don't even need lifetimes as they hold no references I guess functionally it shouldn't make a difference? At least the compiler should recognize "no lifetimes are being used here"

feral trellis
#

Depends on how your structs are used

#

If you have useless lifetimes I'd suggest removing them

#

Complicates the thing for no reason

dawn wave
#

yeah but I'm implementing a loading trait

#

tbfh

#

i think it would be smarter to remove the loading trait

#

it serves no purpose but to apply limitations onto my assets which can have different loading methods

feral trellis
#

if that's what you need then do what you must do tbh

dawn wave
#

Geh I should probably also merge them into one thing

#

rn I have the horrible if not horrendous paradigm of cpu_buffer and vulkan_buffer
cpu_image, vulkan_image etc....

#

idk how to solve it however ig I should bite the bullet and accept that I will store all my assets as vulkan stuff i.e. buffers, images since well I'm probably only gonna do it. The only reason why I didn't was for asset loaders

tropic vigil
#

its asking for trouble really

#

make your context send+sync+clone by wrapping its entire state in a big Arc<Mutex<InnerContext>> and pass it around all you want

dawn wave
#

Mhm alright

tropic vigil
#

its how i handle all my global-ish state in andromeda

#

and in phobos too actually

#

Some stuff has a RwLock instead of a mutex because most accesses are read-only though

#

Like the asset store is inside a RwLock because you only need write access to load an asset

dawn wave
#

KEKW Iirc i am using it to handle my storage, handle classes

#

But god damn is having to change my ctx class gonna f everything over

dawn wave
#

holy shit

#

RwLock is revolutionary

#

if not innovative

#

holy shit

#

it just fucking works (nvm i deadlocked it)

devout mesa
#

Where sponza

dawn wave
#

bork

devout mesa
#

If you make me wait too long I'll have to trace my own

#

#wip message

dawn wave
#

kekw you may suceed before i do

devout mesa
#

get a move on soldier

#

we need pretty things on screen

dawn wave
#

i am its just that i discovered my entire engine is shit

devout mesa
#

doesn't matter

dawn wave
devout mesa
#

my raytracer is literally a main function and a trace function

dawn wave
#

it's time to become italian and spaghetti

devout mesa
#

I didn't even write a ray struct

dawn wave
#

ok so update i got the Arc<RwLock<ctx>> refactor to work

#

wasn't as bad

#

In 🦀 we believe 🙏 it made handling memory fuckery so much easier

dawn wave
dawn wave
#

You guys think it would be a smart idea to add a weak ptr pointing to the original data my handle is pointing to?

#

Kinda ruins the purpose of a handle tbfh 💀

tropic vigil
#

I wouldn’t

#

You rarely actually need the data inside except for right when you render it

dawn wave
#

Hmmm yeah

#

Ig ill rewirk it again so it just only includes the handle rather than the actual data

#

Then have the loader struct take in a pointer to the storage

dawn wave
#

I’m just confused how I would get it my struct to add to the storage class… Should I just pass it in the loader struct as a ref?

tropic vigil
#

What I do is I have the storage call the loader

#
struct Texture {
}

impl Texture {
  fn load(info: LoadInfo) -> Texture {
    // all load logic
  }
}

struct TextureStorage {
  textures: SlotMap<Handle<Texture>, Texture>
}

impl TextureStorage {
  pub fn load(&mut self, info: LoadInfo) -> Handle<Texture> {
    let texture = Texture::load(info);
    let handle = self.textures.insert(texture);
    handle
  }
}
#

@dawn wave simple not generic example to illustrate the idea

dawn wave
#

Hmm so the texture storage effectively just loads the textures? @tropic vigil

#

Hmmm

tropic vigil
#

yep

dawn wave
#

Ohh this makes more sense now

tropic vigil
#

well, it calls into the texture loading code

#

Then I make this more generic by having an Asset trait that abstracts this load function

dawn wave
#

Hmmmmm okok

#

Well I can’t work on it sadly cuz Barbebheimer

tropic vigil
dawn wave
#

Oppenshitter <<<< BarbiPeak 🙏

tropic vigil
#

fake

#

though i havent seen either

devout mesa
#

do we have sponza yet

dawn wave
#

shh

#

sponzaing

devout mesa
#

time's officially up

feral trellis
#

He has sponza'd

dawn wave
#

Huston we have a problem windows 10 died>
Windows 10 fixed itself. i hate microsoft

tropic vigil
#

sounds like a skill issue

dawn wave
#

@tropic vigil I'm so confused how to seemlessly convert one type to another with bytemuck bleakekw Afaik it seems like they don't actually cast it rather just use the existing bytes to reinterpret the data

white vessel
#

hmm?

dawn wave
#

eh I'll just make a macro then iterate over the bytes then just individually cast each one good enough KEKW

white vessel
#

are you loading vertices from a gltf?

dawn wave
#

yeah I honeslty shouldn't worru too much about converting between types

white vessel
#

I made some lambdas for converting between types before I used fastgltf

#

fastgltf has its own buffer tools that make this manual conversion unnecessary

dawn wave
#

yeah i'll figure something out with macros

white vessel
#

I used a lambda template fyi

dawn wave
#

okok

feral trellis
#

Reinterprets the bytes from one Pod to another Pod type

#

If you want to actually "cast" types you can use the as keyword or the into() or from() methods from the std::convert traits

dawn wave
#
/// Convert a slice of bytes from one type to another
fn cast_bytes_slice_type<T: Into<U> + bytemuck::Pod, U: bytemuck::Pod>(
    contents: &[u8],
) -> Vec<u8> {
    let from_size = std::mem::size_of::<T>();
    let target_size = std::mem::size_of::<U>();

    assert_eq!(contents.len() % from_size, 0); // Must perfectly fit

    // Cast contents (bytes) -> T -> Cast to U -> Reinterpret back to bytes
    let contents: Vec<U> = bytemuck::cast_slice::<u8, T>(contents)
        .iter()
        .map(|x| (*x).into())
        .collect();
    bytemuck::cast_slice::<U, u8>(contents.as_slice()).to_vec()
}

Good enough bleakekw

dawn wave
#

I got two wolves in me:
One tells me to go fast and worry about it later
The other is telling to actually finish vulkan-tutorial

tropic vigil
#

no need to allocate new memory, just reinterpret old memory

dawn wave
#

thonk

#

should i implement mip mapping on my texture loader

#

or within my gltf loader

tropic vigil
#

in the texture loader imo

dawn wave
#

no way i deleted my old mip mapping code it's joever

#

gone reduced to atoms

tropic vigil
#

i have a standalone program that generates mipmaps

#

but it uses a custom texture format

dawn wave
#

eah i can't decipher wtf you did KEKW it's magic ✨

#

don't have a need to create seperate texture types yet

tropic vigil
#

it uses old c++ phobos i think

#

oh wait no

#

its pure vk

#

ok yeah you cna totally adapt that then

dawn wave
#

i havent even lartn compute shaders yet bleakekw

devout mesa
#

compute shaders are like other shaders

#

but different

tropic vigil
#

yeah theyre not hard really

dawn wave
#

im just lost what your compute shader is doing

tropic vigil
#

i totally came up with this math myself dont worry

dawn wave
tropic vigil
#

its just a cubic filter instead of a normal linear one

#

gives somewhat better results

devout mesa
tropic vigil
#

ye

dawn wave
#

🤔 blits seem good enough

tropic vigil
#

blits are linear filter

#

cubic looks a tad better

#

but its more expensive to compute, hence offline preprocessing

#

blits are fine though

dawn wave
#

my beloved blits

devout mesa
#

btw VK_EXT_filter_cubic totally exists

tropic vigil
#

oh damn

dawn wave
tropic vigil
#

since when

devout mesa
#

it is also totally supported bleakekw

tropic vigil
#

froge_bleak yep

dawn wave
#

uh what does that mean

tropic vigil
#

10%

dawn wave
#

oh only 10% of devices KEKW i was confused with the 89.66

dawn wave
#

fellas I realized we’ll need egui support. Is there a way to manually add support or will I have to rely on the other crate.

devout mesa
#

can I has sponza first pls

dawn wave
#

ok fine

#

i’m gonna 🥄za

white vessel
#

🥄🇿🇦

tropic vigil
#

already exists

#

just have to update it to latest phobos

#

its really easy to integrate though

dawn wave
#

what does the crate do differently from the existing egui-winit integration?

tropic vigil
#

It uses egui-winit internally

#

egui-winit just does event handling, no drawing

dawn wave
#

oh so the crate handles making the renderpass for egui. could i integrate egui into phobos myself or is that not possible?

tropic vigil
#

i mean

#

i wouldnt add it to the core lib

#

but yeah the crate manages buffers/attachments for egui and creates the pass to insert into your graph

dawn wave
#

no i meant like in my app program i add egui myself 💀 but okok

#

maybe i'll do that

tropic vigil
#

ooh

dawn wave
#

i gotta sponza first though KEKW

tropic vigil
#

i mean yeah but it'd just be rewriting the integration crate in the end

#

might as well use that

dawn wave
#

oh ok ill wait for the crate to update then

tropic vigil
#

ill do it rn

#

its not much work

dawn wave
#

🙏

tropic vigil
#

publishing rn

#

it re-exports egui, so make sure to use that one (use egui_winit_phobos::egui) instead of what you use if you get version conflicts

dawn wave
#

oh lawd

#

alright

tropic vigil
#

its pretty common to do

#

ill update to egui 0.22 later but i need to make sure egui-winit is also updated

dawn wave
#

Ahh I give up on images. I should probably get some sleep bleakekw

dawn wave
#

Okay so like how should I handle having no images to bind?

#

If I don’t bind any images, the validation layer will throw a fit as my shader expects it

tropic vigil
#

With bindless?

#

I think you can bind an empty array

devout mesa
#

remember to PARTIALLY_BOUND

dawn wave
#

I’ll check if that flag was enabled

tropic vigil
#

phobos enables it for unbounded arrays

dawn wave
dawn wave
#

so it seems like gltf borked and for some reason is saying all of my matrices in my scene are identity matrices

dawn wave
#

I CAN HEAR IT

#

THE 🥄

#

THE 🥄 🥄 🥄 🥄 🥄 🥄 🥄 🥄 🥄 🥄 🥄

dawn wave
#

Wait should my image types all be R8G8B8A8 as like R8G8B8 isn't supported as well iirc?

feral trellis
#

In terms of performance I think it depends on the hardware you're running on

#

Iirc I heard some things saying that internally everything is aligned to R8G8B8A8 size so it doesn't even matter

#

But yea in my engine I stick with those (WGPU doesn't even support R8G8B8 anyways lel)

dawn wave
#

kekw

 ERROR phobos::core::debug             > [VALIDATION]: VUID-VkImageCreateInfo-imageCreateMaxMipLevels-02251 (-1094930823): Validation Error: [ VUID-VkImageCreateInfo-imageCreateMaxMipLevels-02251 ] Object 0: handle = 0x246e0666970, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xbebcae79 | vkCreateImage(): Format VK_FORMAT_R8G8B8_UNORM is not supported for this combination of parameters and VkGetPhysicalDeviceImageFormatProperties returned back VK_ERROR_FORMAT_NOT_SUPPORTED. The Vulkan spec states: Each of the following values (as described in Image Creation Limits) must not be undefined : imageCreateMaxMipLevels, imageCreateMaxArrayLayers, imageCreateMaxExtent, and imageCreateSampleCounts (https://vulkan.lunarg.com/doc/view/1.3.250.1/windows/1.3-extensions/vkspec.html#VUID-VkImageCreateInfo-imageCreateMaxMipLevels-02251)
#

i think i have to do rgba

#

it doesn't like rgb

feral trellis
#

Yeap

dawn wave
#

froge_bleak It’s so joever. How the hell is my transfer buffer larger than my image buffer

dawn wave
#

I don't think the image is supposed to be rotated like that...

#

hmmm why... i think i got my world coordinate wrong

feral trellis
#

Oh also

#

The PR in phobos for a growable scratch buffer merged

#

So you could test that out and it should™️ work

dawn wave
#

should KEKW

#

OHH WAIT

#

I DIDN'T NORMALIZE MY UV COORDINATES

#

BETWEEN 0-1

#

LAMOOO

#

what

#

that isn't the issue however they're incorrectly rotated somehow

dawn wave
#
 ERROR phobos::core::debug             > [VALIDATION]: VUID-VkWriteDescriptorSet-dstArrayElement-00321 (-1862672269): Validation Error: [ VUID-VkWriteDescriptorSet-dstArrayElement-00321 ] Object 0: handle = 0xb6bee80000000073, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; | MessageID = 0x90f9e073 | vkUpdateDescriptorSets() pDescriptorWrites[2] failed write update validation for VkDescriptorSet 0xb6bee80000000073[] with error: Attempting write update to descriptor set VkDescriptorSet 0xb6bee80000000073[] binding #3 with #4 descriptors being updated but this update oversteps the bounds of this binding and the next binding is not consistent with current binding (update past the end of the descriptor set) so this update is invalid. The Vulkan spec states: The sum of dstArrayElement and descriptorCount must be less than or equal to the number of array elements in the descriptor set binding specified by dstBinding, and all applicable consecutive bindings, as described by consecutive binding updates
#

Uh is this phobos?

dawn wave
#

im gonna go insane

#

this issue has to be related to the incorrectly rotated textures

#

dawg wtf

devout mesa
dawn wave
dawn wave
#

geniunely have no clue what caused it or why it was caused

tropic vigil
#

new bindless system coming soon ™️

dawn wave
#

What does it do?

#

🤔

tropic vigil
#

keep track of a bindless descriptor set for you

dawn wave
#

uhh

#

Ohh it will deal with the binding of the bindless descriptors?

dawn wave
#
let samplers: Vec<phobos::Sampler> = vec![phobos::Sampler::new(
            ctx_read.device.clone(),
            vk::SamplerCreateInfo {
                s_type: vk::StructureType::SAMPLER_CREATE_INFO,
                mag_filter: vk::Filter::LINEAR,
                min_filter: vk::Filter::LINEAR,
                mipmap_mode: vk::SamplerMipmapMode::LINEAR,
                address_mode_u: vk::SamplerAddressMode::REPEAT,
                address_mode_v: vk::SamplerAddressMode::REPEAT,
                address_mode_w: vk::SamplerAddressMode::REPEAT,
                mip_lod_bias: 0.0,
                anisotropy_enable: vk::FALSE,
                max_anisotropy: 16.0,
                compare_enable: vk::FALSE,
                compare_op: vk::CompareOp::ALWAYS,
                min_lod: 0.0,
                max_lod: vk::LOD_CLAMP_NONE,
                border_color: vk::BorderColor::INT_OPAQUE_BLACK,
                unnormalized_coordinates: vk::FALSE,
                ..std::default::Default::default()
            },
        )
#

🤔 This sampler should work?

devout mesa
#

yes

dawn wave
#

it's the same bug

#

despite it being a different gltf loader

#

it's the same bug

#

hmmmm maybe I'm handling it entirely wrong?

#

waut a minute

#

no way bleakekw

#

Is it because of multiuvs?

devout mesa
#

sponza has only one set of uvs

tropic vigil
#

.bind_bindless_pool(pool) is all you need

dawn wave
#

Hmmm is it instancing?

#

irc I didn't implement that which is probably why deccer's complex cubes isn't 100% correct

dawn wave
#

🤔 This bug is affecting just one triangle??
It has to be UV related as you can see patterns in the stretched texture

feral trellis
#

Seems to me like your UVs are being clamped

dawn wave
#

bleakekw Is that related to the sampler?

devout mesa
#

Just display the UVs

dawn wave
#

Wait no I think this is fine?

#

Oh no they're very wrong

devout mesa
#

Indeed, here's a correct reference

dawn wave
#

lion is fixed

#

hmm maybe i'm referencing on the wrong UVs?

dawn wave
#

do these barycentrics seem right?

devout mesa
#

probably

#

Barycentrics have 3 components

dawn wave
#

yeah i've omitted the 1 - x - y

devout mesa
#

It should be vec3(1 - u - v, u, v)

dawn wave
#

hmmm i'm really stumped on this bug wtff

#

i'll try other meshes with multiple uv textures and see if the issue continues are there any others?

devout mesa
#

how are you getting the uvs, in the hit shader that is

dawn wave
#
vec2 t_v0 = tex_coords.v[ind.x];
            vec2 t_v1 = tex_coords.v[ind.y];
            vec2 t_v2 = tex_coords.v[ind.z];
            vec2 tex_coords = t_v0 * barycentrics.x + t_v1 * barycentrics.y + t_v2 * barycentrics.z;

            payload.hit_value = texture(texture_samplers[nonuniformEXT(material_resource.albedo_texture)], tex_coords).rgb
#

funny thing is that this only happens to sponza

devout mesa
#

show the whole shader

dawn wave
devout mesa
#

display normals

dawn wave
#

iirc these are gonna be normals provided either by the buffer or generated from geometry

devout mesa
#

dunno

#

try bistro lol

dawn wave
devout mesa
#

I can't see anything wrong with the shader

dawn wave
#

is there a bistro file?

dawn wave
#

fbx

#

oh import to blender

devout mesa
#

if you have >=32GB of ram you can convert it

dawn wave
#

bleakekw i don't

devout mesa
#

#1128020727380054046 message

#

here

#

this is just the exterior though

dawn wave
#

eh that's fine

#

nah we ballin' we're gonna import all 32gb 🫡 say goodbye to my pc's memory

#

it crashed KEKW

#

Wait is it because of merged texture atlases?

devout mesa
#

wat

dawn wave
#

nvm

#

ah fuck

#

bistro has multiple uvs

#

the uh texcoords(1) thingy. i haven't even implemented it yet KEKW

devout mesa
#

doesn't matter, use only the first set

dawn wave
#

bistro loaded but i forgor to removed the normal shader

#

Huston, we got a problem

#

uhh 1) textures are f'd

#
  1. seems like the odd stretching bug no longer occurs
#

textures ids seem fine

#

i need a scene with like 2,3,4, and etc. different textures to just test it

#

this 100% is a uv issue

#

if it were textures there wouldn't be any sembelance of normalacy

#

OH WAIT

#

I'M STUPID

#

IS IT BECAUSE DOUBLE SIDED?

#

LMAOOO

#

nvm i am stupid

dawn wave
#

this is weird. I would get if it was black i.e. u is inverted, but instead the back wall is v.

#

i've tested the individual texcoords of each vertices

#

and it's still stating that the backwall is somehow v

#

when it really should be u

#

maybe i'll consult chatgpt KEKW

dawn wave
#

works with smaller # of meshes, but borks itself upon larger number

dawn wave
#

i also realized some of the uvs are rotated horizontally and stretched too

#

YOOO THE FLOOR WORKS !!!

#

(everything else is completely broken beyond disrepair)

feral trellis
#

Lel

dawn wave
#

i'm gonna go insane

devout mesa
#

sounds about right bleakekw

dawn wave
#

this is 100%

#

if not 1000% some stupid fucking issue with memory limits

#

yet everything looks right

#

TEARS IN MY EYES

#

I FOUND A SMALLER MANAGEABLE MESH THAT I CAN DEBUG

#

OH MY GOD

devout mesa
#

I'm willing to bet it's the loading

#

because you keep abstracting it

dawn wave
#

shh

devout mesa
#

if deccer was here he would've blasted you one thousand times over

dawn wave
#

thank god he isn't

devout mesa
#

don't worry

#

i am here

dawn wave
#

it's probably? down to indexing issues

#

oh.

#

oh

#

oh

#

oh

#

ha

#

heh

#

no way

#

ah nvm

#

huston we have a problem

Primitive name: Some("Unnamed 0") Texture name: Some("Unnamed image 1"). Texture index: 0
Primitive name: Some("Unnamed 1") Texture name: Some("Unnamed image 4"). Texture index: 7
Primitive name: Some("Unnamed 2") Texture name: Some("Unnamed image 7"). Texture index: 3
Primitive name: Some("Unnamed 3") Texture name: Some("Unnamed image 10"). Texture index: 10

KEKW

#

this was 100% indexing issues

#

IT WAS NOT

#

WHAT

#

THIS IS NOT A LOADING ISSUE I REPEAT

#

THIS IS A SHADER ISSUE

#

WHAT

#

it is

#

it was

#
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `102`', src\assets\scene\loader\gltf.rs:561:13
devout mesa
#

now fix

dawn wave
#

this is gonna be a shit storm to fix

#

kekw

devout mesa
#

and the next time you abstract something without understanding how you want to use it I will be coming to your house personally.

dawn wave
#

but i did know :(

devout mesa
dawn wave
#

this was caused by doing what you did actually bleakekw

#

iterating over every mesh -> iterating over every accessor in that prim

devout mesa
#

ye

#

how did that cause this bug

dawn wave
#

cuz i returned a vector of buffer views

#

problem is that same order of the gltf ordering

#

is not assured

devout mesa
#

why does order matter

#

it doesn't matter for me

dawn wave
#

because i index that using the gltf information provided

devout mesa
#

I don't understand

#

where do you get the texture indices from?

#

actually scratch that

#

if you get the texture indices from anywhere you're doing it wrong

dawn wave
#

kekw

#

will redo sir

devout mesa
#

I am amazed

#

why did you not think of using the size of the vector at insertion time as your index

dawn wave
#

that's what i did KEKW. it's just that it didn't lineup with the gltf

devout mesa
#

for each texture {
    index = textures.size();
    textures.emplace_back(texture);
}```
devout mesa
dawn wave
#

wait fuck it doesn't

devout mesa
#

"it doesn't" what

dawn wave
#

the index of the accessors does not need to lineup with that in the gltf

#
accessor_struct_views.push(entry);
            // Put index of the accessor struct in the vector
            primitive
                .accessors
                .insert(semantic.clone(), accessor_struct_views.len() - 1);
#

so this stupidity arises from somewhere else

devout mesa
#

I fail to understand why you need to assign an index to a primitive's accessor but ok

#

so where's the actual issue

dawn wave
#

i got n o clue

devout mesa
#

amazing

#

look do this

dawn wave
#

i don't think it's accessor related? But also points to me that it is just because the UVs are horrendously wrong which are from the accessors. But if my accessors are wrong, then my vertices would be too, but they aren't

devout mesa
#
hash_map<texture*, uint32> texture_indices;
vector<texture> textures;
for each texture {
    ptr = &textures.emplace_back(texture);
    texture_indices[ptr] = textures.size() - 1;
}

// later
for each primitive {
    if (primitive.material.has_texture) {
        your_thing.texture_index = texture_cache[primitive.material.texture];
    }
}
dawn wave
#

kekw will do

devout mesa
#

also for accessors

#

I dunno why you do any of that

#

I would suggest doing this

#
vector<vec3> positions;
vector<vec3> normals;
vector<vec2> uvs;
for (accessor in primitive.accessors) {
    switch (accessor.type) {
        case position:
            positions.reserve(accessor.count);
            memcpy(positions.data(), accessor.buffer_view ..., accessor.count * sizeof(vec3));
            break;
        ...
    }
}```
dawn wave
#

HMMMMM so this issue isn't accessor

#

and it isn't texture

#

so it must be

#

the shader

#

but my shaders looks right

#

AAAAAAAHHHHHHHHHHHHHH

#

maybe rendering everything assuming a white texture

#

isn't that bad

#

like when i add the lighting

#

it can't be that bad

devout mesa
#

I mean

#

radiance only rendering is super cool

dawn wave
#

yeah that's what i'm saying 🗣️

#

it's actually mystical this bug

devout mesa
#

#1090390868449558618 message

#

super cool

dawn wave
#

sexy

#

See I don't think the issue would lie in my type conversions I do for the buffers

#

as they work with my vertices just fine and smaller meshes

devout mesa
#

if only there was a way to check whether that's the issue or not

#

(hint: there is)

dawn wave
#

Yeah my tests pass

devout mesa
#

no, not tests

#

an even better solution

dawn wave
#

Oh just pass it in without type conversion?

devout mesa
#

nuking the shit out of that code and just memcpy'ing vec2's like god intended

dawn wave
devout mesa
#

then you can plug it in again after you fixed the issue

dawn wave
#

ill try that

devout mesa
#

so you un-nuke the nuked code

dawn wave
#

trust me it won't work

devout mesa
#

do whatever feels right tbh

#

there isn't a right way of debugging

dawn wave
#

yeah but if it works KEKW

devout mesa
#

typically removing chunks of code what I do

dawn wave
#

print 🙏

devout mesa
#

it shrimplifies and removes points of failure