hal/gl: start the backend, port the Instance

This commit is contained in:
Dzmitry Malyshau
2021-06-18 00:38:27 -04:00
committed by Dzmitry Malyshau
parent 81214b21ec
commit 41bc9d0625
6 changed files with 993 additions and 3 deletions

33
Cargo.lock generated
View File

@@ -687,6 +687,18 @@ dependencies = [
"weezl",
]
[[package]]
name = "glow"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "945be163fdb893227410c8b44c2412dade922585b262d1daa6a7e96135217d4c"
dependencies = [
"js-sys",
"slotmap",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gpu-alloc"
version = "0.4.7"
@@ -846,6 +858,16 @@ dependencies = [
"winapi-build",
]
[[package]]
name = "khronos-egl"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3"
dependencies = [
"libc",
"libloading 0.7.0",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -1586,6 +1608,15 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
[[package]]
name = "slotmap"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "585cd5dffe4e9e06f6dfdf66708b70aca3f781bed561f4f667b2d9c0d4559e36"
dependencies = [
"version_check",
]
[[package]]
name = "smallvec"
version = "1.6.1"
@@ -1957,9 +1988,11 @@ dependencies = [
"env_logger",
"foreign-types",
"fxhash",
"glow",
"gpu-alloc",
"gpu-descriptor",
"inplace_it",
"khronos-egl",
"libloading 0.7.0",
"log",
"metal",

View File

@@ -15,6 +15,7 @@ license = "MIT OR Apache-2.0"
default = []
metal = ["naga/msl-out", "block", "foreign-types"]
vulkan = ["naga/spv-out", "ash", "gpu-alloc", "gpu-descriptor", "libloading", "inplace_it", "renderdoc-sys"]
gles = ["naga/glsl-out", "glow", "egl", "libloading"]
[dependencies]
bitflags = "1.0"
@@ -26,7 +27,6 @@ wgt = { package = "wgpu-types", path = "../wgpu-types" }
# backends common
arrayvec = "0.5"
fxhash = "0.2.1"
libloading = { version = "0.7", optional = true }
log = "0.4"
# backend: Metal
block = { version = "0.1", optional = true }
@@ -37,6 +37,12 @@ gpu-alloc = { version = "0.4", optional = true }
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 }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
egl = { package = "khronos-egl", version = "4.1", features = ["dynamic"], optional = true }
libloading = { version = "0.7", optional = true }
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["libloaderapi", "windef", "winuser"] }

View File

@@ -681,7 +681,9 @@ impl<A: hal::Api> Example<A> {
type Api = hal::api::Metal;
#[cfg(all(feature = "vulkan", not(feature = "metal")))]
type Api = hal::api::Vulkan;
#[cfg(all(not(feature = "vulkan"), not(feature = "metal")))]
#[cfg(all(feature = "gles", not(feature = "metal"), not(feature = "vulkan")))]
type Api = hal::api::Gles;
#[cfg(not(any(feature = "metal", feature = "vulkan", feature = "gles")))]
type Api = hal::api::Empty;
fn main() {

556
wgpu-hal/src/gles/egl.rs Normal file
View File

@@ -0,0 +1,556 @@
use glow::HasContext;
use parking_lot::Mutex;
use std::{os::raw, ptr, sync::Arc};
const EGL_PLATFORM_WAYLAND_KHR: u32 = 0x31D8;
const EGL_PLATFORM_X11_KHR: u32 = 0x31D5;
type XOpenDisplayFun =
unsafe extern "system" fn(display_name: *const raw::c_char) -> *mut raw::c_void;
type WlDisplayConnectFun =
unsafe extern "system" fn(display_name: *const raw::c_char) -> *mut raw::c_void;
type WlDisplayDisconnectFun = unsafe extern "system" fn(display: *const raw::c_void);
#[cfg(not(any(target_os = "android", target_os = "macos")))]
type WlEglWindowCreateFun = unsafe extern "system" fn(
surface: *const raw::c_void,
width: raw::c_int,
height: raw::c_int,
) -> *mut raw::c_void;
type WlEglWindowResizeFun = unsafe extern "system" fn(
window: *const raw::c_void,
width: raw::c_int,
height: raw::c_int,
dx: raw::c_int,
dy: raw::c_int,
);
type WlEglWindowDestroyFun = unsafe extern "system" fn(window: *const raw::c_void);
#[cfg(target_os = "android")]
extern "C" {
pub fn ANativeWindow_setBuffersGeometry(
window: *mut raw::c_void,
width: i32,
height: i32,
format: i32,
) -> i32;
}
fn open_x_display() -> Option<(ptr::NonNull<raw::c_void>, libloading::Library)> {
log::info!("Loading X11 library to get the current display");
unsafe {
let library = libloading::Library::new("libX11.so").ok()?;
let func: libloading::Symbol<XOpenDisplayFun> = library.get(b"XOpenDisplay").unwrap();
let result = func(ptr::null());
ptr::NonNull::new(result).map(|ptr| (ptr, library))
}
}
fn test_wayland_display() -> Option<libloading::Library> {
/* We try to connect and disconnect here to simply ensure there
* is an active wayland display available.
*/
log::info!("Loading Wayland library to get the current display");
let library = unsafe {
let client_library = libloading::Library::new("libwayland-client.so").ok()?;
let wl_display_connect: libloading::Symbol<WlDisplayConnectFun> =
client_library.get(b"wl_display_connect").unwrap();
let wl_display_disconnect: libloading::Symbol<WlDisplayDisconnectFun> =
client_library.get(b"wl_display_disconnect").unwrap();
let display = ptr::NonNull::new(wl_display_connect(ptr::null()))?;
wl_display_disconnect(display.as_ptr());
libloading::Library::new("libwayland-egl.so").ok()?
};
Some(library)
}
/// Choose GLES framebuffer configuration.
fn choose_config(
egl: &egl::DynamicInstance<egl::EGL1_4>,
display: egl::Display,
) -> Result<(egl::Config, bool), crate::InstanceError> {
//TODO: EGL_SLOW_CONFIG
let tiers = [
(
"off-screen",
&[egl::RENDERABLE_TYPE, egl::OPENGL_ES2_BIT][..],
),
("presentation", &[egl::SURFACE_TYPE, egl::WINDOW_BIT]),
#[cfg(not(target_os = "android"))]
("native-render", &[egl::NATIVE_RENDERABLE, egl::TRUE as _]),
];
let mut attributes = Vec::with_capacity(7);
for tier_max in (0..tiers.len()).rev() {
let name = tiers[tier_max].0;
log::info!("Trying {}", name);
attributes.clear();
for &(_, tier_attr) in tiers[..=tier_max].iter() {
attributes.extend_from_slice(tier_attr);
}
attributes.push(egl::NONE);
match egl.choose_first_config(display, &attributes) {
Ok(Some(config)) => {
return Ok((config, tier_max >= 1));
}
Ok(None) => {
log::warn!("No config found!");
}
Err(e) => {
log::error!("error in choose_first_config: {:?}", e);
}
}
}
Err(crate::InstanceError)
}
#[derive(Debug)]
struct Inner {
egl: Arc<egl::DynamicInstance<egl::EGL1_4>>,
version: (i32, i32),
supports_native_window: bool,
display: egl::Display,
config: egl::Config,
context: egl::Context,
/// Dummy pbuffer (1x1).
/// Required for `eglMakeCurrent` on platforms that doesn't supports `EGL_KHR_surfaceless_context`.
pbuffer: Option<egl::Surface>,
wl_display: Option<*mut raw::c_void>,
}
impl Inner {
fn create(
flags: crate::InstanceFlag,
egl: Arc<egl::DynamicInstance<egl::EGL1_4>>,
display: egl::Display,
wsi_library: Option<&libloading::Library>,
) -> Result<Self, crate::InstanceError> {
let version = egl.initialize(display).map_err(|_| crate::InstanceError)?;
let vendor = egl.query_string(Some(display), egl::VENDOR).unwrap();
let display_extensions = egl
.query_string(Some(display), egl::EXTENSIONS)
.unwrap()
.to_string_lossy();
log::info!(
"Display vendor {:?}, version {:?}, extensions: {:?}",
vendor,
version,
display_extensions
);
if log::max_level() >= log::LevelFilter::Trace {
log::trace!("Configurations:");
let config_count = egl.get_config_count(display).unwrap();
let mut configurations = Vec::with_capacity(config_count);
egl.get_configs(display, &mut configurations).unwrap();
for &config in configurations.iter() {
log::trace!("\tCONFORMANT=0x{:X}, RENDERABLE=0x{:X}, NATIVE_RENDERABLE=0x{:X}, SURFACE_TYPE=0x{:X}",
egl.get_config_attrib(display, config, egl::CONFORMANT).unwrap(),
egl.get_config_attrib(display, config, egl::RENDERABLE_TYPE).unwrap(),
egl.get_config_attrib(display, config, egl::NATIVE_RENDERABLE).unwrap(),
egl.get_config_attrib(display, config, egl::SURFACE_TYPE).unwrap(),
);
}
}
let (config, supports_native_window) = choose_config(&egl, display)?;
egl.bind_api(egl::OPENGL_ES_API).unwrap();
//TODO: make it so `Device` == EGL Context
let mut context_attributes = vec![
egl::CONTEXT_CLIENT_VERSION,
3, // Request GLES 3.0 or higher
];
if flags.contains(crate::InstanceFlag::VALIDATION)
&& wsi_library.is_none()
&& !cfg!(target_os = "android")
{
//TODO: figure out why this is needed
context_attributes.push(egl::CONTEXT_OPENGL_DEBUG);
context_attributes.push(egl::TRUE as _);
}
context_attributes.push(egl::NONE);
let context = match egl.create_context(display, config, None, &context_attributes) {
Ok(context) => context,
Err(e) => {
log::warn!("unable to create GLES 3.x context: {:?}", e);
return Err(crate::InstanceError);
}
};
// Testing if context can be binded without surface
// and creating dummy pbuffer surface if not.
let pbuffer = if version < (1, 5)
|| !display_extensions.contains("EGL_KHR_surfaceless_context")
{
let attributes = [egl::WIDTH, 1, egl::HEIGHT, 1, egl::NONE];
egl.create_pbuffer_surface(display, config, &attributes)
.map(Some)
.map_err(|e| {
log::warn!("Error in create_pbuffer_surface: {:?}", e);
crate::InstanceError
})?
} else {
log::info!("EGL_KHR_surfaceless_context is present. No need to create a dummy pbuffer");
None
};
Ok(Self {
egl,
display,
version,
supports_native_window,
config,
context,
pbuffer,
wl_display: None,
})
}
}
impl Drop for Inner {
fn drop(&mut self) {
if let Err(e) = self.egl.destroy_context(self.display, self.context) {
log::warn!("Error in destroy_context: {:?}", e);
}
if let Err(e) = self.egl.terminate(self.display) {
log::warn!("Error in terminate: {:?}", e);
}
}
}
pub struct Instance {
wsi_library: Option<libloading::Library>,
flags: crate::InstanceFlag,
inner: Mutex<Inner>,
}
unsafe impl Send for Instance {}
unsafe impl Sync for Instance {}
impl crate::Instance<super::Api> for Instance {
unsafe fn init(desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
let egl = match unsafe { egl::DynamicInstance::<egl::EGL1_4>::load_required() } {
Ok(egl) => Arc::new(egl),
Err(e) => {
log::warn!("Unable to open libEGL.so: {:?}", e);
return Err(crate::InstanceError);
}
};
let client_extensions = egl.query_string(None, egl::EXTENSIONS);
let client_ext_str = match client_extensions {
Ok(ext) => ext.to_string_lossy().into_owned(),
Err(_) => String::new(),
};
log::info!("Client extensions: {:?}", client_ext_str);
let mut wsi_library = None;
let wayland_library = if client_ext_str.contains(&"EGL_EXT_platform_wayland") {
test_wayland_display()
} else {
None
};
let x11_display_library = if client_ext_str.contains(&"EGL_EXT_platform_x11") {
open_x_display()
} else {
None
};
let display = if let (Some(library), Some(egl)) =
(wayland_library, egl.upcast::<egl::EGL1_5>())
{
log::info!("Using Wayland platform");
let display_attributes = [egl::ATTRIB_NONE];
wsi_library = Some(library);
egl.get_platform_display(
EGL_PLATFORM_WAYLAND_KHR,
egl::DEFAULT_DISPLAY,
&display_attributes,
)
.unwrap()
} else if let (Some((display, library)), Some(egl)) =
(x11_display_library, egl.upcast::<egl::EGL1_5>())
{
log::info!("Using X11 platform");
let display_attributes = [egl::ATTRIB_NONE];
wsi_library = Some(library);
egl.get_platform_display(EGL_PLATFORM_X11_KHR, display.as_ptr(), &display_attributes)
.unwrap()
} else {
log::info!("Using default platform");
egl.get_display(egl::DEFAULT_DISPLAY).unwrap()
};
let inner = Inner::create(desc.flags, egl, display, wsi_library.as_ref())?;
Ok(Instance {
wsi_library,
flags: desc.flags,
inner: Mutex::new(inner),
})
}
#[cfg_attr(target_os = "macos", allow(unused, unused_mut, unreachable_code))]
unsafe fn create_surface(
&self,
has_handle: &impl raw_window_handle::HasRawWindowHandle,
) -> Result<Surface, crate::InstanceError> {
use raw_window_handle::RawWindowHandle as Rwh;
let mut inner = self.inner.lock();
let mut wl_window = None;
#[cfg(not(any(target_os = "android", target_os = "macos")))]
let (mut temp_xlib_handle, mut temp_xcb_handle);
let native_window_ptr = match has_handle.raw_window_handle() {
#[cfg(not(any(target_os = "android", target_os = "macos")))]
Rwh::Xlib(handle) => {
temp_xlib_handle = handle.window;
&mut temp_xlib_handle as *mut _ as *mut std::ffi::c_void
}
#[cfg(not(any(target_os = "android", target_os = "macos")))]
Rwh::Xcb(handle) => {
temp_xcb_handle = handle.window;
&mut temp_xcb_handle as *mut _ as *mut std::ffi::c_void
}
#[cfg(target_os = "android")]
Rwh::Android(handle) => handle.a_native_window as *mut _ as *mut std::ffi::c_void,
#[cfg(not(any(target_os = "android", target_os = "macos")))]
Rwh::Wayland(handle) => {
/* Wayland displays are not sharable between surfaces so if the
* surface we receive from this handle is from a different
* display, we must re-initialize the context.
*
* See gfx-rs/gfx#3545
*/
if inner
.wl_display
.map(|ptr| ptr != handle.display)
.unwrap_or(true)
{
use std::ops::DerefMut;
let display_attributes = [egl::ATTRIB_NONE];
let display = inner
.egl
.upcast::<egl::EGL1_5>()
.unwrap()
.get_platform_display(
EGL_PLATFORM_WAYLAND_KHR,
handle.display,
&display_attributes,
)
.unwrap();
let new_inner =
Inner::create(inner.egl.clone(), display, self.wsi_library.as_ref())
.map_err(|_| w::InitError::UnsupportedWindowHandle)?;
let old_inner = std::mem::replace(inner.deref_mut(), new_inner);
inner.wl_display = Some(handle.display);
drop(old_inner);
}
let wl_egl_window_create: libloading::Symbol<WlEglWindowCreateFun> = self
.wsi_library
.as_ref()
.expect("unsupported window")
.get(b"wl_egl_window_create")
.unwrap();
let result = wl_egl_window_create(handle.surface, 640, 480) as *mut _
as *mut std::ffi::c_void;
wl_window = Some(result);
result
}
other => {
log::error!("Unsupported window: {:?}", other);
return Err(crate::InstanceError);
}
};
let mut attributes = vec![
egl::RENDER_BUFFER as usize,
if cfg!(target_os = "android") {
egl::BACK_BUFFER as usize
} else {
egl::SINGLE_BUFFER as usize
},
];
if inner.version >= (1, 5) {
// Always enable sRGB in EGL 1.5
attributes.push(egl::GL_COLORSPACE as usize);
attributes.push(egl::GL_COLORSPACE_SRGB as usize);
}
attributes.push(egl::ATTRIB_NONE);
let raw = if let Some(egl) = inner.egl.upcast::<egl::EGL1_5>() {
egl.create_platform_window_surface(
inner.display,
inner.config,
native_window_ptr,
&attributes,
)
.map_err(|e| {
log::warn!("Error in create_platform_window_surface: {:?}", e);
crate::InstanceError
})
} else {
let attributes_i32: Vec<i32> = attributes.iter().map(|a| (*a as i32).into()).collect();
inner
.egl
.create_window_surface(
inner.display,
inner.config,
native_window_ptr,
Some(&attributes_i32),
)
.map_err(|e| {
log::warn!("Error in create_platform_window_surface: {:?}", e);
crate::InstanceError
})
}?;
#[cfg(target_os = "android")]
{
let format = inner
.egl
.get_config_attrib(inner.display, inner.config, egl::NATIVE_VISUAL_ID)
.unwrap();
let ret = ANativeWindow_setBuffersGeometry(native_window_ptr, 0, 0, format);
if ret != 0 {
log::error!("Error returned from ANativeWindow_setBuffersGeometry");
return Err(w::InitError::UnsupportedWindowHandle);
}
}
Ok(Surface {
egl: Arc::clone(&inner.egl),
raw,
display: inner.display,
context: inner.context,
presentable: inner.supports_native_window,
pbuffer: inner.pbuffer,
wl_window,
swapchain: None,
})
}
unsafe fn destroy_surface(&self, surface: Surface) {}
unsafe fn enumerate_adapters(&self) -> Vec<crate::ExposedAdapter<super::Api>> {
Vec::new()
}
}
#[derive(Debug)]
pub struct Swapchain {
framebuffer: glow::Framebuffer,
renderbuffer: glow::Renderbuffer,
/// Extent because the window lies
extent: wgt::Extent3d,
format: super::TextureFormat,
sample_type: wgt::TextureSampleType,
}
#[derive(Debug)]
pub struct Surface {
egl: Arc<egl::DynamicInstance<egl::EGL1_4>>,
raw: egl::Surface,
display: egl::Display,
context: egl::Context,
pbuffer: Option<egl::Surface>,
presentable: bool,
wl_window: Option<*mut raw::c_void>,
swapchain: Option<Swapchain>,
}
unsafe impl Send for Surface {}
unsafe impl Sync for Surface {}
impl crate::Surface<super::Api> for Surface {
unsafe fn configure(
&mut self,
device: &super::Context,
config: &crate::SurfaceConfiguration,
) -> Result<(), crate::SurfaceError> {
self.unconfigure(device);
if let Some(window) = self.wl_window {
let library = libloading::Library::new("libwayland-egl.so").unwrap();
let wl_egl_window_resize: libloading::Symbol<WlEglWindowResizeFun> =
library.get(b"wl_egl_window_resize").unwrap();
wl_egl_window_resize(
window,
config.extent.width as i32,
config.extent.height as i32,
0,
0,
);
}
//let desc = conv::describe_format(config.format).unwrap();
let desc: super::FormatDescription = unimplemented!();
let gl: glow::Context = unimplemented!(); //&device.share.context;
let renderbuffer = gl.create_renderbuffer().unwrap();
gl.bind_renderbuffer(glow::RENDERBUFFER, Some(renderbuffer));
gl.renderbuffer_storage(
glow::RENDERBUFFER,
desc.tex_internal,
config.extent.width as _,
config.extent.height as _,
);
let framebuffer = gl.create_framebuffer().unwrap();
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(framebuffer));
gl.framebuffer_renderbuffer(
glow::READ_FRAMEBUFFER,
glow::COLOR_ATTACHMENT0,
glow::RENDERBUFFER,
Some(renderbuffer),
);
gl.bind_renderbuffer(glow::RENDERBUFFER, None);
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None);
self.swapchain = Some(Swapchain {
renderbuffer,
framebuffer,
extent: config.extent,
format: desc.tex_internal,
sample_type: wgt::TextureSampleType::Float { filterable: false },
});
Ok(())
}
unsafe fn unconfigure(&mut self, device: &super::Context) {
/*
let gl = &device.share.context;
if let Some(sc) = self.swapchain.take() {
gl.delete_renderbuffer(sc.renderbuffer);
gl.delete_framebuffer(sc.framebuffer);
}*/
}
unsafe fn acquire_texture(
&mut self,
timeout_ms: u32,
) -> Result<Option<crate::AcquiredSurfaceTexture<super::Api>>, crate::SurfaceError> {
let sc = self.swapchain.as_ref().unwrap();
//let sc_image =
// native::SwapchainImage::new(sc.renderbuffer, sc.format, sc.extent, sc.channel);
Ok(None)
}
unsafe fn discard_texture(&mut self, texture: super::Resource) {}
}

390
wgpu-hal/src/gles/mod.rs Normal file
View File

@@ -0,0 +1,390 @@
#![allow(unused_variables)]
#[cfg(not(target_arch = "wasm32"))]
mod egl;
#[cfg(not(target_arch = "wasm32"))]
use self::egl::{Instance, Surface};
use std::ops::Range;
#[derive(Clone)]
pub struct Api;
pub struct Context;
pub struct Encoder;
#[derive(Debug)]
pub struct Resource;
type DeviceResult<T> = Result<T, crate::DeviceError>;
impl crate::Api for Api {
type Instance = Instance;
type Surface = Surface;
type Adapter = Context;
type Device = Context;
type Queue = Context;
type CommandEncoder = Encoder;
type CommandBuffer = Resource;
type Buffer = Resource;
type Texture = Resource;
type SurfaceTexture = Resource;
type TextureView = Resource;
type Sampler = Resource;
type QuerySet = Resource;
type Fence = Resource;
type BindGroupLayout = Resource;
type BindGroup = Resource;
type PipelineLayout = Resource;
type ShaderModule = Resource;
type RenderPipeline = Resource;
type ComputePipeline = Resource;
}
type TextureFormat = u32;
#[derive(Debug, Clone, Copy)]
enum VertexAttribKind {
Float, // glVertexAttribPointer
Integer, // glVertexAttribIPointer
Double, // glVertexAttribLPointer
}
struct FormatDescription {
tex_internal: u32,
tex_external: u32,
data_type: u32,
num_components: u8,
va_kind: VertexAttribKind,
}
impl FormatDescription {
fn new(
tex_internal: u32,
tex_external: u32,
data_type: u32,
num_components: u8,
va_kind: VertexAttribKind,
) -> Self {
FormatDescription {
tex_internal,
tex_external,
data_type,
num_components,
va_kind,
}
}
}
impl crate::Adapter<Api> for Context {
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
}
}
impl crate::Queue<Api> for Context {
unsafe fn submit(
&mut self,
command_buffers: &[&Resource],
signal_fence: Option<(&mut Resource, crate::FenceValue)>,
) -> DeviceResult<()> {
Ok(())
}
unsafe fn present(
&mut self,
surface: &mut Surface,
texture: Resource,
) -> Result<(), crate::SurfaceError> {
Ok(())
}
}
impl crate::Device<Api> for Context {
unsafe fn exit(self) {}
unsafe fn create_buffer(&self, desc: &crate::BufferDescriptor) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_buffer(&self, buffer: Resource) {}
unsafe fn map_buffer(
&self,
buffer: &Resource,
range: crate::MemoryRange,
) -> DeviceResult<crate::BufferMapping> {
Err(crate::DeviceError::Lost)
}
unsafe fn unmap_buffer(&self, buffer: &Resource) -> DeviceResult<()> {
Ok(())
}
unsafe fn flush_mapped_ranges<I>(&self, buffer: &Resource, ranges: I) {}
unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &Resource, ranges: I) {}
unsafe fn create_texture(&self, desc: &crate::TextureDescriptor) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_texture(&self, texture: Resource) {}
unsafe fn create_texture_view(
&self,
texture: &Resource,
desc: &crate::TextureViewDescriptor,
) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_texture_view(&self, view: Resource) {}
unsafe fn create_sampler(&self, desc: &crate::SamplerDescriptor) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_sampler(&self, sampler: Resource) {}
unsafe fn create_command_encoder(
&self,
desc: &crate::CommandEncoderDescriptor<Api>,
) -> DeviceResult<Encoder> {
Ok(Encoder)
}
unsafe fn destroy_command_encoder(&self, encoder: Encoder) {}
unsafe fn create_bind_group_layout(
&self,
desc: &crate::BindGroupLayoutDescriptor,
) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_bind_group_layout(&self, bg_layout: Resource) {}
unsafe fn create_pipeline_layout(
&self,
desc: &crate::PipelineLayoutDescriptor<Api>,
) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Resource) {}
unsafe fn create_bind_group(
&self,
desc: &crate::BindGroupDescriptor<Api>,
) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_bind_group(&self, group: Resource) {}
unsafe fn create_shader_module(
&self,
desc: &crate::ShaderModuleDescriptor,
shader: crate::NagaShader,
) -> Result<Resource, crate::ShaderError> {
Ok(Resource)
}
unsafe fn destroy_shader_module(&self, module: Resource) {}
unsafe fn create_render_pipeline(
&self,
desc: &crate::RenderPipelineDescriptor<Api>,
) -> Result<Resource, crate::PipelineError> {
Ok(Resource)
}
unsafe fn destroy_render_pipeline(&self, pipeline: Resource) {}
unsafe fn create_compute_pipeline(
&self,
desc: &crate::ComputePipelineDescriptor<Api>,
) -> Result<Resource, crate::PipelineError> {
Ok(Resource)
}
unsafe fn destroy_compute_pipeline(&self, pipeline: Resource) {}
unsafe fn create_query_set(
&self,
desc: &wgt::QuerySetDescriptor<crate::Label>,
) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_query_set(&self, set: Resource) {}
unsafe fn create_fence(&self) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_fence(&self, fence: Resource) {}
unsafe fn get_fence_value(&self, fence: &Resource) -> DeviceResult<crate::FenceValue> {
Ok(0)
}
unsafe fn wait(
&self,
fence: &Resource,
value: crate::FenceValue,
timeout_ms: u32,
) -> DeviceResult<bool> {
Ok(true)
}
unsafe fn start_capture(&self) -> bool {
false
}
unsafe fn stop_capture(&self) {}
}
impl crate::CommandEncoder<Api> for Encoder {
unsafe fn begin_encoding(&mut self, label: crate::Label) -> DeviceResult<()> {
Ok(())
}
unsafe fn discard_encoding(&mut self) {}
unsafe fn end_encoding(&mut self) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn reset_all<I>(&mut self, command_buffers: I) {}
unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
where
T: Iterator<Item = crate::BufferBarrier<'a, Api>>,
{
}
unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
where
T: Iterator<Item = crate::TextureBarrier<'a, Api>>,
{
}
unsafe fn fill_buffer(&mut self, buffer: &Resource, range: crate::MemoryRange, value: u8) {}
unsafe fn copy_buffer_to_buffer<T>(&mut self, src: &Resource, dst: &Resource, regions: T) {}
unsafe fn copy_texture_to_texture<T>(
&mut self,
src: &Resource,
src_usage: crate::TextureUse,
dst: &Resource,
regions: T,
) {
}
unsafe fn copy_buffer_to_texture<T>(&mut self, src: &Resource, dst: &Resource, regions: T) {}
unsafe fn copy_texture_to_buffer<T>(
&mut self,
src: &Resource,
src_usage: crate::TextureUse,
dst: &Resource,
regions: T,
) {
}
unsafe fn begin_query(&mut self, set: &Resource, index: u32) {}
unsafe fn end_query(&mut self, set: &Resource, index: u32) {}
unsafe fn write_timestamp(&mut self, set: &Resource, index: u32) {}
unsafe fn reset_queries(&mut self, set: &Resource, range: Range<u32>) {}
unsafe fn copy_query_results(
&mut self,
set: &Resource,
range: Range<u32>,
buffer: &Resource,
offset: wgt::BufferAddress,
) {
}
// render
unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<Api>) {}
unsafe fn end_render_pass(&mut self) {}
unsafe fn set_bind_group(
&mut self,
layout: &Resource,
index: u32,
group: &Resource,
dynamic_offsets: &[wgt::DynamicOffset],
) {
}
unsafe fn set_push_constants(
&mut self,
layout: &Resource,
stages: wgt::ShaderStage,
offset: u32,
data: &[u32],
) {
}
unsafe fn insert_debug_marker(&mut self, label: &str) {}
unsafe fn begin_debug_marker(&mut self, group_label: &str) {}
unsafe fn end_debug_marker(&mut self) {}
unsafe fn set_render_pipeline(&mut self, pipeline: &Resource) {}
unsafe fn set_index_buffer<'a>(
&mut self,
binding: crate::BufferBinding<'a, Api>,
format: wgt::IndexFormat,
) {
}
unsafe fn set_vertex_buffer<'a>(&mut self, index: u32, binding: crate::BufferBinding<'a, Api>) {
}
unsafe fn set_viewport(&mut self, rect: &crate::Rect<f32>, depth_range: Range<f32>) {}
unsafe fn set_scissor_rect(&mut self, rect: &crate::Rect<u32>) {}
unsafe fn set_stencil_reference(&mut self, value: u32) {}
unsafe fn set_blend_constants(&mut self, color: &wgt::Color) {}
unsafe fn draw(
&mut self,
start_vertex: u32,
vertex_count: u32,
start_instance: u32,
instance_count: u32,
) {
}
unsafe fn draw_indexed(
&mut self,
start_index: u32,
index_count: u32,
base_vertex: i32,
start_instance: u32,
instance_count: u32,
) {
}
unsafe fn draw_indirect(
&mut self,
buffer: &Resource,
offset: wgt::BufferAddress,
draw_count: u32,
) {
}
unsafe fn draw_indexed_indirect(
&mut self,
buffer: &Resource,
offset: wgt::BufferAddress,
draw_count: u32,
) {
}
unsafe fn draw_indirect_count(
&mut self,
buffer: &Resource,
offset: wgt::BufferAddress,
count_buffer: &Resource,
count_offset: wgt::BufferAddress,
max_count: u32,
) {
}
unsafe fn draw_indexed_indirect_count(
&mut self,
buffer: &Resource,
offset: wgt::BufferAddress,
count_buffer: &Resource,
count_offset: wgt::BufferAddress,
max_count: u32,
) {
}
// compute
unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {}
unsafe fn end_compute_pass(&mut self) {}
unsafe fn set_compute_pipeline(&mut self, pipeline: &Resource) {}
unsafe fn dispatch(&mut self, count: [u32; 3]) {}
unsafe fn dispatch_indirect(&mut self, buffer: &Resource, offset: wgt::BufferAddress) {}
}

View File

@@ -48,11 +48,14 @@ mod empty;
#[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
mod metal;
#[cfg(feature = "vulkan")]
mod vulkan;
mod vulkan;#[cfg(feature = "gles")]
mod gles;
pub mod util;
pub mod api {
pub use super::empty::Api as Empty;
#[cfg(feature = "gles")]
pub use super::gles::Api as Gles;
#[cfg(feature = "metal")]
pub use super::metal::Api as Metal;
#[cfg(feature = "vulkan")]