Skip to content

Commit

Permalink
Implement msaa API + particle example use msaa
Browse files Browse the repository at this point in the history
  • Loading branch information
EriKWDev committed Dec 4, 2024
1 parent 36edbdf commit 2464e11
Show file tree
Hide file tree
Showing 14 changed files with 301 additions and 46 deletions.
2 changes: 1 addition & 1 deletion 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
11 changes: 9 additions & 2 deletions blade-egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ impl GuiPainter {
/// It supports renderpasses with only a color attachment,
/// and this attachment format must be The `output_format`.
#[profiling::function]
pub fn new(info: blade_graphics::SurfaceInfo, context: &blade_graphics::Context) -> Self {
pub fn new(
info: blade_graphics::SurfaceInfo,
context: &blade_graphics::Context,
sample_count: u32,
) -> Self {
let shader = context.create_shader(blade_graphics::ShaderDesc {
source: SHADER_SOURCE,
});
Expand All @@ -151,7 +155,10 @@ impl GuiPainter {
blend: Some(blade_graphics::BlendState::ALPHA_BLENDING),
write_mask: blade_graphics::ColorWrites::all(),
}],
multisample_state: blade_graphics::MultisampleState::default(),
multisample_state: blade_graphics::MultisampleState {
sample_count,
..Default::default()
},
});

let belt = BufferBelt::new(BufferBeltDescriptor {
Expand Down
63 changes: 63 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 @@ impl super::CommandEncoder {
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 @@ -806,6 +810,65 @@ impl super::Command {
None,
);
}

Self::BlitFramebuffer { from, to } => {
/*
TODO(ErikWDev): Validate
*/

let target_from = match from.inner {
super::TextureInner::Renderbuffer { raw } => raw,
_ => panic!("Unsupported resolve between non-renderbuffers"),
};
let target_to = match to.inner {
super::TextureInner::Renderbuffer { raw } => raw,
_ => panic!("Unsupported resolve between non-renderbuffers"),
};

let framebuf_from = gl.create_framebuffer().unwrap();
let framebuf_to = gl.create_framebuffer().unwrap();

gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(framebuf_from));
gl.framebuffer_renderbuffer(
glow::READ_FRAMEBUFFER,
glow::COLOR_ATTACHMENT0, // NOTE: Assuming color attachment
glow::RENDERBUFFER,
Some(target_from),
);

gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(framebuf_to));
gl.framebuffer_renderbuffer(
glow::DRAW_FRAMEBUFFER,
glow::COLOR_ATTACHMENT0, // NOTE: Assuming color attachment
glow::RENDERBUFFER,
Some(target_to),
);
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);
gl.delete_framebuffer(framebuf_to);
}

Self::BindAttachment {
attachment,
ref view,
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
59 changes: 45 additions & 14 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,6 +156,7 @@ impl crate::traits::ResourceDevice for super::Context {
);
}
}

super::TextureInner::Renderbuffer { raw }
} else {
let raw = unsafe { gl.create_texture().unwrap() };
Expand All @@ -159,7 +172,11 @@ impl crate::traits::ResourceDevice for super::Context {
if desc.array_layer_count > 1 {
glow::TEXTURE_2D_ARRAY
} else {
glow::TEXTURE_2D
if desc.sample_count <= 1 {
glow::TEXTURE_2D
} else {
glow::TEXTURE_2D_MULTISAMPLE
}
}
}
crate::TextureDimension::D3 => glow::TEXTURE_3D,
Expand All @@ -184,13 +201,27 @@ 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 {
/*
TODO(ErikWDev): How to set mip count and sample count? Not possible in gles?
*/
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
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
7 changes: 6 additions & 1 deletion blade-graphics/src/metal/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,11 @@ impl crate::traits::ResourceDevice for super::Context {
if desc.array_layer_count > 1 {
metal::MTLTextureType::D2Array
} else {
metal::MTLTextureType::D2
if desc.sample_count <= 1 {
metal::MTLTextureType::D2
} else {
metal::MTLTextureType::D2Multisample
}
}
}
crate::TextureDimension::D3 => metal::MTLTextureType::D3,
Expand All @@ -198,6 +202,7 @@ impl crate::traits::ResourceDevice for super::Context {
descriptor.set_array_length(desc.array_layer_count as u64);
descriptor.set_mipmap_level_count(desc.mip_level_count as u64);
descriptor.set_pixel_format(mtl_format);
descriptor.set_sample_count(desc.sample_count as _);
descriptor.set_usage(mtl_usage);
descriptor.set_storage_mode(metal::MTLStorageMode::Private);

Expand Down
24 changes: 24 additions & 0 deletions blade-graphics/src/vulkan/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,34 @@ fn map_render_target(rt: &crate::RenderTarget) -> vk::RenderingAttachmentInfo<'s
},
}
};

vk_info.load_op = vk::AttachmentLoadOp::CLEAR;
vk_info.clear_value = cv;
}

if let crate::FinishOp::ResolveTo(resolve_view) = rt.finish_op {
vk_info = vk_info
.resolve_image_view(resolve_view.raw)
.resolve_image_layout(vk::ImageLayout::GENERAL)
.resolve_mode(vk::ResolveModeFlags::AVERAGE);
}

vk_info.store_op = match rt.finish_op {
crate::FinishOp::Store => vk::AttachmentStoreOp::STORE,
crate::FinishOp::Discard => vk::AttachmentStoreOp::DONT_CARE,
crate::FinishOp::Ignore => vk::AttachmentStoreOp::DONT_CARE,
crate::FinishOp::ResolveTo(..) => {
/*
TODO: DONT_CARE is most optimal in many cases where the msaa texture itself is never read afterwards but only the resolved,
but how can the user specify this in blade?
https://docs.vulkan.org/samples/latest/samples/performance/msaa/README.html#_best_practice_summary
*/

// vk::AttachmentStoreOp::STORE
vk::AttachmentStoreOp::DONT_CARE
}
};

vk_info
}

Expand Down
11 changes: 9 additions & 2 deletions blade-graphics/src/vulkan/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,9 +486,16 @@ impl crate::traits::ShaderDevice for super::Context {
.scissor_count(1)
.viewport_count(1);

let vk_sample_mask = [1u32, 0];
let vk_sample_mask = [
desc.multisample_state.sample_mask as u32,
(desc.multisample_state.sample_mask >> 32) as u32,
];

let vk_multisample = vk::PipelineMultisampleStateCreateInfo::default()
.rasterization_samples(vk::SampleCountFlags::TYPE_1)
.rasterization_samples(vk::SampleCountFlags::from_raw(
desc.multisample_state.sample_count,
))
.alpha_to_coverage_enable(desc.multisample_state.alpha_to_coverage)
.sample_mask(&vk_sample_mask);

let mut d_format = vk::Format::UNDEFINED;
Expand Down
8 changes: 6 additions & 2 deletions blade-graphics/src/vulkan/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ impl crate::traits::ResourceDevice for super::Context {
let mut create_flags = vk::ImageCreateFlags::empty();
if desc.dimension == crate::TextureDimension::D2
&& desc.size.depth % 6 == 0
//&& desc.sample_count == 1
&& desc.sample_count == 1
&& desc.size.width == desc.size.height
{
create_flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE;
Expand All @@ -265,13 +265,17 @@ impl crate::traits::ResourceDevice for super::Context {
extent: super::map_extent_3d(&desc.size),
mip_levels: desc.mip_level_count,
array_layers: desc.array_layer_count,
samples: vk::SampleCountFlags::from_raw(1), // desc.sample_count
samples: vk::SampleCountFlags::from_raw(desc.sample_count),
tiling: vk::ImageTiling::OPTIMAL,
usage: map_texture_usage(desc.usage, desc.format.aspects()),
sharing_mode: vk::SharingMode::EXCLUSIVE,
..Default::default()
};

/*
TODO(ErikWDev): Support lazily allocated texture with transient allocation for efficient msaa?
Measure bandwidth usage!
*/
let raw = unsafe { self.device.core.create_image(&vk_info, None).unwrap() };
let requirements = unsafe { self.device.core.get_image_memory_requirements(raw) };
let allocation = self.allocate_memory(requirements, crate::Memory::Device);
Expand Down
Loading

0 comments on commit 2464e11

Please sign in to comment.