From d06fefc463329a60f1da335f26bb094e34099588 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Fri, 14 Apr 2023 20:44:34 -0700 Subject: [PATCH 1/2] WIP add support for parsing Op::AtomicIAdd in spv frontend --- src/front/spv/mod.rs | 15 +++++++++++++++ tests/in/compute_atomics.spv | Bin 0 -> 840 bytes tests/spirv-frontend.rs | 17 +++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 tests/in/compute_atomics.spv create mode 100644 tests/spirv-frontend.rs diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index c69a230cb0..a773075a57 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -1315,6 +1315,21 @@ impl> Frontend { log::debug!("\t\t{:?} [{}]", inst.op, inst.wc); match inst.op { + Op::AtomicIAdd => { + inst.expect(7)?; + let type_id = self.next()?; + let id = self.next()?; + let pointer = self.next()?; + let memory = self.next()?; + let semantics = self.next()?; + let value = self.next()?; + + let pointer = self.lookup_expression.lookup(pointer)?.handle; + let expr = crate::Expression::Load { pointer }; + let handle = ctx.expressions.append(expr, span); + let expr = LookupExpression { handle, type_id, block_id }; + self.lookup_expression.insert(id, expr); + } Op::Line => { inst.expect(4)?; let _file_id = self.next()?; diff --git a/tests/in/compute_atomics.spv b/tests/in/compute_atomics.spv new file mode 100644 index 0000000000000000000000000000000000000000..33010a74827904281f1f802b42d5566584287cbd GIT binary patch literal 840 zcmYk4$xZ@M5JgL9L{S;US;0me7VeFSaY15&Tfe{<;=%>NMEolkewRPskeGN*(;X>t zyQW+9>eZuM>Q|$(5D|?yBd^8z9zfK?TAEuM>)93|uWXuHJ zjKz%8!cKvFF^q&?#0ogb{VIA97$4GM32m=iPSRHTGnM6+v5UO6@}Ez#TyGZ6&XapI z=X)FT#XR~&ev>I`_$g4@baU1obFHGa&vVWiwz2`IjxOR2YlA!pAWV7)RR=ACwdJ>0=HJ)M6KIQv~*x1YyQ@kY!Y`R2y$`ALTkTKS>UTo)Vy zXHdWAbt(3IUGZMlnbYqB>(sy8NZa^;f0r{K1MlI?_Hu6TcLL0Pux {} + Err(e) => { + panic!("{e:#?}"); + } + } +} From d3696f52c157545ba8982281dca494a1e0ed00d9 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 17 Apr 2023 11:45:39 -0700 Subject: [PATCH 2/2] more progress towards AtomicLoad --- src/front/spv/convert.rs | 20 +++++++++ src/front/spv/error.rs | 8 +++- src/front/spv/mod.rs | 76 ++++++++++++++++++++++++++++++----- tests/in/compute_atomics.spv | Bin 840 -> 832 bytes 4 files changed, 94 insertions(+), 10 deletions(-) diff --git a/src/front/spv/convert.rs b/src/front/spv/convert.rs index 2967555d2b..a297cf3c02 100644 --- a/src/front/spv/convert.rs +++ b/src/front/spv/convert.rs @@ -179,3 +179,23 @@ pub(super) fn map_storage_class(word: spirv::Word) -> Result return Err(Error::UnsupportedStorageClass(word)), }) } + +impl crate::AddressSpace { + pub(super) const fn try_from_spirv_semantics_and_scope( + semantics: spirv::MemorySemantics, + scope: spirv::Scope, + ) -> Result { + match (semantics, scope) { + (spirv::MemorySemantics::UNIFORM_MEMORY, spirv::Scope::Device) => { + Ok(crate::AddressSpace::Storage { access: crate::StorageAccess::all() }) + } + (spirv::MemorySemantics::WORKGROUP_MEMORY, spirv::Scope::Workgroup) => { + Ok(crate::AddressSpace::WorkGroup) + } + (spirv::MemorySemantics::NONE, spirv::Scope::Invocation) => { + Ok(crate::AddressSpace::Private) + } + _ => Err(Error::UnsupportedMemoryScopeSemantics(scope, semantics)), + } + } +} diff --git a/src/front/spv/error.rs b/src/front/spv/error.rs index 6c9cf384f1..bd3d09817f 100644 --- a/src/front/spv/error.rs +++ b/src/front/spv/error.rs @@ -1,5 +1,5 @@ use super::ModuleState; -use crate::arena::Handle; +use crate::{arena::Handle, ScalarKind}; #[derive(Debug, thiserror::Error)] pub enum Error { @@ -50,6 +50,8 @@ pub enum Error { rows: u8, width: u8, }, + #[error("unsupported memory scope {0:?} and/or semantics {1:?}")] + UnsupportedMemoryScopeSemantics(spirv::Scope, spirv::MemorySemantics), #[error("unknown binary operator {0:?}")] UnknownBinaryOperator(spirv::Op), #[error("unknown relational function {0:?}")] @@ -92,6 +94,10 @@ pub enum Error { InvalidAsType(Handle), #[error("invalid vector type {0:?}")] InvalidVectorType(Handle), + #[error("invalid atomic pointer of type {0:?}")] + InvalidAtomicScalarKind( ScalarKind ), + #[error("invalid atomic pointer of type {0:?}")] + InvalidAtomicPointer( Handle ), #[error("inconsistent comparison sampling {0:?}")] InconsistentComparisonSampling(Handle), #[error("wrong function result type %{0}")] diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index a773075a57..0ab38c7a47 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -1315,19 +1315,43 @@ impl> Frontend { log::debug!("\t\t{:?} [{}]", inst.op, inst.wc); match inst.op { - Op::AtomicIAdd => { - inst.expect(7)?; + Op::AtomicLoad => { + // parse all the parameters + inst.expect(6)?; let type_id = self.next()?; let id = self.next()?; - let pointer = self.next()?; - let memory = self.next()?; + let pointer_id = self.next()?; + let scope = self.next()?; let semantics = self.next()?; - let value = self.next()?; - - let pointer = self.lookup_expression.lookup(pointer)?.handle; - let expr = crate::Expression::Load { pointer }; + // convert raw ids into spirv + let scope = spirv::Scope::from_u32(scope) + .ok_or_else(|| Error::InvalidBarrierScope(scope))?; + let semantics = spirv::MemorySemantics::from_bits(semantics) + .ok_or_else(|| Error::InvalidBarrierMemorySemantics(semantics))?; + // type check the pointer we are loading + let pointer_lexp = self.lookup_expression.lookup(pointer_id)?.clone(); + let pointer_handle = self.get_expr_handle( + pointer_id, + &pointer_lexp, + ctx, + &mut emitter, + &mut block, + body_idx, + ); + let (kind, width) = self.ensure_atomic_pointer(&pointer_lexp, ctx, span)?; + // convert scope and semantics into an address space... + let space = + crate::AddressSpace::try_from_spirv_semantics_and_scope(semantics, scope)?; + let atomic_type = crate::TypeInner::Atomic { kind, width }; + let expr = crate::Expression::Load { + pointer: pointer_handle, + }; let handle = ctx.expressions.append(expr, span); - let expr = LookupExpression { handle, type_id, block_id }; + let expr = LookupExpression { + handle, + type_id, + block_id, + }; self.lookup_expression.insert(id, expr); } Op::Line => { @@ -3578,6 +3602,40 @@ impl> Frontend { Ok(()) } + fn ensure_atomic_pointer( + &mut self, + pointer_lexp: &LookupExpression, + ctx: &mut BlockContext, + span: crate::Span, + ) -> Result<(crate::ScalarKind, u8), Error> { + let pointer_lookup = self.lookup_type.lookup(pointer_lexp.type_id)?; + let pointer_type = ctx + .type_arena + .get_handle(pointer_lookup.handle) + .map_err(|h| Error::UnsupportedType(pointer_lookup.handle))?; + match pointer_type.inner { + crate::TypeInner::Pointer { base, .. } => match ctx.type_arena[base].inner { + crate::TypeInner::Scalar { kind, width } => match kind { + crate::ScalarKind::Uint + | crate::ScalarKind::Sint + | crate::ScalarKind::Float => Ok((kind, width)), + _ => { + log::error!("Pointer type to {:?} passed to atomic op", kind); + Err(Error::InvalidAtomicScalarKind(kind)) + } + }, + ref other => { + log::error!("Pointer type to {:?} passed to atomic op", other); + Err(Error::InvalidAtomicPointer(pointer_lookup.handle)) + } + }, + ref other => { + log::error!("Type {:?} passed to atomic op", other); + Err(Error::InvalidAtomicPointer(pointer_lookup.handle)) + } + } + } + fn make_expression_storage( &mut self, globals: &Arena, diff --git a/tests/in/compute_atomics.spv b/tests/in/compute_atomics.spv index 33010a74827904281f1f802b42d5566584287cbd..607f056bdf96f6c33ef1db6adad28e944bd140fb 100644 GIT binary patch delta 56 zcmX@Xc7TnSnMs+Qft8Vgfq|bvZ6oh}uKM?ay I7G%~3008L*nE(I)