Completely computerize wgpu-info ascii art (#3546)

This commit is contained in:
Connor Fitzgerald 2023-03-01 15:41:53 -05:00 committed by GitHub
parent 6ee0d4c14d
commit 9d6a7a9fe5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 180 additions and 55 deletions

1
Cargo.lock generated
View File

@ -3112,6 +3112,7 @@ name = "wgpu-info"
version = "0.15.0"
dependencies = [
"env_logger",
"num-traits 0.2.15",
"wgpu",
]

View File

@ -65,6 +65,7 @@ libloading = "0.7"
libc = "0.2"
log = "0.4"
nanorand = { version = "0.7", default-features = false }
num-traits = { version = "0.2" }
# Opt out of noise's "default-features" to avoid "image" feature as a dependency count optimization.
# This will not be required in the next release since it has been removed from the default feature in https://github.com/Razaekel/noise-rs/commit/1af9e1522236b2c584fb9a02150c9c67a5e6bb04#diff-2e9d962a08321605940b5a657135052fbcef87b5e360662bb527c96d9a615542
noise = { version = "0.7", default-features = false }

View File

@ -12,4 +12,5 @@ publish = false
[dependencies]
env_logger.workspace = true
num-traits.workspace = true
wgpu.workspace = true

View File

@ -1,11 +1,14 @@
#[cfg(not(target_arch = "wasm32"))]
mod inner {
use std::{
fmt::Debug,
mem::size_of,
process::{exit, Command},
time::Instant,
};
use num_traits::FromPrimitive;
// Lets keep these on one line
#[rustfmt::skip]
const TEXTURE_FORMAT_LIST: [wgpu::TextureFormat; 114] = [
@ -133,6 +136,10 @@ mod inner {
let features = adapter.features();
let limits = adapter.limits();
//////////////////
// Adapter Info //
//////////////////
println!("Adapter {idx}:");
println!("\t Backend: {:?}", info.backend);
println!("\t Name: {:?}", info.name);
@ -142,15 +149,20 @@ mod inner {
println!("\t Driver: {:?}", info.driver);
println!("\tDriverInfo: {:?}", info.driver_info);
println!("\t Compliant: {:?}", downlevel.is_webgpu_compliant());
//////////////
// Features //
//////////////
println!("\tFeatures:");
for i in 0..(size_of::<wgpu::Features>() * 8) {
let bit = wgpu::Features::from_bits(1 << i as u64);
if let Some(bit) = bit {
if wgpu::Features::all().contains(bit) {
println!("\t\t{:>63} {}", format!("{bit:?}:"), features.contains(bit));
}
}
}
let max_feature_flag_width = wgpu::Features::max_debug_print_width();
wgpu::Features::for_valid_bits(|bit, _i| {
println!("\t\t{:>width$}: {}", format!("{bit:?}"), features.contains(bit), width = max_feature_flag_width);
});
////////////
// Limits //
////////////
println!("\tLimits:");
let wgpu::Limits {
@ -214,6 +226,10 @@ mod inner {
println!("\t\t Max Compute Workgroup Size Z: {max_compute_workgroup_size_z}");
println!("\t\t Max Compute Workgroups Per Dimension: {max_compute_workgroups_per_dimension}");
//////////////////////////
// Downlevel Properties //
//////////////////////////
println!("\tDownlevel Properties:");
let wgpu::DownlevelCapabilities {
shader_model,
@ -221,60 +237,69 @@ mod inner {
flags,
} = downlevel;
println!("\t\t Shader Model: {shader_model:?}");
for i in 0..(size_of::<wgpu::DownlevelFlags>() * 8) {
let bit = wgpu::DownlevelFlags::from_bits(1 << i as u64);
if let Some(bit) = bit {
if wgpu::DownlevelFlags::all().contains(bit) {
println!("\t\t{:>37} {}", format!("{bit:?}:"), flags.contains(bit));
}
}
}
let max_downlevel_flag_width = wgpu::DownlevelFlags::max_debug_print_width();
wgpu::DownlevelFlags::for_valid_bits(|bit, _i| {
println!("\t\t{:>width$}: {}", format!("{bit:?}"), flags.contains(bit), width = max_downlevel_flag_width);
});
println!("\tTexture Format Features: ┌──────────┬──────────┬──────────Allowed┬Usages───────────┬───────────────────┐ ┌────────────┬────────────────┬────────────────┬─────────Feature┬Flags────────────┬─────────────────────┬────────────────────┬───────────┐");
////////////////////
// Texture Usages //
////////////////////
let max_format_name_size = max_texture_format_name_size();
let texture_format_whitespace = " ".repeat(max_format_name_size);
println!("\n\t Texture Format Allowed Usages:");
print!("\t\t {texture_format_whitespace}");
wgpu::TextureUsages::println_table_header();
for format in TEXTURE_FORMAT_LIST {
let features = adapter.get_texture_format_features(format);
let format_name = match format {
wgpu::TextureFormat::Astc { block, channel } => {
format!("Astc{block:?}{channel:?}:")
let format_name = texture_format_name(format);
print!("\t\t{format_name:>0$}", max_format_name_size);
wgpu::TextureUsages::for_valid_bits(|bit, _i| {
print!("");
if features.allowed_usages.contains(bit) {
print!("{bit:?}");
}
_ => {
format!("{format:?}:")
else {
let length = format!("{bit:?}").len();
print!("{}", " ".repeat(length))
}
};
print!("\t\t{format_name:>21}");
for i in 0..(size_of::<wgpu::TextureUsages>() * 8) {
let bit = wgpu::TextureUsages::from_bits(1 << i as u32);
if let Some(bit) = bit {
print!("");
if features.allowed_usages.contains(bit) {
print!("{bit:?}");
}
else {
let length = format!("{bit:?}").len();
print!("{}", " ".repeat(length))
}
}
}
print!(" │ │ ");
for i in 0..(size_of::<wgpu::TextureFormatFeatureFlags>() * 8) {
let bit = wgpu::TextureFormatFeatureFlags::from_bits(1 << i as u32);
if let Some(bit) = bit {
if i != 0 {
print!("")
}
if features.flags.contains(bit) {
print!("{bit:?}");
}
else {
let length = format!("{bit:?}").len();
print!("{}", " ".repeat(length))
}
}
}
});
println!("");
}
println!("\t └──────────┴──────────┴─────────────────┴─────────────────┴───────────────────┘ └────────────┴────────────────┴────────────────┴────────────────┴─────────────────┴─────────────────────┴────────────────────┴───────────┘");
print!("\t\t {texture_format_whitespace}");
wgpu::TextureUsages::println_table_footer();
//////////////////////////
// Texture Format Flags //
//////////////////////////
println!("\n\t Texture Format Flags:");
print!("\t\t {texture_format_whitespace}");
wgpu::TextureFormatFeatureFlags::println_table_header();
for format in TEXTURE_FORMAT_LIST {
let features = adapter.get_texture_format_features(format);
let format_name = texture_format_name(format);
print!("\t\t{format_name:>0$}", max_format_name_size);
wgpu::TextureFormatFeatureFlags::for_valid_bits(|bit, _i| {
print!("");
if features.flags.contains(bit) {
print!("{bit:?}");
}
else {
let length = format!("{bit:?}").len();
print!("{}", " ".repeat(length))
}
});
println!("");
}
print!("\t\t ");
wgpu::TextureFormatFeatureFlags::println_table_footer();
}
pub fn main() {
@ -341,6 +366,103 @@ mod inner {
println!("=========== {adapter_count} adapters PASSED in {all_time:.3}s ===========");
}
}
trait Bitflags: Sized + Debug {
type Underlying: FromPrimitive;
fn from_bits(bits: Self::Underlying) -> Option<Self>;
fn for_valid_bits(mut func: impl FnMut(Self, usize)) {
for i in 0..(size_of::<Self>() * 8) {
let bit = Self::from_bits(
<Self::Underlying as FromPrimitive>::from_u64(1 << i as u64).unwrap(),
);
if let Some(bit) = bit {
func(bit, i)
}
}
}
fn max_debug_print_width() -> usize {
let mut width = 0;
Self::for_valid_bits(|bit, _i| {
width = width.max(format!("{bit:?}").len());
});
width
}
fn println_table_header() {
print!("┌─");
Self::for_valid_bits(|bit, i| {
if i != 0 {
print!("─┬─");
}
let length = format!("{bit:?}").len();
print!("{}", "".repeat(length));
});
println!("─┐");
}
fn println_table_footer() {
print!("└─");
Self::for_valid_bits(|bit, i| {
if i != 0 {
print!("─┴─");
}
let length = format!("{bit:?}").len();
print!("{}", "".repeat(length));
});
println!("─┘")
}
}
impl Bitflags for wgpu::DownlevelFlags {
type Underlying = u32;
fn from_bits(bits: u32) -> Option<Self> {
Self::from_bits(bits)
}
}
impl Bitflags for wgpu::Features {
type Underlying = u64;
fn from_bits(bits: u64) -> Option<Self> {
Self::from_bits(bits)
}
}
impl Bitflags for wgpu::TextureUsages {
type Underlying = u32;
fn from_bits(bits: u32) -> Option<Self> {
Self::from_bits(bits)
}
}
impl Bitflags for wgpu::TextureFormatFeatureFlags {
type Underlying = u32;
fn from_bits(bits: u32) -> Option<Self> {
Self::from_bits(bits)
}
}
fn max_texture_format_name_size() -> usize {
TEXTURE_FORMAT_LIST
.into_iter()
.map(|f| texture_format_name(f).len())
.max()
.unwrap()
}
fn texture_format_name(format: wgpu::TextureFormat) -> String {
match format {
wgpu::TextureFormat::Astc { block, channel } => {
format!("Astc{block:?}{channel:?}:")
}
_ => {
format!("{format:?}:")
}
}
}
}
fn main() {