Enable Gles backend, add checks for downlevel flags

This commit is contained in:
Dzmitry Malyshau 2021-06-25 23:03:11 -04:00
parent cf10138c64
commit 952173efde
15 changed files with 118 additions and 92 deletions

View File

@ -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"] }

View File

@ -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) },
}
}

View File

@ -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)]

View File

@ -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<T> From<T> for RenderBundleErrorInner

View File

@ -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<G: GlobalIdentityHandlerFactory> Global<G> {
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<G: GlobalIdentityHandlerFactory> Global<G> {
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<G: GlobalIdentityHandlerFactory> Global<G> {
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

View File

@ -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<NonZeroU32>,
@ -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<id::TextureId>,
selector: &'a TextureSelector,
@ -1402,12 +1396,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
};
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<G: GlobalIdentityHandlerFactory> Global<G> {
true => mem::size_of::<wgt::DrawIndexedIndirectArgs>(),
} 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

View File

@ -254,6 +254,27 @@ pub enum CreateDeviceError {
OutOfMemory,
}
impl<A: hal::Api> Device<A> {
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<A: HalApi> Device<A> {
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
@ -312,25 +333,6 @@ impl<A: HalApi> Device<A> {
})
}
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<life::LifetimeTracker<A>>,
_token: &mut Token<'token, Self>,
@ -1038,6 +1040,14 @@ impl<A: HalApi> Device<A> {
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);

View File

@ -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<IdentityManagerFactory>) {

View File

@ -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<A: HalApi>(mask: BackendBit) -> Option<A::Instance> {
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::<hal::api::Vulkan>(backends),
#[cfg(metal)]
metal: map(Backend::Metal),
metal: init::<hal::api::Metal>(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::<hal::api::Gles>(backends),
}
}

View File

@ -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),
}

View File

@ -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 {

View File

@ -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));
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -558,11 +558,6 @@ impl crate::Device<super::Api> 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),