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

gles: implement blending and write masks #126

Merged
merged 1 commit into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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 @@
) -> 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 @@ -372,7 +383,7 @@
self.commands.push(super::Command::SetScissor(rect.clone()));
}

fn bind_vertex(&mut self, index: u32, vertex_buf: crate::BufferPiece) {

Check warning on line 386 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Web, ubuntu-latest, wasm32-unknown-unknown)

unused variable: `index`

Check warning on line 386 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Linux, ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `index`
self.commands.push(super::Command::BindVertex {
buffer: vertex_buf.buffer.raw,
});
Expand Down Expand Up @@ -458,6 +469,38 @@
}
}

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 @@ -553,9 +596,9 @@
gl.dispatch_compute_indirect(indirect_buf.offset as i32);
}
Self::FillBuffer {
ref dst,

Check warning on line 599 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Web, ubuntu-latest, wasm32-unknown-unknown)

unused variable: `dst`

Check warning on line 599 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Linux, ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `dst`
size,

Check warning on line 600 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Web, ubuntu-latest, wasm32-unknown-unknown)

unused variable: `size`

Check warning on line 600 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Linux, ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `size`
value,

Check warning on line 601 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Web, ubuntu-latest, wasm32-unknown-unknown)

unused variable: `value`

Check warning on line 601 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Linux, ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `value`
} => unimplemented!(),
Self::CopyBufferToBuffer {
ref src,
Expand Down Expand Up @@ -611,7 +654,7 @@
} => {
let format_desc = super::describe_texture_format(dst.format);
let block_info = dst.format.block_info();
let row_texels =

Check warning on line 657 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Web, ubuntu-latest, wasm32-unknown-unknown)

unused variable: `row_texels`

Check warning on line 657 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Linux, ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `row_texels`
bytes_per_row / block_info.size as u32 * block_info.dimensions.0 as u32;
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, Some(src.raw));
Expand Down Expand Up @@ -685,10 +728,10 @@
gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, None);
}
Self::CopyTextureToBuffer {
ref src,

Check warning on line 731 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Web, ubuntu-latest, wasm32-unknown-unknown)

unused variable: `src`

Check warning on line 731 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Linux, ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `src`
ref dst,

Check warning on line 732 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Web, ubuntu-latest, wasm32-unknown-unknown)

unused variable: `dst`

Check warning on line 732 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Linux, ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `dst`
bytes_per_row,

Check warning on line 733 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Web, ubuntu-latest, wasm32-unknown-unknown)

unused variable: `bytes_per_row`

Check warning on line 733 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Linux, ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `bytes_per_row`
ref size,

Check warning on line 734 in blade-graphics/src/gles/command.rs

View workflow job for this annotation

GitHub Actions / build (Web, ubuntu-latest, wasm32-unknown-unknown)

unused variable: `size`
} => unimplemented!(),
Self::ResetFramebuffer => {
for &attachment in COLOR_ATTACHMENTS.iter() {
Expand Down Expand Up @@ -737,6 +780,48 @@
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 @@
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 @@ -197,7 +197,7 @@
egl1_5
.get_platform_display(
EGL_PLATFORM_SURFACELESS_MESA,
std::ptr::null_mut(),

Check warning on line 200 in blade-graphics/src/gles/egl.rs

View workflow job for this annotation

GitHub Actions / build (Linux, ubuntu-latest, x86_64-unknown-linux-gnu)

unnecessary qualification
&[egl::ATTRIB_NONE],
)
.unwrap()
Expand Down Expand Up @@ -810,6 +810,16 @@
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
Loading