Skip to content
This repository has been archived by the owner on Jan 29, 2025. It is now read-only.

Commit

Permalink
Validate image stores
Browse files Browse the repository at this point in the history
  • Loading branch information
kvark committed Mar 24, 2021
1 parent 69a0fbd commit a0b5717
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 45 deletions.
28 changes: 4 additions & 24 deletions src/valid/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub enum ExpressionError {
InvalidImageArrayIndexType(Handle<crate::Expression>),
#[error("Image other index type of {0:?} is not an integer scalar")]
InvalidImageOtherIndexType(Handle<crate::Expression>),
#[error("Image coordinate index type of {1:?} does not match dimension {0:?}")]
#[error("Image coordinate type of {1:?} does not match dimension {0:?}")]
InvalidImageCoordinateType(crate::ImageDimension, Handle<crate::Expression>),
#[error("Comparison sampling mismatch: image has class {image:?}, but the sampler is comparison={sampler}, and the reference was provided={has_ref}")]
ComparisonSamplingMismatch {
Expand Down Expand Up @@ -543,34 +543,14 @@ impl super::Validator {
arrayed,
dim,
} => {
match (dim, resolver.resolve(coordinate)?) {
(
crate::ImageDimension::D1,
&Ti::Scalar {
kind: crate::ScalarKind::Sint,
..
},
)
| (
crate::ImageDimension::D2,
&Ti::Vector {
kind: crate::ScalarKind::Sint,
..
},
)
| (
crate::ImageDimension::D3,
&Ti::Vector {
kind: crate::ScalarKind::Sint,
..
},
) => {}
match resolver.resolve(coordinate)?.image_storage_coordinates() {
Some(coord_dim) if coord_dim == dim => {}
_ => {
return Err(ExpressionError::InvalidImageCoordinateType(
dim, coordinate,
))
}
}
};
let needs_index = match class {
crate::ImageClass::Storage { .. } => false,
_ => true,
Expand Down
97 changes: 76 additions & 21 deletions src/valid/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,10 @@ pub enum FunctionError {
pointer: Handle<crate::Expression>,
value: Handle<crate::Expression>,
},
#[error("The image array can't be indexed by {0:?}")]
InvalidArrayIndex(Handle<crate::Expression>),
#[error("The expression {0:?} is currupted")]
InvalidExpression(Handle<crate::Expression>),
#[error("The expression {0:?} is not an image")]
InvalidImage(Handle<crate::Expression>),
#[error("Image store parameters are invalid")]
InvalidImageStore(#[source] ExpressionError),
#[error("Call to {function:?} is invalid")]
InvalidCall {
function: Handle<crate::Function>,
Expand Down Expand Up @@ -120,6 +118,7 @@ struct BlockContext<'a> {
info: &'a FunctionInfo,
expressions: &'a Arena<crate::Expression>,
types: &'a Arena<crate::Type>,
global_vars: &'a Arena<crate::GlobalVariable>,
functions: &'a Arena<crate::Function>,
return_type: Option<Handle<crate::Type>>,
}
Expand All @@ -131,6 +130,7 @@ impl<'a> BlockContext<'a> {
info,
expressions: &fun.expressions,
types: &module.types,
global_vars: &module.global_variables,
functions: &module.functions,
return_type: fun.result.as_ref().map(|fr| fr.ty),
}
Expand All @@ -142,6 +142,7 @@ impl<'a> BlockContext<'a> {
info: self.info,
expressions: self.expressions,
types: self.types,
global_vars: self.global_vars,
functions: self.functions,
return_type: self.return_type,
}
Expand Down Expand Up @@ -329,7 +330,7 @@ impl super::Validator {
let mut current = pointer;
loop {
let _ = context.resolve_type(current)?;
match context.expressions[current] {
match *context.get_expression(current)? {
crate::Expression::Access { base, .. }
| crate::Expression::AccessIndex { base, .. } => current = base,
crate::Expression::LocalVariable(_)
Expand Down Expand Up @@ -368,28 +369,82 @@ impl super::Validator {
}
S::ImageStore {
image,
coordinate: _,
coordinate,
array_index,
value,
} => {
let _expected_coordinate_ty = match *context.get_expression(image)? {
crate::Expression::GlobalVariable(_var_handle) => (), //TODO
_ => return Err(FunctionError::InvalidImage(image)),
};
match *context.resolve_type(value)? {
Ti::Scalar { .. } | Ti::Vector { .. } => {}
//Note: this code uses a lot of `FunctionError::InvalidImageStore`,
// and could probably be refactored.
let var = match *context.get_expression(image)? {
crate::Expression::GlobalVariable(var_handle) => {
&context.global_vars[var_handle]
}
_ => {
return Err(FunctionError::InvalidStoreValue(value));
return Err(FunctionError::InvalidImageStore(
ExpressionError::ExpectedGlobalVariable,
))
}
}
if let Some(expr) = array_index {
match *context.resolve_type(expr)? {
Ti::Scalar {
kind: crate::ScalarKind::Sint,
width: _,
} => (),
_ => return Err(FunctionError::InvalidArrayIndex(expr)),
};

let value_ty = match context.types[var.ty].inner {
Ti::Image {
class,
arrayed,
dim,
} => {
match context
.resolve_type(coordinate)?
.image_storage_coordinates()
{
Some(coord_dim) if coord_dim == dim => {}
_ => {
return Err(FunctionError::InvalidImageStore(
ExpressionError::InvalidImageCoordinateType(
dim, coordinate,
),
))
}
};
if arrayed != array_index.is_some() {
return Err(FunctionError::InvalidImageStore(
ExpressionError::InvalidImageArrayIndex,
));
}
if let Some(expr) = array_index {
match *context.resolve_type(expr)? {
Ti::Scalar {
kind: crate::ScalarKind::Sint,
width: _,
} => {}
_ => {
return Err(FunctionError::InvalidImageStore(
ExpressionError::InvalidImageArrayIndexType(expr),
))
}
}
}
match class {
crate::ImageClass::Storage(format) => crate::TypeInner::Vector {
kind: format.into(),
size: crate::VectorSize::Quad,
width: 4,
},
_ => {
return Err(FunctionError::InvalidImageStore(
ExpressionError::InvalidImageClass(class),
))
}
}
}
_ => {
return Err(FunctionError::InvalidImageStore(
ExpressionError::ExpectedImageType(var.ty),
))
}
};

if *context.resolve_type(value)? != value_ty {
return Err(FunctionError::InvalidStoreValue(value));
}
}
S::Call {
Expand Down
20 changes: 20 additions & 0 deletions src/valid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,26 @@ impl crate::TypeInner {
Self::Array { .. } | Self::Image { .. } | Self::Sampler { .. } => false,
}
}

fn image_storage_coordinates(&self) -> Option<crate::ImageDimension> {
match *self {
Self::Scalar {
kind: crate::ScalarKind::Sint,
..
} => Some(crate::ImageDimension::D1),
Self::Vector {
size: crate::VectorSize::Bi,
kind: crate::ScalarKind::Sint,
..
} => Some(crate::ImageDimension::D2),
Self::Vector {
size: crate::VectorSize::Tri,
kind: crate::ScalarKind::Sint,
..
} => Some(crate::ImageDimension::D3),
_ => None,
}
}
}

impl Validator {
Expand Down

0 comments on commit a0b5717

Please sign in to comment.