1#[cfg(not(any(windows, webgl)))]
84mod egl;
85#[cfg(Emscripten)]
86mod emscripten;
87#[cfg(webgl)]
88mod web;
89#[cfg(windows)]
90mod wgl;
91
92mod adapter;
93mod command;
94mod conv;
95mod device;
96mod fence;
97mod queue;
98
99pub use fence::Fence;
100
101#[cfg(not(any(windows, webgl)))]
102pub use self::egl::{AdapterContext, AdapterContextLock};
103#[cfg(not(any(windows, webgl)))]
104use self::egl::{Instance, Surface};
105
106#[cfg(webgl)]
107pub use self::web::AdapterContext;
108#[cfg(webgl)]
109use self::web::{Instance, Surface};
110
111#[cfg(windows)]
112use self::wgl::AdapterContext;
113#[cfg(windows)]
114use self::wgl::{Instance, Surface};
115
116use alloc::{boxed::Box, string::String, string::ToString as _, sync::Arc, vec::Vec};
117use core::{
118 fmt,
119 ops::Range,
120 sync::atomic::{AtomicU32, AtomicU8},
121};
122use parking_lot::Mutex;
123
124use arrayvec::ArrayVec;
125use glow::HasContext;
126use naga::FastHashMap;
127
128use crate::{CopyExtent, TextureDescriptor};
129
130#[derive(Clone, Debug)]
131pub struct Api;
132
133const MAX_TEXTURE_SLOTS: usize = 16;
136const MAX_SAMPLERS: usize = 16;
137const MAX_VERTEX_ATTRIBUTES: usize = 16;
138const ZERO_BUFFER_SIZE: usize = 256 << 10;
139const MAX_PUSH_CONSTANTS: usize = 64;
140const MAX_PUSH_CONSTANT_COMMANDS: usize = MAX_PUSH_CONSTANTS * crate::MAX_CONCURRENT_SHADER_STAGES;
142
143impl crate::Api for Api {
144 type Instance = Instance;
145 type Surface = Surface;
146 type Adapter = Adapter;
147 type Device = Device;
148
149 type Queue = Queue;
150 type CommandEncoder = CommandEncoder;
151 type CommandBuffer = CommandBuffer;
152
153 type Buffer = Buffer;
154 type Texture = Texture;
155 type SurfaceTexture = Texture;
156 type TextureView = TextureView;
157 type Sampler = Sampler;
158 type QuerySet = QuerySet;
159 type Fence = Fence;
160 type AccelerationStructure = AccelerationStructure;
161 type PipelineCache = PipelineCache;
162
163 type BindGroupLayout = BindGroupLayout;
164 type BindGroup = BindGroup;
165 type PipelineLayout = PipelineLayout;
166 type ShaderModule = ShaderModule;
167 type RenderPipeline = RenderPipeline;
168 type ComputePipeline = ComputePipeline;
169}
170
171crate::impl_dyn_resource!(
172 Adapter,
173 AccelerationStructure,
174 BindGroup,
175 BindGroupLayout,
176 Buffer,
177 CommandBuffer,
178 CommandEncoder,
179 ComputePipeline,
180 Device,
181 Fence,
182 Instance,
183 PipelineCache,
184 PipelineLayout,
185 QuerySet,
186 Queue,
187 RenderPipeline,
188 Sampler,
189 ShaderModule,
190 Surface,
191 Texture,
192 TextureView
193);
194
195bitflags::bitflags! {
196 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
199 struct PrivateCapabilities: u32 {
200 const BUFFER_ALLOCATION = 1 << 0;
202 const SHADER_BINDING_LAYOUT = 1 << 1;
204 const SHADER_TEXTURE_SHADOW_LOD = 1 << 2;
206 const MEMORY_BARRIERS = 1 << 3;
208 const VERTEX_BUFFER_LAYOUT = 1 << 4;
210 const INDEX_BUFFER_ROLE_CHANGE = 1 << 5;
213 const GET_BUFFER_SUB_DATA = 1 << 7;
215 const COLOR_BUFFER_HALF_FLOAT = 1 << 8;
217 const COLOR_BUFFER_FLOAT = 1 << 9;
219 const QUERY_BUFFERS = 1 << 11;
221 const QUERY_64BIT = 1 << 12;
223 const TEXTURE_STORAGE = 1 << 13;
225 const DEBUG_FNS = 1 << 14;
227 const INVALIDATE_FRAMEBUFFER = 1 << 15;
229 const FULLY_FEATURED_INSTANCING = 1 << 16;
233 }
234}
235
236bitflags::bitflags! {
237 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
239 struct Workarounds: u32 {
240 const MESA_I915_SRGB_SHADER_CLEAR = 1 << 0;
247 const EMULATE_BUFFER_MAP = 1 << 1;
249 }
250}
251
252type BindTarget = u32;
253
254#[derive(Debug, Clone, Copy)]
255enum VertexAttribKind {
256 Float, Integer, }
260
261impl Default for VertexAttribKind {
262 fn default() -> Self {
263 Self::Float
264 }
265}
266
267#[derive(Clone, Debug)]
268pub struct TextureFormatDesc {
269 pub internal: u32,
270 pub external: u32,
271 pub data_type: u32,
272}
273
274struct AdapterShared {
275 context: AdapterContext,
276 private_caps: PrivateCapabilities,
277 features: wgt::Features,
278 limits: wgt::Limits,
279 workarounds: Workarounds,
280 options: wgt::GlBackendOptions,
281 shading_language_version: naga::back::glsl::Version,
282 next_shader_id: AtomicU32,
283 program_cache: Mutex<ProgramCache>,
284 es: bool,
285
286 max_msaa_samples: i32,
290}
291
292pub struct Adapter {
293 shared: Arc<AdapterShared>,
294}
295
296pub struct Device {
297 shared: Arc<AdapterShared>,
298 main_vao: glow::VertexArray,
299 #[cfg(all(native, feature = "renderdoc"))]
300 render_doc: crate::auxil::renderdoc::RenderDoc,
301 counters: Arc<wgt::HalCounters>,
302}
303
304impl Drop for Device {
305 fn drop(&mut self) {
306 let gl = &self.shared.context.lock();
307 unsafe { gl.delete_vertex_array(self.main_vao) };
308 }
309}
310
311pub struct ShaderClearProgram {
312 pub program: glow::Program,
313 pub color_uniform_location: glow::UniformLocation,
314}
315
316pub struct Queue {
317 shared: Arc<AdapterShared>,
318 features: wgt::Features,
319 draw_fbo: glow::Framebuffer,
320 copy_fbo: glow::Framebuffer,
321 shader_clear_program: Option<ShaderClearProgram>,
324 zero_buffer: glow::Buffer,
327 temp_query_results: Mutex<Vec<u64>>,
328 draw_buffer_count: AtomicU8,
329 current_index_buffer: Mutex<Option<glow::Buffer>>,
330}
331
332impl Drop for Queue {
333 fn drop(&mut self) {
334 let gl = &self.shared.context.lock();
335 unsafe { gl.delete_framebuffer(self.draw_fbo) };
336 unsafe { gl.delete_framebuffer(self.copy_fbo) };
337 unsafe { gl.delete_buffer(self.zero_buffer) };
338 }
339}
340
341#[derive(Clone, Debug)]
342pub struct Buffer {
343 raw: Option<glow::Buffer>,
344 target: BindTarget,
345 size: wgt::BufferAddress,
346 map_flags: u32,
347 data: Option<Arc<MaybeMutex<Vec<u8>>>>,
348 offset_of_current_mapping: Arc<MaybeMutex<wgt::BufferAddress>>,
349}
350
351#[cfg(send_sync)]
352unsafe impl Sync for Buffer {}
353#[cfg(send_sync)]
354unsafe impl Send for Buffer {}
355
356impl crate::DynBuffer for Buffer {}
357
358#[derive(Clone, Debug)]
359pub enum TextureInner {
360 Renderbuffer {
361 raw: glow::Renderbuffer,
362 },
363 DefaultRenderbuffer,
364 Texture {
365 raw: glow::Texture,
366 target: BindTarget,
367 },
368 #[cfg(webgl)]
369 ExternalFramebuffer {
373 inner: web_sys::WebGlFramebuffer,
374 },
375 #[cfg(native)]
376 ExternalNativeFramebuffer {
382 inner: glow::NativeFramebuffer,
383 },
384}
385
386#[cfg(send_sync)]
387unsafe impl Sync for TextureInner {}
388#[cfg(send_sync)]
389unsafe impl Send for TextureInner {}
390
391impl TextureInner {
392 fn as_native(&self) -> (glow::Texture, BindTarget) {
393 match *self {
394 Self::Renderbuffer { .. } | Self::DefaultRenderbuffer => {
395 panic!("Unexpected renderbuffer");
396 }
397 Self::Texture { raw, target } => (raw, target),
398 #[cfg(webgl)]
399 Self::ExternalFramebuffer { .. } => panic!("Unexpected external framebuffer"),
400 #[cfg(native)]
401 Self::ExternalNativeFramebuffer { .. } => panic!("unexpected external framebuffer"),
402 }
403 }
404}
405
406#[derive(Debug)]
407pub struct Texture {
408 pub inner: TextureInner,
409 pub drop_guard: Option<crate::DropGuard>,
410 pub mip_level_count: u32,
411 pub array_layer_count: u32,
412 pub format: wgt::TextureFormat,
413 #[allow(unused)]
414 pub format_desc: TextureFormatDesc,
415 pub copy_size: CopyExtent,
416}
417
418impl crate::DynTexture for Texture {}
419impl crate::DynSurfaceTexture for Texture {}
420
421impl core::borrow::Borrow<dyn crate::DynTexture> for Texture {
422 fn borrow(&self) -> &dyn crate::DynTexture {
423 self
424 }
425}
426
427impl Texture {
428 pub fn default_framebuffer(format: wgt::TextureFormat) -> Self {
429 Self {
430 inner: TextureInner::DefaultRenderbuffer,
431 drop_guard: None,
432 mip_level_count: 1,
433 array_layer_count: 1,
434 format,
435 format_desc: TextureFormatDesc {
436 internal: 0,
437 external: 0,
438 data_type: 0,
439 },
440 copy_size: CopyExtent {
441 width: 0,
442 height: 0,
443 depth: 0,
444 },
445 }
446 }
447
448 fn get_info_from_desc(desc: &TextureDescriptor) -> u32 {
450 match desc.dimension {
451 wgt::TextureDimension::D1 => glow::TEXTURE_2D,
454 wgt::TextureDimension::D2 => {
455 match (desc.is_cube_compatible(), desc.size.depth_or_array_layers) {
457 (false, 1) => glow::TEXTURE_2D,
458 (false, _) => glow::TEXTURE_2D_ARRAY,
459 (true, 6) => glow::TEXTURE_CUBE_MAP,
460 (true, _) => glow::TEXTURE_CUBE_MAP_ARRAY,
461 }
462 }
463 wgt::TextureDimension::D3 => glow::TEXTURE_3D,
464 }
465 }
466
467 fn log_failing_target_heuristics(view_dimension: wgt::TextureViewDimension, target: u32) {
469 let expected_target = match view_dimension {
470 wgt::TextureViewDimension::D1 => glow::TEXTURE_2D,
471 wgt::TextureViewDimension::D2 => glow::TEXTURE_2D,
472 wgt::TextureViewDimension::D2Array => glow::TEXTURE_2D_ARRAY,
473 wgt::TextureViewDimension::Cube => glow::TEXTURE_CUBE_MAP,
474 wgt::TextureViewDimension::CubeArray => glow::TEXTURE_CUBE_MAP_ARRAY,
475 wgt::TextureViewDimension::D3 => glow::TEXTURE_3D,
476 };
477
478 if expected_target == target {
479 return;
480 }
481
482 let buffer;
483 let got = match target {
484 glow::TEXTURE_2D => "D2",
485 glow::TEXTURE_2D_ARRAY => "D2Array",
486 glow::TEXTURE_CUBE_MAP => "Cube",
487 glow::TEXTURE_CUBE_MAP_ARRAY => "CubeArray",
488 glow::TEXTURE_3D => "D3",
489 target => {
490 buffer = target.to_string();
491 &buffer
492 }
493 };
494
495 log::error!(
496 concat!(
497 "wgpu-hal heuristics assumed that ",
498 "the view dimension will be equal to `{}` rather than `{:?}`.\n",
499 "`D2` textures with ",
500 "`depth_or_array_layers == 1` ",
501 "are assumed to have view dimension `D2`\n",
502 "`D2` textures with ",
503 "`depth_or_array_layers > 1` ",
504 "are assumed to have view dimension `D2Array`\n",
505 "`D2` textures with ",
506 "`depth_or_array_layers == 6` ",
507 "are assumed to have view dimension `Cube`\n",
508 "`D2` textures with ",
509 "`depth_or_array_layers > 6 && depth_or_array_layers % 6 == 0` ",
510 "are assumed to have view dimension `CubeArray`\n",
511 ),
512 got,
513 view_dimension,
514 );
515 }
516}
517
518#[derive(Clone, Debug)]
519pub struct TextureView {
520 inner: TextureInner,
521 aspects: crate::FormatAspects,
522 mip_levels: Range<u32>,
523 array_layers: Range<u32>,
524 format: wgt::TextureFormat,
525}
526
527impl crate::DynTextureView for TextureView {}
528
529#[derive(Debug)]
530pub struct Sampler {
531 raw: glow::Sampler,
532}
533
534impl crate::DynSampler for Sampler {}
535
536#[derive(Debug)]
537pub struct BindGroupLayout {
538 entries: Arc<[wgt::BindGroupLayoutEntry]>,
539}
540
541impl crate::DynBindGroupLayout for BindGroupLayout {}
542
543#[derive(Debug)]
544struct BindGroupLayoutInfo {
545 entries: Arc<[wgt::BindGroupLayoutEntry]>,
546 binding_to_slot: Box<[u8]>,
552}
553
554#[derive(Debug)]
555pub struct PipelineLayout {
556 group_infos: Box<[BindGroupLayoutInfo]>,
557 naga_options: naga::back::glsl::Options,
558}
559
560impl crate::DynPipelineLayout for PipelineLayout {}
561
562impl PipelineLayout {
563 fn get_slot(&self, br: &naga::ResourceBinding) -> u8 {
564 let group_info = &self.group_infos[br.group as usize];
565 group_info.binding_to_slot[br.binding as usize]
566 }
567}
568
569#[derive(Debug)]
570enum BindingRegister {
571 UniformBuffers,
572 StorageBuffers,
573 Textures,
574 Images,
575}
576
577#[derive(Debug)]
578enum RawBinding {
579 Buffer {
580 raw: glow::Buffer,
581 offset: i32,
582 size: i32,
583 },
584 Texture {
585 raw: glow::Texture,
586 target: BindTarget,
587 aspects: crate::FormatAspects,
588 mip_levels: Range<u32>,
589 },
591 Image(ImageBinding),
592 Sampler(glow::Sampler),
593}
594
595#[derive(Debug)]
596pub struct BindGroup {
597 contents: Box<[RawBinding]>,
598}
599
600impl crate::DynBindGroup for BindGroup {}
601
602type ShaderId = u32;
603
604#[derive(Debug)]
605pub struct ShaderModule {
606 naga: crate::NagaShader,
607 label: Option<String>,
608 id: ShaderId,
609}
610
611impl crate::DynShaderModule for ShaderModule {}
612
613#[derive(Clone, Debug, Default)]
614struct VertexFormatDesc {
615 element_count: i32,
616 element_format: u32,
617 attrib_kind: VertexAttribKind,
618}
619
620#[derive(Clone, Debug, Default)]
621struct AttributeDesc {
622 location: u32,
623 offset: u32,
624 buffer_index: u32,
625 format_desc: VertexFormatDesc,
626}
627
628#[derive(Clone, Debug)]
629struct BufferBinding {
630 raw: glow::Buffer,
631 offset: wgt::BufferAddress,
632}
633
634#[derive(Clone, Debug)]
635struct ImageBinding {
636 raw: glow::Texture,
637 mip_level: u32,
638 array_layer: Option<u32>,
639 access: u32,
640 format: u32,
641}
642
643#[derive(Clone, Debug, Default, PartialEq)]
644struct VertexBufferDesc {
645 step: wgt::VertexStepMode,
646 stride: u32,
647}
648
649#[derive(Clone, Debug)]
650struct PushConstantDesc {
651 location: glow::UniformLocation,
652 ty: naga::TypeInner,
653 offset: u32,
654 size_bytes: u32,
655}
656
657#[cfg(send_sync)]
658unsafe impl Sync for PushConstantDesc {}
659#[cfg(send_sync)]
660unsafe impl Send for PushConstantDesc {}
661
662type SamplerBindMap = [Option<u8>; MAX_TEXTURE_SLOTS];
665
666#[derive(Debug)]
667struct PipelineInner {
668 program: glow::Program,
669 sampler_map: SamplerBindMap,
670 first_instance_location: Option<glow::UniformLocation>,
671 push_constant_descs: ArrayVec<PushConstantDesc, MAX_PUSH_CONSTANT_COMMANDS>,
672 clip_distance_count: u32,
673}
674
675#[derive(Clone, Debug)]
676struct DepthState {
677 function: u32,
678 mask: bool,
679}
680
681#[derive(Clone, Debug, PartialEq)]
682struct BlendComponent {
683 src: u32,
684 dst: u32,
685 equation: u32,
686}
687
688#[derive(Clone, Debug, PartialEq)]
689struct BlendDesc {
690 alpha: BlendComponent,
691 color: BlendComponent,
692}
693
694#[derive(Clone, Debug, Default, PartialEq)]
695struct ColorTargetDesc {
696 mask: wgt::ColorWrites,
697 blend: Option<BlendDesc>,
698}
699
700#[derive(PartialEq, Eq, Hash)]
701struct ProgramStage {
702 naga_stage: naga::ShaderStage,
703 shader_id: ShaderId,
704 entry_point: String,
705 zero_initialize_workgroup_memory: bool,
706}
707
708#[derive(PartialEq, Eq, Hash)]
709struct ProgramCacheKey {
710 stages: ArrayVec<ProgramStage, 3>,
711 group_to_binding_to_slot: Box<[Box<[u8]>]>,
712}
713
714type ProgramCache = FastHashMap<ProgramCacheKey, Result<Arc<PipelineInner>, crate::PipelineError>>;
715
716#[derive(Debug)]
717pub struct RenderPipeline {
718 inner: Arc<PipelineInner>,
719 primitive: wgt::PrimitiveState,
720 vertex_buffers: Box<[VertexBufferDesc]>,
721 vertex_attributes: Box<[AttributeDesc]>,
722 color_targets: Box<[ColorTargetDesc]>,
723 depth: Option<DepthState>,
724 depth_bias: wgt::DepthBiasState,
725 stencil: Option<StencilState>,
726 alpha_to_coverage_enabled: bool,
727}
728
729impl crate::DynRenderPipeline for RenderPipeline {}
730
731#[cfg(send_sync)]
732unsafe impl Sync for RenderPipeline {}
733#[cfg(send_sync)]
734unsafe impl Send for RenderPipeline {}
735
736#[derive(Debug)]
737pub struct ComputePipeline {
738 inner: Arc<PipelineInner>,
739}
740
741impl crate::DynComputePipeline for ComputePipeline {}
742
743#[cfg(send_sync)]
744unsafe impl Sync for ComputePipeline {}
745#[cfg(send_sync)]
746unsafe impl Send for ComputePipeline {}
747
748#[derive(Debug)]
749pub struct QuerySet {
750 queries: Box<[glow::Query]>,
751 target: BindTarget,
752}
753
754impl crate::DynQuerySet for QuerySet {}
755
756#[derive(Debug)]
757pub struct AccelerationStructure;
758
759impl crate::DynAccelerationStructure for AccelerationStructure {}
760
761#[derive(Debug)]
762pub struct PipelineCache;
763
764impl crate::DynPipelineCache for PipelineCache {}
765
766#[derive(Clone, Debug, PartialEq)]
767struct StencilOps {
768 pass: u32,
769 fail: u32,
770 depth_fail: u32,
771}
772
773impl Default for StencilOps {
774 fn default() -> Self {
775 Self {
776 pass: glow::KEEP,
777 fail: glow::KEEP,
778 depth_fail: glow::KEEP,
779 }
780 }
781}
782
783#[derive(Clone, Debug, PartialEq)]
784struct StencilSide {
785 function: u32,
786 mask_read: u32,
787 mask_write: u32,
788 reference: u32,
789 ops: StencilOps,
790}
791
792impl Default for StencilSide {
793 fn default() -> Self {
794 Self {
795 function: glow::ALWAYS,
796 mask_read: 0xFF,
797 mask_write: 0xFF,
798 reference: 0,
799 ops: StencilOps::default(),
800 }
801 }
802}
803
804#[derive(Debug, Clone, Default)]
805struct StencilState {
806 front: StencilSide,
807 back: StencilSide,
808}
809
810#[derive(Clone, Debug, Default, PartialEq)]
811struct PrimitiveState {
812 front_face: u32,
813 cull_face: u32,
814 unclipped_depth: bool,
815 polygon_mode: u32,
816}
817
818type InvalidatedAttachments = ArrayVec<u32, { crate::MAX_COLOR_ATTACHMENTS + 2 }>;
819
820#[derive(Debug)]
821enum Command {
822 Draw {
823 topology: u32,
824 first_vertex: u32,
825 vertex_count: u32,
826 first_instance: u32,
827 instance_count: u32,
828 first_instance_location: Option<glow::UniformLocation>,
829 },
830 DrawIndexed {
831 topology: u32,
832 index_type: u32,
833 index_count: u32,
834 index_offset: wgt::BufferAddress,
835 base_vertex: i32,
836 first_instance: u32,
837 instance_count: u32,
838 first_instance_location: Option<glow::UniformLocation>,
839 },
840 DrawIndirect {
841 topology: u32,
842 indirect_buf: glow::Buffer,
843 indirect_offset: wgt::BufferAddress,
844 first_instance_location: Option<glow::UniformLocation>,
845 },
846 DrawIndexedIndirect {
847 topology: u32,
848 index_type: u32,
849 indirect_buf: glow::Buffer,
850 indirect_offset: wgt::BufferAddress,
851 first_instance_location: Option<glow::UniformLocation>,
852 },
853 Dispatch([u32; 3]),
854 DispatchIndirect {
855 indirect_buf: glow::Buffer,
856 indirect_offset: wgt::BufferAddress,
857 },
858 ClearBuffer {
859 dst: Buffer,
860 dst_target: BindTarget,
861 range: crate::MemoryRange,
862 },
863 CopyBufferToBuffer {
864 src: Buffer,
865 src_target: BindTarget,
866 dst: Buffer,
867 dst_target: BindTarget,
868 copy: crate::BufferCopy,
869 },
870 #[cfg(webgl)]
871 CopyExternalImageToTexture {
872 src: wgt::CopyExternalImageSourceInfo,
873 dst: glow::Texture,
874 dst_target: BindTarget,
875 dst_format: wgt::TextureFormat,
876 dst_premultiplication: bool,
877 copy: crate::TextureCopy,
878 },
879 CopyTextureToTexture {
880 src: glow::Texture,
881 src_target: BindTarget,
882 dst: glow::Texture,
883 dst_target: BindTarget,
884 copy: crate::TextureCopy,
885 },
886 CopyBufferToTexture {
887 src: Buffer,
888 #[allow(unused)]
889 src_target: BindTarget,
890 dst: glow::Texture,
891 dst_target: BindTarget,
892 dst_format: wgt::TextureFormat,
893 copy: crate::BufferTextureCopy,
894 },
895 CopyTextureToBuffer {
896 src: glow::Texture,
897 src_target: BindTarget,
898 src_format: wgt::TextureFormat,
899 dst: Buffer,
900 #[allow(unused)]
901 dst_target: BindTarget,
902 copy: crate::BufferTextureCopy,
903 },
904 SetIndexBuffer(glow::Buffer),
905 BeginQuery(glow::Query, BindTarget),
906 EndQuery(BindTarget),
907 TimestampQuery(glow::Query),
908 CopyQueryResults {
909 query_range: Range<u32>,
910 dst: Buffer,
911 dst_target: BindTarget,
912 dst_offset: wgt::BufferAddress,
913 },
914 ResetFramebuffer {
915 is_default: bool,
916 },
917 BindAttachment {
918 attachment: u32,
919 view: TextureView,
920 depth_slice: Option<u32>,
921 },
922 ResolveAttachment {
923 attachment: u32,
924 dst: TextureView,
925 size: wgt::Extent3d,
926 },
927 InvalidateAttachments(InvalidatedAttachments),
928 SetDrawColorBuffers(u8),
929 ClearColorF {
930 draw_buffer: u32,
931 color: [f32; 4],
932 is_srgb: bool,
933 },
934 ClearColorU(u32, [u32; 4]),
935 ClearColorI(u32, [i32; 4]),
936 ClearDepth(f32),
937 ClearStencil(u32),
938 ClearDepthAndStencil(f32, u32),
943 BufferBarrier(glow::Buffer, wgt::BufferUses),
944 TextureBarrier(wgt::TextureUses),
945 SetViewport {
946 rect: crate::Rect<i32>,
947 depth: Range<f32>,
948 },
949 SetScissor(crate::Rect<i32>),
950 SetStencilFunc {
951 face: u32,
952 function: u32,
953 reference: u32,
954 read_mask: u32,
955 },
956 SetStencilOps {
957 face: u32,
958 write_mask: u32,
959 ops: StencilOps,
960 },
961 SetDepth(DepthState),
962 SetDepthBias(wgt::DepthBiasState),
963 ConfigureDepthStencil(crate::FormatAspects),
964 SetAlphaToCoverage(bool),
965 SetVertexAttribute {
966 buffer: Option<glow::Buffer>,
967 buffer_desc: VertexBufferDesc,
968 attribute_desc: AttributeDesc,
969 },
970 UnsetVertexAttribute(u32),
971 SetVertexBuffer {
972 index: u32,
973 buffer: BufferBinding,
974 buffer_desc: VertexBufferDesc,
975 },
976 SetProgram(glow::Program),
977 SetPrimitive(PrimitiveState),
978 SetBlendConstant([f32; 4]),
979 SetColorTarget {
980 draw_buffer_index: Option<u32>,
981 desc: ColorTargetDesc,
982 },
983 BindBuffer {
984 target: BindTarget,
985 slot: u32,
986 buffer: glow::Buffer,
987 offset: i32,
988 size: i32,
989 },
990 BindSampler(u32, Option<glow::Sampler>),
991 BindTexture {
992 slot: u32,
993 texture: glow::Texture,
994 target: BindTarget,
995 aspects: crate::FormatAspects,
996 mip_levels: Range<u32>,
997 },
998 BindImage {
999 slot: u32,
1000 binding: ImageBinding,
1001 },
1002 InsertDebugMarker(Range<u32>),
1003 PushDebugGroup(Range<u32>),
1004 PopDebugGroup,
1005 SetPushConstants {
1006 uniform: PushConstantDesc,
1007 offset: u32,
1009 },
1010 SetClipDistances {
1011 old_count: u32,
1012 new_count: u32,
1013 },
1014}
1015
1016#[derive(Default)]
1017pub struct CommandBuffer {
1018 label: Option<String>,
1019 commands: Vec<Command>,
1020 data_bytes: Vec<u8>,
1021 queries: Vec<glow::Query>,
1022}
1023
1024impl crate::DynCommandBuffer for CommandBuffer {}
1025
1026impl fmt::Debug for CommandBuffer {
1027 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1028 let mut builder = f.debug_struct("CommandBuffer");
1029 if let Some(ref label) = self.label {
1030 builder.field("label", label);
1031 }
1032 builder.finish()
1033 }
1034}
1035
1036#[cfg(send_sync)]
1037unsafe impl Sync for CommandBuffer {}
1038#[cfg(send_sync)]
1039unsafe impl Send for CommandBuffer {}
1040
1041pub struct CommandEncoder {
1046 cmd_buffer: CommandBuffer,
1047 state: command::State,
1048 private_caps: PrivateCapabilities,
1049 counters: Arc<wgt::HalCounters>,
1050}
1051
1052impl fmt::Debug for CommandEncoder {
1053 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1054 f.debug_struct("CommandEncoder")
1055 .field("cmd_buffer", &self.cmd_buffer)
1056 .finish()
1057 }
1058}
1059
1060#[cfg(send_sync)]
1061unsafe impl Sync for CommandEncoder {}
1062#[cfg(send_sync)]
1063unsafe impl Send for CommandEncoder {}
1064
1065#[cfg(not(webgl))]
1066fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, message: &str) {
1067 let source_str = match source {
1068 glow::DEBUG_SOURCE_API => "API",
1069 glow::DEBUG_SOURCE_WINDOW_SYSTEM => "Window System",
1070 glow::DEBUG_SOURCE_SHADER_COMPILER => "ShaderCompiler",
1071 glow::DEBUG_SOURCE_THIRD_PARTY => "Third Party",
1072 glow::DEBUG_SOURCE_APPLICATION => "Application",
1073 glow::DEBUG_SOURCE_OTHER => "Other",
1074 _ => unreachable!(),
1075 };
1076
1077 let log_severity = match severity {
1078 glow::DEBUG_SEVERITY_HIGH => log::Level::Error,
1079 glow::DEBUG_SEVERITY_MEDIUM => log::Level::Warn,
1080 glow::DEBUG_SEVERITY_LOW => log::Level::Info,
1081 glow::DEBUG_SEVERITY_NOTIFICATION => log::Level::Trace,
1082 _ => unreachable!(),
1083 };
1084
1085 let type_str = match gltype {
1086 glow::DEBUG_TYPE_DEPRECATED_BEHAVIOR => "Deprecated Behavior",
1087 glow::DEBUG_TYPE_ERROR => "Error",
1088 glow::DEBUG_TYPE_MARKER => "Marker",
1089 glow::DEBUG_TYPE_OTHER => "Other",
1090 glow::DEBUG_TYPE_PERFORMANCE => "Performance",
1091 glow::DEBUG_TYPE_POP_GROUP => "Pop Group",
1092 glow::DEBUG_TYPE_PORTABILITY => "Portability",
1093 glow::DEBUG_TYPE_PUSH_GROUP => "Push Group",
1094 glow::DEBUG_TYPE_UNDEFINED_BEHAVIOR => "Undefined Behavior",
1095 _ => unreachable!(),
1096 };
1097
1098 let _ = std::panic::catch_unwind(|| {
1099 log::log!(
1100 log_severity,
1101 "GLES: [{}/{}] ID {} : {}",
1102 source_str,
1103 type_str,
1104 id,
1105 message
1106 );
1107 });
1108
1109 #[cfg(feature = "validation_canary")]
1110 if cfg!(debug_assertions) && log_severity == log::Level::Error {
1111 crate::VALIDATION_CANARY.add(message.to_string());
1113 }
1114}
1115
1116cfg_if::cfg_if! {
1118 if #[cfg(gles_with_std)] {
1119 type MaybeMutex<T> = std::sync::Mutex<T>;
1120
1121 fn lock<T>(mutex: &MaybeMutex<T>) -> std::sync::MutexGuard<'_, T> {
1122 mutex.lock().unwrap()
1123 }
1124 } else {
1125 #[cfg(all(send_sync, not(feature = "fragile-send-sync-non-atomic-wasm")))]
1129 compile_error!("cannot provide non-fragile Send+Sync without std");
1130
1131 type MaybeMutex<T> = core::cell::RefCell<T>;
1132
1133 fn lock<T>(mutex: &MaybeMutex<T>) -> core::cell::RefMut<'_, T> {
1134 mutex.borrow_mut()
1135 }
1136 }
1137}