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