#Fwog and co.

1 messages · Page 20 of 1

heavy cipher
#

random static constexpr be like

long robin
#

hey man static constexpr is actually considered helpful

#

or maybe it was inline constexpr bleakekw but still

heavy cipher
#

no doubt it has an effect, but i wonder why that single declaration merits it, but not the rest

long robin
#

ah

#

probably copied it from my examples which have a similar construct in the global namespace

#

putting the static bit in a function is a bit quirky fr

tired sandal
#

Fwog is love
Fwog is live frogeheart

modern saffron
#

Most sane opengl driver

fiery sorrel
#

Thanks for spotting the mistake.

#

I am looking through the history of that file to see if I did get it from there

fiery sorrel
golden schooner
#

thats exactly how i pictured you for a long time

#

: >

#

this kind of glasses hehe

golden schooner
#

@fiery sorrel i did click it, but the dark theme looks better

fiery sorrel
#

I think I could set if I want it to be Dark or Light as default. I prefer light and find it more professional. Maybe there's a way to set it to system default or something even from a website?

golden schooner
#

there should be ways to detect it

#

but i know 0 when it comes to webshit

fiery sorrel
#

Yea. There are for native apps. Not sure if there is from javascript tho or if thats a security thing. Maybe id look into it as a form of curiousity

#

anyways my Sunday is nearly out so it was nice to chat on the Discord

#

ive been more productive without bein on the cord. I DM @long robin sometimes with the side stuff i work on

golden schooner
#

jaker should install office hours and charge for it too 🙂

fiery sorrel
#

I dont ask him for help!

#

Unless you meant office hours like a therapist type of deal

golden schooner
#

neither, but thats ok

#

there is also a smiley at the end

fiery sorrel
#

:p

#

anyways point is even tho im less active, im actually "more active" when it comes to coding and GP stuff in general.

#

Been spending my newfound free time freed up by less Discording with studying and stuff

#

mayb id become more active in a year or two once I have the skill level to slack off, but now I feel more inspired to catch up to the big guys ig haha

#

point is, just becos i ain't here doesn't mean I gave up on GP and all the stuff I learned here u know

golden schooner
#

i got that the first time 🙂

#

its good that you made it out of the discord hole

long robin
#

mostly

fiery sorrel
#

I let myself come on Sunday

#

but I also notice that when I have it i end up way more distracted n get last done

#

I guess for now its like a 'reminder' why i have such a personal goal.

dapper gorge
#

I wish I had your will

#

I don't know how I got through this years exam session KEKW

#

I'm stuck in endless self-destructive procrastination

#

but at least I have traced sponza

fiery sorrel
#

you got this! If you start studying as soon as you can its a lot easier. You seem to have the work ethic since you do work on your projects often, so its just a matter of prioritization for you. I believe you can do it :)

heavy cipher
#

had n idea @long robin

#

do you share headers between ye glsl and ye host

long robin
#

not yet. I haven't thought of a good way to do it

#

well, I haven't tried too hard either nervous

heavy cipher
#

i don't think it is too bad as long as you don't use glsl to align

#

aka let glsl layout and then match the host to that

long robin
#

hmm

heavy cipher
#

anyways, i wuz thinking - it would not be terribly difficult to have a lil' bit of cheeky cmake build part that would dump layouts of the shared structs for both glsl and ZE HOST and then verify if they match

long robin
#

I could imagine doing shared headers if I had a compatibility header, like what we use in FidelityFX

long robin
heavy cipher
#

which one?

long robin
#

either one

heavy cipher
#

glsl via glslang

long robin
#

ye

#

ok what about host

#

clang?

heavy cipher
#

host via clang

#

yes

long robin
#

now how do I match the structs between the two

heavy cipher
#

with the power of baba and booey

long robin
#

or is that where the shared header part comes in

heavy cipher
#

well yeah

#

you just match the fields

#

if they are at the same offset

#

the contract is correct

long robin
#

I think it would be better to make matching the layouts easier in the first place, rather than offering a way to check that they match

#

ya feel?

#

I could ask potrick how he does it for daxa (I think with macros)

heavy cipher
#

i do not feel

long robin
#

making a struct-layout-checker feels equivalent to a sanitizer, when those bugs could (ideally) be impossible to make by construction

heavy cipher
#

@snow sun reveal thine secrets

long robin
#

custom types with alignas should be able to match std430 without too much difficulty I think

#

could gate those types with a define in a header, then include that in headers where I define shared structs

heavy cipher
#

you would need a macro to introduce the type name i guess - not the end of the world i suppose

#

but still, what you get is not superbly C++

heavy cipher
#

its scalar only

long robin
#

hecc

#

another alternative is to never use built-in vector and matrix types in glsl

heavy cipher
#

naw, won't save you

long robin
#

also don't use std140

heavy cipher
#

ah

long robin
heavy cipher
#

also thats just scalar with extra steps

long robin
#

exshrimpactly

heavy cipher
#

this word has permanently damaged my anterior cingulate cortex

#

i'd still like to know the impact of scalar on the various hw and buffer types

long robin
#

on AMD, you get at worst unnecessarily small loads (in my testing, though it seems the SC has gotten better since), which can cause extra cache misses

dapper gorge
#

I'd much rather study the impact of scalar on my brain

long robin
#

idk about NV and idc since they won't let me see ISA very easily

#

clamclusion: always use scalar block layout frOK

heavy cipher
#

i am more worried about coalescing

#

lets deal with the devil

long robin
#

coalescing what

#

loads and stores?

heavy cipher
#

lmao gottem

long robin
#

mao le

heavy cipher
#

but yes

long robin
#

AMD should be perfectly capable of doing it for UBOs and SSBOs

heavy cipher
#

what do you base this on

long robin
#

my own tests and interpretation of the ISA

dapper gorge
#

so you made it up

#

got it

long robin
#

I have benched the perf impact of scalar block layout on AMD

heavy cipher
#

but coalescing is independent of the isa

long robin
#

then clarify what you mean

heavy cipher
#

coalescing is the hw grouping mem accesses

#

it doesn't happen on the isa level

long robin
#

ah, I thought you meant turning small loads into big loads in the ISA

heavy cipher
#

thats one thing

long robin
#

I do not have any idea about the hw coalescing

heavy cipher
#

perhaps even starts with that

valid oriole
#

looks at author
god he's everywhere

heavy cipher
#

yeah

long robin
#

I guess the question is (pardon my jargon) how does unaligned mem access affect hw schtuff

heavy cipher
#

ig this is what devsh is sayin

#

you still do 430 alignemenets, the compiler doesn't generate shittier code with scalar

long robin
#

that's boring

heavy cipher
#

maybe we can send pixel into the aco mines

long robin
#

can you unroll that abbreviation for me

heavy cipher
#

P pixelduck
I ig its pixelduck
X x gon give it to ya (it == pixelduck)
E eeeey its pixelduck
L life is going by while i meme on this server

valid oriole
#

aco stands for AMD compiler

#

v helpful I know

#

(it’s the amd gpu compiler backend in mesa)

heavy cipher
#

@valid oriole do you know anything bout this stuff

valid oriole
#

hmm I think at least as long as you stay 4-byte aligned amd hw shouldn't really do stupid stuffs

#

at least I don't know of any reason to do stupid things

#

i'd be quite disappointed if scalar loads of e.g. a vec3 + a float won't turn up as buffer_load_dwordx4

heavy cipher
#

right, but thats not the entire picture

long robin
#

@silver shoal might know

heavy cipher
#

but can he tell frog_think

long robin
#

he can tell if he can tell

heavy cipher
#

but can he

long robin
#

alternatively, I can dig and then see if I can tell

#

but I don't feel like looking at hw docs tomorrow bleakekw

heavy cipher
#

does that mean you look today

long robin
#

well it's 3am, so technically you're correct

#

which is one of the corrects of all time

long robin
#

yeah std140 arrays suck and I don't use them

heavy cipher
#

430 arrays of vec3 too

long robin
#

why would you ever want more than one of something

snow sun
#

one of the problems i had with scalar was that anything above 64 didnt properly align but that was a bug and fixed

#

usually scalar exactly matches c

long robin
#

but you have to qualify it or martty hits you with a chair

snow sun
#

as long as you have the same type bit width. eg you must enable int64 if you wanna transport buffer references in steucts to march them

#

i have some tests foe it

#

but i went to always use scalar to preserve my hair, the aligning thing was just too sketchy for me in the end

snow sun
#

you can cheat

#

just make vec3 a vec4

#

😎

heavy cipher
#

its an option to ban vec3

snow sun
#

yea

long robin
#

alignment doesn't really cause me issues anymore

#

it's more annoying having to synchronize structs

snow sun
#

agreed

heavy cipher
#

there is benefit to shared, yes

snow sun
#

@heavy cipher curious what cases you could cause you trouble for unaligned ness and worse coalesing

#

i accidentally tested unaligned aromic perf a few weeks back, even if you are 3 bytes off they are the same speed on a 1080

#

i would assume amd can do similar but my renderer crashes on amd atm

#

but i am in the camp now what when i could be read or write limited i manually make sure vec4 and mats and such are 16byte aligned

#

no biggie

#

scalar for life

heavy cipher
#

don't think the atomic perf is the key

snow sun
#

ok

silver shoal
#

Uhhhhh in terms of coalescing vmem operations it should all happen inside the L0? Just by manner of being a cache

#

It just takes an address per thread so if they all hit it will be quick

snow sun
#

not sure if that is much of a problem anymore

#

but i got into situations where even okish close loads were just filling the read queue so it couldnt issue more reads

#

but this is oldold

#

new gpus likely can just have the unaligned load in the queue instead of having to issue split loads directly

#

nvidia also makes a big point about how coalesing within warps is very important, but they never really mention alignment

silver shoal
snow sun
silver shoal
#

Damn the word quad has been changed to queue

heavy cipher
#

just uhh send over the hw docs, we can fish it out from there yaymd

silver shoal
#

In that case yes hits will get stuck behind misses to return to shader in order

silver shoal
heavy cipher
#

but idk bout rdna

snow sun
#

yea

#

gcn is angery

#

wait 64???

#

i thought it was 16 only

#

oh im dummi

heavy cipher
#

as i suspected, you have to look at cuda

#

Global memory resides in device memory and device memory is accessed via 32-, 64-, or 128-byte memory transactions. These memory transactions must be naturally aligned: Only the 32-, 64-, or 128-byte segments of device memory that are aligned to their size (i.e., whose first address is a multiple of their size) can be read or written by memory transactions.

When a warp executes an instruction that accesses global memory, it coalesces the memory accesses of the threads within the warp into one or more of these memory transactions depending on the size of the word accessed by each thread and the distribution of the memory addresses across the threads. In general, the more transactions are necessary, the more unused words are transferred in addition to the words accessed by the threads, reducing the instruction throughput accordingly. For example, if a 32-byte memory transaction is generated for each thread’s 4-byte access, throughput is divided by 8.

snow sun
#

cuda docs are actually pretty insightful many times

heavy cipher
#

let me correct you: nvidia forgoes publishing anything else basically

snow sun
snow sun
#

but its clear that aligned makes life easier

heavy cipher
#

it seems clearish to me

#

what is vague?

snow sun
#

the limitation of the coalesing

#

it doesnt really say it will always merge all addresses that follow on each other into larger loads

#

frog_thinkk i guess they say that

#

what does it mean with "unused words"

#

does it do a 16 byte load when for example you issue 4byte loads at 0 and 8 leaving half the load unused?

heavy cipher
#

yes

#

the loads are always at least 32 byte big

#

if the invocs don't use all of it, effective throughput goes down

snow sun
#

oh i read bits

#

byte

#

damn

#

i literally cant read

#

🦯

heavy cipher
#

what is the potrick coalescing situation

#

must've misaligned the text KEKW

snow sun
snow sun
#

so its more about having addresses close together

#

and ofc not overstepping the bounds of an aligned load when possible

#

so when loading 32 bytes, better make that aligned

heavy cipher
#

this is global memory

snow sun
#

yea

#

interesting that its not simply cache line size, or is a cache line only 32 bytes?

#

128bytes

#

hmm

heavy cipher
#

so on amd it seems like the cacheline is 64 byte

snow sun
#

aha

#

nvidia l2 is 32 byte

#

l1 is 128

#

this makes sense now

oak garden
#

unarchiveth thee

sullen carbon
#

did you get some oil money or sth KEKW

long robin
#

mashallah

wind trout
#

FwogVk confirmed 💯

dapper gorge
#

pog

final cove
#

wow 100 stars

golden schooner
#

but nobody provided any feedback neh?

#

except basil and the few of us

final cove
#

I have no idea how other people use github tbh

golden schooner
#

same

daring surge
#

272 stars, only like 10 people max who i've seen talking about actually having used it

#

i'd guess the percentages of the remainder are

  • people who use it but don't communicate at all (5% max)
  • people who don't use it but think they might at some point (~45%)
  • people who just think it's cool (~50%)
golden schooner
#

ja its sad somehow

#

but same for all my other projects too

#

at least we have us 🙂

dapper gorge
#

mfw I am one of the people who don't give feedback bleakekw

golden schooner
#

you do

final cove
#

aren't the last 2 types pretty much the same

#

95% "oh this is neat I gotta use it/copy it at some point" forgets

daring surge
#

#3 isn't even really necessarily a graphics programmer to me

#

like the couple people in college that i talked to about my game at the time that starred it despite the fact that they could never build it

golden schooner
#

i also forget about things i have starred in the past : )

final cove
#

I basically don't star anything, if it's useful I just clone it into my "other people's repos" dump folder

#

especially since keyword searching in github sucked for a long time (maybe still sucks?)

#

greping local files is convenient

golden schooner
#

i know what you mean

#

finding/searching information really sucks

#

or catalogueing and then finding 🙂

long robin
#

the talk about tracy in #bikeshed-😇 has me thinking if I should add some integration in fwog

heavy cipher
#

ye, i was thinking the same

#

get working

long robin
#

hmm how should I handle the case where the user already has tracy installed

heavy cipher
#

i wouldn't integrate tracy

#

profiling hooks

long robin
#

are those just callbacks

#

I guess that'd be an easy API change

heavy cipher
long robin
#

hmm

#

does tracy see gpu frame markers or nah

heavy cipher
#

dunno

long robin
#

alright I'll see how it turns out

#

but I will prepare for the worst

heavy cipher
#

and i shall prepare for the wurst

long robin
#

hmm

#

can tracy even use runtime identifiers for scopes

#

I remember someone here having an issue with it

heavy cipher
#

transient zones or summin

long robin
#

3.1
Handling text strings
When dealing with Tracy macros, you will encounter two ways of providing string data to the profiler. In
both cases, you should pass const char* pointers, but there are differences in the expected lifetime of the
pointed data.

  1. When a macro only accepts a pointer (for example: TracyMessageL(text)), the provided string data
    must be accessible at any time in program execution (this also includes the time after exiting the main
    function). The string also cannot be changed. This basically means that the only option is to use a string
    literal (e.g.: TracyMessageL("Hello")).
  2. If there’s a string pointer with a size parameter (for example TracyMessage(text, size)), the profiler
    will allocate a temporary internal buffer to store the data. The size count should not include the
    terminating null character, using strlen(text) is fine. The pointed-to data is not used afterward.
    Remember that allocating and copying memory involved in this operation has a small time cost.
#

we good

#

now I'm trying to remember why I didn't use a string_view here froge_bleak
void (*verboseMessageCallback)(const char* message) = nullptr;

heavy cipher
#

robert downstream junior

long robin
#

be me
want type-erased callable wrapper to dodge a fat include that leaks impl details in a header
realize std::function is exactly what I want
realize that #include <functional> is probably 10x more expensive than the other header

wind trout
#

How difficult do you think FwogVk would be? Do you think it would be possible to keep 100% of the current Fwog api but have a version that was Vulkan behind the scenes?

golden schooner
#

fwog is more or less inspired by vookan

long robin
#

I think if I made a vk version of this I'd just expose raw sync primitives

#

I could also make a render graph but I know that's a bit of a worm innit

daring surge
#

vuk backend for fwog

wind trout
#

I wonder how close fwog is to being a layer on top of a low level backend that people could add as needed

#

Especially since you did all the hard work to come up with the interface already

final cove
#

make a validator that throws errors at the user for not calling your barrier funcs appropriately, even in GL

#

that way when you make FwogVk no code will change

long robin
heavy cipher
#

the problem is that the amount of info ( misinfo ) you give to the gl driver is not the optimal amount

long robin
#

Yeah that's why I'm not keen on making fwogvk have the exact same interface

heavy cipher
#

aye

#

in fact vuk is higher level than opengl in some respects, funny that

long robin
#

but you have figured out the optimal amount of info to ask for and determined what things can be automated with that

golden schooner
#

did you fix the srgb-imgui-ism yet?

heavy cipher
#

PRs welcome deccy

golden schooner
#

im still afraid of vk : S

long robin
#

Have you considered getting over it

#

Inshallah deccer will write an epic Vulkan renderer

golden schooner
#

vkEnumerateInstanceExtensionProperties is the only function call in there vk related : >

heavy cipher
#

just use vook

golden schooner
#

: )

#

i would like to be comfy enough making a gpu driven thing first, using opengl 🙂

long robin
#

more optimal than gl at least 🙂

#

||sorry, that must be borderline insulting as it's not hard to be better than GL bleakekw||

heavy cipher
long robin
#

yeah like [redacted]

golden schooner
#

: )

#

did you have something comparable before vuk?

heavy cipher
#

no, nothing of the sort

golden schooner
#

ah

#

would be interesting to see people go from api1 to api2 and compare, see if api2 is the holy grail and that it was absolute worth the effort

#

or whether performance is now worse 🙂

heavy cipher
# long robin yeah like [redacted]

mmm, currently i have ideas for: new FE, new BE, improving allocators, new pipeline paradigm, support lib stuff like reactors, batcher, SPIRV templating and third party integrations of le FSR and SPD and other algos

#

time machine when 😔

golden schooner
#

when do you start?

dapper gorge
#

or time machine as in go back

golden schooner
#

perchance lvstri can help

dapper gorge
#

I'd rather the first one tbh KEKW

golden schooner
#

vukfood thread when

heavy cipher
#

go back, shoot my kneecaps out of mercy

golden schooner
#

fukvood*

dapper gorge
#

except maybe FSR and SPD

golden schooner
#

haha

#

FE = frontend

#

BE = backend

#

martty is a webdev, trying to improve build pipelines and CSS generators 😛

long robin
#

BE = bellend

golden schooner
#

hehe

heavy cipher
#

most of these have some work done already

golden schooner
#

is that going into the (series of) article(s)

heavy cipher
#

ah yes, thanks, i could also be writing articles frog_gone

golden schooner
#

: )

#

need to keep the frogs on their toes

long robin
#

Btw reflection is a bit annoying to implement because

  1. Images and samplers use regular uniforms, which are queried with GL_UNIFORM
  2. variables in uniform blocks are also iterated over with GL_UNIFORM
golden schooner
#

blocks are ugly af to reflect

long robin
#

Luckily I just need the binding

#

But for images and samplers, I have to iterate all uniforms 😦

golden schooner
#

indeed

#

are you reflecting right after linking the program?

long robin
#

So I'll have a massive switch to check the uniform type

heavy cipher
#

continously reflecting on if torturing oneself with opengl is a good hobby

long robin
#

It's like acupuncture

#

It's healthy if you ignore proven fact

golden schooner
#

thats a good response : D

#

acupuncture healed my sister's hay fever

long robin
heavy cipher
#

is fwog spirv only or not btw

long robin
#

Only not spirv atm

#

Raw glsl as god intended

heavy cipher
#

dank

long robin
#

As in uncomfortably damp and moldy

heavy cipher
#

e

fallen fog
#

does this wrapper add some debugging features? as people generally complain about openGL being a bad degbugging experience

tired sandal
#

Fwog gives you a callback

#

and also logs what Fwog creates/destroys

long robin
#

Ye not as good as Vulkan/dx in it's debug layer, but better than raw gl

golden schooner
long robin
golden schooner
long robin
#

I'm gonna have to add a feature to fwog to enable rendering to imageless framebuffers

golden schooner
#

oh?

#

to detect formats?

long robin
#

um I'll show you

golden schooner
#

let me strap in

long robin
#

that is how you set the render dimensions, etc. when rendering to no texture

golden schooner
#

oooh (its gl4.3+ stuff, explains why i thought it would otherwise be nimcoimplete)

long robin
#

actually, shouldn't glViewport suffice already frog_think

golden schooner
#

dependson what you want to do? 🙂

long robin
#

e.g., I want to render to a 16k x 16k area

#

but have no texture attached

#

I want to use gl_FragCoord.xy and write to an image instead

golden schooner
#

i would imagine, fbs need to be complete with a color or depth target

#

and if you dont you get an error 🙂 no?

#

then the param you showed will make sure you can have an empty fb

long robin
#

param specifies the assumed width for a framebuffer object with no attachments. If a framebuffer has attachments then the width of those attachments is used, otherwise the value of GL_FRAMEBUFFER_DEFAULT_WIDTH is used for the framebuffer

#

maybe this stuff is just for glGet frog_thinkk

golden schooner
#

should do the trick then

#

hmm

#

render to an image... is also still beyond my imagination

#

i am thinking you draw to using a compoot shader?

golden schooner
#

aaah : this feels like a hack, crammed in there after the fact

long robin
#

we don't want a literal 16k texture, we just want to see where the samples land and write them to resident pages

golden schooner
#

i see

#

then glViewport wont do the trick alone

long robin
#

so what happens if you glViewport larger than the area of the framebuffer

#

error?

golden schooner
#

at least a warning

long robin
#

However, the rasterization of primitives is always based on the area and characteristics of the bound framebuffer
yeah so I guess I need glViewport in addition to this

golden schooner
#

indeed it also says "otherwise business as usual"

#

you only pretty much just disabled fragment stage

#

now re fwog

#

would it be reasonable to have a dedicated BeginRenderism function for that sort of ism

long robin
#

I can add a shrimple check in fwog to see if there are any attachments, then call glFramebufferParameter if there are none

golden schooner
#

hmm

#

i think thats dangerous, what if you accidentally forgor to specify any targets, and dont want to render into empty fbo

long robin
#

because the Render function already takes a viewport that we can derive a size from

#

idk when the viewport size would need to differ from the framebuffer size in this case

long robin
golden schooner
#

can we spdlog::warn loggerHackCallback("are you sure you are doing the right thing? ill assume x for now. just so you know. dont come back and complain if the screen is black my mf");

long robin
#

hehe

#

a specific function for rendering with no attachments wouldn't be bad either

golden schooner
#

ikr

long robin
#

it would allow expressing the other glFramebufferParameter stuff like layers too

#

and shrimple count

golden schooner
#

exactly

long robin
#

curious

Conceptually, virtual shadow maps are just very high-resolution shadow maps. In their current implementation, they have a virtual resolution of 16k x 16k pixels

#

max viewport for most things is also 16k

golden schooner
#

16k should be enough

long robin
#

ye

golden schooner
#

would be cool if all that technicality could be visualized later down the road too

#

for debugging purposes... somehow

long robin
#

visualize what exaccly

golden schooner
#

hmm i didnt think that through tbh

#

: >

long robin
#

I could make a residency visualization like js has in #1090536732769927178

golden schooner
#

HOWEVER

long robin
#

#1090536732769927178 message

golden schooner
#

usually my dumb comments trigger a little corner of your brains a few days later somehow, and you always come around with some idea/solution/implementation of sorts

long robin
#

had to scroll really far to find that one

golden schooner
#

proof once again i am right 😛 (jk) (jk = jaker kidding)

long robin
#

that only adds up to 22 bits

long robin
#

maybe there are 2 bits for the guard band for 24 bits total

#

then the other 8 bits are ???

golden schooner
#

__reserved

long robin
#

or maybe it's just 10 guard band bits

#

that gives the gpu a yuuge area in which it doesn't have to do clipping

golden schooner
#

which is a good thing

long robin
#

I should pay closer attention to those internal docs

golden schooner
long robin
#

there's no deccer at work to dogjiff.gifjif me when I forgor something

golden schooner
#

put it on your fone, quick access button thing

long robin
#

-100000 productivity

#

maybe I should just tape a pic of the dogjif to my monitor to remind me

golden schooner
#

or find one of those photo frame thingies which can play a clip

wind trout
signal widget
long robin
signal widget
#

Neat 📸

long robin
#

it is not the funny number. you may not laugh

valid oriole
#

now push two commits at once

brazen glacier
#

unreal engine in shambles

golden schooner
#

fwog does a weird thing with stbi

#

i wonder why you decided to include it that way

#

hand including vendor/stb_image.cpp to all projects etc, rather than just compiling into a liblibstbi 😛

#

i cant trivially include <stb_image.h> in Application.cpp

long robin
#

Fwog does nothing with stbi

#

Just the exshrimples

heavy cipher
#

jaker, fix your 🇸🇹 🇧🇮🇸🇲s immediately though

  • signed, deccer
golden schooner
#

and i did a thing

long robin
heavy cipher
#

make the icon be froghorror but the eyes follow the cursor

golden schooner
#

i use that icon for my shit already 😄

#
error C2664: 'char *stb_include_string(char *,char *,char *,char *,char [])': cannot convert argument 3 from 'const char [19]' to 'char *'
#

wth

#
    char* accumulateDensity =
      stb_include_string(Application::LoadFile("shaders/volumetric/CellLightingAndDensity.comp.glsl").data(),
                         nullptr,
                         "shaders/volumetric",
                         "CellLightingAndDensity",
                         error);
heavy cipher
#

const cast time

golden schooner
#

seems to be a msvc via cmake-tools-in-vscode thing now

#

didnt even touch those lines

#

alright, vs doesnt give a shit... and the frog works

long robin
#

Lol

long robin
golden schooner
#

i worked around that artificial stick

#

is there a/another reason for the fork?

long robin
#

Nope. I just fixed const correctness

long robin
#

that is why you needed const_cast

#

explains the entire previous convo froge_bleak

long robin
golden schooner
#

hmm

#

i kind of remember now

#

but im also not a fan of keeping copies which go stale on day 1

#

i could perchance fetchcontent your fork instead of pulling it from upstream, unless stb accepts your PR

heavy cipher
#

fat chance of that i think

long robin
#

Why do you have to fetchcontent anything

#

This all feels pretty orthogonal to what the PR is supposed to do

final cove
#

imagine rerunning cmake and every time there's a chance that some web pull will maybe break your engine

#

using a never-upstream'd fork is not that different to keeping a submodule locked on a particular commit

golden schooner
#

it would just be fantastic if stb wrote warning free code, but thats what you get from using a 30 year old compiler?

golden schooner
final cove
#

30 year old coding practices more like

golden schooner
#

its also partially my inability to c++, vscode, vs and clion also behave different

long robin
#

Some (most) people are stuck doing what they are comfortable with

final cove
#

personally I'm starting to warm up a ton to keeping frankenstein'd forks of libs I use

#

that's the beauty of open source after all

golden schooner
#

why fetchcontent? because everything else is also fetchedcontented tbhed, and having lose dependencies flying around in your folders is "weird" (tm)

final cove
#

third_party directory

golden schooner
#

its still a mix

#

i like order 🙂

#

and i want to smear it all over the place when i can, obviously hehe

final cove
#

so many people use the third_party directory thing that it doesn't feel out of order to me

#

silently making web requests whenever I rerun cmake is out of order

golden schooner
#

if cmake worked/is used properly it shouldnt, but i understand what you mean

long robin
golden schooner
#

none of the tools can compile fwog from main, as is

#

its weird

long robin
#

Hm

golden schooner
#

ci can it seems

#

but when i change #include <stb_image.h> #include "stb_image.h" in vendor/stb_image.cpp then it work

#

< > means there needs to be a -I set properly

#

but there is none

#

oki, fetchcontent is gone, only thing i did to stbi is the "stb_image.h" thing

long robin
#

I don't get the difference between <> and ""

#

I thought they just changed which directories were searched first in most compilers

golden schooner
#

from my little c++ understanding is "foo" is just raw directory structure, while <foo> relies on include dirs

#

<stb_image.h> would work if i did -Ivendor

long robin
#

I think in msvc it works a little differently but you can change that if you need

golden schooner
#

i did change it 😉

#

it should also be same in vs, but vs do be doing something differently for some obvious raisins

#

let me boot into windows to just double check that it also works there still

heavy cipher
#

you probably were compiling in permissive mode

#

or something to that effect

golden schooner
#

is there some sort of "sane" default flags one should set?

#

for either cmake or individual compilers somehow

long robin
#

I'm compiling with permissive- on msvc

golden schooner
#

indeed

#

/permissive-

long robin
#

I have the compile flags a bit looser for gcc/clang since I don't regularly build with them

heavy cipher
#

what are all the flags?

golden schooner
#

that syntax is a nightmare 😄

long robin
#

Ye luckily I copied it from another project so I know it works smart

heavy cipher
#

inshallah the structure was padded

golden schooner
#

asan also seems to be available as a definition already ASAN

#

or possible leaked from other dependencies which doesnt properly name it

#

anywho... booting into michaelsoft binbows

heavy cipher
#

why are you enabling asan for debug builds 🤔

golden schooner
#

pointing at hajji

long robin
#

When should I enable it

#

I figured it would be helpful to have in debug builds

heavy cipher
#

asan is a significant overhead i thought

long robin
#

All the exshrimples run fine here, even in debug

final cove
#

I think there are indeed asan-related builtins in cmake

golden schooner
#

almost all

#

msaa needs to build with stbi too 😉

heavy cipher
long robin
#

at least 240 fps (vsync limited)

#

Tbh I'm not even sure if asan is being enabled correctly

#

I'll have to check later

heavy cipher
#

is DEBUG a cmake thing

golden schooner
#

good question

heavy cipher
#

i haven't seen it, nor does it seem to be mentioned in your cmakelists

golden schooner
#

CMAKE_BUILD_TYPE is and default values seem to be Debug, Release, RelWithDebInfo and MinSizeRel

heavy cipher
#

this asan is gonna be fast bc its not enabled i bet

golden schooner
#

: )

long robin
#

mao le

final cove
#

and [empty string], the secret build type

golden schooner
#

at least the frog runs fine now everywhere

#

ci seems also happy

long robin
golden schooner
#

at thomas the train

long robin
#

eheh

#

I just copied that project when I was learning cmake

golden schooner
#

: )

#

nothing wrong with that

long robin
#

nvm it still doesn't crash with this 💀

int i[5];
int main()
{
  i[100] = 2;
}
#

oh but it crashes when I make the array have 100 elements like in their example frog_thinkk maybe it only works if you go barely oob

#

asan found one error on cleanup already

long robin
#

seems like a false positive since it is erroring in a non-null optional with "container overflow" frog_think
(it wasn't a false positive in the end)

golden schooner
long robin
#

a static analyzer can detect it

golden schooner
#

code analyzers dont prohibit the compiler from saying no

#

unless its confiktured to emit one and not just a hint/warning???!

long robin
#

ye

#

but it's def not a compile error

golden schooner
#

why not 🙂

#

*rhetorical question

dapper gorge
#

there's actually an answer

#

albeit not a satisfying one KEKW

golden schooner
#

its ridiculous

dapper gorge
#

the C++ stanadard™️ says that OOB is "ill-formed no diagnostics required"

golden schooner
#

smh

dapper gorge
#

many things are "no diagnostics required" KEKW

golden schooner
#

im sure its useful for some stupid embedded bs

dapper gorge
#

probably

golden schooner
#

but then it should be an opt in

dapper gorge
#

you can get the header of a malloc allocation by going out of bounds, if you so wish KEKW

golden schooner
#

anyway i shouldnt complain about anything c++ related, i barely know her

long robin
#

I just got the email

#

what kind of edge case did you discover?

golden schooner
#

my main monitor is at -something, +something not at 0,0

#

you get that when you arrange your desktops in various control panels... right monitor is vertical and i do be rembering that i fiddled with moving the main one around to not get stuck all the time when moving le cursor

long robin
#

interesting

golden schooner
#

and was wondering why my setwindowpos always made the window appear towards the top of the screen and is no longer centered 😛

#

since you and i use the same centering code, i took it upon me to fix it in fwoggi too

#

i should check erhe too probably

#

and send PRs to ALL!! other repos using glfw xD

long robin
#

I can fix it myself in frogfood lol

golden schooner
#

i should have made it into 3 PRs tbh ;P

long robin
#

heh idc

golden schooner
#

its good practice 🙂

golden schooner
#

i need to look into tbb, its quite annoying 🙂

robust bough
#

Is it legal to not provide any input desc if I'm doing a bufferless FST?

golden schooner
#

no, but you need a default vao for it

robust bough
golden schooner
#

: (

#

you say FST, i understand FST vs, where the vertices are defined there, the layout implicitly too => no vao setup needed, besides having a default vao bound

#

where FST = Full Screen Triangle

#

@robust bough or what do you mean?

robust bough
#

im basically wondering if I can do this

void renderer::composite(const glm::ivec2 &target_size) {
  Fwog::RenderToSwapchain(
    Fwog::SwapchainRenderInfo{
      .name = "Render Triangle",
      .viewport = Fwog::Viewport{.drawRect{.offset = {0, 0}, .extent = {static_cast<uint32_t>(target_size.x), static_cast<uint32_t>(target_size.y)}}},
      .colorLoadOp = Fwog::AttachmentLoadOp::CLEAR,
      .clearColorValue = {.2f, .0f, .2f, 1.0f},
    },
    [&]
    {
      Fwog::Cmd::BindGraphicsPipeline(pipelines.composite);

      Fwog::Cmd::Draw(3, 1, 0, 0);
    });
}```
#

when the pipeline is just a bufferless fst

golden schooner
#

if your vs is a FST that should work

#

then your composite pipeline wouldnt require vertexinputdescriptions

robust bough
#

yeah, i really should have just seen if it worked before asking facepalm

#

(im having unrelated issues now)

golden schooner
#

hehe, does it?

robust bough
#

heh

#

yes opengl, main is already defined for sure

#version 460 core

layout(location = 0) out vec3 v_color;
layout(location = 1) out vec2 uv;

void main()
{
    vec2 position = vec2(gl_VertexID % 2, gl_VertexID / 2) * 4.0 - 1;

    gl_Position = vec4(position, 0.0, 1.0);
    uv = (position + 1) * 0.5;
}
golden schooner
#

perhaps you assigned vertexshader twice

#

not sure if fwog asserts proper vs/fs types

robust bough
#
Fwog::GraphicsPipeline renderer::create_composite_pipeline() {
  auto vertex = create_vertex_shader("assets/shaders/composite/vert.glsl");
  auto fragment = create_fragment_shader("assets/shaders/composite/frag.glsl");

  return Fwog::GraphicsPipeline{{
                                  .name = "Composite Pipeline",
                                  .vertexShader = &vertex,
                                  .fragmentShader = &fragment,
                                  .inputAssemblyState = {.topology = Fwog::PrimitiveTopology::TRIANGLE_LIST},
                                }};
}```
#

this is the code for creating it

#

oh for fucks sake

golden schooner
#

😄

robust bough
#

i dont want to talk about it

#

dont copy paste code kids!

#
Fwog::Shader renderer::create_fragment_shader(const std::filesystem::path &path) {
  return Fwog::Shader(Fwog::PipelineStage::VERTEX_SHADER, read_shader_source(path));
}

Fwog::Shader renderer::create_vertex_shader(const std::filesystem::path &path) {
  return Fwog::Shader(Fwog::PipelineStage::VERTEX_SHADER, read_shader_source(path));
}

Fwog::Shader renderer::create_compute_shader(const std::filesystem::path &path) {
  return Fwog::Shader(Fwog::PipelineStage::VERTEX_SHADER, read_shader_source(path));
}```
robust bough
#

i swear i never had these errors back when I did graphics a lot more ;-;

#
"0(8) : error C5052: gl_VertexID is not accessible in this profile\n0(8) : error C5052: gl_VertexID is not accessible in this profile\n0(10) : error C5052: gl_Position is not accessible in this profile\n"```
golden schooner
#

ah you fooked glfw up

#

fwog doesnt handle context creation for you

robust bough
#
  glfwInit();

  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
  glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);

  handle = glfwCreateWindow(width, height, title.data(), nullptr, nullptr);
  glfwMakeContextCurrent(handle);

  gladLoadGL(glfwGetProcAddress);

  Fwog::Initialize({});```
#

did I?

golden schooner
#

you need core

robust bough
#

i tried core before

#
"0(8) : error C5052: gl_VertexID is not accessible in this profile\n0(8) : error C5052: gl_VertexID is not accessible in this profile\n0(10) : error C5052: gl_Position is not accessible in this profile\n"```
#

thats why im so confused ._.

golden schooner
#

add core in your vs/fs

#

ah no its tehre

#

weird

robust bough
#

(ive tried all of the permutations)

#

maybe i should jump to #opengl

golden schooner
#

can you confirm its not the fragment shader?

#

gl_Position/gl_VertexID are not allowed in fs

robust bough
#

yes

golden schooner
#
Fwog::Shader renderer::create_compute_shader(const std::filesystem::path &path) {
  return Fwog::Shader(Fwog::PipelineStage::VERTEX_SHADER, read_shader_source(path));
}
#

stage is wrong here too

robust bough
#

oh my god

#

i fixed it there, but rereading it made me realize what i did wrong

#

i quit

#

im never doing graphics again

#
Fwog::Shader renderer::create_fragment_shader(const std::filesystem::path &path) {
  return Fwog::Shader(Fwog::PipelineStage::VERTEX_SHADER, read_shader_source(path));
}

Fwog::Shader renderer::create_vertex_shader(const std::filesystem::path &path) {
  return Fwog::Shader(Fwog::PipelineStage::FRAGMENT_SHADER, read_shader_source(path));
}
golden schooner
#

😛

robust bough
#

im sorry i've failed you

golden schooner
#

no worries, happens to me too

#

but a dogjiff.gif should be in order

robust bough
#

lel yeah

#

now to see if i can get a compute shader working

#

(something tells me im about to fail horribily)

long robin
#

@heavy cipher what was the issue you had with std::source_location in msvc?

#

I was thinking about upgrading my exceptions

daring surge
#

@long robin how is this meant to be avoided monkaHmm

long robin
#

are you using my enet fork

daring surge
#

ye

long robin
#

I see

daring surge
#

tbh i didn't even remember until i went to source and saw your name lmao

long robin
#

yeah I put my name in there so I'd remember where I made changes lol

daring surge
#

i can just ifndef it but perhaps that is not "correct"

long robin
#

yeah it's kinda tricky

#

I think the most robust way would be to ifndef it in enet.h, then later undef it only if enet.h def'd it

#
#ifndef NOMINMAX
  #define NOMINMAX
  #define UNDEF_NOMINMAX
#endif

#include <Winsock.h> // or whatever windows header

#ifdef UNDEF_NOMINMAX
  #undef UNDEF_NOMINMAX
  #undef NOMINMAX
#endif
#

nice and symmetrical

daring surge
#

mmm i might just undef it when including enet

long robin
#

I can update my fork too

daring surge
#

i don't really care to not have it defined anywhere dogekek

long robin
#

if you come up with a solution, let me know

#

otherwise drop an issue in the enet fork so I don't forgor

golden schooner
#

re Fwog::Cmd::DispatchInvocations can i nitpick to distract you a little?

#

whats the difference to ::Dispatch?

heavy cipher
#

it takes number of invocations

#

if this has been inspired by vuk

#

normal dispatch takes # of workgroups

golden schooner
#

ah its an actual thing

#

DispatchInvocations sounds like DispatchIndirect

#

ah its not

dapper gorge
#

It's just sugar for glDispatchCompute((x + w - 1) / w, ...)

golden schooner
#

ye i saw the code

long robin
#

something came to me in a dream

#

I was thinking about the fact that descriptors in metal are called arguments, and I realized that we should be able to call our shaders like regular (albeit async) functions

#

so basically cuda lol

#

possibly unhinged idea: custom build step that reflects shaders and generates a header with declarations that allow you to call the shader like a function

#

if we restrict it to compute shaders, a shader like this one:

// FooShader
layout(binding = 0) buffer FooBuffer {
  float data[];
};

void main() {}

would generate the following declaration:

void FooShader(Extent3D numWorkGroups, Buffer& FooBuffer);
#

the shit part is that, since it's not single-source, definitions and struct declarations would still not be shared automagically

#

I guess if you're willing to go as far as to make a custom build step, you might as well just make a C++ dialect bleakekw

daring surge
#

this sounds like something martty would say

long robin
#

you pick things up when you live in people's walls

final cove
#

all roads lead to writing custom C++ -> shaders

hexed bay
#

https://ebitengine.org/en/documents/shader.html
Ebitengine has custom shaders written in Go-like language. It's kinda impressive

Ebitengine - A dead simple 2D game engine for Go

Ebitengine is an open source game engine for the Go programming language. Ebitengine's simple API allows you to quickly and easily develop 2D games that can be deployed across multiple platforms.

#

It's written from scratch, btw

#

(but this is a bit of a different problem, yeah :D)
But still, imagine coding shaders in C++ and calling them directly froge

golden schooner
#

cute logo

long robin
hexed bay
#

Ebitengine's dev and some guy also made it so you can call C functions in Go without cgo (which is too magical) and it's really impressive 😄

dapper gorge
hexed bay
hexed bay
#

Gonna post it here too

heavy cipher
long robin
#

Yes and they're somewhat disturbing

#

But very cool nonetheless

#

iirc there are some inherent restrictions with the method

heavy cipher
long robin
#

Like all good template metaprogramming of course

heavy cipher
#

after more than a year, my typo correction pr was merged on the refpages

oak garden
hexed bay
#

Does fwog have abstractions for array textures and cubemaps?
Want to see how this can be done froge

#

I see so many things I can’t abstract away as neatly without going full modern OpenGL froge_bleak

golden schooner
#

yes

#

you just fill in TextureCreate/TextureUpload accordingly

#

ah lol

#

i was too late

long robin
#

It's part of the texture class

golden schooner
#

weird how github never picks the default branch when copying source code links by default

long robin
#

Isn't it good, so your links don't decay when the branch is updated

golden schooner
#

fair

#

didnt see it this way, but also who would link to stale code 😄

long robin
#

It does make the links ugly though

hexed bay
#

It’s good that it does it, because without it, 99% old code links are broken, which is -retty infuriating when you read old issues

long robin
#

At least for the texture and buffer classes

#

No texture views though, which would hurt

hexed bay
#

Yeah, it’s just the binding part that requires a bit more work, since no glBindTextureUnit
But that’s pretty easy to do

long robin
#

it's just two function calls instead of one if you don't have that

hexed bay
#

I just have this "texture" class which is only abstracts "textures" (mostly diffuse) and I do array/cubemaps by hand

#

Also I don’t want to write stuff like "shader.bindCubeMap("skybox", tex, slot)" anymore

long robin
#

A thing I see in texture abstractions that mildly triggers me are constructors that take a path

golden schooner
#

no you are right

long robin
#

Even worse, the only non-move constructor taking a path

golden schooner
#

textures should be created from buffers 🙂

long robin
#

Vulkan moment

golden schooner
#

Fwulkan moment

long robin
#

I'm going to call my Vulkan library Fuk

golden schooner
#

that was my plan already xD

hexed bay
#

Well, I have
void loadFromFile(const std::filesystem::path& path);

But I think it’s better to make a free/static function which returns a texture and loads it from file

golden schooner
#

a method factory for Texture is also ok, which consumes a path

#

static Texture Texture::LoadFromFile(...)

hexed bay
#

I also recently abstracted away default FBO and made it look like a normal frame buffer… made me feel good 😂
No more "bind fbo 0" now.

golden schooner
#

we do it via BeginRenderToFramebuffer(someStruct)/EndRender

long robin
#

You're also free to add fwog as a submodule to your thingy

#

Hehe

golden schooner
#

and BeginRenderToSwapchain/EndRender, which renders to fb0

hexed bay
golden schooner
#

fair 🙂

hexed bay
#

Btw, about abstractions… what does fwog do on render passes? Does it reset all state on each pass?
E.g. clear scissor (if not specified), disable blend, disable depth testing, disable cull, etc.
That’s the thing I don’t really like about my code now - constantly have to keep in mind if the rasterizer state is correct

#

And it’s easy to remember to enable depth/blend where you need it (and I do it explicitly), but for more "rare" stuff (like scissor), I turn it on and then off

golden schooner
#

yes

#

you describe your state into the struct you pass into BeginRenderXXX

#

thats what it will be set to for the time being within BeginRender/EndRender

#

there is not really a "turn off again after it was turned on" thing

#

each pass will just set what it was set up for in said descriptor

#

and explicitly turned on/off at certain corner cases (framebuffer srgb ism for instance)

hexed bay
#

Yeah, I need to make some more explicit "render pass" descriptions and objects which control it
Because right now my code is too stateful at times
(But the main renderer is immediate, you add draw commands and lights to it on each frame, and then call "draw" - makes it so much easier to manage)

long robin
#

what I plan to implement is a generic state-tracking wrapper below fwog, then fwog will call that to set state

#

hmm I might implement it as a separate library

hexed bay
#

Yeah, I guess you can have a "global" context which keeps track of current state and changes it to a new render state if necessary

long robin
#

anyways, it will allow me to efficiently do this without having state tracking clutter the impl

void BindPipeline(Pipeline pipeline)
{
  state.glEnable(pipeline.someState1);
  state.glEnable(pipeline.someState2);
  state.glEnable(pipeline.someState3);
  state.glEnable(pipeline.someState4);
}
long robin
hexed bay
#

Btw, have you seen any engines which have similar abstractions around GL? Most games I’ve seen seemed to do a lot of stuff manually

long robin
#

I might slim things down by removing my vao and framebuffer caches too

long robin
#

and most (all?) engines that use GL I've looked at do not use it in a very good way lol

#

or let's say, "modern"

hexed bay
#

I guess I’m already far ahead if I start using fwog as an inspiration kekwfroggified

#

At least I stopped unbinding vaos/textures froge_bleak

long robin
#

you can have just one vao and set the attrib format and whatnot whenever a pipeline is bound

#

likewise, you can have just one fbo and bind render targets when a pass begins

golden schooner
#

i also believe our engines do a better job at abstracting opengl than anything else ive seen, other engines just wrap buffer/texture/shader and thats it

hexed bay
long robin
#

idk

#

driver blackbox be real

hexed bay
#

Also I have a "mesh" abstraction, which has vao+vbo/ebo for each mesh, which is also a pretty GL-beginner territory, probably

long robin
#

it's not bad for 3.3

golden schooner
#

yeah its fine

long robin
#

the only thing I'd change for moderner gl is to not put a vao in every mesh

golden schooner
#

yep

#

and put geometry together in one big buffers (vbo/ibo)

long robin
#

that's approaching brainworm territory, but yeah that's what I'd currently do

golden schooner
#

and use an indirection to handle multiple meshies

hexed bay
hexed bay
long robin
#

yeah who knows if drivers just cache each unique fbo combination or if each fbo corresponds to some low-level object in the driver

#

I doubt it's the latter

#

fwog kinda attempts to make performance more predictable by restricting the user in certain ways (you can only set state with Render and BindPipeline calls), but if you want a guarantee you would just use vulkan or d3d12

hexed bay
#

I guess you can really have only two fbos for your entire program (one for reading, one for writing) and swapping between them when needed
That’s a problem for a future bikeshedding, though 😂

long robin
#

true, I forgot about read and write fbos, but that's only needed for blitting, no?

#

you could just make two temp fbos in your blit function

hexed bay
#

Yeah. 99% of the time I only write, not read

hexed bay
#

Why even two? One would probably do, and the other one will be the "main" one

long robin
#

just to keep things shrimple I guess, but yeah that'd work

golden schooner
#

hehe

#

im a little proud of the engines

#

fwoggi and mine

hexed bay
#

I also learned about fb blitting only this week kekwfroggified

long robin
#

it's a dumb name for what is essentially a copy

#

though it behaves more like a fullscreen tri draw that samples the read framebuffer

hexed bay
#

Yeah, I only previously seen blit as a "draw to screen, swap backbuffers" thing

#

And I copied contents of FBOs via shaders froge_bleak

#

Speaking of abstractions… I see so much student code (sometimes pretty impressive stuff) with 0 abstractions, haha
"Download zip of my project" ones especially
Just raw gl calls, nothing else

long robin
#

I did one renderer with raw (modern) gl and it wasn't too horrible

golden schooner
#

same

#

a little space esque (ofc) scene, with a ring of "cubes" and some jank 6dof thing driven by physx

long robin
#

the fact that fwog lets me use local reasoning when adding a new pass is probably the biggest productivity boon

hexed bay
#

You have a shader abstraction there at least KEKW
(But I think most people at least do it to keep their sanity)

long robin
#

I also have a really bad texture abstraction in there

final cove
#

I think that's like the bare minimum you need

#

my text renderer thingy just has a Pipeline and Image, and that's about as far as I'll touch GL

hexed bay
#

I wish there were books that went beyond explaining the basics of OpenGL and teached you how to build a renderer. I guess "3D Game Engine Architecture" is pretty close, but it feels very outdated, especially how it relies on scene graphs

long robin
#

at that point you're beyond API-specific guides

golden schooner
#

das a super fresh blorg porst

#

are you ghostwriting jaker? 🙂

#

hehe

hexed bay
#

Also was wondering why I never found it before. sends this article to myself from 5 years ago

hexed bay
# long robin at that point you're beyond API-specific guides

Well, I don’t even need API specific guides anymore… the problem is that no one writes stuff like this even without being API specific. It’s all "sort your draw calls! merge geometry together!", but no one shows how to do it efficiently and not-stupidly froge_bleak

final cove
#

do people tell you to sort your draw calls in 2023

final cove
#

yep I knew you were thinking of that one

#

I have it bookmarked somewhere but I think it was irrelevant even before I started graphics stuff

hexed bay
#

Yeah, but you get my point. Deferred shading is the closest to the "structure" that was given to me, and I’m grateful that at least it helped me get on the right track

long robin
#

yeah it's kinda a too-optimized way to sort draws

#

like bro your draws can be more than 64 bits of data

#

std::sort will get you 90% of the way there

final cove
#

and really the only thing you need to sort is your alpha stuff at the end of the day, assuming you're not doing OIT

long robin
#

and it's super easy to implement

final cove
#

I'd argue other constructs should naturally cause things to be grouped

#

with pretty much everything except alpha passes you have stuff you might want to be "together" but not necessarily "in order"

hexed bay
#

Are there any good resources on batching, btw?
I get the idea, but the implementation seems really tricky

final cove
#

how hard do you wanna go with batching? like full MDI?

#

the vkguide compute culling section is probably good for that

long robin
#

there are different levels of batching

#

the easiest one is just instancing the same mesh

golden schooner
#

the 2ndiest is merging geometry

#

and using an indirectbuffer to point at the elements + gl(Multi)DrawIndirect

hexed bay
golden schooner
#

the current complexity of your game world is probably still alright for good old plain glDrawElements

final cove
#

yeah if anything that sounds more like a job for fairly naive culling

#

especially since you have a fixed camera angle right

hexed bay
#

Yeah… it’s not like I’ll be drawing huge cities any time soon 😂

golden schooner
#

but when you add shadows, you might want to have the gpu tell the gpu what to draw, so you merge all geometry, feed it to a compute shader, have the cs cull all the things, and what is not culled is written into the indirect buffer

final cove
#

you could probably just chunk your map on the CPU

#

and that would be more than good enough

hexed bay
#

Okay, I think I’ll just do render passes and stop bikeshedding for now kekwfroggified

final cove
#

or you could convert it all to meshlets and implement compute culling

#

I definitely know which one is more fun

golden schooner
#

doesnt have to be meshlets yet, as in visbuffer meshlets, but that would probably the next level

golden schooner
#

i think you can do something like that in a fragment shader as well

#

but yeah 🙂

#

gl46 my beloved

#

indirect draw is also a nono on gl33 iirc

final cove
#

yeah, your world is definitely in a very good state for simple CPU-side hints to go a long way though

golden schooner
#

ah no, its an extension in 3.1

long robin
#

I should do a multi-part writeup of ff's renderer at some point

#

in collaboration with lvstri of course

hexed bay
long robin
#

ye

hexed bay
#

Which one?

long robin
#

final fantasy: frog

#

#1128020727380054046

signal widget
#

FF:F

hexed bay
long robin
#

I had an idea while ponderin me orb

#

related to a rant I had a day or two ago

#

but wouldn't it be neat if you could invoke a pipeline with one function call, then you just provide all the bindings as literal function arguments

#

to make it more like normal programming and reduce boilerplate

hexed bay
#

Need some code examples frOK

long robin
#

uh right

#

let's do hello tringle

#

right now, hello tringle in fwog is something like

  Fwog::RenderToSwapchain({
      .name = "Render Triangle",
      .viewport = Fwog::Viewport{.drawRect{.offset = {0, 0}, .extent = {windowWidth, windowHeight}}},
      .colorLoadOp = Fwog::AttachmentLoadOp::CLEAR,
      .clearColorValue = {.2f, .0f, .2f, 1.0f},
    },
    [&]
    {
      Fwog::Cmd::BindGraphicsPipeline(pipeline);
      Fwog::Cmd::BindVertexBuffer(0, vertexPosBuffer, 0, 2 * sizeof(float));
      Fwog::Cmd::BindVertexBuffer(1, vertexColorBuffer, 0, 3 * sizeof(uint8_t));
      Fwog::Cmd::Draw(3, 1, 0, 0);
    });
#

let's also pretend that manual vertex pulling is the only thing that exists

#

so you have to provide vertices via ssbo

#

Ideally, I'd want to write something more like

sceneTexture.Clear(.2f, .0f, .2f, 1.0f);
pipeline.Draw(3, 1, 0, 0, viewport, vertexPosBuffer, vertexColorBuffer);
#

I mean the API looks kinda unhinged for draw calls, but I think for compute it would be more streamlined since the required state is much smaller

#

computePipeline.Dispatch(dispatchDims, someBuffer1, someBuffer2, someImage);

#

which is more CUDA-like

hexed bay
#

Maybe can even make this overload:

pipeline.Draw(viewport, vertexPosBuffer, vertexColorBuffer); // 1 instance, use all vertices
long robin
long robin
#

mostly because it complicates things lol

hexed bay
#

Can't you store it in buffer structs?

long robin
#

to the API it would just be an untyped buffer

#

it wouldn't know how big a vertex is or even if the buffer held vertices

hexed bay
#

Hmm, well, maybe it can be like this at least:

pipeline.Draw(3, viewport, vertexPosBuffer, vertexColorBuffer);

since there's no point of using instances everywhere and having to write "1, 0, 0" everywhere might be a bit annoying

In my game, I store number of vertices next to EBO/VBO so I don't have to manually pass the count to glDrawElements

long robin
#

fair

#

yeah in fwog I only expose the best draw calls

#

which means glDrawElementsInstancedBaseVertexBaseInstance, glMultiDrawElementsIndirect, glMultiDrawElementsIndirectCount, and the non-indexed variants

hexed bay
#

glDrawElementsInstancedBaseVertexBaseInstance what Vulkan-speak is this... kekwfroggified

long robin
#

it's vkCmdDrawIndexed

#

it lets you specify:

  • indexCount is the number of vertices to draw.
  • instanceCount is the number of instances to draw.
  • firstIndex is the base index within the index buffer.
  • vertexOffset is the value added to the vertex index before indexing into the vertex buffer.
  • firstInstance is the instance ID of the first instance to draw.
#

opengl just makes it look scary because it's opengl

hexed bay
#

Yeah, I was joking because the function name is so long, but Vulkan's is surprisingly shorter

heavy cipher
#

the difficult bit with creating a high level interface is getting it right

#

when you depart from the wrap to greenfield the decisions are not obvious:/

long robin
#

yeah the neat thing about cuda is that a kernel really is just a main function that you invoke and pass some arguments to

#

with graphics pipelines it's way more complicated

heavy cipher
#

you could do compoot first

long robin
#

I suppose I could make such an abstraction for compute pipelines as a start, but there are still some things I'd have to 'shed since it's not truly single-source

#

like deciding how function arguments are mapped to glsl resource declarations

heavy cipher
#

join me brother for my spirv template quest

#

for gl it just needs to be spirv crossed back

long robin
#

gl can eat spirv directly

#

but aren't there some fundamental limitations to the template approach or am I trippin

heavy cipher
#

can't spell fundamental limitations without fun

#

but wdym

heavy cipher
long robin
#

I mean, it's probably turing complete, so I guess what I'm asking is if it's sane to write complex shaders with it

heavy cipher
#

the key is to throw sanity in the bin at the first opportunity

#

but i'd say the tricky bit is control flow

long robin
#

yeah I have no idea how you would express that in a way that feels like normal programming to use

#

gimme uhh
branch(condition, trueExec, falseExec)

heavy cipher
#

yeah

#

select is easy

long robin
#

doesn't shady allow unstructured control flow? you could just make the programmer write it as a linear stream of instructions and have them use goto

#

shrimple solutions for clamplex problems

heavy cipher
#

uhh, can't parse that

long robin
#

yea

#

gob certainly didn't make it easy to find his thing on google

#

but iirc the IR for it has unstructured control flow

#

anyways I'm just memeing so it doesn't matter

heavy cipher
#

bueno

#

anyways, i too was meming

#

i am not sure how feasible is to do full spirv

#

the effort skyrockets

#

whereas "gpu lambdas" is reasonable

long robin
#

yeah that was basically my concern

#

I do have a few places where that would be handy, but ideally I'd like my hot new shading lang system to support everything (that I deem to be useful)

#

maybe I could cope by telling myself that I'm actually using a cool functional language when I write spirv templates

devout jolt
#

What does fwog provide?

long robin
#

in general? or with respect to the ongoing convo?

devout jolt
#

in general

#

more exact than the post description

long robin
#

gotcha

#

there are examples in the repo

gilded widget
#

GL_DONT_CARE froge_bleak

golden schooner
#

i think i like the idea of temporal coupling as a tool more

#

for something like that