wgpu/api/
shader_module.rs

1use std::{borrow::Cow, future::Future, marker::PhantomData};
2
3use crate::*;
4
5/// Handle to a compiled shader module.
6///
7/// A `ShaderModule` represents a compiled shader module on the GPU. It can be created by passing
8/// source code to [`Device::create_shader_module`] or valid SPIR-V binary to
9/// [`Device::create_shader_module_spirv`]. Shader modules are used to define programmable stages
10/// of a pipeline.
11///
12/// Corresponds to [WebGPU `GPUShaderModule`](https://gpuweb.github.io/gpuweb/#shader-module).
13#[derive(Debug, Clone)]
14pub struct ShaderModule {
15    pub(crate) inner: dispatch::DispatchShaderModule,
16}
17#[cfg(send_sync)]
18static_assertions::assert_impl_all!(ShaderModule: Send, Sync);
19
20crate::cmp::impl_eq_ord_hash_proxy!(ShaderModule => .inner);
21
22impl ShaderModule {
23    /// Get the compilation info for the shader module.
24    pub fn get_compilation_info(&self) -> impl Future<Output = CompilationInfo> + WasmNotSend {
25        self.inner.get_compilation_info()
26    }
27}
28
29/// Compilation information for a shader module.
30///
31/// Corresponds to [WebGPU `GPUCompilationInfo`](https://gpuweb.github.io/gpuweb/#gpucompilationinfo).
32/// The source locations use bytes, and index a UTF-8 encoded string.
33#[derive(Debug, Clone)]
34pub struct CompilationInfo {
35    /// The messages from the shader compilation process.
36    pub messages: Vec<CompilationMessage>,
37}
38
39/// A single message from the shader compilation process.
40///
41/// Roughly corresponds to [`GPUCompilationMessage`](https://www.w3.org/TR/webgpu/#gpucompilationmessage),
42/// except that the location uses UTF-8 for all positions.
43#[derive(Debug, Clone)]
44pub struct CompilationMessage {
45    /// The text of the message.
46    pub message: String,
47    /// The type of the message.
48    pub message_type: CompilationMessageType,
49    /// Where in the source code the message points at.
50    pub location: Option<SourceLocation>,
51}
52
53/// The type of a compilation message.
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum CompilationMessageType {
56    /// An error message.
57    Error,
58    /// A warning message.
59    Warning,
60    /// An informational message.
61    Info,
62}
63
64/// A human-readable representation for a span, tailored for text source.
65///
66/// Roughly corresponds to the positional members of [`GPUCompilationMessage`][gcm] from
67/// the WebGPU specification, except
68/// - `offset` and `length` are in bytes (UTF-8 code units), instead of UTF-16 code units.
69/// - `line_position` is in bytes (UTF-8 code units), and is usually not directly intended for humans.
70///
71/// [gcm]: https://www.w3.org/TR/webgpu/#gpucompilationmessage
72#[derive(Copy, Clone, Debug, PartialEq, Eq)]
73pub struct SourceLocation {
74    /// 1-based line number.
75    pub line_number: u32,
76    /// 1-based column in code units (in bytes) of the start of the span.
77    /// Remember to convert accordingly when displaying to the user.
78    pub line_position: u32,
79    /// 0-based Offset in code units (in bytes) of the start of the span.
80    pub offset: u32,
81    /// Length in code units (in bytes) of the span.
82    pub length: u32,
83}
84
85#[cfg(all(feature = "wgsl", wgpu_core))]
86impl From<crate::naga::error::ShaderError<crate::naga::front::wgsl::ParseError>>
87    for CompilationInfo
88{
89    fn from(value: crate::naga::error::ShaderError<crate::naga::front::wgsl::ParseError>) -> Self {
90        CompilationInfo {
91            messages: vec![CompilationMessage {
92                message: value.to_string(),
93                message_type: CompilationMessageType::Error,
94                location: value.inner.location(&value.source).map(Into::into),
95            }],
96        }
97    }
98}
99#[cfg(feature = "glsl")]
100impl From<naga::error::ShaderError<naga::front::glsl::ParseErrors>> for CompilationInfo {
101    fn from(value: naga::error::ShaderError<naga::front::glsl::ParseErrors>) -> Self {
102        let messages = value
103            .inner
104            .errors
105            .into_iter()
106            .map(|err| CompilationMessage {
107                message: err.to_string(),
108                message_type: CompilationMessageType::Error,
109                location: err.location(&value.source).map(Into::into),
110            })
111            .collect();
112        CompilationInfo { messages }
113    }
114}
115
116#[cfg(feature = "spirv")]
117impl From<naga::error::ShaderError<naga::front::spv::Error>> for CompilationInfo {
118    fn from(value: naga::error::ShaderError<naga::front::spv::Error>) -> Self {
119        CompilationInfo {
120            messages: vec![CompilationMessage {
121                message: value.to_string(),
122                message_type: CompilationMessageType::Error,
123                location: None,
124            }],
125        }
126    }
127}
128
129#[cfg(any(wgpu_core, naga))]
130impl
131    From<
132        crate::naga::error::ShaderError<crate::naga::WithSpan<crate::naga::valid::ValidationError>>,
133    > for CompilationInfo
134{
135    fn from(
136        value: crate::naga::error::ShaderError<
137            crate::naga::WithSpan<crate::naga::valid::ValidationError>,
138        >,
139    ) -> Self {
140        CompilationInfo {
141            messages: vec![CompilationMessage {
142                message: value.to_string(),
143                message_type: CompilationMessageType::Error,
144                location: value.inner.location(&value.source).map(Into::into),
145            }],
146        }
147    }
148}
149
150#[cfg(any(wgpu_core, naga))]
151impl From<crate::naga::SourceLocation> for SourceLocation {
152    fn from(value: crate::naga::SourceLocation) -> Self {
153        SourceLocation {
154            length: value.length,
155            offset: value.offset,
156            line_number: value.line_number,
157            line_position: value.line_position,
158        }
159    }
160}
161
162/// Source of a shader module.
163///
164/// The source will be parsed and validated.
165///
166/// Any necessary shader translation (e.g. from WGSL to SPIR-V or vice versa)
167/// will be done internally by wgpu.
168///
169/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
170/// only WGSL source code strings are accepted.
171#[cfg_attr(feature = "naga-ir", expect(clippy::large_enum_variant))]
172#[derive(Clone, Debug)]
173#[non_exhaustive]
174pub enum ShaderSource<'a> {
175    /// SPIR-V module represented as a slice of words.
176    ///
177    /// See also: [`util::make_spirv`], [`include_spirv`]
178    #[cfg(feature = "spirv")]
179    SpirV(Cow<'a, [u32]>),
180    /// GLSL module as a string slice.
181    ///
182    /// Note: GLSL is not yet fully supported and must be a specific ShaderStage.
183    #[cfg(feature = "glsl")]
184    Glsl {
185        /// The source code of the shader.
186        shader: Cow<'a, str>,
187        /// The shader stage that the shader targets. For example, `naga::ShaderStage::Vertex`
188        stage: naga::ShaderStage,
189        /// Defines to unlock configured shader features.
190        defines: naga::FastHashMap<String, String>,
191    },
192    /// WGSL module as a string slice.
193    #[cfg(feature = "wgsl")]
194    Wgsl(Cow<'a, str>),
195    /// Naga module.
196    #[cfg(feature = "naga-ir")]
197    Naga(Cow<'static, naga::Module>),
198    /// Dummy variant because `Naga` doesn't have a lifetime and without enough active features it
199    /// could be the last one active.
200    #[doc(hidden)]
201    Dummy(PhantomData<&'a ()>),
202}
203static_assertions::assert_impl_all!(ShaderSource<'_>: Send, Sync);
204
205/// Descriptor for use with [`Device::create_shader_module`].
206///
207/// Corresponds to [WebGPU `GPUShaderModuleDescriptor`](
208/// https://gpuweb.github.io/gpuweb/#dictdef-gpushadermoduledescriptor).
209#[derive(Clone, Debug)]
210pub struct ShaderModuleDescriptor<'a> {
211    /// Debug label of the shader module. This will show up in graphics debuggers for easy identification.
212    pub label: Label<'a>,
213    /// Source code for the shader.
214    pub source: ShaderSource<'a>,
215}
216static_assertions::assert_impl_all!(ShaderModuleDescriptor<'_>: Send, Sync);
217
218/// Descriptor for a shader module given by SPIR-V binary, for use with
219/// [`Device::create_shader_module_spirv`].
220///
221/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
222/// only WGSL source code strings are accepted.
223#[derive(Debug)]
224pub struct ShaderModuleDescriptorSpirV<'a> {
225    /// Debug label of the shader module. This will show up in graphics debuggers for easy identification.
226    pub label: Label<'a>,
227    /// Binary SPIR-V data, in 4-byte words.
228    pub source: Cow<'a, [u32]>,
229}
230static_assertions::assert_impl_all!(ShaderModuleDescriptorSpirV<'_>: Send, Sync);