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