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 Multisampled Anti-Aliasing #213

Merged
merged 13 commits into from
Dec 10, 2024
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
/blade-asset/cooked
/_failure.wgsl

libEGL.dylib
libGLESv2.dylib

.DS_Store
/.vs
/.vscode
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ profiling = "1"
slab = "0.4"
strum = { version = "0.25", features = ["derive"] }
web-sys = "0.3.60"
winit = "0.30"
winit = { version = "0.30" }

[lib]

Expand Down Expand Up @@ -90,9 +90,11 @@ del-geo = "=0.1.29"

[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
# see https://github.com/emilk/egui/issues/4270
egui-winit = "0.29"
egui-winit = { version="0.29", default-features=false, features=["links"] }

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
# see https://github.com/emilk/egui/issues/4270
egui-winit = { version="0.29", default-features=false, features=["links"] }
Copy link
Owner

Choose a reason for hiding this comment

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

it's now the same dependency between wasm and normal, can we move it into a common block of dev dependencies?

console_error_panic_hook = "0.1.7"
console_log = "1"
web-sys = { workspace = true, features = ["Window"] }
Expand Down
2 changes: 2 additions & 0 deletions blade-egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ impl GuiTexture {
mip_level_count: 1,
dimension: blade_graphics::TextureDimension::D2,
usage: blade_graphics::TextureUsage::COPY | blade_graphics::TextureUsage::RESOURCE,
sample_count: 1,
});
let view = context.create_texture_view(
allocation,
Expand Down Expand Up @@ -161,6 +162,7 @@ impl GuiPainter {
}),
write_mask: blade_graphics::ColorWrites::all(),
}],
multisample_state: Default::default(),
});

let belt = BufferBelt::new(BufferBeltDescriptor {
Expand Down
81 changes: 81 additions & 0 deletions blade-graphics/src/gles/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@
if let crate::FinishOp::Discard = rt.finish_op {
invalidate_attachments.push(attachment);
}
if let crate::FinishOp::ResolveTo(to) = rt.finish_op {
self.commands
.push(super::Command::BlitFramebuffer { from: rt.view, to });
}
}
if let Some(ref rt) = targets.depth_stencil {
let attachment = match rt.view.aspects {
Expand Down Expand Up @@ -785,10 +789,10 @@
gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, None);
}
Self::CopyTextureToBuffer {
ref src,

Check warning on line 792 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`

Check warning on line 792 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`
ref dst,

Check warning on line 793 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`

Check warning on line 793 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`
bytes_per_row,

Check warning on line 794 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`

Check warning on line 794 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`
ref size,

Check warning on line 795 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`

Check warning on line 795 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 All @@ -806,6 +810,83 @@
None,
);
}

Self::BlitFramebuffer { from, to } => {
/*
TODO: Framebuffers could be re-used instead of being created on the fly.
Currently deleted down below
*/
let framebuf_from = gl.create_framebuffer().unwrap();
let framebuf_to = gl.create_framebuffer().unwrap();

gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(framebuf_from));
match from.inner {
super::TextureInner::Renderbuffer { raw } => {
gl.framebuffer_renderbuffer(
glow::READ_FRAMEBUFFER,
glow::COLOR_ATTACHMENT0, // NOTE: Assuming color attachment
glow::RENDERBUFFER,
Some(raw),
);
}
super::TextureInner::Texture { raw, target } => {
gl.framebuffer_texture_2d(
glow::READ_FRAMEBUFFER,
glow::COLOR_ATTACHMENT0,
target,
Some(raw),
0,
);
}
}

gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(framebuf_to));
match to.inner {
super::TextureInner::Renderbuffer { raw } => {
gl.framebuffer_renderbuffer(
glow::DRAW_FRAMEBUFFER,
glow::COLOR_ATTACHMENT0, // NOTE: Assuming color attachment
glow::RENDERBUFFER,
Some(raw),
);
}
super::TextureInner::Texture { raw, target } => {
gl.framebuffer_texture_2d(
glow::DRAW_FRAMEBUFFER,
glow::COLOR_ATTACHMENT0,
target,
Some(raw),
0,
);
}
}

debug_assert_eq!(
gl.check_framebuffer_status(glow::DRAW_FRAMEBUFFER),
glow::FRAMEBUFFER_COMPLETE,
"DRAW_FRAMEBUFFER is not complete"
);

gl.blit_framebuffer(
0,
0,
from.target_size[0] as _,
from.target_size[1] as _,
0,
0,
to.target_size[0] as _,
to.target_size[1] as _,
glow::COLOR_BUFFER_BIT, // NOTE: Assuming color
glow::NEAREST,
);

gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None);
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None);

gl.delete_framebuffer(framebuf_from);
EriKWDev marked this conversation as resolved.
Show resolved Hide resolved
gl.delete_framebuffer(framebuf_to);
}

Self::BindAttachment {
attachment,
ref view,
Expand Down Expand Up @@ -935,13 +1016,13 @@
gl.scissor(rect.x, rect.y, rect.w as i32, rect.h as i32);
}
Self::SetStencilFunc {
face,

Check warning on line 1019 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: `face`

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

View workflow job for this annotation

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

unused variable: `face`
function,

Check warning on line 1020 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: `function`

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

View workflow job for this annotation

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

unused variable: `function`
reference,

Check warning on line 1021 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: `reference`

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

View workflow job for this annotation

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

unused variable: `reference`
read_mask,

Check warning on line 1022 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: `read_mask`

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

View workflow job for this annotation

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

unused variable: `read_mask`
} => unimplemented!(),
Self::SetStencilOps {
face,

Check warning on line 1025 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: `face`

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

View workflow job for this annotation

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

unused variable: `face`
write_mask,
//ops: crate::StencilOps,
} => unimplemented!(),
Expand Down
3 changes: 2 additions & 1 deletion blade-graphics/src/gles/egl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,8 @@ impl super::Context {
let window_ptr = unsafe {
use objc::{msg_send, runtime::Object, sel, sel_impl};
// ns_view always have a layer and don't need to verify that it exists.
let layer: *mut Object = msg_send![handle.ns_view.as_ptr(), layer];
let layer: *mut Object =
msg_send![handle.ns_view.as_ptr() as *mut Object, layer];
Copy link
Owner

Choose a reason for hiding this comment

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

curious, does this cast do anything? I think the type is essentially erased at that point, anyway

Copy link
Contributor Author

@EriKWDev EriKWDev Dec 9, 2024

Choose a reason for hiding this comment

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

It didn't compile for me, msg_send![] required the thing to implement the "Message" trait and it wasn't implemented by a raw pointer. The cast fixed the compilation though ofc no guarantees

This made it compile, though I could still not get it to run :/

layer as *mut ffi::c_void
};
window_ptr
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 @@ -274,6 +274,10 @@ enum Command {
size: crate::Extent,
},
ResetFramebuffer,
BlitFramebuffer {
from: TextureView,
to: TextureView,
},
BindAttachment {
attachment: u32,
view: TextureView,
Expand Down
74 changes: 58 additions & 16 deletions blade-graphics/src/gles/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,24 @@ impl crate::traits::ResourceDevice for super::Context {
let raw = unsafe { gl.create_renderbuffer().unwrap() };
unsafe {
gl.bind_renderbuffer(glow::RENDERBUFFER, Some(raw));
gl.renderbuffer_storage(
glow::RENDERBUFFER,
format_desc.internal,
desc.size.width as i32,
desc.size.height as i32,
);

if desc.sample_count <= 1 {
gl.renderbuffer_storage(
glow::RENDERBUFFER,
format_desc.internal,
desc.size.width as i32,
desc.size.height as i32,
);
} else {
gl.renderbuffer_storage_multisample(
glow::RENDERBUFFER,
desc.sample_count as i32,
format_desc.internal,
desc.size.width as i32,
desc.size.height as i32,
);
}

gl.bind_renderbuffer(glow::RENDERBUFFER, None);
#[cfg(not(target_arch = "wasm32"))]
if !desc.name.is_empty() && gl.supports_debug() {
Expand All @@ -144,11 +156,16 @@ impl crate::traits::ResourceDevice for super::Context {
);
}
}

super::TextureInner::Renderbuffer { raw }
} else {
let raw = unsafe { gl.create_texture().unwrap() };

let target = match desc.dimension {
crate::TextureDimension::D1 => {
if desc.sample_count > 1 {
log::warn!("Sample count is ignored: not supported for 1D textures",);
}
if desc.array_layer_count > 1 {
glow::TEXTURE_1D_ARRAY
} else {
Expand All @@ -157,12 +174,25 @@ impl crate::traits::ResourceDevice for super::Context {
}
crate::TextureDimension::D2 => {
if desc.array_layer_count > 1 {
glow::TEXTURE_2D_ARRAY
if desc.sample_count <= 1 {
glow::TEXTURE_2D_ARRAY
} else {
glow::TEXTURE_2D_MULTISAMPLE_ARRAY
}
} else {
glow::TEXTURE_2D
if desc.sample_count <= 1 {
glow::TEXTURE_2D
} else {
glow::TEXTURE_2D_MULTISAMPLE
}
}
}
crate::TextureDimension::D3 => {
if desc.sample_count > 1 {
log::warn!("Sample count is ignored: not supported for 3D textures",);
}
glow::TEXTURE_3D
}
crate::TextureDimension::D3 => glow::TEXTURE_3D,
};

unsafe {
Expand All @@ -184,13 +214,25 @@ impl crate::traits::ResourceDevice for super::Context {
);
}
crate::TextureDimension::D2 => {
gl.tex_storage_2d(
target,
desc.mip_level_count as i32,
format_desc.internal,
desc.size.width as i32,
desc.size.height as i32,
);
if desc.sample_count <= 1 {
gl.tex_storage_2d(
target,
desc.mip_level_count as i32,
format_desc.internal,
desc.size.width as i32,
desc.size.height as i32,
);
} else {
assert_eq!(desc.mip_level_count, 1);
gl.tex_storage_2d_multisample(
target,
desc.sample_count as i32,
format_desc.internal,
desc.size.width as i32,
desc.size.height as i32,
true,
);
}
}
crate::TextureDimension::D1 => {
gl.tex_storage_1d(
Expand Down
22 changes: 22 additions & 0 deletions blade-graphics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ pub struct TextureDesc<'a> {
pub size: Extent,
pub array_layer_count: u32,
pub mip_level_count: u32,
pub sample_count: u32,
pub dimension: TextureDimension,
pub usage: TextureUsage,
}
Expand Down Expand Up @@ -1018,18 +1019,39 @@ pub struct RenderPipelineDesc<'a> {
pub depth_stencil: Option<DepthStencilState>,
pub fragment: ShaderFunction<'a>,
pub color_targets: &'a [ColorTargetState],
pub multisample_state: MultisampleState,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct MultisampleState {
pub sample_count: u32,
pub sample_mask: u64,
pub alpha_to_coverage: bool,
}

impl Default for MultisampleState {
fn default() -> Self {
Self {
sample_count: 1,
sample_mask: !0,
alpha_to_coverage: false,
}
}
}

#[derive(Clone, Copy, Debug)]
pub enum InitOp {
Load,
Clear(TextureColor),
DontCare,
}

#[derive(Clone, Copy, Debug)]
pub enum FinishOp {
Store,
Discard,
/// The texture specified here will be stored but it is undefined what
/// happens to the original render target
ResolveTo(TextureView),
Ignore,
}
Expand Down
2 changes: 2 additions & 0 deletions blade-graphics/src/metal/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ impl super::CommandEncoder {
at_descriptor.set_clear_color(clear_color);
metal::MTLLoadAction::Clear
}
crate::InitOp::DontCare => metal::MTLLoadAction::DontCare,
};
at_descriptor.set_load_action(load_action);

Expand Down Expand Up @@ -247,6 +248,7 @@ impl super::CommandEncoder {
at_descriptor.set_clear_depth(clear_depth);
metal::MTLLoadAction::Clear
}
crate::InitOp::DontCare => metal::MTLLoadAction::DontCare,
};
let store_action = match rt.finish_op {
crate::FinishOp::Store | crate::FinishOp::Ignore => {
Expand Down
2 changes: 2 additions & 0 deletions blade-graphics/src/metal/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,8 @@ impl crate::traits::ShaderDevice for super::Context {
},
);
descriptor.set_vertex_function(Some(&vs.function));
descriptor.set_raster_sample_count(desc.multisample_state.sample_count as _);
descriptor.set_alpha_to_coverage_enabled(desc.multisample_state.alpha_to_coverage);

// Fragment shader
let fs = self.load_shader(
Expand Down
Loading
Loading