mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
msl: inject point size if needed
This commit is contained in:
committed by
Dzmitry Malyshau
parent
a1840beb1a
commit
76814a83a2
@@ -196,7 +196,7 @@ impl Default for Options {
|
||||
}
|
||||
|
||||
// A subset of options that are meant to be changed per pipeline.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
|
||||
pub struct PipelineOptions {
|
||||
@@ -205,14 +205,6 @@ pub struct PipelineOptions {
|
||||
pub allow_point_size: bool,
|
||||
}
|
||||
|
||||
impl Default for PipelineOptions {
|
||||
fn default() -> Self {
|
||||
PipelineOptions {
|
||||
allow_point_size: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Options {
|
||||
fn resolve_local_binding(
|
||||
&self,
|
||||
|
||||
@@ -46,10 +46,7 @@ impl<'a> Display for TypeContext<'a> {
|
||||
match kind {
|
||||
// work around Metal toolchain bug with `uint` typedef
|
||||
crate::ScalarKind::Uint => write!(out, "{}::uint", NAMESPACE),
|
||||
_ => {
|
||||
let kind_str = kind.to_msl_name();
|
||||
write!(out, "{}", kind_str)
|
||||
}
|
||||
_ => write!(out, "{}", kind.to_msl_name()),
|
||||
}
|
||||
}
|
||||
crate::TypeInner::Atomic { kind, .. } => {
|
||||
@@ -96,7 +93,11 @@ impl<'a> Display for TypeContext<'a> {
|
||||
Some(name) => name,
|
||||
None => return Ok(()),
|
||||
};
|
||||
write!(out, "{} {}&", class_name, kind.to_msl_name(),)
|
||||
write!(out, "{} ", class_name)?;
|
||||
if kind == crate::ScalarKind::Uint {
|
||||
write!(out, "{}::", NAMESPACE)?;
|
||||
}
|
||||
write!(out, "{}&", kind.to_msl_name())
|
||||
}
|
||||
crate::TypeInner::ValuePointer {
|
||||
size: Some(size),
|
||||
@@ -1708,20 +1709,25 @@ impl<W: Write> Writer<W> {
|
||||
self.put_expression(expr_handle, context, true)?;
|
||||
writeln!(self.out, ";")?;
|
||||
write!(self.out, "{}return {} {{", level, struct_name)?;
|
||||
|
||||
let mut is_first = true;
|
||||
let mut has_point_size = false;
|
||||
|
||||
for (index, member) in members.iter().enumerate() {
|
||||
if !context.pipeline_options.allow_point_size
|
||||
&& member.binding
|
||||
== Some(crate::Binding::BuiltIn(crate::BuiltIn::PointSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if member.binding
|
||||
== Some(crate::Binding::BuiltIn(crate::BuiltIn::CullDistance))
|
||||
{
|
||||
log::warn!("Ignoring CullDistance BuiltIn");
|
||||
continue;
|
||||
match member.binding {
|
||||
Some(crate::Binding::BuiltIn(crate::BuiltIn::PointSize)) => {
|
||||
has_point_size = true;
|
||||
if !context.pipeline_options.allow_point_size {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Some(crate::Binding::BuiltIn(crate::BuiltIn::CullDistance)) => {
|
||||
log::warn!("Ignoring CullDistance built-in");
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let comma = if is_first { "" } else { "," };
|
||||
is_first = false;
|
||||
let name = &self.names[&NameKey::StructMember(result_ty, index as u32)];
|
||||
@@ -1752,6 +1758,17 @@ impl<W: Write> Writer<W> {
|
||||
write!(self.out, "{} {}.{}", comma, tmp, name)?;
|
||||
}
|
||||
}
|
||||
|
||||
if let FunctionOrigin::EntryPoint(ep_index) = context.origin {
|
||||
let stage = context.module.entry_points[ep_index as usize].stage;
|
||||
if context.pipeline_options.allow_point_size
|
||||
&& stage == crate::ShaderStage::Vertex
|
||||
&& !has_point_size
|
||||
{
|
||||
// point size was injected and comes last
|
||||
write!(self.out, ", 1.0")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
write!(self.out, "{}return {} {{ ", level, struct_name)?;
|
||||
@@ -2874,6 +2891,7 @@ impl<W: Write> Writer<W> {
|
||||
}
|
||||
|
||||
writeln!(self.out, "struct {} {{", stage_out_name)?;
|
||||
let mut has_point_size = false;
|
||||
for (name, ty, binding) in result_members {
|
||||
let ty_name = TypeContext {
|
||||
handle: ty,
|
||||
@@ -2883,19 +2901,27 @@ impl<W: Write> Writer<W> {
|
||||
first_time: true,
|
||||
};
|
||||
let binding = binding.ok_or(Error::Validation)?;
|
||||
// Cull Distance is not supported in Metal.
|
||||
// But we can't return UnsupportedBuiltIn error to user.
|
||||
// Because otherwise we can't generate msl shader from any glslang SPIR-V shaders.
|
||||
// glslang generates gl_PerVertex struct with gl_CullDistance builtin inside by default.
|
||||
if *binding == crate::Binding::BuiltIn(crate::BuiltIn::CullDistance) {
|
||||
log::warn!("Ignoring CullDistance BuiltIn");
|
||||
continue;
|
||||
}
|
||||
if !pipeline_options.allow_point_size
|
||||
&& *binding == crate::Binding::BuiltIn(crate::BuiltIn::PointSize)
|
||||
{
|
||||
continue;
|
||||
|
||||
match *binding {
|
||||
// Point size is only supported in VS of pipelines with
|
||||
// point primitive topology.
|
||||
crate::Binding::BuiltIn(crate::BuiltIn::PointSize) => {
|
||||
has_point_size = true;
|
||||
if !pipeline_options.allow_point_size {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Cull Distance is not supported in Metal.
|
||||
// But we can't return UnsupportedBuiltIn error to user.
|
||||
// Because otherwise we can't generate msl shader from any glslang SPIR-V shaders.
|
||||
// glslang generates gl_PerVertex struct with gl_CullDistance builtin inside by default.
|
||||
crate::Binding::BuiltIn(crate::BuiltIn::CullDistance) => {
|
||||
log::warn!("Ignoring CullDistance BuiltIn");
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let array_len = match module.types[ty].inner {
|
||||
crate::TypeInner::Array {
|
||||
size: crate::ArraySize::Constant(handle),
|
||||
@@ -2911,6 +2937,18 @@ impl<W: Write> Writer<W> {
|
||||
}
|
||||
writeln!(self.out, ";")?;
|
||||
}
|
||||
|
||||
if pipeline_options.allow_point_size
|
||||
&& ep.stage == crate::ShaderStage::Vertex
|
||||
&& !has_point_size
|
||||
{
|
||||
// inject the point size output last
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}float _point_size [[point_size]];",
|
||||
back::INDENT
|
||||
)?;
|
||||
}
|
||||
writeln!(self.out, "}};")?;
|
||||
&stage_out_name
|
||||
}
|
||||
|
||||
@@ -16,4 +16,7 @@
|
||||
wgsl: (
|
||||
explicit_types: true,
|
||||
),
|
||||
msl_pipeline: (
|
||||
allow_point_size: true,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ struct vertex_Input {
|
||||
struct vertex_Output {
|
||||
metal::float4 position [[position]];
|
||||
float varying [[user(loc1), center_perspective]];
|
||||
float _point_size [[point_size]];
|
||||
};
|
||||
vertex vertex_Output vertex_(
|
||||
vertex_Input varyings [[stage_in]]
|
||||
@@ -30,7 +31,7 @@ vertex vertex_Output vertex_(
|
||||
const auto color = varyings.color;
|
||||
metal::uint tmp = (vertex_index + instance_index) + color;
|
||||
const auto _tmp = VertexOutput {metal::float4(1.0), static_cast<float>(tmp)};
|
||||
return vertex_Output { _tmp.position, _tmp.varying };
|
||||
return vertex_Output { _tmp.position, _tmp.varying, 1.0 };
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ struct Parameters {
|
||||
#[cfg(all(feature = "deserialize", feature = "msl-out"))]
|
||||
#[serde(default)]
|
||||
msl: naga::back::msl::Options,
|
||||
#[cfg(all(feature = "deserialize", feature = "msl-out"))]
|
||||
#[serde(default)]
|
||||
msl_pipeline: naga::back::msl::PipelineOptions,
|
||||
#[cfg(all(feature = "deserialize", feature = "glsl-out"))]
|
||||
#[serde(default)]
|
||||
glsl: naga::back::glsl::Options,
|
||||
@@ -135,6 +138,7 @@ fn check_targets(module: &naga::Module, name: &str, targets: Targets) {
|
||||
&dest,
|
||||
name,
|
||||
¶ms.msl,
|
||||
¶ms.msl_pipeline,
|
||||
params.bounds_check_policies,
|
||||
);
|
||||
}
|
||||
@@ -235,20 +239,17 @@ fn write_output_msl(
|
||||
destination: &PathBuf,
|
||||
file_name: &str,
|
||||
options: &naga::back::msl::Options,
|
||||
pipeline_options: &naga::back::msl::PipelineOptions,
|
||||
bounds_check_policies: naga::proc::BoundsCheckPolicies,
|
||||
) {
|
||||
use naga::back::msl;
|
||||
|
||||
println!("writing MSL");
|
||||
|
||||
let pipeline_options = msl::PipelineOptions {
|
||||
allow_point_size: true,
|
||||
};
|
||||
|
||||
let mut options = options.clone();
|
||||
options.bounds_check_policies = bounds_check_policies;
|
||||
let (string, tr_info) =
|
||||
msl::write_string(module, info, &options, &pipeline_options).expect("Metal write failed");
|
||||
msl::write_string(module, info, &options, pipeline_options).expect("Metal write failed");
|
||||
|
||||
for (ep, result) in module.entry_points.iter().zip(tr_info.entry_point_names) {
|
||||
if let Err(error) = result {
|
||||
|
||||
Reference in New Issue
Block a user