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