profile
viewpoint

nikomatsakis/skill-tree 87

Skill-tree rendering

XAMPPRocky/ddg 12

A DuckDuckGo API wrapper library in Rust

XAMPPRocky/deploy-mdbook 10

A GitHub Action to automatically build and deploy your mdbook project.

rust-lang/pontoon 2

Localization platform used by Rust

rust-lang/project-group-template 2

Template for creating Project Groups

XAMPPRocky/csv-to-md 2

A small tool to convert a csv to markdown.

rust-lang/all-hands-2020 0

Website for the Rust All Hands 2020

XAMPPRocky/.github 0

Global github settings

XAMPPRocky/askama 0

Type-safe, compiled Jinja-like templates for Rust

Pull request review commentEmbarkStudios/rust-gpu

Refactor and document storage classes

+//! # Storage Classes+//!+//! Class of storage for declared variables. Intermediate values do not form a+//! storage class, and unless stated otherwise, storage class-based restrictions+//! are not restrictions on intermediate objects and their types.

Pointing out that they're aliases for pointers is important I think. I've seen some confusion over this in the rust-gpu discord, I don't think it's very clear right now that "Input<T>" means "a pointer to T, where that pointer is of style "input"" - and considering storage classes are literally "pointer flavors", seems important to document.

XAMPPRocky

comment created time in 19 minutes

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {+    VertexOutput {+        position: world_to_clip.mul(input.position),+        normal: input.normal,+        color: input.color,+    }+}++struct PixelOutput {+    // albedo and material id packed into same RGBA8 render target+    #[render_target(0)]+    albedo: Vec3,+    #[render_target(0)]+    material_idx: u8,++    // normal and exponent packed into RGBA8 render target

To be clear, I'm talking about having >1 field mapping to the same render target, and concatenating those fields into a single output.

Ah - I thought you meant the part about packing stuff together with u8 types and such. From the looks of it, it looks like the Component decoration isn't valid for render-target outputs and so all packing should be done manually.

In an earlier draft of this I actually had the pixel shader return a fixed-length array of (float|vec) from the pixel shader, something along these lines, which I feel is quite a bit simpler, but might run into trouble when outputting to render-targets with different components, or when outputting depth for example.

fn ps_main(#[stage_in] input: &VertexOutput, shading: &ShadingInputs, indirect_lighting: &IndirectLighting) -> [Vec4; 2] {
    let mut T = brdf(&shading);
    T += input.color;
    T += gi(&indirect_lighting);

    [
        pack_gbuffer0(T, material_idx),
        pack_gbuffer1(normal, specular_exponent),
    ]
}

I think maybe the best option could be to have the ps output a struct where each member represents one render target. What do you think?

Jasper-Bekkers

comment created time in 33 minutes

startedXAMPPRocky/tokei

started time in 42 minutes

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {+    VertexOutput {+        position: world_to_clip.mul(input.position),+        normal: input.normal,+        color: input.color,+    }+}++struct PixelOutput {+    // albedo and material id packed into same RGBA8 render target+    #[render_target(0)]

Ah right, I was thinking of these along the same lines as the regular rustc built-in attributes. However, if we feel putting these in their own namespace is the best way forward then I think we should do that. I would suggest putting them in another namespace then the spriv namespace though, mostly to keep them separate and avoid potential name clashes, but also to keep the new attribute clean and only add things there after some deliberation (instead of straight up forwarding spirv_headers symbols) and so we can avoid naming things after spirv-isms such as gl_compute or the confusion between workgroup and subgroup (two separate but very similar concepts in spirv).

Jasper-Bekkers

comment created time in an hour

PublicEvent

pull request commentEmbarkStudios/rust-gpu

Textures!

Why was it merged..? It should have waited for your review.

khyperia

comment created time in 2 hours

fork brson/wasmi

Wasm interpreter in Rust

https://paritytech.github.io/wasmi/

fork in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {+    VertexOutput {+        position: world_to_clip.mul(input.position),+        normal: input.normal,+        color: input.color,+    }+}++struct PixelOutput {+    // albedo and material id packed into same RGBA8 render target+    #[render_target(0)]+    albedo: Vec3,+    #[render_target(0)]+    material_idx: u8,++    // normal and exponent packed into RGBA8 render target

I'm confused, the shader-playground link doesn't have the same packing thing here, and so I'm not sure if you're saying that SPIR-V supports doing this packing built-in, or if we have to implement it ourselves. To be clear, I'm talking about having >1 field mapping to the same render target, and concatenating those fields into a single output.

Jasper-Bekkers

comment created time in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]

I think it's most likely that all of the members of a #[stage_in] struct will have to have some kind of decoration - either #[position], #[vertex_id], etc or #[attribute(..)]. However, I don't think it's required for #[stage_in] to have to have an #[attribute(..)] (see below).

Jasper-Bekkers

comment created time in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {

We should probably require both for now, I think there might be some obscure use-cases for vertex shaders so we can try to list them here and see.

  • Procedural full-screen quad will require VertexId, and so will need to declare that in #[stage_in] through something like a #[vertex_id] attribute. This would imply that at least #[attribute(N)] would be optional.
  • It might be wanted occasionally would want to store out vertex data to a buffer (think debugging tools doing mesh visualization) - in this case you probably wouldn't want to run a pixel shader directly after (or maybe you would). However, this would probably require stream-out support (which we don't have, and probably won't have for a long time since it's quite an obscure feature).
  • Another (much more likely) case would be shadow-map rendering. In this case you don't bind a pixel shader, but still need to output position from the vertex shader.

I think it's safe to require them both, unless somebody has another valid use-case that I didn't think of?

Jasper-Bekkers

comment created time in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {+    VertexOutput {+        position: world_to_clip.mul(input.position),+        normal: input.normal,+        color: input.color,+    }+}++struct PixelOutput {+    // albedo and material id packed into same RGBA8 render target+    #[render_target(0)]

The conclusion of 128 is that we're keeping spirv for now, and perhaps we rename it to #[shader(render_target = 0)] in the future. Besides, there's significant technical difficulties in supporting #[render_target(0)], and is the reason #[spirv(...)] was invented in the first place.

Jasper-Bekkers

comment created time in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {+    VertexOutput {+        position: world_to_clip.mul(input.position),+        normal: input.normal,+        color: input.color,+    }+}++struct PixelOutput {+    // albedo and material id packed into same RGBA8 render target+    #[render_target(0)]+    albedo: Vec3,+    #[render_target(0)]+    material_idx: u8,++    // normal and exponent packed into RGBA8 render target

Vec4 -> RGBA8 already happens automatically of course. And it's relatively common to be (bit) packing data into render-targets (example: gbuffer / vbuffer laydown). However, judging by the sketchy support (shader-playground)[http://shader-playground.timjones.io/2a474cd68f38f6891cadeebe41f394b3] we probably should just only support f32 (and vectors thereof) types in fragment shader outputs.

Jasper-Bekkers

comment created time in 3 hours

PR opened EmbarkStudios/rust-gpu

Reviewers
Pass in span to type translator, remove zombie_even_in_user_code

This is pre-work to clean up the zombie system, tangentially related to fixing https://github.com/EmbarkStudios/rust-gpu/issues/274

This does two things:

  • Removes the two remaining calls to zombie_even_in_user_code (other calls were cleaned up in previous PRs)
  • Passes in a span to the type translator to improve error messages

The second bit causes a lot of diff spam, so I'm submitting this as a separate PR. I did so because tracking down the errors caused by the type translator are absolutely horrible to figure out without span information (it's completely opaque what's going on). Unfortunately, quite a few places don't have span information, but still, most do, and those cases are useful. Examples of places without spans are rustc_codegen_ssa APIs that ask for, say, the type for a u64, completely without context or other information. So, we avoid calling those APIs ourselves, and instead try to call wrapper methods that do take spans, hopefully minimizing the cases where that happens. DUMMY_SP is used where spans are not available.

+305 -252

0 comment

11 changed files

pr created time in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

Textures!

 pub fn parse_attrs(     result.collect::<Vec<_>>().into_iter() } +fn parse_image(cx: &CodegenCx<'_>, attr: &NestedMetaItem) -> Option<SpirvAttribute> {+    let args = match attr.meta_item_list() {+        Some(args) => args,+        None => {+            cx.tcx+                .sess+                .span_err(attr.span(), "image attribute must have arguments");+            return None;+        }+    };+    if args.len() != 6 && args.len() != 7 {

Could we specify some of these with const generics instead of attributes?

khyperia

comment created time in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

Textures!

 fn name_of_struct(ty: TyAndLayout<'_>) -> String {     }     name }++fn trans_image<'tcx>(+    cx: &CodegenCx<'tcx>,+    ty: TyAndLayout<'tcx>,+    attr: SpirvAttribute,+) -> Option<Word> {+    match attr {+        SpirvAttribute::Image {+            dim,+            depth,+            arrayed,+            multisampled,+            sampled,+            image_format,+            access_qualifier,+        } => {+            // see SpirvType::sizeof+            if ty.size != Size::from_bytes(4) {+                cx.tcx.sess.err("#[spirv(image)] type must have size 4");+                return None;+            }

The other way to think about this is we could represent them as small as 1-byte structs, but no less, so that the offset bijectively maps to the field, and generally to avoid any ZST special-casing.

The only reason to use pointer-size is the analogy with WASM, which has e.g. "function pointers" (and more generally externref), that are abstract values which can be referred to by an usize index into a global "table", if need be. (Is that a plausible concern/direction with SPIR-V? Could we actually have a global array of e.g. Images?)

We can also avoid any Abi special-casing by using [u8; 1], IIRC, since that should create Abi::Aggregate. (Either way we should assert the .abi is what we expect, in case it does change in the future)

khyperia

comment created time in 3 hours

create barnchEmbarkStudios/rust-gpu

branch : zombie-user-code

created branch time in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]

Only a relatively small amount of those builtins actually make sense in this context - for example one can't output a VertexId and some of those are shader-stage specific like TessLevelOuter or LocalInvocationId so I would suggest we curate a list of attributes that we allow as inputs and outputs per shader stage.

Jasper-Bekkers

comment created time in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {+    VertexOutput {+        position: world_to_clip.mul(input.position),+        normal: input.normal,+        color: input.color,+    }+}++struct PixelOutput {+    // albedo and material id packed into same RGBA8 render target+    #[render_target(0)]+    albedo: Vec3,+    #[render_target(0)]+    material_idx: u8,++    // normal and exponent packed into RGBA8 render target+    #[render_target(1)]+    normal: Vec3,+    #[render_target(1)]+    specular_exponent: f32+}++fn ps_main(#[stage_in] input: &VertexOutput, shading: &ShadingInputs, indirect_lighting: &IndirectLighting) -> PixelOutput {

I think by-ref here is an omission on my part, I think by-value doesn't make this code any more or less usable from a user's point of view, so by all means if it makes life easier on our end by-value it is.

Jasper-Bekkers

comment created time in 3 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {+    VertexOutput {+        position: world_to_clip.mul(input.position),+        normal: input.normal,+        color: input.color,+    }+}++struct PixelOutput {+    // albedo and material id packed into same RGBA8 render target+    #[render_target(0)]

I thought we had consensus that we shouldn't do that #128 and I was under the impression that most of those #[spirv] attributes were either temporary or to get at specific implementation specific things from spirv. Not for higher level features.

Jasper-Bekkers

comment created time in 3 hours

startedXAMPPRocky/deploy-mdbook

started time in 4 hours

startedXAMPPRocky/tokei

started time in 4 hours

startedXAMPPRocky/tokei

started time in 5 hours

startedXAMPPRocky/tokei

started time in 5 hours

startedXAMPPRocky/rasn

started time in 6 hours

create barnchEmbarkStudios/rust-gpu

branch : texture-example

created branch time in 6 hours

startedXAMPPRocky/Rustacean.app

started time in 6 hours

created repositorybrson/paxos-for-dummies-like-me

created time in 6 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {

Is it valid to not have a #[spirv(stage_in)] attribute? No return value?

Jasper-Bekkers

comment created time in 7 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]+    color: Vec3,+}++// naming this is hard, since vertex shader won't really know what shader+// stages will run after it until the pipeline state object gets created+// in vulkan. a tesselation shader may run after this for example,+// and that decision won't be known by our compiler.+struct VertexOutput {+    #[position]+    position: Vec3,+    normal: Vec3,+    color: Vec3,+}++fn vs_main(#[stage_in] input: &VertexInput) -> VertexOutput {+    VertexOutput {+        position: world_to_clip.mul(input.position),+        normal: input.normal,+        color: input.color,+    }+}++struct PixelOutput {+    // albedo and material id packed into same RGBA8 render target+    #[render_target(0)]+    albedo: Vec3,+    #[render_target(0)]+    material_idx: u8,++    // normal and exponent packed into RGBA8 render target

Does SPIR-V support doing this packing like this built-in, or is this something we need to implement ourselves? If ourselves, what's the justification? Seems like a really obscure feature.

Jasper-Bekkers

comment created time in 7 hours

Pull request review commentEmbarkStudios/rust-gpu

[RFC] Input / output proposal

+# Summary++Shader stage interpolants are arguments used to communicate between shader stages. For simplicities sake we'll look at communicating between the Vertex Shader stage and Pixel Shader stage, and generalize later to other stages.++There is another concern here as well, which is vertex shader inputs from the input assembler. Typically these are the data that's in vertex buffers and index buffers, and it's either pre-fetched through special fixed function units or just accessed through global memory. On the API side of things this is part of the input assembler which is responsible for declaring vertex buffer layouts and optional format conversions. One thing to note here is that recently applications have started to bypass the input assembler in order to manually fetch vertex data that's needed in order to simplify application design.++# Explanation++Typically shaders communicate between stages using on-chip memory, so resources are usually limited or fall off of a performance cliff when using lots of them, so care must be taken into packing these resources together and wasting minimal space. Usually data here is packed together into 4 component vectors because hardware expects it. And a general rule of thumb would be that less parameters passed through, means more work can run in parallel (because the on-chip memory of fixed size can contain more vs/ps combintions).++## DirectX++DirectX mandates a minimum set of input and output slots available to the user of the API:++| Shader stage | Minimum requirement+| ---- | ---- |+| vertex input | 16 32-bit vectors (up to 4 components each)+| vertex output | 16 32-bit vectors (up to 4 components each)+| pixel input w/o geometry shader| 16 32-bit vectors (up to 4 components each)+| pixel input w/ geometry shader | 32 32-bit vectors (up to 4 components each)+| pixel output | 8 32-bit vectors (up to 4 components each) and 1 32-bit 1 component floating point depth value.++When the pipeline is configured without a geometry shader, a pixel shader is limited to 16, 32-bit, 4-component inputs (so 16 `int4`'s). Otherwise, a pixel shader can take up to 32, 32-bit, 4-component inputs (so 32 `int4`'s).++A pixel shader can output up to 8, 32-bit, 4-component colors, or no color if the pixel is discarded.  (so 8 `float4`'s).++### Linkage mechanism++In HLSL shader stages are linked by semanics, and can be incomplete (eg. one stage can export more then the next shader stage would import). While the semantics are documented and can be named; they don't actually imply anything other then which elements need to match up. Lots of semantics are available (`COLOR`, `BLENDWEIGHTS` etc) however, typically only `TEXCOORD[n]` is used to keep things positional and simple.++```hlsl+struct VertexInput+{+    float4 Position : POSITION;+    float3 Normal: NORMAL;+    float4 TexCoord: TEXCOORD0;+};++struct VertexOut+{+    float4 Position: SV_POSITION;+    float4 TexCoord: TEXCOORD0;+    float3 ViewNormal: NORMAL;+};++VertexOut VS(VertexInput input)+{+     // ...+}++struct PixelInput+{+    float4 Position: SV_POSITION;+    nointerpolation float4 TexCoord: TEXCOORD0;+};++float4 PS(PixelInput input)+{+    // ...+}+```+++### Additional specifiers++On top of the usual syntax that hlsl has for specifying interpolants, there are some modifier keywords that express how the interpolation between stages is being done.++| Interpolation Modifier | Description+| ---- | ---- |+| linear | Interpolate between shader inputs; linear is the _default_ value if no interpolation modifier is specified.+| centroid | Interpolate between samples that are somewhere within the covered area of the pixel (this may require extrapolating end points from a pixel center). Centroid sampling may improve antialiasing if a pixel is partially covered (even if the pixel center is not covered). The centroid modifier must be combined with either the linear or noperspective modifier.+| nointerpolation |	Do not interpolate.+| noperspective | Do not perform perspective-correction during interpolation. The noperspective modifier can be combined with the centroid modifier.+| sample |  	Available in shader model 4.1 and laterInterpolate at sample location rather than at the pixel center.+++## Vulkan Shader Stage limitations++In Vulkan no minima are enforced by the specification, however, an application can runtime query the amount of attributes that one can bind per shader stage. A quick survey on the Vulkan GPU Database gives:++| Shader Interface  | Locations Available | Min value | Max value+| ---- | ---- | ---- | ---- |+| vertex input | maxVertexInputAttributes | 16 | 4294969856+| vertex output  | maxVertexOutputComponents / 4 | 16 | 128+| tessellation control input | maxTessellationControlPerVertexInputComponents / 4 | 128 | 128+| tessellation control output | maxTessellationControlPerVertexOutputComponents / 4 | 128 | 128+| tessellation evaluation input | maxTessellationEvaluationInputComponents / 4 | 128 | 128+| tessellation evaluation output | maxTessellationEvaluationOutputComponents / 4 | 128 | 128+| geometry input | maxGeometryInputComponents / 4 | 64 | 128+| geometry output | maxGeometryOutputComponents / 4 | 128 | 128+| fragment input | maxFragmentInputComponents / 4 | 64 | 128+| fragment output | maxFragmentOutputAttachments | 4 | 8+++### GLSL Linkage mechanism++Historically GLSL used to link shader stage interpolants by name, however in recent years it acquired the `layout(location = N, component = K)` attribute on interpolants. GLSL also allows partial linking where a previous stage can output more data then the stage before.++For pixel shader outputs in modern GLSL, instead of return a value from a function one writes to a global `out` type. And similarly, shader inputs also come from globals.++### Decorators++Similar to DirectX, Vulkan has the following decorations that can be applied to interpolants.++| Vulkan | DirectX equivalent+| ---- | ---- |+| - | linear |+| Flat| nointerpolation+| NoPerspective| noperspective+| Centroid | centroid+| Sample| sample++Vulkan has some additional explanations about these decorations as well:++> A variable decorated with `Flat` will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex. A variable decorated with `Flat` can also be decorated with Centroid or Sample, which will mean the same thing as decorating it only as `Flat`.++## Metal shading language++__Mostly todo.__++One thing to note as a different to SPIR-V, GLSL and HLSL is that MSL doesn't seem to require explicit binding semantics or `Location` specifiers. It's specification has a `[[attribute(N)]]` specifier, but it's only used on tesselation control points and vertex shader inputs. It's specifically not used for communication between shader stages.++# SPIR-V Practicalities++Vertex shaders allow `Location` and `Component` decorations on input variable declarations. The `Location` decoration specifies which vertex input attribute is used to read and interpret the data that a variable will consume. The `Component` decoration allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. The components within a location are 0, 1, 2, and 3. A variable starting at component N will consume components N, N+1, N+2, …​ up through its size. For single precision types, it is invalid if the sequence of components gets larger than 3.+++## Proposal++```rust+// these `attribute`'s would match the input assembler setup on the CPU+struct VertexInput {+    #[attribute(0)]+    position: Vec3,+    #[attribute(1)]+    normal: Vec3,+    #[attribute(2)]

What behavior do you imagine when attributes are missing? Error, implicit default value, something else?

Jasper-Bekkers

comment created time in 7 hours

more