From 5083f56149ad39f5f504d2c8af3159019ba1690d Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 21 Jun 2021 00:26:17 -0400 Subject: [PATCH] Add more downlevel flags, implement device opening on Gles --- Cargo.lock | 3 +- wgpu-hal/Cargo.toml | 2 +- wgpu-hal/src/gles/adapter.rs | 115 ++++++++++++++++++++++++++++++--- wgpu-hal/src/gles/egl.rs | 53 ++++++++++++++- wgpu-hal/src/gles/mod.rs | 38 ++--------- wgpu-hal/src/lib.rs | 5 +- wgpu-hal/src/metal/adapter.rs | 3 + wgpu-hal/src/vulkan/adapter.rs | 4 +- wgpu-types/src/lib.rs | 22 ++++--- 9 files changed, 186 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c43e4600..1727c05ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -690,8 +690,7 @@ dependencies = [ [[package]] name = "glow" version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945be163fdb893227410c8b44c2412dade922585b262d1daa6a7e96135217d4c" +source = "git+https://github.com/grovesNL/glow?rev=23d16276aaa8095d9ae507b1f70d0c9edfe3527f#23d16276aaa8095d9ae507b1f70d0c9edfe3527f" dependencies = [ "js-sys", "slotmap", diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 2aeea651c..95a3b2220 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -38,7 +38,7 @@ gpu-descriptor = { version = "0.1", optional = true } inplace_it = { version ="0.3.3", optional = true } renderdoc-sys = { version = "0.7.1", optional = true } # backend: Gles -glow = { version = "0.10", optional = true } +glow = { git = "https://github.com/grovesNL/glow", rev = "23d16276aaa8095d9ae507b1f70d0c9edfe3527f", optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] egl = { package = "khronos-egl", version = "4.1", features = ["dynamic"], optional = true } diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index 6ab1ad6fc..2b87939c9 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -161,10 +161,36 @@ impl super::Adapter { let vendor = gl.get_parameter_string(glow::VENDOR); let renderer = gl.get_parameter_string(glow::RENDERER); let version = gl.get_parameter_string(glow::VERSION); + log::info!("Vendor: {}", vendor); + log::info!("Renderer: {}", renderer); + log::info!("Version: {}", version); let ver = Self::parse_version(&version).ok()?; + let extensions = gl.supported_extensions(); + log::info!("Extensions: {:?}", extensions); + + let mut features = wgt::Features::empty() | wgt::Features::NON_FILL_POLYGON_MODE; + features.set( + wgt::Features::DEPTH_CLAMPING, + extensions.contains("GL_EXT_depth_clamp"), + ); + features.set(wgt::Features::VERTEX_WRITABLE_STORAGE, ver >= (3, 1)); + + let mut downlevel_flags = wgt::DownlevelFlags::empty() + | wgt::DownlevelFlags::DEVICE_LOCAL_IMAGE_COPIES + | wgt::DownlevelFlags::NON_POWER_OF_TWO_MIPMAPPED_TEXTURES + | wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES + | wgt::DownlevelFlags::COMPARISON_SAMPLERS; + downlevel_flags.set(wgt::DownlevelFlags::COMPUTE_SHADERS, ver >= (3, 1)); + downlevel_flags.set( + wgt::DownlevelFlags::FRAGMENT_WRITABLE_STORAGE, + ver >= (3, 1), + ); + downlevel_flags.set(wgt::DownlevelFlags::INDIRECT_EXECUTION, ver >= (3, 1)); + downlevel_flags.set(wgt::DownlevelFlags::BASE_VERTEX, ver >= (3, 2)); let max_texture_size = gl.get_parameter_i32(glow::MAX_TEXTURE_SIZE) as u32; + let max_texture_3d_size = gl.get_parameter_i32(glow::MAX_3D_TEXTURE_SIZE) as u32; let min_uniform_buffer_offset_alignment = gl.get_parameter_i32(glow::UNIFORM_BUFFER_OFFSET_ALIGNMENT); @@ -173,29 +199,36 @@ impl super::Adapter { } else { gl.get_parameter_i32(glow::SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT) }; + let max_uniform_buffers_per_shader_stage = + gl.get_parameter_i32(glow::MAX_VERTEX_UNIFORM_BLOCKS) + .min(gl.get_parameter_i32(glow::MAX_FRAGMENT_UNIFORM_BLOCKS)) as u32; let limits = wgt::Limits { max_texture_dimension_1d: max_texture_size, max_texture_dimension_2d: max_texture_size, - max_texture_dimension_3d: max_texture_size, + max_texture_dimension_3d: max_texture_3d_size, max_texture_array_layers: gl.get_parameter_i32(glow::MAX_ARRAY_TEXTURE_LAYERS) as u32, - max_bind_groups: 4, + max_bind_groups: crate::MAX_BIND_GROUPS as u32, max_dynamic_uniform_buffers_per_pipeline_layout: 8, max_dynamic_storage_buffers_per_pipeline_layout: 4, max_sampled_textures_per_shader_stage: 16, max_samplers_per_shader_stage: 16, max_storage_buffers_per_shader_stage: 8, max_storage_textures_per_shader_stage: 8, - max_uniform_buffers_per_shader_stage: 12, - max_uniform_buffer_binding_size: 16384, - max_storage_buffer_binding_size: 128 << 20, - max_vertex_buffers: 8, - max_vertex_attributes: 16, + max_uniform_buffers_per_shader_stage, + max_uniform_buffer_binding_size: gl.get_parameter_i32(glow::MAX_UNIFORM_BLOCK_SIZE) + as u32, + max_storage_buffer_binding_size: if ver >= (3, 1) { + gl.get_parameter_i32(glow::MAX_SHADER_STORAGE_BLOCK_SIZE) as u32 + } else { + 0 + }, + max_vertex_buffers: gl.get_parameter_i32(glow::MAX_VERTEX_ATTRIB_BINDINGS) as u32, + max_vertex_attributes: gl.get_parameter_i32(glow::MAX_VERTEX_ATTRIBS) as u32, max_vertex_buffer_array_stride: 2048, max_push_constant_size: 0, }; - let features = wgt::Features::empty(); //TODO let mut private_caps = super::PrivateCapability::empty(); private_caps.set( super::PrivateCapability::EXPLICIT_LAYOUTS_IN_SHADER, @@ -207,14 +240,16 @@ impl super::Adapter { shared: Arc::new(super::AdapterShared { context: gl, private_caps, - extra_flags: super::ExtraDownlevelFlag::empty(), }), }, info: Self::make_info(vendor, renderer), features, capabilities: crate::Capabilities { limits, - downlevel: wgt::DownlevelCapabilities::default(), //TODO + downlevel: wgt::DownlevelCapabilities { + flags: downlevel_flags, + shader_model: wgt::ShaderModel::Sm5, + }, alignments: crate::Alignments { buffer_copy_offset: wgt::BufferSize::new(4).unwrap(), buffer_copy_pitch: wgt::BufferSize::new(4).unwrap(), @@ -232,6 +267,66 @@ impl super::Adapter { } } +impl crate::Adapter for super::Adapter { + unsafe fn open( + &self, + features: wgt::Features, + ) -> Result, crate::DeviceError> { + let gl = &self.shared.context; + gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1); + let main_vao = gl.create_vertex_array().unwrap(); + gl.bind_vertex_array(Some(main_vao)); + + Ok(crate::OpenDevice { + device: super::Device { + shared: Arc::clone(&self.shared), + main_vao, + }, + queue: super::Queue { + shared: Arc::clone(&self.shared), + features, + }, + }) + } + + unsafe fn texture_format_capabilities( + &self, + format: wgt::TextureFormat, + ) -> crate::TextureFormatCapability { + crate::TextureFormatCapability::empty() //TODO + } + + unsafe fn surface_capabilities( + &self, + surface: &super::Surface, + ) -> Option { + if surface.presentable { + Some(crate::SurfaceCapabilities { + formats: vec![ + wgt::TextureFormat::Rgba8UnormSrgb, + wgt::TextureFormat::Bgra8UnormSrgb, + ], + present_modes: vec![wgt::PresentMode::Fifo], //TODO + composite_alpha_modes: vec![crate::CompositeAlphaMode::Opaque], //TODO + swap_chain_sizes: 2..=2, + current_extent: None, + extents: wgt::Extent3d { + width: 4, + height: 4, + depth_or_array_layers: 1, + }..=wgt::Extent3d { + width: 4096, + height: 4096, + depth_or_array_layers: 1, + }, + usage: crate::TextureUse::COLOR_TARGET, + }) + } else { + None + } + } +} + #[cfg(test)] mod tests { use super::super::Adapter; diff --git a/wgpu-hal/src/gles/egl.rs b/wgpu-hal/src/gles/egl.rs index bae87b106..e564bf0ed 100644 --- a/wgpu-hal/src/gles/egl.rs +++ b/wgpu-hal/src/gles/egl.rs @@ -112,6 +112,48 @@ fn choose_config( Err(crate::InstanceError) } +fn debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, message: &str) { + let source_str = match source { + glow::DEBUG_SOURCE_API => "API", + glow::DEBUG_SOURCE_WINDOW_SYSTEM => "Window System", + glow::DEBUG_SOURCE_SHADER_COMPILER => "ShaderCompiler", + glow::DEBUG_SOURCE_THIRD_PARTY => "Third Party", + glow::DEBUG_SOURCE_APPLICATION => "Application", + glow::DEBUG_SOURCE_OTHER => "Other", + _ => unreachable!(), + }; + + let log_severity = match severity { + glow::DEBUG_SEVERITY_HIGH => log::Level::Error, + glow::DEBUG_SEVERITY_MEDIUM => log::Level::Warn, + glow::DEBUG_SEVERITY_LOW => log::Level::Info, + glow::DEBUG_SEVERITY_NOTIFICATION => log::Level::Trace, + _ => unreachable!(), + }; + + let type_str = match gltype { + glow::DEBUG_TYPE_DEPRECATED_BEHAVIOR => "Deprecated Behavior", + glow::DEBUG_TYPE_ERROR => "Error", + glow::DEBUG_TYPE_MARKER => "Marker", + glow::DEBUG_TYPE_OTHER => "Other", + glow::DEBUG_TYPE_PERFORMANCE => "Performance", + glow::DEBUG_TYPE_POP_GROUP => "Pop Group", + glow::DEBUG_TYPE_PORTABILITY => "Portability", + glow::DEBUG_TYPE_PUSH_GROUP => "Push Group", + glow::DEBUG_TYPE_UNDEFINED_BEHAVIOR => "Undefined Behavior", + _ => unreachable!(), + }; + + log::log!( + log_severity, + "[{}/{}] ID {} : {}", + source_str, + type_str, + id, + message + ); +} + #[derive(Debug)] struct Inner { egl: Arc>, @@ -477,14 +519,19 @@ impl crate::Instance for Instance { ) .unwrap(); - let context = glow::Context::from_loader_function(|name| { + let gl = glow::Context::from_loader_function(|name| { inner .egl .get_proc_address(name) .map_or(ptr::null(), |p| p as *const _) }); - super::Adapter::expose(context).into_iter().collect() + if self.flags.contains(crate::InstanceFlag::DEBUG) && gl.supports_debug() { + gl.enable(glow::DEBUG_OUTPUT); + gl.debug_message_callback(debug_message_callback); + } + + super::Adapter::expose(gl).into_iter().collect() } } @@ -505,7 +552,7 @@ pub struct Surface { display: egl::Display, context: egl::Context, pbuffer: Option, - presentable: bool, + pub(super) presentable: bool, wl_window: Option<*mut raw::c_void>, swapchain: Option, } diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 51bce3504..98df9f8f9 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -26,7 +26,7 @@ impl crate::Api for Api { type Adapter = Adapter; type Device = Device; - type Queue = Context; + type Queue = Queue; type CommandEncoder = Encoder; type CommandBuffer = Resource; @@ -46,20 +46,6 @@ impl crate::Api for Api { type ComputePipeline = Resource; } -//TODO: uplift these to `DownlevelFlags` -bitflags::bitflags! { - /// Flags for features that are required for Vulkan but may not - /// be supported by legacy backends (GL/DX11). - struct ExtraDownlevelFlag: u32 { - /// Support indirect drawing and dispatching. - const INDIRECT_EXECUTION = 0x00000001; - /// Support indexed drawing with base vertex. - const BASE_VERTEX = 0x00000010; - /// Support offsets for instanced drawing with base instance. - const BASE_INSTANCE = 0x0000020; - } -} - bitflags::bitflags! { /// Flags that affect internal code paths but do not /// change the exposed feature set. @@ -88,7 +74,6 @@ struct FormatDescription { struct AdapterShared { context: glow::Context, - extra_flags: ExtraDownlevelFlag, private_caps: PrivateCapability, } @@ -98,24 +83,15 @@ pub struct Adapter { pub struct Device { shared: Arc, + main_vao: glow::VertexArray, } -impl crate::Adapter for Adapter { - unsafe fn open(&self, features: wgt::Features) -> DeviceResult> { - Err(crate::DeviceError::Lost) - } - unsafe fn texture_format_capabilities( - &self, - format: wgt::TextureFormat, - ) -> crate::TextureFormatCapability { - crate::TextureFormatCapability::empty() - } - unsafe fn surface_capabilities(&self, surface: &Surface) -> Option { - None - } +pub struct Queue { + shared: Arc, + features: wgt::Features, } -impl crate::Queue for Context { +impl crate::Queue for Queue { unsafe fn submit( &mut self, command_buffers: &[&Resource], @@ -201,7 +177,7 @@ impl crate::Device for Device { unsafe fn create_shader_module( &self, desc: &crate::ShaderModuleDescriptor, - shader: crate::NagaShader, + shader: crate::ShaderInput, ) -> Result { Ok(Resource) } diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index cf67f8320..df37f5540 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -45,11 +45,12 @@ compile_error!("Metal backend enabled on non-Apple OS. If your project is not using resolver=\"2\" in Cargo.toml, it should."); mod empty; +#[cfg(feature = "gles")] +mod gles; #[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))] mod metal; #[cfg(feature = "vulkan")] -mod vulkan;#[cfg(feature = "gles")] -mod gles; +mod vulkan; pub mod util; pub mod api { diff --git a/wgpu-hal/src/metal/adapter.rs b/wgpu-hal/src/metal/adapter.rs index ec3a6eb07..3d7cc3b2c 100644 --- a/wgpu-hal/src/metal/adapter.rs +++ b/wgpu-hal/src/metal/adapter.rs @@ -880,6 +880,9 @@ impl super::PrivateCapabilities { wgt::DownlevelFlags::COMPARISON_SAMPLERS, self.mutable_comparison_samplers, ); + downlevel + .flags + .set(wgt::DownlevelFlags::ANISOTROPIC_FILTERING, true); crate::Capabilities { limits: wgt::Limits { diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index dbf0df96e..9af802a82 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -99,7 +99,7 @@ impl PhysicalDeviceFeatures { requested_features.contains(wgt::Features::VERTEX_WRITABLE_STORAGE), ) .fragment_stores_and_atomics( - downlevel_flags.contains(wgt::DownlevelFlags::STORAGE_IMAGES), + downlevel_flags.contains(wgt::DownlevelFlags::FRAGMENT_WRITABLE_STORAGE), ) //.shader_image_gather_extended( //.shader_storage_image_extended_formats( @@ -239,7 +239,7 @@ impl PhysicalDeviceFeatures { dl_flags.set(Df::CUBE_ARRAY_TEXTURES, self.core.image_cube_array != 0); dl_flags.set(Df::ANISOTROPIC_FILTERING, self.core.sampler_anisotropy != 0); dl_flags.set( - Df::STORAGE_IMAGES, + Df::FRAGMENT_WRITABLE_STORAGE, self.core.fragment_stores_and_atomics != 0, ); diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 0f1a10751..99fffc8ef 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -619,24 +619,30 @@ bitflags::bitflags! { pub struct DownlevelFlags: u32 { /// The device supports compiling and using compute shaders. const COMPUTE_SHADERS = 0x0000_0001; - /// Supports creating storage images. - const STORAGE_IMAGES = 0x0000_0002; + /// Supports binding storage buffers and textures to fragment shaders. + const FRAGMENT_WRITABLE_STORAGE = 0x0000_0002; + /// Supports indirect drawing and dispatching. + const INDIRECT_EXECUTION = 0x0000_0004; + /// Supports non-zero `base_vertex` parameter to indexed draw calls. + const BASE_VERTEX = 0x0000_0008; + /// Supports non-zero `base_instance` parameter to draw calls. + const BASE_INSTANCE = 0x0000_0010; /// Supports reading from a depth/stencil buffer while using as a read-only depth/stencil attachment. - const READ_ONLY_DEPTH_STENCIL = 0x0000_0004; + const READ_ONLY_DEPTH_STENCIL = 0x0000_0020; /// Supports: /// - copy_image_to_image /// - copy_buffer_to_image and copy_image_to_buffer with a buffer without a MAP_* usage - const DEVICE_LOCAL_IMAGE_COPIES = 0x0000_0008; + const DEVICE_LOCAL_IMAGE_COPIES = 0x0000_0040; /// Supports textures with mipmaps which have a non power of two size. - const NON_POWER_OF_TWO_MIPMAPPED_TEXTURES = 0x0000_0010; + const NON_POWER_OF_TWO_MIPMAPPED_TEXTURES = 0x0000_0080; /// Supports textures that are cube arrays. - const CUBE_ARRAY_TEXTURES = 0x0000_0020; + const CUBE_ARRAY_TEXTURES = 0x0000_0100; /// Supports comparison samplers. - const COMPARISON_SAMPLERS = 0x0000_0040; + const COMPARISON_SAMPLERS = 0x0000_0200; /// Supports samplers with anisotropic filtering const ANISOTROPIC_FILTERING = 0x0001_0000; /// All flags are in their compliant state. - const COMPLIANT = 0x0000_007F; + const COMPLIANT = 0x0000_02FF; } }