hotline_rs/gfx.rs
1use crate::os;
2use std::any::Any;
3use serde::{Deserialize, Serialize};
4use std::hash::Hash;
5use maths_rs::max;
6
7/// Implemets this interface with a Direct3D12 backend.
8#[cfg(target_os = "windows")]
9pub mod d3d12;
10
11type Error = super::Error;
12
13/// Macro to pass data!\[expression\] or data!\[\] (None) to a create function, so you don't have to deduce a 'T'.
14#[macro_export]
15macro_rules! data {
16 () => {
17 None::<&[()]>
18 };
19 ($input:expr) => {
20 Some($input)
21 }
22}
23
24/// Macro to inject debug names into gpu resources
25#[cfg(target_os = "windows")]
26#[macro_export]
27macro_rules! gfx_debug_name {
28 ($object:expr, $name:expr) => {
29 d3d12_debug_name($object, $name);
30 }
31}
32
33/// 3-Dimensional struct for compute shader thread count / thread group size.
34#[derive(Copy, Clone)]
35pub struct Size3 {
36 pub x: u32,
37 pub y: u32,
38 pub z: u32,
39}
40
41/// 3-Dimensional region used for copying resources
42#[derive(Copy, Clone)]
43pub struct Region {
44 pub left: u32,
45 pub top: u32,
46 pub front: u32,
47 pub right: u32,
48 pub bottom: u32,
49 pub back: u32
50}
51
52/// Structure to specify viewport coordinates on a `CmdBuf`.
53#[derive(Copy, Clone)]
54pub struct Viewport {
55 /// Top left x coordinate.
56 pub x: f32,
57 /// Top left y coordinate.
58 pub y: f32,
59 /// Width of the viewport rectangle.
60 pub width: f32,
61 /// Height of the viewport rectangle (Y is down).
62 pub height: f32,
63 /// Minimum depth of the viewport. Ranges between 0 and 1.
64 pub min_depth: f32,
65 /// Maximum depth of the viewport. Ranges between 0 and 1.
66 pub max_depth: f32,
67}
68
69/// Structure to specify scissor rect coordinates on a `CmdBuf`.
70#[derive(Copy, Clone)]
71pub struct ScissorRect {
72 // Left x coordinate.
73 pub left: i32,
74 // Top y coordinate.
75 pub top: i32,
76 /// Right x coordinate.
77 pub right: i32,
78 /// Bottom y coordinate.
79 pub bottom: i32,
80}
81
82/// Format for resource types (textures / buffers).
83/// n = normalised unsigned integer,
84/// u = unsigned integer,
85/// i = signed integer,
86/// f = float
87#[derive(Copy, Clone, Serialize, Deserialize, Hash, PartialEq)]
88pub enum Format {
89 Unknown,
90 R16n,
91 R16u,
92 R16i,
93 R16f,
94 R32u,
95 R32i,
96 R32f,
97 RG16f,
98 RG16u,
99 RG16i,
100 RG32u,
101 RG32i,
102 RG32f,
103 RGB32u,
104 RGB32i,
105 RGB32f,
106 RGBA8nSRGB,
107 RGBA8n,
108 RGBA8u,
109 RGBA8i,
110 BGRA8n,
111 BGRX8n,
112 BGRA8nSRGB,
113 BGRX8nSRGB,
114 RGBA16u,
115 RGBA16i,
116 RGBA16f,
117 RGBA32u,
118 RGBA32i,
119 RGBA32f,
120 D32fS8X24u,
121 D32f,
122 D24nS8u,
123 D16n,
124 BC1n,
125 BC1nSRGB,
126 BC2n,
127 BC2nSRGB,
128 BC3n,
129 BC3nSRGB,
130 BC4n,
131 BC5n,
132}
133
134/// Information to create a device, it contains default heaps for resource views
135/// resources will be automatically allocated into these heaps, you can supply custom heaps if necessary.
136#[derive(Default)]
137pub struct DeviceInfo {
138 /// optional adapter to choose a specific adapter in the scenario of a multi-adapter system
139 /// if None is supplied the first non-software emulation adapter would be selected.
140 pub adapter_name: Option<String>,
141 /// space for shader resource views, constant buffers and unordered access views.
142 pub shader_heap_size: usize,
143 /// space for colour render targets.
144 pub render_target_heap_size: usize,
145 /// space for depth stencil targets.
146 pub depth_stencil_heap_size: usize,
147}
148
149/// Information returned from `Device::get_adapter_info`.
150#[derive(Clone)]
151pub struct AdapterInfo {
152 /// The chosen adapter a device was created with.
153 pub name: String,
154 /// Description of the device.
155 pub description: String,
156 /// Dedicated video memory in bytes.
157 pub dedicated_video_memory: usize,
158 /// Dedicated system memory in bytes.
159 pub dedicated_system_memory: usize,
160 /// Shared system memory in bytes.
161 pub shared_system_memory: usize,
162 /// List of available adapter descriptons.
163 pub available: Vec<String>,
164}
165
166/// Information to create a desciptor heap... `Device` will contain default heaps, but you can create your own if required.
167pub struct HeapInfo {
168 /// ie: Shader, RenderTarget, DepthStencil, Sampler.
169 pub heap_type: HeapType,
170 /// Total size of the heap in number of resources.
171 pub num_descriptors: usize,
172}
173
174/// Options for heap types.
175#[derive(Copy, Clone, PartialEq, Eq)]
176pub enum HeapType {
177 /// For shader resource view, constant buffer or unordered access.
178 Shader,
179 /// For render targets
180 RenderTarget,
181 /// For depth stencil targets
182 DepthStencil,
183 /// For sampler states
184 Sampler,
185}
186
187/// Allows user specified heaps to be used for creating views when creating textures through `create_texture_with_heap`
188/// you can supply `None` for the heap types are not applicable and if a view is requested for a `None` heap the
189/// default device heaps will be used instead
190pub struct TextureHeapInfo<'stack, D: Device> {
191 /// Heap to allocate shader resource views and un-ordered access views
192 pub shader: Option<&'stack mut D::Heap>,
193 /// Heap to allocate render target views
194 pub render_target: Option<&'stack mut D::Heap>,
195 /// Heap to allocate depth stencil views
196 pub depth_stencil: Option<&'stack mut D::Heap>,
197}
198
199/// Information to create a query heap.
200pub struct QueryHeapInfo {
201 /// ie: Timestamp, Occlusion, PipelineStatistics
202 pub heap_type: QueryType,
203 /// Total size of the heap in number of queries.
204 pub num_queries: usize,
205}
206
207/// Options for query heap types, and queries
208#[derive(Copy, Clone, PartialEq, Eq)]
209pub enum QueryType {
210 /// Used for occlusion query heap or occlusion queries
211 Occlusion,
212 /// Can be used in the same heap as occlusion
213 BinaryOcclusion,
214 /// Create a heap to contain timestamp queries
215 Timestamp,
216 /// Create a heap to contain a structure of `PipelineStatistics`
217 PipelineStatistics,
218 /// Create video decoder statistics query and heap
219 VideoDecodeStatistics,
220}
221
222/// GPU pipeline statistics obtain by using a `PipelineStatistics` query
223pub struct PipelineStatistics {
224 pub input_assembler_vertices: u64,
225 pub input_assembler_primitives: u64,
226 pub vertex_shader_invocations: u64,
227 pub pixel_shader_primitives: u64,
228 pub compute_shader_invocations: u64
229}
230
231/// Information to pass to `Device::create_swap_chain`.
232pub struct SwapChainInfo {
233 /// Number of internal buffers to keep behind the scenes, which are swapped between each frame
234 /// to allow overlapped CPU/GPU command buffer producer / consumer
235 pub num_buffers: u32,
236 /// Must be BGRA8n, RGBA8n or RGBA16f.
237 pub format: Format,
238 /// Colour for clearing the window when using the backbuffer pass, use None to not clear.
239 pub clear_colour: Option<ClearColour>,
240}
241
242/// Information to create a buffer through `Device::create_buffer`.
243#[derive(Copy, Clone)]
244pub struct BufferInfo {
245 /// Indicates how the buffer will be used on the GPU.
246 pub usage: BufferUsage,
247 /// Used to indicate if we want to read or write from the CPU, use NONE if possible for best performance.
248 pub cpu_access: CpuAccessFlags,
249 /// Data format of the buffer this is is only required for index buffers and can be `gfx::Format::Unknown` otherwise
250 pub format: Format,
251 /// The stride of a vertex or structure in bytes.
252 pub stride: usize,
253 /// The number of array elements.
254 pub num_elements: usize,
255 /// Initial state to start image transition barriers before state
256 pub initial_state: ResourceState,
257}
258
259/// Information to create a shader through `Device::create_shader`.
260pub struct ShaderInfo {
261 /// Type of the shader (Vertex, Fragment, Compute, etc...).
262 pub shader_type: ShaderType,
263 /// Optional info to compile from source, if this is none then
264 /// the shader will be treated as a precompiled byte code blob.
265 pub compile_info: Option<ShaderCompileInfo>,
266}
267
268/// Information required to compile a shader from source code.
269pub struct ShaderCompileInfo {
270 /// The name of the entry point function in the shader to compile.
271 pub entry_point: String,
272 /// The target you wish to compile for, this is paltform specific.
273 /// hlsl: (vs_5_0, ps_5_0, vs_6_0, ps_6_0).
274 pub target: String,
275 /// Flags to pass to the compiler.
276 pub flags: ShaderCompileFlags,
277}
278
279/// The stage to which a shader will bind itself.
280#[derive(Copy, Clone)]
281pub enum ShaderType {
282 Vertex,
283 Fragment,
284 Compute,
285}
286
287bitflags! {
288 /// Device feature flags.
289 pub struct DeviceFeatureFlags: u32 {
290 const NONE = 0;
291 const RAYTRACING = 1<<0;
292 const MESH_SAHDER = 1<<1;
293 }
294
295 /// Shader compilation flags.
296 pub struct ShaderCompileFlags: u32 {
297 /// No flags, default compilation.
298 const NONE = 0b00000000;
299 /// Generates shader with debug info
300 const DEBUG = 0b00000001;
301 /// Skips optimization for easier debuggability, deterministic results and faster compilation.
302 const SKIP_OPTIMIZATION = 0b00000010;
303 }
304
305 /// Render target write mask flags.
306 #[derive(Serialize, Deserialize)]
307 pub struct WriteMask : u8 {
308 // Write no colour channels
309 const NONE = 0;
310 /// Write the red colour channel
311 const RED = 1<<0;
312 /// Write the green colour channel
313 const GREEN = 1<<1;
314 /// Write the blue colour channel
315 const BLUE = 1<<2;
316 /// Write the alpha channel
317 const ALPHA = 1<<3;
318 /// Write (RED|GREEN|BLUE|ALPHA)
319 const ALL = (1<<4)-1;
320 }
321
322 /// CPU Access flags for buffers or textures.
323 pub struct CpuAccessFlags: u8 {
324 /// No CPUT access required, use this for best performance if you do not need to write data to a resource
325 const NONE = 1<<0;
326 /// CPU will read data from the resource
327 const READ = 1<<1;
328 /// CPU will write data to the resourc
329 const WRITE = 1<<2;
330 /// Must be used in conjunction with READ or WRITE, the resource will mapped once and never un-mapped
331 const PERSISTENTLY_MAPPED = 1<<3;
332 }
333
334 /// Textures can be used in one or more of the following ways
335 #[derive(Serialize, Deserialize)]
336 pub struct TextureUsage: u32 {
337 /// Texture will be only used for data storage and not used on any GPU pipeline stages
338 const NONE = 0;
339 /// Texture will be sampled in a shader
340 const SHADER_RESOURCE = (1 << 0);
341 /// Used as a read-writable resource in compute shaders
342 const UNORDERED_ACCESS = (1 << 1);
343 /// Used as a colour render target
344 const RENDER_TARGET = (1 << 2);
345 /// Used as a depth stencil buffer
346 const DEPTH_STENCIL = (1 << 3);
347 /// Used as a target for hardware assisted video decoding operations
348 const VIDEO_DECODE_TARGET = (1 << 4);
349 /// Indicates the texture will have mip-maps generated at run time
350 const GENERATE_MIP_MAPS = (1 << 5);
351 }
352
353 /// Describes how a buffer will be used on the GPU.
354 //#[derive(Copy, Clone, PartialEq)]
355 pub struct BufferUsage : u32 {
356 /// Used to simply store data (query results, copy buffers etc)
357 const NONE = 0;
358 /// Used as a Vertex buffer binding
359 const VERTEX = (1 << 0);
360 /// Used as a Vertex buffer binding
361 const INDEX = (1 << 1);
362 /// Used as constant buffer for shader data
363 const CONSTANT_BUFFER = (1 << 2);
364 /// Texture will be sampled in a shader
365 const SHADER_RESOURCE = (1 << 3);
366 /// Used as a read-writable resource in compute shaders
367 const UNORDERED_ACCESS = (1 << 4);
368 /// Used as indirect arguments for `execute_indirect`
369 const INDIRECT_ARGUMENT_BUFFER = (1 << 5);
370 /// Used in shader as `AppendStructuredBuffer` and contains a counter element
371 const APPEND_COUNTER = (1 << 6);
372 }
373}
374
375/// `PipelineLayout` is required to create a pipeline it describes the layout of resources for access on the GPU.
376#[derive(Default, Clone, Serialize, Deserialize)]
377pub struct PipelineLayout {
378 /// Vector of `DescriptorBinding` which are arrays of textures, samplers or structured buffers, etc
379 pub bindings: Option<Vec<DescriptorBinding>>,
380 /// Small amounts of data that can be pushed into a command buffer and available as data in shaders
381 pub push_constants: Option<Vec<PushConstantInfo>>,
382 /// Static samplers that come along with the pipeline,
383 pub static_samplers: Option<Vec<SamplerBinding>>,
384}
385
386/// Describes a range of resources for access on the GPU.
387#[derive(Clone, Serialize, Deserialize)]
388pub struct DescriptorBinding {
389 /// The shader stage the resources will be accessible to.
390 pub visibility: ShaderVisibility,
391 /// Register index to bind to (supplied in shader).
392 pub shader_register: u32,
393 /// Register space to bind to (supplied in shader).
394 pub register_space: u32,
395 /// Type of resources in this descriptor binding.
396 pub binding_type: DescriptorType,
397 /// Number of descriptors in this table, use `None` for unbounded.
398 pub num_descriptors: Option<u32>,
399}
400
401/// Describes the type of descriptor binding to create.
402#[derive(Clone, Copy, Serialize, Deserialize, Hash)]
403pub enum DescriptorType {
404 /// Used for textures or structured buffers.
405 ShaderResource,
406 /// Used for cbuffers.
407 ConstantBuffer,
408 /// Used for read-write textures.
409 UnorderedAccess,
410 /// Used for texture samplers.
411 Sampler,
412 /// Used for push constants
413 PushConstants
414}
415
416/// Describes the visibility of which shader stages can access a descriptor.
417#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Default)]
418pub enum ShaderVisibility {
419 #[default]
420 All,
421 Vertex,
422 Fragment,
423 Compute,
424}
425
426/// Describes space in the shader to send data to via `CmdBuf::push_constants`.
427#[derive(Clone, Serialize, Deserialize)]
428pub struct PushConstantInfo {
429 /// The shader stage the constants will be accessible to.
430 pub visibility: ShaderVisibility,
431 /// Register index to bind to (supplied in shader).
432 pub shader_register: u32,
433 /// Register space to bind to (supplied in shader).
434 pub register_space: u32,
435 /// Number of 32-bit values to push.
436 pub num_values: u32,
437}
438
439/// You can request this based on resource type, register and space (as specified in shader)
440#[derive(Clone)]
441pub struct PipelineSlotInfo {
442 /// The slot in the pipeline layout to bind to
443 pub index: u32,
444 /// The number of descriptors or the number of 32-bit push constant values, if `None` the table is unbounded
445 pub count: Option<u32>
446}
447
448/// Input layout describes the layout of vertex buffers bound to the input assembler.
449pub type InputLayout = Vec<InputElementInfo>;
450
451/// Describe a single element of an `InputLayoutInfo`.
452#[derive(Clone, Serialize, Deserialize)]
453pub struct InputElementInfo {
454 /// Element semantic ie. POSITION, TEXCOORD, COLOR etc.
455 pub semantic: String,
456 /// Index of the semantic ie. TEXCOORD0, TEXCOORD1 etc.
457 pub index: u32,
458 /// Format of the element size and width.
459 pub format: Format,
460 /// The vertex buffer slot this buffer will be bound to.
461 pub input_slot: u32,
462 /// Aligned byte offset of this element from the start of the struct.
463 pub aligned_byte_offset: u32,
464 /// Vertex or Instance stride.
465 pub input_slot_class: InputSlotClass,
466 /// Rate at which to step vertices.
467 pub step_rate: u32,
468}
469
470/// Describes the frequency of which elements are fetched from a vertex input element.
471#[derive(Clone, Serialize, Deserialize)]
472pub enum InputSlotClass {
473 PerVertex,
474 PerInstance,
475}
476
477/// Individual sampler state binding for use in static samplers in a `PipelineLayout`.
478#[derive(Copy, Clone, Serialize, Deserialize)]
479pub struct SamplerBinding {
480 /// The shader stage the sampler will be accessible to
481 pub visibility: ShaderVisibility,
482 /// Register index to bind to (supplied in shader)
483 pub shader_register: u32,
484 /// Register space to bind to (supplied in shader)
485 pub register_space: u32,
486 /// Sampler Info
487 pub sampler_info: SamplerInfo
488}
489
490/// Info to create a sampler state object to sample textures in shaders.
491#[derive(Copy, Clone, Serialize, Deserialize)]
492pub struct SamplerInfo {
493 pub filter: SamplerFilter,
494 pub address_u: SamplerAddressMode,
495 pub address_v: SamplerAddressMode,
496 pub address_w: SamplerAddressMode,
497 pub comparison: Option<ComparisonFunc>,
498 /// Colour is rgba8 packed into a u32
499 pub border_colour: Option<u32>,
500 pub mip_lod_bias: f32,
501 pub max_aniso: u32,
502 pub min_lod: f32,
503 pub max_lod: f32,
504}
505
506/// Filtering mode for the sampler (controls bilinear and trilinear interpolation).
507#[derive(Copy, Clone, Serialize, Deserialize)]
508pub enum SamplerFilter {
509 Point,
510 Linear,
511 Anisotropic,
512}
513
514/// Address mode for the sampler (controls wrapping and clamping).
515#[derive(Copy, Clone, Serialize, Deserialize)]
516pub enum SamplerAddressMode {
517 Wrap,
518 Mirror,
519 Clamp,
520 Border,
521 MirrorOnce,
522}
523
524/// Used for comparison ops in depth testing, samplers.
525#[derive(Copy, Clone, Serialize, Deserialize)]
526pub enum ComparisonFunc {
527 Never,
528 Less,
529 Equal,
530 LessEqual,
531 Greater,
532 NotEqual,
533 GreaterEqual,
534 Always,
535}
536
537/// Information to create a pipeline through `Device::create_render_pipeline`.
538pub struct RenderPipelineInfo<'stack, D: Device> {
539 /// Vertex Shader
540 pub vs: Option<&'stack D::Shader>,
541 /// Fragment Shader
542 pub fs: Option<&'stack D::Shader>,
543 /// Vertex shader input layout
544 pub input_layout: InputLayout,
545 /// Layout of shader resources (constant buffers, structured buffers, textures, etc)
546 pub pipeline_layout: PipelineLayout,
547 /// Control rasterisation of primitives
548 pub raster_info: RasterInfo,
549 /// Control depth test and stencil oprations
550 pub depth_stencil_info: DepthStencilInfo,
551 /// Control blending settings for the output merge stage
552 pub blend_info: BlendInfo,
553 /// Primitive topolgy oof the input assembler
554 pub topology: Topology,
555 /// Only required for Topology::PatchList use 0 as default
556 pub patch_index: u32,
557 /// Sample mask for which MSAA samples to write
558 pub sample_mask: u32,
559 /// A valid render pass, you can share pipelines across passes providing the render target
560 /// formats and sample count are the same of the passes you wish to use the pipeline on
561 pub pass: Option<&'stack D::RenderPass>,
562}
563
564/// Indicates how the pipeline interprets vertex data at the input assembler stage
565/// This will be also used to infer primitive topology types for geometry or hull shaders
566#[derive(Copy, Clone, Serialize, Deserialize)]
567pub enum Topology {
568 Undefined,
569 PointList,
570 LineList,
571 LineStrip,
572 TriangleList,
573 TriangleStrip,
574 LineListAdj,
575 LineStripAdj,
576 TriangleListAdj,
577 TriangleStripAdj,
578 PatchList,
579}
580
581/// Information to control the rasterisation mode of primitives when using a `RenderPipeline`
582#[derive(Clone, Copy, Serialize, Deserialize)]
583pub struct RasterInfo {
584 pub fill_mode: FillMode,
585 pub cull_mode: CullMode,
586 pub front_ccw: bool,
587 pub depth_bias: i32,
588 pub depth_bias_clamp: f32,
589 pub slope_scaled_depth_bias: f32,
590 pub depth_clip_enable: bool,
591 pub multisample_enable: bool,
592 pub antialiased_line_enable: bool,
593 pub forced_sample_count: u32,
594 pub conservative_raster_mode: bool,
595}
596
597/// Polygon fillmode
598#[derive(Clone, Copy, Serialize, Deserialize)]
599pub enum FillMode {
600 Wireframe,
601 Solid,
602}
603
604/// Polygon cull mode
605#[derive(Clone, Copy, Serialize, Deserialize)]
606pub enum CullMode {
607 None,
608 Front,
609 Back,
610}
611
612/// Information to control the depth and stencil testing of primitves when using a `RenderPipeline`
613#[derive(Clone, Copy, Serialize, Deserialize)]
614pub struct DepthStencilInfo {
615 /// Enable depth testing
616 pub depth_enabled: bool,
617 /// Choose to write or not write to the depth buffer
618 pub depth_write_mask: DepthWriteMask,
619 pub depth_func: ComparisonFunc,
620 /// Enable stencil testing
621 pub stencil_enabled: bool,
622 pub stencil_read_mask: u8,
623 pub stencil_write_mask: u8,
624 pub front_face: StencilInfo,
625 pub back_face: StencilInfo,
626}
627
628/// Write to the depth buffer, or omit writes and just perform depth testing
629#[derive(Clone, Copy, Serialize, Deserialize)]
630pub enum DepthWriteMask {
631 Zero,
632 All,
633}
634
635/// Stencil info for various outcomes of the depth stencil test
636#[derive(Clone, Copy, Serialize, Deserialize)]
637pub struct StencilInfo {
638 pub fail: StencilOp,
639 pub depth_fail: StencilOp,
640 pub pass: StencilOp,
641 pub func: ComparisonFunc,
642}
643
644/// Stencil operations
645#[derive(Clone, Copy, Serialize, Deserialize)]
646pub enum StencilOp {
647 Keep,
648 Zero,
649 Replace,
650 IncrSat,
651 DecrSat,
652 Invert,
653 Incr,
654 Decr,
655}
656
657/// Information to control blending operations on render targets
658#[derive(Default)]
659pub struct BlendInfo {
660 pub alpha_to_coverage_enabled: bool,
661 /// Separate blending on colour and alpha channels
662 pub independent_blend_enabled: bool,
663 /// Separate blend operations for each bout render targets
664 pub render_target: Vec<RenderTargetBlendInfo>,
665}
666
667/// Blending operations for a single render target
668#[derive(Clone, Serialize, Deserialize)]
669pub struct RenderTargetBlendInfo {
670 pub blend_enabled: bool,
671 pub logic_op_enabled: bool,
672 pub src_blend: BlendFactor,
673 pub dst_blend: BlendFactor,
674 pub blend_op: BlendOp,
675 pub src_blend_alpha: BlendFactor,
676 pub dst_blend_alpha: BlendFactor,
677 pub blend_op_alpha: BlendOp,
678 pub logic_op: LogicOp,
679 pub write_mask: WriteMask,
680}
681
682/// Controls how the source and destination terms in blend equation are derrived
683#[derive(Clone, Copy, Serialize, Deserialize)]
684pub enum BlendFactor {
685 Zero,
686 One,
687 SrcColour,
688 InvSrcColour,
689 SrcAlpha,
690 InvSrcAlpha,
691 DstAlpha,
692 InvDstAlpha,
693 DstColour,
694 InvDstColour,
695 SrcAlphaSat,
696 BlendFactor,
697 InvBlendFactor,
698 Src1Colour,
699 InvSrc1Colour,
700 Src1Alpha,
701 InvSrc1Alpha,
702}
703
704/// Controls how the source and destination terms are combined: final = src (op) dest
705#[derive(Clone, Copy, Serialize, Deserialize)]
706pub enum BlendOp {
707 Add,
708 Subtract,
709 RevSubtract,
710 Min,
711 Max,
712}
713
714/// The logical operation to configure for a render target blend with logic op enabled
715#[derive(Clone, Copy, Serialize, Deserialize)]
716pub enum LogicOp {
717 Clear,
718 Set,
719 Copy,
720 CopyInverted,
721 NoOp,
722 Invert,
723 And,
724 Nand,
725 Or,
726 Nor,
727 Xor,
728 Equiv,
729 AndReverse,
730 AndInverted,
731 OrReverse,
732 OrInverted,
733}
734
735/// Information to create a compute pipeline through `Device::create_compute_pipeline`
736pub struct ComputePipelineInfo<'stack, D: Device> {
737 /// Compute Shader
738 pub cs: &'stack D::Shader,
739 /// Describe the layout of resources we bind on the pipeline
740 pub pipeline_layout: PipelineLayout,
741}
742
743/// Information to create a pipeline through `Device::create_texture`.
744#[derive(Copy, Clone)]
745pub struct TextureInfo {
746 /// Texture type
747 pub tex_type: TextureType,
748 /// Texture format
749 pub format: Format,
750 /// Width of the image in texels
751 pub width: u64,
752 /// Height of the image in texels for `TextureType::Texture2D` and `Texture3D` use 1 for `Texture1D`
753 pub height: u64,
754 /// Depth of the image in slices of (`width` x `height`) for `TextureType::Texture3D` only (use 1 other wise)
755 pub depth: u32,
756 /// Number of array levels or slices for `Texture1D` or `Texture2D` arrays. use 1 otherwise
757 pub array_layers: u32,
758 /// Number of mip levels in the image
759 pub mip_levels: u32,
760 /// Number of MSAA samples
761 pub samples: u32,
762 /// Indicate how this texture will be used on the GPU
763 pub usage: TextureUsage,
764 /// Initial state to start image transition barriers before state
765 pub initial_state: ResourceState,
766}
767
768/// Describes the dimension of a texture
769#[derive(Copy, Clone, Debug)]
770pub enum TextureType {
771 Texture1D,
772 Texture1DArray,
773 Texture2D,
774 Texture2DArray,
775 Texture3D,
776 TextureCube,
777 TextureCubeArray
778}
779
780/// Values to clear colour render targets at the start of a `RenderPass`
781#[derive(Copy, Clone)]
782pub struct ClearColour {
783 pub r: f32,
784 pub g: f32,
785 pub b: f32,
786 pub a: f32,
787}
788
789/// Values to clear depth stencil buffers during a `RenderPass`
790pub struct ClearDepthStencil {
791 /// Clear value for the depth buffer. Use `None` to preserve existing contents.
792 pub depth: Option<f32>,
793 /// Clear value for the stencil buffer. Use `None` to preserve existing contents.
794 pub stencil: Option<u8>,
795}
796
797/// Information to create a render pass
798pub struct RenderPassInfo<'stack, D: Device> {
799 /// Array of textures which have been created with render target flags
800 pub render_targets: Vec<&'stack D::Texture>,
801 /// Colour to clear render target when the pass starts, use None to preserve previous contents
802 pub rt_clear: Option<ClearColour>,
803 /// A texture which was created with depth stencil flags
804 pub depth_stencil: Option<&'stack D::Texture>,
805 /// Depth value (in view) to clear depth stencil, use None to preserve previous contents
806 pub ds_clear: Option<ClearDepthStencil>,
807 /// Choose to resolve multi-sample AA targets,
808 pub resolve: bool,
809 /// (must also specify None to clear). This can save having to Load conents from main memory
810 pub discard: bool,
811 /// Array layer, depth slice or cubemap face to render to
812 pub array_slice: usize
813}
814
815/// Transitions are required to be performed to switch resources from reading to writing or into different formats
816pub struct TransitionBarrier<'stack, D: Device> {
817 /// A texture to perform the transition on, either `texture` xor `buffer` must be `Some`
818 pub texture: Option<&'stack D::Texture>,
819 /// A buffer to perform the transition on, either `buffer` xor `texture` must be `Some`
820 pub buffer: Option<&'stack D::Buffer>,
821 /// The state of the resource before the transition is made, this must be correct otherwise it will throw validation warnings
822 pub state_before: ResourceState,
823 /// The state we want to transition into
824 pub state_after: ResourceState,
825}
826
827/// All possible resource states, some for buffers and some for textures
828#[derive(Copy, Clone, Serialize, Deserialize, PartialEq, Debug)]
829pub enum ResourceState {
830 /// Used for texture only to be written to from fragment shaders
831 RenderTarget,
832 /// Used for a texture to be used as a depth stencil buffer
833 DepthStencil,
834 /// Used for when depth testing is enabled, but depth writes are disabled
835 DepthStencilReadOnly,
836 /// Used for swap chain textures only, required before calling swap
837 Present,
838 /// Access for read/write from shaders
839 UnorderedAccess,
840 /// Readable from shaders
841 ShaderResource,
842 /// Bindable as a vertex or constant buffer for use in shaders
843 VertexConstantBuffer,
844 /// Bindable as an index buffer
845 IndexBuffer,
846 /// Used as a source msaa texture to resolve into a non-msaa resource
847 ResolveSrc,
848 /// Used as a destination sngle sample texture to be resolved into by an msaa resource
849 ResolveDst,
850 /// Used as a source for copies from into other resources
851 CopySrc,
852 /// Used as a destination for copies from other resources or queries
853 CopyDst,
854 /// Used as destination to read back data from buffers / queries
855 GenericRead,
856 /// Used for argument buffer in `execute_indirect` calls
857 IndirectArgument,
858}
859
860/// ome resources may contain subresources for resolving
861#[derive(Copy, Clone, Serialize, Deserialize, PartialEq)]
862pub enum Subresource {
863 /// The resource itself for example a multi-sample texture has x number of MSAA samples
864 Resource,
865 /// The sub resource for example an MSAA texture will also create a non-MSAA subresource for resolving in to.
866 ResolveResource
867}
868
869/// Info to control mapping of resources for read/write access
870#[derive(Default)]
871pub struct MapInfo {
872 /// Sub resource to map ie. mip level, cubemap face, array slice
873 pub subresource: u32,
874 /// Range start of data we wish to read, for write-only access supply 0
875 pub read_start: usize,
876 /// Range end of data we wish to read, for write only access supply 0, to read the whole resource supply usize::MAX
877 pub read_end: usize,
878}
879
880/// Info to control writing of mapped resources
881pub struct UnmapInfo {
882 /// Sub resource to map ie. mip level, cubemap face, array slice
883 pub subresource: u32,
884 /// Range start of data we have written to the buffer, supply 0 for read-only
885 pub write_start: usize,
886 /// Range end of data we have written to the buffer, supply 0 for read only
887 pub write_end: usize,
888}
889
890/// Enum to differentiate between render and compute pipelines but also still work on them generically
891pub enum PipelineType {
892 Render,
893 Compute
894}
895
896/// An opaque Shader type
897pub trait Shader<D: Device>: Send + Sync {}
898
899/// An opaque render pipeline type set blend, depth stencil, raster states on a pipeline, and bind with `CmdBuf::set_pipeline_state`
900pub trait RenderPipeline<D: Device>: Send + Sync {}
901
902/// An opaque RenderPass containing an optional set of colour render targets and an optional depth stencil target
903pub trait RenderPass<D: Device>: Send + Sync {
904 /// Returns a hash based on the render target format so that pipelines can be shared amonst compatible passes
905 /// hash is based on render target format, depth stencil format and MSAA sample count
906 fn get_format_hash(&self) -> u64;
907}
908/// An opaque compute pipeline type..
909pub trait ComputePipeline<D: Device>: Send + Sync {}
910
911/// A pipeline trait for shared functionality between Compute and Render pipelines
912pub trait Pipeline {
913 /// Returns the `PipelineSlotInfo` of which slot to bind a heap to based on the reequested `register` and `descriptor_type`
914 /// if `None` is returned the pipeline does not contain bindings for the requested information
915 fn get_pipeline_slot(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> Option<&PipelineSlotInfo>;
916 /// Returns a vec of all pipeline slot indices
917 fn get_pipeline_slots(&self) -> &Vec<u32>;
918 /// Returns the pipeline type
919 fn get_pipeline_type() -> PipelineType;
920}
921
922/// A command signature is used to `execute_indirect` commands
923pub trait CommandSignature<D: Device>: Send + Sync {}
924
925/// Different types of arguments which can be changed through execute indirect calls
926#[derive(Clone, Copy)]
927pub enum IndirectArgumentType {
928 /// Used to issue indirect `draw` calls
929 Draw,
930 /// Used to issue indirect `draw_indexed` calls
931 DrawIndexed,
932 /// Used to issue indirect compute `dispatch` calls
933 Dispatch,
934 /// Used to change a vertex buffer binding
935 VertexBuffer,
936 /// Used to change an index buffer binding
937 IndexBuffer,
938 /// Used to change push constants
939 PushConstants,
940 /// Used to change constant buffer binding
941 ConstantBuffer,
942 /// Used to change a shader resource view binding
943 ShaderResource,
944 /// Userd to change an unordered access view binding
945 UnorderedAccess
946}
947
948/// Arguments to change push constants during an `execute_indirect` call when `Constant` is the `IndirectArgumentType`
949#[derive(Clone, Copy)]
950pub struct IndirectPushConstantsArguments {
951 /// The pipeline slot to modify
952 pub slot: u32,
953 /// Offset in 32bit values
954 pub offset: u32,
955 /// Number of 32bit values
956 pub num_values: u32,
957}
958
959/// Arguments to change a buffer during an `execute_indirect` call when `ConstantBuffer`, `ShaderResource` or `UnorderedAccess`
960/// are the `IndirectArgumentType`
961#[derive(Clone, Copy)]
962pub struct IndirectBufferArguments {
963 /// The pipeline layout slot or the vertex buffer / index buffer slot
964 pub slot: u32
965}
966
967/// This can be used for `Draw`, `DrawIndexed`, or `Dispatch` `IndirectArgumentType`
968#[derive(Clone, Copy)]
969pub struct IndirectNoArguments;
970
971/// Union of `IndirectArguments` where data can be selected by the `IndirectArgumentType`
972pub union IndirectTypeArguments {
973 pub push_constants: IndirectPushConstantsArguments,
974 pub buffer: IndirectBufferArguments
975}
976
977/// Pair of `IndirectArgumentType` and `IndirectTypeArguments` where the type selects the union member of data
978pub struct IndirectArgument {
979 pub argument_type: IndirectArgumentType,
980 pub arguments: Option<IndirectTypeArguments>
981}
982
983/// Structure of arguments which can be used to execute `draw_instanced` calls indirectly
984#[repr(C)]
985#[derive(Clone, Copy)]
986pub struct DrawArguments {
987 pub vertex_count_per_instance: u32,
988 pub instance_count: u32,
989 pub start_vertex_location: u32,
990 pub start_instance_location: u32
991}
992
993/// Structure of arguments which can be used to execute `draw_indexed_instanced` calls indirectly
994#[repr(C)]
995#[derive(Clone, Copy)]
996pub struct DrawIndexedArguments {
997 pub index_count_per_instance: u32,
998 pub instance_count: u32,
999 pub start_index_location: u32,
1000 pub base_vertex_location: i32,
1001 pub start_instance_location: u32,
1002}
1003
1004/// Structure of arguments which can be used to execute `dispatch` calls indirectly
1005#[repr(C)]
1006#[derive(Clone, Copy)]
1007pub struct DispatchArguments {
1008 pub thread_group_count_x: u32,
1009 pub thread_group_count_y: u32,
1010 pub thread_group_count_z: u32,
1011}
1012
1013/// Structure of arguments which can be used to change a vertex buffer during `execute_indirect`
1014#[repr(C)]
1015#[derive(Clone, Copy)]
1016pub struct VertexBufferView {
1017 pub location: u64,
1018 pub size_bytes: u32,
1019 pub stride_bytes: u32,
1020}
1021
1022/// Structure of arguments which can be used to change an index buffer during `execute_indirect`
1023#[repr(C)]
1024#[derive(Clone, Copy)]
1025pub struct IndexBufferView {
1026 pub location: u64,
1027 pub size_bytes: u32,
1028 pub format: u32,
1029}
1030
1031/// A GPU device is used to create GPU resources, the device also contains a single a single command queue
1032/// to which all command buffers will submitted and executed each frame. Default heaps for shader resources,
1033/// render targets and depth stencils are also provided
1034pub trait Device: 'static + Send + Sync + Sized + Any + Clone {
1035 type SwapChain: SwapChain<Self>;
1036 type CmdBuf: CmdBuf<Self>;
1037 type Buffer: Buffer<Self>;
1038 type Shader: Shader<Self>;
1039 type RenderPipeline: RenderPipeline<Self>;
1040 type Texture: Texture<Self>;
1041 type ReadBackRequest: ReadBackRequest<Self>;
1042 type RenderPass: RenderPass<Self>;
1043 type Heap: Heap<Self>;
1044 type QueryHeap: QueryHeap<Self>;
1045 type ComputePipeline: ComputePipeline<Self>;
1046 type CommandSignature: CommandSignature<Self>;
1047 /// Create a new GPU `Device` from `Device Info`
1048 fn create(info: &DeviceInfo) -> Self;
1049 /// Create a new resource `Heap` from `HeapInfo`
1050 fn create_heap(&mut self, info: &HeapInfo) -> Self::Heap;
1051 /// Create a new `QueryHeap` from `QueryHeapInfo`
1052 fn create_query_heap(&self, info: &QueryHeapInfo) -> Self::QueryHeap;
1053 /// Create a new `SwapChain` from `SwapChainInfo` and bind it to the specified `window`
1054 fn create_swap_chain<A: os::App>(
1055 &mut self,
1056 info: &SwapChainInfo,
1057 window: &A::Window,
1058 ) -> Result<Self::SwapChain, Error>;
1059 /// Create a new `CmdBuf` with `num_buffers` internal buffers, the buffers can be swapped and syncronised
1060 /// with a new `SwapChain` to allow in-flight gpu/cpu overlapped prodicer consumers
1061 fn create_cmd_buf(&self, num_buffers: u32) -> Self::CmdBuf;
1062 /// Create a new `Shader` from `ShaderInfo`
1063 fn create_shader<T: Sized>(&self, info: &ShaderInfo, src: &[T]) -> Result<Self::Shader, Error>;
1064 /// Create a new `Buffer` from `BufferInfo` with any resource views allocated on the devices `shader_heap`
1065 fn create_buffer<T: Sized>(
1066 &mut self,
1067 info: &BufferInfo,
1068 data: Option<&[T]>,
1069 ) -> Result<Self::Buffer, Error>;
1070 /// Create a new `Buffer` from `BufferInfo` with any resource views allocated on the specified `Heap` that must be of `HeapType::Shader`
1071 fn create_buffer_with_heap<T: Sized>(
1072 &mut self,
1073 info: &BufferInfo,
1074 data: Option<&[T]>,
1075 heap: &mut Self::Heap
1076 ) -> Result<Self::Buffer, Error>;
1077 /// Create a `Buffer` specifically for reading back data from the GPU mainly for `Query` use
1078 fn create_read_back_buffer(
1079 &mut self,
1080 size: usize,
1081 ) -> Result<Self::Buffer, Error>;
1082 /// Create a new texture from `TextureInfo` and initialise it with optional data which can be any slice of a sized `T`
1083 fn create_texture<T: Sized>(
1084 &mut self,
1085 info: &TextureInfo,
1086 data: Option<&[T]>,
1087 ) -> Result<Self::Texture, Error>;
1088 /// Create a new texture from `TextureInfo` and initialise it with optional data which can be any slice of a sized `T`
1089 /// allocates requested views into the supplied heaps, if the heaps are `None` this will use the default device heaps.
1090 fn create_texture_with_heaps<T: Sized>(
1091 &mut self,
1092 info: &TextureInfo,
1093 heaps: TextureHeapInfo<Self>,
1094 data: Option<&[T]>,
1095 ) -> Result<Self::Texture, Error>;
1096 /// Create a new render pipeline state object from the supplied `RenderPipelineInfo`
1097 fn create_render_pipeline(
1098 &self,
1099 info: &RenderPipelineInfo<Self>,
1100 ) -> Result<Self::RenderPipeline, Error>;
1101 /// Create a new render pass from `RenderPassInfo`
1102 fn create_render_pass(&self, info: &RenderPassInfo<Self>) -> Result<Self::RenderPass, Error>;
1103 /// Create a new compute pipeline state object from `ComputePipelineInfo`
1104 fn create_compute_pipeline(
1105 &self,
1106 info: &ComputePipelineInfo<Self>,
1107 ) -> Result<Self::ComputePipeline, Error>;
1108 /// Creat a command signature for `execute_indirect` commands associated on the `RenderPipeline`
1109 fn create_indirect_render_command<T: Sized>(
1110 &mut self,
1111 arguments: Vec<IndirectArgument>,
1112 pipeline: Option<&Self::RenderPipeline>
1113 ) -> Result<Self::CommandSignature, super::Error>;
1114 /// Execute a command buffer on the internal device command queue which still hold references
1115 fn execute(&self, cmd: &Self::CmdBuf);
1116 /// Borrow the internally managed shader resource heap the device creates, for binding buffers / textures in shaders
1117 fn get_shader_heap(&self) -> &Self::Heap;
1118 /// Mutably borrow the internally managed shader resource heap the device creates, for binding buffers / textures in shaders
1119 fn get_shader_heap_mut(&mut self) -> &mut Self::Heap;
1120 /// Cleans up resources which have been dropped associated with the device heaps, safeley waiting for
1121 /// any in-flight GPU operations to complete
1122 fn cleanup_dropped_resources(&mut self, swap_chain: &Self::SwapChain);
1123 /// Returns an `AdapterInfo` struct (info about GPU vendor, and HW statistics)
1124 fn get_adapter_info(&self) -> &AdapterInfo;
1125 /// Returns a `DeviceFeatureFlags` struct containing flags for supported hardware features
1126 fn get_feature_flags(&self) -> &DeviceFeatureFlags;
1127 /// Read data back from GPU buffer into CPU `ReadBackData` assumes the `Buffer` is created with `create_read_back_buffer`
1128 /// None is returned if the buffer has yet to br written on the GPU
1129 fn read_buffer(&self, swap_chain: &Self::SwapChain, buffer: &Self::Buffer, size_bytes: usize, frame_written_fence: u64) -> Option<ReadBackData>;
1130 /// Read back u64 timestamp values as values in seconds, the vector will be empty if the buffer is yet to be written
1131 /// on the GPU
1132 fn read_timestamps(&self, swap_chain: &Self::SwapChain, buffer: &Self::Buffer, size_bytes: usize, frame_written_fence: u64) -> Vec<f64>;
1133 /// Read back a single pipeline statistics query, assuming `buffer` was created with `create_read_back_buffer`
1134 /// and is of size `get_pipeline_statistics_size_bytes()`. None is returned if the buffer is not ready
1135 fn read_pipeline_statistics(&self, swap_chain: &Self::SwapChain, buffer: &Self::Buffer, frame_written_fence: u64) -> Option<PipelineStatistics>;
1136 /// Reorts internal graphics api backend resources
1137 fn report_live_objects(&self) -> Result<(), Error>;
1138 /// Retrieve messages in the info queue since they were last drained
1139 fn get_info_queue_messages(&self) -> Result<Vec<String>, Error>;
1140 /// Size of a single timestamp query result in bytes
1141 fn get_timestamp_size_bytes() -> usize;
1142 /// Size of a single pipeline statistics query result in bytes
1143 fn get_pipeline_statistics_size_bytes() -> usize;
1144 /// Size of the indirect draw command in bytes
1145 fn get_indirect_command_size(argument_type: IndirectArgumentType) -> usize;
1146 /// Returns the alignment requirement size in bytes for counters (append buffers / uavs)
1147 fn get_counter_alignment() -> usize;
1148}
1149
1150/// A swap chain is connected to a window, controls fences and signals as we swap buffers.
1151pub trait SwapChain<D: Device>: 'static + Sized + Any + Send + Sync + Clone {
1152 /// Call to begin a new frame, to synconise with v-sync and internally swap buffers
1153 fn new_frame(&mut self);
1154 /// Update to syncornise with the window, this may require the backbuffer to resize
1155 fn update<A: os::App>(&mut self, device: &mut D, window: &A::Window, cmd: &mut D::CmdBuf);
1156 /// Waits on the CPU for the last frame that was submitted with `swap` to be completed by the GPU
1157 fn wait_for_last_frame(&self);
1158 /// Returns the fence value for the current frame, you can use this to syncronise reads
1159 fn get_frame_fence_value(&self) -> u64;
1160 /// Returns the number of buffers in the swap chain
1161 fn get_num_buffers(&self) -> u32;
1162 /// Returns the current backbuffer index, this is the buffer that will be written during
1163 /// the current frame
1164 fn get_backbuffer_index(&self) -> u32;
1165 /// Returns the current backbuffer texture
1166 fn get_backbuffer_texture(&self) -> &D::Texture;
1167 /// Returns the current backbuffer pass this is the one
1168 /// we want to render to during the current frame
1169 fn get_backbuffer_pass(&self) -> &D::RenderPass;
1170 /// Returns the current backbuffer pass mutuably
1171 fn get_backbuffer_pass_mut(&mut self) -> &mut D::RenderPass;
1172 /// Returns the current backbuffer pass without a clear
1173 fn get_backbuffer_pass_no_clear(&self) -> &D::RenderPass;
1174 /// Returns the current backbuffer pass without a clear mutably
1175 fn get_backbuffer_pass_no_clear_mut(&mut self) -> &mut D::RenderPass;
1176 /// Call swap at the end of the frame to swap the back buffer, we rotate through n-buffers
1177 fn swap(&mut self, device: &D);
1178}
1179
1180/// Responsible for buffering graphics commands. Internally it will contain a platform specific
1181/// command list for each buffer in the associated swap chain.
1182/// At the start of each frame `reset` must be called with an associated swap chain to internally switch
1183/// which buffer we are writing to. At the end of each frame `close` must be called
1184/// and finally the `CmdBuf` can be passed to `Device::execute` to be processed on the GPU.
1185pub trait CmdBuf<D: Device>: Send + Sync + Clone {
1186 /// Reset the `CmdBuf` for use on a new frame, it will be syncronised with the `SwapChain` so that
1187 /// in-flight command buffers are not overwritten
1188 fn reset(&mut self, swap_chain: &D::SwapChain);
1189 /// Call close to the command buffer after all commands have been added and before passing to `Device::execute`
1190 fn close(&mut self) -> Result<(), Error>;
1191 /// Internally the `CmdBuf` contains a set of buffers which it rotates through to allow inflight operations
1192 /// to complete, this value indicates the buffer number you should `write` to during the current frame
1193 fn get_backbuffer_index(&self) -> u32;
1194 /// Begins a render pass, end must be called
1195 fn begin_render_pass(&self, render_pass: &D::RenderPass);
1196 /// End a render pass must be called after `begin_render_pass` has been called
1197 fn end_render_pass(&self);
1198 /// Begin a names marker event which will be visible in tools such as PIX or RenderDoc
1199 fn begin_event(&mut self, colour: u32, name: &str);
1200 /// End an event that was started with `begin_event`
1201 fn end_event(&mut self);
1202 /// Similar to `begin_event/end_event` except it inserts a single marker point instead of a range
1203 fn set_marker(&self, colour: u32, name: &str);
1204 /// Function to specifically insert a timestamp query and request readback into the `Buffer`
1205 /// read back the rsult with `Device::read_timestamps`
1206 fn timestamp_query(&mut self, heap: &mut D::QueryHeap, resolve_buffer: &mut D::Buffer);
1207 /// Begin a new query in the heap, it will allocate an index which is returned as `usize`
1208 fn begin_query(&mut self, heap: &mut D::QueryHeap, query_type: QueryType) -> usize;
1209 /// End a query that was made on the heap results will be pushed into the `resolve_buffer`
1210 /// the data can be read by `Device::read_buffer` or specialisations such as `read_pipeline_statistics`
1211 fn end_query(&mut self, heap: &mut D::QueryHeap, query_type: QueryType, index: usize, resolve_buffer: &mut D::Buffer);
1212 /// Add a transition barrier for resources to change states based on info supplied in `TransitionBarrier`
1213 fn transition_barrier(&mut self, barrier: &TransitionBarrier<D>);
1214 /// Add a transition barrier for a sub resource (ie. resolve texture)
1215 fn transition_barrier_subresource(&mut self, barrier: &TransitionBarrier<D>, subresource: Subresource);
1216 /// Set the viewport on the rasterizer stage
1217 fn set_viewport(&self, viewport: &Viewport);
1218 /// Set the scissor rect on the rasterizer stage
1219 fn set_scissor_rect(&self, scissor_rect: &ScissorRect);
1220 /// Set the index `buffer` to use for draw calls, the buffer should be created with `BufferUsage::INDEX`
1221 fn set_index_buffer(&self, buffer: &D::Buffer);
1222 /// Set the index `buffer` on `slot` to use for draw calls, the buffer should be created with `BufferUsage::VERTEX`
1223 fn set_vertex_buffer(&self, buffer: &D::Buffer, slot: u32);
1224 /// Set render pipeline for `draw` commands
1225 fn set_render_pipeline(&self, pipeline: &D::RenderPipeline);
1226 /// Set a compute pipeline for `dispatch`
1227 fn set_compute_pipeline(&self, pipeline: &D::ComputePipeline);
1228 /// Set's the active shader heap for the pipeline (srv, uav and cbv) and sets all descriptor tables to the root of the heap
1229 fn set_heap<T: Pipeline>(&self, pipeline: &T, heap: &D::Heap);
1230 /// Binds the heap with offset (texture srv, uav) on to the `slot` of a pipeline.
1231 /// this is like a traditional bindful render architecture `cmd.set_binding(pipeline, heap, 0, texture1_id)`
1232 fn set_binding<T: Pipeline>(&self, pipeline: &T, heap: &D::Heap, slot: u32, offset: usize);
1233 /// Push a small amount of data into the command buffer for a render pipeline, num values and dest offset are the numbr of 32bit values
1234 fn push_render_constants<T: Sized>(&self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]);
1235 /// Push a small amount of data into the command buffer for a compute pipeline, num values and dest offset are the numbr of 32bit values
1236 fn push_compute_constants<T: Sized>(&self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]);
1237 /// Make a non-indexed draw call supplying vertex and instance counts
1238 fn draw_instanced(
1239 &self,
1240 vertex_count: u32,
1241 instance_count: u32,
1242 start_vertex: u32,
1243 start_instance: u32,
1244 );
1245 /// Make an indexed draw call supplying index and instance counts, an index buffer should be bound
1246 fn draw_indexed_instanced(
1247 &self,
1248 index_count: u32,
1249 instance_count: u32,
1250 start_index: u32,
1251 base_vertex: i32,
1252 start_instance: u32,
1253 );
1254 /// Thread count is required for metal, in hlsl it is specified in the shader
1255 fn dispatch(&self, group_count: Size3, numthreads: Size3);
1256 /// Issue indirect commands with signature created from `create_indirect_render_command`
1257 fn execute_indirect(
1258 &self,
1259 command: &D::CommandSignature,
1260 max_command_count: u32,
1261 argument_buffer: &D::Buffer,
1262 argument_buffer_offset: usize,
1263 counter_buffer: Option<&D::Buffer>,
1264 counter_buffer_offset: usize
1265 );
1266 /// Resolves the `subresource` (mip index, 3d texture slice or array slice)
1267 fn resolve_texture_subresource(&self, texture: &D::Texture, subresource: u32) -> Result<(), Error>;
1268 /// Generates a full mip chain for the specified `texture` where `heap` is the shader heap the texture was created on
1269 fn generate_mip_maps(&mut self, texture: &D::Texture, device: &D, heap: &D::Heap) -> Result<(), Error>;
1270 /// Read back the swapchains contents to CPU
1271 fn read_back_backbuffer(&mut self, swap_chain: &D::SwapChain) -> Result<D::ReadBackRequest, Error>;
1272 /// Copy from one buffer to another with offsets
1273 fn copy_buffer_region(
1274 &mut self,
1275 dst_buffer: &D::Buffer,
1276 dst_offset: usize,
1277 src_buffer: &D::Buffer,
1278 src_offset: usize,
1279 num_bytes: usize
1280 );
1281 /// Copy from one texture to another with offsets, if `None` is specified for `src_region`
1282 /// it will copy the full size of src
1283 fn copy_texture_region(
1284 &mut self,
1285 dst_texture: &D::Texture,
1286 subresource_index: u32,
1287 dst_x: u32,
1288 dst_y: u32,
1289 dst_z: u32,
1290 src_texture: &D::Texture,
1291 src_region: Option<Region>
1292 );
1293}
1294
1295/// An opaque Buffer type used for vertex, index, constant or unordered access.
1296pub trait Buffer<D: Device>: Send + Sync {
1297 /// updates the buffer by mapping and copying memory, if you update while a buffer is in use on the GPU you may see tearing
1298 /// multi-buffer updates to buffer so that a buffer is never written to while in flight on the GPU.
1299 /// this function internally will map and unmap
1300 fn update<T: Sized>(&mut self, offset: usize, data: &[T]) -> Result<(), Error>; // TODO: should be mut surely?
1301 // write data directly to the buffer, the buffer is required to be persistently mapped
1302 fn write<T: Sized>(&mut self, offset: usize, data: &[T]) -> Result<(), Error>;
1303 /// maps the entire buffer for reading or writing... see MapInfo
1304 fn map(&mut self, info: &MapInfo) -> *mut u8;
1305 /// unmap buffer... see UnmapInfo
1306 fn unmap(&mut self, info: &UnmapInfo);
1307 /// Return the index to access in a shader as a structured buffer
1308 fn get_srv_index(&self) -> Option<usize>;
1309 /// Return the index to access in a shader as a cbuffer
1310 fn get_cbv_index(&self) -> Option<usize>;
1311 /// Return the index to unorder access view for read/write from shaders...
1312 fn get_uav_index(&self) -> Option<usize>;
1313 /// Return a vertex buffer view
1314 fn get_vbv(&self) -> Option<VertexBufferView>;
1315 /// Return an index buffer view
1316 fn get_ibv(&self) -> Option<IndexBufferView>;
1317 /// Returns the offset in bytes of a counter element for an append structured buffer
1318 /// `None` is returned if the buffer was not created with `BufferUsage::APPEND_COUNTER`
1319 fn get_counter_offset(&self) -> Option<usize>;
1320}
1321
1322/// An opaque Texture type
1323pub trait Texture<D: Device>: Send + Sync {
1324 /// Return the index to access in a shader (if the resource has msaa this is the resolved view)
1325 fn get_srv_index(&self) -> Option<usize>;
1326 /// Return the index to unorderd access view for read/write from shaders...
1327 fn get_uav_index(&self) -> Option<usize>;
1328 /// Return the subresource index unorderd access view for read/write from shaders
1329 /// where subresource is the array slice * num mips + mip you want to access
1330 fn get_subresource_uav_index(&self, subresource: u32) -> Option<usize>;
1331 /// Return the index of an msaa resource to access in a shader
1332 fn get_msaa_srv_index(&self) -> Option<usize>;
1333 /// Return a clone of the internal (platform specific) resource
1334 fn clone_inner(&self) -> Self;
1335 /// Returns true if this texture has a subresource which can be resolved into
1336 fn is_resolvable(&self) -> bool;
1337 /// Return the id of the shader heap
1338 fn get_shader_heap_id(&self) -> Option<u16>;
1339}
1340
1341/// An opaque shader heap type, use to create views of resources for binding and access in shaders
1342pub trait Heap<D: Device>: Send + Sync {
1343 /// Deallocate a resource from the heap and mark space in free list for re-use
1344 fn deallocate(&mut self, index: usize);
1345 /// Cleans up resources which have been dropped associated with this heap, safeley waiting for
1346 /// any in-flight GPU operations to complete
1347 fn cleanup_dropped_resources(&mut self, swap_chain: &D::SwapChain);
1348 /// Returns the id of the heap to verify and correlate with resources
1349 fn get_heap_id(&self) -> u16;
1350}
1351
1352/// An opaque query heap type, use to create queries
1353pub trait QueryHeap<D: Device>: Send + Sync {
1354 /// Reset queries at the start of the frame, each query requested will bump the allocation index
1355 fn reset(&mut self);
1356}
1357
1358/// Used to readback data from the GPU, once the request is issued `is_complete` needs to be waited on for completion
1359/// you must poll this every frame and not block so the GPU can flush the request. Once the result is ready the
1360/// data can be obtained using `get_data`
1361pub trait ReadBackRequest<D: Device> {
1362 /// Returns true when a reload request has completed and it is safe to call map
1363 fn is_complete(&self, swap_chain: &D::SwapChain) -> bool;
1364 /// Maps the buffer to allow the CPU to read GPU mapped data
1365 fn map(&self, info: &MapInfo) -> Result<ReadBackData, Error>;
1366 /// Balance with a call to map. note: it is possible to leave buffers persitently mapped
1367 fn unmap(&self);
1368}
1369
1370/// Results from an issued ReadBackRequest
1371#[derive(Clone)]
1372pub struct ReadBackData {
1373 /// Slice of data bytes
1374 pub data: &'static [u8],
1375 /// GPU format to interperet the data
1376 pub format: Format,
1377 /// Total size of data (should be == data.len())
1378 pub size: usize,
1379 /// Pitch of a row of data
1380 pub row_pitch: usize,
1381 /// Pitch of a slice (3D texture or array level, cubemap face etc)
1382 pub slice_pitch: usize,
1383}
1384
1385/// Take any sized type and return a u8 slice. This can be useful to pass `data` to `Device::create_buffer`.
1386pub fn as_u8_slice<T: Sized>(p: &T) -> &[u8] {
1387 unsafe {
1388 ::std::slice::from_raw_parts((p as *const T) as *const u8, ::std::mem::size_of::<T>())
1389 }
1390}
1391
1392/// Take any sized silce and convert to a slice of u8
1393pub fn slice_as_u8_slice<T: Sized>(p: &[T]) -> &[u8] {
1394 unsafe {
1395 ::std::slice::from_raw_parts(
1396 (p.as_ptr() as *const T) as *const u8,
1397 ::std::mem::size_of::<T>() * p.len(),
1398 )
1399 }
1400}
1401
1402/// Returns the 'block size' (texel, compressed block of texels or single buffer element) for a given format
1403pub const fn block_size_for_format(format: Format) -> u32 {
1404 match format {
1405 Format::Unknown => 0,
1406 Format::R16n => 2,
1407 Format::R16u => 2,
1408 Format::R16i => 2,
1409 Format::R16f => 2,
1410 Format::R32u => 4,
1411 Format::R32i => 4,
1412 Format::R32f => 4,
1413 Format::RG16u => 4,
1414 Format::RG16i => 4,
1415 Format::RG16f => 4,
1416 Format::RG32u => 8,
1417 Format::RG32i => 8,
1418 Format::RG32f => 8,
1419 Format::RGBA8nSRGB => 4,
1420 Format::RGBA8n => 4,
1421 Format::RGBA8u => 4,
1422 Format::RGBA8i => 4,
1423 Format::BGRA8n => 4,
1424 Format::BGRX8n => 4,
1425 Format::BGRA8nSRGB => 4,
1426 Format::BGRX8nSRGB => 4,
1427 Format::RGB32u => 12,
1428 Format::RGB32i => 12,
1429 Format::RGB32f => 12,
1430 Format::RGBA16u => 8,
1431 Format::RGBA16i => 8,
1432 Format::RGBA16f => 8,
1433 Format::RGBA32u => 16,
1434 Format::RGBA32i => 16,
1435 Format::RGBA32f => 16,
1436 Format::D32fS8X24u => 8,
1437 Format::D32f => 16,
1438 Format::D24nS8u => 32,
1439 Format::D16n => 2,
1440 Format::BC1n => 8,
1441 Format::BC1nSRGB => 8,
1442 Format::BC2n => 4,
1443 Format::BC2nSRGB => 4,
1444 Format::BC3n => 16,
1445 Format::BC3nSRGB => 16,
1446 Format::BC4n => 8,
1447 Format::BC5n => 16,
1448 }
1449}
1450
1451/// Returns the number of texels (texel x texel) in each block for the specified texture format
1452pub const fn texels_per_block_for_format(format: Format) -> u64 {
1453 match format {
1454 Format::BC1n => 4,
1455 Format::BC1nSRGB => 4,
1456 Format::BC2n => 4,
1457 Format::BC2nSRGB => 4,
1458 Format::BC3n => 4,
1459 Format::BC3nSRGB => 4,
1460 Format::BC4n => 4,
1461 Format::BC5n => 4,
1462 _ => 1,
1463 }
1464}
1465
1466/// Returns the number of components for a given format. ie RGBA = 4 and RGB = 3
1467pub const fn components_for_format(format: Format) -> u32 {
1468 match format {
1469 Format::Unknown => 0,
1470 Format::R16n => 1,
1471 Format::R16u => 1,
1472 Format::R16i => 1,
1473 Format::R16f => 1,
1474 Format::R32u => 1,
1475 Format::R32i => 1,
1476 Format::R32f => 1,
1477 Format::RG16u => 2,
1478 Format::RG16i => 2,
1479 Format::RG16f => 2,
1480 Format::RG32u => 2,
1481 Format::RG32i => 2,
1482 Format::RG32f => 2,
1483 Format::RGBA8nSRGB => 4,
1484 Format::RGBA8n => 4,
1485 Format::RGBA8u => 4,
1486 Format::RGBA8i => 4,
1487 Format::BGRA8n => 4,
1488 Format::BGRX8n => 4,
1489 Format::BGRA8nSRGB => 4,
1490 Format::BGRX8nSRGB => 4,
1491 Format::RGB32u => 3,
1492 Format::RGB32i => 3,
1493 Format::RGB32f => 3,
1494 Format::RGBA16u => 4,
1495 Format::RGBA16i => 4,
1496 Format::RGBA16f => 4,
1497 Format::RGBA32u => 4,
1498 Format::RGBA32i => 4,
1499 Format::RGBA32f => 4,
1500 Format::D32fS8X24u => 2,
1501 Format::D32f => 1,
1502 Format::D24nS8u => 2,
1503 Format::D16n => 1,
1504 Format::BC1n => 4,
1505 Format::BC1nSRGB => 4,
1506 Format::BC2n => 3,
1507 Format::BC2nSRGB => 3,
1508 Format::BC3n => 4,
1509 Format::BC3nSRGB => 4,
1510 Format::BC4n => 1,
1511 Format::BC5n => 2,
1512 }
1513}
1514
1515/// Returns the row pitch of an image in bytes: width * block size
1516pub fn row_pitch_for_format(format: Format, width: u64) -> u64 {
1517 let tpb = texels_per_block_for_format(format);
1518 block_size_for_format(format) as u64 * (width / tpb).max(1)
1519}
1520
1521/// Returns the slice pitch of an image in bytes: width * height * block size, a slice is a single 2D image
1522/// or a single slice of a 3D texture or texture array
1523pub fn slice_pitch_for_format(format: Format, width: u64, height: u64) -> u64 {
1524 let tpb = texels_per_block_for_format(format);
1525 block_size_for_format(format) as u64 * (width / tpb).max(1) * (height / tpb).max(1)
1526}
1527
1528/// Return the size in bytes of a 3 dimensional resource: width * height * depth block size
1529pub fn size_for_format(format: Format, width: u64, height: u64, depth: u32) -> u64 {
1530 let tpb = texels_per_block_for_format(format);
1531
1532 block_size_for_format(format) as u64 * (width / tpb).max(1) * (height / tpb).max(1) * depth as u64
1533}
1534
1535/// Return the size in bytes of up to dimensional resource: width * height * depth block size
1536/// for each mip level and account for array layers
1537pub fn size_for_format_mipped(format: Format, width: u64, height: u64, depth: u32, array_layers: u32, mips: u32) -> u64 {
1538 let mut total = 0;
1539 let mut mip_width = width;
1540 let mut mip_height = height;
1541 let mut mip_depth = depth;
1542 for _ in 0..mips {
1543 total += size_for_format(format, mip_width, mip_height, mip_depth) * array_layers as u64;
1544 mip_width = max(mip_width / 2, 1);
1545 mip_height = max(mip_height / 2, 1);
1546 mip_depth = max(mip_depth / 2, 1);
1547 }
1548 total
1549}
1550
1551/// Returns the number of mip levels required for a 2D texture
1552pub fn mip_levels_for_dimension(width: u64, height: u64) -> u32 {
1553 f32::log2(width.max(height) as f32) as u32 + 1
1554}
1555
1556/// Aligns value to the alignment specified by align. value must be a power of 2
1557pub fn align_pow2(value: u64, align: u64) -> u64 {
1558 (value + (align - 1)) & !(align - 1)
1559}
1560
1561/// Aligns value to the alignment specified by align. value can be non-power of 2
1562pub fn align(value: u64, align: u64) -> u64 {
1563 let div = value / align;
1564 let rem = value % align;
1565 if rem != 0 {
1566 return (div + 1) * align;
1567 }
1568 value
1569}
1570
1571/// For the supplied sized struct `&_` returns the number of 32bit constants required for use as `push_constants`
1572pub const fn num_32bit_constants<T: Sized>(_: &T) -> u32 {
1573 (std::mem::size_of::<T>() / 4) as u32
1574}
1575
1576/// Trait for sized types where num constants is the number of 32-bit constants in type
1577trait NumConstants {
1578 fn num_constants() -> u32;
1579}
1580
1581/// Blanket implmenetation for sized `T`
1582impl<T> NumConstants for T where T: Sized {
1583 fn num_constants() -> u32 {
1584 (std::mem::size_of::<T>() / 4) as u32
1585 }
1586}
1587
1588impl From<os::Rect<i32>> for Viewport {
1589 fn from(rect: os::Rect<i32>) -> Viewport {
1590 Viewport {
1591 x: rect.x as f32,
1592 y: rect.y as f32,
1593 width: rect.width as f32,
1594 height: rect.height as f32,
1595 min_depth: 0.0,
1596 max_depth: 1.0,
1597 }
1598 }
1599}
1600
1601impl From<os::Rect<i32>> for ScissorRect {
1602 fn from(rect: os::Rect<i32>) -> ScissorRect {
1603 ScissorRect {
1604 left: rect.x,
1605 top: rect.y,
1606 right: rect.width,
1607 bottom: rect.height,
1608 }
1609 }
1610}
1611
1612/// Convert from WritMask bit mask to raw u8
1613impl From<WriteMask> for u8 {
1614 fn from(mask: WriteMask) -> u8 {
1615 mask.bits
1616 }
1617}
1618
1619/// Display for `AdapterInfo` displays as so:
1620/// hotline_rs::d3d12::Device:
1621/// NVIDIA GeForce GTX 1060 6GB
1622/// Video Memory: 6052(mb)
1623/// System Memory: 0(mb)
1624/// Shared System Memory: 8159(mb)
1625/// Available Adapters:
1626/// NVIDIA GeForce GTX 1060 6GB
1627/// Microsoft Basic Render Driver
1628impl std::fmt::Display for AdapterInfo {
1629 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1630 let mut available = String::from("");
1631 for adapter in &self.available {
1632 available += " ";
1633 available += adapter;
1634 available += "\n";
1635 }
1636 write!(
1637 f,
1638 "{}:
1639 {}
1640 Video Memory: {}(mb)
1641 System Memory: {}(mb)
1642 Shared System Memory: {}(mb)
1643Available Adapters:
1644{}",
1645 self.name,
1646 self.description,
1647 self.dedicated_video_memory / 1024 / 1024,
1648 self.dedicated_system_memory / 1024 / 1024,
1649 self.shared_system_memory / 1024 / 1024,
1650 available
1651 )
1652 }
1653}
1654
1655/// Useful defaults for quick creation of `TextureInfo`
1656impl Default for TextureInfo {
1657 fn default() -> Self {
1658 TextureInfo {
1659 tex_type: TextureType::Texture2D,
1660 format: Format::RGBA8n,
1661 width: 1,
1662 height: 1,
1663 depth: 1,
1664 array_layers: 1,
1665 mip_levels: 1,
1666 samples: 1,
1667 usage: TextureUsage::SHADER_RESOURCE,
1668 initial_state: ResourceState::ShaderResource
1669 }
1670 }
1671}
1672
1673/// Useful defaults for raster state on a pipeline state object, efetively means no culling, solid fill
1674impl Default for RasterInfo {
1675 fn default() -> Self {
1676 RasterInfo {
1677 fill_mode: FillMode::Solid,
1678 cull_mode: CullMode::None,
1679 front_ccw: false,
1680 depth_bias: 0,
1681 depth_bias_clamp: 0.0,
1682 slope_scaled_depth_bias: 0.0,
1683 depth_clip_enable: false,
1684 multisample_enable: false,
1685 antialiased_line_enable: false,
1686 forced_sample_count: 0,
1687 conservative_raster_mode: false,
1688 }
1689 }
1690}
1691
1692/// Useful defaults for smample states, wrap linear
1693impl Default for SamplerInfo {
1694 fn default() -> Self {
1695 SamplerInfo {
1696 filter: SamplerFilter::Linear,
1697 address_u: SamplerAddressMode::Wrap,
1698 address_v: SamplerAddressMode::Wrap,
1699 address_w: SamplerAddressMode::Wrap,
1700 comparison: None,
1701 border_colour: None,
1702 mip_lod_bias: 0.0,
1703 max_aniso: 0,
1704 min_lod: -1.0,
1705 max_lod: -1.0,
1706 }
1707 }
1708}
1709
1710/// Useful defaults for depth stencil state on a pipeline state object, no depth test or write
1711impl Default for DepthStencilInfo {
1712 fn default() -> Self {
1713 DepthStencilInfo {
1714 depth_enabled: false,
1715 depth_write_mask: DepthWriteMask::Zero,
1716 depth_func: ComparisonFunc::Always,
1717 stencil_enabled: false,
1718 stencil_read_mask: 0,
1719 stencil_write_mask: 0,
1720 front_face: StencilInfo {
1721 fail: StencilOp::Keep,
1722 depth_fail: StencilOp::Keep,
1723 pass: StencilOp::Keep,
1724 func: ComparisonFunc::Always,
1725 },
1726 back_face: StencilInfo {
1727 fail: StencilOp::Keep,
1728 depth_fail: StencilOp::Keep,
1729 pass: StencilOp::Keep,
1730 func: ComparisonFunc::Always,
1731 },
1732 }
1733 }
1734}
1735
1736/// Useful defaults for blend state on a pipeline state object, no blending
1737impl Default for RenderTargetBlendInfo {
1738 fn default() -> Self {
1739 RenderTargetBlendInfo {
1740 blend_enabled: false,
1741 logic_op_enabled: false,
1742 src_blend: BlendFactor::Zero,
1743 dst_blend: BlendFactor::Zero,
1744 blend_op: BlendOp::Add,
1745 src_blend_alpha: BlendFactor::Zero,
1746 dst_blend_alpha: BlendFactor::Zero,
1747 blend_op_alpha: BlendOp::Add,
1748 logic_op: LogicOp::Clear,
1749 write_mask: WriteMask::ALL,
1750 }
1751 }
1752}
1753
1754/// Defaults for a render pipline, which would do nothing
1755impl<'stack, D> Default for RenderPipelineInfo<'stack, D> where D: Device {
1756 fn default() -> Self {
1757 Self {
1758 vs: None,
1759 fs: None,
1760 input_layout: Vec::new(),
1761 pipeline_layout: PipelineLayout::default(),
1762 raster_info: RasterInfo::default(),
1763 depth_stencil_info: DepthStencilInfo::default(),
1764 blend_info: BlendInfo::default(),
1765 topology: Topology::TriangleList,
1766 patch_index: 0,
1767 sample_mask: u32::max_value(),
1768 pass: None
1769 }
1770 }
1771}
1772
1773/// Pipeline stats initialised to zero
1774impl Default for PipelineStatistics {
1775 fn default() -> Self {
1776 PipelineStatistics {
1777 input_assembler_vertices: 0,
1778 input_assembler_primitives: 0,
1779 vertex_shader_invocations: 0,
1780 pixel_shader_primitives: 0,
1781 compute_shader_invocations: 0
1782 }
1783 }
1784}
1785
1786
1787/// Pipeline stats initialised to zero
1788impl<'stack, D> Default for TextureHeapInfo<'stack, D> where D: Device {
1789 fn default() -> Self {
1790 Self {
1791 shader: None,
1792 render_target: None,
1793 depth_stencil: None
1794 }
1795 }
1796}
1797
1798/// Ability to add 2 pipeline stats to accumulate
1799impl std::ops::Add for PipelineStatistics {
1800 type Output = Self;
1801 fn add(self, other: Self) -> Self {
1802 Self {
1803 input_assembler_vertices: self.input_assembler_vertices + other.input_assembler_vertices,
1804 input_assembler_primitives: self.input_assembler_primitives + other.input_assembler_primitives,
1805 vertex_shader_invocations: self.vertex_shader_invocations + other.vertex_shader_invocations,
1806 pixel_shader_primitives: self.pixel_shader_primitives + other.pixel_shader_primitives,
1807 compute_shader_invocations: self.compute_shader_invocations + other.compute_shader_invocations,
1808 }
1809 }
1810}
1811
1812/// Ability to add_assign 2 pipeline stats to accumulate
1813impl std::ops::AddAssign for PipelineStatistics {
1814 fn add_assign(&mut self, other: Self) {
1815 self.input_assembler_vertices += other.input_assembler_vertices;
1816 self.input_assembler_primitives += other.input_assembler_primitives;
1817 self.vertex_shader_invocations += other.vertex_shader_invocations;
1818 self.pixel_shader_primitives += other.pixel_shader_primitives;
1819 self.compute_shader_invocations += other.compute_shader_invocations;
1820 }
1821}
1822
1823/// Display for resource state enums
1824impl std::fmt::Display for ResourceState {
1825 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1826 write!(f, "{:?}", self)
1827 }
1828}