Use RenderTarget instead of RenderPass directly

This commit is contained in:
hodasemi 2023-01-21 14:14:43 +01:00
parent 672c0f00ba
commit febcfbc0b4
2 changed files with 181 additions and 196 deletions

View file

@ -54,6 +54,16 @@ impl<T> TargetMode<T> {
TargetMode::Stereo(l, r) => (l, r),
}
}
pub fn execute<F, R>(&self, mut f: F) -> anyhow::Result<TargetMode<R>>
where
F: FnMut(&T) -> anyhow::Result<R>,
{
Ok(match self {
TargetMode::Mono(s) => TargetMode::Mono(f(s)?),
TargetMode::Stereo(l, r) => TargetMode::Stereo(f(l)?, f(r)?),
})
}
}
impl<T: Clone> Clone for TargetMode<T> {
@ -64,3 +74,15 @@ impl<T: Clone> Clone for TargetMode<T> {
}
}
}
impl<T> From<T> for TargetMode<T> {
fn from(value: T) -> Self {
TargetMode::Mono(value)
}
}
impl<T> From<(T, T)> for TargetMode<T> {
fn from((lhs, rhs): (T, T)) -> Self {
TargetMode::Stereo(lhs, rhs)
}
}

View file

@ -72,7 +72,6 @@ impl<'a> GuiHandlerCreateInfo<'a> {
struct GuiSeparator {
_descriptor_layout: Arc<DescriptorSetLayout>,
_pipeline_layout: Arc<PipelineLayout>,
_pipeline: Arc<Pipeline>,
}
@ -111,13 +110,12 @@ pub struct GuiHandler {
top_ui: RwLock<Option<Arc<dyn TopGui>>>,
tooltip_ui: RwLock<Option<Arc<dyn TopGui>>>,
render_pass: Arc<RenderPass>,
framebuffers: Mutex<TargetMode<Vec<Arc<Framebuffer>>>>,
render_targets: TargetMode<RwLock<RenderTarget>>,
command_buffers: TargetMode<Vec<CommandBufferState>>,
text_objects: GuiSeparator,
rectangle_objects: GuiSeparator,
single_color_objects: GuiSeparator,
text_objects: TargetMode<GuiSeparator>,
rectangle_objects: TargetMode<GuiSeparator>,
single_color_objects: TargetMode<GuiSeparator>,
_bitmap_font: Arc<Image>,
_bitmap_desc_pool: Arc<DescriptorPool>,
@ -183,18 +181,25 @@ impl GuiHandler {
}
};
let render_pass =
Self::create_render_pass(device, context.format(), context.image_layout())?;
let framebuffers = Self::create_framebuffers(device, &context.images(), &render_pass)?;
// let render_pass =
// Self::create_render_pass(device, context.format(), context.image_layout())?;
// let framebuffers = Self::create_framebuffers(device, &context.images(), &render_pass)?;
let (text_objs, color_layout) = Self::init_text_objects(device, &render_pass)?;
let rect_objs = Self::init_rectangle_objects(device, &render_pass)?;
let single_color_objects = Self::init_single_color_objects(device, &render_pass)?;
let render_targets = Self::create_render_targets(device, &context.images())?;
let (text_objs, color_layout) = Self::init_text_objects(device, &render_targets)?;
let rect_objs = Self::init_rectangle_objects(device, &render_targets)?;
let single_color_objects = Self::init_single_color_objects(device, &render_targets)?;
let (bitmap_texture, bitmap_desc_pool, bitmap_desc_set) = Self::init_bitmap_font(
device,
queue,
text_objs._descriptor_layout.clone(),
match &text_objs {
TargetMode::Mono(l) => l,
TargetMode::Stereo(l, _) => l,
}
._descriptor_layout
.clone(),
gui_handler_create_info.font.clone(),
)?;
@ -252,8 +257,7 @@ impl GuiHandler {
top_ui: RwLock::new(None),
tooltip_ui: RwLock::new(None),
render_pass,
framebuffers: Mutex::new(framebuffers),
render_targets,
command_buffers,
text_objects: text_objs,
@ -382,6 +386,14 @@ impl GuiHandler {
}
}
fn text_desc_layout(&self) -> &Arc<DescriptorSetLayout> {
&match &self.text_objects {
TargetMode::Mono(l) => l,
TargetMode::Stereo(l, _) => l,
}
._descriptor_layout
}
pub(crate) fn image_descriptor(&self, mut path: AssetPath) -> Result<Arc<DescriptorSet>> {
if !path.has_prefix() {
path.set_prefix(&self.resource_base_path.full_path());
@ -398,7 +410,7 @@ impl GuiHandler {
.build(&self.device, &self.queue)?;
let desc_pool = DescriptorPool::builder()
.set_layout(self.text_objects._descriptor_layout.clone())
.set_layout(self.text_desc_layout().clone())
.build(self.device.clone())?;
let descriptor_set = DescriptorPool::prepare_set(&desc_pool).allocate()?;
@ -761,17 +773,15 @@ impl GuiHandler {
fn render(
&self,
command_buffer_state: &CommandBufferState,
framebuffer: &Arc<Framebuffer>,
render_target: &RenderTarget,
single_color_objects: &GuiSeparator,
rectangle_objects: &GuiSeparator,
text_objects: &GuiSeparator,
) -> Result<()> {
if !command_buffer_state.valid.load(SeqCst) {
let gui_command_buffer = &command_buffer_state.command_buffer;
let inheritance_info = CommandBuffer::inheritance_info(
Some(&self.render_pass),
Some(0),
Some(framebuffer),
None,
);
let inheritance_info = render_target.inheritance_info();
let mut command_buffer_begin_info = VkCommandBufferBeginInfo::new(
VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
@ -802,7 +812,7 @@ impl GuiHandler {
for (_, elements) in layers.iter() {
if !elements.is_colorables_empty() {
buffer_recorder.bind_pipeline(&self.single_color_objects._pipeline)?;
buffer_recorder.bind_pipeline(&single_color_objects._pipeline)?;
buffer_recorder.set_scissor(&scissor);
buffer_recorder.set_viewport(&viewport);
@ -819,7 +829,7 @@ impl GuiHandler {
}
if !elements.is_displayables_empty() || !elements.is_iconizables_empty() {
buffer_recorder.bind_pipeline(&self.rectangle_objects._pipeline)?;
buffer_recorder.bind_pipeline(&rectangle_objects._pipeline)?;
buffer_recorder.set_scissor(&scissor);
buffer_recorder.set_viewport(&viewport);
@ -846,7 +856,7 @@ impl GuiHandler {
}
if !elements.is_textables_empty() {
buffer_recorder.bind_pipeline(&self.text_objects._pipeline)?;
buffer_recorder.bind_pipeline(&text_objects._pipeline)?;
buffer_recorder.set_scissor(&scissor);
buffer_recorder.set_viewport(&viewport);
@ -1139,113 +1149,27 @@ impl GuiHandler {
// private
impl GuiHandler {
/// Creates a simple render pass for gui rendering
/// Only color framebuffer is attached
fn create_render_pass(
device: &Arc<Device>,
final_format: VkFormat,
target_layout: VkImageLayout,
) -> Result<Arc<RenderPass>> {
let target_reference = VkAttachmentReference {
attachment: 0,
layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
};
let subpass_descriptions = [VkSubpassDescription::new(
0,
&[],
slice::from_ref(&target_reference),
&[],
None,
&[],
)];
let attachments = [VkAttachmentDescription::new(
0,
final_format,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
target_layout,
target_layout,
)];
let src_access = Image::src_layout_to_access(target_layout);
let dst_access = Image::dst_layout_to_access(target_layout);
let render_pass_image_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
let dependencies = [
VkSubpassDependency::new(
VK_SUBPASS_EXTERNAL,
0,
CommandBuffer::access_to_stage(src_access),
CommandBuffer::access_to_stage(render_pass_image_access),
src_access,
render_pass_image_access,
VK_DEPENDENCY_BY_REGION_BIT,
),
VkSubpassDependency::new(
0,
VK_SUBPASS_EXTERNAL,
CommandBuffer::access_to_stage(render_pass_image_access),
CommandBuffer::access_to_stage(dst_access),
render_pass_image_access,
dst_access,
VK_DEPENDENCY_BY_REGION_BIT,
),
];
let renderpass = RenderPass::new(
device.clone(),
&subpass_descriptions,
&attachments,
&dependencies,
)?;
Ok(renderpass)
}
fn create_framebuffers(
fn create_render_targets(
device: &Arc<Device>,
target_images: &TargetMode<Vec<Arc<Image>>>,
render_pass: &Arc<RenderPass>,
) -> Result<TargetMode<Vec<Arc<Framebuffer>>>> {
// closure to create array of framebuffer from array of images
let create_framebuffer = |device: &Arc<Device>,
images: &Vec<Arc<Image>>,
render_pass: &Arc<RenderPass>|
-> Result<Vec<Arc<Framebuffer>>> {
let mut framebuffers = Vec::with_capacity(images.len());
for image in images.iter() {
Image::convert_layout(image, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)?;
framebuffers.push(
Framebuffer::builder()
.set_render_pass(render_pass)
.add_attachment(image)
.build(device.clone())?,
) -> Result<TargetMode<RwLock<RenderTarget>>> {
let create = |target_images: &Vec<Arc<Image>>| -> Result<RenderTarget> {
RenderTarget::builder()
.add_sub_pass(
SubPass::builder(target_images[0].width(), target_images[0].height())
.set_prepared_targets(target_images, 0, [0.0, 0.0, 0.0, 0.0], false)
.build(device)?,
)
}
Ok(framebuffers)
.build(device)
};
match target_images {
TargetMode::Mono(images) => {
let framebuffers = create_framebuffer(device, images, render_pass)?;
Ok(TargetMode::Mono(framebuffers))
}
TargetMode::Stereo(left_images, right_images) => {
let left_framebuffers = create_framebuffer(device, left_images, render_pass)?;
let right_framebuffers = create_framebuffer(device, right_images, render_pass)?;
Ok(TargetMode::Stereo(left_framebuffers, right_framebuffers))
}
}
Ok(match target_images {
TargetMode::Mono(images) => TargetMode::Mono(RwLock::new(create(images)?)),
TargetMode::Stereo(left_images, right_images) => TargetMode::Stereo(
RwLock::new(create(left_images)?),
RwLock::new(create(right_images)?),
),
})
}
fn create_command_buffers(
@ -1295,8 +1219,8 @@ impl GuiHandler {
fn init_text_objects(
device: &Arc<Device>,
render_pass: &Arc<RenderPass>,
) -> Result<(GuiSeparator, Arc<DescriptorSetLayout>)> {
render_targets: &TargetMode<RwLock<RenderTarget>>,
) -> Result<(TargetMode<GuiSeparator>, Arc<DescriptorSetLayout>)> {
// --- layout creation ---
let descriptor_layout = DescriptorSetLayout::builder()
.add_layout_binding(
@ -1332,31 +1256,30 @@ impl GuiHandler {
let (input_bindings, input_attributes) = TexturedVertex::vertex_input_state();
let pipeline = GuiHandler::init_gui_pipeline(
device,
input_bindings,
input_attributes,
render_pass,
&pipeline_layout,
vertex_shader,
fragment_shader,
)?;
Ok((
GuiSeparator {
_descriptor_layout: descriptor_layout,
_pipeline_layout: pipeline_layout,
render_targets.execute(|render_target| {
Ok(GuiSeparator {
_descriptor_layout: descriptor_layout.clone(),
_pipeline: pipeline,
},
_pipeline: GuiHandler::init_gui_pipeline(
device,
input_bindings.clone(),
input_attributes.clone(),
render_target.read().unwrap().render_pass(),
&pipeline_layout,
vertex_shader.clone(),
fragment_shader.clone(),
)?,
})
})?,
color_layout,
))
}
fn init_rectangle_objects(
device: &Arc<Device>,
render_pass: &Arc<RenderPass>,
) -> Result<GuiSeparator> {
render_targets: &TargetMode<RwLock<RenderTarget>>,
) -> Result<TargetMode<GuiSeparator>> {
let descriptor_layout = DescriptorSetLayout::builder()
.add_layout_binding(
0,
@ -1384,28 +1307,27 @@ impl GuiHandler {
let (input_bindings, input_attributes) = TexturedVertex::vertex_input_state();
let pipeline = GuiHandler::init_gui_pipeline(
device,
input_bindings,
input_attributes,
render_pass,
&pipeline_layout,
vertex_shader,
fragment_shader,
)?;
render_targets.execute(|render_target| {
Ok(GuiSeparator {
_descriptor_layout: descriptor_layout.clone(),
Ok(GuiSeparator {
_descriptor_layout: descriptor_layout,
_pipeline_layout: pipeline_layout,
_pipeline: pipeline,
_pipeline: GuiHandler::init_gui_pipeline(
device,
input_bindings.clone(),
input_attributes.clone(),
render_target.read().unwrap().render_pass(),
&pipeline_layout,
vertex_shader.clone(),
fragment_shader.clone(),
)?,
})
})
}
fn init_single_color_objects(
device: &Arc<Device>,
render_pass: &Arc<RenderPass>,
) -> Result<GuiSeparator> {
render_targets: &TargetMode<RwLock<RenderTarget>>,
) -> Result<TargetMode<GuiSeparator>> {
let color_layout = DescriptorSetLayout::builder()
.add_layout_binding(
0,
@ -1433,21 +1355,20 @@ impl GuiHandler {
let (input_bindings, input_attributes) = Colorable::vertex_input_state();
let pipeline = GuiHandler::init_gui_pipeline(
device,
input_bindings,
input_attributes,
render_pass,
&pipeline_layout,
vertex_shader,
fragment_shader,
)?;
render_targets.execute(|render_target| {
Ok(GuiSeparator {
_descriptor_layout: color_layout.clone(),
Ok(GuiSeparator {
_descriptor_layout: color_layout,
_pipeline_layout: pipeline_layout,
_pipeline: pipeline,
_pipeline: GuiHandler::init_gui_pipeline(
device,
input_bindings.clone(),
input_attributes.clone(),
render_target.read().unwrap().render_pass(),
&pipeline_layout,
vertex_shader.clone(),
fragment_shader.clone(),
)?,
})
})
}
@ -1475,24 +1396,31 @@ impl GuiHandler {
&self,
buffer_recorder: &mut CommandBufferRecorder<'_>,
command_buffer_states: &[CommandBufferState],
framebuffers: &[Arc<Framebuffer>],
render_target: &RenderTarget,
single_color_objects: &GuiSeparator,
rectangle_objects: &GuiSeparator,
text_objects: &GuiSeparator,
index: usize,
) -> Result<()> {
let command_buffer_state = &command_buffer_states[index];
let framebuffer = &framebuffers[index];
self.render(command_buffer_state, framebuffer)?;
self.render(
command_buffer_state,
render_target,
single_color_objects,
rectangle_objects,
text_objects,
)?;
buffer_recorder.begin_render_pass_full(
&self.render_pass,
framebuffer,
&[],
render_target.begin(
buffer_recorder,
VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS,
index,
);
buffer_recorder.execute_commands(&[&command_buffer_state.command_buffer]);
buffer_recorder.end_render_pass();
render_target.end(buffer_recorder);
Ok(())
}
@ -1537,23 +1465,56 @@ impl GuiHandler {
match (
&self.command_buffers,
self.framebuffers.lock().unwrap().deref(),
&self.render_targets,
&self.text_objects,
&self.rectangle_objects,
&self.single_color_objects,
indices,
) {
(
TargetMode::Mono(command_buffers),
TargetMode::Mono(framebuffers),
TargetMode::Mono(render_target),
TargetMode::Mono(text_objects),
TargetMode::Mono(rectangle_objects),
TargetMode::Mono(single_color_object),
TargetMode::Mono(index),
) => {
self.select_rendering(buffer_recorder, command_buffers, framebuffers, *index)?;
self.select_rendering(
buffer_recorder,
command_buffers,
&*render_target.read().unwrap(),
single_color_object,
rectangle_objects,
text_objects,
*index,
)?;
}
(
TargetMode::Stereo(left_cbs, right_cbs),
TargetMode::Stereo(left_frb, right_frb),
TargetMode::Stereo(left_rt, right_rt),
TargetMode::Stereo(left_text_objects, right_text_objects),
TargetMode::Stereo(left_rectangle_objects, right_rectangle_objects),
TargetMode::Stereo(left_single_color_object, right_single_color_object),
TargetMode::Stereo(left_index, right_index),
) => {
self.select_rendering(buffer_recorder, left_cbs, left_frb, *left_index)?;
self.select_rendering(buffer_recorder, right_cbs, right_frb, *right_index)?;
self.select_rendering(
buffer_recorder,
left_cbs,
&*left_rt.read().unwrap(),
left_single_color_object,
left_rectangle_objects,
left_text_objects,
*left_index,
)?;
self.select_rendering(
buffer_recorder,
right_cbs,
&*right_rt.read().unwrap(),
right_single_color_object,
right_rectangle_objects,
right_text_objects,
*right_index,
)?;
}
_ => panic!("Invalid TargetMode combination"),
};
@ -1562,11 +1523,13 @@ impl GuiHandler {
}
pub fn resize(&self, width: u32, height: u32) -> Result<()> {
*self.framebuffers.lock().unwrap() = Self::create_framebuffers(
self.context.device(),
&self.context.images(),
&self.render_pass,
)?;
todo!();
// *self.framebuffers.lock().unwrap() = Self::create_framebuffers(
// self.context.device(),
// &self.context.images(),
// &self.render_pass,
// )?;
self.needs_update.store(true, SeqCst);
*self.ortho.write().unwrap() = ortho(0.0, width as f32, 0.0, height as f32, -1.0, 1.0);