pub fn run(&mut self) -> Result<(), Error>
    {
        use dacite::core::Error::OutOfDateKhr;

        self.window.show();
        for i in 0..self.swapchain_data.images.len() {
            self.record_command_buffer(i)?;
        }
        self.memory.log_usage();

        let mut framenumber: u64 = 0;

        let loop_throttle = if self.config.fps_cap > 0 {
            Duration::new(0, 1_000_000_000 / self.config.fps_cap)
        } else {
            Duration::new(0, 0)
        };

        let mut timings_60 = Timings::new();
        let mut timings_600 = Timings::new();

        let mut last_loop_start: Instant;
        let mut loop_start: Instant = Instant::now();
        loop {
            last_loop_start = loop_start;
            loop_start = Instant::now();
            let looptime_1 = loop_start.duration_since(last_loop_start);

            // On windows (at least, perhaps also elsewhere), vulkan won't give us an
            // OutOfDateKhr error on a window resize.  But the window will remain black
            // after resizing.  We have to detect resizes and rebuild the swapchain.
            if self.resized.load(Ordering::Relaxed) {
                self.rebuild()?;
                self.resized.store(false, Ordering::Relaxed);
                continue;
            }

            // Be sure any outstanding memory transfers are completed.
            self.memory.flush()?;

            // Issue the commands to render a frame (this does not wait)
            let present_image = match self.start_render() {
                Err(e) => {
                    if let Error::Dacite(OutOfDateKhr) = e {
                        // Rebuild the swapchain if Vulkan complains that it is out of date.
                        // This is typical on linux.
                        self.rebuild()?;

                        // Rebuild waited for device idle, so no other waits necessary.
                        // Just go back up and try again
                        continue;
                    } else {
                        return Err(e);
                    }
                },
                Ok(i) => i
            };

            // Update plugins. If any of them needs a re-record, we mark all of the
            // command buffers as stale.
            let mut need_rerecord = false;
            for plugin in &mut self.plugins {
                let params = self.params_ubo.as_ptr::<Params>().unwrap();
                if plugin.update(params, &self.stats)? {
                    need_rerecord = true;
                }
            }
            if need_rerecord {
                // mark them all stale
                for elem in self.commander.gfx_command_buffer_stale.iter_mut() {
                    *elem=true;
                }
            }

            // Re-record all stale non-in-flight command buffers
            for i in 0..self.swapchain_data.images.len() {
                if i == present_image {
                    // We cannot re-record the in-flight command buffer
                    // It will stay marked 'stale' and get re-recorded next
                    // loop iteration.
                    continue;
                }
                if self.commander.gfx_command_buffer_stale[i] {
                    self.record_command_buffer(i)?;
                    self.commander.gfx_command_buffer_stale[i] = false;
                }
            }

            // PLACEHOLDER FOR OPTIONAL JOBS
            // Here we can query the fence status, and if not signalled, we can go do
            // some job that is waiting, ala:
            /*
            loop {
              fence_status = vkGetFenceStatus(device, fences[nextImageIndex]);
              if fence_status==VK_SUCCESS {
                break;
              }
              if smallJobQueue.empty() {
                break;
              }
              //execute next small job
            }
            */

            // Wait until the current frame is rendered, so that objects tied
            // into that render remain alive during the render, and also to
            // wait for the Query pool results. This does not wait for
            // presentation (however rendering had to wait for acquisition and
            // this might not have been ready until vsync, depending on
            // presentation mode).
            let x = Instant::now();
            self.rendered_fence.wait_for(Timeout::Infinite)?;
            let cpu_exclude_time = x.elapsed();

            // Run plugin gpu_update() functions now that the GPU has finished
            // rendering
            for plugin in &mut self.plugins {
                plugin.gpu_update()?;
            }

            framenumber += 1;

            // Shutdown when it is time to do so
            if self.shutdown.load(Ordering::Relaxed) {
                info!("Graphics is shutting down...");
                self.device.wait_idle()?;
                self.window.hide();
                return Ok(());
            }

            // Query render timings
            let timings_1 = {
                let mut results: [QueryResult; TS_QUERY_COUNT as usize]
                    = [QueryResult::U32(0); TS_QUERY_COUNT as usize];
                self.timestamp_query_pool.get_results(
                    0, // first query
                    TS_QUERY_COUNT, // query count
                    1, // stride (dacite takes this and multiplies by size of u32 or u64
                    QueryResultFlags::WAIT,
                    &mut results
                )?;

                // This skips the render wait, and the throttle (below), but also
                // the update statistics (although that is short).
                let cputime = loop_start.elapsed().checked_sub(cpu_exclude_time)
                    .unwrap_or(Duration::new(0,0));
                let cputime_ms = cputime.as_secs() as f32 * 1000.0
                    + cputime.subsec_nanos() as f32 * 0.000_001;

                Timings::one(
                    &looptime_1,
                    &results,
                    cputime_ms,
                    self.ph_props.limits.timestamp_period)
            };

            // Throttle FPS
            let elapsed = loop_start.elapsed();
            if elapsed < loop_throttle {
                ::std::thread::sleep(loop_throttle - elapsed);
            }

            // Update statistics
            timings_60.accumulate(&timings_1);
            timings_600.accumulate(&timings_1);

            if framenumber % 600 == 0 {
                let pass = ::std::mem::replace(&mut timings_600, Timings::new());
                self.stats.update_600(pass);
            }
            if framenumber % 60 == 0 {
                let pass = ::std::mem::replace(&mut timings_60, Timings::new());
                self.stats.update_60(pass);
            }
        }
    }
// This will hog the current thread and wont return until the renderer shuts down.
This will hog the current thread and wont return until the renderer shuts down.
This will hog the current thread and wont return until the renderer shuts down .
pub fn run(&mut self) -> Result<(), Error>
    {
        use dacite::core::Error::OutOfDateKhr;
        self.window.show();
        for i in 0..self.swapchain_data.images.len() {
            self.record_command_buffer(i)?;
        }
        self.memory.log_usage();
        let mut framenumber: u64 = 0;
        let loop_throttle = if self.config.fps_cap > 0 {
            Duration::new(0, 1_000_000_000 / self.config.fps_cap)
        } else {
            Duration::new(0, 0)
        };
        let mut timings_60 = Timings::new();
        let mut timings_600 = Timings::new();
        let mut last_loop_start: Instant;
        let mut loop_start: Instant = Instant::now();
        loop {
            last_loop_start = loop_start;
            loop_start = Instant::now();
            let looptime_1 = loop_start.duration_since(last_loop_start);
            // On windows (at least, perhaps also elsewhere), vulkan won't give us an
            // OutOfDateKhr error on a window resize.  But the window will remain black
            // after resizing.  We have to detect resizes and rebuild the swapchain.
            if self.resized.load(Ordering::Relaxed) {
                self.rebuild()?;
                self.resized.store(false, Ordering::Relaxed);
                continue;
            }
            // Be sure any outstanding memory transfers are completed.
            self.memory.flush()?;
            // Issue the commands to render a frame (this does not wait)
            let present_image = match self.start_render() {
                Err(e) => {
                    if let Error::Dacite(OutOfDateKhr) = e {
                        // Rebuild the swapchain if Vulkan complains that it is out of date.
                        // This is typical on linux.
                        self.rebuild()?;
                        // Rebuild waited for device idle, so no other waits necessary.
                        // Just go back up and try again
                        continue;
                    } else {
                        return Err(e);
                    }
                },
                Ok(i) => i
            };
            // Update plugins. If any of them needs a re-record, we mark all of the
            // command buffers as stale.
            let mut need_rerecord = false;
            for plugin in &mut self.plugins {
                let params = self.params_ubo.as_ptr::<Params>().unwrap();
                if plugin.update(params, &self.stats)? {
                    need_rerecord = true;
                }
            }
            if need_rerecord {
                // mark them all stale
                for elem in self.commander.gfx_command_buffer_stale.iter_mut() {
                    *elem=true;
                }
            }
            // Re-record all stale non-in-flight command buffers
            for i in 0..self.swapchain_data.images.len() {
                if i == present_image {
                    // We cannot re-record the in-flight command buffer
                    // It will stay marked 'stale' and get re-recorded next
                    // loop iteration.
                    continue;
                }
                if self.commander.gfx_command_buffer_stale[i] {
                    self.record_command_buffer(i)?;
                    self.commander.gfx_command_buffer_stale[i] = false;
                }
            }
            // PLACEHOLDER FOR OPTIONAL JOBS
            // Here we can query the fence status, and if not signalled, we can go do
            // some job that is waiting, ala:
            /*
            loop {
              fence_status = vkGetFenceStatus(device, fences[nextImageIndex]);
              if fence_status==VK_SUCCESS {
                break;
              }
              if smallJobQueue.empty() {
                break;
              }
              //execute next small job
            }
            */
            // Wait until the current frame is rendered, so that objects tied
            // into that render remain alive during the render, and also to
            // wait for the Query pool results. This does not wait for
            // presentation (however rendering had to wait for acquisition and
            // this might not have been ready until vsync, depending on
            // presentation mode).
            let x = Instant::now();
            self.rendered_fence.wait_for(Timeout::Infinite)?;
            let cpu_exclude_time = x.elapsed();
            // Run plugin gpu_update() functions now that the GPU has finished
            // rendering
            for plugin in &mut self.plugins {
                plugin.gpu_update()?;
            }
            framenumber += 1;
            // Shutdown when it is time to do so
            if self.shutdown.load(Ordering::Relaxed) {
                info!("Graphics is shutting down...");
                self.device.wait_idle()?;
                self.window.hide();
                return Ok(());
            }
            // Query render timings
            let timings_1 = {
                let mut results: [QueryResult; TS_QUERY_COUNT as usize]
                    = [QueryResult::U32(0); TS_QUERY_COUNT as usize];
                self.timestamp_query_pool.get_results(
                    0, // first query
                    TS_QUERY_COUNT, // query count
                    1, // stride (dacite takes this and multiplies by size of u32 or u64
                    QueryResultFlags::WAIT,
                    &mut results
                )?;
                // This skips the render wait, and the throttle (below), but also
                // the update statistics (although that is short).
                let cputime = loop_start.elapsed().checked_sub(cpu_exclude_time)
                    .unwrap_or(Duration::new(0,0));
                let cputime_ms = cputime.as_secs() as f32 * 1000.0
                    + cputime.subsec_nanos() as f32 * 0.000_001;
                Timings::one(
                    &looptime_1,
                    &results,
                    cputime_ms,
                    self.ph_props.limits.timestamp_period)
            };
            // Throttle FPS
            let elapsed = loop_start.elapsed();
            if elapsed < loop_throttle {
                ::std::thread::sleep(loop_throttle - elapsed);
            }
            // Update statistics
            timings_60.accumulate(&timings_1);
            timings_600.accumulate(&timings_1);
            if framenumber % 600 == 0 {
                let pass = ::std::mem::replace(&mut timings_600, Timings::new());
                self.stats.update_600(pass);
            }
            if framenumber % 60 == 0 {
                let pass = ::std::mem::replace(&mut timings_60, Timings::new());
                self.stats.update_60(pass);
            }
        }
    }
pub fn run ( & mut self ) -> Result < ( ) , Error > { use dacite :: core :: Error :: OutOfDateKhr ; self . window . show ( ) ; for i in 0 .. self . swapchain_data . images . len ( ) { self . record_command_buffer ( i ) ? ; } self . memory . log_usage ( ) ; let mut framenumber : u64 = 0 ; let loop_throttle = if self . config . fps_cap > 0 { Duration :: new ( 0 , 1_000_000_000 / self . config . fps_cap ) } else { Duration :: new ( 0 , 0 ) } ; let mut timings_60 = Timings :: new ( ) ; let mut timings_600 = Timings :: new ( ) ; let mut last_loop_start : Instant ; let mut loop_start : Instant = Instant :: now ( ) ; loop { last_loop_start = loop_start ; loop_start = Instant :: now ( ) ; let looptime_1 = loop_start . duration_since ( last_loop_start ) ; // On windows (at least, perhaps also elsewhere), vulkan won't give us an // OutOfDateKhr error on a window resize.  But the window will remain black // after resizing.  We have to detect resizes and rebuild the swapchain. if self . resized . load ( Ordering :: Relaxed ) { self . rebuild ( ) ? ; self . resized . store ( false , Ordering :: Relaxed ) ; continue ; } // Be sure any outstanding memory transfers are completed. self . memory . flush ( ) ? ; // Issue the commands to render a frame (this does not wait) let present_image = match self . start_render ( ) { Err ( e ) => { if let Error :: Dacite ( OutOfDateKhr ) = e { // Rebuild the swapchain if Vulkan complains that it is out of date. // This is typical on linux. self . rebuild ( ) ? ; // Rebuild waited for device idle, so no other waits necessary. // Just go back up and try again continue ; } else { return Err ( e ) ; } } , Ok ( i ) => i } ; // Update plugins. If any of them needs a re-record, we mark all of the // command buffers as stale. let mut need_rerecord = false ; for plugin in & mut self . plugins { let params = self . params_ubo . as_ptr :: < Params > ( ) . unwrap ( ) ; if plugin . update ( params , & self . stats ) ? { need_rerecord = true ; } } if need_rerecord { // mark them all stale for elem in self . commander . gfx_command_buffer_stale . iter_mut ( ) { * elem = true ; } } // Re-record all stale non-in-flight command buffers for i in 0 .. self . swapchain_data . images . len ( ) { if i == present_image { // We cannot re-record the in-flight command buffer // It will stay marked 'stale' and get re-recorded next // loop iteration. continue ; } if self . commander . gfx_command_buffer_stale [ i ] { self . record_command_buffer ( i ) ? ; self . commander . gfx_command_buffer_stale [ i ] = false ; } } // PLACEHOLDER FOR OPTIONAL JOBS // Here we can query the fence status, and if not signalled, we can go do // some job that is waiting, ala: /*
            loop {
              fence_status = vkGetFenceStatus(device, fences[nextImageIndex]);
              if fence_status==VK_SUCCESS {
                break;
              }
              if smallJobQueue.empty() {
                break;
              }
              //execute next small job
            }
            */ // Wait until the current frame is rendered, so that objects tied // into that render remain alive during the render, and also to // wait for the Query pool results. This does not wait for // presentation (however rendering had to wait for acquisition and // this might not have been ready until vsync, depending on // presentation mode). let x = Instant :: now ( ) ; self . rendered_fence . wait_for ( Timeout :: Infinite ) ? ; let cpu_exclude_time = x . elapsed ( ) ; // Run plugin gpu_update() functions now that the GPU has finished // rendering for plugin in & mut self . plugins { plugin . gpu_update ( ) ? ; } framenumber += 1 ; // Shutdown when it is time to do so if self . shutdown . load ( Ordering :: Relaxed ) { info ! ( " " ) ; self . device . wait_idle ( ) ? ; self . window . hide ( ) ; return Ok ( ( ) ) ; } // Query render timings let timings_1 = { let mut results : [ QueryResult ; TS_QUERY_COUNT as usize ] = [ QueryResult :: U32 ( 0 ) ; TS_QUERY_COUNT as usize ] ; self . timestamp_query_pool . get_results ( 0 , // first query TS_QUERY_COUNT , // query count 1 , // stride (dacite takes this and multiplies by size of u32 or u64 QueryResultFlags :: WAIT , & mut results ) ? ; // This skips the render wait, and the throttle (below), but also // the update statistics (although that is short). let cputime = loop_start . elapsed ( ) . checked_sub ( cpu_exclude_time ) . unwrap_or ( Duration :: new ( 0 , 0 ) ) ; let cputime_ms = cputime . as_secs ( ) as f32 * 1000.0 + cputime . subsec_nanos ( ) as f32 * 0.000_001 ; Timings :: one ( & looptime_1 , & results , cputime_ms , self . ph_props . limits . timestamp_period ) } ; // Throttle FPS let elapsed = loop_start . elapsed ( ) ; if elapsed < loop_throttle { :: std :: thread :: sleep ( loop_throttle - elapsed ) ; } // Update statistics timings_60 . accumulate ( & timings_1 ) ; timings_600 . accumulate ( & timings_1 ) ; if framenumber % 600 == 0 { let pass = :: std :: mem :: replace ( & mut timings_600 , Timings :: new ( ) ) ; self . stats . update_600 ( pass ) ; } if framenumber % 60 == 0 { let pass = :: std :: mem :: replace ( & mut timings_60 , Timings :: new ( ) ) ; self . stats . update_60 ( pass ) ; } } }
This will hog the current thread and wont return until the renderer shuts down.
This will hog the current thread and wont return until the renderer shuts down .
&mut self
&mut self