mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-21 22:33:49 +00:00
Make wgpu-info
into a proper CLI Tool (#3856)
This commit is contained in:
parent
acb7712c5a
commit
e6be20f72e
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -1883,6 +1883,12 @@ dependencies = [
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pico-args"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.0"
|
||||
@ -3188,9 +3194,14 @@ dependencies = [
|
||||
name = "wgpu-info"
|
||||
version = "0.16.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.3.2",
|
||||
"env_logger",
|
||||
"pico-args",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wgpu",
|
||||
"wgpu-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -55,6 +55,7 @@ rev = "76003dc0035d53a474d366dcdf49d2e4d12e921f"
|
||||
version = "0.12.0"
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0"
|
||||
arrayvec = "0.7"
|
||||
async-executor = "1"
|
||||
bitflags = "2"
|
||||
@ -82,6 +83,7 @@ noise = { version = "0.7", default-features = false }
|
||||
obj = "0.10"
|
||||
# parking_lot 0.12 switches from `winapi` to `windows`; permit either
|
||||
parking_lot = ">=0.11,<0.13"
|
||||
pico-args = { version = "0.5.0", features = ["eq-separator", "short-space-opt", "combined-flags"] }
|
||||
png = "0.17.9"
|
||||
pollster = "0.2"
|
||||
profiling = { version = "1", default-features = false }
|
||||
|
@ -3,14 +3,18 @@ name = "wgpu-info"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
description = "Adapter information and per-adapter test program"
|
||||
description = "A tool to print and process information about available wgpu adapters."
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
bitflags.workspace = true
|
||||
env_logger.workspace = true
|
||||
pico-args.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
wgpu.workspace = true
|
||||
wgpu-types = { workspace = true, features = ["trace", "replay"] }
|
||||
|
90
wgpu-info/src/cli.rs
Normal file
90
wgpu-info/src/cli.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use std::{io, process::exit};
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
const HELP: &str = "\
|
||||
Usage: wgpu-info [--input <PATH>] [--output <PATH>] [--json]
|
||||
|
||||
Options:
|
||||
-h, --help Print this help message.
|
||||
-i, --input <PATH> Source to read JSON report from. (\"-\" reads from stdin)
|
||||
-o, --output <PATH> Destination to write output to. (\"-\" writes to stdout)
|
||||
-j, --json Output JSON information instead of human-readable text.
|
||||
";
|
||||
|
||||
fn exit_with_help() {
|
||||
eprintln!("{HELP}");
|
||||
exit(101);
|
||||
}
|
||||
|
||||
pub fn main() -> anyhow::Result<()> {
|
||||
let mut args = pico_args::Arguments::from_env();
|
||||
// Check for help flag before parsing arguments
|
||||
let help = args.contains(["-h", "--help"]);
|
||||
|
||||
if help {
|
||||
exit_with_help();
|
||||
}
|
||||
|
||||
// Argument parsing
|
||||
let input_path: Option<String> = args.opt_value_from_str(["-i", "--input"]).unwrap();
|
||||
let output_path: Option<String> = args.opt_value_from_str(["-o", "--output"]).unwrap();
|
||||
let json = args.contains(["-j", "--json"]);
|
||||
|
||||
let remaining = args.finish();
|
||||
if !remaining.is_empty() {
|
||||
eprint!("Unknown argument(s): ");
|
||||
for arg in remaining {
|
||||
eprint!("\"{}\" ", arg.to_string_lossy());
|
||||
}
|
||||
eprint!("\n\n");
|
||||
exit_with_help();
|
||||
}
|
||||
|
||||
env_logger::init();
|
||||
|
||||
// Generate or load report
|
||||
let report = match input_path.as_deref() {
|
||||
// Pull report from stdin or file
|
||||
Some(path) => {
|
||||
let json = if "-" == path {
|
||||
std::io::read_to_string(std::io::stdin()).context("Could not read from stdin")?
|
||||
} else {
|
||||
std::fs::read_to_string(path)
|
||||
.with_context(|| format!("Could not read from file \"{path}\""))?
|
||||
};
|
||||
crate::report::GpuReport::from_json(&json).context("Could not parse JSON")?
|
||||
}
|
||||
// Generate the report natively
|
||||
None => crate::report::GpuReport::generate(),
|
||||
};
|
||||
|
||||
// Setup output writer
|
||||
let mut file_handle;
|
||||
let mut std_handle;
|
||||
let output: &mut dyn io::Write = match output_path.as_deref() {
|
||||
None | Some("-") => {
|
||||
std_handle = io::stdout();
|
||||
&mut std_handle
|
||||
}
|
||||
Some(path) => {
|
||||
file_handle = std::fs::File::create(path)
|
||||
.with_context(|| format!("Could not create file \"{path}\""))?;
|
||||
&mut file_handle
|
||||
}
|
||||
};
|
||||
let mut output = io::BufWriter::new(output);
|
||||
|
||||
let output_name = output_path.as_deref().unwrap_or("stdout");
|
||||
|
||||
if json {
|
||||
report
|
||||
.into_json(output)
|
||||
.with_context(|| format!("Failed to write to output: {output_name}"))?;
|
||||
} else {
|
||||
crate::human::print_adapters(&mut output, &report)
|
||||
.with_context(|| format!("Failed to write to output: {output_name}"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
240
wgpu-info/src/human.rs
Normal file
240
wgpu-info/src/human.rs
Normal file
@ -0,0 +1,240 @@
|
||||
use std::io;
|
||||
|
||||
use bitflags::Flags;
|
||||
|
||||
use crate::{
|
||||
report::{AdapterReport, GpuReport},
|
||||
texture::{self, TEXTURE_FORMAT_LIST},
|
||||
};
|
||||
|
||||
trait FlagsExt: Flags {
|
||||
fn name(&self) -> &'static str {
|
||||
self.iter_names().next().unwrap().0
|
||||
}
|
||||
|
||||
fn valid_bits() -> std::iter::Enumerate<bitflags::iter::Iter<Self>> {
|
||||
Self::all().iter().enumerate()
|
||||
}
|
||||
|
||||
fn max_debug_print_width() -> usize {
|
||||
let mut width = 0;
|
||||
for bit in Self::all().iter() {
|
||||
width = width.max(bit.name().len());
|
||||
}
|
||||
width
|
||||
}
|
||||
|
||||
fn println_table_header(output: &mut impl io::Write) -> io::Result<()> {
|
||||
write!(output, "┌─")?;
|
||||
for (i, bit) in Self::valid_bits() {
|
||||
if i != 0 {
|
||||
write!(output, "─┬─")?;
|
||||
}
|
||||
let length = bit.name().len();
|
||||
write!(output, "{}", "─".repeat(length))?;
|
||||
}
|
||||
writeln!(output, "─┐")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn println_table_footer(output: &mut impl io::Write) -> io::Result<()> {
|
||||
write!(output, "└─")?;
|
||||
for (i, bit) in Self::valid_bits() {
|
||||
if i != 0 {
|
||||
write!(output, "─┴─")?;
|
||||
}
|
||||
let length = bit.name().len();
|
||||
write!(output, "{}", "─".repeat(length))?;
|
||||
}
|
||||
writeln!(output, "─┘")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FlagsExt for T where T: Flags {}
|
||||
|
||||
// Lets keep these print statements on one line
|
||||
#[rustfmt::skip]
|
||||
fn print_adapter(output: &mut impl io::Write, report: &AdapterReport, idx: usize) -> io::Result<()> {
|
||||
let AdapterReport {
|
||||
info,
|
||||
features,
|
||||
limits,
|
||||
downlevel_caps:
|
||||
downlevel,
|
||||
texture_format_features
|
||||
} = &report;
|
||||
|
||||
//////////////////
|
||||
// Adapter Info //
|
||||
//////////////////
|
||||
|
||||
writeln!(output, "Adapter {idx}:")?;
|
||||
writeln!(output, "\t Backend: {:?}", info.backend)?;
|
||||
writeln!(output, "\t Name: {:?}", info.name)?;
|
||||
writeln!(output, "\t VendorID: {:?}", info.vendor)?;
|
||||
writeln!(output, "\t DeviceID: {:?}", info.device)?;
|
||||
writeln!(output, "\t Type: {:?}", info.device_type)?;
|
||||
writeln!(output, "\t Driver: {:?}", info.driver)?;
|
||||
writeln!(output, "\tDriverInfo: {:?}", info.driver_info)?;
|
||||
writeln!(output, "\t Compliant: {:?}", downlevel.is_webgpu_compliant())?;
|
||||
|
||||
//////////////
|
||||
// Features //
|
||||
//////////////
|
||||
|
||||
writeln!(output, "\tFeatures:")?;
|
||||
let max_feature_flag_width = wgpu::Features::max_debug_print_width();
|
||||
for bit in wgpu::Features::all().iter() {
|
||||
writeln!(output, "\t\t{:>width$}: {}", bit.name(), features.contains(bit), width = max_feature_flag_width)?;
|
||||
}
|
||||
|
||||
////////////
|
||||
// Limits //
|
||||
////////////
|
||||
|
||||
writeln!(output, "\tLimits:")?;
|
||||
let wgpu::Limits {
|
||||
max_texture_dimension_1d,
|
||||
max_texture_dimension_2d,
|
||||
max_texture_dimension_3d,
|
||||
max_texture_array_layers,
|
||||
max_bind_groups,
|
||||
max_bindings_per_bind_group,
|
||||
max_dynamic_uniform_buffers_per_pipeline_layout,
|
||||
max_dynamic_storage_buffers_per_pipeline_layout,
|
||||
max_sampled_textures_per_shader_stage,
|
||||
max_samplers_per_shader_stage,
|
||||
max_storage_buffers_per_shader_stage,
|
||||
max_storage_textures_per_shader_stage,
|
||||
max_uniform_buffers_per_shader_stage,
|
||||
max_uniform_buffer_binding_size,
|
||||
max_storage_buffer_binding_size,
|
||||
max_buffer_size,
|
||||
max_vertex_buffers,
|
||||
max_vertex_attributes,
|
||||
max_vertex_buffer_array_stride,
|
||||
max_push_constant_size,
|
||||
min_uniform_buffer_offset_alignment,
|
||||
min_storage_buffer_offset_alignment,
|
||||
max_inter_stage_shader_components,
|
||||
max_compute_workgroup_storage_size,
|
||||
max_compute_invocations_per_workgroup,
|
||||
max_compute_workgroup_size_x,
|
||||
max_compute_workgroup_size_y,
|
||||
max_compute_workgroup_size_z,
|
||||
max_compute_workgroups_per_dimension,
|
||||
} = limits;
|
||||
writeln!(output, "\t\t Max Texture Dimension 1d: {max_texture_dimension_1d}")?;
|
||||
writeln!(output, "\t\t Max Texture Dimension 2d: {max_texture_dimension_2d}")?;
|
||||
writeln!(output, "\t\t Max Texture Dimension 3d: {max_texture_dimension_3d}")?;
|
||||
writeln!(output, "\t\t Max Texture Array Layers: {max_texture_array_layers}")?;
|
||||
writeln!(output, "\t\t Max Bind Groups: {max_bind_groups}")?;
|
||||
writeln!(output, "\t\t Max Bindings Per Bind Group: {max_bindings_per_bind_group}")?;
|
||||
writeln!(output, "\t\t Max Dynamic Uniform Buffers Per Pipeline Layout: {max_dynamic_uniform_buffers_per_pipeline_layout}")?;
|
||||
writeln!(output, "\t\t Max Dynamic Storage Buffers Per Pipeline Layout: {max_dynamic_storage_buffers_per_pipeline_layout}")?;
|
||||
writeln!(output, "\t\t Max Sampled Textures Per Shader Stage: {max_sampled_textures_per_shader_stage}")?;
|
||||
writeln!(output, "\t\t Max Samplers Per Shader Stage: {max_samplers_per_shader_stage}")?;
|
||||
writeln!(output, "\t\t Max Storage Buffers Per Shader Stage: {max_storage_buffers_per_shader_stage}")?;
|
||||
writeln!(output, "\t\t Max Storage Textures Per Shader Stage: {max_storage_textures_per_shader_stage}")?;
|
||||
writeln!(output, "\t\t Max Uniform Buffers Per Shader Stage: {max_uniform_buffers_per_shader_stage}")?;
|
||||
writeln!(output, "\t\t Max Uniform Buffer Binding Size: {max_uniform_buffer_binding_size}")?;
|
||||
writeln!(output, "\t\t Max Storage Buffer Binding Size: {max_storage_buffer_binding_size}")?;
|
||||
writeln!(output, "\t\t Max Buffer Size: {max_buffer_size}")?;
|
||||
writeln!(output, "\t\t Max Vertex Buffers: {max_vertex_buffers}")?;
|
||||
writeln!(output, "\t\t Max Vertex Attributes: {max_vertex_attributes}")?;
|
||||
writeln!(output, "\t\t Max Vertex Buffer Array Stride: {max_vertex_buffer_array_stride}")?;
|
||||
writeln!(output, "\t\t Max Push Constant Size: {max_push_constant_size}")?;
|
||||
writeln!(output, "\t\t Min Uniform Buffer Offset Alignment: {min_uniform_buffer_offset_alignment}")?;
|
||||
writeln!(output, "\t\t Min Storage Buffer Offset Alignment: {min_storage_buffer_offset_alignment}")?;
|
||||
writeln!(output, "\t\t Max Inter-Stage Shader Component: {max_inter_stage_shader_components}")?;
|
||||
writeln!(output, "\t\t Max Compute Workgroup Storage Size: {max_compute_workgroup_storage_size}")?;
|
||||
writeln!(output, "\t\t Max Compute Invocations Per Workgroup: {max_compute_invocations_per_workgroup}")?;
|
||||
writeln!(output, "\t\t Max Compute Workgroup Size X: {max_compute_workgroup_size_x}")?;
|
||||
writeln!(output, "\t\t Max Compute Workgroup Size Y: {max_compute_workgroup_size_y}")?;
|
||||
writeln!(output, "\t\t Max Compute Workgroup Size Z: {max_compute_workgroup_size_z}")?;
|
||||
writeln!(output, "\t\t Max Compute Workgroups Per Dimension: {max_compute_workgroups_per_dimension}")?;
|
||||
|
||||
//////////////////////////
|
||||
// Downlevel Properties //
|
||||
//////////////////////////
|
||||
|
||||
writeln!(output, "\tDownlevel Properties:")?;
|
||||
let wgpu::DownlevelCapabilities {
|
||||
shader_model,
|
||||
limits: _,
|
||||
flags,
|
||||
} = downlevel;
|
||||
writeln!(output, "\t\t Shader Model: {shader_model:?}")?;
|
||||
let max_downlevel_flag_width = wgpu::DownlevelFlags::max_debug_print_width();
|
||||
for bit in wgpu::DownlevelFlags::all().iter() {
|
||||
writeln!(output, "\t\t{:>width$}: {}", bit.name(), flags.contains(bit), width = max_downlevel_flag_width)?;
|
||||
};
|
||||
|
||||
////////////////////
|
||||
// Texture Usages //
|
||||
////////////////////
|
||||
|
||||
let max_format_name_size = texture::max_texture_format_string_size();
|
||||
let texture_format_whitespace = " ".repeat(max_format_name_size);
|
||||
|
||||
writeln!(output, "\n\t Texture Format Allowed Usages:")?;
|
||||
|
||||
write!(output, "\t\t {texture_format_whitespace}")?;
|
||||
wgpu::TextureUsages::println_table_header(output)?;
|
||||
for format in TEXTURE_FORMAT_LIST {
|
||||
let features = texture_format_features[&format];
|
||||
let format_name = texture::texture_format_name(format);
|
||||
write!(output, "\t\t{format_name:>0$}", max_format_name_size)?;
|
||||
for bit in wgpu::TextureUsages::all().iter() {
|
||||
write!(output, " │ ")?;
|
||||
if features.allowed_usages.contains(bit) {
|
||||
write!(output, "{}", bit.name())?;
|
||||
}
|
||||
else {
|
||||
let length = bit.name().len();
|
||||
write!(output, "{}", " ".repeat(length))?;
|
||||
}
|
||||
};
|
||||
writeln!(output, " │")?;
|
||||
}
|
||||
write!(output, "\t\t {texture_format_whitespace}")?;
|
||||
wgpu::TextureUsages::println_table_footer(output)?;
|
||||
|
||||
//////////////////////////
|
||||
// Texture Format Flags //
|
||||
//////////////////////////
|
||||
|
||||
writeln!(output, "\n\t Texture Format Flags:")?;
|
||||
|
||||
write!(output, "\t\t {texture_format_whitespace}")?;
|
||||
wgpu::TextureFormatFeatureFlags::println_table_header(output)?;
|
||||
|
||||
for format in TEXTURE_FORMAT_LIST {
|
||||
let features = texture_format_features[&format];
|
||||
let format_name = texture::texture_format_name(format);
|
||||
|
||||
write!(output, "\t\t{format_name:>0$}", max_format_name_size)?;
|
||||
for bit in wgpu::TextureFormatFeatureFlags::all().iter() {
|
||||
write!(output, " │ ")?;
|
||||
if features.flags.contains(bit) {
|
||||
write!(output, "{}", bit.name())?;
|
||||
}
|
||||
else {
|
||||
let length = bit.name().len();
|
||||
write!(output, "{}", " ".repeat(length))?;
|
||||
}
|
||||
};
|
||||
writeln!(output, " │")?;
|
||||
}
|
||||
write!(output, "\t\t {texture_format_whitespace}")?;
|
||||
wgpu::TextureFormatFeatureFlags::println_table_footer(output)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_adapters(output: &mut impl io::Write, report: &GpuReport) -> io::Result<()> {
|
||||
for (idx, adapter) in report.devices.iter().enumerate() {
|
||||
print_adapter(output, adapter, idx)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -1,435 +1,16 @@
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod inner {
|
||||
use std::{
|
||||
process::{exit, Command},
|
||||
time::Instant,
|
||||
};
|
||||
mod cli;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod human;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod report;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod texture;
|
||||
|
||||
use bitflags::Flags;
|
||||
|
||||
// Lets keep these on one line
|
||||
#[rustfmt::skip]
|
||||
const TEXTURE_FORMAT_LIST: [wgpu::TextureFormat; 114] = [
|
||||
wgpu::TextureFormat::R8Unorm,
|
||||
wgpu::TextureFormat::R8Snorm,
|
||||
wgpu::TextureFormat::R8Uint,
|
||||
wgpu::TextureFormat::R8Sint,
|
||||
wgpu::TextureFormat::R16Uint,
|
||||
wgpu::TextureFormat::R16Sint,
|
||||
wgpu::TextureFormat::R16Unorm,
|
||||
wgpu::TextureFormat::R16Snorm,
|
||||
wgpu::TextureFormat::R16Float,
|
||||
wgpu::TextureFormat::Rg8Unorm,
|
||||
wgpu::TextureFormat::Rg8Snorm,
|
||||
wgpu::TextureFormat::Rg8Uint,
|
||||
wgpu::TextureFormat::Rg8Sint,
|
||||
wgpu::TextureFormat::R32Uint,
|
||||
wgpu::TextureFormat::R32Sint,
|
||||
wgpu::TextureFormat::R32Float,
|
||||
wgpu::TextureFormat::Rg16Uint,
|
||||
wgpu::TextureFormat::Rg16Sint,
|
||||
wgpu::TextureFormat::Rg16Unorm,
|
||||
wgpu::TextureFormat::Rg16Snorm,
|
||||
wgpu::TextureFormat::Rg16Float,
|
||||
wgpu::TextureFormat::Rgba8Unorm,
|
||||
wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
wgpu::TextureFormat::Rgba8Snorm,
|
||||
wgpu::TextureFormat::Rgba8Uint,
|
||||
wgpu::TextureFormat::Rgba8Sint,
|
||||
wgpu::TextureFormat::Bgra8Unorm,
|
||||
wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
wgpu::TextureFormat::Rgb10a2Unorm,
|
||||
wgpu::TextureFormat::Rg11b10Float,
|
||||
wgpu::TextureFormat::Rg32Uint,
|
||||
wgpu::TextureFormat::Rg32Sint,
|
||||
wgpu::TextureFormat::Rg32Float,
|
||||
wgpu::TextureFormat::Rgba16Uint,
|
||||
wgpu::TextureFormat::Rgba16Sint,
|
||||
wgpu::TextureFormat::Rgba16Unorm,
|
||||
wgpu::TextureFormat::Rgba16Snorm,
|
||||
wgpu::TextureFormat::Rgba16Float,
|
||||
wgpu::TextureFormat::Rgba32Uint,
|
||||
wgpu::TextureFormat::Rgba32Sint,
|
||||
wgpu::TextureFormat::Rgba32Float,
|
||||
wgpu::TextureFormat::Stencil8,
|
||||
wgpu::TextureFormat::Depth16Unorm,
|
||||
wgpu::TextureFormat::Depth32Float,
|
||||
wgpu::TextureFormat::Depth32FloatStencil8,
|
||||
wgpu::TextureFormat::Depth24Plus,
|
||||
wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
wgpu::TextureFormat::Rgb9e5Ufloat,
|
||||
wgpu::TextureFormat::Bc1RgbaUnorm,
|
||||
wgpu::TextureFormat::Bc1RgbaUnormSrgb,
|
||||
wgpu::TextureFormat::Bc2RgbaUnorm,
|
||||
wgpu::TextureFormat::Bc2RgbaUnormSrgb,
|
||||
wgpu::TextureFormat::Bc3RgbaUnorm,
|
||||
wgpu::TextureFormat::Bc3RgbaUnormSrgb,
|
||||
wgpu::TextureFormat::Bc4RUnorm,
|
||||
wgpu::TextureFormat::Bc4RSnorm,
|
||||
wgpu::TextureFormat::Bc5RgUnorm,
|
||||
wgpu::TextureFormat::Bc5RgSnorm,
|
||||
wgpu::TextureFormat::Bc6hRgbUfloat,
|
||||
wgpu::TextureFormat::Bc6hRgbFloat,
|
||||
wgpu::TextureFormat::Bc7RgbaUnorm,
|
||||
wgpu::TextureFormat::Bc7RgbaUnormSrgb,
|
||||
wgpu::TextureFormat::Etc2Rgb8Unorm,
|
||||
wgpu::TextureFormat::Etc2Rgb8UnormSrgb,
|
||||
wgpu::TextureFormat::Etc2Rgb8A1Unorm,
|
||||
wgpu::TextureFormat::Etc2Rgb8A1UnormSrgb,
|
||||
wgpu::TextureFormat::Etc2Rgba8Unorm,
|
||||
wgpu::TextureFormat::Etc2Rgba8UnormSrgb,
|
||||
wgpu::TextureFormat::EacR11Unorm,
|
||||
wgpu::TextureFormat::EacR11Snorm,
|
||||
wgpu::TextureFormat::EacRg11Unorm,
|
||||
wgpu::TextureFormat::EacRg11Snorm,
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::Hdr },
|
||||
];
|
||||
|
||||
// Lets keep these on one line
|
||||
#[rustfmt::skip]
|
||||
fn print_info_from_adapter(adapter: &wgpu::Adapter, idx: usize) {
|
||||
let info = adapter.get_info();
|
||||
let downlevel = adapter.get_downlevel_capabilities();
|
||||
let features = adapter.features();
|
||||
let limits = adapter.limits();
|
||||
|
||||
//////////////////
|
||||
// Adapter Info //
|
||||
//////////////////
|
||||
|
||||
println!("Adapter {idx}:");
|
||||
println!("\t Backend: {:?}", info.backend);
|
||||
println!("\t Name: {:?}", info.name);
|
||||
println!("\t VendorID: {:?}", info.vendor);
|
||||
println!("\t DeviceID: {:?}", info.device);
|
||||
println!("\t Type: {:?}", info.device_type);
|
||||
println!("\t Driver: {:?}", info.driver);
|
||||
println!("\tDriverInfo: {:?}", info.driver_info);
|
||||
println!("\t Compliant: {:?}", downlevel.is_webgpu_compliant());
|
||||
|
||||
//////////////
|
||||
// Features //
|
||||
//////////////
|
||||
|
||||
println!("\tFeatures:");
|
||||
let max_feature_flag_width = wgpu::Features::max_debug_print_width();
|
||||
for bit in wgpu::Features::all().iter() {
|
||||
println!("\t\t{:>width$}: {}", bit.name(), features.contains(bit), width = max_feature_flag_width);
|
||||
}
|
||||
|
||||
////////////
|
||||
// Limits //
|
||||
////////////
|
||||
|
||||
println!("\tLimits:");
|
||||
let wgpu::Limits {
|
||||
max_texture_dimension_1d,
|
||||
max_texture_dimension_2d,
|
||||
max_texture_dimension_3d,
|
||||
max_texture_array_layers,
|
||||
max_bind_groups,
|
||||
max_bindings_per_bind_group,
|
||||
max_dynamic_uniform_buffers_per_pipeline_layout,
|
||||
max_dynamic_storage_buffers_per_pipeline_layout,
|
||||
max_sampled_textures_per_shader_stage,
|
||||
max_samplers_per_shader_stage,
|
||||
max_storage_buffers_per_shader_stage,
|
||||
max_storage_textures_per_shader_stage,
|
||||
max_uniform_buffers_per_shader_stage,
|
||||
max_uniform_buffer_binding_size,
|
||||
max_storage_buffer_binding_size,
|
||||
max_buffer_size,
|
||||
max_vertex_buffers,
|
||||
max_vertex_attributes,
|
||||
max_vertex_buffer_array_stride,
|
||||
max_push_constant_size,
|
||||
min_uniform_buffer_offset_alignment,
|
||||
min_storage_buffer_offset_alignment,
|
||||
max_inter_stage_shader_components,
|
||||
max_compute_workgroup_storage_size,
|
||||
max_compute_invocations_per_workgroup,
|
||||
max_compute_workgroup_size_x,
|
||||
max_compute_workgroup_size_y,
|
||||
max_compute_workgroup_size_z,
|
||||
max_compute_workgroups_per_dimension,
|
||||
} = limits;
|
||||
println!("\t\t Max Texture Dimension 1d: {max_texture_dimension_1d}");
|
||||
println!("\t\t Max Texture Dimension 2d: {max_texture_dimension_2d}");
|
||||
println!("\t\t Max Texture Dimension 3d: {max_texture_dimension_3d}");
|
||||
println!("\t\t Max Texture Array Layers: {max_texture_array_layers}");
|
||||
println!("\t\t Max Bind Groups: {max_bind_groups}");
|
||||
println!("\t\t Max Bindings Per Bind Group: {max_bindings_per_bind_group}");
|
||||
println!("\t\t Max Dynamic Uniform Buffers Per Pipeline Layout: {max_dynamic_uniform_buffers_per_pipeline_layout}");
|
||||
println!("\t\t Max Dynamic Storage Buffers Per Pipeline Layout: {max_dynamic_storage_buffers_per_pipeline_layout}");
|
||||
println!("\t\t Max Sampled Textures Per Shader Stage: {max_sampled_textures_per_shader_stage}");
|
||||
println!("\t\t Max Samplers Per Shader Stage: {max_samplers_per_shader_stage}");
|
||||
println!("\t\t Max Storage Buffers Per Shader Stage: {max_storage_buffers_per_shader_stage}");
|
||||
println!("\t\t Max Storage Textures Per Shader Stage: {max_storage_textures_per_shader_stage}");
|
||||
println!("\t\t Max Uniform Buffers Per Shader Stage: {max_uniform_buffers_per_shader_stage}");
|
||||
println!("\t\t Max Uniform Buffer Binding Size: {max_uniform_buffer_binding_size}");
|
||||
println!("\t\t Max Storage Buffer Binding Size: {max_storage_buffer_binding_size}");
|
||||
println!("\t\t Max Buffer Size: {max_buffer_size}");
|
||||
println!("\t\t Max Vertex Buffers: {max_vertex_buffers}");
|
||||
println!("\t\t Max Vertex Attributes: {max_vertex_attributes}");
|
||||
println!("\t\t Max Vertex Buffer Array Stride: {max_vertex_buffer_array_stride}");
|
||||
println!("\t\t Max Push Constant Size: {max_push_constant_size}");
|
||||
println!("\t\t Min Uniform Buffer Offset Alignment: {min_uniform_buffer_offset_alignment}");
|
||||
println!("\t\t Min Storage Buffer Offset Alignment: {min_storage_buffer_offset_alignment}");
|
||||
println!("\t\t Max Inter-Stage Shader Component: {max_inter_stage_shader_components}");
|
||||
println!("\t\t Max Compute Workgroup Storage Size: {max_compute_workgroup_storage_size}");
|
||||
println!("\t\t Max Compute Invocations Per Workgroup: {max_compute_invocations_per_workgroup}");
|
||||
println!("\t\t Max Compute Workgroup Size X: {max_compute_workgroup_size_x}");
|
||||
println!("\t\t Max Compute Workgroup Size Y: {max_compute_workgroup_size_y}");
|
||||
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,
|
||||
limits: _,
|
||||
flags,
|
||||
} = downlevel;
|
||||
println!("\t\t Shader Model: {shader_model:?}");
|
||||
let max_downlevel_flag_width = wgpu::DownlevelFlags::max_debug_print_width();
|
||||
for bit in wgpu::DownlevelFlags::all().iter() {
|
||||
println!("\t\t{:>width$}: {}", bit.name(), flags.contains(bit), width = max_downlevel_flag_width);
|
||||
};
|
||||
|
||||
////////////////////
|
||||
// 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 = texture_format_name(format);
|
||||
print!("\t\t{format_name:>0$}", max_format_name_size);
|
||||
for bit in wgpu::TextureUsages::all().iter() {
|
||||
print!(" │ ");
|
||||
if features.allowed_usages.contains(bit) {
|
||||
print!("{}", bit.name());
|
||||
}
|
||||
else {
|
||||
let length = bit.name().len();
|
||||
print!("{}", " ".repeat(length))
|
||||
}
|
||||
};
|
||||
println!(" │");
|
||||
}
|
||||
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);
|
||||
for bit in wgpu::TextureFormatFeatureFlags::all().iter() {
|
||||
print!(" │ ");
|
||||
if features.flags.contains(bit) {
|
||||
print!("{}", bit.name());
|
||||
}
|
||||
else {
|
||||
let length = bit.name().len();
|
||||
print!("{}", " ".repeat(length))
|
||||
}
|
||||
};
|
||||
println!(" │");
|
||||
}
|
||||
print!("\t\t {texture_format_whitespace}");
|
||||
wgpu::TextureFormatFeatureFlags::println_table_footer();
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
env_logger::init();
|
||||
let args: Vec<_> = std::env::args().skip(1).collect();
|
||||
|
||||
let instance = wgpu::Instance::default();
|
||||
let adapters: Vec<_> = instance.enumerate_adapters(wgpu::Backends::all()).collect();
|
||||
let adapter_count = adapters.len();
|
||||
|
||||
if args.is_empty() {
|
||||
for (idx, adapter) in adapters.into_iter().enumerate() {
|
||||
print_info_from_adapter(&adapter, idx)
|
||||
}
|
||||
} else {
|
||||
let all_start = Instant::now();
|
||||
|
||||
for (idx, adapter) in adapters.into_iter().enumerate() {
|
||||
let adapter_start_time = Instant::now();
|
||||
let idx = idx + 1;
|
||||
let info = adapter.get_info();
|
||||
println!(
|
||||
"=========== TESTING {} on {:?} ({} of {}) ===========",
|
||||
info.name, info.backend, idx, adapter_count
|
||||
);
|
||||
let exit_status = Command::new(&args[0])
|
||||
.args(&args[1..])
|
||||
.env("WGPU_ADAPTER_NAME", &info.name)
|
||||
.env(
|
||||
"WGPU_BACKEND",
|
||||
match info.backend {
|
||||
wgpu::Backend::Empty => unreachable!(),
|
||||
wgpu::Backend::Vulkan => "vulkan",
|
||||
wgpu::Backend::Metal => "metal",
|
||||
wgpu::Backend::Dx12 => "dx12",
|
||||
wgpu::Backend::Dx11 => "dx11",
|
||||
wgpu::Backend::Gl => "gl",
|
||||
wgpu::Backend::BrowserWebGpu => "webgpu",
|
||||
},
|
||||
)
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
|
||||
let adapter_time = adapter_start_time.elapsed().as_secs_f32();
|
||||
|
||||
if exit_status.success() {
|
||||
println!(
|
||||
"=========== PASSED! {} on {:?} ({} of {}) in {:.3}s ===========",
|
||||
info.name, info.backend, idx, adapter_count, adapter_time
|
||||
);
|
||||
} else {
|
||||
println!(
|
||||
"=========== FAILED! {} on {:?} ({} of {}) in {:.3}s ===========",
|
||||
info.name, info.backend, idx, adapter_count, adapter_time
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
let all_time = all_start.elapsed().as_secs_f32();
|
||||
|
||||
println!("=========== {adapter_count} adapters PASSED in {all_time:.3}s ===========");
|
||||
}
|
||||
}
|
||||
|
||||
trait FlagsExt: Flags {
|
||||
fn name(&self) -> &'static str {
|
||||
self.iter_names().next().unwrap().0
|
||||
}
|
||||
|
||||
fn valid_bits() -> std::iter::Enumerate<bitflags::iter::Iter<Self>> {
|
||||
Self::all().iter().enumerate()
|
||||
}
|
||||
|
||||
fn max_debug_print_width() -> usize {
|
||||
let mut width = 0;
|
||||
for bit in Self::all().iter() {
|
||||
width = width.max(bit.name().len());
|
||||
}
|
||||
width
|
||||
}
|
||||
|
||||
fn println_table_header() {
|
||||
print!("┌─");
|
||||
for (i, bit) in Self::valid_bits() {
|
||||
if i != 0 {
|
||||
print!("─┬─");
|
||||
}
|
||||
let length = bit.name().len();
|
||||
print!("{}", "─".repeat(length));
|
||||
}
|
||||
println!("─┐");
|
||||
}
|
||||
|
||||
fn println_table_footer() {
|
||||
print!("└─");
|
||||
for (i, bit) in Self::valid_bits() {
|
||||
if i != 0 {
|
||||
print!("─┴─");
|
||||
}
|
||||
let length = bit.name().len();
|
||||
print!("{}", "─".repeat(length));
|
||||
}
|
||||
println!("─┘")
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FlagsExt for T where T: Flags {}
|
||||
|
||||
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() {
|
||||
fn main() -> anyhow::Result<()> {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
inner::main();
|
||||
{
|
||||
cli::main()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
58
wgpu-info/src/report.rs
Normal file
58
wgpu-info/src/report.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use std::{collections::HashMap, io};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use wgpu::{
|
||||
AdapterInfo, DownlevelCapabilities, Features, Limits, TextureFormat, TextureFormatFeatures,
|
||||
};
|
||||
|
||||
use crate::texture;
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct GpuReport {
|
||||
pub devices: Vec<AdapterReport>,
|
||||
}
|
||||
|
||||
impl GpuReport {
|
||||
pub fn generate() -> Self {
|
||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::default());
|
||||
let adapters = instance.enumerate_adapters(wgpu::Backends::all());
|
||||
|
||||
let mut devices = Vec::with_capacity(adapters.len());
|
||||
for adapter in adapters {
|
||||
let features = adapter.features();
|
||||
let limits = adapter.limits();
|
||||
let downlevel_caps = adapter.get_downlevel_capabilities();
|
||||
let texture_format_features = texture::TEXTURE_FORMAT_LIST
|
||||
.into_iter()
|
||||
.map(|format| (format, adapter.get_texture_format_features(format)))
|
||||
.collect();
|
||||
|
||||
devices.push(AdapterReport {
|
||||
info: adapter.get_info(),
|
||||
features,
|
||||
limits,
|
||||
downlevel_caps,
|
||||
texture_format_features,
|
||||
});
|
||||
}
|
||||
|
||||
Self { devices }
|
||||
}
|
||||
|
||||
pub fn from_json(file: &str) -> serde_json::Result<Self> {
|
||||
serde_json::from_str(file)
|
||||
}
|
||||
|
||||
pub fn into_json(self, output: impl io::Write) -> serde_json::Result<()> {
|
||||
serde_json::to_writer_pretty(output, &self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct AdapterReport {
|
||||
pub info: AdapterInfo,
|
||||
pub features: Features,
|
||||
pub limits: Limits,
|
||||
pub downlevel_caps: DownlevelCapabilities,
|
||||
pub texture_format_features: HashMap<TextureFormat, TextureFormatFeatures>,
|
||||
}
|
137
wgpu-info/src/texture.rs
Normal file
137
wgpu-info/src/texture.rs
Normal file
@ -0,0 +1,137 @@
|
||||
// Lets keep these on one line
|
||||
#[rustfmt::skip]
|
||||
pub const TEXTURE_FORMAT_LIST: [wgpu::TextureFormat; 114] = [
|
||||
wgpu::TextureFormat::R8Unorm,
|
||||
wgpu::TextureFormat::R8Snorm,
|
||||
wgpu::TextureFormat::R8Uint,
|
||||
wgpu::TextureFormat::R8Sint,
|
||||
wgpu::TextureFormat::R16Uint,
|
||||
wgpu::TextureFormat::R16Sint,
|
||||
wgpu::TextureFormat::R16Unorm,
|
||||
wgpu::TextureFormat::R16Snorm,
|
||||
wgpu::TextureFormat::R16Float,
|
||||
wgpu::TextureFormat::Rg8Unorm,
|
||||
wgpu::TextureFormat::Rg8Snorm,
|
||||
wgpu::TextureFormat::Rg8Uint,
|
||||
wgpu::TextureFormat::Rg8Sint,
|
||||
wgpu::TextureFormat::R32Uint,
|
||||
wgpu::TextureFormat::R32Sint,
|
||||
wgpu::TextureFormat::R32Float,
|
||||
wgpu::TextureFormat::Rg16Uint,
|
||||
wgpu::TextureFormat::Rg16Sint,
|
||||
wgpu::TextureFormat::Rg16Unorm,
|
||||
wgpu::TextureFormat::Rg16Snorm,
|
||||
wgpu::TextureFormat::Rg16Float,
|
||||
wgpu::TextureFormat::Rgba8Unorm,
|
||||
wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
wgpu::TextureFormat::Rgba8Snorm,
|
||||
wgpu::TextureFormat::Rgba8Uint,
|
||||
wgpu::TextureFormat::Rgba8Sint,
|
||||
wgpu::TextureFormat::Bgra8Unorm,
|
||||
wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
wgpu::TextureFormat::Rgb10a2Unorm,
|
||||
wgpu::TextureFormat::Rg11b10Float,
|
||||
wgpu::TextureFormat::Rg32Uint,
|
||||
wgpu::TextureFormat::Rg32Sint,
|
||||
wgpu::TextureFormat::Rg32Float,
|
||||
wgpu::TextureFormat::Rgba16Uint,
|
||||
wgpu::TextureFormat::Rgba16Sint,
|
||||
wgpu::TextureFormat::Rgba16Unorm,
|
||||
wgpu::TextureFormat::Rgba16Snorm,
|
||||
wgpu::TextureFormat::Rgba16Float,
|
||||
wgpu::TextureFormat::Rgba32Uint,
|
||||
wgpu::TextureFormat::Rgba32Sint,
|
||||
wgpu::TextureFormat::Rgba32Float,
|
||||
wgpu::TextureFormat::Stencil8,
|
||||
wgpu::TextureFormat::Depth16Unorm,
|
||||
wgpu::TextureFormat::Depth32Float,
|
||||
wgpu::TextureFormat::Depth32FloatStencil8,
|
||||
wgpu::TextureFormat::Depth24Plus,
|
||||
wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
wgpu::TextureFormat::Rgb9e5Ufloat,
|
||||
wgpu::TextureFormat::Bc1RgbaUnorm,
|
||||
wgpu::TextureFormat::Bc1RgbaUnormSrgb,
|
||||
wgpu::TextureFormat::Bc2RgbaUnorm,
|
||||
wgpu::TextureFormat::Bc2RgbaUnormSrgb,
|
||||
wgpu::TextureFormat::Bc3RgbaUnorm,
|
||||
wgpu::TextureFormat::Bc3RgbaUnormSrgb,
|
||||
wgpu::TextureFormat::Bc4RUnorm,
|
||||
wgpu::TextureFormat::Bc4RSnorm,
|
||||
wgpu::TextureFormat::Bc5RgUnorm,
|
||||
wgpu::TextureFormat::Bc5RgSnorm,
|
||||
wgpu::TextureFormat::Bc6hRgbUfloat,
|
||||
wgpu::TextureFormat::Bc6hRgbFloat,
|
||||
wgpu::TextureFormat::Bc7RgbaUnorm,
|
||||
wgpu::TextureFormat::Bc7RgbaUnormSrgb,
|
||||
wgpu::TextureFormat::Etc2Rgb8Unorm,
|
||||
wgpu::TextureFormat::Etc2Rgb8UnormSrgb,
|
||||
wgpu::TextureFormat::Etc2Rgb8A1Unorm,
|
||||
wgpu::TextureFormat::Etc2Rgb8A1UnormSrgb,
|
||||
wgpu::TextureFormat::Etc2Rgba8Unorm,
|
||||
wgpu::TextureFormat::Etc2Rgba8UnormSrgb,
|
||||
wgpu::TextureFormat::EacR11Unorm,
|
||||
wgpu::TextureFormat::EacR11Snorm,
|
||||
wgpu::TextureFormat::EacRg11Unorm,
|
||||
wgpu::TextureFormat::EacRg11Snorm,
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::Hdr },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::Unorm },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::UnormSrgb },
|
||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::Hdr },
|
||||
];
|
||||
|
||||
pub fn max_texture_format_string_size() -> usize {
|
||||
TEXTURE_FORMAT_LIST
|
||||
.into_iter()
|
||||
.map(|f| texture_format_name(f).len())
|
||||
.max()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn texture_format_name(format: wgpu::TextureFormat) -> String {
|
||||
match format {
|
||||
wgpu::TextureFormat::Astc { block, channel } => {
|
||||
format!("Astc{block:?}{channel:?}:")
|
||||
}
|
||||
_ => {
|
||||
format!("{format:?}:")
|
||||
}
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ pub mod math;
|
||||
// behavior to this macro (unspecified bit do not produce an error).
|
||||
macro_rules! impl_bitflags {
|
||||
($name:ident) => {
|
||||
#[cfg(feature = "trace")]
|
||||
#[cfg(feature = "serde")]
|
||||
impl serde::Serialize for $name {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -36,7 +36,7 @@ macro_rules! impl_bitflags {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de> serde::Deserialize<'de> for $name {
|
||||
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
|
||||
where
|
||||
@ -92,8 +92,7 @@ pub const QUERY_SIZE: u32 = 8;
|
||||
/// Backends supported by wgpu.
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum Backend {
|
||||
/// Dummy backend, used for testing.
|
||||
Empty = 0,
|
||||
@ -825,8 +824,7 @@ impl Features {
|
||||
/// [`downlevel_defaults()`]: Limits::downlevel_defaults
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase", default))]
|
||||
pub struct Limits {
|
||||
/// Maximum allowed value for the `size.width` of a texture created with `TextureDimension::D1`.
|
||||
@ -1116,6 +1114,7 @@ impl Limits {
|
||||
/// Represents the sets of additional limits on an adapter,
|
||||
/// which take place when running on downlevel backends.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct DownlevelLimits {}
|
||||
|
||||
#[allow(unknown_lints)] // derivable_impls is nightly only currently
|
||||
@ -1128,6 +1127,7 @@ impl Default for DownlevelLimits {
|
||||
|
||||
/// Lists various ways the underlying platform does not conform to the WebGPU standard.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct DownlevelCapabilities {
|
||||
/// Combined boolean flags.
|
||||
pub flags: DownlevelFlags,
|
||||
@ -1282,6 +1282,7 @@ impl DownlevelFlags {
|
||||
/// Collections of shader features a device supports if they support less than WebGPU normally allows.
|
||||
// TODO: Fill out the differences between shader models more completely
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum ShaderModel {
|
||||
/// Extremely limited shaders, including a total instruction limit.
|
||||
Sm2,
|
||||
@ -1294,8 +1295,7 @@ pub enum ShaderModel {
|
||||
/// Supported physical device types.
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum DeviceType {
|
||||
/// Other or Unknown.
|
||||
Other,
|
||||
@ -1313,8 +1313,7 @@ pub enum DeviceType {
|
||||
|
||||
/// Information about an adapter.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct AdapterInfo {
|
||||
/// Adapter name
|
||||
pub name: String,
|
||||
@ -1865,6 +1864,7 @@ impl_bitflags!(TextureFormatFeatureFlags);
|
||||
///
|
||||
/// Features are defined by WebGPU specification unless `Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` is enabled.
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct TextureFormatFeatures {
|
||||
/// Valid bits for `TextureDescriptor::Usage` provided for format creation.
|
||||
pub allowed_usages: TextureUsages,
|
||||
|
@ -1440,7 +1440,7 @@ impl Instance {
|
||||
target_os = "emscripten",
|
||||
feature = "webgl"
|
||||
))]
|
||||
pub fn enumerate_adapters(&self, backends: Backends) -> impl Iterator<Item = Adapter> {
|
||||
pub fn enumerate_adapters(&self, backends: Backends) -> impl ExactSizeIterator<Item = Adapter> {
|
||||
let context = Arc::clone(&self.context);
|
||||
self.context
|
||||
.as_any()
|
||||
|
Loading…
Reference in New Issue
Block a user