#![allow(
// We don't use syntax sugar where it's not necessary.
clippy::match_like_matches_macro,
)]
#![warn(missing_docs)]
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::{num::NonZeroU32, ops::Range};
pub type BufferAddress = u64;
pub type BufferSize = std::num::NonZeroU64;
pub type ShaderLocation = u32;
pub type DynamicOffset = u32;
pub const COPY_BYTES_PER_ROW_ALIGNMENT: u32 = 256;
pub const QUERY_RESOLVE_BUFFER_ALIGNMENT: BufferAddress = 256;
pub const COPY_BUFFER_ALIGNMENT: BufferAddress = 4;
pub const MAP_ALIGNMENT: BufferAddress = 8;
pub const VERTEX_STRIDE_ALIGNMENT: BufferAddress = 4;
pub const PUSH_CONSTANT_ALIGNMENT: u32 = 4;
pub const QUERY_SET_MAX_QUERIES: u32 = 8192;
pub const QUERY_SIZE: u32 = 8;
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum Backend {
Empty = 0,
Vulkan = 1,
Metal = 2,
Dx12 = 3,
Dx11 = 4,
Gl = 5,
BrowserWebGpu = 6,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum PowerPreference {
LowPower = 0,
HighPerformance = 1,
}
impl Default for PowerPreference {
fn default() -> Self {
Self::LowPower
}
}
bitflags::bitflags! {
#[repr(transparent)]
pub struct Backends: u32 {
const VULKAN = 1 << Backend::Vulkan as u32;
const GL = 1 << Backend::Gl as u32;
const METAL = 1 << Backend::Metal as u32;
const DX12 = 1 << Backend::Dx12 as u32;
const DX11 = 1 << Backend::Dx11 as u32;
const BROWSER_WEBGPU = 1 << Backend::BrowserWebGpu as u32;
const PRIMARY = Self::VULKAN.bits
| Self::METAL.bits
| Self::DX12.bits
| Self::BROWSER_WEBGPU.bits;
const SECONDARY = Self::GL.bits | Self::DX11.bits;
}
}
#[cfg(feature = "bitflags_serde_shim")]
bitflags_serde_shim::impl_serde_for_bitflags!(Backends);
impl From<Backend> for Backends {
fn from(backend: Backend) -> Self {
Self::from_bits(1 << backend as u32).unwrap()
}
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct RequestAdapterOptions<S> {
pub power_preference: PowerPreference,
pub force_fallback_adapter: bool,
pub compatible_surface: Option<S>,
}
impl<S> Default for RequestAdapterOptions<S> {
fn default() -> Self {
Self {
power_preference: PowerPreference::default(),
force_fallback_adapter: false,
compatible_surface: None,
}
}
}
bitflags::bitflags! {
#[repr(transparent)]
#[derive(Default)]
pub struct Features: u64 {
const DEPTH_CLIP_CONTROL = 1 << 0;
const TEXTURE_COMPRESSION_BC = 1 << 1;
const INDIRECT_FIRST_INSTANCE = 1 << 2;
const TIMESTAMP_QUERY = 1 << 3;
const PIPELINE_STATISTICS_QUERY = 1 << 4;
const MAPPABLE_PRIMARY_BUFFERS = 1 << 16;
const TEXTURE_BINDING_ARRAY = 1 << 17;
const BUFFER_BINDING_ARRAY = 1 << 18;
const STORAGE_RESOURCE_BINDING_ARRAY = 1 << 19;
const SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 1 << 20;
const UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 1 << 21;
const PARTIALLY_BOUND_BINDING_ARRAY = 1 << 22;
const UNSIZED_BINDING_ARRAY = 1 << 23;
const MULTI_DRAW_INDIRECT = 1 << 24;
const MULTI_DRAW_INDIRECT_COUNT = 1 << 25;
const PUSH_CONSTANTS = 1 << 26;
const ADDRESS_MODE_CLAMP_TO_BORDER = 1 << 27;
const POLYGON_MODE_LINE= 1 << 28;
const POLYGON_MODE_POINT = 1 << 29;
const TEXTURE_COMPRESSION_ETC2 = 1 << 30;
const TEXTURE_COMPRESSION_ASTC_LDR = 1 << 31;
const TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES = 1 << 32;
const SHADER_FLOAT64 = 1 << 33;
const VERTEX_ATTRIBUTE_64BIT = 1 << 34;
const CONSERVATIVE_RASTERIZATION = 1 << 35;
const VERTEX_WRITABLE_STORAGE = 1 << 36;
const CLEAR_COMMANDS = 1 << 37;
const SPIRV_SHADER_PASSTHROUGH = 1 << 38;
const SHADER_PRIMITIVE_INDEX = 1 << 39;
const MULTIVIEW = 1 << 40;
const TEXTURE_FORMAT_16BIT_NORM = 1 << 41;
}
}
#[cfg(feature = "bitflags_serde_shim")]
bitflags_serde_shim::impl_serde_for_bitflags!(Features);
impl Features {
pub const fn all_webgpu_mask() -> Self {
Self::from_bits_truncate(0x0000_0000_0000_FFFF)
}
pub const fn all_native_mask() -> Self {
Self::from_bits_truncate(0xFFFF_FFFF_FFFF_0000)
}
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Limits {
pub max_texture_dimension_1d: u32,
pub max_texture_dimension_2d: u32,
pub max_texture_dimension_3d: u32,
pub max_texture_array_layers: u32,
pub max_bind_groups: u32,
pub max_dynamic_uniform_buffers_per_pipeline_layout: u32,
pub max_dynamic_storage_buffers_per_pipeline_layout: u32,
pub max_sampled_textures_per_shader_stage: u32,
pub max_samplers_per_shader_stage: u32,
pub max_storage_buffers_per_shader_stage: u32,
pub max_storage_textures_per_shader_stage: u32,
pub max_uniform_buffers_per_shader_stage: u32,
pub max_uniform_buffer_binding_size: u32,
pub max_storage_buffer_binding_size: u32,
pub max_vertex_buffers: u32,
pub max_vertex_attributes: u32,
pub max_vertex_buffer_array_stride: u32,
pub max_push_constant_size: u32,
pub min_uniform_buffer_offset_alignment: u32,
pub min_storage_buffer_offset_alignment: u32,
pub max_inter_stage_shader_components: u32,
pub max_compute_workgroup_storage_size: u32,
pub max_compute_invocations_per_workgroup: u32,
pub max_compute_workgroup_size_x: u32,
pub max_compute_workgroup_size_y: u32,
pub max_compute_workgroup_size_z: u32,
pub max_compute_workgroups_per_dimension: u32,
}
impl Default for Limits {
fn default() -> Self {
Self {
max_texture_dimension_1d: 8192,
max_texture_dimension_2d: 8192,
max_texture_dimension_3d: 2048,
max_texture_array_layers: 256,
max_bind_groups: 4,
max_dynamic_uniform_buffers_per_pipeline_layout: 8,
max_dynamic_storage_buffers_per_pipeline_layout: 4,
max_sampled_textures_per_shader_stage: 16,
max_samplers_per_shader_stage: 16,
max_storage_buffers_per_shader_stage: 8,
max_storage_textures_per_shader_stage: 8,
max_uniform_buffers_per_shader_stage: 12,
max_uniform_buffer_binding_size: 64 << 10,
max_storage_buffer_binding_size: 128 << 20,
max_vertex_buffers: 8,
max_vertex_attributes: 16,
max_vertex_buffer_array_stride: 2048,
max_push_constant_size: 0,
min_uniform_buffer_offset_alignment: 256,
min_storage_buffer_offset_alignment: 256,
max_inter_stage_shader_components: 60,
max_compute_workgroup_storage_size: 16352,
max_compute_invocations_per_workgroup: 256,
max_compute_workgroup_size_x: 256,
max_compute_workgroup_size_y: 256,
max_compute_workgroup_size_z: 64,
max_compute_workgroups_per_dimension: 65535,
}
}
}
impl Limits {
pub fn downlevel_defaults() -> Self {
Self {
max_texture_dimension_1d: 2048,
max_texture_dimension_2d: 2048,
max_texture_dimension_3d: 256,
max_texture_array_layers: 256,
max_bind_groups: 4,
max_dynamic_uniform_buffers_per_pipeline_layout: 8,
max_dynamic_storage_buffers_per_pipeline_layout: 4,
max_sampled_textures_per_shader_stage: 16,
max_samplers_per_shader_stage: 16,
max_storage_buffers_per_shader_stage: 4,
max_storage_textures_per_shader_stage: 4,
max_uniform_buffers_per_shader_stage: 12,
max_uniform_buffer_binding_size: 16 << 10,
max_storage_buffer_binding_size: 128 << 20,
max_vertex_buffers: 8,
max_vertex_attributes: 16,
max_vertex_buffer_array_stride: 2048,
max_push_constant_size: 0,
min_uniform_buffer_offset_alignment: 256,
min_storage_buffer_offset_alignment: 256,
max_inter_stage_shader_components: 60,
max_compute_workgroup_storage_size: 16352,
max_compute_invocations_per_workgroup: 256,
max_compute_workgroup_size_x: 256,
max_compute_workgroup_size_y: 256,
max_compute_workgroup_size_z: 64,
max_compute_workgroups_per_dimension: 65535,
}
}
pub fn downlevel_webgl2_defaults() -> Self {
Self {
max_uniform_buffers_per_shader_stage: 11,
max_storage_buffers_per_shader_stage: 0,
max_storage_textures_per_shader_stage: 0,
max_dynamic_storage_buffers_per_pipeline_layout: 0,
max_storage_buffer_binding_size: 0,
max_vertex_buffer_array_stride: 255,
max_compute_workgroup_storage_size: 0,
max_compute_invocations_per_workgroup: 0,
max_compute_workgroup_size_x: 0,
max_compute_workgroup_size_y: 0,
max_compute_workgroup_size_z: 0,
max_compute_workgroups_per_dimension: 0,
..Self::downlevel_defaults()
}
}
pub fn using_resolution(self, other: Self) -> Self {
Self {
max_texture_dimension_1d: other.max_texture_dimension_1d,
max_texture_dimension_2d: other.max_texture_dimension_2d,
max_texture_dimension_3d: other.max_texture_dimension_3d,
..self
}
}
pub fn using_alignment(self, other: Self) -> Self {
Self {
min_uniform_buffer_offset_alignment: other.min_uniform_buffer_offset_alignment,
min_storage_buffer_offset_alignment: other.min_storage_buffer_offset_alignment,
..self
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DownlevelLimits {}
#[allow(unknown_lints)] #[allow(clippy::derivable_impls)]
impl Default for DownlevelLimits {
fn default() -> Self {
DownlevelLimits {}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DownlevelCapabilities {
pub flags: DownlevelFlags,
pub limits: DownlevelLimits,
pub shader_model: ShaderModel,
}
impl Default for DownlevelCapabilities {
fn default() -> Self {
Self {
flags: DownlevelFlags::compliant(),
limits: DownlevelLimits::default(),
shader_model: ShaderModel::Sm5,
}
}
}
impl DownlevelCapabilities {
pub fn is_webgpu_compliant(&self) -> bool {
self.flags.contains(DownlevelFlags::compliant())
&& self.limits == DownlevelLimits::default()
&& self.shader_model >= ShaderModel::Sm5
}
}
bitflags::bitflags! {
pub struct DownlevelFlags: u32 {
const COMPUTE_SHADERS = 1 << 0;
const FRAGMENT_WRITABLE_STORAGE = 1 << 1;
const INDIRECT_EXECUTION = 1 << 2;
const BASE_VERTEX = 1 << 3;
const READ_ONLY_DEPTH_STENCIL = 1 << 4;
const DEVICE_LOCAL_IMAGE_COPIES = 1 << 5;
const NON_POWER_OF_TWO_MIPMAPPED_TEXTURES = 1 << 6;
const CUBE_ARRAY_TEXTURES = 1 << 7;
const COMPARISON_SAMPLERS = 1 << 8;
const INDEPENDENT_BLENDING = 1 << 9;
const VERTEX_STORAGE = 1 << 10;
const ANISOTROPIC_FILTERING = 1 << 11;
const FRAGMENT_STORAGE = 1 << 12;
}
}
#[cfg(feature = "bitflags_serde_shim")]
bitflags_serde_shim::impl_serde_for_bitflags!(DownlevelFlags);
impl DownlevelFlags {
pub const fn compliant() -> Self {
Self::from_bits_truncate(Self::all().bits() & !Self::ANISOTROPIC_FILTERING.bits)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ShaderModel {
Sm2,
Sm4,
Sm5,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub enum DeviceType {
Other,
IntegratedGpu,
DiscreteGpu,
VirtualGpu,
Cpu,
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct AdapterInfo {
pub name: String,
pub vendor: usize,
pub device: usize,
pub device_type: DeviceType,
pub backend: Backend,
}
#[repr(C)]
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct DeviceDescriptor<L> {
pub label: L,
pub features: Features,
pub limits: Limits,
}
impl<L> DeviceDescriptor<L> {
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> DeviceDescriptor<K> {
DeviceDescriptor {
label: fun(&self.label),
features: self.features,
limits: self.limits.clone(),
}
}
}
bitflags::bitflags! {
#[repr(transparent)]
pub struct ShaderStages: u32 {
const NONE = 0;
const VERTEX = 1 << 0;
const FRAGMENT = 1 << 1;
const COMPUTE = 1 << 2;
const VERTEX_FRAGMENT = Self::VERTEX.bits | Self::FRAGMENT.bits;
}
}
#[cfg(feature = "bitflags_serde_shim")]
bitflags_serde_shim::impl_serde_for_bitflags!(ShaderStages);
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum TextureViewDimension {
#[cfg_attr(feature = "serde", serde(rename = "1d"))]
D1,
#[cfg_attr(feature = "serde", serde(rename = "2d"))]
D2,
#[cfg_attr(feature = "serde", serde(rename = "2d-array"))]
D2Array,
#[cfg_attr(feature = "serde", serde(rename = "cube"))]
Cube,
#[cfg_attr(feature = "serde", serde(rename = "cube-array"))]
CubeArray,
#[cfg_attr(feature = "serde", serde(rename = "3d"))]
D3,
}
impl Default for TextureViewDimension {
fn default() -> Self {
Self::D2
}
}
impl TextureViewDimension {
pub fn compatible_texture_dimension(self) -> TextureDimension {
match self {
Self::D1 => TextureDimension::D1,
Self::D2 | Self::D2Array | Self::Cube | Self::CubeArray => TextureDimension::D2,
Self::D3 => TextureDimension::D3,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum BlendFactor {
Zero = 0,
One = 1,
Src = 2,
OneMinusSrc = 3,
SrcAlpha = 4,
OneMinusSrcAlpha = 5,
Dst = 6,
OneMinusDst = 7,
DstAlpha = 8,
OneMinusDstAlpha = 9,
SrcAlphaSaturated = 10,
Constant = 11,
OneMinusConstant = 12,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum BlendOperation {
Add = 0,
Subtract = 1,
ReverseSubtract = 2,
Min = 3,
Max = 4,
}
impl Default for BlendOperation {
fn default() -> Self {
Self::Add
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct BlendComponent {
pub src_factor: BlendFactor,
pub dst_factor: BlendFactor,
pub operation: BlendOperation,
}
impl BlendComponent {
pub const REPLACE: Self = Self {
src_factor: BlendFactor::One,
dst_factor: BlendFactor::Zero,
operation: BlendOperation::Add,
};
pub const OVER: Self = Self {
src_factor: BlendFactor::One,
dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add,
};
pub fn uses_constant(&self) -> bool {
match (self.src_factor, self.dst_factor) {
(BlendFactor::Constant, _)
| (BlendFactor::OneMinusConstant, _)
| (_, BlendFactor::Constant)
| (_, BlendFactor::OneMinusConstant) => true,
(_, _) => false,
}
}
}
impl Default for BlendComponent {
fn default() -> Self {
Self::REPLACE
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct BlendState {
pub color: BlendComponent,
pub alpha: BlendComponent,
}
impl BlendState {
pub const REPLACE: Self = Self {
color: BlendComponent::REPLACE,
alpha: BlendComponent::REPLACE,
};
pub const ALPHA_BLENDING: Self = Self {
color: BlendComponent {
src_factor: BlendFactor::SrcAlpha,
dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add,
},
alpha: BlendComponent::OVER,
};
pub const PREMULTIPLIED_ALPHA_BLENDING: Self = Self {
color: BlendComponent::OVER,
alpha: BlendComponent::OVER,
};
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct ColorTargetState {
pub format: TextureFormat,
#[cfg_attr(feature = "serde", serde(default))]
pub blend: Option<BlendState>,
#[cfg_attr(feature = "serde", serde(default))]
pub write_mask: ColorWrites,
}
impl From<TextureFormat> for ColorTargetState {
fn from(format: TextureFormat) -> Self {
Self {
format,
blend: None,
write_mask: ColorWrites::ALL,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum PrimitiveTopology {
PointList = 0,
LineList = 1,
LineStrip = 2,
TriangleList = 3,
TriangleStrip = 4,
}
impl Default for PrimitiveTopology {
fn default() -> Self {
PrimitiveTopology::TriangleList
}
}
impl PrimitiveTopology {
pub fn is_strip(&self) -> bool {
match *self {
Self::PointList | Self::LineList | Self::TriangleList => false,
Self::LineStrip | Self::TriangleStrip => true,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum FrontFace {
Ccw = 0,
Cw = 1,
}
impl Default for FrontFace {
fn default() -> Self {
Self::Ccw
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum Face {
Front = 0,
Back = 1,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum PolygonMode {
Fill = 0,
Line = 1,
Point = 2,
}
impl Default for PolygonMode {
fn default() -> Self {
Self::Fill
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct PrimitiveState {
pub topology: PrimitiveTopology,
#[cfg_attr(feature = "serde", serde(default))]
pub strip_index_format: Option<IndexFormat>,
#[cfg_attr(feature = "serde", serde(default))]
pub front_face: FrontFace,
#[cfg_attr(feature = "serde", serde(default))]
pub cull_mode: Option<Face>,
#[cfg_attr(feature = "serde", serde(default))]
pub unclipped_depth: bool,
#[cfg_attr(feature = "serde", serde(default))]
pub polygon_mode: PolygonMode,
pub conservative: bool,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct MultisampleState {
pub count: u32,
pub mask: u64,
pub alpha_to_coverage_enabled: bool,
}
impl Default for MultisampleState {
fn default() -> Self {
MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
}
}
}
bitflags::bitflags! {
#[repr(transparent)]
pub struct TextureFormatFeatureFlags: u32 {
const STORAGE_READ_WRITE = 1 << 0;
const STORAGE_ATOMICS = 1 << 1;
}
}
#[cfg(feature = "bitflags_serde_shim")]
bitflags_serde_shim::impl_serde_for_bitflags!(TextureFormatFeatureFlags);
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct TextureFormatFeatures {
pub allowed_usages: TextureUsages,
pub flags: TextureFormatFeatureFlags,
pub filterable: bool,
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct TextureFormatInfo {
pub required_features: Features,
pub sample_type: TextureSampleType,
pub block_dimensions: (u8, u8),
pub block_size: u8,
pub components: u8,
pub srgb: bool,
pub guaranteed_format_features: TextureFormatFeatures,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum TextureFormat {
#[cfg_attr(feature = "serde", serde(rename = "r8unorm"))]
R8Unorm,
#[cfg_attr(feature = "serde", serde(rename = "r8snorm"))]
R8Snorm,
#[cfg_attr(feature = "serde", serde(rename = "r8uint"))]
R8Uint,
#[cfg_attr(feature = "serde", serde(rename = "r8sint"))]
R8Sint,
#[cfg_attr(feature = "serde", serde(rename = "r16uint"))]
R16Uint,
#[cfg_attr(feature = "serde", serde(rename = "r16sint"))]
R16Sint,
#[cfg_attr(feature = "serde", serde(rename = "r16unorm"))]
R16Unorm,
#[cfg_attr(feature = "serde", serde(rename = "r16snorm"))]
R16Snorm,
#[cfg_attr(feature = "serde", serde(rename = "r16float"))]
R16Float,
#[cfg_attr(feature = "serde", serde(rename = "rg8unorm"))]
Rg8Unorm,
#[cfg_attr(feature = "serde", serde(rename = "rg8snorm"))]
Rg8Snorm,
#[cfg_attr(feature = "serde", serde(rename = "rg8uint"))]
Rg8Uint,
#[cfg_attr(feature = "serde", serde(rename = "rg8sint"))]
Rg8Sint,
#[cfg_attr(feature = "serde", serde(rename = "r32uint"))]
R32Uint,
#[cfg_attr(feature = "serde", serde(rename = "r32sint"))]
R32Sint,
#[cfg_attr(feature = "serde", serde(rename = "r32float"))]
R32Float,
#[cfg_attr(feature = "serde", serde(rename = "rg16uint"))]
Rg16Uint,
#[cfg_attr(feature = "serde", serde(rename = "rg16sint"))]
Rg16Sint,
#[cfg_attr(feature = "serde", serde(rename = "rg16unorm"))]
Rg16Unorm,
#[cfg_attr(feature = "serde", serde(rename = "rg16snorm"))]
Rg16Snorm,
#[cfg_attr(feature = "serde", serde(rename = "rg16float"))]
Rg16Float,
#[cfg_attr(feature = "serde", serde(rename = "rgba8unorm"))]
Rgba8Unorm,
#[cfg_attr(feature = "serde", serde(rename = "rgba8unorm-srgb"))]
Rgba8UnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "rgba8snorm"))]
Rgba8Snorm,
#[cfg_attr(feature = "serde", serde(rename = "rgba8uint"))]
Rgba8Uint,
#[cfg_attr(feature = "serde", serde(rename = "rgba8sint"))]
Rgba8Sint,
#[cfg_attr(feature = "serde", serde(rename = "bgra8unorm"))]
Bgra8Unorm,
#[cfg_attr(feature = "serde", serde(rename = "bgra8unorm-srgb"))]
Bgra8UnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "rgb10a2unorm"))]
Rgb10a2Unorm,
#[cfg_attr(feature = "serde", serde(rename = "rg11b10ufloat"))]
Rg11b10Float,
#[cfg_attr(feature = "serde", serde(rename = "rg32uint"))]
Rg32Uint,
#[cfg_attr(feature = "serde", serde(rename = "rg32sint"))]
Rg32Sint,
#[cfg_attr(feature = "serde", serde(rename = "rg32float"))]
Rg32Float,
#[cfg_attr(feature = "serde", serde(rename = "rgba16uint"))]
Rgba16Uint,
#[cfg_attr(feature = "serde", serde(rename = "rgba16sint"))]
Rgba16Sint,
#[cfg_attr(feature = "serde", serde(rename = "rgba16unorm"))]
Rgba16Unorm,
#[cfg_attr(feature = "serde", serde(rename = "rgba16snorm"))]
Rgba16Snorm,
#[cfg_attr(feature = "serde", serde(rename = "rgba16float"))]
Rgba16Float,
#[cfg_attr(feature = "serde", serde(rename = "rgba32uint"))]
Rgba32Uint,
#[cfg_attr(feature = "serde", serde(rename = "rgba32sint"))]
Rgba32Sint,
#[cfg_attr(feature = "serde", serde(rename = "rgba32float"))]
Rgba32Float,
#[cfg_attr(feature = "serde", serde(rename = "depth32float"))]
Depth32Float,
#[cfg_attr(feature = "serde", serde(rename = "depth24plus"))]
Depth24Plus,
#[cfg_attr(feature = "serde", serde(rename = "depth24plus-stencil8"))]
Depth24PlusStencil8,
#[cfg_attr(feature = "serde", serde(rename = "rgb9e5ufloat"))]
Rgb9e5Ufloat,
#[cfg_attr(feature = "serde", serde(rename = "bc1-rgba-unorm"))]
Bc1RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "bc1-rgba-unorm-srgb"))]
Bc1RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "bc2-rgba-unorm"))]
Bc2RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "bc2-rgba-unorm-srgb"))]
Bc2RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "bc3-rgba-unorm"))]
Bc3RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "bc3-rgba-unorm-srgb"))]
Bc3RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "bc4-r-unorm"))]
Bc4RUnorm,
#[cfg_attr(feature = "serde", serde(rename = "bc4-r-snorm"))]
Bc4RSnorm,
#[cfg_attr(feature = "serde", serde(rename = "bc5-rg-unorm"))]
Bc5RgUnorm,
#[cfg_attr(feature = "serde", serde(rename = "bc5-rg-snorm"))]
Bc5RgSnorm,
#[cfg_attr(feature = "serde", serde(rename = "bc6h-rgb-ufloat"))]
Bc6hRgbUfloat,
#[cfg_attr(feature = "serde", serde(rename = "bc6h-rgb-float"))]
Bc6hRgbSfloat,
#[cfg_attr(feature = "serde", serde(rename = "bc7-rgba-unorm"))]
Bc7RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "bc7-rgba-unorm-srgb"))]
Bc7RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "etc2-rgb8unorm"))]
Etc2Rgb8Unorm,
#[cfg_attr(feature = "serde", serde(rename = "etc2-rgb8unorm-srgb"))]
Etc2Rgb8UnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "etc2-rgb8a1unorm"))]
Etc2Rgb8A1Unorm,
#[cfg_attr(feature = "serde", serde(rename = "etc2-rgb8a1unorm-srgb"))]
Etc2Rgb8A1UnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "etc2-rgba8unorm"))]
Etc2Rgba8Unorm,
#[cfg_attr(feature = "serde", serde(rename = "etc2-rgba8unorm-srgb"))]
Etc2Rgba8UnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "eac-r11unorm"))]
EacR11Unorm,
#[cfg_attr(feature = "serde", serde(rename = "eac-r11snorm"))]
EacR11Snorm,
#[cfg_attr(feature = "serde", serde(rename = "eac-rg11unorm"))]
EacRg11Unorm,
#[cfg_attr(feature = "serde", serde(rename = "eac-rg11snorm"))]
EacRg11Snorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-4x4-unorm"))]
Astc4x4RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-4x4-unorm-srgb"))]
Astc4x4RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-5x4-unorm"))]
Astc5x4RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-5x4-unorm-srgb"))]
Astc5x4RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-5x5-unorm"))]
Astc5x5RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-5x5-unorm-srgb"))]
Astc5x5RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-6x5-unorm"))]
Astc6x5RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-6x5-unorm-srgb"))]
Astc6x5RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-6x6-unorm"))]
Astc6x6RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-6x6-unorm-srgb"))]
Astc6x6RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-8x5-unorm"))]
Astc8x5RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-8x5-unorm-srgb"))]
Astc8x5RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-8x6-unorm"))]
Astc8x6RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-8x6-unorm-srgb"))]
Astc8x6RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-10x5-unorm"))]
Astc10x5RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-10x5-unorm-srgb"))]
Astc10x5RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-10x6-unorm"))]
Astc10x6RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-10x6-unorm-srgb"))]
Astc10x6RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-8x8-unorm"))]
Astc8x8RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-8x8-unorm-srgb"))]
Astc8x8RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-10x8-unorm"))]
Astc10x8RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-10x8-unorm-srgb"))]
Astc10x8RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-10x10-unorm"))]
Astc10x10RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-10x10-unorm-srgb"))]
Astc10x10RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-12x10-unorm"))]
Astc12x10RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-12x10-unorm-srgb"))]
Astc12x10RgbaUnormSrgb,
#[cfg_attr(feature = "serde", serde(rename = "astc-12x12-unorm"))]
Astc12x12RgbaUnorm,
#[cfg_attr(feature = "serde", serde(rename = "astc-12x12-unorm-srgb"))]
Astc12x12RgbaUnormSrgb,
}
impl TextureFormat {
pub fn describe(&self) -> TextureFormatInfo {
let native = Features::empty();
let bc = Features::TEXTURE_COMPRESSION_BC;
let etc2 = Features::TEXTURE_COMPRESSION_ETC2;
let astc_ldr = Features::TEXTURE_COMPRESSION_ASTC_LDR;
let norm16bit = Features::TEXTURE_FORMAT_16BIT_NORM;
let uint = TextureSampleType::Uint;
let sint = TextureSampleType::Sint;
let nearest = TextureSampleType::Float { filterable: false };
let float = TextureSampleType::Float { filterable: true };
let depth = TextureSampleType::Depth;
let linear = false;
let srgb = true;
let basic =
TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING;
let attachment = basic | TextureUsages::RENDER_ATTACHMENT;
let storage = basic | TextureUsages::STORAGE_BINDING;
let all_flags = TextureUsages::all();
let (
required_features,
sample_type,
srgb,
block_dimensions,
block_size,
allowed_usages,
components,
) = match self {
Self::R8Unorm => (native, float, linear, (1, 1), 1, attachment, 1),
Self::R8Snorm => (native, float, linear, (1, 1), 1, basic, 1),
Self::R8Uint => (native, uint, linear, (1, 1), 1, attachment, 1),
Self::R8Sint => (native, sint, linear, (1, 1), 1, attachment, 1),
Self::R16Uint => (native, uint, linear, (1, 1), 2, attachment, 1),
Self::R16Sint => (native, sint, linear, (1, 1), 2, attachment, 1),
Self::R16Float => (native, float, linear, (1, 1), 2, attachment, 1),
Self::Rg8Unorm => (native, float, linear, (1, 1), 2, attachment, 2),
Self::Rg8Snorm => (native, float, linear, (1, 1), 2, attachment, 2),
Self::Rg8Uint => (native, uint, linear, (1, 1), 2, attachment, 2),
Self::Rg8Sint => (native, sint, linear, (1, 1), 2, basic, 2),
Self::R32Uint => (native, uint, linear, (1, 1), 4, all_flags, 1),
Self::R32Sint => (native, sint, linear, (1, 1), 4, all_flags, 1),
Self::R32Float => (native, nearest, linear, (1, 1), 4, all_flags, 1),
Self::Rg16Uint => (native, uint, linear, (1, 1), 4, attachment, 2),
Self::Rg16Sint => (native, sint, linear, (1, 1), 4, attachment, 2),
Self::Rg16Float => (native, float, linear, (1, 1), 4, attachment, 2),
Self::Rgba8Unorm => (native, float, linear, (1, 1), 4, all_flags, 4),
Self::Rgba8UnormSrgb => (native, float, srgb, (1, 1), 4, attachment, 4),
Self::Rgba8Snorm => (native, float, linear, (1, 1), 4, storage, 4),
Self::Rgba8Uint => (native, uint, linear, (1, 1), 4, all_flags, 4),
Self::Rgba8Sint => (native, sint, linear, (1, 1), 4, all_flags, 4),
Self::Bgra8Unorm => (native, float, linear, (1, 1), 4, attachment, 4),
Self::Bgra8UnormSrgb => (native, float, srgb, (1, 1), 4, attachment, 4),
Self::Rgb10a2Unorm => (native, float, linear, (1, 1), 4, attachment, 4),
Self::Rg11b10Float => (native, float, linear, (1, 1), 4, basic, 3),
Self::Rg32Uint => (native, uint, linear, (1, 1), 8, all_flags, 2),
Self::Rg32Sint => (native, sint, linear, (1, 1), 8, all_flags, 2),
Self::Rg32Float => (native, nearest, linear, (1, 1), 8, all_flags, 2),
Self::Rgba16Uint => (native, uint, linear, (1, 1), 8, all_flags, 4),
Self::Rgba16Sint => (native, sint, linear, (1, 1), 8, all_flags, 4),
Self::Rgba16Float => (native, float, linear, (1, 1), 8, all_flags, 4),
Self::Rgba32Uint => (native, uint, linear, (1, 1), 16, all_flags, 4),
Self::Rgba32Sint => (native, sint, linear, (1, 1), 16, all_flags, 4),
Self::Rgba32Float => (native, nearest, linear, (1, 1), 16, all_flags, 4),
Self::Depth32Float => (native, depth, linear, (1, 1), 4, attachment, 1),
Self::Depth24Plus => (native, depth, linear, (1, 1), 4, attachment, 1),
Self::Depth24PlusStencil8 => (native, depth, linear, (1, 1), 4, attachment, 2),
Self::Rgb9e5Ufloat => (native, float, linear, (1, 1), 4, basic, 3),
Self::Bc1RgbaUnorm => (bc, float, linear, (4, 4), 8, basic, 4),
Self::Bc1RgbaUnormSrgb => (bc, float, srgb, (4, 4), 8, basic, 4),
Self::Bc2RgbaUnorm => (bc, float, linear, (4, 4), 16, basic, 4),
Self::Bc2RgbaUnormSrgb => (bc, float, srgb, (4, 4), 16, basic, 4),
Self::Bc3RgbaUnorm => (bc, float, linear, (4, 4), 16, basic, 4),
Self::Bc3RgbaUnormSrgb => (bc, float, srgb, (4, 4), 16, basic, 4),
Self::Bc4RUnorm => (bc, float, linear, (4, 4), 8, basic, 1),
Self::Bc4RSnorm => (bc, float, linear, (4, 4), 8, basic, 1),
Self::Bc5RgUnorm => (bc, float, linear, (4, 4), 16, basic, 2),
Self::Bc5RgSnorm => (bc, float, linear, (4, 4), 16, basic, 2),
Self::Bc6hRgbUfloat => (bc, float, linear, (4, 4), 16, basic, 3),
Self::Bc6hRgbSfloat => (bc, float, linear, (4, 4), 16, basic, 3),
Self::Bc7RgbaUnorm => (bc, float, linear, (4, 4), 16, basic, 4),
Self::Bc7RgbaUnormSrgb => (bc, float, srgb, (4, 4), 16, basic, 4),
Self::Etc2Rgb8Unorm => (etc2, float, linear, (4, 4), 8, basic, 3),
Self::Etc2Rgb8UnormSrgb => (etc2, float, srgb, (4, 4), 8, basic, 3),
Self::Etc2Rgb8A1Unorm => (etc2, float, linear, (4, 4), 8, basic, 4),
Self::Etc2Rgb8A1UnormSrgb => (etc2, float, srgb, (4, 4), 8, basic, 4),
Self::Etc2Rgba8Unorm => (etc2, float, linear, (4, 4), 16, basic, 4),
Self::Etc2Rgba8UnormSrgb => (etc2, float, srgb, (4, 4), 16, basic, 4),
Self::EacR11Unorm => (etc2, float, linear, (4, 4), 8, basic, 1),
Self::EacR11Snorm => (etc2, float, linear, (4, 4), 8, basic, 1),
Self::EacRg11Unorm => (etc2, float, linear, (4, 4), 16, basic, 2),
Self::EacRg11Snorm => (etc2, float, linear, (4, 4), 16, basic, 2),
Self::Astc4x4RgbaUnorm => (astc_ldr, float, linear, (4, 4), 16, basic, 4),
Self::Astc4x4RgbaUnormSrgb => (astc_ldr, float, srgb, (4, 4), 16, basic, 4),
Self::Astc5x4RgbaUnorm => (astc_ldr, float, linear, (5, 4), 16, basic, 4),
Self::Astc5x4RgbaUnormSrgb => (astc_ldr, float, srgb, (5, 4), 16, basic, 4),
Self::Astc5x5RgbaUnorm => (astc_ldr, float, linear, (5, 5), 16, basic, 4),
Self::Astc5x5RgbaUnormSrgb => (astc_ldr, float, srgb, (5, 5), 16, basic, 4),
Self::Astc6x5RgbaUnorm => (astc_ldr, float, linear, (6, 5), 16, basic, 4),
Self::Astc6x5RgbaUnormSrgb => (astc_ldr, float, srgb, (6, 5), 16, basic, 4),
Self::Astc6x6RgbaUnorm => (astc_ldr, float, linear, (6, 6), 16, basic, 4),
Self::Astc6x6RgbaUnormSrgb => (astc_ldr, float, srgb, (6, 6), 16, basic, 4),
Self::Astc8x5RgbaUnorm => (astc_ldr, float, linear, (8, 5), 16, basic, 4),
Self::Astc8x5RgbaUnormSrgb => (astc_ldr, float, srgb, (8, 5), 16, basic, 4),
Self::Astc8x6RgbaUnorm => (astc_ldr, float, linear, (8, 6), 16, basic, 4),
Self::Astc8x6RgbaUnormSrgb => (astc_ldr, float, srgb, (8, 6), 16, basic, 4),
Self::Astc10x5RgbaUnorm => (astc_ldr, float, linear, (10, 5), 16, basic, 4),
Self::Astc10x5RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 5), 16, basic, 4),
Self::Astc10x6RgbaUnorm => (astc_ldr, float, linear, (10, 6), 16, basic, 4),
Self::Astc10x6RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 6), 16, basic, 4),
Self::Astc8x8RgbaUnorm => (astc_ldr, float, linear, (8, 8), 16, basic, 4),
Self::Astc8x8RgbaUnormSrgb => (astc_ldr, float, srgb, (8, 8), 16, basic, 4),
Self::Astc10x8RgbaUnorm => (astc_ldr, float, linear, (10, 8), 16, basic, 4),
Self::Astc10x8RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 8), 16, basic, 4),
Self::Astc10x10RgbaUnorm => (astc_ldr, float, linear, (10, 10), 16, basic, 4),
Self::Astc10x10RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 10), 16, basic, 4),
Self::Astc12x10RgbaUnorm => (astc_ldr, float, linear, (12, 10), 16, basic, 4),
Self::Astc12x10RgbaUnormSrgb => (astc_ldr, float, srgb, (12, 10), 16, basic, 4),
Self::Astc12x12RgbaUnorm => (astc_ldr, float, linear, (12, 12), 16, basic, 4),
Self::Astc12x12RgbaUnormSrgb => (astc_ldr, float, srgb, (12, 12), 16, basic, 4),
Self::R16Unorm => (norm16bit, float, linear, (1, 1), 2, storage, 1),
Self::R16Snorm => (norm16bit, float, linear, (1, 1), 2, storage, 1),
Self::Rg16Unorm => (norm16bit, float, linear, (1, 1), 4, storage, 2),
Self::Rg16Snorm => (norm16bit, float, linear, (1, 1), 4, storage, 2),
Self::Rgba16Unorm => (norm16bit, float, linear, (1, 1), 8, storage, 4),
Self::Rgba16Snorm => (norm16bit, float, linear, (1, 1), 8, storage, 4),
};
TextureFormatInfo {
required_features,
sample_type,
block_dimensions,
block_size,
components,
srgb,
guaranteed_format_features: TextureFormatFeatures {
allowed_usages,
flags: TextureFormatFeatureFlags::empty(),
filterable: sample_type == TextureSampleType::Float { filterable: true },
},
}
}
}
bitflags::bitflags! {
#[repr(transparent)]
pub struct ColorWrites: u32 {
const RED = 1 << 0;
const GREEN = 1 << 1;
const BLUE = 1 << 2;
const ALPHA = 1 << 3;
const COLOR = Self::RED.bits | Self::GREEN.bits | Self::BLUE.bits;
const ALL = Self::RED.bits | Self::GREEN.bits | Self::BLUE.bits | Self::ALPHA.bits;
}
}
#[cfg(feature = "bitflags_serde_shim")]
bitflags_serde_shim::impl_serde_for_bitflags!(ColorWrites);
impl Default for ColorWrites {
fn default() -> Self {
Self::ALL
}
}
#[repr(C)]
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct StencilState {
pub front: StencilFaceState,
pub back: StencilFaceState,
pub read_mask: u32,
pub write_mask: u32,
}
impl StencilState {
pub fn is_enabled(&self) -> bool {
(self.front != StencilFaceState::IGNORE || self.back != StencilFaceState::IGNORE)
&& (self.read_mask != 0 || self.write_mask != 0)
}
pub fn is_read_only(&self) -> bool {
self.write_mask == 0
}
pub fn needs_ref_value(&self) -> bool {
self.front.needs_ref_value() || self.back.needs_ref_value()
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct DepthBiasState {
pub constant: i32,
pub slope_scale: f32,
pub clamp: f32,
}
impl DepthBiasState {
pub fn is_enabled(&self) -> bool {
self.constant != 0 || self.slope_scale != 0.0
}
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct DepthStencilState {
pub format: TextureFormat,
pub depth_write_enabled: bool,
pub depth_compare: CompareFunction,
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
pub stencil: StencilState,
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
pub bias: DepthBiasState,
}
impl DepthStencilState {
pub fn is_depth_enabled(&self) -> bool {
self.depth_compare != CompareFunction::Always || self.depth_write_enabled
}
pub fn is_read_only(&self) -> bool {
!self.depth_write_enabled && self.stencil.is_read_only()
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum IndexFormat {
Uint16 = 0,
Uint32 = 1,
}
impl Default for IndexFormat {
fn default() -> Self {
Self::Uint32
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum StencilOperation {
Keep = 0,
Zero = 1,
Replace = 2,
Invert = 3,
IncrementClamp = 4,
DecrementClamp = 5,
IncrementWrap = 6,
DecrementWrap = 7,
}
impl Default for StencilOperation {
fn default() -> Self {
Self::Keep
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct StencilFaceState {
pub compare: CompareFunction,
pub fail_op: StencilOperation,
pub depth_fail_op: StencilOperation,
pub pass_op: StencilOperation,
}
impl StencilFaceState {
pub const IGNORE: Self = StencilFaceState {
compare: CompareFunction::Always,
fail_op: StencilOperation::Keep,
depth_fail_op: StencilOperation::Keep,
pass_op: StencilOperation::Keep,
};
pub fn needs_ref_value(&self) -> bool {
self.compare.needs_ref_value()
|| self.fail_op == StencilOperation::Replace
|| self.depth_fail_op == StencilOperation::Replace
|| self.pass_op == StencilOperation::Replace
}
}
impl Default for StencilFaceState {
fn default() -> Self {
Self::IGNORE
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum CompareFunction {
Never = 1,
Less = 2,
Equal = 3,
LessEqual = 4,
Greater = 5,
NotEqual = 6,
GreaterEqual = 7,
Always = 8,
}
impl CompareFunction {
pub fn needs_ref_value(self) -> bool {
match self {
Self::Never | Self::Always => false,
_ => true,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum VertexStepMode {
Vertex = 0,
Instance = 1,
}
impl Default for VertexStepMode {
fn default() -> Self {
VertexStepMode::Vertex
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct VertexAttribute {
pub format: VertexFormat,
pub offset: BufferAddress,
pub shader_location: ShaderLocation,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum VertexFormat {
Uint8x2 = 0,
Uint8x4 = 1,
Sint8x2 = 2,
Sint8x4 = 3,
Unorm8x2 = 4,
Unorm8x4 = 5,
Snorm8x2 = 6,
Snorm8x4 = 7,
Uint16x2 = 8,
Uint16x4 = 9,
Sint16x2 = 10,
Sint16x4 = 11,
Unorm16x2 = 12,
Unorm16x4 = 13,
Snorm16x2 = 14,
Snorm16x4 = 15,
Float16x2 = 16,
Float16x4 = 17,
Float32 = 18,
Float32x2 = 19,
Float32x3 = 20,
Float32x4 = 21,
Uint32 = 22,
Uint32x2 = 23,
Uint32x3 = 24,
Uint32x4 = 25,
Sint32 = 26,
Sint32x2 = 27,
Sint32x3 = 28,
Sint32x4 = 29,
Float64 = 30,
Float64x2 = 31,
Float64x3 = 32,
Float64x4 = 33,
}
impl VertexFormat {
pub const fn size(&self) -> u64 {
match self {
Self::Uint8x2 | Self::Sint8x2 | Self::Unorm8x2 | Self::Snorm8x2 => 2,
Self::Uint8x4
| Self::Sint8x4
| Self::Unorm8x4
| Self::Snorm8x4
| Self::Uint16x2
| Self::Sint16x2
| Self::Unorm16x2
| Self::Snorm16x2
| Self::Float16x2
| Self::Float32
| Self::Uint32
| Self::Sint32 => 4,
Self::Uint16x4
| Self::Sint16x4
| Self::Unorm16x4
| Self::Snorm16x4
| Self::Float16x4
| Self::Float32x2
| Self::Uint32x2
| Self::Sint32x2
| Self::Float64 => 8,
Self::Float32x3 | Self::Uint32x3 | Self::Sint32x3 => 12,
Self::Float32x4 | Self::Uint32x4 | Self::Sint32x4 | Self::Float64x2 => 16,
Self::Float64x3 => 24,
Self::Float64x4 => 32,
}
}
}
bitflags::bitflags! {
#[repr(transparent)]
pub struct BufferUsages: u32 {
const MAP_READ = 1 << 0;
const MAP_WRITE = 1 << 1;
const COPY_SRC = 1 << 2;
const COPY_DST = 1 << 3;
const INDEX = 1 << 4;
const VERTEX = 1 << 5;
const UNIFORM = 1 << 6;
const STORAGE = 1 << 7;
const INDIRECT = 1 << 8;
}
}
#[cfg(feature = "bitflags_serde_shim")]
bitflags_serde_shim::impl_serde_for_bitflags!(BufferUsages);
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct BufferDescriptor<L> {
pub label: L,
pub size: BufferAddress,
pub usage: BufferUsages,
pub mapped_at_creation: bool,
}
impl<L> BufferDescriptor<L> {
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> BufferDescriptor<K> {
BufferDescriptor {
label: fun(&self.label),
size: self.size,
usage: self.usage,
mapped_at_creation: self.mapped_at_creation,
}
}
}
#[repr(C)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct CommandEncoderDescriptor<L> {
pub label: L,
}
impl<L> CommandEncoderDescriptor<L> {
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandEncoderDescriptor<K> {
CommandEncoderDescriptor {
label: fun(&self.label),
}
}
}
impl<T> Default for CommandEncoderDescriptor<Option<T>> {
fn default() -> Self {
Self { label: None }
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum PresentMode {
Immediate = 0,
Mailbox = 1,
Fifo = 2,
}
bitflags::bitflags! {
#[repr(transparent)]
pub struct TextureUsages: u32 {
const COPY_SRC = 1 << 0;
const COPY_DST = 1 << 1;
const TEXTURE_BINDING = 1 << 2;
const STORAGE_BINDING = 1 << 3;
const RENDER_ATTACHMENT = 1 << 4;
}
}
#[cfg(feature = "bitflags_serde_shim")]
bitflags_serde_shim::impl_serde_for_bitflags!(TextureUsages);
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct SurfaceConfiguration {
pub usage: TextureUsages,
pub format: TextureFormat,
pub width: u32,
pub height: u32,
pub present_mode: PresentMode,
}
#[repr(C)]
#[derive(Debug)]
pub enum SurfaceStatus {
Good,
Suboptimal,
Timeout,
Outdated,
Lost,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Color {
pub r: f64,
pub g: f64,
pub b: f64,
pub a: f64,
}
#[allow(missing_docs)]
impl Color {
pub const TRANSPARENT: Self = Self {
r: 0.0,
g: 0.0,
b: 0.0,
a: 0.0,
};
pub const BLACK: Self = Self {
r: 0.0,
g: 0.0,
b: 0.0,
a: 1.0,
};
pub const WHITE: Self = Self {
r: 1.0,
g: 1.0,
b: 1.0,
a: 1.0,
};
pub const RED: Self = Self {
r: 1.0,
g: 0.0,
b: 0.0,
a: 1.0,
};
pub const GREEN: Self = Self {
r: 0.0,
g: 1.0,
b: 0.0,
a: 1.0,
};
pub const BLUE: Self = Self {
r: 0.0,
g: 0.0,
b: 1.0,
a: 1.0,
};
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum TextureDimension {
#[cfg_attr(feature = "serde", serde(rename = "1d"))]
D1,
#[cfg_attr(feature = "serde", serde(rename = "2d"))]
D2,
#[cfg_attr(feature = "serde", serde(rename = "3d"))]
D3,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Origin3d {
pub x: u32,
pub y: u32,
pub z: u32,
}
impl Origin3d {
pub const ZERO: Self = Self { x: 0, y: 0, z: 0 };
}
impl Default for Origin3d {
fn default() -> Self {
Self::ZERO
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Extent3d {
pub width: u32,
pub height: u32,
#[cfg_attr(feature = "serde", serde(default = "default_depth"))]
pub depth_or_array_layers: u32,
}
#[cfg(feature = "serde")]
fn default_depth() -> u32 {
1
}
impl Default for Extent3d {
fn default() -> Self {
Self {
width: 1,
height: 1,
depth_or_array_layers: 1,
}
}
}
impl Extent3d {
pub fn physical_size(&self, format: TextureFormat) -> Self {
let (block_width, block_height) = format.describe().block_dimensions;
let block_width = block_width as u32;
let block_height = block_height as u32;
let width = ((self.width + block_width - 1) / block_width) * block_width;
let height = ((self.height + block_height - 1) / block_height) * block_height;
Self {
width,
height,
depth_or_array_layers: self.depth_or_array_layers,
}
}
pub fn max_mips(&self) -> u32 {
let max_dim = self.width.max(self.height.max(self.depth_or_array_layers));
32 - max_dim.leading_zeros()
}
pub fn mip_level_size(&self, level: u32, is_3d_texture: bool) -> Extent3d {
Extent3d {
width: u32::max(1, self.width >> level),
height: u32::max(1, self.height >> level),
depth_or_array_layers: match is_3d_texture {
false => self.depth_or_array_layers,
true => u32::max(1, self.depth_or_array_layers >> level),
},
}
}
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct TextureDescriptor<L> {
pub label: L,
pub size: Extent3d,
pub mip_level_count: u32,
pub sample_count: u32,
pub dimension: TextureDimension,
pub format: TextureFormat,
pub usage: TextureUsages,
}
impl<L> TextureDescriptor<L> {
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> TextureDescriptor<K> {
TextureDescriptor {
label: fun(&self.label),
size: self.size,
mip_level_count: self.mip_level_count,
sample_count: self.sample_count,
dimension: self.dimension,
format: self.format,
usage: self.usage,
}
}
pub fn mip_level_size(&self, level: u32) -> Option<Extent3d> {
if level >= self.mip_level_count {
return None;
}
Some(
self.size
.mip_level_size(level, self.dimension == TextureDimension::D3),
)
}
pub fn array_layer_count(&self) -> u32 {
match self.dimension {
TextureDimension::D1 | TextureDimension::D2 => self.size.depth_or_array_layers,
TextureDimension::D3 => 1,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum TextureAspect {
All,
StencilOnly,
DepthOnly,
}
impl Default for TextureAspect {
fn default() -> Self {
Self::All
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum AddressMode {
ClampToEdge = 0,
Repeat = 1,
MirrorRepeat = 2,
ClampToBorder = 3,
}
impl Default for AddressMode {
fn default() -> Self {
Self::ClampToEdge
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum FilterMode {
Nearest = 0,
Linear = 1,
}
impl Default for FilterMode {
fn default() -> Self {
Self::Nearest
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct PushConstantRange {
pub stages: ShaderStages,
pub range: Range<u32>,
}
#[repr(C)]
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct CommandBufferDescriptor<L> {
pub label: L,
}
impl<L> CommandBufferDescriptor<L> {
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandBufferDescriptor<K> {
CommandBufferDescriptor {
label: fun(&self.label),
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct RenderBundleDepthStencil {
pub format: TextureFormat,
pub depth_read_only: bool,
pub stencil_read_only: bool,
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct RenderBundleDescriptor<L> {
pub label: L,
}
impl<L> RenderBundleDescriptor<L> {
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> RenderBundleDescriptor<K> {
RenderBundleDescriptor {
label: fun(&self.label),
}
}
}
impl<T> Default for RenderBundleDescriptor<Option<T>> {
fn default() -> Self {
Self { label: None }
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct ImageDataLayout {
pub offset: BufferAddress,
pub bytes_per_row: Option<NonZeroU32>,
pub rows_per_image: Option<NonZeroU32>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum BufferBindingType {
Uniform,
Storage {
read_only: bool,
},
}
impl Default for BufferBindingType {
fn default() -> Self {
Self::Uniform
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum TextureSampleType {
Float {
filterable: bool,
},
Depth,
Sint,
Uint,
}
impl Default for TextureSampleType {
fn default() -> Self {
Self::Float { filterable: true }
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum StorageTextureAccess {
WriteOnly,
ReadOnly,
ReadWrite,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum SamplerBindingType {
Filtering,
NonFiltering,
Comparison,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum BindingType {
Buffer {
ty: BufferBindingType,
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
has_dynamic_offset: bool,
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
min_binding_size: Option<BufferSize>,
},
Sampler(SamplerBindingType),
Texture {
sample_type: TextureSampleType,
view_dimension: TextureViewDimension,
multisampled: bool,
},
StorageTexture {
access: StorageTextureAccess,
format: TextureFormat,
view_dimension: TextureViewDimension,
},
}
impl BindingType {
pub fn has_dynamic_offset(&self) -> bool {
match *self {
Self::Buffer {
has_dynamic_offset, ..
} => has_dynamic_offset,
_ => false,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct BindGroupLayoutEntry {
pub binding: u32,
pub visibility: ShaderStages,
pub ty: BindingType,
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
pub count: Option<NonZeroU32>,
}
#[repr(C)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct ImageCopyBuffer<B> {
pub buffer: B,
pub layout: ImageDataLayout,
}
#[repr(C)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct ImageCopyTexture<T> {
pub texture: T,
pub mip_level: u32,
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
pub origin: Origin3d,
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
pub aspect: TextureAspect,
}
#[repr(C)]
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct ImageSubresourceRange {
pub aspect: TextureAspect,
pub base_mip_level: u32,
pub mip_level_count: Option<NonZeroU32>,
pub base_array_layer: u32,
pub array_layer_count: Option<NonZeroU32>,
}
impl ImageSubresourceRange {
pub fn mip_range<L>(&self, texture_desc: &TextureDescriptor<L>) -> Range<u32> {
self.base_mip_level..match self.mip_level_count {
Some(mip_level_count) => self.base_mip_level + mip_level_count.get(),
None => texture_desc.mip_level_count,
}
}
pub fn layer_range<L>(&self, texture_desc: &TextureDescriptor<L>) -> Range<u32> {
self.base_array_layer..match self.array_layer_count {
Some(array_layer_count) => self.base_array_layer + array_layer_count.get(),
None => {
if texture_desc.dimension == TextureDimension::D3 {
self.base_array_layer + 1
} else {
texture_desc.size.depth_or_array_layers
}
}
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub enum SamplerBorderColor {
TransparentBlack,
OpaqueBlack,
OpaqueWhite,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct QuerySetDescriptor<L> {
pub label: L,
pub ty: QueryType,
pub count: u32,
}
impl<L> QuerySetDescriptor<L> {
pub fn map_label<'a, K>(&'a self, fun: impl FnOnce(&'a L) -> K) -> QuerySetDescriptor<K> {
QuerySetDescriptor {
label: fun(&self.label),
ty: self.ty,
count: self.count,
}
}
}
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub enum QueryType {
Occlusion,
PipelineStatistics(PipelineStatisticsTypes),
Timestamp,
}
bitflags::bitflags! {
#[repr(transparent)]
pub struct PipelineStatisticsTypes : u8 {
const VERTEX_SHADER_INVOCATIONS = 1 << 0;
const CLIPPER_INVOCATIONS = 1 << 1;
const CLIPPER_PRIMITIVES_OUT = 1 << 2;
const FRAGMENT_SHADER_INVOCATIONS = 1 << 3;
const COMPUTE_SHADER_INVOCATIONS = 1 << 4;
}
}
#[cfg(feature = "bitflags_serde_shim")]
bitflags_serde_shim::impl_serde_for_bitflags!(PipelineStatisticsTypes);
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct DrawIndirectArgs {
pub vertex_count: u32,
pub instance_count: u32,
pub first_vertex: u32,
pub first_instance: u32,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct DrawIndexedIndirectArgs {
pub index_count: u32,
pub instance_count: u32,
pub first_index: u32,
pub base_vertex: i32,
pub first_instance: u32,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct DispatchIndirectArgs {
pub group_size_x: u32,
pub group_size_y: u32,
pub group_size_z: u32,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct ShaderBoundChecks {
runtime_checks: bool,
}
impl ShaderBoundChecks {
pub fn new() -> Self {
ShaderBoundChecks {
runtime_checks: true,
}
}
pub unsafe fn unchecked() -> Self {
ShaderBoundChecks {
runtime_checks: false,
}
}
pub fn runtime_checks(&self) -> bool {
self.runtime_checks
}
}
impl Default for ShaderBoundChecks {
fn default() -> Self {
Self::new()
}
}