aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:21 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:21 +0100
commit92e7aea7472693236e43c84cab603d78fdcebed0 (patch)
treeb3fcb1de6ea0ba8a80700815cb9893642c943415 /stockton-render/src
parent7f541bdb1456886c2819263f2d119bbacde7ecaf (diff)
refactor(render): use push constants for vp matrix
Diffstat (limited to 'stockton-render/src')
-rw-r--r--stockton-render/src/draw/camera.rs168
-rw-r--r--stockton-render/src/draw/context.rs30
-rw-r--r--stockton-render/src/draw/data/stockton.frag7
-rw-r--r--stockton-render/src/draw/data/stockton.vert8
4 files changed, 58 insertions, 155 deletions
diff --git a/stockton-render/src/draw/camera.rs b/stockton-render/src/draw/camera.rs
index cbad9b1..1a16803 100644
--- a/stockton-render/src/draw/camera.rs
+++ b/stockton-render/src/draw/camera.rs
@@ -19,7 +19,7 @@ use std::iter::once;
use std::f32::consts::PI;
use hal::prelude::*;
use hal::buffer::Usage;
-use na::{look_at_lh, perspective_lh_zo, radians};
+use na::{look_at_lh, perspective_lh_zo};
use core::mem::ManuallyDrop;
@@ -30,6 +30,9 @@ use stockton_types::{Vector3, Matrix4};
use na::{Mat4, Vec4};
/// 90 degrees in radians
+const R89: f32 = (PI / 180.0) * 89.0;
+
+/// 90 degrees in radians
const R90: f32 = PI / 2.0;
/// 180 degrees in radians
@@ -69,32 +72,23 @@ pub struct CameraSettings {
/// Holds settings related to the projection of world space to screen space
/// Also holds maths for generating important matrices
-pub struct WorkingCamera<'a> {
+pub struct WorkingCamera {
/// Settings for the camera
settings: CameraSettings,
/// Aspect ratio as a fraction
aspect_ratio: f32,
- /// Layout of the descriptor set to pass to the shader
- pub descriptor_set_layout: ManuallyDrop<DescriptorSetLayout>,
-
- /// Buffer of memory used for passing data to shaders
- // TODO: Does this need to be staged?
- buffer: ManuallyDrop<StagedBuffer<'a, Matrix4>>,
-
- // TODO: Share descriptor pool with textures?
- descriptor_pool: ManuallyDrop<DescriptorPool>,
- descriptor_set: DescriptorSet,
+ /// Cached view projection matrix
+ vp_matrix: Mat4,
- /// If true, buffer needs updated
+ /// If true, cached value needs updated
is_dirty: bool
}
-impl<'a> WorkingCamera<'a> {
- pub fn defaults(aspect_ratio: f32, device: &mut Device, adapter: &Adapter,
- command_queue: &mut CommandQueue,
- command_pool: &mut CommandPool) -> Result<WorkingCamera<'a>, error::CreationError> {
+impl WorkingCamera {
+ /// Return a camera with default settings
+ pub fn defaults(aspect_ratio: f32) -> WorkingCamera {
WorkingCamera::with_settings(CameraSettings {
position: Vector3::new(0.0, 0.0, 0.0),
rotation: Vector3::new(0.0, R90, 0.0),
@@ -102,100 +96,33 @@ impl<'a> WorkingCamera<'a> {
fov: f32::to_radians(90.0),
near: 0.1,
far: 1024.0,
- }, aspect_ratio, device, adapter, command_queue, command_pool)
+ }, aspect_ratio)
}
- /// Return a camera with default settings
- // TODO
- pub fn with_settings(settings: CameraSettings, aspect_ratio: f32, device: &mut Device, adapter: &Adapter,
- command_queue: &mut CommandQueue,
- command_pool: &mut CommandPool) -> Result<WorkingCamera<'a>, error::CreationError> {
-
- let descriptor_type = {
- use hal::pso::{DescriptorType, BufferDescriptorType, BufferDescriptorFormat};
-
- DescriptorType::Buffer {
- ty: BufferDescriptorType::Uniform,
- format: BufferDescriptorFormat::Structured {
- dynamic_offset: false
- }
- }
- };
-
- // Create set layout
- let descriptor_set_layout = unsafe {
- use hal::pso::{DescriptorSetLayoutBinding, ShaderStageFlags};
-
- device.create_descriptor_set_layout(
- &[
- DescriptorSetLayoutBinding {
- binding: 0,
- ty: descriptor_type,
- count: 1,
- stage_flags: ShaderStageFlags::VERTEX,
- immutable_samplers: false
- }
- ],
- &[],
- )
- }.map_err(|_| error::CreationError::OutOfMemoryError)?;
-
- // Create pool and allocate set
- let (descriptor_pool, descriptor_set) = unsafe {
- use hal::pso::{DescriptorRangeDesc, DescriptorPoolCreateFlags};
-
- let mut pool = device.create_descriptor_pool(
- 1,
- &[
- DescriptorRangeDesc {
- ty: descriptor_type,
- count: 1
- }
- ],
- DescriptorPoolCreateFlags::empty()
- ).map_err(|_| error::CreationError::OutOfMemoryError)?;
-
- let set = pool.allocate_set(&descriptor_set_layout).map_err(|_| error::CreationError::OutOfMemoryError)?;
-
- (pool, set)
- };
-
- // Create buffer for descriptor
- let mut buffer = StagedBuffer::new(device, adapter, Usage::UNIFORM, 1)?;
-
- // Bind our buffer to our descriptor set
- unsafe {
- use hal::pso::{Descriptor, DescriptorSetWrite};
- use hal::buffer::SubRange;
-
- device.write_descriptor_sets(once(
- DescriptorSetWrite {
- set: &descriptor_set,
- binding: 0,
- array_offset: 0,
- descriptors: once(
- Descriptor::Buffer(buffer.commit(device, command_queue, command_pool), SubRange::WHOLE)
- )
- }
- ));
- }
-
- Ok(WorkingCamera {
+ /// Return a camera with the given settings
+ pub fn with_settings(settings: CameraSettings, aspect_ratio: f32) -> WorkingCamera {
+ WorkingCamera {
aspect_ratio,
settings,
+ vp_matrix: Mat4::identity(),
+ is_dirty: true
+ }
+ }
- descriptor_set_layout: ManuallyDrop::new(descriptor_set_layout),
- buffer: ManuallyDrop::new(buffer),
-
- descriptor_pool: ManuallyDrop::new(descriptor_pool),
- descriptor_set: descriptor_set,
+ /// Get the VP matrix, updating cache if needed
+ pub fn get_matrix<'a>(&'a mut self) -> &'a Mat4 {
+ // Update matrix if needed
+ if self.is_dirty {
+ self.vp_matrix = self.calc_vp_matrix();
+ self.is_dirty = false;
+ }
- is_dirty: true
- })
+ // Return the matrix
+ &self.vp_matrix
}
/// Returns a matrix that transforms from world space to screen space
- pub fn vp_matrix(&self) -> Matrix4 {
+ fn calc_vp_matrix(&self) -> Matrix4 {
// Get look direction from euler angles
let direction = euler_to_direction(&self.settings.rotation);
@@ -238,10 +165,10 @@ impl<'a> WorkingCamera<'a> {
self.settings.rotation += euler;
// Clamp -pi/2 < pitch < pi/2
- if self.settings.rotation.x > R90 {
- self.settings.rotation.x = R90;
- } else if self.settings.rotation.x < -R90 {
- self.settings.rotation.x = -R90;
+ if self.settings.rotation.x > R89 {
+ self.settings.rotation.x = R89;
+ } else if self.settings.rotation.x <= -R89 {
+ self.settings.rotation.x = -R89;
}
// -pi < yaw <= pi
@@ -269,35 +196,6 @@ impl<'a> WorkingCamera<'a> {
self.is_dirty = true;
}
- /// Ensures the VP matrix on the GPU is up-to-date
- pub fn commit<'b>(&'b mut self, device: &Device,
- command_queue: &mut CommandQueue,
- command_pool: &mut CommandPool) -> &'b DescriptorSet {
- // Update buffer if needed
- if self.is_dirty {
- self.buffer[0] = self.vp_matrix();
- self.buffer.commit(device, command_queue, command_pool);
-
- self.is_dirty = false;
- }
-
- // Return the descriptor set for matrices
- &self.descriptor_set
- }
-
- /// This should be called before dropping
- pub fn deactivate(mut self, device: &mut Device) -> () {
- unsafe {
- use core::ptr::read;
-
- ManuallyDrop::into_inner(read(&self.buffer)).deactivate(device);
-
- self.descriptor_pool.reset();
- device.destroy_descriptor_pool(ManuallyDrop::into_inner(read(&self.descriptor_pool)));
- device.destroy_descriptor_set_layout(ManuallyDrop::into_inner(read(&self.descriptor_set_layout)));
- }
- }
-
pub fn camera_pos(&self) -> Vector3 {
self.settings.position
}
diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs
index 16fbf9f..a02203d 100644
--- a/stockton-render/src/draw/context.rs
+++ b/stockton-render/src/draw/context.rs
@@ -118,7 +118,7 @@ pub struct RenderingContext<'a> {
pub vert_buffer: ManuallyDrop<StagedBuffer<'a, UVPoint>>,
pub index_buffer: ManuallyDrop<StagedBuffer<'a, (u16, u16, u16)>>,
- camera: ManuallyDrop<WorkingCamera<'a>>
+ camera: WorkingCamera
}
impl<'a> RenderingContext<'a> {
@@ -268,10 +268,9 @@ impl<'a> RenderingContext<'a> {
// Camera
// TODO: Settings
let ratio = extent.width as f32 / extent.height as f32;
- let camera = WorkingCamera::defaults(ratio, &mut device, &adapter, &mut queue_group.queues[0], &mut cmd_pool)?;
+ let camera = WorkingCamera::defaults(ratio);
let mut descriptor_set_layouts: ArrayVec<[_; 2]> = ArrayVec::new();
- descriptor_set_layouts.push(camera.descriptor_set_layout.deref());
descriptor_set_layouts.push(texture_store.descriptor_set_layout.deref());
// Graphics pipeline
@@ -308,7 +307,7 @@ impl<'a> RenderingContext<'a> {
vert_buffer: ManuallyDrop::new(vert_buffer),
index_buffer: ManuallyDrop::new(index_buffer),
- camera: ManuallyDrop::new(camera)
+ camera
})
}
@@ -339,7 +338,6 @@ impl<'a> RenderingContext<'a> {
let (pipeline_layout, pipeline) = {
let mut descriptor_set_layouts: ArrayVec<[_; 2]> = ArrayVec::new();
- descriptor_set_layouts.push(self.camera.descriptor_set_layout.deref());
descriptor_set_layouts.push(self.texture_store.descriptor_set_layout.deref());
let subpass = hal::pass::Subpass {
@@ -583,7 +581,11 @@ impl<'a> RenderingContext<'a> {
// Pipeline layout
let layout = unsafe {
- device.create_pipeline_layout(set_layouts, &[])
+ device.create_pipeline_layout(
+ set_layouts,
+ // vp matrix, 4x4 f32
+ &[(ShaderStageFlags::VERTEX, 0..64)]
+ )
}.map_err(|_| error::CreationError::OutOfMemoryError)?;
// Colour blending
@@ -752,6 +754,7 @@ impl<'a> RenderingContext<'a> {
unsafe {
use hal::buffer::{IndexBufferView, SubRange};
use hal::command::{SubpassContents, CommandBufferFlags, ClearValue, ClearColor};
+ use hal::pso::ShaderStageFlags;
let buffer = &mut self.cmd_buffers[image_index];
let clear_values = [ClearValue {
@@ -789,10 +792,7 @@ impl<'a> RenderingContext<'a> {
);
buffer.bind_graphics_pipeline(&self.pipeline);
- let mut descriptor_sets: ArrayVec<[_; 2]> = ArrayVec::new();
- descriptor_sets.push(self.camera.commit(&self.device,
- &mut self.queue_group.queues[0],
- &mut self.cmd_pool));
+ let mut descriptor_sets: ArrayVec<[_; 1]> = ArrayVec::new();
descriptor_sets.push(&self.texture_store.descriptor_set);
buffer.bind_graphics_descriptor_sets(
@@ -802,6 +802,15 @@ impl<'a> RenderingContext<'a> {
&[]
);
+ let vp = self.camera.get_matrix().as_slice();
+ let vp = std::mem::transmute::<&[f32], &[u32]>(vp);
+
+ buffer.push_graphics_constants(
+ &self.pipeline_layout,
+ ShaderStageFlags::VERTEX,
+ 0,
+ vp);
+
buffer.bind_vertex_buffers(0, vbufs);
buffer.bind_index_buffer(IndexBufferView {
buffer: ibuf,
@@ -924,7 +933,6 @@ impl<'a> core::ops::Drop for RenderingContext<'a> {
ManuallyDrop::into_inner(read(&self.vert_buffer)).deactivate(&mut self.device);
ManuallyDrop::into_inner(read(&self.index_buffer)).deactivate(&mut self.device);
ManuallyDrop::into_inner(read(&self.texture_store)).deactivate(&mut self.device);
- ManuallyDrop::into_inner(read(&self.camera)).deactivate(&mut self.device);
self.device.destroy_command_pool(
ManuallyDrop::into_inner(read(&self.cmd_pool)),
diff --git a/stockton-render/src/draw/data/stockton.frag b/stockton-render/src/draw/data/stockton.frag
index b558335..c50e1b9 100644
--- a/stockton-render/src/draw/data/stockton.frag
+++ b/stockton-render/src/draw/data/stockton.frag
@@ -1,9 +1,8 @@
#version 450
-// DescriptorSet 0 = Matrices
-// DescriptorSet 1 = Textures
-layout(set = 1, binding = 0) uniform texture2D tex[2];
-layout(set = 1, binding = 1) uniform sampler samp[2];
+// DescriptorSet 0 = Textures
+layout(set = 0, binding = 0) uniform texture2D tex[2];
+layout(set = 0, binding = 1) uniform sampler samp[2];
layout (location = 1) in vec2 frag_uv;
layout (location = 2) in flat int frag_tex;
diff --git a/stockton-render/src/draw/data/stockton.vert b/stockton-render/src/draw/data/stockton.vert
index d3f4438..3146a25 100644
--- a/stockton-render/src/draw/data/stockton.vert
+++ b/stockton-render/src/draw/data/stockton.vert
@@ -1,11 +1,9 @@
#version 450
// DescriptorSet 0 = Matrices
-layout (binding = 0) uniform UniformBufferObject {
+layout (push_constant) uniform PushConsts {
mat4 vp;
-} matrices;
-
-// DescriptorSet 1 = Textures/Samplers
+} push;
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 uv;
@@ -19,7 +17,7 @@ layout (location = 2) out flat int frag_tex;
void main()
{
- gl_Position = matrices.vp * vec4(position, 1.0);
+ gl_Position = push.vp * vec4(position, 1.0);
frag_uv = uv;
frag_tex = tex;
} \ No newline at end of file