diff --git a/demo/common/src/device.rs b/demo/common/src/device.rs index 17b14e9a..29b27540 100644 --- a/demo/common/src/device.rs +++ b/demo/common/src/device.rs @@ -59,6 +59,7 @@ where device: &D, ground_program: &GroundProgram, quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer, ) -> GroundVertexArray { let vertex_array = device.create_vertex_array(); @@ -75,6 +76,7 @@ where offset: 0, divisor: 0, }); + device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index); GroundVertexArray { vertex_array } } diff --git a/demo/common/src/lib.rs b/demo/common/src/lib.rs index 147eef59..fc946316 100644 --- a/demo/common/src/lib.rs +++ b/demo/common/src/lib.rs @@ -148,7 +148,8 @@ impl DemoApp where W: Window { let ground_program = GroundProgram::new(&renderer.device, resources); let ground_vertex_array = GroundVertexArray::new(&renderer.device, &ground_program, - &renderer.quad_vertex_positions_buffer()); + &renderer.quad_vertex_positions_buffer(), + &renderer.quad_vertex_indices_buffer()); let mut ui_model = DemoUIModel::new(&options); diff --git a/demo/common/src/renderer.rs b/demo/common/src/renderer.rs index 3220b5ff..01df38c5 100644 --- a/demo/common/src/renderer.rs +++ b/demo/common/src/renderer.rs @@ -248,9 +248,9 @@ impl DemoApp where W: Window { ); device.set_uniform(&self.ground_program.gridline_count_uniform, UniformData::Int(GRIDLINE_COUNT)); - device.draw_arrays( - Primitive::TriangleFan, - 4, + device.draw_elements( + Primitive::Triangles, + 6, &RenderState { depth: Some(DepthState { func: DepthFunc::Less, write: true }), ..RenderState::default() diff --git a/gl/src/lib.rs b/gl/src/lib.rs index 79eb8038..4fe6fd78 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -550,17 +550,18 @@ impl Device for GLDevice { self.reset_render_state(render_state); } - fn draw_arrays_instanced(&self, - primitive: Primitive, - index_count: u32, - instance_count: u32, - render_state: &RenderState) { + fn draw_elements_instanced(&self, + primitive: Primitive, + index_count: u32, + instance_count: u32, + render_state: &RenderState) { self.set_render_state(render_state); unsafe { - gl::DrawArraysInstanced(primitive.to_gl_primitive(), - 0, - index_count as GLsizei, - instance_count as GLsizei); ck(); + gl::DrawElementsInstanced(primitive.to_gl_primitive(), + index_count as GLsizei, + gl::UNSIGNED_INT, + ptr::null(), + instance_count as GLsizei); ck(); } self.reset_render_state(render_state); } @@ -861,7 +862,6 @@ impl PrimitiveExt for Primitive { fn to_gl_primitive(self) -> GLuint { match self { Primitive::Triangles => gl::TRIANGLES, - Primitive::TriangleFan => gl::TRIANGLE_FAN, Primitive::Lines => gl::LINES, } } diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index a369b54e..21d475d5 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -80,13 +80,11 @@ pub trait Device { fn clear(&self, params: &ClearParams); 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_arrays_instanced( - &self, - primitive: Primitive, - index_count: u32, - instance_count: u32, - render_state: &RenderState, - ); + fn draw_elements_instanced(&self, + primitive: Primitive, + index_count: u32, + instance_count: u32, + render_state: &RenderState); fn create_timer_query(&self) -> Self::TimerQuery; fn begin_timer_query(&self, query: &Self::TimerQuery); fn end_timer_query(&self, query: &Self::TimerQuery); @@ -198,7 +196,6 @@ pub enum UniformData { #[derive(Clone, Copy)] pub enum Primitive { Triangles, - TriangleFan, Lines, } diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index f7ed599d..b5b03a61 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -31,6 +31,7 @@ use std::time::Duration; use std::u32; 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! const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * 256; @@ -63,6 +64,7 @@ where alpha_monochrome_tile_vertex_array: AlphaTileVertexArray, area_lut_texture: D::Texture, quad_vertex_positions_buffer: D::Buffer, + quad_vertex_indices_buffer: D::Buffer, fill_vertex_array: FillVertexArray, mask_framebuffer: D::Framebuffer, paint_texture: Option, @@ -127,39 +129,56 @@ where BufferTarget::Vertex, 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 = - FillVertexArray::new(&device, &fill_program, &quad_vertex_positions_buffer); + let fill_vertex_array = FillVertexArray::new( + &device, + &fill_program, + &quad_vertex_positions_buffer, + &quad_vertex_indices_buffer, + ); let alpha_multicolor_tile_vertex_array = AlphaTileVertexArray::new( &device, &alpha_multicolor_tile_program.alpha_tile_program, &quad_vertex_positions_buffer, + &quad_vertex_indices_buffer, ); let solid_multicolor_tile_vertex_array = SolidTileVertexArray::new( &device, &solid_multicolor_tile_program.solid_tile_program, &quad_vertex_positions_buffer, + &quad_vertex_indices_buffer, ); let alpha_monochrome_tile_vertex_array = AlphaTileVertexArray::new( &device, &alpha_monochrome_tile_program.alpha_tile_program, &quad_vertex_positions_buffer, + &quad_vertex_indices_buffer, ); let solid_monochrome_tile_vertex_array = SolidTileVertexArray::new( &device, &solid_monochrome_tile_program.solid_tile_program, &quad_vertex_positions_buffer, + &quad_vertex_indices_buffer, ); let postprocess_vertex_array = PostprocessVertexArray::new( &device, &postprocess_program, &quad_vertex_positions_buffer, + &quad_vertex_indices_buffer, ); let stencil_vertex_array = StencilVertexArray::new(&device, &stencil_program); let reprojection_vertex_array = ReprojectionVertexArray::new( &device, &reprojection_program, &quad_vertex_positions_buffer, + &quad_vertex_indices_buffer, ); let mask_framebuffer_size = @@ -186,6 +205,7 @@ where alpha_multicolor_tile_vertex_array, area_lut_texture, quad_vertex_positions_buffer, + quad_vertex_indices_buffer, fill_vertex_array, mask_framebuffer, paint_texture: None, @@ -338,6 +358,11 @@ where &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) { match self.paint_texture { Some(ref paint_texture) if @@ -446,9 +471,9 @@ where ..RenderState::default() }; debug_assert!(self.buffered_fills.len() <= u32::MAX as usize); - self.device.draw_arrays_instanced( - Primitive::TriangleFan, - 4, + self.device.draw_elements_instanced( + Primitive::Triangles, + 6, self.buffered_fills.len() as u32, &render_state, ); @@ -523,8 +548,7 @@ where stencil: self.stencil_state(), ..RenderState::default() }; - self.device - .draw_arrays_instanced(Primitive::TriangleFan, 4, count, &render_state); + self.device.draw_elements_instanced(Primitive::Triangles, 6, count, &render_state); } fn draw_solid_tiles(&mut self, count: u32) { @@ -585,8 +609,7 @@ where stencil: self.stencil_state(), ..RenderState::default() }; - self.device - .draw_arrays_instanced(Primitive::TriangleFan, 4, count, &render_state); + self.device.draw_elements_instanced(Primitive::Triangles, 6, count, &render_state); } fn postprocess(&mut self) { @@ -661,8 +684,7 @@ where &self.postprocess_program.gamma_correction_enabled_uniform, UniformData::Int(gamma_correction_enabled as i32), ); - self.device - .draw_arrays(Primitive::TriangleFan, 4, &RenderState::default()); + self.device.draw_arrays(Primitive::Triangles, 4, &RenderState::default()); } fn solid_tile_program(&self) -> &SolidTileProgram { @@ -700,14 +722,27 @@ where BufferTarget::Vertex, BufferUploadMode::Dynamic, ); + + // Create indices for a triangle fan. (This is OK because the clipped quad should always be + // convex.) + let mut indices: Vec = 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.device - .bind_vertex_array(&self.stencil_vertex_array.vertex_array); + self.device.bind_vertex_array(&self.stencil_vertex_array.vertex_array); self.device.use_program(&self.stencil_program.program); - self.device.draw_arrays( - Primitive::TriangleFan, - 4, + self.device.draw_elements( + Primitive::Triangles, + indices.len() as u32, &RenderState { // FIXME(pcwalton): Should we really write to the depth buffer? depth: Some(DepthState { @@ -734,8 +769,7 @@ where ) { self.bind_draw_framebuffer(); - self.device - .bind_vertex_array(&self.reprojection_vertex_array.vertex_array); + self.device.bind_vertex_array(&self.reprojection_vertex_array.vertex_array); self.device.use_program(&self.reprojection_program.program); self.device.set_uniform( &self.reprojection_program.old_transform_uniform, @@ -750,9 +784,9 @@ where &self.reprojection_program.texture_uniform, UniformData::TextureUnit(0), ); - self.device.draw_arrays( - Primitive::TriangleFan, - 4, + self.device.draw_elements( + Primitive::Triangles, + 6, &RenderState { blend: BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha, depth: Some(DepthState { @@ -896,6 +930,7 @@ where device: &D, fill_program: &FillProgram, quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer, ) -> FillVertexArray { let vertex_array = device.create_vertex_array(); @@ -968,6 +1003,7 @@ where offset: 6, divisor: 1, }); + device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index); FillVertexArray { vertex_array, vertex_buffer } } @@ -989,6 +1025,7 @@ where device: &D, alpha_tile_program: &AlphaTileProgram, quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer, ) -> AlphaTileVertexArray { let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); @@ -1045,6 +1082,7 @@ where offset: 8, divisor: 1, }); + device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index); AlphaTileVertexArray { vertex_array, vertex_buffer } } @@ -1066,6 +1104,7 @@ where device: &D, solid_tile_program: &SolidTileProgram, quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer, ) -> SolidTileVertexArray { let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); @@ -1104,6 +1143,7 @@ where offset: 4, divisor: 1, }); + device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index); SolidTileVertexArray { vertex_array, vertex_buffer } } @@ -1366,6 +1406,7 @@ where device: &D, postprocess_program: &PostprocessProgram, quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer, ) -> PostprocessVertexArray { let vertex_array = device.create_vertex_array(); let position_attr = device.get_vertex_attr(&postprocess_program.program, "Position"); @@ -1381,6 +1422,7 @@ where offset: 0, divisor: 0, }); + device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index); PostprocessVertexArray { vertex_array } } @@ -1409,6 +1451,7 @@ where { vertex_array: D::VertexArray, vertex_buffer: D::Buffer, + index_buffer: D::Buffer, } impl StencilVertexArray @@ -1416,7 +1459,8 @@ where D: Device, { fn new(device: &D, stencil_program: &StencilProgram) -> StencilVertexArray { - 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"); @@ -1431,8 +1475,9 @@ where offset: 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, reprojection_program: &ReprojectionProgram, quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer, ) -> ReprojectionVertexArray { let vertex_array = device.create_vertex_array(); @@ -1496,6 +1542,7 @@ where offset: 0, divisor: 0, }); + device.bind_buffer(quad_vertex_indices_buffer, BufferTarget::Index); ReprojectionVertexArray { vertex_array } }