mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Check that stores are permitted by the pointer's storage access.
Fixes #1533.
This commit is contained in:
committed by
Dzmitry Malyshau
parent
3d6cbcf8a6
commit
ce18eba695
@@ -184,6 +184,21 @@ impl super::TypeInner {
|
||||
}
|
||||
}
|
||||
|
||||
impl super::StorageClass {
|
||||
pub fn access(self) -> crate::StorageAccess {
|
||||
use crate::StorageAccess as Sa;
|
||||
match self {
|
||||
crate::StorageClass::Function
|
||||
| crate::StorageClass::Private
|
||||
| crate::StorageClass::WorkGroup => Sa::LOAD | Sa::STORE,
|
||||
crate::StorageClass::Uniform => Sa::LOAD,
|
||||
crate::StorageClass::Storage { access } => access,
|
||||
crate::StorageClass::Handle => Sa::LOAD,
|
||||
crate::StorageClass::PushConstant => Sa::LOAD,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl super::MathFunction {
|
||||
pub fn argument_count(&self) -> usize {
|
||||
match *self {
|
||||
|
||||
@@ -606,10 +606,12 @@ impl super::Validator {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let good = match *context
|
||||
|
||||
let pointer_ty = context
|
||||
.resolve_pointer_type(pointer)
|
||||
.map_err(|e| e.with_span())?
|
||||
{
|
||||
.map_err(|e| e.with_span())?;
|
||||
|
||||
let good = match *pointer_ty {
|
||||
Ti::Pointer { base, class: _ } => match context.types[base].inner {
|
||||
Ti::Atomic { kind, width } => *value_ty == Ti::Scalar { kind, width },
|
||||
ref other => value_ty == other,
|
||||
@@ -634,6 +636,16 @@ impl super::Validator {
|
||||
.with_handle(pointer, context.expressions)
|
||||
.with_handle(value, context.expressions));
|
||||
}
|
||||
|
||||
if let Some(class) = pointer_ty.pointer_class() {
|
||||
if !class.access().contains(crate::StorageAccess::STORE) {
|
||||
return Err(FunctionError::InvalidStorePointer(pointer)
|
||||
.with_span_static(
|
||||
context.expressions.get_span(pointer),
|
||||
"writing to this location is not permitted",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
S::ImageStore {
|
||||
image,
|
||||
|
||||
@@ -7,7 +7,7 @@ struct Globals {
|
||||
m: mat3x4<f32>;
|
||||
};
|
||||
|
||||
[[group(0), binding(0)]] var<storage> globals: Globals;
|
||||
[[group(0), binding(0)]] var<storage, read_write> globals: Globals;
|
||||
|
||||
fn index_array(i: i32) -> f32 {
|
||||
return globals.a[i];
|
||||
|
||||
@@ -14,7 +14,6 @@ OpMemberDecorate %9 1 Offset 48
|
||||
OpMemberDecorate %9 2 Offset 64
|
||||
OpMemberDecorate %9 2 ColMajor
|
||||
OpMemberDecorate %9 2 MatrixStride 16
|
||||
OpDecorate %10 NonWritable
|
||||
OpDecorate %10 DescriptorSet 0
|
||||
OpDecorate %10 Binding 0
|
||||
%2 = OpTypeVoid
|
||||
|
||||
@@ -1029,3 +1029,45 @@ fn missing_default_case() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_access_mode() {
|
||||
// The assignments to `global.i` should be forbidden, because they are in
|
||||
// variables whose access mode is `read`, not `read_write`.
|
||||
check_validation_error! {
|
||||
"
|
||||
[[block]]
|
||||
struct Globals {
|
||||
i: i32;
|
||||
};
|
||||
|
||||
[[group(0), binding(0)]]
|
||||
var<storage> globals: Globals;
|
||||
|
||||
fn store(v: i32) {
|
||||
globals.i = v;
|
||||
}
|
||||
",
|
||||
"
|
||||
[[block]]
|
||||
struct Globals {
|
||||
i: i32;
|
||||
};
|
||||
|
||||
[[group(0), binding(0)]]
|
||||
var<uniform> globals: Globals;
|
||||
|
||||
fn store(v: i32) {
|
||||
globals.i = v;
|
||||
}
|
||||
":
|
||||
Err(
|
||||
naga::valid::ValidationError::Function {
|
||||
name,
|
||||
error: naga::valid::FunctionError::InvalidStorePointer(_),
|
||||
..
|
||||
},
|
||||
)
|
||||
if name == "store"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user