aboutsummaryrefslogtreecommitdiff
path: root/stockton-render
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:19 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:19 +0100
commita963fc3b65eff0f20afff71d0388f1d472467733 (patch)
treef3521822186a17711f52d62080d0a5992e2b7046 /stockton-render
parentcd94fb83fb51d37a84cbb80c8135430e26c74566 (diff)
feat(render): Resize vertex buffers and rainbow triangles example
Diffstat (limited to 'stockton-render')
-rw-r--r--stockton-render/src/draw/context.rs140
-rw-r--r--stockton-render/src/draw/data/stockton.frag6
-rw-r--r--stockton-render/src/draw/data/stockton.vert5
-rw-r--r--stockton-render/src/lib.rs19
4 files changed, 104 insertions, 66 deletions
diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs
index 6e51f46..07340c6 100644
--- a/stockton-render/src/draw/context.rs
+++ b/stockton-render/src/draw/context.rs
@@ -44,19 +44,25 @@ const COLOR_RANGE: image::SubresourceRange = image::SubresourceRange {
const VERTEX_SOURCE: &str = include_str!("./data/stockton.vert");
const FRAGMENT_SOURCE: &str = include_str!("./data/stockton.frag");
+const VERTEX_BUFFER_BATCH_SIZE: u64 = 10;
+const VERTEX_BUFFER_INITIAL_BATCHES: u64 = 1;
+
/// Represents a triangle in 2D (screen) space.
#[derive(Debug, Clone, Copy)]
pub struct Tri2 (pub [Vector2; 3]);
/// Easy conversion to proper format.
-impl From<Tri2> for [f32; 6] {
- fn from(tri: Tri2) -> [f32; 6] {
- [tri.0[0].x, tri.0[0].y,
- tri.0[1].x, tri.0[1].y,
- tri.0[2].x, tri.0[2].y]
+impl From<Tri2> for [f32; 15] {
+ fn from(tri: Tri2) -> [f32; 15] {
+ [tri.0[0].x, tri.0[0].y, 1.0, 0.0, 0.0,
+ tri.0[1].x, tri.0[1].y, 0.0, 1.0, 0.0,
+ tri.0[2].x, tri.0[2].y, 0.0, 0.0, 1.0]
}
}
+const TRI2_SIZE_F32: usize = 15;
+const TRI2_SIZE_BYTES: usize = size_of::<f32>() * TRI2_SIZE_F32;
+
/// Contains all the hal related stuff.
/// In the end, this takes some 3D points and puts it on the screen.
// TODO: Settings for clear colour, buffer sizes, etc
@@ -93,6 +99,7 @@ pub struct RenderingContext {
descriptor_set_layouts: <Backend as hal::Backend>::DescriptorSetLayout,
pipeline_layout: ManuallyDrop<<Backend as hal::Backend>::PipelineLayout>,
pipeline: ManuallyDrop<<Backend as hal::Backend>::GraphicsPipeline>,
+ adapter: adapter::Adapter<Backend>
}
@@ -237,27 +244,7 @@ impl RenderingContext {
// Vertex buffer
// TODO: Proper sizing / resizing
- let mut buffer = unsafe { device
- .create_buffer((size_of::<Tri2>() * 3).try_into().unwrap(), buffer::Usage::VERTEX) }
- .map_err(|e| CreationError::BufferError (e))?;
-
- let requirements = unsafe { device.get_buffer_requirements(&buffer) };
- let memory_type_id = adapter.physical_device
- .memory_properties().memory_types
- .iter().enumerate()
- .find(|&(id, memory_type)| {
- requirements.type_mask & (1 << id) != 0 && memory_type.properties.contains(memory::Properties::CPU_VISIBLE)
- })
- .map(|(id, _)| MemoryTypeId(id))
- .ok_or(CreationError::BufferNoMemory)?;
-
- let memory = unsafe {device
- .allocate_memory(memory_type_id, requirements.size) }
- .map_err(|_| CreationError::OutOfMemoryError)?;
-
- unsafe { device
- .bind_buffer_memory(&memory, 0, &mut buffer) }
- .map_err(|_| CreationError::BufferNoMemory)?;
+ let (buffer, requirements, memory) = Self::allocate_vertex_buffer(VERTEX_BUFFER_INITIAL_BATCHES, &mut device, &adapter)?;
// Command Pools, Buffers, imageviews, framebuffers & Sync objects
let frames_in_flight = backbuffer.len();
@@ -330,7 +317,9 @@ impl RenderingContext {
buffer: ManuallyDrop::new(buffer),
memory: ManuallyDrop::new(memory),
- requirements
+ requirements,
+
+ adapter
})
}
@@ -392,7 +381,7 @@ impl RenderingContext {
// Vertex buffers
let vertex_buffers: Vec<VertexBufferDesc> = vec![VertexBufferDesc {
binding: 0,
- stride: (size_of::<f32>() * 2) as u32,
+ stride: (size_of::<f32>() * 5) as u32,
rate: VertexInputRate::Vertex,
}];
@@ -403,6 +392,13 @@ impl RenderingContext {
format: Format::Rg32Sfloat,
offset: 0,
},
+ }, AttributeDesc {
+ location: 1,
+ binding: 0,
+ element: Element {
+ format: Format::Rgb32Sfloat,
+ offset: (size_of::<f32>() * 2) as ElemOffset,
+ }
}];
// Rasterizer
@@ -493,6 +489,35 @@ impl RenderingContext {
Ok((set_layout, layout, pipeline))
}
+ pub fn allocate_vertex_buffer(batches: u64, device: &mut <Backend as hal::Backend>::Device, adapter: &adapter::Adapter<Backend>)
+ -> Result<(<Backend as hal::Backend>::Buffer,
+ memory::Requirements,
+ <Backend as hal::Backend>::Memory), CreationError> {
+ let mut buffer = unsafe { device
+ .create_buffer(batches * VERTEX_BUFFER_BATCH_SIZE * TRI2_SIZE_BYTES as u64, buffer::Usage::VERTEX) }
+ .map_err(|e| CreationError::BufferError (e))?;
+
+ let requirements = unsafe { device.get_buffer_requirements(&buffer) };
+ let memory_type_id = adapter.physical_device
+ .memory_properties().memory_types
+ .iter().enumerate()
+ .find(|&(id, memory_type)| {
+ requirements.type_mask & (1 << id) != 0 && memory_type.properties.contains(memory::Properties::CPU_VISIBLE)
+ })
+ .map(|(id, _)| MemoryTypeId(id))
+ .ok_or(CreationError::BufferNoMemory)?;
+
+ let memory = unsafe {device
+ .allocate_memory(memory_type_id, requirements.size) }
+ .map_err(|_| CreationError::OutOfMemoryError)?;
+
+ unsafe { device
+ .bind_buffer_memory(&memory, 0, &mut buffer) }
+ .map_err(|_| CreationError::BufferNoMemory)?;
+
+ Ok((buffer, requirements, memory))
+ }
+
/// Draw a frame that's just cleared to the color specified.
pub fn draw_clear(&mut self, color: [f32; 4]) -> Result<(), FrameError> {
let get_image = &self.get_image[self.current_frame];
@@ -561,7 +586,45 @@ impl RenderingContext {
Ok(())
}
- pub fn draw_triangle(&mut self, tris: [Tri2; 3]) -> Result<(), &'static str> {
+ pub fn populate_vertices(&mut self, tris: &[Tri2]) -> Result<(), &'static str> {
+ // Ensure buffer is big enough
+ if tris.len() > (self.requirements.size as usize / TRI2_SIZE_BYTES) {
+ // Reallocate buffer
+ // Destroy old one
+ unsafe { self.device.free_memory(ManuallyDrop::take(&mut self.memory)) };
+ unsafe { self.device.destroy_buffer(ManuallyDrop::take(&mut self.buffer)) };
+
+ // Make new one
+ let batches = (tris.len() as u64 / VERTEX_BUFFER_BATCH_SIZE) + 1;
+
+ let (buffer, requirements, memory) = Self::allocate_vertex_buffer(batches, &mut self.device, &self.adapter)
+ .map_err(|_| "Couldn't re-allocate vertex buffer")?;
+ self.buffer = ManuallyDrop::new(buffer);
+ self.requirements = requirements;
+ self.memory = ManuallyDrop::new(memory);
+ }
+
+ // Write triangles to the vertex buffer
+ unsafe {
+ let mut data_target: mapping::Writer<_, f32> = self.device
+ .acquire_mapping_writer(&self.memory, 0..self.requirements.size)
+ .map_err(|_| "Failed to acquire a memory writer!")?;
+
+ for (i,tri) in tris.into_iter().enumerate() {
+ let points: [f32; 15] = (*tri).into();
+ data_target[i * TRI2_SIZE_F32..(i * TRI2_SIZE_F32) + TRI2_SIZE_F32].copy_from_slice(&points);
+ }
+
+ self
+ .device
+ .release_mapping_writer(data_target)
+ .map_err(|_| "Couldn't release the mapping writer!")?;
+ };
+
+ Ok(())
+ }
+
+ pub fn draw_vertices(&mut self) -> Result<(), &'static str> {
let get_image = &self.get_image[self.current_frame];
let render_complete = &self.render_complete[self.current_frame];
@@ -588,23 +651,6 @@ impl RenderingContext {
.map_err(|_| "FrameError::SyncObjectError")?;
};
- // Write triangle to the vertex buffer
- unsafe {
- let mut data_target = self.device
- .acquire_mapping_writer(&self.memory, 0..self.requirements.size)
- .map_err(|_| "Failed to acquire a memory writer!")?;
-
- for (i,tri) in tris.into_iter().enumerate() {
- let points: [f32; 6] = (*tri).into();
- data_target[i * 6..(i * 6) + 6].copy_from_slice(&points);
- }
-
- self
- .device
- .release_mapping_writer(data_target)
- .map_err(|_| "Couldn't release the mapping writer!")?;
- }
-
// Record commands
unsafe {
let buffer = &mut self.cmd_buffers[image_index];
@@ -625,7 +671,7 @@ impl RenderingContext {
let buffers: ArrayVec<[_; 1]> = [(buffer_ref, 0)].into();
encoder.bind_vertex_buffers(0, buffers);
- encoder.draw(0..18, 0..3);
+ encoder.draw(0..self.requirements.size as u32, 0..(self.requirements.size / TRI2_SIZE_BYTES as u64) as u32);
}
buffer.finish();
};
diff --git a/stockton-render/src/draw/data/stockton.frag b/stockton-render/src/draw/data/stockton.frag
index 032ff67..7cb4a47 100644
--- a/stockton-render/src/draw/data/stockton.frag
+++ b/stockton-render/src/draw/data/stockton.frag
@@ -1,8 +1,10 @@
#version 450
-layout(location = 0) out vec4 color;
+layout(location = 1) in vec3 frag_colour;
+
+layout(location = 0) out vec4 colour;
void main()
{
- color = vec4(1.0);
+ colour = vec4(frag_colour, 1.0);
} \ No newline at end of file
diff --git a/stockton-render/src/draw/data/stockton.vert b/stockton-render/src/draw/data/stockton.vert
index e0aea99..f6cafa9 100644
--- a/stockton-render/src/draw/data/stockton.vert
+++ b/stockton-render/src/draw/data/stockton.vert
@@ -1,12 +1,15 @@
#version 450
layout (location = 0) in vec2 position;
+layout (location = 1) in vec3 colour;
out gl_PerVertex {
vec4 gl_Position;
};
+layout (location = 1) out vec3 frag_colour;
void main()
{
- gl_Position = vec4(position, 0.0, 1.0);
+ gl_Position = vec4(position, 0.0, 1.0);
+ frag_colour = colour;
} \ No newline at end of file
diff --git a/stockton-render/src/lib.rs b/stockton-render/src/lib.rs
index 7d6c140..0bfc8ef 100644
--- a/stockton-render/src/lib.rs
+++ b/stockton-render/src/lib.rs
@@ -20,6 +20,7 @@
//! On Mac, you should use `metal`.
//! If your targetting machines without Vulkan, OpenGL or dx11/dx12 is preferred.
//! `empty` is used for testing
+#![feature(manually_drop_take)]
#[cfg(feature = "dx11")]
extern crate gfx_backend_dx11 as back;
@@ -44,7 +45,7 @@ extern crate winit;
extern crate arrayvec;
mod error;
-mod draw;
+pub mod draw;
use error::{CreationError, FrameError};
use draw::{RenderingContext, Tri2};
@@ -72,21 +73,7 @@ impl<'a> Renderer<'a> {
/// Render a single frame of the world
pub fn render_frame(&mut self) -> Result<(), FrameError>{
- // self.context.draw_clear([0.0, 0.5, 0.5, 1.0]).unwrap();
- // Ok(())
- self.context.draw_triangle([Tri2 ([
- Vector2::new(-1.0, -1.0),
- Vector2::new(-0.5, 0.0),
- Vector2::new(0.0, -1.0)
- ]), Tri2 ([
- Vector2::new(-0.5, -0.5),
- Vector2::new(0.5, -0.5),
- Vector2::new(0.0, 0.5)
- ]), Tri2 ([
- Vector2::new(0.5, 0.5),
- Vector2::new(1.0, 0.0),
- Vector2::new(0.0, 0.0)
- ]), ]).unwrap();
+ self.context.draw_vertices().unwrap();
Ok(())
}
}