Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for the OVR_multiview2 WebGL extension #1933

Merged
merged 22 commits into from
Jun 30, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
45c2ee9
Make some (currently hacky) changes to enable multiview in webgl
expenses May 20, 2022
6fb65fb
Merge remote-tracking branch 'origin/master' into webgl-multiview
expenses May 20, 2022
eb52d36
Fix ViewIndex built in for this extension
expenses May 20, 2022
91874c7
Run cargo fmt, fix tests
expenses May 20, 2022
639557e
Allow specifying if we're targetting webgl in the glsl version
expenses Jun 3, 2022
4c6aaa3
Document multiview2 extension
expenses Jun 3, 2022
3c6b5ed
fn embedded -> const fn embedded
expenses Jun 4, 2022
670cce0
Merge remote-tracking branch 'origin/master' into webgl-multiview
expenses Jun 13, 2022
ae64716
Fix tests
expenses Jun 13, 2022
a0d9b69
Fix benches
expenses Jun 13, 2022
4c0d7cd
Add snapshot tests
expenses Jun 15, 2022
928e2da
Merge remote-tracking branch 'origin/master' into webgl-multiview
expenses Jun 15, 2022
a1fffea
Revamp so that the glsl options have some multiview options. Also add…
expenses Jun 15, 2022
5d49ee9
Make clippy happier
expenses Jun 15, 2022
ba4cb8d
Merge remote-tracking branch 'origin/master' into webgl-multiview
expenses Jun 16, 2022
ef77cc2
Go back to having is_webgl be part of Version
expenses Jun 16, 2022
19d61ca
Merge remote-tracking branch 'origin/master' into webgl-multiview
expenses Jun 21, 2022
16feed3
Use wgsl as input for tests
expenses Jun 21, 2022
fbd0cc9
Rename Version::new_embedded to Version::new_gles, fix glsl validation
expenses Jun 21, 2022
95747a5
Merge remote-tracking branch 'origin/master' into webgl-multiview
expenses Jun 30, 2022
428a206
Run cargo fmt
expenses Jun 30, 2022
a4e3c38
Fix brand new clippy warnings
expenses Jun 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion benches/criterion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ fn backends(c: &mut Criterion) {
b.iter(|| {
let mut string = String::new();
let options = naga::back::glsl::Options {
version: naga::back::glsl::Version::Embedded(320),
version: naga::back::glsl::Version::new_embedded(320),
writer_flags: naga::back::glsl::WriterFlags::empty(),
binding_map: Default::default(),
};
Expand All @@ -248,6 +248,7 @@ fn backends(c: &mut Criterion) {
let pipeline_options = naga::back::glsl::PipelineOptions {
shader_stage: ep.stage,
entry_point: ep.name.clone(),
multiview: None,
};
match naga::back::glsl::Writer::new(
&mut string,
Expand Down
3 changes: 2 additions & 1 deletion cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ impl FromStr for GlslProfileArg {
Ok(Self(if s.starts_with("core") {
Version::Desktop(s[4..].parse().unwrap_or(330))
} else if s.starts_with("es") {
Version::Embedded(s[2..].parse().unwrap_or(310))
Version::new_embedded(s[2..].parse().unwrap_or(310))
} else {
return Err(format!("Unknown profile: {}", s));
}))
Expand Down Expand Up @@ -454,6 +454,7 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
"comp" => naga::ShaderStage::Compute,
_ => unreachable!(),
},
multiview: None,
};

let mut buffer = String::new();
Expand Down
22 changes: 17 additions & 5 deletions src/back/glsl/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl FeaturesManager {
// Used when both core and es support the feature
($feature:ident, $core:literal, $es:literal) => {
if self.0.contains(Features::$feature)
&& (version < Version::Desktop($core) || version < Version::Embedded($es))
&& (version < Version::Desktop($core) || version < Version::new_embedded($es))
{
missing |= Features::$feature;
}
Expand All @@ -106,7 +106,10 @@ impl FeaturesManager {
check_feature!(CULL_DISTANCE, 450, 300);
check_feature!(SAMPLE_VARIABLES, 400, 300);
check_feature!(DYNAMIC_ARRAY_SIZE, 430, 310);
check_feature!(MULTI_VIEW, 140, 310);
match version {
Version::Embedded { is_webgl: true, .. } => check_feature!(MULTI_VIEW, 140, 300),
JCapucho marked this conversation as resolved.
Show resolved Hide resolved
_ => check_feature!(MULTI_VIEW, 140, 310),
};
// Only available on glsl core, this means that opengl es can't query the number
// of samples nor levels in a image and neither do bound checks on the sample nor
// the level argument of texelFecth
Expand Down Expand Up @@ -212,11 +215,16 @@ impl FeaturesManager {
}

if self.0.contains(Features::MULTI_VIEW) {
// https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GL_EXT_multiview.txt
writeln!(out, "#extension GL_EXT_multiview : require")?;
if let Version::Embedded { is_webgl: true, .. } = version {
// https://www.khronos.org/registry/OpenGL/extensions/OVR/OVR_multiview2.txt
writeln!(out, "#extension GL_OVR_multiview2 : require")?;
} else {
// https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GL_EXT_multiview.txt
writeln!(out, "#extension GL_EXT_multiview : require")?;
}
}

if self.0.contains(Features::FMA) && version >= Version::Embedded(310) {
if self.0.contains(Features::FMA) && version >= Version::new_embedded(310) {
// https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_gpu_shader5.txt
writeln!(out, "#extension GL_EXT_gpu_shader5 : require")?;
}
Expand Down Expand Up @@ -269,6 +277,10 @@ impl<'a, W> Writer<'a, W> {
self.features.request(Features::COMPUTE_SHADER)
}

if self.multiview.is_some() {
self.features.request(Features::MULTI_VIEW);
}

for (ty_handle, ty) in self.module.types.iter() {
match ty.inner {
TypeInner::Scalar { kind, width } => self.scalar_required_features(kind, width),
Expand Down
76 changes: 62 additions & 14 deletions src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,31 @@ pub enum Version {
/// `core` GLSL.
Desktop(u16),
/// `es` GLSL.
Embedded(u16),
Embedded { version: u16, is_webgl: bool },
}

impl Version {
/// Create a new non-WebGL embedded version
pub const fn new_embedded(version: u16) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a better name for this would be gles since embedded is the name of the glsl profile and in this case we are trying to distinguish the platform.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Self::Embedded {
version,
is_webgl: false,
}
}

/// Returns true if self is `Version::Embedded` (i.e. is a es version)
const fn is_es(&self) -> bool {
match *self {
Version::Desktop(_) => false,
Version::Embedded(_) => true,
Version::Embedded { .. } => true,
}
}

/// Returns true if targetting WebGL
const fn is_webgl(&self) -> bool {
match *self {
Version::Desktop(_) => false,
Version::Embedded { is_webgl, .. } => is_webgl,
}
}

Expand All @@ -140,7 +156,7 @@ impl Version {
fn is_supported(&self) -> bool {
match *self {
Version::Desktop(v) => SUPPORTED_CORE_VERSIONS.contains(&v),
Version::Embedded(v) => SUPPORTED_ES_VERSIONS.contains(&v),
Version::Embedded { version: v, .. } => SUPPORTED_ES_VERSIONS.contains(&v),
}
}

Expand All @@ -151,27 +167,29 @@ impl Version {
/// Note: `location=` for vertex inputs and fragment outputs is supported
/// unconditionally for GLES 300.
fn supports_explicit_locations(&self) -> bool {
*self >= Version::Embedded(310) || *self >= Version::Desktop(410)
*self >= Version::Desktop(410) || *self >= Version::new_embedded(310)
}

fn supports_early_depth_test(&self) -> bool {
*self >= Version::Desktop(130) || *self >= Version::Embedded(310)
*self >= Version::Desktop(130) || *self >= Version::new_embedded(310)
}

fn supports_std430_layout(&self) -> bool {
*self >= Version::Desktop(430) || *self >= Version::Embedded(310)
*self >= Version::Desktop(430) || *self >= Version::new_embedded(310)
}

fn supports_fma_function(&self) -> bool {
*self >= Version::Desktop(400) || *self >= Version::Embedded(310)
*self >= Version::Desktop(400) || *self >= Version::new_embedded(310)
}
}

impl PartialOrd for Version {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (*self, *other) {
(Version::Desktop(x), Version::Desktop(y)) => Some(x.cmp(&y)),
(Version::Embedded(x), Version::Embedded(y)) => Some(x.cmp(&y)),
(Version::Embedded { version: x, .. }, Version::Embedded { version: y, .. }) => {
Some(x.cmp(&y))
}
_ => None,
}
}
Expand All @@ -181,7 +199,7 @@ impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Version::Desktop(v) => write!(f, "{} core", v),
Version::Embedded(v) => write!(f, "{} es", v),
Version::Embedded { version: v, .. } => write!(f, "{} es", v),
}
}
}
Expand Down Expand Up @@ -215,7 +233,7 @@ pub struct Options {
impl Default for Options {
fn default() -> Self {
Options {
version: Version::Embedded(310),
version: Version::new_embedded(310),
writer_flags: WriterFlags::ADJUST_COORDINATE_SPACE,
binding_map: BindingMap::default(),
}
Expand All @@ -233,6 +251,8 @@ pub struct PipelineOptions {
///
/// If no entry point that matches is found while creating a [`Writer`], a error will be thrown.
pub entry_point: String,
/// How many views to render to, if doing multiview rendering.
pub multiview: Option<std::num::NonZeroU32>,
}

/// Reflection info for texture mappings and uniforms.
Expand Down Expand Up @@ -285,6 +305,7 @@ struct VaryingName<'a> {
binding: &'a crate::Binding,
stage: ShaderStage,
output: bool,
targetting_webgl: bool,
}
impl fmt::Display for VaryingName<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand All @@ -302,7 +323,11 @@ impl fmt::Display for VaryingName<'_> {
write!(f, "_{}_location{}", prefix, location,)
}
crate::Binding::BuiltIn(built_in) => {
write!(f, "{}", glsl_built_in(built_in, self.output))
write!(
f,
"{}",
glsl_built_in(built_in, self.output, self.targetting_webgl)
)
}
}
}
Expand Down Expand Up @@ -400,6 +425,8 @@ pub struct Writer<'a, W> {
named_expressions: crate::NamedExpressions,
/// Set of expressions that need to be baked to avoid unnecessary repetition in output
need_bake_expressions: back::NeedBakeExpressions,
/// How many views to render to, if doing multiview rendering.
multiview: Option<std::num::NonZeroU32>,
}

impl<'a, W: Write> Writer<'a, W> {
Expand Down Expand Up @@ -451,7 +478,7 @@ impl<'a, W: Write> Writer<'a, W> {
reflection_names_globals: crate::FastHashMap::default(),
entry_point: &module.entry_points[ep_idx],
entry_point_idx: ep_idx as u16,

multiview: pipeline_options.multiview,
block_id: IdGenerator::default(),
named_expressions: Default::default(),
need_bake_expressions: Default::default(),
Expand Down Expand Up @@ -540,6 +567,13 @@ impl<'a, W: Write> Writer<'a, W> {
}
}

if self.entry_point.stage == ShaderStage::Vertex {
if let Some(multiview) = self.multiview.as_ref() {
writeln!(self.out, "layout(num_views = {}) in;", multiview)?;
writeln!(self.out)?;
}
}

let ep_info = self.info.get_entry_point(self.entry_point_idx as usize);

// Write struct types.
Expand Down Expand Up @@ -1180,7 +1214,11 @@ impl<'a, W: Write> Writer<'a, W> {
} => (location, interpolation, sampling),
crate::Binding::BuiltIn(built_in) => {
if let crate::BuiltIn::Position { invariant: true } = built_in {
writeln!(self.out, "invariant {};", glsl_built_in(built_in, output))?;
writeln!(
self.out,
"invariant {};",
glsl_built_in(built_in, output, self.options.version.is_webgl())
)?;
}
return Ok(());
}
Expand Down Expand Up @@ -1238,6 +1276,7 @@ impl<'a, W: Write> Writer<'a, W> {
},
stage: self.entry_point.stage,
output,
targetting_webgl: self.options.version.is_webgl(),
};
writeln!(self.out, " {};", vname)?;

Expand Down Expand Up @@ -1378,6 +1417,7 @@ impl<'a, W: Write> Writer<'a, W> {
binding: member.binding.as_ref().unwrap(),
stage,
output: false,
targetting_webgl: self.options.version.is_webgl(),
};
if index != 0 {
write!(self.out, ", ")?;
Expand All @@ -1391,6 +1431,7 @@ impl<'a, W: Write> Writer<'a, W> {
binding: arg.binding.as_ref().unwrap(),
stage,
output: false,
targetting_webgl: self.options.version.is_webgl(),
};
writeln!(self.out, "{};", varying_name)?;
}
Expand Down Expand Up @@ -1887,6 +1928,7 @@ impl<'a, W: Write> Writer<'a, W> {
binding: member.binding.as_ref().unwrap(),
stage: ep.stage,
output: true,
targetting_webgl: self.options.version.is_webgl(),
};
write!(self.out, "{} = ", varying_name)?;

Expand All @@ -1911,6 +1953,7 @@ impl<'a, W: Write> Writer<'a, W> {
binding: result.binding.as_ref().unwrap(),
stage: ep.stage,
output: true,
targetting_webgl: self.options.version.is_webgl(),
};
write!(self.out, "{} = ", name)?;
self.write_expr(value, ctx)?;
Expand Down Expand Up @@ -3607,7 +3650,11 @@ const fn glsl_scalar(
}

/// Helper function that returns the glsl variable name for a builtin
const fn glsl_built_in(built_in: crate::BuiltIn, output: bool) -> &'static str {
const fn glsl_built_in(
built_in: crate::BuiltIn,
output: bool,
targetting_webgl: bool,
) -> &'static str {
use crate::BuiltIn as Bi;

match built_in {
Expand All @@ -3618,6 +3665,7 @@ const fn glsl_built_in(built_in: crate::BuiltIn, output: bool) -> &'static str {
"gl_FragCoord"
}
}
Bi::ViewIndex if targetting_webgl => "int(gl_ViewID_OVR)",
Bi::ViewIndex => "gl_ViewIndex",
// vertex
Bi::BaseInstance => "uint(gl_BaseInstance)",
Expand Down
5 changes: 4 additions & 1 deletion tests/in/functions-webgl.param.ron
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
(
glsl: (
version: Embedded(300),
version: Embedded(
version: 300,
is_webgl: false
),
writer_flags: (bits: 0),
binding_map: {},
),
Expand Down
10 changes: 10 additions & 0 deletions tests/in/multiview_webgl.param.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(
glsl: (
version: Embedded(
version: 300,
is_webgl: true
),
writer_flags: (bits: 0),
binding_map: {},
),
)
5 changes: 4 additions & 1 deletion tests/in/push-constants.param.ron
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
(
god_mode: true,
glsl: (
version: Embedded(320),
version: Embedded(
version: 320,
is_webgl: false
),
writer_flags: (bits: 0),
binding_map: {},
),
Expand Down
5 changes: 4 additions & 1 deletion tests/in/quad.param.ron
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
adjust_coordinate_space: true,
),
glsl: (
version: Embedded(300),
version: Embedded(
version: 300,
is_webgl: false
),
writer_flags: (bits: 0),
binding_map: {},
),
Expand Down
5 changes: 4 additions & 1 deletion tests/in/skybox.param.ron
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@
fake_missing_bindings: false,
),
glsl: (
version: Embedded(320),
version: Embedded(
version: 320,
is_webgl: false
),
writer_flags: (bits: 0),
binding_map: {
(group: 0, binding: 0): 0,
Expand Down
Binary file added tests/in/spv/multiview.spv
Binary file not shown.
Binary file added tests/in/spv/multiview_webgl.spv
Binary file not shown.
22 changes: 22 additions & 0 deletions tests/out/glsl/multiview.main.Fragment.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#version 310 es
#extension GL_EXT_multiview : require

precision highp float;
precision highp int;

int gen_gl_ViewIndex_1 = 0;


void main_1() {
int view_index = 0;
int _e6 = gen_gl_ViewIndex_1;
view_index = _e6;
return;
}

void main() {
int gen_gl_ViewIndex = gl_ViewIndex;
gen_gl_ViewIndex_1 = gen_gl_ViewIndex;
main_1();
}

Loading