use crate::{WgpuAtlas, WgpuContext};use bytemuck::{Pod, Zeroable};use gpui::{ AtlasTextureId, Background, Bounds, DevicePixels, GpuSpecs, MonochromeSprite, Path, Point, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size, SubpixelSprite, Underline, get_gamma_correction_ratios,};use raw_window_handle::{HasDisplayHandle, HasWindowHandle};use std::num::NonZeroU64;use std::sync::Arc; #[repr(C)]#[derive(Clone, Copy, Pod, Zeroable)]struct GlobalParams { viewport_size: [f32; 2], premultiplied_alpha: u32, pad: u32,} #[repr(C)]#[derive(Clone, Copy, Pod, Zeroable)]struct PodBounds { origin: [f32; 2], size: [f32; 2],} impl From<Bounds<ScaledPixels>> for PodBounds { fn from(bounds: Bounds<ScaledPixels>) -> Self { Self { origin: [bounds.origin.x.0, bounds.origin.y.0], size: [bounds.size.width.0, bounds.size.height.0], } }} #[repr(C)]#[derive(Clone, Copy, Pod, Zeroable)]struct SurfaceParams { bounds: PodBounds, content_mask: PodBounds,} #[repr(C)]#[derive(Clone, Copy, Pod, Zeroable)]struct GammaParams { gamma_ratios: [f32; 4], grayscale_enhanced_contrast: f32, subpixel_enhanced_contrast: f32, _pad: [f32; 2],} #[derive(Clone, Debug)]#[repr(C)]struct PathSprite { bounds: Bounds<ScaledPixels>,} #[derive(Clone, Debug)]#[repr(C)]struct PathRasterizationVertex { xy_position: Point<ScaledPixels>, st_position: Point<f32>, color: Background, bounds: Bounds<ScaledPixels>,} pub struct WgpuSurfaceConfig { pub size: Size<DevicePixels>, pub transparent: bool,} struct WgpuPipelines { quads: wgpu::RenderPipeline, shadows: wgpu::RenderPipeline, path_rasterization: wgpu::RenderPipeline, paths: wgpu::RenderPipeline, underlines: wgpu::RenderPipeline, mono_sprites: wgpu::RenderPipeline, subpixel_sprites: Option<wgpu::RenderPipeline>, poly_sprites: wgpu::RenderPipeline, #[allow(dead_code)] surfaces: wgpu::RenderPipeline,} struct WgpuBindGroupLayouts { globals: wgpu::BindGroupLayout, instances: wgpu::BindGroupLayout, instances_with_texture: wgpu::BindGroupLayout, surfaces: wgpu::BindGroupLayout,} pub struct WgpuRenderer { device: Arc<wgpu::Device>, queue: Arc<wgpu::Queue>, surface: wgpu::Surface<'static>, surface_config: wgpu::SurfaceConfiguration, pipelines: WgpuPipelines, bind_group_layouts: WgpuBindGroupLayouts, atlas: Arc<WgpuAtlas>, atlas_sampler: wgpu::Sampler, globals_buffer: wgpu::Buffer, path_globals_offset: u64, gamma_offset: u64, globals_bind_group: wgpu::BindGroup, path_globals_bind_group: wgpu::BindGroup, instance_buffer: wgpu::Buffer, instance_buffer_capacity: u64, storage_buffer_alignment: u64, path_intermediate_texture: wgpu::Texture, path_intermediate_view: wgpu::TextureView, path_msaa_texture: Option<wgpu::Texture>, path_msaa_view: Option<wgpu::TextureView>, rendering_params: RenderingParameters, dual_source_blending: bool, adapter_info: wgpu::AdapterInfo, transparent_alpha_mode: wgpu::CompositeAlphaMode, opaque_alpha_mode: wgpu::CompositeAlphaMode,} impl WgpuRenderer { /// Creates a new WgpuRenderer from raw window handles. /// /// # Safety /// The caller must ensure that the window handle remains valid for the lifetime /// of the returned renderer. pub fn new<W: HasWindowHandle + HasDisplayHandle>( context: &WgpuContext, window: &W, config: WgpuSurfaceConfig, ) -> anyhow::Result<Self> { let window_handle = window .window_handle() .map_err(|e| anyhow::anyhow!("Failed to get window handle: {e}"))?; let display_handle = window .display_handle() .map_err(|e| anyhow::anyhow!("Failed to get display handle: {e}"))?; let target = wgpu::SurfaceTargetUnsafe::RawHandle { raw_display_handle: display_handle.as_raw(), raw_window_handle: window_handle.as_raw(), }; // Safety: The caller guarantees that the window handle is valid for the // lifetime of this renderer. In practice, the RawWindow struct is created // from the native window handles and the surface is dropped before the window. let surface = unsafe { context .instance .create_surface_unsafe(target) .map_err(|e| anyhow::anyhow!("Failed to create surface: {e}"))? }; let surface_caps = surface.get_capabilities(&context.adapter); // Prefer standard 8-bit non-sRGB formats that don't require special features. // Other formats like Rgba16Unorm require TEXTURE_FORMAT_16BIT_NORM which may // not be available on all devices. let preferred_formats = [ wgpu::TextureFormat::Bgra8Unorm, wgpu::TextureFormat::Rgba8Unorm, ]; let surface_format = preferred_formats .iter() .find(|f| surface_caps.formats.contains(f)) .copied() .or_else(|| surface_caps.formats.iter().find(|f| !f.is_srgb()).copied()) .unwrap_or(surface_caps.formats[0]); let pick_alpha_mode = |preferences: &[wgpu::CompositeAlphaMode]| -> wgpu::CompositeAlphaMode { preferences .iter() .find(|p| surface_caps.alpha_modes.contains(p)) .copied() .unwrap_or(surface_caps.alpha_modes[0]) }; let transparent_alpha_mode = pick_alpha_mode(&[ wgpu::CompositeAlphaMode::PreMultiplied, wgpu::CompositeAlphaMode::Inherit, ]); let opaque_alpha_mode = pick_alpha_mode(&[ wgpu::CompositeAlphaMode::Opaque, wgpu::CompositeAlphaMode::Inherit, ]); let alpha_mode = if config.transparent { transparent_alpha_mode } else { opaque_alpha_mode }; let surface_config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: surface_format, width: config.size.width.0 as u32, height: config.size.height.0 as u32, present_mode: wgpu::PresentMode::Fifo, desired_maximum_frame_latency: 2, alpha_mode, view_formats: vec![], }; surface.configure(&context.device, &surface_config); let device = Arc::clone(&context.device); let queue = Arc::clone(&context.queue); let dual_source_blending = context.supports_dual_source_blending(); let rendering_params = RenderingParameters::new(&context.adapter, surface_format); let bind_group_layouts = Self::create_bind_group_layouts(&device); let pipelines = Self::create_pipelines( &device, &bind_group_layouts, surface_format, alpha_mode, rendering_params.path_sample_count, dual_source_blending, ); let atlas = Arc::new(WgpuAtlas::new(Arc::clone(&device), Arc::clone(&queue))); let atlas_sampler = device.create_sampler(&wgpu::SamplerDescriptor { label: Some("atlas_sampler"), mag_filter: wgpu::FilterMode::Linear, min_filter: wgpu::FilterMode::Linear, ..Default::default() }); let uniform_alignment = device.limits().min_uniform_buffer_offset_alignment as u64; let globals_size = std::mem::size_of::<GlobalParams>() as u64; let gamma_size = std::mem::size_of::<GammaParams>() as u64; let path_globals_offset = globals_size.next_multiple_of(uniform_alignment); let gamma_offset = (path_globals_offset + globals_size).next_multiple_of(uniform_alignment); let globals_buffer = device.create_buffer(&wgpu::BufferDescriptor { label: Some("globals_buffer"), size: gamma_offset + gamma_size, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, }); let storage_buffer_alignment = device.limits().min_storage_buffer_offset_alignment as u64; let initial_instance_buffer_capacity = 2 * 1024 * 1024; let instance_buffer = device.create_buffer(&wgpu::BufferDescriptor { label: Some("instance_buffer"), size: initial_instance_buffer_capacity, usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, }); let (path_intermediate_texture, path_intermediate_view) = Self::create_path_intermediate( &device, surface_format, config.size.width.0 as u32, config.size.height.0 as u32, ); let (path_msaa_texture, path_msaa_view) = Self::create_msaa_if_needed( &device, surface_format, config.size.width.0 as u32, config.size.height.0 as u32, rendering_params.path_sample_count, ) .map(|(t, v)| (Some(t), Some(v))) .unwrap_or((None, None)); let globals_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: Some("globals_bind_group"), layout: &bind_group_layouts.globals, entries: &[ wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &globals_buffer, offset: 0, size: Some(NonZeroU64::new(globals_size).unwrap()), }), }, wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &globals_buffer, offset: gamma_offset, size: Some(NonZeroU64::new(gamma_size).unwrap()), }), }, ], }); let path_globals_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: Some("path_globals_bind_group"), layout: &bind_group_layouts.globals, entries: &[ wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &globals_buffer, offset: path_globals_offset, size: Some(NonZeroU64::new(globals_size).unwrap()), }), }, wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &globals_buffer, offset: gamma_offset, size: Some(NonZeroU64::new(gamma_size).unwrap()), }), }, ], }); let adapter_info = context.adapter.get_info(); Ok(Self { device, queue, surface, surface_config, pipelines, bind_group_layouts, atlas, atlas_sampler, globals_buffer, path_globals_offset, gamma_offset, globals_bind_group, path_globals_bind_group, instance_buffer, instance_buffer_capacity: initial_instance_buffer_capacity, storage_buffer_alignment, path_intermediate_texture, path_intermediate_view, path_msaa_texture, path_msaa_view, rendering_params, dual_source_blending, adapter_info, transparent_alpha_mode, opaque_alpha_mode, }) } fn create_bind_group_layouts(device: &wgpu::Device) -> WgpuBindGroupLayouts { let globals = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("globals_layout"), entries: &[ wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: NonZeroU64::new( std::mem::size_of::<GlobalParams>() as u64 ), }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: NonZeroU64::new( std::mem::size_of::<GammaParams>() as u64 ), }, count: None, }, ], }); let storage_buffer_entry = |binding: u32| wgpu::BindGroupLayoutEntry { binding, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Storage { read_only: true }, has_dynamic_offset: false, min_binding_size: None, }, count: None, }; let instances = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("instances_layout"), entries: &[storage_buffer_entry(0)], }); let instances_with_texture = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("instances_with_texture_layout"), entries: &[ storage_buffer_entry(0), wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), count: None, }, ], }); let surfaces = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("surfaces_layout"), entries: &[ wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: NonZeroU64::new( std::mem::size_of::<SurfaceParams>() as u64 ), }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), count: None, }, ], }); WgpuBindGroupLayouts { globals, instances, instances_with_texture, surfaces, } } fn create_pipelines( device: &wgpu::Device, layouts: &WgpuBindGroupLayouts, surface_format: wgpu::TextureFormat, alpha_mode: wgpu::CompositeAlphaMode, path_sample_count: u32, dual_source_blending: bool, ) -> WgpuPipelines { let shader_source = include_str!("shaders.wgsl"); let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor { label: Some("gpui_shaders"), source: wgpu::ShaderSource::Wgsl(shader_source.into()), }); let blend_mode = match alpha_mode { wgpu::CompositeAlphaMode::PreMultiplied => { wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING } _ => wgpu::BlendState::ALPHA_BLENDING, }; let color_target = wgpu::ColorTargetState { format: surface_format, blend: Some(blend_mode), write_mask: wgpu::ColorWrites::ALL, }; let create_pipeline = |name: &str, vs_entry: &str, fs_entry: &str, globals_layout: &wgpu::BindGroupLayout, data_layout: &wgpu::BindGroupLayout, topology: wgpu::PrimitiveTopology,Lines 1–500 of 1390. Load more
use crate::{WgpuAtlas, WgpuContext}; use bytemuck::{Pod, Zeroable}; use gpui::{ AtlasTextureId, Background, Bounds, DevicePixels, GpuSpecs, MonochromeSprite, Path, Point, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size, SubpixelSprite, Underline, get_gamma_correction_ratios, }; use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::num::NonZeroU64; use std::sync::Arc; #[repr(C)] #[derive(Clone, Copy, Pod, Zeroable)] struct GlobalParams { viewport_size: [f32; 2], premultiplied_alpha: u32, pad: u32, } #[repr(C)] #[derive(Clone, Copy, Pod, Zeroable)] struct PodBounds { origin: [f32; 2], size: [f32; 2], } impl From<Bounds<ScaledPixels>> for PodBounds { fn from(bounds: Bounds<ScaledPixels>) -> Self { Self { origin: [bounds.origin.x.0, bounds.origin.y.0], size: [bounds.size.width.0, bounds.size.height.0], } } } #[repr(C)] #[derive(Clone, Copy, Pod, Zeroable)] struct SurfaceParams { bounds: PodBounds, content_mask: PodBounds, } #[repr(C)] #[derive(Clone, Copy, Pod, Zeroable)] struct GammaParams { gamma_ratios: [f32; 4], grayscale_enhanced_contrast: f32, subpixel_enhanced_contrast: f32, _pad: [f32; 2], } #[derive(Clone, Debug)] #[repr(C)] struct PathSprite { bounds: Bounds<ScaledPixels>, } #[derive(Clone, Debug)] #[repr(C)] struct PathRasterizationVertex { xy_position: Point<ScaledPixels>, st_position: Point<f32>, color: Background, bounds: Bounds<ScaledPixels>, } pub struct WgpuSurfaceConfig { pub size: Size<DevicePixels>, pub transparent: bool, } struct WgpuPipelines { quads: wgpu::RenderPipeline, shadows: wgpu::RenderPipeline, path_rasterization: wgpu::RenderPipeline, paths: wgpu::RenderPipeline, underlines: wgpu::RenderPipeline, mono_sprites: wgpu::RenderPipeline, subpixel_sprites: Option<wgpu::RenderPipeline>, poly_sprites: wgpu::RenderPipeline, #[allow(dead_code)] surfaces: wgpu::RenderPipeline, } struct WgpuBindGroupLayouts { globals: wgpu::BindGroupLayout, instances: wgpu::BindGroupLayout, instances_with_texture: wgpu::BindGroupLayout, surfaces: wgpu::BindGroupLayout, } pub struct WgpuRenderer { device: Arc<wgpu::Device>, queue: Arc<wgpu::Queue>, surface: wgpu::Surface<'static>, surface_config: wgpu::SurfaceConfiguration, pipelines: WgpuPipelines, bind_group_layouts: WgpuBindGroupLayouts, atlas: Arc<WgpuAtlas>, atlas_sampler: wgpu::Sampler, globals_buffer: wgpu::Buffer, path_globals_offset: u64, gamma_offset: u64, globals_bind_group: wgpu::BindGroup, path_globals_bind_group: wgpu::BindGroup, instance_buffer: wgpu::Buffer, instance_buffer_capacity: u64, storage_buffer_alignment: u64, path_intermediate_texture: wgpu::Texture, path_intermediate_view: wgpu::TextureView, path_msaa_texture: Option<wgpu::Texture>, path_msaa_view: Option<wgpu::TextureView>, rendering_params: RenderingParameters, dual_source_blending: bool, adapter_info: wgpu::AdapterInfo, transparent_alpha_mode: wgpu::CompositeAlphaMode, opaque_alpha_mode: wgpu::CompositeAlphaMode, } impl WgpuRenderer { /// Creates a new WgpuRenderer from raw window handles. /// /// # Safety /// The caller must ensure that the window handle remains valid for the lifetime /// of the returned renderer. pub fn new<W: HasWindowHandle + HasDisplayHandle>( context: &WgpuContext, window: &W, config: WgpuSurfaceConfig, ) -> anyhow::Result<Self> { let window_handle = window .window_handle() .map_err(|e| anyhow::anyhow!("Failed to get window handle: {e}"))?; let display_handle = window .display_handle() .map_err(|e| anyhow::anyhow!("Failed to get display handle: {e}"))?; let target = wgpu::SurfaceTargetUnsafe::RawHandle { raw_display_handle: display_handle.as_raw(), raw_window_handle: window_handle.as_raw(), }; // Safety: The caller guarantees that the window handle is valid for the // lifetime of this renderer. In practice, the RawWindow struct is created // from the native window handles and the surface is dropped before the window. let surface = unsafe { context .instance .create_surface_unsafe(target) .map_err(|e| anyhow::anyhow!("Failed to create surface: {e}"))? }; let surface_caps = surface.get_capabilities(&context.adapter); // Prefer standard 8-bit non-sRGB formats that don't require special features. // Other formats like Rgba16Unorm require TEXTURE_FORMAT_16BIT_NORM which may // not be available on all devices. let preferred_formats = [ wgpu::TextureFormat::Bgra8Unorm, wgpu::TextureFormat::Rgba8Unorm, ]; let surface_format = preferred_formats .iter() .find(|f| surface_caps.formats.contains(f)) .copied() .or_else(|| surface_caps.formats.iter().find(|f| !f.is_srgb()).copied()) .unwrap_or(surface_caps.formats[0]); let pick_alpha_mode = |preferences: &[wgpu::CompositeAlphaMode]| -> wgpu::CompositeAlphaMode { preferences .iter() .find(|p| surface_caps.alpha_modes.contains(p)) .copied() .unwrap_or(surface_caps.alpha_modes[0]) }; let transparent_alpha_mode = pick_alpha_mode(&[ wgpu::CompositeAlphaMode::PreMultiplied, wgpu::CompositeAlphaMode::Inherit, ]); let opaque_alpha_mode = pick_alpha_mode(&[ wgpu::CompositeAlphaMode::Opaque, wgpu::CompositeAlphaMode::Inherit, ]); let alpha_mode = if config.transparent { transparent_alpha_mode } else { opaque_alpha_mode }; let surface_config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: surface_format, width: config.size.width.0 as u32, height: config.size.height.0 as u32, present_mode: wgpu::PresentMode::Fifo, desired_maximum_frame_latency: 2, alpha_mode, view_formats: vec![], }; surface.configure(&context.device, &surface_config); let device = Arc::clone(&context.device); let queue = Arc::clone(&context.queue); let dual_source_blending = context.supports_dual_source_blending(); let rendering_params = RenderingParameters::new(&context.adapter, surface_format); let bind_group_layouts = Self::create_bind_group_layouts(&device); let pipelines = Self::create_pipelines( &device, &bind_group_layouts, surface_format, alpha_mode, rendering_params.path_sample_count, dual_source_blending, ); let atlas = Arc::new(WgpuAtlas::new(Arc::clone(&device), Arc::clone(&queue))); let atlas_sampler = device.create_sampler(&wgpu::SamplerDescriptor { label: Some("atlas_sampler"), mag_filter: wgpu::FilterMode::Linear, min_filter: wgpu::FilterMode::Linear, ..Default::default() }); let uniform_alignment = device.limits().min_uniform_buffer_offset_alignment as u64; let globals_size = std::mem::size_of::<GlobalParams>() as u64; let gamma_size = std::mem::size_of::<GammaParams>() as u64; let path_globals_offset = globals_size.next_multiple_of(uniform_alignment); let gamma_offset = (path_globals_offset + globals_size).next_multiple_of(uniform_alignment); let globals_buffer = device.create_buffer(&wgpu::BufferDescriptor { label: Some("globals_buffer"), size: gamma_offset + gamma_size, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, }); let storage_buffer_alignment = device.limits().min_storage_buffer_offset_alignment as u64; let initial_instance_buffer_capacity = 2 * 1024 * 1024; let instance_buffer = device.create_buffer(&wgpu::BufferDescriptor { label: Some("instance_buffer"), size: initial_instance_buffer_capacity, usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, }); let (path_intermediate_texture, path_intermediate_view) = Self::create_path_intermediate( &device, surface_format, config.size.width.0 as u32, config.size.height.0 as u32, ); let (path_msaa_texture, path_msaa_view) = Self::create_msaa_if_needed( &device, surface_format, config.size.width.0 as u32, config.size.height.0 as u32, rendering_params.path_sample_count, ) .map(|(t, v)| (Some(t), Some(v))) .unwrap_or((None, None)); let globals_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: Some("globals_bind_group"), layout: &bind_group_layouts.globals, entries: &[ wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &globals_buffer, offset: 0, size: Some(NonZeroU64::new(globals_size).unwrap()), }), }, wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &globals_buffer, offset: gamma_offset, size: Some(NonZeroU64::new(gamma_size).unwrap()), }), }, ], }); let path_globals_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: Some("path_globals_bind_group"), layout: &bind_group_layouts.globals, entries: &[ wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &globals_buffer, offset: path_globals_offset, size: Some(NonZeroU64::new(globals_size).unwrap()), }), }, wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &globals_buffer, offset: gamma_offset, size: Some(NonZeroU64::new(gamma_size).unwrap()), }), }, ], }); let adapter_info = context.adapter.get_info(); Ok(Self { device, queue, surface, surface_config, pipelines, bind_group_layouts, atlas, atlas_sampler, globals_buffer, path_globals_offset, gamma_offset, globals_bind_group, path_globals_bind_group, instance_buffer, instance_buffer_capacity: initial_instance_buffer_capacity, storage_buffer_alignment, path_intermediate_texture, path_intermediate_view, path_msaa_texture, path_msaa_view, rendering_params, dual_source_blending, adapter_info, transparent_alpha_mode, opaque_alpha_mode, }) } fn create_bind_group_layouts(device: &wgpu::Device) -> WgpuBindGroupLayouts { let globals = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("globals_layout"), entries: &[ wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: NonZeroU64::new( std::mem::size_of::<GlobalParams>() as u64 ), }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: NonZeroU64::new( std::mem::size_of::<GammaParams>() as u64 ), }, count: None, }, ], }); let storage_buffer_entry = |binding: u32| wgpu::BindGroupLayoutEntry { binding, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Storage { read_only: true }, has_dynamic_offset: false, min_binding_size: None, }, count: None, }; let instances = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("instances_layout"), entries: &[storage_buffer_entry(0)], }); let instances_with_texture = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("instances_with_texture_layout"), entries: &[ storage_buffer_entry(0), wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), count: None, }, ], }); let surfaces = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("surfaces_layout"), entries: &[ wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: NonZeroU64::new( std::mem::size_of::<SurfaceParams>() as u64 ), }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), count: None, }, ], }); WgpuBindGroupLayouts { globals, instances, instances_with_texture, surfaces, } } fn create_pipelines( device: &wgpu::Device, layouts: &WgpuBindGroupLayouts, surface_format: wgpu::TextureFormat, alpha_mode: wgpu::CompositeAlphaMode, path_sample_count: u32, dual_source_blending: bool, ) -> WgpuPipelines { let shader_source = include_str!("shaders.wgsl"); let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor { label: Some("gpui_shaders"), source: wgpu::ShaderSource::Wgsl(shader_source.into()), }); let blend_mode = match alpha_mode { wgpu::CompositeAlphaMode::PreMultiplied => { wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING } _ => wgpu::BlendState::ALPHA_BLENDING, }; let color_target = wgpu::ColorTargetState { format: surface_format, blend: Some(blend_mode), write_mask: wgpu::ColorWrites::ALL, }; let create_pipeline = |name: &str, vs_entry: &str, fs_entry: &str, globals_layout: &wgpu::BindGroupLayout, data_layout: &wgpu::BindGroupLayout, topology: wgpu::PrimitiveTopology,