Encode mask directly in shader

This commit is contained in:
Maximilian Ammann 2021-12-29 22:00:18 +01:00
parent 45fa50962e
commit a5fc17a2e6
4 changed files with 73 additions and 106 deletions

View File

@ -112,64 +112,38 @@ pub mod tile_mask {
pub const VERTEX: VertexShaderState = VertexShaderState::new( pub const VERTEX: VertexShaderState = VertexShaderState::new(
include_str!("tile_mask.vertex.wgsl"), include_str!("tile_mask.vertex.wgsl"),
&[ &[wgpu::VertexBufferLayout {
wgpu::VertexBufferLayout { array_stride: std::mem::size_of::<MaskInstanceUniform>() as u64,
array_stride: std::mem::size_of::<GpuVertexUniform>() as u64, step_mode: wgpu::VertexStepMode::Instance,
step_mode: wgpu::VertexStepMode::Vertex, attributes: &[
attributes: &[ // offset position
// position wgpu::VertexAttribute {
wgpu::VertexAttribute { offset: 0,
offset: 0, format: wgpu::VertexFormat::Float32x2,
format: wgpu::VertexFormat::Float32x2, shader_location: 4,
shader_location: 0, },
}, // target_width
// normal wgpu::VertexAttribute {
wgpu::VertexAttribute { offset: 1 * wgpu::VertexFormat::Float32x2.size(),
offset: wgpu::VertexFormat::Float32x2.size(), format: wgpu::VertexFormat::Float32,
format: wgpu::VertexFormat::Float32x2, shader_location: 5,
shader_location: 1, },
}, // target_height
// ? wgpu::VertexAttribute {
wgpu::VertexAttribute { offset: 1 * wgpu::VertexFormat::Float32x2.size()
offset: 2 * wgpu::VertexFormat::Float32x2.size(), + wgpu::VertexFormat::Float32.size(),
format: wgpu::VertexFormat::Uint32, format: wgpu::VertexFormat::Float32,
shader_location: 2, shader_location: 6,
}, },
], // debug_color
}, wgpu::VertexAttribute {
wgpu::VertexBufferLayout { offset: 1 * wgpu::VertexFormat::Float32x2.size()
array_stride: std::mem::size_of::<MaskInstanceUniform>() as u64, + 2 * wgpu::VertexFormat::Float32.size(),
step_mode: wgpu::VertexStepMode::Instance, format: wgpu::VertexFormat::Float32x4,
attributes: &[ shader_location: 7,
// offset position },
wgpu::VertexAttribute { ],
offset: 0, }],
format: wgpu::VertexFormat::Float32x2,
shader_location: 4,
},
// target_width
wgpu::VertexAttribute {
offset: 1 * wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Float32,
shader_location: 5,
},
// target_height
wgpu::VertexAttribute {
offset: 1 * wgpu::VertexFormat::Float32x2.size()
+ wgpu::VertexFormat::Float32.size(),
format: wgpu::VertexFormat::Float32,
shader_location: 6,
},
// debug_color
wgpu::VertexAttribute {
offset: 1 * wgpu::VertexFormat::Float32x2.size()
+ 2 * wgpu::VertexFormat::Float32.size(),
format: wgpu::VertexFormat::Float32x4,
shader_location: 7,
},
],
},
],
); );
pub const FRAGMENT: FragmentShaderState = FragmentShaderState::new( pub const FRAGMENT: FragmentShaderState = FragmentShaderState::new(

View File

@ -38,12 +38,12 @@ fn main(
[[location(2)]] a_prim_id: u32, [[location(2)]] a_prim_id: u32,
[[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object" [[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object"
) -> VertexOutput { ) -> VertexOutput {
var prim: PrimitiveUniform = u_primitives.primitives[a_prim_id]; let prim: PrimitiveUniform = u_primitives.primitives[a_prim_id];
var z = 0.0; let z = 0.0;
var world_pos = a_position + prim.translate + a_normal * prim.width; let world_pos = a_position + prim.translate + a_normal * prim.width;
var position = globals.camera.view_proj * vec4<f32>(world_pos, z, 1.0); let position = globals.camera.view_proj * vec4<f32>(world_pos, z, 1.0);
return VertexOutput(prim.color, position); return VertexOutput(prim.color, position);
} }

View File

@ -15,27 +15,54 @@ struct VertexOutput {
[[builtin(position)]] position: vec4<f32>; [[builtin(position)]] position: vec4<f32>;
}; };
let EXTENT = 4096.0;
[[stage(vertex)]] [[stage(vertex)]]
fn main( fn main(
[[location(0)]] a_position: vec2<f32>,
[[location(4)]] mask_offset: vec2<f32>, [[location(4)]] mask_offset: vec2<f32>,
[[location(5)]] target_width: f32, [[location(5)]] target_width: f32,
[[location(6)]] target_height: f32, [[location(6)]] target_height: f32,
[[location(7)]] debug_color: vec4<f32>, [[location(7)]] debug_color: vec4<f32>,
[[builtin(vertex_index)]] vertex_idx: u32,
[[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object" [[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object"
) -> VertexOutput { ) -> VertexOutput {
let z = 0.0; var a_position: vec2<f32>;
var m: mat3x3<f32> = mat3x3<f32>( // Encode a square within the shader
switch (vertex_idx) {
case 0: {
a_position = vec2<f32>(0.0, 0.0);
}
case 1: {
a_position = vec2<f32>(0.0, EXTENT);
}
case 2: {
a_position = vec2<f32>(EXTENT, 0.0);
}
case 3: {
a_position = vec2<f32>(EXTENT, 0.0);
}
case 4: {
a_position = vec2<f32>(0.0, EXTENT);
}
case 5: {
a_position = vec2<f32>(EXTENT, EXTENT);
}
default: { }
}
let scaling: mat3x3<f32> = mat3x3<f32>(
vec3<f32>(target_width, 0.0, 0.0), vec3<f32>(target_width, 0.0, 0.0),
vec3<f32>(0.0, target_height, 0.0), vec3<f32>(0.0, target_height, 0.0),
vec3<f32>(0.0, 0.0, 1.0) vec3<f32>(0.0, 0.0, 1.0)
); );
var world_pos_3d = vec3<f32>(a_position + mask_offset, z); let z = 0.0;
var world_pos = m * world_pos_3d;
var position = globals.camera.view_proj * vec4<f32>(world_pos, 1.0); let world_pos_3d = vec3<f32>(a_position + mask_offset, z);
let world_pos = scaling * world_pos_3d;
let position = globals.camera.view_proj * vec4<f32>(world_pos, 1.0);
return VertexOutput(debug_color, position); return VertexOutput(debug_color, position);
} }

View File

@ -42,13 +42,10 @@ impl Default for SceneParams {
const INDEX_FORMAT: wgpu::IndexFormat = wgpu::IndexFormat::Uint32; const INDEX_FORMAT: wgpu::IndexFormat = wgpu::IndexFormat::Uint32;
type IndexDataType = u32; // Must match INDEX_FORMAT
const PRIM_BUFFER_LEN: usize = 256; const PRIM_BUFFER_LEN: usize = 256;
const STROKE_PRIM_ID: u32 = 0; const STROKE_PRIM_ID: u32 = 0;
const FILL_PRIM_ID: u32 = 1; const FILL_PRIM_ID: u32 = 1;
const SECOND_TILE_FILL_PRIM_ID: u32 = 2; const SECOND_TILE_FILL_PRIM_ID: u32 = 2;
const MASK_FILL_PRIM_ID: u32 = 3;
const SECOND_TILE_STROKE_PRIM_ID: u32 = 5; const SECOND_TILE_STROKE_PRIM_ID: u32 = 5;
pub struct State { pub struct State {
@ -84,9 +81,6 @@ pub struct State {
tile2_fill_range: Range<u32>, tile2_fill_range: Range<u32>,
tile2_stroke_range: Range<u32>, tile2_stroke_range: Range<u32>,
tile_mask_vertex_uniform_buffer: wgpu::Buffer,
tile_mask_indices_uniform_buffer: wgpu::Buffer,
tile_mask_range: Range<u32>,
tile_mask_instances: wgpu::Buffer, tile_mask_instances: wgpu::Buffer,
pub camera: camera::Camera, pub camera: camera::Camera,
@ -120,9 +114,6 @@ impl SceneParams {
cpu_primitives[SECOND_TILE_FILL_PRIM_ID as usize] = cpu_primitives[SECOND_TILE_FILL_PRIM_ID as usize] =
PrimitiveUniform::new([0.0, 1.0, 1.0, 1.0], [4096.0, 0.0], 0, 1.0, 0.0, 1.0); PrimitiveUniform::new([0.0, 1.0, 1.0, 1.0], [4096.0, 0.0], 0, 1.0, 0.0, 1.0);
cpu_primitives[MASK_FILL_PRIM_ID as usize] =
PrimitiveUniform::new([0.0, 0.0, 1.0, 1.0], [0.0, 0.0], 0, 1.0, 0.0, 1.0);
Self { Self {
cpu_primitives, cpu_primitives,
..SceneParams::default() ..SceneParams::default()
@ -243,24 +234,6 @@ impl State {
usage: wgpu::BufferUsages::INDEX, usage: wgpu::BufferUsages::INDEX,
}); });
let mut tile_mask_geometry: VertexBuffers<GpuVertexUniform, IndexDataType> =
VertexBuffers::new();
let tile_mask = TileMask();
let tile_mask_range = tile_mask.tesselate_fill(&mut tile_mask_geometry, MASK_FILL_PRIM_ID);
let tile_mask_vertex_uniform_buffer =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None,
contents: bytemuck::cast_slice(&tile_mask_geometry.vertices),
usage: wgpu::BufferUsages::VERTEX,
});
let tile_mask_indices_uniform_buffer =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None,
contents: bytemuck::cast_slice(&tile_mask_geometry.indices),
usage: wgpu::BufferUsages::INDEX,
});
let instances = [ let instances = [
// Step 1 // Step 1
MaskInstanceUniform::new([0.0, 0.0], 4.0, 4.0, [1.0, 0.0, 0.0, 1.0]), // horizontal MaskInstanceUniform::new([0.0, 0.0], 4.0, 4.0, [1.0, 0.0, 0.0, 1.0]), // horizontal
@ -439,12 +412,9 @@ impl State {
globals_uniform_buffer, globals_uniform_buffer,
prims_uniform_buffer, prims_uniform_buffer,
indices_uniform_buffer, indices_uniform_buffer,
tile_mask_vertex_uniform_buffer,
fps_meter: FPSMeter::new(), fps_meter: FPSMeter::new(),
tile_stroke_range, tile_stroke_range,
tile2_fill_range, tile2_fill_range,
tile_mask_indices_uniform_buffer,
tile_mask_range,
tile_mask_instances, tile_mask_instances,
camera, camera,
projection, projection,
@ -567,15 +537,11 @@ impl State {
pass.set_bind_group(0, &self.bind_group, &[]); pass.set_bind_group(0, &self.bind_group, &[]);
{ {
// Draw Mask // Draw masks
pass.set_pipeline(&self.mask_pipeline); pass.set_pipeline(&self.mask_pipeline);
pass.set_index_buffer( pass.set_vertex_buffer(0, self.tile_mask_instances.slice(..));
self.tile_mask_indices_uniform_buffer.slice(..), // Draw 11 squares each out of 6 vertices
INDEX_FORMAT, pass.draw(0..6, 0..11);
);
pass.set_vertex_buffer(0, self.tile_mask_vertex_uniform_buffer.slice(..));
pass.set_vertex_buffer(1, self.tile_mask_instances.slice(..));
pass.draw_indexed(self.tile_mask_range.clone(), 0, 0..11);
} }
{ {
pass.set_pipeline(&self.render_pipeline); pass.set_pipeline(&self.render_pipeline);