webgl backend supports now non-srgb framebuffer (#3070)

This commit is contained in:
Andreas Reich
2022-10-09 05:48:44 +02:00
committed by GitHub
parent 81dc1e24eb
commit acadd8dad5
5 changed files with 71 additions and 40 deletions

View File

@@ -49,7 +49,13 @@ Bottom level categories:
### Added/New Features
Add the `"wgsl"` feature, to enable WGSL shaders in `wgpu-core` and `wgpu`. Enabled by default in `wgpu`. By @daxpedda in [#2890](https://github.com/gfx-rs/wgpu/pull/2890).
#### General
- Add the `"wgsl"` feature, to enable WGSL shaders in `wgpu-core` and `wgpu`. Enabled by default in `wgpu`. By @daxpedda in [#2890](https://github.com/gfx-rs/wgpu/pull/2890).
#### GLES
- Surfaces support now `TextureFormat::Rgba8Unorm` and (non-web only) `TextureFormat::Bgra8Unorm`
### Bug Fixes

View File

@@ -786,27 +786,27 @@ impl crate::Adapter<super::Api> for super::Adapter {
&self,
surface: &super::Surface,
) -> Option<crate::SurfaceCapabilities> {
let mut formats = if surface.supports_srgb() {
vec![
wgt::TextureFormat::Rgba8UnormSrgb,
#[cfg(not(target_arch = "wasm32"))]
wgt::TextureFormat::Bgra8UnormSrgb,
]
} else {
vec![
if surface.presentable {
let mut formats = vec![
wgt::TextureFormat::Rgba8Unorm,
#[cfg(not(target_arch = "wasm32"))]
wgt::TextureFormat::Bgra8Unorm,
]
};
if self
.shared
.private_caps
.contains(super::PrivateCapabilities::COLOR_BUFFER_HALF_FLOAT)
{
formats.push(wgt::TextureFormat::Rgba16Float)
}
if surface.presentable {
];
if surface.supports_srgb() {
formats.extend(&[
wgt::TextureFormat::Rgba8UnormSrgb,
#[cfg(not(target_arch = "wasm32"))]
wgt::TextureFormat::Bgra8UnormSrgb,
])
}
if self
.shared
.private_caps
.contains(super::PrivateCapabilities::COLOR_BUFFER_HALF_FLOAT)
{
formats.push(wgt::TextureFormat::Rgba16Float)
}
Some(crate::SurfaceCapabilities {
formats,
present_modes: vec![wgt::PresentMode::Fifo], //TODO

View File

@@ -43,7 +43,7 @@ impl Instance {
Ok(Surface {
webgl2_context,
present_program: None,
srgb_present_program: None,
swapchain: None,
texture: None,
presentable: true,
@@ -64,7 +64,7 @@ impl Instance {
Ok(Surface {
webgl2_context,
present_program: None,
srgb_present_program: None,
swapchain: None,
texture: None,
presentable: true,
@@ -144,7 +144,7 @@ pub struct Surface {
pub(super) swapchain: Option<Swapchain>,
texture: Option<glow::Texture>,
pub(super) presentable: bool,
present_program: Option<glow::Program>,
srgb_present_program: Option<glow::Program>,
}
// SAFE: Because web doesn't have threads ( yet )
@@ -166,35 +166,59 @@ impl Surface {
_suf_texture: super::Texture,
gl: &glow::Context,
) -> Result<(), crate::SurfaceError> {
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None);
gl.bind_sampler(0, None);
gl.active_texture(glow::TEXTURE0);
gl.bind_texture(glow::TEXTURE_2D, self.texture);
gl.use_program(self.present_program);
gl.disable(glow::DEPTH_TEST);
gl.disable(glow::STENCIL_TEST);
gl.disable(glow::SCISSOR_TEST);
gl.disable(glow::BLEND);
gl.disable(glow::CULL_FACE);
gl.draw_buffers(&[glow::BACK]);
gl.draw_arrays(glow::TRIANGLES, 0, 3);
let swapchain = self.swapchain.as_ref().ok_or(crate::SurfaceError::Other(
"need to configure surface before presenting",
))?;
if swapchain.format.describe().srgb {
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None);
gl.bind_sampler(0, None);
gl.active_texture(glow::TEXTURE0);
gl.bind_texture(glow::TEXTURE_2D, self.texture);
gl.use_program(self.srgb_present_program);
gl.disable(glow::DEPTH_TEST);
gl.disable(glow::STENCIL_TEST);
gl.disable(glow::SCISSOR_TEST);
gl.disable(glow::BLEND);
gl.disable(glow::CULL_FACE);
gl.draw_buffers(&[glow::BACK]);
gl.draw_arrays(glow::TRIANGLES, 0, 3);
} else {
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(swapchain.framebuffer));
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None);
// Note the Y-flipping here. GL's presentation is not flipped,
// but main rendering is. Therefore, we Y-flip the output positions
// in the shader, and also this blit.
gl.blit_framebuffer(
0,
swapchain.extent.height as i32,
swapchain.extent.width as i32,
0,
0,
0,
swapchain.extent.width as i32,
swapchain.extent.height as i32,
glow::COLOR_BUFFER_BIT,
glow::NEAREST,
);
}
Ok(())
}
unsafe fn create_present_program(gl: &glow::Context) -> glow::Program {
unsafe fn create_srgb_present_program(gl: &glow::Context) -> glow::Program {
let program = gl
.create_program()
.expect("Could not create shader program");
let vertex = gl
.create_shader(glow::VERTEX_SHADER)
.expect("Could not create shader");
gl.shader_source(vertex, include_str!("./shaders/present.vert"));
gl.shader_source(vertex, include_str!("./shaders/srgb_present.vert"));
gl.compile_shader(vertex);
let fragment = gl
.create_shader(glow::FRAGMENT_SHADER)
.expect("Could not create shader");
gl.shader_source(fragment, include_str!("./shaders/present.frag"));
gl.shader_source(fragment, include_str!("./shaders/srgb_present.frag"));
gl.compile_shader(fragment);
gl.attach_shader(program, vertex);
gl.attach_shader(program, fragment);
@@ -207,7 +231,8 @@ impl Surface {
}
pub fn supports_srgb(&self) -> bool {
true // WebGL only supports sRGB
// present.frag takes care of handling srgb conversion
true
}
}
@@ -224,8 +249,8 @@ impl crate::Surface<super::Api> for Surface {
gl.delete_framebuffer(swapchain.framebuffer);
}
if self.present_program.is_none() {
self.present_program = Some(Self::create_present_program(gl));
if self.srgb_present_program.is_none() && config.format.describe().srgb {
self.srgb_present_program = Some(Self::create_srgb_present_program(gl));
}
if let Some(texture) = self.texture.take() {