wgpu/api/
shader_module.rs

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