Iris asked whether the 'unknown number of images' approach even works on mobile. It does not, measured with a new rig (rigs/gpu-probe, no APK needed) and sourced rather than recalled: the emulator's software Vulkan refuses iris's descriptor-indexing request outright, and on real hardware the current Android Vulkan Profile baseline (80.1% of active devices) does not require VK_EXT_descriptor_indexing either -- Arm's own docs say only Valhall/5th-Gen Mali (2019+) support it. iris already solved the identical problem for text in I1 (the glyph atlas). The recommendation is to generalize it to images rather than widen the binding array further; not yet implemented, since it changes iris's render core. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
109 lines
4.1 KiB
Rust
109 lines
4.1 KiB
Rust
//! The raw Vulkan half of the probe.
|
|
//!
|
|
//! wgpu reports a feature only after a chain of its own decisions -- which
|
|
//! physical device, which API version, which extension list -- so "wgpu says
|
|
//! no" and "the driver says no" are different claims. This asks
|
|
//! `vkGetPhysicalDeviceFeatures2` itself and prints the inputs to that chain,
|
|
//! so a disagreement can be attributed rather than guessed at.
|
|
|
|
use ash::{Entry, vk};
|
|
use std::ffi::CStr;
|
|
|
|
pub fn report() {
|
|
let entry = match unsafe { Entry::load() } {
|
|
Ok(e) => e,
|
|
Err(e) => {
|
|
println!("\nraw vulkan: cannot load loader -- {e}");
|
|
return;
|
|
}
|
|
};
|
|
|
|
let instance_version = match unsafe { entry.try_enumerate_instance_version() } {
|
|
Ok(Some(v)) => v,
|
|
Ok(None) => vk::API_VERSION_1_0,
|
|
Err(e) => {
|
|
println!("\nraw vulkan: enumerate_instance_version failed -- {e}");
|
|
return;
|
|
}
|
|
};
|
|
println!("\nraw vulkan:");
|
|
println!(" loader instance version: {}", ver(instance_version));
|
|
|
|
// Ask for the highest instance version the loader admits to: wgpu clamps
|
|
// the device version by the instance's, so an instance created at 1.0
|
|
// makes a 1.3 device look like 1.0.
|
|
let app_info = vk::ApplicationInfo::default().api_version(instance_version);
|
|
let create = vk::InstanceCreateInfo::default().application_info(&app_info);
|
|
let instance = match unsafe { entry.create_instance(&create, None) } {
|
|
Ok(i) => i,
|
|
Err(e) => {
|
|
println!(" create_instance failed -- {e}");
|
|
return;
|
|
}
|
|
};
|
|
|
|
let devices = unsafe { instance.enumerate_physical_devices() }.unwrap_or_default();
|
|
for phd in devices {
|
|
let props = unsafe { instance.get_physical_device_properties(phd) };
|
|
let name = unsafe { CStr::from_ptr(props.device_name.as_ptr()) };
|
|
println!(" device: {}", name.to_string_lossy());
|
|
println!(" device api version: {}", ver(props.api_version));
|
|
|
|
let exts =
|
|
unsafe { instance.enumerate_device_extension_properties(phd) }.unwrap_or_default();
|
|
let has_ext = exts.iter().any(|e| {
|
|
(unsafe { CStr::from_ptr(e.extension_name.as_ptr()) }) == c"VK_EXT_descriptor_indexing"
|
|
});
|
|
println!(" VK_EXT_descriptor_indexing advertised: {has_ext}");
|
|
println!(" device extensions: {}", exts.len());
|
|
|
|
let mut indexing = vk::PhysicalDeviceDescriptorIndexingFeatures::default();
|
|
let mut features2 = vk::PhysicalDeviceFeatures2::default().push_next(&mut indexing);
|
|
unsafe { instance.get_physical_device_features2(phd, &mut features2) };
|
|
|
|
for (name, v) in [
|
|
(
|
|
"shaderSampledImageArrayNonUniformIndexing",
|
|
indexing.shader_sampled_image_array_non_uniform_indexing,
|
|
),
|
|
(
|
|
"descriptorBindingSampledImageUpdateAfterBind",
|
|
indexing.descriptor_binding_sampled_image_update_after_bind,
|
|
),
|
|
(
|
|
"shaderStorageImageArrayNonUniformIndexing",
|
|
indexing.shader_storage_image_array_non_uniform_indexing,
|
|
),
|
|
(
|
|
"descriptorBindingStorageImageUpdateAfterBind",
|
|
indexing.descriptor_binding_storage_image_update_after_bind,
|
|
),
|
|
(
|
|
"shaderStorageBufferArrayNonUniformIndexing",
|
|
indexing.shader_storage_buffer_array_non_uniform_indexing,
|
|
),
|
|
(
|
|
"descriptorBindingStorageBufferUpdateAfterBind",
|
|
indexing.descriptor_binding_storage_buffer_update_after_bind,
|
|
),
|
|
(
|
|
"descriptorBindingPartiallyBound",
|
|
indexing.descriptor_binding_partially_bound,
|
|
),
|
|
] {
|
|
println!(" {name:48} {}", if v != 0 { "yes" } else { "NO" });
|
|
}
|
|
}
|
|
|
|
unsafe { instance.destroy_instance(None) };
|
|
}
|
|
|
|
fn ver(v: u32) -> String {
|
|
format!(
|
|
"{}.{}.{}",
|
|
vk::api_version_major(v),
|
|
vk::api_version_minor(v),
|
|
vk::api_version_patch(v)
|
|
)
|
|
}
|