1#![allow(
2 clippy::match_like_matches_macro,
4 clippy::redundant_pattern_matching,
6 clippy::needless_lifetimes,
8 clippy::new_without_default,
10 clippy::single_match,
12 clippy::vec_init_then_push,
14 clippy::missing_safety_doc,
16)]
17#![warn(
18 trivial_numeric_casts,
19 unused_extern_crates,
20 clippy::pattern_type_mismatch,
24)]
25
26pub use naga::{back::PipelineConstants, StorageAccess, VectorSize};
27pub type Transform = mint::RowMatrix3x4<f32>;
28
29pub const IDENTITY_TRANSFORM: Transform = mint::RowMatrix3x4 {
30 x: mint::Vector4 {
31 x: 1.0,
32 y: 0.0,
33 z: 0.0,
34 w: 0.0,
35 },
36 y: mint::Vector4 {
37 x: 0.0,
38 y: 1.0,
39 z: 0.0,
40 w: 0.0,
41 },
42 z: mint::Vector4 {
43 x: 0.0,
44 y: 0.0,
45 z: 1.0,
46 w: 0.0,
47 },
48};
49
50pub mod derive;
51#[cfg_attr(
52 all(not(vulkan), not(gles), any(target_os = "ios", target_os = "macos")),
53 path = "metal/mod.rs"
54)]
55#[cfg_attr(
56 all(
57 not(gles),
58 any(
59 vulkan,
60 windows,
61 target_os = "linux",
62 target_os = "android",
63 target_os = "freebsd"
64 )
65 ),
66 path = "vulkan/mod.rs"
67)]
68#[cfg_attr(any(gles, target_arch = "wasm32"), path = "gles/mod.rs")]
69mod hal;
70mod shader;
71pub mod traits;
72pub mod util;
73pub mod limits {
74 pub const PASS_COUNT: usize = 100;
76 pub const PLAIN_DATA_SIZE: u32 = 256;
78 pub const RESOURCES_IN_GROUP: u32 = 8;
80 pub const STORAGE_BUFFER_ALIGNMENT: u64 = 16;
82 pub const ACCELERATION_STRUCTURE_SCRATCH_ALIGNMENT: u64 = 256;
84}
85
86pub use hal::*;
87
88#[cfg(target_arch = "wasm32")]
89pub const CANVAS_ID: &str = "blade";
90
91use std::{fmt, num::NonZeroU32};
92
93#[derive(Clone, Debug, Default)]
94pub struct ContextDesc {
95 pub presentation: bool,
97 pub validation: bool,
100 pub timing: bool,
102 pub capture: bool,
104 pub overlay: bool,
106 pub device_id: u32,
108}
109
110#[derive(Debug)]
111pub enum NotSupportedError {
112 Platform(PlatformError),
113 NoSupportedDeviceFound,
114 PlatformNotSupported,
115}
116
117impl From<PlatformError> for NotSupportedError {
118 fn from(error: PlatformError) -> Self {
119 Self::Platform(error)
120 }
121}
122
123#[derive(Clone, Debug, Default, PartialEq)]
124pub struct Capabilities {
125 pub ray_query: ShaderVisibility,
127 pub sample_count_mask: u32,
129}
130
131#[derive(Clone, Debug, Default)]
132pub struct DeviceInformation {
133 pub is_software_emulated: bool,
135 pub device_name: String,
137 pub driver_name: String,
139 pub driver_info: String,
141}
142
143impl Context {
144 pub fn create_surface_configured<
145 I: raw_window_handle::HasWindowHandle + raw_window_handle::HasDisplayHandle,
146 >(
147 &self,
148 window: &I,
149 config: SurfaceConfig,
150 ) -> Result<Surface, NotSupportedError> {
151 let mut surface = self.create_surface(window)?;
152 self.reconfigure_surface(&mut surface, config);
153 Ok(surface)
154 }
155}
156
157#[derive(Clone, Copy, Debug, PartialEq)]
158pub enum Memory {
159 Device,
161 Shared,
163 Upload,
165 External(ExternalMemorySource),
167}
168
169#[derive(Clone, Copy, Debug, PartialEq, Hash)]
172pub enum ExternalMemorySource {
173 #[cfg(target_os = "windows")]
174 Win32(Option<isize>),
175
176 #[cfg(target_os = "windows")]
177 Win32KMT(Option<isize>),
178
179 #[cfg(not(target_os = "windows"))]
180 Fd(Option<i32>),
181
182 #[cfg(target_os = "linux")]
183 Dma(Option<i32>),
184
185 HostAllocation(usize),
187}
188
189impl Memory {
190 pub fn is_host_visible(&self) -> bool {
191 match *self {
192 Self::Shared
193 | Self::Upload
194 | Self::External(ExternalMemorySource::HostAllocation(_)) => true,
195 Self::Device | Self::External(_) => false,
196 }
197 }
198}
199
200#[derive(Debug)]
201pub struct BufferDesc<'a> {
202 pub name: &'a str,
203 pub size: u64,
204 pub memory: Memory,
205}
206
207#[derive(Clone, Copy, Debug)]
208pub struct BufferPiece {
209 pub buffer: Buffer,
210 pub offset: u64,
211}
212
213impl From<Buffer> for BufferPiece {
214 fn from(buffer: Buffer) -> Self {
215 Self { buffer, offset: 0 }
216 }
217}
218
219impl BufferPiece {
220 pub fn data(&self) -> *mut u8 {
221 let base = self.buffer.data();
222 assert!(!base.is_null());
223 unsafe { base.offset(self.offset as isize) }
224 }
225}
226
227impl Buffer {
228 pub fn at(self, offset: u64) -> BufferPiece {
229 BufferPiece {
230 buffer: self,
231 offset,
232 }
233 }
234}
235
236pub type ResourceIndex = u32;
237pub struct ResourceArray<T, const N: ResourceIndex> {
240 data: Vec<T>,
241 free_list: Vec<ResourceIndex>,
242}
243impl<T, const N: ResourceIndex> ResourceArray<T, N> {
244 pub fn new() -> Self {
245 Self {
246 data: Vec::with_capacity(N as usize),
247 free_list: Vec::new(),
248 }
249 }
250 pub fn alloc(&mut self, value: T) -> ResourceIndex {
251 if let Some(index) = self.free_list.pop() {
252 self.data[index as usize] = value;
253 index
254 } else {
255 let index = self.data.len() as u32;
256 assert!(index < N);
257 self.data.push(value);
258 index
259 }
260 }
261 pub fn free(&mut self, index: ResourceIndex) {
262 self.free_list.push(index);
263 }
264 pub fn clear(&mut self) {
265 self.data.clear();
266 self.free_list.clear();
267 }
268}
269impl<T, const N: ResourceIndex> std::ops::Index<ResourceIndex> for ResourceArray<T, N> {
270 type Output = T;
271 fn index(&self, index: ResourceIndex) -> &T {
272 &self.data[index as usize]
273 }
274}
275impl<T, const N: ResourceIndex> std::ops::IndexMut<ResourceIndex> for ResourceArray<T, N> {
276 fn index_mut(&mut self, index: ResourceIndex) -> &mut T {
277 &mut self.data[index as usize]
278 }
279}
280pub type BufferArray<const N: ResourceIndex> = ResourceArray<BufferPiece, N>;
281pub type TextureArray<const N: ResourceIndex> = ResourceArray<TextureView, N>;
282
283#[derive(Clone, Copy, Debug)]
284pub struct TexturePiece {
285 pub texture: Texture,
286 pub mip_level: u32,
287 pub array_layer: u32,
288 pub origin: [u32; 3],
289}
290
291impl From<Texture> for TexturePiece {
292 fn from(texture: Texture) -> Self {
293 Self {
294 texture,
295 mip_level: 0,
296 array_layer: 0,
297 origin: [0; 3],
298 }
299 }
300}
301
302#[non_exhaustive]
303#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
304pub enum TextureFormat {
305 R8Unorm,
307 Rg8Unorm,
308 Rg8Snorm,
309 Rgba8Unorm,
310 Rgba8UnormSrgb,
311 Bgra8Unorm,
312 Bgra8UnormSrgb,
313 Rgba8Snorm,
314 R16Float,
315 Rg16Float,
316 Rgba16Float,
317 R32Float,
318 Rg32Float,
319 Rgba32Float,
320 R32Uint,
321 Rg32Uint,
322 Rgba32Uint,
323 Depth32Float,
325 Depth32FloatStencil8Uint,
326 Stencil8Uint,
327 Bc1Unorm,
329 Bc1UnormSrgb,
330 Bc2Unorm,
331 Bc2UnormSrgb,
332 Bc3Unorm,
333 Bc3UnormSrgb,
334 Bc4Unorm,
335 Bc4Snorm,
336 Bc5Unorm,
337 Bc5Snorm,
338 Bc6hUfloat,
339 Bc6hFloat,
340 Bc7Unorm,
341 Bc7UnormSrgb,
342 Rgb10a2Unorm,
344 Rg11b10Ufloat,
345 Rgb9e5Ufloat,
346}
347
348#[derive(Clone, Copy, Debug)]
349pub struct TexelBlockInfo {
350 pub dimensions: (u8, u8),
351 pub size: u8,
352}
353
354bitflags::bitflags! {
355 #[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
356 pub struct TexelAspects: u8 {
357 const COLOR = 0x1;
358 const DEPTH = 0x2;
359 const STENCIL = 0x4;
360 }
361}
362
363#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
365pub enum TextureDimension {
366 D1,
368 D2,
370 D3,
372}
373
374#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
375pub enum ViewDimension {
376 D1,
377 D1Array,
378 D2,
379 D2Array,
380 Cube,
381 CubeArray,
382 D3,
383}
384
385#[repr(C)]
386#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
387pub struct Extent {
388 pub width: u32,
389 pub height: u32,
390 pub depth: u32,
391}
392impl Default for Extent {
393 fn default() -> Self {
394 Self {
395 width: 1,
396 height: 1,
397 depth: 1,
398 }
399 }
400}
401impl fmt::Display for Extent {
402 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
403 write!(f, "{}x{}x{}", self.width, self.height, self.depth)
404 }
405}
406
407impl Extent {
408 pub fn max_mip_levels(&self) -> u32 {
409 self.width
410 .max(self.height)
411 .max(self.depth)
412 .next_power_of_two()
413 .trailing_zeros()
414 }
415 pub fn at_mip_level(&self, level: u32) -> Self {
416 Self {
417 width: (self.width >> level).max(1),
418 height: (self.height >> level).max(1),
419 depth: (self.depth >> level).max(1),
420 }
421 }
422}
423
424bitflags::bitflags! {
425 #[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
426 pub struct TextureUsage: u32 {
427 const COPY = 1 << 0;
428 const TARGET = 1 << 1;
429 const RESOURCE = 1 << 2;
430 const STORAGE = 1 << 3;
431 }
432}
433
434#[derive(Debug)]
435pub struct TextureDesc<'a> {
436 pub name: &'a str,
437 pub format: TextureFormat,
438 pub size: Extent,
439 pub array_layer_count: u32,
440 pub mip_level_count: u32,
441 pub sample_count: u32,
442 pub dimension: TextureDimension,
443 pub usage: TextureUsage,
444 pub external: Option<ExternalMemorySource>,
445}
446
447#[derive(Clone, Debug, Default, Eq, PartialEq)]
448pub struct TextureSubresources {
449 pub base_mip_level: u32,
450 pub mip_level_count: Option<NonZeroU32>,
451 pub base_array_layer: u32,
452 pub array_layer_count: Option<NonZeroU32>,
453}
454
455#[derive(Debug)]
456pub struct TextureViewDesc<'a> {
457 pub name: &'a str,
458 pub format: TextureFormat,
459 pub dimension: ViewDimension,
460 pub subresources: &'a TextureSubresources,
461}
462
463bitflags::bitflags! {
464 #[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
465 pub struct ShaderVisibility: u32 {
466 const COMPUTE = 1 << 0;
467 const VERTEX = 1 << 1;
468 const FRAGMENT = 1 << 2;
469 }
470}
471
472#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
474pub enum AddressMode {
475 #[default]
477 ClampToEdge,
478 Repeat,
480 MirrorRepeat,
482 ClampToBorder,
484}
485
486#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
488pub enum FilterMode {
489 #[default]
491 Nearest,
492 Linear,
494}
495
496#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
498pub enum CompareFunction {
499 Never,
501 Less,
503 Equal,
507 LessEqual,
509 Greater,
511 NotEqual,
515 GreaterEqual,
517 #[default]
519 Always,
520}
521
522#[derive(Clone, Copy, Debug)]
523pub enum TextureColor {
524 TransparentBlack,
525 OpaqueBlack,
526 White,
527}
528
529#[derive(Debug, Default)]
530pub struct SamplerDesc<'a> {
531 pub name: &'a str,
532 pub address_modes: [AddressMode; 3],
533 pub mag_filter: FilterMode,
534 pub min_filter: FilterMode,
535 pub mipmap_filter: FilterMode,
536 pub lod_min_clamp: f32,
537 pub lod_max_clamp: Option<f32>,
538 pub compare: Option<CompareFunction>,
539 pub anisotropy_clamp: u32,
540 pub border_color: Option<TextureColor>,
541}
542
543#[derive(Debug)]
544pub enum AccelerationStructureType {
545 TopLevel,
546 BottomLevel,
547}
548
549#[derive(Debug)]
550pub struct AccelerationStructureDesc<'a> {
551 pub name: &'a str,
552 pub ty: AccelerationStructureType,
553 pub size: u64,
554}
555
556#[non_exhaustive]
557#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
558pub enum VertexFormat {
559 F32,
560 F32Vec2,
561 F32Vec3,
562 F32Vec4,
563 U32,
564 U32Vec2,
565 U32Vec3,
566 U32Vec4,
567 I32,
568 I32Vec2,
569 I32Vec3,
570 I32Vec4,
571}
572
573#[derive(Clone, Debug)]
574pub struct AccelerationStructureMesh {
575 pub vertex_data: BufferPiece,
576 pub vertex_format: VertexFormat,
577 pub vertex_stride: u32,
578 pub vertex_count: u32,
579 pub index_data: BufferPiece,
580 pub index_type: Option<IndexType>,
581 pub triangle_count: u32,
582 pub transform_data: BufferPiece,
583 pub is_opaque: bool,
584}
585
586#[derive(Clone, Debug)]
587pub struct AccelerationStructureInstance {
588 pub acceleration_structure_index: u32,
589 pub transform: Transform,
590 pub mask: u32,
591 pub custom_index: u32,
592}
593
594impl Default for AccelerationStructureInstance {
595 fn default() -> Self {
596 Self {
597 acceleration_structure_index: 0,
598 transform: IDENTITY_TRANSFORM,
599 mask: 0xFF,
600 custom_index: 0,
601 }
602 }
603}
604
605#[derive(Clone, Copy, Debug, Default, PartialEq)]
606pub struct AccelerationStructureSizes {
607 pub data: u64,
609 pub scratch: u64,
611}
612
613pub struct Shader {
614 module: naga::Module,
615 info: naga::valid::ModuleInfo,
616 source: String,
617}
618
619#[derive(Clone, Copy)]
620pub struct ShaderFunction<'a> {
621 pub shader: &'a Shader,
622 pub entry_point: &'a str,
623 pub constants: &'a PipelineConstants,
624}
625
626impl ShaderFunction<'_> {
627 fn entry_point_index(&self) -> usize {
628 self.shader
629 .module
630 .entry_points
631 .iter()
632 .position(|ep| ep.name == self.entry_point)
633 .expect("Entry point not found in the shader")
634 }
635}
636
637#[derive(Clone, Copy, Debug, PartialEq)]
638pub enum ShaderBinding {
639 Texture,
640 TextureArray { count: u32 },
641 Sampler,
642 Buffer,
643 BufferArray { count: u32 },
644 AccelerationStructure,
645 Plain { size: u32 },
646}
647
648pub trait ShaderBindable: Clone + Copy + derive::HasShaderBinding {
649 fn bind_to(&self, context: &mut PipelineContext, index: u32);
650}
651
652#[derive(Debug)]
653struct ShaderDataInfo {
654 visibility: ShaderVisibility,
655 binding_access: Box<[StorageAccess]>,
656}
657
658#[derive(Clone, Debug, Default, PartialEq)]
659pub struct ShaderDataLayout {
660 pub bindings: Vec<(&'static str, ShaderBinding)>,
661}
662impl ShaderDataLayout {
663 pub const EMPTY: &'static Self = &Self {
664 bindings: Vec::new(),
665 };
666
667 fn to_info(&self) -> ShaderDataInfo {
668 ShaderDataInfo {
669 visibility: ShaderVisibility::empty(),
670 binding_access: vec![StorageAccess::empty(); self.bindings.len()].into_boxed_slice(),
671 }
672 }
673}
674
675pub trait ShaderData {
676 fn layout() -> ShaderDataLayout;
677 fn fill(&self, context: PipelineContext);
678}
679
680#[derive(Copy, Clone, Debug, PartialEq)]
681pub struct VertexAttribute {
682 pub offset: u32,
683 pub format: VertexFormat,
684}
685
686struct VertexAttributeMapping {
687 buffer_index: usize,
688 attribute_index: usize,
689}
690
691#[derive(Clone, Debug, Default, PartialEq)]
692pub struct VertexLayout {
693 pub attributes: Vec<(&'static str, VertexAttribute)>,
694 pub stride: u32,
695}
696
697pub trait Vertex {
698 fn layout() -> VertexLayout;
699}
700
701#[derive(Clone, Debug, PartialEq)]
702pub struct VertexFetchState<'a> {
703 pub layout: &'a VertexLayout,
704 pub instanced: bool,
705}
706
707pub struct ShaderDesc<'a> {
708 pub source: &'a str,
709}
710
711#[derive(Clone, Debug, Default, PartialEq)]
712pub enum CommandType {
713 Transfer,
714 Compute,
715 #[default]
716 General,
717}
718
719pub struct CommandEncoderDesc<'a> {
720 pub name: &'a str,
721 pub buffer_count: u32,
725}
726
727pub struct ComputePipelineDesc<'a> {
728 pub name: &'a str,
729 pub data_layouts: &'a [&'a ShaderDataLayout],
730 pub compute: ShaderFunction<'a>,
731}
732
733#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
735pub enum PrimitiveTopology {
736 PointList,
738 LineList,
742 LineStrip,
746 #[default]
750 TriangleList,
751 TriangleStrip,
755}
756
757#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
759pub enum FrontFace {
760 #[default]
764 Ccw,
765 Cw,
769}
770
771#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
773pub enum Face {
774 Front,
776 Back,
778}
779
780#[derive(Clone, Debug, Default)]
781pub struct PrimitiveState {
782 pub topology: PrimitiveTopology,
784 pub front_face: FrontFace,
786 pub cull_mode: Option<Face>,
788 pub unclipped_depth: bool,
790 pub wireframe: bool,
792}
793
794#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
796pub enum StencilOperation {
797 #[default]
799 Keep,
800 Zero,
802 Replace,
804 Invert,
806 IncrementClamp,
808 DecrementClamp,
810 IncrementWrap,
812 DecrementWrap,
814}
815
816#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
820pub struct StencilFaceState {
821 pub compare: CompareFunction,
823 pub fail_op: StencilOperation,
825 pub depth_fail_op: StencilOperation,
827 pub pass_op: StencilOperation,
829}
830
831impl StencilFaceState {
832 pub const IGNORE: Self = StencilFaceState {
834 compare: CompareFunction::Always,
835 fail_op: StencilOperation::Keep,
836 depth_fail_op: StencilOperation::Keep,
837 pass_op: StencilOperation::Keep,
838 };
839}
840
841impl Default for StencilFaceState {
842 fn default() -> Self {
843 Self::IGNORE
844 }
845}
846
847#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
851pub struct StencilState {
852 pub front: StencilFaceState,
854 pub back: StencilFaceState,
856 pub read_mask: u32,
858 pub write_mask: u32,
860}
861
862#[derive(Clone, Copy, Debug, Default, PartialEq)]
863pub struct DepthBiasState {
864 pub constant: i32,
866 pub slope_scale: f32,
868 pub clamp: f32,
870}
871
872#[derive(Clone, Debug)]
874pub struct DepthStencilState {
875 pub format: TextureFormat,
877 pub depth_write_enabled: bool,
879 pub depth_compare: CompareFunction,
881 pub stencil: StencilState,
883 pub bias: DepthBiasState,
885}
886
887#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
889pub enum BlendFactor {
890 Zero,
892 One,
894 Src,
896 OneMinusSrc,
898 SrcAlpha,
900 OneMinusSrcAlpha,
902 Dst,
904 OneMinusDst,
906 DstAlpha,
908 OneMinusDstAlpha,
910 SrcAlphaSaturated,
912 Constant,
914 OneMinusConstant,
916}
917
918#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
920pub enum BlendOperation {
921 #[default]
923 Add,
924 Subtract,
926 ReverseSubtract,
928 Min,
930 Max,
932}
933
934#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
936pub struct BlendComponent {
937 pub src_factor: BlendFactor,
939 pub dst_factor: BlendFactor,
941 pub operation: BlendOperation,
944}
945
946impl BlendComponent {
947 pub const REPLACE: Self = Self {
949 src_factor: BlendFactor::One,
950 dst_factor: BlendFactor::Zero,
951 operation: BlendOperation::Add,
952 };
953
954 pub const OVER: Self = Self {
956 src_factor: BlendFactor::One,
957 dst_factor: BlendFactor::OneMinusSrcAlpha,
958 operation: BlendOperation::Add,
959 };
960
961 pub const ADDITIVE: Self = Self {
963 src_factor: BlendFactor::One,
964 dst_factor: BlendFactor::One,
965 operation: BlendOperation::Add,
966 };
967}
968
969impl Default for BlendComponent {
970 fn default() -> Self {
971 Self::REPLACE
972 }
973}
974
975#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
978pub struct BlendState {
979 pub color: BlendComponent,
981 pub alpha: BlendComponent,
983}
984
985impl BlendState {
986 pub const REPLACE: Self = Self {
988 color: BlendComponent::REPLACE,
989 alpha: BlendComponent::REPLACE,
990 };
991
992 pub const ALPHA_BLENDING: Self = Self {
994 color: BlendComponent {
995 src_factor: BlendFactor::SrcAlpha,
996 dst_factor: BlendFactor::OneMinusSrcAlpha,
997 operation: BlendOperation::Add,
998 },
999 alpha: BlendComponent::OVER,
1000 };
1001
1002 pub const PREMULTIPLIED_ALPHA_BLENDING: Self = Self {
1004 color: BlendComponent::OVER,
1005 alpha: BlendComponent::OVER,
1006 };
1007
1008 pub const ADDITIVE: Self = Self {
1010 color: BlendComponent::ADDITIVE,
1011 alpha: BlendComponent::ADDITIVE,
1012 };
1013}
1014
1015bitflags::bitflags! {
1016 #[repr(transparent)]
1018 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1019 pub struct ColorWrites: u32 {
1020 const RED = 1 << 0;
1022 const GREEN = 1 << 1;
1024 const BLUE = 1 << 2;
1026 const ALPHA = 1 << 3;
1028 const COLOR = Self::RED.bits() | Self::GREEN.bits() | Self::BLUE.bits();
1030 const ALL = Self::RED.bits() | Self::GREEN.bits() | Self::BLUE.bits() | Self::ALPHA.bits();
1032 }
1033}
1034
1035impl Default for ColorWrites {
1036 fn default() -> Self {
1037 Self::ALL
1038 }
1039}
1040
1041#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1043pub struct ColorTargetState {
1044 pub format: TextureFormat,
1046 pub blend: Option<BlendState>,
1048 pub write_mask: ColorWrites,
1050}
1051
1052impl From<TextureFormat> for ColorTargetState {
1053 fn from(format: TextureFormat) -> Self {
1054 Self {
1055 format,
1056 blend: None,
1057 write_mask: ColorWrites::ALL,
1058 }
1059 }
1060}
1061
1062pub struct RenderPipelineDesc<'a> {
1063 pub name: &'a str,
1064 pub data_layouts: &'a [&'a ShaderDataLayout],
1065 pub vertex: ShaderFunction<'a>,
1066 pub vertex_fetches: &'a [VertexFetchState<'a>],
1067 pub primitive: PrimitiveState,
1068 pub depth_stencil: Option<DepthStencilState>,
1069 pub fragment: Option<ShaderFunction<'a>>,
1070 pub color_targets: &'a [ColorTargetState],
1071 pub multisample_state: MultisampleState,
1072}
1073
1074#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1075pub struct MultisampleState {
1076 pub sample_count: u32,
1077 pub sample_mask: u64,
1078 pub alpha_to_coverage: bool,
1079}
1080
1081impl Default for MultisampleState {
1082 fn default() -> Self {
1083 Self {
1084 sample_count: 1,
1085 sample_mask: !0,
1086 alpha_to_coverage: false,
1087 }
1088 }
1089}
1090
1091#[derive(Clone, Copy, Debug)]
1092pub enum InitOp {
1093 Load,
1094 Clear(TextureColor),
1095 DontCare,
1096}
1097
1098#[derive(Clone, Copy, Debug)]
1099pub enum FinishOp {
1100 Store,
1101 Discard,
1102 ResolveTo(TextureView),
1105 Ignore,
1106}
1107
1108#[derive(Debug)]
1109pub struct RenderTarget {
1110 pub view: TextureView,
1111 pub init_op: InitOp,
1112 pub finish_op: FinishOp,
1113}
1114
1115#[derive(Debug)]
1116pub struct RenderTargetSet<'a> {
1117 pub colors: &'a [RenderTarget],
1118 pub depth_stencil: Option<RenderTarget>,
1119}
1120
1121#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
1123pub enum DisplaySync {
1124 #[default]
1126 Block,
1127 Recent,
1130 Tear,
1132}
1133
1134#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
1135pub enum ColorSpace {
1136 #[default]
1137 Linear,
1138 Srgb,
1139}
1140
1141#[derive(Clone, Copy, Debug, Default, PartialEq)]
1142pub struct SurfaceConfig {
1143 pub size: Extent,
1144 pub usage: TextureUsage,
1145 pub display_sync: DisplaySync,
1146 pub color_space: ColorSpace,
1153 pub transparent: bool,
1154 pub allow_exclusive_full_screen: bool,
1155}
1156
1157#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
1158pub enum AlphaMode {
1159 #[default]
1160 Ignored,
1161 PreMultiplied,
1162 PostMultiplied,
1163}
1164
1165#[derive(Clone, Copy, Debug, PartialEq)]
1166pub struct SurfaceInfo {
1167 pub format: TextureFormat,
1168 pub alpha: AlphaMode,
1169}
1170
1171#[derive(Clone, Copy, Debug, PartialEq)]
1172pub enum IndexType {
1173 U16,
1174 U32,
1175}
1176
1177#[derive(Clone, Debug, PartialEq)]
1178pub struct ScissorRect {
1179 pub x: i32,
1180 pub y: i32,
1181 pub w: u32,
1182 pub h: u32,
1183}
1184
1185#[derive(Clone, Debug, PartialEq)]
1186pub struct Viewport {
1187 pub x: f32,
1188 pub y: f32,
1189 pub w: f32,
1190 pub h: f32,
1191 pub depth: std::ops::Range<f32>,
1192}
1193
1194pub type Timings = Vec<(String, std::time::Duration)>;