Skip to content

Commit

Permalink
gles: implement blending and write masks
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaslihotzki committed Jun 15, 2024
1 parent f9c2fd4 commit 15f04f4
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 2 deletions.
87 changes: 86 additions & 1 deletion blade-graphics/src/gles/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,17 @@ impl super::PassEncoder<'_, super::RenderPipeline> {
) -> super::PipelineEncoder<'b> {
self.commands
.push(super::Command::SetProgram(pipeline.inner.program));

match &pipeline.inner.color_targets[..] {
&[(blend_state, write_masks)] => self
.commands
.push(super::Command::SetAllColorTargets(blend_state, write_masks)),
separate => self.commands.extend(separate.iter().zip(0..).map(
|(&(blend_state, write_masks), i)| {
super::Command::SetSingleColorTarget(i, blend_state, write_masks)
},
)),
}
super::PipelineEncoder {
commands: self.commands,
plain_data: self.plain_data,
Expand Down Expand Up @@ -458,6 +469,38 @@ impl crate::VertexFormat {
}
}

impl crate::BlendFactor {
fn to_gles(self) -> u32 {
match self {
Self::Zero => glow::ZERO,
Self::One => glow::ONE,
Self::Src => glow::SRC_COLOR,
Self::OneMinusSrc => glow::ONE_MINUS_SRC_COLOR,
Self::SrcAlpha => glow::SRC_ALPHA,
Self::OneMinusSrcAlpha => glow::ONE_MINUS_SRC_ALPHA,
Self::Dst => glow::DST_COLOR,
Self::OneMinusDst => glow::ONE_MINUS_DST_COLOR,
Self::DstAlpha => glow::DST_ALPHA,
Self::OneMinusDstAlpha => glow::ONE_MINUS_DST_ALPHA,
Self::SrcAlphaSaturated => glow::SRC_ALPHA_SATURATE,
Self::Constant => glow::CONSTANT_ALPHA,
Self::OneMinusConstant => glow::ONE_MINUS_CONSTANT_ALPHA,
}
}
}

impl crate::BlendOperation {
fn to_gles(self) -> u32 {
match self {
Self::Add => glow::FUNC_ADD,
Self::Subtract => glow::FUNC_SUBTRACT,
Self::ReverseSubtract => glow::FUNC_REVERSE_SUBTRACT,
Self::Min => glow::MIN,
Self::Max => glow::MAX,
}
}
}

const CUBEMAP_FACES: [u32; 6] = [
glow::TEXTURE_CUBE_MAP_POSITIVE_X,
glow::TEXTURE_CUBE_MAP_NEGATIVE_X,
Expand Down Expand Up @@ -737,6 +780,48 @@ impl super::Command {
Self::SetDrawColorBuffers(count) => {
gl.draw_buffers(&COLOR_ATTACHMENTS[..count as usize]);
}
Self::SetAllColorTargets(blend, write_mask) => {
if let Some(blend_state) = blend {
gl.enable(glow::BLEND);
gl.blend_func_separate(
blend_state.color.src_factor.to_gles(),
blend_state.color.dst_factor.to_gles(),
blend_state.alpha.src_factor.to_gles(),
blend_state.alpha.dst_factor.to_gles(),
);
gl.blend_equation(blend_state.color.operation.to_gles());
} else {
gl.disable(glow::BLEND);
}
gl.color_mask(
write_mask.contains(crate::ColorWrites::RED),
write_mask.contains(crate::ColorWrites::GREEN),
write_mask.contains(crate::ColorWrites::BLUE),
write_mask.contains(crate::ColorWrites::ALPHA),
);
}
Self::SetSingleColorTarget(i, blend, write_mask) => {
if let Some(blend_state) = blend {
gl.enable_draw_buffer(glow::BLEND, i);
gl.blend_func_separate_draw_buffer(
i,
blend_state.color.src_factor.to_gles(),
blend_state.color.dst_factor.to_gles(),
blend_state.alpha.src_factor.to_gles(),
blend_state.alpha.dst_factor.to_gles(),
);
gl.blend_equation_draw_buffer(i, blend_state.color.operation.to_gles());
} else {
gl.disable_draw_buffer(glow::BLEND, i);
}
gl.color_mask_draw_buffer(
i,
write_mask.contains(crate::ColorWrites::RED),
write_mask.contains(crate::ColorWrites::GREEN),
write_mask.contains(crate::ColorWrites::BLUE),
write_mask.contains(crate::ColorWrites::ALPHA),
);
}
Self::ClearColor {
draw_buffer,
color,
Expand Down Expand Up @@ -813,7 +898,7 @@ impl super::Command {
gl.use_program(None);
}
//SetPrimitive(PrimitiveState),
Self::SetBlendConstant(constant) => unimplemented!(),
Self::SetBlendConstant([r, g, b, a]) => gl.blend_color(r, g, b, a),
Self::SetColorTarget {
draw_buffer_index,
//desc: ColorTargetDesc,
Expand Down
10 changes: 10 additions & 0 deletions blade-graphics/src/gles/egl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,16 @@ impl EglContext {
super::Capabilities::BUFFER_STORAGE,
extensions.contains("GL_EXT_buffer_storage"),
);
capabilities.set(
super::Capabilities::DRAW_BUFFERS_INDEXED,
if gl.version().is_embedded {
(gl.version().major, gl.version().minor) >= (3, 2)
} else {
(gl.version().major, gl.version().minor) >= (3, 0)
},
// glow uses unsuffixed functions like glEnablei instead of glEnableiEXT.
// Therefore, GL_EXT_draw_buffers_indexed is not sufficient.
);

let limits = super::Limits {
uniform_buffer_alignment: gl.get_parameter_i32(glow::UNIFORM_BUFFER_OFFSET_ALIGNMENT)
Expand Down
4 changes: 4 additions & 0 deletions blade-graphics/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const DEBUG_ID: u32 = 0;
bitflags::bitflags! {
struct Capabilities: u32 {
const BUFFER_STORAGE = 1 << 0;
const DRAW_BUFFERS_INDEXED = 1 << 1;
}
}

Expand Down Expand Up @@ -100,6 +101,7 @@ struct PipelineInner {
program: glow::Program,
group_mappings: Box<[ShaderDataMapping]>,
vertex_attribute_infos: Box<[VertexAttributeInfo]>,
color_targets: Box<[(Option<crate::BlendState>, crate::ColorWrites)]>,
}

pub struct ComputePipeline {
Expand Down Expand Up @@ -253,6 +255,8 @@ enum Command {
},
InvalidateAttachment(u32),
SetDrawColorBuffers(u8),
SetAllColorTargets(Option<crate::BlendState>, crate::ColorWrites),
SetSingleColorTarget(u32, Option<crate::BlendState>, crate::ColorWrites),
ClearColor {
draw_buffer: u32,
color: crate::TextureColor,
Expand Down
32 changes: 31 additions & 1 deletion blade-graphics/src/gles/pipeline.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
use glow::HasContext as _;
use naga::back::glsl;

fn separate<T: PartialEq>(mut iter: impl Iterator<Item = T>) -> bool {
if let Some(first) = iter.next() {
iter.all(|el| el == first)
} else {
false
}
}

fn conflate<T: PartialEq>(iter: impl Iterator<Item = T> + Clone) -> Box<[T]> {
if separate(iter.clone()) {
iter.collect()
} else {
iter.take(1).collect()
}
}

impl super::Context {
unsafe fn create_pipeline(
&self,
Expand Down Expand Up @@ -276,6 +292,7 @@ impl super::Context {
program,
group_mappings,
vertex_attribute_infos: attributes.into_boxed_slice(),
color_targets: Box::new([]),
}
}

Expand Down Expand Up @@ -303,7 +320,7 @@ impl super::Context {
} else {
glsl::WriterFlags::empty()
};
let inner = unsafe {
let mut inner = unsafe {
self.create_pipeline(
&[desc.vertex, desc.fragment],
desc.data_layouts,
Expand All @@ -312,6 +329,19 @@ impl super::Context {
extra_flags,
)
};

inner.color_targets = conflate(desc.color_targets.iter().map(|t| (t.blend, t.write_mask)));

if !self
.capabilities
.contains(super::Capabilities::DRAW_BUFFERS_INDEXED)
{
assert!(
inner.color_targets.len() <= 1,
"separate blend states or write masks of multiple color targets are not supported"
);
}

super::RenderPipeline {
inner,
topology: desc.primitive.topology,
Expand Down

0 comments on commit 15f04f4

Please sign in to comment.