1#![no_std]
91
92extern crate alloc;
93
94use alloc::string::String;
95
96#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
97mod vk_cmd;
98#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
99mod vk_dev;
100#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
101mod vk_ffi;
102#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
103mod vk_inst;
104#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
105mod vk_load;
106#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
107mod vk_mem;
108#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
109mod vk_res;
110#[cfg(not(any(jfgui_glibc, target_arch = "wasm32", target_vendor = "apple")))]
111mod vk_swap;
112#[cfg(jfgui_glibc)]
114#[path = "vk_dmabuf.rs"]
115mod vk_swap;
116#[cfg(target_arch = "wasm32")]
118mod web_cmd;
119#[cfg(target_arch = "wasm32")]
120mod web_dev;
121#[cfg(target_arch = "wasm32")]
122mod web_res;
123#[cfg(target_arch = "wasm32")]
124mod web_swap;
125#[cfg(target_vendor = "apple")]
127mod mtl_cmd;
128#[cfg(target_vendor = "apple")]
129mod mtl_dev;
130#[cfg(target_vendor = "apple")]
131mod mtl_objc;
132#[cfg(target_vendor = "apple")]
133mod mtl_res;
134#[cfg(target_vendor = "apple")]
135mod mtl_swap;
136
137#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
138pub use vk_cmd::{CommandBuffer, CommandEncoder};
139#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
140pub use vk_dev::{ComputeQueue, Device, Queue};
141#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
142pub use vk_inst::{Adapter, Instance, low_power_rank, validation_messages};
143#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
144pub use vk_res::{BindGroup, BindGroupLayout, Bindless, Buffer, ComputePipeline, PipelineLayout, RenderPipeline, Sampler,
145 ShaderModule, Texture, TextureView, Timestamps};
146#[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
147pub use vk_swap::{Frame, Surface, Swapchain, TryAcquire};
148#[cfg(target_arch = "wasm32")]
149pub use web_cmd::{CommandBuffer, CommandEncoder};
150#[cfg(target_arch = "wasm32")]
151pub use web_dev::{Adapter, ComputeQueue, Device, Instance, Queue, low_power_rank, validation_messages};
152#[cfg(target_arch = "wasm32")]
153pub use web_res::{BindGroup, BindGroupLayout, Bindless, Buffer, ComputePipeline, PipelineLayout, RenderPipeline, Sampler,
154 ShaderModule, Texture, TextureView, Timestamps};
155#[cfg(target_arch = "wasm32")]
156pub use web_swap::{Frame, Surface, Swapchain, TryAcquire};
157#[cfg(target_vendor = "apple")]
158pub use mtl_cmd::{CommandBuffer, CommandEncoder};
159#[cfg(target_vendor = "apple")]
160pub use mtl_dev::{Adapter, ComputeQueue, Device, Instance, Queue, low_power_rank, validation_messages};
161#[cfg(target_vendor = "apple")]
162pub use mtl_res::{BindGroup, BindGroupLayout, Bindless, Buffer, ComputePipeline, PipelineLayout, RenderPipeline, Sampler,
163 ShaderModule, Texture, TextureView, Timestamps};
164#[cfg(target_vendor = "apple")]
165pub use mtl_swap::{Frame, Surface, Swapchain, TryAcquire};
166
167pub type Result<T> = core::result::Result<T, GpuError>;
168
169pub const PUSH_CONSTANTS_MAX: u32 = 128;
171pub const BIND_GROUPS_MAX: u32 = 4;
173pub const COLOR_TARGETS_MAX: usize = 8;
175
176#[derive(Clone, Copy, Debug, PartialEq, Eq)]
178#[non_exhaustive]
179pub enum GpuError {
180 Disabled,
182 NoLoader,
187 NoAdapter,
189 Unsupported(&'static str),
191 Invalid(&'static str),
193 OutOfMemory,
195 DeviceLost,
197 SurfaceLost,
199 Timeout,
201 NotReady,
203 Failed(i32),
205}
206
207impl core::fmt::Display for GpuError {
208 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
209 match self {
210 GpuError::Disabled => f.write_str("GPU disabled (jfgui_GPU=0)"),
211 #[cfg(not(any(target_arch = "wasm32", target_vendor = "apple")))]
212 GpuError::NoLoader => f.write_str("no GPU API installed (Vulkan loader missing)"),
213 #[cfg(target_vendor = "apple")]
215 GpuError::NoLoader => f.write_str("no GPU API installed"),
216 #[cfg(target_arch = "wasm32")]
217 GpuError::NoLoader => f.write_str("no WebGPU in this browser"),
218 GpuError::NoAdapter => f.write_str("no usable GPU"),
219 GpuError::Unsupported(w) => write!(f, "not supported: {w}"),
220 GpuError::Invalid(w) => write!(f, "invalid use: {w}"),
221 GpuError::OutOfMemory => f.write_str("out of GPU or host memory"),
222 GpuError::DeviceLost => f.write_str("GPU device lost"),
223 GpuError::SurfaceLost => f.write_str("window surface lost"),
224 GpuError::Timeout => f.write_str("GPU wait timed out"),
225 GpuError::NotReady => f.write_str("GPU results not ready"),
226 GpuError::Failed(c) => write!(f, "GPU call failed ({c})"),
227 }
228 }
229}
230
231pub unsafe trait Pod: Copy + 'static {}
237unsafe impl Pod for u8 {}
239unsafe impl Pod for i8 {}
241unsafe impl Pod for u16 {}
243unsafe impl Pod for i16 {}
245unsafe impl Pod for u32 {}
247unsafe impl Pod for i32 {}
249unsafe impl Pod for u64 {}
251unsafe impl Pod for i64 {}
253unsafe impl Pod for f32 {}
255unsafe impl Pod for f64 {}
257unsafe impl<T: Pod, const N: usize> Pod for [T; N] {}
259
260pub fn bytes_of<T: Pod>(s: &[T]) -> &[u8] {
262 unsafe { core::slice::from_raw_parts(s.as_ptr() as *const u8, core::mem::size_of_val(s)) }
264}
265
266#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
268#[non_exhaustive]
269pub enum Level {
270 Basis,
272 Voll,
274}
275
276#[derive(Clone, Copy, Debug, PartialEq, Eq)]
278#[non_exhaustive]
279pub enum AdapterKind {
280 Discrete,
281 Integrated,
282 Virtual,
283 Cpu,
284 Other,
285}
286
287#[derive(Clone, Debug)]
289pub struct AdapterInfo {
290 pub name: String,
292 pub vendor_id: u32,
293 pub device_id: u32,
294 pub vendor: &'static str,
296 pub kind: AdapterKind,
297 pub driver: String,
300 pub driver_info: String,
301 pub driver_version: String,
303 pub api_version: (u32, u32, u32),
305 pub backend: &'static str,
307 pub missing: Option<&'static str>,
309}
310
311#[derive(Clone, Copy, Debug, Default)]
313pub struct Features {
314 pub timestamps: bool,
316 pub multi_draw_indirect: bool,
318 pub draw_indirect_first_instance: bool,
320 pub draw_indirect_count: bool,
322 pub bindless: bool,
324 pub subgroups: bool,
326 pub subgroups_webgpu: bool,
329 pub subgroup_stages: u32,
332 pub subgroup_ops: u32,
333 pub subgroup_size_control: bool,
336 pub subgroup_extended_types: bool,
338 pub draw_parameters: bool,
340 pub shader_f16: bool,
341 pub shader_f64: bool,
342 pub shader_i16: bool,
343 pub shader_i64: bool,
344 pub shader_i8: bool,
345 pub storage_16bit: bool,
347 pub uniform_16bit: bool,
349 pub push_constant_16bit: bool,
350 pub uniform_standard_layout: bool,
353 pub demote: bool,
355 pub clip_distances: bool,
358 pub primitive_index: bool,
359 pub sample_shading: bool,
360 pub storage_8bit: bool,
361 pub texture_bc: bool,
363 pub anisotropy: bool,
364 pub depth_clamp: bool,
365 pub vertex_stores: bool,
367 pub fragment_stores: bool,
368 pub storage_write_without_format: bool,
370 pub buffer_address: bool,
372 pub swapchain: bool,
374 pub mesh_shader: bool,
376 pub ray_query: bool,
377 pub ray_pipeline: bool,
378}
379
380pub mod subgroup_stage {
382 pub const COMPUTE: u32 = 1;
383 pub const FRAGMENT: u32 = 2;
384 pub const VERTEX: u32 = 4;
385}
386
387pub mod subgroup_op {
389 pub const BASIC: u32 = 1;
390 pub const VOTE: u32 = 2;
391 pub const ARITHMETIC: u32 = 4;
392 pub const BALLOT: u32 = 8;
393 pub const SHUFFLE: u32 = 0x10;
394 pub const SHUFFLE_RELATIVE: u32 = 0x20;
395 pub const CLUSTERED: u32 = 0x40;
396 pub const QUAD: u32 = 0x80;
397}
398
399#[derive(Clone, Copy, Debug, Default)]
401pub struct Limits {
402 pub max_texture_2d: u32,
403 pub max_texture_3d: u32,
404 pub max_texture_layers: u32,
405 pub max_storage_binding: u32,
407 pub max_uniform_binding: u32,
408 pub max_push_constants: u32,
410 pub max_bind_groups: u32,
411 pub max_compute_workgroup_size: [u32; 3],
412 pub max_compute_invocations: u32,
413 pub max_compute_workgroups: [u32; 3],
414 pub max_compute_shared_memory: u32,
415 pub min_uniform_offset_alignment: u32,
416 pub min_storage_offset_alignment: u32,
417 pub max_color_targets: u32,
418 pub max_vertex_buffers: u32,
419 pub max_vertex_attributes: u32,
420 pub max_draw_indirect_count: u32,
421 pub max_anisotropy: f32,
422 pub timestamp_period_ns: f32,
424 pub subgroup_size: u32,
426 pub subgroup_min_size: u32,
428 pub subgroup_max_size: u32,
429 pub max_bindless_textures: u32,
431 pub max_bindless_samplers: u32,
432 pub max_bindless_buffers: u32,
433 pub max_bindless_storage_textures: u32,
434 pub device_memory: u64,
436}
437
438#[derive(Clone, Copy)]
440pub struct InstanceDesc<'a> {
441 pub app_name: &'a str,
443 pub validate: bool,
445}
446
447impl InstanceDesc<'_> {
448 pub const DEFAULT: InstanceDesc<'static> = InstanceDesc { app_name: "jfgui", validate: false };
449}
450
451#[derive(Clone, Copy)]
453pub struct DeviceDesc {
454 pub max_level: Level,
456}
457
458impl DeviceDesc {
459 pub const DEFAULT: DeviceDesc = DeviceDesc { max_level: Level::Voll };
460}
461
462#[derive(Clone, Copy, Debug, PartialEq, Eq)]
465#[non_exhaustive]
466pub struct DeviceOptions {
467 pub compute_queue: bool,
471}
472
473impl DeviceOptions {
474 pub const DEFAULT: DeviceOptions = DeviceOptions { compute_queue: false };
475
476 pub const fn with_compute_queue(self) -> DeviceOptions {
478 DeviceOptions { compute_queue: true, ..self }
479 }
480}
481
482impl Default for DeviceOptions {
483 fn default() -> DeviceOptions {
484 DeviceOptions::DEFAULT
485 }
486}
487
488#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
490pub struct SubmitId(pub u64);
491
492macro_rules! flags {
493 ($(#[$m:meta])* $name:ident { $( $(#[$fm:meta])* $f:ident = $v:expr ),* $(,)? }) => {
494 $(#[$m])*
495 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
496 pub struct $name(pub u32);
497 impl $name {
498 pub const NONE: $name = $name(0);
499 $( $(#[$fm])* pub const $f: $name = $name($v); )*
500 pub const fn contains(self, o: $name) -> bool {
501 self.0 & o.0 == o.0
502 }
503 pub const fn intersects(self, o: $name) -> bool {
504 self.0 & o.0 != 0
505 }
506 }
507 impl core::ops::BitOr for $name {
508 type Output = $name;
509 fn bitor(self, o: $name) -> $name {
510 $name(self.0 | o.0)
511 }
512 }
513 };
514}
515
516flags! {
517 BufferUsage {
519 UNIFORM = 1,
520 STORAGE = 2,
521 INDEX = 4,
522 VERTEX = 8,
523 INDIRECT = 16,
525 }
526}
527
528flags! {
529 TextureUsage {
531 COPY_SRC = 1,
532 COPY_DST = 2,
533 SAMPLED = 4,
534 STORAGE = 8,
535 COLOR_TARGET = 16,
536 DEPTH_TARGET = 32,
537 }
538}
539
540flags! {
541 Stages {
543 VERTEX = 1,
544 FRAGMENT = 2,
545 COMPUTE = 4,
546 ALL = 7,
547 }
548}
549
550flags! {
551 Access {
554 COPY_READ = 1,
555 COPY_WRITE = 2,
556 COMPUTE_READ = 4,
557 COMPUTE_WRITE = 8,
558 GRAPHICS_READ = 16,
560 GRAPHICS_WRITE = 32,
561 INDIRECT = 64,
563 INDEX_VERTEX = 128,
565 COLOR_TARGET = 256,
566 DEPTH_TARGET = 512,
567 HOST_READ = 1024,
569 HOST_WRITE = 2048,
570 }
571}
572
573#[derive(Clone, Copy, Debug, PartialEq, Eq)]
575#[non_exhaustive]
576pub enum MemoryKind {
577 Device,
579 Upload,
581 Readback,
583}
584
585#[derive(Clone, Copy, Debug)]
587pub struct BufferDesc {
588 pub size: u64,
589 pub usage: BufferUsage,
590 pub memory: MemoryKind,
591}
592
593#[derive(Clone, Copy, Debug, PartialEq, Eq)]
595#[non_exhaustive]
596pub enum Format {
597 R8Unorm,
598 Rg8Unorm,
599 Rgba8Unorm,
600 Rgba8Srgb,
601 Bgra8Unorm,
602 Bgra8Srgb,
603 Rgb10a2Unorm,
604 Rg11b10Float,
605 R16Float,
606 Rg16Float,
607 Rgba16Float,
608 R32Uint,
609 R32Sint,
610 R32Float,
611 Rg32Uint,
612 Rg32Float,
613 Rgba32Uint,
614 Rgba32Float,
615 Depth16,
616 Depth32Float,
617 Depth24Stencil8,
618 Depth32FloatStencil8,
619 Bc1Unorm,
620 Bc1Srgb,
621 Bc3Unorm,
622 Bc3Srgb,
623 Bc4Unorm,
624 Bc5Unorm,
625 Bc7Unorm,
626 Bc7Srgb,
627}
628
629impl Format {
630 pub const fn block_bytes(self) -> u32 {
632 use Format::*;
633 match self {
634 R8Unorm => 1,
635 Rg8Unorm | R16Float | Depth16 => 2,
636 Rgba8Unorm | Rgba8Srgb | Bgra8Unorm | Bgra8Srgb | Rgb10a2Unorm | Rg11b10Float | Rg16Float | R32Uint
637 | R32Sint | R32Float | Depth32Float | Depth24Stencil8 => 4,
638 Rgba16Float | Rg32Uint | Rg32Float | Depth32FloatStencil8 => 8,
639 Rgba32Uint | Rgba32Float => 16,
640 Bc1Unorm | Bc1Srgb | Bc4Unorm => 8,
641 Bc3Unorm | Bc3Srgb | Bc5Unorm | Bc7Unorm | Bc7Srgb => 16,
642 }
643 }
644 pub const fn block_dim(self) -> u32 {
646 if self.is_compressed() { 4 } else { 1 }
647 }
648 pub const fn is_compressed(self) -> bool {
649 use Format::*;
650 matches!(self, Bc1Unorm | Bc1Srgb | Bc3Unorm | Bc3Srgb | Bc4Unorm | Bc5Unorm | Bc7Unorm | Bc7Srgb)
651 }
652 pub const fn is_depth(self) -> bool {
653 matches!(self, Format::Depth16 | Format::Depth32Float | Format::Depth24Stencil8 | Format::Depth32FloatStencil8)
654 }
655 pub const fn has_stencil(self) -> bool {
656 matches!(self, Format::Depth24Stencil8 | Format::Depth32FloatStencil8)
657 }
658 pub const fn is_srgb(self) -> bool {
659 matches!(self, Format::Rgba8Srgb | Format::Bgra8Srgb | Format::Bc1Srgb | Format::Bc3Srgb | Format::Bc7Srgb)
660 }
661}
662
663#[derive(Clone, Copy, Debug)]
666pub struct TextureDesc {
667 pub width: u32,
668 pub height: u32,
669 pub depth: u32,
671 pub layers: u32,
673 pub mips: u32,
675 pub format: Format,
676 pub usage: TextureUsage,
677 pub cube: bool,
679}
680
681impl TextureDesc {
682 pub const fn d2(width: u32, height: u32, format: Format, usage: TextureUsage) -> TextureDesc {
684 TextureDesc { width, height, depth: 1, layers: 1, mips: 1, format, usage, cube: false }
685 }
686}
687
688#[derive(Clone, Copy, Debug, PartialEq, Eq)]
690#[non_exhaustive]
691pub enum ViewDim {
692 D2,
693 D2Array,
694 Cube,
695 CubeArray,
696 D3,
697}
698
699#[derive(Clone, Copy, Debug)]
701pub struct ViewDesc {
702 pub dim: ViewDim,
703 pub base_mip: u32,
704 pub mips: u32,
705 pub base_layer: u32,
706 pub layers: u32,
707}
708
709#[derive(Clone, Copy, Debug, PartialEq, Eq)]
711#[non_exhaustive]
712pub enum Layout {
713 Undefined,
716 General,
718 CopySrc,
719 CopyDst,
720 Sampled,
722 ColorTarget,
723 DepthTarget,
724 DepthRead,
726 Present,
728}
729
730#[derive(Clone, Copy, Debug, PartialEq, Eq)]
731#[non_exhaustive]
732pub enum Filter {
733 Nearest,
734 Linear,
735}
736
737#[derive(Clone, Copy, Debug, PartialEq, Eq)]
738#[non_exhaustive]
739pub enum AddressMode {
740 Repeat,
741 MirrorRepeat,
742 ClampToEdge,
743}
744
745#[derive(Clone, Copy, Debug, PartialEq, Eq)]
747#[non_exhaustive]
748pub enum Compare {
749 Never,
750 Less,
751 Equal,
752 LessEqual,
753 Greater,
754 NotEqual,
755 GreaterEqual,
756 Always,
757}
758
759#[derive(Clone, Copy, Debug)]
761pub struct SamplerDesc {
762 pub mag: Filter,
763 pub min: Filter,
764 pub mip: Filter,
765 pub address: [AddressMode; 3],
767 pub anisotropy: u16,
769 pub compare: Option<Compare>,
771 pub lod_min: f32,
772 pub lod_max: f32,
773}
774
775impl SamplerDesc {
776 pub const LINEAR: SamplerDesc = SamplerDesc {
777 mag: Filter::Linear,
778 min: Filter::Linear,
779 mip: Filter::Linear,
780 address: [AddressMode::ClampToEdge; 3],
781 anisotropy: 1,
782 compare: None,
783 lod_min: 0.0,
784 lod_max: 1000.0,
785 };
786 pub const NEAREST: SamplerDesc =
787 SamplerDesc { mag: Filter::Nearest, min: Filter::Nearest, mip: Filter::Nearest, ..SamplerDesc::LINEAR };
788}
789
790#[derive(Clone, Copy, Debug, PartialEq, Eq)]
792#[non_exhaustive]
793pub enum BindingKind {
794 UniformBuffer,
795 StorageBuffer,
797 StorageBufferRead,
799 Texture,
801 StorageTexture,
803 Sampler,
804}
805
806#[derive(Clone, Copy, Debug)]
808pub struct Binding {
809 pub binding: u32,
810 pub kind: BindingKind,
811 pub stages: Stages,
812}
813
814#[derive(Clone, Copy)]
816pub struct PipelineLayoutDesc<'a> {
817 pub groups: &'a [&'a BindGroupLayout],
819 pub push_constants: u32,
821}
822
823#[derive(Clone, Copy)]
825#[non_exhaustive]
826pub enum Resource<'a> {
827 Buffer { buffer: &'a Buffer, offset: u64, size: u64 },
829 Texture(&'a TextureView),
830 StorageTexture(&'a TextureView),
831 Sampler(&'a Sampler),
832}
833
834#[derive(Clone, Copy)]
835pub struct BindEntry<'a> {
836 pub binding: u32,
837 pub resource: Resource<'a>,
838}
839
840#[derive(Clone, Copy)]
842pub struct BindGroupDesc<'a> {
843 pub layout: &'a BindGroupLayout,
844 pub entries: &'a [BindEntry<'a>],
845}
846
847#[derive(Clone, Copy, Debug)]
850pub struct BindlessDesc {
851 pub textures: u32,
852 pub samplers: u32,
853 pub buffers: u32,
854 pub storage_textures: u32,
855}
856
857#[derive(Clone, Copy, Debug, PartialEq)]
865pub struct Constant {
866 pub id: u32,
867 pub value: f64,
868}
869
870#[derive(Clone, Copy)]
872pub struct ShaderStage<'a> {
873 pub module: &'a ShaderModule,
874 pub entry: &'a str,
875 pub constants: &'a [Constant],
877}
878
879impl<'a> ShaderStage<'a> {
880 pub const fn new(module: &'a ShaderModule, entry: &'a str) -> ShaderStage<'a> {
882 ShaderStage { module, entry, constants: &[] }
883 }
884}
885
886#[derive(Clone, Copy)]
888pub struct ComputePipelineDesc<'a> {
889 pub layout: &'a PipelineLayout,
890 pub shader: ShaderStage<'a>,
891}
892
893#[derive(Clone, Copy, Debug, PartialEq, Eq)]
894#[non_exhaustive]
895pub enum Topology {
896 Points,
897 Lines,
898 LineStrip,
899 Triangles,
900 TriangleStrip,
901}
902
903#[derive(Clone, Copy, Debug, PartialEq, Eq)]
904#[non_exhaustive]
905pub enum Cull {
906 None,
907 Front,
908 Back,
909}
910
911#[derive(Clone, Copy, Debug, PartialEq, Eq)]
913#[non_exhaustive]
914pub enum VertexFormat {
915 F32,
916 F32x2,
917 F32x3,
918 F32x4,
919 U32,
920 U32x2,
921 U32x4,
922 Unorm8x4,
924}
925
926#[derive(Clone, Copy, Debug)]
927pub struct VertexAttribute {
928 pub location: u32,
929 pub format: VertexFormat,
930 pub offset: u32,
931}
932
933#[derive(Clone, Copy)]
935pub struct VertexBufferLayout<'a> {
936 pub stride: u32,
937 pub per_instance: bool,
938 pub attributes: &'a [VertexAttribute],
939}
940
941#[derive(Clone, Copy, Debug, PartialEq, Eq)]
942#[non_exhaustive]
943pub enum BlendFactor {
944 Zero,
945 One,
946 Src,
947 OneMinusSrc,
948 Dst,
949 OneMinusDst,
950 SrcAlpha,
951 OneMinusSrcAlpha,
952 DstAlpha,
953 OneMinusDstAlpha,
954}
955
956#[derive(Clone, Copy, Debug, PartialEq, Eq)]
957#[non_exhaustive]
958pub enum BlendOp {
959 Add,
960 Subtract,
961 ReverseSubtract,
962 Min,
963 Max,
964}
965
966#[derive(Clone, Copy, Debug, PartialEq, Eq)]
967pub struct BlendComponent {
968 pub src: BlendFactor,
969 pub dst: BlendFactor,
970 pub op: BlendOp,
971}
972
973#[derive(Clone, Copy, Debug, PartialEq, Eq)]
975pub struct Blend {
976 pub color: BlendComponent,
977 pub alpha: BlendComponent,
978}
979
980impl Blend {
981 pub const PREMULTIPLIED: Blend = Blend {
983 color: BlendComponent { src: BlendFactor::One, dst: BlendFactor::OneMinusSrcAlpha, op: BlendOp::Add },
984 alpha: BlendComponent { src: BlendFactor::One, dst: BlendFactor::OneMinusSrcAlpha, op: BlendOp::Add },
985 };
986 pub const ALPHA: Blend = Blend {
988 color: BlendComponent { src: BlendFactor::SrcAlpha, dst: BlendFactor::OneMinusSrcAlpha, op: BlendOp::Add },
989 alpha: BlendComponent { src: BlendFactor::One, dst: BlendFactor::OneMinusSrcAlpha, op: BlendOp::Add },
990 };
991 pub const ADD: Blend = Blend {
993 color: BlendComponent { src: BlendFactor::One, dst: BlendFactor::One, op: BlendOp::Add },
994 alpha: BlendComponent { src: BlendFactor::One, dst: BlendFactor::One, op: BlendOp::Add },
995 };
996}
997
998#[derive(Clone, Copy, Debug)]
1000pub struct ColorTarget {
1001 pub format: Format,
1002 pub blend: Option<Blend>,
1003 pub write_mask: u32,
1005}
1006
1007#[derive(Clone, Copy, Debug)]
1009pub struct DepthState {
1010 pub format: Format,
1011 pub write: bool,
1012 pub compare: Compare,
1013}
1014
1015#[derive(Clone, Copy)]
1017pub struct RenderPipelineDesc<'a> {
1018 pub layout: &'a PipelineLayout,
1019 pub vertex: ShaderStage<'a>,
1020 pub fragment: Option<ShaderStage<'a>>,
1021 pub buffers: &'a [VertexBufferLayout<'a>],
1023 pub topology: Topology,
1024 pub cull: Cull,
1025 pub front_cw: bool,
1027 pub targets: &'a [ColorTarget],
1028 pub depth: Option<DepthState>,
1029}
1030
1031#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1033#[non_exhaustive]
1034pub enum Load {
1035 Keep,
1036 Clear,
1037 Discard,
1038}
1039
1040#[derive(Clone, Copy)]
1043pub struct ColorAttachment<'a> {
1044 pub view: &'a TextureView,
1045 pub load: Load,
1046 pub clear: [f32; 4],
1047 pub store: bool,
1048 pub before: Layout,
1049 pub after: Layout,
1050}
1051
1052#[derive(Clone, Copy)]
1054pub struct DepthAttachment<'a> {
1055 pub view: &'a TextureView,
1056 pub load: Load,
1057 pub clear: f32,
1058 pub store: bool,
1059 pub before: Layout,
1060 pub after: Layout,
1061}
1062
1063#[derive(Clone, Copy)]
1066pub struct RenderPassDesc<'d, 'a> {
1067 pub color: &'d [ColorAttachment<'a>],
1068 pub depth: Option<DepthAttachment<'a>>,
1069}
1070
1071#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1072#[non_exhaustive]
1073pub enum IndexFormat {
1074 U16,
1075 U32,
1076}
1077
1078#[derive(Clone, Copy)]
1080pub struct TextureRegion<'a> {
1081 pub texture: &'a Texture,
1082 pub mip: u32,
1083 pub origin: [u32; 3],
1084 pub size: [u32; 3],
1085 pub base_layer: u32,
1086 pub layers: u32,
1087}
1088
1089impl<'a> TextureRegion<'a> {
1090 pub fn mip(texture: &'a Texture, mip: u32) -> TextureRegion<'a> {
1092 let s = |v: u32| (v >> mip).max(1);
1093 TextureRegion {
1094 texture,
1095 mip,
1096 origin: [0; 3],
1097 size: [s(texture.width()), s(texture.height()), s(texture.depth())],
1098 base_layer: 0,
1099 layers: texture.layers(),
1100 }
1101 }
1102}
1103
1104#[derive(Clone, Copy, Debug, Default)]
1107pub struct DataLayout {
1108 pub offset: u64,
1109 pub bytes_per_row: u32,
1110 pub rows_per_image: u32,
1111}
1112
1113#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1115pub enum PresentMode {
1116 Fifo,
1118 Mailbox,
1120 Immediate,
1122}
1123
1124#[derive(Clone, Copy, Debug)]
1126pub struct SwapchainDesc {
1127 pub present: PresentMode,
1128 pub srgb: bool,
1130 pub copy_src: bool,
1132 pub frames_in_flight: u32,
1134 pub min_images: u32,
1136}
1137
1138impl SwapchainDesc {
1139 pub const DEFAULT: SwapchainDesc =
1140 SwapchainDesc { present: PresentMode::Fifo, srgb: false, copy_src: false, frames_in_flight: 2, min_images: 0 };
1141}