@ -5,9 +5,8 @@ use vulkano::sync::{GpuFuture, FlushError, NowFuture};
use vulkano ::sync ::now ;
use vulkano ::sync ::now ;
use vulkano ::sync ;
use vulkano ::sync ;
use std ::sync ::Arc ;
use std ::sync ::Arc ;
use vulkano ::swapchain ::{ Swapchain , PresentMode , SurfaceTransform , Surface , SwapchainCreationError , AcquireError , Capabilities };
use vulkano ::swapchain ::{ Swapchain , PresentMode , SurfaceTransform , Surface , SwapchainCreationError , AcquireError , Capabilities , FullscreenExclusive , ColorSpace };
use vulkano ::image ::swapchain ::SwapchainImage ;
use vulkano ::image ::swapchain ::SwapchainImage ;
use winit ::Window ;
use crate ::compute ::compu_state ::CompuState ;
use crate ::compute ::compu_state ::CompuState ;
use vulkano ::image ::ImageUsage ;
use vulkano ::image ::ImageUsage ;
use crate ::compute ::compu_frame ::CompuFrame ;
use crate ::compute ::compu_frame ::CompuFrame ;
@ -21,6 +20,12 @@ use crate::canvas::managed::shader::text_shader::TextShader;
use crate ::canvas ::managed ::handles ::{ CanvasTextureHandle , CompiledShaderHandle , CanvasFontHandle , CanvasImageHandle } ;
use crate ::canvas ::managed ::handles ::{ CanvasTextureHandle , CompiledShaderHandle , CanvasFontHandle , CanvasImageHandle } ;
use crate ::compute ::managed ::handles ::{ CompuKernelHandle , CompuBufferHandle } ;
use crate ::compute ::managed ::handles ::{ CompuKernelHandle , CompuBufferHandle } ;
use crate ::util ::vertex ::{ VertexTypes , ColorVertex3D , TextVertex3D , TextureVertex3D , ImageVertex3D } ;
use crate ::util ::vertex ::{ VertexTypes , ColorVertex3D , TextVertex3D , TextureVertex3D , ImageVertex3D } ;
use vulkano_text ::DrawText ;
use winit ::window ::{ Window , WindowBuilder } ;
use vulkano ::instance ::debug ::DebugCallback ;
use winit ::dpi ::LogicalSize ;
use vulkano_win ::VkSurfaceBuild ;
use winit ::event_loop ::EventLoop ;
/// VKProcessor holds the vulkan instance information, the swapchain,
/// VKProcessor holds the vulkan instance information, the swapchain,
@ -36,7 +41,10 @@ pub struct VkProcessor<'a> {
pub swapchain : Option < Arc < Swapchain < Window > > > ,
pub swapchain : Option < Arc < Swapchain < Window > > > ,
pub swapchain_images : Option < Vec < Arc < SwapchainImage < Window > > > > ,
pub swapchain_images : Option < Vec < Arc < SwapchainImage < Window > > > > ,
swapchain_recreate_needed : bool ,
pub swapchain_recreate_needed : bool ,
pub surface : Arc < Surface < Window > > ,
pub event_loop : Arc < EventLoop < ( ) > > ,
/// State holding textures, images, and their related vertex buffers
/// State holding textures, images, and their related vertex buffers
canvas_state : CanvasState ,
canvas_state : CanvasState ,
@ -49,12 +57,24 @@ pub struct VkProcessor<'a> {
impl < ' a > VkProcessor < ' a > {
impl < ' a > VkProcessor < ' a > {
/// Creates a new VkProcessor from an instance and surface
/// Creates a new VkProcessor from an instance and surface
/// This includes the physical device, queues, compute and canvas state
/// This includes the physical device, queues, compute and canvas state
pub fn new ( instance : & ' a Arc < Instance > , surface : & ' a Arc < Surface < Window > > ) -> VkProcessor < ' a > {
//pub fn new(instance: &'a Arc<Instance>, surface: &'a Arc<Surface<Window>>) -> VkProcessor<'a> {
pub fn new ( instance : Arc < Instance > ) -> VkProcessor < ' a > {
let _callback = DebugCallback ::errors_and_warnings ( & instance , | msg | {
println! ( "Debug callback: {:?}" , msg . description ) ;
} ) . ok ( ) ;
let mut events_loop = Arc ::new ( EventLoop ::new ( ) ) ;
let physical = PhysicalDevice ::enumerate ( instance ) . next ( ) . unwrap ( ) ;
let mut surface = WindowBuilder ::new ( )
. with_inner_size ( LogicalSize ::new ( 800 , 800 ) ) ;
// Some weird namespacing issue here
let mut surface = VkSurfaceBuild ::build_vk_surface ( surface , & events_loop , instance . clone ( ) ) . unwrap ( ) ;
let physical = PhysicalDevice ::enumerate ( & instance ) . next ( ) . unwrap ( ) ;
let queue_family = physical . queue_families ( ) . find ( | & q | {
let queue_family = physical . queue_families ( ) . find ( | & q | {
// We take the first queue that supports drawing to our window.
// We take the first queue that supports drawing to our window.
@ -85,6 +105,8 @@ impl<'a> VkProcessor<'a> {
compute_state : CompuState ::new ( ) ,
compute_state : CompuState ::new ( ) ,
capabilities : capabilities . clone ( ) ,
capabilities : capabilities . clone ( ) ,
canvas_state : CanvasState ::new ( queue , device , physical , capabilities ) ,
canvas_state : CanvasState ::new ( queue , device , physical , capabilities ) ,
surface : surface ,
event_loop : events_loop ,
}
}
}
}
@ -94,19 +116,24 @@ impl<'a> VkProcessor<'a> {
true
true
}
}
pub fn event_loop ( & mut self ) -> Arc < EventLoop < ( ) > > {
self . event_loop ( )
}
/// Using the surface, we calculate the surface capabilities and create the swapchain and swapchain images
/// Using the surface, we calculate the surface capabilities and create the swapchain and swapchain images
pub fn create_swapchain ( & mut self , surface : & ' a Arc < Surface < Window > > ) {
pub fn create_swapchain ( & mut self ) {
let ( mut swapchain , images ) = {
let ( mut swapchain , images ) = {
let capabilities = surface . capabilities ( self . physical ) . unwrap ( ) ;
let capabilities = self . surface . capabilities ( self . physical ) . unwrap ( ) ;
let usage = capabilities . supported_usage_flags ;
let usage = capabilities . supported_usage_flags ;
let alpha = capabilities . supported_composite_alpha . iter ( ) . next ( ) . unwrap ( ) ;
let alpha = capabilities . supported_composite_alpha . iter ( ) . next ( ) . unwrap ( ) ;
// Choosing the internal format that the images will have.
// Choosing the internal format that the images will have.
let format = capabilities . supported_formats [ 0 ] . 0 ;
let format = capabilities . supported_formats [ 0 ] . 0 ;
// Set the swapchains window dimensions
// Set the swapchains window dimensions
let initial_dimensions = if let Some ( dimensions ) = surface . window ( ) . get_ inner_size( ) {
let initial_dimensions = if let dimensions = self . surface . window ( ) . inner_size( ) {
// convert to physical pixels
// convert to physical pixels
let dimensions : ( u32 , u32 ) = dimensions . to_ physical( surface . window ( ) . get_hidpi _factor( ) ) . into ( ) ;
let dimensions : ( u32 , u32 ) = dimensions . to_ logical::< u32 > ( self . surface . window ( ) . scale _factor( ) ) . into ( ) ;
[ dimensions . 0 , dimensions . 1 ]
[ dimensions . 0 , dimensions . 1 ]
} else {
} else {
// The window no longer exists so exit the application.
// The window no longer exists so exit the application.
@ -114,7 +141,7 @@ impl<'a> VkProcessor<'a> {
} ;
} ;
Swapchain ::new ( self . device . clone ( ) ,
Swapchain ::new ( self . device . clone ( ) ,
surface . clone ( ) ,
self . surface . clone ( ) ,
capabilities . min_image_count , // number of attachment images
capabilities . min_image_count , // number of attachment images
format ,
format ,
initial_dimensions ,
initial_dimensions ,
@ -123,7 +150,9 @@ impl<'a> VkProcessor<'a> {
& self . queue ,
& self . queue ,
SurfaceTransform ::Identity ,
SurfaceTransform ::Identity ,
alpha ,
alpha ,
PresentMode ::Immediate , true , None ) . unwrap ( )
PresentMode ::Immediate ,
FullscreenExclusive ::Default , true ,
ColorSpace ::PassThrough ) . unwrap ( )
} ;
} ;
self . swapchain = Some ( swapchain ) ;
self . swapchain = Some ( swapchain ) ;
@ -131,15 +160,16 @@ impl<'a> VkProcessor<'a> {
}
}
/// On screen resizes, the swapchain and images must be recreated
/// On screen resizes, the swapchain and images must be recreated
pub fn recreate_swapchain ( & mut self , surface : & ' a Arc < Surface < Window > > ) {
pub fn recreate_swapchain ( & mut self ) {
let dimensions = if let Some ( dimensions ) = surface . window ( ) . get_ inner_size( ) {
let dimensions = if let dimensions = self . surface . window ( ) . inner_size( ) {
let dimensions : ( u32 , u32 ) = dimensions . to_ physical( surface . window ( ) . get_hidpi _factor( ) ) . into ( ) ;
let dimensions : ( u32 , u32 ) = dimensions . to_ logical::< u32 > ( self . surface . window ( ) . scale _factor( ) ) . into ( ) ;
[ dimensions . 0 , dimensions . 1 ]
[ dimensions . 0 , dimensions . 1 ]
} else {
} else {
return ;
return ;
} ;
} ;
let ( new_swapchain , new_images ) = match self . swapchain . clone ( ) . unwrap ( ) . clone ( ) . recreate_with_dimension ( dimensions ) {
let ( new_swapchain , new_images ) = match self . swapchain . clone ( ) . unwrap ( ) . clone ( )
. recreate_with_dimensions ( dimensions ) {
Ok ( r ) = > r ,
Ok ( r ) = > r ,
// This error tends to happen when the user is manually resizing the window.
// This error tends to happen when the user is manually resizing the window.
// Simply restarting the loop is the easiest way to fix this issue.
// Simply restarting the loop is the easiest way to fix this issue.
@ -176,7 +206,7 @@ impl<'a> VkProcessor<'a> {
/// A hardcoded list of shaders which can be proloaded from this function
/// A hardcoded list of shaders which can be proloaded from this function
pub fn preload_fonts ( & mut self ) {
pub fn preload_fonts ( & mut self ) {
self . canvas_state . load_font ( String ::from ( "sansation.ttf" ) ) ;
//self.canvas_state.load_font(String::from("sansation.ttf"));
}
}
/// O(n) Lookup for the matching texture string
/// O(n) Lookup for the matching texture string
@ -224,11 +254,9 @@ impl<'a> VkProcessor<'a> {
/// Run the VKprocessor for a single frame, consuming the Canvas/Compu Frames
/// Run the VKprocessor for a single frame, consuming the Canvas/Compu Frames
pub fn run ( & mut self ,
pub fn run ( & mut self ,
surface : & ' a Arc < Surface < Window > > ,
canvas_frame : CanvasFrame ,
canvas_frame : CanvasFrame ,
compute_frame : CompuFrame ,
compute_frame : CompuFrame ,
) {
) {
{
{
let g = hprof ::enter ( "Waiting at queue" ) ;
let g = hprof ::enter ( "Waiting at queue" ) ;
self . queue . wait ( ) ;
self . queue . wait ( ) ;
@ -241,7 +269,7 @@ impl<'a> VkProcessor<'a> {
// Whenever the window resizes we need to recreate everything dependent on the window size.
// Whenever the window resizes we need to recreate everything dependent on the window size.
// In this example that includes the swapchain, the framebuffers and the dynamic state viewport.
// In this example that includes the swapchain, the framebuffers and the dynamic state viewport.
if self . swapchain_recreate_needed {
if self . swapchain_recreate_needed {
self . recreate_swapchain ( surface ) ;
self . recreate_swapchain ( ) ;
framebuffers =
framebuffers =
self . canvas_state . window_size_dependent_setup ( & self . swapchain_images . clone ( ) . unwrap ( ) . clone ( ) ) ;
self . canvas_state . window_size_dependent_setup ( & self . swapchain_images . clone ( ) . unwrap ( ) . clone ( ) ) ;
self . swapchain_recreate_needed = false ;
self . swapchain_recreate_needed = false ;
@ -249,7 +277,7 @@ impl<'a> VkProcessor<'a> {
// This function can block if no image is available. The parameter is an optional timeout
// This function can block if no image is available. The parameter is an optional timeout
// after which the function call will return an error.
// after which the function call will return an error.
let ( image_num , acquire_future) =
let ( image_num , suboptimal, acquire_future) =
match vulkano ::swapchain ::acquire_next_image (
match vulkano ::swapchain ::acquire_next_image (
self . swapchain . clone ( ) . unwrap ( ) . clone ( ) ,
self . swapchain . clone ( ) . unwrap ( ) . clone ( ) ,
None ,
None ,
@ -262,6 +290,10 @@ impl<'a> VkProcessor<'a> {
Err ( err ) = > panic! ( "{:?}" , err )
Err ( err ) = > panic! ( "{:?}" , err )
} ;
} ;
if suboptimal {
self . swapchain_recreate_needed = true ;
}
drop ( g ) ;
drop ( g ) ;
let allocated_buffers = {
let allocated_buffers = {
@ -271,20 +303,21 @@ impl<'a> VkProcessor<'a> {
self . canvas_state . allocate ( canvas_frame )
self . canvas_state . allocate ( canvas_frame )
} ;
} ;
// let mut draw_text = DrawText::new(self.device.clone(), self.queue.clone(), self.swapchain.unwrap().clone(), &self.swapchain_images.images);
let mut command_buffer =
let mut command_buffer =
AutoCommandBufferBuilder ::primary_one_time_submit ( self . device . clone ( ) , self . queue . family ( ) ) . unwrap ( ) ;
AutoCommandBufferBuilder ::primary_one_time_submit ( self . device . clone ( ) , self . queue . family ( ) ) . unwrap ( ) ;
let g = hprof ::enter ( "Push compute commands to command buffer" ) ;
let g = hprof ::enter ( "Push compute commands to command buffer" ) ;
// Add the compute commands
// Add the compute commands
let mut command_buffer = self . compute_state . compute_commands ( compute_frame , command_buffer , & self . canvas_state ) ;
self . compute_state . compute_commands ( compute_frame , & mut command_buffer , & self . canvas_state ) ;
drop ( g ) ;
drop ( g ) ;
let g = hprof ::enter ( "Push draw commands to command buffer" ) ;
let g = hprof ::enter ( "Push draw commands to command buffer" ) ;
// Add the draw commands
// Add the draw commands
//let mut command_buffer = self.canvas_state.draw_commands(command_buffer, framebuffers, image_num);
//let mut command_buffer = self.canvas_state.draw_commands(command_buffer, framebuffers, image_num);
let mut command_buffer =
self . canvas_state . draw_commands ( & mut command_buffer , framebuffers , image_num , allocated_buffers ) ;
self . canvas_state . draw_commands ( command_buffer , framebuffers , image_num , allocated_buffers ) ;
// And build
// And build
let command_buffer = command_buffer . build ( ) . unwrap ( ) ;
let command_buffer = command_buffer . build ( ) . unwrap ( ) ;
@ -292,7 +325,6 @@ impl<'a> VkProcessor<'a> {
// Wait on the previous frame, then execute the command buffer and present the image
// Wait on the previous frame, then execute the command buffer and present the image
{
{
let g = hprof ::enter ( "Joining on the framebuffer" ) ;
let g = hprof ::enter ( "Joining on the framebuffer" ) ;
let mut future = sync ::now ( self . device . clone ( ) )
let mut future = sync ::now ( self . device . clone ( ) )
. join ( acquire_future ) ;
. join ( acquire_future ) ;