This commit is contained in:
nora 2026-01-01 03:03:28 +01:00
parent 45e2971d69
commit c883f37739

View file

@ -8,18 +8,18 @@ use wayland_client::{Proxy, protocol::wl_surface::WlSurface};
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
pub struct AppGpuState { pub struct AppGpuState {
wgpu_instance: wgpu::Instance, instance: wgpu::Instance,
wgpu_adapter: wgpu::Adapter, adapter: wgpu::Adapter,
wgpu_device: wgpu::Device, device: wgpu::Device,
wgpu_queue: wgpu::Queue, queue: wgpu::Queue,
wgpu_render_pipeline: wgpu::RenderPipeline, render_pipeline: wgpu::RenderPipeline,
wgpu_screen_size_bind_group_layout: wgpu::BindGroupLayout, screen_size_bind_group_layout: wgpu::BindGroupLayout,
} }
pub struct SurfaceGpuState { pub struct SurfaceGpuState {
wgpu_surface: wgpu::Surface<'static>, surface: wgpu::Surface<'static>,
wgpu_screen_size_buffer: wgpu::Buffer, screen_size_buffer: wgpu::Buffer,
wgpu_screen_size_bind_group: wgpu::BindGroup, screen_size_bind_group: wgpu::BindGroup,
} }
#[repr(C)] #[repr(C)]
@ -30,20 +30,18 @@ struct ScreenSizeUniform {
impl AppGpuState { impl AppGpuState {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let wgpu_instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default()); let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default());
let wgpu_adapter = pollster::block_on( let adapter =
wgpu_instance.request_adapter(&wgpu::RequestAdapterOptions::default()), pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions::default()))
) .wrap_err("failed to request adapter")?;
.wrap_err("failed to request adapter")?;
let (wgpu_device, wgpu_queue) = let (device, queue) = pollster::block_on(adapter.request_device(&Default::default()))
pollster::block_on(wgpu_adapter.request_device(&Default::default())) .wrap_err("failed to request device")?;
.wrap_err("failed to request device")?;
let shader = wgpu_device.create_shader_module(wgpu::include_wgsl!("shader.wgsl")); let shader = device.create_shader_module(wgpu::include_wgsl!("shader.wgsl"));
let wgpu_screen_size_bind_group_layout = let screen_size_bind_group_layout =
wgpu_device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None, label: None,
entries: &[wgpu::BindGroupLayoutEntry { entries: &[wgpu::BindGroupLayoutEntry {
binding: 0, binding: 0,
@ -57,58 +55,57 @@ impl AppGpuState {
}], }],
}); });
let render_pipeline_layout = let render_pipeline_layout =
wgpu_device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Render Pipeline Layout"), label: Some("Render Pipeline Layout"),
bind_group_layouts: &[&wgpu_screen_size_bind_group_layout], bind_group_layouts: &[&screen_size_bind_group_layout],
immediate_size: 0, immediate_size: 0,
}); });
let wgpu_render_pipeline = let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
wgpu_device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Render Pipeline"),
label: Some("Render Pipeline"), layout: Some(&render_pipeline_layout),
layout: Some(&render_pipeline_layout), vertex: wgpu::VertexState {
vertex: wgpu::VertexState { module: &shader,
module: &shader, entry_point: Some("vs_main"),
entry_point: Some("vs_main"), buffers: &[],
buffers: &[], compilation_options: wgpu::PipelineCompilationOptions::default(),
compilation_options: wgpu::PipelineCompilationOptions::default(), },
}, fragment: Some(wgpu::FragmentState {
fragment: Some(wgpu::FragmentState { module: &shader,
module: &shader, entry_point: Some("fs_main"),
entry_point: Some("fs_main"), targets: &[Some(wgpu::ColorTargetState {
targets: &[Some(wgpu::ColorTargetState { format: wgpu::TextureFormat::Rgba8UnormSrgb,
format: wgpu::TextureFormat::Rgba8UnormSrgb, blend: Some(wgpu::BlendState::REPLACE),
blend: Some(wgpu::BlendState::REPLACE), write_mask: wgpu::ColorWrites::ALL,
write_mask: wgpu::ColorWrites::ALL, })],
})], compilation_options: wgpu::PipelineCompilationOptions::default(),
compilation_options: wgpu::PipelineCompilationOptions::default(), }),
}), primitive: wgpu::PrimitiveState {
primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList,
topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None,
strip_index_format: None, front_face: wgpu::FrontFace::Ccw,
front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back),
cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill,
polygon_mode: wgpu::PolygonMode::Fill, unclipped_depth: false,
unclipped_depth: false, conservative: false,
conservative: false, },
}, depth_stencil: None,
depth_stencil: None, multisample: wgpu::MultisampleState {
multisample: wgpu::MultisampleState { count: 1,
count: 1, mask: !0,
mask: !0, alpha_to_coverage_enabled: false,
alpha_to_coverage_enabled: false, },
}, multiview_mask: None,
multiview_mask: None, cache: None,
cache: None, });
});
Ok(Self { Ok(Self {
wgpu_instance, instance,
wgpu_adapter, adapter,
wgpu_device, device,
wgpu_queue, queue,
wgpu_render_pipeline, render_pipeline,
wgpu_screen_size_bind_group_layout, screen_size_bind_group_layout,
}) })
} }
} }
@ -119,9 +116,9 @@ impl SurfaceGpuState {
wayland_backend: &wayland_backend::client::Backend, wayland_backend: &wayland_backend::client::Backend,
wl_surface: &WlSurface, wl_surface: &WlSurface,
) -> Result<Self> { ) -> Result<Self> {
let wgpu_surface = unsafe { let surface = unsafe {
gpu_state gpu_state
.wgpu_instance .instance
.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::RawHandle { .create_surface_unsafe(wgpu::SurfaceTargetUnsafe::RawHandle {
raw_display_handle: RawDisplayHandle::Wayland(WaylandDisplayHandle::new( raw_display_handle: RawDisplayHandle::Wayland(WaylandDisplayHandle::new(
NonNull::new(wayland_backend.display_ptr().cast()).unwrap(), NonNull::new(wayland_backend.display_ptr().cast()).unwrap(),
@ -133,24 +130,24 @@ impl SurfaceGpuState {
} }
.wrap_err("failed to create wgpu surface")?; .wrap_err("failed to create wgpu surface")?;
let wgpu_screen_size_buffer = let screen_size_buffer =
gpu_state gpu_state
.wgpu_device .device
.create_buffer_init(&wgpu::util::BufferInitDescriptor { .create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Screen Size Uniform Buffer"), label: Some("Screen Size Uniform Buffer"),
contents: bytemuck::bytes_of(&ScreenSizeUniform { size: [0.0, 0.0] }), contents: bytemuck::bytes_of(&ScreenSizeUniform { size: [0.0, 0.0] }),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
}); });
let wgpu_screen_size_bind_group = let screen_size_bind_group =
gpu_state gpu_state
.wgpu_device .device
.create_bind_group(&wgpu::BindGroupDescriptor { .create_bind_group(&wgpu::BindGroupDescriptor {
layout: &gpu_state.wgpu_screen_size_bind_group_layout, layout: &gpu_state.screen_size_bind_group_layout,
entries: &[wgpu::BindGroupEntry { entries: &[wgpu::BindGroupEntry {
binding: 0, binding: 0,
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
buffer: &wgpu_screen_size_buffer, buffer: &screen_size_buffer,
offset: 0, offset: 0,
size: None, size: None,
}), }),
@ -159,22 +156,22 @@ impl SurfaceGpuState {
}); });
Ok(Self { Ok(Self {
wgpu_surface, surface,
wgpu_screen_size_buffer, screen_size_buffer,
wgpu_screen_size_bind_group, screen_size_bind_group,
}) })
} }
pub fn resize(&self, gpu_state: &AppGpuState, width: u32, height: u32) { pub fn resize(&self, gpu_state: &AppGpuState, width: u32, height: u32) {
gpu_state.wgpu_queue.write_buffer( gpu_state.queue.write_buffer(
&self.wgpu_screen_size_buffer, &self.screen_size_buffer,
0, 0,
bytemuck::bytes_of(&ScreenSizeUniform { bytemuck::bytes_of(&ScreenSizeUniform {
size: [width as f32, height as f32], size: [width as f32, height as f32],
}), }),
); );
let cap = self.wgpu_surface.get_capabilities(&gpu_state.wgpu_adapter); let cap = self.surface.get_capabilities(&gpu_state.adapter);
let surface_config = wgpu::SurfaceConfiguration { let surface_config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: cap.formats[0], format: cap.formats[0],
@ -186,20 +183,17 @@ impl SurfaceGpuState {
// Wayland is inherently a mailbox system. // Wayland is inherently a mailbox system.
present_mode: wgpu::PresentMode::Mailbox, present_mode: wgpu::PresentMode::Mailbox,
}; };
self.wgpu_surface self.surface.configure(&gpu_state.device, &surface_config);
.configure(&gpu_state.wgpu_device, &surface_config);
let surface_texture = self let surface_texture = self
.wgpu_surface .surface
.get_current_texture() .get_current_texture()
.expect("failed to acquire next swapchain texture"); .expect("failed to acquire next swapchain texture");
let texture_view: wgpu::TextureView = surface_texture let texture_view: wgpu::TextureView = surface_texture
.texture .texture
.create_view(&wgpu::TextureViewDescriptor::default()); .create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = gpu_state let mut encoder = gpu_state.device.create_command_encoder(&Default::default());
.wgpu_device
.create_command_encoder(&Default::default());
{ {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"), label: Some("Render Pass"),
@ -224,12 +218,12 @@ impl SurfaceGpuState {
..Default::default() ..Default::default()
}); });
render_pass.set_pipeline(&gpu_state.wgpu_render_pipeline); render_pass.set_pipeline(&gpu_state.render_pipeline);
render_pass.set_bind_group(0, Some(&self.wgpu_screen_size_bind_group), &[]); render_pass.set_bind_group(0, Some(&self.screen_size_bind_group), &[]);
render_pass.draw(0..6, 0..1); render_pass.draw(0..6, 0..1);
} }
gpu_state.wgpu_queue.submit(Some(encoder.finish())); gpu_state.queue.submit(Some(encoder.finish()));
surface_texture.present(); surface_texture.present();
} }
} }