From a7cacab27671db53eae01229eab1ea0158b306d8 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Fri, 18 Jun 2021 09:14:19 -0700 Subject: [PATCH] [spv-out] Move Writer type to back/spv/mod.rs. The `impl` blocks for `Writer` and its associated types remain in spv/writer.rs. There should be no substantive code changes in this commit, only moving code around and adjusting `use` declarations to match. --- src/back/spv/mod.rs | 204 +++++++++++++++++++++++++++++++++++++-- src/back/spv/writer.rs | 212 ++++------------------------------------- 2 files changed, 210 insertions(+), 206 deletions(-) diff --git a/src/back/spv/mod.rs b/src/back/spv/mod.rs index e571c3ba1..c579f0546 100644 --- a/src/back/spv/mod.rs +++ b/src/back/spv/mod.rs @@ -7,18 +7,12 @@ mod layout; mod writer; pub use spirv::Capability; -pub use writer::{Error, Writer}; + +use crate::arena::Handle; use spirv::Word; - -bitflags::bitflags! { - pub struct WriterFlags: u32 { - /// Include debug labels for everything. - const DEBUG = 0x1; - /// Flip Y coordinate of `BuiltIn::Position` output. - const ADJUST_COORDINATE_SPACE = 0x2; - } -} +use std::ops; +use thiserror::Error; struct PhysicalLayout { magic_number: Word, @@ -51,6 +45,196 @@ struct Instruction { operands: Vec, } +const BITS_PER_BYTE: crate::Bytes = 8; + +#[derive(Clone, Debug, Error)] +pub enum Error { + #[error("target SPIRV-{0}.{1} is not supported")] + UnsupportedVersion(u8, u8), + #[error("one of the required capabilities {0:?} is missing")] + MissingCapabilities(Vec), + #[error("unimplemented {0}")] + FeatureNotImplemented(&'static str), + #[error("module is not validated properly: {0}")] + Validation(&'static str), +} + +#[derive(Default)] +struct IdGenerator(Word); + +impl IdGenerator { + fn next(&mut self) -> Word { + self.0 += 1; + self.0 + } +} + +struct Block { + label_id: Word, + body: Vec, + termination: Option, +} + +impl Block { + fn new(label_id: Word) -> Self { + Block { + label_id, + body: Vec::new(), + termination: None, + } + } +} + +struct LocalVariable { + id: Word, + instruction: Instruction, +} + +struct ResultMember { + id: Word, + type_id: Word, + built_in: Option, +} + +struct EntryPointContext { + argument_ids: Vec, + results: Vec, +} + +#[derive(Default)] +struct Function { + signature: Option, + parameters: Vec, + variables: crate::FastHashMap, LocalVariable>, + blocks: Vec, + entry_point_context: Option, +} + +#[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)] +enum LocalType { + Value { + vector_size: Option, + kind: crate::ScalarKind, + width: crate::Bytes, + pointer_class: Option, + }, + Matrix { + columns: crate::VectorSize, + rows: crate::VectorSize, + width: crate::Bytes, + }, + Pointer { + base: Handle, + class: spirv::StorageClass, + }, + Image { + dim: crate::ImageDimension, + arrayed: bool, + class: crate::ImageClass, + }, + SampledImage { + image_type_id: Word, + }, + Sampler, +} + +#[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)] +enum LookupType { + Handle(Handle), + Local(LocalType), +} + +impl From for LookupType { + fn from(local: LocalType) -> Self { + Self::Local(local) + } +} + +#[derive(Debug, PartialEq, Clone, Hash, Eq)] +struct LookupFunctionType { + parameter_type_ids: Vec, + return_type_id: Word, +} + +#[derive(Debug)] +enum Dimension { + Scalar, + Vector, + Matrix, +} + +#[derive(Default)] +struct CachedExpressions { + ids: Vec, +} +impl CachedExpressions { + fn reset(&mut self, length: usize) { + self.ids.clear(); + self.ids.resize(length, 0); + } +} +impl ops::Index> for CachedExpressions { + type Output = Word; + fn index(&self, h: Handle) -> &Word { + let id = &self.ids[h.index()]; + if *id == 0 { + unreachable!("Expression {:?} is not cached!", h); + } + id + } +} +impl ops::IndexMut> for CachedExpressions { + fn index_mut(&mut self, h: Handle) -> &mut Word { + let id = &mut self.ids[h.index()]; + if *id != 0 { + unreachable!("Expression {:?} is already cached!", h); + } + id + } +} + +struct GlobalVariable { + /// Actual ID of the variable. + id: Word, + /// For `StorageClass::Handle` variables, this ID is recorded in the function + /// prelude block (and reset before every function) as `OpLoad` of the variable. + /// It is then used for all the global ops, such as `OpImageSample`. + handle_id: Word, +} + +pub struct Writer { + physical_layout: PhysicalLayout, + logical_layout: LogicalLayout, + id_gen: IdGenerator, + capabilities: crate::FastHashSet, + forbidden_caps: Option<&'static [Capability]>, + debugs: Vec, + annotations: Vec, + flags: WriterFlags, + void_type: u32, + //TODO: convert most of these into vectors, addressable by handle indices + lookup_type: crate::FastHashMap, + lookup_function: crate::FastHashMap, Word>, + lookup_function_type: crate::FastHashMap, + lookup_function_call: crate::FastHashMap, Word>, + constant_ids: Vec, + cached_constants: crate::FastHashMap<(crate::ScalarValue, crate::Bytes), Word>, + global_variables: Vec, + cached: CachedExpressions, + gl450_ext_inst_id: Word, + // Just a temporary list of SPIR-V ids + temp_list: Vec, +} + +bitflags::bitflags! { + pub struct WriterFlags: u32 { + /// Include debug labels for everything. + const DEBUG = 0x1; + /// Flip Y coordinate of `BuiltIn::Position` output. + const ADJUST_COORDINATE_SPACE = 0x2; + } +} + #[derive(Debug, Clone)] pub struct Options { /// (Major, Minor) target version of the SPIR-V. diff --git a/src/back/spv/writer.rs b/src/back/spv/writer.rs index a6927d2d7..abcce32e2 100644 --- a/src/back/spv/writer.rs +++ b/src/back/spv/writer.rs @@ -1,6 +1,8 @@ use super::{ helpers::{contains_builtin, map_storage_class}, - Instruction, LogicalLayout, Options, PhysicalLayout, WriterFlags, + Block, CachedExpressions, Dimension, EntryPointContext, Error, Function, GlobalVariable, + IdGenerator, Instruction, LocalType, LocalVariable, LogicalLayout, LookupFunctionType, + LookupType, Options, PhysicalLayout, ResultMember, Writer, WriterFlags, BITS_PER_BYTE, }; use crate::{ arena::{Arena, Handle}, @@ -8,74 +10,26 @@ use crate::{ valid::{FunctionInfo, ModuleInfo}, }; use spirv::Word; -use std::{collections::hash_map::Entry, ops}; -use thiserror::Error; +use std::collections::hash_map::Entry; -const BITS_PER_BYTE: crate::Bytes = 8; - -#[derive(Clone, Debug, Error)] -pub enum Error { - #[error("target SPIRV-{0}.{1} is not supported")] - UnsupportedVersion(u8, u8), - #[error("one of the required capabilities {0:?} is missing")] - MissingCapabilities(Vec), - #[error("unimplemented {0}")] - FeatureNotImplemented(&'static str), - #[error("module is not validated properly: {0}")] - Validation(&'static str), -} - -#[derive(Default)] -struct IdGenerator(Word); - -impl IdGenerator { - fn next(&mut self) -> Word { - self.0 += 1; - self.0 +fn map_dim(dim: crate::ImageDimension) -> spirv::Dim { + match dim { + crate::ImageDimension::D1 => spirv::Dim::Dim1D, + crate::ImageDimension::D2 => spirv::Dim::Dim2D, + crate::ImageDimension::D3 => spirv::Dim::Dim3D, + crate::ImageDimension::Cube => spirv::Dim::DimCube, } } -struct Block { - label_id: Word, - body: Vec, - termination: Option, -} - -impl Block { - fn new(label_id: Word) -> Self { - Block { - label_id, - body: Vec::new(), - termination: None, - } +fn get_dimension(type_inner: &crate::TypeInner) -> Dimension { + match *type_inner { + crate::TypeInner::Scalar { .. } => Dimension::Scalar, + crate::TypeInner::Vector { .. } => Dimension::Vector, + crate::TypeInner::Matrix { .. } => Dimension::Matrix, + _ => unreachable!(), } } -struct LocalVariable { - id: Word, - instruction: Instruction, -} - -struct ResultMember { - id: Word, - type_id: Word, - built_in: Option, -} - -struct EntryPointContext { - argument_ids: Vec, - results: Vec, -} - -#[derive(Default)] -struct Function { - signature: Option, - parameters: Vec, - variables: crate::FastHashMap, LocalVariable>, - blocks: Vec, - entry_point_context: Option, -} - impl Function { fn to_words(&self, sink: &mut impl Extend) { self.signature.as_ref().unwrap().to_words(sink); @@ -102,34 +56,6 @@ impl Function { } } -#[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)] -enum LocalType { - Value { - vector_size: Option, - kind: crate::ScalarKind, - width: crate::Bytes, - pointer_class: Option, - }, - Matrix { - columns: crate::VectorSize, - rows: crate::VectorSize, - width: crate::Bytes, - }, - Pointer { - base: Handle, - class: spirv::StorageClass, - }, - Image { - dim: crate::ImageDimension, - arrayed: bool, - class: crate::ImageClass, - }, - SampledImage { - image_type_id: Word, - }, - Sampler, -} - impl PhysicalLayout { fn make_local(&self, inner: &crate::TypeInner) -> Option { Some(match *inner { @@ -184,118 +110,12 @@ impl PhysicalLayout { } } -#[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)] -enum LookupType { - Handle(Handle), - Local(LocalType), -} - -impl From for LookupType { - fn from(local: LocalType) -> Self { - Self::Local(local) - } -} - -fn map_dim(dim: crate::ImageDimension) -> spirv::Dim { - match dim { - crate::ImageDimension::D1 => spirv::Dim::Dim1D, - crate::ImageDimension::D2 => spirv::Dim::Dim2D, - crate::ImageDimension::D3 => spirv::Dim::Dim3D, - crate::ImageDimension::Cube => spirv::Dim::DimCube, - } -} - -#[derive(Debug, PartialEq, Clone, Hash, Eq)] -struct LookupFunctionType { - parameter_type_ids: Vec, - return_type_id: Word, -} - -#[derive(Debug)] -enum Dimension { - Scalar, - Vector, - Matrix, -} - -fn get_dimension(type_inner: &crate::TypeInner) -> Dimension { - match *type_inner { - crate::TypeInner::Scalar { .. } => Dimension::Scalar, - crate::TypeInner::Vector { .. } => Dimension::Vector, - crate::TypeInner::Matrix { .. } => Dimension::Matrix, - _ => unreachable!(), - } -} - #[derive(Clone, Copy, Default)] struct LoopContext { continuing_id: Option, break_id: Option, } -#[derive(Default)] -struct CachedExpressions { - ids: Vec, -} -impl CachedExpressions { - fn reset(&mut self, length: usize) { - self.ids.clear(); - self.ids.resize(length, 0); - } -} -impl ops::Index> for CachedExpressions { - type Output = Word; - fn index(&self, h: Handle) -> &Word { - let id = &self.ids[h.index()]; - if *id == 0 { - unreachable!("Expression {:?} is not cached!", h); - } - id - } -} -impl ops::IndexMut> for CachedExpressions { - fn index_mut(&mut self, h: Handle) -> &mut Word { - let id = &mut self.ids[h.index()]; - if *id != 0 { - unreachable!("Expression {:?} is already cached!", h); - } - id - } -} - -struct GlobalVariable { - /// Actual ID of the variable. - id: Word, - /// For `StorageClass::Handle` variables, this ID is recorded in the function - /// prelude block (and reset before every function) as `OpLoad` of the variable. - /// It is then used for all the global ops, such as `OpImageSample`. - handle_id: Word, -} - -pub struct Writer { - physical_layout: PhysicalLayout, - logical_layout: LogicalLayout, - id_gen: IdGenerator, - capabilities: crate::FastHashSet, - forbidden_caps: Option<&'static [spirv::Capability]>, - debugs: Vec, - annotations: Vec, - flags: WriterFlags, - void_type: u32, - //TODO: convert most of these into vectors, addressable by handle indices - lookup_type: crate::FastHashMap, - lookup_function: crate::FastHashMap, Word>, - lookup_function_type: crate::FastHashMap, - lookup_function_call: crate::FastHashMap, Word>, - constant_ids: Vec, - cached_constants: crate::FastHashMap<(crate::ScalarValue, crate::Bytes), Word>, - global_variables: Vec, - cached: CachedExpressions, - gl450_ext_inst_id: Word, - // Just a temporary list of SPIR-V ids - temp_list: Vec, -} - impl Writer { pub fn new(options: &Options) -> Result { let (major, minor) = options.lang_version;