mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
glsl-in: Add support for image declarations
This commit is contained in:
@@ -139,6 +139,8 @@ pub enum QualifierKey<'a> {
|
||||
String(Cow<'a, str>),
|
||||
/// Used for `std140` and `std430` layout qualifiers
|
||||
Layout,
|
||||
/// Used for image formats
|
||||
Format,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -146,6 +148,7 @@ pub enum QualifierValue {
|
||||
None,
|
||||
Uint(u32),
|
||||
Layout(StructLayout),
|
||||
Format(crate::StorageFormat),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
||||
@@ -285,24 +285,28 @@ impl<'source> ParsingContext<'source> {
|
||||
QualifierKey::Layout,
|
||||
QualifierValue::Layout(StructLayout::Std430),
|
||||
),
|
||||
_ => {
|
||||
let key = QualifierKey::String(name.into());
|
||||
let value = if self.bump_if(parser, TokenValue::Assign).is_some() {
|
||||
let (value, end_meta) = match self.parse_uint_constant(parser) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
parser.errors.push(e);
|
||||
(0, Span::default())
|
||||
}
|
||||
};
|
||||
token.meta.subsume(end_meta);
|
||||
|
||||
QualifierValue::Uint(value)
|
||||
word => {
|
||||
if let Some(format) = map_image_format(word) {
|
||||
(QualifierKey::Format, QualifierValue::Format(format))
|
||||
} else {
|
||||
QualifierValue::None
|
||||
};
|
||||
let key = QualifierKey::String(name.into());
|
||||
let value = if self.bump_if(parser, TokenValue::Assign).is_some() {
|
||||
let (value, end_meta) = match self.parse_uint_constant(parser) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
parser.errors.push(e);
|
||||
(0, Span::default())
|
||||
}
|
||||
};
|
||||
token.meta.subsume(end_meta);
|
||||
|
||||
(key, value)
|
||||
QualifierValue::Uint(value)
|
||||
} else {
|
||||
QualifierValue::None
|
||||
};
|
||||
|
||||
(key, value)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -326,3 +330,54 @@ impl<'source> ParsingContext<'source> {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn map_image_format(word: &str) -> Option<crate::StorageFormat> {
|
||||
let format = match word {
|
||||
// float-image-format-qualifier:
|
||||
"rgba32f" => crate::StorageFormat::Rgba32Float,
|
||||
"rgba16f" => crate::StorageFormat::Rgba16Float,
|
||||
"rg32f" => crate::StorageFormat::Rg32Float,
|
||||
"rg16f" => crate::StorageFormat::Rg16Float,
|
||||
"r11f_g11f_b10f" => crate::StorageFormat::Rg11b10Float,
|
||||
"r32f" => crate::StorageFormat::R32Float,
|
||||
"r16f" => crate::StorageFormat::R16Float,
|
||||
"rgba16" => crate::StorageFormat::Rgba16Float,
|
||||
"rgb10_a2" => crate::StorageFormat::Rgb10a2Unorm,
|
||||
"rgba8" => crate::StorageFormat::Rgba8Unorm,
|
||||
"rg16" => crate::StorageFormat::Rg16Float,
|
||||
"rg8" => crate::StorageFormat::Rg8Unorm,
|
||||
"r16" => crate::StorageFormat::R16Float,
|
||||
"r8" => crate::StorageFormat::R8Unorm,
|
||||
"rgba8_snorm" => crate::StorageFormat::Rgba8Snorm,
|
||||
"rg8_snorm" => crate::StorageFormat::Rg8Snorm,
|
||||
"r8_snorm" => crate::StorageFormat::R8Snorm,
|
||||
// int-image-format-qualifier:
|
||||
"rgba32i" => crate::StorageFormat::Rgba32Sint,
|
||||
"rgba16i" => crate::StorageFormat::Rgba16Sint,
|
||||
"rgba8i" => crate::StorageFormat::Rgba8Sint,
|
||||
"rg32i" => crate::StorageFormat::Rg32Sint,
|
||||
"rg16i" => crate::StorageFormat::Rg16Sint,
|
||||
"rg8i" => crate::StorageFormat::Rg8Sint,
|
||||
"r32i" => crate::StorageFormat::R32Sint,
|
||||
"r16i" => crate::StorageFormat::R16Sint,
|
||||
"r8i" => crate::StorageFormat::R8Sint,
|
||||
// uint-image-format-qualifier:
|
||||
"rgba32ui" => crate::StorageFormat::Rgba32Uint,
|
||||
"rgba16ui" => crate::StorageFormat::Rgba16Uint,
|
||||
"rgba8ui" => crate::StorageFormat::Rgba8Uint,
|
||||
"rg32ui" => crate::StorageFormat::Rg32Uint,
|
||||
"rg16ui" => crate::StorageFormat::Rg16Uint,
|
||||
"rg8ui" => crate::StorageFormat::Rg8Uint,
|
||||
"r32ui" => crate::StorageFormat::R32Uint,
|
||||
"r16ui" => crate::StorageFormat::R16Uint,
|
||||
"r8ui" => crate::StorageFormat::R8Uint,
|
||||
// TODO: These next ones seem incorrect to me
|
||||
// "rgba16_snorm" => crate::StorageFormat::Rgba16Float,
|
||||
// "rg16_snorm" => crate::StorageFormat::Rg16Float,
|
||||
// "r16_snorm" => crate::StorageFormat::R16Float,
|
||||
// "rgb10_a2ui" => crate::StorageFormat::Rgb10a2Unorm,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(format)
|
||||
}
|
||||
|
||||
@@ -150,9 +150,60 @@ pub fn parse_type(type_name: &str) -> Option<Type> {
|
||||
})
|
||||
};
|
||||
|
||||
let image_parse = |word: &str| {
|
||||
let mut iter = word.split("image");
|
||||
|
||||
let texture_kind = |ty| {
|
||||
Some(match ty {
|
||||
"" => ScalarKind::Float,
|
||||
"i" => ScalarKind::Sint,
|
||||
"u" => ScalarKind::Uint,
|
||||
_ => return None,
|
||||
})
|
||||
};
|
||||
|
||||
let kind = iter.next()?;
|
||||
let size = iter.next()?;
|
||||
let kind = texture_kind(kind)?;
|
||||
|
||||
let class = ImageClass::Storage {
|
||||
format: match kind {
|
||||
ScalarKind::Sint => crate::StorageFormat::Rgba32Sint,
|
||||
ScalarKind::Uint => crate::StorageFormat::Rgba32Uint,
|
||||
ScalarKind::Float => crate::StorageFormat::Rgba32Float,
|
||||
ScalarKind::Bool => unreachable!(),
|
||||
},
|
||||
access: crate::StorageAccess::all(),
|
||||
};
|
||||
|
||||
// TODO: glsl support multisampled storage images, naga doesn't
|
||||
let (dim, arrayed) = match size {
|
||||
"1D" => (ImageDimension::D1, false),
|
||||
"1DArray" => (ImageDimension::D1, true),
|
||||
"2D" => (ImageDimension::D2, false),
|
||||
"2DArray" => (ImageDimension::D2, true),
|
||||
"3D" => (ImageDimension::D3, false),
|
||||
// Naga doesn't support cube images and it's usefulness
|
||||
// is questionable, so they won't be supported for now
|
||||
// "Cube" => (ImageDimension::Cube, false),
|
||||
// "CubeArray" => (ImageDimension::Cube, true),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(Type {
|
||||
name: None,
|
||||
inner: TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
class,
|
||||
},
|
||||
})
|
||||
};
|
||||
|
||||
vec_parse(word)
|
||||
.or_else(|| mat_parse(word))
|
||||
.or_else(|| texture_parse(word))
|
||||
.or_else(|| image_parse(word))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,7 +393,7 @@ impl Parser {
|
||||
body: &mut Block,
|
||||
VarDeclaration {
|
||||
qualifiers,
|
||||
ty,
|
||||
mut ty,
|
||||
name,
|
||||
init,
|
||||
meta,
|
||||
@@ -469,17 +469,58 @@ impl Parser {
|
||||
access.remove(restricted_access);
|
||||
}
|
||||
}
|
||||
AddressSpace::Uniform => {
|
||||
if let TypeInner::Image { .. } | TypeInner::Sampler { .. } =
|
||||
self.module.types[ty].inner
|
||||
{
|
||||
AddressSpace::Uniform => match self.module.types[ty].inner {
|
||||
TypeInner::Image {
|
||||
class,
|
||||
dim,
|
||||
arrayed,
|
||||
} => {
|
||||
if let crate::ImageClass::Storage {
|
||||
mut access,
|
||||
mut format,
|
||||
} = class
|
||||
{
|
||||
if let Some((restricted_access, _)) =
|
||||
qualifiers.storage_acess.take()
|
||||
{
|
||||
access.remove(restricted_access);
|
||||
}
|
||||
|
||||
match qualifiers.layout_qualifiers.remove(&QualifierKey::Format) {
|
||||
Some((QualifierValue::Format(f), _)) => format = f,
|
||||
// TODO: glsl supports images without format qualifier
|
||||
// if they are `writeonly`
|
||||
None => self.errors.push(Error {
|
||||
kind: ErrorKind::SemanticError(
|
||||
"image types require a format layout qualifier".into(),
|
||||
),
|
||||
meta,
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
ty = self.module.types.insert(
|
||||
Type {
|
||||
name: None,
|
||||
inner: TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
class: crate::ImageClass::Storage { format, access },
|
||||
},
|
||||
},
|
||||
meta,
|
||||
);
|
||||
}
|
||||
|
||||
space = AddressSpace::Handle
|
||||
} else if qualifiers
|
||||
.none_layout_qualifier("push_constant", &mut self.errors)
|
||||
{
|
||||
space = AddressSpace::PushConstant
|
||||
}
|
||||
}
|
||||
TypeInner::Sampler { .. } => space = AddressSpace::Handle,
|
||||
_ => {
|
||||
if qualifiers.none_layout_qualifier("push_constant", &mut self.errors) {
|
||||
space = AddressSpace::PushConstant
|
||||
}
|
||||
}
|
||||
},
|
||||
AddressSpace::Function => space = AddressSpace::Private,
|
||||
_ => {}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user