Rendy: Requirements for `nitric`

(Thomas Schaller) #1

@omni-viral I was wondering whether nitric could be used by rendy. I unfortunately couldn’t keep up with it, so I don’t know a lot about rendy currently.

If there are any things it could provide, please just tell me and we can discuss here :wink:

#2

rendy-graph uses arbitrary data-source T. In specs ultimate data source is World. But typed nature of the World require you to write rendering nodes specifically for specs::World. And even worse, rendering nodes fetch data from specific storages in World.
This is OK for fully-featured game engine like Amethyst. Because it basically dictate where data is stored (e.g. entity position is in Transform, mesh in Mesh, material in Material etc) and how to retrieve it (World::read* methods family).

But for user who uses rendy directly this may seem not flexible enough.
I imagine if nitric could be more friendly for data-driven structures.

Lets say we write a main render-pass. It needs render meshes transformed by the camera view. Output must contain this info: albedo, screen-space normal, roughness, metalness. Well… That’s enough for simple example. But not all renderable objects are the same. Some meshes are very simple (position+color). Some requires special effects and uses custom shaders. To handle all cases rendering node reads description for the renderable object first. Then it chooses pipeline (creates if required pipeline doesn’t exists yet). But what next? It must it must populate descriptor set specifically for the shader. Thankfully there is spirv-reflect, we read layout from shaders directly (yey, no more errors because of pipeline layout doesn’t match shader layout).

But here we got a problem if we use specs. For example shader uses uniform buffer:

uniform VertexArgs {
  mat4 transform;
  mat4 camera_view;
}

OK. we hardcoded how to get that from World into our rendering node. Node reads Transform and Camera storages and populates uniform buffer.
Now user writes a custom shader to render his object with wibbily wobbly timey wimey effect. Custom shader has uniform buffer:

uniform VertexArgs {
  mat4 transform;
  mat4 camera_view;
  vec4 wibbily_wobbly;
  float timey;
  uint wimey;
}

Render node has no idea that World contains WibblyWobbly and TimeyWimey storages where data for the renderable object resides and it goes like this ¯\_(ツ)_/¯ and either skips that renderable object or screams in panic!.

Now this where nitric comes onto stage and declares that it enables this use case.
For example it can allow reading from storages in form of unified data types.
world.read::<[f32; 4]>("WibblyWobbly") can return a proxy to the storage given that when WibblyWobbly was registered a function to get [f32; 4] from there was specified.

2 Likes
(Jacob Kiesel) #3

That’s an interesting proposal, though I’m struggling with a few things about it. The renderer uses data from both components and resources. For a shader uniform variable how are we to determine whether the data should come from a component or resource? Furthermore, oftentimes this data is provided by wrapping Rust types such as struct Transform which means for example nitric wouldn’t have enough info to retrieve it if it tried to use world.read::<[[f32; 4]; 4]>("Transform")

The basic gist of this is I’m not sure shaders provide enough info to allow nitric to do this.

#4

We figured that independently from nitric we should solve this problem. So instead of adding this strange functionality into nitric we should just make it on top of it. We think that it is possible to register encoders for components. So encoder registered for “Transform” name will know to red from Transform component storage and write it as [[f32; 4]; 4] into gpu buffer.