#DARE (Danny's Awesome Rendering Engine)

1 messages ยท Page 7 of 1

dawn wave
#

it's back :(

#

i did get color blending to work

#

LETS GOO

#

IT WORKS

dawn wave
#

Gojo my beloved <333333

dawn wave
#

okay now it's time to lock in

#

bindless

#

@devout mesa sorry for pinging again but uh why do you only allocate 1 ssbo descriptor buffer?

devout mesa
#

the rest is bda

dawn wave
#

oh wait yeah

#

i assume you just use that buffer to hold a giant array of bda pointers...?

devout mesa
#

yes

dawn wave
#

ok thanks lvstri

dawn wave
#

dude descriptor sets are pain

dawn wave
#

AHHH

#

how did it work again

#

that free list allocator thingy

#

NOOOO

#

the code is gone

#

whatever ill fucking throw in a slot map allocator and call it a day

dawn wave
#

nuh uh im throwing a slot map

dawn wave
#

wait so for bindless

#

are you making a descriptor set PER each PoolSize

#

or are you making one massive monolithic descriptor set?

devout mesa
#

guess

dawn wave
#

you have too much faith in me

devout mesa
#

hint: I like massive things

dawn wave
#

so it's just one monolithic descriptor

devout mesa
#

yes

dawn wave
#

i was led astray by embark studios smh

#

uh

#

how did you expand the address buffer...

devout mesa
#

expand?

dawn wave
#

not expand i meant

#

like insert buffers

dawn wave
#

ahh wait i found the code

dawn wave
#

god im so fucking jealous

#

actually storing pointers in your class without going into compiler error hell

#

๐Ÿฆ€ struggles

devout mesa
#

meme lang

dawn wave
#

nuh uh

#

(C++ is too scary)

tropic vigil
#

I see bugs waiting to happen

devout mesa
#

I lack the skill issue needed to write bugs

#

I am simply too strong

tropic vigil
dawn wave
#

im kinda jealous CPP lets you indicate conditional for your templates

devout mesa
#

one day you'll come back

dawn wave
#

wait why did you switch from free list to slot allocation

devout mesa
#

easier

dawn wave
#

can you like "unbind" a descriptor set

#

or is it just not worth it to do that for bindless since at the end of the day, defined behavior is that you should never get a dead descriptor

devout mesa
dawn wave
#

descriptor

devout mesa
#

sure, you erase the slot from the slotlist

#

just switch the bit back to 0

winged raptor
#

What is the difference between free list and slot allocation?

dawn wave
#

dawg wtfff

#
thread 'main' panicked at dare\src\main.rs:210:88:
called `Result::unwrap()` on an `Err` value: Requested feature is not available on this device

๐Ÿ’€

#

how does memory allocation

#

even invoke this error

#

you know

#

maybe ill give up on bindless for now

#

oh yeah wtf does RETINA_FALLTHROUGH mean in a switch case?

#

like you use the next case below?

devout mesa
#

it's just [[fallthrough]]

devout mesa
dawn wave
#

oh alright

#

hm what allocations flags should i have if i want my host to access gpu

devout mesa
#

host visible?

#

if you want to read host cached

dawn wave
#

you know maybe i should bite the bullet and actually use vma's built in allocate buffer but that kinda sucks

#

since gpu allocator makes no distinction ๐Ÿ’€

#

WAITT

#

GPU_ALLOCATOR HAS AN UP TO DATE BRANCG

#

LETS GOOO

dawn wave
#
layout(set = 0, binding = 3) readonly buffer BDA {
    uint64_t buffer_addresses[];
};
#

HMMMMM

#

why is this syntax error

#

unexpected identifier uhh

#

WAIT

#

FUCK LKMAOO

#

i forgot to enable the 64 uint extensions

dawn wave
#

AHHH

#

IT WORKS

#

BINDLESS

#

AHAHAHAA

#

IT WORKS

#
#version 450
#extension GL_EXT_buffer_reference : require
#extension GL_EXT_nonuniform_qualifier : require
#extension GL_ARB_gpu_shader_int64 : enable


layout(set = 0, binding = 0) uniform sampler samplers;
layout(set = 0, binding = 1) uniform texture2D sampled_images[];
layout(set = 0, binding = 2, r32f) uniform image2D storage_images[];
layout(set = 0, binding = 3) readonly buffer BDA {
    uint64_t  buffer_addresses[];
};

layout (location = 0) out vec3 outColor;
layout (location = 1) out vec2 outUV;

struct Vertex {
    vec3 position;
    float uv_x;
    vec3 normal;
    float uv_y;
    vec4 color;
};

layout(buffer_reference, std430) readonly buffer VertexBuffer{
    Vertex vertices[];
};

//push constants block
layout( push_constant ) uniform constants
{
    mat4 render_matrix;
    uint vertex_buffer_id;
} pc;

void main()
{
    //load vertex data from device adress
    VertexBuffer vertex_buffer = VertexBuffer(buffer_addresses[pc.vertex_buffer_id]);
    Vertex v = vertex_buffer.vertices[gl_VertexIndex];

    //output data
    gl_Position = pc.render_matrix * vec4(v.position, 1.0f);
    outColor = v.color.xyz;
    outUV.x = v.uv_x;
    outUV.y = v.uv_y;
}

LETS FUCKING GOO

#

LAHAHAHAHA

#

tears in my eyes

#

i should probably render out deccer's thingies

dawn wave
#

@devout mesa is it fine if i literally yoink your descriptor abstractions

#

sorry for pinging btw

devout mesa
#

my license is "you can literally claim my work as yours if you want"

dawn wave
#

alright thank you

#

now it's my descriptor abstraction ๐Ÿ˜Ž

dawn wave
#

glsl my most hated language

#

the urge to use slang

#

does slang support bindless?

near fern
#

yes

dawn wave
#

mmm

#

ok

#

hm in glsl can you not redefine your types KEKW

#
#define u64 uint64_t
#

pain.

#
layout(set = 0, binding = 3) readonly buffer BDA {
    u64 buffer_addresses[];
};

Does not work :(

near fern
#

i do exactly that

dawn wave
#

ahh

#

i figured it out

#

i had a typo bleakekw

#

#define u64 uint64_t**;**

near fern
#

lol

dawn wave
#

now i need a good glsl linter

devout mesa
dawn wave
#

i forgot there is none

#

everyday we inch closer to making c ffi bindings for slang

#

slang is a c api yeah?

devout mesa
#

it does have one

dawn wave
#

mmm

#

learn vulkan or go off track and make ffi bindings

#

HMMMMM

devout mesa
#

use a superior language? froge

dawn wave
#

nuh uh

#

rust may make me cry

#

but i won't have to cry searching for some stupid double free or memory bug

dawn wave
#

also i wanna finish the cpp guidelines book so i can code as the way god, Bjarne Stroustrup, intended

#

also cpp is so fucking annoying as literally there is so much implicit fucking behavior ๐Ÿ’€

near fern
near fern
dawn wave
#

๐Ÿ’€

near fern
#

use c++ like c and use c++ features with restraint

near fern
#

and undefined

#

stick with rust

#

you will live like 30 years longer then us

dawn wave
near fern
#

^ this is me (im 14 (not really))

#

too much c++

near fern
#

sorry

#

it wont be much longer

devout mesa
#

thank god

dawn wave
#

most youthful c++ programmer

dawn wave
#

Waut

#

i might've fucked up ๐Ÿ’€

#

When making bindless handles

#

should they literally also hide the resource behind them?

#

or should they just be handles strictly for bindless and are not reliant on the resource being hidden behind them?

#

seems like lvstri handles bindless as a massive storage system for all resources

devout mesa
#

one handle can be many things

#

resource aliasing is key to bindless

dawn wave
#

ahh alright

#
/// Represents a bindless resource held
///
/// T: The resource type
/// A: The resource that is being aliased by T
///
/// This dual type system allows us to effectively alias the return type of the free list.
#[derive(Debug, Clone)]
pub struct GPUResourceTableHandle<T: Clone + Destructible, A: Clone + Destructible = T> {
    handle: Handle<T>,
    free_list: FreeList<A>,
}
#

GPUResourceTableHandle<TypedBuffer<T>, Buffer>

#

this seems so

#

uh

#

unergonomic

#

maybe i just say skill issue and just make all handles untyped KEKW

devout mesa
#

why does the handle have a free list wtf

dawn wave
#

so i can do GPUResourceTableHandle.destroy() KEKW

#

probably makes more sense to not do that

#

but like

devout mesa
#

???

dawn wave
#

?

devout mesa
#

each handle has its own free list?

dawn wave
#

no a reference

#

rustism

devout mesa
#

ok

dawn wave
#
#[derive(Debug)]
struct FreeListInner<T> {
    resources: Vec<Option<T>>,
    free_ids: Vec<u64>,
    _marker: PhantomData<T>
}

#[derive(Debug, Clone)]
pub struct FreeList<T> {
    inner: Arc<RwLock<FreeListInner<T>>>,
}
devout mesa
#

there's no &

dawn wave
#

yeah because FreeList is literally just a pointer

devout mesa
#

I'll allow it

dawn wave
#

im saved

devout mesa
#

but table.destroy(handle) is better

dawn wave
#

yeah probably since it'll be easier to handle when they get deallocated

devout mesa
#

storing anything other than a u64 in a handle is dum

dawn wave
#

yeah you're right

#

i'll change it

near fern
#

just have objects if you want that

dawn wave
#

mmm i hate rust

devout mesa
#

yes you do

#

come back

dawn wave
#

i think i'm just doing this wrong KEKW

#

god dammit do i just have to live with

#

not being able to throw everything into a deletion stack

#

fml

near fern
dawn wave
#

no it doesn't i just have a skill issue-ish

#

it's just annoying if i wanna reference stuff

#

i need to hail marry wrap it around some shared pointer and interior mutability/sync locking

near fern
#

that is very bad tho

#

rust intentionally prevents this

dawn wave
#

true

#

but it's still pain bleakekw

dawn wave
#

MMMMMM

#

discovered my slot map implementation was fucked

#

hence causing a 50% chance of my program to crash

dawn wave
#

Wait so when submitting samplers

#

do I just only specify

dawn wave
#

nvm

#

man i uh kinda

#

forgotten how to get my sampler2D again

#
layout(set = 0, binding = 0) uniform sampler samplers[];
layout(set = 0, binding = 1) uniform texture2D sampled_images[];
layout(set = 0, binding = 2, r32f) uniform image2D storage_images[];
layout(set = 0, binding = 3) readonly buffer BDA {
    uint64_t buffer_addresses[];
}

KEKW

#

I FUCKING DID

#

IT

#

AHAHAAHHA

#

i can see it

#

i can hear the frames

#

all while being 100% bindless

dawn wave
#

Although itโ€™s weird

#

I canโ€™t do sampler2D sampler = sampler2D(โ€ฆ)

dawn wave
#

man

#

it seems like the architecture of the vkguide engine is uh

#

not that nice in rust KEKW

tropic vigil
dawn wave
#

should i like hail marry it and use bevy-ecs

tropic vigil
#

its not bad

#

i wanted to roll my own thingy but its not really ecs

#

its tied into the event system thing i wrote

dawn wave
#

not sure if i wanna do an event system

#

i mean iirc it's very easy to quickly implement ecs in it

#

so is adding event sys to ecs

dawn wave
#

Now that I think of it

#

how do you even implement a renderer in ecs

#

Nvm make a RenderDevice context which handles all interactions the gpu. Have a command submission system which runs last to all โ€œRenderableโ€ entities and submits all commands on a single thread

dawn wave
#

penguin you think it's advisable to like wrap my allocator in Arc<RwLock<A>>?

#[derive(Debug, Clone)]
struct GPUAllocatorImpl {
  allocator: Arc<RwLock<GPUAllocator>>
}

impl Allocator for GPUAllocatorImpl {...}
#

So I can do something like:

#[derive(Debug, Clone)]
struct ArcAllocation<A: Allocator> {
  allocator: A,
  allocation: Arc<RwLock<Option<A::Allocation>>>
}

impl<A: Allocator> Drop for ArcAllocator<A> {
  fn drop(&mut self) {
    self.allocator.free(self.allocation.take().unwrap()); // not 100% right but you get the point
  }
}
#

@tropic vigil sorry for pinging

tropic vigil
#

allocator sure, but I wouldnt wrap the actual allocation

#

you dont have shared mutable access to an allocation

dawn wave
#

RefCell?

#

wait mutex works

#

hmm i mean yeah but i liked being handle to clone my vk resources KEKW

#
#[derive(Clone)]
struct Image {
  allocation: Option<ArcAllocation<...>>
}
tropic vigil
#

no your resources should be owned uniquely

#

Or you get a mess

#

Alternatively add Arc<Image> or something but keep Image itself clean of refcounters

tropic vigil
#

No sharing

dawn wave
#

bleakekw why not

tropic vigil
#

because then youre writing java

dawn wave
#

all roads lead back to java

#

KEKW but the dx was so nice

#

the misery

dawn wave
#

my entire engine was built around the idea i could abuse the opaque pointers to clone them ininfitely

tropic vigil
dawn wave
#

i yearn for the unsafe pointers

#

maybe lvstri was right

#

no i want to be sane im staying in rust KEKW

#

i mean i could like "daxa" it

#

and like wrap everything inside an Option<> bleakekw to prevent use after free issues

tropic vigil
#

Use after free is impossible if you just Drop your resources properly

dawn wave
#

im talking if i go down

#

the

#

"fuck it we clone" route

dawn wave
#

FUCK

#

even wgpu uses arc

#

kms

#

nuh uh

#

safety is premature optimization if you think about it

#

therefore i will not optimize

#

im sorry penguin

#

nah now im stuck bikeshedding i can't pick

tropic vigil
#

ok wait so

#

theres a legitimate reason to Arc sometimes

#

For example your global caches or allocators need to be passed around everywhere and referenced in multiple places, totally fine to Arc

#

Your entire application shares ownership of this resource

#

When you use Arc<>, you're using std::shared_ptr. You're saying "Everyone owns this resource!"

#

The problem with this is that it becomes hard (impossible) to reason about lifetimes, because anywhere in the program you might still have a reference to your object

#

For a global allocator this is fine because its lifetime is tied to the program lifetime

#

For an image or a buffer however, it needs to be allocated and freed more commonly

#

If you use shared ownership, it should only be freed when no references exist anymore, but this is pretty hard to guarantee

#

If you don't guarantee that and just .destroy() or whatever, you get use-after-free errors

#

Structuring your program around proper unique ownership can be a bit tricky, but it's very clean and useful once it's done and the compiler will help a lot with it

dawn wave
#

Ah alright I'll probably have a try at making a nicer ownership system

tropic vigil
#

Where exactly do you run into issues with it rn

dawn wave
#

Main reason I'm clinging onto cloning so much is that it's so nice having a deletion queue

tropic vigil
#

You can still do deletion queues with unique ownership

dawn wave
#

Right now my deletion queue just holds a clone of the underlying resource and a ref count to the device then deletes it once it is flushed

tropic vigil
#

It's just a little different

#

Instead of that, you transfer ownership of the resource to the deletion queue

#

It then holds on to it for a few frames, and deletes it

#
impl DeletionQueue<T> {
  fn push(resource: T) {
    self.queue.push(resource);
  }
}

struct Image {}

fn main() {
  let image = Image::new();
  // do some stuff with image
  // ok im done
  // image moved into queue, now no longer accessible.
  // it is owned by the queue instead of by main()
  deletion_queue.push(image);
}
dawn wave
#

Hmmm

#

What if I need to reuse said image? Would I not end up in a weird situation where all my resources are only cleaned up until the very end?

tropic vigil
#

If you want to reuse it you shouldn't delete it ๐Ÿ™ƒ

dawn wave
#

yeah true

tropic vigil
#

You can keep the underlying allocation, gpu-allocator or vk-mem-rs already do this

dawn wave
#

ill think about it more

tropic vigil
#

It takes a little conscious effort at first but it's really one of the things that makes Rust worth it

dawn wave
#

Hm guess I've kinda been treating the deletion queue as this giant "Throw this resoruce into it" and forget about how you manage said lifetime KEKW

tropic vigil
#

What I use it for is just as a way to delay running Drop for some frames until the GPU is done with it, because there's no way to know that in Rust. For all other cases the compiler can know about it

dawn wave
#

Ah your deferred deletor kinda makes sense now KEKW

#

man I kinda liked the old way though since it wouldn't be hard at all to deal with order of deletion

tropic vigil
#

It still isn't really, it's the same as C++

#

If you need to delete A before B, either

  • Store A inside B
  • Store A alongside B so the Drop order is right
dawn wave
#

yeah true i just gotta handle the organization of data more carefully

#

seems like wgpu

#

uses refcounting

#

apperantly that's what most wgpu apps are bounded by KEKW

tropic vigil
#

Another L for wgpu

dawn wave
#

feel so bad for them KEKW

tropic vigil
#

But it makes sense since web support

dawn wave
#

"yeah man this feature would be so great"

#

"but firefox-"

tropic vigil
#

Yeah

dawn wave
#

I mean deferred deletion works but what if I need an object still once it's been pushed into a deletion queue?
i.e. an image view to create an attachment for dynamic rendering or would i just delete that last

#

eh i guess i delete it last

#

i'll just organize my device to be last in the struct so everything gets deleted before it

tropic vigil
#

what if I need an object still once it's been pushed into a deletion queue?
Then it shouldn't be pushed into the queue

dawn wave
#

KEKW sorry for asking so many dumb questions

#

im really overthinking this

tropic vigil
#

No worries lol

#

I don't mind

dawn wave
#

oh god

#

my free list allocators are all broken KEKW

#

probably should've returned a reference

tropic vigil
#

You can't return a reference to something inside an object in rust

dawn wave
#

we might be cooked

tropic vigil
#

something something self referential struct

#

Theres a reasonable explanation for it but every attempt to get around it the compiler will slap you

dawn wave
#

nah wait i guess in this case the context it's being used (bindless descriptors)

#

it probably makes sense to keep it as an arc

tropic vigil
#

Probably

#

Here's a typical example

#
struct S {
  thing: Mutex<i32>
}

impl S {
  fn lock<'a>(&'a self) -> LockGuard<'a, i32> {
    return thing.lock(); // error, return value may outlive struct
  }
}
dawn wave
#

i mean could you not use lifetime'ism?

tropic vigil
#

A good attempt, but the rust compiler does not like being tricked

#

Not all hope is lost however

#

There is a nice solution

#
struct S {
  thing: Mutex<i32>
}

impl S {
  fn with_lock<R>(&self, f: impl FnOnce(&mut i32) -> R) -> R {
    let value = thing.lock(); // LockGuard<i32>
    f(*value)
  }
}

fn test() {
  let s = S::new();
  let value = s.with_lock(|value| {
    value += 1;
    value
  });
}
#

This is how I deal with assets btw

dawn wave
#

oh KEKW

#

yeah that works but uh seems like that will run me back into cloning hell with all the vk resources i would need to copy,clone,etc. into that closure

tropic vigil
#

You don't need to move or copy them

#

You can just pass by ref

#
/// Calls the provided callback function with the asset corresponding to the given handle and returns its result.
/// Does not call the function if the asset was not found, and returns None instead.
pub fn with<A, R, F>(&self, handle: Handle<A>, f: F) -> Option<R>
where
    A: Asset + Send + 'static,
    F: FnOnce(AssetRef<A>) -> R, {
    // To access an asset we only need read access, so acquire a read lock to
    // the correct container
    self.with_container(|container| {
        // Look up the entry in the container, and call the function on a reference
        // to it if it exists.
        let entry = container.items.get(handle);
        entry.map(|entry| f(entry.as_ref()))
    })
}

Here is the pattern used with assets

#
fn load_new_mesh(
    old: Handle<Terrain>,
    options: TerrainOptions,
    bus: EventBus<DI>,
) -> Result<Terrain> {
    let di = bus.data().read().unwrap();
    let assets = di.get::<AssetStorage>().unwrap();
    assets
        .with_when_ready(old, |terrain| {
            let di = bus.data().read().unwrap();
            let assets = di.get::<AssetStorage>().unwrap();
            let mesh = assets.load(options);
            Ok(Terrain {
                height_map: terrain.height_map,
                normal_map: terrain.normal_map,
                diffuse_map: terrain.diffuse_map,
                mesh,
            })
        })
        .ok_or_else(|| anyhow!("error creating terrain from old terrain: old terrain is invalid"))?
}

Example usage

#

with_when_ready is like with but it waits for the asset to load if it was still loading

dawn wave
#

man

#

im aint cut out for this one cuh

tropic vigil
#

The asset system is uh

#

A bit of a beast

#

but I really like it

dawn wave
#

KEKW I kinda shot myself in the foot by cloning my vk handles

tropic vigil
#

It's by far the cleanest implementation of an asset store I've done over the years

dawn wave
#

its uh

#

hmmm

#

i mean i could go down that route with my bindless descriptor manager

#

since it kinda becomes a glorified resource holder

tropic vigil
#

Should say it's a little more high level than raw vk stuff but yeah the same principles can apply

#

It also does some fun bits of type erasure

dawn wave
#

ok so free list arcing probably isn't gonna work bleakekw

#

man im too deep into the engine however this is like a giant headache bleakekw

#

how is a AssetRef different from a regular ref

#
pub unsafe fn untyped_with_handle<A, R, F: FnOnce(&T) -> R>(&self, handle: &Handle<A>, f: F) -> Result<R> {
        if unsafe { !self.untyped_is_valid(handle)? } {
            return Err(anyhow::Error::from(errors::Errors::InvalidHandle));
        }
        self
            .inner
            .read()
            .map_err(|_| {
                anyhow::Error::from(crate::DagalError::PoisonError)
            })?
            .resources.get(handle.id as usize)
            .unwrap()
            .as_ref()
            .map_or(Err(anyhow::Error::from(crate::DagalError::PoisonError)), |data| Ok(f(data)))
    }
#

man

#

you know this sounds cursed

#

but in a free list i realistically do not care for the contents of a data: Vec<T> and just that they exist

#

is there a way to seperate the mutexes?

#

so like if i were to modify an element in T, it wouldn't end up locking up the entire Vec<T>

#

nah wait that's a horrible idea

#

what if i commit to the resource stack meme

#

and instead offer
push_handle_with_free_list()

#

holds a copy of the handle, and a ref of the free list allocator

#

then deletes it ๐Ÿ˜Ž

tropic vigil
#

Why do you have an unsafe block in an unsafe function

#

Either don't mark the function as unsafe or remove the block

dawn wave
#

woops

tropic vigil
dawn wave
#

natural instincts from calling ash device KEKW

#

are there like

#

any resources

#

on lifetime management so i can watch them

#

you know

#
struct TypedBuffer<'a, T> {
  handle: &'a mut T,
  _marker: PhantomDat<T>,
}
#

I just wanna be able to quickly wrap a Buffer over and have some type safety but this seems a little too niche

#

nah i should have it so i can seamlessly convert between and from TypedBuffers to regular Buffers rather than needlessly restricting TypedBuffers like this

#

bro

#

FUCK

#

i'm gonna end up with a monolithic app Drop function bleakekw

dawn wave
#

shush

tropic vigil
#

what is this typedbuffer

#

Is it like a vk::Buffer but with a type?

dawn wave
#

yeah

tropic vigil
#

Alright

#

What I've found is that trying to make views like ImageViews somehow have a lifetime reference to their owning Image gets really clunky sadly

#

I'd love to do it but I haven't found a good way

#

A typed buffer is not too different, it's just another view

dawn wave
#

yeah hmmm

tropic vigil
#

For buffers the way I've solved this is only typing mappings

#

.mapped_ptr<T>()

dawn wave
#

ah

tropic vigil
#

But you could totally have like

struct TypedBuffer<T> {
  buffer: vk::Buffer 
 _marker: PhantomData<T>
}

impl Buffer {
  pub fn into_typed<T>(self) -> TypedBuffer<T> {
    return TypedBuffer {
       buffer: self.buffer,
       // include metadata etc
       _marker: PhantomData::new()
    }
  }
}
#

Just having the typed variant own the buffer works

#

But then it's easier to just make your buffers typed by default and then alias Buffer to TypedBuffer<()>

dawn wave
#

yeahh

#

i think mapped_ptr is just gonna be easier

tropic vigil
#

Yeah

dawn wave
#

since aliasing a typedbuffer is gonna be hell

tropic vigil
#

I mean it's just type Buffer = TypedBuffer<()>

#

The only thing you have to make sure is that things that require your type to be Sized or have other properties need to be in a different impl block

#
impl<T> TypedBuffer<T> where T: Sized {
  // Stuff that needs a 'valid' type T
}

impl<T> TypedBuffer<T> {
  // Things that work on Buffers even if T = ()
}

Though you can't specialize functions this way

dawn wave
#

ahh fuck it i guess i could force a typed buffer. it's just nicer to get that type safety

tropic vigil
#

It is

dawn wave
#

accidentially submitting indices to my vertex buffer bleakekw

tropic vigil
dawn wave
#

totally never happened with my phobos engine

#

nuh uh

tropic vigil
#

Template specialization is something I'd love to have in Rust but sadly it's not that close

tropic vigil
#

Should fix that

dawn wave
#

it was also my fault too as i ended up hail marrying it since i wanted to suballocate it all

#

so i started throwing out u8 KEKW

tropic vigil
#

More type safety is always good

dawn wave
#

dude i hate PhantomData
It's 100% a skill issue but for some fucking reason despite it literally being marked as phantom data, rust will complain the generic does not implement x,y,z when it's only used in the phantom data

tropic vigil
#

Huh

#

What's your code

#

It should be fine

dawn wave
#

yeah probably which is why im saying it's a skill issue KEKW

dawn wave
#

i forgot rust

#

is really rigid

#

copium rust's new borrow checker will help

#

iirc polonious or smth like that

tropic vigil
#

Is that in stable nowadays

dawn wave
#

i have no clue

tropic vigil
#

Last time I heard it was slow as balls

#

And the compiler is already slow bleakekw

dawn wave
#

yeah i checked on it seems like development is halted since it relies on other improvements

#

since it's like being refactored to work at a lower/higher level (i think mir??)

tropic vigil
#

Makes sense

dawn wave
#

god i need it

#

since rust doesn't have partial borrowing at all

#

which is so fucking annoying

#

maybe the solution is another programming language frog_think KEKW

tropic vigil
#

The problem as always with Rust features is that even the smallest change has a million edge cases that need to be considered

dawn wave
#

yeah and also it's just slow as hell to iterate with

tropic vigil
#

Which makes it take a long time for new things to be standardized (see for example const generics)

#

Or for a more recent thing, async fn in traits

dawn wave
#

like rust is nowhere close to ever being used for game dev froge_sad

tropic vigil
#

It seems so harmless but has a huge heap of implications

dawn wave
#

yeah

#

also the rust team isn't some monolithic board like c++

tropic vigil
#

I don't mind that

#

Makes contributing a lot more straightforward and accessible

dawn wave
#

oh yeah true

#

uh

#
/// Write to a mapped pointer if one exists
    pub fn write(&mut self, offset: vk::DeviceSize, data: &[T]) -> Result<()> {
        if offset + (mem::size_of_val(data) as vk::DeviceSize) < self.size {
            return Err(anyhow::Error::from(crate::DagalError::InsufficientSpace));
        }
        if let Some(mapped_ptr) = self.mapped_ptr() {
            unsafe {
                let data_ptr = data.as_ptr() as *const _ as *const c_void;
                let mapped_ptr = mapped_ptr.as_ptr().add(offset as usize);
                ptr::copy_nonoverlapping(data_ptr, mapped_ptr, data.len());
            }
            Ok(())
        } else {
            Err(anyhow::Error::from(crate::DagalError::NoMappedPointer))
        }
    }
#

so like wtf would

#

&[()] do KEKW

tropic vigil
#

nothing

dawn wave
#

makes sense im just more concerned about type coercion since () is supposed to represent no-type

#

although maybe it's a good idea i force you to use unsafe to arbitrarily upload any data then

tropic vigil
#

btw add some //SAFETY: comments to explain why what you're doing is safe

#

Standard practice is to add a big comment to any unsafe block which details why what you're doing is completely safe in every scenario

#

It's also a good way to make sure for yourself

dawn wave
#

ohh gotcha will do thanks

tropic vigil
#

tbh, I would probably just remove the write function and instead do

pub fn mapped_slice<T>(&mut self) -> Result<&mut [T]> {
        if let Some(pointer) = self.pointer {
            Ok(unsafe {
                std::slice::from_raw_parts_mut(
                    pointer.cast::<T>().as_ptr(),
                    self.size as usize / std::mem::size_of::<T>(),
                )
            })
        } else {
            Err(anyhow::Error::from(Error::UnmappableBuffer))
        }
    }
devout mesa
#
//SAFETY: this is never safe, fuck you```
dawn wave
tropic vigil
#

looks at undocumented unsafe block after giving advice on doing so

devout mesa
dawn wave
tropic vigil
#

Actually

#

Your code probably would too

#
let data_ptr = data.as_ptr() as *const _ as *const c_void;
                let mapped_ptr = mapped_ptr.as_ptr().add(offset as usize);
                ptr::copy_nonoverlapping(data_ptr, mapped_ptr, data.len());

If T = (), then the total size in bytes of the array might be zero bytes, but data.len() won't return 0

dawn wave
#

oh KEKW

#

uhhhhhh

tropic vigil
#

(It's also wrong because data.len() is just the amount of items to be copied, but you are copying bytes (c_voids but okay) so your count is off)

#

tldr it bogus

dawn wave
#

wait fuck

#

LMAOO

#

yeah

#

i would want to do

#

mem::size_of_val yeah?

tropic vigil
#

Yeah probably

#

I like my function because it returns an actual slice

#

Which you can do easy and safe operations on

dawn wave
#

hm i have no clue how to deal with the TypedBuffer<()> issue

#

do i just do some unimplemented! panic

#

man all roads point back to just doing a .mapped_ptr::<T>()

tropic vigil
#

You simply do not implement the method for TypedBuffer<()>

dawn wave
#

wait

tropic vigil
#

Though I actually don't know if there's a trait to detect that

#

hm

dawn wave
#

() doesn't implement Sized

tropic vigil
#

Oh it doesn't, perfect

#

Then you have your trait

dawn wave
#

nah it nvm bleakekw

#

ah actually

#

let me go into rust playground

tropic vigil
#

It does

dawn wave
#

AHH

#

dammit

tropic vigil
#

Well

#

There is T: !MyTrait but you can only use it on builtin traits

#

Otherwise you could just use

trait Unit {}

impl Unit for () {}

fn foo<T: !Unit>(arr: &[T]) {
    
}

fn main() {
    foo(&[(), (), ()]);   
}
dawn wave
#

doesn't solve of still exposing the existing write methods

tropic vigil
#

If you could write this it would but sadly you can't

dawn wave
#

oh wait i see

#

!Unit

tropic vigil
#

Yeah that's not possible, only with builtin traits like Sized, Send, Sync

#

grabbing a slice seems better then

dawn wave
#

yeah probably

tropic vigil
#

Since a slice of () is valid, though you'd never actually call that because it's nonsense

#

"hmm yes I'd like a view of this GPU buffer of nothing please"

dawn wave
#

the hacky way

#

is to detect if the generic has a size of zero

tropic vigil
#

Oh yeah you can do that in the function

#

I was just hoping there'd be a nice way of expressing that as a trait bound

dawn wave
#

just throw some if size_of::<T> == 0 { unimplemented!() } expept for unsafe fn write_arbitrary

tropic vigil
#

Which would trigger a compiler error

dawn wave
#

yeah me too

#

i'm probably not gonna do that tbfh

#

but atp i might as well mapped_ptr::<T>

#

dude i fucking overengineered it

#

LMAOOO

#

i just realized

#

.into_typed::<T>

.into_untyped()

#

boom

#

no lifetime bullshit

#

nah wait

#

i'm stupid

#

there are situations i wish to simply view into a buffer but cannot take ownership

tropic vigil
#

thatโ€™s what I was originally suggesting yeah lol

#

But yes

#

Sometimes you just need a view

#

Though the only time you care about its type is when you are writing or reading data from the mapped pointer

#

So itโ€™s pretty natural to return a typed slice, which is exactly that

#

A typed view

dawn wave
#

you know what

#

im calling it for a day

#

my brain hurts

#

im emotionally hurt knowing all of my progress was a lie

tropic vigil
#

It is the way forward

#

Good way to learn

dawn wave
#

yeah true can't learn without failing

#

but also a part of me thinks i'm probably fine just clonining my handles for now as i make through vkguide

#

lower the number of things i need to juggle for now basically

#

cuz like figuring lifetimes + learning vulkan bleakekw

tropic vigil
#

a pretty good rule of thumb is that if youโ€™re using lifetime parameters youโ€™re probably overcomplicating things

#

of course you need them sometimes though

dawn wave
#

i mean i think this case is a pretty good use of them probably

devout mesa
#

there are no lifetimes in C++ btw froge

dawn wave
#

lvstri your propaganda won't get me

devout mesa
#

it's not mere propaganda, simply the truth froge

dawn wave
#

bleakekw mmm

#
use core::marker::PhantomData;
pub struct my_generic<T> { _marker: PhantomData<T> }
pub struct not_clone {}


#[derive(Clone)]
pub struct my_stuff {
    my_data: my_generic<not_clone>
}

fn main() {
    println!("Hello, world!");
}
#

curse you phantomdata

#

this probably makes sense but why can you not just be normal and not force your generic onto the entire type's requirements since it quite literally does not need them

#

ah- i could technically do ::size_of::<T>() KEKW

#

ahhh

#

is there a phantomdata that uh removes that

tropic vigil
dawn wave
#

yeah it doesn't

tropic vigil
#

It has nothing to do with PhantomData

dawn wave
#

it shou;dn't

tropic vigil
#

Your generic doesnโ€™t implement Clone

dawn wave
#

yeah i realized that KEKW

tropic vigil
#

You can do impl<T: Clone> Clone for my_generic<T> though

dawn wave
#

yeah that's what i did

#
let sampler = self.with_sampler(&sampler_handle, |sampler| {
            sampler.handle()
        })?;

bleakekw

tropic vigil
#

(Derive sadly does not include those bounds)

dawn wave
#

i mean tbfh

#

with_sampler

#

isn't that bad

#

i mean

#

copium

tropic vigil
#

Why is that needed here

devout mesa
#

average rust user

tropic vigil
#

Im confused

dawn wave
#

remember the uh stupid quirk

#

well not stupid

#

but like you can't return a ref

tropic vigil
#

Yeah

dawn wave
#

so you offered to just do with_...

tropic vigil
#

Whatโ€™s the type of sampler here

dawn wave
#

i mean it works

#

vk::Sampler

tropic vigil
#

And sampler_handle?

dawn wave
#

Handle<Sampler>

tropic vigil
#

Whatโ€™s that

dawn wave
#

A free list handle

tropic vigil
#

Hmm

dawn wave
#

aka u64

tropic vigil
#

I would just expose a method in Handle<T> to grab the T if youโ€™re returning a copy anyway

#

Can guard it behind a T: Copy bound

dawn wave
#

ahh

#

real

#

factual

tropic vigil
#

Maybe make it unsafe because it allows concurrent usage without that being checked

dawn wave
#

ah nah it wouldn't work

#

since handles are just u64

tropic vigil
#

In Phobos everything that returns a raw vk object is unsafe

dawn wave
#

contain no ref back to their free list as that kinda defeats their purpose

tropic vigil
#

So then free_list.get(handle) or something

dawn wave
#

KEKW so tiny

#

eh well

#

impl<T: Resource then T::HandleType: Copy>

#

tbf i could just restrict handletype to copy only

#
/// If you're simply acquiring handle of a resource
    pub fn get_resource_handle(&self, handle: &Handle<T>) -> Result<T::HandleType> {
        if !self.is_valid(handle)? {
            return Err(anyhow::Error::from(errors::Errors::InvalidHandle));
        }
        Ok(self.inner
               .read()
               .map_err(|_| Err(anyhow::Error::from(crate::DagalError::PoisonError)))?
            .resources
            .get(handle.id as usize)
            .unwrap()
            .as_ref()
            .unwrap()
            .handle())
    }
#

sadge it only works for .handle

#

in theory i could shove all copyable data in resources

#

to something like type Copyable or like type Metadata

#

then do like
get_resource_metadata()

#

although i wouldn't say metadata makes sense KEKW

#

i think i cooked

dawn wave
#

now

#

time for the final boss: how the fuck do i manage lifetimes

#

ah yeah rust drops items in order

dawn wave
#

Iโ€™m really determined to get deletion stacks working ๐Ÿ˜ญ

Maybe I created an Inner struct which can be freely copied around. This copying is restricted to deletion stacks only and they store them to be deleted

#

Penguin is this a good idea

dawn wave
#

WAIT FUCK

#

VULKANO EXISTS

#

LMAOOO

tropic vigil
tropic vigil
dawn wave
#

Data: Vec<Option<T>>

#

we already checked that Option<T> is Some(T)

tropic vigil
#

hm true

dawn wave
#

im gonna lose it

#

Okay, we're gonna use Inner structs which can be copied

#

deletion stacks can accept this inner

#

and use this to delete them

#

this will keep me sane

#

and not end up with me wanting to commit henious crimes against memory lifetimes

#

nuh uh

#

99% of rust programmers quit before the hit it big (lifetimes)

tropic vigil
#

real

dawn wave
#

MR PENGUIN

#

WE DID

#

WE FUCKING DID IT

#

NO CLONING OF THOSE NASTY VULKAN HANDLES

#

ME? USE AFTER FREE ISSUES? NAAHHHHH

#

I DON'T FW THAT

#

i also figured out i could use manuallydrop on my swapchain images to never drop them

dawn wave
#

dude i forgot rust dropped stuff in order of their declaration bleakekw

#

so i had a massive drop function for no reason

tropic vigil
#

its the reverse of in C++ iirc

#

its fun

dawn wave
#

how does cpp drop?

#

struct {
int a;
int b;
}

C++ drops b then a?

#

rust drops a then b

devout mesa
#

non trivial types have destruction in reverse order of initialization

dawn wave
#

ahh

#

what is a trivial type?

#

just anything that is stored on the stack?

devout mesa
#

this is C++

dawn wave
#

oh rust copy?

devout mesa
#
 Trivially copyable class

A trivially copyable class is a class that

    has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator,
    each eligible copy constructor is trivial
    each eligible move constructor is trivial
    each eligible copy assignment operator is trivial
    each eligible move assignment operator is trivial, and
    has a non-deleted trivial destructor. 

Trivial class

A trivial class is a class that

    is trivially copyable, and
    has one or more eligible default constructors such that each is trivial. 

Standard-layout class

A standard-layout class is a class that

    has no non-static data members of type non-standard-layout class (or array of such types) or reference,
    has no virtual functions and no virtual base classes,
    has the same access control for all non-static data members,
    has no non-standard-layout base classes,
    only one class in the hierarchy has non-static data members, and
    Informally, none of the base classes has the same type as the first non-static data member. Or, formally: given the class as S, has no element of the set M(S) of types as a base class, where M(X) for a type X is defined as: 

        If X is a non-union class type with no (possibly inherited) non-static data members, the set M(X) is empty.
        If X is a non-union class type whose first non-static data member has type X0 (where said member may be an anonymous union), the set M(X) consists of X0 and the elements of M(X0).
        If X is a union type, the set M(X) is the union of all M(Ui) and the set containing all Ui, where each Ui is the type of the ith non-static data member of X.
        If X is an array type with element type Xe, the set M(X) consists of Xe and the elements of M(Xe).
        If X is a non-class, non-array type, the set M(X) is empty.```
dawn wave
#

mmmm rust copy

#

i need to pick up c++ one day since i need to get an actual job KEKW

devout mesa
#

the TL;DR version of that is:

  • constructor is trivial or defaulted inline trivial
  • destructor is trivial or defaulted inline trivial
  • trivial copy constructors
  • every subobject is trivial and or primitive
  • no virtual functions
  • no non-trivial base classes (this still introduces padding
  • same access specifiers for all subobjects
  • no references
#

this is why learning C++ is valuable btw

#

it trains your brain to this

dawn wave
#

it does train your brain to deal with a lot of implicit behavior

#

and also multiple compilers

devout mesa
#

nothing is implicit if you know the standard

dawn wave
#

true

#

but i like rust being very explicit in every move/copy/clone you do

#

makes it harder for me to go braindead and accidentially doing a bunch of copies i never meant to do

devout mesa
#

on the contrary, your trust in the compiler means that if something goes wrong it's joever

dawn wave
#

KEKW true

devout mesa
#

meanwhile I trust nothing, therefore I can't be hurt in any way

dawn wave
#

i just like how cpp has multiple implementations

devout mesa
#

stuff going wrong is the default behavior

dawn wave
#

forcing you to rely wholly on spec

#

and makes cpp spec just more rigirious since more people are implementing it

dawn wave
devout mesa
#

the only reason why cpp has a spec is because you can't understand it otherwise

dawn wave
#

mhm

devout mesa
#

anyways go back to c++

dawn wave
devout mesa
#

it's good for you

dawn wave
#

one day

devout mesa
#

trust

dawn wave
#

nuh uh

#

one day

#

soon(tm)

#

i need good cpp resources anyways

#

eh i guess i could use cppcon back to basics

#

it's very much a speedrun of cpp for those who are "familiar" with it so i guess i would fit in

#

anyways

#

AHAHAHA

#

it worky now

near fern
#

stay strong

#

brain workout

#

rust is more weight

#

you ll get stronger then c++ people

dawn wave
#

real and factual

#

my renderer no longer uses unsafe pointers

#

all objects are now exclusively owned by their own class and no longer duplicate their vk pointer handles

#

im one step closer to the most safe code

#

OH FUCK

#

MY TESTS

#

ALL MY TESTS

dawn wave
#

Okay here is an insane idea

#
pub trait ResourceInner: Copy + Debug {
  type HandleType;
  pub fn get_handle(&self) -> Self::HandleType
  ...
}

pub trait Resource: Debug {
  type HandleType;
  type ResourceIn: ResourceInner;
  pub fn inner(&self) -> ResourceIn;
}
#

we reimplement resource onto deletion stack element

#

and force everything to have a Result<...> return

#

then we can in theory

#

use a deletion stack still

devout mesa
dawn wave
#

mmm rust requires me to think harder

dawn wave
#

ray tracing or meshlets

#

๐Ÿค”

#

rust does have a metis lib

#

i guess i could start with meshlets for now since they can be applied in both rt + rasterization

devout mesa
#

where did you hear that

#

what are you trying to cook

#

metis is forbidden knowledge

dawn wave
#

i remember reading it on some blog post

devout mesa
#

anyway no

#

don't do anything with metis

dawn wave
#

aw

devout mesa
#

come back in one year

dawn wave
#

ok

devout mesa
#

also no HWRT and meshlet don't mix

#

research is still active

dawn wave
#

mmm alright

dawn wave
#

dude why the fuck

#

does rust have no good gui integration with ash

dawn wave
#

uh how does one bind multiple push constants

tropic vigil
#

egui

dawn wave
tropic vigil
tropic vigil
#

that just uses phobos apis

devout mesa
dawn wave
#

nvm made a mistake

#

you can bind descriptor sets with constants in them

devout mesa
#

what

dawn wave
#
layout(set = 0, binding = 0) uniform  SceneData{   

    mat4 view;
    mat4 proj;
    mat4 viewproj;
    vec4 ambientColor;
    vec4 sunlightDirection; //w for sun power
    vec4 sunlightColor;
} sceneData;

layout(set = 1, binding = 0) uniform GLTFMaterialData{   

    vec4 colorFactors;
    vec4 metal_rough_factors;
    
} materialData;
devout mesa
#

why are these in two different sets

dawn wave
#

ask vkguide

devout mesa
#

didn't you achieve bindless

dawn wave
#

oh yeah

#

should i just throw these into 1 big push constant

#

or like

devout mesa
#

no

#

buffer

dawn wave
#

AH

devout mesa
#

give address to shader

dawn wave
#

yeah

devout mesa
#

be happy

dawn wave
#

thanks lvstri

dawn wave
#

uh

#

for a material buffer yeah?

#

should i just have it so when i render i re-upload that data

#

or should i just make a some really big material buffer

tropic vigil
#

Start by just copying every frame

dawn wave
#

Penguin

#

uh do you have idea if it's a good idea to group my vk::PipelineLayout with my vk::Pipeline?

#

My only issue is that it makes it hard to reuse

#

without resorting to Arc<>'ing it

tropic vigil
#

You can do that yeah

#

I think I pack that data together in phobos

dawn wave
#

Eh I went with just seperatikg them

dawn wave
#

Bro I need to do graphics

#

I'm too addicted to modded Minecraft

#

i refuse to gregify because it will be an unstoppable addiction

tropic vigil
#

DO IT

#

GREGIFY

#

come join the GTNH discord I know you want to

tropic vigil
#

Eearslya has already joined us ElmoFire

dawn wave
#

nuh uh im too deep into create mod

#

gregification will wait until i graduate from uni

#

but MMMMM

#

The G in graphics programming stands for Gregtech

tropic vigil
#

create sucks

dawn wave
#

yeah but moving contraption makes me goo oo oo ee ee aa aa

tropic vigil
#

Ok but you could have AE going brrr in GTNH

dawn wave
#

guys i got a split keyboard

#

this is so com confusing to use

#

now i just need to learn vim kekw

#

but my wpm is so badd

#

how do i even code in this condition

dawn wave
#

ok so material creation now works

#

also i am typing at 30 wpm now instead of 20 wpm

tropic vigil
#

big gains

#

still slow kekw

dawn wave
#

kekw now we're back to 40wpm

#

it is suprisingly alright for gaming tbfh

dawn wave
#

OH MY HOR

#

GOD

#

I CAN ACTUALLY DO VKGUIDE WITHOUT KILLING MYSELF

#

THIS IS ACTUALLY AMAZIJG

#

HOLY SHIT

#

OH MY HOD

#

THIS IS ACTUALLY AMAZING

tropic vigil
dawn wave
#

oh my god my school's student formula team allowed me to rewrite some of their shit in rust

dawn wave
#

IM FINALLY A TRUE RUST PROGRAMMER

#

PENGUIN I MADE IT

feral trellis
#

I'm gonna steal ur code next year vro...

dawn wave
#

kekw

#

wanna join gryphon fsae

#

we deadass just make cares n shit

#

im trying to gaslight them to rewriting the entire car in rust

feral trellis
#

At least that's one club

dawn wave
#

it's the most funded one ๐Ÿ˜Ž

#

we literally suck all of the engineering's club money

#

"yes sir we need 10k to print our carbon fibre"

#

we'll be there at the engineering section of the club faire

feral trellis
#

Holy based lol

dawn wave
#

there are 2 during o-week. the first is the general one. the second is the engineering one

#

first is if you wanna touch grass and join social shit

#

second is if you wanna do activism or not touch grass and make cars and aerospace shit

#

wait fuck first is wrong, there was an anime club KEKW they fucking meow'd when i went there

feral trellis
#

๐Ÿ’€ fitting for me ngl...

#

eh we'll see next year

dawn wave
#

mm you'll be fine

#

people hype up the first weeks way too much lmaoo

tropic vigil
dawn wave
#

mmm

#

i think i'll just clone my vulkan stuff

#

it'll keep me sane

dawn wave
#

also vkguide is designed with that in mind KEKW

dawn wave
#

dude vkguide is getting confusing now

devout mesa
#

vkguide doesn't clone anything sir

dawn wave
#

no like clone my vulkan handles

devout mesa
#

yea

#

but then destructors don't make sense

dawn wave
#

hmm

#

aaa fine ill stay with the pain

devout mesa
#

I'll be comfortable in my C++ penthouse

#

you're always invited

dawn wave
#

mmmm

#

i somehow fucked up me matrices

#

it seems like the mesh is only visible from the inside

dawn wave
#

fml

#

i mixed up view and proj

#

materials

#

well sorta

#

close enough

#

i really dislike how vkguide does it

dawn wave
#

hmm is there a nice way to handle mesh resource lifetimes

dawn wave
#

cuz i have a weird issue with my vertex buffers and index buffers

#

since they're all hidden behind a freelist allocator, i can't just throw arc on them

dawn wave
#

fellas

#

Do I make a seperate MeshBuffer (contains the addresses of all my vertices + indices) and it contains an index into my MaterialBuffer which contains ids to textures + samplers

#

or should I just throw it into one massive mesh info buffer then just provide an id to index into said buffer

dawn wave
#

will i need to ever worry about more than 1 texcoords

dawn wave
#

@tropic vigil sorry for pinging, but what would make the most sense for suballocations of a buffer? Should I just have:

pub struct BufferView<A: Allocation> {
  buffer: Arc<Buffer<A>>,
  offset: vk::DeviceSize,
  length: vk::DeviceSize,
  stride: vk::DeviceSize
}

?

tropic vigil
#

That seems sensible yeah

#

Well

#

idk why the stride would be useful

#

since its a single contiguous view

dawn wave
#

true

#

mmm i really don't like i have to use arc kinda feels like giving up

tropic vigil
#

feels wrong ye

#

I still dont really get where you run into major issues not using arcs though

dawn wave
#

it's mainly if 2 meshes reference the same buffer

#

cuz the other solution is to throw into some slot map and have a pseudo reference counting system but atp, i might as well throw on rc/arc

tropic vigil
#

Is that because the buffer is suballocated or do they actually reference the same data

dawn wave
#

same data

tropic vigil
#

In this case why are they not the same mesh

#

To me the real problem sounds like your mesh is too concrete

dawn wave
#

yeah i mean i could make that assumption

tropic vigil
#

If two meshes hold the same data, they are the same - if you need something to build differences on top that means that thing shouldn't be a mesh but an abstraction above it (that refers to a mesh)

dawn wave
#

hmm how to make sure allocations are valid throughout a suballocations' lifetimes

#

hmmm

#

tbfh i could just yolo it and throw it into a giant slot map and hope the logic just works out

tropic vigil
#

I would probably handle this by letting SuballocatedBuffer return handles or strong ids that refer to a unique range in the buffer (could simply be offset/size packed into a u64), and then have another method that allows getting the actual view when you need it

#

So for storage purposes you just have this BufferSliceID or something, but when you need to actually access the buffer you make a quick query to the backing buffer

dawn wave
#

handle-ception

#

KEKW my buffers are already handles themselves

tropic vigil
#

If you want to make your id fancy and hold a reference to the storage, you could consider std::sync::Weak to store alongside it

tropic vigil
#

So if your buffers are something like Handle<RawBuffer>, then your SuballocatedBuffer holds a RawBuffer

dawn wave
#

so i just forget about using Handle<RawBuffer> and prefer suballocatedbuffer

#

?

tropic vigil
#

If thats what your handles were for, probably

#

I mean the id/handle that your suballocatedbuffer would return is effectively what your handles from before were doing

#

Except now you keep the possibility of using full buffers that are not suballocated by simply using whatever buffer type SuballocatedBuffer is abstracting over

dawn wave
#

kekw it's probably easier to just have a seperate buffer position/normal/tangents per mesh

#

i mean isn't that what ue5 literally does

#

someone needs to remind to stop overthinking stuff

dawn wave
#

WAIIIIIIT DRAW INDIRECT FUCK

tropic vigil
dawn wave
#

??

#

you know how could i handle uploading mesh data in a nicer way

#

cuz i feel like there it isn't a good idea to literally double my gpu memory for a:
GpuOnly buffer as well a CpuToGpu buffer

devout mesa
tropic vigil
#

?? my beloved

#

my favorite operator

dawn wave
dawn wave
#

one thing that pisses me off rn is that

#

my surface structs only hold handles since i submit all my buffers to the gpu resource table

tropic vigil
#

real

dawn wave
dawn wave
#

guys i need a logo for my engine

#

hmmmmm

tropic vigil
#

Your pfp seems good

dawn wave
#

fuck it one buffer per material

#

this suballocation shit is hurting me head too much

dawn wave
#

okay hear me out

#

nvm don't

#

Dude I don't wanna end up having to do this:

struct Material {
  handle: Handle<render::Material>,
  freelist_suballocator: Arc<RwLock<FreeListSuballocator>>,
}

impl Drop for Material {
  fn drop(&mut self) {
    self.freelist_suballocator.free(self.handle);
  }
}
#

This literally makes handles redundant

#

penguin pls help how do i make a material buffer i am once again overthinking

tropic vigil
#

this seems like an antipattern

#

if you have something that is referred to by handles

#

then something else owns it

#

so that something else should be responsible for removing it from the freelist (or should be the freelist entirely)

feral trellis
dawn wave
#

wdym penguinm?

#

hmmm deletion queue is fine? but at the end of the day, the resource still needs to be deleted regardless

dawn wave
#

there really is no nice way to deal with this bleakekw

#

rust moment (tm)

#

it's weird cuz my materials can be referenced by multiple meshes

#

do i need to make sure they don't get deleted then

#

but also make sure they get destroyed if not needed

#

all my resources are effectively owned by my bindless gpu resource table which just hands out handles when inserted into

#

maybe i make it no longer own them?