pub fn draw_cubes_frame(&mut self, models: &[glm::TMat4<f32>]) -> Result<(), &'static str> {
    // SETUP FOR THIS FRAME
    let flight_fence = &self.in_flight_fences[self.current_frame];
    let image_available = &self.image_available_semaphores[self.current_frame];
    let render_finished = &self.render_finished_semaphores[self.current_frame];
    // Advance the frame _before_ we start using the `?` operator
    self.current_frame = (self.current_frame + 1) % self.frames_in_flight;

    let (i_u32, i_usize) = unsafe {
      self
        .device
        .wait_for_fence(flight_fence, core::u64::MAX)
        .map_err(|_| "Failed to wait on the fence!")?;
      self
        .device
        .reset_fence(flight_fence)
        .map_err(|_| "Couldn't reset the fence!")?;
      let image_index = self
        .swapchain
        .acquire_image(core::u64::MAX, FrameSync::Semaphore(image_available))
        .map_err(|_| "Couldn't acquire an image from the swapchain!")?;
      (image_index, image_index as usize)
    };

    // DETERMINE VIEW MATRIX (just once)
    let view = glm::look_at_lh(
      &glm::make_vec3(&[0.0, 0.0, -5.0]),
      &glm::make_vec3(&[0.0, 0.0, 0.0]),
      &glm::make_vec3(&[0.0, 1.0, 0.0]).normalize(),
    );

    // DETERMINE PROJECTION MATRIX (just once)
    let projection = {
      let mut temp = glm::perspective_lh_zo(800.0 / 600.0, f32::to_radians(50.0), 0.1, 100.0);
      temp[(1, 1)] *= -1.0;
      temp
    };

    // COMBINE THE VIEW AND PROJECTION MATRIX AHEAD OF TIME (just once)
    let vp = projection * view;

    // RECORD COMMANDS
    unsafe {
      let buffer = &mut self.command_buffers[i_usize];
      const QUAD_CLEAR: [ClearValue; 1] =
        [ClearValue::Color(ClearColor::Float([0.1, 0.2, 0.3, 1.0]))];
      buffer.begin(false);
      {
        let mut encoder = buffer.begin_render_pass_inline(
          &self.render_pass,
          &self.framebuffers[i_usize],
          self.render_area,
          QUAD_CLEAR.iter(),
        );
        encoder.bind_graphics_pipeline(&self.graphics_pipeline);
        encoder.bind_vertex_buffers(0, Some((self.cube_vertices.buffer.deref(), 0)));
        encoder.bind_index_buffer(IndexBufferView {
          buffer: &self.cube_indexes.buffer,
          offset: 0,
          index_type: IndexType::U16,
        });
        encoder.bind_graphics_descriptor_sets(
          &self.pipeline_layout,
          0,
          Some(self.descriptor_set.deref()),
          &[],
        );
        // ONE DRAW CALL PER MODEL MATRIX WE'RE GIVEN
        for model in models.iter() {
          // DETERMINE FINAL MVP MATRIX (once per model)
          let mvp = vp * model;
          for d in mvp.data.iter() {
            if d.is_nan() {
              dbg!(model);
              dbg!(view);
              dbg!(projection);
              dbg!(mvp);
              assert!(false);
            }
          }
          encoder.push_graphics_constants(
            &self.pipeline_layout,
            ShaderStageFlags::VERTEX,
            0,
            cast_slice::<f32, u32>(&mvp.data)
              .expect("this cast never fails for same-aligned same-size data"),
          );
          encoder.draw_indexed(0..36, 0, 0..1);
        }
      }
      buffer.finish();
    }

    // SUBMISSION AND PRESENT
    let command_buffers = &self.command_buffers[i_usize..=i_usize];
    let wait_semaphores: ArrayVec<[_; 1]> =
      [(image_available, PipelineStage::COLOR_ATTACHMENT_OUTPUT)].into();
    let signal_semaphores: ArrayVec<[_; 1]> = [render_finished].into();
    // yes, you have to write it twice like this. yes, it's silly.
    let present_wait_semaphores: ArrayVec<[_; 1]> = [render_finished].into();
    let submission = Submission {
      command_buffers,
      wait_semaphores,
      signal_semaphores,
    };
    let the_command_queue = &mut self.queue_group.queues[0];
    unsafe {
      the_command_queue.submit(submission, Some(flight_fence));
      self
        .swapchain
        .present(the_command_queue, i_u32, present_wait_semaphores)
        .map_err(|_| "Failed to present into the swapchain!")
    }
  }
/// Draws one cube per model matrix given.
Draws one cube per model matrix given.
Draws one cube per model matrix given .
pub fn draw_cubes_frame(&mut self, models: &[glm::TMat4<f32>]) -> Result<(), &'static str> {
    // SETUP FOR THIS FRAME
    let flight_fence = &self.in_flight_fences[self.current_frame];
    let image_available = &self.image_available_semaphores[self.current_frame];
    let render_finished = &self.render_finished_semaphores[self.current_frame];
    // Advance the frame _before_ we start using the `?` operator
    self.current_frame = (self.current_frame + 1) % self.frames_in_flight;
    let (i_u32, i_usize) = unsafe {
      self
        .device
        .wait_for_fence(flight_fence, core::u64::MAX)
        .map_err(|_| "Failed to wait on the fence!")?;
      self
        .device
        .reset_fence(flight_fence)
        .map_err(|_| "Couldn't reset the fence!")?;
      let image_index = self
        .swapchain
        .acquire_image(core::u64::MAX, FrameSync::Semaphore(image_available))
        .map_err(|_| "Couldn't acquire an image from the swapchain!")?;
      (image_index, image_index as usize)
    };
    // DETERMINE VIEW MATRIX (just once)
    let view = glm::look_at_lh(
      &glm::make_vec3(&[0.0, 0.0, -5.0]),
      &glm::make_vec3(&[0.0, 0.0, 0.0]),
      &glm::make_vec3(&[0.0, 1.0, 0.0]).normalize(),
    );
    // DETERMINE PROJECTION MATRIX (just once)
    let projection = {
      let mut temp = glm::perspective_lh_zo(800.0 / 600.0, f32::to_radians(50.0), 0.1, 100.0);
      temp[(1, 1)] *= -1.0;
      temp
    };
    // COMBINE THE VIEW AND PROJECTION MATRIX AHEAD OF TIME (just once)
    let vp = projection * view;
    // RECORD COMMANDS
    unsafe {
      let buffer = &mut self.command_buffers[i_usize];
      const QUAD_CLEAR: [ClearValue; 1] =
        [ClearValue::Color(ClearColor::Float([0.1, 0.2, 0.3, 1.0]))];
      buffer.begin(false);
      {
        let mut encoder = buffer.begin_render_pass_inline(
          &self.render_pass,
          &self.framebuffers[i_usize],
          self.render_area,
          QUAD_CLEAR.iter(),
        );
        encoder.bind_graphics_pipeline(&self.graphics_pipeline);
        encoder.bind_vertex_buffers(0, Some((self.cube_vertices.buffer.deref(), 0)));
        encoder.bind_index_buffer(IndexBufferView {
          buffer: &self.cube_indexes.buffer,
          offset: 0,
          index_type: IndexType::U16,
        });
        encoder.bind_graphics_descriptor_sets(
          &self.pipeline_layout,
          0,
          Some(self.descriptor_set.deref()),
          &[],
        );
        // ONE DRAW CALL PER MODEL MATRIX WE'RE GIVEN
        for model in models.iter() {
          // DETERMINE FINAL MVP MATRIX (once per model)
          let mvp = vp * model;
          for d in mvp.data.iter() {
            if d.is_nan() {
              dbg!(model);
              dbg!(view);
              dbg!(projection);
              dbg!(mvp);
              assert!(false);
            }
          }
          encoder.push_graphics_constants(
            &self.pipeline_layout,
            ShaderStageFlags::VERTEX,
            0,
            cast_slice::<f32, u32>(&mvp.data)
              .expect("this cast never fails for same-aligned same-size data"),
          );
          encoder.draw_indexed(0..36, 0, 0..1);
        }
      }
      buffer.finish();
    }
    // SUBMISSION AND PRESENT
    let command_buffers = &self.command_buffers[i_usize..=i_usize];
    let wait_semaphores: ArrayVec<[_; 1]> =
      [(image_available, PipelineStage::COLOR_ATTACHMENT_OUTPUT)].into();
    let signal_semaphores: ArrayVec<[_; 1]> = [render_finished].into();
    // yes, you have to write it twice like this. yes, it's silly.
    let present_wait_semaphores: ArrayVec<[_; 1]> = [render_finished].into();
    let submission = Submission {
      command_buffers,
      wait_semaphores,
      signal_semaphores,
    };
    let the_command_queue = &mut self.queue_group.queues[0];
    unsafe {
      the_command_queue.submit(submission, Some(flight_fence));
      self
        .swapchain
        .present(the_command_queue, i_u32, present_wait_semaphores)
        .map_err(|_| "Failed to present into the swapchain!")
    }
  }
pub fn draw_cubes_frame ( & mut self , models : & [ glm :: TMat4 < f32 > ] ) -> Result < ( ) , & ' static str > { // SETUP FOR THIS FRAME let flight_fence = & self . in_flight_fences [ self . current_frame ] ; let image_available = & self . image_available_semaphores [ self . current_frame ] ; let render_finished = & self . render_finished_semaphores [ self . current_frame ] ; // Advance the frame _before_ we start using the `?` operator self . current_frame = ( self . current_frame + 1 ) % self . frames_in_flight ; let ( i_u32 , i_usize ) = unsafe { self . device . wait_for_fence ( flight_fence , core :: u64 :: MAX ) . map_err ( | _ | " " ) ? ; self . device . reset_fence ( flight_fence ) . map_err ( | _ | " " ) ? ; let image_index = self . swapchain . acquire_image ( core :: u64 :: MAX , FrameSync :: Semaphore ( image_available ) ) . map_err ( | _ | " " ) ? ; ( image_index , image_index as usize ) } ; // DETERMINE VIEW MATRIX (just once) let view = glm :: look_at_lh ( & glm :: make_vec3 ( & [ 0.0 , 0.0 , - 5.0 ] ) , & glm :: make_vec3 ( & [ 0.0 , 0.0 , 0.0 ] ) , & glm :: make_vec3 ( & [ 0.0 , 1.0 , 0.0 ] ) . normalize ( ) , ) ; // DETERMINE PROJECTION MATRIX (just once) let projection = { let mut temp = glm :: perspective_lh_zo ( 800.0 / 600.0 , f32 :: to_radians ( 50.0 ) , 0.1 , 100.0 ) ; temp [ ( 1 , 1 ) ] *= - 1.0 ; temp } ; // COMBINE THE VIEW AND PROJECTION MATRIX AHEAD OF TIME (just once) let vp = projection * view ; // RECORD COMMANDS unsafe { let buffer = & mut self . command_buffers [ i_usize ] ; const QUAD_CLEAR : [ ClearValue ; 1 ] = [ ClearValue :: Color ( ClearColor :: Float ( [ 0.1 , 0.2 , 0.3 , 1.0 ] ) ) ] ; buffer . begin ( false ) ; { let mut encoder = buffer . begin_render_pass_inline ( & self . render_pass , & self . framebuffers [ i_usize ] , self . render_area , QUAD_CLEAR . iter ( ) , ) ; encoder . bind_graphics_pipeline ( & self . graphics_pipeline ) ; encoder . bind_vertex_buffers ( 0 , Some ( ( self . cube_vertices . buffer . deref ( ) , 0 ) ) ) ; encoder . bind_index_buffer ( IndexBufferView { buffer : & self . cube_indexes . buffer , offset : 0 , index_type : IndexType :: U16 , } ) ; encoder . bind_graphics_descriptor_sets ( & self . pipeline_layout , 0 , Some ( self . descriptor_set . deref ( ) ) , & [ ] , ) ; // ONE DRAW CALL PER MODEL MATRIX WE'RE GIVEN for model in models . iter ( ) { // DETERMINE FINAL MVP MATRIX (once per model) let mvp = vp * model ; for d in mvp . data . iter ( ) { if d . is_nan ( ) { dbg ! ( model ) ; dbg ! ( view ) ; dbg ! ( projection ) ; dbg ! ( mvp ) ; assert ! ( false ) ; } } encoder . push_graphics_constants ( & self . pipeline_layout , ShaderStageFlags :: VERTEX , 0 , cast_slice :: < f32 , u32 > ( & mvp . data ) . expect ( " " ) , ) ; encoder . draw_indexed ( 0 .. 36 , 0 , 0 .. 1 ) ; } } buffer . finish ( ) ; } // SUBMISSION AND PRESENT let command_buffers = & self . command_buffers [ i_usize ..= i_usize ] ; let wait_semaphores : ArrayVec < [ _ ; 1 ] > = [ ( image_available , PipelineStage :: COLOR_ATTACHMENT_OUTPUT ) ] . into ( ) ; let signal_semaphores : ArrayVec < [ _ ; 1 ] > = [ render_finished ] . into ( ) ; // yes, you have to write it twice like this. yes, it's silly. let present_wait_semaphores : ArrayVec < [ _ ; 1 ] > = [ render_finished ] . into ( ) ; let submission = Submission { command_buffers , wait_semaphores , signal_semaphores , } ; let the_command_queue = & mut self . queue_group . queues [ 0 ] ; unsafe { the_command_queue . submit ( submission , Some ( flight_fence ) ) ; self . swapchain . present ( the_command_queue , i_u32 , present_wait_semaphores ) . map_err ( | _ | " " ) } }
Draws one cube per model matrix given.
Draws one cube per model matrix given .
&mut self
models
&[glm::TMat4<f32>]