profile
viewpoint

gfx-rs/rspirv 322

Rust implementation of SPIR-V module processing functionalities

khyperia/CudaSharp 154

A library to make C# run on CUDA-enabled GPUs

khyperia/Clam 37

A high-quality fractal viewer

khyperia/scopie 30

Astrophotography control software for khyperia's setup

khyperia/Bifrost 3

DCPU mod for KSP

khyperia/pseudogrey 2

Example of pseudogrey colors

khyperia/Astropress 1

An astrophotography stacking program

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)]

Potentially #[spirv(attribute="position")] or #[spirv(attribute=0)] instead?

Jasper-Bekkers

comment created time in 2 hours

PR opened EmbarkStudios/rust-gpu

Add GlobalBuffer proposal

This proposal stems from #249, and attempts to address #232. It does not intend to conflict with #8 but barriers may be inherently necessary to allow mutable access. It may be possible to enable specific access paradigms for trivial cases where no synchronization is necessary, but that is intended to be a potential next step.

Rendered

+324 -0

0 comment

1 changed file

pr created time in 2 hours

PR opened EmbarkStudios/rust-gpu

Use new toolchain file

I'm not quite sure where is best to document that we require nightly rust, but in that list of instructions is definitely not it.

+3 -23

0 comment

4 changed files

pr created time in 3 hours

push eventEmbarkStudios/rust-gpu

mergify[bot]

commit sha 8be59349d97b4594d965bf85696744378164af0d

Deploying to gh-pages from @ 16c380a71bd2dde6f8bf8dd4ff160edf984a9e64 🚀

view details

push time in 7 hours

push eventEmbarkStudios/rust-gpu

XAMPPRocky

commit sha 16c380a71bd2dde6f8bf8dd4ff160edf984a9e64

Refactor and document storage classes (#280) * Refactor storage classes macro and organisation * Update storage_class.rs

view details

push time in 8 hours

delete branch EmbarkStudios/rust-gpu

delete branch : refactor-storage-class

delete time in 8 hours

PR merged EmbarkStudios/rust-gpu

Refactor and document storage classes

This PR changes how storage classes where defined to their own module, refactors the macro to allow you to define multiple storage classes in a single macro invocation and more importantly allows you to add documentation to the storage classes. With the refactor I also changed the DSL you use to define storage so that's a more descriptive, and hopefully more intuitive, for example here is now what the definition of the Input and Output storage classes look like.

storage_class! {
    /// Input from pipeline.
    ///
    /// Visible across all functions in the current invocation. Variables
    /// declared with this storage class are read-only, and must not
    /// have initializers.
    #[spirv(input)] storage_class Input;

    /// Output to pipeline.
    ///
    /// Visible across all functions in the current invocation.
    #[spirv(output)] writeable storage_class Output;
}
+208 -59

1 comment

5 changed files

XAMPPRocky

pr closed time in 8 hours

push eventEmbarkStudios/rust-gpu

XAMPPRocky

commit sha d2f6c1e4c5bf36af2f3c3b159c1bb4341e6afe51

Update storage_class.rs

view details

push time in 8 hours

pull request commentEmbarkStudios/rust-gpu

Refactor and document storage classes

I've also now also added a conivence function for "load and store" operations. For example multiplying and storing the result.

// Before
input.store(input.load() * 5);
// Now
input.then(|i| i * 5);
XAMPPRocky

comment created time in 8 hours

push eventEmbarkStudios/rust-gpu

Erin Power

commit sha 15aca53ac38bbd0f2f5fb1da3f996fb6b3572684

Refactor storage classes macro and organisation

view details

push time in 8 hours

push eventEmbarkStudios/rust-gpu

XAMPPRocky

commit sha 3cc3fdb7245fa21c86322fe048afde496e7b3dbe

Update crates/spirv-std/src/storage_class.rs

view details

push time in 8 hours

Pull request review commentEmbarkStudios/rust-gpu

Refactor and document storage classes

+//! # Storage Classes+//!+//! Class of storage for declared variables. These types act as pointers to+//! values either contained in the GPU's. For example; `Input<f32>` points to a
//! values either contained in the GPU's memory. For example; `Input<f32>` points to a
XAMPPRocky

comment created time in 8 hours

push eventEmbarkStudios/rust-gpu

Erin Power

commit sha eba862f744e65cdf3552137f17152969255ef947

Refactor storage classes macro and organisation

view details

push time in 8 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

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 9 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)]

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 9 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)]

Yeah, I agree even if it's not called spirv there should be at least one wrapper attribute around the inner attribute. It would get confusing as a user as to who is defined the attribute.

Jasper-Bekkers

comment created time in 10 hours

PR opened EmbarkStudios/rust-gpu

Reviewers
Refactor and documentation storage classes

This PR changes how storage classes where defined to their own module, refactors the macro to allow you to define multiple storage classes in a single macro invocation and more importantly allows you to add documentation to the storage classes. With the refactor I also changed the DSL you use to define storage so that's a more descriptive, and hopefully more intuitive, for example here is now what the definition of the Input and Output storage classes look like.

storage_class! {
    /// Input from pipeline.
    ///
    /// Visible across all functions in the current invocation. Variables
    /// declared with this storage class are read-only, and must not
    /// have initializers.
    #[spirv(input)] storage_class Input;

    /// Output to pipeline.
    ///
    /// Visible across all functions in the current invocation.
    #[spirv(output)] writeable storage_class Output;
}
+198 -59

0 comment

5 changed files

pr created time in 10 hours

create barnchEmbarkStudios/rust-gpu

branch : refactor-storage-class

created branch time in 10 hours

PR opened EmbarkStudios/rust-gpu

Update to nightly 2020-11-26

I had problems using cargo with 2020-11-24, switching to 2020-11-26 worked and doesnt require any updates to code.

+3 -3

0 comment

3 changed files

pr created time in 10 hours

create barnchEmbarkStudios/rust-gpu

branch : update-rustup

created branch time in 10 hours

pull request commentEmbarkStudios/rust-gpu

Textures!

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

khyperia

comment created time in 10 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 11 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 11 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 11 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 12 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 12 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 12 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 12 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 12 hours

issue commentEmbarkStudios/rust-gpu

Texture support

So, if we were to support sampled_type that is f64, or any integer type, we would need vector types for f64 and integers. Glam currently doesn't support those. So, do we want to put in that work eventually? Probably not now, probably not soon, but should it be on our roadmap to do eventually?

There's a already an issue on glam for it, so we could just track that for now. https://github.com/bitshifter/glam-rs/issues/70

khyperia

comment created time in 13 hours

more