Expose Instance flags (#4230)

Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
This commit is contained in:
Nicolas Silva 2023-10-11 19:39:04 +02:00 committed by GitHub
parent 0f7b530ea8
commit f95d1c55e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 107 additions and 46 deletions

View File

@ -113,6 +113,7 @@ By @teoxoy in [#4185](https://github.com/gfx-rs/wgpu/pull/4185)
- Add trace-level logging for most entry points in wgpu-core By @nical in [4183](https://github.com/gfx-rs/wgpu/pull/4183)
- Add `Rgb10a2Uint` format. By @teoxoy in [4199](https://github.com/gfx-rs/wgpu/pull/4199)
- Validate that resources are used on the right device. By @nical in [4207](https://github.com/gfx-rs/wgpu/pull/4207)
- Expose instance flags. By @nical in [4230](https://github.com/gfx-rs/wgpu/pull/4230)
#### Vulkan

View File

@ -404,6 +404,7 @@ pub async fn op_webgpu_request_adapter(
wgpu_core::identity::IdentityManagerFactory,
wgpu_types::InstanceDescriptor {
backends,
flags: wgpu_types::InstanceFlags::from_build_config(),
dx12_shader_compiler: wgpu_types::Dx12Compiler::Fxc,
gles_minor_version: wgpu_types::Gles3MinorVersion::default(),
},

View File

@ -160,6 +160,7 @@ async fn setup<E: Example>(title: &str) -> Setup {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends,
flags: wgpu::InstanceFlags::from_build_config().with_env(),
dx12_shader_compiler,
gles_minor_version,
});

View File

@ -179,6 +179,7 @@ async fn run() {
let backends = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all);
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends,
flags: wgpu::InstanceFlags::from_build_config().with_env(),
dx12_shader_compiler: wgpu::Dx12Compiler::default(),
gles_minor_version: wgpu::Gles3MinorVersion::default(),
});

View File

@ -184,6 +184,7 @@ impl Corpus {
IdentityPassThroughFactory,
wgt::InstanceDescriptor {
backends: corpus.backends,
flags: wgt::InstanceFlags::debugging(),
dx12_shader_compiler: wgt::Dx12Compiler::Fxc,
gles_minor_version: wgt::Gles3MinorVersion::default(),
},

View File

@ -517,6 +517,7 @@ pub fn initialize_instance() -> Instance {
let gles_minor_version = wgpu::util::gles_minor_version_from_env().unwrap_or_default();
Instance::new(wgpu::InstanceDescriptor {
backends,
flags: wgpu::InstanceFlags::debugging().with_env(),
dx12_shader_compiler,
gles_minor_version,
})

View File

@ -5,6 +5,7 @@ use wasm_bindgen_test::*;
fn initialize() {
let _ = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all),
flags: wgpu::InstanceFlags::debugging().with_env(),
dx12_shader_compiler: wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(),
gles_minor_version: wgpu::util::gles_minor_version_from_env().unwrap_or_default(),
});
@ -13,6 +14,7 @@ fn initialize() {
fn request_adapter_inner(power: wgt::PowerPreference) {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all),
flags: wgpu::InstanceFlags::debugging().with_env(),
dx12_shader_compiler: wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(),
gles_minor_version: wgpu::util::gles_minor_version_from_env().unwrap_or_default(),
});

View File

@ -73,14 +73,9 @@ impl Instance {
pub fn new(name: &str, instance_desc: wgt::InstanceDescriptor) -> Self {
fn init<A: HalApi>(_: A, instance_desc: &wgt::InstanceDescriptor) -> Option<A::Instance> {
if instance_desc.backends.contains(A::VARIANT.into()) {
let mut flags = hal::InstanceFlags::empty();
if cfg!(debug_assertions) {
flags |= hal::InstanceFlags::VALIDATION;
flags |= hal::InstanceFlags::DEBUG;
}
let hal_desc = hal::InstanceDescriptor {
name: "wgpu",
flags,
flags: instance_desc.flags,
dx12_shader_compiler: instance_desc.dx12_shader_compiler.clone(),
gles_minor_version: instance_desc.gles_minor_version,
};

View File

@ -89,11 +89,7 @@ impl<A: hal::Api> Example<A> {
fn init(window: &winit::window::Window) -> Result<Self, Box<dyn std::error::Error>> {
let instance_desc = hal::InstanceDescriptor {
name: "example",
flags: if cfg!(debug_assertions) {
hal::InstanceFlags::all()
} else {
hal::InstanceFlags::empty()
},
flags: wgt::InstanceFlags::from_build_config().with_env(),
// Can't rely on having DXC available, so use FXC instead
dx12_shader_compiler: wgt::Dx12Compiler::Fxc,
gles_minor_version: wgt::Gles3MinorVersion::default(),

View File

@ -94,7 +94,7 @@ pub fn enumerate_adapters(factory: d3d12::DxgiFactory) -> Vec<d3d12::DxgiAdapter
/// created.
pub fn create_factory(
required_factory_type: DxgiFactoryType,
instance_flags: crate::InstanceFlags,
instance_flags: wgt::InstanceFlags,
) -> Result<(d3d12::DxgiLib, d3d12::DxgiFactory), crate::InstanceError> {
let lib_dxgi = d3d12::DxgiLib::new().map_err(|e| {
crate::InstanceError::with_source(String::from("failed to load dxgi.dll"), e)
@ -102,7 +102,7 @@ pub fn create_factory(
let mut factory_flags = d3d12::FactoryCreationFlags::empty();
if instance_flags.contains(crate::InstanceFlags::VALIDATION) {
if instance_flags.contains(wgt::InstanceFlags::VALIDATION) {
// The `DXGI_CREATE_FACTORY_DEBUG` flag is only allowed to be passed to
// `CreateDXGIFactory2` if the debug interface is actually available. So
// we check for whether it exists first.

View File

@ -15,7 +15,7 @@ impl Drop for super::Adapter {
&& self
.private_caps
.instance_flags
.contains(crate::InstanceFlags::VALIDATION)
.contains(wgt::InstanceFlags::VALIDATION)
{
unsafe {
self.report_live_objects();
@ -47,7 +47,7 @@ impl super::Adapter {
pub(super) fn expose(
adapter: d3d12::DxgiAdapter,
library: &Arc<d3d12::D3D12Lib>,
instance_flags: crate::InstanceFlags,
instance_flags: wgt::InstanceFlags,
dx12_shader_compiler: &wgt::Dx12Compiler,
) -> Option<crate::ExposedAdapter<super::Api>> {
// Create the device so that we can get the capabilities.

View File

@ -16,7 +16,7 @@ impl crate::Instance<super::Api> for super::Instance {
crate::InstanceError::with_source(String::from("failed to load d3d12.dll"), e)
})?;
if desc.flags.contains(crate::InstanceFlags::VALIDATION) {
if desc.flags.contains(wgt::InstanceFlags::VALIDATION) {
// Enable debug layer
match lib_main.get_debug_interface() {
Ok(pair) => match pair.into_result() {

View File

@ -94,7 +94,7 @@ pub struct Instance {
library: Arc<d3d12::D3D12Lib>,
supports_allow_tearing: bool,
_lib_dxgi: d3d12::DxgiLib,
flags: crate::InstanceFlags,
flags: wgt::InstanceFlags,
dx12_shader_compiler: wgt::Dx12Compiler,
}
@ -185,7 +185,7 @@ enum MemoryArchitecture {
#[derive(Debug, Clone, Copy)]
struct PrivateCapabilities {
instance_flags: crate::InstanceFlags,
instance_flags: wgt::InstanceFlags,
#[allow(unused)]
heterogeneous_resource_heaps: bool,
memory_architecture: MemoryArchitecture,

View File

@ -28,7 +28,7 @@ pub(super) fn compile_fxc(
if device
.private_caps
.instance_flags
.contains(crate::InstanceFlags::DEBUG)
.contains(wgt::InstanceFlags::DEBUG)
{
compile_flags |= d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION;
}
@ -148,7 +148,7 @@ mod dxc {
if device
.private_caps
.instance_flags
.contains(crate::InstanceFlags::DEBUG)
.contains(wgt::InstanceFlags::DEBUG)
{
compile_flags.push("-Zi"); // d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION
compile_flags.push("-Od"); // d3dcompiler::D3DCOMPILE_DEBUG

View File

@ -493,7 +493,7 @@ struct Inner {
impl Inner {
fn create(
flags: crate::InstanceFlags,
flags: wgt::InstanceFlags,
egl: Arc<EglInstance>,
display: khronos_egl::Display,
force_gles_minor_version: wgt::Gles3MinorVersion,
@ -567,7 +567,7 @@ impl Inner {
});
}
if flags.contains(crate::InstanceFlags::DEBUG) {
if flags.contains(wgt::InstanceFlags::DEBUG) {
if version >= (1, 5) {
log::info!("\tEGL context: +debug");
context_attributes.push(khronos_egl::CONTEXT_OPENGL_DEBUG);
@ -689,7 +689,7 @@ struct WindowSystemInterface {
pub struct Instance {
wsi: WindowSystemInterface,
flags: crate::InstanceFlags,
flags: wgt::InstanceFlags,
inner: Mutex<Inner>,
}
@ -817,7 +817,7 @@ impl crate::Instance<super::Api> for Instance {
EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE as khronos_egl::Attrib,
EGL_PLATFORM_X11_KHR as khronos_egl::Attrib,
EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED as khronos_egl::Attrib,
usize::from(desc.flags.contains(crate::InstanceFlags::VALIDATION)),
usize::from(desc.flags.contains(wgt::InstanceFlags::VALIDATION)),
khronos_egl::ATTRIB_NONE,
];
let display = unsafe {
@ -848,7 +848,7 @@ impl crate::Instance<super::Api> for Instance {
(display, None, WindowKind::Unknown)
};
if desc.flags.contains(crate::InstanceFlags::VALIDATION)
if desc.flags.contains(wgt::InstanceFlags::VALIDATION)
&& client_ext_str.contains("EGL_KHR_debug")
{
log::info!("Enabling EGL debug output");
@ -1005,13 +1005,13 @@ impl crate::Instance<super::Api> for Instance {
})
};
if self.flags.contains(crate::InstanceFlags::DEBUG) && gl.supports_debug() {
if self.flags.contains(wgt::InstanceFlags::DEBUG) && gl.supports_debug() {
log::info!("Max label length: {}", unsafe {
gl.get_parameter_i32(glow::MAX_LABEL_LENGTH)
});
}
if self.flags.contains(crate::InstanceFlags::VALIDATION) && gl.supports_debug() {
if self.flags.contains(wgt::InstanceFlags::VALIDATION) && gl.supports_debug() {
log::info!("Enabling GLES debug output");
unsafe { gl.enable(glow::DEBUG_OUTPUT) };
unsafe { gl.debug_message_callback(gl_debug_message_callback) };

View File

@ -608,17 +608,6 @@ pub trait CommandEncoder<A: Api>: WasmNotSend + WasmNotSync + fmt::Debug {
unsafe fn dispatch_indirect(&mut self, buffer: &A::Buffer, offset: wgt::BufferAddress);
}
bitflags!(
/// Instance initialization flags.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct InstanceFlags: u32 {
/// Generate debug information in shaders and objects.
const DEBUG = 1 << 0;
/// Enable validation, if possible.
const VALIDATION = 1 << 1;
}
);
bitflags!(
/// Pipeline layout creation flags.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -834,7 +823,7 @@ bitflags::bitflags! {
#[derive(Clone, Debug)]
pub struct InstanceDescriptor<'a> {
pub name: &'a str,
pub flags: InstanceFlags,
pub flags: wgt::InstanceFlags,
pub dx12_shader_compiler: wgt::Dx12Compiler,
pub gles_minor_version: wgt::Gles3MinorVersion,
}

View File

@ -1267,7 +1267,7 @@ impl super::Adapter {
let mut flags = spv::WriterFlags::empty();
flags.set(
spv::WriterFlags::DEBUG,
self.instance.flags.contains(crate::InstanceFlags::DEBUG),
self.instance.flags.contains(wgt::InstanceFlags::DEBUG),
);
flags.set(
spv::WriterFlags::LABEL_VARYINGS,

View File

@ -207,7 +207,7 @@ impl super::Instance {
pub fn desired_extensions(
entry: &ash::Entry,
_driver_api_version: u32,
flags: crate::InstanceFlags,
flags: wgt::InstanceFlags,
) -> Result<Vec<&'static CStr>, crate::InstanceError> {
let instance_extensions = entry
.enumerate_instance_extension_properties(None)
@ -251,7 +251,7 @@ impl super::Instance {
extensions.push(ash::vk::KhrPortabilityEnumerationFn::name());
}
if flags.contains(crate::InstanceFlags::DEBUG) {
if flags.contains(wgt::InstanceFlags::DEBUG) {
// VK_EXT_debug_utils
extensions.push(ext::DebugUtils::name());
}
@ -297,7 +297,7 @@ impl super::Instance {
android_sdk_version: u32,
debug_utils_user_data: Option<super::DebugUtilsMessengerUserData>,
extensions: Vec<&'static CStr>,
flags: crate::InstanceFlags,
flags: wgt::InstanceFlags,
has_nv_optimus: bool,
drop_guard: Option<crate::DropGuard>,
) -> Result<Self, crate::InstanceError> {
@ -639,7 +639,7 @@ impl crate::Instance<super::Api> for super::Instance {
// Request validation layer if asked.
let mut debug_callback_user_data = None;
if desc.flags.contains(crate::InstanceFlags::VALIDATION) {
if desc.flags.contains(wgt::InstanceFlags::VALIDATION) {
let validation_layer_name =
CStr::from_bytes_with_nul(b"VK_LAYER_KHRONOS_validation\0").unwrap();
if let Some(layer_properties) = find_layer(&instance_layers, validation_layer_name) {

View File

@ -106,7 +106,7 @@ pub struct InstanceShared {
raw: ash::Instance,
extensions: Vec<&'static CStr>,
drop_guard: Option<crate::DropGuard>,
flags: crate::InstanceFlags,
flags: wgt::InstanceFlags,
debug_utils: Option<DebugUtils>,
get_physical_device_properties: Option<khr::GetPhysicalDeviceProperties2>,
entry: ash::Entry,

View File

@ -818,6 +818,76 @@ impl Features {
}
}
bitflags::bitflags! {
/// Instance debugging flags.
///
/// These are not part of the webgpu standard.
///
/// Defaults to enabling debugging-related flags if the build configuration has `debug_assertions`.
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct InstanceFlags: u32 {
/// Generate debug information in shaders and objects.
const DEBUG = 1 << 0;
/// Enable validation, if possible.
const VALIDATION = 1 << 1;
}
}
impl Default for InstanceFlags {
fn default() -> Self {
Self::from_build_config()
}
}
impl InstanceFlags {
/// Enable debugging and validation flags.
pub fn debugging() -> Self {
InstanceFlags::DEBUG | InstanceFlags::VALIDATION
}
/// Infer good defaults from the build type
///
/// Returns the default flags and add debugging flags if the build configuration has `debug_assertions`.
pub fn from_build_config() -> Self {
if cfg!(debug_assertions) {
return InstanceFlags::debugging();
}
InstanceFlags::empty()
}
/// Returns this set of flags, affected by environment variables.
///
/// The presence of an environment variable implies that the corresponding flag should be set
/// unless the value is "0" in which case the flag is unset. If the environment variable is
/// not present, then the flag is unaffected.
///
/// For example `let flags = InstanceFlags::debugging().with_env();` with `WGPU_VALIDATION=0`
/// does not contain `InstanceFlags::VALIDATION`.
///
/// The environment variables are named after the flags prefixed with "WGPU_". For example:
/// - WGPU_DEBUG
/// - WGPU_VALIDATION
pub fn with_env(mut self) -> Self {
fn env(key: &str) -> Option<bool> {
std::env::var(key).ok().map(|s| match s.as_str() {
"0" => false,
_ => true,
})
}
if let Some(bit) = env("WGPU_VALIDATION") {
self.set(Self::VALIDATION, bit);
}
if let Some(bit) = env("WGPU_DEBUG") {
self.set(Self::DEBUG, bit);
}
self
}
}
/// Represents the sets of limits an adapter/device supports.
///
/// We provide three different defaults.
@ -6496,6 +6566,8 @@ pub enum Gles3MinorVersion {
pub struct InstanceDescriptor {
/// Which `Backends` to enable.
pub backends: Backends,
/// Flags to tune the behavior of the instance.
pub flags: InstanceFlags,
/// Which DX12 shader compiler to use.
pub dx12_shader_compiler: Dx12Compiler,
/// Which OpenGL ES 3 minor version to request.
@ -6506,6 +6578,7 @@ impl Default for InstanceDescriptor {
fn default() -> Self {
Self {
backends: Backends::all(),
flags: InstanceFlags::default(),
dx12_shader_compiler: Dx12Compiler::default(),
gles_minor_version: Gles3MinorVersion::default(),
}

View File

@ -34,7 +34,7 @@ pub use wgt::{
CommandBufferDescriptor, CompareFunction, CompositeAlphaMode, DepthBiasState,
DepthStencilState, DeviceType, DownlevelCapabilities, DownlevelFlags, Dx12Compiler,
DynamicOffset, Extent3d, Face, Features, FilterMode, FrontFace, Gles3MinorVersion,
ImageDataLayout, ImageSubresourceRange, IndexFormat, InstanceDescriptor, Limits,
ImageDataLayout, ImageSubresourceRange, IndexFormat, InstanceDescriptor, InstanceFlags, Limits,
MultisampleState, Origin2d, Origin3d, PipelineStatisticsTypes, PolygonMode, PowerPreference,
PredefinedColorSpace, PresentMode, PresentationTimestamp, PrimitiveState, PrimitiveTopology,
PushConstantRange, QueryType, RenderBundleDepthStencil, SamplerBindingType, SamplerBorderColor,