Create RenderContext and Renderer structs

This commit is contained in:
Jarrod Doyle 2023-04-07 19:32:45 +01:00
parent 1b0e1f4bce
commit 6a9335089b
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
1 changed files with 150 additions and 0 deletions

150
src/renderer.rs Normal file
View File

@ -0,0 +1,150 @@
use winit::{dpi::PhysicalSize, window::Window};
pub(crate) struct RenderContext {
pub instance: wgpu::Instance,
pub size: PhysicalSize<u32>,
pub surface: wgpu::Surface,
pub surface_config: wgpu::SurfaceConfiguration,
pub adapter: wgpu::Adapter,
pub device: wgpu::Device,
pub queue: wgpu::Queue,
}
impl RenderContext {
pub async fn new(window: &Window) -> Self {
log::info!("Initialising WGPU context...");
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::VULKAN,
dx12_shader_compiler: Default::default(),
});
// To be able to start drawing we need a few things:
// - A surface
// - A GPU device to draw to the surface
// - A draw command queue
log::info!("Initialising window surface...");
let surface = unsafe { instance.create_surface(&window) }.unwrap();
log::info!("Requesting GPU adapter...");
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
force_fallback_adapter: false,
compatible_surface: Some(&surface),
})
.await
.unwrap();
log::info!("Checking GPU adapter meets requirements");
log::info!("Requesting GPU device...");
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
},
None,
)
.await
.unwrap();
log::info!("Configuring window surface...");
let size = window.inner_size();
let surface_config = surface
.get_default_config(&adapter, size.width, size.height)
.unwrap();
surface.configure(&device, &surface_config);
Self {
instance,
size,
surface,
surface_config,
adapter,
device,
queue,
}
}
}
pub(crate) struct Renderer {
clear_color: wgpu::Color,
render_pipeline: wgpu::RenderPipeline,
}
impl Renderer {
pub fn new(context: &RenderContext) -> Self {
log::info!("Creating render shader...");
let shader_descriptor = wgpu::include_wgsl!("../assets/shaders/shader.wgsl");
let shader = context.device.create_shader_module(shader_descriptor);
log::info!("Creating render pipeline...");
let render_pipeline =
context
.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: Some(&context.device.create_pipeline_layout(
&wgpu::PipelineLayoutDescriptor {
label: Some("draw"),
bind_group_layouts: &[],
push_constant_ranges: &[],
},
)),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vertex",
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fragment",
targets: &[Some(context.surface_config.format.into())],
}),
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
multiview: None,
});
let clear_color = wgpu::Color {
r: 255.0 / 255.0,
g: 216.0 / 255.0,
b: 102.0 / 255.0,
a: 1.0,
};
Self {
clear_color,
render_pipeline,
}
}
pub fn render(&mut self, context: &RenderContext) {
let frame = context.surface.get_current_texture().unwrap();
let view = frame
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = context
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(self.clear_color),
store: true,
},
})],
depth_stencil_attachment: None,
});
context.queue.submit(Some(encoder.finish()));
frame.present();
}
}