diff --git a/CHANGELOG.md b/CHANGELOG.md index 10ea5b3b12..d01d1a4671 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index 2ae01cd2a0..8e2eda06f9 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -786,27 +786,27 @@ impl crate::Adapter for super::Adapter { &self, surface: &super::Surface, ) -> Option { - 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 diff --git a/wgpu-hal/src/gles/shaders/present.frag b/wgpu-hal/src/gles/shaders/srgb_present.frag similarity index 100% rename from wgpu-hal/src/gles/shaders/present.frag rename to wgpu-hal/src/gles/shaders/srgb_present.frag diff --git a/wgpu-hal/src/gles/shaders/present.vert b/wgpu-hal/src/gles/shaders/srgb_present.vert similarity index 100% rename from wgpu-hal/src/gles/shaders/present.vert rename to wgpu-hal/src/gles/shaders/srgb_present.vert diff --git a/wgpu-hal/src/gles/web.rs b/wgpu-hal/src/gles/web.rs index 11eeb30d23..130da483e6 100644 --- a/wgpu-hal/src/gles/web.rs +++ b/wgpu-hal/src/gles/web.rs @@ -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, texture: Option, pub(super) presentable: bool, - present_program: Option, + srgb_present_program: Option, } // 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 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() {