Check surface compatibility

This commit is contained in:
Dzmitry Malyshau 2020-03-30 09:07:07 -04:00
parent 306554600a
commit f3eee020e6
8 changed files with 158 additions and 95 deletions

View File

@ -43,10 +43,58 @@ void request_adapter_callback(WGPUAdapterId received, void *userdata) {
}
int main() {
if (!glfwInit()) {
printf("Cannot initialize glfw");
return 1;
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow *window =
glfwCreateWindow(640, 480, "wgpu with glfw", NULL, NULL);
if (!window) {
printf("Cannot create window");
return 1;
}
WGPUSurfaceId surface;
#if WGPU_TARGET == WGPU_TARGET_MACOS
{
id metal_layer = NULL;
NSWindow *ns_window = glfwGetCocoaWindow(window);
[ns_window.contentView setWantsLayer:YES];
metal_layer = [CAMetalLayer layer];
[ns_window.contentView setLayer:metal_layer];
surface = wgpu_create_surface_from_metal_layer(metal_layer);
}
#elif WGPU_TARGET == WGPU_TARGET_LINUX_X11
{
Display *x11_display = glfwGetX11Display();
Window x11_window = glfwGetX11Window(window);
surface = wgpu_create_surface_from_xlib((const void **)x11_display, x11_window);
}
#elif WGPU_TARGET == WGPU_TARGET_LINUX_WAYLAND
{
struct wl_display *wayland_display = glfwGetWaylandDisplay();
struct wl_surface *wayland_surface = glfwGetWaylandWindow(window);
surface = wgpu_create_surface_from_wayland(wayland_surface, wayland_display);
}
#elif WGPU_TARGET == WGPU_TARGET_WINDOWS
{
HWND hwnd = glfwGetWin32Window(window);
HINSTANCE hinstance = GetModuleHandle(NULL);
surface = wgpu_create_surface_from_windows_hwnd(hinstance, hwnd);
}
#else
#error "Unsupported WGPU_TARGET"
#endif
WGPUAdapterId adapter = { 0 };
wgpu_request_adapter_async(
&(WGPURequestAdapterOptions){
.power_preference = WGPUPowerPreference_LowPower,
.compatible_surface = surface,
},
2 | 4 | 8,
request_adapter_callback,
@ -153,53 +201,6 @@ int main() {
.sample_count = 1,
});
if (!glfwInit()) {
printf("Cannot initialize glfw");
return 1;
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow *window =
glfwCreateWindow(640, 480, "wgpu with glfw", NULL, NULL);
if (!window) {
printf("Cannot create window");
return 1;
}
WGPUSurfaceId surface;
#if WGPU_TARGET == WGPU_TARGET_MACOS
{
id metal_layer = NULL;
NSWindow *ns_window = glfwGetCocoaWindow(window);
[ns_window.contentView setWantsLayer:YES];
metal_layer = [CAMetalLayer layer];
[ns_window.contentView setLayer:metal_layer];
surface = wgpu_create_surface_from_metal_layer(metal_layer);
}
#elif WGPU_TARGET == WGPU_TARGET_LINUX_X11
{
Display *x11_display = glfwGetX11Display();
Window x11_window = glfwGetX11Window(window);
surface = wgpu_create_surface_from_xlib((const void **)x11_display, x11_window);
}
#elif WGPU_TARGET == WGPU_TARGET_LINUX_WAYLAND
{
struct wl_display *wayland_display = glfwGetWaylandDisplay();
struct wl_surface *wayland_surface = glfwGetWaylandWindow(window);
surface = wgpu_create_surface_from_wayland(wayland_surface, wayland_display);
}
#elif WGPU_TARGET == WGPU_TARGET_WINDOWS
{
HWND hwnd = glfwGetWin32Window(window);
HINSTANCE hinstance = GetModuleHandle(NULL);
surface = wgpu_create_surface_from_windows_hwnd(hinstance, hwnd);
}
#else
#error "Unsupported WGPU_TARGET"
#endif
int prev_width = 0;
int prev_height = 0;
glfwGetWindowSize(window, &prev_width, &prev_height);

View File

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Generated with cbindgen:0.13.2 */
/* Generated with cbindgen:0.13.1 */
/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
* To generate this file:
@ -19,6 +19,8 @@
#include <stdint.h>
#include <stdlib.h>
#define WGPUBIND_BUFFER_ALIGNMENT 256
#define WGPUDEFAULT_BIND_GROUPS 4
#define WGPUDESIRED_NUM_FRAMES 3
@ -695,6 +697,7 @@ typedef WGPUId_RenderBundle_Dummy WGPURenderBundleId;
typedef struct {
WGPUPowerPreference power_preference;
WGPUSurfaceId compatible_surface;
} WGPURequestAdapterOptions;
typedef uint32_t WGPUBackendBit;

View File

@ -39,7 +39,7 @@ use vec_map::VecMap;
#[cfg(debug_assertions)]
use std::cell::Cell;
use std::{fmt::Debug, marker::PhantomData, ops};
use std::{fmt::Debug, iter, marker::PhantomData, ops};
/// A simple structure to manage identities of objects.
@ -271,7 +271,7 @@ impl<I: TypedId + Debug> IdentityHandler<I> for Mutex<IdentityManager> {
pub trait IdentityHandlerFactory<I> {
type Filter: IdentityHandler<I>;
fn spawn(&self) -> Self::Filter;
fn spawn(&self, min_index: Index) -> Self::Filter;
}
#[derive(Debug)]
@ -279,8 +279,11 @@ pub struct IdentityManagerFactory;
impl<I: TypedId + Debug> IdentityHandlerFactory<I> for IdentityManagerFactory {
type Filter = Mutex<IdentityManager>;
fn spawn(&self) -> Self::Filter {
Mutex::new(IdentityManager::default())
fn spawn(&self, min_index: Index) -> Self::Filter {
let mut man = IdentityManager::default();
man.free.extend(0 .. min_index);
man.epochs.extend(iter::repeat(1).take(min_index as usize));
Mutex::new(man)
}
}
@ -317,7 +320,7 @@ pub struct Registry<T, I: TypedId, F: IdentityHandlerFactory<I>> {
impl<T, I: TypedId, F: IdentityHandlerFactory<I>> Registry<T, I, F> {
fn new(backend: Backend, factory: &F) -> Self {
Registry {
identity: factory.spawn(),
identity: factory.spawn(0),
data: RwLock::new(Storage {
map: VecMap::new(),
_phantom: PhantomData,
@ -325,6 +328,17 @@ impl<T, I: TypedId, F: IdentityHandlerFactory<I>> Registry<T, I, F> {
backend,
}
}
fn without_backend(factory: &F) -> Self {
Registry {
identity: factory.spawn(1),
data: RwLock::new(Storage {
map: VecMap::new(),
_phantom: PhantomData,
}),
backend: Backend::Empty,
}
}
}
impl<T, I: TypedId + Copy, F: IdentityHandlerFactory<I>> Registry<T, I, F> {
@ -545,7 +559,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn new(name: &str, factory: G) -> Self {
Global {
instance: Instance::new(name, 1),
surfaces: Registry::new(Backend::Empty, &factory),
surfaces: Registry::without_backend(&factory),
hubs: Hubs::new(&factory),
}
}

View File

@ -6,23 +6,45 @@ use crate::{
backend,
device::Device,
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token},
id::{AdapterId, DeviceId},
id::{AdapterId, DeviceId, SurfaceId},
power,
};
use wgt::{Backend, BackendBit, DeviceDescriptor, PowerPreference, RequestAdapterOptions, BIND_BUFFER_ALIGNMENT};
use wgt::{Backend, BackendBit, DeviceDescriptor, PowerPreference, BIND_BUFFER_ALIGNMENT};
#[cfg(feature = "serde")]
use serde_crate::{Deserialize, Serialize};
use hal::{
self,
adapter::{AdapterInfo as HalAdapterInfo, DeviceType as HalDeviceType, PhysicalDevice as _},
adapter::{
AdapterInfo as HalAdapterInfo,
DeviceType as HalDeviceType,
PhysicalDevice as _,
},
queue::QueueFamily as _,
window::Surface as _,
Instance as _,
};
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate="serde_crate"))]
pub struct RequestAdapterOptions {
pub power_preference: PowerPreference,
pub compatible_surface: SurfaceId,
}
impl Default for RequestAdapterOptions {
fn default() -> Self {
RequestAdapterOptions {
power_preference: PowerPreference::Default,
compatible_surface: SurfaceId::ERROR,
}
}
}
#[derive(Debug)]
pub struct Instance {
#[cfg(any(
@ -261,6 +283,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
inputs: AdapterInputs<Input<G, AdapterId>>,
) -> Option<AdapterId> {
let instance = &self.instance;
let mut token = Token::root();
let (surface_guard, mut token) = self.surfaces.read(&mut token);
let compatible_surface = if desc.compatible_surface != SurfaceId::ERROR {
Some(&surface_guard[desc.compatible_surface])
} else {
None
};
let mut device_types = Vec::new();
let id_vulkan = inputs.find(Backend::Vulkan);
@ -274,7 +303,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
))]
let mut adapters_vk = match instance.vulkan {
Some(ref inst) if id_vulkan.is_some() => {
let adapters = inst.enumerate_adapters();
let mut adapters = inst.enumerate_adapters();
if let Some(&Surface { vulkan: Some(ref surface), .. }) = compatible_surface {
adapters.retain(|a|
a.queue_families
.iter()
.find(|qf| qf.queue_type().supports_graphics())
.map_or(false, |qf| surface.supports_queue_family(qf))
);
}
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
adapters
}
@ -282,7 +319,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
};
#[cfg(any(target_os = "ios", target_os = "macos"))]
let mut adapters_mtl = if id_metal.is_some() {
let adapters = instance.metal.enumerate_adapters();
let mut adapters = instance.metal.enumerate_adapters();
if let Some(surface) = compatible_surface {
adapters.retain(|a|
a.queue_families
.iter()
.find(|qf| qf.queue_type().supports_graphics())
.map_or(false, |qf| surface.metal.supports_queue_family(qf))
);
}
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
adapters
} else {
@ -291,7 +336,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
#[cfg(windows)]
let mut adapters_dx12 = match instance.dx12 {
Some(ref inst) if id_dx12.is_some() => {
let adapters = inst.enumerate_adapters();
let mut adapters = inst.enumerate_adapters();
if let Some(&Surface { dx12: Some(ref surface), .. }) = compatible_surface {
adapters.retain(|a|
a.queue_families
.iter()
.find(|qf| qf.queue_type().supports_graphics())
.map_or(false, |qf| surface.supports_queue_family(qf))
);
}
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
adapters
}
@ -299,7 +352,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
};
#[cfg(windows)]
let mut adapters_dx11 = if id_dx11.is_some() {
let adapters = instance.dx11.enumerate_adapters();
let mut adapters = instance.dx11.enumerate_adapters();
if let Some(surface) = compatible_surface {
adapters.retain(|a|
a.queue_families
.iter()
.find(|qf| qf.queue_type().supports_graphics())
.map_or(false, |qf| surface.dx11.supports_queue_family(qf))
);
}
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
adapters
} else {
@ -345,7 +406,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
PowerPreference::HighPerformance => discrete.or(other).or(integrated).or(virt),
};
let mut token = Token::root();
let mut selected = preferred_gpu.unwrap_or(0);
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),

View File

@ -4,7 +4,7 @@
use crate::GLOBAL;
use wgt::{BackendBit, DeviceDescriptor, Limits, RequestAdapterOptions};
use wgt::{BackendBit, DeviceDescriptor, Limits};
use core::{gfx_select, hub::Token, id};
use std::{marker::PhantomData, slice};
@ -153,7 +153,7 @@ pub fn wgpu_enumerate_adapters(mask: BackendBit) -> Vec<id::AdapterId> {
/// This function is unsafe as it calls an unsafe extern callback.
#[no_mangle]
pub unsafe extern "C" fn wgpu_request_adapter_async(
desc: Option<&RequestAdapterOptions>,
desc: Option<&core::instance::RequestAdapterOptions>,
mask: BackendBit,
callback: RequestAdapterCallback,
userdata: *mut std::ffi::c_void,

View File

@ -49,7 +49,7 @@ pub struct IdentityRecyclerFactory {
impl core::hub::IdentityHandlerFactory<id::AdapterId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::AdapterId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_adapter,
param: self.param,
@ -59,7 +59,7 @@ impl core::hub::IdentityHandlerFactory<id::AdapterId> for IdentityRecyclerFactor
}
impl core::hub::IdentityHandlerFactory<id::DeviceId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::DeviceId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_device,
param: self.param,
@ -69,7 +69,7 @@ impl core::hub::IdentityHandlerFactory<id::DeviceId> for IdentityRecyclerFactory
}
impl core::hub::IdentityHandlerFactory<id::SwapChainId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::SwapChainId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_swap_chain,
param: self.param,
@ -79,7 +79,7 @@ impl core::hub::IdentityHandlerFactory<id::SwapChainId> for IdentityRecyclerFact
}
impl core::hub::IdentityHandlerFactory<id::PipelineLayoutId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::PipelineLayoutId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_pipeline_layout,
param: self.param,
@ -89,7 +89,7 @@ impl core::hub::IdentityHandlerFactory<id::PipelineLayoutId> for IdentityRecycle
}
impl core::hub::IdentityHandlerFactory<id::ShaderModuleId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::ShaderModuleId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_shader_module,
param: self.param,
@ -99,7 +99,7 @@ impl core::hub::IdentityHandlerFactory<id::ShaderModuleId> for IdentityRecyclerF
}
impl core::hub::IdentityHandlerFactory<id::BindGroupLayoutId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::BindGroupLayoutId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_bind_group_layout,
param: self.param,
@ -109,7 +109,7 @@ impl core::hub::IdentityHandlerFactory<id::BindGroupLayoutId> for IdentityRecycl
}
impl core::hub::IdentityHandlerFactory<id::BindGroupId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::BindGroupId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_bind_group,
param: self.param,
@ -119,7 +119,7 @@ impl core::hub::IdentityHandlerFactory<id::BindGroupId> for IdentityRecyclerFact
}
impl core::hub::IdentityHandlerFactory<id::CommandBufferId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::CommandBufferId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_command_buffer,
param: self.param,
@ -129,7 +129,7 @@ impl core::hub::IdentityHandlerFactory<id::CommandBufferId> for IdentityRecycler
}
impl core::hub::IdentityHandlerFactory<id::RenderPipelineId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::RenderPipelineId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_render_pipeline,
param: self.param,
@ -139,7 +139,7 @@ impl core::hub::IdentityHandlerFactory<id::RenderPipelineId> for IdentityRecycle
}
impl core::hub::IdentityHandlerFactory<id::ComputePipelineId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::ComputePipelineId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_compute_pipeline,
param: self.param,
@ -149,7 +149,7 @@ impl core::hub::IdentityHandlerFactory<id::ComputePipelineId> for IdentityRecycl
}
impl core::hub::IdentityHandlerFactory<id::BufferId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::BufferId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_buffer,
param: self.param,
@ -159,7 +159,7 @@ impl core::hub::IdentityHandlerFactory<id::BufferId> for IdentityRecyclerFactory
}
impl core::hub::IdentityHandlerFactory<id::TextureId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::TextureId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_texture,
param: self.param,
@ -169,7 +169,7 @@ impl core::hub::IdentityHandlerFactory<id::TextureId> for IdentityRecyclerFactor
}
impl core::hub::IdentityHandlerFactory<id::TextureViewId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::TextureViewId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_texture_view,
param: self.param,
@ -179,7 +179,7 @@ impl core::hub::IdentityHandlerFactory<id::TextureViewId> for IdentityRecyclerFa
}
impl core::hub::IdentityHandlerFactory<id::SamplerId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::SamplerId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_sampler,
param: self.param,
@ -189,7 +189,7 @@ impl core::hub::IdentityHandlerFactory<id::SamplerId> for IdentityRecyclerFactor
}
impl core::hub::IdentityHandlerFactory<id::SurfaceId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::SurfaceId>;
fn spawn(&self) -> Self::Filter {
fn spawn(&self, _min_index: u32) -> Self::Filter {
IdentityRecycler {
fun: self.free_surface,
param: self.param,

View File

@ -46,7 +46,7 @@ pub extern "C" fn wgpu_server_poll_all_devices(global: &Global, force_wait: bool
#[no_mangle]
pub unsafe extern "C" fn wgpu_server_instance_request_adapter(
global: &Global,
desc: &wgt::RequestAdapterOptions,
desc: &core::instance::RequestAdapterOptions,
ids: *const id::AdapterId,
id_length: usize,
) -> i8 {

View File

@ -30,21 +30,6 @@ pub enum PowerPreference {
HighPerformance = 2,
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct RequestAdapterOptions {
pub power_preference: PowerPreference,
}
impl Default for RequestAdapterOptions {
fn default() -> Self {
RequestAdapterOptions {
power_preference: PowerPreference::Default,
}
}
}
bitflags::bitflags! {
#[repr(transparent)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]