Skip to content

Parameterise Renderer over Device and rename CommandBufferHelper #563

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 64 additions & 30 deletions src/device/gl_device/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,49 @@

//! OpenGL implementation of the Command Buffer

use Command;
use std::slice;

use {attrib, draw, target, tex, shade, state};
use {AttributeSlot, IndexType, InstanceCount, PrimitiveType, TextureSlot, UniformBlockIndex, UniformBufferSlot, VertexCount};
use super::{ArrayBuffer, Buffer, FrameBuffer, Program, Surface, Texture};

/// Serialized device command.
#[derive(Copy, Debug)]
pub enum Command {
BindProgram(Program),
BindArrayBuffer(ArrayBuffer),
BindAttribute(AttributeSlot, Buffer, attrib::Format),
BindIndex(Buffer),
BindFrameBuffer(target::Access, FrameBuffer),
UnbindTarget(target::Access, target::Target),
BindTargetSurface(target::Access, target::Target, Surface),
BindTargetTexture(target::Access, target::Target, Texture, target::Level, Option<target::Layer>),
BindUniformBlock(Program, UniformBufferSlot, UniformBlockIndex, Buffer),
BindUniform(shade::Location, shade::UniformValue),
BindTexture(TextureSlot, tex::TextureKind, Texture, Option<::SamplerHandle>),
SetDrawColorBuffers(usize),
SetPrimitiveState(state::Primitive),
SetViewport(target::Rect),
SetMultiSampleState(Option<state::MultiSample>),
SetScissor(Option<target::Rect>),
SetDepthStencilState(Option<state::Depth>, Option<state::Stencil>, state::CullMode),
SetBlendState(Option<state::Blend>),
SetColorMask(state::ColorMask),
UpdateBuffer(Buffer, draw::DataPointer, usize),
UpdateTexture(tex::TextureKind, Texture, tex::ImageInfo, draw::DataPointer),
// drawing
Clear(target::ClearData, target::Mask),
Draw(PrimitiveType, VertexCount, VertexCount, Option<(InstanceCount, VertexCount)>),
DrawIndexed(PrimitiveType, IndexType, VertexCount, VertexCount, VertexCount, Option<(InstanceCount, VertexCount)>),
Blit(target::Rect, target::Rect, target::Mirror, target::Mask),
}

pub struct GlCommandBuffer {
buf: Vec<::Command>,
buf: Vec<Command>,
}

impl GlCommandBuffer {
pub fn iter<'a>(&'a self) -> slice::Iter<'a, ::Command> {
pub fn iter<'a>(&'a self) -> slice::Iter<'a, Command> {
self.buf.iter()
}
}
Expand All @@ -38,99 +72,99 @@ impl ::draw::CommandBuffer for GlCommandBuffer {
self.buf.clear();
}

fn bind_program(&mut self, prog: super::Program) {
fn bind_program(&mut self, prog: Program) {
self.buf.push(Command::BindProgram(prog));
}

fn bind_array_buffer(&mut self, vao: super::ArrayBuffer) {
fn bind_array_buffer(&mut self, vao: ArrayBuffer) {
self.buf.push(Command::BindArrayBuffer(vao));
}

fn bind_attribute(&mut self, slot: ::AttributeSlot, buf: super::Buffer,
fn bind_attribute(&mut self, slot: ::AttributeSlot, buf: Buffer,
format: ::attrib::Format) {
self.buf.push(Command::BindAttribute(slot, buf, format));
}

fn bind_index(&mut self, buf: super::Buffer) {
fn bind_index(&mut self, buf: Buffer) {
self.buf.push(Command::BindIndex(buf));
}

fn bind_frame_buffer(&mut self, access: ::target::Access, fbo: super::FrameBuffer) {
fn bind_frame_buffer(&mut self, access: target::Access, fbo: FrameBuffer) {
self.buf.push(Command::BindFrameBuffer(access, fbo));
}

fn unbind_target(&mut self, access: ::target::Access, tar: ::target::Target) {
fn unbind_target(&mut self, access: target::Access, tar: target::Target) {
self.buf.push(Command::UnbindTarget(access, tar));
}

fn bind_target_surface(&mut self, access: ::target::Access,
tar: ::target::Target, suf: super::Surface) {
fn bind_target_surface(&mut self, access: target::Access,
tar: target::Target, suf: Surface) {
self.buf.push(Command::BindTargetSurface(access, tar, suf));
}

fn bind_target_texture(&mut self, access: ::target::Access,
tar: ::target::Target, tex: super::Texture,
level: ::target::Level, layer: Option<::target::Layer>) {
fn bind_target_texture(&mut self, access: target::Access,
tar: target::Target, tex: Texture,
level: target::Level, layer: Option<target::Layer>) {
self.buf.push(Command::BindTargetTexture(access, tar, tex, level, layer));
}

fn bind_uniform_block(&mut self, prog: super::Program, slot: ::UniformBufferSlot,
index: ::UniformBlockIndex, buf: super::Buffer) {
fn bind_uniform_block(&mut self, prog: Program, slot: ::UniformBufferSlot,
index: ::UniformBlockIndex, buf: Buffer) {
self.buf.push(Command::BindUniformBlock(prog, slot, index, buf));
}

fn bind_uniform(&mut self, loc: ::shade::Location, value: ::shade::UniformValue) {
self.buf.push(Command::BindUniform(loc, value));
}
fn bind_texture(&mut self, slot: ::TextureSlot, kind: ::tex::TextureKind,
tex: super::Texture, sampler: Option<::SamplerHandle>) {
tex: Texture, sampler: Option<::SamplerHandle>) {
self.buf.push(Command::BindTexture(slot, kind, tex, sampler));
}

fn set_draw_color_buffers(&mut self, num: usize) {
self.buf.push(Command::SetDrawColorBuffers(num));
}

fn set_primitive(&mut self, prim: ::state::Primitive) {
fn set_primitive(&mut self, prim: state::Primitive) {
self.buf.push(Command::SetPrimitiveState(prim));
}

fn set_viewport(&mut self, view: ::target::Rect) {
fn set_viewport(&mut self, view: target::Rect) {
self.buf.push(Command::SetViewport(view));
}

fn set_multi_sample(&mut self, ms: Option<::state::MultiSample>) {
fn set_multi_sample(&mut self, ms: Option<state::MultiSample>) {
self.buf.push(Command::SetMultiSampleState(ms));
}

fn set_scissor(&mut self, rect: Option<::target::Rect>) {
fn set_scissor(&mut self, rect: Option<target::Rect>) {
self.buf.push(Command::SetScissor(rect));
}

fn set_depth_stencil(&mut self, depth: Option<::state::Depth>,
stencil: Option<::state::Stencil>, cull: ::state::CullMode) {
fn set_depth_stencil(&mut self, depth: Option<state::Depth>,
stencil: Option<state::Stencil>, cull: state::CullMode) {
self.buf.push(Command::SetDepthStencilState(depth, stencil, cull));
}

fn set_blend(&mut self, blend: Option<::state::Blend>) {
fn set_blend(&mut self, blend: Option<state::Blend>) {
self.buf.push(Command::SetBlendState(blend));
}

fn set_color_mask(&mut self, mask: ::state::ColorMask) {
fn set_color_mask(&mut self, mask: state::ColorMask) {
self.buf.push(Command::SetColorMask(mask));
}

fn update_buffer(&mut self, buf: super::Buffer, data: ::draw::DataPointer,
fn update_buffer(&mut self, buf: Buffer, data: ::draw::DataPointer,
offset_bytes: usize) {
self.buf.push(Command::UpdateBuffer(buf, data, offset_bytes));
}

fn update_texture(&mut self, kind: ::tex::TextureKind, tex: super::Texture,
fn update_texture(&mut self, kind: ::tex::TextureKind, tex: Texture,
info: ::tex::ImageInfo, data: ::draw::DataPointer) {
self.buf.push(Command::UpdateTexture(kind, tex, info, data));
}

fn call_clear(&mut self, data: ::target::ClearData, mask: ::target::Mask) {
fn call_clear(&mut self, data: target::ClearData, mask: target::Mask) {
self.buf.push(Command::Clear(data, mask));
}

Expand All @@ -145,8 +179,8 @@ impl ::draw::CommandBuffer for GlCommandBuffer {
self.buf.push(Command::DrawIndexed(ptype, itype, start, count, base, instances));
}

fn call_blit(&mut self, s_rect: ::target::Rect, d_rect: ::target::Rect,
mirror: ::target::Mirror, mask: ::target::Mask) {
fn call_blit(&mut self, s_rect: target::Rect, d_rect: target::Rect,
mirror: target::Mirror, mask: target::Mask) {
self.buf.push(Command::Blit(s_rect, d_rect, mirror, mask));
}
}
6 changes: 3 additions & 3 deletions src/device/gl_device/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ use state::{CullMode, RasterMethod, WindingOrder};
use target::{Access, Target};

use BufferUsage;
use Command;
use Device;
use {MapAccess, ReadableMapping, WritableMapping, RWMapping, BufferHandle, PrimitiveType};
use self::draw::Command;

pub use self::draw::GlCommandBuffer;
pub use self::info::{Info, PlatformName, Version};
Expand Down Expand Up @@ -170,7 +170,7 @@ impl GlDevice {
}

/// Fails during a debug build if the implementation's error flag was set.
fn check(&mut self, cmd: &::Command) {
fn check(&mut self, cmd: &Command) {
if cfg!(not(ndebug)) {
let err = GlError::from_error_code(unsafe { self.gl.GetError() });
if err != GlError::NoError {
Expand Down Expand Up @@ -221,7 +221,7 @@ impl GlDevice {
}
}

fn process(&mut self, cmd: &::Command, data_buf: &::draw::DataBuffer) {
fn process(&mut self, cmd: &Command, data_buf: &::draw::DataBuffer) {
match *cmd {
Command::Clear(ref data, mask) => {
let mut flags = 0;
Expand Down
39 changes: 0 additions & 39 deletions src/device/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,45 +315,6 @@ pub struct BufferInfo {
pub size: usize,
}

/// Serialized device command.
/// While this is supposed to be an internal detail of a device,
/// this particular representation may be used by different backends,
/// such as OpenGL (prior to GLNG) and DirectX (prior to DX12)
#[allow(missing_docs)]
#[derive(Copy, Debug)]
pub enum Command {
BindProgram(back::Program),
BindArrayBuffer(back::ArrayBuffer),
BindAttribute(AttributeSlot, back::Buffer, attrib::Format),
BindIndex(back::Buffer),
BindFrameBuffer(target::Access, back::FrameBuffer),
/// Unbind any surface from the specified target slot
UnbindTarget(target::Access, target::Target),
/// Bind a surface to the specified target slot
BindTargetSurface(target::Access, target::Target, back::Surface),
/// Bind a level of the texture to the specified target slot
BindTargetTexture(target::Access, target::Target, back::Texture,
target::Level, Option<target::Layer>),
BindUniformBlock(back::Program, UniformBufferSlot, UniformBlockIndex, back::Buffer),
BindUniform(shade::Location, shade::UniformValue),
BindTexture(TextureSlot, tex::TextureKind, back::Texture, Option<SamplerHandle>),
SetDrawColorBuffers(usize),
SetPrimitiveState(state::Primitive),
SetViewport(target::Rect),
SetMultiSampleState(Option<state::MultiSample>),
SetScissor(Option<target::Rect>),
SetDepthStencilState(Option<state::Depth>, Option<state::Stencil>, state::CullMode),
SetBlendState(Option<state::Blend>),
SetColorMask(state::ColorMask),
UpdateBuffer(back::Buffer, draw::DataPointer, usize),
UpdateTexture(tex::TextureKind, back::Texture, tex::ImageInfo, draw::DataPointer),
// drawing
Clear(target::ClearData, target::Mask),
Draw(PrimitiveType, VertexCount, VertexCount, Option<(InstanceCount, VertexCount)>),
DrawIndexed(PrimitiveType, IndexType, VertexCount, VertexCount, VertexCount, Option<(InstanceCount, VertexCount)>),
Blit(target::Rect, target::Rect, target::Mirror, target::Mask),
}

/// An interface for performing draw calls using a specific graphics API
#[allow(missing_docs)]
pub trait Device {
Expand Down
2 changes: 1 addition & 1 deletion src/gfx/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub struct Graphics<D: device::Device> {
/// Graphics device.
pub device: D,
/// Renderer front-end.
pub renderer: Renderer<<D as device::Device>::CommandBuffer>,
pub renderer: Renderer<D>,
/// Hidden batch context.
context: batch::Context,
}
Expand Down
4 changes: 2 additions & 2 deletions src/render/device_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl<'a> ShaderSource<'a> {
/// Backend extension trait for convenience methods
pub trait DeviceExt: device::Device {
/// Create a new renderer
fn create_renderer(&mut self) -> ::Renderer<<Self as device::Device>::CommandBuffer>;
fn create_renderer(&mut self) -> ::Renderer<Self>;
/// Create a new mesh from the given vertex data.
/// Convenience function around `create_buffer` and `Mesh::from_format`.
fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh;
Expand All @@ -73,7 +73,7 @@ pub trait DeviceExt: device::Device {
}

impl<D: device::Device> DeviceExt for D {
fn create_renderer(&mut self) -> ::Renderer<D::CommandBuffer> {
fn create_renderer(&mut self) -> ::Renderer<D> {
::Renderer {
command_buffer: device::draw::CommandBuffer::new(),
data_buffer: device::draw::DataBuffer::new(),
Expand Down
17 changes: 9 additions & 8 deletions src/render/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extern crate "gfx_device_gl" as device;

use std::mem;

use device::Device;
use device::attrib;
use device::attrib::IntSize;
use device::draw::CommandBuffer;
Expand Down Expand Up @@ -104,14 +105,14 @@ impl ParamStorage{
}
}

/// Helper routines for the command buffer
/// Extension methods for the command buffer.
/// Useful when Renderer is borrowed, and we need to issue commands.
trait CommandBufferHelper {
trait CommandBufferExt {
/// Bind a plane to some target
fn bind_target(&mut self, Access, Target, Option<&target::Plane>);
}

impl<C: CommandBuffer> CommandBufferHelper for C {
impl<C: CommandBuffer> CommandBufferExt for C {
fn bind_target(&mut self, access: Access, to: Target,
plane: Option<&target::Plane>) {
match plane {
Expand Down Expand Up @@ -141,8 +142,8 @@ pub enum DrawError<E> {
}

/// Renderer front-end
pub struct Renderer<C: CommandBuffer> {
command_buffer: C,
pub struct Renderer<D: Device> {
command_buffer: D::CommandBuffer,
data_buffer: device::draw::DataBuffer,
common_array_buffer: Result<device::ArrayBufferHandle, ()>,
draw_frame_buffer: device::FrameBufferHandle,
Expand All @@ -152,7 +153,7 @@ pub struct Renderer<C: CommandBuffer> {
parameters: ParamStorage,
}

impl<C: CommandBuffer> Renderer<C> {
impl<D: Device> Renderer<D> {
/// Reset all commands for the command buffer re-usal.
pub fn reset(&mut self) {
self.command_buffer.clear();
Expand All @@ -161,12 +162,12 @@ impl<C: CommandBuffer> Renderer<C> {
}

/// Get command and data buffers to be submitted to the device.
pub fn as_buffer(&self) -> (&C, &device::draw::DataBuffer) {
pub fn as_buffer(&self) -> (&D::CommandBuffer, &device::draw::DataBuffer) {
(&self.command_buffer, &self.data_buffer)
}

/// Clone the renderer shared data but ignore the commands.
pub fn clone_empty(&self) -> Renderer<C> {
pub fn clone_empty(&self) -> Renderer<D> {
Renderer {
command_buffer: CommandBuffer::new(),
data_buffer: device::draw::DataBuffer::new(),
Expand Down