Skip to content

Commit

Permalink
feat: split commands into seperate module and simplify execution
Browse files Browse the repository at this point in the history
  • Loading branch information
SkillerRaptor committed Aug 30, 2024
1 parent 3466cb9 commit 66d3dd5
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 137 deletions.
47 changes: 47 additions & 0 deletions crates/hyper_rhi/src/commands/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// Copyright (c) 2024, SkillerRaptor
//
// SPDX-License-Identifier: MIT
//

use std::sync::Arc;

use crate::{buffer::Buffer, graphics_pipeline::GraphicsPipeline, texture::Texture};

#[derive(Clone, Debug)]
pub(crate) enum Command {
// Pass Commands
BeginRenderPass {
texture: Arc<dyn Texture>,
},
EndRenderPass,

// Bind Commands
BindDescriptor {
buffer: Arc<dyn Buffer>,
},

BindGraphicsPipeline {
graphics_pipeline: Arc<dyn GraphicsPipeline>,
},

BindIndexBuffer {
buffer: Arc<dyn Buffer>,
},

// Draw commands
Draw {
vertex_count: u32,
instance_count: u32,
first_vertex: u32,
first_instance: u32,
},

DrawIndexed {
index_count: u32,
instance_count: u32,
first_index: u32,
vertex_offset: i32,
first_instance: u32,
},
}
2 changes: 1 addition & 1 deletion crates/hyper_rhi/src/commands/command_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub trait CommandDecoder {
fn begin_render_pass(&self, texture: &Arc<dyn Texture>);
fn end_render_pass(&self, texture: &Arc<dyn Texture>);

fn bind_descriptor(&self, buffer: ResourceHandle);
fn bind_descriptor(&self, buffer: &Arc<dyn Buffer>);

fn bind_pipeline(
&self,
Expand Down
5 changes: 2 additions & 3 deletions crates/hyper_rhi/src/commands/command_encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
//

use crate::commands::{
command_list::{Command, CommandList},
command::Command,
command_list::CommandList,
render_pass::{RenderPass, RenderPassDescriptor},
};

Expand All @@ -20,8 +21,6 @@ impl CommandEncoder {
}
}

// TODO: Add compute pass

pub fn begin_render_pass(&mut self, descriptor: &RenderPassDescriptor) -> RenderPass {
RenderPass::new(&mut self.commands, descriptor)
}
Expand Down
202 changes: 79 additions & 123 deletions crates/hyper_rhi/src/commands/command_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,148 +7,104 @@
use std::sync::Arc;

use crate::{
buffer::Buffer,
commands::command_decoder::CommandDecoder,
commands::{command::Command, command_decoder::CommandDecoder},
graphics_pipeline::GraphicsPipeline,
resource::ResourceHandle,
texture::Texture,
};

// NOTE: As the command list holds the commands in the vector, all arc resources are automatically held on till the list gets dropped

#[derive(Clone, Debug)]
pub(crate) enum Command {
BeginRenderPass {
texture: Arc<dyn Texture>,
},
EndRenderPass,

BindDescriptor {
buffer: ResourceHandle,
},

BindPipeline {
graphics_pipeline: Arc<dyn GraphicsPipeline>,
},

BindIndexBuffer {
buffer: Arc<dyn Buffer>,
},

Draw {
vertex_count: u32,
instance_count: u32,
first_vertex: u32,
first_instance: u32,
},

DrawIndexed {
index_count: u32,
instance_count: u32,
first_index: u32,
vertex_offset: i32,
first_instance: u32,
},
}

struct RenderPassState {
graphics_pipeline: Option<Arc<dyn GraphicsPipeline>>,
texture: Arc<dyn Texture>,
}

pub struct CommandList {
render_pass_state: Option<RenderPassState>,

commands: Vec<Command>,
}

impl CommandList {
pub(crate) fn new(commands: Vec<Command>) -> Self {
Self {
render_pass_state: None,
commands,
}
Self { commands }
}

pub(crate) fn execute(&mut self, command_decoder: &dyn CommandDecoder) {
for command in &self.commands {
match command {
Command::BeginRenderPass { texture } => {
self.render_pass_state = Some(RenderPassState {
graphics_pipeline: None,
texture: Arc::clone(texture),
});

let render_pass_state = self.render_pass_state.as_ref().unwrap();
command_decoder.begin_render_pass(&render_pass_state.texture);
}
Command::EndRenderPass => {
debug_assert!(self.render_pass_state.is_some());

let render_pass_state = self.render_pass_state.as_ref().unwrap();
command_decoder.end_render_pass(&render_pass_state.texture);

self.render_pass_state = None;
}
Command::BindDescriptor { buffer } => {
debug_assert!(self.render_pass_state.is_some());

command_decoder.bind_descriptor(*buffer);
}
Command::BindPipeline { graphics_pipeline } => {
debug_assert!(self.render_pass_state.is_some());

let render_pass_state = self.render_pass_state.as_mut().unwrap();
render_pass_state.graphics_pipeline = Some(Arc::clone(graphics_pipeline));

command_decoder.bind_pipeline(
render_pass_state.graphics_pipeline.as_ref().unwrap(),
&render_pass_state.texture,
);
}
Command::BindIndexBuffer { buffer } => {
debug_assert!(self.render_pass_state.is_some());

command_decoder.bind_index_buffer(buffer);
}
Command::Draw {
vertex_count,
instance_count,
first_vertex,
first_instance,
} => {
debug_assert!(self.render_pass_state.is_some());

let render_pass_state = self.render_pass_state.as_ref().unwrap();
debug_assert!(render_pass_state.graphics_pipeline.is_some());

command_decoder.draw(
*vertex_count,
*instance_count,
*first_vertex,
*first_instance,
);
}
Command::DrawIndexed {
index_count,
instance_count,
first_index,
vertex_offset,
first_instance,
} => {
debug_assert!(self.render_pass_state.is_some());

let render_pass_state = self.render_pass_state.as_ref().unwrap();
debug_assert!(render_pass_state.graphics_pipeline.is_some());

command_decoder.draw_indexed(
*index_count,
*instance_count,
*first_index,
*vertex_offset,
*first_instance,
);
}
pub(crate) fn execute(self, command_decoder: &dyn CommandDecoder) {
// TODO: Add compute pass state
let mut current_compute_pass_state: Option<()> = None;
let mut current_render_pass_state = None;

for command in self.commands.into_iter() {
match (
current_compute_pass_state.as_mut(),
current_render_pass_state.as_mut(),
) {
(None, None) => match command {
Command::BeginRenderPass { texture } => {
current_render_pass_state = Some(RenderPassState {
graphics_pipeline: None,
texture: Arc::clone(&texture),
});

command_decoder.begin_render_pass(&texture);
}
_ => unreachable!(),
},
(None, Some(render_pass_state)) => match command {
Command::EndRenderPass => {
command_decoder.end_render_pass(&render_pass_state.texture);

current_render_pass_state = None;
}
Command::BindDescriptor { buffer } => {
command_decoder.bind_descriptor(&buffer);
}
Command::BindGraphicsPipeline { graphics_pipeline } => {
render_pass_state.graphics_pipeline = Some(Arc::clone(&graphics_pipeline));

command_decoder.bind_pipeline(
render_pass_state.graphics_pipeline.as_ref().unwrap(),
&render_pass_state.texture,
);
}
Command::BindIndexBuffer { buffer } => {
command_decoder.bind_index_buffer(&buffer);
}
Command::Draw {
vertex_count,
instance_count,
first_vertex,
first_instance,
} => {
debug_assert!(render_pass_state.graphics_pipeline.is_some());

command_decoder.draw(
vertex_count,
instance_count,
first_vertex,
first_instance,
);
}
Command::DrawIndexed {
index_count,
instance_count,
first_index,
vertex_offset,
first_instance,
} => {
debug_assert!(render_pass_state.graphics_pipeline.is_some());

command_decoder.draw_indexed(
index_count,
instance_count,
first_index,
vertex_offset,
first_instance,
);
}
_ => unreachable!(),
},
(Some(_compute_pass_state), None) => todo!(),
(Some(_), Some(_)) => unreachable!(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/hyper_rhi/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// SPDX-License-Identifier: MIT
//

pub(crate) mod command;
pub(crate) mod command_decoder;

pub mod command_encoder;
Expand Down
6 changes: 3 additions & 3 deletions crates/hyper_rhi/src/commands/render_pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{fmt::Debug, sync::Arc};

use crate::{
buffer::Buffer,
commands::{command_list::Command, descriptor::Descriptor},
commands::{command::Command, descriptor::Descriptor},
graphics_pipeline::GraphicsPipeline,
texture::Texture,
};
Expand All @@ -33,12 +33,12 @@ impl<'a> RenderPass<'a> {

pub fn bind_descriptor(&mut self, descriptor: &Descriptor) {
self.commands.push(Command::BindDescriptor {
buffer: descriptor.buffer.handle(),
buffer: Arc::clone(&descriptor.buffer),
});
}

pub fn bind_pipeline(&mut self, pipeline: &Arc<dyn GraphicsPipeline>) {
self.commands.push(Command::BindPipeline {
self.commands.push(Command::BindGraphicsPipeline {
graphics_pipeline: Arc::clone(pipeline),
});
}
Expand Down
3 changes: 1 addition & 2 deletions crates/hyper_rhi/src/d3d12/command_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ use crate::{
graphics_pipeline::GraphicsPipeline,
texture::Texture,
},
resource::ResourceHandle,
texture::Texture as _,
};

Expand Down Expand Up @@ -105,7 +104,7 @@ impl<'a> crate::commands::command_decoder::CommandDecoder for CommandDecoder<'a>
}
}

fn bind_descriptor(&self, buffer: ResourceHandle) {
fn bind_descriptor(&self, _buffer: &Arc<dyn crate::buffer::Buffer>) {
todo!()
}

Expand Down
2 changes: 1 addition & 1 deletion crates/hyper_rhi/src/d3d12/graphics_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ impl crate::graphics_device::GraphicsDevice for GraphicsDevice {

fn end_frame(&self) {}

fn submit(&self, mut command_list: CommandList) {
fn submit(&self, command_list: CommandList) {
let command_allocator = &self.current_frame().command_allocator;
let current_command_list = &self.current_frame().command_list;

Expand Down
5 changes: 2 additions & 3 deletions crates/hyper_rhi/src/vulkan/command_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use std::sync::Arc;
use ash::vk;

use crate::{
resource::ResourceHandle,
texture::Texture as _,
vulkan::{
buffer::Buffer,
Expand Down Expand Up @@ -114,8 +113,8 @@ impl<'a> crate::commands::command_decoder::CommandDecoder for CommandDecoder<'a>
}
}

fn bind_descriptor(&self, buffer: ResourceHandle) {
let bindings_offset = buffer.0;
fn bind_descriptor(&self, buffer: &Arc<dyn crate::buffer::Buffer>) {
let bindings_offset = buffer.handle().0;

unsafe {
self.graphics_device.device().cmd_push_constants(
Expand Down
2 changes: 1 addition & 1 deletion crates/hyper_rhi/src/vulkan/graphics_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ impl crate::graphics_device::GraphicsDevice for GraphicsDevice {
fn end_frame(&self) {}

// NOTE: This function assumes, that there will be only 1 command buffer and 1 submission per frame
fn submit(&self, mut command_list: CommandList) {
fn submit(&self, command_list: CommandList) {
let command_buffer = self.current_frame().command_buffer;

unsafe {
Expand Down

0 comments on commit 66d3dd5

Please sign in to comment.