diff --git a/src/context_interface.rs b/src/context_interface.rs index 3ac43d3..8336859 100644 --- a/src/context_interface.rs +++ b/src/context_interface.rs @@ -54,6 +54,16 @@ impl TargetMode { TargetMode::Stereo(l, r) => (l, r), } } + + pub fn execute(&self, mut f: F) -> anyhow::Result> + where + F: FnMut(&T) -> anyhow::Result, + { + Ok(match self { + TargetMode::Mono(s) => TargetMode::Mono(f(s)?), + TargetMode::Stereo(l, r) => TargetMode::Stereo(f(l)?, f(r)?), + }) + } } impl Clone for TargetMode { @@ -64,3 +74,15 @@ impl Clone for TargetMode { } } } + +impl From for TargetMode { + fn from(value: T) -> Self { + TargetMode::Mono(value) + } +} + +impl From<(T, T)> for TargetMode { + fn from((lhs, rhs): (T, T)) -> Self { + TargetMode::Stereo(lhs, rhs) + } +} diff --git a/src/guihandler/guihandler.rs b/src/guihandler/guihandler.rs index 59860ca..256eb96 100644 --- a/src/guihandler/guihandler.rs +++ b/src/guihandler/guihandler.rs @@ -72,7 +72,6 @@ impl<'a> GuiHandlerCreateInfo<'a> { struct GuiSeparator { _descriptor_layout: Arc, - _pipeline_layout: Arc, _pipeline: Arc, } @@ -111,13 +110,12 @@ pub struct GuiHandler { top_ui: RwLock>>, tooltip_ui: RwLock>>, - render_pass: Arc, - framebuffers: Mutex>>>, + render_targets: TargetMode>, command_buffers: TargetMode>, - text_objects: GuiSeparator, - rectangle_objects: GuiSeparator, - single_color_objects: GuiSeparator, + text_objects: TargetMode, + rectangle_objects: TargetMode, + single_color_objects: TargetMode, _bitmap_font: Arc, _bitmap_desc_pool: Arc, @@ -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 { + &match &self.text_objects { + TargetMode::Mono(l) => l, + TargetMode::Stereo(l, _) => l, + } + ._descriptor_layout + } + pub(crate) fn image_descriptor(&self, mut path: AssetPath) -> Result> { 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, + 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, - final_format: VkFormat, - target_layout: VkImageLayout, - ) -> Result> { - 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, target_images: &TargetMode>>, - render_pass: &Arc, - ) -> Result>>> { - // closure to create array of framebuffer from array of images - let create_framebuffer = |device: &Arc, - images: &Vec>, - render_pass: &Arc| - -> Result>> { - 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>> { + let create = |target_images: &Vec>| -> Result { + 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, - render_pass: &Arc, - ) -> Result<(GuiSeparator, Arc)> { + render_targets: &TargetMode>, + ) -> Result<(TargetMode, Arc)> { // --- 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, - render_pass: &Arc, - ) -> Result { + render_targets: &TargetMode>, + ) -> Result> { 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, - render_pass: &Arc, - ) -> Result { + render_targets: &TargetMode>, + ) -> Result> { 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], + 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);