#Iris - A Journey through OpenGL and beyond to learn Graphics
1 messages · Page 17 of 1
I'll try both
we kinda rely on our meshes having few primitives
well not few but it does not scale well with increasing number of primitves
aren't you and potrick meshlet enjoyers
it shouldn't matter innit
ah wait potrick has the instance culling madness

Uh it does matter because of the way we store the data
each mesh has an array of primitive indices so that we can allocate GPU buffers and all
and the size of this array is set globally
(-:
yes no mesh shader
yeah
mesh shader soon as I get new GPU
but even if we do mesh shaders, we still would have
struct GPUMesh
{
PrimitveIndices[MAX_PRIMITIVES_NUM]
Transform
BlaBla other data
}
no?
mm I like using ranges and having it all separate
so your primitive indices are hiden behind another indirection?
I set a fixed budget for max primitives and max vertices and allocate gpu buffers with those
it's fine
we're already memory bound anyways

but I haven't profiled in depth so perhaps some investigation™️ is in order
We'll see how it goes
everyday I wonder why expression statements are not standard
no
thats just the meshlet layout from nvidia/ the one meshoptimizer gives us
its the same with and without mesh shaders
ye, I prefer to keep stuff separate so I can avoid duplication of stuff
like two meshes can share a primitive, so I decouple meshes from primitives
well pointer or offset inside the mesh struct to the arrays doesnt make a difference, its one indirection to these tables in the end
keep what separate?
mesh info, meshlet info and primitive info
you talk in gltf terms
oh ye primitive in the gltf meaning
we call primitives meshes and meshes mesh groups
ah I see now
i thought you mean triangles with primitive
I was referring to memory locality
That's why we have //gltf mesh is our mesh group and //gltf primitive is our mesh all over
tido also has meshes and primitives decoupled
👾
we allocate primitives into their own buffers so they are able to be unallocated if we want that
simpler to think about imo, one buffer = one primitive
doesnt really matter tho, the same in the end
?
ye
The indices were local to the meshgroup previously
luckily we nearly never pay that price
we solve the indirection on cpu
when we create the draw lists
gpu never needs to do the indirection, it just eats mesh + entity pairs prepared from cpu for each frame
Beast abstraction
If you want to see another meshlet impl, here's mine https://github.com/bevyengine/bevy/pull/10164 @delicate rain
I sadly don't have mesh shaders either (webgpu)
Thanks
I'll check it out once I'm on my PC again!
Happy to answer questions if you have any 🙂
JetBrains will soon release a software to write plain text and call it "The most advanced writing tool ever"
though I have been liking Writerside
it's nice to have first class support for both markdown and LaTeX
Reject modernity, embrace overleaf
I used this for my thesis https://typst.app/
@wicked notch couple questions:
- Why do you have to lock meshlet borders before simplifying?
- What METIS API do I use for partioning the graph?
- How do you project whatever this "error" metric meshopt's simplify gives to screen space pixel size?
- Do you use meshopt's meshlet builder for the initial clusters, or metis for that too?
I don't get why subdividing without locking can cause seams
METIS insits on 2 letter variable/API names -_-
the heck is ncon
https://docs.rs/metis/0.1.2/metis/struct.Mesh.html#method.part_nodal this one I guess?
I use PartGraphRecursive
different parts of the mesh can be at different LOD levels, if you simplify the borders of meshlets too you will have discontinuities between LOD levels
number of shared nodes (vertices) between two elements (triangles) for them to have an edge
there is a handy manual for metis, you need to read it at least 45 times before you figure it out though
you can project the error in many ways, I just scale it by the size of the sphere in screen space (this is stupid though, do what unreal does)
Oh ok, didn't know that
Thanks!
Do I understand the steps correctly?
- Split mesh into initial meshlets
- While meshlet_count > 1:
- PartGraphRecursive, target partitions = meshlet_count / 4
- For each group, simplify group
- For each group, build meshlets within that group (same as step 1.)
- Goto step 2
Meshoptimizer and metis already implement the hard parts for simplifying and graph partioning, I just shell out to them and move the triangle data around
Seems easy
Also mind giving me a list of all the dumb edge cases that break things that I should know about 😅 ?
heh
hehe
he_doesnt_know.meme
yes there are so many edge cases that meshoptimizer's mesheltifier just straight up fails, also you forgor a step (building locality info)
the most infamous edge case are disconnected meshes
then you have the fact that partgraphrecursive doesn't give you a strict upper bound on partition size
after that you have to solve vertex welding for close vertices so you have to build locality info between edges of triangles
this brings its own set of edge cases like:
- what if vertices are close spatially but UVs are completely opposite of each other
- same thing applies for normals and tangents, but at least you can recompute those if you accept some more error
there are more edge cases but I have an exam
Edge cases are the friends we made along the way.
Does that matter? Say you get 6 meshlets per partition instead of the target of 4. Your LODs will be more inefficient, but it shouldn't break anything no?
Can you expand more on this, and the locality info? Whenever you have time
you can make a better graph for the GPU if you can make assumptions about partition size
also it's strictly required for triangle/vertex limits for meshlets no?
partitioning triangles will meshoptimizer will not work
it's unusable for any LOD level other than 0
meshes with lots of disconnected vertices can't be simplified as well and therefore you must weld close vertices together to keep simplifying
locality info just refers to triangle-to-triangle (or meshlet-to-meshlet) distance info
building locality info means building edge weights for adjacent triangles
Well let's say you end up with 6 meshlets in your partition, and after simplifying you have too many triangles for 2 meshlets. Then you just build 3 meshlets instead. Not quite the 4->2 reduction you wanted, but that's ok still. No?
Oh. You need to use metis for building meshlets for other LODs? Damn...
even for the leaf LODs
meshoptimizer will just not work, forget about it for generating meshlets
So, meshoptjmizer for simplify only
it prefers topological locality to spatial locality
Sadge
yeah
Ehh edge cases, not important for my first attempt 🙂
Well in that case it's more of a problem as metis can't guarantee partition size to ensure <= 64 triangles 😭
So manually fixes and such necessary:/
That's depressing
Even with the manual, METIS_PartGraphRecursive is so dumb
I don't get how to build the initial meshlets
each node in the graph is a triangle, ok
what the heck are the weights supposed to be?
How the heck do you turn those into per-triangle pair edge weights
Atl for now I feel like I should just use meshoptimizer's meshlet builder
When you have time to answer questions, I'd like to know how you merge the vertex/index buffers for meshlets. I'm curious if you have to group meshlets based on their real original-mesh vertex IDs, or if using the local indices/vertices to the meshlet is fine.
they remain the same after initial clustering
Wdym?
The vertex buffer remains the same
the index and primitive buffers change per LOD level
you should use local indices yes
I think METIS is actually just this easy
// Group meshlets into roughly groups of 4, grouping meshlets with a high number of shared edges
let mut xadj = vec![];
let mut adjncy = vec![];
let mut adjwgt = vec![];
for meshlet_id in simplification_queue.iter() {
xadj.push(adjncy.len() as i32);
for (connected_meshlet_id, shared_edge_count) in
connected_meshlets_per_meshlet[meshlet_id]
{
adjncy.push((connected_meshlet_id - simplification_queue[0]) as i32);
adjwgt.push(shared_edge_count as i32);
}
}
xadj.push(adjncy.len() as i32);
let mut groups = vec![0; simplification_queue.len()];
Graph::new(1, (simplification_queue.len() / 4) as i32, &xadj, &adjncy)
.unwrap()
.set_adjwgt(&adjwgt)
.part_kway(&mut groups)
.unwrap();
Next up: simplifying each group
you can use vowels in identifiers btw
Eh I decided just to copy metis for this part, given that adjcny is a meaningless name anyways
uh
I mean, "adjcny" isn't a random jumble of letters
Yes, but adjaceny isin't any better 😛
I'd rather just copy metis's name so it's easy to tell what's what when referencing the manual
ok
Why does meshopt_SimplifyLockBorder not work for meshlet LODs?
it does, I use that
How does this fit into that? https://github.com/zeux/meshoptimizer/pull/601
Also I'm a bit confused on some things. You have:
- Original mesh vertices
- Meshlet lod 0 "vertices" (points into above)
- Meshlet lod 0 "indices" (points into above)
When grouping meshlets, you use edges defined by the meshlet indices
When simplifying meshlets, you do the same?
When you split your groups into new meshlets, what do you do with that info?
Also hmm, I somehow need to pass the original mesh vertices to the simplkifier
yeah honestly I don't understand what they're talking about
I fail to understand what they mean by "outer border" of a mesh
Ok, so ignoring that
meshopt_simplify needs the original mesh vertex positions
But my index buffer for meshlets points into the meshlet vertices..
Am I supposed to remap the index buffer to the original vertices myself before simplifying? Or am I missing something
I just build another temporary index buffer tbh
When you split your group, do you just copy the group's error to each new meshlet?
yes
Cool, almost done!
Ok, testing time!
Also curious, did you call any of meshopt's vertex/index buffer optimization functions, before simplifying or building meshlets?
The docs imply they help a lot
I lost my example code to simplify gltf files 😬
Gonna need to write that again 😦
yeah
they do help a lot
having duplicate vertices/edges is horrible
Good to know. What/where specifically do you do?
just call all the optimization functions but the overdraw
does that one even help?
LOD 1 bunny. Seems a bit off...
welcome to "the problem" I was talking to you about meshopt's generator
If you use metis, what are the edge weights between triangles/meshlets?
How do you get it to 64 per partition?
Oh it's just target partitions = triangle count / 64 ig
you bisection the mesh (i.e the graph) until it's within your vertex/triangle limits
You've lost me lol
you know how graph bisection works right?
it's just dividing the graph in two partitions
and assigning a good weight to said partitions
then, until the number of nodes or edges in the bisectioned graphs are within your limits, you keep recursively bisectioning
Hmm ok
I compiled GCC 13.2 and had to fight SPIRV-tools and KTX to get them to compile, but then...
~/work/repos_to_check/Retina/build$ ./RetinaMeshShadingSample
./RetinaMeshShadingSample: /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by ./RetinaMeshShadingSample)
./RetinaMeshShadingSample: /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.31' not found (required by ./RetinaMeshShadingSample)

That's it, I'm updating to Debian Testing and I hope nothing breaks 
@wicked notch it can't find Retina/test/Models/compressed/bistro/bistro.glb 
Why doesn't CMake build not do it, 2/10 literally unusable
lvstri doesn't want to upload multi-gb models to github 
The build script can download it from somewhere 
hardcoding my beloved
imagine figuring out blender's CLI and shit when you could just convert it yourself
Oh wait, Bistro is not even in glTF, I guess I have to export it manually via Blender, yeah
Most user friendly GP build process be like 
at least I'm kind enough to keep a shrimple test model in my repo
~/work/repos_to_check/Retina/build$ ./_deps/meshoptimizer-build/gltfpack -i ~/Desktop/Bistro_v5_2/Bistro.gltf -o ~/work/repos_to_check/Retina/test/Models/compressed/bistro/bistro.glb -tc -tq 10 -vpf -kn -km -ke -noq
Error: gltfpack was built without BasisU support, texture compression is not available

oh yeah, you need lvstri's gltfpack fork 
I wonder if his renderer has a fallback for non-compressed textures
Where can I find it though

- ratio
you can still see his repos btw
somewhere
no sign of meshopt/gltfpack lol
https://github.com/LVSTRI?tab=repositories
I did it by reading TFM
git clone -b gltfpack https://github.com/zeux/basis_universal
cmake . -DMESHOPT_BUILD_GLTFPACK=ON -DMESHOPT_BASISU_PATH=basis_universal -DCMAKE_BUILD_TYPE=Release
damn son
This, but only core 23 is looking and doing nothing 
I think you can also try with the gltfpack from the releases page
That one definitely supports basisU
I compiled it anyways now 
gltfpack has been doing its work for 9 minutes now 
Hope it's not stuck in some endless loop 
I have 7950X even 
high quality bc7 encoding be slow I guess
And that's it...???

I've been jebaited
RayTracing:
[2024-03-05 11:20:13.139] [Device] [critical] Required Extension "VK_KHR_ray_tracing_position_fetch" not supported
AMD sisters...
driverID = DRIVER_ID_MESA_RADV
driverName = radv
driverInfo = Mesa 23.3.5-1
radv skill issue?
I guess. pixelduck, plz fix
It's on Debian unstable, but not on testing 
Maybe some day it'll reach testing
wat distro
Debian Tesiting aka trixie
why is everything related to that distro out of date
oh
Because stability(tm)
"we keep things broken too" stability
use arch (I don't know anything about arch)
soooo outdated
i think the "stable" debian version of mesa has not been updated in literally a full year
man that's a full gpu generation
And they only receive security patches
that's the wrong distro for cutting-edge giraffix
m'lady distro and arch loonix should have both by now
Debian Unstable has it, so it will land into testing eventually
I'm not brave enough to use unstable, but I guess it will be similar to Arch 
m'lady distro
Gentoo?
fedora
fedora
Ah, Gentoo also fits, as it's the target audience 
gentoo should probably indeed have it too
If Debian unstable has it, everyone should have it
But I'll wait for now for it to hit testing anyways 
3 weeks ago my engine was on 3.3 GL 
GP will force me to use Arch and buy programming socks 
@wicked notch anyways, I had to do this for it to compile. Classic template bruh momento:
Also had to update KTX to the latest since they used some funny enum conversions which are deprecared + Werror
Also SPIRV-tools didn't compile for me, but I'll research it and will probably make an issue
yea nearly all of khronos' tools require some sort of hacks to compile
it's actually incredible how annoying it is
I should also make public my fork of gltfpack lol
I actually didn't need to use a fork, just had to pass it path to basisu
Is it all the MeshShading sample is? 
Enjoy your rest 👍
I know how it feels
But also
REMOVE main PLZ AND USE FIXED COMMITS, OK THNX
FetchContent_Declare(
spirv_cross
GIT_REPOSITORY https://github.com/KhronosGroup/SPIRV-Cross
GIT_TAG main
GIT_PROGRESS TRUE
GIT_SHALLOW TRUE
)
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ON CACHE BOOL "" FORCE)
set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(spirv_cross)
FetchContent_Declare(
spirv-headers
GIT_REPOSITORY https://github.com/KhronosGroup/SPIRV-Headers
GIT_TAG main
GIT_PROGRESS TRUE
GIT_SHALLOW TRUE
)
Because apparently they can have borked commits in main. Cringe
https://github.com/KhronosGroup/SPIRV-Tools/pull/5602
I even found the PR which fixes the issue. But seems like their CI is kinda bad if it doesn't get noticed lmao
I guess only 2-3 people in the world compile this stuff from main 
I'm thinking to move to glslang anyways like jaker did
shaderc (and all its dependencies so SPIRV-Tools, SPIRV-Headers, etc.) have consistently given me pain
or, better yet slang, but I hear potrick is still fighting with the ptr guy 
yeah I'll let them cook for a few years
no this thing: https://github.com/KhronosGroup/glslang
it should allow me to ditch many dependencies
So you're telling me there's the third glsl compiler? 
I think this is just glslc and glslValidator combined
would be cool if khronosgroup just renames itself to JohnKhronos, it do be more authentic
Maybe after someone from the GP becomes Khronos chair 
: )
John Khronos
John Khronos
works for me 😄
title adjusted for inflation: Senior Principal John Khronos
@wicked notch did you compile Retina on Linux before, btw?
I’m impressed that it only took me two lines to fix it
Compiling a random Vulkan anime engine now and it’s so full of MSVCisms, it hurts
btw
class NvidiaDlssFeature;
class NvidiaDLSSFeature;
class NVIDIADLSSFeature;
class nvidia_dlss_feature_t;```
choose
I'll let this go democratically
Nvidia don't know how to write their name too, I think 
first tbh... hoever if you stick to your isms_t like in iris, then id go with the last one
i also dont know if serious or not 
I kinda am
I am facing some issues with the C#isms
like get this
class Graph {
public:
struct Partition {
// ...
};
Partition Partition();
};```
but ultimately it doesn't matter too much
i decided to prefix mzy Fukisms with Fk
and can still go with Pascal style where i want then
ala
struct FkPartition { };
FkPartition Partition;
mayhaps Retina stuff can be ReThism or ReThatsm
makes sense
Getting LOD building working is so difficult ugh
@wicked notch If you feel like it, please take a look at my code and tell me if I'm doing something dumb. I know you had better luck using METIS for clustering instead of meshoptimizer, and I'm not weighting clusters by distance between them, but I still feel like I should be getting better results than I am... https://github.com/JMS55/bevy/blob/meshlet-lods/crates/bevy_pbr/src/meshlet/from_mesh.rs#L50
Oh hold on, does meshopt simplify take target index count??
oh, hell
Ok that's a little bit better, but still cursed, and still z-fighting
Ok back to sleep since that didn't work
Tm I should try visualizing the cluster groupings before I try and simplify
Hmm I think tuple_windows is not correct to generate edges 😅
ok yeah I see a lot wrong fml lol
Nope still didn't fix things ahhh
are you drawing both LOD 0 and LOD 1 
Shouldn't be...
I modified the code to throw away lod 0 after calculating lod 1
Hmm let me check in a bit, I just woke up lol
US moment
oh, wait, hold on
I think I was rendering both LODs
nope still looks weird though :/
is this all of LOD 1?
it's weird for only a section of the bunny to be scuffed innit
yeah
right??
And also even lod 0 looks weird compared to what it used to be
It used to be nicely distributed, but now there's some weird patches of small meshlets
But the code didn't even change
I guess you should first focus on fixing that then
scuffed leaf meshlets will inevitably lead to scuffed LOD'ed meshlets
I didn't even change anything though 😭
debugging is a core part of the process
at least you're not hanging your system, like I have many times 
I'm litterly using the same test model and my previous branch and it's not working as well anymore -_-
This is bizzare
@wicked notch is there any chance that i can make you fix the archived Iris? master is not buildable as is : (
I'm checking out a much older commit, maybe I broke something at some point
ye
git checkout saves lives
perchance
if you are not in the middle of learning for exams : )
no, older commit is still broken...
I shall hop on the penguin
the GL one or the VK one
GL

i think some fixes is using model.h vs mesh.h (which doesnt exist anymore) bt wants mesh_t plus a potential fix for its ctor if i saw that correctly to work in the older examples < 5.2
and the warnings from dependencies (looks like ktx is the offender here) need to be silenced
I mean looks fine
jasmine, mayhaps try suzanne or the deccer cubes?
Yeah let me try suzanne
The thing is the bunny used to work fine
The meshlet_mesh I have saved is great
But trying to convert it again, even using a very old commit, looks horrible???
I feel like I'm missing something 😦
hmm
i thought there was a thread called This other mesh will also crash your engine or something similar
deccer balls
deccer balls
yeah, I remember it being under a random channel
I think it looks ok?
is that the main LOD
somewhat
I remember the eyes having more detail
some of the meshlets look very small
hmm it looks also fucked somehow, the green center and white bttom one
Yes
Yeah idk what meshopt is doing all of a sudden
yeah this definitely does not look like the main LOD
I mean, I think I recognize some of the main geometry
maybe the debug view needs triangle outlines
I can switch it to per-triangles, 1s
is this just a very low poly suzanne?
yeah crank up subdivision
that's the default one, so I guess you've been using subdivision
mhm let me figure out how to do that
subdivision surface modifier
add modifier on the blue wrench symbol in the bottom right window
triangles
Btw, do I even need normals/tangents?? I can just bake detail directly, and use geometric normals derived from the triangle position with this amount of density no?
Well lod 0 looks great now
Lets try a different LOD and just give up on the bunny for now, idk why
Lod 1 looks the same??
heck
LOD 0: 1968 meshlets
LOD 5: 1968 meshlets
???
each LOD is just a copy of LOD 0
huh
try building now @wispy spear
[build] 12 warnings and 12 errors generated.
ah you're trying to build the old schtuff
yeah idk how to fix the old ones 
I don't remember anything about them
it was also an unwise decision to name those "5.0" and"4.2" 
let me comment out all the old projects
I didn't finish implementing FSR btw, it's very aliased 
I'm suspicious simplification isin't actually doing anything 🤔
because your code is somewhat readable
this is a good thing to be suspicious of
because simplifying can very easily fail
if you have lots of duplicated vertices or your error value is too small or your mesh is super disconnected
btw look at this guy
5.6ms to render bistro with some shadows
so slow
Each group has 4 meshlets, and after simplication and re-meshletifying, there's 4 meshlets... it's litterly doing nothing 😭
yeah there's nothing about GL to learn from me

thats not correct
glVertex5f
Anti TAA boys look at this and go "it's not aliasing, it's clarity
"
is that AntiAliasing.exe?
ye
ah
Simplification is litterly doing nothing
[crates\bevy_pbr\src\meshlet\from_mesh.rs:140:17] (simplified_group_indices.len(), group_indices.len(), error) = (
384,
384,
0.0,
)
same triangle count before and after
yeah me too, lets find out
did you push the fix already lustri?
: )
iirc if you target_link_libraries(iris SYSTEM ktx) it should be quiet somehow
but i kind of forgot how it really worked
how can they make the greatest graphics API in the entire universe and have the worst possible tooling imaginable
ok I push
because its also just a bunch of weird people and a bnch of smart people like everywhere else : >
your .gitignore looks interesting hehe
@wicked notch can you sanity check me, what are the steps to simplify meshlets? Which index buffers do you use?
the ones you generate anew from the grouped meshlets
for group in groupedMeshlets {
vertices = [];
for triangle in group.triangles {
index = vertexIndices[group.indexOffset + triangle];
vertex = vertices[group.vertexOffset + index];
vertices.push(vertex);
}
indices = GenerateIndexBufferFrom(vertices);
(simplifiedIndices, error) = SimplifyHalf(indices);
}```
What does GenerateIndexBufferFrom do?
calls meshopt_remapVertexBuffer and stuff
and vertex is an index into the mesh's original vertex data yes?
no vertex is the actual vertex
like position data
meshopt_remapVertexBuffer needs the original vertex data
hmm
I'm doing basically the same thing I think, just not calling any of the meshopt remapping stuff
you need to do that though 
let mut group_indices = Vec::new();
for meshlet_id in group_meshlets {
let meshlet = meshlets.get(*meshlet_id);
for meshlet_index in meshlet.triangles {
group_indices.push(meshlet.vertices[*meshlet_index as usize]);
}
}
in this particular case
Wdym?
yes, this is wrong
these are not the indices you want
you want indices local to the group
Why not? What indices should I be using, if not the concanated meshlet indices into the original vertex buffer?
you want to treat this group of meshlets as if it were your only mesh
I'm confused why that would make a difference tbh?
because meshlet.vertices is not really an index buffer
it does not represent the topology of the mesh
https://jglrxavpok.github.io/2024/01/19/recreating-nanite-lod-generation.html#simplifying-cluster-groups is doing the same thing I am I think, and it seems to work for them
Wdym by this exactly?
Once you build a list using meshlet.triangles into meshlet.vertices, do you not have a list of triangles?
meshlet.primitives is the topology meshlet.vertices is just a counter for how many times a certain vertex has been used
I believe the list of triangles is in meshlet.triangles
meshlet.vertices is a counter for vertex reuse
if you look at how meshlet.vertices is generated, you will understand
nevermind it's the opposite 
yeah you're right
it should work
idk why it don't
But it dosen't 😭
did you figure out where meshopt is failing yet
No, going to go try and figure out how to attach gdb tbh
inside meshopt_simplify there's a prepass that classifies all the edges
look at what the classifier is doing
I think meshopt-rs is mapping a null ptr to a no-opt instead of telling me it's erroring 😛
does rust not have its own debugger? 
https://github.com/zeux/meshoptimizer/blob/master/src/simplifier.cpp#L255-L374 this is the prepass btw
classifyVertices
No? Just gdb/lddb, same as C++/C/etc
I guess it all works the same independent of lang if you export the symbols ye
I figured the rust people would just "rewrite it in rust" 😛
@wispy spear it should work now
let me know
also damn it's almost been a full year since I started this thread
Running `cargo build --example=meshlet --package=bevy --release --features meshlet_processor --message-format=json`...
error: unexpected argument '--features meshlet_processor' found
tip: a similar argument exists: '--features'
Usage: cargo.exe build --example [<NAME>] --package [<SPEC>] --release --features <FEATURES>
???
ok fixed
still no worki, lvstri, ill dinglefart from here, no need to be hanging on the penguin for me (for now)
it's ok I like the penguin :)
ktx's fmt dependency now complains about warnings treated as error
btw are you using clang or gcc
gcc
13.2 right?
ok finally got a debugger attached lol
how am I not getting your same error with the same configuration
I'm also using latest gcc
when you updated submodules i dont have to do that, since you modified .gitmodules right
kk
idk
man I'm glad I switched to fetchcontent lol
pog
i did have to update the submodule myself
wtf
sorry for the interruption jasmine, luigi is all yours again
thx lustri ❤️
nor can I kill my app anymore, it's frozen 😛
ye jetbrains has rustrover in EAP
which means it's free to use
maybe give it a try if it's not too much hassle idk
What exactly should I be looking for? I'm unsure why it's failing tbh
It'll be annoying to figure out how to bind to a custom build of meshopt, sigh
Yeah the debugger doesn't recognize VertexKind, it's just binary
just printf tbh
I want to see LODs working
so get a move on 😛
(I'm kidding, but I do want to see your LODs working)
me too : )
https://github.com/gwihlidal/meshopt-rs/issues/37 Maybe it's this
Maybe it dosen't like that I'm passing the entire mesh's vertex buffer to simplify, instead of a stripped down one for just the meshlet vertices? idk
it's always great to read
guy's ramblings 
I read this too, I think I didn't run into the problem because I really create a new vertex buffer for the simplified meshlets
this ends up duplicating a lot of stuff so maybe having a deduplication pass later when everything has been shrimplified can be beneficial
the remapping will be hell though 
who is
guy? 
the FuckTAA guy, in #questions
ah, no better way to start the day than with some entertainment from the court jester
real
btw what do you do for copy ctor/assign
is there a cursed way to avoid duplication here
what if you actually need a copy ctor 
You could implement it the same way as my move semantics, where the assignment operator just calls the constructor
ye but you need swap innit
T::operator =(const T& other) {
if (this == &other) {
return;
}
T(other).swap(*this);
}```
Why is swap needed?
I guess you could do it with placement new
yeah that's cursed enough
this placement new thingy is great, too bad it don't work when destructors are protected :(
and even if it did, the move constructor would be insane in derived classes
why is it protected
thing::clone()
wow holy shit there wasn't even a hint my messages were behind what the hell is going on
class Base {
public:
Base(Base&& other)
: _state(std::exchange(other._state, {})) {}
private:
T _state;
};
class Derived : public Base {
public:
Derived(Derived&& other)
: Base(std::move(other)),
_moreState(std::exchange(other._moreState, {})) {}
private:
T _moreState;
};```
isn't swap only really the elegant thing for move ctors, my understanding was that it was just a convenient way to let the old garbage in the lhs object be swept up because the dtor of the rhs object is about to be called
having the destructor protected that is
you can achieve a similar effect with the this->~T(); new (this) ...
delete this 
something about that seems inherently cursed
yes, that's why I hide it
core::reconstruct(*this, std::move(other))
nobody needs to know
I put mine on full display
I wonder if there's some obscure rule about object lifetimes that makes that ackshually UB
I looked in the spec to make sure it's not UB
anyways how would you deal with something like this
are you sure? my dad works at spec and he said you will be banned for this code
Derived's move ctor is insane and it looks like a use-after-move 
linter complains as well
Why is the derived class referring to a private member of the base
typo
Looks fine to me
ye but linter complains because use-after-move
even though we all know it's actually fine
rip
Just take the linter thing as advice rather than a serious issue
And if you know what you're doing you can safely ignore it
does one ever know what one's doing
C++ lets us try regardless
can you not add an override for the linter at that spot?
with a oneliner comment thing
perchance
behold
def main():
includeDirectories = [
os.path.join(os.environ['VULKAN_SDK'], 'include'),
]
compileDefinitions = [
'VK_NO_PROTOTYPES'
]
cppStandard = 'c++17'
cppArgs = []
for includeDir in includeDirectories:
cppArgs.append(f'-I{includeDir}')
for definition in compileDefinitions:
cppArgs.append(f'-D{definition}')
cppArgs.append(f'-std={cppStandard}')
cppArgs.append(f'-x')
cppArgs.append(f'c++')
vulkanEnumFile = os.path.join(includeDirectories[0], 'vulkan\\vulkan.h')
index = Index.create()
translationUnit = index.parse(
vulkanEnumFile,
args=cppArgs,
options=TranslationUnit.PARSE_INCOMPLETE
)
for diagnostic in translationUnit.diagnostics:
print(diagnostic)
stack = [translationUnit.cursor]
while len(stack) > 0:
current = stack.pop()
if current.kind == CursorKind.ENUM_DECL:
print(current.kind, current.location)
for child in current.get_children():
stack.append(child)
return
worst python code ever written by humans
AI had no hand in the creation of this abomination
this has been painfully handcrafted by yours truly
It’s fine. What years of bikeshed to a man 
Now write a tool that does vk validation in compile time 
duplicateKeys = []
for (k, v) in enums.items():
if HasVendorSuffix(k):
removedVendor = RemoveVendorSuffix(k)
if removedVendor in enums:
duplicateKeys.append(k)
``` mmm efficient python code
what are you building exactly? : )
ah
python is almost not cancerous to write with type annotations btw
who knew that types were useful
the only real gripe i have with it is tab and the stupid indentation
if only
and 100 ways of doing 1 thing
Cringe, use list comprehension NOW
no :gigachad:
Append and loops in Python are forbidden 
its weird why they call it like that
rather than just map reduce blabla
like any other lang....... wait.... c++ also calls it different, c# too 😄
alright the conversions have been executed
now rename vulkan_core.hpp to retina_core.hpp
def as_retina_enum_values(name: str, values: {str: int}) -> {str: int}:
output: {str: int} = {}
common = find_common_enum_string(name)
for (entity, value) in values.items():
entity = entity.replace('VK_', 'E_', 1)
entity = entity.replace('_BIT', '', 1)
entity = entity.replace(f'_{common}', '', 1)
entity = remove_vendor_suffix(entity)
if entity.endswith('MAX_ENUM'):
continue
output[entity] = value
return output``` peak python code
readable
I could make it more readable
there it is
now I only have to figure out mako templates and the codegen is officially complete
it only took a few hours
@pale horizon mistrusted me
smh
It’s only the beginning… you think you’re almost done(tm)
it got worse btw
aight now I have all the enums it's possible to wish for
time to continue the engine™️
9000 untested lines of code of allah 
noice
code review time
@frank sail are you in as well
for the code review
I want the two professional™️ engineers of the server to see this
(because everyone else is a fake engineer frfr)
Alright gpgpu, I'll remind you about review da code in 2 hours, 49 minutes and 25 seconds. ID: 66379570
When you ask so nicely
I guess I can spare a minute
https://github.com/LVSTRI/Retina code review time
small caveat, you may or may not have to update your Vulkan SDK
enums were generated from 1.3.275
inserting barriers non batched like this will have performance penalties on at least nvidia
they arent auto merged
ye right now I can't merge them, unless I do it manually I guess
rendergraph is probably next on the list
its readable
i like that
i also like that not everything is public and static like in any other engine
CommandBuffer's interface is dangerous : )
the uninitiated could just call .End().Begin()
which you might block with some asserts inside, hehe you dont
im not a fan of the screaming constants E_ISMS but ill let it slide, this time
it do be
to solve this puzzle, temporal coupling could solve it, but might explode the class count
I've been lazy because it maps to vulkan 1:1, so validation layers will automagically catch stuff like that (End() before Begin())
fair
what ist temporal coupling?
you would not be able to call on .CommandBuffer at all, but .Begin() would return a new object, which allows all the things you usually record in order when recording a record
and only then you can call .End() on it
which returns CommandBuffer& again
recording commands probably follows the same patterns for various things
with that in mind one could cook up a few of those "temporal couplings" probably
anywho was just saying
ye it's definitely something I will use when rendergraph times come about
because command buffers in that thing will be more clamplicated
heh i can imagine
the class prefix C is also weird
but its tolerable
because all the other stuff is so neat and readable 😄
you could name all your classes and things RtXXX or RetXXX or even RetinaXXX
ah, oki
I'm still thinking about that
including enums and schtructs
deccer be teaching the dark arts to yet another apprentice
these barriers are annoyingly explicit, but obviously they map well to vulkan so eugh
https://github.com/LVSTRI/Retina/blob/master/src/Retina/Entry/Application.cpp#L158-L212
so far it looks clean though
also I'm not sure how useful it is to have these things that return a vector of objects
mesh shaders require geometry shader 
good catch
your code is very clean btw
here's hoping it stays that way
sometimes I feel like like a princess when I sprinkle auto, const, noexcept, and [[nodiscard]] around my code, but then I see your code and it looks like a c++ genie visited
there is one more thing which i dont like that much
MakeXXX instead of CreateXXX
Create shows intent better than make
i blame std::make_xxx<T>
std::make_lifetime_at
😛
c++ people dont know how to name shit properly imho
but its also a hard problem
id also get rid of the Entry folder and have everything in Regtina's root
real
lustri is the Dr. Frankenstein of 
ah good another engine to steal inspire my own design choices
What is the benefit of postfix return types anyway?
All your functions are nicely padded
When will this thread be renamed? 
we "beyond" now
I left it as is for nostalgia
Everyone hyped for Retina while I'm out here waiting for the "optic nerve" (version 3.0)
ray tracing at 3am (gone sexual)
did you know that you can put [[nodiscard]] on constructors
how do I stop clangd from complaining about hidden non virtual functions ffs
You can add comment decorations to turn off warnings
hidden non-virtual functions?
ye, when you do
struct Base {
int Get();
};
struct Derived : Base {
int Get();
};```
ah, that does feel a bit weird
You should put override here though 
is that allowed on a non-virtual?
it's perfectly reasonable to want this though
I don't need dynamic dispatch, I'm 100% sure I'll always know the type statically
I would just name them differently then
Just don't inherit from stuff. Ever 
use CRTP then
ye perhaps that's a solution
RetinaDeclarePushConstant() {
uint u_ViewBufferIndex;
};
RetinaDeclareBuffer(restrict readonly, SViewInfoBuffer) {
mat4 Projection;
mat4 View;
mat4 ProjView;
};
RetinaDeclareBufferPointer(SViewInfoBuffer, g_ViewInfoBuffer, u_ViewBufferIndex);``` this feels so good to use
With this the base Retina is ported over
raytracing is sadly missing but I didn't like the original API anyways
what do you do if the buffer has no qualifiers?
you just omit the first parameter
I thought macros didn't resolve like that, huh
I didn't test this but iirc they to
lemme try
ok yeah you're right
shit
fucking glsl piece of trash
it's a C thing too 😄
I think you only had good variadic macros in C++ 17 or 20
that can automatically tolerate 0 args to the variadic
no reintroducing methods should be a bannable offense
why :(
yeah macros are pretty primitive still unfortunately
because you hide Base::Get
then inheritance isnt the right tool for the job here
how would you do Buffer and TypedBuffer<T> then
same way jaker and i did itin the past
class Buffer {
GetSize(); // size in bytes
}
class TypedBuffer<T> {
GetSize(); // element count
}```
I don't remember 
ok that's fair
but I still need buffer and typedbuffer to be related
that's a hard requirement
also random question, what exactly is ArcPtr? it seems to be a smart pointer of some kind, but it's...odd to me. Reset will delete the underlying pointer which implies the class owns the pointer, but the class is copyable so it's not unique either
it's an intrusive shared_ptr
ahh, I missed the Grab and Drop calls; I thought you'd have a requirement on the template
ye perhaps I should add that requirement
where'd the name come from? 'cause I have the same thing but I just called it IntrusivePtr (which is more of a mouthful)
I might end up renaming mine to just Ref or something
I renamed my IntrusivePtr to RefPtr some time ago after a heavy dose of apple webkit code
call yours &
AmpersandOf<T>
berfect
KaufmannsUnd<T>
I forgor to check whether my thing builds on the penguin
i can try
I can also probably integrate CI as well because I don't clone shaderc anymore 
i am on a penguin laptop atm
KaufmannsUndies
sadness
xD
[build] /home/deccer/Code/External/Retina/include/Retina/Core/STL/ArcPtr.hpp:143:18: internal compiler error: in build_comparison_op, at cp/method.cc:1461
gcc 13.2.1
what in tarnation
actually incredible
and with clang it stops at including windows.h 😛
[build] /home/deccer/Code/External/Retina/src/Retina/WSI/Window.cpp:5:10: fatal error: 'Windows.h' file not found
[build] 5 | #include <Windows.h>
[build] | ^~~~~~~~~~~
[build] 1 error generated.
it makes sense that window.cpp would depend on windows.h
figure out why
figured it out yet?
I forgor to delete the copy constructor
clang decided to tell me in the most unhinged way possible
I tried to read the message on my phone, first I got a pop up to download it, then to read it in Google docs then another pop up that I first need to upload it to Google drive after which a popup of "give me permission to view your files" followed
After which I gave up
Bruh

[build] /usr/include/oneapi/tbb/detail/_task.h:169:(.text+0x3d9): undefined reference to `tbb::detail::r1::execution_slot(tbb::detail::d1::execution_data const*)'
[build] /usr/bin/ld: /tmp/cco0F0AY.lto.o: in function `tbb::detail::d1::current_thread_index()':
[build] /usr/include/oneapi/tbb/task_arena.h:451:(.text+0x3ed): undefined reference to `tbb::detail::r1::execution_slot(tbb::detail::d1::execution_data const*)'
does this tell you where the reference was named?

thats weird, i can only find tbbisms in tracy but it also seems to be disabled there
it's probably cause of LTO innit
i wouldnt know, i only know what lto is spelled out
but not how it conducts its bisnes
i did the classic delete build, lets see if that fixes it : )
ah, itnt
do you use std execution policies
I do not
it's tracy's fault, though idk why it links fine with clang but not with gcc
nope
rip
did rm build/ and reconfictured
idk mayhaps pull tbb (if it has sources available soewhere) if gcc
build and link with it for the time being
or require lunix people to instal libtbb and you just link with it if gcc
idk, I'm using GCC and there's no link to TBB
~/work/edbr/build$ ldd src/game
linux-vdso.so.1 (0x00007ffe2bfd9000)
libglm.so => /home/eliasdaler/work/edbr/build/third_party/glm/glm/libglm.so (0x00007f1b3db17000)
libfreetyped.so.6 => /home/eliasdaler/work/edbr/build/third_party/freetype/libfreetyped.so.6 (0x00007f1b3da1c000)
libSDL2-2.0d.so.0 => /home/eliasdaler/work/edbr/build/third_party/SDL/libSDL2-2.0d.so.0 (0x00007f1b3d600000)
libTracyClient.so.0.10.0 => /home/eliasdaler/work/edbr/build/third_party/tracy/libTracyClient.so.0.10.0 (0x00007f1b3d200000)
libvulkan.so.1 => /home/eliasdaler/work/vulkan_sdk/1.3.275.0/x86_64/lib/libvulkan.so.1 (0x00007f1b3d9a2000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1b3ce00000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1b3d521000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1b3d951000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1b3cc1e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1b3dbd1000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1b3d94a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1b3d945000)
~/work/edbr/build$ ldd /home/eliasdaler/work/edbr/build/third_party/tracy/libTracyClient.so.0.10.0
linux-vdso.so.1 (0x00007ffe0fef8000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1abf400000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1abf721000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1abfa45000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1abf21e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1abfa98000)
fatal: reference is not a tree: 923e865b7da81bfcab5c54f260c0f034953d406e
CMake Error at spirv-tools-subbuild/spirv-tools-populate-prefix/tmp/spirv-tools-populate-gitclone.cmake:49 (message):
Failed to checkout tag: '923e865b7da81bfcab5c54f260c0f034953d406e'
idk 
Don't want to debug for now
incredible
FetchContent issue
Git submodule chads win once again
I don't even clone spirv tools
i think i saw it the conf part too
spirv_cross-src is in build/Deps 😄
also elias is on some outdated debian 😛
I’m on testing! 
spirv-cross isn't spirv-tools; I double-checked the spirv-cross repo and they don't fetchcontent it in either
Okay, it builds, I had some merge conflict 
Did git pull again:
CMake Error at Dependencies/CMakeLists.txt:174 (target_sources):
Cannot find source file:
/home/eliasdaler/work/repos_to_check/Retina/Dependencies/cgltf/Implementation.c
CMake Error at Dependencies/CMakeLists.txt:173 (add_library):
No SOURCES given to target: cgltf
FetchContent is a meme
(Yes, I removed build dir and created it again)
Dependencies/CGLF
bro...
More like case insensitivity here
diff --git a/Dependencies/CMakeLists.txt b/Dependencies/CMakeLists.txt
index 4ee1997..ec72b9c 100644
--- a/Dependencies/CMakeLists.txt
+++ b/Dependencies/CMakeLists.txt
@@ -172,7 +172,7 @@ if (NOT cgltf_POPULATED)
FetchContent_Populate(cgltf)
add_library(cgltf STATIC)
target_sources(cgltf PRIVATE
- ${CMAKE_CURRENT_SOURCE_DIR}/cgltf/Implementation.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/CGLTF/Implementation.c
)
target_include_directories(cgltf PUBLIC
${cgltf_SOURCE_DIR}
xoxo
incredible
ye that's on me 
Also what do I launch now 
are you on latest
Yes
Retina.Entry
Beautiful, 11/10 raytracing
~/work/repos_to_check/Retina/build$ ldd ./src/Retina/Entry/Retina.Entry
linux-vdso.so.1 (0x00007ffce9340000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fcd50600000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fcd50521000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fcd5088c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcd5033f000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcd508df000)
hmm, no Tracy and no TBB
It's actually "no, tbb"
option(RETINA_ENABLE_LOGGER "Enable logging" OFF)
option(RETINA_ENABLE_PROFILER "Enable CPU profiling" OFF)
also they're all static so they wouldn't be in ldd anyway
Build shared libs is ON by default I think. Unless LVSTRI overrides it
true, but all of the parts Retina.Core, Retina.Graphics, etc are set as static, which...I think forces all of their dependencies to be baked in too?
Ah, I see
we're back
now, time to make that VSM sample I promised to jaker
and then rendergraph
VSM shrimple

