mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-30 10:45:06 +00:00
[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:
parent
9146942412
commit
a7cacab276
@ -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.
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user