mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Safe surface creation (#4597)
This commit is contained in:
parent
1d7c7c8a3c
commit
addb1e081f
@ -47,6 +47,14 @@ Bottom level categories:
|
|||||||
- Log vulkan validation layer messages during instance creation and destruction: By @exrook in [#4586](https://github.com/gfx-rs/wgpu/pull/4586)
|
- Log vulkan validation layer messages during instance creation and destruction: By @exrook in [#4586](https://github.com/gfx-rs/wgpu/pull/4586)
|
||||||
- `TextureFormat::block_size` is deprecated, use `TextureFormat::block_copy_size` instead: By @wumpf in [#4647](https://github.com/gfx-rs/wgpu/pull/4647)
|
- `TextureFormat::block_size` is deprecated, use `TextureFormat::block_copy_size` instead: By @wumpf in [#4647](https://github.com/gfx-rs/wgpu/pull/4647)
|
||||||
|
|
||||||
|
#### Safe `Surface` creation
|
||||||
|
|
||||||
|
It is now possible to safely create a `wgpu::Surface` with `Surface::create_surface()` by letting `Surface` hold a lifetime to `window`.
|
||||||
|
|
||||||
|
Passing an owned value `window` to `Surface` will return a `Surface<'static>`. Shared ownership over `window` can still be achieved with e.g. an `Arc`. Alternatively a reference could be passed, which will return a `Surface<'window>`.
|
||||||
|
|
||||||
|
`Surface::create_surface_from_raw()` can be used to continue producing a `Surface<'static>` without any lifetime requirements over `window`, which also remains `unsafe`.
|
||||||
|
|
||||||
#### Naga
|
#### Naga
|
||||||
|
|
||||||
- Introduce a new `Scalar` struct type for use in Naga's IR, and update all frontend, middle, and backend code appropriately. By @jimblandy in [#4673](https://github.com/gfx-rs/wgpu/pull/4673).
|
- Introduce a new `Scalar` struct type for use in Naga's IR, and update all frontend, middle, and backend code appropriately. By @jimblandy in [#4673](https://github.com/gfx-rs/wgpu/pull/4673).
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use wgpu::{Instance, Surface, WasmNotSend, WasmNotSync};
|
use wgpu::{Instance, Surface, WasmNotSend, WasmNotSync};
|
||||||
use wgpu_test::GpuTestConfiguration;
|
use wgpu_test::GpuTestConfiguration;
|
||||||
use winit::{
|
use winit::{
|
||||||
@ -90,7 +92,7 @@ fn init_logger() {
|
|||||||
|
|
||||||
struct EventLoopWrapper {
|
struct EventLoopWrapper {
|
||||||
event_loop: EventLoop<()>,
|
event_loop: EventLoop<()>,
|
||||||
window: Window,
|
window: Arc<Window>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventLoopWrapper {
|
impl EventLoopWrapper {
|
||||||
@ -98,7 +100,7 @@ impl EventLoopWrapper {
|
|||||||
let event_loop = EventLoop::new().unwrap();
|
let event_loop = EventLoop::new().unwrap();
|
||||||
let mut builder = winit::window::WindowBuilder::new();
|
let mut builder = winit::window::WindowBuilder::new();
|
||||||
builder = builder.with_title(title);
|
builder = builder.with_title(title);
|
||||||
let window = builder.build(&event_loop).unwrap();
|
let window = Arc::new(builder.build(&event_loop).unwrap());
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
{
|
{
|
||||||
@ -121,7 +123,7 @@ impl EventLoopWrapper {
|
|||||||
///
|
///
|
||||||
/// As surface usage varies per platform, wrapping this up cleans up the event loop code.
|
/// As surface usage varies per platform, wrapping this up cleans up the event loop code.
|
||||||
struct SurfaceWrapper {
|
struct SurfaceWrapper {
|
||||||
surface: Option<wgpu::Surface>,
|
surface: Option<wgpu::Surface<'static>>,
|
||||||
config: Option<wgpu::SurfaceConfiguration>,
|
config: Option<wgpu::SurfaceConfiguration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,9 +143,9 @@ impl SurfaceWrapper {
|
|||||||
///
|
///
|
||||||
/// We cannot unconditionally create a surface here, as Android requires
|
/// We cannot unconditionally create a surface here, as Android requires
|
||||||
/// us to wait until we recieve the `Resumed` event to do so.
|
/// us to wait until we recieve the `Resumed` event to do so.
|
||||||
fn pre_adapter(&mut self, instance: &Instance, window: &Window) {
|
fn pre_adapter(&mut self, instance: &Instance, window: Arc<Window>) {
|
||||||
if cfg!(target_arch = "wasm32") {
|
if cfg!(target_arch = "wasm32") {
|
||||||
self.surface = Some(unsafe { instance.create_surface(&window).unwrap() });
|
self.surface = Some(instance.create_surface(window).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +165,7 @@ impl SurfaceWrapper {
|
|||||||
/// On all native platforms, this is where we create the surface.
|
/// On all native platforms, this is where we create the surface.
|
||||||
///
|
///
|
||||||
/// Additionally, we configure the surface based on the (now valid) window size.
|
/// Additionally, we configure the surface based on the (now valid) window size.
|
||||||
fn resume(&mut self, context: &ExampleContext, window: &Window, srgb: bool) {
|
fn resume(&mut self, context: &ExampleContext, window: Arc<Window>, srgb: bool) {
|
||||||
// Window size is only actually valid after we enter the event loop.
|
// Window size is only actually valid after we enter the event loop.
|
||||||
let window_size = window.inner_size();
|
let window_size = window.inner_size();
|
||||||
let width = window_size.width.max(1);
|
let width = window_size.width.max(1);
|
||||||
@ -173,7 +175,7 @@ impl SurfaceWrapper {
|
|||||||
|
|
||||||
// We didn't create the surface in pre_adapter, so we need to do so now.
|
// We didn't create the surface in pre_adapter, so we need to do so now.
|
||||||
if !cfg!(target_arch = "wasm32") {
|
if !cfg!(target_arch = "wasm32") {
|
||||||
self.surface = Some(unsafe { context.instance.create_surface(&window).unwrap() });
|
self.surface = Some(context.instance.create_surface(window).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// From here on, self.surface should be Some.
|
// From here on, self.surface should be Some.
|
||||||
@ -252,7 +254,7 @@ struct ExampleContext {
|
|||||||
}
|
}
|
||||||
impl ExampleContext {
|
impl ExampleContext {
|
||||||
/// Initializes the example context.
|
/// Initializes the example context.
|
||||||
async fn init_async<E: Example>(surface: &mut SurfaceWrapper, window: &Window) -> Self {
|
async fn init_async<E: Example>(surface: &mut SurfaceWrapper, window: Arc<Window>) -> Self {
|
||||||
log::info!("Initializing wgpu...");
|
log::info!("Initializing wgpu...");
|
||||||
|
|
||||||
let backends = wgpu::util::backend_bits_from_env().unwrap_or_default();
|
let backends = wgpu::util::backend_bits_from_env().unwrap_or_default();
|
||||||
@ -357,8 +359,7 @@ async fn start<E: Example>(title: &str) {
|
|||||||
init_logger();
|
init_logger();
|
||||||
let window_loop = EventLoopWrapper::new(title);
|
let window_loop = EventLoopWrapper::new(title);
|
||||||
let mut surface = SurfaceWrapper::new();
|
let mut surface = SurfaceWrapper::new();
|
||||||
let context = ExampleContext::init_async::<E>(&mut surface, &window_loop.window).await;
|
let context = ExampleContext::init_async::<E>(&mut surface, window_loop.window.clone()).await;
|
||||||
|
|
||||||
let mut frame_counter = FrameCounter::new();
|
let mut frame_counter = FrameCounter::new();
|
||||||
|
|
||||||
// We wait to create the example until we have a valid surface.
|
// We wait to create the example until we have a valid surface.
|
||||||
@ -384,7 +385,7 @@ async fn start<E: Example>(title: &str) {
|
|||||||
|
|
||||||
match event {
|
match event {
|
||||||
ref e if SurfaceWrapper::start_condition(e) => {
|
ref e if SurfaceWrapper::start_condition(e) => {
|
||||||
surface.resume(&context, &window_loop.window, E::SRGB);
|
surface.resume(&context, window_loop.window.clone(), E::SRGB);
|
||||||
|
|
||||||
// If we haven't created the example yet, do so now.
|
// If we haven't created the example yet, do so now.
|
||||||
if example.is_none() {
|
if example.is_none() {
|
||||||
|
|||||||
@ -12,7 +12,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
|||||||
|
|
||||||
let instance = wgpu::Instance::default();
|
let instance = wgpu::Instance::default();
|
||||||
|
|
||||||
let surface = unsafe { instance.create_surface(&window) }.unwrap();
|
let surface = instance.create_surface(&window).unwrap();
|
||||||
let adapter = instance
|
let adapter = instance
|
||||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
power_preference: wgpu::PowerPreference::default(),
|
power_preference: wgpu::PowerPreference::default(),
|
||||||
@ -84,6 +84,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
|||||||
|
|
||||||
surface.configure(&device, &config);
|
surface.configure(&device, &config);
|
||||||
|
|
||||||
|
let window = &window;
|
||||||
event_loop
|
event_loop
|
||||||
.run(move |event, target| {
|
.run(move |event, target| {
|
||||||
// Have the closure take ownership of the resources.
|
// Have the closure take ownership of the resources.
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#![cfg_attr(target_arch = "wasm32", allow(dead_code))]
|
#![cfg_attr(target_arch = "wasm32", allow(dead_code))]
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, sync::Arc};
|
||||||
use winit::{
|
use winit::{
|
||||||
event::{Event, WindowEvent},
|
event::{Event, WindowEvent},
|
||||||
event_loop::EventLoop,
|
event_loop::EventLoop,
|
||||||
@ -8,9 +8,9 @@ use winit::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ViewportDesc {
|
struct ViewportDesc {
|
||||||
window: Window,
|
window: Arc<Window>,
|
||||||
background: wgpu::Color,
|
background: wgpu::Color,
|
||||||
surface: wgpu::Surface,
|
surface: wgpu::Surface<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Viewport {
|
struct Viewport {
|
||||||
@ -19,8 +19,8 @@ struct Viewport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ViewportDesc {
|
impl ViewportDesc {
|
||||||
fn new(window: Window, background: wgpu::Color, instance: &wgpu::Instance) -> Self {
|
fn new(window: Arc<Window>, background: wgpu::Color, instance: &wgpu::Instance) -> Self {
|
||||||
let surface = unsafe { instance.create_surface(&window) }.unwrap();
|
let surface = instance.create_surface(window.clone()).unwrap();
|
||||||
Self {
|
Self {
|
||||||
window,
|
window,
|
||||||
background,
|
background,
|
||||||
@ -62,7 +62,7 @@ impl Viewport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) {
|
async fn run(event_loop: EventLoop<()>, viewports: Vec<(Arc<Window>, wgpu::Color)>) {
|
||||||
let instance = wgpu::Instance::default();
|
let instance = wgpu::Instance::default();
|
||||||
let viewports: Vec<_> = viewports
|
let viewports: Vec<_> = viewports
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -180,6 +180,7 @@ fn main() {
|
|||||||
.with_inner_size(winit::dpi::PhysicalSize::new(WINDOW_SIZE, WINDOW_SIZE))
|
.with_inner_size(winit::dpi::PhysicalSize::new(WINDOW_SIZE, WINDOW_SIZE))
|
||||||
.build(&event_loop)
|
.build(&event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let window = Arc::new(window);
|
||||||
window.set_outer_position(winit::dpi::PhysicalPosition::new(
|
window.set_outer_position(winit::dpi::PhysicalPosition::new(
|
||||||
WINDOW_PADDING + column * WINDOW_OFFSET,
|
WINDOW_PADDING + column * WINDOW_OFFSET,
|
||||||
WINDOW_PADDING + row * (WINDOW_OFFSET + WINDOW_TITLEBAR),
|
WINDOW_PADDING + row * (WINDOW_OFFSET + WINDOW_TITLEBAR),
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
//! The usage of the uniform buffer within the shader itself is pretty self-explanatory given
|
//! The usage of the uniform buffer within the shader itself is pretty self-explanatory given
|
||||||
//! some understanding of WGSL.
|
//! some understanding of WGSL.
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
// We won't bring StorageBuffer into scope as that might be too easy to confuse
|
// We won't bring StorageBuffer into scope as that might be too easy to confuse
|
||||||
// with actual GPU-allocated WGPU storage buffers.
|
// with actual GPU-allocated WGPU storage buffers.
|
||||||
use encase::ShaderType;
|
use encase::ShaderType;
|
||||||
@ -84,8 +85,8 @@ impl Default for AppState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct WgpuContext {
|
struct WgpuContext {
|
||||||
pub window: Window,
|
pub window: Arc<Window>,
|
||||||
pub surface: wgpu::Surface,
|
pub surface: wgpu::Surface<'static>,
|
||||||
pub surface_config: wgpu::SurfaceConfiguration,
|
pub surface_config: wgpu::SurfaceConfiguration,
|
||||||
pub device: wgpu::Device,
|
pub device: wgpu::Device,
|
||||||
pub queue: wgpu::Queue,
|
pub queue: wgpu::Queue,
|
||||||
@ -95,11 +96,11 @@ struct WgpuContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WgpuContext {
|
impl WgpuContext {
|
||||||
async fn new(window: Window) -> WgpuContext {
|
async fn new(window: Arc<Window>) -> WgpuContext {
|
||||||
let size = window.inner_size();
|
let size = window.inner_size();
|
||||||
|
|
||||||
let instance = wgpu::Instance::default();
|
let instance = wgpu::Instance::default();
|
||||||
let surface = unsafe { instance.create_surface(&window) }.unwrap();
|
let surface = instance.create_surface(window.clone()).unwrap();
|
||||||
let adapter = instance
|
let adapter = instance
|
||||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
power_preference: wgpu::PowerPreference::HighPerformance,
|
power_preference: wgpu::PowerPreference::HighPerformance,
|
||||||
@ -223,7 +224,7 @@ impl WgpuContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(event_loop: EventLoop<()>, window: Window) {
|
async fn run(event_loop: EventLoop<()>, window: Arc<Window>) {
|
||||||
let mut wgpu_context = Some(WgpuContext::new(window).await);
|
let mut wgpu_context = Some(WgpuContext::new(window).await);
|
||||||
// (6)
|
// (6)
|
||||||
let mut state = Some(AppState::default());
|
let mut state = Some(AppState::default());
|
||||||
@ -351,6 +352,7 @@ fn main() {
|
|||||||
.with_inner_size(winit::dpi::LogicalSize::new(900, 900))
|
.with_inner_size(winit::dpi::LogicalSize::new(900, 900))
|
||||||
.build(&event_loop)
|
.build(&event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let window = Arc::new(window);
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
{
|
{
|
||||||
env_logger::builder().format_timestamp_nanos().init();
|
env_logger::builder().format_timestamp_nanos().init();
|
||||||
|
|||||||
@ -1109,7 +1109,7 @@ impl crate::context::Context for Context {
|
|||||||
|
|
||||||
fn instance_request_adapter(
|
fn instance_request_adapter(
|
||||||
&self,
|
&self,
|
||||||
options: &crate::RequestAdapterOptions<'_>,
|
options: &crate::RequestAdapterOptions<'_, '_>,
|
||||||
) -> Self::RequestAdapterFuture {
|
) -> Self::RequestAdapterFuture {
|
||||||
//TODO: support this check, return `None` if the flag is not set.
|
//TODO: support this check, return `None` if the flag is not set.
|
||||||
// It's not trivial, since we need the Future logic to have this check,
|
// It's not trivial, since we need the Future logic to have this check,
|
||||||
|
|||||||
@ -103,7 +103,7 @@ pub trait Context: Debug + WasmNotSend + WasmNotSync + Sized {
|
|||||||
) -> Result<(Self::SurfaceId, Self::SurfaceData), crate::CreateSurfaceError>;
|
) -> Result<(Self::SurfaceId, Self::SurfaceData), crate::CreateSurfaceError>;
|
||||||
fn instance_request_adapter(
|
fn instance_request_adapter(
|
||||||
&self,
|
&self,
|
||||||
options: &RequestAdapterOptions<'_>,
|
options: &RequestAdapterOptions<'_, '_>,
|
||||||
) -> Self::RequestAdapterFuture;
|
) -> Self::RequestAdapterFuture;
|
||||||
fn adapter_request_device(
|
fn adapter_request_device(
|
||||||
&self,
|
&self,
|
||||||
@ -1239,7 +1239,7 @@ pub(crate) trait DynContext: Debug + WasmNotSend + WasmNotSync {
|
|||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn instance_request_adapter(
|
fn instance_request_adapter(
|
||||||
&self,
|
&self,
|
||||||
options: &RequestAdapterOptions<'_>,
|
options: &RequestAdapterOptions<'_, '_>,
|
||||||
) -> Pin<InstanceRequestAdapterFuture>;
|
) -> Pin<InstanceRequestAdapterFuture>;
|
||||||
fn adapter_request_device(
|
fn adapter_request_device(
|
||||||
&self,
|
&self,
|
||||||
@ -2103,7 +2103,7 @@ where
|
|||||||
|
|
||||||
fn instance_request_adapter(
|
fn instance_request_adapter(
|
||||||
&self,
|
&self,
|
||||||
options: &RequestAdapterOptions<'_>,
|
options: &RequestAdapterOptions<'_, '_>,
|
||||||
) -> Pin<InstanceRequestAdapterFuture> {
|
) -> Pin<InstanceRequestAdapterFuture> {
|
||||||
let future: T::RequestAdapterFuture = Context::instance_request_adapter(self, options);
|
let future: T::RequestAdapterFuture = Context::instance_request_adapter(self, options);
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
|
|||||||
102
wgpu/src/lib.rs
102
wgpu/src/lib.rs
@ -27,6 +27,7 @@ use std::{
|
|||||||
use context::{Context, DeviceRequest, DynContext, ObjectId};
|
use context::{Context, DeviceRequest, DynContext, ObjectId};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
|
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||||
pub use wgt::{
|
pub use wgt::{
|
||||||
AdapterInfo, AddressMode, AstcBlock, AstcChannel, Backend, Backends, BindGroupLayoutEntry,
|
AdapterInfo, AddressMode, AstcBlock, AstcChannel, Backend, Backends, BindGroupLayoutEntry,
|
||||||
BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress,
|
BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress,
|
||||||
@ -379,6 +380,10 @@ impl Drop for Sampler {
|
|||||||
pub type SurfaceConfiguration = wgt::SurfaceConfiguration<Vec<TextureFormat>>;
|
pub type SurfaceConfiguration = wgt::SurfaceConfiguration<Vec<TextureFormat>>;
|
||||||
static_assertions::assert_impl_all!(SurfaceConfiguration: Send, Sync);
|
static_assertions::assert_impl_all!(SurfaceConfiguration: Send, Sync);
|
||||||
|
|
||||||
|
trait WgpuSurfaceRequirement: WasmNotSend + WasmNotSync {}
|
||||||
|
|
||||||
|
impl<T: WasmNotSend + WasmNotSync> WgpuSurfaceRequirement for T {}
|
||||||
|
|
||||||
/// Handle to a presentable surface.
|
/// Handle to a presentable surface.
|
||||||
///
|
///
|
||||||
/// A `Surface` represents a platform-specific surface (e.g. a window) onto which rendered images may
|
/// A `Surface` represents a platform-specific surface (e.g. a window) onto which rendered images may
|
||||||
@ -387,9 +392,9 @@ static_assertions::assert_impl_all!(SurfaceConfiguration: Send, Sync);
|
|||||||
/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
|
/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
|
||||||
/// [`GPUCanvasContext`](https://gpuweb.github.io/gpuweb/#canvas-context)
|
/// [`GPUCanvasContext`](https://gpuweb.github.io/gpuweb/#canvas-context)
|
||||||
/// serves a similar role.
|
/// serves a similar role.
|
||||||
#[derive(Debug)]
|
pub struct Surface<'window> {
|
||||||
pub struct Surface {
|
|
||||||
context: Arc<C>,
|
context: Arc<C>,
|
||||||
|
_surface: Option<Box<dyn WgpuSurfaceRequirement + 'window>>,
|
||||||
id: ObjectId,
|
id: ObjectId,
|
||||||
data: Box<Data>,
|
data: Box<Data>,
|
||||||
// Stores the latest `SurfaceConfiguration` that was set using `Surface::configure`.
|
// Stores the latest `SurfaceConfiguration` that was set using `Surface::configure`.
|
||||||
@ -400,6 +405,28 @@ pub struct Surface {
|
|||||||
// been created is is additionally wrapped in an option.
|
// been created is is additionally wrapped in an option.
|
||||||
config: Mutex<Option<SurfaceConfiguration>>,
|
config: Mutex<Option<SurfaceConfiguration>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This custom implementation is required because [`Surface::_surface`] doesn't
|
||||||
|
// require [`Debug`](fmt::Debug), which we should not require from the user.
|
||||||
|
impl<'window> fmt::Debug for Surface<'window> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("Surface")
|
||||||
|
.field("context", &self.context)
|
||||||
|
.field(
|
||||||
|
"_surface",
|
||||||
|
&if self._surface.is_some() {
|
||||||
|
"Some"
|
||||||
|
} else {
|
||||||
|
"None"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.field("id", &self.id)
|
||||||
|
.field("data", &self.data)
|
||||||
|
.field("config", &self.config)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
not(target_arch = "wasm32"),
|
not(target_arch = "wasm32"),
|
||||||
all(
|
all(
|
||||||
@ -409,7 +436,7 @@ pub struct Surface {
|
|||||||
))]
|
))]
|
||||||
static_assertions::assert_impl_all!(Surface: Send, Sync);
|
static_assertions::assert_impl_all!(Surface: Send, Sync);
|
||||||
|
|
||||||
impl Drop for Surface {
|
impl Drop for Surface<'_> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !thread::panicking() {
|
if !thread::panicking() {
|
||||||
self.context.surface_drop(&self.id, self.data.as_ref())
|
self.context.surface_drop(&self.id, self.data.as_ref())
|
||||||
@ -1171,7 +1198,7 @@ pub use wgt::RequestAdapterOptions as RequestAdapterOptionsBase;
|
|||||||
///
|
///
|
||||||
/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
|
/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
|
||||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
|
/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
|
||||||
pub type RequestAdapterOptions<'a> = RequestAdapterOptionsBase<&'a Surface>;
|
pub type RequestAdapterOptions<'a, 'b> = RequestAdapterOptionsBase<&'a Surface<'b>>;
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
not(target_arch = "wasm32"),
|
not(target_arch = "wasm32"),
|
||||||
all(
|
all(
|
||||||
@ -1920,11 +1947,9 @@ impl Instance {
|
|||||||
/// If the specified display and window handle are not supported by any of the backends, then the surface
|
/// If the specified display and window handle are not supported by any of the backends, then the surface
|
||||||
/// will not be supported by any adapters.
|
/// will not be supported by any adapters.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// If a reference is passed in `window`, the returned [`Surface`] will
|
||||||
///
|
/// hold a lifetime to it. Owned values will return a [`Surface<'static>`]
|
||||||
/// - `raw_window_handle` must be a valid object to create a surface upon.
|
/// instead.
|
||||||
/// - `raw_window_handle` must remain valid until after the returned [`Surface`] is
|
|
||||||
/// dropped.
|
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
@ -1936,12 +1961,37 @@ impl Instance {
|
|||||||
/// - On macOS/Metal: will panic if not called on the main thread.
|
/// - On macOS/Metal: will panic if not called on the main thread.
|
||||||
/// - On web: will panic if the `raw_window_handle` does not properly refer to a
|
/// - On web: will panic if the `raw_window_handle` does not properly refer to a
|
||||||
/// canvas element.
|
/// canvas element.
|
||||||
pub unsafe fn create_surface<
|
pub fn create_surface<'window, W>(
|
||||||
W: raw_window_handle::HasWindowHandle + raw_window_handle::HasDisplayHandle,
|
&self,
|
||||||
>(
|
window: W,
|
||||||
|
) -> Result<Surface<'window>, CreateSurfaceError>
|
||||||
|
where
|
||||||
|
W: HasWindowHandle + HasDisplayHandle + WasmNotSend + WasmNotSync + 'window,
|
||||||
|
{
|
||||||
|
let mut surface = unsafe { self.create_surface_from_raw(&window) }?;
|
||||||
|
surface._surface = Some(Box::new(window));
|
||||||
|
Ok(surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An alternative version to [`create_surface()`](Self::create_surface)
|
||||||
|
/// which has no lifetime requirements to `window` and doesn't require
|
||||||
|
/// [`Send`] or [`Sync`] (on non-Wasm targets). This makes it `unsafe`
|
||||||
|
/// instead and always returns a [`Surface<'static>`].
|
||||||
|
///
|
||||||
|
/// See [`create_surface()`](Self::create_surface) for more details.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - `raw_window_handle` must be a valid object to create a surface upon.
|
||||||
|
/// - `raw_window_handle` must remain valid until after the returned [`Surface`] is
|
||||||
|
/// dropped.
|
||||||
|
pub unsafe fn create_surface_from_raw<W>(
|
||||||
&self,
|
&self,
|
||||||
window: &W,
|
window: &W,
|
||||||
) -> Result<Surface, CreateSurfaceError> {
|
) -> Result<Surface<'static>, CreateSurfaceError>
|
||||||
|
where
|
||||||
|
W: HasWindowHandle + HasDisplayHandle,
|
||||||
|
{
|
||||||
let raw_display_handle = window
|
let raw_display_handle = window
|
||||||
.display_handle()
|
.display_handle()
|
||||||
.map_err(|e| CreateSurfaceError {
|
.map_err(|e| CreateSurfaceError {
|
||||||
@ -1963,6 +2013,7 @@ impl Instance {
|
|||||||
}?;
|
}?;
|
||||||
Ok(Surface {
|
Ok(Surface {
|
||||||
context: Arc::clone(&self.context),
|
context: Arc::clone(&self.context),
|
||||||
|
_surface: None,
|
||||||
id,
|
id,
|
||||||
data,
|
data,
|
||||||
config: Mutex::new(None),
|
config: Mutex::new(None),
|
||||||
@ -1978,7 +2029,7 @@ impl Instance {
|
|||||||
pub unsafe fn create_surface_from_core_animation_layer(
|
pub unsafe fn create_surface_from_core_animation_layer(
|
||||||
&self,
|
&self,
|
||||||
layer: *mut std::ffi::c_void,
|
layer: *mut std::ffi::c_void,
|
||||||
) -> Surface {
|
) -> Surface<'static> {
|
||||||
let surface = unsafe {
|
let surface = unsafe {
|
||||||
self.context
|
self.context
|
||||||
.as_any()
|
.as_any()
|
||||||
@ -1988,6 +2039,7 @@ impl Instance {
|
|||||||
};
|
};
|
||||||
Surface {
|
Surface {
|
||||||
context: Arc::clone(&self.context),
|
context: Arc::clone(&self.context),
|
||||||
|
_surface: None,
|
||||||
id: ObjectId::from(surface.id()),
|
id: ObjectId::from(surface.id()),
|
||||||
data: Box::new(surface),
|
data: Box::new(surface),
|
||||||
config: Mutex::new(None),
|
config: Mutex::new(None),
|
||||||
@ -2000,7 +2052,10 @@ impl Instance {
|
|||||||
///
|
///
|
||||||
/// - visual must be a valid IDCompositionVisual to create a surface upon.
|
/// - visual must be a valid IDCompositionVisual to create a surface upon.
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub unsafe fn create_surface_from_visual(&self, visual: *mut std::ffi::c_void) -> Surface {
|
pub unsafe fn create_surface_from_visual(
|
||||||
|
&self,
|
||||||
|
visual: *mut std::ffi::c_void,
|
||||||
|
) -> Surface<'static> {
|
||||||
let surface = unsafe {
|
let surface = unsafe {
|
||||||
self.context
|
self.context
|
||||||
.as_any()
|
.as_any()
|
||||||
@ -2010,6 +2065,7 @@ impl Instance {
|
|||||||
};
|
};
|
||||||
Surface {
|
Surface {
|
||||||
context: Arc::clone(&self.context),
|
context: Arc::clone(&self.context),
|
||||||
|
_surface: None,
|
||||||
id: ObjectId::from(surface.id()),
|
id: ObjectId::from(surface.id()),
|
||||||
data: Box::new(surface),
|
data: Box::new(surface),
|
||||||
config: Mutex::new(None),
|
config: Mutex::new(None),
|
||||||
@ -2025,7 +2081,7 @@ impl Instance {
|
|||||||
pub unsafe fn create_surface_from_surface_handle(
|
pub unsafe fn create_surface_from_surface_handle(
|
||||||
&self,
|
&self,
|
||||||
surface_handle: *mut std::ffi::c_void,
|
surface_handle: *mut std::ffi::c_void,
|
||||||
) -> Surface {
|
) -> Surface<'static> {
|
||||||
let surface = unsafe {
|
let surface = unsafe {
|
||||||
self.context
|
self.context
|
||||||
.as_any()
|
.as_any()
|
||||||
@ -2035,6 +2091,7 @@ impl Instance {
|
|||||||
};
|
};
|
||||||
Surface {
|
Surface {
|
||||||
context: Arc::clone(&self.context),
|
context: Arc::clone(&self.context),
|
||||||
|
_surface: None,
|
||||||
id: ObjectId::from(surface.id()),
|
id: ObjectId::from(surface.id()),
|
||||||
data: Box::new(surface),
|
data: Box::new(surface),
|
||||||
config: Mutex::new(None),
|
config: Mutex::new(None),
|
||||||
@ -2050,7 +2107,7 @@ impl Instance {
|
|||||||
pub unsafe fn create_surface_from_swap_chain_panel(
|
pub unsafe fn create_surface_from_swap_chain_panel(
|
||||||
&self,
|
&self,
|
||||||
swap_chain_panel: *mut std::ffi::c_void,
|
swap_chain_panel: *mut std::ffi::c_void,
|
||||||
) -> Surface {
|
) -> Surface<'static> {
|
||||||
let surface = unsafe {
|
let surface = unsafe {
|
||||||
self.context
|
self.context
|
||||||
.as_any()
|
.as_any()
|
||||||
@ -2060,6 +2117,7 @@ impl Instance {
|
|||||||
};
|
};
|
||||||
Surface {
|
Surface {
|
||||||
context: Arc::clone(&self.context),
|
context: Arc::clone(&self.context),
|
||||||
|
_surface: None,
|
||||||
id: ObjectId::from(surface.id()),
|
id: ObjectId::from(surface.id()),
|
||||||
data: Box::new(surface),
|
data: Box::new(surface),
|
||||||
config: Mutex::new(None),
|
config: Mutex::new(None),
|
||||||
@ -2079,7 +2137,7 @@ impl Instance {
|
|||||||
pub fn create_surface_from_canvas(
|
pub fn create_surface_from_canvas(
|
||||||
&self,
|
&self,
|
||||||
canvas: web_sys::HtmlCanvasElement,
|
canvas: web_sys::HtmlCanvasElement,
|
||||||
) -> Result<Surface, CreateSurfaceError> {
|
) -> Result<Surface<'static>, CreateSurfaceError> {
|
||||||
let surface = self
|
let surface = self
|
||||||
.context
|
.context
|
||||||
.as_any()
|
.as_any()
|
||||||
@ -2090,6 +2148,7 @@ impl Instance {
|
|||||||
// TODO: This is ugly, a way to create things from a native context needs to be made nicer.
|
// TODO: This is ugly, a way to create things from a native context needs to be made nicer.
|
||||||
Ok(Surface {
|
Ok(Surface {
|
||||||
context: Arc::clone(&self.context),
|
context: Arc::clone(&self.context),
|
||||||
|
_surface: None,
|
||||||
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
|
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
|
||||||
id: ObjectId::from(surface.id()),
|
id: ObjectId::from(surface.id()),
|
||||||
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
|
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
|
||||||
@ -2115,7 +2174,7 @@ impl Instance {
|
|||||||
pub fn create_surface_from_offscreen_canvas(
|
pub fn create_surface_from_offscreen_canvas(
|
||||||
&self,
|
&self,
|
||||||
canvas: web_sys::OffscreenCanvas,
|
canvas: web_sys::OffscreenCanvas,
|
||||||
) -> Result<Surface, CreateSurfaceError> {
|
) -> Result<Surface<'static>, CreateSurfaceError> {
|
||||||
let surface = self
|
let surface = self
|
||||||
.context
|
.context
|
||||||
.as_any()
|
.as_any()
|
||||||
@ -2126,6 +2185,7 @@ impl Instance {
|
|||||||
// TODO: This is ugly, a way to create things from a native context needs to be made nicer.
|
// TODO: This is ugly, a way to create things from a native context needs to be made nicer.
|
||||||
Ok(Surface {
|
Ok(Surface {
|
||||||
context: Arc::clone(&self.context),
|
context: Arc::clone(&self.context),
|
||||||
|
_surface: None,
|
||||||
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
|
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
|
||||||
id: ObjectId::from(surface.id()),
|
id: ObjectId::from(surface.id()),
|
||||||
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
|
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
|
||||||
@ -4913,7 +4973,7 @@ impl Drop for SurfaceTexture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Surface {
|
impl Surface<'_> {
|
||||||
/// Returns the capabilities of the surface when used with the given adapter.
|
/// Returns the capabilities of the surface when used with the given adapter.
|
||||||
///
|
///
|
||||||
/// Returns specified values (see [`SurfaceCapabilities`]) if surface is incompatible with the adapter.
|
/// Returns specified values (see [`SurfaceCapabilities`]) if surface is incompatible with the adapter.
|
||||||
@ -5303,7 +5363,7 @@ impl RenderBundle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "expose-ids")]
|
#[cfg(feature = "expose-ids")]
|
||||||
impl Surface {
|
impl Surface<'_> {
|
||||||
/// Returns a globally-unique identifier for this `Surface`.
|
/// Returns a globally-unique identifier for this `Surface`.
|
||||||
///
|
///
|
||||||
/// Calling this method multiple times on the same object will always return the same value.
|
/// Calling this method multiple times on the same object will always return the same value.
|
||||||
|
|||||||
@ -80,7 +80,7 @@ pub fn initialize_adapter_from_env(
|
|||||||
/// Initialize the adapter obeying the WGPU_ADAPTER_NAME environment variable and if it doesn't exist fall back on a default adapter.
|
/// Initialize the adapter obeying the WGPU_ADAPTER_NAME environment variable and if it doesn't exist fall back on a default adapter.
|
||||||
pub async fn initialize_adapter_from_env_or_default(
|
pub async fn initialize_adapter_from_env_or_default(
|
||||||
instance: &Instance,
|
instance: &Instance,
|
||||||
compatible_surface: Option<&Surface>,
|
compatible_surface: Option<&Surface<'_>>,
|
||||||
) -> Option<Adapter> {
|
) -> Option<Adapter> {
|
||||||
match initialize_adapter_from_env(instance, compatible_surface) {
|
match initialize_adapter_from_env(instance, compatible_surface) {
|
||||||
Some(a) => Some(a),
|
Some(a) => Some(a),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user