pub fn render_frame(&self) -> u32 {
        // get index of next image in swapchain
        // NOTE: this operation is asynchronous and we use a semaphore
        // that signals us when the index can actually be used
        let image_index = match unsafe {
            (*self.swapchain.get()).entry.acquire_next_image(
                (*self.swapchain.get()).swapchain,
                std::u64::MAX, // no timeout
                self.image_available_semaphore,
                vk::Fence::null(), // no fence
            )
        } {
            Err(e) => {
                if e == vk::Result::ERROR_OUT_OF_DATE_KHR {
                    unsafe {
                        self.recreate_swapchain()
                            .expect("failed to recreate swapchain in render_frame()");
                    }

                    return self.render_frame(); // try again
                } else {
                    panic!(
                        "error when acquiring image from swapchain in render_frame(): '{}'",
                        e
                    );
                }
            }
            Ok((index, suboptimal)) => {
                // if swapchain doesn't match surface exactly (due to resize)
                if suboptimal {
                    // TODO: we may wish to handle this as well
                }
                index
            }
        };

        // our commands need to wait for the next image to be available before drawing on it
        let wait_semaphore = [self.image_available_semaphore];
        // i.e if we reach the 'COLOR_ATTACHMENT_OUTPUT' stage in our pipeline early,
        // we need to wait on the signal from the semaphore. so this is our wait stage
        let wait_stage = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
        // we want to submit the command buffer that will start a render pass
        // on the framebuffer that holds the image we retrieved (as a color
        // attachment). the index of this command buffer is the same as the
        // index of the image it corresponds to
        let cmd_buf_to_submit =
            unsafe { [(*self.command_buffers.get()).buffers[image_index as usize]] };
        // we don't need any signal semaphores, as render_frame() waits
        // on all graphics queue operations to finish before returning,
        // meaning PixelRenderer::present() won't ever be called prematurely
        let signal_semaphores = [];

        let submit_info = [vk::SubmitInfo::builder()
            .wait_semaphores(&wait_semaphore)
            .wait_dst_stage_mask(&wait_stage)
            .command_buffers(&cmd_buf_to_submit)
            .signal_semaphores(&signal_semaphores)
            .build()];

        // flush potential writes to the pixel buffer mapped memory
        unsafe {
            self.pixel_image
                .flush_mapped_buffer(&self.device.logical)
                .expect("failed to flush mapped memory for pixel buffer in render_frame()");
        }

        // submit command buffer to queue
        unsafe {
            self.device
                .logical
                .queue_submit(
                    self.device.queues.graphics,
                    &submit_info,
                    // no fence
                    vk::Fence::null(),
                )
                .expect("failed to submit command buffer to queue in render_frame()");
        }

        // wait for submitted operations to finish
        unsafe {
            self.device
                .logical
                .queue_wait_idle(self.device.queues.graphics)
                .expect("failed to wait for queue operations to finish in render_frame()")
        };

        image_index

        // OPTIMIZE: instead of waiting for all operations to finish, we could set up a fence to
        // only wait for our buffer copy operation to finish, and then yield from render_frame()
        // when that is done. this way we could allow more work to be done on the cpu before the
        // next call to render_frame() and subsequent command buffer submission (where we would
        // probably have to wait for previous submits anyway, but the waiting would at least have
        // been delayed until all necessary cpu work has completed). doing this could help minimize
        // waiting and maximize cpu work per frame. note that this would also require some changes
        // to present()
    }
// renders a frame without presenting it. returns the index of the image rendered to
renders a frame without presenting it. returns the index of the image rendered to
renders a frame without presenting it . returns the index of the image rendered to
pub fn render_frame(&self) -> u32 {
        // get index of next image in swapchain
        // NOTE: this operation is asynchronous and we use a semaphore
        // that signals us when the index can actually be used
        let image_index = match unsafe {
            (*self.swapchain.get()).entry.acquire_next_image(
                (*self.swapchain.get()).swapchain,
                std::u64::MAX, // no timeout
                self.image_available_semaphore,
                vk::Fence::null(), // no fence
            )
        } {
            Err(e) => {
                if e == vk::Result::ERROR_OUT_OF_DATE_KHR {
                    unsafe {
                        self.recreate_swapchain()
                            .expect("failed to recreate swapchain in render_frame()");
                    }
                    return self.render_frame(); // try again
                } else {
                    panic!(
                        "error when acquiring image from swapchain in render_frame(): '{}'",
                        e
                    );
                }
            }
            Ok((index, suboptimal)) => {
                // if swapchain doesn't match surface exactly (due to resize)
                if suboptimal {
                    // TODO: we may wish to handle this as well
                }
                index
            }
        };
        // our commands need to wait for the next image to be available before drawing on it
        let wait_semaphore = [self.image_available_semaphore];
        // i.e if we reach the 'COLOR_ATTACHMENT_OUTPUT' stage in our pipeline early,
        // we need to wait on the signal from the semaphore. so this is our wait stage
        let wait_stage = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
        // we want to submit the command buffer that will start a render pass
        // on the framebuffer that holds the image we retrieved (as a color
        // attachment). the index of this command buffer is the same as the
        // index of the image it corresponds to
        let cmd_buf_to_submit =
            unsafe { [(*self.command_buffers.get()).buffers[image_index as usize]] };
        // we don't need any signal semaphores, as render_frame() waits
        // on all graphics queue operations to finish before returning,
        // meaning PixelRenderer::present() won't ever be called prematurely
        let signal_semaphores = [];
        let submit_info = [vk::SubmitInfo::builder()
            .wait_semaphores(&wait_semaphore)
            .wait_dst_stage_mask(&wait_stage)
            .command_buffers(&cmd_buf_to_submit)
            .signal_semaphores(&signal_semaphores)
            .build()];
        // flush potential writes to the pixel buffer mapped memory
        unsafe {
            self.pixel_image
                .flush_mapped_buffer(&self.device.logical)
                .expect("failed to flush mapped memory for pixel buffer in render_frame()");
        }
        // submit command buffer to queue
        unsafe {
            self.device
                .logical
                .queue_submit(
                    self.device.queues.graphics,
                    &submit_info,
                    // no fence
                    vk::Fence::null(),
                )
                .expect("failed to submit command buffer to queue in render_frame()");
        }
        // wait for submitted operations to finish
        unsafe {
            self.device
                .logical
                .queue_wait_idle(self.device.queues.graphics)
                .expect("failed to wait for queue operations to finish in render_frame()")
        };
        image_index
        // OPTIMIZE: instead of waiting for all operations to finish, we could set up a fence to
        // only wait for our buffer copy operation to finish, and then yield from render_frame()
        // when that is done. this way we could allow more work to be done on the cpu before the
        // next call to render_frame() and subsequent command buffer submission (where we would
        // probably have to wait for previous submits anyway, but the waiting would at least have
        // been delayed until all necessary cpu work has completed). doing this could help minimize
        // waiting and maximize cpu work per frame. note that this would also require some changes
        // to present()
    }
pub fn render_frame ( & self ) -> u32 { // get index of next image in swapchain // NOTE: this operation is asynchronous and we use a semaphore // that signals us when the index can actually be used let image_index = match unsafe { ( * self . swapchain . get ( ) ) . entry . acquire_next_image ( ( * self . swapchain . get ( ) ) . swapchain , std :: u64 :: MAX , // no timeout self . image_available_semaphore , vk :: Fence :: null ( ) , // no fence ) } { Err ( e ) => { if e == vk :: Result :: ERROR_OUT_OF_DATE_KHR { unsafe { self . recreate_swapchain ( ) . expect ( " " ) ; } return self . render_frame ( ) ; // try again } else { panic ! ( " " e ) ; } } Ok ( ( index , suboptimal ) ) => { // if swapchain doesn't match surface exactly (due to resize) if suboptimal { // TODO: we may wish to handle this as well } index } } ; // our commands need to wait for the next image to be available before drawing on it let wait_semaphore = [ self . image_available_semaphore ] ; // i.e if we reach the 'COLOR_ATTACHMENT_OUTPUT' stage in our pipeline early, // we need to wait on the signal from the semaphore. so this is our wait stage let wait_stage = [ vk :: PipelineStageFlags :: COLOR_ATTACHMENT_OUTPUT ] ; // we want to submit the command buffer that will start a render pass // on the framebuffer that holds the image we retrieved (as a color // attachment). the index of this command buffer is the same as the // index of the image it corresponds to let cmd_buf_to_submit = unsafe { [ ( * self . command_buffers . get ( ) ) . buffers [ image_index as usize ] ] } ; // we don't need any signal semaphores, as render_frame() waits // on all graphics queue operations to finish before returning, // meaning PixelRenderer::present() won't ever be called prematurely let signal_semaphores = [ ] ; let submit_info = [ vk :: SubmitInfo :: builder ( ) . wait_semaphores ( & wait_semaphore ) . wait_dst_stage_mask ( & wait_stage ) . command_buffers ( & cmd_buf_to_submit ) . signal_semaphores ( & signal_semaphores ) . build ( ) ] ; // flush potential writes to the pixel buffer mapped memory unsafe { self . pixel_image . flush_mapped_buffer ( & self . device . logical ) . expect ( " " ) ; } // submit command buffer to queue unsafe { self . device . logical . queue_submit ( self . device . queues . graphics , & submit_info , // no fence vk :: Fence :: null ( ) , ) . expect ( " " ) ; } // wait for submitted operations to finish unsafe { self . device . logical . queue_wait_idle ( self . device . queues . graphics ) . expect ( " " ) } ; image_index // OPTIMIZE: instead of waiting for all operations to finish, we could set up a fence to // only wait for our buffer copy operation to finish, and then yield from render_frame() // when that is done. this way we could allow more work to be done on the cpu before the // next call to render_frame() and subsequent command buffer submission (where we would // probably have to wait for previous submits anyway, but the waiting would at least have // been delayed until all necessary cpu work has completed). doing this could help minimize // waiting and maximize cpu work per frame. note that this would also require some changes // to present() }
renders a frame without presenting it.
renders a frame without presenting it .
&self
&self