use alloc::{string::String, vec::Vec};
use core::{future::Future, marker::PhantomData};
use crate::*;
#[derive(Debug, Clone)]
pub struct ShaderModule {
pub(crate) inner: dispatch::DispatchShaderModule,
}
#[cfg(send_sync)]
static_assertions::assert_impl_all!(ShaderModule: Send, Sync);
crate::cmp::impl_eq_ord_hash_proxy!(ShaderModule => .inner);
impl ShaderModule {
pub fn get_compilation_info(&self) -> impl Future<Output = CompilationInfo> + WasmNotSend {
self.inner.get_compilation_info()
}
#[cfg(custom)]
pub fn as_custom<T: custom::ShaderModuleInterface>(&self) -> Option<&T> {
self.inner.as_custom()
}
}
#[derive(Debug, Clone)]
pub struct CompilationInfo {
pub messages: Vec<CompilationMessage>,
}
#[derive(Debug, Clone)]
pub struct CompilationMessage {
pub message: String,
pub message_type: CompilationMessageType,
pub location: Option<SourceLocation>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompilationMessageType {
Error,
Warning,
Info,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SourceLocation {
pub line_number: u32,
pub line_position: u32,
pub offset: u32,
pub length: u32,
}
#[cfg(all(feature = "wgsl", wgpu_core))]
impl From<crate::naga::error::ShaderError<crate::naga::front::wgsl::ParseError>>
for CompilationInfo
{
fn from(value: crate::naga::error::ShaderError<crate::naga::front::wgsl::ParseError>) -> Self {
use alloc::{string::ToString, vec};
CompilationInfo {
messages: vec![CompilationMessage {
message: value.to_string(),
message_type: CompilationMessageType::Error,
location: value.inner.location(&value.source).map(Into::into),
}],
}
}
}
#[cfg(feature = "glsl")]
impl From<naga::error::ShaderError<naga::front::glsl::ParseErrors>> for CompilationInfo {
fn from(value: naga::error::ShaderError<naga::front::glsl::ParseErrors>) -> Self {
use alloc::string::ToString;
let messages = value
.inner
.errors
.into_iter()
.map(|err| CompilationMessage {
message: err.to_string(),
message_type: CompilationMessageType::Error,
location: err.location(&value.source).map(Into::into),
})
.collect();
CompilationInfo { messages }
}
}
#[cfg(feature = "spirv")]
impl From<naga::error::ShaderError<naga::front::spv::Error>> for CompilationInfo {
fn from(value: naga::error::ShaderError<naga::front::spv::Error>) -> Self {
use alloc::{string::ToString, vec};
CompilationInfo {
messages: vec![CompilationMessage {
message: value.to_string(),
message_type: CompilationMessageType::Error,
location: None,
}],
}
}
}
#[cfg(any(wgpu_core, naga))]
impl
From<
crate::naga::error::ShaderError<crate::naga::WithSpan<crate::naga::valid::ValidationError>>,
> for CompilationInfo
{
fn from(
value: crate::naga::error::ShaderError<
crate::naga::WithSpan<crate::naga::valid::ValidationError>,
>,
) -> Self {
use alloc::{string::ToString, vec};
CompilationInfo {
messages: vec![CompilationMessage {
message: value.to_string(),
message_type: CompilationMessageType::Error,
location: value.inner.location(&value.source).map(Into::into),
}],
}
}
}
#[cfg(any(wgpu_core, naga))]
impl From<crate::naga::SourceLocation> for SourceLocation {
fn from(value: crate::naga::SourceLocation) -> Self {
SourceLocation {
length: value.length,
offset: value.offset,
line_number: value.line_number,
line_position: value.line_position,
}
}
}
#[cfg_attr(feature = "naga-ir", expect(clippy::large_enum_variant))]
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum ShaderSource<'a> {
#[cfg(feature = "spirv")]
SpirV(alloc::borrow::Cow<'a, [u32]>),
#[cfg(feature = "glsl")]
Glsl {
shader: alloc::borrow::Cow<'a, str>,
stage: naga::ShaderStage,
defines: &'a [(&'a str, &'a str)],
},
#[cfg(feature = "wgsl")]
Wgsl(alloc::borrow::Cow<'a, str>),
#[cfg(feature = "naga-ir")]
Naga(alloc::borrow::Cow<'static, naga::Module>),
#[doc(hidden)]
Dummy(PhantomData<&'a ()>),
}
static_assertions::assert_impl_all!(ShaderSource<'_>: Send, Sync);
#[derive(Clone, Debug)]
pub struct ShaderModuleDescriptor<'a> {
pub label: Label<'a>,
pub source: ShaderSource<'a>,
}
static_assertions::assert_impl_all!(ShaderModuleDescriptor<'_>: Send, Sync);
pub type ShaderModuleDescriptorPassthrough<'a> =
wgt::CreateShaderModuleDescriptorPassthrough<'a, Label<'a>>;