Browse Source

Add a ton more docs where missing

pull/16/head
Ian Chamberlain 2 years ago
parent
commit
5eaab0760a
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 15
      citro3d/src/attrib.rs
  2. 65
      citro3d/src/buffer.rs
  3. 7
      citro3d/src/error.rs
  4. 5
      citro3d/src/lib.rs
  5. 3
      citro3d/src/render.rs
  6. 16
      citro3d/src/shader.rs
  7. 15
      citro3d/src/shader/macros.rs
  8. 1
      citro3d/src/texture.rs

15
citro3d/src/attrib.rs

@ -1,7 +1,14 @@
//! Configure vertex attributes.
//!
//! This module has types and helpers for describing the shape/structure of vertex
//! data to be sent to the GPU.
//!
//! See the [`buffer`](crate::buffer) module to use the vertex data itself.
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
/// Vertex attribute info. This struct is used to describe how vertex buffers are /// Vertex attribute info. This struct describes how vertex buffers are
/// used (i.e. the shape of the vertex data). /// layed out and used (i.e. the shape of the vertex data).
#[derive(Debug)] #[derive(Debug)]
pub struct Info(pub(crate) citro3d_sys::C3D_AttrInfo); pub struct Info(pub(crate) citro3d_sys::C3D_AttrInfo);
@ -82,14 +89,14 @@ impl Info {
/// Add an attribute loader to the attribute info. The resulting attribute index /// Add an attribute loader to the attribute info. The resulting attribute index
/// indicates the registration order of the attributes. /// indicates the registration order of the attributes.
/// ///
/// ## Parameters /// # Parameters
/// ///
/// * `register`: the shader program input register for this attribute. /// * `register`: the shader program input register for this attribute.
/// * `format`: the data format of this attribute. /// * `format`: the data format of this attribute.
/// * `count`: the number of elements in each attribute (up to 4, corresponding /// * `count`: the number of elements in each attribute (up to 4, corresponding
/// to `xyzw` / `rgba` / `stpq`). /// to `xyzw` / `rgba` / `stpq`).
/// ///
/// ## Errors /// # Errors
/// ///
/// * If `count > 4` /// * If `count > 4`
/// * If this attribute info already has the maximum number of attributes. /// * If this attribute info already has the maximum number of attributes.

65
citro3d/src/buffer.rs

@ -1,39 +1,64 @@
use std::marker::PhantomData; //! Configure vertex buffer objects to be sent to the GPU for rendering.
//!
//! See the [`attrib`] module for details on how to describe the shape and type
//! of the VBO data.
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use crate::attrib; use crate::attrib;
/// Vertex buffer info. This struct is used to describe the shape of the buffer
/// data to be sent to the GPU for rendering.
#[derive(Debug)] #[derive(Debug)]
pub struct Info(pub(crate) citro3d_sys::C3D_BufInfo); pub struct Info(pub(crate) citro3d_sys::C3D_BufInfo);
/// A slice of buffer data. This borrows the buffer data and can be thought of
/// as similar to `&[T]` obtained by slicing a `Vec<T>`.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Slice<'buf> { pub struct Slice<'buf> {
index: libc::c_int, index: libc::c_int,
size: libc::c_int, size: libc::c_int,
_vbo_data: PhantomData<&'buf ()>,
buf_info: &'buf Info, buf_info: &'buf Info,
// TODO: should we encapsulate the primitive here too, and require it when the
// slice is registered? Could there ever be a use case to draw different primitives
// using the same backing data???
} }
impl Slice<'_> { impl Slice<'_> {
pub fn as_raw(&self) -> libc::c_int { /// Get the index into the buffer for this slice.
pub fn index(&self) -> libc::c_int {
self.index self.index
} }
pub fn size(&self) -> libc::c_int { /// Get the length of the slice.
#[must_use]
pub fn len(&self) -> libc::c_int {
self.size self.size
} }
/// Return whether or not the slice has any elements.
pub fn is_empty(&self) -> bool {
self.len() <= 0
}
/// Get the buffer info this slice is associated with.
pub fn info(&self) -> &Info { pub fn info(&self) -> &Info {
self.buf_info self.buf_info
} }
} }
/// The geometric primitive to draw (i.e. what shapes the buffer data describes).
#[repr(u32)] #[repr(u32)]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Primitive { pub enum Primitive {
/// Draw triangles (3 vertices per triangle).
Triangles = ctru_sys::GPU_TRIANGLES, Triangles = ctru_sys::GPU_TRIANGLES,
/// Draw a triangle strip (each vertex shared by 1-3 triangles).
TriangleStrip = ctru_sys::GPU_TRIANGLE_STRIP, TriangleStrip = ctru_sys::GPU_TRIANGLE_STRIP,
/// Draw a triangle fan (first vertex shared by all triangles).
TriangleFan = ctru_sys::GPU_TRIANGLE_FAN, TriangleFan = ctru_sys::GPU_TRIANGLE_FAN,
/// Geometry primitive. Can be used for more complex use cases like geometry
/// shaders that output custom primitives.
GeometryPrim = ctru_sys::GPU_GEOMETRY_PRIM, GeometryPrim = ctru_sys::GPU_GEOMETRY_PRIM,
} }
@ -49,6 +74,7 @@ impl Default for Info {
} }
impl Info { impl Info {
/// Construct buffer info without any registered data.
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
@ -63,6 +89,18 @@ impl Info {
} }
} }
/// Register vertex buffer object data. The resulting [`Slice`] will have its
/// lifetime tied to both this [`Info`] and the passed-in VBO. `vbo_data` is
/// assumed to use one `T` per drawn primitive, and its layout is assumed to
/// match the given `attrib_info`
///
/// # Errors
///
/// Registering VBO data may fail:
///
/// * if `vbo_data` is not allocated with the [`ctru::linear`] allocator
/// * if the maximum number (12) of VBOs are already registered
///
pub fn add<'this, 'vbo, 'idx, T>( pub fn add<'this, 'vbo, 'idx, T>(
&'this mut self, &'this mut self,
vbo_data: &'vbo [T], vbo_data: &'vbo [T],
@ -87,21 +125,16 @@ impl Info {
) )
}; };
if res < 0 { // Error codes from <https://github.com/devkitPro/citro3d/blob/master/source/buffers.c#L11>
// TODO: should we convert to a more specific error if this fails? match res {
// It looks like the common cases are -2 => Err(crate::Error::InvalidMemoryLocation),
// - too many buffers already added (max 12) -1 => Err(crate::Error::TooManyBuffers),
// - physical memory address in the wrong place (this can be seen by ..=0 => Err(crate::Error::System(res)),
// using default allocator instead of LinearAllocator) _ => Ok(Slice {
// <https://github.com/devkitPro/citro3d/blob/master/source/buffers.c#L13-L17>
Err(crate::Error::System(res))
} else {
Ok(Slice {
index: res, index: res,
size: vbo_data.len().try_into()?, size: vbo_data.len().try_into()?,
_vbo_data: PhantomData,
buf_info: self, buf_info: self,
}) }),
} }
} }
} }

7
citro3d/src/error.rs

@ -24,8 +24,13 @@ pub enum Error {
/// Indicates that a reference could not be obtained because a lock is already /// Indicates that a reference could not be obtained because a lock is already
/// held on the requested object. /// held on the requested object.
LockHeld, LockHeld,
/// Indicates that too many vertex attributes were specified (max 12 supported). /// Indicates that too many vertex attributes were registered (max 12 supported).
TooManyAttributes, TooManyAttributes,
/// Indicates that too many vertex buffer objects were registered (max 12 supported).
TooManyBuffers,
/// The given memory could not be converted to a physical address for sharing
/// with the GPU. Data should be allocated with [`ctru::linear`].
InvalidMemoryLocation,
} }
impl From<TryFromIntError> for Error { impl From<TryFromIntError> for Error {

5
citro3d/src/lib.rs

@ -5,7 +5,6 @@ pub mod buffer;
pub mod error; pub mod error;
pub mod render; pub mod render;
pub mod shader; pub mod shader;
pub mod texture;
use citro3d_sys::C3D_FrameDrawOn; use citro3d_sys::C3D_FrameDrawOn;
pub use error::{Error, Result}; pub use error::{Error, Result};
@ -110,8 +109,8 @@ impl Instance {
unsafe { unsafe {
citro3d_sys::C3D_DrawArrays( citro3d_sys::C3D_DrawArrays(
primitive as ctru_sys::GPU_Primitive_t, primitive as ctru_sys::GPU_Primitive_t,
index.as_raw(), index.index(),
index.size(), index.len(),
); );
} }
} }

3
citro3d/src/render.rs

@ -96,8 +96,11 @@ impl<'screen> Target<'screen> {
bitflags::bitflags! { bitflags::bitflags! {
/// Indicate whether color, depth buffer, or both values should be cleared. /// Indicate whether color, depth buffer, or both values should be cleared.
pub struct ClearFlags: u32 { pub struct ClearFlags: u32 {
/// Clear the color of the render target.
const COLOR = citro3d_sys::C3D_CLEAR_COLOR; const COLOR = citro3d_sys::C3D_CLEAR_COLOR;
/// Clear the depth buffer value of the render target.
const DEPTH = citro3d_sys::C3D_CLEAR_DEPTH; const DEPTH = citro3d_sys::C3D_CLEAR_DEPTH;
/// Clear both color and depth buffer values of the render target.
const ALL = citro3d_sys::C3D_CLEAR_ALL; const ALL = citro3d_sys::C3D_CLEAR_ALL;
} }
} }

16
citro3d/src/shader.rs

@ -7,6 +7,9 @@
use std::error::Error; use std::error::Error;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
// Macros get exported at the crate root, so no reason to document this module.
// It still needs to be `pub` for the helper struct it exports.
#[doc(hidden)]
pub mod macros; pub mod macros;
/// A PICA200 shader program. It may have one or both of: /// A PICA200 shader program. It may have one or both of:
@ -110,11 +113,19 @@ impl Library {
})) }))
} }
/// Get the number of [`Entrypoint`]s in this shader library.
#[must_use] #[must_use]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
unsafe { (*self.0).numDVLE as usize } unsafe { (*self.0).numDVLE as usize }
} }
/// Whether the library has any [`Entrypoint`]s or not.
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Get the [`Entrypoint`] at the given index, if present.
#[must_use] #[must_use]
pub fn get(&self, index: usize) -> Option<Entrypoint> { pub fn get(&self, index: usize) -> Option<Entrypoint> {
if index < self.len() { if index < self.len() {
@ -127,11 +138,6 @@ impl Library {
} }
} }
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
fn as_raw(&mut self) -> *mut ctru_sys::DVLB_s { fn as_raw(&mut self) -> *mut ctru_sys::DVLB_s {
self.0 self.0
} }

15
citro3d/src/shader/macros.rs

@ -1,9 +1,4 @@
/// Helper struct to [`include_bytes`] aligned as a specific type. //! Helper macros for working with shader data.
#[repr(C)] // guarantee 'bytes' comes after '_align'
pub struct AlignedAs<Align, Bytes: ?Sized> {
pub _align: [Align; 0],
pub bytes: Bytes,
}
/// Helper macro for including a file as bytes that are correctly aligned for /// Helper macro for including a file as bytes that are correctly aligned for
/// use as a [`Library`](super::Library). /// use as a [`Library`](super::Library).
@ -22,3 +17,11 @@ macro_rules! include_aligned_bytes {
&ALIGNED.bytes &ALIGNED.bytes
}}; }};
} }
/// Helper struct to [`include_bytes`] aligned as a specific type.
#[repr(C)] // guarantee 'bytes' comes after '_align'
#[doc(hidden)]
pub struct AlignedAs<Align, Bytes: ?Sized> {
pub _align: [Align; 0],
pub bytes: Bytes,
}

1
citro3d/src/texture.rs

@ -1 +0,0 @@
Loading…
Cancel
Save