1#![no_std]
82
83extern crate alloc;
84
85use alloc::string::String;
86
87#[cfg(not(target_arch = "wasm32"))]
88mod vk_cmd;
89#[cfg(not(target_arch = "wasm32"))]
90mod vk_dev;
91#[cfg(not(target_arch = "wasm32"))]
92mod vk_ffi;
93#[cfg(not(target_arch = "wasm32"))]
94mod vk_inst;
95#[cfg(not(target_arch = "wasm32"))]
96mod vk_load;
97#[cfg(not(target_arch = "wasm32"))]
98mod vk_mem;
99#[cfg(not(target_arch = "wasm32"))]
100mod vk_res;
101#[cfg(not(any(jfgui_glibc, target_arch = "wasm32")))]
102mod vk_swap;
103#[cfg(jfgui_glibc)]
105#[path = "vk_dmabuf.rs"]
106mod vk_swap;
107#[cfg(target_arch = "wasm32")]
109mod web_cmd;
110#[cfg(target_arch = "wasm32")]
111mod web_dev;
112#[cfg(target_arch = "wasm32")]
113mod web_res;
114#[cfg(target_arch = "wasm32")]
115mod web_swap;
116
117#[cfg(not(target_arch = "wasm32"))]
118pub use vk_cmd::{CommandBuffer, CommandEncoder};
119#[cfg(not(target_arch = "wasm32"))]
120pub use vk_dev::{Device, Queue};
121#[cfg(not(target_arch = "wasm32"))]
122pub use vk_inst::{Adapter, Instance, low_power_rank, validation_messages};
123#[cfg(not(target_arch = "wasm32"))]
124pub use vk_res::{BindGroup, BindGroupLayout, Bindless, Buffer, ComputePipeline, PipelineLayout, RenderPipeline, Sampler,
125 ShaderModule, Texture, TextureView, Timestamps};
126#[cfg(not(target_arch = "wasm32"))]
127pub use vk_swap::{Frame, Surface, Swapchain, TryAcquire};
128#[cfg(target_arch = "wasm32")]
129pub use web_cmd::{CommandBuffer, CommandEncoder};
130#[cfg(target_arch = "wasm32")]
131pub use web_dev::{Adapter, Device, Instance, Queue, low_power_rank, validation_messages};
132#[cfg(target_arch = "wasm32")]
133pub use web_res::{BindGroup, BindGroupLayout, Bindless, Buffer, ComputePipeline, PipelineLayout, RenderPipeline, Sampler,
134 ShaderModule, Texture, TextureView, Timestamps};
135#[cfg(target_arch = "wasm32")]
136pub use web_swap::{Frame, Surface, Swapchain, TryAcquire};
137
138pub type Result<T> = core::result::Result<T, GpuError>;
139
140pub const PUSH_CONSTANTS_MAX: u32 = 128;
142pub const BIND_GROUPS_MAX: u32 = 4;
144pub const COLOR_TARGETS_MAX: usize = 8;
146
147#[derive(Clone, Copy, Debug, PartialEq, Eq)]
149#[non_exhaustive]
150pub enum GpuError {
151 Disabled,
153 NoLoader,
156 NoAdapter,
158 Unsupported(&'static str),
160 Invalid(&'static str),
162 OutOfMemory,
164 DeviceLost,
166 SurfaceLost,
168 Timeout,
170 NotReady,
172 Failed(i32),
174}
175
176impl core::fmt::Display for GpuError {
177 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
178 match self {
179 GpuError::Disabled => f.write_str("GPU disabled (jfgui_GPU=0)"),
180 #[cfg(not(target_arch = "wasm32"))]
181 GpuError::NoLoader => f.write_str("no GPU API installed (Vulkan loader missing)"),
182 #[cfg(target_arch = "wasm32")]
183 GpuError::NoLoader => f.write_str("no WebGPU in this browser"),
184 GpuError::NoAdapter => f.write_str("no usable GPU"),
185 GpuError::Unsupported(w) => write!(f, "not supported: {w}"),
186 GpuError::Invalid(w) => write!(f, "invalid use: {w}"),
187 GpuError::OutOfMemory => f.write_str("out of GPU or host memory"),
188 GpuError::DeviceLost => f.write_str("GPU device lost"),
189 GpuError::SurfaceLost => f.write_str("window surface lost"),
190 GpuError::Timeout => f.write_str("GPU wait timed out"),
191 GpuError::NotReady => f.write_str("GPU results not ready"),
192 GpuError::Failed(c) => write!(f, "GPU call failed ({c})"),
193 }
194 }
195}
196
197pub unsafe trait Pod: Copy + 'static {}
203unsafe impl Pod for u8 {}
205unsafe impl Pod for i8 {}
207unsafe impl Pod for u16 {}
209unsafe impl Pod for i16 {}
211unsafe impl Pod for u32 {}
213unsafe impl Pod for i32 {}
215unsafe impl Pod for u64 {}
217unsafe impl Pod for i64 {}
219unsafe impl Pod for f32 {}
221unsafe impl Pod for f64 {}
223unsafe impl<T: Pod, const N: usize> Pod for [T; N] {}
225
226pub fn bytes_of<T: Pod>(s: &[T]) -> &[u8] {
228 unsafe { core::slice::from_raw_parts(s.as_ptr() as *const u8, core::mem::size_of_val(s)) }
230}
231
232#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
234#[non_exhaustive]
235pub enum Level {
236 Basis,
238 Voll,
240}
241
242#[derive(Clone, Copy, Debug, PartialEq, Eq)]
244#[non_exhaustive]
245pub enum AdapterKind {
246 Discrete,
247 Integrated,
248 Virtual,
249 Cpu,
250 Other,
251}
252
253#[derive(Clone, Debug)]
255pub struct AdapterInfo {
256 pub name: String,
258 pub vendor_id: u32,
259 pub device_id: u32,
260 pub vendor: &'static str,
262 pub kind: AdapterKind,
263 pub driver: String,
266 pub driver_info: String,
267 pub driver_version: String,
269 pub api_version: (u32, u32, u32),
271 pub backend: &'static str,
273 pub missing: Option<&'static str>,
275}
276
277#[derive(Clone, Copy, Debug, Default)]
279pub struct Features {
280 pub timestamps: bool,
282 pub multi_draw_indirect: bool,
284 pub draw_indirect_first_instance: bool,
286 pub draw_indirect_count: bool,
288 pub bindless: bool,
290 pub subgroups: bool,
292 pub subgroups_webgpu: bool,
295 pub subgroup_stages: u32,
298 pub subgroup_ops: u32,
299 pub subgroup_size_control: bool,
302 pub subgroup_extended_types: bool,
304 pub draw_parameters: bool,
306 pub shader_f16: bool,
307 pub shader_f64: bool,
308 pub shader_i16: bool,
309 pub shader_i64: bool,
310 pub shader_i8: bool,
311 pub storage_16bit: bool,
313 pub uniform_16bit: bool,
315 pub push_constant_16bit: bool,
316 pub uniform_standard_layout: bool,
319 pub demote: bool,
321 pub clip_distances: bool,
324 pub primitive_index: bool,
325 pub sample_shading: bool,
326 pub storage_8bit: bool,
327 pub texture_bc: bool,
329 pub anisotropy: bool,
330 pub depth_clamp: bool,
331 pub vertex_stores: bool,
333 pub fragment_stores: bool,
334 pub storage_write_without_format: bool,
336 pub buffer_address: bool,
338 pub swapchain: bool,
340 pub mesh_shader: bool,
342 pub ray_query: bool,
343 pub ray_pipeline: bool,
344}
345
346pub mod subgroup_stage {
348 pub const COMPUTE: u32 = 1;
349 pub const FRAGMENT: u32 = 2;
350 pub const VERTEX: u32 = 4;
351}
352
353pub mod subgroup_op {
355 pub const BASIC: u32 = 1;
356 pub const VOTE: u32 = 2;
357 pub const ARITHMETIC: u32 = 4;
358 pub const BALLOT: u32 = 8;
359 pub const SHUFFLE: u32 = 0x10;
360 pub const SHUFFLE_RELATIVE: u32 = 0x20;
361 pub const CLUSTERED: u32 = 0x40;
362 pub const QUAD: u32 = 0x80;
363}
364
365#[derive(Clone, Copy, Debug, Default)]
367pub struct Limits {
368 pub max_texture_2d: u32,
369 pub max_texture_3d: u32,
370 pub max_texture_layers: u32,
371 pub max_storage_binding: u32,
373 pub max_uniform_binding: u32,
374 pub max_push_constants: u32,
376 pub max_bind_groups: u32,
377 pub max_compute_workgroup_size: [u32; 3],
378 pub max_compute_invocations: u32,
379 pub max_compute_workgroups: [u32; 3],
380 pub max_compute_shared_memory: u32,
381 pub min_uniform_offset_alignment: u32,
382 pub min_storage_offset_alignment: u32,
383 pub max_color_targets: u32,
384 pub max_vertex_buffers: u32,
385 pub max_vertex_attributes: u32,
386 pub max_draw_indirect_count: u32,
387 pub max_anisotropy: f32,
388 pub timestamp_period_ns: f32,
390 pub subgroup_size: u32,
392 pub subgroup_min_size: u32,
394 pub subgroup_max_size: u32,
395 pub max_bindless_textures: u32,
397 pub max_bindless_samplers: u32,
398 pub max_bindless_buffers: u32,
399 pub max_bindless_storage_textures: u32,
400 pub device_memory: u64,
402}
403
404#[derive(Clone, Copy)]
406pub struct InstanceDesc<'a> {
407 pub app_name: &'a str,
409 pub validate: bool,
411}
412
413impl InstanceDesc<'_> {
414 pub const DEFAULT: InstanceDesc<'static> = InstanceDesc { app_name: "jfgui", validate: false };
415}
416
417#[derive(Clone, Copy)]
419pub struct DeviceDesc {
420 pub max_level: Level,
422}
423
424impl DeviceDesc {
425 pub const DEFAULT: DeviceDesc = DeviceDesc { max_level: Level::Voll };
426}
427
428#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
430pub struct SubmitId(pub u64);
431
432macro_rules! flags {
433 ($(#[$m:meta])* $name:ident { $( $(#[$fm:meta])* $f:ident = $v:expr ),* $(,)? }) => {
434 $(#[$m])*
435 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
436 pub struct $name(pub u32);
437 impl $name {
438 pub const NONE: $name = $name(0);
439 $( $(#[$fm])* pub const $f: $name = $name($v); )*
440 pub const fn contains(self, o: $name) -> bool {
441 self.0 & o.0 == o.0
442 }
443 pub const fn intersects(self, o: $name) -> bool {
444 self.0 & o.0 != 0
445 }
446 }
447 impl core::ops::BitOr for $name {
448 type Output = $name;
449 fn bitor(self, o: $name) -> $name {
450 $name(self.0 | o.0)
451 }
452 }
453 };
454}
455
456flags! {
457 BufferUsage {
459 UNIFORM = 1,
460 STORAGE = 2,
461 INDEX = 4,
462 VERTEX = 8,
463 INDIRECT = 16,
465 }
466}
467
468flags! {
469 TextureUsage {
471 COPY_SRC = 1,
472 COPY_DST = 2,
473 SAMPLED = 4,
474 STORAGE = 8,
475 COLOR_TARGET = 16,
476 DEPTH_TARGET = 32,
477 }
478}
479
480flags! {
481 Stages {
483 VERTEX = 1,
484 FRAGMENT = 2,
485 COMPUTE = 4,
486 ALL = 7,
487 }
488}
489
490flags! {
491 Access {
494 COPY_READ = 1,
495 COPY_WRITE = 2,
496 COMPUTE_READ = 4,
497 COMPUTE_WRITE = 8,
498 GRAPHICS_READ = 16,
500 GRAPHICS_WRITE = 32,
501 INDIRECT = 64,
503 INDEX_VERTEX = 128,
505 COLOR_TARGET = 256,
506 DEPTH_TARGET = 512,
507 HOST_READ = 1024,
509 HOST_WRITE = 2048,
510 }
511}
512
513#[derive(Clone, Copy, Debug, PartialEq, Eq)]
515#[non_exhaustive]
516pub enum MemoryKind {
517 Device,
519 Upload,
521 Readback,
523}
524
525#[derive(Clone, Copy, Debug)]
527pub struct BufferDesc {
528 pub size: u64,
529 pub usage: BufferUsage,
530 pub memory: MemoryKind,
531}
532
533#[derive(Clone, Copy, Debug, PartialEq, Eq)]
535#[non_exhaustive]
536pub enum Format {
537 R8Unorm,
538 Rg8Unorm,
539 Rgba8Unorm,
540 Rgba8Srgb,
541 Bgra8Unorm,
542 Bgra8Srgb,
543 Rgb10a2Unorm,
544 Rg11b10Float,
545 R16Float,
546 Rg16Float,
547 Rgba16Float,
548 R32Uint,
549 R32Sint,
550 R32Float,
551 Rg32Uint,
552 Rg32Float,
553 Rgba32Uint,
554 Rgba32Float,
555 Depth16,
556 Depth32Float,
557 Depth24Stencil8,
558 Depth32FloatStencil8,
559 Bc1Unorm,
560 Bc1Srgb,
561 Bc3Unorm,
562 Bc3Srgb,
563 Bc4Unorm,
564 Bc5Unorm,
565 Bc7Unorm,
566 Bc7Srgb,
567}
568
569impl Format {
570 pub const fn block_bytes(self) -> u32 {
572 use Format::*;
573 match self {
574 R8Unorm => 1,
575 Rg8Unorm | R16Float | Depth16 => 2,
576 Rgba8Unorm | Rgba8Srgb | Bgra8Unorm | Bgra8Srgb | Rgb10a2Unorm | Rg11b10Float | Rg16Float | R32Uint
577 | R32Sint | R32Float | Depth32Float | Depth24Stencil8 => 4,
578 Rgba16Float | Rg32Uint | Rg32Float | Depth32FloatStencil8 => 8,
579 Rgba32Uint | Rgba32Float => 16,
580 Bc1Unorm | Bc1Srgb | Bc4Unorm => 8,
581 Bc3Unorm | Bc3Srgb | Bc5Unorm | Bc7Unorm | Bc7Srgb => 16,
582 }
583 }
584 pub const fn block_dim(self) -> u32 {
586 if self.is_compressed() { 4 } else { 1 }
587 }
588 pub const fn is_compressed(self) -> bool {
589 use Format::*;
590 matches!(self, Bc1Unorm | Bc1Srgb | Bc3Unorm | Bc3Srgb | Bc4Unorm | Bc5Unorm | Bc7Unorm | Bc7Srgb)
591 }
592 pub const fn is_depth(self) -> bool {
593 matches!(self, Format::Depth16 | Format::Depth32Float | Format::Depth24Stencil8 | Format::Depth32FloatStencil8)
594 }
595 pub const fn has_stencil(self) -> bool {
596 matches!(self, Format::Depth24Stencil8 | Format::Depth32FloatStencil8)
597 }
598 pub const fn is_srgb(self) -> bool {
599 matches!(self, Format::Rgba8Srgb | Format::Bgra8Srgb | Format::Bc1Srgb | Format::Bc3Srgb | Format::Bc7Srgb)
600 }
601}
602
603#[derive(Clone, Copy, Debug)]
606pub struct TextureDesc {
607 pub width: u32,
608 pub height: u32,
609 pub depth: u32,
611 pub layers: u32,
613 pub mips: u32,
615 pub format: Format,
616 pub usage: TextureUsage,
617 pub cube: bool,
619}
620
621impl TextureDesc {
622 pub const fn d2(width: u32, height: u32, format: Format, usage: TextureUsage) -> TextureDesc {
624 TextureDesc { width, height, depth: 1, layers: 1, mips: 1, format, usage, cube: false }
625 }
626}
627
628#[derive(Clone, Copy, Debug, PartialEq, Eq)]
630#[non_exhaustive]
631pub enum ViewDim {
632 D2,
633 D2Array,
634 Cube,
635 CubeArray,
636 D3,
637}
638
639#[derive(Clone, Copy, Debug)]
641pub struct ViewDesc {
642 pub dim: ViewDim,
643 pub base_mip: u32,
644 pub mips: u32,
645 pub base_layer: u32,
646 pub layers: u32,
647}
648
649#[derive(Clone, Copy, Debug, PartialEq, Eq)]
651#[non_exhaustive]
652pub enum Layout {
653 Undefined,
656 General,
658 CopySrc,
659 CopyDst,
660 Sampled,
662 ColorTarget,
663 DepthTarget,
664 DepthRead,
666 Present,
668}
669
670#[derive(Clone, Copy, Debug, PartialEq, Eq)]
671#[non_exhaustive]
672pub enum Filter {
673 Nearest,
674 Linear,
675}
676
677#[derive(Clone, Copy, Debug, PartialEq, Eq)]
678#[non_exhaustive]
679pub enum AddressMode {
680 Repeat,
681 MirrorRepeat,
682 ClampToEdge,
683}
684
685#[derive(Clone, Copy, Debug, PartialEq, Eq)]
687#[non_exhaustive]
688pub enum Compare {
689 Never,
690 Less,
691 Equal,
692 LessEqual,
693 Greater,
694 NotEqual,
695 GreaterEqual,
696 Always,
697}
698
699#[derive(Clone, Copy, Debug)]
701pub struct SamplerDesc {
702 pub mag: Filter,
703 pub min: Filter,
704 pub mip: Filter,
705 pub address: [AddressMode; 3],
707 pub anisotropy: u16,
709 pub compare: Option<Compare>,
711 pub lod_min: f32,
712 pub lod_max: f32,
713}
714
715impl SamplerDesc {
716 pub const LINEAR: SamplerDesc = SamplerDesc {
717 mag: Filter::Linear,
718 min: Filter::Linear,
719 mip: Filter::Linear,
720 address: [AddressMode::ClampToEdge; 3],
721 anisotropy: 1,
722 compare: None,
723 lod_min: 0.0,
724 lod_max: 1000.0,
725 };
726 pub const NEAREST: SamplerDesc =
727 SamplerDesc { mag: Filter::Nearest, min: Filter::Nearest, mip: Filter::Nearest, ..SamplerDesc::LINEAR };
728}
729
730#[derive(Clone, Copy, Debug, PartialEq, Eq)]
732#[non_exhaustive]
733pub enum BindingKind {
734 UniformBuffer,
735 StorageBuffer,
737 StorageBufferRead,
739 Texture,
741 StorageTexture,
743 Sampler,
744}
745
746#[derive(Clone, Copy, Debug)]
748pub struct Binding {
749 pub binding: u32,
750 pub kind: BindingKind,
751 pub stages: Stages,
752}
753
754#[derive(Clone, Copy)]
756pub struct PipelineLayoutDesc<'a> {
757 pub groups: &'a [&'a BindGroupLayout],
759 pub push_constants: u32,
761}
762
763#[derive(Clone, Copy)]
765#[non_exhaustive]
766pub enum Resource<'a> {
767 Buffer { buffer: &'a Buffer, offset: u64, size: u64 },
769 Texture(&'a TextureView),
770 StorageTexture(&'a TextureView),
771 Sampler(&'a Sampler),
772}
773
774#[derive(Clone, Copy)]
775pub struct BindEntry<'a> {
776 pub binding: u32,
777 pub resource: Resource<'a>,
778}
779
780#[derive(Clone, Copy)]
782pub struct BindGroupDesc<'a> {
783 pub layout: &'a BindGroupLayout,
784 pub entries: &'a [BindEntry<'a>],
785}
786
787#[derive(Clone, Copy, Debug)]
790pub struct BindlessDesc {
791 pub textures: u32,
792 pub samplers: u32,
793 pub buffers: u32,
794 pub storage_textures: u32,
795}
796
797#[derive(Clone, Copy, Debug, PartialEq)]
805pub struct Constant {
806 pub id: u32,
807 pub value: f64,
808}
809
810#[derive(Clone, Copy)]
812pub struct ShaderStage<'a> {
813 pub module: &'a ShaderModule,
814 pub entry: &'a str,
815 pub constants: &'a [Constant],
817}
818
819impl<'a> ShaderStage<'a> {
820 pub const fn new(module: &'a ShaderModule, entry: &'a str) -> ShaderStage<'a> {
822 ShaderStage { module, entry, constants: &[] }
823 }
824}
825
826#[derive(Clone, Copy)]
828pub struct ComputePipelineDesc<'a> {
829 pub layout: &'a PipelineLayout,
830 pub shader: ShaderStage<'a>,
831}
832
833#[derive(Clone, Copy, Debug, PartialEq, Eq)]
834#[non_exhaustive]
835pub enum Topology {
836 Points,
837 Lines,
838 LineStrip,
839 Triangles,
840 TriangleStrip,
841}
842
843#[derive(Clone, Copy, Debug, PartialEq, Eq)]
844#[non_exhaustive]
845pub enum Cull {
846 None,
847 Front,
848 Back,
849}
850
851#[derive(Clone, Copy, Debug, PartialEq, Eq)]
853#[non_exhaustive]
854pub enum VertexFormat {
855 F32,
856 F32x2,
857 F32x3,
858 F32x4,
859 U32,
860 U32x2,
861 U32x4,
862 Unorm8x4,
864}
865
866#[derive(Clone, Copy, Debug)]
867pub struct VertexAttribute {
868 pub location: u32,
869 pub format: VertexFormat,
870 pub offset: u32,
871}
872
873#[derive(Clone, Copy)]
875pub struct VertexBufferLayout<'a> {
876 pub stride: u32,
877 pub per_instance: bool,
878 pub attributes: &'a [VertexAttribute],
879}
880
881#[derive(Clone, Copy, Debug, PartialEq, Eq)]
882#[non_exhaustive]
883pub enum BlendFactor {
884 Zero,
885 One,
886 Src,
887 OneMinusSrc,
888 Dst,
889 OneMinusDst,
890 SrcAlpha,
891 OneMinusSrcAlpha,
892 DstAlpha,
893 OneMinusDstAlpha,
894}
895
896#[derive(Clone, Copy, Debug, PartialEq, Eq)]
897#[non_exhaustive]
898pub enum BlendOp {
899 Add,
900 Subtract,
901 ReverseSubtract,
902 Min,
903 Max,
904}
905
906#[derive(Clone, Copy, Debug, PartialEq, Eq)]
907pub struct BlendComponent {
908 pub src: BlendFactor,
909 pub dst: BlendFactor,
910 pub op: BlendOp,
911}
912
913#[derive(Clone, Copy, Debug, PartialEq, Eq)]
915pub struct Blend {
916 pub color: BlendComponent,
917 pub alpha: BlendComponent,
918}
919
920impl Blend {
921 pub const PREMULTIPLIED: Blend = Blend {
923 color: BlendComponent { src: BlendFactor::One, dst: BlendFactor::OneMinusSrcAlpha, op: BlendOp::Add },
924 alpha: BlendComponent { src: BlendFactor::One, dst: BlendFactor::OneMinusSrcAlpha, op: BlendOp::Add },
925 };
926 pub const ALPHA: Blend = Blend {
928 color: BlendComponent { src: BlendFactor::SrcAlpha, dst: BlendFactor::OneMinusSrcAlpha, op: BlendOp::Add },
929 alpha: BlendComponent { src: BlendFactor::One, dst: BlendFactor::OneMinusSrcAlpha, op: BlendOp::Add },
930 };
931 pub const ADD: Blend = Blend {
933 color: BlendComponent { src: BlendFactor::One, dst: BlendFactor::One, op: BlendOp::Add },
934 alpha: BlendComponent { src: BlendFactor::One, dst: BlendFactor::One, op: BlendOp::Add },
935 };
936}
937
938#[derive(Clone, Copy, Debug)]
940pub struct ColorTarget {
941 pub format: Format,
942 pub blend: Option<Blend>,
943 pub write_mask: u32,
945}
946
947#[derive(Clone, Copy, Debug)]
949pub struct DepthState {
950 pub format: Format,
951 pub write: bool,
952 pub compare: Compare,
953}
954
955#[derive(Clone, Copy)]
957pub struct RenderPipelineDesc<'a> {
958 pub layout: &'a PipelineLayout,
959 pub vertex: ShaderStage<'a>,
960 pub fragment: Option<ShaderStage<'a>>,
961 pub buffers: &'a [VertexBufferLayout<'a>],
963 pub topology: Topology,
964 pub cull: Cull,
965 pub front_cw: bool,
967 pub targets: &'a [ColorTarget],
968 pub depth: Option<DepthState>,
969}
970
971#[derive(Clone, Copy, Debug, PartialEq, Eq)]
973#[non_exhaustive]
974pub enum Load {
975 Keep,
976 Clear,
977 Discard,
978}
979
980#[derive(Clone, Copy)]
983pub struct ColorAttachment<'a> {
984 pub view: &'a TextureView,
985 pub load: Load,
986 pub clear: [f32; 4],
987 pub store: bool,
988 pub before: Layout,
989 pub after: Layout,
990}
991
992#[derive(Clone, Copy)]
994pub struct DepthAttachment<'a> {
995 pub view: &'a TextureView,
996 pub load: Load,
997 pub clear: f32,
998 pub store: bool,
999 pub before: Layout,
1000 pub after: Layout,
1001}
1002
1003#[derive(Clone, Copy)]
1006pub struct RenderPassDesc<'d, 'a> {
1007 pub color: &'d [ColorAttachment<'a>],
1008 pub depth: Option<DepthAttachment<'a>>,
1009}
1010
1011#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1012#[non_exhaustive]
1013pub enum IndexFormat {
1014 U16,
1015 U32,
1016}
1017
1018#[derive(Clone, Copy)]
1020pub struct TextureRegion<'a> {
1021 pub texture: &'a Texture,
1022 pub mip: u32,
1023 pub origin: [u32; 3],
1024 pub size: [u32; 3],
1025 pub base_layer: u32,
1026 pub layers: u32,
1027}
1028
1029impl<'a> TextureRegion<'a> {
1030 pub fn mip(texture: &'a Texture, mip: u32) -> TextureRegion<'a> {
1032 let s = |v: u32| (v >> mip).max(1);
1033 TextureRegion {
1034 texture,
1035 mip,
1036 origin: [0; 3],
1037 size: [s(texture.width()), s(texture.height()), s(texture.depth())],
1038 base_layer: 0,
1039 layers: texture.layers(),
1040 }
1041 }
1042}
1043
1044#[derive(Clone, Copy, Debug, Default)]
1047pub struct DataLayout {
1048 pub offset: u64,
1049 pub bytes_per_row: u32,
1050 pub rows_per_image: u32,
1051}
1052
1053#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1055pub enum PresentMode {
1056 Fifo,
1058 Mailbox,
1060 Immediate,
1062}
1063
1064#[derive(Clone, Copy, Debug)]
1066pub struct SwapchainDesc {
1067 pub present: PresentMode,
1068 pub srgb: bool,
1070 pub copy_src: bool,
1072 pub frames_in_flight: u32,
1074 pub min_images: u32,
1076}
1077
1078impl SwapchainDesc {
1079 pub const DEFAULT: SwapchainDesc =
1080 SwapchainDesc { present: PresentMode::Fifo, srgb: false, copy_src: false, frames_in_flight: 2, min_images: 0 };
1081}