mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 16:24:24 +00:00
Add more downlevel flags, implement device opening on Gles
This commit is contained in:
parent
804b17bb29
commit
5083f56149
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -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",
|
||||
|
@ -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 }
|
||||
|
@ -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<super::Api> for super::Adapter {
|
||||
unsafe fn open(
|
||||
&self,
|
||||
features: wgt::Features,
|
||||
) -> Result<crate::OpenDevice<super::Api>, 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<crate::SurfaceCapabilities> {
|
||||
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;
|
||||
|
@ -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<egl::DynamicInstance<egl::EGL1_4>>,
|
||||
@ -477,14 +519,19 @@ impl crate::Instance<super::Api> 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<egl::Surface>,
|
||||
presentable: bool,
|
||||
pub(super) presentable: bool,
|
||||
wl_window: Option<*mut raw::c_void>,
|
||||
swapchain: Option<Swapchain>,
|
||||
}
|
||||
|
@ -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<AdapterShared>,
|
||||
main_vao: glow::VertexArray,
|
||||
}
|
||||
|
||||
impl crate::Adapter<Api> for Adapter {
|
||||
unsafe fn open(&self, features: wgt::Features) -> DeviceResult<crate::OpenDevice<Api>> {
|
||||
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<crate::SurfaceCapabilities> {
|
||||
None
|
||||
}
|
||||
pub struct Queue {
|
||||
shared: Arc<AdapterShared>,
|
||||
features: wgt::Features,
|
||||
}
|
||||
|
||||
impl crate::Queue<Api> for Context {
|
||||
impl crate::Queue<Api> for Queue {
|
||||
unsafe fn submit(
|
||||
&mut self,
|
||||
command_buffers: &[&Resource],
|
||||
@ -201,7 +177,7 @@ impl crate::Device<Api> for Device {
|
||||
unsafe fn create_shader_module(
|
||||
&self,
|
||||
desc: &crate::ShaderModuleDescriptor,
|
||||
shader: crate::NagaShader,
|
||||
shader: crate::ShaderInput,
|
||||
) -> Result<Resource, crate::ShaderError> {
|
||||
Ok(Resource)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user