MaikKlein / rlsl

Rust to SPIR-V compiler
Apache License 2.0
557 stars 14 forks source link

Syntax for PerVertex #25

Closed MaikKlein closed 6 years ago

MaikKlein commented 6 years ago

Currently this is how PerVertex is implemented

#[spirv(vertex)]
fn vertex(vertex: &mut Vertex, pos: Vec4<f32>, color: Vec4<f32>) -> Vec4<f32> {
    vertex.position = pos;
    color
}

An alternative would be to output the PerVertex information

#[spirv(vertex)]
fn vertex(pos: Vec4<f32>, color: Vec4<f32>) -> (Vertex, Vec4<f32>) {
    let mut vertex = Vertex::new(..); 
    vertex.position = pos;
    (vertex, color)
}

Then there are other builtin variables

in int gl_VertexID;
in int gl_InstanceID;
in int gl_DrawID; // Requires GLSL 4.60 or ARB_shader_draw_parameters
in int gl_BaseVertex; // Requires GLSL 4.60 or ARB_shader_draw_parameters
in int gl_BaseInstance; // Requires GLSL 4.60 or ARB_shader_draw_parameters
#[spirv(VertexInput)]
pub struct VertexIn{
     instance_id: i32,
     ....
}

#[spirv(vertex)]
fn vertex(input: VertexIn, pos: Vec4<f32>, color: Vec4<f32>) -> (Vertex, Vec4<f32>) {
    let vertex = Vertex::new(..);
    vertex.position = pos;
    (vertex, color)
}
msiglreith commented 6 years ago

I declared the entry point interface like this back then

struct TeapotVarying {
    #[inspirv(location = 0)] v_normal: Float3,
    #[inspirv(builtin = "Position")]
    #[inspirv(location = 1)] pos: Float4,
}

#[inspirv(descriptor(set = 0, binding = 0))]
struct Data {
    world: Float4x4,
    view: Float4x4,
    proj: Float4x4,
}

#[inspirv(entry_point = "vertex")]
fn main(vertex: Attributes<TeapotVertex>, uniforms: Cbuffer<Data>) -> TeapotVarying {
    let worldview = uniforms.view * uniforms.world;
    let v_normal = worldview * Float4::from_3_1(vertex.normal, 0.0);
    let pos = uniforms.proj * worldview * Float4::from_3_1(vertex.position, 1.0);
    TeapotVarying {
        v_normal: v_normal.swizzle3(0, 1, 2),
        pos: pos,
    }
}

Single output struct for each shader with annotated struct fields, allowing to glue these things together.

MaikKlein commented 6 years ago

@msiglreith Yes I think that looks pretty good, but it does bind types to specific information like type qualifiers. I posted some ideas in https://github.com/MaikKlein/rlsl/issues/26 to make this more "reusable".

Of course my "new" proposed syntax might seem too alien

Update:

#[inspirv(descriptor(set = 0, binding = 0))]
struct Data {
    world: Float4x4,
    view: Float4x4,
    proj: Float4x4,
}

This ties Data always to set 0 and binding 0. Where my proposal would be

struct Data {
    world: Float4x4,
    view: Float4x4,
    proj: Float4x4,
}

type SomeName = Descriptor<0, 0, Data>;

where Descriptor will toughly look like this

#[spirv(Descriptor)]
pub struct Descriptor<Set: Const, Binding: Const, T> {
    set: Set,
    binding: Binding,
    data: T
} 

In the future there will be only const generics inside the Descriptor.