-
Notifications
You must be signed in to change notification settings - Fork 81
Description
Roughly ordered from easiest to hardest to design / implement:
- builtins as functions in spirv-std, that any code can just call instead of relying on the callees to patch through the correct variables. Needs validation during linking, since buildins are often valid only in some shader types.
- wgpu "bind group layout" / vulkan "descriptor set layout" should have some kind of direct representation within rust-gpu directly. I'm thinking of a struct declaring all the bindings of one descriptor set, soft of like wgsl does it:
#[spirv(descriptor_set)]
struct BindGroupForSystemX {
#[binding(0)] data: TypedBuffer<MyData>,
#[binding(1)] base_color: Image2D,
#[binding(2)] sampler: Sampler,
}It would be amazing if you could pass them around within this struct (you currently can't), since you could do something like this:
#[spirv(fragment)]
fn my_entry(
#[spirv(descriptor_set = 0)] system_x: &BindGroupForSystemX,
) {
systemx::process(system_x)
}Note how the descriptor_set / bind group id is declared at the entry point, so you could move it to whatever id you'd want and thus avoid conflicts if two systems use the same id? Also I pass it in as a reference, so you can't change eg. the buffer that's in systemx.data to another. We may want that as a feature, but assigning it non-uniformly makes it potentially problematic.
- small extra: Have a non-generic texture that can be unsafely cast to all the generic textures we have right now. For spirv, we need to automatically add a new texture binding of that texture type and the same binding id when casts happen. Super useful for bindless! See rust-gpu zulip, research, slang
__DynamicResource - "pipeline layout" should probably also some some representation as well. It declares the ids of the descriptor sets and the push constants. I'd move it to a struct similarly to above. This also makes it trivial to ensure a vertex and fragment shader have the same pipeline layout.
#[spirv(pipeline_layout)]
struct MyPipelineLayout {
#[descriptor_set(0)] system_x: BindGroupForSystemX,
#[descriptor_set(1)] system_y: BindGroupForSystemY,
#[push_constant] push: MyPushConstant,
}
#[spirv(vertex)]
fn my_fragment(pipeline: MyPipelineLayout) {...}
#[spirv(fragment)]
fn my_fragment(pipeline: MyPipelineLayout) {...}- Offer derive macros to create bind group layouts / descriptor set layouts / pipeline layouts directly from the structs above for wgpu / vulkan. We'd likely want our own struct representation of descriptor sets and pipeline layouts to derive to, which may be used by the application as metadata. We'd likely want a generic & const-generic variant for compile time checked code like below (from my project):
pub fn create_graphics_pipeline<T: BufferStruct>(
vertex_shader: &impl BindlessShader<ShaderType = VertexShader, ParamConstant = T>,
fragment_shader: &impl BindlessShader<ShaderType = FragmentShader, ParamConstant = T>,
...
);We'd also want to offer a non-generic variant for dynamic use-cases, like within this function. And from there offer conversion functions from there to the various wgpu & vulkan objects, hidden behind features. It's just so annoying having to keep bindings and descriptor set IDs in sync!
- The spirv spec requires that an entry point specifies all the in out and built-ins that are used within the shader. Currently, you specify those explicitly in the entry point. But with all of the above, we'd need a fixup pass during linking to assemble the entry points properly. When we already have that, why not add link-time capabilities as well?
Feel free to add suggestions!