Skip to content

Commit

Permalink
Support dual source blending (#2427)
Browse files Browse the repository at this point in the history
Co-authored-by: teoxoy <[email protected]>
  • Loading branch information
freqmod and teoxoy authored Aug 30, 2023
1 parent 3bd2834 commit 0491d39
Show file tree
Hide file tree
Showing 29 changed files with 376 additions and 9 deletions.
11 changes: 11 additions & 0 deletions src/back/glsl/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ bitflags::bitflags! {
const TEXTURE_LEVELS = 1 << 19;
/// Image size query
const IMAGE_SIZE = 1 << 20;
/// Dual source blending
const DUAL_SOURCE_BLENDING = 1 << 21;
}
}

Expand Down Expand Up @@ -104,6 +106,7 @@ impl FeaturesManager {
check_feature!(CULL_DISTANCE, 450, 300 /* with extension */);
check_feature!(SAMPLE_VARIABLES, 400, 300);
check_feature!(DYNAMIC_ARRAY_SIZE, 430, 310);
check_feature!(DUAL_SOURCE_BLENDING, 330, 300 /* with extension */);
match version {
Version::Embedded { is_webgl: true, .. } => check_feature!(MULTI_VIEW, 140, 300),
_ => check_feature!(MULTI_VIEW, 140, 310),
Expand Down Expand Up @@ -233,6 +236,10 @@ impl FeaturesManager {
// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_query_levels.txt
writeln!(out, "#extension GL_ARB_texture_query_levels : require")?;
}
if self.0.contains(Features::DUAL_SOURCE_BLENDING) && version.is_es() {
// https://registry.khronos.org/OpenGL/extensions/EXT/EXT_blend_func_extended.txt
writeln!(out, "#extension GL_EXT_blend_func_extended : require")?;
}

Ok(())
}
Expand Down Expand Up @@ -497,13 +504,17 @@ impl<'a, W> Writer<'a, W> {
location: _,
interpolation,
sampling,
second_blend_source,
} => {
if interpolation == Some(Interpolation::Linear) {
self.features.request(Features::NOPERSPECTIVE_QUALIFIER);
}
if sampling == Some(Sampling::Sample) {
self.features.request(Features::SAMPLE_QUALIFIER);
}
if second_blend_source {
self.features.request(Features::DUAL_SOURCE_BLENDING);
}
}
}
}
Expand Down
18 changes: 15 additions & 3 deletions src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,12 @@ struct VaryingName<'a> {
impl fmt::Display for VaryingName<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self.binding {
crate::Binding::Location {
second_blend_source: true,
..
} => {
write!(f, "_fs2p_location1",)
}
crate::Binding::Location { location, .. } => {
let prefix = match (self.stage, self.output) {
(ShaderStage::Compute, _) => unreachable!(),
Expand Down Expand Up @@ -1235,12 +1241,13 @@ impl<'a, W: Write> Writer<'a, W> {
Some(binding) => binding,
};

let (location, interpolation, sampling) = match *binding {
let (location, interpolation, sampling, second_blend_source) = match *binding {
crate::Binding::Location {
location,
interpolation,
sampling,
} => (location, interpolation, sampling),
second_blend_source,
} => (location, interpolation, sampling, second_blend_source),
crate::Binding::BuiltIn(built_in) => {
if let crate::BuiltIn::Position { invariant: true } = built_in {
match (self.options.version, self.entry_point.stage) {
Expand Down Expand Up @@ -1281,7 +1288,11 @@ impl<'a, W: Write> Writer<'a, W> {

// Write the I/O locations, if allowed
if self.options.version.supports_explicit_locations() || !emit_interpolation_and_auxiliary {
write!(self.out, "layout(location = {location}) ")?;
if second_blend_source {
write!(self.out, "layout(location = {location}, index = 1) ")?;
} else {
write!(self.out, "layout(location = {location}) ")?;
}
}

// Write the interpolation qualifier.
Expand Down Expand Up @@ -1318,6 +1329,7 @@ impl<'a, W: Write> Writer<'a, W> {
location,
interpolation: None,
sampling: None,
second_blend_source,
},
stage: self.entry_point.stage,
output,
Expand Down
12 changes: 11 additions & 1 deletion src/back/hlsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,17 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
let builtin_str = builtin.to_hlsl_str()?;
write!(self.out, " : {builtin_str}")?;
}
crate::Binding::Location { location, .. } => {
crate::Binding::Location {
second_blend_source: true,
..
} => {
write!(self.out, " : SV_Target1")?;
}
crate::Binding::Location {
location,
second_blend_source: false,
..
} => {
if stage == Some((crate::ShaderStage::Fragment, Io::Output)) {
write!(self.out, " : SV_Target{location}")?;
} else {
Expand Down
29 changes: 26 additions & 3 deletions src/back/msl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ pub type EntryPointResourceMap = std::collections::BTreeMap<String, EntryPointRe
enum ResolvedBinding {
BuiltIn(crate::BuiltIn),
Attribute(u32),
Color(u32),
Color {
location: u32,
second_blend_source: bool,
},
User {
prefix: &'static str,
index: u32,
Expand Down Expand Up @@ -245,9 +248,20 @@ impl Options {
location,
interpolation,
sampling,
second_blend_source,
} => match mode {
LocationMode::VertexInput => Ok(ResolvedBinding::Attribute(location)),
LocationMode::FragmentOutput => Ok(ResolvedBinding::Color(location)),
LocationMode::FragmentOutput => {
if second_blend_source && self.lang_version < (1, 2) {
return Err(Error::UnsupportedAttribute(
"second_blend_source".to_string(),
));
}
Ok(ResolvedBinding::Color {
location,
second_blend_source,
})
}
LocationMode::VertexOutput | LocationMode::FragmentInput => {
Ok(ResolvedBinding::User {
prefix: if self.spirv_cross_compatibility {
Expand Down Expand Up @@ -404,7 +418,16 @@ impl ResolvedBinding {
write!(out, "{name}")?;
}
Self::Attribute(index) => write!(out, "attribute({index})")?,
Self::Color(index) => write!(out, "color({index})")?,
Self::Color {
location,
second_blend_source,
} => {
if second_blend_source {
write!(out, "color({location}) index(1)")?
} else {
write!(out, "color({location})")?
}
}
Self::User {
prefix,
index,
Expand Down
4 changes: 4 additions & 0 deletions src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,7 @@ impl Writer {
location,
interpolation,
sampling,
second_blend_source,
} => {
self.decorate(id, Decoration::Location, &[location]);

Expand Down Expand Up @@ -1473,6 +1474,9 @@ impl Writer {
}
}
}
if second_blend_source {
self.decorate(id, Decoration::Index, &[1]);
}
}
crate::Binding::BuiltIn(built_in) => {
use crate::BuiltIn as Bi;
Expand Down
13 changes: 13 additions & 0 deletions src/back/wgsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ enum Attribute {
Invariant,
Interpolate(Option<crate::Interpolation>, Option<crate::Sampling>),
Location(u32),
SecondBlendSource,
Stage(ShaderStage),
WorkGroupSize([u32; 3]),
}
Expand Down Expand Up @@ -319,6 +320,7 @@ impl<W: Write> Writer<W> {
for attribute in attributes {
match *attribute {
Attribute::Location(id) => write!(self.out, "@location({id}) ")?,
Attribute::SecondBlendSource => write!(self.out, "@second_blend_source ")?,
Attribute::BuiltIn(builtin_attrib) => {
let builtin = builtin_str(builtin_attrib)?;
write!(self.out, "@builtin({builtin}) ")?;
Expand Down Expand Up @@ -1917,9 +1919,20 @@ fn map_binding_to_attribute(binding: &crate::Binding) -> Vec<Attribute> {
location,
interpolation,
sampling,
second_blend_source: false,
} => vec![
Attribute::Location(location),
Attribute::Interpolate(interpolation, sampling),
],
crate::Binding::Location {
location,
interpolation,
sampling,
second_blend_source: true,
} => vec![
Attribute::Location(location),
Attribute::SecondBlendSource,
Attribute::Interpolate(interpolation, sampling),
],
}
}
2 changes: 2 additions & 0 deletions src/front/glsl/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,7 @@ impl Frontend {
location,
interpolation,
sampling: None,
second_blend_source: false,
};
location += 1;

Expand Down Expand Up @@ -1336,6 +1337,7 @@ impl Frontend {
location,
interpolation,
sampling: None,
second_blend_source: false,
};
location += 1;
binding
Expand Down
1 change: 1 addition & 0 deletions src/front/glsl/variables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ impl Frontend {
location,
interpolation,
sampling,
second_blend_source: false,
},
handle,
storage,
Expand Down
1 change: 1 addition & 0 deletions src/front/interpolator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl crate::Binding {
location: _,
interpolation: ref mut interpolation @ None,
ref mut sampling,
second_blend_source: _,
} = *self
{
match ty.scalar_kind() {
Expand Down
1 change: 1 addition & 0 deletions src/front/spv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ impl Decoration {
location,
interpolation,
sampling,
second_blend_source: false,
}),
_ => Err(Error::MissingDecoration(spirv::Decoration::Location)),
}
Expand Down
5 changes: 5 additions & 0 deletions src/front/wgsl/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ impl<T> ParsedAttribute<T> {
#[derive(Default)]
struct BindingParser {
location: ParsedAttribute<u32>,
second_blend_source: ParsedAttribute<bool>,
built_in: ParsedAttribute<crate::BuiltIn>,
interpolation: ParsedAttribute<crate::Interpolation>,
sampling: ParsedAttribute<crate::Sampling>,
Expand Down Expand Up @@ -182,6 +183,9 @@ impl BindingParser {
}
lexer.expect(Token::Paren(')'))?;
}
"second_blend_source" => {
self.second_blend_source.set(true, name_span)?;
}
"invariant" => {
self.invariant.set(true, name_span)?;
}
Expand All @@ -208,6 +212,7 @@ impl BindingParser {
location,
interpolation,
sampling,
second_blend_source: self.second_blend_source.value.unwrap_or(false),
}))
}
(None, Some(crate::BuiltIn::Position { .. }), None, None, invariant) => {
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,8 @@ pub enum Binding {
/// [`Fragment`]: crate::ShaderStage::Fragment
Location {
location: u32,
/// Indicates the 2nd input to the blender when dual-source blending.
second_blend_source: bool,
interpolation: Option<Interpolation>,
sampling: Option<Sampling>,
},
Expand Down
5 changes: 5 additions & 0 deletions src/valid/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ pub struct FunctionInfo {
///
/// [`GlobalVariable`]: crate::GlobalVariable
sampling: crate::FastHashSet<Sampling>,

/// Indicates that the function is using dual source blending.
pub dual_source_blending: bool,
}

impl FunctionInfo {
Expand Down Expand Up @@ -999,6 +1002,7 @@ impl ModuleInfo {
global_uses: vec![GlobalUse::empty(); module.global_variables.len()].into_boxed_slice(),
expressions: vec![ExpressionInfo::new(); fun.expressions.len()].into_boxed_slice(),
sampling: crate::FastHashSet::default(),
dual_source_blending: false,
};
let resolve_context =
ResolveContext::with_locals(module, &fun.local_variables, &fun.arguments);
Expand Down Expand Up @@ -1108,6 +1112,7 @@ fn uniform_control_flow() {
global_uses: vec![GlobalUse::empty(); global_var_arena.len()].into_boxed_slice(),
expressions: vec![ExpressionInfo::new(); expressions.len()].into_boxed_slice(),
sampling: crate::FastHashSet::default(),
dual_source_blending: false,
};
let resolve_context = ResolveContext {
constants: &Arena::new(),
Expand Down
Loading

0 comments on commit 0491d39

Please sign in to comment.