From 952173efdebe74756ef7f68d9c26dcb9f4d26f51 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 25 Jun 2021 23:03:11 -0400 Subject: [PATCH] Enable Gles backend, add checks for downlevel flags --- wgpu-core/Cargo.toml | 2 +- wgpu-core/build.rs | 2 +- wgpu-core/src/binding_model.rs | 4 ++- wgpu-core/src/command/bundle.rs | 15 +++++++++- wgpu-core/src/command/compute.rs | 11 +++++++ wgpu-core/src/command/render.rs | 44 +++++++++++++--------------- wgpu-core/src/device/mod.rs | 50 +++++++++++++++++++------------- wgpu-core/src/hub.rs | 4 +-- wgpu-core/src/instance.rs | 38 ++++++++++++------------ wgpu-core/src/lib.rs | 14 ++++----- wgpu-hal/src/gles/adapter.rs | 4 --- wgpu-hal/src/gles/device.rs | 9 ++++-- wgpu-hal/src/gles/egl.rs | 4 ++- wgpu-hal/src/gles/mod.rs | 4 +-- wgpu-hal/src/vulkan/device.rs | 5 ---- 15 files changed, 118 insertions(+), 92 deletions(-) diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index c226235b7..dcd72f749 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -54,7 +54,7 @@ hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["metal"] } #Note: could also enable "vulkan" for Vulkan Portability [target.'cfg(all(not(target_arch = "wasm32"), unix, not(target_os = "ios"), not(target_os = "macos")))'.dependencies] -hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["vulkan"] } +hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["vulkan", "gles"] } [target.'cfg(all(not(target_arch = "wasm32"), windows))'.dependencies] hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["vulkan"] } diff --git a/wgpu-core/build.rs b/wgpu-core/build.rs index ad2c8d836..f9cba2a41 100644 --- a/wgpu-core/build.rs +++ b/wgpu-core/build.rs @@ -11,6 +11,6 @@ fn main() { metal: { all(not(wasm), apple) }, dx12: { all(false, not(wasm), windows) }, dx11: { all(false, not(wasm), windows) }, - gl: { all(false, any(wasm, unix_wo_apple)) }, + gl: { all(not(wasm), unix_wo_apple) }, } } diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index 76be6b52a..c949d71f0 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -1,5 +1,5 @@ use crate::{ - device::{DeviceError, MissingFeatures, SHADER_STAGE_COUNT}, + device::{DeviceError, MissingDownlevelFlags, MissingFeatures, SHADER_STAGE_COUNT}, hub::Resource, id::{BindGroupLayoutId, BufferId, DeviceId, SamplerId, TextureViewId, Valid}, memory_init_tracker::MemoryInitTrackerAction, @@ -28,6 +28,8 @@ pub enum BindGroupLayoutEntryError { ArrayUnsupported, #[error(transparent)] MissingFeatures(#[from] MissingFeatures), + #[error(transparent)] + MissingDownlevelFlags(#[from] MissingDownlevelFlags), } #[derive(Clone, Debug, Error)] diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 7918d2322..cd9b9a61f 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -39,7 +39,10 @@ use crate::{ StateChange, }, conv, - device::{AttachmentData, Device, DeviceError, RenderPassContext, SHADER_STAGE_COUNT}, + device::{ + AttachmentData, Device, DeviceError, MissingDownlevelFlags, RenderPassContext, + SHADER_STAGE_COUNT, + }, hub::{GlobalIdentityHandlerFactory, HalApi, Hub, Resource, Storage, Token}, id, memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction}, @@ -403,6 +406,10 @@ impl RenderBundleEncoder { indirect: true, pipeline: state.pipeline.last_state, }; + device + .require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION) + .map_pass_err(scope)?; + let buffer = state .trackers .buffers @@ -439,6 +446,10 @@ impl RenderBundleEncoder { indirect: true, pipeline: state.pipeline.last_state, }; + device + .require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION) + .map_pass_err(scope)?; + let buffer = state .trackers .buffers @@ -1104,6 +1115,8 @@ pub(super) enum RenderBundleErrorInner { ResourceUsageConflict(#[from] UsageConflict), #[error(transparent)] Draw(#[from] DrawError), + #[error(transparent)] + MissingDownlevelFlags(#[from] MissingDownlevelFlags), } impl From for RenderBundleErrorInner diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index c698dc086..73f037460 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -5,6 +5,7 @@ use crate::{ CommandEncoderError, CommandEncoderStatus, MapPassErr, PassErrorScope, QueryUseError, StateChange, }, + device::MissingDownlevelFlags, hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token}, id, memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction}, @@ -157,6 +158,8 @@ pub enum ComputePassErrorInner { PushConstants(#[from] PushConstantUploadError), #[error(transparent)] QueryUse(#[from] QueryUseError), + #[error(transparent)] + MissingDownlevelFlags(#[from] MissingDownlevelFlags), } /// Error encountered when performing a compute pass. @@ -257,6 +260,8 @@ impl Global { let hub = A::hub(self); let mut token = Token::root(); + let (device_guard, mut token) = hub.devices.read(&mut token); + let (mut cmd_buf_guard, mut token) = hub.command_buffers.write(&mut token); let cmd_buf = CommandBuffer::get_encoder_mut(&mut *cmd_buf_guard, encoder_id).map_pass_err(scope)?; @@ -264,6 +269,8 @@ impl Global { cmd_buf.status = CommandEncoderStatus::Error; let raw = cmd_buf.encoder.open(); + let device = &device_guard[cmd_buf.device_id.value]; + #[cfg(feature = "trace")] if let Some(ref mut list) = cmd_buf.commands { list.push(crate::device::trace::Command::RunComputePass { @@ -500,6 +507,10 @@ impl Global { state.is_ready().map_pass_err(scope)?; + device + .require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION) + .map_pass_err(scope)?; + let indirect_buffer = state .trackers .buffers diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index 40d0655be..66c0965fa 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -6,7 +6,10 @@ use crate::{ PassErrorScope, QueryResetMap, QueryUseError, RenderCommand, RenderCommandError, StateChange, }, - device::{AttachmentData, RenderPassCompatibilityError, RenderPassContext}, + device::{ + AttachmentData, MissingDownlevelFlags, MissingFeatures, RenderPassCompatibilityError, + RenderPassContext, + }, hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token}, id, memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction}, @@ -419,8 +422,10 @@ pub enum RenderPassErrorInner { SampleCountMismatch { actual: u32, expected: u32 }, #[error("setting `values_offset` to be `None` is only for internal use in render bundles")] InvalidValuesOffset, - #[error("required device features not enabled: {0:?}")] - MissingDeviceFeatures(wgt::Features), + #[error(transparent)] + MissingFeatures(#[from] MissingFeatures), + #[error(transparent)] + MissingDownlevelFlags(#[from] MissingDownlevelFlags), #[error("indirect draw uses bytes {offset}..{end_offset} {} which overruns indirect buffer of size {buffer_size}", count.map_or_else(String::new, |v| format!("(using count {})", v)))] IndirectBufferOverrun { count: Option, @@ -483,17 +488,6 @@ where } } -fn check_device_features( - actual: wgt::Features, - expected: wgt::Features, -) -> Result<(), RenderPassErrorInner> { - if !actual.contains(expected) { - Err(RenderPassErrorInner::MissingDeviceFeatures(expected)) - } else { - Ok(()) - } -} - struct RenderAttachment<'a> { texture_id: &'a Stored, selector: &'a TextureSelector, @@ -1402,12 +1396,13 @@ impl Global { }; if count.is_some() { - check_device_features( - device.features, - wgt::Features::MULTI_DRAW_INDIRECT, - ) - .map_pass_err(scope)?; + device + .require_features(wgt::Features::MULTI_DRAW_INDIRECT) + .map_pass_err(scope)?; } + device + .require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION) + .map_pass_err(scope)?; let indirect_buffer = info .trackers @@ -1476,11 +1471,12 @@ impl Global { true => mem::size_of::(), } as u64; - check_device_features( - device.features, - wgt::Features::MULTI_DRAW_INDIRECT_COUNT, - ) - .map_pass_err(scope)?; + device + .require_features(wgt::Features::MULTI_DRAW_INDIRECT_COUNT) + .map_pass_err(scope)?; + device + .require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION) + .map_pass_err(scope)?; let indirect_buffer = info .trackers diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 555c0501a..56ea142f9 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -254,6 +254,27 @@ pub enum CreateDeviceError { OutOfMemory, } +impl Device { + pub(crate) fn require_features(&self, feature: wgt::Features) -> Result<(), MissingFeatures> { + if self.features.contains(feature) { + Ok(()) + } else { + Err(MissingFeatures(feature)) + } + } + + pub(crate) fn require_downlevel_flags( + &self, + flags: wgt::DownlevelFlags, + ) -> Result<(), MissingDownlevelFlags> { + if self.downlevel.flags.contains(flags) { + Ok(()) + } else { + Err(MissingDownlevelFlags(flags)) + } + } +} + impl Device { #[allow(clippy::too_many_arguments)] pub(crate) fn new( @@ -312,25 +333,6 @@ impl Device { }) } - pub(crate) fn require_features(&self, feature: wgt::Features) -> Result<(), MissingFeatures> { - if self.features.contains(feature) { - Ok(()) - } else { - Err(MissingFeatures(feature)) - } - } - - pub(crate) fn require_downlevel_flags( - &self, - flags: wgt::DownlevelFlags, - ) -> Result<(), MissingDownlevelFlags> { - if self.downlevel.flags.contains(flags) { - Ok(()) - } else { - Err(MissingDownlevelFlags(flags)) - } - } - fn lock_life_internal<'this, 'token: 'this>( tracker: &'this Mutex>, _token: &mut Token<'token, Self>, @@ -1038,6 +1040,14 @@ impl Device { if is_writable_storage && entry.visibility.contains(wgt::ShaderStage::VERTEX) { required_features |= wgt::Features::VERTEX_WRITABLE_STORAGE; } + if is_writable_storage && entry.visibility.contains(wgt::ShaderStage::FRAGMENT) { + self.require_downlevel_flags(wgt::DownlevelFlags::FRAGMENT_WRITABLE_STORAGE) + .map_err(binding_model::BindGroupLayoutEntryError::MissingDownlevelFlags) + .map_err(|error| binding_model::CreateBindGroupLayoutError::Entry { + binding: entry.binding, + error, + })?; + } self.require_features(required_features) .map_err(binding_model::BindGroupLayoutEntryError::MissingFeatures) @@ -2423,7 +2433,7 @@ pub struct MissingFeatures(pub wgt::Features); #[derive(Clone, Debug, Error)] #[error( - "Downlevel flags {0:?} are required but not supported on the device. {}", + "Downlevel flags {0:?} are required but not supported on the device.\n{}", DOWNLEVEL_ERROR_WARNING_MESSAGE )] pub struct MissingDownlevelFlags(pub wgt::DownlevelFlags); diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 85676e44b..5a27fcb6f 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -854,7 +854,7 @@ impl HalApi for hal::api::Dx11 { surface.dx11.as_mut().unwrap() } } - +*/ #[cfg(gl)] impl HalApi for hal::api::Gles { const VARIANT: Backend = Backend::Gl; @@ -864,7 +864,7 @@ impl HalApi for hal::api::Gles { fn get_surface_mut(surface: &mut Surface) -> &mut Self::Surface { surface.gl.as_mut().unwrap() } -}*/ +} #[cfg(test)] fn _test_send_sync(global: &Global) { diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index cf4a6f3ec..4e5039e2f 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -31,35 +31,35 @@ pub struct Instance { impl Instance { pub fn new(name: &str, backends: BackendBit) -> Self { - let mut flags = hal::InstanceFlag::empty(); - if cfg!(debug_assertions) { - flags |= hal::InstanceFlag::VALIDATION; - flags |= hal::InstanceFlag::DEBUG; - } - let hal_desc = hal::InstanceDescriptor { - name: "wgpu", - flags, - }; - - let map = |backend: Backend| unsafe { - if backends.contains(backend.into()) { - hal::Instance::init(&hal_desc).ok() + fn init(mask: BackendBit) -> Option { + if mask.contains(A::VARIANT.into()) { + let mut flags = hal::InstanceFlag::empty(); + if cfg!(debug_assertions) { + flags |= hal::InstanceFlag::VALIDATION; + flags |= hal::InstanceFlag::DEBUG; + } + let hal_desc = hal::InstanceDescriptor { + name: "wgpu", + flags, + }; + unsafe { hal::Instance::init(&hal_desc).ok() } } else { None } - }; + } + Self { name: name.to_string(), #[cfg(vulkan)] - vulkan: map(Backend::Vulkan), + vulkan: init::(backends), #[cfg(metal)] - metal: map(Backend::Metal), + metal: init::(backends), #[cfg(dx12)] - dx12: map(Backend::Dx12), + dx12: init(Backend::Dx12, backends), #[cfg(dx11)] - dx11: map(Backend::Dx11), + dx11: init(Backend::Dx11, backends), #[cfg(gl)] - gl: map(Backend::Gl), + gl: init::(backends), } } diff --git a/wgpu-core/src/lib.rs b/wgpu-core/src/lib.rs index f1aa612db..e8118b86b 100644 --- a/wgpu-core/src/lib.rs +++ b/wgpu-core/src/lib.rs @@ -207,14 +207,12 @@ macro_rules! gfx_select { wgt::Backend::Vulkan => $global.$method::<$crate::api::Vulkan>( $($param),* ), #[cfg(all(not(target_arch = "wasm32"), any(target_os = "ios", target_os = "macos")))] wgt::Backend::Metal => $global.$method::<$crate::api::Metal>( $($param),* ), - /* - #[cfg(all(not(target_arch = "wasm32"), windows))] - wgt::Backend::Dx12 => $global.$method::<$crate::backend::Dx12>( $($param),* ), - #[cfg(all(not(target_arch = "wasm32"), windows))] - wgt::Backend::Dx11 => $global.$method::<$crate::backend::Dx11>( $($param),* ), - #[cfg(any(target_arch = "wasm32", all(unix, not(any(target_os = "ios", target_os = "macos")))))] - wgt::Backend::Gl => $global.$method::<$crate::backend::Gl>( $($param),+ ), - */ + //#[cfg(all(not(target_arch = "wasm32"), windows))] + //wgt::Backend::Dx12 => $global.$method::<$crate::api::Dx12>( $($param),* ), + //#[cfg(all(not(target_arch = "wasm32"), windows))] + //wgt::Backend::Dx11 => $global.$method::<$crate::api::Dx11>( $($param),* ), + #[cfg(all(not(target_arch = "wasm32"), unix, not(any(target_os = "ios", target_os = "macos"))))] + wgt::Backend::Gl => $global.$method::<$crate::api::Gles>( $($param),+ ), other => panic!("Unexpected backend {:?}", other), } diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index 75db09a83..e9194d348 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -245,10 +245,6 @@ impl super::Adapter { }; let mut private_caps = super::PrivateCapability::empty(); - private_caps.set( - super::PrivateCapability::EXPLICIT_LAYOUTS_IN_SHADER, - ver >= (3, 1), - ); private_caps.set(super::PrivateCapability::MEMORY_BARRIERS, ver >= (3, 1)); Some(crate::ExposedAdapter { diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 6d7742fe9..55ad914e7 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -36,8 +36,13 @@ impl CompilationContext<'_> { let slot = self.layout.get_slot(br); let name = reflection_info.uniforms[&handle].clone(); - log::debug!("Rebind buffer: {:?} -> {}, register={:?}, slot={}", - var.name.as_ref(), &name, register, slot); + log::debug!( + "Rebind buffer: {:?} -> {}, register={:?}, slot={}", + var.name.as_ref(), + &name, + register, + slot + ); self.name_binding_map.insert(name, (register, slot)); } diff --git a/wgpu-hal/src/gles/egl.rs b/wgpu-hal/src/gles/egl.rs index 8a2bd1bff..33e9d83f3 100644 --- a/wgpu-hal/src/gles/egl.rs +++ b/wgpu-hal/src/gles/egl.rs @@ -42,6 +42,8 @@ extern "C" { } type EglLabel = *const raw::c_void; + +#[allow(clippy::upper_case_acronyms)] type EGLDEBUGPROCKHR = Option< unsafe extern "system" fn( error: egl::Enum, @@ -203,7 +205,7 @@ fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, m message ); - if log_severity == log::Level::Error { + if log_severity == log::Level::Error && false { std::process::exit(1); } } diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 17c7e9ed8..f25b7ed99 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -53,10 +53,8 @@ bitflags::bitflags! { /// Flags that affect internal code paths but do not /// change the exposed feature set. struct PrivateCapability: u32 { - /// Support explicit layouts in shader. - const EXPLICIT_LAYOUTS_IN_SHADER = 0x0001; /// Support memory barriers. - const MEMORY_BARRIERS = 0x0002; + const MEMORY_BARRIERS = 0x0001; } } diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index d2a57f799..22117dc52 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -558,11 +558,6 @@ impl crate::Device for super::Device { { let mut flags = gpu_alloc::UsageFlags::HOST_ACCESS; //TODO: find a way to use `crate::MemoryFlag::PREFER_COHERENT` - flags.set( - gpu_alloc::UsageFlags::COHERENT, - desc.memory_flags - .contains(crate::MemoryFlag::PREFER_COHERENT), - ); flags.set( gpu_alloc::UsageFlags::DOWNLOAD, desc.usage.contains(crate::BufferUse::MAP_READ),