blob: 5e0d3cf77cddca687f5d791fc84774ee8ac6fe2b [file] [log] [blame] [edit]
// Copyright 2023 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
use super::{BindType, ShaderInfo};
use crate::types::msl::BindingIndex;
use naga::back::msl as naga_msl;
pub fn translate(shader: &ShaderInfo) -> Result<String, naga_msl::Error> {
let mut map = naga_msl::EntryPointResourceMap::default();
let mut idx_iter = BindingIndexIterator::default();
let mut binding_map = naga_msl::BindingMap::default();
for resource in &shader.bindings {
let binding = naga::ResourceBinding {
group: resource.location.0,
binding: resource.location.1,
};
let mut target = naga_msl::BindTarget::default();
match idx_iter.next(resource.ty) {
BindingIndex::Buffer(idx) => {
target.buffer = Some(idx);
}
BindingIndex::Texture(idx) => {
target.texture = Some(idx);
}
}
target.mutable = resource.ty.is_mutable();
binding_map.insert(binding, target);
}
map.insert(
"main".to_string(),
naga_msl::EntryPointResources {
resources: binding_map,
push_constant_buffer: None,
sizes_buffer: Some(30),
},
);
let options = naga_msl::Options {
lang_version: (2, 0),
per_entry_point_map: map,
inline_samplers: vec![],
spirv_cross_compatibility: false,
fake_missing_bindings: false,
bounds_check_policies: naga::proc::BoundsCheckPolicies::default(),
zero_initialize_workgroup_memory: true,
force_loop_bounding: true,
};
let (source, _) = naga_msl::write_string(
&shader.module,
&shader.module_info,
&options,
&naga_msl::PipelineOptions::default(),
)?;
Ok(source)
}
#[derive(Default)]
pub struct BindingIndexIterator {
buffer_idx: u8,
tex_idx: u8,
}
impl BindingIndexIterator {
pub fn next(&mut self, ty: BindType) -> BindingIndex {
match ty {
BindType::Buffer | BindType::BufReadOnly | BindType::Uniform => {
let idx = self.buffer_idx;
self.buffer_idx += 1;
assert!(self.buffer_idx > 0);
BindingIndex::Buffer(idx)
}
BindType::Image | BindType::ImageRead => {
let idx = self.tex_idx;
self.tex_idx += 1;
assert!(self.tex_idx > 0);
BindingIndex::Texture(idx)
}
}
}
}