mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[glsl-out] Reduce global import usage
This commit is contained in:
committed by
Dzmitry Malyshau
parent
a5874eb0cf
commit
7eeab393b2
@@ -44,14 +44,9 @@
|
||||
pub use features::Features;
|
||||
|
||||
use crate::{
|
||||
back::{FunctionCtx, FunctionType, COMPONENTS, INDENT},
|
||||
proc::{EntryPointIndex, NameKey, Namer, TypeResolution},
|
||||
valid::{FunctionInfo, ModuleInfo},
|
||||
ArraySize, BinaryOperator, Binding, BuiltIn, Bytes, ConservativeDepth, Constant, ConstantInner,
|
||||
DerivativeAxis, Expression, FastHashMap, Function, GlobalVariable, Handle, ImageClass,
|
||||
Interpolation, Module, RelationalFunction, Sampling, ScalarKind, ScalarValue, ShaderStage,
|
||||
Statement, StorageAccess, StorageClass, StorageFormat, StructMember, Type, TypeInner,
|
||||
UnaryOperator,
|
||||
back,
|
||||
proc::{self, NameKey},
|
||||
valid, Handle, ShaderStage, TypeInner,
|
||||
};
|
||||
use features::FeaturesManager;
|
||||
use std::{
|
||||
@@ -153,8 +148,8 @@ impl Default for Options {
|
||||
|
||||
/// Structure that contains a reflection info
|
||||
pub struct ReflectionInfo {
|
||||
pub texture_mapping: FastHashMap<String, TextureMapping>,
|
||||
pub uniforms: FastHashMap<Handle<GlobalVariable>, String>,
|
||||
pub texture_mapping: crate::FastHashMap<String, TextureMapping>,
|
||||
pub uniforms: crate::FastHashMap<Handle<crate::GlobalVariable>, String>,
|
||||
}
|
||||
|
||||
/// Structure that connects a texture to a sampler or not
|
||||
@@ -169,9 +164,9 @@ pub struct ReflectionInfo {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TextureMapping {
|
||||
/// Handle to the image global variable
|
||||
pub texture: Handle<GlobalVariable>,
|
||||
pub texture: Handle<crate::GlobalVariable>,
|
||||
/// Handle to the associated sampler global variable if it exists
|
||||
pub sampler: Option<Handle<GlobalVariable>>,
|
||||
pub sampler: Option<Handle<crate::GlobalVariable>>,
|
||||
}
|
||||
|
||||
/// Helper structure that generates a number
|
||||
@@ -196,14 +191,14 @@ impl IdGenerator {
|
||||
/// prefix identifying which pipeline stage the varying connects, and `X` is
|
||||
/// the location.
|
||||
struct VaryingName<'a> {
|
||||
binding: &'a Binding,
|
||||
binding: &'a crate::Binding,
|
||||
stage: ShaderStage,
|
||||
output: bool,
|
||||
}
|
||||
impl fmt::Display for VaryingName<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self.binding {
|
||||
Binding::Location { location, .. } => {
|
||||
crate::Binding::Location { location, .. } => {
|
||||
let prefix = match (self.stage, self.output) {
|
||||
(ShaderStage::Compute, _) => unreachable!(),
|
||||
// pipeline to vertex
|
||||
@@ -215,7 +210,7 @@ impl fmt::Display for VaryingName<'_> {
|
||||
};
|
||||
write!(f, "_{}_location{}", prefix, location,)
|
||||
}
|
||||
Binding::BuiltIn(built_in) => {
|
||||
crate::Binding::BuiltIn(built_in) => {
|
||||
write!(f, "{}", glsl_built_in(built_in, self.output))
|
||||
}
|
||||
}
|
||||
@@ -251,7 +246,7 @@ pub enum Error {
|
||||
UnsupportedExternal(String),
|
||||
/// A scalar with an unsupported width was requested
|
||||
#[error("A scalar with an unsupported width was requested: {0:?} {1:?}")]
|
||||
UnsupportedScalar(ScalarKind, Bytes),
|
||||
UnsupportedScalar(crate::ScalarKind, crate::Bytes),
|
||||
/// A image was used with multiple samplers, this isn't supported
|
||||
#[error("A image was used with multiple samplers")]
|
||||
ImageMultipleSamplers,
|
||||
@@ -263,9 +258,9 @@ pub enum Error {
|
||||
pub struct Writer<'a, W> {
|
||||
// Inputs
|
||||
/// The module being written
|
||||
module: &'a Module,
|
||||
module: &'a crate::Module,
|
||||
/// The module analysis.
|
||||
info: &'a ModuleInfo,
|
||||
info: &'a valid::ModuleInfo,
|
||||
/// The output writer
|
||||
out: W,
|
||||
/// User defined configuration to be used
|
||||
@@ -274,16 +269,16 @@ pub struct Writer<'a, W> {
|
||||
// Internal State
|
||||
/// Features manager used to store all the needed features and write them
|
||||
features: FeaturesManager,
|
||||
namer: Namer,
|
||||
namer: proc::Namer,
|
||||
/// A map with all the names needed for writing the module
|
||||
/// (generated by a [`Namer`](crate::proc::Namer))
|
||||
names: FastHashMap<NameKey, String>,
|
||||
names: crate::FastHashMap<NameKey, String>,
|
||||
/// A map with all the names needed for reflections
|
||||
reflection_names: FastHashMap<Handle<Type>, String>,
|
||||
reflection_names: crate::FastHashMap<Handle<crate::Type>, String>,
|
||||
/// The selected entry point
|
||||
entry_point: &'a crate::EntryPoint,
|
||||
/// The index of the selected entry point
|
||||
entry_point_idx: EntryPointIndex,
|
||||
entry_point_idx: proc::EntryPointIndex,
|
||||
/// Used to generate a unique number for blocks
|
||||
block_id: IdGenerator,
|
||||
/// Set of expressions that have associated temporary variables
|
||||
@@ -299,8 +294,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
/// - If the version specified doesn't support some used features
|
||||
pub fn new(
|
||||
out: W,
|
||||
module: &'a Module,
|
||||
info: &'a ModuleInfo,
|
||||
module: &'a crate::Module,
|
||||
info: &'a valid::ModuleInfo,
|
||||
options: &'a Options,
|
||||
) -> Result<Self, Error> {
|
||||
// Check if the requested version is supported
|
||||
@@ -317,8 +312,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
.ok_or(Error::EntryPointNotFound)?;
|
||||
|
||||
// Generate a map with names required to write the module
|
||||
let mut names = FastHashMap::default();
|
||||
let mut namer = Namer::default();
|
||||
let mut names = crate::FastHashMap::default();
|
||||
let mut namer = proc::Namer::default();
|
||||
namer.reset(module, keywords::RESERVED_KEYWORDS, &["gl_"], &mut names);
|
||||
|
||||
// Build the instance
|
||||
@@ -330,7 +325,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
namer,
|
||||
features: FeaturesManager::new(),
|
||||
names,
|
||||
reflection_names: FastHashMap::default(),
|
||||
reflection_names: crate::FastHashMap::default(),
|
||||
entry_point: &module.entry_points[ep_idx],
|
||||
entry_point_idx: ep_idx as u16,
|
||||
|
||||
@@ -390,13 +385,15 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
writeln!(self.out, "layout(early_fragment_tests) in;")?;
|
||||
|
||||
if let Some(conservative) = depth_test.conservative {
|
||||
use crate::ConservativeDepth as Cd;
|
||||
|
||||
writeln!(
|
||||
self.out,
|
||||
"layout (depth_{}) out float gl_FragDepth;",
|
||||
match conservative {
|
||||
ConservativeDepth::GreaterEqual => "greater",
|
||||
ConservativeDepth::LessEqual => "less",
|
||||
ConservativeDepth::Unchanged => "unchanged",
|
||||
Cd::GreaterEqual => "greater",
|
||||
Cd::LessEqual => "less",
|
||||
Cd::Unchanged => "unchanged",
|
||||
}
|
||||
)?;
|
||||
}
|
||||
@@ -444,7 +441,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
} => {
|
||||
// Write the storage format if needed
|
||||
if let TypeInner::Image {
|
||||
class: ImageClass::Storage(format),
|
||||
class: crate::ImageClass::Storage(format),
|
||||
..
|
||||
} = self.module.types[global.ty].inner
|
||||
{
|
||||
@@ -505,13 +502,18 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
let fun_info = &self.info[handle];
|
||||
|
||||
// Write the function
|
||||
self.write_function(FunctionType::Function(handle), function, fun_info, &name)?;
|
||||
self.write_function(
|
||||
back::FunctionType::Function(handle),
|
||||
function,
|
||||
fun_info,
|
||||
&name,
|
||||
)?;
|
||||
|
||||
writeln!(self.out)?;
|
||||
}
|
||||
|
||||
self.write_function(
|
||||
FunctionType::EntryPoint(self.entry_point_idx),
|
||||
back::FunctionType::EntryPoint(self.entry_point_idx),
|
||||
&self.entry_point.function,
|
||||
ep_info,
|
||||
"main",
|
||||
@@ -524,21 +526,23 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
self.collect_reflection_info()
|
||||
}
|
||||
|
||||
fn write_array_size(&mut self, size: ArraySize) -> BackendResult {
|
||||
fn write_array_size(&mut self, size: crate::ArraySize) -> BackendResult {
|
||||
write!(self.out, "[")?;
|
||||
|
||||
// Write the array size
|
||||
// Writes nothing if `ArraySize::Dynamic`
|
||||
// Panics if `ArraySize::Constant` has a constant that isn't an uint
|
||||
match size {
|
||||
ArraySize::Constant(const_handle) => match self.module.constants[const_handle].inner {
|
||||
ConstantInner::Scalar {
|
||||
width: _,
|
||||
value: ScalarValue::Uint(size),
|
||||
} => write!(self.out, "{}", size)?,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
ArraySize::Dynamic => (),
|
||||
crate::ArraySize::Constant(const_handle) => {
|
||||
match self.module.constants[const_handle].inner {
|
||||
crate::ConstantInner::Scalar {
|
||||
width: _,
|
||||
value: crate::ScalarValue::Uint(size),
|
||||
} => write!(self.out, "{}", size)?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
crate::ArraySize::Dynamic => (),
|
||||
}
|
||||
|
||||
write!(self.out, "]")?;
|
||||
@@ -589,7 +593,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
} => write!(
|
||||
self.out,
|
||||
"{}mat{}x{}",
|
||||
glsl_scalar(ScalarKind::Float, width)?.prefix,
|
||||
glsl_scalar(crate::ScalarKind::Float, width)?.prefix,
|
||||
columns as u8,
|
||||
rows as u8
|
||||
)?,
|
||||
@@ -619,7 +623,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
/// - If type is either a image or sampler
|
||||
/// - If it's an Array with a [`ArraySize::Constant`](crate::ArraySize::Constant) with a
|
||||
/// constant that isn't [`Uint`](crate::ConstantInner::Uint)
|
||||
fn write_type(&mut self, ty: Handle<Type>) -> BackendResult {
|
||||
fn write_type(&mut self, ty: Handle<crate::Type>) -> BackendResult {
|
||||
match self.module.types[ty].inner {
|
||||
// glsl has no pointer types so just write types as normal and loads are skipped
|
||||
TypeInner::Pointer { base, .. } => self.write_type(base),
|
||||
@@ -649,7 +653,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
&mut self,
|
||||
dim: crate::ImageDimension,
|
||||
arrayed: bool,
|
||||
class: ImageClass,
|
||||
class: crate::ImageClass,
|
||||
) -> BackendResult {
|
||||
// glsl images consist of four parts the scalar prefix, the image "type", the dimensions
|
||||
// and modifiers
|
||||
@@ -663,12 +667,13 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
// - MS - used if it's a multisampled image
|
||||
// - Array - used if it's an image array
|
||||
// - Shadow - used if it's a depth image
|
||||
use crate::ImageClass as Ic;
|
||||
|
||||
let (base, kind, ms, comparison) = match class {
|
||||
ImageClass::Sampled { kind, multi: true } => ("sampler", kind, "MS", ""),
|
||||
ImageClass::Sampled { kind, multi: false } => ("sampler", kind, "", ""),
|
||||
ImageClass::Depth => ("sampler", crate::ScalarKind::Float, "", "Shadow"),
|
||||
ImageClass::Storage(format) => ("image", format.into(), "", ""),
|
||||
Ic::Sampled { kind, multi: true } => ("sampler", kind, "MS", ""),
|
||||
Ic::Sampled { kind, multi: false } => ("sampler", kind, "", ""),
|
||||
Ic::Depth => ("sampler", crate::ScalarKind::Float, "", "Shadow"),
|
||||
Ic::Storage(format) => ("image", format.into(), "", ""),
|
||||
};
|
||||
|
||||
write!(
|
||||
@@ -694,8 +699,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
/// If the global has type sampler
|
||||
fn write_global(
|
||||
&mut self,
|
||||
handle: Handle<GlobalVariable>,
|
||||
global: &GlobalVariable,
|
||||
handle: Handle<crate::GlobalVariable>,
|
||||
global: &crate::GlobalVariable,
|
||||
) -> BackendResult {
|
||||
if let Some(storage_access) = glsl_storage_access(global.storage_access) {
|
||||
write!(self.out, "{} ", storage_access)?;
|
||||
@@ -737,7 +742,11 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
/// - Globals without bindings use the name from the [`Namer`](crate::proc::Namer)
|
||||
/// - Globals with resource binding are named `_group_X_binding_Y` where `X`
|
||||
/// is the group and `Y` is the binding
|
||||
fn get_global_name(&self, handle: Handle<GlobalVariable>, global: &GlobalVariable) -> String {
|
||||
fn get_global_name(
|
||||
&self,
|
||||
handle: Handle<crate::GlobalVariable>,
|
||||
global: &crate::GlobalVariable,
|
||||
) -> String {
|
||||
match global.binding {
|
||||
Some(ref br) => {
|
||||
format!("_group_{}_binding_{}", br.group, br.binding)
|
||||
@@ -749,8 +758,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
/// Writes the varying declaration.
|
||||
fn write_varying(
|
||||
&mut self,
|
||||
binding: Option<&Binding>,
|
||||
ty: Handle<Type>,
|
||||
binding: Option<&crate::Binding>,
|
||||
ty: Handle<crate::Type>,
|
||||
output: bool,
|
||||
) -> Result<(), Error> {
|
||||
match self.module.types[ty].inner {
|
||||
@@ -761,7 +770,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
}
|
||||
_ => {
|
||||
let (location, interpolation, sampling) = match binding {
|
||||
Some(&Binding::Location {
|
||||
Some(&crate::Binding::Location {
|
||||
location,
|
||||
interpolation,
|
||||
sampling,
|
||||
@@ -814,7 +823,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
// Finally write the global name and end the global with a `;` and a newline
|
||||
// Leading space is important
|
||||
let vname = VaryingName {
|
||||
binding: &Binding::Location {
|
||||
binding: &crate::Binding::Location {
|
||||
location,
|
||||
interpolation: None,
|
||||
sampling: None,
|
||||
@@ -834,13 +843,13 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
/// Adds a newline
|
||||
fn write_function(
|
||||
&mut self,
|
||||
ty: FunctionType,
|
||||
func: &Function,
|
||||
info: &FunctionInfo,
|
||||
ty: back::FunctionType,
|
||||
func: &crate::Function,
|
||||
info: &valid::FunctionInfo,
|
||||
name: &str,
|
||||
) -> BackendResult {
|
||||
// Create a function context for the function being written
|
||||
let ctx = FunctionCtx {
|
||||
let ctx = back::FunctionCtx {
|
||||
ty,
|
||||
info,
|
||||
expressions: &func.expressions,
|
||||
@@ -862,7 +871,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
// Start by writing the return type if any otherwise write void
|
||||
// This is the only place where `void` is a valid type
|
||||
// (though it's more a keyword than a type)
|
||||
if let FunctionType::EntryPoint(_) = ctx.ty {
|
||||
if let back::FunctionType::EntryPoint(_) = ctx.ty {
|
||||
write!(self.out, "void")?;
|
||||
} else if let Some(ref result) = func.result {
|
||||
self.write_type(result.ty)?;
|
||||
@@ -878,8 +887,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
// We need access to `Self` here so we use the reference passed to the closure as an
|
||||
// argument instead of capturing as that would cause a borrow checker error
|
||||
let arguments = match ctx.ty {
|
||||
FunctionType::EntryPoint(_) => &[][..],
|
||||
FunctionType::Function(_) => &func.arguments,
|
||||
back::FunctionType::EntryPoint(_) => &[][..],
|
||||
back::FunctionType::Function(_) => &func.arguments,
|
||||
};
|
||||
self.write_slice(arguments, |this, i, arg| {
|
||||
// Write the argument type
|
||||
@@ -897,10 +906,10 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
writeln!(self.out, ") {{")?;
|
||||
|
||||
// Compose the function arguments from globals, in case of an entry point.
|
||||
if let FunctionType::EntryPoint(ep_index) = ctx.ty {
|
||||
if let back::FunctionType::EntryPoint(ep_index) = ctx.ty {
|
||||
let stage = self.module.entry_points[ep_index as usize].stage;
|
||||
for (index, arg) in func.arguments.iter().enumerate() {
|
||||
write!(self.out, "{}", INDENT)?;
|
||||
write!(self.out, "{}", back::INDENT)?;
|
||||
self.write_type(arg.ty)?;
|
||||
let name = &self.names[&NameKey::EntryPointArgument(ep_index, index as u32)];
|
||||
write!(self.out, " {}", name)?;
|
||||
@@ -941,7 +950,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
for (handle, local) in func.local_variables.iter() {
|
||||
// Write indentation (only for readability) and the type
|
||||
// `write_type` adds no trailing space
|
||||
write!(self.out, "{}", INDENT)?;
|
||||
write!(self.out, "{}", back::INDENT)?;
|
||||
self.write_type(local.ty)?;
|
||||
|
||||
// Write the local name
|
||||
@@ -1009,28 +1018,30 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
///
|
||||
/// # Notes
|
||||
/// Adds no newlines or leading/trailing whitespace
|
||||
fn write_constant(&mut self, constant: &Constant) -> BackendResult {
|
||||
fn write_constant(&mut self, constant: &crate::Constant) -> BackendResult {
|
||||
use crate::ScalarValue as Sv;
|
||||
|
||||
match constant.inner {
|
||||
ConstantInner::Scalar {
|
||||
crate::ConstantInner::Scalar {
|
||||
width: _,
|
||||
ref value,
|
||||
} => match *value {
|
||||
// Signed integers don't need anything special
|
||||
ScalarValue::Sint(int) => write!(self.out, "{}", int)?,
|
||||
Sv::Sint(int) => write!(self.out, "{}", int)?,
|
||||
// Unsigned integers need a `u` at the end
|
||||
//
|
||||
// While `core` doesn't necessarily need it, it's allowed and since `es` needs it we
|
||||
// always write it as the extra branch wouldn't have any benefit in readability
|
||||
ScalarValue::Uint(int) => write!(self.out, "{}u", int)?,
|
||||
Sv::Uint(int) => write!(self.out, "{}u", int)?,
|
||||
// Floats are written using `Debug` instead of `Display` because it always appends the
|
||||
// decimal part even it's zero which is needed for a valid glsl float constant
|
||||
ScalarValue::Float(float) => write!(self.out, "{:?}", float)?,
|
||||
Sv::Float(float) => write!(self.out, "{:?}", float)?,
|
||||
// Booleans are either `true` or `false` so nothing special needs to be done
|
||||
ScalarValue::Bool(boolean) => write!(self.out, "{}", boolean)?,
|
||||
Sv::Bool(boolean) => write!(self.out, "{}", boolean)?,
|
||||
},
|
||||
// Composite constant are created using the same syntax as compose
|
||||
// `type(components)` where `components` is a comma separated list of constants
|
||||
ConstantInner::Composite { ty, ref components } => {
|
||||
crate::ConstantInner::Composite { ty, ref components } => {
|
||||
self.write_type(ty)?;
|
||||
write!(self.out, "(")?;
|
||||
|
||||
@@ -1053,8 +1064,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
fn write_struct(
|
||||
&mut self,
|
||||
block: bool,
|
||||
handle: Handle<Type>,
|
||||
members: &[StructMember],
|
||||
handle: Handle<crate::Type>,
|
||||
members: &[crate::StructMember],
|
||||
) -> BackendResult {
|
||||
// glsl structs are written as in C
|
||||
// `struct name() { members };`
|
||||
@@ -1080,7 +1091,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
|
||||
for (idx, member) in members.iter().enumerate() {
|
||||
// The indentation is only for readability
|
||||
write!(self.out, "{}", INDENT)?;
|
||||
write!(self.out, "{}", back::INDENT)?;
|
||||
|
||||
match self.module.types[member.ty].inner {
|
||||
TypeInner::Array {
|
||||
@@ -1142,10 +1153,13 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
/// Always adds a newline
|
||||
fn write_stmt(
|
||||
&mut self,
|
||||
sta: &Statement,
|
||||
ctx: &FunctionCtx<'_>,
|
||||
sta: &crate::Statement,
|
||||
ctx: &back::FunctionCtx<'_>,
|
||||
indent: usize,
|
||||
) -> BackendResult {
|
||||
use crate::Statement;
|
||||
use back::INDENT;
|
||||
|
||||
match *sta {
|
||||
// This is where we can generate intermediate constants for some expression types.
|
||||
Statement::Emit(ref range) => {
|
||||
@@ -1313,7 +1327,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
Statement::Return { value } => {
|
||||
write!(self.out, "{}", INDENT.repeat(indent))?;
|
||||
match ctx.ty {
|
||||
FunctionType::Function(_) => {
|
||||
back::FunctionType::Function(_) => {
|
||||
write!(self.out, "return")?;
|
||||
// Write the expression to be returned if needed
|
||||
if let Some(expr) = value {
|
||||
@@ -1322,14 +1336,16 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
}
|
||||
writeln!(self.out, ";")?;
|
||||
}
|
||||
FunctionType::EntryPoint(ep_index) => {
|
||||
back::FunctionType::EntryPoint(ep_index) => {
|
||||
let ep = &self.module.entry_points[ep_index as usize];
|
||||
if let Some(ref result) = ep.function.result {
|
||||
let value = value.unwrap();
|
||||
match self.module.types[result.ty].inner {
|
||||
crate::TypeInner::Struct { ref members, .. } => {
|
||||
let (mut is_temp_struct_used, mut return_struct) = (false, "");
|
||||
if let Expression::Compose { .. } = ctx.expressions[value] {
|
||||
if let crate::Expression::Compose { .. } =
|
||||
ctx.expressions[value]
|
||||
{
|
||||
is_temp_struct_used = true;
|
||||
return_struct = "_tmp_return";
|
||||
write!(
|
||||
@@ -1344,7 +1360,9 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
}
|
||||
for (index, member) in members.iter().enumerate() {
|
||||
// TODO: handle builtin in better way
|
||||
if let Some(Binding::BuiltIn(builtin)) = member.binding {
|
||||
if let Some(crate::Binding::BuiltIn(builtin)) =
|
||||
member.binding
|
||||
{
|
||||
match builtin {
|
||||
crate::BuiltIn::ClipDistance
|
||||
| crate::BuiltIn::CullDistance
|
||||
@@ -1461,7 +1479,13 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
///
|
||||
/// # Notes
|
||||
/// Doesn't add any newlines or leading/trailing spaces
|
||||
fn write_expr(&mut self, expr: Handle<Expression>, ctx: &FunctionCtx<'_>) -> BackendResult {
|
||||
fn write_expr(
|
||||
&mut self,
|
||||
expr: Handle<crate::Expression>,
|
||||
ctx: &back::FunctionCtx<'_>,
|
||||
) -> BackendResult {
|
||||
use crate::Expression;
|
||||
|
||||
if let Some(name) = self.named_expressions.get(&expr) {
|
||||
write!(self.out, "{}", name)?;
|
||||
return Ok(());
|
||||
@@ -1494,7 +1518,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
match *resolved {
|
||||
TypeInner::Vector { .. } => {
|
||||
// Write vector access as a swizzle
|
||||
write!(self.out, ".{}", COMPONENTS[index as usize])?
|
||||
write!(self.out, ".{}", back::COMPONENTS[index as usize])?
|
||||
}
|
||||
TypeInner::Matrix { .. }
|
||||
| TypeInner::Array { .. }
|
||||
@@ -1534,7 +1558,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
self.write_expr(vector, ctx)?;
|
||||
write!(self.out, ".")?;
|
||||
for &sc in pattern[..size as usize].iter() {
|
||||
self.out.write_char(COMPONENTS[sc as usize])?;
|
||||
self.out.write_char(back::COMPONENTS[sc as usize])?;
|
||||
}
|
||||
}
|
||||
// `Compose` is pretty simple we just write `type(components)` where `components` is a
|
||||
@@ -1695,10 +1719,10 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
};
|
||||
|
||||
let fun_name = match class {
|
||||
ImageClass::Sampled { .. } => "texelFetch",
|
||||
ImageClass::Storage(_) => "imageLoad",
|
||||
crate::ImageClass::Sampled { .. } => "texelFetch",
|
||||
crate::ImageClass::Storage(_) => "imageLoad",
|
||||
// TODO: Is there even a function for this?
|
||||
ImageClass::Depth => todo!(),
|
||||
crate::ImageClass::Depth => todo!(),
|
||||
};
|
||||
|
||||
write!(self.out, "{}(", fun_name)?;
|
||||
@@ -1717,6 +1741,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
// - textureQueryLevels
|
||||
// - textureSamples/imageSamples
|
||||
Expression::ImageQuery { image, query } => {
|
||||
use crate::ImageClass;
|
||||
|
||||
// This will only panic if the module is invalid
|
||||
let (dim, class) = match *ctx.info[image].ty.inner_with(&self.module.types) {
|
||||
TypeInner::Image {
|
||||
@@ -1764,7 +1790,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
};
|
||||
write!(self.out, "{}(", fun_name)?;
|
||||
self.write_expr(image, ctx)?;
|
||||
write!(self.out, ",0).{}", COMPONENTS[components])?;
|
||||
write!(self.out, ",0).{}", back::COMPONENTS[components])?;
|
||||
}
|
||||
crate::ImageQuery::NumSamples => {
|
||||
// assumes ARB_shader_texture_image_samples
|
||||
@@ -1786,31 +1812,23 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
//
|
||||
// We also wrap the everything in parentheses to avoid precedence issues
|
||||
Expression::Unary { op, expr } => {
|
||||
use crate::{ScalarKind as Sk, UnaryOperator as Uo};
|
||||
|
||||
write!(
|
||||
self.out,
|
||||
"({} ",
|
||||
match op {
|
||||
UnaryOperator::Negate => "-",
|
||||
UnaryOperator::Not =>
|
||||
match *ctx.info[expr].ty.inner_with(&self.module.types) {
|
||||
TypeInner::Scalar {
|
||||
kind: ScalarKind::Sint,
|
||||
..
|
||||
} => "~",
|
||||
TypeInner::Scalar {
|
||||
kind: ScalarKind::Uint,
|
||||
..
|
||||
} => "~",
|
||||
TypeInner::Scalar {
|
||||
kind: ScalarKind::Bool,
|
||||
..
|
||||
} => "!",
|
||||
ref other =>
|
||||
return Err(Error::Custom(format!(
|
||||
"Cannot apply not to type {:?}",
|
||||
other
|
||||
))),
|
||||
},
|
||||
Uo::Negate => "-",
|
||||
Uo::Not => match *ctx.info[expr].ty.inner_with(&self.module.types) {
|
||||
TypeInner::Scalar { kind: Sk::Sint, .. } => "~",
|
||||
TypeInner::Scalar { kind: Sk::Uint, .. } => "~",
|
||||
TypeInner::Scalar { kind: Sk::Bool, .. } => "!",
|
||||
ref other =>
|
||||
return Err(Error::Custom(format!(
|
||||
"Cannot apply not to type {:?}",
|
||||
other
|
||||
))),
|
||||
},
|
||||
}
|
||||
)?;
|
||||
|
||||
@@ -1825,17 +1843,19 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
Expression::Binary { op, left, right } => {
|
||||
// Holds `Some(function_name)` if the binary operation is
|
||||
// implemented as a function call
|
||||
use crate::BinaryOperator as Bo;
|
||||
|
||||
let function = if let (&TypeInner::Vector { .. }, &TypeInner::Vector { .. }) = (
|
||||
ctx.info[left].ty.inner_with(&self.module.types),
|
||||
ctx.info[right].ty.inner_with(&self.module.types),
|
||||
) {
|
||||
match op {
|
||||
BinaryOperator::Less => Some("lessThan"),
|
||||
BinaryOperator::LessEqual => Some("lessThanEqual"),
|
||||
BinaryOperator::Greater => Some("greaterThan"),
|
||||
BinaryOperator::GreaterEqual => Some("greaterThanEqual"),
|
||||
BinaryOperator::Equal => Some("equal"),
|
||||
BinaryOperator::NotEqual => Some("notEqual"),
|
||||
Bo::Less => Some("lessThan"),
|
||||
Bo::LessEqual => Some("lessThanEqual"),
|
||||
Bo::Greater => Some("greaterThan"),
|
||||
Bo::GreaterEqual => Some("greaterThanEqual"),
|
||||
Bo::Equal => Some("equal"),
|
||||
Bo::NotEqual => Some("notEqual"),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
@@ -1872,13 +1892,15 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
}
|
||||
// `Derivative` is a function call to a glsl provided function
|
||||
Expression::Derivative { axis, expr } => {
|
||||
use crate::DerivativeAxis as Da;
|
||||
|
||||
write!(
|
||||
self.out,
|
||||
"{}(",
|
||||
match axis {
|
||||
DerivativeAxis::X => "dFdx",
|
||||
DerivativeAxis::Y => "dFdy",
|
||||
DerivativeAxis::Width => "fwidth",
|
||||
Da::X => "dFdx",
|
||||
Da::Y => "dFdy",
|
||||
Da::Width => "fwidth",
|
||||
}
|
||||
)?;
|
||||
self.write_expr(expr, ctx)?;
|
||||
@@ -1886,15 +1908,17 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
}
|
||||
// `Relational` is a normal function call to some glsl provided functions
|
||||
Expression::Relational { fun, argument } => {
|
||||
use crate::RelationalFunction as Rf;
|
||||
|
||||
let fun_name = match fun {
|
||||
// There's no specific function for this but we can invert the result of `isinf`
|
||||
RelationalFunction::IsFinite => "!isinf",
|
||||
RelationalFunction::IsInf => "isinf",
|
||||
RelationalFunction::IsNan => "isnan",
|
||||
Rf::IsFinite => "!isinf",
|
||||
Rf::IsInf => "isinf",
|
||||
Rf::IsNan => "isnan",
|
||||
// There's also no function for this but we can invert `isnan`
|
||||
RelationalFunction::IsNormal => "!isnan",
|
||||
RelationalFunction::All => "all",
|
||||
RelationalFunction::Any => "any",
|
||||
Rf::IsNormal => "!isnan",
|
||||
Rf::All => "all",
|
||||
Rf::Any => "any",
|
||||
};
|
||||
write!(self.out, "{}(", fun_name)?;
|
||||
|
||||
@@ -2003,18 +2027,20 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
}
|
||||
}
|
||||
None => {
|
||||
use crate::ScalarKind as Sk;
|
||||
|
||||
let source_kind = inner.scalar_kind().unwrap();
|
||||
write!(
|
||||
self.out,
|
||||
"{}",
|
||||
match (source_kind, target_kind) {
|
||||
(ScalarKind::Float, ScalarKind::Sint) => "floatBitsToInt",
|
||||
(ScalarKind::Float, ScalarKind::Uint) => "floatBitsToUInt",
|
||||
(ScalarKind::Sint, ScalarKind::Float) => "intBitsToFloat",
|
||||
(ScalarKind::Uint, ScalarKind::Float) => "uintBitsToFloat",
|
||||
(Sk::Float, Sk::Sint) => "floatBitsToInt",
|
||||
(Sk::Float, Sk::Uint) => "floatBitsToUInt",
|
||||
(Sk::Sint, Sk::Float) => "intBitsToFloat",
|
||||
(Sk::Uint, Sk::Float) => "uintBitsToFloat",
|
||||
// There is no way to bitcast between Uint/Sint in glsl. Use constructor conversion
|
||||
(ScalarKind::Uint, ScalarKind::Sint) => "int",
|
||||
(ScalarKind::Sint, ScalarKind::Uint) => "uint",
|
||||
(Sk::Uint, Sk::Sint) => "int",
|
||||
(Sk::Sint, Sk::Uint) => "uint",
|
||||
_ => {
|
||||
return Err(Error::Custom(format!(
|
||||
"Cannot bitcast {:?} to {:?}",
|
||||
@@ -2044,18 +2070,20 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
|
||||
fn write_texture_coordinates(
|
||||
&mut self,
|
||||
coordinate: Handle<Expression>,
|
||||
array_index: Option<Handle<Expression>>,
|
||||
coordinate: Handle<crate::Expression>,
|
||||
array_index: Option<Handle<crate::Expression>>,
|
||||
dim: crate::ImageDimension,
|
||||
ctx: &FunctionCtx,
|
||||
ctx: &back::FunctionCtx,
|
||||
) -> Result<(), Error> {
|
||||
use crate::ImageDimension as IDim;
|
||||
|
||||
match array_index {
|
||||
Some(layer_expr) => {
|
||||
let tex_coord_type = match dim {
|
||||
crate::ImageDimension::D1 => "ivec2",
|
||||
crate::ImageDimension::D2 => "ivec3",
|
||||
crate::ImageDimension::D3 => "ivec4",
|
||||
crate::ImageDimension::Cube => "ivec4",
|
||||
IDim::D1 => "ivec2",
|
||||
IDim::D2 => "ivec3",
|
||||
IDim::D3 => "ivec4",
|
||||
IDim::Cube => "ivec4",
|
||||
};
|
||||
write!(self.out, "{}(", tex_coord_type)?;
|
||||
self.write_expr(coordinate, ctx)?;
|
||||
@@ -2072,12 +2100,12 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
|
||||
fn write_named_expr(
|
||||
&mut self,
|
||||
handle: Handle<Expression>,
|
||||
handle: Handle<crate::Expression>,
|
||||
name: String,
|
||||
ctx: &FunctionCtx,
|
||||
ctx: &back::FunctionCtx,
|
||||
) -> BackendResult {
|
||||
match ctx.info[handle].ty {
|
||||
TypeResolution::Handle(ty_handle) => match self.module.types[ty_handle].inner {
|
||||
proc::TypeResolution::Handle(ty_handle) => match self.module.types[ty_handle].inner {
|
||||
TypeInner::Struct { .. } => {
|
||||
let ty_name = &self.names[&NameKey::Type(ty_handle)];
|
||||
write!(self.out, "{}", ty_name)?;
|
||||
@@ -2086,7 +2114,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
self.write_type(ty_handle)?;
|
||||
}
|
||||
},
|
||||
TypeResolution::Value(ref inner) => {
|
||||
proc::TypeResolution::Value(ref inner) => {
|
||||
self.write_value_type(inner)?;
|
||||
}
|
||||
}
|
||||
@@ -2117,8 +2145,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
fn collect_reflection_info(&self) -> Result<ReflectionInfo, Error> {
|
||||
use std::collections::hash_map::Entry;
|
||||
let info = self.info.get_entry_point(self.entry_point_idx as usize);
|
||||
let mut mappings = FastHashMap::default();
|
||||
let mut uniforms = FastHashMap::default();
|
||||
let mut mappings = crate::FastHashMap::default();
|
||||
let mut uniforms = crate::FastHashMap::default();
|
||||
|
||||
for sampling in info.sampling_set.iter() {
|
||||
let global = self.module.global_variables[sampling.image].clone();
|
||||
@@ -2146,7 +2174,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
}
|
||||
match self.module.types[var.ty].inner {
|
||||
crate::TypeInner::Struct { .. } => match var.class {
|
||||
StorageClass::Uniform | StorageClass::Storage => {
|
||||
crate::StorageClass::Uniform | crate::StorageClass::Storage => {
|
||||
let name = self.reflection_names[&var.ty].clone();
|
||||
uniforms.insert(handle, name);
|
||||
}
|
||||
@@ -2179,17 +2207,22 @@ struct ScalarString<'a> {
|
||||
///
|
||||
/// # Errors
|
||||
/// If a [`Float`](crate::ScalarKind::Float) with an width that isn't 4 or 8
|
||||
fn glsl_scalar(kind: ScalarKind, width: Bytes) -> Result<ScalarString<'static>, Error> {
|
||||
fn glsl_scalar(
|
||||
kind: crate::ScalarKind,
|
||||
width: crate::Bytes,
|
||||
) -> Result<ScalarString<'static>, Error> {
|
||||
use crate::ScalarKind as Sk;
|
||||
|
||||
Ok(match kind {
|
||||
ScalarKind::Sint => ScalarString {
|
||||
Sk::Sint => ScalarString {
|
||||
prefix: "i",
|
||||
full: "int",
|
||||
},
|
||||
ScalarKind::Uint => ScalarString {
|
||||
Sk::Uint => ScalarString {
|
||||
prefix: "u",
|
||||
full: "uint",
|
||||
},
|
||||
ScalarKind::Float => match width {
|
||||
Sk::Float => match width {
|
||||
4 => ScalarString {
|
||||
prefix: "",
|
||||
full: "float",
|
||||
@@ -2200,7 +2233,7 @@ fn glsl_scalar(kind: ScalarKind, width: Bytes) -> Result<ScalarString<'static>,
|
||||
},
|
||||
_ => return Err(Error::UnsupportedScalar(kind, width)),
|
||||
},
|
||||
ScalarKind::Bool => ScalarString {
|
||||
Sk::Bool => ScalarString {
|
||||
prefix: "b",
|
||||
full: "bool",
|
||||
},
|
||||
@@ -2208,9 +2241,11 @@ fn glsl_scalar(kind: ScalarKind, width: Bytes) -> Result<ScalarString<'static>,
|
||||
}
|
||||
|
||||
/// Helper function that returns the glsl variable name for a builtin
|
||||
fn glsl_built_in(built_in: BuiltIn, output: bool) -> &'static str {
|
||||
fn glsl_built_in(built_in: crate::BuiltIn, output: bool) -> &'static str {
|
||||
use crate::BuiltIn as Bi;
|
||||
|
||||
match built_in {
|
||||
BuiltIn::Position => {
|
||||
Bi::Position => {
|
||||
if output {
|
||||
"gl_Position"
|
||||
} else {
|
||||
@@ -2218,18 +2253,18 @@ fn glsl_built_in(built_in: BuiltIn, output: bool) -> &'static str {
|
||||
}
|
||||
}
|
||||
// vertex
|
||||
BuiltIn::BaseInstance => "uint(gl_BaseInstance)",
|
||||
BuiltIn::BaseVertex => "uint(gl_BaseVertex)",
|
||||
BuiltIn::ClipDistance => "gl_ClipDistance",
|
||||
BuiltIn::CullDistance => "gl_CullDistance",
|
||||
BuiltIn::InstanceIndex => "uint(gl_InstanceID)",
|
||||
BuiltIn::PointSize => "gl_PointSize",
|
||||
BuiltIn::VertexIndex => "uint(gl_VertexID)",
|
||||
Bi::BaseInstance => "uint(gl_BaseInstance)",
|
||||
Bi::BaseVertex => "uint(gl_BaseVertex)",
|
||||
Bi::ClipDistance => "gl_ClipDistance",
|
||||
Bi::CullDistance => "gl_CullDistance",
|
||||
Bi::InstanceIndex => "uint(gl_InstanceID)",
|
||||
Bi::PointSize => "gl_PointSize",
|
||||
Bi::VertexIndex => "uint(gl_VertexID)",
|
||||
// fragment
|
||||
BuiltIn::FragDepth => "gl_FragDepth",
|
||||
BuiltIn::FrontFacing => "gl_FrontFacing",
|
||||
BuiltIn::SampleIndex => "gl_SampleID",
|
||||
BuiltIn::SampleMask => {
|
||||
Bi::FragDepth => "gl_FragDepth",
|
||||
Bi::FrontFacing => "gl_FrontFacing",
|
||||
Bi::SampleIndex => "gl_SampleID",
|
||||
Bi::SampleMask => {
|
||||
if output {
|
||||
"gl_SampleMask"
|
||||
} else {
|
||||
@@ -2237,90 +2272,100 @@ fn glsl_built_in(built_in: BuiltIn, output: bool) -> &'static str {
|
||||
}
|
||||
}
|
||||
// compute
|
||||
BuiltIn::GlobalInvocationId => "gl_GlobalInvocationID",
|
||||
BuiltIn::LocalInvocationId => "gl_LocalInvocationID",
|
||||
BuiltIn::LocalInvocationIndex => "gl_LocalInvocationIndex",
|
||||
BuiltIn::WorkGroupId => "gl_WorkGroupID",
|
||||
BuiltIn::WorkGroupSize => "gl_WorkGroupSize",
|
||||
Bi::GlobalInvocationId => "gl_GlobalInvocationID",
|
||||
Bi::LocalInvocationId => "gl_LocalInvocationID",
|
||||
Bi::LocalInvocationIndex => "gl_LocalInvocationIndex",
|
||||
Bi::WorkGroupId => "gl_WorkGroupID",
|
||||
Bi::WorkGroupSize => "gl_WorkGroupSize",
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function that returns the string corresponding to the storage class
|
||||
fn glsl_storage_class(class: StorageClass) -> Option<&'static str> {
|
||||
fn glsl_storage_class(class: crate::StorageClass) -> Option<&'static str> {
|
||||
use crate::StorageClass as Sc;
|
||||
|
||||
match class {
|
||||
StorageClass::Function => None,
|
||||
StorageClass::Private => None,
|
||||
StorageClass::Storage => Some("buffer"),
|
||||
StorageClass::Uniform => Some("uniform"),
|
||||
StorageClass::Handle => Some("uniform"),
|
||||
StorageClass::WorkGroup => Some("shared"),
|
||||
StorageClass::PushConstant => None,
|
||||
Sc::Function => None,
|
||||
Sc::Private => None,
|
||||
Sc::Storage => Some("buffer"),
|
||||
Sc::Uniform => Some("uniform"),
|
||||
Sc::Handle => Some("uniform"),
|
||||
Sc::WorkGroup => Some("shared"),
|
||||
Sc::PushConstant => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function that returns the string corresponding to the glsl interpolation qualifier
|
||||
fn glsl_interpolation(interpolation: Interpolation) -> &'static str {
|
||||
fn glsl_interpolation(interpolation: crate::Interpolation) -> &'static str {
|
||||
use crate::Interpolation as I;
|
||||
|
||||
match interpolation {
|
||||
Interpolation::Perspective => "smooth",
|
||||
Interpolation::Linear => "noperspective",
|
||||
Interpolation::Flat => "flat",
|
||||
I::Perspective => "smooth",
|
||||
I::Linear => "noperspective",
|
||||
I::Flat => "flat",
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the GLSL auxiliary qualifier for the given sampling value.
|
||||
fn glsl_sampling(sampling: Sampling) -> Option<&'static str> {
|
||||
fn glsl_sampling(sampling: crate::Sampling) -> Option<&'static str> {
|
||||
use crate::Sampling as S;
|
||||
|
||||
match sampling {
|
||||
Sampling::Center => None,
|
||||
Sampling::Centroid => Some("centroid"),
|
||||
Sampling::Sample => Some("sample"),
|
||||
S::Center => None,
|
||||
S::Centroid => Some("centroid"),
|
||||
S::Sample => Some("sample"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function that returns the glsl dimension string of [`ImageDimension`](crate::ImageDimension)
|
||||
fn glsl_dimension(dim: crate::ImageDimension) -> &'static str {
|
||||
use crate::ImageDimension as IDim;
|
||||
|
||||
match dim {
|
||||
crate::ImageDimension::D1 => "1D",
|
||||
crate::ImageDimension::D2 => "2D",
|
||||
crate::ImageDimension::D3 => "3D",
|
||||
crate::ImageDimension::Cube => "Cube",
|
||||
IDim::D1 => "1D",
|
||||
IDim::D2 => "2D",
|
||||
IDim::D3 => "3D",
|
||||
IDim::Cube => "Cube",
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function that returns the glsl storage format string of [`StorageFormat`](crate::StorageFormat)
|
||||
fn glsl_storage_format(format: StorageFormat) -> &'static str {
|
||||
fn glsl_storage_format(format: crate::StorageFormat) -> &'static str {
|
||||
use crate::StorageFormat as Sf;
|
||||
|
||||
match format {
|
||||
StorageFormat::R8Unorm => "r8",
|
||||
StorageFormat::R8Snorm => "r8_snorm",
|
||||
StorageFormat::R8Uint => "r8ui",
|
||||
StorageFormat::R8Sint => "r8i",
|
||||
StorageFormat::R16Uint => "r16ui",
|
||||
StorageFormat::R16Sint => "r16i",
|
||||
StorageFormat::R16Float => "r16f",
|
||||
StorageFormat::Rg8Unorm => "rg8",
|
||||
StorageFormat::Rg8Snorm => "rg8_snorm",
|
||||
StorageFormat::Rg8Uint => "rg8ui",
|
||||
StorageFormat::Rg8Sint => "rg8i",
|
||||
StorageFormat::R32Uint => "r32ui",
|
||||
StorageFormat::R32Sint => "r32i",
|
||||
StorageFormat::R32Float => "r32f",
|
||||
StorageFormat::Rg16Uint => "rg16ui",
|
||||
StorageFormat::Rg16Sint => "rg16i",
|
||||
StorageFormat::Rg16Float => "rg16f",
|
||||
StorageFormat::Rgba8Unorm => "rgba8ui",
|
||||
StorageFormat::Rgba8Snorm => "rgba8_snorm",
|
||||
StorageFormat::Rgba8Uint => "rgba8ui",
|
||||
StorageFormat::Rgba8Sint => "rgba8i",
|
||||
StorageFormat::Rgb10a2Unorm => "rgb10_a2ui",
|
||||
StorageFormat::Rg11b10Float => "r11f_g11f_b10f",
|
||||
StorageFormat::Rg32Uint => "rg32ui",
|
||||
StorageFormat::Rg32Sint => "rg32i",
|
||||
StorageFormat::Rg32Float => "rg32f",
|
||||
StorageFormat::Rgba16Uint => "rgba16ui",
|
||||
StorageFormat::Rgba16Sint => "rgba16i",
|
||||
StorageFormat::Rgba16Float => "rgba16f",
|
||||
StorageFormat::Rgba32Uint => "rgba32ui",
|
||||
StorageFormat::Rgba32Sint => "rgba32i",
|
||||
StorageFormat::Rgba32Float => "rgba32f",
|
||||
Sf::R8Unorm => "r8",
|
||||
Sf::R8Snorm => "r8_snorm",
|
||||
Sf::R8Uint => "r8ui",
|
||||
Sf::R8Sint => "r8i",
|
||||
Sf::R16Uint => "r16ui",
|
||||
Sf::R16Sint => "r16i",
|
||||
Sf::R16Float => "r16f",
|
||||
Sf::Rg8Unorm => "rg8",
|
||||
Sf::Rg8Snorm => "rg8_snorm",
|
||||
Sf::Rg8Uint => "rg8ui",
|
||||
Sf::Rg8Sint => "rg8i",
|
||||
Sf::R32Uint => "r32ui",
|
||||
Sf::R32Sint => "r32i",
|
||||
Sf::R32Float => "r32f",
|
||||
Sf::Rg16Uint => "rg16ui",
|
||||
Sf::Rg16Sint => "rg16i",
|
||||
Sf::Rg16Float => "rg16f",
|
||||
Sf::Rgba8Unorm => "rgba8ui",
|
||||
Sf::Rgba8Snorm => "rgba8_snorm",
|
||||
Sf::Rgba8Uint => "rgba8ui",
|
||||
Sf::Rgba8Sint => "rgba8i",
|
||||
Sf::Rgb10a2Unorm => "rgb10_a2ui",
|
||||
Sf::Rg11b10Float => "r11f_g11f_b10f",
|
||||
Sf::Rg32Uint => "rg32ui",
|
||||
Sf::Rg32Sint => "rg32i",
|
||||
Sf::Rg32Float => "rg32f",
|
||||
Sf::Rgba16Uint => "rgba16ui",
|
||||
Sf::Rgba16Sint => "rgba16i",
|
||||
Sf::Rgba16Float => "rgba16f",
|
||||
Sf::Rgba32Uint => "rgba32ui",
|
||||
Sf::Rgba32Sint => "rgba32i",
|
||||
Sf::Rgba32Float => "rgba32f",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2329,10 +2374,10 @@ fn glsl_storage_format(format: StorageFormat) -> &'static str {
|
||||
/// glsl allows adding both `readonly` and `writeonly` but this means that
|
||||
/// they can only be used to query information about the resource which isn't what
|
||||
/// we want here so when storage access is both `LOAD` and `STORE` add no modifiers
|
||||
fn glsl_storage_access(storage_access: StorageAccess) -> Option<&'static str> {
|
||||
if storage_access == StorageAccess::LOAD {
|
||||
fn glsl_storage_access(storage_access: crate::StorageAccess) -> Option<&'static str> {
|
||||
if storage_access == crate::StorageAccess::LOAD {
|
||||
Some("readonly")
|
||||
} else if storage_access == StorageAccess::STORE {
|
||||
} else if storage_access == crate::StorageAccess::STORE {
|
||||
Some("writeonly")
|
||||
} else {
|
||||
None
|
||||
@@ -2343,7 +2388,7 @@ fn glsl_storage_access(storage_access: StorageAccess) -> Option<&'static str> {
|
||||
fn zero_init_value_str(inner: &TypeInner) -> Option<String> {
|
||||
match *inner {
|
||||
TypeInner::Scalar { kind, .. } => match kind {
|
||||
ScalarKind::Bool => Some(String::from("false")),
|
||||
crate::ScalarKind::Bool => Some(String::from("false")),
|
||||
_ => Some(String::from("0")),
|
||||
},
|
||||
TypeInner::Vector { size, kind, width } => {
|
||||
|
||||
Reference in New Issue
Block a user