diff options
Diffstat (limited to 'src/graphics_window_dressing.rs')
| -rw-r--r-- | src/graphics_window_dressing.rs | 309 |
1 files changed, 186 insertions, 123 deletions
diff --git a/src/graphics_window_dressing.rs b/src/graphics_window_dressing.rs index 51483cf..1b5b602 100644 --- a/src/graphics_window_dressing.rs +++ b/src/graphics_window_dressing.rs @@ -27,8 +27,9 @@ pub const N_SIMULTANEOUS_FRAMES: usize = 5; // The WindowDressing collects the Vulkan graphics objects which need to be // regenerated or modified when the window changes in certain ways, such as -// resizing. The ones which don't need that are collected above, in -// PermanentGraphicsState. +// resizing, but are not needed during rendering. The ones which don't need to +// be regenerated are collected in PermanentGraphicsState. The ones which are +// needed during rendering are collected in RenderState, below. #[derive(Debug)] pub struct WindowDressing { pub swapchain: Swapchain, @@ -42,23 +43,9 @@ pub struct WindowDressing { depth_image_view: vk::ImageView, depth_format: vk::Format, - pub render_pass: vk::RenderPass, - - pub pipeline: vk::Pipeline, - pub pipeline_layout: vk::PipelineLayout, - - pub framebuffers: Vec<vk::Framebuffer>, - primary_command_pool: vk::CommandPool, transient_command_pool: vk::CommandPool, - pub vertex_buffer: vk::Buffer, - vertex_buffer_memory: vk::DeviceMemory, - - pub index_buffer: vk::Buffer, - index_buffer_memory: vk::DeviceMemory, - pub index_count: usize, - texture_image: vk::Image, texture_image_memory: vk::DeviceMemory, texture_image_view: vk::ImageView, @@ -69,13 +56,32 @@ pub struct WindowDressing { pub uniform_buffer_memory: Vec<vk::DeviceMemory>, descriptor_pool: vk::DescriptorPool, - pub descriptor_sets: Vec<vk::DescriptorSet>, - - pub command_buffers: Vec<vk::CommandBuffer>, pub concurrency: Concurrency, } +// The RenderState collects the Vulkan graphics objects which need to be +// regenerated or modified when the window changes, as with WindowDressing, +// and which are also used as part of rendering. +#[derive(Debug)] +pub struct RenderState { + pub render_pass: vk::RenderPass, + + pub pipeline: vk::Pipeline, + pub pipeline_layout: vk::PipelineLayout, + + pub vertex_buffer: vk::Buffer, + vertex_buffer_memory: vk::DeviceMemory, + + pub index_buffer: vk::Buffer, + index_buffer_memory: vk::DeviceMemory, + pub index_count: usize, + + pub framebuffers: Vec<vk::Framebuffer>, + pub command_buffers: Vec<vk::CommandBuffer>, + pub descriptor_sets: Vec<vk::DescriptorSet>, +} + // A swapchain is the generalized facility that is used to implement // double buffering, triple buffering, rendering passes that feed into each // other, and other things of that nature. It's a first-class thing but for @@ -125,7 +131,6 @@ impl WindowDressing { let physical_device = &for_reinit.physical_device; let sample_count = for_reinit.sample_count; let indices = &for_reinit.indices; - let descriptor_set_layout = &for_reinit.descriptor_set_layout; let swapchain = init_swapchain( window, instance, surface, &physical_device, device, &indices)?; @@ -138,30 +143,9 @@ impl WindowDressing { = init_depth(instance, &physical_device, device, &swapchain.extent, sample_count)?; - let render_pass = init_render_pass(device, sample_count, - &swapchain.format, &depth_format)?; - - let (pipeline_layout, pipeline) - = init_pipeline(device, descriptor_set_layout, &swapchain.extent, - sample_count, &render_pass)?; - - let framebuffers = init_framebuffers( - device, &swapchain.extent, &swapchain.image_views, - &color_image_view, &depth_image_view, &render_pass)?; - let (primary_command_pool, transient_command_pool) = init_command_pools(device, indices)?; - let (vertices, indices) = load_model()?; - let index_count = indices.len(); - - let (vertex_buffer, vertex_buffer_memory) - = init_vertex_buffer(vertices, instance, physical_device, device, - graphics_queue, &transient_command_pool)?; - let (index_buffer, index_buffer_memory) - = init_index_buffer(indices, instance, physical_device, device, - graphics_queue, &transient_command_pool)?; - let (texture_image, texture_image_memory, texture_image_view, mip_count) = init_texture(instance, physical_device, device, graphics_queue, &transient_command_pool)?; @@ -174,16 +158,6 @@ impl WindowDressing { let descriptor_pool = init_descriptor_pool(device, swapchain.images.len())?; - let descriptor_sets - = init_descriptor_sets(device, descriptor_set_layout, - &uniform_buffers, &descriptor_pool, - swapchain.images.len(), - &texture_image_view, &sampler)?; - - let command_buffers = init_command_buffers( - device, &swapchain.extent, &framebuffers, &render_pass, - &pipeline_layout, &pipeline, &vertex_buffer, &index_buffer, - index_count, &descriptor_sets, &primary_command_pool)?; let concurrency = init_concurrency(device, &swapchain.images)?; @@ -196,15 +170,6 @@ impl WindowDressing { depth_image_memory, depth_image_view, depth_format, - render_pass, - pipeline, - pipeline_layout, - framebuffers, - vertex_buffer, - vertex_buffer_memory, - index_buffer, - index_buffer_memory, - index_count, texture_image, texture_image_memory, texture_image_view, @@ -213,10 +178,8 @@ impl WindowDressing { uniform_buffers, uniform_buffer_memory, descriptor_pool, - descriptor_sets, primary_command_pool, transient_command_pool, - command_buffers, concurrency, }) } @@ -251,17 +214,6 @@ impl WindowDressing { = init_depth(instance, &physical_device, device, &swapchain.extent, sample_count)?; - let render_pass = init_render_pass(device, sample_count, - &swapchain.format, &depth_format)?; - - let (pipeline_layout, pipeline) - = init_pipeline(device, descriptor_set_layout, &swapchain.extent, - sample_count, &render_pass)?; - - let framebuffers = init_framebuffers( - device, &swapchain.extent, &swapchain.image_views, - &color_image_view, &depth_image_view, &render_pass)?; - let (uniform_buffers, uniform_buffer_memory) = init_uniform_buffers(instance, physical_device, device, swapchain.images.len())?; @@ -270,19 +222,6 @@ impl WindowDressing { let descriptor_pool = init_descriptor_pool(device, swapchain.images.len())?; - let descriptor_sets - = init_descriptor_sets(device, descriptor_set_layout, - &uniform_buffers, &descriptor_pool, - swapchain.images.len(), - &self.texture_image_view, &self.sampler)?; - - // Notice that we reused the command pool. - let command_buffers = init_command_buffers( - device, &swapchain.extent, &framebuffers, &render_pass, - &pipeline_layout, &pipeline, &self.vertex_buffer, - &self.index_buffer, self.index_count, &descriptor_sets, - &self.primary_command_pool)?; - self.concurrency.image_fences.resize(swapchain.images.len(), vk::Fence::null()); @@ -294,15 +233,9 @@ impl WindowDressing { self.depth_image_memory = depth_image_memory; self.depth_image_view = depth_image_view; self.depth_format = depth_format; - self.render_pass = render_pass; - self.pipeline = pipeline; - self.pipeline_layout = pipeline_layout; - self.framebuffers = framebuffers; self.uniform_buffers = uniform_buffers; self.uniform_buffer_memory = uniform_buffer_memory; self.descriptor_pool = descriptor_pool; - self.descriptor_sets = descriptor_sets; - self.command_buffers = command_buffers; Ok(()) } @@ -314,12 +247,6 @@ impl WindowDressing { pub fn destroy(mut self, device: &Device) { self.destroy_replaceable(device); - unsafe { device.destroy_buffer(self.vertex_buffer, None) }; - unsafe { device.free_memory(self.vertex_buffer_memory, None) }; - - unsafe { device.destroy_buffer(self.index_buffer, None) }; - unsafe { device.free_memory(self.index_buffer_memory, None) }; - unsafe { device.destroy_image(self.texture_image, None) }; unsafe { device.free_memory(self.texture_image_memory, None) }; unsafe { device.destroy_image_view(self.texture_image_view, None) }; @@ -346,20 +273,6 @@ impl WindowDressing { #[allow(unsafe_code)] fn destroy_replaceable(&mut self, device: &Device) { - for framebuffer in &self.framebuffers { - unsafe { device.destroy_framebuffer(*framebuffer, None) }; - } - - // Notice that we free the buffers in the pool, but do not destroy the - // pool itself. Notice also that we only do this for the primary command - // pool, because that's the only one where we've kept track of the - // buffers. We promise ourselves to free buffers in the transient pool - // immediately after using them. - unsafe { - device.free_command_buffers(self.primary_command_pool, - &self.command_buffers) - }; - // While the descriptor pool is also a pool, it has a preallocated size // which will be different next time. So, we destroy it all the way. unsafe { device.destroy_descriptor_pool(self.descriptor_pool, None) }; @@ -374,9 +287,6 @@ impl WindowDressing { unsafe { device.free_memory(*memory, None) }; } - unsafe { device.destroy_pipeline(self.pipeline, None) }; - unsafe { device.destroy_pipeline_layout(self.pipeline_layout, None) }; - unsafe { device.destroy_render_pass(self.render_pass, None) }; unsafe { device.destroy_image(self.color_image, None) }; unsafe { device.free_memory(self.color_image_memory, None) }; unsafe { device.destroy_image_view(self.color_image_view, None) }; @@ -393,6 +303,167 @@ impl WindowDressing { } +impl RenderState { + pub fn new(permanent: &PermanentGraphicsState, + for_reinit: &GraphicsStateForReinit, + window_dressing: &WindowDressing) + -> Result<Self> + { + let device = &permanent.device; + let instance = &permanent.instance; + let graphics_queue = &permanent.graphics_queue; + let physical_device = &for_reinit.physical_device; + let sample_count = for_reinit.sample_count; + let descriptor_set_layout = &for_reinit.descriptor_set_layout; + let primary_command_pool = &window_dressing.primary_command_pool; + let transient_command_pool = &window_dressing.transient_command_pool; + let swapchain = &window_dressing.swapchain; + let depth_format = &window_dressing.depth_format; + let color_image_view = &window_dressing.color_image_view; + let depth_image_view = &window_dressing.depth_image_view; + let texture_image_view = &window_dressing.texture_image_view; + let uniform_buffers = &window_dressing.uniform_buffers; + let descriptor_pool = &window_dressing.descriptor_pool; + let sampler = &window_dressing.sampler; + + let render_pass = init_render_pass(device, sample_count, + &swapchain.format, &depth_format)?; + + let (pipeline_layout, pipeline) + = init_pipeline(device, descriptor_set_layout, &swapchain.extent, + sample_count, &render_pass)?; + + let framebuffers = init_framebuffers( + device, &swapchain.extent, &swapchain.image_views, + &color_image_view, &depth_image_view, &render_pass)?; + + let (vertices, indices) = load_model()?; + let index_count = indices.len(); + + let command_buffers = init_command_buffers(device, &framebuffers, + primary_command_pool)?; + + let (vertex_buffer, vertex_buffer_memory) + = init_vertex_buffer(vertices, instance, physical_device, device, + graphics_queue, &transient_command_pool)?; + let (index_buffer, index_buffer_memory) + = init_index_buffer(indices, instance, physical_device, device, + graphics_queue, &transient_command_pool)?; + + let descriptor_sets + = init_descriptor_sets(device, descriptor_set_layout, + &uniform_buffers, &descriptor_pool, + swapchain.images.len(), + &texture_image_view, &sampler)?; + + Ok(RenderState { + render_pass, + pipeline, + pipeline_layout, + vertex_buffer, + vertex_buffer_memory, + index_buffer, + index_buffer_memory, + index_count, + framebuffers, + command_buffers, + descriptor_sets, + }) + } + + // This relies on its caller to have already waited for the device to be + // idle. + pub fn reinit(&mut self, permanent: &PermanentGraphicsState, + for_reinit: &GraphicsStateForReinit, + window_dressing: &WindowDressing) + -> Result<()> + { + let device = &permanent.device; + let sample_count = for_reinit.sample_count; + let descriptor_set_layout = &for_reinit.descriptor_set_layout; + let primary_command_pool = &window_dressing.primary_command_pool; + let swapchain = &window_dressing.swapchain; + let depth_format = &window_dressing.depth_format; + let color_image_view = &window_dressing.color_image_view; + let depth_image_view = &window_dressing.depth_image_view; + let texture_image_view = &window_dressing.texture_image_view; + let uniform_buffers = &window_dressing.uniform_buffers; + let descriptor_pool = &window_dressing.descriptor_pool; + let sampler = &window_dressing.sampler; + + self.destroy_replaceable(device, primary_command_pool); + + let render_pass = init_render_pass(device, sample_count, + &swapchain.format, &depth_format)?; + + let (pipeline_layout, pipeline) + = init_pipeline(device, descriptor_set_layout, &swapchain.extent, + sample_count, &render_pass)?; + + let framebuffers = init_framebuffers( + device, &swapchain.extent, &swapchain.image_views, + &color_image_view, &depth_image_view, &render_pass)?; + + // Notice that we reused the command pool. + let command_buffers = init_command_buffers(device, &framebuffers, + primary_command_pool)?; + + let descriptor_sets + = init_descriptor_sets(device, descriptor_set_layout, + &uniform_buffers, &descriptor_pool, + swapchain.images.len(), + texture_image_view, sampler)?; + + self.render_pass = render_pass; + self.pipeline = pipeline; + self.pipeline_layout = pipeline_layout; + self.framebuffers = framebuffers; + self.command_buffers = command_buffers; + self.descriptor_sets = descriptor_sets; + + Ok(()) + } + + // This relies on its caller to have already waited for the device to be + // idle. + #[allow(unsafe_code)] + pub fn destroy(mut self, device: &Device, + window_dressing: &WindowDressing) + { + self.destroy_replaceable(device, &window_dressing.primary_command_pool); + + unsafe { device.destroy_buffer(self.vertex_buffer, None) }; + unsafe { device.free_memory(self.vertex_buffer_memory, None) }; + + unsafe { device.destroy_buffer(self.index_buffer, None) }; + unsafe { device.free_memory(self.index_buffer_memory, None) }; + } + + #[allow(unsafe_code)] + fn destroy_replaceable(&mut self, device: &Device, + primary_command_pool: &vk::CommandPool) + { + for framebuffer in &self.framebuffers { + unsafe { device.destroy_framebuffer(*framebuffer, None) }; + } + + // Notice that we free the buffers in the pool, but do not destroy the + // pool itself. Notice also that we only do this for the primary command + // pool, because that's the only one where we've kept track of the + // buffers. We promise ourselves to free buffers in the transient pool + // immediately after using them. + unsafe { + device.free_command_buffers(*primary_command_pool, + &self.command_buffers) + }; + + unsafe { device.destroy_pipeline(self.pipeline, None) }; + unsafe { device.destroy_pipeline_layout(self.pipeline_layout, None) }; + unsafe { device.destroy_render_pass(self.render_pass, None) }; + } +} + + #[allow(unsafe_code)] fn init_swapchain(window: &Window, instance: &Instance, surface: &vk::SurfaceKHR, @@ -1041,15 +1112,7 @@ fn init_command_pools(device: &Device, indices: &QueueFamilyIndices) #[allow(unsafe_code)] fn init_command_buffers(device: &Device, - extent: &vk::Extent2D, framebuffers: &Vec<vk::Framebuffer>, - render_pass: &vk::RenderPass, - pipeline_layout: &vk::PipelineLayout, - pipeline: &vk::Pipeline, - vertex_buffer: &vk::Buffer, - index_buffer: &vk::Buffer, - index_count: usize, - descriptor_sets: &Vec<vk::DescriptorSet>, command_pool: &vk::CommandPool) -> Result<Vec<vk::CommandBuffer>> { |