[msl] write down inline samplers

This commit is contained in:
Dzmitry Malyshau
2021-04-07 01:38:22 -04:00
committed by Dzmitry Malyshau
parent dcbedd17d0
commit 9e09c792dc
3 changed files with 150 additions and 10 deletions

View File

@@ -195,7 +195,7 @@ impl Options {
}
impl ResolvedBinding {
fn _as_inline_sampler<'a>(&self, options: &'a Options) -> Option<&'a sampler::InlineSampler> {
fn as_inline_sampler<'a>(&self, options: &'a Options) -> Option<&'a sampler::InlineSampler> {
match *self {
Self::Resource(BindTarget {
sampler: Some(BindSamplerTarget::Inline(handle)),

View File

@@ -1,4 +1,4 @@
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Coord {
Normalized,
Pixel,
@@ -10,7 +10,7 @@ impl Default for Coord {
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Address {
Repeat,
MirroredRepeat,
@@ -25,7 +25,19 @@ impl Default for Address {
}
}
#[derive(Clone, Debug, PartialEq)]
impl Address {
pub fn as_str(&self) -> &'static str {
match *self {
Self::Repeat => "repeat",
Self::MirroredRepeat => "mirrored_repeat",
Self::ClampToEdge => "clamp_to_edge",
Self::ClampToZero => "clamp_to_zero",
Self::ClampToBorder => "clamp_to_border",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BorderColor {
TransparentBlack,
OpaqueBlack,
@@ -38,19 +50,38 @@ impl Default for BorderColor {
}
}
#[derive(Clone, Debug, PartialEq)]
impl BorderColor {
pub fn as_str(&self) -> &'static str {
match *self {
Self::TransparentBlack => "transparent_black",
Self::OpaqueBlack => "opaque_black",
Self::OpaqueWhite => "opaque_white",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Filter {
Nearest,
Linear,
}
impl Filter {
pub fn as_str(&self) -> &'static str {
match *self {
Self::Nearest => "nearest",
Self::Linear => "linear",
}
}
}
impl Default for Filter {
fn default() -> Self {
Self::Nearest
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CompareFunc {
Never,
Less,
@@ -68,6 +99,21 @@ impl Default for CompareFunc {
}
}
impl CompareFunc {
pub fn as_str(&self) -> &'static str {
match *self {
Self::Never => "never",
Self::Less => "less",
Self::LessEqual => "less_equal",
Self::Greater => "greater",
Self::GreaterEqual => "greater_equal",
Self::Equal => "equal",
Self::NotEqual => "not_equal",
Self::Always => "always",
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct InlineSampler {
pub coord: Coord,

View File

@@ -1,4 +1,6 @@
use super::{keywords::RESERVED, Error, LocationMode, Options, SubOptions, TranslationInfo};
use super::{
keywords::RESERVED, sampler as sm, Error, LocationMode, Options, SubOptions, TranslationInfo,
};
use crate::{
arena::Handle,
proc::{EntryPointIndex, NameKey, Namer, TypeResolution},
@@ -163,6 +165,7 @@ struct StatementContext<'a> {
expression: ExpressionContext<'a>,
mod_info: &'a ModuleInfo,
result_struct: Option<&'a str>,
inline_global_handles: &'a BitSet,
}
impl<W: Write> Writer<W> {
@@ -1043,7 +1046,10 @@ impl<W: Write> Writer<W> {
let mut separate = !arguments.is_empty();
let fun_info = &context.mod_info[function];
for (handle, var) in context.expression.module.global_variables.iter() {
if !fun_info[handle].is_empty() && var.class.needs_pass_through() {
if !fun_info[handle].is_empty()
&& !context.inline_global_handles.contains(handle.index())
&& var.class.needs_pass_through()
{
let name = &self.names[&NameKey::GlobalVariable(handle)];
if separate {
write!(self.out, ", ")?;
@@ -1316,6 +1322,63 @@ impl<W: Write> Writer<W> {
Ok(())
}
fn write_inline_sampler(
&mut self,
sampler: &sm::InlineSampler,
stage: crate::ShaderStage,
handle: Handle<crate::GlobalVariable>,
) -> Result<(), Error> {
write!(
self.out,
"constexpr sampler ism_{}_{:?}(",
handle.index(),
stage
)?;
for (&letter, address) in ['s', 't', 'r'].iter().zip(sampler.address.iter()) {
write!(
self.out,
"{}{}_address::{},",
INDENT,
letter,
address.as_str()
)?;
}
write!(
self.out,
"{}mag_filter::{},",
INDENT,
sampler.mag_filter.as_str()
)?;
write!(
self.out,
"{}min_filter::{},",
INDENT,
sampler.min_filter.as_str()
)?;
if let Some(filter) = sampler.mip_filter {
write!(self.out, "{}mip_filter::{},", INDENT, filter.as_str())?;
}
// avoid setting it on platforms that don't support it
if sampler.border_color != sm::BorderColor::TransparentBlack {
write!(
self.out,
"{}border_color::{},",
INDENT,
sampler.border_color.as_str()
)?;
}
if sampler.compare_func != sm::CompareFunc::Never {
write!(
self.out,
"{}compare_func::{},",
INDENT,
sampler.compare_func.as_str()
)?;
}
writeln!(self.out, "{}coord::normalized);", INDENT)?;
Ok(())
}
// Returns the array of mapped entry point names.
fn write_functions(
&mut self,
@@ -1324,12 +1387,38 @@ impl<W: Write> Writer<W> {
options: &Options,
sub_options: &SubOptions,
) -> Result<TranslationInfo, Error> {
// first, write down immutable samplers as const expressions
let mut inline_global_handles = BitSet::new();
for (handle, var) in module.global_variables.iter() {
let binding = match var.binding {
Some(ref binding) => binding,
None => continue,
};
for &stage in [
crate::ShaderStage::Vertex,
crate::ShaderStage::Fragment,
crate::ShaderStage::Compute,
]
.iter()
{
if let Ok(resolved) = options.resolve_global_binding(stage, binding) {
if let Some(sampler) = resolved.as_inline_sampler(options) {
inline_global_handles.insert(handle.index());
self.write_inline_sampler(sampler, stage, handle)?;
}
}
}
}
let mut pass_through_globals = Vec::new();
for (fun_handle, fun) in module.functions.iter() {
let fun_info = &mod_info[fun_handle];
pass_through_globals.clear();
for (handle, var) in module.global_variables.iter() {
if !fun_info[handle].is_empty() && var.class.needs_pass_through() {
if !fun_info[handle].is_empty()
&& !inline_global_handles.contains(handle.index())
&& var.class.needs_pass_through()
{
pass_through_globals.push(handle);
}
}
@@ -1388,6 +1477,7 @@ impl<W: Write> Writer<W> {
},
mod_info,
result_struct: None,
inline_global_handles: &inline_global_handles,
};
self.named_expressions.clear();
self.put_block(Level(1), &fun.body, &context)?;
@@ -1558,7 +1648,10 @@ impl<W: Write> Writer<W> {
}
for (handle, var) in module.global_variables.iter() {
let usage = fun_info[handle];
if usage.is_empty() || var.class == crate::StorageClass::Private {
if usage.is_empty()
|| var.class == crate::StorageClass::Private
|| inline_global_handles.contains(handle.index())
{
continue;
}
let tyvar = TypedGlobalVariable {
@@ -1676,6 +1769,7 @@ impl<W: Write> Writer<W> {
},
mod_info,
result_struct: Some(&stage_out_name),
inline_global_handles: &inline_global_handles,
};
self.named_expressions.clear();
self.put_block(Level(1), &fun.body, &context)?;