[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.
This commit is contained in:
Jim Blandy 2021-06-18 09:14:19 -07:00 committed by Dzmitry Malyshau
parent 9146942412
commit a7cacab276
2 changed files with 210 additions and 206 deletions

View File

@ -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<Word>,
}
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<Capability>),
#[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<Instruction>,
termination: Option<Instruction>,
}
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<crate::BuiltIn>,
}
struct EntryPointContext {
argument_ids: Vec<Word>,
results: Vec<ResultMember>,
}
#[derive(Default)]
struct Function {
signature: Option<Instruction>,
parameters: Vec<Instruction>,
variables: crate::FastHashMap<Handle<crate::LocalVariable>, LocalVariable>,
blocks: Vec<Block>,
entry_point_context: Option<EntryPointContext>,
}
#[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)]
enum LocalType {
Value {
vector_size: Option<crate::VectorSize>,
kind: crate::ScalarKind,
width: crate::Bytes,
pointer_class: Option<spirv::StorageClass>,
},
Matrix {
columns: crate::VectorSize,
rows: crate::VectorSize,
width: crate::Bytes,
},
Pointer {
base: Handle<crate::Type>,
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<crate::Type>),
Local(LocalType),
}
impl From<LocalType> for LookupType {
fn from(local: LocalType) -> Self {
Self::Local(local)
}
}
#[derive(Debug, PartialEq, Clone, Hash, Eq)]
struct LookupFunctionType {
parameter_type_ids: Vec<Word>,
return_type_id: Word,
}
#[derive(Debug)]
enum Dimension {
Scalar,
Vector,
Matrix,
}
#[derive(Default)]
struct CachedExpressions {
ids: Vec<Word>,
}
impl CachedExpressions {
fn reset(&mut self, length: usize) {
self.ids.clear();
self.ids.resize(length, 0);
}
}
impl ops::Index<Handle<crate::Expression>> for CachedExpressions {
type Output = Word;
fn index(&self, h: Handle<crate::Expression>) -> &Word {
let id = &self.ids[h.index()];
if *id == 0 {
unreachable!("Expression {:?} is not cached!", h);
}
id
}
}
impl ops::IndexMut<Handle<crate::Expression>> for CachedExpressions {
fn index_mut(&mut self, h: Handle<crate::Expression>) -> &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<Capability>,
forbidden_caps: Option<&'static [Capability]>,
debugs: Vec<Instruction>,
annotations: Vec<Instruction>,
flags: WriterFlags,
void_type: u32,
//TODO: convert most of these into vectors, addressable by handle indices
lookup_type: crate::FastHashMap<LookupType, Word>,
lookup_function: crate::FastHashMap<Handle<crate::Function>, Word>,
lookup_function_type: crate::FastHashMap<LookupFunctionType, Word>,
lookup_function_call: crate::FastHashMap<Handle<crate::Expression>, Word>,
constant_ids: Vec<Word>,
cached_constants: crate::FastHashMap<(crate::ScalarValue, crate::Bytes), Word>,
global_variables: Vec<GlobalVariable>,
cached: CachedExpressions,
gl450_ext_inst_id: Word,
// Just a temporary list of SPIR-V ids
temp_list: Vec<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;
}
}
#[derive(Debug, Clone)]
pub struct Options {
/// (Major, Minor) target version of the SPIR-V.

View File

@ -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<spirv::Capability>),
#[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<Instruction>,
termination: Option<Instruction>,
}
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<crate::BuiltIn>,
}
struct EntryPointContext {
argument_ids: Vec<Word>,
results: Vec<ResultMember>,
}
#[derive(Default)]
struct Function {
signature: Option<Instruction>,
parameters: Vec<Instruction>,
variables: crate::FastHashMap<Handle<crate::LocalVariable>, LocalVariable>,
blocks: Vec<Block>,
entry_point_context: Option<EntryPointContext>,
}
impl Function {
fn to_words(&self, sink: &mut impl Extend<Word>) {
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<crate::VectorSize>,
kind: crate::ScalarKind,
width: crate::Bytes,
pointer_class: Option<spirv::StorageClass>,
},
Matrix {
columns: crate::VectorSize,
rows: crate::VectorSize,
width: crate::Bytes,
},
Pointer {
base: Handle<crate::Type>,
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<LocalType> {
Some(match *inner {
@ -184,118 +110,12 @@ impl PhysicalLayout {
}
}
#[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)]
enum LookupType {
Handle(Handle<crate::Type>),
Local(LocalType),
}
impl From<LocalType> 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<Word>,
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<Word>,
break_id: Option<Word>,
}
#[derive(Default)]
struct CachedExpressions {
ids: Vec<Word>,
}
impl CachedExpressions {
fn reset(&mut self, length: usize) {
self.ids.clear();
self.ids.resize(length, 0);
}
}
impl ops::Index<Handle<crate::Expression>> for CachedExpressions {
type Output = Word;
fn index(&self, h: Handle<crate::Expression>) -> &Word {
let id = &self.ids[h.index()];
if *id == 0 {
unreachable!("Expression {:?} is not cached!", h);
}
id
}
}
impl ops::IndexMut<Handle<crate::Expression>> for CachedExpressions {
fn index_mut(&mut self, h: Handle<crate::Expression>) -> &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<spirv::Capability>,
forbidden_caps: Option<&'static [spirv::Capability]>,
debugs: Vec<Instruction>,
annotations: Vec<Instruction>,
flags: WriterFlags,
void_type: u32,
//TODO: convert most of these into vectors, addressable by handle indices
lookup_type: crate::FastHashMap<LookupType, Word>,
lookup_function: crate::FastHashMap<Handle<crate::Function>, Word>,
lookup_function_type: crate::FastHashMap<LookupFunctionType, Word>,
lookup_function_call: crate::FastHashMap<Handle<crate::Expression>, Word>,
constant_ids: Vec<Word>,
cached_constants: crate::FastHashMap<(crate::ScalarValue, crate::Bytes), Word>,
global_variables: Vec<GlobalVariable>,
cached: CachedExpressions,
gl450_ext_inst_id: Word,
// Just a temporary list of SPIR-V ids
temp_list: Vec<Word>,
}
impl Writer {
pub fn new(options: &Options) -> Result<Self, Error> {
let (major, minor) = options.lang_version;