diff options
Diffstat (limited to 'src/graphics_window_dressing.rs')
| -rw-r--r-- | src/graphics_window_dressing.rs | 148 |
1 files changed, 117 insertions, 31 deletions
diff --git a/src/graphics_window_dressing.rs b/src/graphics_window_dressing.rs index eb08d53..f949af0 100644 --- a/src/graphics_window_dressing.rs +++ b/src/graphics_window_dressing.rs @@ -34,10 +34,12 @@ pub struct WindowDressing { framebuffers: Vec<vk::Framebuffer>, + primary_command_pool: vk::CommandPool, + transient_command_pool: vk::CommandPool, + vertex_buffer: vk::Buffer, vertex_buffer_memory: vk::DeviceMemory, - command_pool: vk::CommandPool, pub command_buffers: Vec<vk::CommandBuffer>, pub concurrency: Concurrency, @@ -87,6 +89,7 @@ impl WindowDressing { let instance = &permanent.instance; let surface = &permanent.surface; let device = &permanent.device; + let graphics_queue = &permanent.graphics_queue; let physical_device = &for_reinit.physical_device; let indices = &for_reinit.indices; @@ -101,14 +104,17 @@ impl WindowDressing { let framebuffers = init_framebuffers( device, &swapchain.extent, &swapchain.image_views, &render_pass)?; + let (primary_command_pool, transient_command_pool) + = init_command_pools(device, indices)?; + let (vertex_buffer, vertex_buffer_memory) - = init_vertex_buffer(instance, physical_device, device)?; + = init_vertex_buffer(instance, physical_device, device, + graphics_queue, &transient_command_pool)?; - let command_pool = init_command_pool(device, indices)?; let command_buffers = init_commands(device, &swapchain.extent, &framebuffers, &render_pass, &pipeline, &vertex_buffer, - &command_pool)?; + &primary_command_pool)?; let concurrency = init_concurrency(device, &swapchain.images)?; @@ -120,7 +126,8 @@ impl WindowDressing { framebuffers, vertex_buffer, vertex_buffer_memory, - command_pool, + primary_command_pool, + transient_command_pool, command_buffers, concurrency, }) @@ -157,7 +164,7 @@ impl WindowDressing { // Notice that we reused the command pool. let command_buffers = init_commands( device, &swapchain.extent, &framebuffers, &render_pass, - &pipeline, &self.vertex_buffer, &self.command_pool)?; + &pipeline, &self.vertex_buffer, &self.primary_command_pool)?; self.concurrency.image_fences.resize(swapchain.images.len(), vk::Fence::null()); @@ -194,8 +201,10 @@ impl WindowDressing { unsafe { device.destroy_fence(fence, None) }; } - // Notice that destroy_replaceable freed the pool, but did not destroy it. - unsafe { device.destroy_command_pool(self.command_pool, None) }; + // Notice that destroy_replaceable() freed the buffers in the pools, but + // did not destroy the pools. + unsafe { device.destroy_command_pool(self.primary_command_pool, None) }; + unsafe { device.destroy_command_pool(self.transient_command_pool, None) }; } @@ -205,9 +214,14 @@ impl WindowDressing { unsafe { device.destroy_framebuffer(*framebuffer, None) }; } - // Notice that we free the pool, but do not destroy it. + // 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.command_pool, &self.command_buffers) + device.free_command_buffers(self.primary_command_pool, + &self.command_buffers) }; unsafe { device.destroy_pipeline(self.pipeline, None) }; @@ -528,28 +542,44 @@ fn init_framebuffers(device: &Device, extent: &vk::Extent2D, #[allow(unsafe_code)] fn init_vertex_buffer(instance: &Instance, - physical_device: &vk::PhysicalDevice, device: &Device) + physical_device: &vk::PhysicalDevice, device: &Device, + queue: &vk::Queue, command_pool: &vk::CommandPool) -> Result<(vk::Buffer, vk::DeviceMemory)> { let size = (size_of::<Vertex<f32>>() * VERTICES.len()) as u64; - let usage = vk::BufferUsageFlags::VERTEX_BUFFER; - let memory_flags = vk::MemoryPropertyFlags::HOST_COHERENT - | vk::MemoryPropertyFlags::HOST_VISIBLE; - let (buffer, device_memory) = init_buffer(instance, physical_device, device, - size, usage, memory_flags)?; + + let staging_usage = vk::BufferUsageFlags::TRANSFER_SRC; + let staging_memory_flags = vk::MemoryPropertyFlags::HOST_COHERENT + | vk::MemoryPropertyFlags::HOST_VISIBLE; + let (staging_buffer, staging_memory) + = init_buffer(instance, physical_device, device, + size, staging_usage, staging_memory_flags)?; let host_memory = unsafe { - device.map_memory(device_memory, 0, size, vk::MemoryMapFlags::empty()) + device.map_memory(staging_memory, 0, size, vk::MemoryMapFlags::empty()) }?; unsafe { - ptr::copy_nonoverlapping(VERTICES.as_ptr(), host_memory.cast(), - VERTICES.len()) + ptr::copy_nonoverlapping( + VERTICES.as_ptr(), host_memory.cast(), VERTICES.len()) }; - unsafe { device.unmap_memory(device_memory) }; + unsafe { device.unmap_memory(staging_memory) }; - Ok((buffer, device_memory)) + let final_usage = vk::BufferUsageFlags::TRANSFER_DST + | vk::BufferUsageFlags::VERTEX_BUFFER; + let final_memory_flags = vk::MemoryPropertyFlags::DEVICE_LOCAL; + let (final_buffer, device_memory) + = init_buffer(instance, physical_device, device, + size, final_usage, final_memory_flags)?; + + copy_buffer(device, queue, command_pool, + &staging_buffer, &final_buffer, size)?; + + unsafe { device.destroy_buffer(staging_buffer, None) }; + unsafe { device.free_memory(staging_memory, None) }; + + Ok((final_buffer, device_memory)) } @@ -590,16 +620,23 @@ fn init_buffer(instance: &Instance, #[allow(unsafe_code)] -fn init_command_pool(device: &Device, indices: &QueueFamilyIndices) - -> Result<vk::CommandPool> +fn init_command_pools(device: &Device, indices: &QueueFamilyIndices) + -> Result<(vk::CommandPool, vk::CommandPool)> { let command_pool_info = vk::CommandPoolCreateInfo::builder() .flags(vk::CommandPoolCreateFlags::empty()) .queue_family_index(indices.graphics); - Ok(unsafe { + let primary = unsafe { device.create_command_pool(&command_pool_info, None) - }?) + }?; + + command_pool_info.flags(vk::CommandPoolCreateFlags::TRANSIENT); + let transient = unsafe { + device.create_command_pool(&command_pool_info, None) + }?; + + Ok((primary, transient)) } @@ -627,14 +664,12 @@ fn init_commands(device: &Device, let inheritance_info = vk::CommandBufferInheritanceInfo::builder(); - let command_buffer_begin_info - = vk::CommandBufferBeginInfo::builder() - .flags(vk::CommandBufferUsageFlags::empty()) - .inheritance_info(&inheritance_info); + let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder() + .flags(vk::CommandBufferUsageFlags::empty()) + .inheritance_info(&inheritance_info); unsafe { - device.begin_command_buffer(command_buffer, - &command_buffer_begin_info) + device.begin_command_buffer(command_buffer, &command_buffer_begin_info) }?; let render_area = vk::Rect2D::builder() @@ -801,3 +836,54 @@ fn pick_memory_type(instance: &Instance, }) } + +#[allow(unsafe_code)] +fn copy_buffer(device: &Device, queue: &vk::Queue, + command_pool: &vk::CommandPool, + source: &vk::Buffer, destination: &vk::Buffer, + size: vk::DeviceSize) + -> Result<()> +{ + let command_buffer_allocation_info + = vk::CommandBufferAllocateInfo::builder() + .command_pool(*command_pool) + .level(vk::CommandBufferLevel::PRIMARY) + .command_buffer_count(1); + let command_buffer = unsafe { + device.allocate_command_buffers(&command_buffer_allocation_info) + }?[0]; + + let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder() + .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT); + + unsafe { + device.begin_command_buffer(command_buffer, &command_buffer_begin_info) + }?; + + let copy_info = vk::BufferCopy::builder().size(size); + unsafe { + device.cmd_copy_buffer(command_buffer, *source, *destination, + &[copy_info]) + }; + + unsafe { device.end_command_buffer(command_buffer) }?; + + let command_buffers = [command_buffer]; + + let submit_info = vk::SubmitInfo::builder() + .command_buffers(&command_buffers); + unsafe { + device.queue_submit(*queue, &[submit_info], vk::Fence::null()) + }?; + + unsafe { + device.queue_wait_idle(*queue) + }?; + + unsafe { + device.free_command_buffers(*command_pool, &command_buffers) + }; + + Ok(()) +} + |