rust-lang / rust-lang/rust

Internal SIMD layout specification is not flexible enough for SPIR-V

Open
#130,405 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-align A-repr A-SIMD PG-portable-simd T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

In rust-gpu we implement a codegen backend for SPIR-V.

SPIR-V supports vector types, which we currently model by analogue of Rust Abi::Vector types, i.e. #[repr(simd)]. However, SPIR-V supports vector types of the same size that have a different representation depending on their element, which is incompatible with how Rust currently handles vector type data layouts.

Base SPIR-V Vector Layout

The default representation of SPIR-V vectors is specified in section 2.2.2 and 2.18.1 of the SPIR-V spec. This default representation is effectively an align of the underlying element type and size of element_size * count. As specified in section 2.16, the count is limited to 2, 3, or 4 elements, unless certain capabilities are enabled which allow 8 and 16 element vectors as well.

Extra requirements

However, the actual layout requirements of vector types change and can get rather messy depending on where and how they are used. As far as the SPIR-V spec itself is concerned, the above are the only rules. In practice, you must run SPIR-V code through a client implementation of some graphics API. For Vulkan, this adds extra rules for how you can load vector types from different kinds of buffers. The rules are specified in the Vulkan specification here.

Basically, under so-called scalar alignment rules (the least restrictive), stuff in buffers behaves just like repr(C) layout, with vectors retaining the property of having the same alignment as their base element.

Under the more restrictive layout rules (i.e. older versions of the spec without extensions enabled), vectors start to behave more like on x86 or aarch64: two component vectors have an alignment of twice their base element, and 3 and 4 component vectors both have alignment of 4 times the element.

Something that is unclear to me is whether it's even sensical within Rust's type model to allow the same type to exhibit different alignment requirements in different locations. If not, it makes most sense to me to always follow the less restrictive model and force the programmer to respect the more restrictive rules manually where applicable.

Alternative solutions

We already have a set of #[spirv(X)] attributes. It would be possible, though more annoying and perhaps less flexible, for us to implement a #[spirv(vector)] attribute which handles things separately. Right now we are experimenting with basically doing this to patch internal simd vector layouting.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by comparing Rust's current Abi::Vector and #[repr(simd)] layout model with the SPIR-V sections and Vulkan interface-layout rules linked in the issue. Review rust-gpu's existing #[spirv(X)] attributes and the referenced internal SIMD layout experiment; done means a decided, implementable approach for representing the required vector layouts.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.