#DARE (Danny's Awesome Rendering Engine)

1 messages Β· Page 6 of 1

dawn wave
#

im stupid

#

better question

#

how do we abstract semaphores in a nice way

#

such that i dont wanna die

dawn wave
#

oh fuck*

#

barriers

#

uh

#

what the fuck do i do

#

i don't have subpasses since i am dynamic rendering

dawn wave
#

you know what

#

that is tomorrow me problem

#

i'll worry about how to transition images tomorrow

#

and vulkan sychronization

dawn wave
#

how tf did i even get dynamic rendering to work last time

dawn wave
#

Throughout the devices and commands, I alone am the synchronized one

#

Stand proud, binary Semaphore, you’re strong

#

Are you visible memory because *_WRITE_BIT_KHR or are you *_WRITE_BIT_KHR because you are visible?

#

For the next 4ms and 11mbs, the acceleration structure would be built on the device

dawn wave
#

i messed up my alpha blending πŸ’€

#

but triangle now appears πŸ₯³

devout mesa
#

hey I got one too

#

mine is sRGB correct as well

dawn wave
#

lvstri really said skill issue to me in srgb

devout mesa
#

my triangle is also raytraced

dawn wave
#

i used to have one

#

then i killed it

devout mesa
dawn wave
devout mesa
#

also

#

last flex

#

it's only 300LOC

#

thanks to new Irisℒ️

dawn wave
#

that's impressive

#

KEKW mines is 500 loc even with my abstractions

dawn wave
#

@tropic vigil sorry for ponging but how do you manage the lifetimes of gpu-allocator? Wrapping in Arc doesn't reallly work since literally all allocations produced some references (???)

tropic vigil
#

hmm im not sure what u mean by that last bit

#

the allocations returned own the memory

#

buffers hold their Allocation (which is parametrized over a trait because yes)

#

when you drop the buffer you drop the allocation

#

keeping the buffer alive is your responsibility

dawn wave
#

ohh this makes sense

#

thank you

tropic vigil
#

if you want delayed deletion you need to make a deletion queue for them and push them in there

#

that stuff is mostly on the user side in phobos atm

dawn wave
#

bleakekw im not doing a deletion queue im gonna ref count it all

tropic vigil
#

because afaik theres no good generic way to do it

#

you cant just refcount

#

since you may also have references on the gpu in flight

#

while all actual references are gone

dawn wave
#

wait wdym?

tropic vigil
#

if you submit come commands that use a buffer

#

and then drop all references to that buffer

#

even if you refcount itll be deleted while its in use on the gpu

dawn wave
#

ohh

#

RefCounting + RwLock 😎

#

maximum overhead

tropic vigil
#

more like refcounting + deletion queue

#

deletion queue is stupidly simple

dawn wave
#

bleakekw
Has drop submit the commands to a deletion queue which itself is dropped when refcount is zero

tropic vigil
#

43 lines of rust

#

and you have a deletion queue

dawn wave
#

oh you use deferred

tropic vigil
#

no the deletion queue you keep around and just "advance" once every frame

#

yeah

dawn wave
#

im more used to flushing the queue

tropic vigil
#

ah

devout mesa
#

A shrimpler way is to keep track of cpu and gpu timeline

#

and only delete when the gpu timeline reached the cpu timeline

dawn wave
#

vkDeviceWaitIdle 😎 (this single menovour will take us 50 years)

devout mesa
dawn wave
#

hmhmhmh

#

so like when i drop my lifetime

I put it into a deletion queue then I wait until the gpu timeline for that resource reaches the cpu?

#

then I can destroy it?

#

isn't that expensive however? Since you need to constantly query everything in that deletion queue to see when the timelines reach

dawn wave
#

wat

devout mesa
#

you send the cpu timeline value and the object to destroy

#

every frame you get the gpu's timeline counter

#

if it is > then you can safely delete

dawn wave
#

ohh

#

i forgot timeline semaphores can have multiple listeners

#

and signalers

#

so you just have one universal timeline semaphore you just use across everything?

devout mesa
#

you can just vkGetSemaphoreCounter yknow

#

no need to signal or wait

#

the only thing that signals is the device

dawn wave
#

uhhh okay

devout mesa
#

I'll show exshrimple when I get home

dawn wave
#

okok thank you

devout mesa
#

but the easy way is what penguin did

dawn wave
#

OH i understand why penguin does it per frame since you'll know you won't have those resources in flight

#

i guess yours is similar but allows for more granular control in the frames itself...?

dawn wave
#

How tf do you integrate egui into your ash renderer

tropic vigil
#

theres an integration for ash i think

dawn wave
#

Bro i need to overhaul my entire engine bleakekw

#

vkguide2 was not built for this one

#

Do i just bite the bullet and use the imgui rs wrapper

dawn wave
#

what is the legality

#

of including vulkan in my project's name

#

πŸ€”

#

Danny's Awesome Vulkan Layer

dawn wave
#

@devout mesa can you uh explain how your lifetime management system works im so confused bleakekw

devout mesa
#
uint32 hostTimelineValue = 0;
TimelineSemaphore deviceTimelineSemaphore = {};
uint32 maxTimelineDifference = FRAMES_IN_FLIGHT;
while (window.IsOpen()) {
    hostTimelineValue = max(hostTimelineValue - maxTimelineDifference + 1, 0);
    vkQueueSubmit2(
        Signal = { deviceTimelineSemaphore, hostTimelineSemaphore };
    );
}```
#

is this clear

#

if it is then I can explain how the deletion queue works

#

if not, read how timeline semaphores work

dawn wave
#

yeah it is

devout mesa
#

ok

#
DeletionQueue::push(T object) {
    _vector.push(object, currentHostTimelineValue);
}

DeletionQueue::tick() {
    uint32 deviceCounter = deviceTimelineSemaphore.GetCounter();
    for each item in _vector {
        if (deviceCounter > item.timelineValue) {
            delete(item);
        }
    }
}```
dawn wave
#

uh

#

timelineValue? Is this assigned at the end of each FIF?

devout mesa
#

no, here _vector.push(object, currentHostTimelineValue);

dawn wave
#

OH

#

i think it makes sense

#

wait no currentHostTimelineValue? Is this assigned based off of hostTimelineValue? i.e. hostTimelineValue + maxTimelineDifference

devout mesa
#

here, have another exshrimple

#
uint32 hostTimelineValue = 0;
TimelineSemaphore deviceTimelineSemaphore = {};
uint32 maxTimelineDifference = FRAMES_IN_FLIGHT;
while (window.IsOpen()) {
    hostTimelineValue = max(hostTimelineValue - maxTimelineDifference + 1, 0);
    deletionQueue.Push(someRandomObject, hostTimelineValue);
    vkQueueSubmit2(
        Signal = { deviceTimelineSemaphore, hostTimelineSemaphore };
    );
    deletionQueue.Tick();
}```
dawn wave
#

ohh

#

it makes sense now

#

it is shrimple

#

thanks lvstri

winged raptor
#

Why do you subtract the maxTimelineDifference?

devout mesa
#

I did omit the vkWaitSemaphores

#

That's when you wait for hostTimelineValue

#

the difference is subtracted such that you wait for nothing the first N frames

winged raptor
#

Oh you have the same sema for swapchain and deletion?

devout mesa
#

ye

winged raptor
#

I see I see

dawn wave
#

wait wtf phobos has a pipelien cache

#

oh wiat i forgot phobos removes thme from the deletion queue

#

then i assume that causes it to drop then cleanup

dawn wave
#

@tropic vigil Does phobos use the deletion queue to manage its lifetimes?

tropic vigil
#

yea

dawn wave
#

oh ok now it starts to make more sense

tropic vigil
#

it pushes things to be deleted onto that queue

#

and that queue keeps them alive

dawn wave
#

how does it ensure that stuff gets destroyed in the proper order however?

tropic vigil
#

then drops them

dawn wave
#

or do you just rely on first in first out

tropic vigil
#

by storing dependent resources inside each other

#

like

dawn wave
#

dependency injection?

tropic vigil
#

if X needs Y to be destroyed first

#

store Y inside X

#

and destruction order handles the rest

dawn wave
#

wat

#

oh wait

tropic vigil
#

if X's destructor runs

#

it'll destroy Y

#

then X

dawn wave
#

oh yeah KEKW

#

okok thank you penguin

tropic vigil
#

using language constructs for this sort of stuff is usually best

#

because its mostly intuitive to someone who doesnt know about the gpu internals

dawn wave
#

still debating if i should hit my abstraction layer with strong reference counting
πŸ€”

#

waaiai im dumb how tf does it ensure stuff that is used in frames in flight doesn't get destroyed?

#

since it iterates every frame but you do FIF so some resources may still be used in the next frame in flight

tropic vigil
#

you see that max_ttl parameter

#

every resource is kept in the queue for that many frames

#

i set it to frames_in_flight + 1 or so

dawn wave
#

oh-

#

im stupid LMAOO

#

yeah that makes sense

tropic vigil
#

its pretty much just a "time until death" for the resource

dawn wave
#

in a world where a penguin gives everyone a time to death KEKW

dawn wave
#

slowly i begin cookinfg

dawn wave
#

@tropic vigil Yo is phobos bindless?

#

I forgot πŸ’€

tropic vigil
#

yes and no

dawn wave
#

going through the code base, it doesn't seem to be?

tropic vigil
#

it supports bindless just fine

#

there was some stuff in the works to make it easier but thats kind of on hold for now

dawn wave
#

huh alright im just trying to figure out how to make a good descriptor abstraction 😭

tropic vigil
#

its a bit complicated

dawn wave
#

bit

winged raptor
#

What I did (stole from daxa) when recently hacking together quick thingy for uni is just create a single descriptor set with four bindings (one for each buffers, sampled images, storage images and samplers). Then whenever user creates a resource I assign it a slot in the binding (basically a hashmap) and update the descriptor set

#

I then can use the key to the slot to index this resource on both the GPU and CPU

dawn wave
#

man im too stupid

#

πŸ’€

winged raptor
#

Do you want me to describe in more detail?

dawn wave
#

uh yeah

devout mesa
winged raptor
#

It is very shriple and works perfectly

#

Ill explain better when I'm at my PC (tag me in an hour or so if I forget πŸ˜…)

dawn wave
devout mesa
#

I'll try explaining it in more detail myself then

#

alright look at this

#

First: I create a huge descriptor pool with 4 bindings (don't mind the storage buffer one, you technically don't need it) descriptor pool

#

Then I create a descriptor layout that has one descriptor type per binding, totaling 4 bindings

#

so binding 0 is samplers, binding 1 is sampled images etc..

#

you still with me?

dawn wave
#

yeah i think so

devout mesa
#

do you understand descriptor layouts?

#

what they describe/map to in a shader

dawn wave
#

KEKW
I think they just describe metadata around the descriptors themselves, no?

devout mesa
#

no, they describe the descriptors themselves

dawn wave
devout mesa
#

if you see this shader

#
layout (set = 0, binding = 0) uniform image2D image;
void main() {}```
#

What is the descriptor layout of this shader

dawn wave
#

it has a single binding of I believe a sampled image?

devout mesa
#

storage image, but yes

dawn wave
#

at dstBinding = 0

devout mesa
#

alright, now what about this

#
layout (set = 0, binding = 0) uniform image2D[] image;
dawn wave
#

bleakekw
Uh it's the same but with a .count indicating there are more than 1 descriptors in that binding or maybe just 1

devout mesa
#

good, with an unbounded array you are telling GLSL that you don't to define any upper bound (yet, you'll define one when creating the descriptor layout using count)

#

so when I set 65536 as the count, I'm saying, "I want this binding to have 65536 MAX descriptors"

dawn wave
#

okok

devout mesa
#

now

#

here comes the interesting part

#

what happens if I do this

#
layout (set = 0, binding = 0) uniform image1D[] image1Ds;
layout (set = 0, binding = 0) uniform image2D[] image2Ds;
layout (set = 0, binding = 0) uniform image3D[] image3Ds;
...```
dawn wave
#

uh an error?

devout mesa
#

nope this is valid GLSL

#

and a core concept for implementing this thingy

#

Think about it

#

How many different descriptor types am I describing here

dawn wave
#

you have 3 of those bindings all set to binding = 0, but with different descriptor types

devout mesa
#

remember when I refer to descriptor type I strictly refer to VkDescriptorType

devout mesa
#

Give me the VkDescriptorType entry

dawn wave
#

STORAGE_IMAGE?

devout mesa
#

correct, what about the second one

dawn wave
#

STORAGE_IMAGE again

devout mesa
#

yep

#

so here's the thing

#

you can alias multiple GLSL types to the same descriptor type

#

anything that has *image* in it is a storage image, no exceptions

#

so image2DArray, image2DMSArray, etc..

#

they're all storage images

#

you got this?

#

(take your time)

dawn wave
#

hmm ok

devout mesa
#

if you don't fully get this, we can't proceed, re-read everything again, ask me questions and then we can continue

dawn wave
#

so in other words i can alias multiple types to a binding?

devout mesa
#

This really is a core concept, the aliasing of GLSL types

#

yes

dawn wave
#

ohh ok

#

yeah i get it

devout mesa
#

alright, now

#

I only make one descriptor set

#

from now on, let's erase the name "descriptor set" which means nothing

#

and let's replace that with "table of descriptors"

#

because that's what we're gonna be treating this as

dawn wave
#

wait why is descriptor set meainginless?

devout mesa
#

a big ass array of descriptors

dawn wave
#

oh you're gonna treat it as a table

#

oh ok KEKW

devout mesa
dawn wave
#

okok

devout mesa
#

so

#

do you know how a free list allocator works

#

a simple one

#

not one with offsets and shit

#

just one with IDs

#

the simplest of them all

dawn wave
#

what KEKW

devout mesa
#

alright

#

let's focus on the storage image descriptor table

#

we have an big ass array of storage image descriptors

#

but it's empty now

#

we want to put stuff in the array in a way that is simple and works for us

#

that's our goal

#

now we're gonna use two vectors to achieve this goal

#
std::vector<Resource> resources;
std::vector<uint64> freeIds;```
#

the first vector is a descriptor table, but a concrete one, we store our storage images in there

#

it will map directly to the array in our shader

devout mesa
#

do you understand that resources is the C++ version of uniform *image*[] images;

dawn wave
#

yes

devout mesa
#

good

#

now what happens when we allocate a resource

#

we want to get back a unique identifier to locate said resource in the shader

#

which better unique identifier than the index of the resource within the array

#

so our allocation function is literally just this

uint64 allocate(...) {
    const auto id = resources.size();
    resources.emplace_back(...);
    return id;
}```
#

since we know resources maps directly to the image table in the shader, we can just pass this ID as a push constant to access our resource in the shader

#

you got this?

dawn wave
#

yeah

#

makes sense

devout mesa
#

good

#

This has a problem though

#

what happens when we want to destroy a resource

#

we would do this right?

void deallocate(uint64 id) {
    resources[id] = {}; 
}```
dawn wave
#

yeah

#

but wouldn't leave a gap

devout mesa
#

yes

#

can you think of a way to change allocate and deallocate to fix this issue using the second vector we declared before?

#

std::vector<uint64> freeIds; this one

dawn wave
#

uhhhhh

#

hold up

devout mesa
#

take your time

#

it's fine if you don't get it right, I've done this a million times and I still had a bug regarding my free list when did this

dawn wave
#

i would've make a stack where i push free_ids into it then pop ids as they're used

#
uint64 allocate(...) {
    const auto id = freeIds.pop();
    resources.emplace_back(...);
    return id;
}
devout mesa
#

right

dawn wave
#
void deallocate(uint64 id) {
    resources[id] = {}; 
    freeIds.push(id);
}
devout mesa
#

yeah, the idea is exactly it, but it's not quite there yet

#

(also a stack and a vector are functionally equivalent in C++ KEKW)

dawn wave
devout mesa
#

So, here's allocate

#
uint64 allocate(...) {
  if (freeIds.empty()) {
    const auto id = resources.size();
    resources.emplace_back(...);
    return id;
  }
  const auto id = freeIds.back();
  freeIds.pop_back();
  resources[id] = ...;
  return id;
}```
devout mesa
#

alright now we got Ids and a resource array

#

what's missing?

dawn wave
devout mesa
#

why would we

#

if the free list is empty then no IDs before the current one are empty

dawn wave
#

like why not an error instead since no ids are avaliable?

devout mesa
#

why though

#

why throw away this perfectly reasonable assumption

#

"if free list is empty then we can allocate with no worries of leaving gaps"

dawn wave
#

OHH

#

freeList holds any "gaps"

devout mesa
#

yes

dawn wave
#

LMAOO alright this makes sense now

devout mesa
#

alright so

#

what are we missing

#

my CDescriptorTable<D>::AllocateResource has one more line in it

dawn wave
#

uhh allocating the resources themselves i..e updating the descriptor set?

devout mesa
#

yes

#

so we need a third vector

#

std::vector<Descriptor> writes;

#

where do we use this vector? in allocate?

dawn wave
#

wdym allocate?

devout mesa
#

add the missing line

dawn wave
#

oh kekw

#
uint64 allocate(...) {
  if (freeIds.empty()) {
    const auto id = resources.size();
    resources.emplace_back(...);
    return id;
  }
  const auto id = freeIds.back();
  freeIds.pop_back();
  resources[id] = ...;
  writes[id] = ...->Descriptors;
  return id;
}
#

?

devout mesa
#

nope, we don't want to traverse the whole writes array to get to a good descriptor

#

we shrimply emplace every time we allocate

#

and clear vector once we have confirmed the updates using vkUpdateDescriptorSets

#

so, here's the final impl

dawn wave
#

hmhmhm

#

okok

devout mesa
#

that's it

#

shrimple enough?

dawn wave
#

uh
Wait how would you enforce the ordering of resources in
vkUpdateDescriptorSets?

#

I'm just uh lost how writes ensures that order?

devout mesa
#

look under dstBinding

dawn wave
#

yeah

devout mesa
#

what would you set dstArrayElement to?

dawn wave
#

set the starting element to start writing descriptors to

devout mesa
#

they're not gonna be necessarily in sequence though

#

now, I merge writes into one big write where possible, but it's not necessary

#

you can shrimply have one write per Allocate call you do

#

since you're gonna do that once and that's it

dawn wave
#

bleakekw
I think i get it

devout mesa
#

Here's where I do the writing

#

@dawn wave do you know where index comes from?

dawn wave
#

the index of the resource in resources?

dawn wave
#

wtf is ->GetDescriptor btw?

#

oh it returns a descriptor binding

devout mesa
#

it returns my version of VkDescriptorBufferInfo/VkDescriptorImageInfo/...

dawn wave
#

aghh

#

so you make 3 descriptor sets?

#

which are effectively just arrays

devout mesa
#

no

#

one, single, lonely set

winged raptor
#

One set and multiple "array" bindings

devout mesa
#

saky you can take over btw

#

the fbx export is done cooking

#

hehe

dawn wave
#

hmhmh okay

#

p_immutable_samplers literally exists if you want to initalize samplers?

#

KEKW i got stuck on this so long

winged raptor
#

Uh oh I want really keeping up

#

Where have you gotten?

#

Danny what do you understand?

dawn wave
#

i tihnk most of it

#

i just need to implement it now

winged raptor
#

Prof LVSTRI did a good job?

dawn wave
#

yes someone give him model-view-projection

winged raptor
#

Very good very good

dawn wave
#

wait so uh

#

do you just keep a reference towards each resource?

winged raptor
#

What do you mean?

#

On the CPU?

dawn wave
#

lvstri uses a resource vector

#

yes

winged raptor
#

Well the resource is stored in the vector and I use an Id to refer to it

#

So when you create an image you get an id back (which is essential just an index to the resource vector)

dawn wave
#

yeah i get that im talking more to

#

nah wait nvm

#

ill just accept my bindless descriptor

#

will have ownership of my resources

devout mesa
#

what if

#
auto GetResource(uint64 id) -> Resource& {
    return resources[id];
}```
winged raptor
#

I do that for some fields, so for example to extract the create info of any resource

#

But yeah the resources are owned by the resource table (it's really just the info, the vkhandle and VMA allocation)

dawn wave
#

yo uh

#

for writes im a bit lost

#

when iterating through it, right?

#

im just kinda lost how tf

#

wait nvm

#

no i need help

#

if writes contains Descriptor...Info about what is going to be written

#

how would we know the indices that would need to be written?

#

do we keep an IndiceUpdate<u32> vector or smth?

devout mesa
#

when you allocate

#

you know you gotta write

#

that's it

dawn wave
#

oh wait

#

does your write struct like contain info about the id?

winged raptor
#

it's literally this for me

dawn wave
#

no alr i get it

#

im just being stupid

dawn wave
#

it doesn't work

#

rust -> memory access error

#

how

devout mesa
#

C++ moment

dawn wave
#

New plan, gang

#

We’ll store each resource in it;s own dedicated vector

devout mesa
#

wtf

winged raptor
#

Do you mean resource type?

dawn wave
#

Yeah each resource type

dawn wave
#

uh

#

i might have a dropping error?

#

is it normal for image view to be negative...?

#

bleakekw u64

devout mesa
#

either your debugger is smoking crack or you did something very very bad

dawn wave
#

im smoking crack

devout mesa
#

yes there's that possibility too kekwfroggified

dawn wave
#

nah my debugger is smoking crack this time

#

no iam

#

@tropic vigil sorry for ponging, but is it normal for ash to return negative pointers...?

tropic vigil
#

uhh

dawn wave
tropic vigil
#

sounds odd

#

lol

devout mesa
#

(no)

dawn wave
tropic vigil
#

could just be the debugger on crack though

#

because u64 cant be negative

dawn wave
#

could be

#

but like it's impossible to determine if i have null pointer or not now

dawn wave
#

how would you free a resource again?

#

like unbind it in the update function

devout mesa
#

why unbind

dawn wave
#

what if i need to remove/delete resources

devout mesa
#

why unbind

winged raptor
#

You can bind the slot with some default resource to easier spot mistakes

#

Or just leave as is

dawn wave
#

uh i would assume i don't want a descriptor to be binded to a destroyed resource?

devout mesa
#

why not

#

what's the harm

winged raptor
#

Well if you never access it it's okay

dawn wave
#

eh i guess so worse case i get some weird visual error

devout mesa
#

just drop all references to the id you want to destroy

#

should be easy enough

winged raptor
#

So you might not crash if you access dead descriptor

dawn wave
#

i rewritten it

#

and it still crashes with a forbidden access error

#

also what are sane defaults for a sampler

dawn wave
#

no wait

#
[Debug][Error][Validation] "Validation Error: [ VUID-VkWriteDescriptorSet-descriptorType-02996 ] Object 0: handle = 0x26759546a90, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0x1cc3d039 | vkUpdateDescriptorSets():  Invalid VkImageView Object 0xb9181f0000000029. The Vulkan spec states: If descriptorType i
s VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, or VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, the imageView member of each element of pImageInfo must be either a valid VkImageView handle or VK_NULL_HANDLE (https://vulkan.lunarg.com/doc/view/1.3.268.0/windows/1.3-extensions/vkspec.html#VUID-VkWriteDescriptorSet-descriptorType-02996)"
#

NO SHOT

#

im gonna kms

#

this would break it

DescriptorInfo::Image(vk::DescriptorImageInfo {
                image_view: self.get_view(),
                image_layout: vk::ImageLayout::GENERAL,
                ..Default::default()
            })
#

but this would'nt

DescriptorInfo::Image(vk::DescriptorImageInfo {
                image_view: self.get_view(),
                image_layout: vk::ImageLayout::GENERAL,
                sampler: vk::Sampler::null()
            })
#

KEKW it was trying to access a non-existent sampler and i never indicated that the sampler is null

dawn wave
#

uhhh

#

who wants to help me name

#

My vulkan thingy is split into two parts rn:
The abstraction layer which literally only abstracts and does nothing else
And the "Utility" layer i.e. lifetime management + gpu resource table + rendergraph + ...

There has to be a better name of utility layer πŸ’€

winged raptor
#

a_layer_of_utility

#

layer_providing_utilization

dawn wave
#

Danny's Awesome Graphics Framework

#

DAGF

#

Danny's Graphics Ameture FramewoorK
(DGAF) KEKW

winged raptor
#

Danny's Owsm Graphics Set-up

#

DOGS

dawn wave
#

[Debug][Error][Validation] "Validation Error: [ VUID-vkCmdDispatch-None-08114 ] Object 0: handle = 0x2e2941000000001f, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; | MessageID = 0x30b6e267 | vkQueueSubmit(): pSubmits[0].pCommandBuffers[0] the descriptor (VkDescriptorSet 0x2e2941000000001f[], binding 0, index

  1. is being used in draw but has never been updated via vkUpdateDescriptorSets() or a similar call. The Vulkan spec states: Descriptors in each bound descriptor set, specified via vkCmdBindDescriptorSets, must be valid if they are statically used by the VkPipeline bound to the pipeline bind point used by this command and the bound VkPipeline was not created with VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT (https://vulkan.lunarg.com/doc/view/1.3.268.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdDispatch-None-08114)"
#

huh

#

😭 I thought I enabled partial bounding

winged raptor
#

It complains that you never wrote it no?

#

And tried to use it

dawn wave
#

huh

#
//descriptor bindings for the pipeline
layout(rgba16f,set = 0, binding = 0) uniform image2D image;
#

unsolved mysteries

#

AHHH

#

WAIT

#

I NEED TO TURN THIS INTO AN ARRAY

#

LMAO

winged raptor
#

Ah right

dawn wave
#

no that didn't fix it

winged raptor
#

Did you create all of them with partially bound?

#

You need to gib array to the pnext when creating them iirc

dawn wave
#
let descriptor_flags = [
            vk::DescriptorBindingFlags::UPDATE_AFTER_BIND,
            vk::DescriptorBindingFlags::PARTIALLY_BOUND,
            vk::DescriptorBindingFlags::UPDATE_UNUSED_WHILE_PENDING,
        ];
#
let binding_flags = vk::DescriptorSetLayoutBindingFlagsCreateInfo {
            s_type: vk::DescriptorSetLayoutBindingFlagsCreateInfo::STRUCTURE_TYPE,
            p_next: ptr::null(),
            binding_count: types.len() as u32,
            p_binding_flags: descriptor_flags.as_ptr(),
        };
#
let layout_ci = vk::DescriptorSetLayoutCreateInfo {
            s_type: vk::DescriptorSetLayoutCreateInfo::STRUCTURE_TYPE,
            p_next: &binding_flags as *const _ as *const c_void,
            binding_count: descriptor_bindings.len() as u32,
            p_bindings: descriptor_bindings.as_ptr(),
            ..Default::default()
        };
winged raptor
#

Uh oh Rust πŸ‘½

dawn wave
#

KEKW maybe i ask penguin

winged raptor
#

I'm a cpp boi

#

Yeah, sorry πŸ˜…

dawn wave
#

but DescriptorSetLayoutBindingFlagsCreateInfo go into the pnext of DescriptorSetLayoutCreateInfo yeah?

winged raptor
#

yeah

#
std::array<VkDescriptorBindingFlags, 4> const descriptor_binding_flags = {
            VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
            VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
            VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
            VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
        };

        VkDescriptorSetLayoutBindingFlagsCreateInfo descriptor_set_layout_binding_flags_create_info{
            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
            .pNext = nullptr,
            .bindingCount = static_cast<u32>(descriptor_binding_flags.size()),
            .pBindingFlags = descriptor_binding_flags.data(),
        };

        VkDescriptorSetLayoutCreateInfo const descriptor_set_layout_create_info{
            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
            .pNext = &descriptor_set_layout_binding_flags_create_info,
            .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
            .bindingCount = static_cast<u32>(descriptor_set_layout_bindings.size()),
            .pBindings = descriptor_set_layout_bindings.data(),
        };
        CHECK_VK_RESULT(vkCreateDescriptorSetLayout(vulkan_device, &descriptor_set_layout_create_info, nullptr, &descriptor_set_layout));
winged raptor
dawn wave
#

o-

#

i need 4?

#

HUH

winged raptor
#

Yeah one for each descriptor

dawn wave
#

waiaia i need to pnext chain them?

#

like chain 4 of them

#

rn im just testing with just 1 descriptor binding

winged raptor
#

But if you are only testing with one it should be fine

dawn wave
#

hmhmhm

#

yeah no fucking clue

#

@tropic vigil could you uh help me debug this please

tropic vigil
#

whats going on

dawn wave
#

bindless indexing is not recognizing that i had set the layout of my descriptors to be partially bounded

tropic vigil
#

pretty sure you need to provide an array of flags

#

like

dawn wave
#

array of flags?

tropic vigil
#

each descriptor needs its own set of flags

dawn wave
#

[flag, flag, flag].as_ptr?

tropic vigil
#

more like uh

#

| the flags together

#

i think

#

basically the flags apply to individual descriptors in the set

#

or something

#

uhhh

#

its been a while

#

you should check out my code for it lol

dawn wave
#

lmao okok

tropic vigil
#

sorry i forgot so much stuff πŸ’€

dawn wave
#

nah it's good you're doing post grad stuff

#

oh ok i solved it

#

nvm

#

thanks penguin

dawn wave
#

you know

#

dumb question

#

but what the fuck is "reflection"? I hear it like shader reflection or like code reflection

tropic vigil
#

Inspecting source code to get information from it at runtime

#

Shader reflection usually involves reading the shader code to generate pipeline layouts from it

dawn wave
#

huh alright

#

time to make cursed code reflection
.rs

#[align(glsl)]
struct Ray {
  hit: glm::Vec3,
  direction: glm::Vec3
}

.glsl

struct Ray {
  vec3 hit,
  vec3 direction
}
#

can't be that bad

devout mesa
#

with the trusty GRTℒ️ (patent pending) you won't need reflection ever

#

except for push constants maybe

dawn wave
#

GRT? watbulb

devout mesa
#

gpu resource table

#

the thing that gives you ez mode descriptors

dawn wave
#

oh KEKW

devout mesa
#

that's what we call it

dawn wave
#

i got the gpu resource table working btw

devout mesa
#

though I like to call it SRT

#

Or ShaRT

dawn wave
devout mesa
#

it has higher meme value

dawn wave
#

ShaRT is better

#

renaming my structs as we speak

devout mesa
#

course it is

dawn wave
#

peak

#

i should probably finish vkguide

#

but im gonna procastinate

dawn wave
#

geh

#

i don't like using deferred deletion to manage my lifetimes :(

#

i can't do dependency injection

#

or else i risk the chance of dropping my object πŸ’€

#

I could in theory wrap it in Arc but that ruins the point

#

you know

#

how does daxa do it

#

maybe i can copy their system

#

oh

#

it's the same

#

you know

#

what if i combined and uses ref counting for some stuff and non-refcounting

devout mesa
#

all vulkan enjoyers use deletion queues

#

daxa does too

#

(not for resource handles though)

dawn wave
#

okok deletion queue

#

well deferred deletion queue

#

wait no that doesn't solve my problem

#

how do i know when to put it in the deletion queue

#

do i just ref count it πŸ’€

#

I mean i could put all my dependents in my dependencies, but dependency injection becomes impossible πŸ’€

devout mesa
dawn wave
#

yeah but what if i have other objects dependent on it

#

you know i am overthinking

devout mesa
#

when you put something in the deletion queue you say "imma not need this anymore"

#

if you do need it though, you have lied

dawn wave
#

yeah but there are many ways to check if you lied or not

#

like reference counting

devout mesa
#

I chose the best one

#

invoke UB if I lie

dawn wave
#

undefined behavior

dawn wave
#

New idea babe for bikeshedding my lifetime mansger

#

No more queues, just ref counting any any resources bounded at command submission is automatically refcounted up then dropped upon the submission fence ending

#

Domain Expansion: 25% overhead

dawn wave
#

No that is swuare one afain

#

FUCK IT ARC + DEFERRED DELETION USING TIMELINE SEMAPHORE
200% OVERHEAD

dawn wave
#

egui integration wtf

#

i basically need to rewrite my entire thing

#

nah im not doing this 😭 What the hell I literally just destroy half of my work since the egui-vulkan integration just simplifies the rest

#

nah im sorry penguin im gonna do imgui-rs
(nvm i realized it doesn't even support vulkan bleakekw )

dawn wave
#

@tropic vigil Uh question, I can't find your code for egui-winit-phobos? I need some example code to reference while trying to figure how tf to implement egui

#

Could you link it please?

tropic vigil
dawn wave
#

thanks penguin

tropic vigil
#

np

dawn wave
#

oh ffs

#

500 lines to integrate this

tropic vigil
#

i think the original is even longer

dawn wave
#

you know

#

bleakekw my only issue is im relying so much on this crate

dawn wave
#

AHHHHH

#

okay im gonna skip imgui section of vkguide

dawn wave
#

huh

#

so my push constants are just entirely wrong?

#
#[repr(C)]
struct ComputePushConstants {
    data1: [f32; 4],
    data2: [f32; 4],
    data3: [f32; 4],
    data4: [f32; 4],
}
let pc = ComputePushConstants {
                data1: glam::Vec4::new(1.0, 0.0, 0.0, 1.0).to_array(),
                data2: glam::Vec4::new(0.0, 0.0, 1.0, 1.0).to_array(),
                data3: glam::Vec4::ZERO.to_array(),
                data4: glam::Vec4::ZERO.to_array(),
            };
            self.logical_device.handle.cmd_push_constants(
                command_buffer,
                self.gradient_pipeline.get_layout(),
                vk::ShaderStageFlags::COMPUTE,
                0,
                std::slice::from_raw_parts(
                    &pc as *const _ as *const u8,
                    std::mem::size_of::<PushConstantRange>(),
                ),
            );
#

repr(C) should make it compatiable, no?

#

is it normal for the range to be zero...?

devout mesa
#

no

#

when are you coming back to C++

dawn wave
#

why should i KEKW

#

actually my experience with imgui and egui might make me also rust has barely any gp support beyond the initial bindings of ash bleakekw

devout mesa
#

right so when are you coming back

dawn wave
#

im too deep into rust bleakekw

#

but also iam way too borrow checker'd at this point

dawn wave
#

man i looked at c++ again

#

it's scary

#

so many things

dawn wave
#

it seems to randomly only decide to render 1 or 2 color channels

#

wtfff

#

okay now my traignel no longer appears

dawn wave
#

we're so fucking back

#

yippee

dawn wave
#

I should do a very simple n-body simulator :)
I think that would allow me to apply my knowledge beyond abstraction hell

dawn wave
#

wait im stupid

#

LMAOOO

dawn wave
#

sorry :(

#

i asked a question and realized i was being dumb

tropic vigil
#

thats fine lol but you dont have to delete it

dawn wave
#

HUSTON

#

WE HAVE A PROBLEM

#

AHHHHHHHHH

#

HOW DID I MAKE 32765 QUEUES

#

@tropic vigil sorry for ponging but does ash-rs working in crago tests?

dawn wave
#

it does

#

i somehow got dangling pointers in rust

#

professional rust programmer fr

tropic vigil
#

try cargo test --tests

#

maybe doctest is failing

dawn wave
#

I fixed it

#

Tears in my eyes

#

But also why tf does amd’s integrated gpus not support vk 1.3

dawn wave
#

Lvstri is right, sleep is for the weak

tropic vigil
#

real

dawn wave
#

@tropic vigil Yo uh penguin i notice in phobos you just different logging crates, wtf do they all do?

#

i realized it's gonna be insanely useful to log when all objects are made/destroyed

tropic vigil
#

it’s called log

#

it doesn’t do any logging

#

Emm

#

Well

#

It doesn’t print logs

#

Just forwards them to a log handler that can be set by the user of the library

dawn wave
#

Maybe i just bite the bullet and use cpp. Windowing + gui in rust is miserable if you aren’t using wgpu or smth
Cuz like why tf is imgui implementation on cpp is so much easier than rust. Rust you need to destroy your entire render loop and refactor it for egui to even work

dawn wave
#

Nah quitting is for losers

dawn wave
#

Nah fuck it is might just return to the standard since cpp is suoported way more and egui ash integration is horrendous

feral trellis
dawn wave
#

Problem is I have a ray tracing pipeline…

#

Not a rasterization…

#

Do I just first render to the image using rt

#

Then render over that with egui + rasterization?

feral trellis
feral trellis
#

Unless you want to pain yourself trying to implement UI with raytracing which would most probably be wasteful and worse for performance anyways

#

Pretty sure it's not even possible to even begin with lol

dawn wave
#

I mean you could…

#

At the end of the day they just give you triangles + a texture

#

More ui => more performance since rt will not ray tracing through the ui

feral trellis
#

True but UI layered rasterization is relatively fast

#

Idk I haven't touched rt pipelines at all so I don't even know how they would work, but in a normal case I'd implement UI rendering using rasterization that's for sure

dawn wave
#

dawg

#

how tf do i make a deletion queue in rust πŸ’€

#

i mean it's not hard literally a stack

#

my only issue is that i cannot pass by references into my deletion functions i push onto the stack

#

since borrow checkers get angry. i mean i could in theory just duplicate every fucking vulkan object since they're at the end of the day pointers

#

but that seems like a bad idea

#

@feral trellis asking for help here nodle men

feral trellis
#

Uhhh my naive approach would be to do some sort of IDing system

#

Idk how well that would work or if there any major pitfalls with that

#

Just a really simple unique id for each resource that you can use to delete them afterwards

#

Could simply be an Arc reference

dawn wave
#

arc for gc

#

it's probably fine for commonly used stuff but like having to deal with that overhead over and over seems kinda painful

feral trellis
#

Yea fair

#

I mean tbf wgpu uses it and so does phobos internally

dawn wave
#

phobos uses arc mainly for very commonly used stuff like device

#

but iirc it's raii from there

feral trellis
#

Ahh fair fair

dawn wave
#

still doesn't deal with gc'ing it though maybe i just do dependency injection over and over but that makes a lot of "coupling"?? like i would have to add too many abstractions then since like:

Device {
pools: {...}
asdas: { { surface: { .... } } }
}

#

so like change seems to be annoying

feral trellis
#

Hmm right

dawn wave
#

holy fuck

#
struct Buffer {
 asd asdadasdfsadfsadf
}

impl Buffer {
  fn new() -> Weak<Self> {
    
  }
}
#

like hear me out

#

i have an arc pointer but it realistically is only used once

#

that is it's only rc'd once for the deletion queue

#

but everything else interacts with the actual struct as a weak pointer

#

no reference counting overhead

#

i think

feral trellis
#

Or you can make it so whenever the value gets dropped it adds it to the deletion queue automatically

#

So there'd be no need for an arc to even begin with

#

Unless I'm misunderstanding what a deletion queue is

dawn wave
#

well you wanna use a deletion queue

#

to ensure you delete your objects in order

#

having it push on drop means that you just moved the problem down the road to you

#

like:

let mut deletion_stack = DeletionStack::new();
        deletion_stack.push({
            let surface_extension = surface_extension.clone();
            move || unsafe {
                surface_extension.destroy_surface(surface, None);
            }
        });
        deletion_stack.push({
            let logical_device = logical_device.clone();
            move || unsafe {
                logical_device.destroy_device(None);
            }
        });
#

bottom 2 blocks ig

#

ut ensures the surface is destroyed before the loigcal device

feral trellis
#

Ohh icic

#

I mean if it's nothing dynamic then I'd just call them directly without a stack but I assume that's not the case lol

dawn wave
#

no i just want to be able to fire and forget by cleanup KEKW

#

im gonna bench mark

feral trellis
#

Hmmmmm

dawn wave
#
Weak Pointer Dereference
                        time:   [3.1106 ns 3.1220 ns 3.1327 ns]

Arc Pointer Dereference time:   [187.87 ps 188.68 ps 189.56 ps]
Found 8 outliers among 100 measurements (8.00%)
  2 (2.00%) high mild
  6 (6.00%) high severe

Direct Reference        time:   [186.97 ps 187.63 ps 188.35 ps]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high severe
#

it so joever

#

maybe i need to start c++ maxxing

dawn wave
tropic vigil
#

Let me see

#

That’s not cloning

#

It swaps the new one with the old one

#

Then pushes the old one to the deletion queue

dawn wave
#

ohh

tropic vigil
#

swap is really useful for things like this

dawn wave
#

aghhh i just want a deletion queue without having to literally clone everything froge_sad

#

interior mutability is kinda being doodoo rn since it doesn't ensure lifetimes

dawn wave
#

@tropic vigil sorry for pinging, but how does phobos ensure it deletes each allocation? A bit lost how the image.rs resource is managing to free all allocations

tropic vigil
#

good evening

#

Well when the struct is dropped its contents are dropped

#

memory is an Allocation

dawn wave
#

So when Allocation is dropped, gpu_alloactor frees it implicitly?

tropic vigil
#
impl traits::Allocation for Allocation {
    unsafe fn memory(&self) -> DeviceMemory {
        self.allocation.as_ref().unwrap().memory()
    }

    fn offset(&self) -> DeviceSize {
        self.allocation.as_ref().unwrap().offset()
    }

    fn mapped_ptr(&self) -> Option<NonNull<c_void>> {
        self.allocation.as_ref().unwrap().mapped_ptr()
    }
}

impl Drop for Allocation {
    fn drop(&mut self) {
        let mut allocator = self.allocator.clone().unwrap();
        allocator.free_impl(self).unwrap();
    }
}

I made it do that

#

I wrap around the gpu_allocator allocation

dawn wave
#

ah

#

That makes sense now

tropic vigil
#
impl DefaultAllocator {
    fn free_impl(&mut self, allocation: &mut <Self as Allocator>::Allocation) -> Result<()> {
        let mut alloc = self.alloc.lock().map_err(|_| Error::PoisonError)?;
        match allocation.allocation.take() {
            None => {}
            Some(allocation) => {
                alloc.free(allocation)?;
            }
        }
        Ok(())
    }
}
#

But Allocation as a trait has docs specifycing that Drop must be implemented properly

dawn wave
#

Okok thank you

dawn wave
#

Roses are red, violets are violent, how the fuck do i task graph

tropic vigil
#

Task graphs are quite an undertaking

dawn wave
#

maybe i just live with manually syncing it all until i figure out async rust

dawn wave
#

where tf does phobos actually implement the validation layer

#

like the function that is ran

#

found it

dawn wave
#

@tropic vigil sorry to ping again but uh could you give me advice on this strategy for command buffers?

/// A command buffer which is actively recording commands
struct CommandBufferRecording {
  ...
}

/// A command buffer which has been ended.
/// 
/// No guarantees if the inactive command buffer has been properly
/// reset.
struct CommandBufferInactive {
  ...
}
#
impl CommandBufferRecording {
  pub fn end_recording(self) -> CommandBufferInactive;
}

impl CommandBufferInactive {
  pub fn start_recording(self) -> CommandBufferRecording
  pub fn reset(&self);
}
tropic vigil
#

I do something like that yeah

#

But end gives a Finished command buffer that has to be submitted

tropic vigil
#
struct CommandBuffer {
  
}

impl CommandBuffer {
  fn submit(queue: &Queue) -> Result<()> {}
}

trait CmdBuffer {
  fn finish() -> CommandBuffer;
}

Something like this

dawn wave
#

Ooh alright

#

Thank you

dawn wave
#

I give up on RAII. It scares me

#

Deletion stack 🫑

#

LVSTRI was right

#

I can clone my resources and not have to worry about cleaning them up since it’s already on the stack. Now I just need to figure out synchronization which doesn’t require me to bring a fucking task graph

dawn wave
#

Should combine memory allocation implicitly? Like
Image::new_allocate(device, image_data_to_be_uploaded)
or do

let image = Image::new();

let buffer = Buffer::new().upload(yapyapyap);

image.bind_buffer(buffer);
tropic vigil
#

Have both

#
let image = Image::new_uninitialized(...); // Empty image

let image = Image::new_with_data(..., buffer, context); // fill it

@dawn wave

dawn wave
#

ahhh alright

dawn wave
#

AHHH how do i enable extensions again

dawn wave
#
let handle = Self::new_empty(device.clone(), image_ci)?;
        let allocation = allocator.allocate(name, &unsafe {
            device.get_handle().get_image_memory_requirements(handle.handle)
        }, memory_type)?;
        unsafe {
            device.get_handle().bind_image_memory(handle.handle.clone(), allocation.memory(), allocation.offset())?
        }
        Ok(handle)
#

I geniunely have no clue how to nicely implement an allocator trait

#

since vk-mem-rs uses using allocator functions depending on what you're allocating

#

while gpu-allocator hasn't updating to ash 0.30.0

#

no way this is right since im getitng offset errors that the memory occupied isn't aligned to 65536

tropic vigil
#

I don't think an allocator trait should be too complicated

dawn wave
#

It wasn't and most of my allocator was copied from your stuff KEKW

#

But it seems like vk-mem-rs needed some extra work to ensure the offsets are padded to alignment

#

But thank you penguin once again

#

i did not mean to click

tropic vigil
dawn wave
#

Yeah that worked

dawn wave
#
[VALIDATION]: VUID-vkDestroyDevice-device-05137 (1215490720): Validation Error: [ VUID-vkDestroyDevice-device-05137 ] Object 0: handle = 0x980f360000000011, type = VK_OBJECT_TYPE_DEVICE_MEMORY; | MessageID = 0x4872eaa0 | vkCreateDevice():  OBJ ERROR : For VkDevice 0x1817b053160[], VkDeviceMemory 0x980f360000000011[] has not been destroyed. The Vulkan spec states: All child objects created on device must have been destroyed prior to destroying device (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-vkDestroyDevice-device-05137)
stack backtrace:
Destroying memory allocation 0x980f360000000011

bleakekw

#

I-

#

how?

dawn wave
#

okay now im convinced vk-mem-rs is broken

tropic vigil
dawn wave
#

yeah for whatever reason freeing the memory does not actually free it KEKW

tropic vigil
#

yeah the allocator lib might want to reuse the memory block

#

That makes sense

dawn wave
#

yeah but no clue how to then tell it "bro please no one wants to use this memory like dead ass destroy it frfrfr"

tropic vigil
#

It'll do that when it feels like it, do you really need it destroyed?

#

You can just free it through the lib and forget about it

dawn wave
#

AH.

#

I probably should drop the allocator before my device KEKW

tropic vigil
#

Probably

dawn wave
#

LMAOO

#

THAT FIXED IT

#

πŸ’€

#

im such an idiot

#

thank you penguin once again

tropic vigil
dawn wave
#

This seems like a viable synchronization method

#

I really don't wanna make a render graph πŸ’€

#

Track global sync state and instead of issuing errors, I just issue out barriers

dawn wave
#

AHHHH

#

descriptor bindless

#

how do i uh

#

do that free slot allocator

#

lvstri if you can hear me please save me

#

on another note

#

plus resizing

#

istg there is probably some really nice abstraction using slices or borrowing from rust and images and subresources

dawn wave
#

hmmm

#

how to do pipelines

eager chasm
#

just fill out the create structs

#

and picture renderdoc in front of view

#

when you are on the pipeline view

dawn wave
#

oh ok

dawn wave
#

huh

#

phobos handles resources by caching them all

dawn wave
#

@tropic vigil Sorry for pinigng so late, but do you know if you can just wrap glam structs with repr(C) and it will automatically convert them?

#

it's for shaders

dawn wave
#

you know maybe bevy-rs is the way

#

i don't have to think about architecture or event systems

#

NAHH

tropic vigil
#

repr(C) has a few rules

#

make sure to check the docs

dawn wave
#

what the fuck

#

why does validation vulkan crash in nsight

#

but perfectly outside of it

#

what the fuck nvidia

dawn wave
#

why the fuck does ash

#

never provide good defaults πŸ’€

#

is it that much effort to set the default s_type and p_next

dawn wave
#

wait phobos uses a cache hashmap because it needs to be able to refer to resources via name

#

AHHH

tropic vigil
dawn wave
#

@tropic vigil Uh sorry for pinging, but do you know where/if phobos has immediate command submission?

tropic vigil
#

What do you mean by that

#
let cmd = record_command_buffer();
let batch = SubmitBatch::new(device, exec, &pool);
batch.submit(cmd);
let fence = batch.finish()?;
fence.await;
dawn wave
#

ahh okay thank you penguin

tropic vigil
#

You can submit batches anytime with phobos

#

for andromeda I made a system that stores such a batch per frame

#

which allows you to add command buffers to this frame's submission from anywhere

dawn wave
#

God I hate rust

#

nvm i love rust πŸ¦€

devout mesa
dawn wave
#

mmm squares

#

tasty

#

wtf does cleanup chain do in phobos

#

oh it's a linked list

#

of functions which are continiously executed

#

hmmmm

#

why

#

AHHH

#

SO YOU CAN ATTACH CLEAN UP FUNCTIONS

#

AHHHHHHHHHHHHHH

#

i'll just use a deletion queue instead

tropic vigil
#

ah, the duality

tropic vigil
#

old code

#

they only exist on fences

#

so you can do something like

#
fn upload(data) -> Fence<Buffer> {
  let cmd = exec.on_domain::<Transfer>();
  let buffer = Buffer::new();
  let staging = Buffer::new(data);
  cmd.copy_buffer(&staging, &buffer);
  fence = submit(cmd);
  fence.attach_value(buffer)
       .with_cleanup(move || drop(staging));
  return fence;
}

let fence = upload([1, 2, 3]);
let buffer = fence.wait()?;
#

this will make sure the staging buffer is deleted after the fence completes

dawn wave
#

Hmm ok

dawn wave
#

Also πŸ€“ the lifetime of staging is not ensured you akshually must use move ||

tropic vigil
#

True

#

Been a while since I got to write Rust

dawn wave
#

rust my beloved πŸ¦€

#

now im back into gp

#

does nsight have a way to view what you're drawing?

#

iirc renderdoc had a similar feature

tropic vigil
tropic vigil
#

And neither are my assignments

dawn wave
#

rust bytecode when KEKW

tropic vigil
#

I mean

#

I think it's technically possible to load rust code in MC

dawn wave
tropic vigil
#

But it's not practical

dawn wave
#

it'd be so fun to deal with the java gc

tropic vigil
#

Don't remind me

#

To be fair it has been fun just dealing with high level gameplay code for once

#

I joined the dev team of the GTNH modpack

dawn wave
#

wait what that's sick

#

but also gtnh bleakekw how many hours

tropic vigil
#

I almost beat it, currently 2300 ish

#

It's not as bad as the memes make it seem froge_bleak

dawn wave
tropic vigil
#

couldve been faster but I've spent a lot of time just building

dawn wave
#

woahh

tropic vigil
#

Looks better in game with shaders but I cba to start it now bleakekw

dawn wave
#

rust rewrite of gtnh when KEKW

tropic vigil
#

I wish

dawn wave
#

WHY IS IT A BLACK SCREEN AHHHHHH

#

FUYCK

#

FUCK

#

FUCK YOU LINEAR ALGEBRA

#

WHEN I CATCH YOU GAUSS WHEN I CATCH YOU JORDAN

tropic vigil
dawn wave
#

LETS FUCKING GOOOO

#

now the question is

#

why is glam not working

#

what is the glam equivalent to glm perspective KEKW

#

i...

#

i mixed up z_near and z_far...

#

no that was wrong

#

vkguide does switch them

#

wtffff

#

uh

#

i think

#

i got a read write issue

#

i might be wrong however

tropic vigil
dawn wave
#

@devout mesa sorry for pinging, but where was your shader resource table code at again

dawn wave
#

thanks lvstri

feral trellis
#

Fellow modded minecraft enjoyers, rejoice

tropic vigil
dawn wave
#

dawg what the fucl

tropic vigil
#

i have become blocc

dawn wave
#

alpha blending is the killer of joy