-
Notifications
You must be signed in to change notification settings - Fork 40
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is amazing work, thank you!
High quality, something that any open source project would cherish and greatly appreciate.
Very solid for the first contribution, I'm excited to see this finished.
blade-graphics/src/gles/command.rs
Outdated
|
||
Self::BlitFramebuffer { from, to } => { | ||
/* | ||
TODO(ErikWDev): Validate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please follow these instructions - https://github.com/kvark/blade/tree/main/blade-graphics#opengl-es
and let me know if something doesn't work!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, I am unable to get it to work.
[2024-12-07T20:55:05Z ERROR blade_graphics::hal::platform] EGL 'eglCreatePlatformWindowSurface' code 0x300b: _eglCreateWindowSurfaceCommon
thread 'main' panicked at blade-graphics/src/gles/egl.rs:431:26:
called `Result::unwrap()` on an `Err` value: BadNativeWindow
I have tried forcing X11 and Wayland and both return the same issue. I am running on Debian GNU/Linux 12 (bookworm) x86_64 with kernel 6.1.0-28-amd64.
I have libgles-dev 1.6.0-1 installed as well as libegl-dev 1.6.0-1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, good to know, thank you for trying!
This has probably regressed recently due to #203
I'll check on a few more devices I have...
blade-graphics/src/gles/command.rs
Outdated
|
||
let target_from = match from.inner { | ||
super::TextureInner::Renderbuffer { raw } => raw, | ||
_ => panic!("Unsupported resolve between non-renderbuffers"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this just a thing we want to leave for a follow-up, or you are seeing actual technical difficulty here? I think, handling a texture here should be straightforward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nop, just unfamiliar with opengl. Found framebufferTexture2D so should be easy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think this should work
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,
);
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep! if in doubt, we can also check wgpu-hal
@@ -198,7 +202,7 @@ impl System { | |||
} | |||
} | |||
|
|||
pub fn draw(&self, pass: &mut gpu::RenderCommandEncoder) { | |||
pub fn draw(&self, pass: &mut gpu::RenderCommandEncoder, size: (u32, u32)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we just get the aspect here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used the size and sent it directly to the shader before but changed it to be the aspect ratio xP Maybe should be the input to the function now yeah since that is what is used
examples/particle/main.rs
Outdated
@@ -4,51 +4,110 @@ use blade_graphics as gpu; | |||
|
|||
mod particle; | |||
|
|||
// const SAMPLE_COUNT: u32 = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be useful to support SAMPLE_COUNT = 1
in the code here, which would mean - not creating the extra MSAA texture at all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually do it that way. Should I make the SAMPLE_COUNT parameter dynamically changable in the UI as well? Should be possible but the pipeline needs recreating as well in that case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a nice feature but it wouldn't block this PR from landing
Compared to having created this whole package for us to use and tinker with I don't think its much :) We will continue to evaluate blade for a period and my intention is to contribute if I make good changes. Can probably fix some of the open winit issues too since have been having to deal with their API changes as well for our game.. |
will re-request review when ready. Will get my hands on a mac and also try the metal as well as gles impl |
Don't know if related: For some reason I feel like the egui in blade is much more pixelated than I am used to. To the left is our game using wgpu and right is blade opened #215 |
e849398
to
a63bc0d
Compare
(force push from rebase on main) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, let's get this in!
Just one question though - how do you see this being merged? Do you want to make a pass over commits to have a reasonable (and testable) history, or I can just squash it all together.
|
||
[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"] } |
There was a problem hiding this comment.
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?
@@ -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]; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 :/
As for merging, I am totally fine with a squash. The reason I am still hesitant is I have not gotten the OpenGL version to run as the surface creation fail, so can only guess that my code is working in that path. I also still observe an issue on pipeline recreation on Mac for the new particle sample (when sample count changes), though will continue looking into it as I am working to get blade running on iOS |
closes #198
Changes
This PR introduces a
sample_count: u32
toTextureDesc
as well as amultisample_state: MultisampleState
to theRenderPipelineDesc
. Also addedalpha_to_coverage
while at it.Together with the existing
FinishOp::ResolveTo(TextureView)
, a multisampled renderpass can now be described and executedImplementations
Vulkan
The rendering attachment needs to be told to resolve
The store_op is currently always set to
DONT_CARE
as in many cases for msaa rendering the resolved texture is the only one required. Would be nice to be able to specify this behaviour in blade as well though:For the texture creation, a
SampleCountFlags
is constructed for thevk::ImageCreateInfo
:and for the pipeline, I looked at how wgpu does it and came to the following code
Metal
The metal backend already had support for the `ResolveTo` finishop so no changes needed for the renderpipeline. The creation of the renderpipeline required description though:For the texture, only specifying the sample_count was required
OpenGL ES
This was the hardest one as I am very unfamiliar with msaa in opengl, but in summary the texture needs to be created with
renderbuffer_storage_multisample
if it is a rendertarget and with aglow::TEXTURE_2D_MULTISAMPLE
target type if it is a normal texture.The sample count is then set with
tex_storage_2d_multisample
, but there is now no-longer a way to specifymip_count
so don't know if that is even possible.For the rendering, I use
blit_framebuffer
to blit the msaa texture onto the resolve target which required turning the renderbuffers into FBO:s. Currently, the FBO:s are created and deleted ad-hoc but could be saved as done in wgpu-hal. See #198Testing
The vulkan implementation has been validated on an AMD RX 6600 on debian, an integrated intel GPU on Fedora as well as a GTX 1050 on Windows and it all seems to work (the particle sample). After inspection in renderdoc the result is as expected.
The metal implementation has been tested on a Mac Mini M4 and works. However, particle example seems to break after the sample count is adjusted in runtime for some reason.
The Opengl ES implementation has not been tested!!!
Particle Example
I changed the particle example to now utilize msaa which requires it to keep a msaa texture with the desired
sample_count
available and recreated upon resizing as well as a FinishOp::ResolveTo to resolve the msaa texture to the acquired frame texture as such:Egui
Furthermore, the
blade_egui
renderer also requires information about the multisample state since it has a pipeline that now needs information about the texture it's going to render to so it's initializer now takes a sample_count as well:Let me know what needs changing or if testing fails somewhere. Especially the Opengl ES implementation as I didn't know how to run using it