Skip to content

Commit bbd64de

Browse files
[render] render pipeline/first triangle
1 parent a5b3d44 commit bbd64de

File tree

2 files changed

+90
-4
lines changed

2 files changed

+90
-4
lines changed

crates/eqx_window/src/window.rs

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use eqx_app::prelude::Module;
2-
use wgpu::{MemoryHints, RenderPassDescriptor};
2+
use wgpu::{MemoryHints, RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor};
33

44
use winit::{
55
event::*,
@@ -10,16 +10,21 @@ use winit::{
1010

1111
use winit::window::Window as WInitWindow;
1212

13+
const VS_MAIN: &str = "vs_main";
14+
const FS_MAIN: &str = "fs_main";
15+
1316
struct State<'a> {
1417
surface: wgpu::Surface<'a>,
1518
device: wgpu::Device,
1619
queue: wgpu::Queue,
1720
config: wgpu::SurfaceConfiguration,
1821
size: winit::dpi::PhysicalSize<u32>,
1922
window: &'a WInitWindow,
23+
render_pipeline: wgpu::RenderPipeline,
2024
}
2125

2226
impl<'a> State<'a> {
27+
/// Accepts only mesh with counter-clockwise winding
2328
async fn new(window: &'a WInitWindow) -> State<'a> {
2429
let size = window.inner_size();
2530

@@ -72,13 +77,66 @@ impl<'a> State<'a> {
7277
desired_maximum_frame_latency: 2,
7378
};
7479

80+
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
81+
label: Some("TrigShader"),
82+
source: wgpu::ShaderSource::Wgsl(
83+
include_str!("../../../shaders/trig/shader.wgsl").into(),
84+
),
85+
});
86+
87+
let render_pipeline_layout =
88+
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
89+
label: Some("RenderPipelineLayout"),
90+
bind_group_layouts: &[],
91+
push_constant_ranges: &[],
92+
});
93+
94+
let render_pipeline = device.create_render_pipeline(&RenderPipelineDescriptor {
95+
label: Some("RenderPipeline"),
96+
layout: Some(&render_pipeline_layout),
97+
vertex: wgpu::VertexState {
98+
module: &shader,
99+
entry_point: Some(VS_MAIN),
100+
buffers: &[],
101+
compilation_options: wgpu::PipelineCompilationOptions::default(),
102+
},
103+
fragment: Some(wgpu::FragmentState {
104+
module: &shader,
105+
entry_point: Some(FS_MAIN),
106+
targets: &[Some(wgpu::ColorTargetState {
107+
format: config.format,
108+
blend: Some(wgpu::BlendState::REPLACE),
109+
write_mask: wgpu::ColorWrites::ALL,
110+
})],
111+
compilation_options: wgpu::PipelineCompilationOptions::default(),
112+
}),
113+
primitive: wgpu::PrimitiveState {
114+
topology: wgpu::PrimitiveTopology::TriangleList,
115+
strip_index_format: None,
116+
front_face: wgpu::FrontFace::Ccw,
117+
cull_mode: Some(wgpu::Face::Back),
118+
polygon_mode: wgpu::PolygonMode::Fill,
119+
unclipped_depth: false,
120+
conservative: false,
121+
},
122+
depth_stencil: None,
123+
multisample: wgpu::MultisampleState {
124+
count: 1, // TODO: check multi-sampling
125+
mask: !0, // enable all the mask bits
126+
alpha_to_coverage_enabled: false, // TODO: check anti-aliasing
127+
},
128+
multiview: None,
129+
cache: None,
130+
});
131+
75132
Self {
76133
surface,
77134
device,
78135
queue,
79136
config,
80137
size,
81138
window,
139+
render_pipeline,
82140
}
83141
}
84142

@@ -95,7 +153,7 @@ impl<'a> State<'a> {
95153
}
96154
}
97155

98-
fn fully_processed(&self, event: &WindowEvent) -> bool {
156+
fn process_input(&self, event: &WindowEvent) -> bool {
99157
false
100158
}
101159

@@ -115,7 +173,7 @@ impl<'a> State<'a> {
115173
});
116174

117175
{
118-
let _render_pass = encoder.begin_render_pass(&RenderPassDescriptor {
176+
let mut render_pass = encoder.begin_render_pass(&RenderPassDescriptor {
119177
label: Some("RenderPass"),
120178
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
121179
view: &view,
@@ -134,6 +192,9 @@ impl<'a> State<'a> {
134192
timestamp_writes: None,
135193
occlusion_query_set: None,
136194
});
195+
196+
render_pass.set_pipeline(&self.render_pipeline);
197+
render_pass.draw(0..3, 0..1)
137198
}
138199

139200
self.queue.submit(std::iter::once(encoder.finish()));
@@ -143,6 +204,7 @@ impl<'a> State<'a> {
143204
}
144205
}
145206

207+
// TODO: refactor this class, so that more utilities (e.g. `Input`) can be integrated
146208
pub struct WindowDisplay {}
147209

148210
impl Default for WindowDisplay {
@@ -165,7 +227,7 @@ impl Module for WindowDisplay {
165227
ref event,
166228
window_id,
167229
} if window_id == state.window.id() => {
168-
if (!state.fully_processed(event)) {
230+
if (!state.process_input(event)) {
169231
match event {
170232
WindowEvent::CloseRequested
171233
| WindowEvent::KeyboardInput {

shaders/trig/shader.wgsl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
struct VertexOutput {
2+
@builtin(position) clip_position: vec4<f32>,
3+
@location(0) vert_pos: vec3<f32>,
4+
}
5+
6+
@vertex
7+
fn vs_main(
8+
@builtin(vertex_index) in_vertex_index: u32
9+
) -> VertexOutput {
10+
var out: VertexOutput;
11+
let x = f32(1 - i32(in_vertex_index)) * 0.5;
12+
let y = f32(i32(in_vertex_index & 1u) * 2 - 1) * 0.5;
13+
out.clip_position = vec4<f32>(x, y, 0.0, 1.0);
14+
out.vert_pos = out.clip_position.xyz;
15+
return out;
16+
}
17+
18+
@fragment
19+
fn fs_main(
20+
in: VertexOutput
21+
) -> @location(0) vec4<f32> {
22+
return vec4<f32>(0.3, 0.2, 0.1, 1.0);
23+
}
24+

0 commit comments

Comments
 (0)