From 02b6b29da044e4f5d773c06d84f9f8834e60f6e1 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Wed, 17 Jul 2024 16:47:54 -0600 Subject: [PATCH 1/3] Expose some debugging information for Zed We'd like to be able to tell users not to use a software renderer, and to provide more information in the case of failures. Fixes: kvark/blade#142 --- blade-graphics/src/gles/egl.rs | 22 +++++++++++++++---- blade-graphics/src/gles/mod.rs | 4 ++++ blade-graphics/src/gles/web.rs | 9 ++++++++ blade-graphics/src/lib.rs | 26 ++++++++++++++++++++++ blade-graphics/src/metal/mod.rs | 4 ++++ blade-graphics/src/vulkan/init.rs | 36 ++++++++++++++++++++++++++++++- blade-graphics/src/vulkan/mod.rs | 1 + examples/bunnymark/main.rs | 1 + 8 files changed, 98 insertions(+), 5 deletions(-) diff --git a/blade-graphics/src/gles/egl.rs b/blade-graphics/src/gles/egl.rs index 09f92331..0a76a7f0 100644 --- a/blade-graphics/src/gles/egl.rs +++ b/blade-graphics/src/gles/egl.rs @@ -124,6 +124,7 @@ pub struct Context { inner: Mutex, pub(super) capabilities: super::Capabilities, pub(super) limits: super::Limits, + pub(super) device_information: crate::DeviceInformation, } pub struct ContextLock<'a> { @@ -208,7 +209,7 @@ impl Context { let egl_context = EglContext::init(&desc, egl, display)?; egl_context.make_current(); - let (glow, capabilities, limits) = egl_context.load_functions(&desc); + let (glow, capabilities, device_information, limits) = egl_context.load_functions(&desc); egl_context.unmake_current(); Ok(Self { @@ -220,6 +221,7 @@ impl Context { }), capabilities, limits, + device_information, }) } @@ -322,7 +324,7 @@ impl Context { let egl_context = EglContext::init(&desc, egl, display)?; egl_context.make_current(); - let (glow, capabilities, limits) = egl_context.load_functions(&desc); + let (glow, capabilities, device_information, limits) = egl_context.load_functions(&desc); let renderbuf = glow.create_renderbuffer().unwrap(); let framebuf = glow.create_framebuffer().unwrap(); egl_context.unmake_current(); @@ -341,6 +343,7 @@ impl Context { }), capabilities, limits, + device_information, }) } @@ -775,7 +778,12 @@ impl EglContext { unsafe fn load_functions( &self, desc: &crate::ContextDesc, - ) -> (glow::Context, super::Capabilities, super::Limits) { + ) -> ( + glow::Context, + super::Capabilities, + crate::DeviceInformation, + super::Limits, + ) { let mut gl = glow::Context::from_loader_function(|name| { self.instance .get_proc_address(name) @@ -804,6 +812,12 @@ impl EglContext { log::info!("Vendor: {}", vendor); log::info!("Renderer: {}", renderer); log::info!("Version: {}", version); + let device_information = crate::DeviceInformation { + device_kind: crate::DeviceKind::Unknown, // todo + device_name: vendor, + driver_name: renderer, + driver_info: version, + }; let mut capabilities = super::Capabilities::empty(); capabilities.set( @@ -825,7 +839,7 @@ impl EglContext { uniform_buffer_alignment: gl.get_parameter_i32(glow::UNIFORM_BUFFER_OFFSET_ALIGNMENT) as u32, }; - (gl, capabilities, limits) + (gl, capabilities, device_information, limits) } } diff --git a/blade-graphics/src/gles/mod.rs b/blade-graphics/src/gles/mod.rs index 213f1b1d..f2fcbe1e 100644 --- a/blade-graphics/src/gles/mod.rs +++ b/blade-graphics/src/gles/mod.rs @@ -404,6 +404,10 @@ impl Context { ray_query: crate::ShaderVisibility::empty(), } } + + pub fn device_information(&self) -> &crate::DeviceInformation { + &self.device_information + } } #[hidden_trait::expose] diff --git a/blade-graphics/src/gles/web.rs b/blade-graphics/src/gles/web.rs index 4311167c..e1cf9128 100644 --- a/blade-graphics/src/gles/web.rs +++ b/blade-graphics/src/gles/web.rs @@ -17,6 +17,7 @@ pub struct Context { swapchain: Swapchain, pub(super) capabilities: super::Capabilities, pub(super) limits: super::Limits, + pub(super) device_information: crate::DeviceInformation, } impl Context { @@ -73,12 +74,20 @@ impl Context { extent: Cell::default(), }; + let device_information = crate::DeviceInformation { + device_kind: crate::DeviceKind::VirtualGPU, + device_name: glow.get_parameter_string(glow::VENDOR), + driver_name: glow.get_parameter_string(glow::RENDERER), + driver_info: glow.get_parameter_string(glow::VERSION), + }; + Ok(Self { webgl2, glow, swapchain, capabilities, limits, + device_information, }) } diff --git a/blade-graphics/src/lib.rs b/blade-graphics/src/lib.rs index 8ecb34ad..c231e238 100644 --- a/blade-graphics/src/lib.rs +++ b/blade-graphics/src/lib.rs @@ -114,6 +114,32 @@ pub struct Capabilities { pub ray_query: ShaderVisibility, } +#[derive(Clone, Debug, Default, PartialEq)] +pub enum DeviceKind { + #[default] + Unknown, + /// Integrated hardware GPU + IntegratedGPU, + /// Discrete hardware GPU + DiscreteGPU, + /// Virtualized GPU + VirtualGPU, + /// Emulated software GPU + SoftwareEmulator, +} + +#[derive(Clone, Debug, Default)] +pub struct DeviceInformation { + /// The kind of GPU + pub device_kind: DeviceKind, + /// The name of the GPU device + pub device_name: String, + /// The driver used to talk to the GPU + pub driver_name: String, + /// Further information about the driver + pub driver_info: String, +} + #[derive(Clone, Copy, Debug, PartialEq)] pub enum Memory { /// Device-local memory. Fast for GPU operations. diff --git a/blade-graphics/src/metal/mod.rs b/blade-graphics/src/metal/mod.rs index 56caf6c9..82fe9460 100644 --- a/blade-graphics/src/metal/mod.rs +++ b/blade-graphics/src/metal/mod.rs @@ -465,6 +465,10 @@ impl Context { } } + pub fn device_information(&self) -> &crate::DeviceInformation { + todo!(); + } + /// Get the CALayerMetal for this surface, if any. /// This is platform specific API. pub fn metal_layer(&self) -> Option { diff --git a/blade-graphics/src/vulkan/init.rs b/blade-graphics/src/vulkan/init.rs index a2b74c2f..6472dd5b 100644 --- a/blade-graphics/src/vulkan/init.rs +++ b/blade-graphics/src/vulkan/init.rs @@ -37,6 +37,7 @@ struct SystemBugs { struct AdapterCapabilities { api_version: u32, properties: vk::PhysicalDeviceProperties, + device_information: crate::DeviceInformation, queue_family_index: u32, layered: bool, ray_tracing: bool, @@ -88,12 +89,15 @@ unsafe fn inspect_adapter( vk::PhysicalDeviceAccelerationStructurePropertiesKHR::default(); let mut portability_subset_properties = vk::PhysicalDevicePortabilitySubsetPropertiesKHR::default(); + + let mut driver_properties = vk::PhysicalDeviceDriverPropertiesKHR::default(); let mut properties2_khr = vk::PhysicalDeviceProperties2KHR::default() .push_next(&mut inline_uniform_block_properties) .push_next(&mut timeline_semaphore_properties) .push_next(&mut descriptor_indexing_properties) .push_next(&mut acceleration_structure_properties) - .push_next(&mut portability_subset_properties); + .push_next(&mut portability_subset_properties) + .push_next(&mut driver_properties); instance .get_physical_device_properties2 .get_physical_device_properties2(phd, &mut properties2_khr); @@ -153,6 +157,10 @@ unsafe fn inspect_adapter( .get_physical_device_properties2 .get_physical_device_features2(phd, &mut features2_khr); + instance + .get_physical_device_properties2 + .get_physical_device_properties2(phd, &mut properties2_khr); + let properties = properties2_khr.properties; let name = ffi::CStr::from_ptr(properties.device_name.as_ptr()); log::info!("Adapter {:?}", name); @@ -232,9 +240,30 @@ unsafe fn inspect_adapter( let shader_info = supported_extensions.contains(&vk::AMD_SHADER_INFO_NAME); let full_screen_exclusive = supported_extensions.contains(&vk::EXT_FULL_SCREEN_EXCLUSIVE_NAME); + let device_kind = match properties.device_type { + ash::vk::PhysicalDeviceType::CPU => crate::DeviceKind::SoftwareEmulator, + ash::vk::PhysicalDeviceType::INTEGRATED_GPU => crate::DeviceKind::IntegratedGPU, + ash::vk::PhysicalDeviceType::DISCRETE_GPU => crate::DeviceKind::DiscreteGPU, + ash::vk::PhysicalDeviceType::VIRTUAL_GPU => crate::DeviceKind::VirtualGPU, + _ => crate::DeviceKind::Unknown, + }; + let device_information = crate::DeviceInformation { + device_kind, + device_name: ffi::CStr::from_ptr(properties.device_name.as_ptr()) + .to_string_lossy() + .to_string(), + driver_name: ffi::CStr::from_ptr(driver_properties.driver_name.as_ptr()) + .to_string_lossy() + .to_string(), + driver_info: ffi::CStr::from_ptr(driver_properties.driver_info.as_ptr()) + .to_string_lossy() + .to_string(), + }; + Some(AdapterCapabilities { api_version, properties, + device_information, queue_family_index, layered: portability_subset_properties.min_vertex_input_binding_stride_alignment != 0, ray_tracing, @@ -530,6 +559,7 @@ impl super::Context { None }, core: device_core, + device_information: capabilities.device_information, //TODO: detect GPU family workarounds: super::Workarounds { extra_sync_src_access: vk::AccessFlags::TRANSFER_WRITE, @@ -701,6 +731,10 @@ impl super::Context { }, } } + + pub fn device_information(&self) -> &crate::DeviceInformation { + &self.device.device_information + } } impl super::Context { diff --git a/blade-graphics/src/vulkan/mod.rs b/blade-graphics/src/vulkan/mod.rs index 7434721e..5329527d 100644 --- a/blade-graphics/src/vulkan/mod.rs +++ b/blade-graphics/src/vulkan/mod.rs @@ -29,6 +29,7 @@ struct Workarounds { #[derive(Clone)] struct Device { core: ash::Device, + device_information: crate::DeviceInformation, debug_utils: ash::ext::debug_utils::Device, timeline_semaphore: khr::timeline_semaphore::Device, dynamic_rendering: khr::dynamic_rendering::Device, diff --git a/examples/bunnymark/main.rs b/examples/bunnymark/main.rs index 2d2898c3..1e0740d4 100644 --- a/examples/bunnymark/main.rs +++ b/examples/bunnymark/main.rs @@ -73,6 +73,7 @@ impl Example { ) .unwrap() }; + println!("{:?}", context.device_information()); let surface_info = context.resize(gpu::SurfaceConfig { size: gpu::Extent { From f13d39a4ac54dbe865acae7c69c94436da56a3df Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 19 Jul 2024 10:00:43 -0600 Subject: [PATCH 2/3] Simplify output --- blade-graphics/src/gles/egl.rs | 2 +- blade-graphics/src/gles/web.rs | 2 +- blade-graphics/src/lib.rs | 18 ++---------------- blade-graphics/src/vulkan/init.rs | 9 +-------- 4 files changed, 5 insertions(+), 26 deletions(-) diff --git a/blade-graphics/src/gles/egl.rs b/blade-graphics/src/gles/egl.rs index 0a76a7f0..f8c8348f 100644 --- a/blade-graphics/src/gles/egl.rs +++ b/blade-graphics/src/gles/egl.rs @@ -813,7 +813,7 @@ impl EglContext { log::info!("Renderer: {}", renderer); log::info!("Version: {}", version); let device_information = crate::DeviceInformation { - device_kind: crate::DeviceKind::Unknown, // todo + is_software_emulated: false, device_name: vendor, driver_name: renderer, driver_info: version, diff --git a/blade-graphics/src/gles/web.rs b/blade-graphics/src/gles/web.rs index e1cf9128..53282bf5 100644 --- a/blade-graphics/src/gles/web.rs +++ b/blade-graphics/src/gles/web.rs @@ -75,7 +75,7 @@ impl Context { }; let device_information = crate::DeviceInformation { - device_kind: crate::DeviceKind::VirtualGPU, + is_software_emulated: false, device_name: glow.get_parameter_string(glow::VENDOR), driver_name: glow.get_parameter_string(glow::RENDERER), driver_info: glow.get_parameter_string(glow::VERSION), diff --git a/blade-graphics/src/lib.rs b/blade-graphics/src/lib.rs index c231e238..8f7d03ee 100644 --- a/blade-graphics/src/lib.rs +++ b/blade-graphics/src/lib.rs @@ -114,24 +114,10 @@ pub struct Capabilities { pub ray_query: ShaderVisibility, } -#[derive(Clone, Debug, Default, PartialEq)] -pub enum DeviceKind { - #[default] - Unknown, - /// Integrated hardware GPU - IntegratedGPU, - /// Discrete hardware GPU - DiscreteGPU, - /// Virtualized GPU - VirtualGPU, - /// Emulated software GPU - SoftwareEmulator, -} - #[derive(Clone, Debug, Default)] pub struct DeviceInformation { - /// The kind of GPU - pub device_kind: DeviceKind, + /// If this is something like llvmpipe, not a real GPU + pub is_software_emulated: bool, /// The name of the GPU device pub device_name: String, /// The driver used to talk to the GPU diff --git a/blade-graphics/src/vulkan/init.rs b/blade-graphics/src/vulkan/init.rs index 6472dd5b..5035155f 100644 --- a/blade-graphics/src/vulkan/init.rs +++ b/blade-graphics/src/vulkan/init.rs @@ -240,15 +240,8 @@ unsafe fn inspect_adapter( let shader_info = supported_extensions.contains(&vk::AMD_SHADER_INFO_NAME); let full_screen_exclusive = supported_extensions.contains(&vk::EXT_FULL_SCREEN_EXCLUSIVE_NAME); - let device_kind = match properties.device_type { - ash::vk::PhysicalDeviceType::CPU => crate::DeviceKind::SoftwareEmulator, - ash::vk::PhysicalDeviceType::INTEGRATED_GPU => crate::DeviceKind::IntegratedGPU, - ash::vk::PhysicalDeviceType::DISCRETE_GPU => crate::DeviceKind::DiscreteGPU, - ash::vk::PhysicalDeviceType::VIRTUAL_GPU => crate::DeviceKind::VirtualGPU, - _ => crate::DeviceKind::Unknown, - }; let device_information = crate::DeviceInformation { - device_kind, + is_software_emulated: properties.device_type == ash::vk::PhysicalDeviceType::CPU, device_name: ffi::CStr::from_ptr(properties.device_name.as_ptr()) .to_string_lossy() .to_string(), From ca789a16eff6146ea7249c47a67b5e6c7f11aabe Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 22 Jul 2024 09:52:49 -0600 Subject: [PATCH 3/3] Metal implementation --- blade-graphics/src/metal/mod.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/blade-graphics/src/metal/mod.rs b/blade-graphics/src/metal/mod.rs index 82fe9460..22352ca8 100644 --- a/blade-graphics/src/metal/mod.rs +++ b/blade-graphics/src/metal/mod.rs @@ -49,6 +49,7 @@ pub struct Context { surface: Option>, capture: Option, info: DeviceInfo, + device_information: crate::DeviceInformation, } #[derive(Clone, Copy, Debug, Hash, PartialEq)] @@ -413,6 +414,12 @@ impl Context { } else { None }; + let device_information = crate::DeviceInformation { + is_software_emulated: false, + device_name: device.name().to_string(), + driver_name: "Metal".to_string(), + driver_info: "".to_string(), + }; Ok(Context { device: Mutex::new(device), @@ -423,6 +430,7 @@ impl Context { //TODO: determine based on OS version language_version: metal::MTLLanguageVersion::V2_4, }, + device_information, }) } @@ -466,7 +474,7 @@ impl Context { } pub fn device_information(&self) -> &crate::DeviceInformation { - todo!(); + &self.device_information } /// Get the CALayerMetal for this surface, if any.