wgpu: Make WgpuRenderBackend::build_descriptors async

This will be necessary for using wgpu on web, where the whole
renderer creation will need to be async.
This commit is contained in:
Mike Welsh 2021-09-08 16:40:51 -07:00
parent 9067dd3668
commit df270c55af
6 changed files with 47 additions and 32 deletions

1
Cargo.lock generated
View File

@ -3538,6 +3538,7 @@ version = "0.1.0"
dependencies = [
"approx",
"env_logger",
"futures",
"image",
"pretty_assertions",
"ruffle_core",

View File

@ -384,13 +384,14 @@ fn trace_path(_opt: &Opt) -> Option<&Path> {
fn main() -> Result<(), Box<dyn Error>> {
let opt: Opt = Opt::parse();
let instance = wgpu::Instance::new(opt.graphics.into());
let descriptors = WgpuRenderBackend::<TextureTarget>::build_descriptors(
opt.graphics.into(),
instance,
None,
opt.power.into(),
trace_path(&opt),
)?;
let descriptors =
futures::executor::block_on(WgpuRenderBackend::<TextureTarget>::build_descriptors(
opt.graphics.into(),
instance,
None,
opt.power.into(),
trace_path(&opt),
))?;
if opt.swf.is_file() {
capture_single_swf(descriptors, &opt)?;

View File

@ -291,13 +291,13 @@ impl WgpuRenderBackend<SwapChainTarget> {
}
let instance = wgpu::Instance::new(backend);
let surface = unsafe { instance.create_surface(window) };
let descriptors = Self::build_descriptors(
let descriptors = block_on(Self::build_descriptors(
backend,
instance,
Some(&surface),
power_preference,
trace_path,
)?;
))?;
let target = SwapChainTarget::new(
surface,
descriptors.surface_format,
@ -322,8 +322,13 @@ impl WgpuRenderBackend<TextureTarget> {
);
}
let instance = wgpu::Instance::new(backend);
let descriptors =
Self::build_descriptors(backend, instance, None, power_preference, trace_path)?;
let descriptors = block_on(Self::build_descriptors(
backend,
instance,
None,
power_preference,
trace_path,
))?;
let target = TextureTarget::new(&descriptors.device, size);
Self::new(descriptors, target)
}
@ -388,18 +393,18 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
})
}
pub fn build_descriptors(
pub async fn build_descriptors(
backend: wgpu::Backends,
instance: wgpu::Instance,
surface: Option<&wgpu::Surface>,
power_preference: wgpu::PowerPreference,
trace_path: Option<&Path>,
) -> Result<Descriptors, Error> {
let adapter = block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
let adapter = instance.request_adapter(&wgpu::RequestAdapterOptions {
power_preference,
compatible_surface: surface,
force_fallback_adapter: false,
}))
}).await
.ok_or_else(|| {
let names = get_backend_names(backend);
if names.is_empty() {
@ -409,14 +414,16 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
}
})?;
let (device, queue) = block_on(adapter.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::empty(),
..Default::default()
},
trace_path,
))?;
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::empty(),
..Default::default()
},
trace_path,
)
.await?;
let info = adapter.get_info();
// Prefer a linear surface format, when available.
let surface_format = if info.backend == wgpu::Backend::Gl {

View File

@ -7,6 +7,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
futures = "0.3.17"
ruffle_core = { path = "../core" }
ruffle_render_wgpu = { path = "../render/wgpu" }
image = "0.23.14"

View File

@ -1028,12 +1028,14 @@ fn run_swf(
if check_img {
let instance = wgpu::Instance::new(backend_bit);
let descriptors = WgpuRenderBackend::<TextureTarget>::build_descriptors(
backend_bit,
instance,
None,
Default::default(),
None,
let descriptors = futures::executor::block_on(
WgpuRenderBackend::<TextureTarget>::build_descriptors(
backend_bit,
instance,
None,
Default::default(),
None,
),
)?;
platform_id = Some(get_img_platform_suffix(&descriptors.info));

View File

@ -411,7 +411,11 @@ export class RufflePlayer extends HTMLElement {
throw e;
});
this.instance = new ruffleConstructor(this.container, this, config);
this.instance = await new ruffleConstructor(
this.container,
this,
config
);
console.log("New Ruffle instance created.");
// In Firefox, AudioContext.state is always "suspended" when the object has just been created.
@ -1226,9 +1230,8 @@ export class RufflePlayer extends HTMLElement {
}
protected debugPlayerInfo(): string {
return `Allows script access: ${
this.options?.allowScriptAccess ?? false
}\n`;
return `Allows script access: ${this.options?.allowScriptAccess ?? false
}\n`;
}
private setMetadata(metadata: MovieMetadata) {