diff --git a/Makefile b/Makefile index 7613d6dbef4..7f2c49a4439 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ else endif ifeq ($(OS),Windows_NT) - EXCLUDES+= --exclude gfx-backend-metal + EXCLUDES+= --exclude gfx-backend-metal --exclude gfx-backend-gl FEATURES_HAL=vulkan ifeq ($(TARGET),x86_64-pc-windows-gnu) # No d3d12 support on GNU windows ATM diff --git a/src/backend/gl/Cargo.toml b/src/backend/gl/Cargo.toml index 85ae51b6b8e..23518edfc8e 100644 --- a/src/backend/gl/Cargo.toml +++ b/src/backend/gl/Cargo.toml @@ -27,7 +27,7 @@ log = { version = "0.4" } gfx-hal = { path = "../../hal", version = "0.6" } auxil = { path = "../../auxil/auxil", version = "0.5", package = "gfx-auxil", features = ["spirv_cross"] } smallvec = "1.0" -glow = "0.4" +glow = "0.6.1" parking_lot = "0.11" spirv_cross = { version = "0.22", features = ["glsl"] } lazy_static = "1" diff --git a/src/backend/gl/src/device.rs b/src/backend/gl/src/device.rs index 96c8a964088..69aad45f7f1 100644 --- a/src/backend/gl/src/device.rs +++ b/src/backend/gl/src/device.rs @@ -848,7 +848,7 @@ impl d::Device for Device { match btype { n::BindingTypes::Images => { let loc = gl.get_uniform_location(name, bname); - gl.uniform_1_i32(loc, *binding as _); + gl.uniform_1_i32(loc.as_ref(), *binding as _); } n::BindingTypes::UniformBuffers => { let index = gl.get_uniform_block_index(name, bname).unwrap(); @@ -975,7 +975,7 @@ impl d::Device for Device { match btype { n::BindingTypes::Images => { let loc = gl.get_uniform_location(name, bname); - gl.uniform_1_i32(loc, *binding as _); + gl.uniform_1_i32(loc.as_ref(), *binding as _); } n::BindingTypes::UniformBuffers | n::BindingTypes::StorageBuffers => { let index = gl.get_uniform_block_index(name, bname).unwrap(); diff --git a/src/backend/gl/src/lib.rs b/src/backend/gl/src/lib.rs index 4dc8ad1f514..624ee72ed5d 100644 --- a/src/backend/gl/src/lib.rs +++ b/src/backend/gl/src/lib.rs @@ -97,7 +97,7 @@ impl GlContainer { where F: FnMut(&str) -> *const std::os::raw::c_void, { - let context = glow::Context::from_loader_function(fn_proc); + let context = unsafe { glow::Context::from_loader_function(fn_proc) }; GlContainer { context, surfman_device, diff --git a/src/backend/gl/src/queue.rs b/src/backend/gl/src/queue.rs index e4291f87e10..17242027ac2 100644 --- a/src/backend/gl/src/queue.rs +++ b/src/backend/gl/src/queue.rs @@ -2,11 +2,12 @@ use std::borrow::Borrow; use std::{mem, slice}; use glow::HasContext; +use parking_lot::Mutex; use smallvec::SmallVec; use crate::{ - command as com, device, info::LegacyFeatures, native, state, Backend, GlContext, Share, Starc, - Surface, Swapchain, + command as com, device, info::LegacyFeatures, native, state, Backend, Error, GlContext, Share, + Starc, Surface, Swapchain, }; // State caching system for command queue. @@ -62,6 +63,7 @@ pub struct CommandQueue { features: hal::Features, vao: Option, state: State, + presentation_fence: Starc<::Fence>, } impl CommandQueue { @@ -76,6 +78,7 @@ impl CommandQueue { features, vao, state: State::new(), + presentation_fence: Starc::new(std::ptr::null_mut()), } } @@ -203,10 +206,15 @@ impl CommandQueue { &data[ptr.offset as usize..(ptr.offset + ptr.size) as usize] } - fn present_by_copy(&self, swapchain: &Swapchain, index: hal::window::SwapImageIndex) { + fn present_by_copy(&self, swapchain: &Swapchain, _index: hal::window::SwapImageIndex) { let gl = &self.share.context; let extent = swapchain.extent; + // Wait for rendering to finish + unsafe { + gl.wait_sync(*self.presentation_fence, 0, glow::TIMEOUT_IGNORED); + } + #[cfg(wgl)] swapchain.make_current(); @@ -218,7 +226,7 @@ impl CommandQueue { // Use the framebuffer from the surfman context #[cfg(surfman)] - let fbo = gl + let draw_fbo = gl .surfman_device .read() .context_surface_info(&swapchain.context.read()) @@ -227,12 +235,20 @@ impl CommandQueue { .framebuffer_object; unsafe { + let tmp_read_fbo = gl.context.create_framebuffer().expect("TODO"); gl.context - .bind_framebuffer(glow::READ_FRAMEBUFFER, Some(swapchain.fbos[index as usize])); + .bind_framebuffer(glow::READ_FRAMEBUFFER, Some(tmp_read_fbo)); + gl.context.framebuffer_renderbuffer( + glow::READ_FRAMEBUFFER, + glow::COLOR_ATTACHMENT0, + glow::RENDERBUFFER, + Some(swapchain.renderbuffer), + ); + gl.context.bind_framebuffer( glow::DRAW_FRAMEBUFFER, #[cfg(surfman)] - match fbo { + match draw_fbo { 0 => None, other => Some(other), }, @@ -251,6 +267,8 @@ impl CommandQueue { glow::COLOR_BUFFER_BIT, glow::LINEAR, ); + + gl.context.delete_framebuffer(tmp_read_fbo); } // Present the surfman surface @@ -703,7 +721,7 @@ impl CommandQueue { match texture_target { glow::TEXTURE_2D => { gl.bind_texture(glow::TEXTURE_2D, Some(dst_texture)); - gl.tex_sub_image_2d_pixel_buffer_offset( + gl.tex_sub_image_2d( glow::TEXTURE_2D, data.image_layers.level as _, data.image_offset.x, @@ -712,12 +730,12 @@ impl CommandQueue { data.image_extent.height as _, texture_format, pixel_type, - data.buffer_offset as i32, + glow::PixelUnpackData::BufferOffset(data.buffer_offset as u32), ); } glow::TEXTURE_2D_ARRAY => { gl.bind_texture(glow::TEXTURE_2D_ARRAY, Some(dst_texture)); - gl.tex_sub_image_3d_pixel_buffer_offset( + gl.tex_sub_image_3d( glow::TEXTURE_2D_ARRAY, data.image_layers.level as _, data.image_offset.x, @@ -729,7 +747,7 @@ impl CommandQueue { - data.image_layers.layers.start as i32, texture_format, pixel_type, - data.buffer_offset as i32, + glow::PixelUnpackData::BufferOffset(data.buffer_offset as u32), ); } _ => unimplemented!(), @@ -756,7 +774,7 @@ impl CommandQueue { gl.active_texture(glow::TEXTURE0); gl.bind_buffer(glow::PIXEL_PACK_BUFFER, Some(dst_buffer)); gl.bind_texture(glow::TEXTURE_2D, Some(src_texture)); - gl.get_tex_image_pixel_buffer_offset( + gl.get_tex_image( glow::TEXTURE_2D, data.image_layers.level as _, //data.image_offset.x, @@ -765,7 +783,7 @@ impl CommandQueue { //data.image_extent.height as _, texture_format, pixel_type, - data.buffer_offset as i32, + glow::PixelPackData::BufferOffset(data.buffer_offset as u32), ); gl.bind_buffer(glow::PIXEL_PACK_BUFFER, None); }, @@ -921,46 +939,46 @@ impl CommandQueue { match uniform.utype { glow::FLOAT => { let data = Self::get::(data_buf, buffer)[0]; - gl.uniform_1_f32(Some((*uniform.location).clone()), data); + gl.uniform_1_f32(Some(&(*uniform.location).clone()), data); } glow::FLOAT_VEC2 => { // TODO: Remove`mut` let mut data = Self::get::<[f32; 2]>(data_buf, buffer)[0]; - gl.uniform_2_f32_slice(Some((*uniform.location).clone()), &mut data); + gl.uniform_2_f32_slice(Some(&(*uniform.location).clone()), &mut data); } glow::FLOAT_VEC3 => { // TODO: Remove`mut` let mut data = Self::get::<[f32; 3]>(data_buf, buffer)[0]; - gl.uniform_3_f32_slice(Some((*uniform.location).clone()), &mut data); + gl.uniform_3_f32_slice(Some(&(*uniform.location).clone()), &mut data); } glow::FLOAT_VEC4 => { // TODO: Remove`mut` let mut data = Self::get::<[f32; 4]>(data_buf, buffer)[0]; - gl.uniform_4_f32_slice(Some((*uniform.location).clone()), &mut data); + gl.uniform_4_f32_slice(Some(&(*uniform.location).clone()), &mut data); } glow::INT => { let data = Self::get::(data_buf, buffer)[0]; - gl.uniform_1_i32(Some((*uniform.location).clone()), data); + gl.uniform_1_i32(Some(&(*uniform.location).clone()), data); } glow::INT_VEC2 => { // TODO: Remove`mut` let mut data = Self::get::<[i32; 2]>(data_buf, buffer)[0]; - gl.uniform_2_i32_slice(Some((*uniform.location).clone()), &mut data); + gl.uniform_2_i32_slice(Some(&(*uniform.location).clone()), &mut data); } glow::INT_VEC3 => { // TODO: Remove`mut` let mut data = Self::get::<[i32; 3]>(data_buf, buffer)[0]; - gl.uniform_3_i32_slice(Some((*uniform.location).clone()), &mut data); + gl.uniform_3_i32_slice(Some(&(*uniform.location).clone()), &mut data); } glow::INT_VEC4 => { // TODO: Remove`mut` let mut data = Self::get::<[i32; 4]>(data_buf, buffer)[0]; - gl.uniform_4_i32_slice(Some((*uniform.location).clone()), &mut data); + gl.uniform_4_i32_slice(Some(&(*uniform.location).clone()), &mut data); } glow::FLOAT_MAT2 => { let data = Self::get::<[f32; 4]>(data_buf, buffer)[0]; gl.uniform_matrix_2_f32_slice( - Some((*uniform.location).clone()), + Some(&(*uniform.location).clone()), false, &data, ); @@ -968,7 +986,7 @@ impl CommandQueue { glow::FLOAT_MAT3 => { let data = Self::get::<[f32; 9]>(data_buf, buffer)[0]; gl.uniform_matrix_3_f32_slice( - Some((*uniform.location).clone()), + Some(&(*uniform.location).clone()), false, &data, ); @@ -976,7 +994,7 @@ impl CommandQueue { glow::FLOAT_MAT4 => { let data = Self::get::<[f32; 16]>(data_buf, buffer)[0]; gl.uniform_matrix_4_f32_slice( - Some((*uniform.location).clone()), + Some(&(*uniform.location).clone()), false, &data, ); @@ -1196,6 +1214,15 @@ impl hal::queue::CommandQueue for CommandQueue { } } + // Create a fence used to synchronize the finish of the rendering and + // the blit used to present on the surface. + self.presentation_fence = Starc::new( + self.share + .context + .fence_sync(glow::SYNC_GPU_COMMANDS_COMPLETE, 0) + .unwrap(), + ); + if let Some(fence) = fence { if self.share.private_caps.sync { fence.0.set(native::FenceInner::Pending(Some( diff --git a/src/backend/gl/src/window/surfman.rs b/src/backend/gl/src/window/surfman.rs index d65ffd22680..d2f227c6c44 100644 --- a/src/backend/gl/src/window/surfman.rs +++ b/src/backend/gl/src/window/surfman.rs @@ -24,6 +24,8 @@ pub struct Swapchain { pub(crate) raw_format: native::TextureFormat, /// pub(crate) fbos: ArrayVec<[native::RawFrameBuffer; 3]>, + /// Renderbuffer + pub(crate) renderbuffer: native::Renderbuffer } thread_local! { @@ -104,7 +106,7 @@ impl Instance { Surface { renderbuffer: None, swapchain: None, - context: Starc::new(RwLock::new(context)), + surface_context: Starc::new(RwLock::new(context)), } } } @@ -172,21 +174,21 @@ impl hal::Instance for Instance { let raw_surface = self .device .read() - .unbind_surface_from_context(&mut surface.context.write()) + .unbind_surface_from_context(&mut surface.surface_context.write()) .expect("TODO"); if let Some(mut raw_surface) = raw_surface { // Destroy the underlying surface self.device .read() - .destroy_surface(&mut surface.context.write(), &mut raw_surface) + .destroy_surface(&mut surface.surface_context.write(), &mut raw_surface) .expect("TODO"); } // Destroy the backing context self.device .read() - .destroy_context(&mut surface.context.write()) + .destroy_context(&mut surface.surface_context.write()) .expect("TODO"); } } @@ -194,13 +196,13 @@ impl hal::Instance for Instance { #[derive(Debug)] pub struct Surface { pub(crate) swapchain: Option, - pub(crate) context: Starc>, + pub(crate) surface_context: Starc>, renderbuffer: Option, } impl Surface { pub fn context(&self) -> Starc> { - self.context.clone() + self.surface_context.clone() } fn swapchain_formats(&self) -> Vec { @@ -239,7 +241,6 @@ impl window::PresentationSurface for Surface { config.extent.height as i32, ); - // let fbo = surface_info.framebuffer_object; let fbo = gl.create_framebuffer().unwrap(); gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(fbo)); gl.framebuffer_renderbuffer( @@ -249,12 +250,12 @@ impl window::PresentationSurface for Surface { self.renderbuffer, ); self.swapchain = Some(Swapchain { - context: self.context.clone(), + context: self.surface_context.clone(), extent: config.extent, channel: config.format.base_format().1, raw_format: desc.tex_external, fbos: iter::once(fbo).collect(), - // out_fbo: Some(surface_info.framebuffer_object), + renderbuffer: self.renderbuffer.unwrap(), }); Ok(())