|  | # Chromium Experimental Static Samplers | 
|  |  | 
|  | The chromium_experimental_static_samplers extension is an experimental extension that allows the use of static samplers in WGSL. | 
|  | Static samplers translate to immutable samplers in Vulkan, constexpr samplers in Metal Shading Language, and static samplers in Direct3D 12. | 
|  |  | 
|  | # Status | 
|  |  | 
|  | This extension is experimental and the syntax is being discussed. No official WebGPU specification has been written yet. | 
|  |  | 
|  | # Design considerations | 
|  |  | 
|  | ## const or var | 
|  |  | 
|  | `@group(X) @binding(Y) const mySampler;` | 
|  | or | 
|  | `@group(X) @binding(Y) var mySampler;` | 
|  |  | 
|  |  | 
|  | In HLSL and SPIR-V, static samplers need a binding slot, hence the `@group(X) @binding(Y)` syntax. | 
|  | Vulkan and Direct3D 12 supply static samplers via the API. | 
|  | Metal Shading Language declares static samplers with `constexpr`, which is ready to be used in the shader without Metal API interaction. | 
|  |  | 
|  | Normal samplers in WGSL are declared with `var` because they have a handle address space, which is read-only. | 
|  | Using the `const` keyword for static samplers is sensible, as static samplers are immutable objects. | 
|  | However, `const` does not have a handle address space which is required for HLSL and SPIR-V and would require spec changes to support it. | 
|  |  | 
|  | Using `var` for static samplers is recommended for consistency with the rest of the language and they are already immutable. | 
|  |  | 
|  | ## Using a struct | 
|  |  | 
|  | ```wgsl | 
|  | @group(X) @binding(Y) const mySampler = sampler { | 
|  | addressModeU: mirror_repeat, // enumerant | 
|  | magFilter: linear, | 
|  | lodMinClamp: 1, // abstract float | 
|  | ... | 
|  | }; | 
|  | ``` | 
|  |  | 
|  | The `sampler` is a built-in struct that can be used to define samplers. | 
|  | Advantages are its readability and similarity to the WebGPU API's `GPUSamplerDescriptor` struct. | 
|  |  | 
|  | This approach would require a new WGSL feature for initializing struct values. | 
|  |  | 
|  | If the new WGSL feature is introduced, this approach is recommended for readability and intuitiveness. | 
|  | However, for the initial implementation, it is not desirable to introduce a substantial change in WGSL. | 
|  |  | 
|  | ## Using a function | 
|  |  | 
|  | ```wgsl | 
|  | const clamp_to_edge = 0; | 
|  | const mirror_repeat = 1; | 
|  | ... | 
|  | sampler(mirror_repeat, linear, 0.0, 16); | 
|  | sampler_comparison(mirror_repeat, linear, 0.0, 16); | 
|  | ``` | 
|  |  | 
|  | or | 
|  |  | 
|  | ```wgsl | 
|  | sampler<mirror_repeat, linear>(0.0, 16); | 
|  | sampler_comparison<mirror_repeat, linear>(0.0, 16); | 
|  | ``` | 
|  |  | 
|  | In both cases, `sampler` is a built-in function that returns a static sampler. | 
|  | The first approach takes a list of arguments. These arguments are predefined constant values and not enums. | 
|  | The second approach takes a list of enum template parameters and a list of arguments. The arguments are LOD min and max clamps, because they are not enums. | 
|  |  | 
|  | Both approaches are readable and intuitive but due to the large amount of parameters that can be set on a sampler, the approaches may become hard to read and write. | 
|  | The approaches do not need any new WGSL features and are sufficient for a prototype implementation. | 
|  |  | 
|  | For the prototype implementation, the first function approach is good for its simplicity. | 
|  |  | 
|  | # Pseudo-specification | 
|  |  | 
|  | This extension adds `sampler(...)` and `sampler_comparison(...)` functions to return a sampler type. | 
|  | The functions take integer values that are predefined constants. If a sampler is initialized with any of the two functions, it is considered a static sampler, otherwise it is a normal sampler. | 
|  | The predefined constant variable names are similar to the WebGPU API enums. | 
|  |  | 
|  | Function restrictions include: | 
|  | - The function can only be called to initialize a static sampler. | 
|  | - Only built-in functions can return a sampler, user-defined functions cannot. | 
|  | - The function can not be used in an expression, only in a declaration. | 
|  |  | 
|  | Order of arguments: | 
|  | - addressModeU | 
|  | - addressModeV | 
|  | - addressModeW | 
|  | - magFilter | 
|  | - minFilter | 
|  | - mipmapFilter | 
|  | - compare (only for `sampler_comparison(...)`) | 
|  | - lodMinClamp | 
|  | - lodMaxClamp | 
|  |  | 
|  | New Constants: | 
|  | - Address Mode: | 
|  | - WGSL: `clamp_to_edge=0`, `repeat=1`, `mirror_repeat=2` | 
|  | - WebGPU equivalent: `"clamp-to-edge"`, `"repeat"`, `"mirror-repeat"` | 
|  | - Filter Mode: | 
|  | - WGSL: `nearest=0`, `linear=1` | 
|  | - WebGPU equivalent: `"nearest"`, `"linear"` | 
|  | - Mipmap Filter Mode: | 
|  | - WGSL: `mipmap_nearest=0`, `mipmap_linear=1` | 
|  | - WebGPU equivalent: `"nearest"`, `"linear"` | 
|  | - Comparison Function: | 
|  | - WGSL: `never=0`, `less=1`, `equal=2`, `less_equal=3`, `greater=4`, `not_equal=5`, `greater_equal=6`, `always=7` | 
|  | - WebGPU equivalent: `"never"`, `"less"`, `"equal"`, `"less-equal"`, `"greater"`, `"not-equal"`, `"greater-equal"`, `"always"` | 
|  |  | 
|  | # Example usage | 
|  |  | 
|  | ```wgsl | 
|  | @group(0) @binding(0) var mySampler = sampler(mirror_repeat, clamp_to_edge, mirror_repeat, linear, linear, mipmap_linear, 0.0, 16.0) | 
|  |  | 
|  | @group(0) @binding(1) var myComparisonSampler = sampler_comparison(mirror_repeat, clamp_to_edge, mirror_repeat, linear, linear, mipmap_linear, less, 0.0, 16.0) | 
|  |  | 
|  | ``` | 
|  |  |