Stop using triangle fans for DX12/Vulkan compatibility.

Closes #165.
This commit is contained in:
Patrick Walton 2019-05-29 16:04:33 -07:00
parent 339397bf23
commit acf666b701
6 changed files with 92 additions and 45 deletions

View File

@ -59,6 +59,7 @@ where
device: &D, device: &D,
ground_program: &GroundProgram<D>, ground_program: &GroundProgram<D>,
quad_vertex_positions_buffer: &D::Buffer, quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> GroundVertexArray<D> { ) -> GroundVertexArray<D> {
let vertex_array = device.create_vertex_array(); let vertex_array = device.create_vertex_array();
@ -75,6 +76,7 @@ where
offset: 0, offset: 0,
divisor: 0, divisor: 0,
}); });
device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index);
GroundVertexArray { vertex_array } GroundVertexArray { vertex_array }
} }

View File

@ -148,7 +148,8 @@ impl<W> DemoApp<W> where W: Window {
let ground_program = GroundProgram::new(&renderer.device, resources); let ground_program = GroundProgram::new(&renderer.device, resources);
let ground_vertex_array = GroundVertexArray::new(&renderer.device, let ground_vertex_array = GroundVertexArray::new(&renderer.device,
&ground_program, &ground_program,
&renderer.quad_vertex_positions_buffer()); &renderer.quad_vertex_positions_buffer(),
&renderer.quad_vertex_indices_buffer());
let mut ui_model = DemoUIModel::new(&options); let mut ui_model = DemoUIModel::new(&options);

View File

@ -248,9 +248,9 @@ impl<W> DemoApp<W> where W: Window {
); );
device.set_uniform(&self.ground_program.gridline_count_uniform, device.set_uniform(&self.ground_program.gridline_count_uniform,
UniformData::Int(GRIDLINE_COUNT)); UniformData::Int(GRIDLINE_COUNT));
device.draw_arrays( device.draw_elements(
Primitive::TriangleFan, Primitive::Triangles,
4, 6,
&RenderState { &RenderState {
depth: Some(DepthState { func: DepthFunc::Less, write: true }), depth: Some(DepthState { func: DepthFunc::Less, write: true }),
..RenderState::default() ..RenderState::default()

View File

@ -550,17 +550,18 @@ impl Device for GLDevice {
self.reset_render_state(render_state); self.reset_render_state(render_state);
} }
fn draw_arrays_instanced(&self, fn draw_elements_instanced(&self,
primitive: Primitive, primitive: Primitive,
index_count: u32, index_count: u32,
instance_count: u32, instance_count: u32,
render_state: &RenderState) { render_state: &RenderState) {
self.set_render_state(render_state); self.set_render_state(render_state);
unsafe { unsafe {
gl::DrawArraysInstanced(primitive.to_gl_primitive(), gl::DrawElementsInstanced(primitive.to_gl_primitive(),
0, index_count as GLsizei,
index_count as GLsizei, gl::UNSIGNED_INT,
instance_count as GLsizei); ck(); ptr::null(),
instance_count as GLsizei); ck();
} }
self.reset_render_state(render_state); self.reset_render_state(render_state);
} }
@ -861,7 +862,6 @@ impl PrimitiveExt for Primitive {
fn to_gl_primitive(self) -> GLuint { fn to_gl_primitive(self) -> GLuint {
match self { match self {
Primitive::Triangles => gl::TRIANGLES, Primitive::Triangles => gl::TRIANGLES,
Primitive::TriangleFan => gl::TRIANGLE_FAN,
Primitive::Lines => gl::LINES, Primitive::Lines => gl::LINES,
} }
} }

View File

@ -80,13 +80,11 @@ pub trait Device {
fn clear(&self, params: &ClearParams); fn clear(&self, params: &ClearParams);
fn draw_arrays(&self, primitive: Primitive, index_count: u32, render_state: &RenderState); fn draw_arrays(&self, primitive: Primitive, index_count: u32, render_state: &RenderState);
fn draw_elements(&self, primitive: Primitive, index_count: u32, render_state: &RenderState); fn draw_elements(&self, primitive: Primitive, index_count: u32, render_state: &RenderState);
fn draw_arrays_instanced( fn draw_elements_instanced(&self,
&self, primitive: Primitive,
primitive: Primitive, index_count: u32,
index_count: u32, instance_count: u32,
instance_count: u32, render_state: &RenderState);
render_state: &RenderState,
);
fn create_timer_query(&self) -> Self::TimerQuery; fn create_timer_query(&self) -> Self::TimerQuery;
fn begin_timer_query(&self, query: &Self::TimerQuery); fn begin_timer_query(&self, query: &Self::TimerQuery);
fn end_timer_query(&self, query: &Self::TimerQuery); fn end_timer_query(&self, query: &Self::TimerQuery);
@ -198,7 +196,6 @@ pub enum UniformData {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum Primitive { pub enum Primitive {
Triangles, Triangles,
TriangleFan,
Lines, Lines,
} }

View File

@ -31,6 +31,7 @@ use std::time::Duration;
use std::u32; use std::u32;
static QUAD_VERTEX_POSITIONS: [u8; 8] = [0, 0, 1, 0, 1, 1, 0, 1]; static QUAD_VERTEX_POSITIONS: [u8; 8] = [0, 0, 1, 0, 1, 1, 0, 1];
static QUAD_VERTEX_INDICES: [u32; 6] = [0, 1, 3, 1, 2, 3];
// FIXME(pcwalton): Shrink this again! // FIXME(pcwalton): Shrink this again!
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * 256; const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * 256;
@ -63,6 +64,7 @@ where
alpha_monochrome_tile_vertex_array: AlphaTileVertexArray<D>, alpha_monochrome_tile_vertex_array: AlphaTileVertexArray<D>,
area_lut_texture: D::Texture, area_lut_texture: D::Texture,
quad_vertex_positions_buffer: D::Buffer, quad_vertex_positions_buffer: D::Buffer,
quad_vertex_indices_buffer: D::Buffer,
fill_vertex_array: FillVertexArray<D>, fill_vertex_array: FillVertexArray<D>,
mask_framebuffer: D::Framebuffer, mask_framebuffer: D::Framebuffer,
paint_texture: Option<D::Texture>, paint_texture: Option<D::Texture>,
@ -127,39 +129,56 @@ where
BufferTarget::Vertex, BufferTarget::Vertex,
BufferUploadMode::Static, BufferUploadMode::Static,
); );
let quad_vertex_indices_buffer = device.create_buffer();
device.allocate_buffer(
&quad_vertex_indices_buffer,
BufferData::Memory(&QUAD_VERTEX_INDICES),
BufferTarget::Index,
BufferUploadMode::Static,
);
let fill_vertex_array = let fill_vertex_array = FillVertexArray::new(
FillVertexArray::new(&device, &fill_program, &quad_vertex_positions_buffer); &device,
&fill_program,
&quad_vertex_positions_buffer,
&quad_vertex_indices_buffer,
);
let alpha_multicolor_tile_vertex_array = AlphaTileVertexArray::new( let alpha_multicolor_tile_vertex_array = AlphaTileVertexArray::new(
&device, &device,
&alpha_multicolor_tile_program.alpha_tile_program, &alpha_multicolor_tile_program.alpha_tile_program,
&quad_vertex_positions_buffer, &quad_vertex_positions_buffer,
&quad_vertex_indices_buffer,
); );
let solid_multicolor_tile_vertex_array = SolidTileVertexArray::new( let solid_multicolor_tile_vertex_array = SolidTileVertexArray::new(
&device, &device,
&solid_multicolor_tile_program.solid_tile_program, &solid_multicolor_tile_program.solid_tile_program,
&quad_vertex_positions_buffer, &quad_vertex_positions_buffer,
&quad_vertex_indices_buffer,
); );
let alpha_monochrome_tile_vertex_array = AlphaTileVertexArray::new( let alpha_monochrome_tile_vertex_array = AlphaTileVertexArray::new(
&device, &device,
&alpha_monochrome_tile_program.alpha_tile_program, &alpha_monochrome_tile_program.alpha_tile_program,
&quad_vertex_positions_buffer, &quad_vertex_positions_buffer,
&quad_vertex_indices_buffer,
); );
let solid_monochrome_tile_vertex_array = SolidTileVertexArray::new( let solid_monochrome_tile_vertex_array = SolidTileVertexArray::new(
&device, &device,
&solid_monochrome_tile_program.solid_tile_program, &solid_monochrome_tile_program.solid_tile_program,
&quad_vertex_positions_buffer, &quad_vertex_positions_buffer,
&quad_vertex_indices_buffer,
); );
let postprocess_vertex_array = PostprocessVertexArray::new( let postprocess_vertex_array = PostprocessVertexArray::new(
&device, &device,
&postprocess_program, &postprocess_program,
&quad_vertex_positions_buffer, &quad_vertex_positions_buffer,
&quad_vertex_indices_buffer,
); );
let stencil_vertex_array = StencilVertexArray::new(&device, &stencil_program); let stencil_vertex_array = StencilVertexArray::new(&device, &stencil_program);
let reprojection_vertex_array = ReprojectionVertexArray::new( let reprojection_vertex_array = ReprojectionVertexArray::new(
&device, &device,
&reprojection_program, &reprojection_program,
&quad_vertex_positions_buffer, &quad_vertex_positions_buffer,
&quad_vertex_indices_buffer,
); );
let mask_framebuffer_size = let mask_framebuffer_size =
@ -186,6 +205,7 @@ where
alpha_multicolor_tile_vertex_array, alpha_multicolor_tile_vertex_array,
area_lut_texture, area_lut_texture,
quad_vertex_positions_buffer, quad_vertex_positions_buffer,
quad_vertex_indices_buffer,
fill_vertex_array, fill_vertex_array,
mask_framebuffer, mask_framebuffer,
paint_texture: None, paint_texture: None,
@ -338,6 +358,11 @@ where
&self.quad_vertex_positions_buffer &self.quad_vertex_positions_buffer
} }
#[inline]
pub fn quad_vertex_indices_buffer(&self) -> &D::Buffer {
&self.quad_vertex_indices_buffer
}
fn upload_paint_data(&mut self, paint_data: &PaintData) { fn upload_paint_data(&mut self, paint_data: &PaintData) {
match self.paint_texture { match self.paint_texture {
Some(ref paint_texture) if Some(ref paint_texture) if
@ -446,9 +471,9 @@ where
..RenderState::default() ..RenderState::default()
}; };
debug_assert!(self.buffered_fills.len() <= u32::MAX as usize); debug_assert!(self.buffered_fills.len() <= u32::MAX as usize);
self.device.draw_arrays_instanced( self.device.draw_elements_instanced(
Primitive::TriangleFan, Primitive::Triangles,
4, 6,
self.buffered_fills.len() as u32, self.buffered_fills.len() as u32,
&render_state, &render_state,
); );
@ -523,8 +548,7 @@ where
stencil: self.stencil_state(), stencil: self.stencil_state(),
..RenderState::default() ..RenderState::default()
}; };
self.device self.device.draw_elements_instanced(Primitive::Triangles, 6, count, &render_state);
.draw_arrays_instanced(Primitive::TriangleFan, 4, count, &render_state);
} }
fn draw_solid_tiles(&mut self, count: u32) { fn draw_solid_tiles(&mut self, count: u32) {
@ -585,8 +609,7 @@ where
stencil: self.stencil_state(), stencil: self.stencil_state(),
..RenderState::default() ..RenderState::default()
}; };
self.device self.device.draw_elements_instanced(Primitive::Triangles, 6, count, &render_state);
.draw_arrays_instanced(Primitive::TriangleFan, 4, count, &render_state);
} }
fn postprocess(&mut self) { fn postprocess(&mut self) {
@ -661,8 +684,7 @@ where
&self.postprocess_program.gamma_correction_enabled_uniform, &self.postprocess_program.gamma_correction_enabled_uniform,
UniformData::Int(gamma_correction_enabled as i32), UniformData::Int(gamma_correction_enabled as i32),
); );
self.device self.device.draw_arrays(Primitive::Triangles, 4, &RenderState::default());
.draw_arrays(Primitive::TriangleFan, 4, &RenderState::default());
} }
fn solid_tile_program(&self) -> &SolidTileProgram<D> { fn solid_tile_program(&self) -> &SolidTileProgram<D> {
@ -700,14 +722,27 @@ where
BufferTarget::Vertex, BufferTarget::Vertex,
BufferUploadMode::Dynamic, BufferUploadMode::Dynamic,
); );
// Create indices for a triangle fan. (This is OK because the clipped quad should always be
// convex.)
let mut indices: Vec<u32> = vec![];
for index in 1..(quad_positions.len() as u32 - 1) {
indices.extend_from_slice(&[0, index as u32, index + 1]);
}
self.device.allocate_buffer(
&self.stencil_vertex_array.index_buffer,
BufferData::Memory(&indices),
BufferTarget::Index,
BufferUploadMode::Dynamic,
);
self.bind_draw_framebuffer(); self.bind_draw_framebuffer();
self.device self.device.bind_vertex_array(&self.stencil_vertex_array.vertex_array);
.bind_vertex_array(&self.stencil_vertex_array.vertex_array);
self.device.use_program(&self.stencil_program.program); self.device.use_program(&self.stencil_program.program);
self.device.draw_arrays( self.device.draw_elements(
Primitive::TriangleFan, Primitive::Triangles,
4, indices.len() as u32,
&RenderState { &RenderState {
// FIXME(pcwalton): Should we really write to the depth buffer? // FIXME(pcwalton): Should we really write to the depth buffer?
depth: Some(DepthState { depth: Some(DepthState {
@ -734,8 +769,7 @@ where
) { ) {
self.bind_draw_framebuffer(); self.bind_draw_framebuffer();
self.device self.device.bind_vertex_array(&self.reprojection_vertex_array.vertex_array);
.bind_vertex_array(&self.reprojection_vertex_array.vertex_array);
self.device.use_program(&self.reprojection_program.program); self.device.use_program(&self.reprojection_program.program);
self.device.set_uniform( self.device.set_uniform(
&self.reprojection_program.old_transform_uniform, &self.reprojection_program.old_transform_uniform,
@ -750,9 +784,9 @@ where
&self.reprojection_program.texture_uniform, &self.reprojection_program.texture_uniform,
UniformData::TextureUnit(0), UniformData::TextureUnit(0),
); );
self.device.draw_arrays( self.device.draw_elements(
Primitive::TriangleFan, Primitive::Triangles,
4, 6,
&RenderState { &RenderState {
blend: BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha, blend: BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha,
depth: Some(DepthState { depth: Some(DepthState {
@ -896,6 +930,7 @@ where
device: &D, device: &D,
fill_program: &FillProgram<D>, fill_program: &FillProgram<D>,
quad_vertex_positions_buffer: &D::Buffer, quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> FillVertexArray<D> { ) -> FillVertexArray<D> {
let vertex_array = device.create_vertex_array(); let vertex_array = device.create_vertex_array();
@ -968,6 +1003,7 @@ where
offset: 6, offset: 6,
divisor: 1, divisor: 1,
}); });
device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index);
FillVertexArray { vertex_array, vertex_buffer } FillVertexArray { vertex_array, vertex_buffer }
} }
@ -989,6 +1025,7 @@ where
device: &D, device: &D,
alpha_tile_program: &AlphaTileProgram<D>, alpha_tile_program: &AlphaTileProgram<D>,
quad_vertex_positions_buffer: &D::Buffer, quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> AlphaTileVertexArray<D> { ) -> AlphaTileVertexArray<D> {
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
@ -1045,6 +1082,7 @@ where
offset: 8, offset: 8,
divisor: 1, divisor: 1,
}); });
device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index);
AlphaTileVertexArray { vertex_array, vertex_buffer } AlphaTileVertexArray { vertex_array, vertex_buffer }
} }
@ -1066,6 +1104,7 @@ where
device: &D, device: &D,
solid_tile_program: &SolidTileProgram<D>, solid_tile_program: &SolidTileProgram<D>,
quad_vertex_positions_buffer: &D::Buffer, quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> SolidTileVertexArray<D> { ) -> SolidTileVertexArray<D> {
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
@ -1104,6 +1143,7 @@ where
offset: 4, offset: 4,
divisor: 1, divisor: 1,
}); });
device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index);
SolidTileVertexArray { vertex_array, vertex_buffer } SolidTileVertexArray { vertex_array, vertex_buffer }
} }
@ -1366,6 +1406,7 @@ where
device: &D, device: &D,
postprocess_program: &PostprocessProgram<D>, postprocess_program: &PostprocessProgram<D>,
quad_vertex_positions_buffer: &D::Buffer, quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> PostprocessVertexArray<D> { ) -> PostprocessVertexArray<D> {
let vertex_array = device.create_vertex_array(); let vertex_array = device.create_vertex_array();
let position_attr = device.get_vertex_attr(&postprocess_program.program, "Position"); let position_attr = device.get_vertex_attr(&postprocess_program.program, "Position");
@ -1381,6 +1422,7 @@ where
offset: 0, offset: 0,
divisor: 0, divisor: 0,
}); });
device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index);
PostprocessVertexArray { vertex_array } PostprocessVertexArray { vertex_array }
} }
@ -1409,6 +1451,7 @@ where
{ {
vertex_array: D::VertexArray, vertex_array: D::VertexArray,
vertex_buffer: D::Buffer, vertex_buffer: D::Buffer,
index_buffer: D::Buffer,
} }
impl<D> StencilVertexArray<D> impl<D> StencilVertexArray<D>
@ -1416,7 +1459,8 @@ where
D: Device, D: Device,
{ {
fn new(device: &D, stencil_program: &StencilProgram<D>) -> StencilVertexArray<D> { fn new(device: &D, stencil_program: &StencilProgram<D>) -> StencilVertexArray<D> {
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); let vertex_array = device.create_vertex_array();
let (vertex_buffer, index_buffer) = (device.create_buffer(), device.create_buffer());
let position_attr = device.get_vertex_attr(&stencil_program.program, "Position"); let position_attr = device.get_vertex_attr(&stencil_program.program, "Position");
@ -1431,8 +1475,9 @@ where
offset: 0, offset: 0,
divisor: 0, divisor: 0,
}); });
device.bind_buffer(&index_buffer, BufferTarget::Index);
StencilVertexArray { vertex_array, vertex_buffer } StencilVertexArray { vertex_array, vertex_buffer, index_buffer }
} }
} }
@ -1480,6 +1525,7 @@ where
device: &D, device: &D,
reprojection_program: &ReprojectionProgram<D>, reprojection_program: &ReprojectionProgram<D>,
quad_vertex_positions_buffer: &D::Buffer, quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> ReprojectionVertexArray<D> { ) -> ReprojectionVertexArray<D> {
let vertex_array = device.create_vertex_array(); let vertex_array = device.create_vertex_array();
@ -1496,6 +1542,7 @@ where
offset: 0, offset: 0,
divisor: 0, divisor: 0,
}); });
device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index);
ReprojectionVertexArray { vertex_array } ReprojectionVertexArray { vertex_array }
} }