From 9af5bc6d35785fc9bb96c69dd09aba9de96d1837 Mon Sep 17 00:00:00 2001 From: Pawel Lapinski Date: Tue, 14 Nov 2017 09:57:36 +0100 Subject: [PATCH] Changed line endings from Windows (\r\n) to Linux (\n) style. --- Project/Common/ListOfFunctions.inl | 368 ++-- Project/Common/OperatingSystem.cpp | 770 ++++---- Project/Common/OperatingSystem.h | 278 +-- Project/Common/Tools.cpp | 314 ++-- Project/Common/Tools.h | 236 +-- Project/Common/VulkanCommon.cpp | 1500 +++++++-------- Project/Common/VulkanCommon.h | 312 ++-- Project/Common/VulkanFunctions.cpp | 54 +- Project/Common/VulkanFunctions.h | 64 +- Project/Tutorial01/Tutorial01.cpp | 566 +++--- Project/Tutorial01/Tutorial01.h | 150 +- Project/Tutorial01/main.cpp | 78 +- Project/Tutorial02/Tutorial02.cpp | 1738 +++++++++--------- Project/Tutorial02/Tutorial02.h | 212 +-- Project/Tutorial02/main.cpp | 90 +- Project/Tutorial03/Tutorial03.cpp | 1190 ++++++------ Project/Tutorial03/Tutorial03.h | 164 +- Project/Tutorial03/main.cpp | 118 +- Project/Tutorial04/Tutorial04.cpp | 1566 ++++++++-------- Project/Tutorial04/Tutorial04.h | 264 +-- Project/Tutorial04/main.cpp | 106 +- Project/Tutorial05/Tutorial05.cpp | 1724 ++++++++--------- Project/Tutorial05/Tutorial05.h | 276 +-- Project/Tutorial05/main.cpp | 118 +- Project/Tutorial06/Tutorial06.cpp | 2456 ++++++++++++------------- Project/Tutorial06/Tutorial06.h | 344 ++-- Project/Tutorial06/main.cpp | 148 +- Project/Tutorial07/Tutorial07.cpp | 2740 ++++++++++++++-------------- Project/Tutorial07/Tutorial07.h | 352 ++-- Project/Tutorial07/main.cpp | 154 +- Project/compile_shaders.bat | 82 +- 31 files changed, 9266 insertions(+), 9266 deletions(-) diff --git a/Project/Common/ListOfFunctions.inl b/Project/Common/ListOfFunctions.inl index 0a1ee81..fe617b4 100644 --- a/Project/Common/ListOfFunctions.inl +++ b/Project/Common/ListOfFunctions.inl @@ -1,185 +1,185 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -// ************************************************************ // -// Exported functions // -// // -// These functions are always exposed by vulkan libraries. // -// ************************************************************ // - -#if !defined(VK_EXPORTED_FUNCTION) -#define VK_EXPORTED_FUNCTION( fun ) -#endif - -VK_EXPORTED_FUNCTION( vkGetInstanceProcAddr ) - -#undef VK_EXPORTED_FUNCTION - - -// ************************************************************ // -// Global level functions // -// // -// They allow checking what instance extensions are available // -// and allow creation of a Vulkan Instance. // -// ************************************************************ // - -#if !defined(VK_GLOBAL_LEVEL_FUNCTION) -#define VK_GLOBAL_LEVEL_FUNCTION( fun ) -#endif - -// Tutorial 01 -VK_GLOBAL_LEVEL_FUNCTION( vkCreateInstance ) - -// Tutorial 02 -VK_GLOBAL_LEVEL_FUNCTION( vkEnumerateInstanceExtensionProperties ) - -#undef VK_GLOBAL_LEVEL_FUNCTION - - -// ************************************************************ // -// Instance level functions // -// // -// These functions allow for device queries and creation. // -// They help choose which device is well suited for our needs. // -// ************************************************************ // - -#if !defined(VK_INSTANCE_LEVEL_FUNCTION) -#define VK_INSTANCE_LEVEL_FUNCTION( fun ) -#endif - -// Tutorial 01 -VK_INSTANCE_LEVEL_FUNCTION( vkEnumeratePhysicalDevices ) -VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceProperties ) -VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceFeatures ) -VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceQueueFamilyProperties ) -VK_INSTANCE_LEVEL_FUNCTION( vkCreateDevice ) -VK_INSTANCE_LEVEL_FUNCTION( vkGetDeviceProcAddr ) -VK_INSTANCE_LEVEL_FUNCTION( vkDestroyInstance ) - -// Tutorial 02 -VK_INSTANCE_LEVEL_FUNCTION( vkEnumerateDeviceExtensionProperties ) -#if defined(USE_SWAPCHAIN_EXTENSIONS) -VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceSurfaceSupportKHR ) -VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceSurfaceCapabilitiesKHR ) -VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceSurfaceFormatsKHR ) -VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceSurfacePresentModesKHR ) -VK_INSTANCE_LEVEL_FUNCTION( vkDestroySurfaceKHR ) -#if defined(VK_USE_PLATFORM_WIN32_KHR) -VK_INSTANCE_LEVEL_FUNCTION( vkCreateWin32SurfaceKHR ) -#elif defined(VK_USE_PLATFORM_XCB_KHR) -VK_INSTANCE_LEVEL_FUNCTION( vkCreateXcbSurfaceKHR ) -#elif defined(VK_USE_PLATFORM_XLIB_KHR) -VK_INSTANCE_LEVEL_FUNCTION( vkCreateXlibSurfaceKHR ) -#endif -#endif - -// Tutorial 04 -VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceMemoryProperties ) - -#undef VK_INSTANCE_LEVEL_FUNCTION - - -// ************************************************************ // -// Device level functions // -// // -// These functions are used mainly for drawing // -// ************************************************************ // - -#if !defined(VK_DEVICE_LEVEL_FUNCTION) -#define VK_DEVICE_LEVEL_FUNCTION( fun ) -#endif - -// Tutorial 01 -VK_DEVICE_LEVEL_FUNCTION( vkGetDeviceQueue ) -VK_DEVICE_LEVEL_FUNCTION( vkDeviceWaitIdle ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyDevice ) - -// Tutorial 02 -VK_DEVICE_LEVEL_FUNCTION( vkCreateSemaphore ) -VK_DEVICE_LEVEL_FUNCTION( vkCreateCommandPool ) -VK_DEVICE_LEVEL_FUNCTION( vkAllocateCommandBuffers ) -VK_DEVICE_LEVEL_FUNCTION( vkBeginCommandBuffer ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdPipelineBarrier ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdClearColorImage ) -VK_DEVICE_LEVEL_FUNCTION( vkEndCommandBuffer ) -VK_DEVICE_LEVEL_FUNCTION( vkQueueSubmit ) -VK_DEVICE_LEVEL_FUNCTION( vkFreeCommandBuffers ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyCommandPool ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroySemaphore ) -#if defined(USE_SWAPCHAIN_EXTENSIONS) -VK_DEVICE_LEVEL_FUNCTION( vkCreateSwapchainKHR ) -VK_DEVICE_LEVEL_FUNCTION( vkGetSwapchainImagesKHR ) -VK_DEVICE_LEVEL_FUNCTION( vkAcquireNextImageKHR ) -VK_DEVICE_LEVEL_FUNCTION( vkQueuePresentKHR ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroySwapchainKHR ) -#endif - -// Tutorial 03 -VK_DEVICE_LEVEL_FUNCTION( vkCreateImageView ) -VK_DEVICE_LEVEL_FUNCTION( vkCreateRenderPass ) -VK_DEVICE_LEVEL_FUNCTION( vkCreateFramebuffer ) -VK_DEVICE_LEVEL_FUNCTION( vkCreateShaderModule ) -VK_DEVICE_LEVEL_FUNCTION( vkCreatePipelineLayout ) -VK_DEVICE_LEVEL_FUNCTION( vkCreateGraphicsPipelines ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdBeginRenderPass ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdBindPipeline ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdDraw ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdEndRenderPass ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyShaderModule ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyPipelineLayout ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyPipeline ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyRenderPass ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyFramebuffer ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyImageView ) - -// Tutorial 04 -VK_DEVICE_LEVEL_FUNCTION( vkCreateFence ) -VK_DEVICE_LEVEL_FUNCTION( vkCreateBuffer ) -VK_DEVICE_LEVEL_FUNCTION( vkGetBufferMemoryRequirements ) -VK_DEVICE_LEVEL_FUNCTION( vkAllocateMemory ) -VK_DEVICE_LEVEL_FUNCTION( vkBindBufferMemory ) -VK_DEVICE_LEVEL_FUNCTION( vkMapMemory ) -VK_DEVICE_LEVEL_FUNCTION( vkFlushMappedMemoryRanges ) -VK_DEVICE_LEVEL_FUNCTION( vkUnmapMemory ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdSetViewport ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdSetScissor ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdBindVertexBuffers ) -VK_DEVICE_LEVEL_FUNCTION( vkWaitForFences ) -VK_DEVICE_LEVEL_FUNCTION( vkResetFences ) -VK_DEVICE_LEVEL_FUNCTION( vkFreeMemory ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyBuffer ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyFence ) - -// Tutorial 05 -VK_DEVICE_LEVEL_FUNCTION( vkCmdCopyBuffer ) - -// Tutorial 06 -VK_DEVICE_LEVEL_FUNCTION( vkCreateImage ) -VK_DEVICE_LEVEL_FUNCTION( vkGetImageMemoryRequirements ) -VK_DEVICE_LEVEL_FUNCTION( vkBindImageMemory ) -VK_DEVICE_LEVEL_FUNCTION( vkCreateSampler ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdCopyBufferToImage ) -VK_DEVICE_LEVEL_FUNCTION( vkCreateDescriptorSetLayout ) -VK_DEVICE_LEVEL_FUNCTION( vkCreateDescriptorPool ) -VK_DEVICE_LEVEL_FUNCTION( vkAllocateDescriptorSets ) -VK_DEVICE_LEVEL_FUNCTION( vkUpdateDescriptorSets ) -VK_DEVICE_LEVEL_FUNCTION( vkCmdBindDescriptorSets ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyDescriptorPool ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyDescriptorSetLayout ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroySampler ) -VK_DEVICE_LEVEL_FUNCTION( vkDestroyImage ) - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +// ************************************************************ // +// Exported functions // +// // +// These functions are always exposed by vulkan libraries. // +// ************************************************************ // + +#if !defined(VK_EXPORTED_FUNCTION) +#define VK_EXPORTED_FUNCTION( fun ) +#endif + +VK_EXPORTED_FUNCTION( vkGetInstanceProcAddr ) + +#undef VK_EXPORTED_FUNCTION + + +// ************************************************************ // +// Global level functions // +// // +// They allow checking what instance extensions are available // +// and allow creation of a Vulkan Instance. // +// ************************************************************ // + +#if !defined(VK_GLOBAL_LEVEL_FUNCTION) +#define VK_GLOBAL_LEVEL_FUNCTION( fun ) +#endif + +// Tutorial 01 +VK_GLOBAL_LEVEL_FUNCTION( vkCreateInstance ) + +// Tutorial 02 +VK_GLOBAL_LEVEL_FUNCTION( vkEnumerateInstanceExtensionProperties ) + +#undef VK_GLOBAL_LEVEL_FUNCTION + + +// ************************************************************ // +// Instance level functions // +// // +// These functions allow for device queries and creation. // +// They help choose which device is well suited for our needs. // +// ************************************************************ // + +#if !defined(VK_INSTANCE_LEVEL_FUNCTION) +#define VK_INSTANCE_LEVEL_FUNCTION( fun ) +#endif + +// Tutorial 01 +VK_INSTANCE_LEVEL_FUNCTION( vkEnumeratePhysicalDevices ) +VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceProperties ) +VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceFeatures ) +VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceQueueFamilyProperties ) +VK_INSTANCE_LEVEL_FUNCTION( vkCreateDevice ) +VK_INSTANCE_LEVEL_FUNCTION( vkGetDeviceProcAddr ) +VK_INSTANCE_LEVEL_FUNCTION( vkDestroyInstance ) + +// Tutorial 02 +VK_INSTANCE_LEVEL_FUNCTION( vkEnumerateDeviceExtensionProperties ) +#if defined(USE_SWAPCHAIN_EXTENSIONS) +VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceSurfaceSupportKHR ) +VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceSurfaceCapabilitiesKHR ) +VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceSurfaceFormatsKHR ) +VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceSurfacePresentModesKHR ) +VK_INSTANCE_LEVEL_FUNCTION( vkDestroySurfaceKHR ) +#if defined(VK_USE_PLATFORM_WIN32_KHR) +VK_INSTANCE_LEVEL_FUNCTION( vkCreateWin32SurfaceKHR ) +#elif defined(VK_USE_PLATFORM_XCB_KHR) +VK_INSTANCE_LEVEL_FUNCTION( vkCreateXcbSurfaceKHR ) +#elif defined(VK_USE_PLATFORM_XLIB_KHR) +VK_INSTANCE_LEVEL_FUNCTION( vkCreateXlibSurfaceKHR ) +#endif +#endif + +// Tutorial 04 +VK_INSTANCE_LEVEL_FUNCTION( vkGetPhysicalDeviceMemoryProperties ) + +#undef VK_INSTANCE_LEVEL_FUNCTION + + +// ************************************************************ // +// Device level functions // +// // +// These functions are used mainly for drawing // +// ************************************************************ // + +#if !defined(VK_DEVICE_LEVEL_FUNCTION) +#define VK_DEVICE_LEVEL_FUNCTION( fun ) +#endif + +// Tutorial 01 +VK_DEVICE_LEVEL_FUNCTION( vkGetDeviceQueue ) +VK_DEVICE_LEVEL_FUNCTION( vkDeviceWaitIdle ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyDevice ) + +// Tutorial 02 +VK_DEVICE_LEVEL_FUNCTION( vkCreateSemaphore ) +VK_DEVICE_LEVEL_FUNCTION( vkCreateCommandPool ) +VK_DEVICE_LEVEL_FUNCTION( vkAllocateCommandBuffers ) +VK_DEVICE_LEVEL_FUNCTION( vkBeginCommandBuffer ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdPipelineBarrier ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdClearColorImage ) +VK_DEVICE_LEVEL_FUNCTION( vkEndCommandBuffer ) +VK_DEVICE_LEVEL_FUNCTION( vkQueueSubmit ) +VK_DEVICE_LEVEL_FUNCTION( vkFreeCommandBuffers ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyCommandPool ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroySemaphore ) +#if defined(USE_SWAPCHAIN_EXTENSIONS) +VK_DEVICE_LEVEL_FUNCTION( vkCreateSwapchainKHR ) +VK_DEVICE_LEVEL_FUNCTION( vkGetSwapchainImagesKHR ) +VK_DEVICE_LEVEL_FUNCTION( vkAcquireNextImageKHR ) +VK_DEVICE_LEVEL_FUNCTION( vkQueuePresentKHR ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroySwapchainKHR ) +#endif + +// Tutorial 03 +VK_DEVICE_LEVEL_FUNCTION( vkCreateImageView ) +VK_DEVICE_LEVEL_FUNCTION( vkCreateRenderPass ) +VK_DEVICE_LEVEL_FUNCTION( vkCreateFramebuffer ) +VK_DEVICE_LEVEL_FUNCTION( vkCreateShaderModule ) +VK_DEVICE_LEVEL_FUNCTION( vkCreatePipelineLayout ) +VK_DEVICE_LEVEL_FUNCTION( vkCreateGraphicsPipelines ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdBeginRenderPass ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdBindPipeline ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdDraw ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdEndRenderPass ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyShaderModule ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyPipelineLayout ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyPipeline ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyRenderPass ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyFramebuffer ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyImageView ) + +// Tutorial 04 +VK_DEVICE_LEVEL_FUNCTION( vkCreateFence ) +VK_DEVICE_LEVEL_FUNCTION( vkCreateBuffer ) +VK_DEVICE_LEVEL_FUNCTION( vkGetBufferMemoryRequirements ) +VK_DEVICE_LEVEL_FUNCTION( vkAllocateMemory ) +VK_DEVICE_LEVEL_FUNCTION( vkBindBufferMemory ) +VK_DEVICE_LEVEL_FUNCTION( vkMapMemory ) +VK_DEVICE_LEVEL_FUNCTION( vkFlushMappedMemoryRanges ) +VK_DEVICE_LEVEL_FUNCTION( vkUnmapMemory ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdSetViewport ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdSetScissor ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdBindVertexBuffers ) +VK_DEVICE_LEVEL_FUNCTION( vkWaitForFences ) +VK_DEVICE_LEVEL_FUNCTION( vkResetFences ) +VK_DEVICE_LEVEL_FUNCTION( vkFreeMemory ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyBuffer ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyFence ) + +// Tutorial 05 +VK_DEVICE_LEVEL_FUNCTION( vkCmdCopyBuffer ) + +// Tutorial 06 +VK_DEVICE_LEVEL_FUNCTION( vkCreateImage ) +VK_DEVICE_LEVEL_FUNCTION( vkGetImageMemoryRequirements ) +VK_DEVICE_LEVEL_FUNCTION( vkBindImageMemory ) +VK_DEVICE_LEVEL_FUNCTION( vkCreateSampler ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdCopyBufferToImage ) +VK_DEVICE_LEVEL_FUNCTION( vkCreateDescriptorSetLayout ) +VK_DEVICE_LEVEL_FUNCTION( vkCreateDescriptorPool ) +VK_DEVICE_LEVEL_FUNCTION( vkAllocateDescriptorSets ) +VK_DEVICE_LEVEL_FUNCTION( vkUpdateDescriptorSets ) +VK_DEVICE_LEVEL_FUNCTION( vkCmdBindDescriptorSets ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyDescriptorPool ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyDescriptorSetLayout ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroySampler ) +VK_DEVICE_LEVEL_FUNCTION( vkDestroyImage ) + #undef VK_DEVICE_LEVEL_FUNCTION \ No newline at end of file diff --git a/Project/Common/OperatingSystem.cpp b/Project/Common/OperatingSystem.cpp index 0d40e07..b738092 100644 --- a/Project/Common/OperatingSystem.cpp +++ b/Project/Common/OperatingSystem.cpp @@ -1,385 +1,385 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include "OperatingSystem.h" - -namespace ApiWithoutSecrets { - - namespace OS { - - Window::Window() : - Parameters() { - } - - WindowParameters Window::GetParameters() const { - return Parameters; - } - -#if defined(VK_USE_PLATFORM_WIN32_KHR) - -#define TUTORIAL_NAME "API without Secrets: Introduction to Vulkan" - - LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { - switch( message ) { - case WM_SIZE: - case WM_EXITSIZEMOVE: - PostMessage( hWnd, WM_USER + 1, wParam, lParam ); - break; - case WM_KEYDOWN: - case WM_CLOSE: - PostMessage( hWnd, WM_USER + 2, wParam, lParam ); - break; - default: - return DefWindowProc( hWnd, message, wParam, lParam ); - } - return 0; - } - - Window::~Window() { - if( Parameters.Handle ) { - DestroyWindow( Parameters.Handle ); - } - - if( Parameters.Instance ) { - UnregisterClass( TUTORIAL_NAME, Parameters.Instance ); - } - } - - bool Window::Create( const char *title ) { - Parameters.Instance = GetModuleHandle( nullptr ); - - // Register window class - WNDCLASSEX wcex; - - wcex.cbSize = sizeof(WNDCLASSEX); - - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = WndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = Parameters.Instance; - wcex.hIcon = NULL; - wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wcex.lpszMenuName = NULL; - wcex.lpszClassName = TUTORIAL_NAME; - wcex.hIconSm = NULL; - - if( !RegisterClassEx( &wcex ) ) { - return false; - } - - // Create window - Parameters.Handle = CreateWindow( TUTORIAL_NAME, title, WS_OVERLAPPEDWINDOW, 20, 20, 500, 500, nullptr, nullptr, Parameters.Instance, nullptr ); - if( !Parameters.Handle ) { - return false; - } - - return true; - } - - bool Window::RenderingLoop( TutorialBase &tutorial ) const { - // Display window - ShowWindow( Parameters.Handle, SW_SHOWNORMAL ); - UpdateWindow( Parameters.Handle ); - - // Main message loop - MSG message; - bool loop = true; - bool resize = false; - bool result = true; - - while( loop ) { - if( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) ) { - // Process events - switch( message.message ) { - // Resize - case WM_USER + 1: - resize = true; - break; - // Close - case WM_USER + 2: - loop = false; - break; - } - TranslateMessage( &message ); - DispatchMessage( &message ); - } else { - // Draw - if( resize ) { - resize = false; - if( !tutorial.OnWindowSizeChanged() ) { - result = false; - break; - } - } - if( tutorial.ReadyToDraw() ) { - if( !tutorial.Draw() ) { - result = false; - break; - } - } else { - std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); - } - } - } - - return result; - } - -#elif defined(VK_USE_PLATFORM_XCB_KHR) - - Window::~Window() { - xcb_destroy_window( Parameters.Connection, Parameters.Handle ); - xcb_disconnect( Parameters.Connection ); - } - - bool Window::Create( const char *title ) { - int screen_index; - Parameters.Connection = xcb_connect( nullptr, &screen_index ); - - if( !Parameters.Connection ) { - return false; - } - - const xcb_setup_t *setup = xcb_get_setup( Parameters.Connection ); - xcb_screen_iterator_t screen_iterator = xcb_setup_roots_iterator( setup ); - - while( screen_index-- > 0 ) { - xcb_screen_next( &screen_iterator ); - } - - xcb_screen_t *screen = screen_iterator.data; - - Parameters.Handle = xcb_generate_id( Parameters.Connection ); - - uint32_t value_list[] = { - screen->white_pixel, - XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_STRUCTURE_NOTIFY - }; - - xcb_create_window( - Parameters.Connection, - XCB_COPY_FROM_PARENT, - Parameters.Handle, - screen->root, - 20, - 20, - 500, - 500, - 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - screen->root_visual, - XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, - value_list ); - - xcb_flush( Parameters.Connection ); - - xcb_change_property( - Parameters.Connection, - XCB_PROP_MODE_REPLACE, - Parameters.Handle, - XCB_ATOM_WM_NAME, - XCB_ATOM_STRING, - 8, - strlen( title ), - title ); - - return true; - } - - bool Window::RenderingLoop( TutorialBase &tutorial ) const { - // Prepare notification for window destruction - xcb_intern_atom_cookie_t protocols_cookie = xcb_intern_atom( Parameters.Connection, 1, 12, "WM_PROTOCOLS" ); - xcb_intern_atom_reply_t *protocols_reply = xcb_intern_atom_reply( Parameters.Connection, protocols_cookie, 0 ); - xcb_intern_atom_cookie_t delete_cookie = xcb_intern_atom( Parameters.Connection, 0, 16, "WM_DELETE_WINDOW" ); - xcb_intern_atom_reply_t *delete_reply = xcb_intern_atom_reply( Parameters.Connection, delete_cookie, 0 ); - xcb_change_property( Parameters.Connection, XCB_PROP_MODE_REPLACE, Parameters.Handle, (*protocols_reply).atom, 4, 32, 1, &(*delete_reply).atom ); - free( protocols_reply ); - - // Display window - xcb_map_window( Parameters.Connection, Parameters.Handle ); - xcb_flush( Parameters.Connection ); - - // Main message loop - xcb_generic_event_t *event; - bool loop = true; - bool resize = false; - bool result = true; - - while( loop ) { - event = xcb_poll_for_event( Parameters.Connection ); - - if( event ) { - // Process events - switch (event->response_type & 0x7f) { - // Resize - case XCB_CONFIGURE_NOTIFY: { - xcb_configure_notify_event_t *configure_event = (xcb_configure_notify_event_t*)event; - static uint16_t width = configure_event->width; - static uint16_t height = configure_event->height; - - if( ((configure_event->width > 0) && (width != configure_event->width)) || - ((configure_event->height > 0) && (height != configure_event->height)) ) { - resize = true; - width = configure_event->width; - height = configure_event->height; - } - } - break; - // Close - case XCB_CLIENT_MESSAGE: - if( (*(xcb_client_message_event_t*)event).data.data32[0] == (*delete_reply).atom ) { - loop = false; - free( delete_reply ); - } - break; - case XCB_KEY_PRESS: - loop = false; - break; - } - free( event ); - } else { - // Draw - if( resize ) { - resize = false; - if( !tutorial.OnWindowSizeChanged() ) { - result = false; - break; - } - } - if( tutorial.ReadyToDraw() ) { - if( !tutorial.Draw() ) { - result = false; - break; - } - } else { - std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); - } - } - } - - return result; - } - -#elif defined(VK_USE_PLATFORM_XLIB_KHR) - - Window::~Window() { - XDestroyWindow( Parameters.DisplayPtr, Parameters.Handle ); - XCloseDisplay( Parameters.DisplayPtr ); - } - - bool Window::Create( const char *title ) { - Parameters.DisplayPtr = XOpenDisplay( nullptr ); - if( !Parameters.DisplayPtr ) { - return false; - } - - int default_screen = DefaultScreen( Parameters.DisplayPtr ); - - Parameters.Handle = XCreateSimpleWindow( - Parameters.DisplayPtr, - DefaultRootWindow( Parameters.DisplayPtr ), - 20, - 20, - 500, - 500, - 1, - BlackPixel( Parameters.DisplayPtr, default_screen ), - WhitePixel( Parameters.DisplayPtr, default_screen ) ); - - // XSync( Parameters.DisplayPtr, false ); - XSetStandardProperties( Parameters.DisplayPtr, Parameters.Handle, title, title, None, nullptr, 0, nullptr ); - XSelectInput( Parameters.DisplayPtr, Parameters.Handle, ExposureMask | KeyPressMask | StructureNotifyMask ); - - return true; - } - - bool Window::RenderingLoop( TutorialBase &tutorial ) const { - // Prepare notification for window destruction - Atom delete_window_atom; - delete_window_atom = XInternAtom( Parameters.DisplayPtr, "WM_DELETE_WINDOW", false ); - XSetWMProtocols( Parameters.DisplayPtr, Parameters.Handle, &delete_window_atom, 1); - - // Display window - XClearWindow( Parameters.DisplayPtr, Parameters.Handle ); - XMapWindow( Parameters.DisplayPtr, Parameters.Handle ); - - // Main message loop - XEvent event; - bool loop = true; - bool resize = false; - bool result = true; - - while( loop ) { - if( XPending( Parameters.DisplayPtr ) ) { - XNextEvent( Parameters.DisplayPtr, &event ); - switch( event.type ) { - //Process events - case ConfigureNotify: { - static int width = event.xconfigure.width; - static int height = event.xconfigure.height; - - if( ((event.xconfigure.width > 0) && (event.xconfigure.width != width)) || - ((event.xconfigure.height > 0) && (event.xconfigure.width != height)) ) { - width = event.xconfigure.width; - height = event.xconfigure.height; - resize = true; - } - } - break; - case KeyPress: - loop = false; - break; - case DestroyNotify: - loop = false; - break; - case ClientMessage: - if( static_cast(event.xclient.data.l[0]) == delete_window_atom ) { - loop = false; - } - break; - } - } else { - // Draw - if( resize ) { - resize = false; - if( !tutorial.OnWindowSizeChanged() ) { - result = false; - break; - } - } - if( tutorial.ReadyToDraw() ) { - if( !tutorial.Draw() ) { - result = false; - break; - } - } else { - std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); - } - } - } - - return result; - } - -#endif - - } // namespace OS - -} // namespace ApiWithoutSecrets +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "OperatingSystem.h" + +namespace ApiWithoutSecrets { + + namespace OS { + + Window::Window() : + Parameters() { + } + + WindowParameters Window::GetParameters() const { + return Parameters; + } + +#if defined(VK_USE_PLATFORM_WIN32_KHR) + +#define TUTORIAL_NAME "API without Secrets: Introduction to Vulkan" + + LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { + switch( message ) { + case WM_SIZE: + case WM_EXITSIZEMOVE: + PostMessage( hWnd, WM_USER + 1, wParam, lParam ); + break; + case WM_KEYDOWN: + case WM_CLOSE: + PostMessage( hWnd, WM_USER + 2, wParam, lParam ); + break; + default: + return DefWindowProc( hWnd, message, wParam, lParam ); + } + return 0; + } + + Window::~Window() { + if( Parameters.Handle ) { + DestroyWindow( Parameters.Handle ); + } + + if( Parameters.Instance ) { + UnregisterClass( TUTORIAL_NAME, Parameters.Instance ); + } + } + + bool Window::Create( const char *title ) { + Parameters.Instance = GetModuleHandle( nullptr ); + + // Register window class + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = Parameters.Instance; + wcex.hIcon = NULL; + wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszMenuName = NULL; + wcex.lpszClassName = TUTORIAL_NAME; + wcex.hIconSm = NULL; + + if( !RegisterClassEx( &wcex ) ) { + return false; + } + + // Create window + Parameters.Handle = CreateWindow( TUTORIAL_NAME, title, WS_OVERLAPPEDWINDOW, 20, 20, 500, 500, nullptr, nullptr, Parameters.Instance, nullptr ); + if( !Parameters.Handle ) { + return false; + } + + return true; + } + + bool Window::RenderingLoop( TutorialBase &tutorial ) const { + // Display window + ShowWindow( Parameters.Handle, SW_SHOWNORMAL ); + UpdateWindow( Parameters.Handle ); + + // Main message loop + MSG message; + bool loop = true; + bool resize = false; + bool result = true; + + while( loop ) { + if( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) ) { + // Process events + switch( message.message ) { + // Resize + case WM_USER + 1: + resize = true; + break; + // Close + case WM_USER + 2: + loop = false; + break; + } + TranslateMessage( &message ); + DispatchMessage( &message ); + } else { + // Draw + if( resize ) { + resize = false; + if( !tutorial.OnWindowSizeChanged() ) { + result = false; + break; + } + } + if( tutorial.ReadyToDraw() ) { + if( !tutorial.Draw() ) { + result = false; + break; + } + } else { + std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); + } + } + } + + return result; + } + +#elif defined(VK_USE_PLATFORM_XCB_KHR) + + Window::~Window() { + xcb_destroy_window( Parameters.Connection, Parameters.Handle ); + xcb_disconnect( Parameters.Connection ); + } + + bool Window::Create( const char *title ) { + int screen_index; + Parameters.Connection = xcb_connect( nullptr, &screen_index ); + + if( !Parameters.Connection ) { + return false; + } + + const xcb_setup_t *setup = xcb_get_setup( Parameters.Connection ); + xcb_screen_iterator_t screen_iterator = xcb_setup_roots_iterator( setup ); + + while( screen_index-- > 0 ) { + xcb_screen_next( &screen_iterator ); + } + + xcb_screen_t *screen = screen_iterator.data; + + Parameters.Handle = xcb_generate_id( Parameters.Connection ); + + uint32_t value_list[] = { + screen->white_pixel, + XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_STRUCTURE_NOTIFY + }; + + xcb_create_window( + Parameters.Connection, + XCB_COPY_FROM_PARENT, + Parameters.Handle, + screen->root, + 20, + 20, + 500, + 500, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, + XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, + value_list ); + + xcb_flush( Parameters.Connection ); + + xcb_change_property( + Parameters.Connection, + XCB_PROP_MODE_REPLACE, + Parameters.Handle, + XCB_ATOM_WM_NAME, + XCB_ATOM_STRING, + 8, + strlen( title ), + title ); + + return true; + } + + bool Window::RenderingLoop( TutorialBase &tutorial ) const { + // Prepare notification for window destruction + xcb_intern_atom_cookie_t protocols_cookie = xcb_intern_atom( Parameters.Connection, 1, 12, "WM_PROTOCOLS" ); + xcb_intern_atom_reply_t *protocols_reply = xcb_intern_atom_reply( Parameters.Connection, protocols_cookie, 0 ); + xcb_intern_atom_cookie_t delete_cookie = xcb_intern_atom( Parameters.Connection, 0, 16, "WM_DELETE_WINDOW" ); + xcb_intern_atom_reply_t *delete_reply = xcb_intern_atom_reply( Parameters.Connection, delete_cookie, 0 ); + xcb_change_property( Parameters.Connection, XCB_PROP_MODE_REPLACE, Parameters.Handle, (*protocols_reply).atom, 4, 32, 1, &(*delete_reply).atom ); + free( protocols_reply ); + + // Display window + xcb_map_window( Parameters.Connection, Parameters.Handle ); + xcb_flush( Parameters.Connection ); + + // Main message loop + xcb_generic_event_t *event; + bool loop = true; + bool resize = false; + bool result = true; + + while( loop ) { + event = xcb_poll_for_event( Parameters.Connection ); + + if( event ) { + // Process events + switch (event->response_type & 0x7f) { + // Resize + case XCB_CONFIGURE_NOTIFY: { + xcb_configure_notify_event_t *configure_event = (xcb_configure_notify_event_t*)event; + static uint16_t width = configure_event->width; + static uint16_t height = configure_event->height; + + if( ((configure_event->width > 0) && (width != configure_event->width)) || + ((configure_event->height > 0) && (height != configure_event->height)) ) { + resize = true; + width = configure_event->width; + height = configure_event->height; + } + } + break; + // Close + case XCB_CLIENT_MESSAGE: + if( (*(xcb_client_message_event_t*)event).data.data32[0] == (*delete_reply).atom ) { + loop = false; + free( delete_reply ); + } + break; + case XCB_KEY_PRESS: + loop = false; + break; + } + free( event ); + } else { + // Draw + if( resize ) { + resize = false; + if( !tutorial.OnWindowSizeChanged() ) { + result = false; + break; + } + } + if( tutorial.ReadyToDraw() ) { + if( !tutorial.Draw() ) { + result = false; + break; + } + } else { + std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); + } + } + } + + return result; + } + +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + + Window::~Window() { + XDestroyWindow( Parameters.DisplayPtr, Parameters.Handle ); + XCloseDisplay( Parameters.DisplayPtr ); + } + + bool Window::Create( const char *title ) { + Parameters.DisplayPtr = XOpenDisplay( nullptr ); + if( !Parameters.DisplayPtr ) { + return false; + } + + int default_screen = DefaultScreen( Parameters.DisplayPtr ); + + Parameters.Handle = XCreateSimpleWindow( + Parameters.DisplayPtr, + DefaultRootWindow( Parameters.DisplayPtr ), + 20, + 20, + 500, + 500, + 1, + BlackPixel( Parameters.DisplayPtr, default_screen ), + WhitePixel( Parameters.DisplayPtr, default_screen ) ); + + // XSync( Parameters.DisplayPtr, false ); + XSetStandardProperties( Parameters.DisplayPtr, Parameters.Handle, title, title, None, nullptr, 0, nullptr ); + XSelectInput( Parameters.DisplayPtr, Parameters.Handle, ExposureMask | KeyPressMask | StructureNotifyMask ); + + return true; + } + + bool Window::RenderingLoop( TutorialBase &tutorial ) const { + // Prepare notification for window destruction + Atom delete_window_atom; + delete_window_atom = XInternAtom( Parameters.DisplayPtr, "WM_DELETE_WINDOW", false ); + XSetWMProtocols( Parameters.DisplayPtr, Parameters.Handle, &delete_window_atom, 1); + + // Display window + XClearWindow( Parameters.DisplayPtr, Parameters.Handle ); + XMapWindow( Parameters.DisplayPtr, Parameters.Handle ); + + // Main message loop + XEvent event; + bool loop = true; + bool resize = false; + bool result = true; + + while( loop ) { + if( XPending( Parameters.DisplayPtr ) ) { + XNextEvent( Parameters.DisplayPtr, &event ); + switch( event.type ) { + //Process events + case ConfigureNotify: { + static int width = event.xconfigure.width; + static int height = event.xconfigure.height; + + if( ((event.xconfigure.width > 0) && (event.xconfigure.width != width)) || + ((event.xconfigure.height > 0) && (event.xconfigure.width != height)) ) { + width = event.xconfigure.width; + height = event.xconfigure.height; + resize = true; + } + } + break; + case KeyPress: + loop = false; + break; + case DestroyNotify: + loop = false; + break; + case ClientMessage: + if( static_cast(event.xclient.data.l[0]) == delete_window_atom ) { + loop = false; + } + break; + } + } else { + // Draw + if( resize ) { + resize = false; + if( !tutorial.OnWindowSizeChanged() ) { + result = false; + break; + } + } + if( tutorial.ReadyToDraw() ) { + if( !tutorial.Draw() ) { + result = false; + break; + } + } else { + std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); + } + } + } + + return result; + } + +#endif + + } // namespace OS + +} // namespace ApiWithoutSecrets diff --git a/Project/Common/OperatingSystem.h b/Project/Common/OperatingSystem.h index 397d88c..15d6a29 100644 --- a/Project/Common/OperatingSystem.h +++ b/Project/Common/OperatingSystem.h @@ -1,140 +1,140 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(OPERATING_SYSTEM_HEADER) -#define OPERATING_SYSTEM_HEADER - -#if defined(VK_USE_PLATFORM_WIN32_KHR) -#include - -#elif defined(VK_USE_PLATFORM_XCB_KHR) -#include -#include -#include - -#elif defined(VK_USE_PLATFORM_XLIB_KHR) -#include -#include -#include -#include - -#endif - -#include -#include - -namespace ApiWithoutSecrets { - - namespace OS { - - // ************************************************************ // - // LibraryHandle // - // // - // Dynamic Library OS dependent type // - // ************************************************************ // - // -#if defined(VK_USE_PLATFORM_WIN32_KHR) - typedef HMODULE LibraryHandle; - -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - typedef void* LibraryHandle; - -#endif - - // ************************************************************ // - // OnWindowSizeChanged // - // // - // Base class for handling window size changes // - // ************************************************************ // - class TutorialBase { - public: - virtual bool OnWindowSizeChanged() = 0; - virtual bool Draw() = 0; - - virtual bool ReadyToDraw() const final { - return CanRender; - } - - TutorialBase() : - CanRender( false ) { - } - - virtual ~TutorialBase() { - } - - protected: - bool CanRender; - }; - - // ************************************************************ // - // WindowParameters // - // // - // OS dependent window parameters // - // ************************************************************ // - struct WindowParameters { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - HINSTANCE Instance; - HWND Handle; - - WindowParameters() : - Instance(), - Handle() { - } - -#elif defined(VK_USE_PLATFORM_XCB_KHR) - xcb_connection_t *Connection; - xcb_window_t Handle; - - WindowParameters() : - Connection(), - Handle() { - } - -#elif defined(VK_USE_PLATFORM_XLIB_KHR) - Display *DisplayPtr; - Window Handle; - - WindowParameters() : - DisplayPtr(), - Handle() { - } - -#endif - }; - - // ************************************************************ // - // Window // - // // - // OS dependent window creation and destruction class // - // ************************************************************ // - class Window { - public: - Window(); - ~Window(); - - bool Create( const char *title ); - bool RenderingLoop( TutorialBase &tutorial ) const; - WindowParameters GetParameters() const; - - private: - WindowParameters Parameters; - }; - - } // namespace OS - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(OPERATING_SYSTEM_HEADER) +#define OPERATING_SYSTEM_HEADER + +#if defined(VK_USE_PLATFORM_WIN32_KHR) +#include + +#elif defined(VK_USE_PLATFORM_XCB_KHR) +#include +#include +#include + +#elif defined(VK_USE_PLATFORM_XLIB_KHR) +#include +#include +#include +#include + +#endif + +#include +#include + +namespace ApiWithoutSecrets { + + namespace OS { + + // ************************************************************ // + // LibraryHandle // + // // + // Dynamic Library OS dependent type // + // ************************************************************ // + // +#if defined(VK_USE_PLATFORM_WIN32_KHR) + typedef HMODULE LibraryHandle; + +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + typedef void* LibraryHandle; + +#endif + + // ************************************************************ // + // OnWindowSizeChanged // + // // + // Base class for handling window size changes // + // ************************************************************ // + class TutorialBase { + public: + virtual bool OnWindowSizeChanged() = 0; + virtual bool Draw() = 0; + + virtual bool ReadyToDraw() const final { + return CanRender; + } + + TutorialBase() : + CanRender( false ) { + } + + virtual ~TutorialBase() { + } + + protected: + bool CanRender; + }; + + // ************************************************************ // + // WindowParameters // + // // + // OS dependent window parameters // + // ************************************************************ // + struct WindowParameters { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + HINSTANCE Instance; + HWND Handle; + + WindowParameters() : + Instance(), + Handle() { + } + +#elif defined(VK_USE_PLATFORM_XCB_KHR) + xcb_connection_t *Connection; + xcb_window_t Handle; + + WindowParameters() : + Connection(), + Handle() { + } + +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + Display *DisplayPtr; + Window Handle; + + WindowParameters() : + DisplayPtr(), + Handle() { + } + +#endif + }; + + // ************************************************************ // + // Window // + // // + // OS dependent window creation and destruction class // + // ************************************************************ // + class Window { + public: + Window(); + ~Window(); + + bool Create( const char *title ); + bool RenderingLoop( TutorialBase &tutorial ) const; + WindowParameters GetParameters() const; + + private: + WindowParameters Parameters; + }; + + } // namespace OS + +} // namespace ApiWithoutSecrets + #endif // OPERATING_SYSTEM_HEADER \ No newline at end of file diff --git a/Project/Common/Tools.cpp b/Project/Common/Tools.cpp index c2314eb..5a3fa9b 100644 --- a/Project/Common/Tools.cpp +++ b/Project/Common/Tools.cpp @@ -1,158 +1,158 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include "Tools.h" -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" - -namespace ApiWithoutSecrets { - - namespace Tools { - - // ************************************************************ // - // GetBinaryFileContents // - // // - // Function reading binary contents of a file // - // ************************************************************ // - std::vector GetBinaryFileContents( std::string const &filename ) { - - std::ifstream file( filename, std::ios::binary ); - if( file.fail() ) { - std::cout << "Could not open \"" << filename << "\" file!" << std::endl; - return std::vector(); - } - - std::streampos begin, end; - begin = file.tellg(); - file.seekg( 0, std::ios::end ); - end = file.tellg(); - - std::vector result( static_cast(end - begin) ); - file.seekg( 0, std::ios::beg ); - file.read( &result[0], end - begin ); - file.close(); - - return result; - } - - // ************************************************************ // - // GetImageData // - // // - // Function loading image (texture) data from a specified file // - // ************************************************************ // - std::vector GetImageData( std::string const &filename, int requested_components, int *width, int *height, int *components, int *data_size ) { - std::vector file_data = Tools::GetBinaryFileContents( filename ); - if( file_data.size() == 0 ) { - return std::vector(); - } - - int tmp_width = 0, tmp_height = 0, tmp_components = 0; - unsigned char *image_data = stbi_load_from_memory( reinterpret_cast(&file_data[0]), static_cast(file_data.size()), &tmp_width, &tmp_height, &tmp_components, requested_components ); - if( (image_data == nullptr) || - (tmp_width <= 0) || - (tmp_height <= 0) || - (tmp_components <= 0) ) { - std::cout << "Could not read image data!" << std::endl; - return std::vector(); - } - - int size = (tmp_width) * (tmp_height) * (requested_components <= 0 ? tmp_components : requested_components); - if( data_size ) { - *data_size = size; - } - if( width ) { - *width = tmp_width; - } - if( height ) { - *height = tmp_height; - } - if( components ) { - *components = tmp_components; - } - - std::vector output(size); - memcpy( &output[0], image_data, size ); - - stbi_image_free( image_data ); - return output; - } - - // ************************************************************ // - // GetPerspectiveProjectionMatrix // - // // - // Function calculating perspective projection matrix // - // ************************************************************ // - std::array GetPerspectiveProjectionMatrix( float const aspect_ratio, float const field_of_view, float const near_clip, float const far_clip ) { - float f = 1.0f / std::tan( field_of_view * 0.5f * 0.01745329251994329576923690768489f ); - - return { - f / aspect_ratio, - 0.0f, - 0.0f, - 0.0f, - - 0.0f, - f, - 0.0f, - 0.0f, - - 0.0f, - 0.0f, - (near_clip + far_clip) / (near_clip - far_clip), - -1.0f, - - 0.0f, - 0.0f, - (2.0f * near_clip * far_clip) / (near_clip - far_clip), - 0.0f - }; - } - - // ************************************************************ // - // GetOrthographicsProjectionMatrix // - // // - // Function calculating orthographic projection matrix // - // ************************************************************ // - std::array GetOrthographicProjectionMatrix( float const left_plane, float const right_plane, float const top_plane, float const bottom_plane, float const near_plane, float const far_plane ) { - return { - 2.0f / (right_plane - left_plane), - 0.0f, - 0.0f, - 0.0f, - - 0.0f, - 2.0f / (bottom_plane - top_plane), - 0.0f, - 0.0f, - - 0.0f, - 0.0f, - -2.0f / (far_plane - near_plane), - 0.0f, - - -(right_plane + left_plane) / (right_plane - left_plane), - -(bottom_plane + top_plane) / (bottom_plane - top_plane), - -(far_plane + near_plane) / (far_plane - near_plane), - 1.0f - }; - } - - } // namespace Tools - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "Tools.h" +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +namespace ApiWithoutSecrets { + + namespace Tools { + + // ************************************************************ // + // GetBinaryFileContents // + // // + // Function reading binary contents of a file // + // ************************************************************ // + std::vector GetBinaryFileContents( std::string const &filename ) { + + std::ifstream file( filename, std::ios::binary ); + if( file.fail() ) { + std::cout << "Could not open \"" << filename << "\" file!" << std::endl; + return std::vector(); + } + + std::streampos begin, end; + begin = file.tellg(); + file.seekg( 0, std::ios::end ); + end = file.tellg(); + + std::vector result( static_cast(end - begin) ); + file.seekg( 0, std::ios::beg ); + file.read( &result[0], end - begin ); + file.close(); + + return result; + } + + // ************************************************************ // + // GetImageData // + // // + // Function loading image (texture) data from a specified file // + // ************************************************************ // + std::vector GetImageData( std::string const &filename, int requested_components, int *width, int *height, int *components, int *data_size ) { + std::vector file_data = Tools::GetBinaryFileContents( filename ); + if( file_data.size() == 0 ) { + return std::vector(); + } + + int tmp_width = 0, tmp_height = 0, tmp_components = 0; + unsigned char *image_data = stbi_load_from_memory( reinterpret_cast(&file_data[0]), static_cast(file_data.size()), &tmp_width, &tmp_height, &tmp_components, requested_components ); + if( (image_data == nullptr) || + (tmp_width <= 0) || + (tmp_height <= 0) || + (tmp_components <= 0) ) { + std::cout << "Could not read image data!" << std::endl; + return std::vector(); + } + + int size = (tmp_width) * (tmp_height) * (requested_components <= 0 ? tmp_components : requested_components); + if( data_size ) { + *data_size = size; + } + if( width ) { + *width = tmp_width; + } + if( height ) { + *height = tmp_height; + } + if( components ) { + *components = tmp_components; + } + + std::vector output(size); + memcpy( &output[0], image_data, size ); + + stbi_image_free( image_data ); + return output; + } + + // ************************************************************ // + // GetPerspectiveProjectionMatrix // + // // + // Function calculating perspective projection matrix // + // ************************************************************ // + std::array GetPerspectiveProjectionMatrix( float const aspect_ratio, float const field_of_view, float const near_clip, float const far_clip ) { + float f = 1.0f / std::tan( field_of_view * 0.5f * 0.01745329251994329576923690768489f ); + + return { + f / aspect_ratio, + 0.0f, + 0.0f, + 0.0f, + + 0.0f, + f, + 0.0f, + 0.0f, + + 0.0f, + 0.0f, + (near_clip + far_clip) / (near_clip - far_clip), + -1.0f, + + 0.0f, + 0.0f, + (2.0f * near_clip * far_clip) / (near_clip - far_clip), + 0.0f + }; + } + + // ************************************************************ // + // GetOrthographicsProjectionMatrix // + // // + // Function calculating orthographic projection matrix // + // ************************************************************ // + std::array GetOrthographicProjectionMatrix( float const left_plane, float const right_plane, float const top_plane, float const bottom_plane, float const near_plane, float const far_plane ) { + return { + 2.0f / (right_plane - left_plane), + 0.0f, + 0.0f, + 0.0f, + + 0.0f, + 2.0f / (bottom_plane - top_plane), + 0.0f, + 0.0f, + + 0.0f, + 0.0f, + -2.0f / (far_plane - near_plane), + 0.0f, + + -(right_plane + left_plane) / (right_plane - left_plane), + -(bottom_plane + top_plane) / (bottom_plane - top_plane), + -(far_plane + near_plane) / (far_plane - near_plane), + 1.0f + }; + } + + } // namespace Tools + } // namespace ApiWithoutSecrets \ No newline at end of file diff --git a/Project/Common/Tools.h b/Project/Common/Tools.h index 67504e0..d8d1e56 100644 --- a/Project/Common/Tools.h +++ b/Project/Common/Tools.h @@ -1,119 +1,119 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(TOOLS_HEADER) -#define TOOLS_HEADER - -#include -#include -#include -#include "vulkan.h" - -namespace ApiWithoutSecrets { - - namespace Tools { - - // ************************************************************ // - // AutoDeleter // - // // - // Auto-deleter helper template class responsible for calling // - // provided function which deletes given object of type T // - // ************************************************************ // - template - class AutoDeleter { - public: - AutoDeleter() : - Object( VK_NULL_HANDLE ), - Deleter( nullptr ), - Device( VK_NULL_HANDLE ) { - } - - AutoDeleter( T object, F deleter, VkDevice device ) : - Object( object ), - Deleter( deleter ), - Device( device ) { - } - - AutoDeleter( AutoDeleter&& other ) { - *this = std::move( other ); - } - - ~AutoDeleter() { - if( (Object != VK_NULL_HANDLE) && (Deleter != nullptr) && (Device != VK_NULL_HANDLE) ) { - Deleter( Device, Object, nullptr ); - } - } - - AutoDeleter& operator=(AutoDeleter&& other) { - if( this != &other ) { - Object = other.Object; - Deleter = other.Deleter; - Device = other.Device; - other.Object = VK_NULL_HANDLE; - } - return *this; - } - - T Get() { - return Object; - } - - bool operator !() const { - return Object == VK_NULL_HANDLE; - } - - private: - AutoDeleter( const AutoDeleter& ); - AutoDeleter& operator=( const AutoDeleter& ); - T Object; - F Deleter; - VkDevice Device; - }; - - // ************************************************************ // - // GetBinaryFileContents // - // // - // Function reading binary contents of a file // - // ************************************************************ // - std::vector GetBinaryFileContents( std::string const &filename ); - - // ************************************************************ // - // GetImageData // - // // - // Function loading image (texture) data from a specified file // - // ************************************************************ // - std::vector GetImageData( std::string const &filename, int requested_components, int *width, int *height, int *components, int *data_size ); - - // ************************************************************ // - // GetPerspectiveProjectionMatrix // - // // - // Function calculating perspective projection matrix // - // ************************************************************ // - std::array GetPerspectiveProjectionMatrix( float const aspect_ratio, float const field_of_view, float const near_clip, float const far_clip ); - - // ************************************************************ // - // GetOrthographicsProjectionMatrix // - // // - // Function calculating orthographic projection matrix // - // ************************************************************ // - std::array GetOrthographicProjectionMatrix( float const left_plane, float const right_plane, float const top_plane, float const bottom_plane, float const near_plane, float const far_plane ); - - } // namespace Tools - -} // namespace ApiWithoutSecrets - - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(TOOLS_HEADER) +#define TOOLS_HEADER + +#include +#include +#include +#include "vulkan.h" + +namespace ApiWithoutSecrets { + + namespace Tools { + + // ************************************************************ // + // AutoDeleter // + // // + // Auto-deleter helper template class responsible for calling // + // provided function which deletes given object of type T // + // ************************************************************ // + template + class AutoDeleter { + public: + AutoDeleter() : + Object( VK_NULL_HANDLE ), + Deleter( nullptr ), + Device( VK_NULL_HANDLE ) { + } + + AutoDeleter( T object, F deleter, VkDevice device ) : + Object( object ), + Deleter( deleter ), + Device( device ) { + } + + AutoDeleter( AutoDeleter&& other ) { + *this = std::move( other ); + } + + ~AutoDeleter() { + if( (Object != VK_NULL_HANDLE) && (Deleter != nullptr) && (Device != VK_NULL_HANDLE) ) { + Deleter( Device, Object, nullptr ); + } + } + + AutoDeleter& operator=(AutoDeleter&& other) { + if( this != &other ) { + Object = other.Object; + Deleter = other.Deleter; + Device = other.Device; + other.Object = VK_NULL_HANDLE; + } + return *this; + } + + T Get() { + return Object; + } + + bool operator !() const { + return Object == VK_NULL_HANDLE; + } + + private: + AutoDeleter( const AutoDeleter& ); + AutoDeleter& operator=( const AutoDeleter& ); + T Object; + F Deleter; + VkDevice Device; + }; + + // ************************************************************ // + // GetBinaryFileContents // + // // + // Function reading binary contents of a file // + // ************************************************************ // + std::vector GetBinaryFileContents( std::string const &filename ); + + // ************************************************************ // + // GetImageData // + // // + // Function loading image (texture) data from a specified file // + // ************************************************************ // + std::vector GetImageData( std::string const &filename, int requested_components, int *width, int *height, int *components, int *data_size ); + + // ************************************************************ // + // GetPerspectiveProjectionMatrix // + // // + // Function calculating perspective projection matrix // + // ************************************************************ // + std::array GetPerspectiveProjectionMatrix( float const aspect_ratio, float const field_of_view, float const near_clip, float const far_clip ); + + // ************************************************************ // + // GetOrthographicsProjectionMatrix // + // // + // Function calculating orthographic projection matrix // + // ************************************************************ // + std::array GetOrthographicProjectionMatrix( float const left_plane, float const right_plane, float const top_plane, float const bottom_plane, float const near_plane, float const far_plane ); + + } // namespace Tools + +} // namespace ApiWithoutSecrets + + #endif // TOOLS_HEADER \ No newline at end of file diff --git a/Project/Common/VulkanCommon.cpp b/Project/Common/VulkanCommon.cpp index a854ecb..343e8c8 100644 --- a/Project/Common/VulkanCommon.cpp +++ b/Project/Common/VulkanCommon.cpp @@ -1,751 +1,751 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "VulkanCommon.h" -#include "VulkanFunctions.h" - -namespace ApiWithoutSecrets { - - VulkanCommon::VulkanCommon() : - VulkanLibrary(), - Window(), - Vulkan() { - } - - bool VulkanCommon::PrepareVulkan( OS::WindowParameters parameters ) { - Window = parameters; - - if( !LoadVulkanLibrary() ) { - return false; - } - if( !LoadExportedEntryPoints() ) { - return false; - } - if( !LoadGlobalLevelEntryPoints() ) { - return false; - } - if( !CreateInstance() ) { - return false; - } - if( !LoadInstanceLevelEntryPoints() ) { - return false; - } - if( !CreatePresentationSurface() ) { - return false; - } - if( !CreateDevice() ) { - return false; - } - if( !LoadDeviceLevelEntryPoints() ) { - return false; - } - if( !GetDeviceQueue() ) { - return false; - } - if( !CreateSwapChain() ) { - return false; - } - return true; - } - - bool VulkanCommon::OnWindowSizeChanged() { - ChildClear(); - - if( CreateSwapChain() ) { - if( CanRender ) { - return ChildOnWindowSizeChanged(); - } - return true; - } - - return false; - } - - VkPhysicalDevice VulkanCommon::GetPhysicalDevice() const { - return Vulkan.PhysicalDevice; - } - - VkDevice VulkanCommon::GetDevice() const { - return Vulkan.Device; - } - - const QueueParameters VulkanCommon::GetGraphicsQueue() const { - return Vulkan.GraphicsQueue; - } - - const QueueParameters VulkanCommon::GetPresentQueue() const { - return Vulkan.PresentQueue; - } - - const SwapChainParameters VulkanCommon::GetSwapChain() const { - return Vulkan.SwapChain; - } - - bool VulkanCommon::LoadVulkanLibrary() { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - VulkanLibrary = LoadLibrary( "vulkan-1.dll" ); -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - VulkanLibrary = dlopen( "libvulkan.so.1", RTLD_NOW ); -#endif - - if( VulkanLibrary == nullptr ) { - std::cout << "Could not load Vulkan library!" << std::endl; - return false; - } - return true; - } - - bool VulkanCommon::LoadExportedEntryPoints() { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - #define LoadProcAddress GetProcAddress -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - #define LoadProcAddress dlsym -#endif - -#define VK_EXPORTED_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)LoadProcAddress( VulkanLibrary, #fun )) ) { \ - std::cout << "Could not load exported function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool VulkanCommon::LoadGlobalLevelEntryPoints() { -#define VK_GLOBAL_LEVEL_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( nullptr, #fun )) ) { \ - std::cout << "Could not load global level function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool VulkanCommon::CreateInstance() { - uint32_t extensions_count = 0; - if( (vkEnumerateInstanceExtensionProperties( nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || - (extensions_count == 0) ) { - std::cout << "Error occurred during instance extensions enumeration!" << std::endl; - return false; - } - - std::vector available_extensions( extensions_count ); - if( vkEnumerateInstanceExtensionProperties( nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during instance extensions enumeration!" << std::endl; - return false; - } - - std::vector extensions = { - VK_KHR_SURFACE_EXTENSION_NAME, -#if defined(VK_USE_PLATFORM_WIN32_KHR) - VK_KHR_WIN32_SURFACE_EXTENSION_NAME -#elif defined(VK_USE_PLATFORM_XCB_KHR) - VK_KHR_XCB_SURFACE_EXTENSION_NAME -#elif defined(VK_USE_PLATFORM_XLIB_KHR) - VK_KHR_XLIB_SURFACE_EXTENSION_NAME -#endif - }; - - for( size_t i = 0; i < extensions.size(); ++i ) { - if( !CheckExtensionAvailability( extensions[i], available_extensions ) ) { - std::cout << "Could not find instance extension named \"" << extensions[i] << "\"!" << std::endl; - return false; - } - } - - VkApplicationInfo application_info = { - VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType - nullptr, // const void *pNext - "API without Secrets: Introduction to Vulkan", // const char *pApplicationName - VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t applicationVersion - "Vulkan Tutorial by Intel", // const char *pEngineName - VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t engineVersion - VK_MAKE_VERSION( 1, 0, 0 ) // uint32_t apiVersion - }; - - VkInstanceCreateInfo instance_create_info = { - VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkInstanceCreateFlags flags - &application_info, // const VkApplicationInfo *pApplicationInfo - 0, // uint32_t enabledLayerCount - nullptr, // const char * const *ppEnabledLayerNames - static_cast(extensions.size()), // uint32_t enabledExtensionCount - &extensions[0] // const char * const *ppEnabledExtensionNames - }; - - if( vkCreateInstance( &instance_create_info, nullptr, &Vulkan.Instance ) != VK_SUCCESS ) { - std::cout << "Could not create Vulkan instance!" << std::endl; - return false; - } - return true; - } - - bool VulkanCommon::LoadInstanceLevelEntryPoints() { -#define VK_INSTANCE_LEVEL_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( Vulkan.Instance, #fun )) ) { \ - std::cout << "Could not load instance level function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool VulkanCommon::CreatePresentationSurface() { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - VkWin32SurfaceCreateInfoKHR surface_create_info = { - VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkWin32SurfaceCreateFlagsKHR flags - Window.Instance, // HINSTANCE hinstance - Window.Handle // HWND hwnd - }; - - if( vkCreateWin32SurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { - return true; - } - -#elif defined(VK_USE_PLATFORM_XCB_KHR) - VkXcbSurfaceCreateInfoKHR surface_create_info = { - VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkXcbSurfaceCreateFlagsKHR flags - Window.Connection, // xcb_connection_t *connection - Window.Handle // xcb_window_t window - }; - - if( vkCreateXcbSurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { - return true; - } - -#elif defined(VK_USE_PLATFORM_XLIB_KHR) - VkXlibSurfaceCreateInfoKHR surface_create_info = { - VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkXlibSurfaceCreateFlagsKHR flags - Window.DisplayPtr, // Display *dpy - Window.Handle // Window window - }; - if( vkCreateXlibSurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { - return true; - } - -#endif - - std::cout << "Could not create presentation surface!" << std::endl; - return false; - } - - bool VulkanCommon::CreateDevice() { - uint32_t num_devices = 0; - if( (vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, nullptr ) != VK_SUCCESS) || - (num_devices == 0) ) { - std::cout << "Error occurred during physical devices enumeration!" << std::endl; - return false; - } - - std::vector physical_devices( num_devices ); - if( vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, &physical_devices[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during physical devices enumeration!" << std::endl; - return false; - } - - uint32_t selected_graphics_queue_family_index = UINT32_MAX; - uint32_t selected_present_queue_family_index = UINT32_MAX; - - for( uint32_t i = 0; i < num_devices; ++i ) { - if( CheckPhysicalDeviceProperties( physical_devices[i], selected_graphics_queue_family_index, selected_present_queue_family_index ) ) { - Vulkan.PhysicalDevice = physical_devices[i]; - break; - } - } - if( Vulkan.PhysicalDevice == VK_NULL_HANDLE ) { - std::cout << "Could not select physical device based on the chosen properties!" << std::endl; - return false; - } - - std::vector queue_create_infos; - std::vector queue_priorities = { 1.0f }; - - queue_create_infos.push_back( { - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDeviceQueueCreateFlags flags - selected_graphics_queue_family_index, // uint32_t queueFamilyIndex - static_cast(queue_priorities.size()), // uint32_t queueCount - &queue_priorities[0] // const float *pQueuePriorities - } ); - - if( selected_graphics_queue_family_index != selected_present_queue_family_index ) { - queue_create_infos.push_back( { - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDeviceQueueCreateFlags flags - selected_present_queue_family_index, // uint32_t queueFamilyIndex - static_cast(queue_priorities.size()), // uint32_t queueCount - &queue_priorities[0] // const float *pQueuePriorities - } ); - } - - std::vector extensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - - VkDeviceCreateInfo device_create_info = { - VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDeviceCreateFlags flags - static_cast(queue_create_infos.size()), // uint32_t queueCreateInfoCount - &queue_create_infos[0], // const VkDeviceQueueCreateInfo *pQueueCreateInfos - 0, // uint32_t enabledLayerCount - nullptr, // const char * const *ppEnabledLayerNames - static_cast(extensions.size()), // uint32_t enabledExtensionCount - &extensions[0], // const char * const *ppEnabledExtensionNames - nullptr // const VkPhysicalDeviceFeatures *pEnabledFeatures - }; - - if( vkCreateDevice( Vulkan.PhysicalDevice, &device_create_info, nullptr, &Vulkan.Device ) != VK_SUCCESS ) { - std::cout << "Could not create Vulkan device!" << std::endl; - return false; - } - - Vulkan.GraphicsQueue.FamilyIndex = selected_graphics_queue_family_index; - Vulkan.PresentQueue.FamilyIndex = selected_present_queue_family_index; - return true; - } - - bool VulkanCommon::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &selected_graphics_queue_family_index, uint32_t &selected_present_queue_family_index ) { - uint32_t extensions_count = 0; - if( (vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || - (extensions_count == 0) ) { - std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; - return false; - } - - std::vector available_extensions( extensions_count ); - if( vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; - return false; - } - - std::vector device_extensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - - for( size_t i = 0; i < device_extensions.size(); ++i ) { - if( !CheckExtensionAvailability( device_extensions[i], available_extensions ) ) { - std::cout << "Physical device " << physical_device << " doesn't support extension named \"" << device_extensions[i] << "\"!" << std::endl; - return false; - } - } - - VkPhysicalDeviceProperties device_properties; - VkPhysicalDeviceFeatures device_features; - - vkGetPhysicalDeviceProperties( physical_device, &device_properties ); - vkGetPhysicalDeviceFeatures( physical_device, &device_features ); - - uint32_t major_version = VK_VERSION_MAJOR( device_properties.apiVersion ); - - if( (major_version < 1) || - (device_properties.limits.maxImageDimension2D < 4096) ) { - std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; - return false; - } - - uint32_t queue_families_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); - if( queue_families_count == 0 ) { - std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; - return false; - } - - std::vector queue_family_properties( queue_families_count ); - std::vector queue_present_support( queue_families_count ); - - vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_family_properties[0] ); - - uint32_t graphics_queue_family_index = UINT32_MAX; - uint32_t present_queue_family_index = UINT32_MAX; - - for( uint32_t i = 0; i < queue_families_count; ++i ) { - vkGetPhysicalDeviceSurfaceSupportKHR( physical_device, i, Vulkan.PresentationSurface, &queue_present_support[i] ); - - if( (queue_family_properties[i].queueCount > 0) && - (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { - // Select first queue that supports graphics - if( graphics_queue_family_index == UINT32_MAX ) { - graphics_queue_family_index = i; - } - - // If there is queue that supports both graphics and present - prefer it - if( queue_present_support[i] ) { - selected_graphics_queue_family_index = i; - selected_present_queue_family_index = i; - return true; - } - } - } - - // We don't have queue that supports both graphics and present so we have to use separate queues - for( uint32_t i = 0; i < queue_families_count; ++i ) { - if( queue_present_support[i] ) { - present_queue_family_index = i; - break; - } - } - - // If this device doesn't support queues with graphics and present capabilities don't use it - if( (graphics_queue_family_index == UINT32_MAX) || - (present_queue_family_index == UINT32_MAX) ) { - std::cout << "Could not find queue families with required properties on physical device " << physical_device << "!" << std::endl; - return false; - } - - selected_graphics_queue_family_index = graphics_queue_family_index; - selected_present_queue_family_index = present_queue_family_index; - return true; - } - - bool VulkanCommon::LoadDeviceLevelEntryPoints() { -#define VK_DEVICE_LEVEL_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)vkGetDeviceProcAddr( Vulkan.Device, #fun )) ) { \ - std::cout << "Could not load device level function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool VulkanCommon::GetDeviceQueue() { - vkGetDeviceQueue( Vulkan.Device, Vulkan.GraphicsQueue.FamilyIndex, 0, &Vulkan.GraphicsQueue.Handle ); - vkGetDeviceQueue( Vulkan.Device, Vulkan.PresentQueue.FamilyIndex, 0, &Vulkan.PresentQueue.Handle ); - return true; - } - - bool VulkanCommon::CreateSwapChain() { - CanRender = false; - - if( Vulkan.Device != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( Vulkan.Device ); - } - - for( size_t i = 0; i < Vulkan.SwapChain.Images.size(); ++i ) { - if( Vulkan.SwapChain.Images[i].View != VK_NULL_HANDLE ) { - vkDestroyImageView( GetDevice(), Vulkan.SwapChain.Images[i].View, nullptr ); - Vulkan.SwapChain.Images[i].View = VK_NULL_HANDLE; - } - } - Vulkan.SwapChain.Images.clear(); - - VkSurfaceCapabilitiesKHR surface_capabilities; - if( vkGetPhysicalDeviceSurfaceCapabilitiesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &surface_capabilities ) != VK_SUCCESS ) { - std::cout << "Could not check presentation surface capabilities!" << std::endl; - return false; - } - - uint32_t formats_count; - if( (vkGetPhysicalDeviceSurfaceFormatsKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &formats_count, nullptr ) != VK_SUCCESS) || - (formats_count == 0) ) { - std::cout << "Error occurred during presentation surface formats enumeration!" << std::endl; - return false; - } - - std::vector surface_formats( formats_count ); - if( vkGetPhysicalDeviceSurfaceFormatsKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &formats_count, &surface_formats[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during presentation surface formats enumeration!" << std::endl; - return false; - } - - uint32_t present_modes_count; - if( (vkGetPhysicalDeviceSurfacePresentModesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &present_modes_count, nullptr ) != VK_SUCCESS) || - (present_modes_count == 0) ) { - std::cout << "Error occurred during presentation surface present modes enumeration!" << std::endl; - return false; - } - - std::vector present_modes( present_modes_count ); - if( vkGetPhysicalDeviceSurfacePresentModesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &present_modes_count, &present_modes[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during presentation surface present modes enumeration!" << std::endl; - return false; - } - - uint32_t desired_number_of_images = GetSwapChainNumImages( surface_capabilities ); - VkSurfaceFormatKHR desired_format = GetSwapChainFormat( surface_formats ); - VkExtent2D desired_extent = GetSwapChainExtent( surface_capabilities ); - VkImageUsageFlags desired_usage = GetSwapChainUsageFlags( surface_capabilities ); - VkSurfaceTransformFlagBitsKHR desired_transform = GetSwapChainTransform( surface_capabilities ); - VkPresentModeKHR desired_present_mode = GetSwapChainPresentMode( present_modes ); - VkSwapchainKHR old_swap_chain = Vulkan.SwapChain.Handle; - - if( static_cast(desired_usage) == -1 ) { - return false; - } - if( static_cast(desired_present_mode) == -1 ) { - return false; - } - if( (desired_extent.width == 0) || (desired_extent.height == 0) ) { - // Current surface size is (0, 0) so we can't create a swap chain and render anything (CanRender == false) - // But we don't wont to kill the application as this situation may occur i.e. when window gets minimized - return true; - } - - VkSwapchainCreateInfoKHR swap_chain_create_info = { - VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkSwapchainCreateFlagsKHR flags - Vulkan.PresentationSurface, // VkSurfaceKHR surface - desired_number_of_images, // uint32_t minImageCount - desired_format.format, // VkFormat imageFormat - desired_format.colorSpace, // VkColorSpaceKHR imageColorSpace - desired_extent, // VkExtent2D imageExtent - 1, // uint32_t imageArrayLayers - desired_usage, // VkImageUsageFlags imageUsage - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode - 0, // uint32_t queueFamilyIndexCount - nullptr, // const uint32_t *pQueueFamilyIndices - desired_transform, // VkSurfaceTransformFlagBitsKHR preTransform - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, // VkCompositeAlphaFlagBitsKHR compositeAlpha - desired_present_mode, // VkPresentModeKHR presentMode - VK_TRUE, // VkBool32 clipped - old_swap_chain // VkSwapchainKHR oldSwapchain - }; - - if( vkCreateSwapchainKHR( Vulkan.Device, &swap_chain_create_info, nullptr, &Vulkan.SwapChain.Handle ) != VK_SUCCESS ) { - std::cout << "Could not create swap chain!" << std::endl; - return false; - } - if( old_swap_chain != VK_NULL_HANDLE ) { - vkDestroySwapchainKHR( Vulkan.Device, old_swap_chain, nullptr ); - } - - Vulkan.SwapChain.Format = desired_format.format; - - uint32_t image_count = 0; - if( (vkGetSwapchainImagesKHR( Vulkan.Device, Vulkan.SwapChain.Handle, &image_count, nullptr ) != VK_SUCCESS) || - (image_count == 0) ) { - std::cout << "Could not get swap chain images!" << std::endl; - return false; - } - Vulkan.SwapChain.Images.resize( image_count ); - - std::vector images( image_count ); - if( vkGetSwapchainImagesKHR( Vulkan.Device, Vulkan.SwapChain.Handle, &image_count, &images[0] ) != VK_SUCCESS ) { - std::cout << "Could not get swap chain images!" << std::endl; - return false; - } - - for( size_t i = 0; i < Vulkan.SwapChain.Images.size(); ++i ) { - Vulkan.SwapChain.Images[i].Handle = images[i]; - } - Vulkan.SwapChain.Extent = desired_extent; - - return CreateSwapChainImageViews(); - } - - bool VulkanCommon::CreateSwapChainImageViews() { - for( size_t i = 0; i < Vulkan.SwapChain.Images.size(); ++i ) { - VkImageViewCreateInfo image_view_create_info = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkImageViewCreateFlags flags - Vulkan.SwapChain.Images[i].Handle, // VkImage image - VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType - GetSwapChain().Format, // VkFormat format - { // VkComponentMapping components - VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle r - VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle g - VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle b - VK_COMPONENT_SWIZZLE_IDENTITY // VkComponentSwizzle a - }, - { // VkImageSubresourceRange subresourceRange - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - } - }; - - if( vkCreateImageView( GetDevice(), &image_view_create_info, nullptr, &Vulkan.SwapChain.Images[i].View ) != VK_SUCCESS ) { - std::cout << "Could not create image view for framebuffer!" << std::endl; - return false; - } - } - - CanRender = true; - - return true; - } - - bool VulkanCommon::CheckExtensionAvailability( const char *extension_name, const std::vector &available_extensions ) { - for( size_t i = 0; i < available_extensions.size(); ++i ) { - if( strcmp( available_extensions[i].extensionName, extension_name ) == 0 ) { - return true; - } - } - return false; - } - - uint32_t VulkanCommon::GetSwapChainNumImages( VkSurfaceCapabilitiesKHR &surface_capabilities ) { - // Set of images defined in a swap chain may not always be available for application to render to: - // One may be displayed and one may wait in a queue to be presented - // If application wants to use more images at the same time it must ask for more images - uint32_t image_count = surface_capabilities.minImageCount + 1; - if( (surface_capabilities.maxImageCount > 0) && - (image_count > surface_capabilities.maxImageCount) ) { - image_count = surface_capabilities.maxImageCount; - } - return image_count; - } - - VkSurfaceFormatKHR VulkanCommon::GetSwapChainFormat( std::vector &surface_formats ) { - // If the list contains only one entry with undefined format - // it means that there are no preferred surface formats and any can be chosen - if( (surface_formats.size() == 1) && - (surface_formats[0].format == VK_FORMAT_UNDEFINED) ) { - return{ VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR }; - } - - // Check if list contains most widely used R8 G8 B8 A8 format - // with nonlinear color space - for( VkSurfaceFormatKHR &surface_format : surface_formats ) { - if( surface_format.format == VK_FORMAT_R8G8B8A8_UNORM ) { - return surface_format; - } - } - - // Return the first format from the list - return surface_formats[0]; - } - - VkExtent2D VulkanCommon::GetSwapChainExtent( VkSurfaceCapabilitiesKHR &surface_capabilities ) { - // Special value of surface extent is width == height == -1 - // If this is so we define the size by ourselves but it must fit within defined confines - if( surface_capabilities.currentExtent.width == -1 ) { - VkExtent2D swap_chain_extent = { 640, 480 }; - if( swap_chain_extent.width < surface_capabilities.minImageExtent.width ) { - swap_chain_extent.width = surface_capabilities.minImageExtent.width; - } - if( swap_chain_extent.height < surface_capabilities.minImageExtent.height ) { - swap_chain_extent.height = surface_capabilities.minImageExtent.height; - } - if( swap_chain_extent.width > surface_capabilities.maxImageExtent.width ) { - swap_chain_extent.width = surface_capabilities.maxImageExtent.width; - } - if( swap_chain_extent.height > surface_capabilities.maxImageExtent.height ) { - swap_chain_extent.height = surface_capabilities.maxImageExtent.height; - } - return swap_chain_extent; - } - - // Most of the cases we define size of the swap_chain images equal to current window's size - return surface_capabilities.currentExtent; - } - - VkImageUsageFlags VulkanCommon::GetSwapChainUsageFlags( VkSurfaceCapabilitiesKHR &surface_capabilities ) { - // Color attachment flag must always be supported - // We can define other usage flags but we always need to check if they are supported - if( surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { - return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - } - std::cout << "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT image usage is not supported by the swap chain!" << std::endl - << "Supported swap chain's image usages include:" << std::endl - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT ? " VK_IMAGE_USAGE_TRANSFER_SRC\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT ? " VK_IMAGE_USAGE_TRANSFER_DST\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT ? " VK_IMAGE_USAGE_SAMPLED\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT ? " VK_IMAGE_USAGE_STORAGE\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_COLOR_ATTACHMENT\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_INPUT_ATTACHMENT" : "") - << std::endl; - return static_cast(-1); - } - - VkSurfaceTransformFlagBitsKHR VulkanCommon::GetSwapChainTransform( VkSurfaceCapabilitiesKHR &surface_capabilities ) { - // Sometimes images must be transformed before they are presented (i.e. due to device's orienation - // being other than default orientation) - // If the specified transform is other than current transform, presentation engine will transform image - // during presentation operation; this operation may hit performance on some platforms - // Here we don't want any transformations to occur so if the identity transform is supported use it - // otherwise just use the same transform as current transform - if( surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ) { - return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - } else { - return surface_capabilities.currentTransform; - } - } - - VkPresentModeKHR VulkanCommon::GetSwapChainPresentMode( std::vector &present_modes ) { - // FIFO present mode is always available - // MAILBOX is the lowest latency V-Sync enabled mode (something like triple-buffering) so use it if available - for( VkPresentModeKHR &present_mode : present_modes ) { - if( present_mode == VK_PRESENT_MODE_MAILBOX_KHR ) { - return present_mode; - } - } - for( VkPresentModeKHR &present_mode : present_modes ) { - if( present_mode == VK_PRESENT_MODE_FIFO_KHR ) { - return present_mode; - } - } - std::cout << "FIFO present mode is not supported by the swap chain!" << std::endl; - return static_cast(-1); - } - - VulkanCommon::~VulkanCommon() { - if( Vulkan.Device != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( Vulkan.Device ); - - for( size_t i = 0; i < Vulkan.SwapChain.Images.size(); ++i ) { - if( Vulkan.SwapChain.Images[i].View != VK_NULL_HANDLE ) { - vkDestroyImageView( GetDevice(), Vulkan.SwapChain.Images[i].View, nullptr ); - } - } - - if( Vulkan.SwapChain.Handle != VK_NULL_HANDLE ) { - vkDestroySwapchainKHR( Vulkan.Device, Vulkan.SwapChain.Handle, nullptr ); - } - vkDestroyDevice( Vulkan.Device, nullptr ); - } - - if( Vulkan.PresentationSurface != VK_NULL_HANDLE ) { - vkDestroySurfaceKHR( Vulkan.Instance, Vulkan.PresentationSurface, nullptr ); - } - - if( Vulkan.Instance != VK_NULL_HANDLE ) { - vkDestroyInstance( Vulkan.Instance, nullptr ); - } - - if( VulkanLibrary ) { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - FreeLibrary( VulkanLibrary ); -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - dlclose( VulkanLibrary ); -#endif - } - } - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "VulkanCommon.h" +#include "VulkanFunctions.h" + +namespace ApiWithoutSecrets { + + VulkanCommon::VulkanCommon() : + VulkanLibrary(), + Window(), + Vulkan() { + } + + bool VulkanCommon::PrepareVulkan( OS::WindowParameters parameters ) { + Window = parameters; + + if( !LoadVulkanLibrary() ) { + return false; + } + if( !LoadExportedEntryPoints() ) { + return false; + } + if( !LoadGlobalLevelEntryPoints() ) { + return false; + } + if( !CreateInstance() ) { + return false; + } + if( !LoadInstanceLevelEntryPoints() ) { + return false; + } + if( !CreatePresentationSurface() ) { + return false; + } + if( !CreateDevice() ) { + return false; + } + if( !LoadDeviceLevelEntryPoints() ) { + return false; + } + if( !GetDeviceQueue() ) { + return false; + } + if( !CreateSwapChain() ) { + return false; + } + return true; + } + + bool VulkanCommon::OnWindowSizeChanged() { + ChildClear(); + + if( CreateSwapChain() ) { + if( CanRender ) { + return ChildOnWindowSizeChanged(); + } + return true; + } + + return false; + } + + VkPhysicalDevice VulkanCommon::GetPhysicalDevice() const { + return Vulkan.PhysicalDevice; + } + + VkDevice VulkanCommon::GetDevice() const { + return Vulkan.Device; + } + + const QueueParameters VulkanCommon::GetGraphicsQueue() const { + return Vulkan.GraphicsQueue; + } + + const QueueParameters VulkanCommon::GetPresentQueue() const { + return Vulkan.PresentQueue; + } + + const SwapChainParameters VulkanCommon::GetSwapChain() const { + return Vulkan.SwapChain; + } + + bool VulkanCommon::LoadVulkanLibrary() { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + VulkanLibrary = LoadLibrary( "vulkan-1.dll" ); +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + VulkanLibrary = dlopen( "libvulkan.so.1", RTLD_NOW ); +#endif + + if( VulkanLibrary == nullptr ) { + std::cout << "Could not load Vulkan library!" << std::endl; + return false; + } + return true; + } + + bool VulkanCommon::LoadExportedEntryPoints() { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + #define LoadProcAddress GetProcAddress +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + #define LoadProcAddress dlsym +#endif + +#define VK_EXPORTED_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)LoadProcAddress( VulkanLibrary, #fun )) ) { \ + std::cout << "Could not load exported function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool VulkanCommon::LoadGlobalLevelEntryPoints() { +#define VK_GLOBAL_LEVEL_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( nullptr, #fun )) ) { \ + std::cout << "Could not load global level function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool VulkanCommon::CreateInstance() { + uint32_t extensions_count = 0; + if( (vkEnumerateInstanceExtensionProperties( nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || + (extensions_count == 0) ) { + std::cout << "Error occurred during instance extensions enumeration!" << std::endl; + return false; + } + + std::vector available_extensions( extensions_count ); + if( vkEnumerateInstanceExtensionProperties( nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during instance extensions enumeration!" << std::endl; + return false; + } + + std::vector extensions = { + VK_KHR_SURFACE_EXTENSION_NAME, +#if defined(VK_USE_PLATFORM_WIN32_KHR) + VK_KHR_WIN32_SURFACE_EXTENSION_NAME +#elif defined(VK_USE_PLATFORM_XCB_KHR) + VK_KHR_XCB_SURFACE_EXTENSION_NAME +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + VK_KHR_XLIB_SURFACE_EXTENSION_NAME +#endif + }; + + for( size_t i = 0; i < extensions.size(); ++i ) { + if( !CheckExtensionAvailability( extensions[i], available_extensions ) ) { + std::cout << "Could not find instance extension named \"" << extensions[i] << "\"!" << std::endl; + return false; + } + } + + VkApplicationInfo application_info = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType + nullptr, // const void *pNext + "API without Secrets: Introduction to Vulkan", // const char *pApplicationName + VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t applicationVersion + "Vulkan Tutorial by Intel", // const char *pEngineName + VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t engineVersion + VK_MAKE_VERSION( 1, 0, 0 ) // uint32_t apiVersion + }; + + VkInstanceCreateInfo instance_create_info = { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkInstanceCreateFlags flags + &application_info, // const VkApplicationInfo *pApplicationInfo + 0, // uint32_t enabledLayerCount + nullptr, // const char * const *ppEnabledLayerNames + static_cast(extensions.size()), // uint32_t enabledExtensionCount + &extensions[0] // const char * const *ppEnabledExtensionNames + }; + + if( vkCreateInstance( &instance_create_info, nullptr, &Vulkan.Instance ) != VK_SUCCESS ) { + std::cout << "Could not create Vulkan instance!" << std::endl; + return false; + } + return true; + } + + bool VulkanCommon::LoadInstanceLevelEntryPoints() { +#define VK_INSTANCE_LEVEL_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( Vulkan.Instance, #fun )) ) { \ + std::cout << "Could not load instance level function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool VulkanCommon::CreatePresentationSurface() { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + VkWin32SurfaceCreateInfoKHR surface_create_info = { + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkWin32SurfaceCreateFlagsKHR flags + Window.Instance, // HINSTANCE hinstance + Window.Handle // HWND hwnd + }; + + if( vkCreateWin32SurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { + return true; + } + +#elif defined(VK_USE_PLATFORM_XCB_KHR) + VkXcbSurfaceCreateInfoKHR surface_create_info = { + VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkXcbSurfaceCreateFlagsKHR flags + Window.Connection, // xcb_connection_t *connection + Window.Handle // xcb_window_t window + }; + + if( vkCreateXcbSurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { + return true; + } + +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + VkXlibSurfaceCreateInfoKHR surface_create_info = { + VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkXlibSurfaceCreateFlagsKHR flags + Window.DisplayPtr, // Display *dpy + Window.Handle // Window window + }; + if( vkCreateXlibSurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { + return true; + } + +#endif + + std::cout << "Could not create presentation surface!" << std::endl; + return false; + } + + bool VulkanCommon::CreateDevice() { + uint32_t num_devices = 0; + if( (vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, nullptr ) != VK_SUCCESS) || + (num_devices == 0) ) { + std::cout << "Error occurred during physical devices enumeration!" << std::endl; + return false; + } + + std::vector physical_devices( num_devices ); + if( vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, &physical_devices[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during physical devices enumeration!" << std::endl; + return false; + } + + uint32_t selected_graphics_queue_family_index = UINT32_MAX; + uint32_t selected_present_queue_family_index = UINT32_MAX; + + for( uint32_t i = 0; i < num_devices; ++i ) { + if( CheckPhysicalDeviceProperties( physical_devices[i], selected_graphics_queue_family_index, selected_present_queue_family_index ) ) { + Vulkan.PhysicalDevice = physical_devices[i]; + break; + } + } + if( Vulkan.PhysicalDevice == VK_NULL_HANDLE ) { + std::cout << "Could not select physical device based on the chosen properties!" << std::endl; + return false; + } + + std::vector queue_create_infos; + std::vector queue_priorities = { 1.0f }; + + queue_create_infos.push_back( { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDeviceQueueCreateFlags flags + selected_graphics_queue_family_index, // uint32_t queueFamilyIndex + static_cast(queue_priorities.size()), // uint32_t queueCount + &queue_priorities[0] // const float *pQueuePriorities + } ); + + if( selected_graphics_queue_family_index != selected_present_queue_family_index ) { + queue_create_infos.push_back( { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDeviceQueueCreateFlags flags + selected_present_queue_family_index, // uint32_t queueFamilyIndex + static_cast(queue_priorities.size()), // uint32_t queueCount + &queue_priorities[0] // const float *pQueuePriorities + } ); + } + + std::vector extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME + }; + + VkDeviceCreateInfo device_create_info = { + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDeviceCreateFlags flags + static_cast(queue_create_infos.size()), // uint32_t queueCreateInfoCount + &queue_create_infos[0], // const VkDeviceQueueCreateInfo *pQueueCreateInfos + 0, // uint32_t enabledLayerCount + nullptr, // const char * const *ppEnabledLayerNames + static_cast(extensions.size()), // uint32_t enabledExtensionCount + &extensions[0], // const char * const *ppEnabledExtensionNames + nullptr // const VkPhysicalDeviceFeatures *pEnabledFeatures + }; + + if( vkCreateDevice( Vulkan.PhysicalDevice, &device_create_info, nullptr, &Vulkan.Device ) != VK_SUCCESS ) { + std::cout << "Could not create Vulkan device!" << std::endl; + return false; + } + + Vulkan.GraphicsQueue.FamilyIndex = selected_graphics_queue_family_index; + Vulkan.PresentQueue.FamilyIndex = selected_present_queue_family_index; + return true; + } + + bool VulkanCommon::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &selected_graphics_queue_family_index, uint32_t &selected_present_queue_family_index ) { + uint32_t extensions_count = 0; + if( (vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || + (extensions_count == 0) ) { + std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; + return false; + } + + std::vector available_extensions( extensions_count ); + if( vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; + return false; + } + + std::vector device_extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME + }; + + for( size_t i = 0; i < device_extensions.size(); ++i ) { + if( !CheckExtensionAvailability( device_extensions[i], available_extensions ) ) { + std::cout << "Physical device " << physical_device << " doesn't support extension named \"" << device_extensions[i] << "\"!" << std::endl; + return false; + } + } + + VkPhysicalDeviceProperties device_properties; + VkPhysicalDeviceFeatures device_features; + + vkGetPhysicalDeviceProperties( physical_device, &device_properties ); + vkGetPhysicalDeviceFeatures( physical_device, &device_features ); + + uint32_t major_version = VK_VERSION_MAJOR( device_properties.apiVersion ); + + if( (major_version < 1) || + (device_properties.limits.maxImageDimension2D < 4096) ) { + std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; + return false; + } + + uint32_t queue_families_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); + if( queue_families_count == 0 ) { + std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; + return false; + } + + std::vector queue_family_properties( queue_families_count ); + std::vector queue_present_support( queue_families_count ); + + vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_family_properties[0] ); + + uint32_t graphics_queue_family_index = UINT32_MAX; + uint32_t present_queue_family_index = UINT32_MAX; + + for( uint32_t i = 0; i < queue_families_count; ++i ) { + vkGetPhysicalDeviceSurfaceSupportKHR( physical_device, i, Vulkan.PresentationSurface, &queue_present_support[i] ); + + if( (queue_family_properties[i].queueCount > 0) && + (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { + // Select first queue that supports graphics + if( graphics_queue_family_index == UINT32_MAX ) { + graphics_queue_family_index = i; + } + + // If there is queue that supports both graphics and present - prefer it + if( queue_present_support[i] ) { + selected_graphics_queue_family_index = i; + selected_present_queue_family_index = i; + return true; + } + } + } + + // We don't have queue that supports both graphics and present so we have to use separate queues + for( uint32_t i = 0; i < queue_families_count; ++i ) { + if( queue_present_support[i] ) { + present_queue_family_index = i; + break; + } + } + + // If this device doesn't support queues with graphics and present capabilities don't use it + if( (graphics_queue_family_index == UINT32_MAX) || + (present_queue_family_index == UINT32_MAX) ) { + std::cout << "Could not find queue families with required properties on physical device " << physical_device << "!" << std::endl; + return false; + } + + selected_graphics_queue_family_index = graphics_queue_family_index; + selected_present_queue_family_index = present_queue_family_index; + return true; + } + + bool VulkanCommon::LoadDeviceLevelEntryPoints() { +#define VK_DEVICE_LEVEL_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)vkGetDeviceProcAddr( Vulkan.Device, #fun )) ) { \ + std::cout << "Could not load device level function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool VulkanCommon::GetDeviceQueue() { + vkGetDeviceQueue( Vulkan.Device, Vulkan.GraphicsQueue.FamilyIndex, 0, &Vulkan.GraphicsQueue.Handle ); + vkGetDeviceQueue( Vulkan.Device, Vulkan.PresentQueue.FamilyIndex, 0, &Vulkan.PresentQueue.Handle ); + return true; + } + + bool VulkanCommon::CreateSwapChain() { + CanRender = false; + + if( Vulkan.Device != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( Vulkan.Device ); + } + + for( size_t i = 0; i < Vulkan.SwapChain.Images.size(); ++i ) { + if( Vulkan.SwapChain.Images[i].View != VK_NULL_HANDLE ) { + vkDestroyImageView( GetDevice(), Vulkan.SwapChain.Images[i].View, nullptr ); + Vulkan.SwapChain.Images[i].View = VK_NULL_HANDLE; + } + } + Vulkan.SwapChain.Images.clear(); + + VkSurfaceCapabilitiesKHR surface_capabilities; + if( vkGetPhysicalDeviceSurfaceCapabilitiesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &surface_capabilities ) != VK_SUCCESS ) { + std::cout << "Could not check presentation surface capabilities!" << std::endl; + return false; + } + + uint32_t formats_count; + if( (vkGetPhysicalDeviceSurfaceFormatsKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &formats_count, nullptr ) != VK_SUCCESS) || + (formats_count == 0) ) { + std::cout << "Error occurred during presentation surface formats enumeration!" << std::endl; + return false; + } + + std::vector surface_formats( formats_count ); + if( vkGetPhysicalDeviceSurfaceFormatsKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &formats_count, &surface_formats[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during presentation surface formats enumeration!" << std::endl; + return false; + } + + uint32_t present_modes_count; + if( (vkGetPhysicalDeviceSurfacePresentModesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &present_modes_count, nullptr ) != VK_SUCCESS) || + (present_modes_count == 0) ) { + std::cout << "Error occurred during presentation surface present modes enumeration!" << std::endl; + return false; + } + + std::vector present_modes( present_modes_count ); + if( vkGetPhysicalDeviceSurfacePresentModesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &present_modes_count, &present_modes[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during presentation surface present modes enumeration!" << std::endl; + return false; + } + + uint32_t desired_number_of_images = GetSwapChainNumImages( surface_capabilities ); + VkSurfaceFormatKHR desired_format = GetSwapChainFormat( surface_formats ); + VkExtent2D desired_extent = GetSwapChainExtent( surface_capabilities ); + VkImageUsageFlags desired_usage = GetSwapChainUsageFlags( surface_capabilities ); + VkSurfaceTransformFlagBitsKHR desired_transform = GetSwapChainTransform( surface_capabilities ); + VkPresentModeKHR desired_present_mode = GetSwapChainPresentMode( present_modes ); + VkSwapchainKHR old_swap_chain = Vulkan.SwapChain.Handle; + + if( static_cast(desired_usage) == -1 ) { + return false; + } + if( static_cast(desired_present_mode) == -1 ) { + return false; + } + if( (desired_extent.width == 0) || (desired_extent.height == 0) ) { + // Current surface size is (0, 0) so we can't create a swap chain and render anything (CanRender == false) + // But we don't wont to kill the application as this situation may occur i.e. when window gets minimized + return true; + } + + VkSwapchainCreateInfoKHR swap_chain_create_info = { + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkSwapchainCreateFlagsKHR flags + Vulkan.PresentationSurface, // VkSurfaceKHR surface + desired_number_of_images, // uint32_t minImageCount + desired_format.format, // VkFormat imageFormat + desired_format.colorSpace, // VkColorSpaceKHR imageColorSpace + desired_extent, // VkExtent2D imageExtent + 1, // uint32_t imageArrayLayers + desired_usage, // VkImageUsageFlags imageUsage + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode + 0, // uint32_t queueFamilyIndexCount + nullptr, // const uint32_t *pQueueFamilyIndices + desired_transform, // VkSurfaceTransformFlagBitsKHR preTransform + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, // VkCompositeAlphaFlagBitsKHR compositeAlpha + desired_present_mode, // VkPresentModeKHR presentMode + VK_TRUE, // VkBool32 clipped + old_swap_chain // VkSwapchainKHR oldSwapchain + }; + + if( vkCreateSwapchainKHR( Vulkan.Device, &swap_chain_create_info, nullptr, &Vulkan.SwapChain.Handle ) != VK_SUCCESS ) { + std::cout << "Could not create swap chain!" << std::endl; + return false; + } + if( old_swap_chain != VK_NULL_HANDLE ) { + vkDestroySwapchainKHR( Vulkan.Device, old_swap_chain, nullptr ); + } + + Vulkan.SwapChain.Format = desired_format.format; + + uint32_t image_count = 0; + if( (vkGetSwapchainImagesKHR( Vulkan.Device, Vulkan.SwapChain.Handle, &image_count, nullptr ) != VK_SUCCESS) || + (image_count == 0) ) { + std::cout << "Could not get swap chain images!" << std::endl; + return false; + } + Vulkan.SwapChain.Images.resize( image_count ); + + std::vector images( image_count ); + if( vkGetSwapchainImagesKHR( Vulkan.Device, Vulkan.SwapChain.Handle, &image_count, &images[0] ) != VK_SUCCESS ) { + std::cout << "Could not get swap chain images!" << std::endl; + return false; + } + + for( size_t i = 0; i < Vulkan.SwapChain.Images.size(); ++i ) { + Vulkan.SwapChain.Images[i].Handle = images[i]; + } + Vulkan.SwapChain.Extent = desired_extent; + + return CreateSwapChainImageViews(); + } + + bool VulkanCommon::CreateSwapChainImageViews() { + for( size_t i = 0; i < Vulkan.SwapChain.Images.size(); ++i ) { + VkImageViewCreateInfo image_view_create_info = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkImageViewCreateFlags flags + Vulkan.SwapChain.Images[i].Handle, // VkImage image + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType + GetSwapChain().Format, // VkFormat format + { // VkComponentMapping components + VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle r + VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle g + VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle b + VK_COMPONENT_SWIZZLE_IDENTITY // VkComponentSwizzle a + }, + { // VkImageSubresourceRange subresourceRange + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + } + }; + + if( vkCreateImageView( GetDevice(), &image_view_create_info, nullptr, &Vulkan.SwapChain.Images[i].View ) != VK_SUCCESS ) { + std::cout << "Could not create image view for framebuffer!" << std::endl; + return false; + } + } + + CanRender = true; + + return true; + } + + bool VulkanCommon::CheckExtensionAvailability( const char *extension_name, const std::vector &available_extensions ) { + for( size_t i = 0; i < available_extensions.size(); ++i ) { + if( strcmp( available_extensions[i].extensionName, extension_name ) == 0 ) { + return true; + } + } + return false; + } + + uint32_t VulkanCommon::GetSwapChainNumImages( VkSurfaceCapabilitiesKHR &surface_capabilities ) { + // Set of images defined in a swap chain may not always be available for application to render to: + // One may be displayed and one may wait in a queue to be presented + // If application wants to use more images at the same time it must ask for more images + uint32_t image_count = surface_capabilities.minImageCount + 1; + if( (surface_capabilities.maxImageCount > 0) && + (image_count > surface_capabilities.maxImageCount) ) { + image_count = surface_capabilities.maxImageCount; + } + return image_count; + } + + VkSurfaceFormatKHR VulkanCommon::GetSwapChainFormat( std::vector &surface_formats ) { + // If the list contains only one entry with undefined format + // it means that there are no preferred surface formats and any can be chosen + if( (surface_formats.size() == 1) && + (surface_formats[0].format == VK_FORMAT_UNDEFINED) ) { + return{ VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR }; + } + + // Check if list contains most widely used R8 G8 B8 A8 format + // with nonlinear color space + for( VkSurfaceFormatKHR &surface_format : surface_formats ) { + if( surface_format.format == VK_FORMAT_R8G8B8A8_UNORM ) { + return surface_format; + } + } + + // Return the first format from the list + return surface_formats[0]; + } + + VkExtent2D VulkanCommon::GetSwapChainExtent( VkSurfaceCapabilitiesKHR &surface_capabilities ) { + // Special value of surface extent is width == height == -1 + // If this is so we define the size by ourselves but it must fit within defined confines + if( surface_capabilities.currentExtent.width == -1 ) { + VkExtent2D swap_chain_extent = { 640, 480 }; + if( swap_chain_extent.width < surface_capabilities.minImageExtent.width ) { + swap_chain_extent.width = surface_capabilities.minImageExtent.width; + } + if( swap_chain_extent.height < surface_capabilities.minImageExtent.height ) { + swap_chain_extent.height = surface_capabilities.minImageExtent.height; + } + if( swap_chain_extent.width > surface_capabilities.maxImageExtent.width ) { + swap_chain_extent.width = surface_capabilities.maxImageExtent.width; + } + if( swap_chain_extent.height > surface_capabilities.maxImageExtent.height ) { + swap_chain_extent.height = surface_capabilities.maxImageExtent.height; + } + return swap_chain_extent; + } + + // Most of the cases we define size of the swap_chain images equal to current window's size + return surface_capabilities.currentExtent; + } + + VkImageUsageFlags VulkanCommon::GetSwapChainUsageFlags( VkSurfaceCapabilitiesKHR &surface_capabilities ) { + // Color attachment flag must always be supported + // We can define other usage flags but we always need to check if they are supported + if( surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { + return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + std::cout << "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT image usage is not supported by the swap chain!" << std::endl + << "Supported swap chain's image usages include:" << std::endl + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT ? " VK_IMAGE_USAGE_TRANSFER_SRC\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT ? " VK_IMAGE_USAGE_TRANSFER_DST\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT ? " VK_IMAGE_USAGE_SAMPLED\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT ? " VK_IMAGE_USAGE_STORAGE\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_COLOR_ATTACHMENT\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_INPUT_ATTACHMENT" : "") + << std::endl; + return static_cast(-1); + } + + VkSurfaceTransformFlagBitsKHR VulkanCommon::GetSwapChainTransform( VkSurfaceCapabilitiesKHR &surface_capabilities ) { + // Sometimes images must be transformed before they are presented (i.e. due to device's orienation + // being other than default orientation) + // If the specified transform is other than current transform, presentation engine will transform image + // during presentation operation; this operation may hit performance on some platforms + // Here we don't want any transformations to occur so if the identity transform is supported use it + // otherwise just use the same transform as current transform + if( surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ) { + return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + } else { + return surface_capabilities.currentTransform; + } + } + + VkPresentModeKHR VulkanCommon::GetSwapChainPresentMode( std::vector &present_modes ) { + // FIFO present mode is always available + // MAILBOX is the lowest latency V-Sync enabled mode (something like triple-buffering) so use it if available + for( VkPresentModeKHR &present_mode : present_modes ) { + if( present_mode == VK_PRESENT_MODE_MAILBOX_KHR ) { + return present_mode; + } + } + for( VkPresentModeKHR &present_mode : present_modes ) { + if( present_mode == VK_PRESENT_MODE_FIFO_KHR ) { + return present_mode; + } + } + std::cout << "FIFO present mode is not supported by the swap chain!" << std::endl; + return static_cast(-1); + } + + VulkanCommon::~VulkanCommon() { + if( Vulkan.Device != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( Vulkan.Device ); + + for( size_t i = 0; i < Vulkan.SwapChain.Images.size(); ++i ) { + if( Vulkan.SwapChain.Images[i].View != VK_NULL_HANDLE ) { + vkDestroyImageView( GetDevice(), Vulkan.SwapChain.Images[i].View, nullptr ); + } + } + + if( Vulkan.SwapChain.Handle != VK_NULL_HANDLE ) { + vkDestroySwapchainKHR( Vulkan.Device, Vulkan.SwapChain.Handle, nullptr ); + } + vkDestroyDevice( Vulkan.Device, nullptr ); + } + + if( Vulkan.PresentationSurface != VK_NULL_HANDLE ) { + vkDestroySurfaceKHR( Vulkan.Instance, Vulkan.PresentationSurface, nullptr ); + } + + if( Vulkan.Instance != VK_NULL_HANDLE ) { + vkDestroyInstance( Vulkan.Instance, nullptr ); + } + + if( VulkanLibrary ) { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + FreeLibrary( VulkanLibrary ); +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + dlclose( VulkanLibrary ); +#endif + } + } + } // namespace ApiWithoutSecrets \ No newline at end of file diff --git a/Project/Common/VulkanCommon.h b/Project/Common/VulkanCommon.h index 3529e30..9b00a71 100644 --- a/Project/Common/VulkanCommon.h +++ b/Project/Common/VulkanCommon.h @@ -1,157 +1,157 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(VULKAN_COMMON_HEADER) -#define VULKAN_COMMON_HEADER - -#include -#include "vulkan.h" -#include "OperatingSystem.h" - -namespace ApiWithoutSecrets { - - // ************************************************************ // - // QueueParameters // - // // - // Vulkan Queue's parameters container class // - // ************************************************************ // - struct QueueParameters { - VkQueue Handle; - uint32_t FamilyIndex; - - QueueParameters() : - Handle( VK_NULL_HANDLE ), - FamilyIndex( 0 ) { - } - }; - - // ************************************************************ // - // ImageParameters // - // // - // Vulkan Image's parameters container class // - // ************************************************************ // - struct ImageParameters { - VkImage Handle; - VkImageView View; - VkSampler Sampler; - VkDeviceMemory Memory; - - ImageParameters() : - Handle( VK_NULL_HANDLE ), - View( VK_NULL_HANDLE ), - Sampler( VK_NULL_HANDLE ), - Memory( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // SwapChainParameters // - // // - // Vulkan SwapChain's parameters container class // - // ************************************************************ // - struct SwapChainParameters { - VkSwapchainKHR Handle; - VkFormat Format; - std::vector Images; - VkExtent2D Extent; - - SwapChainParameters() : - Handle( VK_NULL_HANDLE ), - Format( VK_FORMAT_UNDEFINED ), - Images(), - Extent() { - } - }; - - // ************************************************************ // - // VulkanCommonParameters // - // // - // General Vulkan parameters' container class // - // ************************************************************ // - struct VulkanCommonParameters { - VkInstance Instance; - VkPhysicalDevice PhysicalDevice; - VkDevice Device; - QueueParameters GraphicsQueue; - QueueParameters PresentQueue; - VkSurfaceKHR PresentationSurface; - SwapChainParameters SwapChain; - - VulkanCommonParameters() : - Instance( VK_NULL_HANDLE ), - PhysicalDevice( VK_NULL_HANDLE ), - Device( VK_NULL_HANDLE ), - GraphicsQueue(), - PresentQueue(), - PresentationSurface( VK_NULL_HANDLE ), - SwapChain() { - } - }; - - // ************************************************************ // - // VulkanCommon // - // // - // Base class for Vulkan more advanced tutorial classes // - // ************************************************************ // - class VulkanCommon : public OS::TutorialBase { - public: - VulkanCommon(); - virtual ~VulkanCommon(); - - bool PrepareVulkan( OS::WindowParameters parameters ); - virtual bool OnWindowSizeChanged() final override; - - protected: - VkPhysicalDevice GetPhysicalDevice() const; - VkDevice GetDevice() const; - - const QueueParameters GetGraphicsQueue() const; - const QueueParameters GetPresentQueue() const; - - const SwapChainParameters GetSwapChain() const; - - private: - OS::LibraryHandle VulkanLibrary; - OS::WindowParameters Window; - VulkanCommonParameters Vulkan; - - bool LoadVulkanLibrary(); - bool LoadExportedEntryPoints(); - bool LoadGlobalLevelEntryPoints(); - bool CreateInstance(); - bool LoadInstanceLevelEntryPoints(); - bool CreatePresentationSurface(); - bool CreateDevice(); - bool CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &graphics_queue_family_index, uint32_t &present_queue_family_index ); - bool LoadDeviceLevelEntryPoints(); - bool GetDeviceQueue(); - bool CreateSwapChain(); - bool CreateSwapChainImageViews(); - virtual bool ChildOnWindowSizeChanged() = 0; - virtual void ChildClear() = 0; - - bool CheckExtensionAvailability( const char *extension_name, const std::vector &available_extensions ); - uint32_t GetSwapChainNumImages( VkSurfaceCapabilitiesKHR &surface_capabilities ); - VkSurfaceFormatKHR GetSwapChainFormat( std::vector &surface_formats ); - VkExtent2D GetSwapChainExtent( VkSurfaceCapabilitiesKHR &surface_capabilities ); - VkImageUsageFlags GetSwapChainUsageFlags( VkSurfaceCapabilitiesKHR &surface_capabilities ); - VkSurfaceTransformFlagBitsKHR GetSwapChainTransform( VkSurfaceCapabilitiesKHR &surface_capabilities ); - VkPresentModeKHR GetSwapChainPresentMode( std::vector &present_modes ); - }; - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(VULKAN_COMMON_HEADER) +#define VULKAN_COMMON_HEADER + +#include +#include "vulkan.h" +#include "OperatingSystem.h" + +namespace ApiWithoutSecrets { + + // ************************************************************ // + // QueueParameters // + // // + // Vulkan Queue's parameters container class // + // ************************************************************ // + struct QueueParameters { + VkQueue Handle; + uint32_t FamilyIndex; + + QueueParameters() : + Handle( VK_NULL_HANDLE ), + FamilyIndex( 0 ) { + } + }; + + // ************************************************************ // + // ImageParameters // + // // + // Vulkan Image's parameters container class // + // ************************************************************ // + struct ImageParameters { + VkImage Handle; + VkImageView View; + VkSampler Sampler; + VkDeviceMemory Memory; + + ImageParameters() : + Handle( VK_NULL_HANDLE ), + View( VK_NULL_HANDLE ), + Sampler( VK_NULL_HANDLE ), + Memory( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // SwapChainParameters // + // // + // Vulkan SwapChain's parameters container class // + // ************************************************************ // + struct SwapChainParameters { + VkSwapchainKHR Handle; + VkFormat Format; + std::vector Images; + VkExtent2D Extent; + + SwapChainParameters() : + Handle( VK_NULL_HANDLE ), + Format( VK_FORMAT_UNDEFINED ), + Images(), + Extent() { + } + }; + + // ************************************************************ // + // VulkanCommonParameters // + // // + // General Vulkan parameters' container class // + // ************************************************************ // + struct VulkanCommonParameters { + VkInstance Instance; + VkPhysicalDevice PhysicalDevice; + VkDevice Device; + QueueParameters GraphicsQueue; + QueueParameters PresentQueue; + VkSurfaceKHR PresentationSurface; + SwapChainParameters SwapChain; + + VulkanCommonParameters() : + Instance( VK_NULL_HANDLE ), + PhysicalDevice( VK_NULL_HANDLE ), + Device( VK_NULL_HANDLE ), + GraphicsQueue(), + PresentQueue(), + PresentationSurface( VK_NULL_HANDLE ), + SwapChain() { + } + }; + + // ************************************************************ // + // VulkanCommon // + // // + // Base class for Vulkan more advanced tutorial classes // + // ************************************************************ // + class VulkanCommon : public OS::TutorialBase { + public: + VulkanCommon(); + virtual ~VulkanCommon(); + + bool PrepareVulkan( OS::WindowParameters parameters ); + virtual bool OnWindowSizeChanged() final override; + + protected: + VkPhysicalDevice GetPhysicalDevice() const; + VkDevice GetDevice() const; + + const QueueParameters GetGraphicsQueue() const; + const QueueParameters GetPresentQueue() const; + + const SwapChainParameters GetSwapChain() const; + + private: + OS::LibraryHandle VulkanLibrary; + OS::WindowParameters Window; + VulkanCommonParameters Vulkan; + + bool LoadVulkanLibrary(); + bool LoadExportedEntryPoints(); + bool LoadGlobalLevelEntryPoints(); + bool CreateInstance(); + bool LoadInstanceLevelEntryPoints(); + bool CreatePresentationSurface(); + bool CreateDevice(); + bool CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &graphics_queue_family_index, uint32_t &present_queue_family_index ); + bool LoadDeviceLevelEntryPoints(); + bool GetDeviceQueue(); + bool CreateSwapChain(); + bool CreateSwapChainImageViews(); + virtual bool ChildOnWindowSizeChanged() = 0; + virtual void ChildClear() = 0; + + bool CheckExtensionAvailability( const char *extension_name, const std::vector &available_extensions ); + uint32_t GetSwapChainNumImages( VkSurfaceCapabilitiesKHR &surface_capabilities ); + VkSurfaceFormatKHR GetSwapChainFormat( std::vector &surface_formats ); + VkExtent2D GetSwapChainExtent( VkSurfaceCapabilitiesKHR &surface_capabilities ); + VkImageUsageFlags GetSwapChainUsageFlags( VkSurfaceCapabilitiesKHR &surface_capabilities ); + VkSurfaceTransformFlagBitsKHR GetSwapChainTransform( VkSurfaceCapabilitiesKHR &surface_capabilities ); + VkPresentModeKHR GetSwapChainPresentMode( std::vector &present_modes ); + }; + +} // namespace ApiWithoutSecrets + #endif // VULKAN_COMMON_HEADER \ No newline at end of file diff --git a/Project/Common/VulkanFunctions.cpp b/Project/Common/VulkanFunctions.cpp index a136d9e..03af242 100644 --- a/Project/Common/VulkanFunctions.cpp +++ b/Project/Common/VulkanFunctions.cpp @@ -1,28 +1,28 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "vulkan.h" - -namespace ApiWithoutSecrets { - -#define VK_EXPORTED_FUNCTION( fun ) PFN_##fun fun; -#define VK_GLOBAL_LEVEL_FUNCTION( fun ) PFN_##fun fun; -#define VK_INSTANCE_LEVEL_FUNCTION( fun ) PFN_##fun fun; -#define VK_DEVICE_LEVEL_FUNCTION( fun ) PFN_##fun fun; - -#include "ListOfFunctions.inl" - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "vulkan.h" + +namespace ApiWithoutSecrets { + +#define VK_EXPORTED_FUNCTION( fun ) PFN_##fun fun; +#define VK_GLOBAL_LEVEL_FUNCTION( fun ) PFN_##fun fun; +#define VK_INSTANCE_LEVEL_FUNCTION( fun ) PFN_##fun fun; +#define VK_DEVICE_LEVEL_FUNCTION( fun ) PFN_##fun fun; + +#include "ListOfFunctions.inl" + } // namespace ApiWithoutSecrets \ No newline at end of file diff --git a/Project/Common/VulkanFunctions.h b/Project/Common/VulkanFunctions.h index 11ea444..6656b3b 100644 --- a/Project/Common/VulkanFunctions.h +++ b/Project/Common/VulkanFunctions.h @@ -1,33 +1,33 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(VULKAN_FUNCTIONS_HEADER) -#define VULKAN_FUNCTIONS_HEADER - -#include "vulkan.h" - -namespace ApiWithoutSecrets { - -#define VK_EXPORTED_FUNCTION( fun ) extern PFN_##fun fun; -#define VK_GLOBAL_LEVEL_FUNCTION( fun) extern PFN_##fun fun; -#define VK_INSTANCE_LEVEL_FUNCTION( fun ) extern PFN_##fun fun; -#define VK_DEVICE_LEVEL_FUNCTION( fun ) extern PFN_##fun fun; - -#include "ListOfFunctions.inl" - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(VULKAN_FUNCTIONS_HEADER) +#define VULKAN_FUNCTIONS_HEADER + +#include "vulkan.h" + +namespace ApiWithoutSecrets { + +#define VK_EXPORTED_FUNCTION( fun ) extern PFN_##fun fun; +#define VK_GLOBAL_LEVEL_FUNCTION( fun) extern PFN_##fun fun; +#define VK_INSTANCE_LEVEL_FUNCTION( fun ) extern PFN_##fun fun; +#define VK_DEVICE_LEVEL_FUNCTION( fun ) extern PFN_##fun fun; + +#include "ListOfFunctions.inl" + +} // namespace ApiWithoutSecrets + #endif \ No newline at end of file diff --git a/Project/Tutorial01/Tutorial01.cpp b/Project/Tutorial01/Tutorial01.cpp index 06af1db..85ebee5 100644 --- a/Project/Tutorial01/Tutorial01.cpp +++ b/Project/Tutorial01/Tutorial01.cpp @@ -1,284 +1,284 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include -#include "Tutorial01.h" -#include "VulkanFunctions.h" - -namespace ApiWithoutSecrets { - - Tutorial01::Tutorial01() : - VulkanLibrary(), - Vulkan() { - } - - bool Tutorial01::OnWindowSizeChanged() { - return true; - } - - bool Tutorial01::Draw() { - return true; - } - - bool Tutorial01::PrepareVulkan() { - if( !LoadVulkanLibrary() ) { - return false; - } - if( !LoadExportedEntryPoints() ) { - return false; - } - if( !LoadGlobalLevelEntryPoints() ) { - return false; - } - if( !CreateInstance() ) { - return false; - } - if( !LoadInstanceLevelEntryPoints() ) { - return false; - } - if( !CreateDevice() ) { - return false; - } - if( !LoadDeviceLevelEntryPoints() ) { - return false; - } - if( !GetDeviceQueue() ) { - return false; - } - return true; - } - - bool Tutorial01::LoadVulkanLibrary() { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - VulkanLibrary = LoadLibrary( "vulkan-1.dll" ); -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - VulkanLibrary = dlopen( "libvulkan.so.1", RTLD_NOW ); -#endif - - if( VulkanLibrary == nullptr ) { - std::cout << "Could not load Vulkan library!" << std::endl; - return false; - } - return true; - } - - bool Tutorial01::LoadExportedEntryPoints() { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - #define LoadProcAddress GetProcAddress -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - #define LoadProcAddress dlsym -#endif - -#define VK_EXPORTED_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)LoadProcAddress( VulkanLibrary, #fun )) ) { \ - std::cout << "Could not load exported function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool Tutorial01::LoadGlobalLevelEntryPoints() { -#define VK_GLOBAL_LEVEL_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( nullptr, #fun )) ) { \ - std::cout << "Could not load global level function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool Tutorial01::CreateInstance() { - VkApplicationInfo application_info = { - VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType - nullptr, // const void *pNext - "API without Secrets: Introduction to Vulkan", // const char *pApplicationName - VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t applicationVersion - "Vulkan Tutorial by Intel", // const char *pEngineName - VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t engineVersion - VK_MAKE_VERSION( 1, 0, 0 ) // uint32_t apiVersion - }; - - VkInstanceCreateInfo instance_create_info = { - VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0, // VkInstanceCreateFlags flags - &application_info, // const VkApplicationInfo *pApplicationInfo - 0, // uint32_t enabledLayerCount - nullptr, // const char * const *ppEnabledLayerNames - 0, // uint32_t enabledExtensionCount - nullptr // const char * const *ppEnabledExtensionNames - }; - - if( vkCreateInstance( &instance_create_info, nullptr, &Vulkan.Instance ) != VK_SUCCESS ) { - std::cout << "Could not create Vulkan instance!" << std::endl; - return false; - } - return true; - } - - bool Tutorial01::LoadInstanceLevelEntryPoints() { -#define VK_INSTANCE_LEVEL_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( Vulkan.Instance, #fun )) ) { \ - std::cout << "Could not load instance level function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool Tutorial01::CreateDevice() { - uint32_t num_devices = 0; - if( (vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, nullptr ) != VK_SUCCESS) || - (num_devices == 0) ) { - std::cout << "Error occurred during physical devices enumeration!" << std::endl; - return false; - } - - std::vector physical_devices( num_devices ); - if( vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, &physical_devices[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during physical devices enumeration!" << std::endl; - return false; - } - - VkPhysicalDevice selected_physical_device = VK_NULL_HANDLE; - uint32_t selected_queue_family_index = UINT32_MAX; - for( uint32_t i = 0; i < num_devices; ++i ) { - if( CheckPhysicalDeviceProperties( physical_devices[i], selected_queue_family_index ) ) { - selected_physical_device = physical_devices[i]; - break; - } - } - if( selected_physical_device == VK_NULL_HANDLE ) { - std::cout << "Could not select physical device based on the chosen properties!" << std::endl; - return false; - } - - std::vector queue_priorities = { 1.0f }; - - VkDeviceQueueCreateInfo queue_create_info = { - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDeviceQueueCreateFlags flags - selected_queue_family_index, // uint32_t queueFamilyIndex - static_cast(queue_priorities.size()), // uint32_t queueCount - &queue_priorities[0] // const float *pQueuePriorities - }; - - VkDeviceCreateInfo device_create_info = { - VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDeviceCreateFlags flags - 1, // uint32_t queueCreateInfoCount - &queue_create_info, // const VkDeviceQueueCreateInfo *pQueueCreateInfos - 0, // uint32_t enabledLayerCount - nullptr, // const char * const *ppEnabledLayerNames - 0, // uint32_t enabledExtensionCount - nullptr, // const char * const *ppEnabledExtensionNames - nullptr // const VkPhysicalDeviceFeatures *pEnabledFeatures - }; - - if( vkCreateDevice( selected_physical_device, &device_create_info, nullptr, &Vulkan.Device ) != VK_SUCCESS ) { - std::cout << "Could not create Vulkan device!" << std::endl; - return false; - } - - Vulkan.QueueFamilyIndex = selected_queue_family_index; - return true; - } - - bool Tutorial01::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &queue_family_index ) { - VkPhysicalDeviceProperties device_properties; - VkPhysicalDeviceFeatures device_features; - - vkGetPhysicalDeviceProperties( physical_device, &device_properties ); - vkGetPhysicalDeviceFeatures( physical_device, &device_features ); - - uint32_t major_version = VK_VERSION_MAJOR( device_properties.apiVersion ); - uint32_t minor_version = VK_VERSION_MINOR( device_properties.apiVersion ); - uint32_t patch_version = VK_VERSION_PATCH( device_properties.apiVersion ); - - if( (major_version < 1) || - (device_properties.limits.maxImageDimension2D < 4096) ) { - std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; - return false; - } - - uint32_t queue_families_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); - if( queue_families_count == 0 ) { - std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; - return false; - } - - std::vector queue_family_properties( queue_families_count ); - vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_family_properties[0] ); - for( uint32_t i = 0; i < queue_families_count; ++i ) { - if( (queue_family_properties[i].queueCount > 0) && - (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { - queue_family_index = i; - std::cout << "Selected device: " << device_properties.deviceName << std::endl; - return true; - } - } - - std::cout << "Could not find queue family with required properties on physical device " << physical_device << "!" << std::endl; - return false; - } - - bool Tutorial01::LoadDeviceLevelEntryPoints() { -#define VK_DEVICE_LEVEL_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)vkGetDeviceProcAddr( Vulkan.Device, #fun )) ) { \ - std::cout << "Could not load device level function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool Tutorial01::GetDeviceQueue() { - vkGetDeviceQueue( Vulkan.Device, Vulkan.QueueFamilyIndex, 0, &Vulkan.Queue ); - return true; - } - - Tutorial01::~Tutorial01() { - if( Vulkan.Device != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( Vulkan.Device ); - vkDestroyDevice( Vulkan.Device, nullptr ); - } - - if( Vulkan.Instance != VK_NULL_HANDLE ) { - vkDestroyInstance( Vulkan.Instance, nullptr ); - } - - if( VulkanLibrary ) { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - FreeLibrary( VulkanLibrary ); -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - dlclose( VulkanLibrary ); -#endif - } - } - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include +#include "Tutorial01.h" +#include "VulkanFunctions.h" + +namespace ApiWithoutSecrets { + + Tutorial01::Tutorial01() : + VulkanLibrary(), + Vulkan() { + } + + bool Tutorial01::OnWindowSizeChanged() { + return true; + } + + bool Tutorial01::Draw() { + return true; + } + + bool Tutorial01::PrepareVulkan() { + if( !LoadVulkanLibrary() ) { + return false; + } + if( !LoadExportedEntryPoints() ) { + return false; + } + if( !LoadGlobalLevelEntryPoints() ) { + return false; + } + if( !CreateInstance() ) { + return false; + } + if( !LoadInstanceLevelEntryPoints() ) { + return false; + } + if( !CreateDevice() ) { + return false; + } + if( !LoadDeviceLevelEntryPoints() ) { + return false; + } + if( !GetDeviceQueue() ) { + return false; + } + return true; + } + + bool Tutorial01::LoadVulkanLibrary() { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + VulkanLibrary = LoadLibrary( "vulkan-1.dll" ); +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + VulkanLibrary = dlopen( "libvulkan.so.1", RTLD_NOW ); +#endif + + if( VulkanLibrary == nullptr ) { + std::cout << "Could not load Vulkan library!" << std::endl; + return false; + } + return true; + } + + bool Tutorial01::LoadExportedEntryPoints() { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + #define LoadProcAddress GetProcAddress +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + #define LoadProcAddress dlsym +#endif + +#define VK_EXPORTED_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)LoadProcAddress( VulkanLibrary, #fun )) ) { \ + std::cout << "Could not load exported function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool Tutorial01::LoadGlobalLevelEntryPoints() { +#define VK_GLOBAL_LEVEL_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( nullptr, #fun )) ) { \ + std::cout << "Could not load global level function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool Tutorial01::CreateInstance() { + VkApplicationInfo application_info = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType + nullptr, // const void *pNext + "API without Secrets: Introduction to Vulkan", // const char *pApplicationName + VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t applicationVersion + "Vulkan Tutorial by Intel", // const char *pEngineName + VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t engineVersion + VK_MAKE_VERSION( 1, 0, 0 ) // uint32_t apiVersion + }; + + VkInstanceCreateInfo instance_create_info = { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0, // VkInstanceCreateFlags flags + &application_info, // const VkApplicationInfo *pApplicationInfo + 0, // uint32_t enabledLayerCount + nullptr, // const char * const *ppEnabledLayerNames + 0, // uint32_t enabledExtensionCount + nullptr // const char * const *ppEnabledExtensionNames + }; + + if( vkCreateInstance( &instance_create_info, nullptr, &Vulkan.Instance ) != VK_SUCCESS ) { + std::cout << "Could not create Vulkan instance!" << std::endl; + return false; + } + return true; + } + + bool Tutorial01::LoadInstanceLevelEntryPoints() { +#define VK_INSTANCE_LEVEL_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( Vulkan.Instance, #fun )) ) { \ + std::cout << "Could not load instance level function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool Tutorial01::CreateDevice() { + uint32_t num_devices = 0; + if( (vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, nullptr ) != VK_SUCCESS) || + (num_devices == 0) ) { + std::cout << "Error occurred during physical devices enumeration!" << std::endl; + return false; + } + + std::vector physical_devices( num_devices ); + if( vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, &physical_devices[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during physical devices enumeration!" << std::endl; + return false; + } + + VkPhysicalDevice selected_physical_device = VK_NULL_HANDLE; + uint32_t selected_queue_family_index = UINT32_MAX; + for( uint32_t i = 0; i < num_devices; ++i ) { + if( CheckPhysicalDeviceProperties( physical_devices[i], selected_queue_family_index ) ) { + selected_physical_device = physical_devices[i]; + break; + } + } + if( selected_physical_device == VK_NULL_HANDLE ) { + std::cout << "Could not select physical device based on the chosen properties!" << std::endl; + return false; + } + + std::vector queue_priorities = { 1.0f }; + + VkDeviceQueueCreateInfo queue_create_info = { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDeviceQueueCreateFlags flags + selected_queue_family_index, // uint32_t queueFamilyIndex + static_cast(queue_priorities.size()), // uint32_t queueCount + &queue_priorities[0] // const float *pQueuePriorities + }; + + VkDeviceCreateInfo device_create_info = { + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDeviceCreateFlags flags + 1, // uint32_t queueCreateInfoCount + &queue_create_info, // const VkDeviceQueueCreateInfo *pQueueCreateInfos + 0, // uint32_t enabledLayerCount + nullptr, // const char * const *ppEnabledLayerNames + 0, // uint32_t enabledExtensionCount + nullptr, // const char * const *ppEnabledExtensionNames + nullptr // const VkPhysicalDeviceFeatures *pEnabledFeatures + }; + + if( vkCreateDevice( selected_physical_device, &device_create_info, nullptr, &Vulkan.Device ) != VK_SUCCESS ) { + std::cout << "Could not create Vulkan device!" << std::endl; + return false; + } + + Vulkan.QueueFamilyIndex = selected_queue_family_index; + return true; + } + + bool Tutorial01::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &queue_family_index ) { + VkPhysicalDeviceProperties device_properties; + VkPhysicalDeviceFeatures device_features; + + vkGetPhysicalDeviceProperties( physical_device, &device_properties ); + vkGetPhysicalDeviceFeatures( physical_device, &device_features ); + + uint32_t major_version = VK_VERSION_MAJOR( device_properties.apiVersion ); + uint32_t minor_version = VK_VERSION_MINOR( device_properties.apiVersion ); + uint32_t patch_version = VK_VERSION_PATCH( device_properties.apiVersion ); + + if( (major_version < 1) || + (device_properties.limits.maxImageDimension2D < 4096) ) { + std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; + return false; + } + + uint32_t queue_families_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); + if( queue_families_count == 0 ) { + std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; + return false; + } + + std::vector queue_family_properties( queue_families_count ); + vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_family_properties[0] ); + for( uint32_t i = 0; i < queue_families_count; ++i ) { + if( (queue_family_properties[i].queueCount > 0) && + (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { + queue_family_index = i; + std::cout << "Selected device: " << device_properties.deviceName << std::endl; + return true; + } + } + + std::cout << "Could not find queue family with required properties on physical device " << physical_device << "!" << std::endl; + return false; + } + + bool Tutorial01::LoadDeviceLevelEntryPoints() { +#define VK_DEVICE_LEVEL_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)vkGetDeviceProcAddr( Vulkan.Device, #fun )) ) { \ + std::cout << "Could not load device level function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool Tutorial01::GetDeviceQueue() { + vkGetDeviceQueue( Vulkan.Device, Vulkan.QueueFamilyIndex, 0, &Vulkan.Queue ); + return true; + } + + Tutorial01::~Tutorial01() { + if( Vulkan.Device != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( Vulkan.Device ); + vkDestroyDevice( Vulkan.Device, nullptr ); + } + + if( Vulkan.Instance != VK_NULL_HANDLE ) { + vkDestroyInstance( Vulkan.Instance, nullptr ); + } + + if( VulkanLibrary ) { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + FreeLibrary( VulkanLibrary ); +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + dlclose( VulkanLibrary ); +#endif + } + } + } // namespace ApiWithoutSecrets \ No newline at end of file diff --git a/Project/Tutorial01/Tutorial01.h b/Project/Tutorial01/Tutorial01.h index f6dda6b..5bcb3dc 100644 --- a/Project/Tutorial01/Tutorial01.h +++ b/Project/Tutorial01/Tutorial01.h @@ -1,76 +1,76 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(TUTORIAL_01_HEADER) -#define TUTORIAL_01_HEADER - -#include "vulkan.h" -#include "OperatingSystem.h" - -namespace ApiWithoutSecrets { - - // ************************************************************ // - // VulkanTutorial01Parameters // - // // - // Vulkan specific parameters // - // ************************************************************ // - struct VulkanTutorial01Parameters { - VkInstance Instance; - VkDevice Device; - uint32_t QueueFamilyIndex; - VkQueue Queue; - - VulkanTutorial01Parameters() : - Instance( VK_NULL_HANDLE ), - Device( VK_NULL_HANDLE ), - QueueFamilyIndex( 0 ), - Queue( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // Tutorial01 // - // // - // Class for presenting Vulkan usage topics // - // ************************************************************ // - class Tutorial01 : public OS::TutorialBase { - public: - Tutorial01(); - ~Tutorial01(); - - bool OnWindowSizeChanged() override; - bool Draw() override; - - bool PrepareVulkan(); - - private: - OS::LibraryHandle VulkanLibrary; - VulkanTutorial01Parameters Vulkan; - - bool LoadVulkanLibrary(); - bool LoadExportedEntryPoints(); - bool LoadGlobalLevelEntryPoints(); - bool CreateInstance(); - bool LoadInstanceLevelEntryPoints(); - bool CreateDevice(); - bool CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &queue_family_index ); - bool LoadDeviceLevelEntryPoints(); - bool GetDeviceQueue(); - }; - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(TUTORIAL_01_HEADER) +#define TUTORIAL_01_HEADER + +#include "vulkan.h" +#include "OperatingSystem.h" + +namespace ApiWithoutSecrets { + + // ************************************************************ // + // VulkanTutorial01Parameters // + // // + // Vulkan specific parameters // + // ************************************************************ // + struct VulkanTutorial01Parameters { + VkInstance Instance; + VkDevice Device; + uint32_t QueueFamilyIndex; + VkQueue Queue; + + VulkanTutorial01Parameters() : + Instance( VK_NULL_HANDLE ), + Device( VK_NULL_HANDLE ), + QueueFamilyIndex( 0 ), + Queue( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // Tutorial01 // + // // + // Class for presenting Vulkan usage topics // + // ************************************************************ // + class Tutorial01 : public OS::TutorialBase { + public: + Tutorial01(); + ~Tutorial01(); + + bool OnWindowSizeChanged() override; + bool Draw() override; + + bool PrepareVulkan(); + + private: + OS::LibraryHandle VulkanLibrary; + VulkanTutorial01Parameters Vulkan; + + bool LoadVulkanLibrary(); + bool LoadExportedEntryPoints(); + bool LoadGlobalLevelEntryPoints(); + bool CreateInstance(); + bool LoadInstanceLevelEntryPoints(); + bool CreateDevice(); + bool CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &queue_family_index ); + bool LoadDeviceLevelEntryPoints(); + bool GetDeviceQueue(); + }; + +} // namespace ApiWithoutSecrets + #endif // TUTORIAL_01_HEADER \ No newline at end of file diff --git a/Project/Tutorial01/main.cpp b/Project/Tutorial01/main.cpp index f6c7eae..9198c56 100644 --- a/Project/Tutorial01/main.cpp +++ b/Project/Tutorial01/main.cpp @@ -1,39 +1,39 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial01.h" - -int main( int argc, char **argv ) { - ApiWithoutSecrets::OS::Window window; - ApiWithoutSecrets::Tutorial01 tutorial01; - - // Window creation - if( !window.Create( "01 - The Beginning" ) ) { - return -1; - } - - // Vulkan preparations and initialization - if( !tutorial01.PrepareVulkan() ) { - return -1; - } - - // Rendering loop - if( !window.RenderingLoop( tutorial01 ) ) { - return -1; - } - - return 0; -} +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial01.h" + +int main( int argc, char **argv ) { + ApiWithoutSecrets::OS::Window window; + ApiWithoutSecrets::Tutorial01 tutorial01; + + // Window creation + if( !window.Create( "01 - The Beginning" ) ) { + return -1; + } + + // Vulkan preparations and initialization + if( !tutorial01.PrepareVulkan() ) { + return -1; + } + + // Rendering loop + if( !window.RenderingLoop( tutorial01 ) ) { + return -1; + } + + return 0; +} diff --git a/Project/Tutorial02/Tutorial02.cpp b/Project/Tutorial02/Tutorial02.cpp index 2c789d5..25f4a34 100644 --- a/Project/Tutorial02/Tutorial02.cpp +++ b/Project/Tutorial02/Tutorial02.cpp @@ -1,870 +1,870 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial02.h" -#include "VulkanFunctions.h" - -namespace ApiWithoutSecrets { - - Tutorial02::Tutorial02() : - VulkanLibrary(), - Window(), - Vulkan() { - } - - bool Tutorial02::PrepareVulkan( OS::WindowParameters parameters ) { - Window = parameters; - - if( !LoadVulkanLibrary() ) { - return false; - } - if( !LoadExportedEntryPoints() ) { - return false; - } - if( !LoadGlobalLevelEntryPoints() ) { - return false; - } - if( !CreateInstance() ) { - return false; - } - if( !LoadInstanceLevelEntryPoints() ) { - return false; - } - if( !CreatePresentationSurface() ) { - return false; - } - if( !CreateDevice() ) { - return false; - } - if( !LoadDeviceLevelEntryPoints() ) { - return false; - } - if( !GetDeviceQueue() ) { - return false; - } - if( !CreateSemaphores() ) { - return false; - } - return true; - } - - bool Tutorial02::LoadVulkanLibrary() { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - VulkanLibrary = LoadLibrary( "vulkan-1.dll" ); -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - VulkanLibrary = dlopen( "libvulkan.so.1", RTLD_NOW ); -#endif - - if( VulkanLibrary == nullptr ) { - std::cout << "Could not load Vulkan library!" << std::endl; - return false; - } - return true; - } - - bool Tutorial02::LoadExportedEntryPoints() { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - #define LoadProcAddress GetProcAddress -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - #define LoadProcAddress dlsym -#endif - -#define VK_EXPORTED_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)LoadProcAddress( VulkanLibrary, #fun )) ) { \ - std::cout << "Could not load exported function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool Tutorial02::LoadGlobalLevelEntryPoints() { -#define VK_GLOBAL_LEVEL_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( nullptr, #fun )) ) { \ - std::cout << "Could not load global level function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool Tutorial02::CreateInstance() { - uint32_t extensions_count = 0; - if( (vkEnumerateInstanceExtensionProperties( nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || - (extensions_count == 0) ) { - std::cout << "Error occurred during instance extensions enumeration!" << std::endl; - return false; - } - - std::vector available_extensions( extensions_count ); - if( vkEnumerateInstanceExtensionProperties( nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during instance extensions enumeration!" << std::endl; - return false; - } - - std::vector extensions = { - VK_KHR_SURFACE_EXTENSION_NAME, -#if defined(VK_USE_PLATFORM_WIN32_KHR) - VK_KHR_WIN32_SURFACE_EXTENSION_NAME -#elif defined(VK_USE_PLATFORM_XCB_KHR) - VK_KHR_XCB_SURFACE_EXTENSION_NAME -#elif defined(VK_USE_PLATFORM_XLIB_KHR) - VK_KHR_XLIB_SURFACE_EXTENSION_NAME -#endif - }; - - for( size_t i = 0; i < extensions.size(); ++i ) { - if( !CheckExtensionAvailability( extensions[i], available_extensions ) ) { - std::cout << "Could not find instance extension named \"" << extensions[i] << "\"!" << std::endl; - return false; - } - } - - VkApplicationInfo application_info = { - VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType - nullptr, // const void *pNext - "API without Secrets: Introduction to Vulkan", // const char *pApplicationName - VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t applicationVersion - "Vulkan Tutorial by Intel", // const char *pEngineName - VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t engineVersion - VK_MAKE_VERSION( 1, 0, 0 ) // uint32_t apiVersion - }; - - VkInstanceCreateInfo instance_create_info = { - VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkInstanceCreateFlags flags - &application_info, // const VkApplicationInfo *pApplicationInfo - 0, // uint32_t enabledLayerCount - nullptr, // const char * const *ppEnabledLayerNames - static_cast(extensions.size()), // uint32_t enabledExtensionCount - &extensions[0] // const char * const *ppEnabledExtensionNames - }; - - if( vkCreateInstance( &instance_create_info, nullptr, &Vulkan.Instance ) != VK_SUCCESS ) { - std::cout << "Could not create Vulkan instance!" << std::endl; - return false; - } - return true; - } - - bool Tutorial02::CheckExtensionAvailability( const char *extension_name, const std::vector &available_extensions ) { - for( size_t i = 0; i < available_extensions.size(); ++i ) { - if( strcmp( available_extensions[i].extensionName, extension_name ) == 0 ) { - return true; - } - } - return false; - } - - bool Tutorial02::LoadInstanceLevelEntryPoints() { -#define VK_INSTANCE_LEVEL_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( Vulkan.Instance, #fun )) ) { \ - std::cout << "Could not load instance level function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool Tutorial02::CreatePresentationSurface() { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - VkWin32SurfaceCreateInfoKHR surface_create_info = { - VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkWin32SurfaceCreateFlagsKHR flags - Window.Instance, // HINSTANCE hinstance - Window.Handle // HWND hwnd - }; - - if( vkCreateWin32SurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { - return true; - } - -#elif defined(VK_USE_PLATFORM_XCB_KHR) - VkXcbSurfaceCreateInfoKHR surface_create_info = { - VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkXcbSurfaceCreateFlagsKHR flags - Window.Connection, // xcb_connection_t* connection - Window.Handle // xcb_window_t window - }; - - if( vkCreateXcbSurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { - return true; - } - -#elif defined(VK_USE_PLATFORM_XLIB_KHR) - VkXlibSurfaceCreateInfoKHR surface_create_info = { - VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkXlibSurfaceCreateFlagsKHR flags - Window.DisplayPtr, // Display *dpy - Window.Handle // Window window - }; - if( vkCreateXlibSurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { - return true; - } - -#endif - - std::cout << "Could not create presentation surface!" << std::endl; - return false; - } - - bool Tutorial02::CreateDevice() { - uint32_t num_devices = 0; - if( (vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, nullptr ) != VK_SUCCESS) || - (num_devices == 0) ) { - std::cout << "Error occurred during physical devices enumeration!" << std::endl; - return false; - } - - std::vector physical_devices( num_devices ); - if( vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, &physical_devices[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during physical devices enumeration!" << std::endl; - return false; - } - - uint32_t selected_graphics_queue_family_index = UINT32_MAX; - uint32_t selected_present_queue_family_index = UINT32_MAX; - - for( uint32_t i = 0; i < num_devices; ++i ) { - if( CheckPhysicalDeviceProperties( physical_devices[i], selected_graphics_queue_family_index, selected_present_queue_family_index ) ) { - Vulkan.PhysicalDevice = physical_devices[i]; - break; - } - } - if( Vulkan.PhysicalDevice == VK_NULL_HANDLE ) { - std::cout << "Could not select physical device based on the chosen properties!" << std::endl; - return false; - } - - std::vector queue_create_infos; - std::vector queue_priorities = { 1.0f }; - - queue_create_infos.push_back( { - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDeviceQueueCreateFlags flags - selected_graphics_queue_family_index, // uint32_t queueFamilyIndex - static_cast(queue_priorities.size()), // uint32_t queueCount - &queue_priorities[0] // const float *pQueuePriorities - } ); - - if( selected_graphics_queue_family_index != selected_present_queue_family_index ) { - queue_create_infos.push_back( { - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDeviceQueueCreateFlags flags - selected_present_queue_family_index, // uint32_t queueFamilyIndex - static_cast(queue_priorities.size()), // uint32_t queueCount - &queue_priorities[0] // const float *pQueuePriorities - } ); - } - - std::vector extensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - - VkDeviceCreateInfo device_create_info = { - VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDeviceCreateFlags flags - static_cast(queue_create_infos.size()), // uint32_t queueCreateInfoCount - &queue_create_infos[0], // const VkDeviceQueueCreateInfo *pQueueCreateInfos - 0, // uint32_t enabledLayerCount - nullptr, // const char * const *ppEnabledLayerNames - static_cast(extensions.size()), // uint32_t enabledExtensionCount - &extensions[0], // const char * const *ppEnabledExtensionNames - nullptr // const VkPhysicalDeviceFeatures *pEnabledFeatures - }; - - if( vkCreateDevice( Vulkan.PhysicalDevice, &device_create_info, nullptr, &Vulkan.Device ) != VK_SUCCESS ) { - std::cout << "Could not create Vulkan device!" << std::endl; - return false; - } - - Vulkan.GraphicsQueueFamilyIndex = selected_graphics_queue_family_index; - Vulkan.PresentQueueFamilyIndex = selected_present_queue_family_index; - return true; - } - - bool Tutorial02::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &selected_graphics_queue_family_index, uint32_t &selected_present_queue_family_index ) { - uint32_t extensions_count = 0; - if( (vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || - (extensions_count == 0) ) { - std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; - return false; - } - - std::vector available_extensions( extensions_count ); - if( vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; - return false; - } - - std::vector device_extensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - - for( size_t i = 0; i < device_extensions.size(); ++i ) { - if( !CheckExtensionAvailability( device_extensions[i], available_extensions ) ) { - std::cout << "Physical device " << physical_device << " doesn't support extension named \"" << device_extensions[i] << "\"!" << std::endl; - return false; - } - } - - VkPhysicalDeviceProperties device_properties; - VkPhysicalDeviceFeatures device_features; - - vkGetPhysicalDeviceProperties( physical_device, &device_properties ); - vkGetPhysicalDeviceFeatures( physical_device, &device_features ); - - uint32_t major_version = VK_VERSION_MAJOR( device_properties.apiVersion ); - - if( (major_version < 1) || - (device_properties.limits.maxImageDimension2D < 4096) ) { - std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; - return false; - } - - uint32_t queue_families_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); - if( queue_families_count == 0 ) { - std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; - return false; - } - - std::vector queue_family_properties( queue_families_count ); - std::vector queue_present_support( queue_families_count ); - - vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_family_properties[0] ); - - uint32_t graphics_queue_family_index = UINT32_MAX; - uint32_t present_queue_family_index = UINT32_MAX; - - for( uint32_t i = 0; i < queue_families_count; ++i ) { - vkGetPhysicalDeviceSurfaceSupportKHR( physical_device, i, Vulkan.PresentationSurface, &queue_present_support[i] ); - - if( (queue_family_properties[i].queueCount > 0) && - (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { - // Select first queue that supports graphics - if( graphics_queue_family_index == UINT32_MAX ) { - graphics_queue_family_index = i; - } - - // If there is queue that supports both graphics and present - prefer it - if( queue_present_support[i] ) { - selected_graphics_queue_family_index = i; - selected_present_queue_family_index = i; - return true; - } - } - } - - // We don't have queue that supports both graphics and present so we have to use separate queues - for( uint32_t i = 0; i < queue_families_count; ++i ) { - if( queue_present_support[i] ) { - present_queue_family_index = i; - break; - } - } - - // If this device doesn't support queues with graphics and present capabilities don't use it - if( (graphics_queue_family_index == UINT32_MAX) || - (present_queue_family_index == UINT32_MAX) ) { - std::cout << "Could not find queue family with required properties on physical device " << physical_device << "!" << std::endl; - return false; - } - - selected_graphics_queue_family_index = graphics_queue_family_index; - selected_present_queue_family_index = present_queue_family_index; - return true; - } - - bool Tutorial02::LoadDeviceLevelEntryPoints() { -#define VK_DEVICE_LEVEL_FUNCTION( fun ) \ - if( !(fun = (PFN_##fun)vkGetDeviceProcAddr( Vulkan.Device, #fun )) ) { \ - std::cout << "Could not load device level function: " << #fun << "!" << std::endl; \ - return false; \ - } - -#include "ListOfFunctions.inl" - - return true; - } - - bool Tutorial02::GetDeviceQueue() { - vkGetDeviceQueue( Vulkan.Device, Vulkan.GraphicsQueueFamilyIndex, 0, &Vulkan.GraphicsQueue ); - vkGetDeviceQueue( Vulkan.Device, Vulkan.PresentQueueFamilyIndex, 0, &Vulkan.PresentQueue ); - return true; - } - - bool Tutorial02::CreateSemaphores() { - VkSemaphoreCreateInfo semaphore_create_info = { - VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0 // VkSemaphoreCreateFlags flags - }; - - if( (vkCreateSemaphore( Vulkan.Device, &semaphore_create_info, nullptr, &Vulkan.ImageAvailableSemaphore ) != VK_SUCCESS) || - (vkCreateSemaphore( Vulkan.Device, &semaphore_create_info, nullptr, &Vulkan.RenderingFinishedSemaphore ) != VK_SUCCESS) ) { - std::cout << "Could not create semaphores!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial02::CreateSwapChain() { - CanRender = false; - - if( Vulkan.Device != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( Vulkan.Device ); - } - - VkSurfaceCapabilitiesKHR surface_capabilities; - if( vkGetPhysicalDeviceSurfaceCapabilitiesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &surface_capabilities ) != VK_SUCCESS ) { - std::cout << "Could not check presentation surface capabilities!" << std::endl; - return false; - } - - uint32_t formats_count; - if( (vkGetPhysicalDeviceSurfaceFormatsKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &formats_count, nullptr ) != VK_SUCCESS) || - (formats_count == 0) ) { - std::cout << "Error occurred during presentation surface formats enumeration!" << std::endl; - return false; - } - - std::vector surface_formats( formats_count ); - if( vkGetPhysicalDeviceSurfaceFormatsKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &formats_count, &surface_formats[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during presentation surface formats enumeration!" << std::endl; - return false; - } - - uint32_t present_modes_count; - if( (vkGetPhysicalDeviceSurfacePresentModesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &present_modes_count, nullptr ) != VK_SUCCESS) || - (present_modes_count == 0) ) { - std::cout << "Error occurred during presentation surface present modes enumeration!" << std::endl; - return false; - } - - std::vector present_modes( present_modes_count ); - if( vkGetPhysicalDeviceSurfacePresentModesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &present_modes_count, &present_modes[0] ) != VK_SUCCESS ) { - std::cout << "Error occurred during presentation surface present modes enumeration!" << std::endl; - return false; - } - - uint32_t desired_number_of_images = GetSwapChainNumImages( surface_capabilities ); - VkSurfaceFormatKHR desired_format = GetSwapChainFormat( surface_formats ); - VkExtent2D desired_extent = GetSwapChainExtent( surface_capabilities ); - VkImageUsageFlags desired_usage = GetSwapChainUsageFlags( surface_capabilities ); - VkSurfaceTransformFlagBitsKHR desired_transform = GetSwapChainTransform( surface_capabilities ); - VkPresentModeKHR desired_present_mode = GetSwapChainPresentMode( present_modes ); - VkSwapchainKHR old_swap_chain = Vulkan.SwapChain; - - if( static_cast(desired_usage) == -1 ) { - return false; - } - if( static_cast(desired_present_mode) == -1 ) { - return false; - } - if( (desired_extent.width == 0) || (desired_extent.height == 0) ) { - // Current surface size is (0, 0) so we can't create a swap chain and render anything (CanRender == false) - // But we don't wont to kill the application as this situation may occur i.e. when window gets minimized - return true; - } - - VkSwapchainCreateInfoKHR swap_chain_create_info = { - VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkSwapchainCreateFlagsKHR flags - Vulkan.PresentationSurface, // VkSurfaceKHR surface - desired_number_of_images, // uint32_t minImageCount - desired_format.format, // VkFormat imageFormat - desired_format.colorSpace, // VkColorSpaceKHR imageColorSpace - desired_extent, // VkExtent2D imageExtent - 1, // uint32_t imageArrayLayers - desired_usage, // VkImageUsageFlags imageUsage - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode - 0, // uint32_t queueFamilyIndexCount - nullptr, // const uint32_t *pQueueFamilyIndices - desired_transform, // VkSurfaceTransformFlagBitsKHR preTransform - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, // VkCompositeAlphaFlagBitsKHR compositeAlpha - desired_present_mode, // VkPresentModeKHR presentMode - VK_TRUE, // VkBool32 clipped - old_swap_chain // VkSwapchainKHR oldSwapchain - }; - - if( vkCreateSwapchainKHR( Vulkan.Device, &swap_chain_create_info, nullptr, &Vulkan.SwapChain ) != VK_SUCCESS ) { - std::cout << "Could not create swap chain!" << std::endl; - return false; - } - if( old_swap_chain != VK_NULL_HANDLE ) { - vkDestroySwapchainKHR( Vulkan.Device, old_swap_chain, nullptr ); - } - - CanRender = true; - - return true; - } - - uint32_t Tutorial02::GetSwapChainNumImages( VkSurfaceCapabilitiesKHR &surface_capabilities ) { - // Set of images defined in a swap chain may not always be available for application to render to: - // One may be displayed and one may wait in a queue to be presented - // If application wants to use more images at the same time it must ask for more images - uint32_t image_count = surface_capabilities.minImageCount + 1; - if( (surface_capabilities.maxImageCount > 0) && - (image_count > surface_capabilities.maxImageCount) ) { - image_count = surface_capabilities.maxImageCount; - } - return image_count; - } - - VkSurfaceFormatKHR Tutorial02::GetSwapChainFormat( std::vector &surface_formats ) { - // If the list contains only one entry with undefined format - // it means that there are no preferred surface formats and any can be chosen - if( (surface_formats.size() == 1) && - (surface_formats[0].format == VK_FORMAT_UNDEFINED) ) { - return{ VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR }; - } - - // Check if list contains most widely used R8 G8 B8 A8 format - // with nonlinear color space - for( VkSurfaceFormatKHR &surface_format : surface_formats ) { - if( surface_format.format == VK_FORMAT_R8G8B8A8_UNORM ) { - return surface_format; - } - } - - // Return the first format from the list - return surface_formats[0]; - } - - VkExtent2D Tutorial02::GetSwapChainExtent( VkSurfaceCapabilitiesKHR &surface_capabilities ) { - // Special value of surface extent is width == height == -1 - // If this is so we define the size by ourselves but it must fit within defined confines - if( surface_capabilities.currentExtent.width == -1 ) { - VkExtent2D swap_chain_extent = { 640, 480 }; - if( swap_chain_extent.width < surface_capabilities.minImageExtent.width ) { - swap_chain_extent.width = surface_capabilities.minImageExtent.width; - } - if( swap_chain_extent.height < surface_capabilities.minImageExtent.height ) { - swap_chain_extent.height = surface_capabilities.minImageExtent.height; - } - if( swap_chain_extent.width > surface_capabilities.maxImageExtent.width ) { - swap_chain_extent.width = surface_capabilities.maxImageExtent.width; - } - if( swap_chain_extent.height > surface_capabilities.maxImageExtent.height ) { - swap_chain_extent.height = surface_capabilities.maxImageExtent.height; - } - return swap_chain_extent; - } - - // Most of the cases we define size of the swap_chain images equal to current window's size - return surface_capabilities.currentExtent; - } - - VkImageUsageFlags Tutorial02::GetSwapChainUsageFlags( VkSurfaceCapabilitiesKHR &surface_capabilities ) { - // Color attachment flag must always be supported - // We can define other usage flags but we always need to check if they are supported - if( surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT ) { - return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - } - std::cout << "VK_IMAGE_USAGE_TRANSFER_DST image usage is not supported by the swap chain!" << std::endl - << "Supported swap chain's image usages include:" << std::endl - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT ? " VK_IMAGE_USAGE_TRANSFER_SRC\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT ? " VK_IMAGE_USAGE_TRANSFER_DST\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT ? " VK_IMAGE_USAGE_SAMPLED\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT ? " VK_IMAGE_USAGE_STORAGE\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_COLOR_ATTACHMENT\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT\n" : "") - << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_INPUT_ATTACHMENT" : "") - << std::endl; - return static_cast(-1); - } - - VkSurfaceTransformFlagBitsKHR Tutorial02::GetSwapChainTransform( VkSurfaceCapabilitiesKHR &surface_capabilities ) { - // Sometimes images must be transformed before they are presented (i.e. due to device's orienation - // being other than default orientation) - // If the specified transform is other than current transform, presentation engine will transform image - // during presentation operation; this operation may hit performance on some platforms - // Here we don't want any transformations to occur so if the identity transform is supported use it - // otherwise just use the same transform as current transform - if( surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ) { - return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - } else { - return surface_capabilities.currentTransform; - } - } - - VkPresentModeKHR Tutorial02::GetSwapChainPresentMode( std::vector &present_modes ) { - // FIFO present mode is always available - // MAILBOX is the lowest latency V-Sync enabled mode (something like triple-buffering) so use it if available - for( VkPresentModeKHR &present_mode : present_modes ) { - if( present_mode == VK_PRESENT_MODE_MAILBOX_KHR ) { - return present_mode; - } - } - for( VkPresentModeKHR &present_mode : present_modes ) { - if( present_mode == VK_PRESENT_MODE_FIFO_KHR ) { - return present_mode; - } - } - std::cout << "FIFO present mode is not supported by the swap chain!" << std::endl; - return static_cast(-1); - } - - bool Tutorial02::OnWindowSizeChanged() { - Clear(); - - if( !CreateSwapChain() ) { - return false; - } - if( !CreateCommandBuffers() ) { - return false; - } - return true; - } - - bool Tutorial02::CreateCommandBuffers() { - VkCommandPoolCreateInfo cmd_pool_create_info = { - VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0, // VkCommandPoolCreateFlags flags - Vulkan.PresentQueueFamilyIndex // uint32_t queueFamilyIndex - }; - - if( vkCreateCommandPool( Vulkan.Device, &cmd_pool_create_info, nullptr, &Vulkan.PresentQueueCmdPool ) != VK_SUCCESS ) { - std::cout << "Could not create a command pool!" << std::endl; - return false; - } - - uint32_t image_count = 0; - if( (vkGetSwapchainImagesKHR( Vulkan.Device, Vulkan.SwapChain, &image_count, nullptr ) != VK_SUCCESS) || - (image_count == 0) ) { - std::cout << "Could not get the number of swap chain images!" << std::endl; - return false; - } - - Vulkan.PresentQueueCmdBuffers.resize( image_count ); - - VkCommandBufferAllocateInfo cmd_buffer_allocate_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - Vulkan.PresentQueueCmdPool, // VkCommandPool commandPool - VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level - image_count // uint32_t bufferCount - }; - if( vkAllocateCommandBuffers( Vulkan.Device, &cmd_buffer_allocate_info, &Vulkan.PresentQueueCmdBuffers[0] ) != VK_SUCCESS ) { - std::cout << "Could not allocate command buffers!" << std::endl; - return false; - } - - if( !RecordCommandBuffers() ) { - std::cout << "Could not record command buffers!" << std::endl; - return false; - } - return true; - } - - bool Tutorial02::RecordCommandBuffers() { - uint32_t image_count = static_cast(Vulkan.PresentQueueCmdBuffers.size()); - - std::vector swap_chain_images( image_count ); - if( vkGetSwapchainImagesKHR( Vulkan.Device, Vulkan.SwapChain, &image_count, &swap_chain_images[0] ) != VK_SUCCESS ) { - std::cout << "Could not get swap chain images!" << std::endl; - return false; - } - - VkCommandBufferBeginInfo cmd_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - VkClearColorValue clear_color = { - { 1.0f, 0.8f, 0.4f, 0.0f } - }; - - VkImageSubresourceRange image_subresource_range = { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }; - - for( uint32_t i = 0; i < image_count; ++i ) { - VkImageMemoryBarrier barrier_from_present_to_clear = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - swap_chain_images[i], // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - - VkImageMemoryBarrier barrier_from_clear_to_present = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - swap_chain_images[i], // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - - vkBeginCommandBuffer( Vulkan.PresentQueueCmdBuffers[i], &cmd_buffer_begin_info ); - vkCmdPipelineBarrier( Vulkan.PresentQueueCmdBuffers[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_clear ); - - vkCmdClearColorImage( Vulkan.PresentQueueCmdBuffers[i], swap_chain_images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &image_subresource_range ); - - vkCmdPipelineBarrier( Vulkan.PresentQueueCmdBuffers[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_clear_to_present ); - if( vkEndCommandBuffer( Vulkan.PresentQueueCmdBuffers[i] ) != VK_SUCCESS ) { - std::cout << "Could not record command buffers!" << std::endl; - return false; - } - } - - return true; - } - - void Tutorial02::Clear() { - if( Vulkan.Device != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( Vulkan.Device ); - - if( (Vulkan.PresentQueueCmdBuffers.size() > 0) && (Vulkan.PresentQueueCmdBuffers[0] != VK_NULL_HANDLE) ) { - vkFreeCommandBuffers( Vulkan.Device, Vulkan.PresentQueueCmdPool, static_cast(Vulkan.PresentQueueCmdBuffers.size()), &Vulkan.PresentQueueCmdBuffers[0] ); - Vulkan.PresentQueueCmdBuffers.clear(); - } - - if( Vulkan.PresentQueueCmdPool != VK_NULL_HANDLE ) { - vkDestroyCommandPool( Vulkan.Device, Vulkan.PresentQueueCmdPool, nullptr ); - Vulkan.PresentQueueCmdPool = VK_NULL_HANDLE; - } - } - } - - bool Tutorial02::Draw() { - uint32_t image_index; - VkResult result = vkAcquireNextImageKHR( Vulkan.Device, Vulkan.SwapChain, UINT64_MAX, Vulkan.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); - switch( result ) { - case VK_SUCCESS: - case VK_SUBOPTIMAL_KHR: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; - return false; - } - - VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT; - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - &Vulkan.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores - &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - &Vulkan.PresentQueueCmdBuffers[image_index], // const VkCommandBuffer *pCommandBuffers - 1, // uint32_t signalSemaphoreCount - &Vulkan.RenderingFinishedSemaphore // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( Vulkan.PresentQueue, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { - return false; - } - - VkPresentInfoKHR present_info = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - &Vulkan.RenderingFinishedSemaphore, // const VkSemaphore *pWaitSemaphores - 1, // uint32_t swapchainCount - &Vulkan.SwapChain, // const VkSwapchainKHR *pSwapchains - &image_index, // const uint32_t *pImageIndices - nullptr // VkResult *pResults - }; - result = vkQueuePresentKHR( Vulkan.PresentQueue, &present_info ); - - switch( result ) { - case VK_SUCCESS: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - case VK_SUBOPTIMAL_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during image presentation!" << std::endl; - return false; - } - - return true; - } - - Tutorial02::~Tutorial02() { - Clear(); - - if( Vulkan.Device != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( Vulkan.Device ); - - if( Vulkan.ImageAvailableSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( Vulkan.Device, Vulkan.ImageAvailableSemaphore, nullptr ); - } - if( Vulkan.RenderingFinishedSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( Vulkan.Device, Vulkan.RenderingFinishedSemaphore, nullptr ); - } - if( Vulkan.SwapChain != VK_NULL_HANDLE ) { - vkDestroySwapchainKHR( Vulkan.Device, Vulkan.SwapChain, nullptr ); - } - vkDestroyDevice( Vulkan.Device, nullptr ); - } - - if( Vulkan.PresentationSurface != VK_NULL_HANDLE ) { - vkDestroySurfaceKHR( Vulkan.Instance, Vulkan.PresentationSurface, nullptr ); - } - - if( Vulkan.Instance != VK_NULL_HANDLE ) { - vkDestroyInstance( Vulkan.Instance, nullptr ); - } - - if( VulkanLibrary ) { -#if defined(VK_USE_PLATFORM_WIN32_KHR) - FreeLibrary( VulkanLibrary ); -#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) - dlclose( VulkanLibrary ); -#endif - } - } - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial02.h" +#include "VulkanFunctions.h" + +namespace ApiWithoutSecrets { + + Tutorial02::Tutorial02() : + VulkanLibrary(), + Window(), + Vulkan() { + } + + bool Tutorial02::PrepareVulkan( OS::WindowParameters parameters ) { + Window = parameters; + + if( !LoadVulkanLibrary() ) { + return false; + } + if( !LoadExportedEntryPoints() ) { + return false; + } + if( !LoadGlobalLevelEntryPoints() ) { + return false; + } + if( !CreateInstance() ) { + return false; + } + if( !LoadInstanceLevelEntryPoints() ) { + return false; + } + if( !CreatePresentationSurface() ) { + return false; + } + if( !CreateDevice() ) { + return false; + } + if( !LoadDeviceLevelEntryPoints() ) { + return false; + } + if( !GetDeviceQueue() ) { + return false; + } + if( !CreateSemaphores() ) { + return false; + } + return true; + } + + bool Tutorial02::LoadVulkanLibrary() { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + VulkanLibrary = LoadLibrary( "vulkan-1.dll" ); +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + VulkanLibrary = dlopen( "libvulkan.so.1", RTLD_NOW ); +#endif + + if( VulkanLibrary == nullptr ) { + std::cout << "Could not load Vulkan library!" << std::endl; + return false; + } + return true; + } + + bool Tutorial02::LoadExportedEntryPoints() { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + #define LoadProcAddress GetProcAddress +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + #define LoadProcAddress dlsym +#endif + +#define VK_EXPORTED_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)LoadProcAddress( VulkanLibrary, #fun )) ) { \ + std::cout << "Could not load exported function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool Tutorial02::LoadGlobalLevelEntryPoints() { +#define VK_GLOBAL_LEVEL_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( nullptr, #fun )) ) { \ + std::cout << "Could not load global level function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool Tutorial02::CreateInstance() { + uint32_t extensions_count = 0; + if( (vkEnumerateInstanceExtensionProperties( nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || + (extensions_count == 0) ) { + std::cout << "Error occurred during instance extensions enumeration!" << std::endl; + return false; + } + + std::vector available_extensions( extensions_count ); + if( vkEnumerateInstanceExtensionProperties( nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during instance extensions enumeration!" << std::endl; + return false; + } + + std::vector extensions = { + VK_KHR_SURFACE_EXTENSION_NAME, +#if defined(VK_USE_PLATFORM_WIN32_KHR) + VK_KHR_WIN32_SURFACE_EXTENSION_NAME +#elif defined(VK_USE_PLATFORM_XCB_KHR) + VK_KHR_XCB_SURFACE_EXTENSION_NAME +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + VK_KHR_XLIB_SURFACE_EXTENSION_NAME +#endif + }; + + for( size_t i = 0; i < extensions.size(); ++i ) { + if( !CheckExtensionAvailability( extensions[i], available_extensions ) ) { + std::cout << "Could not find instance extension named \"" << extensions[i] << "\"!" << std::endl; + return false; + } + } + + VkApplicationInfo application_info = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType + nullptr, // const void *pNext + "API without Secrets: Introduction to Vulkan", // const char *pApplicationName + VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t applicationVersion + "Vulkan Tutorial by Intel", // const char *pEngineName + VK_MAKE_VERSION( 1, 0, 0 ), // uint32_t engineVersion + VK_MAKE_VERSION( 1, 0, 0 ) // uint32_t apiVersion + }; + + VkInstanceCreateInfo instance_create_info = { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkInstanceCreateFlags flags + &application_info, // const VkApplicationInfo *pApplicationInfo + 0, // uint32_t enabledLayerCount + nullptr, // const char * const *ppEnabledLayerNames + static_cast(extensions.size()), // uint32_t enabledExtensionCount + &extensions[0] // const char * const *ppEnabledExtensionNames + }; + + if( vkCreateInstance( &instance_create_info, nullptr, &Vulkan.Instance ) != VK_SUCCESS ) { + std::cout << "Could not create Vulkan instance!" << std::endl; + return false; + } + return true; + } + + bool Tutorial02::CheckExtensionAvailability( const char *extension_name, const std::vector &available_extensions ) { + for( size_t i = 0; i < available_extensions.size(); ++i ) { + if( strcmp( available_extensions[i].extensionName, extension_name ) == 0 ) { + return true; + } + } + return false; + } + + bool Tutorial02::LoadInstanceLevelEntryPoints() { +#define VK_INSTANCE_LEVEL_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( Vulkan.Instance, #fun )) ) { \ + std::cout << "Could not load instance level function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool Tutorial02::CreatePresentationSurface() { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + VkWin32SurfaceCreateInfoKHR surface_create_info = { + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkWin32SurfaceCreateFlagsKHR flags + Window.Instance, // HINSTANCE hinstance + Window.Handle // HWND hwnd + }; + + if( vkCreateWin32SurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { + return true; + } + +#elif defined(VK_USE_PLATFORM_XCB_KHR) + VkXcbSurfaceCreateInfoKHR surface_create_info = { + VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkXcbSurfaceCreateFlagsKHR flags + Window.Connection, // xcb_connection_t* connection + Window.Handle // xcb_window_t window + }; + + if( vkCreateXcbSurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { + return true; + } + +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + VkXlibSurfaceCreateInfoKHR surface_create_info = { + VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkXlibSurfaceCreateFlagsKHR flags + Window.DisplayPtr, // Display *dpy + Window.Handle // Window window + }; + if( vkCreateXlibSurfaceKHR( Vulkan.Instance, &surface_create_info, nullptr, &Vulkan.PresentationSurface ) == VK_SUCCESS ) { + return true; + } + +#endif + + std::cout << "Could not create presentation surface!" << std::endl; + return false; + } + + bool Tutorial02::CreateDevice() { + uint32_t num_devices = 0; + if( (vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, nullptr ) != VK_SUCCESS) || + (num_devices == 0) ) { + std::cout << "Error occurred during physical devices enumeration!" << std::endl; + return false; + } + + std::vector physical_devices( num_devices ); + if( vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, &physical_devices[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during physical devices enumeration!" << std::endl; + return false; + } + + uint32_t selected_graphics_queue_family_index = UINT32_MAX; + uint32_t selected_present_queue_family_index = UINT32_MAX; + + for( uint32_t i = 0; i < num_devices; ++i ) { + if( CheckPhysicalDeviceProperties( physical_devices[i], selected_graphics_queue_family_index, selected_present_queue_family_index ) ) { + Vulkan.PhysicalDevice = physical_devices[i]; + break; + } + } + if( Vulkan.PhysicalDevice == VK_NULL_HANDLE ) { + std::cout << "Could not select physical device based on the chosen properties!" << std::endl; + return false; + } + + std::vector queue_create_infos; + std::vector queue_priorities = { 1.0f }; + + queue_create_infos.push_back( { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDeviceQueueCreateFlags flags + selected_graphics_queue_family_index, // uint32_t queueFamilyIndex + static_cast(queue_priorities.size()), // uint32_t queueCount + &queue_priorities[0] // const float *pQueuePriorities + } ); + + if( selected_graphics_queue_family_index != selected_present_queue_family_index ) { + queue_create_infos.push_back( { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDeviceQueueCreateFlags flags + selected_present_queue_family_index, // uint32_t queueFamilyIndex + static_cast(queue_priorities.size()), // uint32_t queueCount + &queue_priorities[0] // const float *pQueuePriorities + } ); + } + + std::vector extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME + }; + + VkDeviceCreateInfo device_create_info = { + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDeviceCreateFlags flags + static_cast(queue_create_infos.size()), // uint32_t queueCreateInfoCount + &queue_create_infos[0], // const VkDeviceQueueCreateInfo *pQueueCreateInfos + 0, // uint32_t enabledLayerCount + nullptr, // const char * const *ppEnabledLayerNames + static_cast(extensions.size()), // uint32_t enabledExtensionCount + &extensions[0], // const char * const *ppEnabledExtensionNames + nullptr // const VkPhysicalDeviceFeatures *pEnabledFeatures + }; + + if( vkCreateDevice( Vulkan.PhysicalDevice, &device_create_info, nullptr, &Vulkan.Device ) != VK_SUCCESS ) { + std::cout << "Could not create Vulkan device!" << std::endl; + return false; + } + + Vulkan.GraphicsQueueFamilyIndex = selected_graphics_queue_family_index; + Vulkan.PresentQueueFamilyIndex = selected_present_queue_family_index; + return true; + } + + bool Tutorial02::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &selected_graphics_queue_family_index, uint32_t &selected_present_queue_family_index ) { + uint32_t extensions_count = 0; + if( (vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || + (extensions_count == 0) ) { + std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; + return false; + } + + std::vector available_extensions( extensions_count ); + if( vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; + return false; + } + + std::vector device_extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME + }; + + for( size_t i = 0; i < device_extensions.size(); ++i ) { + if( !CheckExtensionAvailability( device_extensions[i], available_extensions ) ) { + std::cout << "Physical device " << physical_device << " doesn't support extension named \"" << device_extensions[i] << "\"!" << std::endl; + return false; + } + } + + VkPhysicalDeviceProperties device_properties; + VkPhysicalDeviceFeatures device_features; + + vkGetPhysicalDeviceProperties( physical_device, &device_properties ); + vkGetPhysicalDeviceFeatures( physical_device, &device_features ); + + uint32_t major_version = VK_VERSION_MAJOR( device_properties.apiVersion ); + + if( (major_version < 1) || + (device_properties.limits.maxImageDimension2D < 4096) ) { + std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; + return false; + } + + uint32_t queue_families_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); + if( queue_families_count == 0 ) { + std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; + return false; + } + + std::vector queue_family_properties( queue_families_count ); + std::vector queue_present_support( queue_families_count ); + + vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_family_properties[0] ); + + uint32_t graphics_queue_family_index = UINT32_MAX; + uint32_t present_queue_family_index = UINT32_MAX; + + for( uint32_t i = 0; i < queue_families_count; ++i ) { + vkGetPhysicalDeviceSurfaceSupportKHR( physical_device, i, Vulkan.PresentationSurface, &queue_present_support[i] ); + + if( (queue_family_properties[i].queueCount > 0) && + (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { + // Select first queue that supports graphics + if( graphics_queue_family_index == UINT32_MAX ) { + graphics_queue_family_index = i; + } + + // If there is queue that supports both graphics and present - prefer it + if( queue_present_support[i] ) { + selected_graphics_queue_family_index = i; + selected_present_queue_family_index = i; + return true; + } + } + } + + // We don't have queue that supports both graphics and present so we have to use separate queues + for( uint32_t i = 0; i < queue_families_count; ++i ) { + if( queue_present_support[i] ) { + present_queue_family_index = i; + break; + } + } + + // If this device doesn't support queues with graphics and present capabilities don't use it + if( (graphics_queue_family_index == UINT32_MAX) || + (present_queue_family_index == UINT32_MAX) ) { + std::cout << "Could not find queue family with required properties on physical device " << physical_device << "!" << std::endl; + return false; + } + + selected_graphics_queue_family_index = graphics_queue_family_index; + selected_present_queue_family_index = present_queue_family_index; + return true; + } + + bool Tutorial02::LoadDeviceLevelEntryPoints() { +#define VK_DEVICE_LEVEL_FUNCTION( fun ) \ + if( !(fun = (PFN_##fun)vkGetDeviceProcAddr( Vulkan.Device, #fun )) ) { \ + std::cout << "Could not load device level function: " << #fun << "!" << std::endl; \ + return false; \ + } + +#include "ListOfFunctions.inl" + + return true; + } + + bool Tutorial02::GetDeviceQueue() { + vkGetDeviceQueue( Vulkan.Device, Vulkan.GraphicsQueueFamilyIndex, 0, &Vulkan.GraphicsQueue ); + vkGetDeviceQueue( Vulkan.Device, Vulkan.PresentQueueFamilyIndex, 0, &Vulkan.PresentQueue ); + return true; + } + + bool Tutorial02::CreateSemaphores() { + VkSemaphoreCreateInfo semaphore_create_info = { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0 // VkSemaphoreCreateFlags flags + }; + + if( (vkCreateSemaphore( Vulkan.Device, &semaphore_create_info, nullptr, &Vulkan.ImageAvailableSemaphore ) != VK_SUCCESS) || + (vkCreateSemaphore( Vulkan.Device, &semaphore_create_info, nullptr, &Vulkan.RenderingFinishedSemaphore ) != VK_SUCCESS) ) { + std::cout << "Could not create semaphores!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial02::CreateSwapChain() { + CanRender = false; + + if( Vulkan.Device != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( Vulkan.Device ); + } + + VkSurfaceCapabilitiesKHR surface_capabilities; + if( vkGetPhysicalDeviceSurfaceCapabilitiesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &surface_capabilities ) != VK_SUCCESS ) { + std::cout << "Could not check presentation surface capabilities!" << std::endl; + return false; + } + + uint32_t formats_count; + if( (vkGetPhysicalDeviceSurfaceFormatsKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &formats_count, nullptr ) != VK_SUCCESS) || + (formats_count == 0) ) { + std::cout << "Error occurred during presentation surface formats enumeration!" << std::endl; + return false; + } + + std::vector surface_formats( formats_count ); + if( vkGetPhysicalDeviceSurfaceFormatsKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &formats_count, &surface_formats[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during presentation surface formats enumeration!" << std::endl; + return false; + } + + uint32_t present_modes_count; + if( (vkGetPhysicalDeviceSurfacePresentModesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &present_modes_count, nullptr ) != VK_SUCCESS) || + (present_modes_count == 0) ) { + std::cout << "Error occurred during presentation surface present modes enumeration!" << std::endl; + return false; + } + + std::vector present_modes( present_modes_count ); + if( vkGetPhysicalDeviceSurfacePresentModesKHR( Vulkan.PhysicalDevice, Vulkan.PresentationSurface, &present_modes_count, &present_modes[0] ) != VK_SUCCESS ) { + std::cout << "Error occurred during presentation surface present modes enumeration!" << std::endl; + return false; + } + + uint32_t desired_number_of_images = GetSwapChainNumImages( surface_capabilities ); + VkSurfaceFormatKHR desired_format = GetSwapChainFormat( surface_formats ); + VkExtent2D desired_extent = GetSwapChainExtent( surface_capabilities ); + VkImageUsageFlags desired_usage = GetSwapChainUsageFlags( surface_capabilities ); + VkSurfaceTransformFlagBitsKHR desired_transform = GetSwapChainTransform( surface_capabilities ); + VkPresentModeKHR desired_present_mode = GetSwapChainPresentMode( present_modes ); + VkSwapchainKHR old_swap_chain = Vulkan.SwapChain; + + if( static_cast(desired_usage) == -1 ) { + return false; + } + if( static_cast(desired_present_mode) == -1 ) { + return false; + } + if( (desired_extent.width == 0) || (desired_extent.height == 0) ) { + // Current surface size is (0, 0) so we can't create a swap chain and render anything (CanRender == false) + // But we don't wont to kill the application as this situation may occur i.e. when window gets minimized + return true; + } + + VkSwapchainCreateInfoKHR swap_chain_create_info = { + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkSwapchainCreateFlagsKHR flags + Vulkan.PresentationSurface, // VkSurfaceKHR surface + desired_number_of_images, // uint32_t minImageCount + desired_format.format, // VkFormat imageFormat + desired_format.colorSpace, // VkColorSpaceKHR imageColorSpace + desired_extent, // VkExtent2D imageExtent + 1, // uint32_t imageArrayLayers + desired_usage, // VkImageUsageFlags imageUsage + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode + 0, // uint32_t queueFamilyIndexCount + nullptr, // const uint32_t *pQueueFamilyIndices + desired_transform, // VkSurfaceTransformFlagBitsKHR preTransform + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, // VkCompositeAlphaFlagBitsKHR compositeAlpha + desired_present_mode, // VkPresentModeKHR presentMode + VK_TRUE, // VkBool32 clipped + old_swap_chain // VkSwapchainKHR oldSwapchain + }; + + if( vkCreateSwapchainKHR( Vulkan.Device, &swap_chain_create_info, nullptr, &Vulkan.SwapChain ) != VK_SUCCESS ) { + std::cout << "Could not create swap chain!" << std::endl; + return false; + } + if( old_swap_chain != VK_NULL_HANDLE ) { + vkDestroySwapchainKHR( Vulkan.Device, old_swap_chain, nullptr ); + } + + CanRender = true; + + return true; + } + + uint32_t Tutorial02::GetSwapChainNumImages( VkSurfaceCapabilitiesKHR &surface_capabilities ) { + // Set of images defined in a swap chain may not always be available for application to render to: + // One may be displayed and one may wait in a queue to be presented + // If application wants to use more images at the same time it must ask for more images + uint32_t image_count = surface_capabilities.minImageCount + 1; + if( (surface_capabilities.maxImageCount > 0) && + (image_count > surface_capabilities.maxImageCount) ) { + image_count = surface_capabilities.maxImageCount; + } + return image_count; + } + + VkSurfaceFormatKHR Tutorial02::GetSwapChainFormat( std::vector &surface_formats ) { + // If the list contains only one entry with undefined format + // it means that there are no preferred surface formats and any can be chosen + if( (surface_formats.size() == 1) && + (surface_formats[0].format == VK_FORMAT_UNDEFINED) ) { + return{ VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR }; + } + + // Check if list contains most widely used R8 G8 B8 A8 format + // with nonlinear color space + for( VkSurfaceFormatKHR &surface_format : surface_formats ) { + if( surface_format.format == VK_FORMAT_R8G8B8A8_UNORM ) { + return surface_format; + } + } + + // Return the first format from the list + return surface_formats[0]; + } + + VkExtent2D Tutorial02::GetSwapChainExtent( VkSurfaceCapabilitiesKHR &surface_capabilities ) { + // Special value of surface extent is width == height == -1 + // If this is so we define the size by ourselves but it must fit within defined confines + if( surface_capabilities.currentExtent.width == -1 ) { + VkExtent2D swap_chain_extent = { 640, 480 }; + if( swap_chain_extent.width < surface_capabilities.minImageExtent.width ) { + swap_chain_extent.width = surface_capabilities.minImageExtent.width; + } + if( swap_chain_extent.height < surface_capabilities.minImageExtent.height ) { + swap_chain_extent.height = surface_capabilities.minImageExtent.height; + } + if( swap_chain_extent.width > surface_capabilities.maxImageExtent.width ) { + swap_chain_extent.width = surface_capabilities.maxImageExtent.width; + } + if( swap_chain_extent.height > surface_capabilities.maxImageExtent.height ) { + swap_chain_extent.height = surface_capabilities.maxImageExtent.height; + } + return swap_chain_extent; + } + + // Most of the cases we define size of the swap_chain images equal to current window's size + return surface_capabilities.currentExtent; + } + + VkImageUsageFlags Tutorial02::GetSwapChainUsageFlags( VkSurfaceCapabilitiesKHR &surface_capabilities ) { + // Color attachment flag must always be supported + // We can define other usage flags but we always need to check if they are supported + if( surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT ) { + return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + } + std::cout << "VK_IMAGE_USAGE_TRANSFER_DST image usage is not supported by the swap chain!" << std::endl + << "Supported swap chain's image usages include:" << std::endl + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT ? " VK_IMAGE_USAGE_TRANSFER_SRC\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT ? " VK_IMAGE_USAGE_TRANSFER_DST\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT ? " VK_IMAGE_USAGE_SAMPLED\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT ? " VK_IMAGE_USAGE_STORAGE\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_COLOR_ATTACHMENT\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT\n" : "") + << (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT ? " VK_IMAGE_USAGE_INPUT_ATTACHMENT" : "") + << std::endl; + return static_cast(-1); + } + + VkSurfaceTransformFlagBitsKHR Tutorial02::GetSwapChainTransform( VkSurfaceCapabilitiesKHR &surface_capabilities ) { + // Sometimes images must be transformed before they are presented (i.e. due to device's orienation + // being other than default orientation) + // If the specified transform is other than current transform, presentation engine will transform image + // during presentation operation; this operation may hit performance on some platforms + // Here we don't want any transformations to occur so if the identity transform is supported use it + // otherwise just use the same transform as current transform + if( surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ) { + return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + } else { + return surface_capabilities.currentTransform; + } + } + + VkPresentModeKHR Tutorial02::GetSwapChainPresentMode( std::vector &present_modes ) { + // FIFO present mode is always available + // MAILBOX is the lowest latency V-Sync enabled mode (something like triple-buffering) so use it if available + for( VkPresentModeKHR &present_mode : present_modes ) { + if( present_mode == VK_PRESENT_MODE_MAILBOX_KHR ) { + return present_mode; + } + } + for( VkPresentModeKHR &present_mode : present_modes ) { + if( present_mode == VK_PRESENT_MODE_FIFO_KHR ) { + return present_mode; + } + } + std::cout << "FIFO present mode is not supported by the swap chain!" << std::endl; + return static_cast(-1); + } + + bool Tutorial02::OnWindowSizeChanged() { + Clear(); + + if( !CreateSwapChain() ) { + return false; + } + if( !CreateCommandBuffers() ) { + return false; + } + return true; + } + + bool Tutorial02::CreateCommandBuffers() { + VkCommandPoolCreateInfo cmd_pool_create_info = { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0, // VkCommandPoolCreateFlags flags + Vulkan.PresentQueueFamilyIndex // uint32_t queueFamilyIndex + }; + + if( vkCreateCommandPool( Vulkan.Device, &cmd_pool_create_info, nullptr, &Vulkan.PresentQueueCmdPool ) != VK_SUCCESS ) { + std::cout << "Could not create a command pool!" << std::endl; + return false; + } + + uint32_t image_count = 0; + if( (vkGetSwapchainImagesKHR( Vulkan.Device, Vulkan.SwapChain, &image_count, nullptr ) != VK_SUCCESS) || + (image_count == 0) ) { + std::cout << "Could not get the number of swap chain images!" << std::endl; + return false; + } + + Vulkan.PresentQueueCmdBuffers.resize( image_count ); + + VkCommandBufferAllocateInfo cmd_buffer_allocate_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + Vulkan.PresentQueueCmdPool, // VkCommandPool commandPool + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level + image_count // uint32_t bufferCount + }; + if( vkAllocateCommandBuffers( Vulkan.Device, &cmd_buffer_allocate_info, &Vulkan.PresentQueueCmdBuffers[0] ) != VK_SUCCESS ) { + std::cout << "Could not allocate command buffers!" << std::endl; + return false; + } + + if( !RecordCommandBuffers() ) { + std::cout << "Could not record command buffers!" << std::endl; + return false; + } + return true; + } + + bool Tutorial02::RecordCommandBuffers() { + uint32_t image_count = static_cast(Vulkan.PresentQueueCmdBuffers.size()); + + std::vector swap_chain_images( image_count ); + if( vkGetSwapchainImagesKHR( Vulkan.Device, Vulkan.SwapChain, &image_count, &swap_chain_images[0] ) != VK_SUCCESS ) { + std::cout << "Could not get swap chain images!" << std::endl; + return false; + } + + VkCommandBufferBeginInfo cmd_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + VkClearColorValue clear_color = { + { 1.0f, 0.8f, 0.4f, 0.0f } + }; + + VkImageSubresourceRange image_subresource_range = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + for( uint32_t i = 0; i < image_count; ++i ) { + VkImageMemoryBarrier barrier_from_present_to_clear = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + swap_chain_images[i], // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + + VkImageMemoryBarrier barrier_from_clear_to_present = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + swap_chain_images[i], // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + + vkBeginCommandBuffer( Vulkan.PresentQueueCmdBuffers[i], &cmd_buffer_begin_info ); + vkCmdPipelineBarrier( Vulkan.PresentQueueCmdBuffers[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_clear ); + + vkCmdClearColorImage( Vulkan.PresentQueueCmdBuffers[i], swap_chain_images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &image_subresource_range ); + + vkCmdPipelineBarrier( Vulkan.PresentQueueCmdBuffers[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_clear_to_present ); + if( vkEndCommandBuffer( Vulkan.PresentQueueCmdBuffers[i] ) != VK_SUCCESS ) { + std::cout << "Could not record command buffers!" << std::endl; + return false; + } + } + + return true; + } + + void Tutorial02::Clear() { + if( Vulkan.Device != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( Vulkan.Device ); + + if( (Vulkan.PresentQueueCmdBuffers.size() > 0) && (Vulkan.PresentQueueCmdBuffers[0] != VK_NULL_HANDLE) ) { + vkFreeCommandBuffers( Vulkan.Device, Vulkan.PresentQueueCmdPool, static_cast(Vulkan.PresentQueueCmdBuffers.size()), &Vulkan.PresentQueueCmdBuffers[0] ); + Vulkan.PresentQueueCmdBuffers.clear(); + } + + if( Vulkan.PresentQueueCmdPool != VK_NULL_HANDLE ) { + vkDestroyCommandPool( Vulkan.Device, Vulkan.PresentQueueCmdPool, nullptr ); + Vulkan.PresentQueueCmdPool = VK_NULL_HANDLE; + } + } + } + + bool Tutorial02::Draw() { + uint32_t image_index; + VkResult result = vkAcquireNextImageKHR( Vulkan.Device, Vulkan.SwapChain, UINT64_MAX, Vulkan.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); + switch( result ) { + case VK_SUCCESS: + case VK_SUBOPTIMAL_KHR: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; + return false; + } + + VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT; + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + &Vulkan.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores + &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + &Vulkan.PresentQueueCmdBuffers[image_index], // const VkCommandBuffer *pCommandBuffers + 1, // uint32_t signalSemaphoreCount + &Vulkan.RenderingFinishedSemaphore // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( Vulkan.PresentQueue, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { + return false; + } + + VkPresentInfoKHR present_info = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + &Vulkan.RenderingFinishedSemaphore, // const VkSemaphore *pWaitSemaphores + 1, // uint32_t swapchainCount + &Vulkan.SwapChain, // const VkSwapchainKHR *pSwapchains + &image_index, // const uint32_t *pImageIndices + nullptr // VkResult *pResults + }; + result = vkQueuePresentKHR( Vulkan.PresentQueue, &present_info ); + + switch( result ) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_SUBOPTIMAL_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during image presentation!" << std::endl; + return false; + } + + return true; + } + + Tutorial02::~Tutorial02() { + Clear(); + + if( Vulkan.Device != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( Vulkan.Device ); + + if( Vulkan.ImageAvailableSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( Vulkan.Device, Vulkan.ImageAvailableSemaphore, nullptr ); + } + if( Vulkan.RenderingFinishedSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( Vulkan.Device, Vulkan.RenderingFinishedSemaphore, nullptr ); + } + if( Vulkan.SwapChain != VK_NULL_HANDLE ) { + vkDestroySwapchainKHR( Vulkan.Device, Vulkan.SwapChain, nullptr ); + } + vkDestroyDevice( Vulkan.Device, nullptr ); + } + + if( Vulkan.PresentationSurface != VK_NULL_HANDLE ) { + vkDestroySurfaceKHR( Vulkan.Instance, Vulkan.PresentationSurface, nullptr ); + } + + if( Vulkan.Instance != VK_NULL_HANDLE ) { + vkDestroyInstance( Vulkan.Instance, nullptr ); + } + + if( VulkanLibrary ) { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + FreeLibrary( VulkanLibrary ); +#elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) + dlclose( VulkanLibrary ); +#endif + } + } + } // namespace ApiWithoutSecrets \ No newline at end of file diff --git a/Project/Tutorial02/Tutorial02.h b/Project/Tutorial02/Tutorial02.h index 49333bf..efdfd69 100644 --- a/Project/Tutorial02/Tutorial02.h +++ b/Project/Tutorial02/Tutorial02.h @@ -1,107 +1,107 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(TUTORIAL_02_HEADER) -#define TUTORIAL_02_HEADER - -#include -#include "vulkan.h" -#include "OperatingSystem.h" - -namespace ApiWithoutSecrets { - - // ************************************************************ // - // VulkanTutorial02Parameters // - // // - // Vulkan specific parameters // - // ************************************************************ // - struct VulkanTutorial02Parameters { - VkInstance Instance; - VkPhysicalDevice PhysicalDevice; - VkDevice Device; - VkQueue GraphicsQueue; - VkQueue PresentQueue; - uint32_t GraphicsQueueFamilyIndex; - uint32_t PresentQueueFamilyIndex; - VkSurfaceKHR PresentationSurface; - VkSwapchainKHR SwapChain; - std::vector PresentQueueCmdBuffers; - VkCommandPool PresentQueueCmdPool; - VkSemaphore ImageAvailableSemaphore; - VkSemaphore RenderingFinishedSemaphore; - - VulkanTutorial02Parameters() : - Instance( VK_NULL_HANDLE ), - PhysicalDevice( VK_NULL_HANDLE ), - Device( VK_NULL_HANDLE ), - GraphicsQueue( VK_NULL_HANDLE ), - PresentQueue( VK_NULL_HANDLE ), - GraphicsQueueFamilyIndex( 0 ), - PresentQueueFamilyIndex( 0 ), - PresentationSurface( VK_NULL_HANDLE ), - SwapChain( VK_NULL_HANDLE ), - PresentQueueCmdBuffers( 0 ), - PresentQueueCmdPool( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // Tutorial02 // - // // - // Class for presenting Vulkan usage topics // - // ************************************************************ // - class Tutorial02 : public OS::TutorialBase { - public: - Tutorial02(); - ~Tutorial02(); - - bool PrepareVulkan( OS::WindowParameters parameters ); - bool CreateSwapChain(); - bool OnWindowSizeChanged() override; - bool CreateCommandBuffers(); - bool Draw() override; - - private: - OS::LibraryHandle VulkanLibrary; - OS::WindowParameters Window; - VulkanTutorial02Parameters Vulkan; - - bool LoadVulkanLibrary(); - bool LoadExportedEntryPoints(); - bool LoadGlobalLevelEntryPoints(); - bool CreateInstance(); - bool LoadInstanceLevelEntryPoints(); - bool CreatePresentationSurface(); - bool CreateDevice(); - bool CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &graphics_queue_family_index, uint32_t &present_queue_family_index ); - bool LoadDeviceLevelEntryPoints(); - bool GetDeviceQueue(); - bool CreateSemaphores(); - bool RecordCommandBuffers(); - void Clear(); - - bool CheckExtensionAvailability( const char *extension_name, const std::vector &available_extensions ); - uint32_t GetSwapChainNumImages( VkSurfaceCapabilitiesKHR &surface_capabilities ); - VkSurfaceFormatKHR GetSwapChainFormat( std::vector &surface_formats ); - VkExtent2D GetSwapChainExtent( VkSurfaceCapabilitiesKHR &surface_capabilities ); - VkImageUsageFlags GetSwapChainUsageFlags( VkSurfaceCapabilitiesKHR &surface_capabilities ); - VkSurfaceTransformFlagBitsKHR GetSwapChainTransform( VkSurfaceCapabilitiesKHR &surface_capabilities ); - VkPresentModeKHR GetSwapChainPresentMode( std::vector &present_modes ); - }; - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(TUTORIAL_02_HEADER) +#define TUTORIAL_02_HEADER + +#include +#include "vulkan.h" +#include "OperatingSystem.h" + +namespace ApiWithoutSecrets { + + // ************************************************************ // + // VulkanTutorial02Parameters // + // // + // Vulkan specific parameters // + // ************************************************************ // + struct VulkanTutorial02Parameters { + VkInstance Instance; + VkPhysicalDevice PhysicalDevice; + VkDevice Device; + VkQueue GraphicsQueue; + VkQueue PresentQueue; + uint32_t GraphicsQueueFamilyIndex; + uint32_t PresentQueueFamilyIndex; + VkSurfaceKHR PresentationSurface; + VkSwapchainKHR SwapChain; + std::vector PresentQueueCmdBuffers; + VkCommandPool PresentQueueCmdPool; + VkSemaphore ImageAvailableSemaphore; + VkSemaphore RenderingFinishedSemaphore; + + VulkanTutorial02Parameters() : + Instance( VK_NULL_HANDLE ), + PhysicalDevice( VK_NULL_HANDLE ), + Device( VK_NULL_HANDLE ), + GraphicsQueue( VK_NULL_HANDLE ), + PresentQueue( VK_NULL_HANDLE ), + GraphicsQueueFamilyIndex( 0 ), + PresentQueueFamilyIndex( 0 ), + PresentationSurface( VK_NULL_HANDLE ), + SwapChain( VK_NULL_HANDLE ), + PresentQueueCmdBuffers( 0 ), + PresentQueueCmdPool( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // Tutorial02 // + // // + // Class for presenting Vulkan usage topics // + // ************************************************************ // + class Tutorial02 : public OS::TutorialBase { + public: + Tutorial02(); + ~Tutorial02(); + + bool PrepareVulkan( OS::WindowParameters parameters ); + bool CreateSwapChain(); + bool OnWindowSizeChanged() override; + bool CreateCommandBuffers(); + bool Draw() override; + + private: + OS::LibraryHandle VulkanLibrary; + OS::WindowParameters Window; + VulkanTutorial02Parameters Vulkan; + + bool LoadVulkanLibrary(); + bool LoadExportedEntryPoints(); + bool LoadGlobalLevelEntryPoints(); + bool CreateInstance(); + bool LoadInstanceLevelEntryPoints(); + bool CreatePresentationSurface(); + bool CreateDevice(); + bool CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &graphics_queue_family_index, uint32_t &present_queue_family_index ); + bool LoadDeviceLevelEntryPoints(); + bool GetDeviceQueue(); + bool CreateSemaphores(); + bool RecordCommandBuffers(); + void Clear(); + + bool CheckExtensionAvailability( const char *extension_name, const std::vector &available_extensions ); + uint32_t GetSwapChainNumImages( VkSurfaceCapabilitiesKHR &surface_capabilities ); + VkSurfaceFormatKHR GetSwapChainFormat( std::vector &surface_formats ); + VkExtent2D GetSwapChainExtent( VkSurfaceCapabilitiesKHR &surface_capabilities ); + VkImageUsageFlags GetSwapChainUsageFlags( VkSurfaceCapabilitiesKHR &surface_capabilities ); + VkSurfaceTransformFlagBitsKHR GetSwapChainTransform( VkSurfaceCapabilitiesKHR &surface_capabilities ); + VkPresentModeKHR GetSwapChainPresentMode( std::vector &present_modes ); + }; + +} // namespace ApiWithoutSecrets + #endif // TUTORIAL_02_HEADER \ No newline at end of file diff --git a/Project/Tutorial02/main.cpp b/Project/Tutorial02/main.cpp index d9ce7ce..97f4c99 100644 --- a/Project/Tutorial02/main.cpp +++ b/Project/Tutorial02/main.cpp @@ -1,45 +1,45 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial02.h" - -int main( int argc, char **argv ) { - ApiWithoutSecrets::OS::Window window; - ApiWithoutSecrets::Tutorial02 tutorial02; - - // Window creation - if( !window.Create( "02 - Swap chain" ) ) { - return -1; - } - - // Vulkan preparations and initialization - if( !tutorial02.PrepareVulkan( window.GetParameters() ) ) { - return -1; - } - if( !tutorial02.CreateSwapChain() ) { - return -1; - } - if( !tutorial02.CreateCommandBuffers() ) { - return -1; - } - - // Rendering loop - if( !window.RenderingLoop( tutorial02 ) ) { - return -1; - } - - return 0; -} +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial02.h" + +int main( int argc, char **argv ) { + ApiWithoutSecrets::OS::Window window; + ApiWithoutSecrets::Tutorial02 tutorial02; + + // Window creation + if( !window.Create( "02 - Swap chain" ) ) { + return -1; + } + + // Vulkan preparations and initialization + if( !tutorial02.PrepareVulkan( window.GetParameters() ) ) { + return -1; + } + if( !tutorial02.CreateSwapChain() ) { + return -1; + } + if( !tutorial02.CreateCommandBuffers() ) { + return -1; + } + + // Rendering loop + if( !window.RenderingLoop( tutorial02 ) ) { + return -1; + } + + return 0; +} diff --git a/Project/Tutorial03/Tutorial03.cpp b/Project/Tutorial03/Tutorial03.cpp index 0e9c33b..559100d 100644 --- a/Project/Tutorial03/Tutorial03.cpp +++ b/Project/Tutorial03/Tutorial03.cpp @@ -1,596 +1,596 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial03.h" -#include "VulkanFunctions.h" - -namespace ApiWithoutSecrets { - - Tutorial03::Tutorial03() : - Vulkan() { - } - - bool Tutorial03::CreateRenderPass() { - VkAttachmentDescription attachment_descriptions[] = { - { - 0, // VkAttachmentDescriptionFlags flags - GetSwapChain().Format, // VkFormat format - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR // VkImageLayout finalLayout - } - }; - - VkAttachmentReference color_attachment_references[] = { - { - 0, // uint32_t attachment - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout - } - }; - - VkSubpassDescription subpass_descriptions[] = { - { - 0, // VkSubpassDescriptionFlags flags - VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint - 0, // uint32_t inputAttachmentCount - nullptr, // const VkAttachmentReference *pInputAttachments - 1, // uint32_t colorAttachmentCount - color_attachment_references, // const VkAttachmentReference *pColorAttachments - nullptr, // const VkAttachmentReference *pResolveAttachments - nullptr, // const VkAttachmentReference *pDepthStencilAttachment - 0, // uint32_t preserveAttachmentCount - nullptr // const uint32_t* pPreserveAttachments - } - }; - - VkRenderPassCreateInfo render_pass_create_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkRenderPassCreateFlags flags - 1, // uint32_t attachmentCount - attachment_descriptions, // const VkAttachmentDescription *pAttachments - 1, // uint32_t subpassCount - subpass_descriptions, // const VkSubpassDescription *pSubpasses - 0, // uint32_t dependencyCount - nullptr // const VkSubpassDependency *pDependencies - }; - - if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { - std::cout << "Could not create render pass!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial03::CreateFramebuffers() { - const std::vector &swap_chain_images = GetSwapChain().Images; - Vulkan.Framebuffers.resize( swap_chain_images.size() ); - - for( size_t i = 0; i < swap_chain_images.size(); ++i ) { - VkFramebufferCreateInfo framebuffer_create_info = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkFramebufferCreateFlags flags - Vulkan.RenderPass, // VkRenderPass renderPass - 1, // uint32_t attachmentCount - &swap_chain_images[i].View, // const VkImageView *pAttachments - 300, // uint32_t width - 300, // uint32_t height - 1 // uint32_t layers - }; - - if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &Vulkan.Framebuffers[i] ) != VK_SUCCESS ) { - std::cout << "Could not create a framebuffer!" << std::endl; - return false; - } - } - return true; - } - - Tools::AutoDeleter Tutorial03::CreateShaderModule( const char* filename ) { - const std::vector code = Tools::GetBinaryFileContents( filename ); - if( code.size() == 0 ) { - return Tools::AutoDeleter(); - } - - VkShaderModuleCreateInfo shader_module_create_info = { - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkShaderModuleCreateFlags flags - code.size(), // size_t codeSize - reinterpret_cast(&code[0]) // const uint32_t *pCode - }; - - VkShaderModule shader_module; - if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { - std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; - return Tools::AutoDeleter(); - } - - return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); - } - - Tools::AutoDeleter Tutorial03::CreatePipelineLayout() { - VkPipelineLayoutCreateInfo layout_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineLayoutCreateFlags flags - 0, // uint32_t setLayoutCount - nullptr, // const VkDescriptorSetLayout *pSetLayouts - 0, // uint32_t pushConstantRangeCount - nullptr // const VkPushConstantRange *pPushConstantRanges - }; - - VkPipelineLayout pipeline_layout; - if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &pipeline_layout ) != VK_SUCCESS ) { - std::cout << "Could not create pipeline layout!" << std::endl; - return Tools::AutoDeleter(); - } - - return Tools::AutoDeleter( pipeline_layout, vkDestroyPipelineLayout, GetDevice() ); - } - - bool Tutorial03::CreatePipeline() { - Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data03/vert.spv" ); - Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data03/frag.spv" ); - - if( !vertex_shader_module || !fragment_shader_module ) { - return false; - } - - std::vector shader_stage_create_infos = { - // Vertex shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage - vertex_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - }, - // Fragment shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage - fragment_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - } - }; - - VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineVertexInputStateCreateFlags flags; - 0, // uint32_t vertexBindingDescriptionCount - nullptr, // const VkVertexInputBindingDescription *pVertexBindingDescriptions - 0, // uint32_t vertexAttributeDescriptionCount - nullptr // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions - }; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineInputAssemblyStateCreateFlags flags - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology - VK_FALSE // VkBool32 primitiveRestartEnable - }; - - VkViewport viewport = { - 0.0f, // float x - 0.0f, // float y - 300.0f, // float width - 300.0f, // float height - 0.0f, // float minDepth - 1.0f // float maxDepth - }; - - VkRect2D scissor = { - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - { // VkExtent2D extent - 300, // int32_t width - 300 // int32_t height - } - }; - - VkPipelineViewportStateCreateInfo viewport_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineViewportStateCreateFlags flags - 1, // uint32_t viewportCount - &viewport, // const VkViewport *pViewports - 1, // uint32_t scissorCount - &scissor // const VkRect2D *pScissors - }; - - VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineRasterizationStateCreateFlags flags - VK_FALSE, // VkBool32 depthClampEnable - VK_FALSE, // VkBool32 rasterizerDiscardEnable - VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode - VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode - VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace - VK_FALSE, // VkBool32 depthBiasEnable - 0.0f, // float depthBiasConstantFactor - 0.0f, // float depthBiasClamp - 0.0f, // float depthBiasSlopeFactor - 1.0f // float lineWidth - }; - - VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineMultisampleStateCreateFlags flags - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples - VK_FALSE, // VkBool32 sampleShadingEnable - 1.0f, // float minSampleShading - nullptr, // const VkSampleMask *pSampleMask - VK_FALSE, // VkBool32 alphaToCoverageEnable - VK_FALSE // VkBool32 alphaToOneEnable - }; - - VkPipelineColorBlendAttachmentState color_blend_attachment_state = { - VK_FALSE, // VkBool32 blendEnable - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT - }; - - VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineColorBlendStateCreateFlags flags - VK_FALSE, // VkBool32 logicOpEnable - VK_LOGIC_OP_COPY, // VkLogicOp logicOp - 1, // uint32_t attachmentCount - &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments - { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] - }; - - Tools::AutoDeleter pipeline_layout = CreatePipelineLayout(); - if( !pipeline_layout ) { - return false; - } - - VkGraphicsPipelineCreateInfo pipeline_create_info = { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineCreateFlags flags - static_cast(shader_stage_create_infos.size()), // uint32_t stageCount - &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages - &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; - &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState - nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState - &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState - &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState - &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState - nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState - &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState - nullptr, // const VkPipelineDynamicStateCreateInfo *pDynamicState - pipeline_layout.Get(), // VkPipelineLayout layout - Vulkan.RenderPass, // VkRenderPass renderPass - 0, // uint32_t subpass - VK_NULL_HANDLE, // VkPipeline basePipelineHandle - -1 // int32_t basePipelineIndex - }; - - if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { - std::cout << "Could not create graphics pipeline!" << std::endl; - return false; - } - return true; - } - - bool Tutorial03::CreateSemaphores() { - VkSemaphoreCreateInfo semaphore_create_info = { - VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0 // VkSemaphoreCreateFlags flags - }; - - if( (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.ImageAvailableSemaphore ) != VK_SUCCESS) || - (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingFinishedSemaphore ) != VK_SUCCESS) ) { - std::cout << "Could not create semaphores!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial03::CreateCommandBuffers() { - if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.GraphicsCommandPool ) ) { - std::cout << "Could not create command pool!" << std::endl; - return false; - } - - uint32_t image_count = static_cast(GetSwapChain().Images.size()); - Vulkan.GraphicsCommandBuffers.resize( image_count, VK_NULL_HANDLE ); - - if( !AllocateCommandBuffers( Vulkan.GraphicsCommandPool, image_count, &Vulkan.GraphicsCommandBuffers[0] ) ) { - std::cout << "Could not allocate command buffers!" << std::endl; - return false; - } - return true; - } - - bool Tutorial03::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { - VkCommandPoolCreateInfo cmd_pool_create_info = { - VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkCommandPoolCreateFlags flags - queue_family_index // uint32_t queueFamilyIndex - }; - - if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { - return false; - } - return true; - } - - bool Tutorial03::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { - VkCommandBufferAllocateInfo command_buffer_allocate_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - pool, // VkCommandPool commandPool - VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level - count // uint32_t bufferCount - }; - - if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { - return false; - } - return true; - } - - bool Tutorial03::RecordCommandBuffers() { - VkCommandBufferBeginInfo graphics_commandd_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - VkImageSubresourceRange image_subresource_range = { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }; - - VkClearValue clear_value = { - { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color - }; - - const std::vector& swap_chain_images = GetSwapChain().Images; - - for( size_t i = 0; i < Vulkan.GraphicsCommandBuffers.size(); ++i ) { - vkBeginCommandBuffer( Vulkan.GraphicsCommandBuffers[i], &graphics_commandd_buffer_begin_info ); - - if( GetPresentQueue().Handle != GetGraphicsQueue().Handle ) { - VkImageMemoryBarrier barrier_from_present_to_draw = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout - GetPresentQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex - GetGraphicsQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex - swap_chain_images[i].Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( Vulkan.GraphicsCommandBuffers[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); - } - - VkRenderPassBeginInfo render_pass_begin_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.RenderPass, // VkRenderPass renderPass - Vulkan.Framebuffers[i], // VkFramebuffer framebuffer - { // VkRect2D renderArea - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - { // VkExtent2D extent - 300, // int32_t width - 300, // int32_t height - } - }, - 1, // uint32_t clearValueCount - &clear_value // const VkClearValue *pClearValues - }; - - vkCmdBeginRenderPass( Vulkan.GraphicsCommandBuffers[i], &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); - - vkCmdBindPipeline( Vulkan.GraphicsCommandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); - - vkCmdDraw( Vulkan.GraphicsCommandBuffers[i], 3, 1, 0, 0 ); - - vkCmdEndRenderPass( Vulkan.GraphicsCommandBuffers[i] ); - - if( GetGraphicsQueue().Handle != GetPresentQueue().Handle ) { - VkImageMemoryBarrier barrier_from_draw_to_present = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout - GetGraphicsQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex - GetPresentQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex - swap_chain_images[i].Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( Vulkan.GraphicsCommandBuffers[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); - } - if( vkEndCommandBuffer( Vulkan.GraphicsCommandBuffers[i] ) != VK_SUCCESS ) { - std::cout << "Could not record command buffer!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial03::ChildOnWindowSizeChanged() { - if( !CreateRenderPass() ) { - return false; - } - if( !CreateFramebuffers() ) { - return false; - } - if( !CreatePipeline() ) { - return false; - } - if( !CreateCommandBuffers() ) { - return false; - } - if( !RecordCommandBuffers() ) { - return false; - } - - return true; - } - - bool Tutorial03::Draw() { - VkSwapchainKHR swap_chain = GetSwapChain().Handle; - uint32_t image_index; - - VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, Vulkan.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); - switch( result ) { - case VK_SUCCESS: - case VK_SUBOPTIMAL_KHR: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; - return false; - } - - VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - &Vulkan.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores - &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - &Vulkan.GraphicsCommandBuffers[image_index], // const VkCommandBuffer *pCommandBuffers - 1, // uint32_t signalSemaphoreCount - &Vulkan.RenderingFinishedSemaphore // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { - return false; - } - - VkPresentInfoKHR present_info = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - &Vulkan.RenderingFinishedSemaphore, // const VkSemaphore *pWaitSemaphores - 1, // uint32_t swapchainCount - &swap_chain, // const VkSwapchainKHR *pSwapchains - &image_index, // const uint32_t *pImageIndices - nullptr // VkResult *pResults - }; - result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); - - switch( result ) { - case VK_SUCCESS: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - case VK_SUBOPTIMAL_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during image presentation!" << std::endl; - return false; - } - - return true; - } - - void Tutorial03::ChildClear() { - if( GetDevice() != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( GetDevice() ); - - if( (Vulkan.GraphicsCommandBuffers.size() > 0) && (Vulkan.GraphicsCommandBuffers[0] != VK_NULL_HANDLE) ) { - vkFreeCommandBuffers( GetDevice(), Vulkan.GraphicsCommandPool, static_cast(Vulkan.GraphicsCommandBuffers.size()), &Vulkan.GraphicsCommandBuffers[0] ); - Vulkan.GraphicsCommandBuffers.clear(); - } - - if( Vulkan.GraphicsCommandPool != VK_NULL_HANDLE ) { - vkDestroyCommandPool( GetDevice(), Vulkan.GraphicsCommandPool, nullptr ); - Vulkan.GraphicsCommandPool = VK_NULL_HANDLE; - } - - if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { - vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); - Vulkan.GraphicsPipeline = VK_NULL_HANDLE; - } - - if( Vulkan.RenderPass != VK_NULL_HANDLE ) { - vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); - Vulkan.RenderPass = VK_NULL_HANDLE; - } - - for( size_t i = 0; i < Vulkan.Framebuffers.size(); ++i ) { - if( Vulkan.Framebuffers[i] != VK_NULL_HANDLE ) { - vkDestroyFramebuffer( GetDevice(), Vulkan.Framebuffers[i], nullptr ); - Vulkan.Framebuffers[i] = VK_NULL_HANDLE; - } - } - Vulkan.Framebuffers.clear(); - } - } - - Tutorial03::~Tutorial03() { - ChildClear(); - - if( GetDevice() != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( GetDevice() ); - - if( Vulkan.ImageAvailableSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.ImageAvailableSemaphore, nullptr ); - } - - if( Vulkan.RenderingFinishedSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.RenderingFinishedSemaphore, nullptr ); - } - } - } - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial03.h" +#include "VulkanFunctions.h" + +namespace ApiWithoutSecrets { + + Tutorial03::Tutorial03() : + Vulkan() { + } + + bool Tutorial03::CreateRenderPass() { + VkAttachmentDescription attachment_descriptions[] = { + { + 0, // VkAttachmentDescriptionFlags flags + GetSwapChain().Format, // VkFormat format + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR // VkImageLayout finalLayout + } + }; + + VkAttachmentReference color_attachment_references[] = { + { + 0, // uint32_t attachment + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout + } + }; + + VkSubpassDescription subpass_descriptions[] = { + { + 0, // VkSubpassDescriptionFlags flags + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint + 0, // uint32_t inputAttachmentCount + nullptr, // const VkAttachmentReference *pInputAttachments + 1, // uint32_t colorAttachmentCount + color_attachment_references, // const VkAttachmentReference *pColorAttachments + nullptr, // const VkAttachmentReference *pResolveAttachments + nullptr, // const VkAttachmentReference *pDepthStencilAttachment + 0, // uint32_t preserveAttachmentCount + nullptr // const uint32_t* pPreserveAttachments + } + }; + + VkRenderPassCreateInfo render_pass_create_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkRenderPassCreateFlags flags + 1, // uint32_t attachmentCount + attachment_descriptions, // const VkAttachmentDescription *pAttachments + 1, // uint32_t subpassCount + subpass_descriptions, // const VkSubpassDescription *pSubpasses + 0, // uint32_t dependencyCount + nullptr // const VkSubpassDependency *pDependencies + }; + + if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { + std::cout << "Could not create render pass!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial03::CreateFramebuffers() { + const std::vector &swap_chain_images = GetSwapChain().Images; + Vulkan.Framebuffers.resize( swap_chain_images.size() ); + + for( size_t i = 0; i < swap_chain_images.size(); ++i ) { + VkFramebufferCreateInfo framebuffer_create_info = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkFramebufferCreateFlags flags + Vulkan.RenderPass, // VkRenderPass renderPass + 1, // uint32_t attachmentCount + &swap_chain_images[i].View, // const VkImageView *pAttachments + 300, // uint32_t width + 300, // uint32_t height + 1 // uint32_t layers + }; + + if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &Vulkan.Framebuffers[i] ) != VK_SUCCESS ) { + std::cout << "Could not create a framebuffer!" << std::endl; + return false; + } + } + return true; + } + + Tools::AutoDeleter Tutorial03::CreateShaderModule( const char* filename ) { + const std::vector code = Tools::GetBinaryFileContents( filename ); + if( code.size() == 0 ) { + return Tools::AutoDeleter(); + } + + VkShaderModuleCreateInfo shader_module_create_info = { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkShaderModuleCreateFlags flags + code.size(), // size_t codeSize + reinterpret_cast(&code[0]) // const uint32_t *pCode + }; + + VkShaderModule shader_module; + if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { + std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; + return Tools::AutoDeleter(); + } + + return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); + } + + Tools::AutoDeleter Tutorial03::CreatePipelineLayout() { + VkPipelineLayoutCreateInfo layout_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineLayoutCreateFlags flags + 0, // uint32_t setLayoutCount + nullptr, // const VkDescriptorSetLayout *pSetLayouts + 0, // uint32_t pushConstantRangeCount + nullptr // const VkPushConstantRange *pPushConstantRanges + }; + + VkPipelineLayout pipeline_layout; + if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &pipeline_layout ) != VK_SUCCESS ) { + std::cout << "Could not create pipeline layout!" << std::endl; + return Tools::AutoDeleter(); + } + + return Tools::AutoDeleter( pipeline_layout, vkDestroyPipelineLayout, GetDevice() ); + } + + bool Tutorial03::CreatePipeline() { + Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data03/vert.spv" ); + Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data03/frag.spv" ); + + if( !vertex_shader_module || !fragment_shader_module ) { + return false; + } + + std::vector shader_stage_create_infos = { + // Vertex shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage + vertex_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + }, + // Fragment shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage + fragment_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + } + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineVertexInputStateCreateFlags flags; + 0, // uint32_t vertexBindingDescriptionCount + nullptr, // const VkVertexInputBindingDescription *pVertexBindingDescriptions + 0, // uint32_t vertexAttributeDescriptionCount + nullptr // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions + }; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineInputAssemblyStateCreateFlags flags + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology + VK_FALSE // VkBool32 primitiveRestartEnable + }; + + VkViewport viewport = { + 0.0f, // float x + 0.0f, // float y + 300.0f, // float width + 300.0f, // float height + 0.0f, // float minDepth + 1.0f // float maxDepth + }; + + VkRect2D scissor = { + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + { // VkExtent2D extent + 300, // int32_t width + 300 // int32_t height + } + }; + + VkPipelineViewportStateCreateInfo viewport_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineViewportStateCreateFlags flags + 1, // uint32_t viewportCount + &viewport, // const VkViewport *pViewports + 1, // uint32_t scissorCount + &scissor // const VkRect2D *pScissors + }; + + VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineRasterizationStateCreateFlags flags + VK_FALSE, // VkBool32 depthClampEnable + VK_FALSE, // VkBool32 rasterizerDiscardEnable + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode + VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace + VK_FALSE, // VkBool32 depthBiasEnable + 0.0f, // float depthBiasConstantFactor + 0.0f, // float depthBiasClamp + 0.0f, // float depthBiasSlopeFactor + 1.0f // float lineWidth + }; + + VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineMultisampleStateCreateFlags flags + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples + VK_FALSE, // VkBool32 sampleShadingEnable + 1.0f, // float minSampleShading + nullptr, // const VkSampleMask *pSampleMask + VK_FALSE, // VkBool32 alphaToCoverageEnable + VK_FALSE // VkBool32 alphaToOneEnable + }; + + VkPipelineColorBlendAttachmentState color_blend_attachment_state = { + VK_FALSE, // VkBool32 blendEnable + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT + }; + + VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineColorBlendStateCreateFlags flags + VK_FALSE, // VkBool32 logicOpEnable + VK_LOGIC_OP_COPY, // VkLogicOp logicOp + 1, // uint32_t attachmentCount + &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments + { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] + }; + + Tools::AutoDeleter pipeline_layout = CreatePipelineLayout(); + if( !pipeline_layout ) { + return false; + } + + VkGraphicsPipelineCreateInfo pipeline_create_info = { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineCreateFlags flags + static_cast(shader_stage_create_infos.size()), // uint32_t stageCount + &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages + &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; + &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState + nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState + &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState + &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState + &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState + nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState + &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState + nullptr, // const VkPipelineDynamicStateCreateInfo *pDynamicState + pipeline_layout.Get(), // VkPipelineLayout layout + Vulkan.RenderPass, // VkRenderPass renderPass + 0, // uint32_t subpass + VK_NULL_HANDLE, // VkPipeline basePipelineHandle + -1 // int32_t basePipelineIndex + }; + + if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { + std::cout << "Could not create graphics pipeline!" << std::endl; + return false; + } + return true; + } + + bool Tutorial03::CreateSemaphores() { + VkSemaphoreCreateInfo semaphore_create_info = { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0 // VkSemaphoreCreateFlags flags + }; + + if( (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.ImageAvailableSemaphore ) != VK_SUCCESS) || + (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingFinishedSemaphore ) != VK_SUCCESS) ) { + std::cout << "Could not create semaphores!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial03::CreateCommandBuffers() { + if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.GraphicsCommandPool ) ) { + std::cout << "Could not create command pool!" << std::endl; + return false; + } + + uint32_t image_count = static_cast(GetSwapChain().Images.size()); + Vulkan.GraphicsCommandBuffers.resize( image_count, VK_NULL_HANDLE ); + + if( !AllocateCommandBuffers( Vulkan.GraphicsCommandPool, image_count, &Vulkan.GraphicsCommandBuffers[0] ) ) { + std::cout << "Could not allocate command buffers!" << std::endl; + return false; + } + return true; + } + + bool Tutorial03::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { + VkCommandPoolCreateInfo cmd_pool_create_info = { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkCommandPoolCreateFlags flags + queue_family_index // uint32_t queueFamilyIndex + }; + + if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { + return false; + } + return true; + } + + bool Tutorial03::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { + VkCommandBufferAllocateInfo command_buffer_allocate_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + pool, // VkCommandPool commandPool + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level + count // uint32_t bufferCount + }; + + if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { + return false; + } + return true; + } + + bool Tutorial03::RecordCommandBuffers() { + VkCommandBufferBeginInfo graphics_commandd_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + VkImageSubresourceRange image_subresource_range = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + VkClearValue clear_value = { + { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color + }; + + const std::vector& swap_chain_images = GetSwapChain().Images; + + for( size_t i = 0; i < Vulkan.GraphicsCommandBuffers.size(); ++i ) { + vkBeginCommandBuffer( Vulkan.GraphicsCommandBuffers[i], &graphics_commandd_buffer_begin_info ); + + if( GetPresentQueue().Handle != GetGraphicsQueue().Handle ) { + VkImageMemoryBarrier barrier_from_present_to_draw = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout + GetPresentQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex + GetGraphicsQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex + swap_chain_images[i].Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( Vulkan.GraphicsCommandBuffers[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); + } + + VkRenderPassBeginInfo render_pass_begin_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.RenderPass, // VkRenderPass renderPass + Vulkan.Framebuffers[i], // VkFramebuffer framebuffer + { // VkRect2D renderArea + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + { // VkExtent2D extent + 300, // int32_t width + 300, // int32_t height + } + }, + 1, // uint32_t clearValueCount + &clear_value // const VkClearValue *pClearValues + }; + + vkCmdBeginRenderPass( Vulkan.GraphicsCommandBuffers[i], &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); + + vkCmdBindPipeline( Vulkan.GraphicsCommandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); + + vkCmdDraw( Vulkan.GraphicsCommandBuffers[i], 3, 1, 0, 0 ); + + vkCmdEndRenderPass( Vulkan.GraphicsCommandBuffers[i] ); + + if( GetGraphicsQueue().Handle != GetPresentQueue().Handle ) { + VkImageMemoryBarrier barrier_from_draw_to_present = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout + GetGraphicsQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex + GetPresentQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex + swap_chain_images[i].Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( Vulkan.GraphicsCommandBuffers[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); + } + if( vkEndCommandBuffer( Vulkan.GraphicsCommandBuffers[i] ) != VK_SUCCESS ) { + std::cout << "Could not record command buffer!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial03::ChildOnWindowSizeChanged() { + if( !CreateRenderPass() ) { + return false; + } + if( !CreateFramebuffers() ) { + return false; + } + if( !CreatePipeline() ) { + return false; + } + if( !CreateCommandBuffers() ) { + return false; + } + if( !RecordCommandBuffers() ) { + return false; + } + + return true; + } + + bool Tutorial03::Draw() { + VkSwapchainKHR swap_chain = GetSwapChain().Handle; + uint32_t image_index; + + VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, Vulkan.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); + switch( result ) { + case VK_SUCCESS: + case VK_SUBOPTIMAL_KHR: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; + return false; + } + + VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + &Vulkan.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores + &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + &Vulkan.GraphicsCommandBuffers[image_index], // const VkCommandBuffer *pCommandBuffers + 1, // uint32_t signalSemaphoreCount + &Vulkan.RenderingFinishedSemaphore // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { + return false; + } + + VkPresentInfoKHR present_info = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + &Vulkan.RenderingFinishedSemaphore, // const VkSemaphore *pWaitSemaphores + 1, // uint32_t swapchainCount + &swap_chain, // const VkSwapchainKHR *pSwapchains + &image_index, // const uint32_t *pImageIndices + nullptr // VkResult *pResults + }; + result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); + + switch( result ) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_SUBOPTIMAL_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during image presentation!" << std::endl; + return false; + } + + return true; + } + + void Tutorial03::ChildClear() { + if( GetDevice() != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( GetDevice() ); + + if( (Vulkan.GraphicsCommandBuffers.size() > 0) && (Vulkan.GraphicsCommandBuffers[0] != VK_NULL_HANDLE) ) { + vkFreeCommandBuffers( GetDevice(), Vulkan.GraphicsCommandPool, static_cast(Vulkan.GraphicsCommandBuffers.size()), &Vulkan.GraphicsCommandBuffers[0] ); + Vulkan.GraphicsCommandBuffers.clear(); + } + + if( Vulkan.GraphicsCommandPool != VK_NULL_HANDLE ) { + vkDestroyCommandPool( GetDevice(), Vulkan.GraphicsCommandPool, nullptr ); + Vulkan.GraphicsCommandPool = VK_NULL_HANDLE; + } + + if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { + vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); + Vulkan.GraphicsPipeline = VK_NULL_HANDLE; + } + + if( Vulkan.RenderPass != VK_NULL_HANDLE ) { + vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); + Vulkan.RenderPass = VK_NULL_HANDLE; + } + + for( size_t i = 0; i < Vulkan.Framebuffers.size(); ++i ) { + if( Vulkan.Framebuffers[i] != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( GetDevice(), Vulkan.Framebuffers[i], nullptr ); + Vulkan.Framebuffers[i] = VK_NULL_HANDLE; + } + } + Vulkan.Framebuffers.clear(); + } + } + + Tutorial03::~Tutorial03() { + ChildClear(); + + if( GetDevice() != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( GetDevice() ); + + if( Vulkan.ImageAvailableSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.ImageAvailableSemaphore, nullptr ); + } + + if( Vulkan.RenderingFinishedSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.RenderingFinishedSemaphore, nullptr ); + } + } + } + } // namespace ApiWithoutSecrets \ No newline at end of file diff --git a/Project/Tutorial03/Tutorial03.h b/Project/Tutorial03/Tutorial03.h index 56fa077..df8d420 100644 --- a/Project/Tutorial03/Tutorial03.h +++ b/Project/Tutorial03/Tutorial03.h @@ -1,83 +1,83 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(TUTORIAL_03_HEADER) -#define TUTORIAL_03_HEADER - -#include "VulkanCommon.h" -#include "Tools.h" - -namespace ApiWithoutSecrets { - - // ************************************************************ // - // VulkanTutorial03Parameters // - // // - // Vulkan specific parameters // - // ************************************************************ // - struct VulkanTutorial03Parameters { - VkRenderPass RenderPass; - std::vector Framebuffers; - VkPipeline GraphicsPipeline; - VkSemaphore ImageAvailableSemaphore; - VkSemaphore RenderingFinishedSemaphore; - VkCommandPool GraphicsCommandPool; - std::vector GraphicsCommandBuffers; - - VulkanTutorial03Parameters() : - RenderPass( VK_NULL_HANDLE ), - Framebuffers(), - GraphicsCommandPool( VK_NULL_HANDLE ), - GraphicsCommandBuffers(), - GraphicsPipeline( VK_NULL_HANDLE ), - ImageAvailableSemaphore( VK_NULL_HANDLE ), - RenderingFinishedSemaphore( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // Tutorial03 // - // // - // Class for presenting Vulkan usage topics // - // ************************************************************ // - class Tutorial03 : public VulkanCommon { - public: - Tutorial03(); - ~Tutorial03(); - - bool CreateRenderPass(); - bool CreateFramebuffers(); - bool CreatePipeline(); - bool CreateSemaphores(); - bool CreateCommandBuffers(); - bool RecordCommandBuffers(); - - bool Draw() override; - - private: - VulkanTutorial03Parameters Vulkan; - - Tools::AutoDeleter CreateShaderModule( const char* filename ); - Tools::AutoDeleter CreatePipelineLayout(); - bool CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ); - bool AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ); - - void ChildClear() override; - bool ChildOnWindowSizeChanged() override; - }; - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(TUTORIAL_03_HEADER) +#define TUTORIAL_03_HEADER + +#include "VulkanCommon.h" +#include "Tools.h" + +namespace ApiWithoutSecrets { + + // ************************************************************ // + // VulkanTutorial03Parameters // + // // + // Vulkan specific parameters // + // ************************************************************ // + struct VulkanTutorial03Parameters { + VkRenderPass RenderPass; + std::vector Framebuffers; + VkPipeline GraphicsPipeline; + VkSemaphore ImageAvailableSemaphore; + VkSemaphore RenderingFinishedSemaphore; + VkCommandPool GraphicsCommandPool; + std::vector GraphicsCommandBuffers; + + VulkanTutorial03Parameters() : + RenderPass( VK_NULL_HANDLE ), + Framebuffers(), + GraphicsCommandPool( VK_NULL_HANDLE ), + GraphicsCommandBuffers(), + GraphicsPipeline( VK_NULL_HANDLE ), + ImageAvailableSemaphore( VK_NULL_HANDLE ), + RenderingFinishedSemaphore( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // Tutorial03 // + // // + // Class for presenting Vulkan usage topics // + // ************************************************************ // + class Tutorial03 : public VulkanCommon { + public: + Tutorial03(); + ~Tutorial03(); + + bool CreateRenderPass(); + bool CreateFramebuffers(); + bool CreatePipeline(); + bool CreateSemaphores(); + bool CreateCommandBuffers(); + bool RecordCommandBuffers(); + + bool Draw() override; + + private: + VulkanTutorial03Parameters Vulkan; + + Tools::AutoDeleter CreateShaderModule( const char* filename ); + Tools::AutoDeleter CreatePipelineLayout(); + bool CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ); + bool AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ); + + void ChildClear() override; + bool ChildOnWindowSizeChanged() override; + }; + +} // namespace ApiWithoutSecrets + #endif // TUTORIAL_03_HEADER \ No newline at end of file diff --git a/Project/Tutorial03/main.cpp b/Project/Tutorial03/main.cpp index 8ac26c3..2d08d99 100644 --- a/Project/Tutorial03/main.cpp +++ b/Project/Tutorial03/main.cpp @@ -1,59 +1,59 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial03.h" - -int main( int argc, char **argv ) { - ApiWithoutSecrets::OS::Window window; - ApiWithoutSecrets::Tutorial03 tutorial03; - - // Window creation - if( !window.Create( "03 - First Triangle" ) ) { - return -1; - } - - // Vulkan preparations and initialization - if( !tutorial03.PrepareVulkan( window.GetParameters() ) ) { - return -1; - } - - // Tutorial 03 - if( !tutorial03.CreateRenderPass() ) { - return -1; - } - if( !tutorial03.CreateFramebuffers() ) { - return -1; - } - if( !tutorial03.CreatePipeline() ) { - return -1; - } - if( !tutorial03.CreateSemaphores() ) { - return -1; - } - if( !tutorial03.CreateCommandBuffers() ) { - return -1; - } - if( !tutorial03.RecordCommandBuffers() ) { - return -1; - } - - // Rendering loop - if( !window.RenderingLoop( tutorial03 ) ) { - return -1; - } - - return 0; -} +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial03.h" + +int main( int argc, char **argv ) { + ApiWithoutSecrets::OS::Window window; + ApiWithoutSecrets::Tutorial03 tutorial03; + + // Window creation + if( !window.Create( "03 - First Triangle" ) ) { + return -1; + } + + // Vulkan preparations and initialization + if( !tutorial03.PrepareVulkan( window.GetParameters() ) ) { + return -1; + } + + // Tutorial 03 + if( !tutorial03.CreateRenderPass() ) { + return -1; + } + if( !tutorial03.CreateFramebuffers() ) { + return -1; + } + if( !tutorial03.CreatePipeline() ) { + return -1; + } + if( !tutorial03.CreateSemaphores() ) { + return -1; + } + if( !tutorial03.CreateCommandBuffers() ) { + return -1; + } + if( !tutorial03.RecordCommandBuffers() ) { + return -1; + } + + // Rendering loop + if( !window.RenderingLoop( tutorial03 ) ) { + return -1; + } + + return 0; +} diff --git a/Project/Tutorial04/Tutorial04.cpp b/Project/Tutorial04/Tutorial04.cpp index 07ea42f..2c6c1db 100644 --- a/Project/Tutorial04/Tutorial04.cpp +++ b/Project/Tutorial04/Tutorial04.cpp @@ -1,784 +1,784 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include -#include "Tutorial04.h" -#include "VulkanFunctions.h" - -namespace ApiWithoutSecrets { - - Tutorial04::Tutorial04() : - Vulkan() { - } - - bool Tutorial04::CreateRenderPass() { - VkAttachmentDescription attachment_descriptions[] = { - { - 0, // VkAttachmentDescriptionFlags flags - GetSwapChain().Format, // VkFormat format - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR // VkImageLayout finalLayout - } - }; - - VkAttachmentReference color_attachment_references[] = { - { - 0, // uint32_t attachment - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout - } - }; - - VkSubpassDescription subpass_descriptions[] = { - { - 0, // VkSubpassDescriptionFlags flags - VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint - 0, // uint32_t inputAttachmentCount - nullptr, // const VkAttachmentReference *pInputAttachments - 1, // uint32_t colorAttachmentCount - color_attachment_references, // const VkAttachmentReference *pColorAttachments - nullptr, // const VkAttachmentReference *pResolveAttachments - nullptr, // const VkAttachmentReference *pDepthStencilAttachment - 0, // uint32_t preserveAttachmentCount - nullptr // const uint32_t* pPreserveAttachments - } - }; - - std::vector dependencies = { - { - VK_SUBPASS_EXTERNAL, // uint32_t srcSubpass - 0, // uint32_t dstSubpass - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags dstStageMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask - VK_DEPENDENCY_BY_REGION_BIT // VkDependencyFlags dependencyFlags - }, - { - 0, // uint32_t srcSubpass - VK_SUBPASS_EXTERNAL, // uint32_t dstSubpass - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // VkPipelineStageFlags dstStageMask - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_DEPENDENCY_BY_REGION_BIT // VkDependencyFlags dependencyFlags - } - }; - - VkRenderPassCreateInfo render_pass_create_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkRenderPassCreateFlags flags - 1, // uint32_t attachmentCount - attachment_descriptions, // const VkAttachmentDescription *pAttachments - 1, // uint32_t subpassCount - subpass_descriptions, // const VkSubpassDescription *pSubpasses - static_cast(dependencies.size()), // uint32_t dependencyCount - &dependencies[0] // const VkSubpassDependency *pDependencies - }; - - if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { - std::cout << "Could not create render pass!" << std::endl; - return false; - } - - return true; - } - - Tools::AutoDeleter Tutorial04::CreateShaderModule( const char* filename ) { - const std::vector code = Tools::GetBinaryFileContents( filename ); - if( code.size() == 0 ) { - return Tools::AutoDeleter(); - } - - VkShaderModuleCreateInfo shader_module_create_info = { - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkShaderModuleCreateFlags flags - code.size(), // size_t codeSize - reinterpret_cast(&code[0]) // const uint32_t *pCode - }; - - VkShaderModule shader_module; - if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { - std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; - return Tools::AutoDeleter(); - } - - return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); - } - - Tools::AutoDeleter Tutorial04::CreatePipelineLayout() { - VkPipelineLayoutCreateInfo layout_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineLayoutCreateFlags flags - 0, // uint32_t setLayoutCount - nullptr, // const VkDescriptorSetLayout *pSetLayouts - 0, // uint32_t pushConstantRangeCount - nullptr // const VkPushConstantRange *pPushConstantRanges - }; - - VkPipelineLayout pipeline_layout; - if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &pipeline_layout ) != VK_SUCCESS ) { - std::cout << "Could not create pipeline layout!" << std::endl; - return Tools::AutoDeleter(); - } - - return Tools::AutoDeleter( pipeline_layout, vkDestroyPipelineLayout, GetDevice() ); - } - - bool Tutorial04::CreatePipeline() { - Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data04/vert.spv" ); - Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data04/frag.spv" ); - - if( !vertex_shader_module || !fragment_shader_module ) { - return false; - } - - std::vector shader_stage_create_infos = { - // Vertex shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage - vertex_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - }, - // Fragment shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage - fragment_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - } - }; - - std::vector vertex_binding_descriptions = { - { - 0, // uint32_t binding - sizeof(VertexData), // uint32_t stride - VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate - } - }; - - std::vector vertex_attribute_descriptions = { - { - 0, // uint32_t location - vertex_binding_descriptions[0].binding, // uint32_t binding - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format - offsetof(struct VertexData, x) // uint32_t offset - }, - { - 1, // uint32_t location - vertex_binding_descriptions[0].binding, // uint32_t binding - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format - offsetof(struct VertexData, r) // uint32_t offset - } - }; - - VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineVertexInputStateCreateFlags flags - static_cast(vertex_binding_descriptions.size()), // uint32_t vertexBindingDescriptionCount - &vertex_binding_descriptions[0], // const VkVertexInputBindingDescription *pVertexBindingDescriptions - static_cast(vertex_attribute_descriptions.size()), // uint32_t vertexAttributeDescriptionCount - &vertex_attribute_descriptions[0] // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions - }; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineInputAssemblyStateCreateFlags flags - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology - VK_FALSE // VkBool32 primitiveRestartEnable - }; - - VkPipelineViewportStateCreateInfo viewport_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineViewportStateCreateFlags flags - 1, // uint32_t viewportCount - nullptr, // const VkViewport *pViewports - 1, // uint32_t scissorCount - nullptr // const VkRect2D *pScissors - }; - - VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineRasterizationStateCreateFlags flags - VK_FALSE, // VkBool32 depthClampEnable - VK_FALSE, // VkBool32 rasterizerDiscardEnable - VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode - VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode - VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace - VK_FALSE, // VkBool32 depthBiasEnable - 0.0f, // float depthBiasConstantFactor - 0.0f, // float depthBiasClamp - 0.0f, // float depthBiasSlopeFactor - 1.0f // float lineWidth - }; - - VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineMultisampleStateCreateFlags flags - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples - VK_FALSE, // VkBool32 sampleShadingEnable - 1.0f, // float minSampleShading - nullptr, // const VkSampleMask *pSampleMask - VK_FALSE, // VkBool32 alphaToCoverageEnable - VK_FALSE // VkBool32 alphaToOneEnable - }; - - VkPipelineColorBlendAttachmentState color_blend_attachment_state = { - VK_FALSE, // VkBool32 blendEnable - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT - }; - - VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineColorBlendStateCreateFlags flags - VK_FALSE, // VkBool32 logicOpEnable - VK_LOGIC_OP_COPY, // VkLogicOp logicOp - 1, // uint32_t attachmentCount - &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments - { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] - }; - - std::vector dynamic_states = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; - - VkPipelineDynamicStateCreateInfo dynamic_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineDynamicStateCreateFlags flags - static_cast(dynamic_states.size()), // uint32_t dynamicStateCount - &dynamic_states[0] // const VkDynamicState *pDynamicStates - }; - - Tools::AutoDeleter pipeline_layout = CreatePipelineLayout(); - if( !pipeline_layout ) { - return false; - } - - VkGraphicsPipelineCreateInfo pipeline_create_info = { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineCreateFlags flags - static_cast(shader_stage_create_infos.size()), // uint32_t stageCount - &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages - &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; - &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState - nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState - &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState - &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState - &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState - nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState - &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState - &dynamic_state_create_info, // const VkPipelineDynamicStateCreateInfo *pDynamicState - pipeline_layout.Get(), // VkPipelineLayout layout - Vulkan.RenderPass, // VkRenderPass renderPass - 0, // uint32_t subpass - VK_NULL_HANDLE, // VkPipeline basePipelineHandle - -1 // int32_t basePipelineIndex - }; - - if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { - std::cout << "Could not create graphics pipeline!" << std::endl; - return false; - } - return true; - } - - bool Tutorial04::CreateVertexBuffer() { - VertexData vertex_data[] = { - { - -0.7f, -0.7f, 0.0f, 1.0f, - 1.0f, 0.0f, 0.0f, 0.0f - }, - { - -0.7f, 0.7f, 0.0f, 1.0f, - 0.0f, 1.0f, 0.0f, 0.0f - }, - { - 0.7f, -0.7f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, 0.0f - }, - { - 0.7f, 0.7f, 0.0f, 1.0f, - 0.3f, 0.3f, 0.3f, 0.0f - } - }; - - Vulkan.VertexBuffer.Size = sizeof(vertex_data); - - VkBufferCreateInfo buffer_create_info = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkBufferCreateFlags flags - Vulkan.VertexBuffer.Size, // VkDeviceSize size - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode - 0, // uint32_t queueFamilyIndexCount - nullptr // const uint32_t *pQueueFamilyIndices - }; - - if( vkCreateBuffer( GetDevice(), &buffer_create_info, nullptr, &Vulkan.VertexBuffer.Handle ) != VK_SUCCESS ) { - std::cout << "Could not create a vertex buffer!" << std::endl; - return false; - } - - if( !AllocateBufferMemory( Vulkan.VertexBuffer.Handle, &Vulkan.VertexBuffer.Memory ) ) { - std::cout << "Could not allocate memory for a vertex buffer!" << std::endl; - return false; - } - - if( vkBindBufferMemory( GetDevice(), Vulkan.VertexBuffer.Handle, Vulkan.VertexBuffer.Memory, 0 ) != VK_SUCCESS ) { - std::cout << "Could not bind memory for a vertex buffer!" << std::endl; - return false; - } - - void *vertex_buffer_memory_pointer; - if( vkMapMemory( GetDevice(), Vulkan.VertexBuffer.Memory, 0, Vulkan.VertexBuffer.Size, 0, &vertex_buffer_memory_pointer ) != VK_SUCCESS ) { - std::cout << "Could not map memory and upload data to a vertex buffer!" << std::endl; - return false; - } - - memcpy( vertex_buffer_memory_pointer, vertex_data, Vulkan.VertexBuffer.Size ); - - VkMappedMemoryRange flush_range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.VertexBuffer.Memory, // VkDeviceMemory memory - 0, // VkDeviceSize offset - VK_WHOLE_SIZE // VkDeviceSize size - }; - vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); - - vkUnmapMemory( GetDevice(), Vulkan.VertexBuffer.Memory ); - - return true; - } - - bool Tutorial04::AllocateBufferMemory( VkBuffer buffer, VkDeviceMemory *memory ) { - VkMemoryRequirements buffer_memory_requirements; - vkGetBufferMemoryRequirements( GetDevice(), buffer, &buffer_memory_requirements ); - - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); - - for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { - if( (buffer_memory_requirements.memoryTypeBits & (1 << i)) && - (memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ) { - - VkMemoryAllocateInfo memory_allocate_info = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - buffer_memory_requirements.size, // VkDeviceSize allocationSize - i // uint32_t memoryTypeIndex - }; - - if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { - return true; - } - } - } - return false; - } - - bool Tutorial04::CreateRenderingResources() { - if( !CreateCommandBuffers() ) { - return false; - } - if( !CreateSemaphores() ) { - return false; - } - if( !CreateFences() ) { - return false; - } - return true; - } - - bool Tutorial04::CreateCommandBuffers() { - if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.CommandPool ) ) { - std::cout << "Could not create command pool!" << std::endl; - return false; - } - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( !AllocateCommandBuffers( Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ) ) { - std::cout << "Could not allocate command buffer!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial04::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { - VkCommandPoolCreateInfo cmd_pool_create_info = { - VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | // VkCommandPoolCreateFlags flags - VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - queue_family_index // uint32_t queueFamilyIndex - }; - - if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { - return false; - } - return true; - } - - bool Tutorial04::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { - VkCommandBufferAllocateInfo command_buffer_allocate_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - pool, // VkCommandPool commandPool - VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level - count // uint32_t bufferCount - }; - - if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { - return false; - } - return true; - } - - bool Tutorial04::CreateSemaphores() { - VkSemaphoreCreateInfo semaphore_create_info = { - VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0 // VkSemaphoreCreateFlags flags - }; - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].ImageAvailableSemaphore ) != VK_SUCCESS) || - (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].FinishedRenderingSemaphore ) != VK_SUCCESS) ) { - std::cout << "Could not create semaphores!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial04::CreateFences() { - VkFenceCreateInfo fence_create_info = { - VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_FENCE_CREATE_SIGNALED_BIT // VkFenceCreateFlags flags - }; - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( vkCreateFence( GetDevice(), &fence_create_info, nullptr, &Vulkan.RenderingResources[i].Fence ) != VK_SUCCESS ) { - std::cout << "Could not create a fence!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial04::PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ) { - if( !CreateFramebuffer( framebuffer, image_parameters.View ) ) { - return false; - } - - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info ); - - VkImageSubresourceRange image_subresource_range = { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }; - - if( GetPresentQueue().Handle != GetGraphicsQueue().Handle ) { - VkImageMemoryBarrier barrier_from_present_to_draw = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout - GetPresentQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex - GetGraphicsQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex - image_parameters.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); - } - - VkClearValue clear_value = { - { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color - }; - - VkRenderPassBeginInfo render_pass_begin_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.RenderPass, // VkRenderPass renderPass - framebuffer, // VkFramebuffer framebuffer - { // VkRect2D renderArea - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - GetSwapChain().Extent, // VkExtent2D extent; - }, - 1, // uint32_t clearValueCount - &clear_value // const VkClearValue *pClearValues - }; - - vkCmdBeginRenderPass( command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); - - vkCmdBindPipeline( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); - - VkViewport viewport = { - 0.0f, // float x - 0.0f, // float y - static_cast(GetSwapChain().Extent.width), // float width - static_cast(GetSwapChain().Extent.height), // float height - 0.0f, // float minDepth - 1.0f // float maxDepth - }; - - VkRect2D scissor = { - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - { // VkExtent2D extent - GetSwapChain().Extent.width, // uint32_t width - GetSwapChain().Extent.height // uint32_t height - } - }; - - vkCmdSetViewport( command_buffer, 0, 1, &viewport ); - vkCmdSetScissor( command_buffer, 0, 1, &scissor ); - - VkDeviceSize offset = 0; - vkCmdBindVertexBuffers( command_buffer, 0, 1, &Vulkan.VertexBuffer.Handle, &offset ); - - vkCmdDraw( command_buffer, 4, 1, 0, 0 ); - - vkCmdEndRenderPass( command_buffer ); - - if( GetGraphicsQueue().Handle != GetPresentQueue().Handle ) { - VkImageMemoryBarrier barrier_from_draw_to_present = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout - GetGraphicsQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex - GetPresentQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex - image_parameters.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); - } - - if( vkEndCommandBuffer( command_buffer ) != VK_SUCCESS ) { - std::cout << "Could not record command buffer!" << std::endl; - return false; - } - return true; - } - - bool Tutorial04::CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ) { - if( framebuffer != VK_NULL_HANDLE ) { - vkDestroyFramebuffer( GetDevice(), framebuffer, nullptr ); - framebuffer = VK_NULL_HANDLE; - } - - VkFramebufferCreateInfo framebuffer_create_info = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkFramebufferCreateFlags flags - Vulkan.RenderPass, // VkRenderPass renderPass - 1, // uint32_t attachmentCount - &image_view, // const VkImageView *pAttachments - GetSwapChain().Extent.width, // uint32_t width - GetSwapChain().Extent.height, // uint32_t height - 1 // uint32_t layers - }; - - if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &framebuffer ) != VK_SUCCESS ) { - std::cout << "Could not create a framebuffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial04::ChildOnWindowSizeChanged() { - return true; - } - - bool Tutorial04::Draw() { - static size_t resource_index = 0; - RenderingResourcesData ¤t_rendering_resource = Vulkan.RenderingResources[resource_index]; - VkSwapchainKHR swap_chain = GetSwapChain().Handle; - uint32_t image_index; - - resource_index = (resource_index + 1) % VulkanTutorial04Parameters::ResourcesCount; - - if( vkWaitForFences( GetDevice(), 1, ¤t_rendering_resource.Fence, VK_FALSE, 1000000000 ) != VK_SUCCESS ) { - std::cout << "Waiting for fence takes too long!" << std::endl; - return false; - } - vkResetFences( GetDevice(), 1, ¤t_rendering_resource.Fence ); - - VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, current_rendering_resource.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); - switch( result ) { - case VK_SUCCESS: - case VK_SUBOPTIMAL_KHR: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; - return false; - } - - if( !PrepareFrame( current_rendering_resource.CommandBuffer, GetSwapChain().Images[image_index], current_rendering_resource.Framebuffer ) ) { - return false; - } - - VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - ¤t_rendering_resource.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores - &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - ¤t_rendering_resource.CommandBuffer, // const VkCommandBuffer *pCommandBuffers - 1, // uint32_t signalSemaphoreCount - ¤t_rendering_resource.FinishedRenderingSemaphore // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, current_rendering_resource.Fence ) != VK_SUCCESS ) { - return false; - } - - VkPresentInfoKHR present_info = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - ¤t_rendering_resource.FinishedRenderingSemaphore, // const VkSemaphore *pWaitSemaphores - 1, // uint32_t swapchainCount - &swap_chain, // const VkSwapchainKHR *pSwapchains - &image_index, // const uint32_t *pImageIndices - nullptr // VkResult *pResults - }; - result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); - - switch( result ) { - case VK_SUCCESS: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - case VK_SUBOPTIMAL_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during image presentation!" << std::endl; - return false; - } - - return true; - } - - void Tutorial04::ChildClear() { - } - - Tutorial04::~Tutorial04() { - if( GetDevice() != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( GetDevice() ); - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( Vulkan.RenderingResources[i].Framebuffer != VK_NULL_HANDLE ) { - vkDestroyFramebuffer( GetDevice(), Vulkan.RenderingResources[i].Framebuffer, nullptr ); - } - if( Vulkan.RenderingResources[i].CommandBuffer != VK_NULL_HANDLE ) { - vkFreeCommandBuffers( GetDevice(), Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ); - } - if( Vulkan.RenderingResources[i].ImageAvailableSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].ImageAvailableSemaphore, nullptr ); - } - if( Vulkan.RenderingResources[i].FinishedRenderingSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].FinishedRenderingSemaphore, nullptr ); - } - if( Vulkan.RenderingResources[i].Fence != VK_NULL_HANDLE ) { - vkDestroyFence( GetDevice(), Vulkan.RenderingResources[i].Fence, nullptr ); - } - } - - if( Vulkan.CommandPool != VK_NULL_HANDLE ) { - vkDestroyCommandPool( GetDevice(), Vulkan.CommandPool, nullptr ); - Vulkan.CommandPool = VK_NULL_HANDLE; - } - - if( Vulkan.VertexBuffer.Handle != VK_NULL_HANDLE ) { - vkDestroyBuffer( GetDevice(), Vulkan.VertexBuffer.Handle, nullptr ); - Vulkan.VertexBuffer.Handle = VK_NULL_HANDLE; - } - - if( Vulkan.VertexBuffer.Memory != VK_NULL_HANDLE ) { - vkFreeMemory( GetDevice(), Vulkan.VertexBuffer.Memory, nullptr ); - Vulkan.VertexBuffer.Memory = VK_NULL_HANDLE; - } - - if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { - vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); - Vulkan.GraphicsPipeline = VK_NULL_HANDLE; - } - - if( Vulkan.RenderPass != VK_NULL_HANDLE ) { - vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); - Vulkan.RenderPass = VK_NULL_HANDLE; - } - } - } - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include +#include "Tutorial04.h" +#include "VulkanFunctions.h" + +namespace ApiWithoutSecrets { + + Tutorial04::Tutorial04() : + Vulkan() { + } + + bool Tutorial04::CreateRenderPass() { + VkAttachmentDescription attachment_descriptions[] = { + { + 0, // VkAttachmentDescriptionFlags flags + GetSwapChain().Format, // VkFormat format + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR // VkImageLayout finalLayout + } + }; + + VkAttachmentReference color_attachment_references[] = { + { + 0, // uint32_t attachment + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout + } + }; + + VkSubpassDescription subpass_descriptions[] = { + { + 0, // VkSubpassDescriptionFlags flags + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint + 0, // uint32_t inputAttachmentCount + nullptr, // const VkAttachmentReference *pInputAttachments + 1, // uint32_t colorAttachmentCount + color_attachment_references, // const VkAttachmentReference *pColorAttachments + nullptr, // const VkAttachmentReference *pResolveAttachments + nullptr, // const VkAttachmentReference *pDepthStencilAttachment + 0, // uint32_t preserveAttachmentCount + nullptr // const uint32_t* pPreserveAttachments + } + }; + + std::vector dependencies = { + { + VK_SUBPASS_EXTERNAL, // uint32_t srcSubpass + 0, // uint32_t dstSubpass + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags dstStageMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_DEPENDENCY_BY_REGION_BIT // VkDependencyFlags dependencyFlags + }, + { + 0, // uint32_t srcSubpass + VK_SUBPASS_EXTERNAL, // uint32_t dstSubpass + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // VkPipelineStageFlags dstStageMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_DEPENDENCY_BY_REGION_BIT // VkDependencyFlags dependencyFlags + } + }; + + VkRenderPassCreateInfo render_pass_create_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkRenderPassCreateFlags flags + 1, // uint32_t attachmentCount + attachment_descriptions, // const VkAttachmentDescription *pAttachments + 1, // uint32_t subpassCount + subpass_descriptions, // const VkSubpassDescription *pSubpasses + static_cast(dependencies.size()), // uint32_t dependencyCount + &dependencies[0] // const VkSubpassDependency *pDependencies + }; + + if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { + std::cout << "Could not create render pass!" << std::endl; + return false; + } + + return true; + } + + Tools::AutoDeleter Tutorial04::CreateShaderModule( const char* filename ) { + const std::vector code = Tools::GetBinaryFileContents( filename ); + if( code.size() == 0 ) { + return Tools::AutoDeleter(); + } + + VkShaderModuleCreateInfo shader_module_create_info = { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkShaderModuleCreateFlags flags + code.size(), // size_t codeSize + reinterpret_cast(&code[0]) // const uint32_t *pCode + }; + + VkShaderModule shader_module; + if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { + std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; + return Tools::AutoDeleter(); + } + + return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); + } + + Tools::AutoDeleter Tutorial04::CreatePipelineLayout() { + VkPipelineLayoutCreateInfo layout_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineLayoutCreateFlags flags + 0, // uint32_t setLayoutCount + nullptr, // const VkDescriptorSetLayout *pSetLayouts + 0, // uint32_t pushConstantRangeCount + nullptr // const VkPushConstantRange *pPushConstantRanges + }; + + VkPipelineLayout pipeline_layout; + if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &pipeline_layout ) != VK_SUCCESS ) { + std::cout << "Could not create pipeline layout!" << std::endl; + return Tools::AutoDeleter(); + } + + return Tools::AutoDeleter( pipeline_layout, vkDestroyPipelineLayout, GetDevice() ); + } + + bool Tutorial04::CreatePipeline() { + Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data04/vert.spv" ); + Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data04/frag.spv" ); + + if( !vertex_shader_module || !fragment_shader_module ) { + return false; + } + + std::vector shader_stage_create_infos = { + // Vertex shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage + vertex_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + }, + // Fragment shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage + fragment_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + } + }; + + std::vector vertex_binding_descriptions = { + { + 0, // uint32_t binding + sizeof(VertexData), // uint32_t stride + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate + } + }; + + std::vector vertex_attribute_descriptions = { + { + 0, // uint32_t location + vertex_binding_descriptions[0].binding, // uint32_t binding + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format + offsetof(struct VertexData, x) // uint32_t offset + }, + { + 1, // uint32_t location + vertex_binding_descriptions[0].binding, // uint32_t binding + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format + offsetof(struct VertexData, r) // uint32_t offset + } + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineVertexInputStateCreateFlags flags + static_cast(vertex_binding_descriptions.size()), // uint32_t vertexBindingDescriptionCount + &vertex_binding_descriptions[0], // const VkVertexInputBindingDescription *pVertexBindingDescriptions + static_cast(vertex_attribute_descriptions.size()), // uint32_t vertexAttributeDescriptionCount + &vertex_attribute_descriptions[0] // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions + }; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineInputAssemblyStateCreateFlags flags + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology + VK_FALSE // VkBool32 primitiveRestartEnable + }; + + VkPipelineViewportStateCreateInfo viewport_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineViewportStateCreateFlags flags + 1, // uint32_t viewportCount + nullptr, // const VkViewport *pViewports + 1, // uint32_t scissorCount + nullptr // const VkRect2D *pScissors + }; + + VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineRasterizationStateCreateFlags flags + VK_FALSE, // VkBool32 depthClampEnable + VK_FALSE, // VkBool32 rasterizerDiscardEnable + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode + VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace + VK_FALSE, // VkBool32 depthBiasEnable + 0.0f, // float depthBiasConstantFactor + 0.0f, // float depthBiasClamp + 0.0f, // float depthBiasSlopeFactor + 1.0f // float lineWidth + }; + + VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineMultisampleStateCreateFlags flags + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples + VK_FALSE, // VkBool32 sampleShadingEnable + 1.0f, // float minSampleShading + nullptr, // const VkSampleMask *pSampleMask + VK_FALSE, // VkBool32 alphaToCoverageEnable + VK_FALSE // VkBool32 alphaToOneEnable + }; + + VkPipelineColorBlendAttachmentState color_blend_attachment_state = { + VK_FALSE, // VkBool32 blendEnable + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT + }; + + VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineColorBlendStateCreateFlags flags + VK_FALSE, // VkBool32 logicOpEnable + VK_LOGIC_OP_COPY, // VkLogicOp logicOp + 1, // uint32_t attachmentCount + &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments + { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] + }; + + std::vector dynamic_states = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + + VkPipelineDynamicStateCreateInfo dynamic_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineDynamicStateCreateFlags flags + static_cast(dynamic_states.size()), // uint32_t dynamicStateCount + &dynamic_states[0] // const VkDynamicState *pDynamicStates + }; + + Tools::AutoDeleter pipeline_layout = CreatePipelineLayout(); + if( !pipeline_layout ) { + return false; + } + + VkGraphicsPipelineCreateInfo pipeline_create_info = { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineCreateFlags flags + static_cast(shader_stage_create_infos.size()), // uint32_t stageCount + &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages + &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; + &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState + nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState + &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState + &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState + &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState + nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState + &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState + &dynamic_state_create_info, // const VkPipelineDynamicStateCreateInfo *pDynamicState + pipeline_layout.Get(), // VkPipelineLayout layout + Vulkan.RenderPass, // VkRenderPass renderPass + 0, // uint32_t subpass + VK_NULL_HANDLE, // VkPipeline basePipelineHandle + -1 // int32_t basePipelineIndex + }; + + if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { + std::cout << "Could not create graphics pipeline!" << std::endl; + return false; + } + return true; + } + + bool Tutorial04::CreateVertexBuffer() { + VertexData vertex_data[] = { + { + -0.7f, -0.7f, 0.0f, 1.0f, + 1.0f, 0.0f, 0.0f, 0.0f + }, + { + -0.7f, 0.7f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 0.0f + }, + { + 0.7f, -0.7f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 0.0f + }, + { + 0.7f, 0.7f, 0.0f, 1.0f, + 0.3f, 0.3f, 0.3f, 0.0f + } + }; + + Vulkan.VertexBuffer.Size = sizeof(vertex_data); + + VkBufferCreateInfo buffer_create_info = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkBufferCreateFlags flags + Vulkan.VertexBuffer.Size, // VkDeviceSize size + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode + 0, // uint32_t queueFamilyIndexCount + nullptr // const uint32_t *pQueueFamilyIndices + }; + + if( vkCreateBuffer( GetDevice(), &buffer_create_info, nullptr, &Vulkan.VertexBuffer.Handle ) != VK_SUCCESS ) { + std::cout << "Could not create a vertex buffer!" << std::endl; + return false; + } + + if( !AllocateBufferMemory( Vulkan.VertexBuffer.Handle, &Vulkan.VertexBuffer.Memory ) ) { + std::cout << "Could not allocate memory for a vertex buffer!" << std::endl; + return false; + } + + if( vkBindBufferMemory( GetDevice(), Vulkan.VertexBuffer.Handle, Vulkan.VertexBuffer.Memory, 0 ) != VK_SUCCESS ) { + std::cout << "Could not bind memory for a vertex buffer!" << std::endl; + return false; + } + + void *vertex_buffer_memory_pointer; + if( vkMapMemory( GetDevice(), Vulkan.VertexBuffer.Memory, 0, Vulkan.VertexBuffer.Size, 0, &vertex_buffer_memory_pointer ) != VK_SUCCESS ) { + std::cout << "Could not map memory and upload data to a vertex buffer!" << std::endl; + return false; + } + + memcpy( vertex_buffer_memory_pointer, vertex_data, Vulkan.VertexBuffer.Size ); + + VkMappedMemoryRange flush_range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.VertexBuffer.Memory, // VkDeviceMemory memory + 0, // VkDeviceSize offset + VK_WHOLE_SIZE // VkDeviceSize size + }; + vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); + + vkUnmapMemory( GetDevice(), Vulkan.VertexBuffer.Memory ); + + return true; + } + + bool Tutorial04::AllocateBufferMemory( VkBuffer buffer, VkDeviceMemory *memory ) { + VkMemoryRequirements buffer_memory_requirements; + vkGetBufferMemoryRequirements( GetDevice(), buffer, &buffer_memory_requirements ); + + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); + + for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { + if( (buffer_memory_requirements.memoryTypeBits & (1 << i)) && + (memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ) { + + VkMemoryAllocateInfo memory_allocate_info = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + buffer_memory_requirements.size, // VkDeviceSize allocationSize + i // uint32_t memoryTypeIndex + }; + + if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { + return true; + } + } + } + return false; + } + + bool Tutorial04::CreateRenderingResources() { + if( !CreateCommandBuffers() ) { + return false; + } + if( !CreateSemaphores() ) { + return false; + } + if( !CreateFences() ) { + return false; + } + return true; + } + + bool Tutorial04::CreateCommandBuffers() { + if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.CommandPool ) ) { + std::cout << "Could not create command pool!" << std::endl; + return false; + } + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( !AllocateCommandBuffers( Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ) ) { + std::cout << "Could not allocate command buffer!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial04::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { + VkCommandPoolCreateInfo cmd_pool_create_info = { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | // VkCommandPoolCreateFlags flags + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + queue_family_index // uint32_t queueFamilyIndex + }; + + if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { + return false; + } + return true; + } + + bool Tutorial04::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { + VkCommandBufferAllocateInfo command_buffer_allocate_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + pool, // VkCommandPool commandPool + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level + count // uint32_t bufferCount + }; + + if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { + return false; + } + return true; + } + + bool Tutorial04::CreateSemaphores() { + VkSemaphoreCreateInfo semaphore_create_info = { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0 // VkSemaphoreCreateFlags flags + }; + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].ImageAvailableSemaphore ) != VK_SUCCESS) || + (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].FinishedRenderingSemaphore ) != VK_SUCCESS) ) { + std::cout << "Could not create semaphores!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial04::CreateFences() { + VkFenceCreateInfo fence_create_info = { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_FENCE_CREATE_SIGNALED_BIT // VkFenceCreateFlags flags + }; + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( vkCreateFence( GetDevice(), &fence_create_info, nullptr, &Vulkan.RenderingResources[i].Fence ) != VK_SUCCESS ) { + std::cout << "Could not create a fence!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial04::PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ) { + if( !CreateFramebuffer( framebuffer, image_parameters.View ) ) { + return false; + } + + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info ); + + VkImageSubresourceRange image_subresource_range = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + if( GetPresentQueue().Handle != GetGraphicsQueue().Handle ) { + VkImageMemoryBarrier barrier_from_present_to_draw = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout + GetPresentQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex + GetGraphicsQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex + image_parameters.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); + } + + VkClearValue clear_value = { + { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color + }; + + VkRenderPassBeginInfo render_pass_begin_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.RenderPass, // VkRenderPass renderPass + framebuffer, // VkFramebuffer framebuffer + { // VkRect2D renderArea + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + GetSwapChain().Extent, // VkExtent2D extent; + }, + 1, // uint32_t clearValueCount + &clear_value // const VkClearValue *pClearValues + }; + + vkCmdBeginRenderPass( command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); + + vkCmdBindPipeline( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); + + VkViewport viewport = { + 0.0f, // float x + 0.0f, // float y + static_cast(GetSwapChain().Extent.width), // float width + static_cast(GetSwapChain().Extent.height), // float height + 0.0f, // float minDepth + 1.0f // float maxDepth + }; + + VkRect2D scissor = { + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + { // VkExtent2D extent + GetSwapChain().Extent.width, // uint32_t width + GetSwapChain().Extent.height // uint32_t height + } + }; + + vkCmdSetViewport( command_buffer, 0, 1, &viewport ); + vkCmdSetScissor( command_buffer, 0, 1, &scissor ); + + VkDeviceSize offset = 0; + vkCmdBindVertexBuffers( command_buffer, 0, 1, &Vulkan.VertexBuffer.Handle, &offset ); + + vkCmdDraw( command_buffer, 4, 1, 0, 0 ); + + vkCmdEndRenderPass( command_buffer ); + + if( GetGraphicsQueue().Handle != GetPresentQueue().Handle ) { + VkImageMemoryBarrier barrier_from_draw_to_present = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout + GetGraphicsQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex + GetPresentQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex + image_parameters.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); + } + + if( vkEndCommandBuffer( command_buffer ) != VK_SUCCESS ) { + std::cout << "Could not record command buffer!" << std::endl; + return false; + } + return true; + } + + bool Tutorial04::CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ) { + if( framebuffer != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( GetDevice(), framebuffer, nullptr ); + framebuffer = VK_NULL_HANDLE; + } + + VkFramebufferCreateInfo framebuffer_create_info = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkFramebufferCreateFlags flags + Vulkan.RenderPass, // VkRenderPass renderPass + 1, // uint32_t attachmentCount + &image_view, // const VkImageView *pAttachments + GetSwapChain().Extent.width, // uint32_t width + GetSwapChain().Extent.height, // uint32_t height + 1 // uint32_t layers + }; + + if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &framebuffer ) != VK_SUCCESS ) { + std::cout << "Could not create a framebuffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial04::ChildOnWindowSizeChanged() { + return true; + } + + bool Tutorial04::Draw() { + static size_t resource_index = 0; + RenderingResourcesData ¤t_rendering_resource = Vulkan.RenderingResources[resource_index]; + VkSwapchainKHR swap_chain = GetSwapChain().Handle; + uint32_t image_index; + + resource_index = (resource_index + 1) % VulkanTutorial04Parameters::ResourcesCount; + + if( vkWaitForFences( GetDevice(), 1, ¤t_rendering_resource.Fence, VK_FALSE, 1000000000 ) != VK_SUCCESS ) { + std::cout << "Waiting for fence takes too long!" << std::endl; + return false; + } + vkResetFences( GetDevice(), 1, ¤t_rendering_resource.Fence ); + + VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, current_rendering_resource.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); + switch( result ) { + case VK_SUCCESS: + case VK_SUBOPTIMAL_KHR: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; + return false; + } + + if( !PrepareFrame( current_rendering_resource.CommandBuffer, GetSwapChain().Images[image_index], current_rendering_resource.Framebuffer ) ) { + return false; + } + + VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + ¤t_rendering_resource.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores + &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + ¤t_rendering_resource.CommandBuffer, // const VkCommandBuffer *pCommandBuffers + 1, // uint32_t signalSemaphoreCount + ¤t_rendering_resource.FinishedRenderingSemaphore // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, current_rendering_resource.Fence ) != VK_SUCCESS ) { + return false; + } + + VkPresentInfoKHR present_info = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + ¤t_rendering_resource.FinishedRenderingSemaphore, // const VkSemaphore *pWaitSemaphores + 1, // uint32_t swapchainCount + &swap_chain, // const VkSwapchainKHR *pSwapchains + &image_index, // const uint32_t *pImageIndices + nullptr // VkResult *pResults + }; + result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); + + switch( result ) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_SUBOPTIMAL_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during image presentation!" << std::endl; + return false; + } + + return true; + } + + void Tutorial04::ChildClear() { + } + + Tutorial04::~Tutorial04() { + if( GetDevice() != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( GetDevice() ); + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( Vulkan.RenderingResources[i].Framebuffer != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( GetDevice(), Vulkan.RenderingResources[i].Framebuffer, nullptr ); + } + if( Vulkan.RenderingResources[i].CommandBuffer != VK_NULL_HANDLE ) { + vkFreeCommandBuffers( GetDevice(), Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ); + } + if( Vulkan.RenderingResources[i].ImageAvailableSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].ImageAvailableSemaphore, nullptr ); + } + if( Vulkan.RenderingResources[i].FinishedRenderingSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].FinishedRenderingSemaphore, nullptr ); + } + if( Vulkan.RenderingResources[i].Fence != VK_NULL_HANDLE ) { + vkDestroyFence( GetDevice(), Vulkan.RenderingResources[i].Fence, nullptr ); + } + } + + if( Vulkan.CommandPool != VK_NULL_HANDLE ) { + vkDestroyCommandPool( GetDevice(), Vulkan.CommandPool, nullptr ); + Vulkan.CommandPool = VK_NULL_HANDLE; + } + + if( Vulkan.VertexBuffer.Handle != VK_NULL_HANDLE ) { + vkDestroyBuffer( GetDevice(), Vulkan.VertexBuffer.Handle, nullptr ); + Vulkan.VertexBuffer.Handle = VK_NULL_HANDLE; + } + + if( Vulkan.VertexBuffer.Memory != VK_NULL_HANDLE ) { + vkFreeMemory( GetDevice(), Vulkan.VertexBuffer.Memory, nullptr ); + Vulkan.VertexBuffer.Memory = VK_NULL_HANDLE; + } + + if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { + vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); + Vulkan.GraphicsPipeline = VK_NULL_HANDLE; + } + + if( Vulkan.RenderPass != VK_NULL_HANDLE ) { + vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); + Vulkan.RenderPass = VK_NULL_HANDLE; + } + } + } + } // namespace ApiWithoutSecrets \ No newline at end of file diff --git a/Project/Tutorial04/Tutorial04.h b/Project/Tutorial04/Tutorial04.h index 385e8d4..9db8cc0 100644 --- a/Project/Tutorial04/Tutorial04.h +++ b/Project/Tutorial04/Tutorial04.h @@ -1,133 +1,133 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(TUTORIAL_04_HEADER) -#define TUTORIAL_04_HEADER - -#include "VulkanCommon.h" -#include "Tools.h" - -namespace ApiWithoutSecrets { - - // ************************************************************ // - // BufferParameters // - // // - // Vulkan Buffer's parameters container class // - // ************************************************************ // - struct BufferParameters { - VkBuffer Handle; - VkDeviceMemory Memory; - uint32_t Size; - - BufferParameters() : - Handle( VK_NULL_HANDLE ), - Memory( VK_NULL_HANDLE ), - Size( 0 ) { - } - }; - - // ************************************************************ // - // VertexData // - // // - // Struct describing data type and format of vertex attributes // - // ************************************************************ // - struct VertexData { - float x, y, z, w; - float r, g, b, a; - }; - - // ************************************************************ // - // RenderingResourcesData // - // // - // Struct containing data used during rendering process // - // ************************************************************ // - struct RenderingResourcesData { - VkFramebuffer Framebuffer; - VkCommandBuffer CommandBuffer; - VkSemaphore ImageAvailableSemaphore; - VkSemaphore FinishedRenderingSemaphore; - VkFence Fence; - - RenderingResourcesData() : - Framebuffer( VK_NULL_HANDLE ), - CommandBuffer( VK_NULL_HANDLE ), - ImageAvailableSemaphore( VK_NULL_HANDLE ), - FinishedRenderingSemaphore( VK_NULL_HANDLE ), - Fence( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // VulkanTutorial04Parameters // - // // - // Vulkan specific parameters // - // ************************************************************ // - struct VulkanTutorial04Parameters { - VkRenderPass RenderPass; - VkPipeline GraphicsPipeline; - BufferParameters VertexBuffer; - VkCommandPool CommandPool; - std::vector RenderingResources; - - static const size_t ResourcesCount = 3; - - VulkanTutorial04Parameters() : - RenderPass( VK_NULL_HANDLE ), - GraphicsPipeline( VK_NULL_HANDLE ), - VertexBuffer(), - CommandPool( VK_NULL_HANDLE ), - RenderingResources( ResourcesCount ) { - } - }; - - // ************************************************************ // - // Tutorial04 // - // // - // Class for presenting Vulkan usage topics // - // ************************************************************ // - class Tutorial04 : public VulkanCommon { - public: - Tutorial04(); - ~Tutorial04(); - - bool CreateRenderPass(); - bool CreatePipeline(); - bool CreateVertexBuffer(); - bool CreateRenderingResources(); - - bool Draw() override; - - private: - VulkanTutorial04Parameters Vulkan; - - Tools::AutoDeleter CreateShaderModule( const char* filename ); - Tools::AutoDeleter CreatePipelineLayout(); - bool AllocateBufferMemory( VkBuffer buffer, VkDeviceMemory *memory ); - bool CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ); - bool AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ); - bool CreateCommandBuffers(); - bool CreateSemaphores(); - bool CreateFences(); - bool PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ); - bool CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ); - - void ChildClear() override; - bool ChildOnWindowSizeChanged() override; - }; - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(TUTORIAL_04_HEADER) +#define TUTORIAL_04_HEADER + +#include "VulkanCommon.h" +#include "Tools.h" + +namespace ApiWithoutSecrets { + + // ************************************************************ // + // BufferParameters // + // // + // Vulkan Buffer's parameters container class // + // ************************************************************ // + struct BufferParameters { + VkBuffer Handle; + VkDeviceMemory Memory; + uint32_t Size; + + BufferParameters() : + Handle( VK_NULL_HANDLE ), + Memory( VK_NULL_HANDLE ), + Size( 0 ) { + } + }; + + // ************************************************************ // + // VertexData // + // // + // Struct describing data type and format of vertex attributes // + // ************************************************************ // + struct VertexData { + float x, y, z, w; + float r, g, b, a; + }; + + // ************************************************************ // + // RenderingResourcesData // + // // + // Struct containing data used during rendering process // + // ************************************************************ // + struct RenderingResourcesData { + VkFramebuffer Framebuffer; + VkCommandBuffer CommandBuffer; + VkSemaphore ImageAvailableSemaphore; + VkSemaphore FinishedRenderingSemaphore; + VkFence Fence; + + RenderingResourcesData() : + Framebuffer( VK_NULL_HANDLE ), + CommandBuffer( VK_NULL_HANDLE ), + ImageAvailableSemaphore( VK_NULL_HANDLE ), + FinishedRenderingSemaphore( VK_NULL_HANDLE ), + Fence( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // VulkanTutorial04Parameters // + // // + // Vulkan specific parameters // + // ************************************************************ // + struct VulkanTutorial04Parameters { + VkRenderPass RenderPass; + VkPipeline GraphicsPipeline; + BufferParameters VertexBuffer; + VkCommandPool CommandPool; + std::vector RenderingResources; + + static const size_t ResourcesCount = 3; + + VulkanTutorial04Parameters() : + RenderPass( VK_NULL_HANDLE ), + GraphicsPipeline( VK_NULL_HANDLE ), + VertexBuffer(), + CommandPool( VK_NULL_HANDLE ), + RenderingResources( ResourcesCount ) { + } + }; + + // ************************************************************ // + // Tutorial04 // + // // + // Class for presenting Vulkan usage topics // + // ************************************************************ // + class Tutorial04 : public VulkanCommon { + public: + Tutorial04(); + ~Tutorial04(); + + bool CreateRenderPass(); + bool CreatePipeline(); + bool CreateVertexBuffer(); + bool CreateRenderingResources(); + + bool Draw() override; + + private: + VulkanTutorial04Parameters Vulkan; + + Tools::AutoDeleter CreateShaderModule( const char* filename ); + Tools::AutoDeleter CreatePipelineLayout(); + bool AllocateBufferMemory( VkBuffer buffer, VkDeviceMemory *memory ); + bool CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ); + bool AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ); + bool CreateCommandBuffers(); + bool CreateSemaphores(); + bool CreateFences(); + bool PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ); + bool CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ); + + void ChildClear() override; + bool ChildOnWindowSizeChanged() override; + }; + +} // namespace ApiWithoutSecrets + #endif // TUTORIAL_04_HEADER \ No newline at end of file diff --git a/Project/Tutorial04/main.cpp b/Project/Tutorial04/main.cpp index 0479097..c7ca43a 100644 --- a/Project/Tutorial04/main.cpp +++ b/Project/Tutorial04/main.cpp @@ -1,53 +1,53 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial04.h" - -int main( int argc, char **argv ) { - ApiWithoutSecrets::OS::Window window; - ApiWithoutSecrets::Tutorial04 tutorial04; - - // Window creation - if( !window.Create( "04 - Vertex Attributes" ) ) { - return -1; - } - - // Vulkan preparations and initialization - if( !tutorial04.PrepareVulkan( window.GetParameters() ) ) { - return -1; - } - - // Tutorial 04 - if( !tutorial04.CreateRenderPass() ) { - return -1; - } - if( !tutorial04.CreatePipeline() ) { - return -1; - } - if( !tutorial04.CreateVertexBuffer() ) { - return -1; - } - if( !tutorial04.CreateRenderingResources() ) { - return -1; - } - - // Rendering loop - if( !window.RenderingLoop( tutorial04 ) ) { - return -1; - } - - return 0; -} +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial04.h" + +int main( int argc, char **argv ) { + ApiWithoutSecrets::OS::Window window; + ApiWithoutSecrets::Tutorial04 tutorial04; + + // Window creation + if( !window.Create( "04 - Vertex Attributes" ) ) { + return -1; + } + + // Vulkan preparations and initialization + if( !tutorial04.PrepareVulkan( window.GetParameters() ) ) { + return -1; + } + + // Tutorial 04 + if( !tutorial04.CreateRenderPass() ) { + return -1; + } + if( !tutorial04.CreatePipeline() ) { + return -1; + } + if( !tutorial04.CreateVertexBuffer() ) { + return -1; + } + if( !tutorial04.CreateRenderingResources() ) { + return -1; + } + + // Rendering loop + if( !window.RenderingLoop( tutorial04 ) ) { + return -1; + } + + return 0; +} diff --git a/Project/Tutorial05/Tutorial05.cpp b/Project/Tutorial05/Tutorial05.cpp index 8a848fc..e131369 100644 --- a/Project/Tutorial05/Tutorial05.cpp +++ b/Project/Tutorial05/Tutorial05.cpp @@ -1,863 +1,863 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial05.h" -#include "VulkanFunctions.h" - -namespace ApiWithoutSecrets { - - Tutorial05::Tutorial05() : - Vulkan() { - } - - bool Tutorial05::CreateRenderingResources() { - if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.CommandPool ) ) { - return false; - } - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( !AllocateCommandBuffers( Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ) ) { - return false; - } - - if( !CreateSemaphore( &Vulkan.RenderingResources[i].ImageAvailableSemaphore ) ) { - return false; - } - - if( !CreateSemaphore( &Vulkan.RenderingResources[i].FinishedRenderingSemaphore ) ) { - return false; - } - - if( !CreateFence( VK_FENCE_CREATE_SIGNALED_BIT, &Vulkan.RenderingResources[i].Fence ) ) { - return false; - } - } - return true; - } - - bool Tutorial05::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { - VkCommandPoolCreateInfo cmd_pool_create_info = { - VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | // VkCommandPoolCreateFlags flags - VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - queue_family_index // uint32_t queueFamilyIndex - }; - - if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { - std::cout << "Could not create command pool!" << std::endl; - return false; - } - return true; - } - - bool Tutorial05::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { - VkCommandBufferAllocateInfo command_buffer_allocate_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - pool, // VkCommandPool commandPool - VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level - count // uint32_t bufferCount - }; - - if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { - std::cout << "Could not allocate command buffer!" << std::endl; - return false; - } - return true; - } - - bool Tutorial05::CreateSemaphore( VkSemaphore *semaphore ) { - VkSemaphoreCreateInfo semaphore_create_info = { - VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0 // VkSemaphoreCreateFlags flags - }; - - if( vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, semaphore ) != VK_SUCCESS ) { - std::cout << "Could not create semaphore!" << std::endl; - return false; - } - return true; - } - - bool Tutorial05::CreateFence( VkFenceCreateFlags flags, VkFence *fence ) { - VkFenceCreateInfo fence_create_info = { - VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - flags // VkFenceCreateFlags flags - }; - - if( vkCreateFence( GetDevice(), &fence_create_info, nullptr, fence ) != VK_SUCCESS ) { - std::cout << "Could not create a fence!" << std::endl; - return false; - } - return true; - } - - bool Tutorial05::CreateRenderPass() { - VkAttachmentDescription attachment_descriptions[] = { - { - 0, // VkAttachmentDescriptionFlags flags - GetSwapChain().Format, // VkFormat format - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR // VkImageLayout finalLayout - } - }; - - VkAttachmentReference color_attachment_references[] = { - { - 0, // uint32_t attachment - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout - } - }; - - VkSubpassDescription subpass_descriptions[] = { - { - 0, // VkSubpassDescriptionFlags flags - VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint - 0, // uint32_t inputAttachmentCount - nullptr, // const VkAttachmentReference *pInputAttachments - 1, // uint32_t colorAttachmentCount - color_attachment_references, // const VkAttachmentReference *pColorAttachments - nullptr, // const VkAttachmentReference *pResolveAttachments - nullptr, // const VkAttachmentReference *pDepthStencilAttachment - 0, // uint32_t preserveAttachmentCount - nullptr // const uint32_t* pPreserveAttachments - } - }; - - std::vector dependencies = { - { - VK_SUBPASS_EXTERNAL, // uint32_t srcSubpass - 0, // uint32_t dstSubpass - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags dstStageMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask - VK_DEPENDENCY_BY_REGION_BIT // VkDependencyFlags dependencyFlags - }, - { - 0, // uint32_t srcSubpass - VK_SUBPASS_EXTERNAL, // uint32_t dstSubpass - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // VkPipelineStageFlags dstStageMask - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_DEPENDENCY_BY_REGION_BIT // VkDependencyFlags dependencyFlags - } - }; - - VkRenderPassCreateInfo render_pass_create_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkRenderPassCreateFlags flags - 1, // uint32_t attachmentCount - attachment_descriptions, // const VkAttachmentDescription *pAttachments - 1, // uint32_t subpassCount - subpass_descriptions, // const VkSubpassDescription *pSubpasses - static_cast(dependencies.size()), // uint32_t dependencyCount - &dependencies[0] // const VkSubpassDependency *pDependencies - }; - - if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { - std::cout << "Could not create render pass!" << std::endl; - return false; - } - - return true; - } - - Tools::AutoDeleter Tutorial05::CreateShaderModule( const char* filename ) { - const std::vector code = Tools::GetBinaryFileContents( filename ); - if( code.size() == 0 ) { - return Tools::AutoDeleter(); - } - - VkShaderModuleCreateInfo shader_module_create_info = { - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkShaderModuleCreateFlags flags - code.size(), // size_t codeSize - reinterpret_cast(&code[0]) // const uint32_t *pCode - }; - - VkShaderModule shader_module; - if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { - std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; - return Tools::AutoDeleter(); - } - - return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); - } - - Tools::AutoDeleter Tutorial05::CreatePipelineLayout() { - VkPipelineLayoutCreateInfo layout_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineLayoutCreateFlags flags - 0, // uint32_t setLayoutCount - nullptr, // const VkDescriptorSetLayout *pSetLayouts - 0, // uint32_t pushConstantRangeCount - nullptr // const VkPushConstantRange *pPushConstantRanges - }; - - VkPipelineLayout pipeline_layout; - if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &pipeline_layout ) != VK_SUCCESS ) { - std::cout << "Could not create pipeline layout!" << std::endl; - return Tools::AutoDeleter(); - } - - return Tools::AutoDeleter( pipeline_layout, vkDestroyPipelineLayout, GetDevice() ); - } - - bool Tutorial05::CreatePipeline() { - Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data05/vert.spv" ); - Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data05/frag.spv" ); - - if( !vertex_shader_module || !fragment_shader_module ) { - return false; - } - - std::vector shader_stage_create_infos = { - // Vertex shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage - vertex_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - }, - // Fragment shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage - fragment_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - } - }; - - std::vector vertex_binding_descriptions = { - { - 0, // uint32_t binding - sizeof(VertexData), // uint32_t stride - VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate - } - }; - - std::vector vertex_attribute_descriptions = { - { - 0, // uint32_t location - vertex_binding_descriptions[0].binding, // uint32_t binding - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format - offsetof(struct VertexData, x) // uint32_t offset - }, - { - 1, // uint32_t location - vertex_binding_descriptions[0].binding, // uint32_t binding - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format - offsetof(struct VertexData, r) // uint32_t offset - } - }; - - VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineVertexInputStateCreateFlags flags - static_cast(vertex_binding_descriptions.size()), // uint32_t vertexBindingDescriptionCount - &vertex_binding_descriptions[0], // const VkVertexInputBindingDescription *pVertexBindingDescriptions - static_cast(vertex_attribute_descriptions.size()), // uint32_t vertexAttributeDescriptionCount - &vertex_attribute_descriptions[0] // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions - }; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineInputAssemblyStateCreateFlags flags - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology - VK_FALSE // VkBool32 primitiveRestartEnable - }; - - VkPipelineViewportStateCreateInfo viewport_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineViewportStateCreateFlags flags - 1, // uint32_t viewportCount - nullptr, // const VkViewport *pViewports - 1, // uint32_t scissorCount - nullptr // const VkRect2D *pScissors - }; - - VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineRasterizationStateCreateFlags flags - VK_FALSE, // VkBool32 depthClampEnable - VK_FALSE, // VkBool32 rasterizerDiscardEnable - VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode - VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode - VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace - VK_FALSE, // VkBool32 depthBiasEnable - 0.0f, // float depthBiasConstantFactor - 0.0f, // float depthBiasClamp - 0.0f, // float depthBiasSlopeFactor - 1.0f // float lineWidth - }; - - VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineMultisampleStateCreateFlags flags - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples - VK_FALSE, // VkBool32 sampleShadingEnable - 1.0f, // float minSampleShading - nullptr, // const VkSampleMask *pSampleMask - VK_FALSE, // VkBool32 alphaToCoverageEnable - VK_FALSE // VkBool32 alphaToOneEnable - }; - - VkPipelineColorBlendAttachmentState color_blend_attachment_state = { - VK_FALSE, // VkBool32 blendEnable - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT - }; - - VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineColorBlendStateCreateFlags flags - VK_FALSE, // VkBool32 logicOpEnable - VK_LOGIC_OP_COPY, // VkLogicOp logicOp - 1, // uint32_t attachmentCount - &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments - { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] - }; - - std::vector dynamic_states = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; - - VkPipelineDynamicStateCreateInfo dynamic_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineDynamicStateCreateFlags flags - static_cast(dynamic_states.size()), // uint32_t dynamicStateCount - &dynamic_states[0] // const VkDynamicState *pDynamicStates - }; - - Tools::AutoDeleter pipeline_layout = CreatePipelineLayout(); - if( !pipeline_layout ) { - return false; - } - - VkGraphicsPipelineCreateInfo pipeline_create_info = { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineCreateFlags flags - static_cast(shader_stage_create_infos.size()), // uint32_t stageCount - &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages - &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; - &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState - nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState - &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState - &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState - &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState - nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState - &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState - &dynamic_state_create_info, // const VkPipelineDynamicStateCreateInfo *pDynamicState - pipeline_layout.Get(), // VkPipelineLayout layout - Vulkan.RenderPass, // VkRenderPass renderPass - 0, // uint32_t subpass - VK_NULL_HANDLE, // VkPipeline basePipelineHandle - -1 // int32_t basePipelineIndex - }; - - if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { - std::cout << "Could not create graphics pipeline!" << std::endl; - return false; - } - return true; - } - - bool Tutorial05::CreateVertexBuffer() { - const std::vector& vertex_data = GetVertexData(); - - Vulkan.VertexBuffer.Size = static_cast(vertex_data.size() * sizeof(vertex_data[0])); - if( !CreateBuffer( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Vulkan.VertexBuffer ) ) { - std::cout << "Could not create vertex buffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial05::CreateStagingBuffer() { - Vulkan.StagingBuffer.Size = 4000; - if( !CreateBuffer( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, Vulkan.StagingBuffer ) ) { - std::cout << "Could not staging buffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial05::CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer ) { - VkBufferCreateInfo buffer_create_info = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkBufferCreateFlags flags - buffer.Size, // VkDeviceSize size - usage, // VkBufferUsageFlags usage - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode - 0, // uint32_t queueFamilyIndexCount - nullptr // const uint32_t *pQueueFamilyIndices - }; - - if( vkCreateBuffer( GetDevice(), &buffer_create_info, nullptr, &buffer.Handle ) != VK_SUCCESS ) { - std::cout << "Could not create buffer!" << std::endl; - return false; - } - - if( !AllocateBufferMemory( buffer.Handle, memoryProperty, &buffer.Memory ) ) { - std::cout << "Could not allocate memory for a buffer!" << std::endl; - return false; - } - - if( vkBindBufferMemory( GetDevice(), buffer.Handle, buffer.Memory, 0 ) != VK_SUCCESS ) { - std::cout << "Could not bind memory to a buffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial05::AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { - VkMemoryRequirements buffer_memory_requirements; - vkGetBufferMemoryRequirements( GetDevice(), buffer, &buffer_memory_requirements ); - - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); - - for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { - if( (buffer_memory_requirements.memoryTypeBits & (1 << i)) && - ((memory_properties.memoryTypes[i].propertyFlags & property) == property) ) { - - VkMemoryAllocateInfo memory_allocate_info = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - buffer_memory_requirements.size, // VkDeviceSize allocationSize - i // uint32_t memoryTypeIndex - }; - - if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { - return true; - } - } - } - return false; - } - - const std::vector& Tutorial05::GetVertexData() const { - static const std::vector vertex_data = { - -0.7f, -0.7f, 0.0f, 1.0f, - 1.0f, 0.0f, 0.0f, 0.0f, - // - -0.7f, 0.7f, 0.0f, 1.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - // - 0.7f, -0.7f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - // - 0.7f, 0.7f, 0.0f, 1.0f, - 0.3f, 0.3f, 0.3f, 0.0f - }; - - return vertex_data; - } - - bool Tutorial05::CopyVertexData() { - // Prepare data in a staging buffer - const std::vector& vertex_data = GetVertexData(); - - void *staging_buffer_memory_pointer; - if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, Vulkan.VertexBuffer.Size, 0, &staging_buffer_memory_pointer) != VK_SUCCESS ) { - std::cout << "Could not map memory and upload data to a staging buffer!" << std::endl; - return false; - } - - memcpy( staging_buffer_memory_pointer, &vertex_data[0], Vulkan.VertexBuffer.Size ); - - VkMappedMemoryRange flush_range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory - 0, // VkDeviceSize offset - Vulkan.VertexBuffer.Size // VkDeviceSize size - }; - vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); - - vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); - - // Prepare command buffer to copy data from staging buffer to a vertex buffer - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); - - VkBufferCopy buffer_copy_info = { - 0, // VkDeviceSize srcOffset - 0, // VkDeviceSize dstOffset - Vulkan.VertexBuffer.Size // VkDeviceSize size - }; - vkCmdCopyBuffer( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.VertexBuffer.Handle, 1, &buffer_copy_info ); - - VkBufferMemoryBarrier buffer_memory_barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkAccessFlags dstAccessMask - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - Vulkan.VertexBuffer.Handle, // VkBuffer buffer - 0, // VkDeviceSize offset - VK_WHOLE_SIZE // VkDeviceSize size - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, &buffer_memory_barrier, 0, nullptr ); - - vkEndCommandBuffer( command_buffer ); - - // Submit command buffer and copy data from staging buffer to a vertex buffer - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // uint32_t waitSemaphoreCount - nullptr, // const VkSemaphore *pWaitSemaphores - nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - &command_buffer, // const VkCommandBuffer *pCommandBuffers - 0, // uint32_t signalSemaphoreCount - nullptr // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { - return false; - } - - vkDeviceWaitIdle( GetDevice() ); - - return true; - } - - bool Tutorial05::PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ) { - if( !CreateFramebuffer( framebuffer, image_parameters.View ) ) { - return false; - } - - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info ); - - VkImageSubresourceRange image_subresource_range = { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }; - - if( GetPresentQueue().Handle != GetGraphicsQueue().Handle ) { - VkImageMemoryBarrier barrier_from_present_to_draw = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout - GetPresentQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex - GetGraphicsQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex - image_parameters.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); - } - - VkClearValue clear_value = { - { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color - }; - - VkRenderPassBeginInfo render_pass_begin_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.RenderPass, // VkRenderPass renderPass - framebuffer, // VkFramebuffer framebuffer - { // VkRect2D renderArea - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - GetSwapChain().Extent, // VkExtent2D extent; - }, - 1, // uint32_t clearValueCount - &clear_value // const VkClearValue *pClearValues - }; - - vkCmdBeginRenderPass( command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); - - vkCmdBindPipeline( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); - - VkViewport viewport = { - 0.0f, // float x - 0.0f, // float y - static_cast(GetSwapChain().Extent.width), // float width - static_cast(GetSwapChain().Extent.height), // float height - 0.0f, // float minDepth - 1.0f // float maxDepth - }; - - VkRect2D scissor = { - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - { // VkExtent2D extent - GetSwapChain().Extent.width, // uint32_t width - GetSwapChain().Extent.height // uint32_t height - } - }; - - vkCmdSetViewport( command_buffer, 0, 1, &viewport ); - vkCmdSetScissor( command_buffer, 0, 1, &scissor ); - - VkDeviceSize offset = 0; - vkCmdBindVertexBuffers( command_buffer, 0, 1, &Vulkan.VertexBuffer.Handle, &offset ); - - vkCmdDraw( command_buffer, 4, 1, 0, 0 ); - - vkCmdEndRenderPass( command_buffer ); - - if( GetGraphicsQueue().Handle != GetPresentQueue().Handle ) { - VkImageMemoryBarrier barrier_from_draw_to_present = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout - GetGraphicsQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex - GetPresentQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex - image_parameters.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); - } - - if( vkEndCommandBuffer( command_buffer ) != VK_SUCCESS ) { - std::cout << "Could not record command buffer!" << std::endl; - return false; - } - return true; - } - - bool Tutorial05::CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ) { - if( framebuffer != VK_NULL_HANDLE ) { - vkDestroyFramebuffer( GetDevice(), framebuffer, nullptr ); - framebuffer = VK_NULL_HANDLE; - } - - VkFramebufferCreateInfo framebuffer_create_info = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkFramebufferCreateFlags flags - Vulkan.RenderPass, // VkRenderPass renderPass - 1, // uint32_t attachmentCount - &image_view, // const VkImageView *pAttachments - GetSwapChain().Extent.width, // uint32_t width - GetSwapChain().Extent.height, // uint32_t height - 1 // uint32_t layers - }; - - if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &framebuffer ) != VK_SUCCESS ) { - std::cout << "Could not create a framebuffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial05::ChildOnWindowSizeChanged() { - return true; - } - - bool Tutorial05::Draw() { - static size_t resource_index = 0; - RenderingResourcesData ¤t_rendering_resource = Vulkan.RenderingResources[resource_index]; - VkSwapchainKHR swap_chain = GetSwapChain().Handle; - uint32_t image_index; - - resource_index = (resource_index + 1) % VulkanTutorial05Parameters::ResourcesCount; - - if( vkWaitForFences( GetDevice(), 1, ¤t_rendering_resource.Fence, VK_FALSE, 1000000000 ) != VK_SUCCESS ) { - std::cout << "Waiting for fence takes too long!" << std::endl; - return false; - } - vkResetFences( GetDevice(), 1, ¤t_rendering_resource.Fence ); - - VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, current_rendering_resource.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); - switch( result ) { - case VK_SUCCESS: - case VK_SUBOPTIMAL_KHR: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; - return false; - } - - if( !PrepareFrame( current_rendering_resource.CommandBuffer, GetSwapChain().Images[image_index], current_rendering_resource.Framebuffer ) ) { - return false; - } - - VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - ¤t_rendering_resource.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores - &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - ¤t_rendering_resource.CommandBuffer, // const VkCommandBuffer *pCommandBuffers - 1, // uint32_t signalSemaphoreCount - ¤t_rendering_resource.FinishedRenderingSemaphore // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, current_rendering_resource.Fence ) != VK_SUCCESS ) { - return false; - } - - VkPresentInfoKHR present_info = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - ¤t_rendering_resource.FinishedRenderingSemaphore, // const VkSemaphore *pWaitSemaphores - 1, // uint32_t swapchainCount - &swap_chain, // const VkSwapchainKHR *pSwapchains - &image_index, // const uint32_t *pImageIndices - nullptr // VkResult *pResults - }; - result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); - - switch( result ) { - case VK_SUCCESS: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - case VK_SUBOPTIMAL_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during image presentation!" << std::endl; - return false; - } - - return true; - } - - void Tutorial05::ChildClear() { - } - - Tutorial05::~Tutorial05() { - if( GetDevice() != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( GetDevice() ); - - DestroyBuffer( Vulkan.VertexBuffer ); - - DestroyBuffer( Vulkan.StagingBuffer ); - - if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { - vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); - Vulkan.GraphicsPipeline = VK_NULL_HANDLE; - } - - if( Vulkan.RenderPass != VK_NULL_HANDLE ) { - vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); - Vulkan.RenderPass = VK_NULL_HANDLE; - } - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( Vulkan.RenderingResources[i].Framebuffer != VK_NULL_HANDLE ) { - vkDestroyFramebuffer( GetDevice(), Vulkan.RenderingResources[i].Framebuffer, nullptr ); - } - if( Vulkan.RenderingResources[i].CommandBuffer != VK_NULL_HANDLE ) { - vkFreeCommandBuffers( GetDevice(), Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ); - } - if( Vulkan.RenderingResources[i].ImageAvailableSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].ImageAvailableSemaphore, nullptr ); - } - if( Vulkan.RenderingResources[i].FinishedRenderingSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].FinishedRenderingSemaphore, nullptr ); - } - if( Vulkan.RenderingResources[i].Fence != VK_NULL_HANDLE ) { - vkDestroyFence( GetDevice(), Vulkan.RenderingResources[i].Fence, nullptr ); - } - } - - if( Vulkan.CommandPool != VK_NULL_HANDLE ) { - vkDestroyCommandPool( GetDevice(), Vulkan.CommandPool, nullptr ); - Vulkan.CommandPool = VK_NULL_HANDLE; - } - } - } - - void Tutorial05::DestroyBuffer( BufferParameters& buffer ) { - if( buffer.Handle != VK_NULL_HANDLE ) { - vkDestroyBuffer( GetDevice(), buffer.Handle, nullptr ); - buffer.Handle = VK_NULL_HANDLE; - } - - if( buffer.Memory != VK_NULL_HANDLE ) { - vkFreeMemory( GetDevice(), buffer.Memory, nullptr ); - buffer.Memory = VK_NULL_HANDLE; - } - } - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial05.h" +#include "VulkanFunctions.h" + +namespace ApiWithoutSecrets { + + Tutorial05::Tutorial05() : + Vulkan() { + } + + bool Tutorial05::CreateRenderingResources() { + if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.CommandPool ) ) { + return false; + } + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( !AllocateCommandBuffers( Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ) ) { + return false; + } + + if( !CreateSemaphore( &Vulkan.RenderingResources[i].ImageAvailableSemaphore ) ) { + return false; + } + + if( !CreateSemaphore( &Vulkan.RenderingResources[i].FinishedRenderingSemaphore ) ) { + return false; + } + + if( !CreateFence( VK_FENCE_CREATE_SIGNALED_BIT, &Vulkan.RenderingResources[i].Fence ) ) { + return false; + } + } + return true; + } + + bool Tutorial05::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { + VkCommandPoolCreateInfo cmd_pool_create_info = { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | // VkCommandPoolCreateFlags flags + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + queue_family_index // uint32_t queueFamilyIndex + }; + + if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { + std::cout << "Could not create command pool!" << std::endl; + return false; + } + return true; + } + + bool Tutorial05::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { + VkCommandBufferAllocateInfo command_buffer_allocate_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + pool, // VkCommandPool commandPool + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level + count // uint32_t bufferCount + }; + + if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { + std::cout << "Could not allocate command buffer!" << std::endl; + return false; + } + return true; + } + + bool Tutorial05::CreateSemaphore( VkSemaphore *semaphore ) { + VkSemaphoreCreateInfo semaphore_create_info = { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0 // VkSemaphoreCreateFlags flags + }; + + if( vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, semaphore ) != VK_SUCCESS ) { + std::cout << "Could not create semaphore!" << std::endl; + return false; + } + return true; + } + + bool Tutorial05::CreateFence( VkFenceCreateFlags flags, VkFence *fence ) { + VkFenceCreateInfo fence_create_info = { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + flags // VkFenceCreateFlags flags + }; + + if( vkCreateFence( GetDevice(), &fence_create_info, nullptr, fence ) != VK_SUCCESS ) { + std::cout << "Could not create a fence!" << std::endl; + return false; + } + return true; + } + + bool Tutorial05::CreateRenderPass() { + VkAttachmentDescription attachment_descriptions[] = { + { + 0, // VkAttachmentDescriptionFlags flags + GetSwapChain().Format, // VkFormat format + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR // VkImageLayout finalLayout + } + }; + + VkAttachmentReference color_attachment_references[] = { + { + 0, // uint32_t attachment + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout + } + }; + + VkSubpassDescription subpass_descriptions[] = { + { + 0, // VkSubpassDescriptionFlags flags + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint + 0, // uint32_t inputAttachmentCount + nullptr, // const VkAttachmentReference *pInputAttachments + 1, // uint32_t colorAttachmentCount + color_attachment_references, // const VkAttachmentReference *pColorAttachments + nullptr, // const VkAttachmentReference *pResolveAttachments + nullptr, // const VkAttachmentReference *pDepthStencilAttachment + 0, // uint32_t preserveAttachmentCount + nullptr // const uint32_t* pPreserveAttachments + } + }; + + std::vector dependencies = { + { + VK_SUBPASS_EXTERNAL, // uint32_t srcSubpass + 0, // uint32_t dstSubpass + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags dstStageMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_DEPENDENCY_BY_REGION_BIT // VkDependencyFlags dependencyFlags + }, + { + 0, // uint32_t srcSubpass + VK_SUBPASS_EXTERNAL, // uint32_t dstSubpass + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // VkPipelineStageFlags dstStageMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_DEPENDENCY_BY_REGION_BIT // VkDependencyFlags dependencyFlags + } + }; + + VkRenderPassCreateInfo render_pass_create_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkRenderPassCreateFlags flags + 1, // uint32_t attachmentCount + attachment_descriptions, // const VkAttachmentDescription *pAttachments + 1, // uint32_t subpassCount + subpass_descriptions, // const VkSubpassDescription *pSubpasses + static_cast(dependencies.size()), // uint32_t dependencyCount + &dependencies[0] // const VkSubpassDependency *pDependencies + }; + + if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { + std::cout << "Could not create render pass!" << std::endl; + return false; + } + + return true; + } + + Tools::AutoDeleter Tutorial05::CreateShaderModule( const char* filename ) { + const std::vector code = Tools::GetBinaryFileContents( filename ); + if( code.size() == 0 ) { + return Tools::AutoDeleter(); + } + + VkShaderModuleCreateInfo shader_module_create_info = { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkShaderModuleCreateFlags flags + code.size(), // size_t codeSize + reinterpret_cast(&code[0]) // const uint32_t *pCode + }; + + VkShaderModule shader_module; + if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { + std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; + return Tools::AutoDeleter(); + } + + return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); + } + + Tools::AutoDeleter Tutorial05::CreatePipelineLayout() { + VkPipelineLayoutCreateInfo layout_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineLayoutCreateFlags flags + 0, // uint32_t setLayoutCount + nullptr, // const VkDescriptorSetLayout *pSetLayouts + 0, // uint32_t pushConstantRangeCount + nullptr // const VkPushConstantRange *pPushConstantRanges + }; + + VkPipelineLayout pipeline_layout; + if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &pipeline_layout ) != VK_SUCCESS ) { + std::cout << "Could not create pipeline layout!" << std::endl; + return Tools::AutoDeleter(); + } + + return Tools::AutoDeleter( pipeline_layout, vkDestroyPipelineLayout, GetDevice() ); + } + + bool Tutorial05::CreatePipeline() { + Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data05/vert.spv" ); + Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data05/frag.spv" ); + + if( !vertex_shader_module || !fragment_shader_module ) { + return false; + } + + std::vector shader_stage_create_infos = { + // Vertex shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage + vertex_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + }, + // Fragment shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage + fragment_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + } + }; + + std::vector vertex_binding_descriptions = { + { + 0, // uint32_t binding + sizeof(VertexData), // uint32_t stride + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate + } + }; + + std::vector vertex_attribute_descriptions = { + { + 0, // uint32_t location + vertex_binding_descriptions[0].binding, // uint32_t binding + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format + offsetof(struct VertexData, x) // uint32_t offset + }, + { + 1, // uint32_t location + vertex_binding_descriptions[0].binding, // uint32_t binding + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format + offsetof(struct VertexData, r) // uint32_t offset + } + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineVertexInputStateCreateFlags flags + static_cast(vertex_binding_descriptions.size()), // uint32_t vertexBindingDescriptionCount + &vertex_binding_descriptions[0], // const VkVertexInputBindingDescription *pVertexBindingDescriptions + static_cast(vertex_attribute_descriptions.size()), // uint32_t vertexAttributeDescriptionCount + &vertex_attribute_descriptions[0] // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions + }; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineInputAssemblyStateCreateFlags flags + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology + VK_FALSE // VkBool32 primitiveRestartEnable + }; + + VkPipelineViewportStateCreateInfo viewport_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineViewportStateCreateFlags flags + 1, // uint32_t viewportCount + nullptr, // const VkViewport *pViewports + 1, // uint32_t scissorCount + nullptr // const VkRect2D *pScissors + }; + + VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineRasterizationStateCreateFlags flags + VK_FALSE, // VkBool32 depthClampEnable + VK_FALSE, // VkBool32 rasterizerDiscardEnable + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode + VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace + VK_FALSE, // VkBool32 depthBiasEnable + 0.0f, // float depthBiasConstantFactor + 0.0f, // float depthBiasClamp + 0.0f, // float depthBiasSlopeFactor + 1.0f // float lineWidth + }; + + VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineMultisampleStateCreateFlags flags + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples + VK_FALSE, // VkBool32 sampleShadingEnable + 1.0f, // float minSampleShading + nullptr, // const VkSampleMask *pSampleMask + VK_FALSE, // VkBool32 alphaToCoverageEnable + VK_FALSE // VkBool32 alphaToOneEnable + }; + + VkPipelineColorBlendAttachmentState color_blend_attachment_state = { + VK_FALSE, // VkBool32 blendEnable + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT + }; + + VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineColorBlendStateCreateFlags flags + VK_FALSE, // VkBool32 logicOpEnable + VK_LOGIC_OP_COPY, // VkLogicOp logicOp + 1, // uint32_t attachmentCount + &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments + { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] + }; + + std::vector dynamic_states = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + + VkPipelineDynamicStateCreateInfo dynamic_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineDynamicStateCreateFlags flags + static_cast(dynamic_states.size()), // uint32_t dynamicStateCount + &dynamic_states[0] // const VkDynamicState *pDynamicStates + }; + + Tools::AutoDeleter pipeline_layout = CreatePipelineLayout(); + if( !pipeline_layout ) { + return false; + } + + VkGraphicsPipelineCreateInfo pipeline_create_info = { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineCreateFlags flags + static_cast(shader_stage_create_infos.size()), // uint32_t stageCount + &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages + &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; + &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState + nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState + &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState + &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState + &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState + nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState + &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState + &dynamic_state_create_info, // const VkPipelineDynamicStateCreateInfo *pDynamicState + pipeline_layout.Get(), // VkPipelineLayout layout + Vulkan.RenderPass, // VkRenderPass renderPass + 0, // uint32_t subpass + VK_NULL_HANDLE, // VkPipeline basePipelineHandle + -1 // int32_t basePipelineIndex + }; + + if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { + std::cout << "Could not create graphics pipeline!" << std::endl; + return false; + } + return true; + } + + bool Tutorial05::CreateVertexBuffer() { + const std::vector& vertex_data = GetVertexData(); + + Vulkan.VertexBuffer.Size = static_cast(vertex_data.size() * sizeof(vertex_data[0])); + if( !CreateBuffer( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Vulkan.VertexBuffer ) ) { + std::cout << "Could not create vertex buffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial05::CreateStagingBuffer() { + Vulkan.StagingBuffer.Size = 4000; + if( !CreateBuffer( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, Vulkan.StagingBuffer ) ) { + std::cout << "Could not staging buffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial05::CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer ) { + VkBufferCreateInfo buffer_create_info = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkBufferCreateFlags flags + buffer.Size, // VkDeviceSize size + usage, // VkBufferUsageFlags usage + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode + 0, // uint32_t queueFamilyIndexCount + nullptr // const uint32_t *pQueueFamilyIndices + }; + + if( vkCreateBuffer( GetDevice(), &buffer_create_info, nullptr, &buffer.Handle ) != VK_SUCCESS ) { + std::cout << "Could not create buffer!" << std::endl; + return false; + } + + if( !AllocateBufferMemory( buffer.Handle, memoryProperty, &buffer.Memory ) ) { + std::cout << "Could not allocate memory for a buffer!" << std::endl; + return false; + } + + if( vkBindBufferMemory( GetDevice(), buffer.Handle, buffer.Memory, 0 ) != VK_SUCCESS ) { + std::cout << "Could not bind memory to a buffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial05::AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { + VkMemoryRequirements buffer_memory_requirements; + vkGetBufferMemoryRequirements( GetDevice(), buffer, &buffer_memory_requirements ); + + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); + + for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { + if( (buffer_memory_requirements.memoryTypeBits & (1 << i)) && + ((memory_properties.memoryTypes[i].propertyFlags & property) == property) ) { + + VkMemoryAllocateInfo memory_allocate_info = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + buffer_memory_requirements.size, // VkDeviceSize allocationSize + i // uint32_t memoryTypeIndex + }; + + if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { + return true; + } + } + } + return false; + } + + const std::vector& Tutorial05::GetVertexData() const { + static const std::vector vertex_data = { + -0.7f, -0.7f, 0.0f, 1.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + // + -0.7f, 0.7f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + // + 0.7f, -0.7f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + // + 0.7f, 0.7f, 0.0f, 1.0f, + 0.3f, 0.3f, 0.3f, 0.0f + }; + + return vertex_data; + } + + bool Tutorial05::CopyVertexData() { + // Prepare data in a staging buffer + const std::vector& vertex_data = GetVertexData(); + + void *staging_buffer_memory_pointer; + if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, Vulkan.VertexBuffer.Size, 0, &staging_buffer_memory_pointer) != VK_SUCCESS ) { + std::cout << "Could not map memory and upload data to a staging buffer!" << std::endl; + return false; + } + + memcpy( staging_buffer_memory_pointer, &vertex_data[0], Vulkan.VertexBuffer.Size ); + + VkMappedMemoryRange flush_range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory + 0, // VkDeviceSize offset + Vulkan.VertexBuffer.Size // VkDeviceSize size + }; + vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); + + vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); + + // Prepare command buffer to copy data from staging buffer to a vertex buffer + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); + + VkBufferCopy buffer_copy_info = { + 0, // VkDeviceSize srcOffset + 0, // VkDeviceSize dstOffset + Vulkan.VertexBuffer.Size // VkDeviceSize size + }; + vkCmdCopyBuffer( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.VertexBuffer.Handle, 1, &buffer_copy_info ); + + VkBufferMemoryBarrier buffer_memory_barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkAccessFlags dstAccessMask + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + Vulkan.VertexBuffer.Handle, // VkBuffer buffer + 0, // VkDeviceSize offset + VK_WHOLE_SIZE // VkDeviceSize size + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, &buffer_memory_barrier, 0, nullptr ); + + vkEndCommandBuffer( command_buffer ); + + // Submit command buffer and copy data from staging buffer to a vertex buffer + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // uint32_t waitSemaphoreCount + nullptr, // const VkSemaphore *pWaitSemaphores + nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + &command_buffer, // const VkCommandBuffer *pCommandBuffers + 0, // uint32_t signalSemaphoreCount + nullptr // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { + return false; + } + + vkDeviceWaitIdle( GetDevice() ); + + return true; + } + + bool Tutorial05::PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ) { + if( !CreateFramebuffer( framebuffer, image_parameters.View ) ) { + return false; + } + + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info ); + + VkImageSubresourceRange image_subresource_range = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + if( GetPresentQueue().Handle != GetGraphicsQueue().Handle ) { + VkImageMemoryBarrier barrier_from_present_to_draw = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout + GetPresentQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex + GetGraphicsQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex + image_parameters.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); + } + + VkClearValue clear_value = { + { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color + }; + + VkRenderPassBeginInfo render_pass_begin_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.RenderPass, // VkRenderPass renderPass + framebuffer, // VkFramebuffer framebuffer + { // VkRect2D renderArea + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + GetSwapChain().Extent, // VkExtent2D extent; + }, + 1, // uint32_t clearValueCount + &clear_value // const VkClearValue *pClearValues + }; + + vkCmdBeginRenderPass( command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); + + vkCmdBindPipeline( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); + + VkViewport viewport = { + 0.0f, // float x + 0.0f, // float y + static_cast(GetSwapChain().Extent.width), // float width + static_cast(GetSwapChain().Extent.height), // float height + 0.0f, // float minDepth + 1.0f // float maxDepth + }; + + VkRect2D scissor = { + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + { // VkExtent2D extent + GetSwapChain().Extent.width, // uint32_t width + GetSwapChain().Extent.height // uint32_t height + } + }; + + vkCmdSetViewport( command_buffer, 0, 1, &viewport ); + vkCmdSetScissor( command_buffer, 0, 1, &scissor ); + + VkDeviceSize offset = 0; + vkCmdBindVertexBuffers( command_buffer, 0, 1, &Vulkan.VertexBuffer.Handle, &offset ); + + vkCmdDraw( command_buffer, 4, 1, 0, 0 ); + + vkCmdEndRenderPass( command_buffer ); + + if( GetGraphicsQueue().Handle != GetPresentQueue().Handle ) { + VkImageMemoryBarrier barrier_from_draw_to_present = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout + GetGraphicsQueue().FamilyIndex, // uint32_t srcQueueFamilyIndex + GetPresentQueue().FamilyIndex, // uint32_t dstQueueFamilyIndex + image_parameters.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); + } + + if( vkEndCommandBuffer( command_buffer ) != VK_SUCCESS ) { + std::cout << "Could not record command buffer!" << std::endl; + return false; + } + return true; + } + + bool Tutorial05::CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ) { + if( framebuffer != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( GetDevice(), framebuffer, nullptr ); + framebuffer = VK_NULL_HANDLE; + } + + VkFramebufferCreateInfo framebuffer_create_info = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkFramebufferCreateFlags flags + Vulkan.RenderPass, // VkRenderPass renderPass + 1, // uint32_t attachmentCount + &image_view, // const VkImageView *pAttachments + GetSwapChain().Extent.width, // uint32_t width + GetSwapChain().Extent.height, // uint32_t height + 1 // uint32_t layers + }; + + if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &framebuffer ) != VK_SUCCESS ) { + std::cout << "Could not create a framebuffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial05::ChildOnWindowSizeChanged() { + return true; + } + + bool Tutorial05::Draw() { + static size_t resource_index = 0; + RenderingResourcesData ¤t_rendering_resource = Vulkan.RenderingResources[resource_index]; + VkSwapchainKHR swap_chain = GetSwapChain().Handle; + uint32_t image_index; + + resource_index = (resource_index + 1) % VulkanTutorial05Parameters::ResourcesCount; + + if( vkWaitForFences( GetDevice(), 1, ¤t_rendering_resource.Fence, VK_FALSE, 1000000000 ) != VK_SUCCESS ) { + std::cout << "Waiting for fence takes too long!" << std::endl; + return false; + } + vkResetFences( GetDevice(), 1, ¤t_rendering_resource.Fence ); + + VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, current_rendering_resource.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); + switch( result ) { + case VK_SUCCESS: + case VK_SUBOPTIMAL_KHR: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; + return false; + } + + if( !PrepareFrame( current_rendering_resource.CommandBuffer, GetSwapChain().Images[image_index], current_rendering_resource.Framebuffer ) ) { + return false; + } + + VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + ¤t_rendering_resource.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores + &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + ¤t_rendering_resource.CommandBuffer, // const VkCommandBuffer *pCommandBuffers + 1, // uint32_t signalSemaphoreCount + ¤t_rendering_resource.FinishedRenderingSemaphore // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, current_rendering_resource.Fence ) != VK_SUCCESS ) { + return false; + } + + VkPresentInfoKHR present_info = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + ¤t_rendering_resource.FinishedRenderingSemaphore, // const VkSemaphore *pWaitSemaphores + 1, // uint32_t swapchainCount + &swap_chain, // const VkSwapchainKHR *pSwapchains + &image_index, // const uint32_t *pImageIndices + nullptr // VkResult *pResults + }; + result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); + + switch( result ) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_SUBOPTIMAL_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during image presentation!" << std::endl; + return false; + } + + return true; + } + + void Tutorial05::ChildClear() { + } + + Tutorial05::~Tutorial05() { + if( GetDevice() != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( GetDevice() ); + + DestroyBuffer( Vulkan.VertexBuffer ); + + DestroyBuffer( Vulkan.StagingBuffer ); + + if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { + vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); + Vulkan.GraphicsPipeline = VK_NULL_HANDLE; + } + + if( Vulkan.RenderPass != VK_NULL_HANDLE ) { + vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); + Vulkan.RenderPass = VK_NULL_HANDLE; + } + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( Vulkan.RenderingResources[i].Framebuffer != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( GetDevice(), Vulkan.RenderingResources[i].Framebuffer, nullptr ); + } + if( Vulkan.RenderingResources[i].CommandBuffer != VK_NULL_HANDLE ) { + vkFreeCommandBuffers( GetDevice(), Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ); + } + if( Vulkan.RenderingResources[i].ImageAvailableSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].ImageAvailableSemaphore, nullptr ); + } + if( Vulkan.RenderingResources[i].FinishedRenderingSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].FinishedRenderingSemaphore, nullptr ); + } + if( Vulkan.RenderingResources[i].Fence != VK_NULL_HANDLE ) { + vkDestroyFence( GetDevice(), Vulkan.RenderingResources[i].Fence, nullptr ); + } + } + + if( Vulkan.CommandPool != VK_NULL_HANDLE ) { + vkDestroyCommandPool( GetDevice(), Vulkan.CommandPool, nullptr ); + Vulkan.CommandPool = VK_NULL_HANDLE; + } + } + } + + void Tutorial05::DestroyBuffer( BufferParameters& buffer ) { + if( buffer.Handle != VK_NULL_HANDLE ) { + vkDestroyBuffer( GetDevice(), buffer.Handle, nullptr ); + buffer.Handle = VK_NULL_HANDLE; + } + + if( buffer.Memory != VK_NULL_HANDLE ) { + vkFreeMemory( GetDevice(), buffer.Memory, nullptr ); + buffer.Memory = VK_NULL_HANDLE; + } + } + } // namespace ApiWithoutSecrets \ No newline at end of file diff --git a/Project/Tutorial05/Tutorial05.h b/Project/Tutorial05/Tutorial05.h index 20b99df..f8bef39 100644 --- a/Project/Tutorial05/Tutorial05.h +++ b/Project/Tutorial05/Tutorial05.h @@ -1,139 +1,139 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(TUTORIAL_05_HEADER) -#define TUTORIAL_05_HEADER - -#include "VulkanCommon.h" -#include "Tools.h" - -namespace ApiWithoutSecrets { - - // ************************************************************ // - // BufferParameters // - // // - // Vulkan Buffer's parameters container class // - // ************************************************************ // - struct BufferParameters { - VkBuffer Handle; - VkDeviceMemory Memory; - uint32_t Size; - - BufferParameters() : - Handle( VK_NULL_HANDLE ), - Memory( VK_NULL_HANDLE ), - Size( 0 ) { - } - }; - - // ************************************************************ // - // VertexData // - // // - // Struct describing data type and format of vertex attributes // - // ************************************************************ // - struct VertexData { - float x, y, z, w; - float r, g, b, a; - }; - - // ************************************************************ // - // RenderingResourcesData // - // // - // Struct containing data used during rendering process // - // ************************************************************ // - struct RenderingResourcesData { - VkFramebuffer Framebuffer; - VkCommandBuffer CommandBuffer; - VkSemaphore ImageAvailableSemaphore; - VkSemaphore FinishedRenderingSemaphore; - VkFence Fence; - - RenderingResourcesData() : - Framebuffer( VK_NULL_HANDLE ), - CommandBuffer( VK_NULL_HANDLE ), - ImageAvailableSemaphore( VK_NULL_HANDLE ), - FinishedRenderingSemaphore( VK_NULL_HANDLE ), - Fence( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // VulkanTutorial04Parameters // - // // - // Vulkan specific parameters // - // ************************************************************ // - struct VulkanTutorial05Parameters { - VkRenderPass RenderPass; - VkPipeline GraphicsPipeline; - BufferParameters VertexBuffer; - BufferParameters StagingBuffer; - VkCommandPool CommandPool; - std::vector RenderingResources; - - static const size_t ResourcesCount = 3; - - VulkanTutorial05Parameters() : - RenderPass( VK_NULL_HANDLE ), - GraphicsPipeline( VK_NULL_HANDLE ), - VertexBuffer(), - StagingBuffer(), - CommandPool( VK_NULL_HANDLE ), - RenderingResources( ResourcesCount ) { - } - }; - - // ************************************************************ // - // Tutorial04 // - // // - // Class for presenting Vulkan usage topics // - // ************************************************************ // - class Tutorial05 : public VulkanCommon { - public: - Tutorial05(); - ~Tutorial05(); - - bool CreateRenderingResources(); - bool CreateRenderPass(); - bool CreatePipeline(); - bool CreateVertexBuffer(); - bool CreateStagingBuffer(); - bool CopyVertexData(); - - bool Draw() override; - - private: - VulkanTutorial05Parameters Vulkan; - - bool CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ); - bool AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ); - bool CreateSemaphore( VkSemaphore *semaphore ); - bool CreateFence( VkFenceCreateFlags flags, VkFence *fence ); - Tools::AutoDeleter CreateShaderModule( const char* filename ); - Tools::AutoDeleter CreatePipelineLayout(); - bool CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer ); - bool AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ); - const std::vector& GetVertexData() const; - bool PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ); - bool CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ); - void DestroyBuffer( BufferParameters& buffer ); - - void ChildClear() override; - bool ChildOnWindowSizeChanged() override; - }; - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(TUTORIAL_05_HEADER) +#define TUTORIAL_05_HEADER + +#include "VulkanCommon.h" +#include "Tools.h" + +namespace ApiWithoutSecrets { + + // ************************************************************ // + // BufferParameters // + // // + // Vulkan Buffer's parameters container class // + // ************************************************************ // + struct BufferParameters { + VkBuffer Handle; + VkDeviceMemory Memory; + uint32_t Size; + + BufferParameters() : + Handle( VK_NULL_HANDLE ), + Memory( VK_NULL_HANDLE ), + Size( 0 ) { + } + }; + + // ************************************************************ // + // VertexData // + // // + // Struct describing data type and format of vertex attributes // + // ************************************************************ // + struct VertexData { + float x, y, z, w; + float r, g, b, a; + }; + + // ************************************************************ // + // RenderingResourcesData // + // // + // Struct containing data used during rendering process // + // ************************************************************ // + struct RenderingResourcesData { + VkFramebuffer Framebuffer; + VkCommandBuffer CommandBuffer; + VkSemaphore ImageAvailableSemaphore; + VkSemaphore FinishedRenderingSemaphore; + VkFence Fence; + + RenderingResourcesData() : + Framebuffer( VK_NULL_HANDLE ), + CommandBuffer( VK_NULL_HANDLE ), + ImageAvailableSemaphore( VK_NULL_HANDLE ), + FinishedRenderingSemaphore( VK_NULL_HANDLE ), + Fence( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // VulkanTutorial04Parameters // + // // + // Vulkan specific parameters // + // ************************************************************ // + struct VulkanTutorial05Parameters { + VkRenderPass RenderPass; + VkPipeline GraphicsPipeline; + BufferParameters VertexBuffer; + BufferParameters StagingBuffer; + VkCommandPool CommandPool; + std::vector RenderingResources; + + static const size_t ResourcesCount = 3; + + VulkanTutorial05Parameters() : + RenderPass( VK_NULL_HANDLE ), + GraphicsPipeline( VK_NULL_HANDLE ), + VertexBuffer(), + StagingBuffer(), + CommandPool( VK_NULL_HANDLE ), + RenderingResources( ResourcesCount ) { + } + }; + + // ************************************************************ // + // Tutorial04 // + // // + // Class for presenting Vulkan usage topics // + // ************************************************************ // + class Tutorial05 : public VulkanCommon { + public: + Tutorial05(); + ~Tutorial05(); + + bool CreateRenderingResources(); + bool CreateRenderPass(); + bool CreatePipeline(); + bool CreateVertexBuffer(); + bool CreateStagingBuffer(); + bool CopyVertexData(); + + bool Draw() override; + + private: + VulkanTutorial05Parameters Vulkan; + + bool CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ); + bool AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ); + bool CreateSemaphore( VkSemaphore *semaphore ); + bool CreateFence( VkFenceCreateFlags flags, VkFence *fence ); + Tools::AutoDeleter CreateShaderModule( const char* filename ); + Tools::AutoDeleter CreatePipelineLayout(); + bool CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer ); + bool AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ); + const std::vector& GetVertexData() const; + bool PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ); + bool CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ); + void DestroyBuffer( BufferParameters& buffer ); + + void ChildClear() override; + bool ChildOnWindowSizeChanged() override; + }; + +} // namespace ApiWithoutSecrets + #endif // TUTORIAL_05_HEADER \ No newline at end of file diff --git a/Project/Tutorial05/main.cpp b/Project/Tutorial05/main.cpp index 93e1aed..4fb391f 100644 --- a/Project/Tutorial05/main.cpp +++ b/Project/Tutorial05/main.cpp @@ -1,59 +1,59 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial05.h" - -int main( int argc, char **argv ) { - ApiWithoutSecrets::OS::Window window; - ApiWithoutSecrets::Tutorial05 tutorial05; - - // Window creation - if( !window.Create( "05 - Staging Resources" ) ) { - return -1; - } - - // Vulkan preparations and initialization - if( !tutorial05.PrepareVulkan( window.GetParameters() ) ) { - return -1; - } - - // Tutorial 05 - if( !tutorial05.CreateRenderingResources() ) { - return -1; - } - if( !tutorial05.CreateRenderPass() ) { - return -1; - } - if( !tutorial05.CreatePipeline() ) { - return -1; - } - if( !tutorial05.CreateVertexBuffer() ) { - return -1; - } - if( !tutorial05.CreateStagingBuffer() ) { - return -1; - } - if( !tutorial05.CopyVertexData() ) { - return -1; - } - - // Rendering loop - if( !window.RenderingLoop( tutorial05 ) ) { - return -1; - } - - return 0; -} +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial05.h" + +int main( int argc, char **argv ) { + ApiWithoutSecrets::OS::Window window; + ApiWithoutSecrets::Tutorial05 tutorial05; + + // Window creation + if( !window.Create( "05 - Staging Resources" ) ) { + return -1; + } + + // Vulkan preparations and initialization + if( !tutorial05.PrepareVulkan( window.GetParameters() ) ) { + return -1; + } + + // Tutorial 05 + if( !tutorial05.CreateRenderingResources() ) { + return -1; + } + if( !tutorial05.CreateRenderPass() ) { + return -1; + } + if( !tutorial05.CreatePipeline() ) { + return -1; + } + if( !tutorial05.CreateVertexBuffer() ) { + return -1; + } + if( !tutorial05.CreateStagingBuffer() ) { + return -1; + } + if( !tutorial05.CopyVertexData() ) { + return -1; + } + + // Rendering loop + if( !window.RenderingLoop( tutorial05 ) ) { + return -1; + } + + return 0; +} diff --git a/Project/Tutorial06/Tutorial06.cpp b/Project/Tutorial06/Tutorial06.cpp index f2bc219..ee0d284 100644 --- a/Project/Tutorial06/Tutorial06.cpp +++ b/Project/Tutorial06/Tutorial06.cpp @@ -1,1228 +1,1228 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial06.h" -#include "VulkanFunctions.h" - -namespace ApiWithoutSecrets { - - Tutorial06::Tutorial06() : - Vulkan() { - } - - bool Tutorial06::CreateRenderingResources() { - if( !CreateCommandBuffers() ) { - return false; - } - if( !CreateSemaphores() ) { - return false; - } - if( !CreateFences() ) { - return false; - } - return true; - } - - bool Tutorial06::CreateCommandBuffers() { - if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.CommandPool ) ) { - std::cout << "Could not create command pool!" << std::endl; - return false; - } - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( !AllocateCommandBuffers( Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ) ) { - std::cout << "Could not allocate command buffer!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial06::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { - VkCommandPoolCreateInfo cmd_pool_create_info = { - VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | // VkCommandPoolCreateFlags flags - VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - queue_family_index // uint32_t queueFamilyIndex - }; - - if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { - return false; - } - return true; - } - - bool Tutorial06::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { - VkCommandBufferAllocateInfo command_buffer_allocate_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - pool, // VkCommandPool commandPool - VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level - count // uint32_t bufferCount - }; - - if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { - return false; - } - return true; - } - - bool Tutorial06::CreateSemaphores() { - VkSemaphoreCreateInfo semaphore_create_info = { - VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0 // VkSemaphoreCreateFlags flags - }; - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].ImageAvailableSemaphore ) != VK_SUCCESS) || - (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].FinishedRenderingSemaphore ) != VK_SUCCESS) ) { - std::cout << "Could not create semaphores!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial06::CreateFences() { - VkFenceCreateInfo fence_create_info = { - VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_FENCE_CREATE_SIGNALED_BIT // VkFenceCreateFlags flags - }; - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( vkCreateFence( GetDevice(), &fence_create_info, nullptr, &Vulkan.RenderingResources[i].Fence ) != VK_SUCCESS ) { - std::cout << "Could not create a fence!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial06::CreateStagingBuffer() { - Vulkan.StagingBuffer.Size = 1000000; - if( !CreateBuffer( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, Vulkan.StagingBuffer ) ) { - std::cout << "Could not create staging buffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial06::CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer ) { - VkBufferCreateInfo buffer_create_info = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkBufferCreateFlags flags - buffer.Size, // VkDeviceSize size - usage, // VkBufferUsageFlags usage - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode - 0, // uint32_t queueFamilyIndexCount - nullptr // const uint32_t *pQueueFamilyIndices - }; - - if( vkCreateBuffer( GetDevice(), &buffer_create_info, nullptr, &buffer.Handle ) != VK_SUCCESS ) { - std::cout << "Could not create buffer!" << std::endl; - return false; - } - - if( !AllocateBufferMemory( buffer.Handle, memoryProperty, &buffer.Memory ) ) { - std::cout << "Could not allocate memory for a buffer!" << std::endl; - return false; - } - - if( vkBindBufferMemory( GetDevice(), buffer.Handle, buffer.Memory, 0 ) != VK_SUCCESS ) { - std::cout << "Could not bind memory to a buffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial06::AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { - VkMemoryRequirements buffer_memory_requirements; - vkGetBufferMemoryRequirements( GetDevice(), buffer, &buffer_memory_requirements ); - - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); - - for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { - if( (buffer_memory_requirements.memoryTypeBits & (1 << i)) && - (memory_properties.memoryTypes[i].propertyFlags & property) ) { - - VkMemoryAllocateInfo memory_allocate_info = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - buffer_memory_requirements.size, // VkDeviceSize allocationSize - i // uint32_t memoryTypeIndex - }; - - if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { - return true; - } - } - } - return false; - } - - bool Tutorial06::CreateTexture() { - int width = 0, height = 0, data_size = 0; - std::vector texture_data = Tools::GetImageData( "Data06/texture.png", 4, &width, &height, nullptr, &data_size ); - if( texture_data.size() == 0 ) { - return false; - } - - if( !CreateImage( width, height, &Vulkan.Image.Handle ) ) { - std::cout << "Could not create image!" << std::endl; - return false; - } - - if( !AllocateImageMemory( Vulkan.Image.Handle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &Vulkan.Image.Memory ) ) { - std::cout << "Could not allocate memory for image!" << std::endl; - return false; - } - - if( vkBindImageMemory( GetDevice(), Vulkan.Image.Handle, Vulkan.Image.Memory, 0 ) != VK_SUCCESS ) { - std::cout << "Could not bind memory to an image!" << std::endl; - return false; - } - - if( !CreateImageView( Vulkan.Image ) ) { - std::cout << "Could not create image view!" << std::endl; - return false; - } - - if( !CreateSampler( &Vulkan.Image.Sampler ) ) { - std::cout << "Could not create sampler!" << std::endl; - return false; - } - - if( !CopyTextureData( &texture_data[0], data_size, width, height ) ) { - std::cout << "Could not upload texture data to device memory!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial06::CreateImage( uint32_t width, uint32_t height, VkImage *image ) { - VkImageCreateInfo image_create_info = { - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void *pNext - 0, // VkImageCreateFlags flags - VK_IMAGE_TYPE_2D, // VkImageType imageType - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format - { // VkExtent3D extent - width, // uint32_t width - height, // uint32_t height - 1 // uint32_t depth - }, - 1, // uint32_t mipLevels - 1, // uint32_t arrayLayers - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples - VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling - VK_IMAGE_USAGE_TRANSFER_DST_BIT | // VkImageUsageFlags usage - VK_IMAGE_USAGE_SAMPLED_BIT, - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode - 0, // uint32_t queueFamilyIndexCount - nullptr, // const uint32_t* pQueueFamilyIndices - VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout - }; - - return vkCreateImage( GetDevice(), &image_create_info, nullptr, image ) == VK_SUCCESS; - } - - bool Tutorial06::AllocateImageMemory( VkImage image, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { - VkMemoryRequirements image_memory_requirements; - vkGetImageMemoryRequirements( GetDevice(), image, &image_memory_requirements ); - - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); - - for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { - if( (image_memory_requirements.memoryTypeBits & (1 << i)) && - (memory_properties.memoryTypes[i].propertyFlags & property) ) { - - VkMemoryAllocateInfo memory_allocate_info = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - image_memory_requirements.size, // VkDeviceSize allocationSize - i // uint32_t memoryTypeIndex - }; - - if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { - return true; - } - } - } - return false; - } - - bool Tutorial06::CreateImageView( ImageParameters &image_parameters ) { - VkImageViewCreateInfo image_view_create_info = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkImageViewCreateFlags flags - image_parameters.Handle, // VkImage image - VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format - { // VkComponentMapping components - VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle r - VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle g - VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle b - VK_COMPONENT_SWIZZLE_IDENTITY // VkComponentSwizzle a - }, - { // VkImageSubresourceRange subresourceRange - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - } - }; - - return vkCreateImageView( GetDevice(), &image_view_create_info, nullptr, &image_parameters.View ) == VK_SUCCESS; - } - - bool Tutorial06::CreateSampler( VkSampler *sampler ) { - VkSamplerCreateInfo sampler_create_info = { - VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0, // VkSamplerCreateFlags flags - VK_FILTER_LINEAR, // VkFilter magFilter - VK_FILTER_LINEAR, // VkFilter minFilter - VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW - 0.0f, // float mipLodBias - VK_FALSE, // VkBool32 anisotropyEnable - 1.0f, // float maxAnisotropy - VK_FALSE, // VkBool32 compareEnable - VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp - 0.0f, // float minLod - 0.0f, // float maxLod - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor - VK_FALSE // VkBool32 unnormalizedCoordinates - }; - - return vkCreateSampler( GetDevice(), &sampler_create_info, nullptr, sampler ) == VK_SUCCESS; - } - - bool Tutorial06::CopyTextureData( char *texture_data, uint32_t data_size, uint32_t width, uint32_t height ) { - // Prepare data in staging buffer - - void *staging_buffer_memory_pointer; - if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, data_size, 0, &staging_buffer_memory_pointer ) != VK_SUCCESS ) { - std::cout << "Could not map memory and upload texture data to a staging buffer!" << std::endl; - return false; - } - - memcpy( staging_buffer_memory_pointer, texture_data, data_size ); - - VkMappedMemoryRange flush_range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory - 0, // VkDeviceSize offset - data_size // VkDeviceSize size - }; - vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); - - vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); - - // Prepare command buffer to copy data from staging buffer to a vertex buffer - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); - - VkImageSubresourceRange image_subresource_range = { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }; - - VkImageMemoryBarrier image_memory_barrier_from_undefined_to_transfer_dst = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkAccessFlags srcAccessMask - VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - Vulkan.Image.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier_from_undefined_to_transfer_dst); - - VkBufferImageCopy buffer_image_copy_info = { - 0, // VkDeviceSize bufferOffset - 0, // uint32_t bufferRowLength - 0, // uint32_t bufferImageHeight - { // VkImageSubresourceLayers imageSubresource - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t mipLevel - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }, - { // VkOffset3D imageOffset - 0, // int32_t x - 0, // int32_t y - 0 // int32_t z - }, - { // VkExtent3D imageExtent - width, // uint32_t width - height, // uint32_t height - 1 // uint32_t depth - } - }; - vkCmdCopyBufferToImage( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.Image.Handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy_info ); - - VkImageMemoryBarrier image_memory_barrier_from_transfer_to_shader_read = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - Vulkan.Image.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier_from_transfer_to_shader_read); - - vkEndCommandBuffer( command_buffer ); - - // Submit command buffer and copy data from staging buffer to a vertex buffer - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // uint32_t waitSemaphoreCount - nullptr, // const VkSemaphore *pWaitSemaphores - nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - &command_buffer, // const VkCommandBuffer *pCommandBuffers - 0, // uint32_t signalSemaphoreCount - nullptr // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { - return false; - } - - vkDeviceWaitIdle( GetDevice() ); - - return true; - } - - bool Tutorial06::CreateDescriptorSetLayout() { - VkDescriptorSetLayoutBinding layout_binding = { - 0, // uint32_t binding - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType - 1, // uint32_t descriptorCount - VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags - nullptr // const VkSampler *pImmutableSamplers - }; - - VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = { - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDescriptorSetLayoutCreateFlags flags - 1, // uint32_t bindingCount - &layout_binding // const VkDescriptorSetLayoutBinding *pBindings - }; - - if( vkCreateDescriptorSetLayout( GetDevice(), &descriptor_set_layout_create_info, nullptr, &Vulkan.DescriptorSet.Layout ) != VK_SUCCESS ) { - std::cout << "Could not create descriptor set layout!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial06::CreateDescriptorPool() { - VkDescriptorPoolSize pool_size = { - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType type - 1 // uint32_t descriptorCount - }; - - VkDescriptorPoolCreateInfo descriptor_pool_create_info = { - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDescriptorPoolCreateFlags flags - 1, // uint32_t maxSets - 1, // uint32_t poolSizeCount - &pool_size // const VkDescriptorPoolSize *pPoolSizes - }; - - if( vkCreateDescriptorPool( GetDevice(), &descriptor_pool_create_info, nullptr, &Vulkan.DescriptorSet.Pool ) != VK_SUCCESS ) { - std::cout << "Could not create descriptor pool!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial06::AllocateDescriptorSet() { - VkDescriptorSetAllocateInfo descriptor_set_allocate_info = { - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.DescriptorSet.Pool, // VkDescriptorPool descriptorPool - 1, // uint32_t descriptorSetCount - &Vulkan.DescriptorSet.Layout // const VkDescriptorSetLayout *pSetLayouts - }; - - if( vkAllocateDescriptorSets( GetDevice(), &descriptor_set_allocate_info, &Vulkan.DescriptorSet.Handle ) != VK_SUCCESS ) { - std::cout << "Could not allocate descriptor set!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial06::UpdateDescriptorSet() { - VkDescriptorImageInfo image_info = { - Vulkan.Image.Sampler, // VkSampler sampler - Vulkan.Image.View, // VkImageView imageView - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout - }; - - VkWriteDescriptorSet descriptor_writes = { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.DescriptorSet.Handle, // VkDescriptorSet dstSet - 0, // uint32_t dstBinding - 0, // uint32_t dstArrayElement - 1, // uint32_t descriptorCount - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType - &image_info, // const VkDescriptorImageInfo *pImageInfo - nullptr, // const VkDescriptorBufferInfo *pBufferInfo - nullptr // const VkBufferView *pTexelBufferView - }; - - vkUpdateDescriptorSets( GetDevice(), 1, &descriptor_writes, 0, nullptr ); - return true; - } - - bool Tutorial06::CreateRenderPass() { - VkAttachmentDescription attachment_descriptions[] = { - { - 0, // VkAttachmentDescriptionFlags flags - GetSwapChain().Format, // VkFormat format - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout - } - }; - - VkAttachmentReference color_attachment_references[] = { - { - 0, // uint32_t attachment - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout - } - }; - - VkSubpassDescription subpass_descriptions[] = { - { - 0, // VkSubpassDescriptionFlags flags - VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint - 0, // uint32_t inputAttachmentCount - nullptr, // const VkAttachmentReference *pInputAttachments - 1, // uint32_t colorAttachmentCount - color_attachment_references, // const VkAttachmentReference *pColorAttachments - nullptr, // const VkAttachmentReference *pResolveAttachments - nullptr, // const VkAttachmentReference *pDepthStencilAttachment - 0, // uint32_t preserveAttachmentCount - nullptr // const uint32_t* pPreserveAttachments - } - }; - - VkRenderPassCreateInfo render_pass_create_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkRenderPassCreateFlags flags - 1, // uint32_t attachmentCount - attachment_descriptions, // const VkAttachmentDescription *pAttachments - 1, // uint32_t subpassCount - subpass_descriptions, // const VkSubpassDescription *pSubpasses - 0, // uint32_t dependencyCount - nullptr // const VkSubpassDependency *pDependencies - }; - - if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { - std::cout << "Could not create render pass!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial06::CreatePipelineLayout() { - VkPipelineLayoutCreateInfo layout_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineLayoutCreateFlags flags - 1, // uint32_t setLayoutCount - &Vulkan.DescriptorSet.Layout, // const VkDescriptorSetLayout *pSetLayouts - 0, // uint32_t pushConstantRangeCount - nullptr // const VkPushConstantRange *pPushConstantRanges - }; - - if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &Vulkan.PipelineLayout ) != VK_SUCCESS ) { - std::cout << "Could not create pipeline layout!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial06::CreatePipeline() { - Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data06/vert.spv" ); - Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data06/frag.spv" ); - - if( !vertex_shader_module || !fragment_shader_module ) { - return false; - } - - std::vector shader_stage_create_infos = { - // Vertex shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage - vertex_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - }, - // Fragment shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage - fragment_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - } - }; - - VkVertexInputBindingDescription vertex_binding_description = { - 0, // uint32_t binding - sizeof(VertexData), // uint32_t stride - VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate - }; - - VkVertexInputAttributeDescription vertex_attribute_descriptions[] = { - { - 0, // uint32_t location - vertex_binding_description.binding, // uint32_t binding - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format - 0 // uint32_t offset - }, - { - 1, // uint32_t location - vertex_binding_description.binding, // uint32_t binding - VK_FORMAT_R32G32_SFLOAT, // VkFormat format - 4 * sizeof(float) // uint32_t offset - } - }; - - VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineVertexInputStateCreateFlags flags; - 1, // uint32_t vertexBindingDescriptionCount - &vertex_binding_description, // const VkVertexInputBindingDescription *pVertexBindingDescriptions - 2, // uint32_t vertexAttributeDescriptionCount - vertex_attribute_descriptions // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions - }; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineInputAssemblyStateCreateFlags flags - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology - VK_FALSE // VkBool32 primitiveRestartEnable - }; - - VkPipelineViewportStateCreateInfo viewport_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineViewportStateCreateFlags flags - 1, // uint32_t viewportCount - nullptr, // const VkViewport *pViewports - 1, // uint32_t scissorCount - nullptr // const VkRect2D *pScissors - }; - - VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineRasterizationStateCreateFlags flags - VK_FALSE, // VkBool32 depthClampEnable - VK_FALSE, // VkBool32 rasterizerDiscardEnable - VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode - VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode - VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace - VK_FALSE, // VkBool32 depthBiasEnable - 0.0f, // float depthBiasConstantFactor - 0.0f, // float depthBiasClamp - 0.0f, // float depthBiasSlopeFactor - 1.0f // float lineWidth - }; - - VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineMultisampleStateCreateFlags flags - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples - VK_FALSE, // VkBool32 sampleShadingEnable - 1.0f, // float minSampleShading - nullptr, // const VkSampleMask *pSampleMask - VK_FALSE, // VkBool32 alphaToCoverageEnable - VK_FALSE // VkBool32 alphaToOneEnable - }; - - VkPipelineColorBlendAttachmentState color_blend_attachment_state = { - VK_FALSE, // VkBool32 blendEnable - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT - }; - - VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineColorBlendStateCreateFlags flags - VK_FALSE, // VkBool32 logicOpEnable - VK_LOGIC_OP_COPY, // VkLogicOp logicOp - 1, // uint32_t attachmentCount - &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments - { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] - }; - - VkDynamicState dynamic_states[] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; - - VkPipelineDynamicStateCreateInfo dynamic_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineDynamicStateCreateFlags flags - 2, // uint32_t dynamicStateCount - dynamic_states // const VkDynamicState *pDynamicStates - }; - - VkGraphicsPipelineCreateInfo pipeline_create_info = { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineCreateFlags flags - static_cast(shader_stage_create_infos.size()), // uint32_t stageCount - &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages - &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; - &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState - nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState - &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState - &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState - &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState - nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState - &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState - &dynamic_state_create_info, // const VkPipelineDynamicStateCreateInfo *pDynamicState - Vulkan.PipelineLayout, // VkPipelineLayout layout - Vulkan.RenderPass, // VkRenderPass renderPass - 0, // uint32_t subpass - VK_NULL_HANDLE, // VkPipeline basePipelineHandle - -1 // int32_t basePipelineIndex - }; - - if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { - std::cout << "Could not create graphics pipeline!" << std::endl; - return false; - } - return true; - } - - Tools::AutoDeleter Tutorial06::CreateShaderModule( const char* filename ) { - const std::vector code = Tools::GetBinaryFileContents( filename ); - if( code.size() == 0 ) { - return Tools::AutoDeleter(); - } - - VkShaderModuleCreateInfo shader_module_create_info = { - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkShaderModuleCreateFlags flags - code.size(), // size_t codeSize - reinterpret_cast(&code[0]) // const uint32_t *pCode - }; - - VkShaderModule shader_module; - if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { - std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; - return Tools::AutoDeleter(); - } - - return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); - } - - bool Tutorial06::CreateVertexBuffer() { - const std::vector& vertex_data = GetVertexData(); - - Vulkan.VertexBuffer.Size = static_cast(vertex_data.size() * sizeof(vertex_data[0])); - if( !CreateBuffer( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Vulkan.VertexBuffer ) ) { - std::cout << "Could not create vertex buffer!" << std::endl; - return false; - } - - if( !CopyVertexData() ) { - return false; - } - - return true; - } - - const std::vector& Tutorial06::GetVertexData() const { - static const std::vector vertex_data = { - -0.7f, -0.7f, 0.0f, 1.0f, - -0.1f, -0.1f, - // - -0.7f, 0.7f, 0.0f, 1.0f, - -0.1f, 1.1f, - // - 0.7f, -0.7f, 0.0f, 1.0f, - 1.1f, -0.1f, - // - 0.7f, 0.7f, 0.0f, 1.0f, - 1.1f, 1.1f, - }; - - return vertex_data; - } - - bool Tutorial06::CopyVertexData() { - // Prepare data in staging buffer - const std::vector& vertex_data = GetVertexData(); - - void *staging_buffer_memory_pointer; - if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, Vulkan.VertexBuffer.Size, 0, &staging_buffer_memory_pointer) != VK_SUCCESS ) { - std::cout << "Could not map memory and upload data to a staging buffer!" << std::endl; - return false; - } - - memcpy( staging_buffer_memory_pointer, &vertex_data[0], Vulkan.VertexBuffer.Size ); - - VkMappedMemoryRange flush_range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory - 0, // VkDeviceSize offset - Vulkan.VertexBuffer.Size // VkDeviceSize size - }; - vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); - - vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); - - // Prepare command buffer to copy data from staging buffer to a vertex buffer - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); - - VkBufferCopy buffer_copy_info = { - 0, // VkDeviceSize srcOffset - 0, // VkDeviceSize dstOffset - Vulkan.VertexBuffer.Size // VkDeviceSize size - }; - vkCmdCopyBuffer( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.VertexBuffer.Handle, 1, &buffer_copy_info ); - - VkBufferMemoryBarrier buffer_memory_barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; - nullptr, // const void *pNext - VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkAccessFlags dstAccessMask - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - Vulkan.VertexBuffer.Handle, // VkBuffer buffer - 0, // VkDeviceSize offset - VK_WHOLE_SIZE // VkDeviceSize size - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, &buffer_memory_barrier, 0, nullptr ); - - vkEndCommandBuffer( command_buffer ); - - // Submit command buffer and copy data from staging buffer to a vertex buffer - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // uint32_t waitSemaphoreCount - nullptr, // const VkSemaphore *pWaitSemaphores - nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - &command_buffer, // const VkCommandBuffer *pCommandBuffers - 0, // uint32_t signalSemaphoreCount - nullptr // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { - return false; - } - - vkDeviceWaitIdle( GetDevice() ); - - return true; - } - - bool Tutorial06::PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ) { - if( !CreateFramebuffer( framebuffer, image_parameters.View ) ) { - return false; - } - - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info ); - - VkImageSubresourceRange image_subresource_range = { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }; - - uint32_t present_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetPresentQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED; - uint32_t graphics_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetGraphicsQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED; - VkImageMemoryBarrier barrier_from_present_to_draw = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout - present_queue_family_index, // uint32_t srcQueueFamilyIndex - graphics_queue_family_index, // uint32_t dstQueueFamilyIndex - image_parameters.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); - - VkClearValue clear_value = { - { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color - }; - - VkRenderPassBeginInfo render_pass_begin_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.RenderPass, // VkRenderPass renderPass - framebuffer, // VkFramebuffer framebuffer - { // VkRect2D renderArea - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - GetSwapChain().Extent, // VkExtent2D extent; - }, - 1, // uint32_t clearValueCount - &clear_value // const VkClearValue *pClearValues - }; - - vkCmdBeginRenderPass( command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); - - vkCmdBindPipeline( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); - - VkViewport viewport = { - 0.0f, // float x - 0.0f, // float y - static_cast(GetSwapChain().Extent.width), // float width - static_cast(GetSwapChain().Extent.height), // float height - 0.0f, // float minDepth - 1.0f // float maxDepth - }; - - VkRect2D scissor = { - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - { // VkExtent2D extent - GetSwapChain().Extent.width, // uint32_t width - GetSwapChain().Extent.height // uint32_t height - } - }; - - vkCmdSetViewport( command_buffer, 0, 1, &viewport ); - vkCmdSetScissor( command_buffer, 0, 1, &scissor ); - - VkDeviceSize offset = 0; - vkCmdBindVertexBuffers( command_buffer, 0, 1, &Vulkan.VertexBuffer.Handle, &offset ); - - vkCmdBindDescriptorSets( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.PipelineLayout, 0, 1, &Vulkan.DescriptorSet.Handle, 0, nullptr ); - - vkCmdDraw( command_buffer, 4, 1, 0, 0 ); - - vkCmdEndRenderPass( command_buffer ); - - VkImageMemoryBarrier barrier_from_draw_to_present = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout - graphics_queue_family_index, // uint32_t srcQueueFamilyIndex - present_queue_family_index, // uint32_t dstQueueFamilyIndex - image_parameters.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); - - if( vkEndCommandBuffer( command_buffer ) != VK_SUCCESS ) { - std::cout << "Could not record command buffer!" << std::endl; - return false; - } - return true; - } - - bool Tutorial06::CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ) { - if( framebuffer != VK_NULL_HANDLE ) { - vkDestroyFramebuffer( GetDevice(), framebuffer, nullptr ); - framebuffer = VK_NULL_HANDLE; - } - - VkFramebufferCreateInfo framebuffer_create_info = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkFramebufferCreateFlags flags - Vulkan.RenderPass, // VkRenderPass renderPass - 1, // uint32_t attachmentCount - &image_view, // const VkImageView *pAttachments - GetSwapChain().Extent.width, // uint32_t width - GetSwapChain().Extent.height, // uint32_t height - 1 // uint32_t layers - }; - - if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &framebuffer ) != VK_SUCCESS ) { - std::cout << "Could not create a framebuffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial06::ChildOnWindowSizeChanged() { - return true; - } - - bool Tutorial06::Draw() { - static size_t resource_index = 0; - RenderingResourcesData ¤t_rendering_resource = Vulkan.RenderingResources[resource_index]; - VkSwapchainKHR swap_chain = GetSwapChain().Handle; - uint32_t image_index; - - resource_index = (resource_index + 1) % VulkanTutorial06Parameters::ResourcesCount; - - if( vkWaitForFences( GetDevice(), 1, ¤t_rendering_resource.Fence, VK_FALSE, 1000000000 ) != VK_SUCCESS ) { - std::cout << "Waiting for fence takes too long!" << std::endl; - return false; - } - vkResetFences( GetDevice(), 1, ¤t_rendering_resource.Fence ); - - VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, current_rendering_resource.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); - switch( result ) { - case VK_SUCCESS: - case VK_SUBOPTIMAL_KHR: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; - return false; - } - - if( !PrepareFrame( current_rendering_resource.CommandBuffer, GetSwapChain().Images[image_index], current_rendering_resource.Framebuffer ) ) { - return false; - } - - VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - ¤t_rendering_resource.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores - &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - ¤t_rendering_resource.CommandBuffer, // const VkCommandBuffer *pCommandBuffers - 1, // uint32_t signalSemaphoreCount - ¤t_rendering_resource.FinishedRenderingSemaphore // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, current_rendering_resource.Fence ) != VK_SUCCESS ) { - return false; - } - - VkPresentInfoKHR present_info = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - ¤t_rendering_resource.FinishedRenderingSemaphore, // const VkSemaphore *pWaitSemaphores - 1, // uint32_t swapchainCount - &swap_chain, // const VkSwapchainKHR *pSwapchains - &image_index, // const uint32_t *pImageIndices - nullptr // VkResult *pResults - }; - result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); - - switch( result ) { - case VK_SUCCESS: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - case VK_SUBOPTIMAL_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during image presentation!" << std::endl; - return false; - } - - return true; - } - - void Tutorial06::ChildClear() { - } - - Tutorial06::~Tutorial06() { - if( GetDevice() != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( GetDevice() ); - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( Vulkan.RenderingResources[i].Framebuffer != VK_NULL_HANDLE ) { - vkDestroyFramebuffer( GetDevice(), Vulkan.RenderingResources[i].Framebuffer, nullptr ); - } - if( Vulkan.RenderingResources[i].CommandBuffer != VK_NULL_HANDLE ) { - vkFreeCommandBuffers( GetDevice(), Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ); - } - if( Vulkan.RenderingResources[i].ImageAvailableSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].ImageAvailableSemaphore, nullptr ); - } - if( Vulkan.RenderingResources[i].FinishedRenderingSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].FinishedRenderingSemaphore, nullptr ); - } - if( Vulkan.RenderingResources[i].Fence != VK_NULL_HANDLE ) { - vkDestroyFence( GetDevice(), Vulkan.RenderingResources[i].Fence, nullptr ); - } - } - - if( Vulkan.CommandPool != VK_NULL_HANDLE ) { - vkDestroyCommandPool( GetDevice(), Vulkan.CommandPool, nullptr ); - Vulkan.CommandPool = VK_NULL_HANDLE; - } - - DestroyBuffer( Vulkan.VertexBuffer ); - - DestroyBuffer( Vulkan.StagingBuffer ); - - if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { - vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); - Vulkan.GraphicsPipeline = VK_NULL_HANDLE; - } - - if( Vulkan.PipelineLayout != VK_NULL_HANDLE ) { - vkDestroyPipelineLayout( GetDevice(), Vulkan.PipelineLayout, nullptr ); - Vulkan.PipelineLayout = VK_NULL_HANDLE; - } - - if( Vulkan.RenderPass != VK_NULL_HANDLE ) { - vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); - Vulkan.RenderPass = VK_NULL_HANDLE; - } - - if( Vulkan.DescriptorSet.Pool != VK_NULL_HANDLE ) { - vkDestroyDescriptorPool( GetDevice(), Vulkan.DescriptorSet.Pool, nullptr ); - Vulkan.DescriptorSet.Pool = VK_NULL_HANDLE; - } - - if( Vulkan.DescriptorSet.Layout != VK_NULL_HANDLE ) { - vkDestroyDescriptorSetLayout( GetDevice(), Vulkan.DescriptorSet.Layout, nullptr ); - Vulkan.DescriptorSet.Layout = VK_NULL_HANDLE; - } - - if( Vulkan.Image.Sampler != VK_NULL_HANDLE ) { - vkDestroySampler( GetDevice(), Vulkan.Image.Sampler, nullptr ); - Vulkan.Image.Sampler = VK_NULL_HANDLE; - } - - if( Vulkan.Image.View != VK_NULL_HANDLE ) { - vkDestroyImageView( GetDevice(), Vulkan.Image.View, nullptr ); - Vulkan.Image.View = VK_NULL_HANDLE; - } - - if( Vulkan.Image.Handle != VK_NULL_HANDLE ) { - vkDestroyImage( GetDevice(), Vulkan.Image.Handle, nullptr ); - Vulkan.Image.Handle = VK_NULL_HANDLE; - } - - if( Vulkan.Image.Memory != VK_NULL_HANDLE ) { - vkFreeMemory( GetDevice(), Vulkan.Image.Memory, nullptr ); - Vulkan.Image.Memory = VK_NULL_HANDLE; - } - } - } - - void Tutorial06::DestroyBuffer( BufferParameters& buffer ) { - if( buffer.Handle != VK_NULL_HANDLE ) { - vkDestroyBuffer( GetDevice(), buffer.Handle, nullptr ); - buffer.Handle = VK_NULL_HANDLE; - } - - if( buffer.Memory != VK_NULL_HANDLE ) { - vkFreeMemory( GetDevice(), buffer.Memory, nullptr ); - buffer.Memory = VK_NULL_HANDLE; - } - } - -} // namespace ApiWithoutSecrets +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial06.h" +#include "VulkanFunctions.h" + +namespace ApiWithoutSecrets { + + Tutorial06::Tutorial06() : + Vulkan() { + } + + bool Tutorial06::CreateRenderingResources() { + if( !CreateCommandBuffers() ) { + return false; + } + if( !CreateSemaphores() ) { + return false; + } + if( !CreateFences() ) { + return false; + } + return true; + } + + bool Tutorial06::CreateCommandBuffers() { + if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.CommandPool ) ) { + std::cout << "Could not create command pool!" << std::endl; + return false; + } + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( !AllocateCommandBuffers( Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ) ) { + std::cout << "Could not allocate command buffer!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial06::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { + VkCommandPoolCreateInfo cmd_pool_create_info = { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | // VkCommandPoolCreateFlags flags + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + queue_family_index // uint32_t queueFamilyIndex + }; + + if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { + return false; + } + return true; + } + + bool Tutorial06::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { + VkCommandBufferAllocateInfo command_buffer_allocate_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + pool, // VkCommandPool commandPool + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level + count // uint32_t bufferCount + }; + + if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { + return false; + } + return true; + } + + bool Tutorial06::CreateSemaphores() { + VkSemaphoreCreateInfo semaphore_create_info = { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0 // VkSemaphoreCreateFlags flags + }; + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].ImageAvailableSemaphore ) != VK_SUCCESS) || + (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].FinishedRenderingSemaphore ) != VK_SUCCESS) ) { + std::cout << "Could not create semaphores!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial06::CreateFences() { + VkFenceCreateInfo fence_create_info = { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_FENCE_CREATE_SIGNALED_BIT // VkFenceCreateFlags flags + }; + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( vkCreateFence( GetDevice(), &fence_create_info, nullptr, &Vulkan.RenderingResources[i].Fence ) != VK_SUCCESS ) { + std::cout << "Could not create a fence!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial06::CreateStagingBuffer() { + Vulkan.StagingBuffer.Size = 1000000; + if( !CreateBuffer( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, Vulkan.StagingBuffer ) ) { + std::cout << "Could not create staging buffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial06::CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer ) { + VkBufferCreateInfo buffer_create_info = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkBufferCreateFlags flags + buffer.Size, // VkDeviceSize size + usage, // VkBufferUsageFlags usage + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode + 0, // uint32_t queueFamilyIndexCount + nullptr // const uint32_t *pQueueFamilyIndices + }; + + if( vkCreateBuffer( GetDevice(), &buffer_create_info, nullptr, &buffer.Handle ) != VK_SUCCESS ) { + std::cout << "Could not create buffer!" << std::endl; + return false; + } + + if( !AllocateBufferMemory( buffer.Handle, memoryProperty, &buffer.Memory ) ) { + std::cout << "Could not allocate memory for a buffer!" << std::endl; + return false; + } + + if( vkBindBufferMemory( GetDevice(), buffer.Handle, buffer.Memory, 0 ) != VK_SUCCESS ) { + std::cout << "Could not bind memory to a buffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial06::AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { + VkMemoryRequirements buffer_memory_requirements; + vkGetBufferMemoryRequirements( GetDevice(), buffer, &buffer_memory_requirements ); + + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); + + for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { + if( (buffer_memory_requirements.memoryTypeBits & (1 << i)) && + (memory_properties.memoryTypes[i].propertyFlags & property) ) { + + VkMemoryAllocateInfo memory_allocate_info = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + buffer_memory_requirements.size, // VkDeviceSize allocationSize + i // uint32_t memoryTypeIndex + }; + + if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { + return true; + } + } + } + return false; + } + + bool Tutorial06::CreateTexture() { + int width = 0, height = 0, data_size = 0; + std::vector texture_data = Tools::GetImageData( "Data06/texture.png", 4, &width, &height, nullptr, &data_size ); + if( texture_data.size() == 0 ) { + return false; + } + + if( !CreateImage( width, height, &Vulkan.Image.Handle ) ) { + std::cout << "Could not create image!" << std::endl; + return false; + } + + if( !AllocateImageMemory( Vulkan.Image.Handle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &Vulkan.Image.Memory ) ) { + std::cout << "Could not allocate memory for image!" << std::endl; + return false; + } + + if( vkBindImageMemory( GetDevice(), Vulkan.Image.Handle, Vulkan.Image.Memory, 0 ) != VK_SUCCESS ) { + std::cout << "Could not bind memory to an image!" << std::endl; + return false; + } + + if( !CreateImageView( Vulkan.Image ) ) { + std::cout << "Could not create image view!" << std::endl; + return false; + } + + if( !CreateSampler( &Vulkan.Image.Sampler ) ) { + std::cout << "Could not create sampler!" << std::endl; + return false; + } + + if( !CopyTextureData( &texture_data[0], data_size, width, height ) ) { + std::cout << "Could not upload texture data to device memory!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial06::CreateImage( uint32_t width, uint32_t height, VkImage *image ) { + VkImageCreateInfo image_create_info = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void *pNext + 0, // VkImageCreateFlags flags + VK_IMAGE_TYPE_2D, // VkImageType imageType + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format + { // VkExtent3D extent + width, // uint32_t width + height, // uint32_t height + 1 // uint32_t depth + }, + 1, // uint32_t mipLevels + 1, // uint32_t arrayLayers + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling + VK_IMAGE_USAGE_TRANSFER_DST_BIT | // VkImageUsageFlags usage + VK_IMAGE_USAGE_SAMPLED_BIT, + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode + 0, // uint32_t queueFamilyIndexCount + nullptr, // const uint32_t* pQueueFamilyIndices + VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout + }; + + return vkCreateImage( GetDevice(), &image_create_info, nullptr, image ) == VK_SUCCESS; + } + + bool Tutorial06::AllocateImageMemory( VkImage image, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { + VkMemoryRequirements image_memory_requirements; + vkGetImageMemoryRequirements( GetDevice(), image, &image_memory_requirements ); + + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); + + for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { + if( (image_memory_requirements.memoryTypeBits & (1 << i)) && + (memory_properties.memoryTypes[i].propertyFlags & property) ) { + + VkMemoryAllocateInfo memory_allocate_info = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + image_memory_requirements.size, // VkDeviceSize allocationSize + i // uint32_t memoryTypeIndex + }; + + if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { + return true; + } + } + } + return false; + } + + bool Tutorial06::CreateImageView( ImageParameters &image_parameters ) { + VkImageViewCreateInfo image_view_create_info = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkImageViewCreateFlags flags + image_parameters.Handle, // VkImage image + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format + { // VkComponentMapping components + VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle r + VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle g + VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle b + VK_COMPONENT_SWIZZLE_IDENTITY // VkComponentSwizzle a + }, + { // VkImageSubresourceRange subresourceRange + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + } + }; + + return vkCreateImageView( GetDevice(), &image_view_create_info, nullptr, &image_parameters.View ) == VK_SUCCESS; + } + + bool Tutorial06::CreateSampler( VkSampler *sampler ) { + VkSamplerCreateInfo sampler_create_info = { + VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0, // VkSamplerCreateFlags flags + VK_FILTER_LINEAR, // VkFilter magFilter + VK_FILTER_LINEAR, // VkFilter minFilter + VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW + 0.0f, // float mipLodBias + VK_FALSE, // VkBool32 anisotropyEnable + 1.0f, // float maxAnisotropy + VK_FALSE, // VkBool32 compareEnable + VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp + 0.0f, // float minLod + 0.0f, // float maxLod + VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor + VK_FALSE // VkBool32 unnormalizedCoordinates + }; + + return vkCreateSampler( GetDevice(), &sampler_create_info, nullptr, sampler ) == VK_SUCCESS; + } + + bool Tutorial06::CopyTextureData( char *texture_data, uint32_t data_size, uint32_t width, uint32_t height ) { + // Prepare data in staging buffer + + void *staging_buffer_memory_pointer; + if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, data_size, 0, &staging_buffer_memory_pointer ) != VK_SUCCESS ) { + std::cout << "Could not map memory and upload texture data to a staging buffer!" << std::endl; + return false; + } + + memcpy( staging_buffer_memory_pointer, texture_data, data_size ); + + VkMappedMemoryRange flush_range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory + 0, // VkDeviceSize offset + data_size // VkDeviceSize size + }; + vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); + + vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); + + // Prepare command buffer to copy data from staging buffer to a vertex buffer + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); + + VkImageSubresourceRange image_subresource_range = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + VkImageMemoryBarrier image_memory_barrier_from_undefined_to_transfer_dst = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkAccessFlags srcAccessMask + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + Vulkan.Image.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier_from_undefined_to_transfer_dst); + + VkBufferImageCopy buffer_image_copy_info = { + 0, // VkDeviceSize bufferOffset + 0, // uint32_t bufferRowLength + 0, // uint32_t bufferImageHeight + { // VkImageSubresourceLayers imageSubresource + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t mipLevel + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }, + { // VkOffset3D imageOffset + 0, // int32_t x + 0, // int32_t y + 0 // int32_t z + }, + { // VkExtent3D imageExtent + width, // uint32_t width + height, // uint32_t height + 1 // uint32_t depth + } + }; + vkCmdCopyBufferToImage( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.Image.Handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy_info ); + + VkImageMemoryBarrier image_memory_barrier_from_transfer_to_shader_read = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + Vulkan.Image.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier_from_transfer_to_shader_read); + + vkEndCommandBuffer( command_buffer ); + + // Submit command buffer and copy data from staging buffer to a vertex buffer + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // uint32_t waitSemaphoreCount + nullptr, // const VkSemaphore *pWaitSemaphores + nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + &command_buffer, // const VkCommandBuffer *pCommandBuffers + 0, // uint32_t signalSemaphoreCount + nullptr // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { + return false; + } + + vkDeviceWaitIdle( GetDevice() ); + + return true; + } + + bool Tutorial06::CreateDescriptorSetLayout() { + VkDescriptorSetLayoutBinding layout_binding = { + 0, // uint32_t binding + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType + 1, // uint32_t descriptorCount + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags + nullptr // const VkSampler *pImmutableSamplers + }; + + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDescriptorSetLayoutCreateFlags flags + 1, // uint32_t bindingCount + &layout_binding // const VkDescriptorSetLayoutBinding *pBindings + }; + + if( vkCreateDescriptorSetLayout( GetDevice(), &descriptor_set_layout_create_info, nullptr, &Vulkan.DescriptorSet.Layout ) != VK_SUCCESS ) { + std::cout << "Could not create descriptor set layout!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial06::CreateDescriptorPool() { + VkDescriptorPoolSize pool_size = { + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType type + 1 // uint32_t descriptorCount + }; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDescriptorPoolCreateFlags flags + 1, // uint32_t maxSets + 1, // uint32_t poolSizeCount + &pool_size // const VkDescriptorPoolSize *pPoolSizes + }; + + if( vkCreateDescriptorPool( GetDevice(), &descriptor_pool_create_info, nullptr, &Vulkan.DescriptorSet.Pool ) != VK_SUCCESS ) { + std::cout << "Could not create descriptor pool!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial06::AllocateDescriptorSet() { + VkDescriptorSetAllocateInfo descriptor_set_allocate_info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.DescriptorSet.Pool, // VkDescriptorPool descriptorPool + 1, // uint32_t descriptorSetCount + &Vulkan.DescriptorSet.Layout // const VkDescriptorSetLayout *pSetLayouts + }; + + if( vkAllocateDescriptorSets( GetDevice(), &descriptor_set_allocate_info, &Vulkan.DescriptorSet.Handle ) != VK_SUCCESS ) { + std::cout << "Could not allocate descriptor set!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial06::UpdateDescriptorSet() { + VkDescriptorImageInfo image_info = { + Vulkan.Image.Sampler, // VkSampler sampler + Vulkan.Image.View, // VkImageView imageView + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout + }; + + VkWriteDescriptorSet descriptor_writes = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.DescriptorSet.Handle, // VkDescriptorSet dstSet + 0, // uint32_t dstBinding + 0, // uint32_t dstArrayElement + 1, // uint32_t descriptorCount + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType + &image_info, // const VkDescriptorImageInfo *pImageInfo + nullptr, // const VkDescriptorBufferInfo *pBufferInfo + nullptr // const VkBufferView *pTexelBufferView + }; + + vkUpdateDescriptorSets( GetDevice(), 1, &descriptor_writes, 0, nullptr ); + return true; + } + + bool Tutorial06::CreateRenderPass() { + VkAttachmentDescription attachment_descriptions[] = { + { + 0, // VkAttachmentDescriptionFlags flags + GetSwapChain().Format, // VkFormat format + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout + } + }; + + VkAttachmentReference color_attachment_references[] = { + { + 0, // uint32_t attachment + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout + } + }; + + VkSubpassDescription subpass_descriptions[] = { + { + 0, // VkSubpassDescriptionFlags flags + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint + 0, // uint32_t inputAttachmentCount + nullptr, // const VkAttachmentReference *pInputAttachments + 1, // uint32_t colorAttachmentCount + color_attachment_references, // const VkAttachmentReference *pColorAttachments + nullptr, // const VkAttachmentReference *pResolveAttachments + nullptr, // const VkAttachmentReference *pDepthStencilAttachment + 0, // uint32_t preserveAttachmentCount + nullptr // const uint32_t* pPreserveAttachments + } + }; + + VkRenderPassCreateInfo render_pass_create_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkRenderPassCreateFlags flags + 1, // uint32_t attachmentCount + attachment_descriptions, // const VkAttachmentDescription *pAttachments + 1, // uint32_t subpassCount + subpass_descriptions, // const VkSubpassDescription *pSubpasses + 0, // uint32_t dependencyCount + nullptr // const VkSubpassDependency *pDependencies + }; + + if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { + std::cout << "Could not create render pass!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial06::CreatePipelineLayout() { + VkPipelineLayoutCreateInfo layout_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineLayoutCreateFlags flags + 1, // uint32_t setLayoutCount + &Vulkan.DescriptorSet.Layout, // const VkDescriptorSetLayout *pSetLayouts + 0, // uint32_t pushConstantRangeCount + nullptr // const VkPushConstantRange *pPushConstantRanges + }; + + if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &Vulkan.PipelineLayout ) != VK_SUCCESS ) { + std::cout << "Could not create pipeline layout!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial06::CreatePipeline() { + Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data06/vert.spv" ); + Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data06/frag.spv" ); + + if( !vertex_shader_module || !fragment_shader_module ) { + return false; + } + + std::vector shader_stage_create_infos = { + // Vertex shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage + vertex_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + }, + // Fragment shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage + fragment_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + } + }; + + VkVertexInputBindingDescription vertex_binding_description = { + 0, // uint32_t binding + sizeof(VertexData), // uint32_t stride + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate + }; + + VkVertexInputAttributeDescription vertex_attribute_descriptions[] = { + { + 0, // uint32_t location + vertex_binding_description.binding, // uint32_t binding + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format + 0 // uint32_t offset + }, + { + 1, // uint32_t location + vertex_binding_description.binding, // uint32_t binding + VK_FORMAT_R32G32_SFLOAT, // VkFormat format + 4 * sizeof(float) // uint32_t offset + } + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineVertexInputStateCreateFlags flags; + 1, // uint32_t vertexBindingDescriptionCount + &vertex_binding_description, // const VkVertexInputBindingDescription *pVertexBindingDescriptions + 2, // uint32_t vertexAttributeDescriptionCount + vertex_attribute_descriptions // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions + }; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineInputAssemblyStateCreateFlags flags + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology + VK_FALSE // VkBool32 primitiveRestartEnable + }; + + VkPipelineViewportStateCreateInfo viewport_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineViewportStateCreateFlags flags + 1, // uint32_t viewportCount + nullptr, // const VkViewport *pViewports + 1, // uint32_t scissorCount + nullptr // const VkRect2D *pScissors + }; + + VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineRasterizationStateCreateFlags flags + VK_FALSE, // VkBool32 depthClampEnable + VK_FALSE, // VkBool32 rasterizerDiscardEnable + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode + VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace + VK_FALSE, // VkBool32 depthBiasEnable + 0.0f, // float depthBiasConstantFactor + 0.0f, // float depthBiasClamp + 0.0f, // float depthBiasSlopeFactor + 1.0f // float lineWidth + }; + + VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineMultisampleStateCreateFlags flags + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples + VK_FALSE, // VkBool32 sampleShadingEnable + 1.0f, // float minSampleShading + nullptr, // const VkSampleMask *pSampleMask + VK_FALSE, // VkBool32 alphaToCoverageEnable + VK_FALSE // VkBool32 alphaToOneEnable + }; + + VkPipelineColorBlendAttachmentState color_blend_attachment_state = { + VK_FALSE, // VkBool32 blendEnable + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT + }; + + VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineColorBlendStateCreateFlags flags + VK_FALSE, // VkBool32 logicOpEnable + VK_LOGIC_OP_COPY, // VkLogicOp logicOp + 1, // uint32_t attachmentCount + &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments + { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] + }; + + VkDynamicState dynamic_states[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + + VkPipelineDynamicStateCreateInfo dynamic_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineDynamicStateCreateFlags flags + 2, // uint32_t dynamicStateCount + dynamic_states // const VkDynamicState *pDynamicStates + }; + + VkGraphicsPipelineCreateInfo pipeline_create_info = { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineCreateFlags flags + static_cast(shader_stage_create_infos.size()), // uint32_t stageCount + &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages + &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; + &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState + nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState + &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState + &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState + &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState + nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState + &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState + &dynamic_state_create_info, // const VkPipelineDynamicStateCreateInfo *pDynamicState + Vulkan.PipelineLayout, // VkPipelineLayout layout + Vulkan.RenderPass, // VkRenderPass renderPass + 0, // uint32_t subpass + VK_NULL_HANDLE, // VkPipeline basePipelineHandle + -1 // int32_t basePipelineIndex + }; + + if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { + std::cout << "Could not create graphics pipeline!" << std::endl; + return false; + } + return true; + } + + Tools::AutoDeleter Tutorial06::CreateShaderModule( const char* filename ) { + const std::vector code = Tools::GetBinaryFileContents( filename ); + if( code.size() == 0 ) { + return Tools::AutoDeleter(); + } + + VkShaderModuleCreateInfo shader_module_create_info = { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkShaderModuleCreateFlags flags + code.size(), // size_t codeSize + reinterpret_cast(&code[0]) // const uint32_t *pCode + }; + + VkShaderModule shader_module; + if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { + std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; + return Tools::AutoDeleter(); + } + + return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); + } + + bool Tutorial06::CreateVertexBuffer() { + const std::vector& vertex_data = GetVertexData(); + + Vulkan.VertexBuffer.Size = static_cast(vertex_data.size() * sizeof(vertex_data[0])); + if( !CreateBuffer( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Vulkan.VertexBuffer ) ) { + std::cout << "Could not create vertex buffer!" << std::endl; + return false; + } + + if( !CopyVertexData() ) { + return false; + } + + return true; + } + + const std::vector& Tutorial06::GetVertexData() const { + static const std::vector vertex_data = { + -0.7f, -0.7f, 0.0f, 1.0f, + -0.1f, -0.1f, + // + -0.7f, 0.7f, 0.0f, 1.0f, + -0.1f, 1.1f, + // + 0.7f, -0.7f, 0.0f, 1.0f, + 1.1f, -0.1f, + // + 0.7f, 0.7f, 0.0f, 1.0f, + 1.1f, 1.1f, + }; + + return vertex_data; + } + + bool Tutorial06::CopyVertexData() { + // Prepare data in staging buffer + const std::vector& vertex_data = GetVertexData(); + + void *staging_buffer_memory_pointer; + if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, Vulkan.VertexBuffer.Size, 0, &staging_buffer_memory_pointer) != VK_SUCCESS ) { + std::cout << "Could not map memory and upload data to a staging buffer!" << std::endl; + return false; + } + + memcpy( staging_buffer_memory_pointer, &vertex_data[0], Vulkan.VertexBuffer.Size ); + + VkMappedMemoryRange flush_range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory + 0, // VkDeviceSize offset + Vulkan.VertexBuffer.Size // VkDeviceSize size + }; + vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); + + vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); + + // Prepare command buffer to copy data from staging buffer to a vertex buffer + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); + + VkBufferCopy buffer_copy_info = { + 0, // VkDeviceSize srcOffset + 0, // VkDeviceSize dstOffset + Vulkan.VertexBuffer.Size // VkDeviceSize size + }; + vkCmdCopyBuffer( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.VertexBuffer.Handle, 1, &buffer_copy_info ); + + VkBufferMemoryBarrier buffer_memory_barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + nullptr, // const void *pNext + VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkAccessFlags dstAccessMask + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + Vulkan.VertexBuffer.Handle, // VkBuffer buffer + 0, // VkDeviceSize offset + VK_WHOLE_SIZE // VkDeviceSize size + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, &buffer_memory_barrier, 0, nullptr ); + + vkEndCommandBuffer( command_buffer ); + + // Submit command buffer and copy data from staging buffer to a vertex buffer + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // uint32_t waitSemaphoreCount + nullptr, // const VkSemaphore *pWaitSemaphores + nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + &command_buffer, // const VkCommandBuffer *pCommandBuffers + 0, // uint32_t signalSemaphoreCount + nullptr // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { + return false; + } + + vkDeviceWaitIdle( GetDevice() ); + + return true; + } + + bool Tutorial06::PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ) { + if( !CreateFramebuffer( framebuffer, image_parameters.View ) ) { + return false; + } + + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info ); + + VkImageSubresourceRange image_subresource_range = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + uint32_t present_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetPresentQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED; + uint32_t graphics_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetGraphicsQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED; + VkImageMemoryBarrier barrier_from_present_to_draw = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout + present_queue_family_index, // uint32_t srcQueueFamilyIndex + graphics_queue_family_index, // uint32_t dstQueueFamilyIndex + image_parameters.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); + + VkClearValue clear_value = { + { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color + }; + + VkRenderPassBeginInfo render_pass_begin_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.RenderPass, // VkRenderPass renderPass + framebuffer, // VkFramebuffer framebuffer + { // VkRect2D renderArea + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + GetSwapChain().Extent, // VkExtent2D extent; + }, + 1, // uint32_t clearValueCount + &clear_value // const VkClearValue *pClearValues + }; + + vkCmdBeginRenderPass( command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); + + vkCmdBindPipeline( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); + + VkViewport viewport = { + 0.0f, // float x + 0.0f, // float y + static_cast(GetSwapChain().Extent.width), // float width + static_cast(GetSwapChain().Extent.height), // float height + 0.0f, // float minDepth + 1.0f // float maxDepth + }; + + VkRect2D scissor = { + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + { // VkExtent2D extent + GetSwapChain().Extent.width, // uint32_t width + GetSwapChain().Extent.height // uint32_t height + } + }; + + vkCmdSetViewport( command_buffer, 0, 1, &viewport ); + vkCmdSetScissor( command_buffer, 0, 1, &scissor ); + + VkDeviceSize offset = 0; + vkCmdBindVertexBuffers( command_buffer, 0, 1, &Vulkan.VertexBuffer.Handle, &offset ); + + vkCmdBindDescriptorSets( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.PipelineLayout, 0, 1, &Vulkan.DescriptorSet.Handle, 0, nullptr ); + + vkCmdDraw( command_buffer, 4, 1, 0, 0 ); + + vkCmdEndRenderPass( command_buffer ); + + VkImageMemoryBarrier barrier_from_draw_to_present = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout + graphics_queue_family_index, // uint32_t srcQueueFamilyIndex + present_queue_family_index, // uint32_t dstQueueFamilyIndex + image_parameters.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); + + if( vkEndCommandBuffer( command_buffer ) != VK_SUCCESS ) { + std::cout << "Could not record command buffer!" << std::endl; + return false; + } + return true; + } + + bool Tutorial06::CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ) { + if( framebuffer != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( GetDevice(), framebuffer, nullptr ); + framebuffer = VK_NULL_HANDLE; + } + + VkFramebufferCreateInfo framebuffer_create_info = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkFramebufferCreateFlags flags + Vulkan.RenderPass, // VkRenderPass renderPass + 1, // uint32_t attachmentCount + &image_view, // const VkImageView *pAttachments + GetSwapChain().Extent.width, // uint32_t width + GetSwapChain().Extent.height, // uint32_t height + 1 // uint32_t layers + }; + + if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &framebuffer ) != VK_SUCCESS ) { + std::cout << "Could not create a framebuffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial06::ChildOnWindowSizeChanged() { + return true; + } + + bool Tutorial06::Draw() { + static size_t resource_index = 0; + RenderingResourcesData ¤t_rendering_resource = Vulkan.RenderingResources[resource_index]; + VkSwapchainKHR swap_chain = GetSwapChain().Handle; + uint32_t image_index; + + resource_index = (resource_index + 1) % VulkanTutorial06Parameters::ResourcesCount; + + if( vkWaitForFences( GetDevice(), 1, ¤t_rendering_resource.Fence, VK_FALSE, 1000000000 ) != VK_SUCCESS ) { + std::cout << "Waiting for fence takes too long!" << std::endl; + return false; + } + vkResetFences( GetDevice(), 1, ¤t_rendering_resource.Fence ); + + VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, current_rendering_resource.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); + switch( result ) { + case VK_SUCCESS: + case VK_SUBOPTIMAL_KHR: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; + return false; + } + + if( !PrepareFrame( current_rendering_resource.CommandBuffer, GetSwapChain().Images[image_index], current_rendering_resource.Framebuffer ) ) { + return false; + } + + VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + ¤t_rendering_resource.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores + &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + ¤t_rendering_resource.CommandBuffer, // const VkCommandBuffer *pCommandBuffers + 1, // uint32_t signalSemaphoreCount + ¤t_rendering_resource.FinishedRenderingSemaphore // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, current_rendering_resource.Fence ) != VK_SUCCESS ) { + return false; + } + + VkPresentInfoKHR present_info = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + ¤t_rendering_resource.FinishedRenderingSemaphore, // const VkSemaphore *pWaitSemaphores + 1, // uint32_t swapchainCount + &swap_chain, // const VkSwapchainKHR *pSwapchains + &image_index, // const uint32_t *pImageIndices + nullptr // VkResult *pResults + }; + result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); + + switch( result ) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_SUBOPTIMAL_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during image presentation!" << std::endl; + return false; + } + + return true; + } + + void Tutorial06::ChildClear() { + } + + Tutorial06::~Tutorial06() { + if( GetDevice() != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( GetDevice() ); + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( Vulkan.RenderingResources[i].Framebuffer != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( GetDevice(), Vulkan.RenderingResources[i].Framebuffer, nullptr ); + } + if( Vulkan.RenderingResources[i].CommandBuffer != VK_NULL_HANDLE ) { + vkFreeCommandBuffers( GetDevice(), Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ); + } + if( Vulkan.RenderingResources[i].ImageAvailableSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].ImageAvailableSemaphore, nullptr ); + } + if( Vulkan.RenderingResources[i].FinishedRenderingSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].FinishedRenderingSemaphore, nullptr ); + } + if( Vulkan.RenderingResources[i].Fence != VK_NULL_HANDLE ) { + vkDestroyFence( GetDevice(), Vulkan.RenderingResources[i].Fence, nullptr ); + } + } + + if( Vulkan.CommandPool != VK_NULL_HANDLE ) { + vkDestroyCommandPool( GetDevice(), Vulkan.CommandPool, nullptr ); + Vulkan.CommandPool = VK_NULL_HANDLE; + } + + DestroyBuffer( Vulkan.VertexBuffer ); + + DestroyBuffer( Vulkan.StagingBuffer ); + + if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { + vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); + Vulkan.GraphicsPipeline = VK_NULL_HANDLE; + } + + if( Vulkan.PipelineLayout != VK_NULL_HANDLE ) { + vkDestroyPipelineLayout( GetDevice(), Vulkan.PipelineLayout, nullptr ); + Vulkan.PipelineLayout = VK_NULL_HANDLE; + } + + if( Vulkan.RenderPass != VK_NULL_HANDLE ) { + vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); + Vulkan.RenderPass = VK_NULL_HANDLE; + } + + if( Vulkan.DescriptorSet.Pool != VK_NULL_HANDLE ) { + vkDestroyDescriptorPool( GetDevice(), Vulkan.DescriptorSet.Pool, nullptr ); + Vulkan.DescriptorSet.Pool = VK_NULL_HANDLE; + } + + if( Vulkan.DescriptorSet.Layout != VK_NULL_HANDLE ) { + vkDestroyDescriptorSetLayout( GetDevice(), Vulkan.DescriptorSet.Layout, nullptr ); + Vulkan.DescriptorSet.Layout = VK_NULL_HANDLE; + } + + if( Vulkan.Image.Sampler != VK_NULL_HANDLE ) { + vkDestroySampler( GetDevice(), Vulkan.Image.Sampler, nullptr ); + Vulkan.Image.Sampler = VK_NULL_HANDLE; + } + + if( Vulkan.Image.View != VK_NULL_HANDLE ) { + vkDestroyImageView( GetDevice(), Vulkan.Image.View, nullptr ); + Vulkan.Image.View = VK_NULL_HANDLE; + } + + if( Vulkan.Image.Handle != VK_NULL_HANDLE ) { + vkDestroyImage( GetDevice(), Vulkan.Image.Handle, nullptr ); + Vulkan.Image.Handle = VK_NULL_HANDLE; + } + + if( Vulkan.Image.Memory != VK_NULL_HANDLE ) { + vkFreeMemory( GetDevice(), Vulkan.Image.Memory, nullptr ); + Vulkan.Image.Memory = VK_NULL_HANDLE; + } + } + } + + void Tutorial06::DestroyBuffer( BufferParameters& buffer ) { + if( buffer.Handle != VK_NULL_HANDLE ) { + vkDestroyBuffer( GetDevice(), buffer.Handle, nullptr ); + buffer.Handle = VK_NULL_HANDLE; + } + + if( buffer.Memory != VK_NULL_HANDLE ) { + vkFreeMemory( GetDevice(), buffer.Memory, nullptr ); + buffer.Memory = VK_NULL_HANDLE; + } + } + +} // namespace ApiWithoutSecrets diff --git a/Project/Tutorial06/Tutorial06.h b/Project/Tutorial06/Tutorial06.h index 2fada16..c25cfe9 100644 --- a/Project/Tutorial06/Tutorial06.h +++ b/Project/Tutorial06/Tutorial06.h @@ -1,173 +1,173 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(TUTORIAL_06_HEADER) -#define TUTORIAL_06_HEADER - -#include "VulkanCommon.h" -#include "Tools.h" - -namespace ApiWithoutSecrets { - - // ************************************************************ // - // BufferParameters // - // // - // Vulkan Buffer's parameters container class // - // ************************************************************ // - struct BufferParameters { - VkBuffer Handle; - VkDeviceMemory Memory; - uint32_t Size; - - BufferParameters() : - Handle( VK_NULL_HANDLE ), - Memory( VK_NULL_HANDLE ), - Size( 0 ) { - } - }; - - // ************************************************************ // - // DescriptorParameters // - // // - // Container class for descriptor related resources // - // ************************************************************ // - struct DescriptorSetParameters { - VkDescriptorPool Pool; - VkDescriptorSetLayout Layout; - VkDescriptorSet Handle; - - DescriptorSetParameters() : - Pool( VK_NULL_HANDLE ), - Layout( VK_NULL_HANDLE ), - Handle( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // VertexData // - // // - // Struct describing data type and format of vertex attributes // - // ************************************************************ // - struct VertexData { - float x, y, z, w; - float u, v; - }; - - // ************************************************************ // - // RenderingResourcesData // - // // - // Struct containing data used during rendering process // - // ************************************************************ // - struct RenderingResourcesData { - VkFramebuffer Framebuffer; - VkCommandBuffer CommandBuffer; - VkSemaphore ImageAvailableSemaphore; - VkSemaphore FinishedRenderingSemaphore; - VkFence Fence; - - RenderingResourcesData() : - Framebuffer( VK_NULL_HANDLE ), - CommandBuffer( VK_NULL_HANDLE ), - ImageAvailableSemaphore( VK_NULL_HANDLE ), - FinishedRenderingSemaphore( VK_NULL_HANDLE ), - Fence( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // VulkanTutorial04Parameters // - // // - // Vulkan specific parameters // - // ************************************************************ // - struct VulkanTutorial06Parameters { - VkRenderPass RenderPass; - ImageParameters Image; - DescriptorSetParameters DescriptorSet; - VkPipelineLayout PipelineLayout; - VkPipeline GraphicsPipeline; - BufferParameters VertexBuffer; - BufferParameters StagingBuffer; - VkCommandPool CommandPool; - std::vector RenderingResources; - - static const size_t ResourcesCount = 3; - - VulkanTutorial06Parameters() : - RenderPass( VK_NULL_HANDLE ), - Image(), - DescriptorSet(), - PipelineLayout(), - GraphicsPipeline( VK_NULL_HANDLE ), - VertexBuffer(), - StagingBuffer(), - CommandPool( VK_NULL_HANDLE ), - RenderingResources( ResourcesCount ) { - } - }; - - // ************************************************************ // - // Tutorial04 // - // // - // Class for presenting Vulkan usage topics // - // ************************************************************ // - class Tutorial06 : public VulkanCommon { - public: - Tutorial06(); - ~Tutorial06(); - - bool CreateRenderingResources(); - bool CreateStagingBuffer(); - bool CreateTexture(); - bool CreateDescriptorSetLayout(); - bool CreateDescriptorPool(); - bool AllocateDescriptorSet(); - bool UpdateDescriptorSet(); - bool CreateRenderPass(); - bool CreatePipelineLayout(); - bool CreatePipeline(); - bool CreateVertexBuffer(); - - bool Draw() override; - - private: - VulkanTutorial06Parameters Vulkan; - - bool CreateCommandBuffers(); - bool CreateCommandPool(uint32_t queue_family_index, VkCommandPool *pool); - bool AllocateCommandBuffers(VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers); - bool CreateSemaphores(); - bool CreateFences(); - bool CreateBuffer(VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer); - bool AllocateBufferMemory(VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory); - bool CreateImage( uint32_t width, uint32_t height, VkImage *image ); - bool AllocateImageMemory( VkImage image, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ); - bool CreateImageView( ImageParameters &image_parameters ); - bool CreateSampler( VkSampler *sampler ); - bool CopyTextureData( char *texture_data, uint32_t data_size, uint32_t width, uint32_t height ); - Tools::AutoDeleter CreateShaderModule( const char* filename ); - const std::vector& GetVertexData() const; - bool CopyVertexData(); - bool PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ); - bool CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ); - void DestroyBuffer( BufferParameters& buffer ); - - bool ChildOnWindowSizeChanged() override; - void ChildClear() override; - }; - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(TUTORIAL_06_HEADER) +#define TUTORIAL_06_HEADER + +#include "VulkanCommon.h" +#include "Tools.h" + +namespace ApiWithoutSecrets { + + // ************************************************************ // + // BufferParameters // + // // + // Vulkan Buffer's parameters container class // + // ************************************************************ // + struct BufferParameters { + VkBuffer Handle; + VkDeviceMemory Memory; + uint32_t Size; + + BufferParameters() : + Handle( VK_NULL_HANDLE ), + Memory( VK_NULL_HANDLE ), + Size( 0 ) { + } + }; + + // ************************************************************ // + // DescriptorParameters // + // // + // Container class for descriptor related resources // + // ************************************************************ // + struct DescriptorSetParameters { + VkDescriptorPool Pool; + VkDescriptorSetLayout Layout; + VkDescriptorSet Handle; + + DescriptorSetParameters() : + Pool( VK_NULL_HANDLE ), + Layout( VK_NULL_HANDLE ), + Handle( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // VertexData // + // // + // Struct describing data type and format of vertex attributes // + // ************************************************************ // + struct VertexData { + float x, y, z, w; + float u, v; + }; + + // ************************************************************ // + // RenderingResourcesData // + // // + // Struct containing data used during rendering process // + // ************************************************************ // + struct RenderingResourcesData { + VkFramebuffer Framebuffer; + VkCommandBuffer CommandBuffer; + VkSemaphore ImageAvailableSemaphore; + VkSemaphore FinishedRenderingSemaphore; + VkFence Fence; + + RenderingResourcesData() : + Framebuffer( VK_NULL_HANDLE ), + CommandBuffer( VK_NULL_HANDLE ), + ImageAvailableSemaphore( VK_NULL_HANDLE ), + FinishedRenderingSemaphore( VK_NULL_HANDLE ), + Fence( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // VulkanTutorial04Parameters // + // // + // Vulkan specific parameters // + // ************************************************************ // + struct VulkanTutorial06Parameters { + VkRenderPass RenderPass; + ImageParameters Image; + DescriptorSetParameters DescriptorSet; + VkPipelineLayout PipelineLayout; + VkPipeline GraphicsPipeline; + BufferParameters VertexBuffer; + BufferParameters StagingBuffer; + VkCommandPool CommandPool; + std::vector RenderingResources; + + static const size_t ResourcesCount = 3; + + VulkanTutorial06Parameters() : + RenderPass( VK_NULL_HANDLE ), + Image(), + DescriptorSet(), + PipelineLayout(), + GraphicsPipeline( VK_NULL_HANDLE ), + VertexBuffer(), + StagingBuffer(), + CommandPool( VK_NULL_HANDLE ), + RenderingResources( ResourcesCount ) { + } + }; + + // ************************************************************ // + // Tutorial04 // + // // + // Class for presenting Vulkan usage topics // + // ************************************************************ // + class Tutorial06 : public VulkanCommon { + public: + Tutorial06(); + ~Tutorial06(); + + bool CreateRenderingResources(); + bool CreateStagingBuffer(); + bool CreateTexture(); + bool CreateDescriptorSetLayout(); + bool CreateDescriptorPool(); + bool AllocateDescriptorSet(); + bool UpdateDescriptorSet(); + bool CreateRenderPass(); + bool CreatePipelineLayout(); + bool CreatePipeline(); + bool CreateVertexBuffer(); + + bool Draw() override; + + private: + VulkanTutorial06Parameters Vulkan; + + bool CreateCommandBuffers(); + bool CreateCommandPool(uint32_t queue_family_index, VkCommandPool *pool); + bool AllocateCommandBuffers(VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers); + bool CreateSemaphores(); + bool CreateFences(); + bool CreateBuffer(VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer); + bool AllocateBufferMemory(VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory); + bool CreateImage( uint32_t width, uint32_t height, VkImage *image ); + bool AllocateImageMemory( VkImage image, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ); + bool CreateImageView( ImageParameters &image_parameters ); + bool CreateSampler( VkSampler *sampler ); + bool CopyTextureData( char *texture_data, uint32_t data_size, uint32_t width, uint32_t height ); + Tools::AutoDeleter CreateShaderModule( const char* filename ); + const std::vector& GetVertexData() const; + bool CopyVertexData(); + bool PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ); + bool CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ); + void DestroyBuffer( BufferParameters& buffer ); + + bool ChildOnWindowSizeChanged() override; + void ChildClear() override; + }; + +} // namespace ApiWithoutSecrets + #endif // TUTORIAL_06_HEADER \ No newline at end of file diff --git a/Project/Tutorial06/main.cpp b/Project/Tutorial06/main.cpp index cf03a17..0dc0781 100644 --- a/Project/Tutorial06/main.cpp +++ b/Project/Tutorial06/main.cpp @@ -1,74 +1,74 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial06.h" - -int main( int argc, char **argv ) { - ApiWithoutSecrets::OS::Window window; - ApiWithoutSecrets::Tutorial06 tutorial06; - - // Window creation - if( !window.Create( "06 - Descriptor Sets" ) ) { - return -1; - } - - // Vulkan preparations and initialization - if( !tutorial06.PrepareVulkan( window.GetParameters() ) ) { - return -1; - } - - // Tutorial 06 - if( !tutorial06.CreateRenderingResources() ) { - return -1; - } - if( !tutorial06.CreateStagingBuffer() ) { - return -1; - } - if( !tutorial06.CreateTexture() ) { - return -1; - } - if( !tutorial06.CreateDescriptorSetLayout() ) { - return -1; - } - if( !tutorial06.CreateDescriptorPool() ) { - return -1; - } - if( !tutorial06.AllocateDescriptorSet() ) { - return -1; - } - if( !tutorial06.UpdateDescriptorSet() ) { - return -1; - } - if( !tutorial06.CreateRenderPass() ) { - return -1; - } - if( !tutorial06.CreatePipelineLayout() ) { - return -1; - } - if( !tutorial06.CreatePipeline() ) { - return -1; - } - if( !tutorial06.CreateVertexBuffer() ) { - return -1; - } - - // Rendering loop - if( !window.RenderingLoop( tutorial06 ) ) { - return -1; - } - - return 0; -} +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial06.h" + +int main( int argc, char **argv ) { + ApiWithoutSecrets::OS::Window window; + ApiWithoutSecrets::Tutorial06 tutorial06; + + // Window creation + if( !window.Create( "06 - Descriptor Sets" ) ) { + return -1; + } + + // Vulkan preparations and initialization + if( !tutorial06.PrepareVulkan( window.GetParameters() ) ) { + return -1; + } + + // Tutorial 06 + if( !tutorial06.CreateRenderingResources() ) { + return -1; + } + if( !tutorial06.CreateStagingBuffer() ) { + return -1; + } + if( !tutorial06.CreateTexture() ) { + return -1; + } + if( !tutorial06.CreateDescriptorSetLayout() ) { + return -1; + } + if( !tutorial06.CreateDescriptorPool() ) { + return -1; + } + if( !tutorial06.AllocateDescriptorSet() ) { + return -1; + } + if( !tutorial06.UpdateDescriptorSet() ) { + return -1; + } + if( !tutorial06.CreateRenderPass() ) { + return -1; + } + if( !tutorial06.CreatePipelineLayout() ) { + return -1; + } + if( !tutorial06.CreatePipeline() ) { + return -1; + } + if( !tutorial06.CreateVertexBuffer() ) { + return -1; + } + + // Rendering loop + if( !window.RenderingLoop( tutorial06 ) ) { + return -1; + } + + return 0; +} diff --git a/Project/Tutorial07/Tutorial07.cpp b/Project/Tutorial07/Tutorial07.cpp index 9efe33a..31ad39b 100644 --- a/Project/Tutorial07/Tutorial07.cpp +++ b/Project/Tutorial07/Tutorial07.cpp @@ -1,1370 +1,1370 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial07.h" -#include "VulkanFunctions.h" - -namespace ApiWithoutSecrets { - - Tutorial07::Tutorial07() : - Vulkan() { - } - - bool Tutorial07::CreateRenderingResources() { - if( !CreateCommandBuffers() ) { - return false; - } - if( !CreateSemaphores() ) { - return false; - } - if( !CreateFences() ) { - return false; - } - return true; - } - - bool Tutorial07::CreateCommandBuffers() { - if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.CommandPool ) ) { - std::cout << "Could not create command pool!" << std::endl; - return false; - } - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( !AllocateCommandBuffers( Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ) ) { - std::cout << "Could not allocate command buffer!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial07::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { - VkCommandPoolCreateInfo cmd_pool_create_info = { - VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | // VkCommandPoolCreateFlags flags - VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - queue_family_index // uint32_t queueFamilyIndex - }; - - if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { - return false; - } - return true; - } - - bool Tutorial07::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { - VkCommandBufferAllocateInfo command_buffer_allocate_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - pool, // VkCommandPool commandPool - VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level - count // uint32_t bufferCount - }; - - if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { - return false; - } - return true; - } - - bool Tutorial07::CreateSemaphores() { - VkSemaphoreCreateInfo semaphore_create_info = { - VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0 // VkSemaphoreCreateFlags flags - }; - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].ImageAvailableSemaphore ) != VK_SUCCESS) || - (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].FinishedRenderingSemaphore ) != VK_SUCCESS) ) { - std::cout << "Could not create semaphores!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial07::CreateFences() { - VkFenceCreateInfo fence_create_info = { - VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_FENCE_CREATE_SIGNALED_BIT // VkFenceCreateFlags flags - }; - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( vkCreateFence( GetDevice(), &fence_create_info, nullptr, &Vulkan.RenderingResources[i].Fence ) != VK_SUCCESS ) { - std::cout << "Could not create a fence!" << std::endl; - return false; - } - } - return true; - } - - bool Tutorial07::CreateStagingBuffer() { - Vulkan.StagingBuffer.Size = 1000000; - if( !CreateBuffer( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, Vulkan.StagingBuffer ) ) { - std::cout << "Could not create staging buffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial07::CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer ) { - VkBufferCreateInfo buffer_create_info = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkBufferCreateFlags flags - buffer.Size, // VkDeviceSize size - usage, // VkBufferUsageFlags usage - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode - 0, // uint32_t queueFamilyIndexCount - nullptr // const uint32_t *pQueueFamilyIndices - }; - - if( vkCreateBuffer( GetDevice(), &buffer_create_info, nullptr, &buffer.Handle ) != VK_SUCCESS ) { - std::cout << "Could not create buffer!" << std::endl; - return false; - } - - if( !AllocateBufferMemory( buffer.Handle, memoryProperty, &buffer.Memory ) ) { - std::cout << "Could not allocate memory for a buffer!" << std::endl; - return false; - } - - if( vkBindBufferMemory( GetDevice(), buffer.Handle, buffer.Memory, 0 ) != VK_SUCCESS ) { - std::cout << "Could not bind memory to a buffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial07::AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { - VkMemoryRequirements buffer_memory_requirements; - vkGetBufferMemoryRequirements( GetDevice(), buffer, &buffer_memory_requirements ); - - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); - - for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { - if( (buffer_memory_requirements.memoryTypeBits & (1 << i)) && - (memory_properties.memoryTypes[i].propertyFlags & property) ) { - - VkMemoryAllocateInfo memory_allocate_info = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - buffer_memory_requirements.size, // VkDeviceSize allocationSize - i // uint32_t memoryTypeIndex - }; - - if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { - return true; - } - } - } - return false; - } - - bool Tutorial07::CreateTexture() { - int width = 0, height = 0, data_size = 0; - std::vector texture_data = Tools::GetImageData( "Data07/texture.png", 4, &width, &height, nullptr, &data_size ); - if( texture_data.size() == 0 ) { - return false; - } - - if( !CreateImage( width, height, &Vulkan.Image.Handle ) ) { - std::cout << "Could not create image!" << std::endl; - return false; - } - - if( !AllocateImageMemory( Vulkan.Image.Handle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &Vulkan.Image.Memory ) ) { - std::cout << "Could not allocate memory for image!" << std::endl; - return false; - } - - if( vkBindImageMemory( GetDevice(), Vulkan.Image.Handle, Vulkan.Image.Memory, 0 ) != VK_SUCCESS ) { - std::cout << "Could not bind memory to an image!" << std::endl; - return false; - } - - if( !CreateImageView( Vulkan.Image ) ) { - std::cout << "Could not create image view!" << std::endl; - return false; - } - - if( !CreateSampler( &Vulkan.Image.Sampler ) ) { - std::cout << "Could not create sampler!" << std::endl; - return false; - } - - if( !CopyTextureData( &texture_data[0], data_size, width, height ) ) { - std::cout << "Could not upload texture data to device memory!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial07::CreateImage( uint32_t width, uint32_t height, VkImage *image ) { - VkImageCreateInfo image_create_info = { - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void *pNext - 0, // VkImageCreateFlags flags - VK_IMAGE_TYPE_2D, // VkImageType imageType - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format - { // VkExtent3D extent - width, // uint32_t width - height, // uint32_t height - 1 // uint32_t depth - }, - 1, // uint32_t mipLevels - 1, // uint32_t arrayLayers - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples - VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling - VK_IMAGE_USAGE_TRANSFER_DST_BIT | // VkImageUsageFlags usage - VK_IMAGE_USAGE_SAMPLED_BIT, - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode - 0, // uint32_t queueFamilyIndexCount - nullptr, // const uint32_t* pQueueFamilyIndices - VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout - }; - - return vkCreateImage( GetDevice(), &image_create_info, nullptr, image ) == VK_SUCCESS; - } - - bool Tutorial07::AllocateImageMemory( VkImage image, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { - VkMemoryRequirements image_memory_requirements; - vkGetImageMemoryRequirements( GetDevice(), image, &image_memory_requirements ); - - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); - - for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { - if( (image_memory_requirements.memoryTypeBits & (1 << i)) && - (memory_properties.memoryTypes[i].propertyFlags & property) ) { - - VkMemoryAllocateInfo memory_allocate_info = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - image_memory_requirements.size, // VkDeviceSize allocationSize - i // uint32_t memoryTypeIndex - }; - - if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { - return true; - } - } - } - return false; - } - - bool Tutorial07::CreateImageView( ImageParameters &image_parameters ) { - VkImageViewCreateInfo image_view_create_info = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkImageViewCreateFlags flags - image_parameters.Handle, // VkImage image - VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format - { // VkComponentMapping components - VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle r - VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle g - VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle b - VK_COMPONENT_SWIZZLE_IDENTITY // VkComponentSwizzle a - }, - { // VkImageSubresourceRange subresourceRange - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - } - }; - - return vkCreateImageView( GetDevice(), &image_view_create_info, nullptr, &image_parameters.View ) == VK_SUCCESS; - } - - bool Tutorial07::CreateSampler( VkSampler *sampler ) { - VkSamplerCreateInfo sampler_create_info = { - VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0, // VkSamplerCreateFlags flags - VK_FILTER_LINEAR, // VkFilter magFilter - VK_FILTER_LINEAR, // VkFilter minFilter - VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW - 0.0f, // float mipLodBias - VK_FALSE, // VkBool32 anisotropyEnable - 1.0f, // float maxAnisotropy - VK_FALSE, // VkBool32 compareEnable - VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp - 0.0f, // float minLod - 0.0f, // float maxLod - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor - VK_FALSE // VkBool32 unnormalizedCoordinates - }; - - return vkCreateSampler( GetDevice(), &sampler_create_info, nullptr, sampler ) == VK_SUCCESS; - } - - bool Tutorial07::CopyTextureData( char *texture_data, uint32_t data_size, uint32_t width, uint32_t height ) { - // Prepare data in staging buffer - - void *staging_buffer_memory_pointer; - if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, data_size, 0, &staging_buffer_memory_pointer ) != VK_SUCCESS ) { - std::cout << "Could not map memory and upload texture data to a staging buffer!" << std::endl; - return false; - } - - memcpy( staging_buffer_memory_pointer, texture_data, data_size ); - - VkMappedMemoryRange flush_range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory - 0, // VkDeviceSize offset - data_size // VkDeviceSize size - }; - vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); - - vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); - - // Prepare command buffer to copy data from staging buffer to a vertex buffer - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); - - VkImageSubresourceRange image_subresource_range = { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }; - - VkImageMemoryBarrier image_memory_barrier_from_undefined_to_transfer_dst = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkAccessFlags srcAccessMask - VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - Vulkan.Image.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier_from_undefined_to_transfer_dst); - - VkBufferImageCopy buffer_image_copy_info = { - 0, // VkDeviceSize bufferOffset - 0, // uint32_t bufferRowLength - 0, // uint32_t bufferImageHeight - { // VkImageSubresourceLayers imageSubresource - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t mipLevel - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }, - { // VkOffset3D imageOffset - 0, // int32_t x - 0, // int32_t y - 0 // int32_t z - }, - { // VkExtent3D imageExtent - width, // uint32_t width - height, // uint32_t height - 1 // uint32_t depth - } - }; - vkCmdCopyBufferToImage( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.Image.Handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy_info ); - - VkImageMemoryBarrier image_memory_barrier_from_transfer_to_shader_read = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - Vulkan.Image.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier_from_transfer_to_shader_read); - - vkEndCommandBuffer( command_buffer ); - - // Submit command buffer and copy data from staging buffer to a vertex buffer - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // uint32_t waitSemaphoreCount - nullptr, // const VkSemaphore *pWaitSemaphores - nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - &command_buffer, // const VkCommandBuffer *pCommandBuffers - 0, // uint32_t signalSemaphoreCount - nullptr // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { - return false; - } - - vkDeviceWaitIdle( GetDevice() ); - - return true; - } - - bool Tutorial07::CreateUniformBuffer() { - Vulkan.UniformBuffer.Size = 16 * sizeof(float); - if( !CreateBuffer( VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Vulkan.UniformBuffer ) ) { - std::cout << "Could not create uniform buffer!" << std::endl; - return false; - } - - if( !CopyUniformBufferData() ) { - return false; - } - - return true; - } - - const std::array Tutorial07::GetUniformBufferData() const { - float half_width = static_cast(GetSwapChain().Extent.width) * 0.5f; - float half_height = static_cast(GetSwapChain().Extent.height) * 0.5f; - - return Tools::GetOrthographicProjectionMatrix( -half_width, half_width, -half_height, half_height, -1.0f, 1.0f ); - } - - bool Tutorial07::CopyUniformBufferData() { - // Prepare data in staging buffer - const std::array uniform_data = GetUniformBufferData(); - - void *staging_buffer_memory_pointer; - if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, Vulkan.UniformBuffer.Size, 0, &staging_buffer_memory_pointer) != VK_SUCCESS ) { - std::cout << "Could not map memory and upload data to a staging buffer!" << std::endl; - return false; - } - - memcpy( staging_buffer_memory_pointer, &uniform_data[0], Vulkan.UniformBuffer.Size ); - - VkMappedMemoryRange flush_range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory - 0, // VkDeviceSize offset - Vulkan.UniformBuffer.Size // VkDeviceSize size - }; - vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); - - vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); - - // Prepare command buffer to copy data from staging buffer to a uniform buffer - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); - - VkBufferCopy buffer_copy_info = { - 0, // VkDeviceSize srcOffset - 0, // VkDeviceSize dstOffset - Vulkan.UniformBuffer.Size // VkDeviceSize size - }; - vkCmdCopyBuffer( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.UniformBuffer.Handle, 1, &buffer_copy_info ); - - VkBufferMemoryBarrier buffer_memory_barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; - nullptr, // const void *pNext - VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_UNIFORM_READ_BIT, // VkAccessFlags dstAccessMask - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - Vulkan.UniformBuffer.Handle, // VkBuffer buffer - 0, // VkDeviceSize offset - VK_WHOLE_SIZE // VkDeviceSize size - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1, &buffer_memory_barrier, 0, nullptr ); - - vkEndCommandBuffer( command_buffer ); - - // Submit command buffer and copy data from staging buffer to a vertex buffer - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // uint32_t waitSemaphoreCount - nullptr, // const VkSemaphore *pWaitSemaphores - nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - &command_buffer, // const VkCommandBuffer *pCommandBuffers - 0, // uint32_t signalSemaphoreCount - nullptr // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { - return false; - } - - vkDeviceWaitIdle( GetDevice() ); - - return true; - } - - bool Tutorial07::CreateDescriptorSetLayout() { - std::vector layout_bindings = { - { - 0, // uint32_t binding - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType - 1, // uint32_t descriptorCount - VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags - nullptr // const VkSampler *pImmutableSamplers - }, - { - 1, // uint32_t binding - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType descriptorType - 1, // uint32_t descriptorCount - VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags - nullptr // const VkSampler *pImmutableSamplers - } - }; - - VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = { - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDescriptorSetLayoutCreateFlags flags - static_cast(layout_bindings.size()), // uint32_t bindingCount - &layout_bindings[0] // const VkDescriptorSetLayoutBinding *pBindings - }; - - if( vkCreateDescriptorSetLayout( GetDevice(), &descriptor_set_layout_create_info, nullptr, &Vulkan.DescriptorSet.Layout ) != VK_SUCCESS ) { - std::cout << "Could not create descriptor set layout!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial07::CreateDescriptorPool() { - std::vector pool_sizes = { - { - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType type - 1 // uint32_t descriptorCount - }, - { - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType type - 1 // uint32_t descriptorCount - } - }; - - VkDescriptorPoolCreateInfo descriptor_pool_create_info = { - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkDescriptorPoolCreateFlags flags - 1, // uint32_t maxSets - static_cast(pool_sizes.size()), // uint32_t poolSizeCount - &pool_sizes[0] // const VkDescriptorPoolSize *pPoolSizes - }; - - if( vkCreateDescriptorPool( GetDevice(), &descriptor_pool_create_info, nullptr, &Vulkan.DescriptorSet.Pool ) != VK_SUCCESS ) { - std::cout << "Could not create descriptor pool!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial07::AllocateDescriptorSet() { - VkDescriptorSetAllocateInfo descriptor_set_allocate_info = { - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.DescriptorSet.Pool, // VkDescriptorPool descriptorPool - 1, // uint32_t descriptorSetCount - &Vulkan.DescriptorSet.Layout // const VkDescriptorSetLayout *pSetLayouts - }; - - if( vkAllocateDescriptorSets( GetDevice(), &descriptor_set_allocate_info, &Vulkan.DescriptorSet.Handle ) != VK_SUCCESS ) { - std::cout << "Could not allocate descriptor set!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial07::UpdateDescriptorSet() { - VkDescriptorImageInfo image_info = { - Vulkan.Image.Sampler, // VkSampler sampler - Vulkan.Image.View, // VkImageView imageView - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout - }; - - VkDescriptorBufferInfo buffer_info = { - Vulkan.UniformBuffer.Handle, // VkBuffer buffer - 0, // VkDeviceSize offset - Vulkan.UniformBuffer.Size // VkDeviceSize range - }; - - std::vector descriptor_writes = { - { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.DescriptorSet.Handle, // VkDescriptorSet dstSet - 0, // uint32_t dstBinding - 0, // uint32_t dstArrayElement - 1, // uint32_t descriptorCount - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType - &image_info, // const VkDescriptorImageInfo *pImageInfo - nullptr, // const VkDescriptorBufferInfo *pBufferInfo - nullptr // const VkBufferView *pTexelBufferView - }, - { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.DescriptorSet.Handle, // VkDescriptorSet dstSet - 1, // uint32_t dstBinding - 0, // uint32_t dstArrayElement - 1, // uint32_t descriptorCount - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType descriptorType - nullptr, // const VkDescriptorImageInfo *pImageInfo - &buffer_info, // const VkDescriptorBufferInfo *pBufferInfo - nullptr // const VkBufferView *pTexelBufferView - } - }; - - vkUpdateDescriptorSets( GetDevice(), static_cast(descriptor_writes.size()), &descriptor_writes[0], 0, nullptr ); - return true; - } - - bool Tutorial07::CreateRenderPass() { - VkAttachmentDescription attachment_descriptions[] = { - { - 0, // VkAttachmentDescriptionFlags flags - GetSwapChain().Format, // VkFormat format - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout - } - }; - - VkAttachmentReference color_attachment_references[] = { - { - 0, // uint32_t attachment - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout - } - }; - - VkSubpassDescription subpass_descriptions[] = { - { - 0, // VkSubpassDescriptionFlags flags - VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint - 0, // uint32_t inputAttachmentCount - nullptr, // const VkAttachmentReference *pInputAttachments - 1, // uint32_t colorAttachmentCount - color_attachment_references, // const VkAttachmentReference *pColorAttachments - nullptr, // const VkAttachmentReference *pResolveAttachments - nullptr, // const VkAttachmentReference *pDepthStencilAttachment - 0, // uint32_t preserveAttachmentCount - nullptr // const uint32_t* pPreserveAttachments - } - }; - - VkRenderPassCreateInfo render_pass_create_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkRenderPassCreateFlags flags - 1, // uint32_t attachmentCount - attachment_descriptions, // const VkAttachmentDescription *pAttachments - 1, // uint32_t subpassCount - subpass_descriptions, // const VkSubpassDescription *pSubpasses - 0, // uint32_t dependencyCount - nullptr // const VkSubpassDependency *pDependencies - }; - - if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { - std::cout << "Could not create render pass!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial07::CreatePipelineLayout() { - VkPipelineLayoutCreateInfo layout_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineLayoutCreateFlags flags - 1, // uint32_t setLayoutCount - &Vulkan.DescriptorSet.Layout, // const VkDescriptorSetLayout *pSetLayouts - 0, // uint32_t pushConstantRangeCount - nullptr // const VkPushConstantRange *pPushConstantRanges - }; - - if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &Vulkan.PipelineLayout ) != VK_SUCCESS ) { - std::cout << "Could not create pipeline layout!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial07::CreatePipeline() { - Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data07/vert.spv" ); - Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data07/frag.spv" ); - - if( !vertex_shader_module || !fragment_shader_module ) { - return false; - } - - std::vector shader_stage_create_infos = { - // Vertex shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage - vertex_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - }, - // Fragment shader - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineShaderStageCreateFlags flags - VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage - fragment_shader_module.Get(), // VkShaderModule module - "main", // const char *pName - nullptr // const VkSpecializationInfo *pSpecializationInfo - } - }; - - VkVertexInputBindingDescription vertex_binding_description = { - 0, // uint32_t binding - sizeof(VertexData), // uint32_t stride - VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate - }; - - VkVertexInputAttributeDescription vertex_attribute_descriptions[] = { - { - 0, // uint32_t location - vertex_binding_description.binding, // uint32_t binding - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format - 0 // uint32_t offset - }, - { - 1, // uint32_t location - vertex_binding_description.binding, // uint32_t binding - VK_FORMAT_R32G32_SFLOAT, // VkFormat format - 4 * sizeof(float) // uint32_t offset - } - }; - - VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineVertexInputStateCreateFlags flags; - 1, // uint32_t vertexBindingDescriptionCount - &vertex_binding_description, // const VkVertexInputBindingDescription *pVertexBindingDescriptions - 2, // uint32_t vertexAttributeDescriptionCount - vertex_attribute_descriptions // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions - }; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineInputAssemblyStateCreateFlags flags - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology - VK_FALSE // VkBool32 primitiveRestartEnable - }; - - VkPipelineViewportStateCreateInfo viewport_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineViewportStateCreateFlags flags - 1, // uint32_t viewportCount - nullptr, // const VkViewport *pViewports - 1, // uint32_t scissorCount - nullptr // const VkRect2D *pScissors - }; - - VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineRasterizationStateCreateFlags flags - VK_FALSE, // VkBool32 depthClampEnable - VK_FALSE, // VkBool32 rasterizerDiscardEnable - VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode - VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode - VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace - VK_FALSE, // VkBool32 depthBiasEnable - 0.0f, // float depthBiasConstantFactor - 0.0f, // float depthBiasClamp - 0.0f, // float depthBiasSlopeFactor - 1.0f // float lineWidth - }; - - VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineMultisampleStateCreateFlags flags - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples - VK_FALSE, // VkBool32 sampleShadingEnable - 1.0f, // float minSampleShading - nullptr, // const VkSampleMask *pSampleMask - VK_FALSE, // VkBool32 alphaToCoverageEnable - VK_FALSE // VkBool32 alphaToOneEnable - }; - - VkPipelineColorBlendAttachmentState color_blend_attachment_state = { - VK_FALSE, // VkBool32 blendEnable - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp - VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor - VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor - VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT - }; - - VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineColorBlendStateCreateFlags flags - VK_FALSE, // VkBool32 logicOpEnable - VK_LOGIC_OP_COPY, // VkLogicOp logicOp - 1, // uint32_t attachmentCount - &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments - { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] - }; - - VkDynamicState dynamic_states[] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; - - VkPipelineDynamicStateCreateInfo dynamic_state_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineDynamicStateCreateFlags flags - 2, // uint32_t dynamicStateCount - dynamic_states // const VkDynamicState *pDynamicStates - }; - - VkGraphicsPipelineCreateInfo pipeline_create_info = { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineCreateFlags flags - static_cast(shader_stage_create_infos.size()), // uint32_t stageCount - &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages - &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; - &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState - nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState - &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState - &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState - &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState - nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState - &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState - &dynamic_state_create_info, // const VkPipelineDynamicStateCreateInfo *pDynamicState - Vulkan.PipelineLayout, // VkPipelineLayout layout - Vulkan.RenderPass, // VkRenderPass renderPass - 0, // uint32_t subpass - VK_NULL_HANDLE, // VkPipeline basePipelineHandle - -1 // int32_t basePipelineIndex - }; - - if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { - std::cout << "Could not create graphics pipeline!" << std::endl; - return false; - } - return true; - } - - Tools::AutoDeleter Tutorial07::CreateShaderModule( const char* filename ) { - const std::vector code = Tools::GetBinaryFileContents( filename ); - if( code.size() == 0 ) { - return Tools::AutoDeleter(); - } - - VkShaderModuleCreateInfo shader_module_create_info = { - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkShaderModuleCreateFlags flags - code.size(), // size_t codeSize - reinterpret_cast(&code[0]) // const uint32_t *pCode - }; - - VkShaderModule shader_module; - if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { - std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; - return Tools::AutoDeleter(); - } - - return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); - } - - bool Tutorial07::CreateVertexBuffer() { - const std::vector& vertex_data = GetVertexData(); - - Vulkan.VertexBuffer.Size = static_cast(vertex_data.size() * sizeof(vertex_data[0])); - if( !CreateBuffer( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Vulkan.VertexBuffer ) ) { - std::cout << "Could not create vertex buffer!" << std::endl; - return false; - } - - if( !CopyVertexData() ) { - return false; - } - - return true; - } - - const std::vector& Tutorial07::GetVertexData() const { - static const std::vector vertex_data = { - -170.0f, -170.0f, 0.0f, 1.0f, - -0.1f, -0.1f, - // - -170.0f, 170.0f, 0.0f, 1.0f, - -0.1f, 1.1f, - // - 170.0f, -170.0f, 0.0f, 1.0f, - 1.1f, -0.1f, - // - 170.0f, 170.0f, 0.0f, 1.0f, - 1.1f, 1.1f, - }; - - return vertex_data; - } - - bool Tutorial07::CopyVertexData() { - // Prepare data in staging buffer - const std::vector& vertex_data = GetVertexData(); - - void *staging_buffer_memory_pointer; - if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, Vulkan.VertexBuffer.Size, 0, &staging_buffer_memory_pointer) != VK_SUCCESS ) { - std::cout << "Could not map memory and upload data to a staging buffer!" << std::endl; - return false; - } - - memcpy( staging_buffer_memory_pointer, &vertex_data[0], Vulkan.VertexBuffer.Size ); - - VkMappedMemoryRange flush_range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory - 0, // VkDeviceSize offset - Vulkan.VertexBuffer.Size // VkDeviceSize size - }; - vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); - - vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); - - // Prepare command buffer to copy data from staging buffer to a vertex buffer - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); - - VkBufferCopy buffer_copy_info = { - 0, // VkDeviceSize srcOffset - 0, // VkDeviceSize dstOffset - Vulkan.VertexBuffer.Size // VkDeviceSize size - }; - vkCmdCopyBuffer(command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.VertexBuffer.Handle, 1, &buffer_copy_info); - - VkBufferMemoryBarrier buffer_memory_barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; - nullptr, // const void *pNext - VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkAccessFlags dstAccessMask - VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex - VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex - Vulkan.VertexBuffer.Handle, // VkBuffer buffer - 0, // VkDeviceSize offset - VK_WHOLE_SIZE // VkDeviceSize size - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, &buffer_memory_barrier, 0, nullptr ); - - vkEndCommandBuffer( command_buffer ); - - // Submit command buffer and copy data from staging buffer to a vertex buffer - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // uint32_t waitSemaphoreCount - nullptr, // const VkSemaphore *pWaitSemaphores - nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - &command_buffer, // const VkCommandBuffer *pCommandBuffers - 0, // uint32_t signalSemaphoreCount - nullptr // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { - return false; - } - - vkDeviceWaitIdle( GetDevice() ); - - return true; - } - - bool Tutorial07::PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ) { - if( !CreateFramebuffer( framebuffer, image_parameters.View ) ) { - return false; - } - - VkCommandBufferBeginInfo command_buffer_begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags - nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo - }; - - vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info ); - - VkImageSubresourceRange image_subresource_range = { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask - 0, // uint32_t baseMipLevel - 1, // uint32_t levelCount - 0, // uint32_t baseArrayLayer - 1 // uint32_t layerCount - }; - - uint32_t present_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetPresentQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED; - uint32_t graphics_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetGraphicsQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED; - VkImageMemoryBarrier barrier_from_present_to_draw = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout - present_queue_family_index, // uint32_t srcQueueFamilyIndex - graphics_queue_family_index, // uint32_t dstQueueFamilyIndex - image_parameters.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); - - VkClearValue clear_value = { - { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color - }; - - VkRenderPassBeginInfo render_pass_begin_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType - nullptr, // const void *pNext - Vulkan.RenderPass, // VkRenderPass renderPass - framebuffer, // VkFramebuffer framebuffer - { // VkRect2D renderArea - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - GetSwapChain().Extent, // VkExtent2D extent; - }, - 1, // uint32_t clearValueCount - &clear_value // const VkClearValue *pClearValues - }; - - vkCmdBeginRenderPass( command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); - - vkCmdBindPipeline( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); - - VkViewport viewport = { - 0.0f, // float x - 0.0f, // float y - static_cast(GetSwapChain().Extent.width), // float width - static_cast(GetSwapChain().Extent.height), // float height - 0.0f, // float minDepth - 1.0f // float maxDepth - }; - - VkRect2D scissor = { - { // VkOffset2D offset - 0, // int32_t x - 0 // int32_t y - }, - { // VkExtent2D extent - GetSwapChain().Extent.width, // uint32_t width - GetSwapChain().Extent.height // uint32_t height - } - }; - - vkCmdSetViewport( command_buffer, 0, 1, &viewport ); - vkCmdSetScissor( command_buffer, 0, 1, &scissor ); - - VkDeviceSize offset = 0; - vkCmdBindVertexBuffers( command_buffer, 0, 1, &Vulkan.VertexBuffer.Handle, &offset ); - - vkCmdBindDescriptorSets( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.PipelineLayout, 0, 1, &Vulkan.DescriptorSet.Handle, 0, nullptr ); - - vkCmdDraw( command_buffer, 4, 1, 0, 0 ); - - vkCmdEndRenderPass( command_buffer ); - - VkImageMemoryBarrier barrier_from_draw_to_present = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType - nullptr, // const void *pNext - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask - VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout - graphics_queue_family_index, // uint32_t srcQueueFamilyIndex - present_queue_family_index, // uint32_t dstQueueFamilyIndex - image_parameters.Handle, // VkImage image - image_subresource_range // VkImageSubresourceRange subresourceRange - }; - vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); - - if( vkEndCommandBuffer( command_buffer ) != VK_SUCCESS ) { - std::cout << "Could not record command buffer!" << std::endl; - return false; - } - return true; - } - - bool Tutorial07::CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ) { - if( framebuffer != VK_NULL_HANDLE ) { - vkDestroyFramebuffer( GetDevice(), framebuffer, nullptr ); - framebuffer = VK_NULL_HANDLE; - } - - VkFramebufferCreateInfo framebuffer_create_info = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkFramebufferCreateFlags flags - Vulkan.RenderPass, // VkRenderPass renderPass - 1, // uint32_t attachmentCount - &image_view, // const VkImageView *pAttachments - GetSwapChain().Extent.width, // uint32_t width - GetSwapChain().Extent.height, // uint32_t height - 1 // uint32_t layers - }; - - if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &framebuffer ) != VK_SUCCESS ) { - std::cout << "Could not create a framebuffer!" << std::endl; - return false; - } - - return true; - } - - bool Tutorial07::ChildOnWindowSizeChanged() { - if( (GetDevice() != VK_NULL_HANDLE) && - (Vulkan.StagingBuffer.Handle != VK_NULL_HANDLE) ) { - vkDeviceWaitIdle( GetDevice() ); - return CopyUniformBufferData(); - } - return true; - } - - bool Tutorial07::Draw() { - static size_t resource_index = 0; - RenderingResourcesData ¤t_rendering_resource = Vulkan.RenderingResources[resource_index]; - VkSwapchainKHR swap_chain = GetSwapChain().Handle; - uint32_t image_index; - - resource_index = (resource_index + 1) % VulkanTutorial07Parameters::ResourcesCount; - - if( vkWaitForFences( GetDevice(), 1, ¤t_rendering_resource.Fence, VK_FALSE, 1000000000 ) != VK_SUCCESS ) { - std::cout << "Waiting for fence takes too long!" << std::endl; - return false; - } - vkResetFences( GetDevice(), 1, ¤t_rendering_resource.Fence ); - - VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, current_rendering_resource.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); - switch( result ) { - case VK_SUCCESS: - case VK_SUBOPTIMAL_KHR: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; - return false; - } - - if( !PrepareFrame( current_rendering_resource.CommandBuffer, GetSwapChain().Images[image_index], current_rendering_resource.Framebuffer ) ) { - return false; - } - - VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - ¤t_rendering_resource.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores - &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; - 1, // uint32_t commandBufferCount - ¤t_rendering_resource.CommandBuffer, // const VkCommandBuffer *pCommandBuffers - 1, // uint32_t signalSemaphoreCount - ¤t_rendering_resource.FinishedRenderingSemaphore // const VkSemaphore *pSignalSemaphores - }; - - if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, current_rendering_resource.Fence ) != VK_SUCCESS ) { - return false; - } - - VkPresentInfoKHR present_info = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType - nullptr, // const void *pNext - 1, // uint32_t waitSemaphoreCount - ¤t_rendering_resource.FinishedRenderingSemaphore, // const VkSemaphore *pWaitSemaphores - 1, // uint32_t swapchainCount - &swap_chain, // const VkSwapchainKHR *pSwapchains - &image_index, // const uint32_t *pImageIndices - nullptr // VkResult *pResults - }; - result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); - - switch( result ) { - case VK_SUCCESS: - break; - case VK_ERROR_OUT_OF_DATE_KHR: - case VK_SUBOPTIMAL_KHR: - return OnWindowSizeChanged(); - default: - std::cout << "Problem occurred during image presentation!" << std::endl; - return false; - } - - return true; - } - - void Tutorial07::ChildClear() { - } - - Tutorial07::~Tutorial07() { - if( GetDevice() != VK_NULL_HANDLE ) { - vkDeviceWaitIdle( GetDevice() ); - - for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { - if( Vulkan.RenderingResources[i].Framebuffer != VK_NULL_HANDLE ) { - vkDestroyFramebuffer( GetDevice(), Vulkan.RenderingResources[i].Framebuffer, nullptr ); - } - if( Vulkan.RenderingResources[i].CommandBuffer != VK_NULL_HANDLE ) { - vkFreeCommandBuffers( GetDevice(), Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ); - } - if( Vulkan.RenderingResources[i].ImageAvailableSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].ImageAvailableSemaphore, nullptr ); - } - if( Vulkan.RenderingResources[i].FinishedRenderingSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].FinishedRenderingSemaphore, nullptr ); - } - if( Vulkan.RenderingResources[i].Fence != VK_NULL_HANDLE ) { - vkDestroyFence( GetDevice(), Vulkan.RenderingResources[i].Fence, nullptr ); - } - } - - if( Vulkan.CommandPool != VK_NULL_HANDLE ) { - vkDestroyCommandPool( GetDevice(), Vulkan.CommandPool, nullptr ); - Vulkan.CommandPool = VK_NULL_HANDLE; - } - - DestroyBuffer( Vulkan.VertexBuffer ); - - DestroyBuffer( Vulkan.StagingBuffer ); - - if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { - vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); - Vulkan.GraphicsPipeline = VK_NULL_HANDLE; - } - - if( Vulkan.PipelineLayout != VK_NULL_HANDLE ) { - vkDestroyPipelineLayout( GetDevice(), Vulkan.PipelineLayout, nullptr ); - Vulkan.PipelineLayout = VK_NULL_HANDLE; - } - - if( Vulkan.RenderPass != VK_NULL_HANDLE ) { - vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); - Vulkan.RenderPass = VK_NULL_HANDLE; - } - - if( Vulkan.DescriptorSet.Pool != VK_NULL_HANDLE ) { - vkDestroyDescriptorPool( GetDevice(), Vulkan.DescriptorSet.Pool, nullptr ); - Vulkan.DescriptorSet.Pool = VK_NULL_HANDLE; - } - - if( Vulkan.DescriptorSet.Layout != VK_NULL_HANDLE ) { - vkDestroyDescriptorSetLayout( GetDevice(), Vulkan.DescriptorSet.Layout, nullptr ); - Vulkan.DescriptorSet.Layout = VK_NULL_HANDLE; - } - - DestroyBuffer( Vulkan.UniformBuffer ); - - if( Vulkan.Image.Sampler != VK_NULL_HANDLE ) { - vkDestroySampler( GetDevice(), Vulkan.Image.Sampler, nullptr ); - Vulkan.Image.Sampler = VK_NULL_HANDLE; - } - - if( Vulkan.Image.View != VK_NULL_HANDLE ) { - vkDestroyImageView( GetDevice(), Vulkan.Image.View, nullptr ); - Vulkan.Image.View = VK_NULL_HANDLE; - } - - if( Vulkan.Image.Handle != VK_NULL_HANDLE ) { - vkDestroyImage( GetDevice(), Vulkan.Image.Handle, nullptr ); - Vulkan.Image.Handle = VK_NULL_HANDLE; - } - - if( Vulkan.Image.Memory != VK_NULL_HANDLE ) { - vkFreeMemory( GetDevice(), Vulkan.Image.Memory, nullptr ); - Vulkan.Image.Memory = VK_NULL_HANDLE; - } - } - } - - void Tutorial07::DestroyBuffer( BufferParameters& buffer ) { - if( buffer.Handle != VK_NULL_HANDLE ) { - vkDestroyBuffer( GetDevice(), buffer.Handle, nullptr ); - buffer.Handle = VK_NULL_HANDLE; - } - - if( buffer.Memory != VK_NULL_HANDLE ) { - vkFreeMemory( GetDevice(), buffer.Memory, nullptr ); - buffer.Memory = VK_NULL_HANDLE; - } - } - -} // namespace ApiWithoutSecrets +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial07.h" +#include "VulkanFunctions.h" + +namespace ApiWithoutSecrets { + + Tutorial07::Tutorial07() : + Vulkan() { + } + + bool Tutorial07::CreateRenderingResources() { + if( !CreateCommandBuffers() ) { + return false; + } + if( !CreateSemaphores() ) { + return false; + } + if( !CreateFences() ) { + return false; + } + return true; + } + + bool Tutorial07::CreateCommandBuffers() { + if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.CommandPool ) ) { + std::cout << "Could not create command pool!" << std::endl; + return false; + } + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( !AllocateCommandBuffers( Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ) ) { + std::cout << "Could not allocate command buffer!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial07::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) { + VkCommandPoolCreateInfo cmd_pool_create_info = { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | // VkCommandPoolCreateFlags flags + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + queue_family_index // uint32_t queueFamilyIndex + }; + + if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) { + return false; + } + return true; + } + + bool Tutorial07::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) { + VkCommandBufferAllocateInfo command_buffer_allocate_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + pool, // VkCommandPool commandPool + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level + count // uint32_t bufferCount + }; + + if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) { + return false; + } + return true; + } + + bool Tutorial07::CreateSemaphores() { + VkSemaphoreCreateInfo semaphore_create_info = { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0 // VkSemaphoreCreateFlags flags + }; + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].ImageAvailableSemaphore ) != VK_SUCCESS) || + (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].FinishedRenderingSemaphore ) != VK_SUCCESS) ) { + std::cout << "Could not create semaphores!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial07::CreateFences() { + VkFenceCreateInfo fence_create_info = { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_FENCE_CREATE_SIGNALED_BIT // VkFenceCreateFlags flags + }; + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( vkCreateFence( GetDevice(), &fence_create_info, nullptr, &Vulkan.RenderingResources[i].Fence ) != VK_SUCCESS ) { + std::cout << "Could not create a fence!" << std::endl; + return false; + } + } + return true; + } + + bool Tutorial07::CreateStagingBuffer() { + Vulkan.StagingBuffer.Size = 1000000; + if( !CreateBuffer( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, Vulkan.StagingBuffer ) ) { + std::cout << "Could not create staging buffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial07::CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer ) { + VkBufferCreateInfo buffer_create_info = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkBufferCreateFlags flags + buffer.Size, // VkDeviceSize size + usage, // VkBufferUsageFlags usage + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode + 0, // uint32_t queueFamilyIndexCount + nullptr // const uint32_t *pQueueFamilyIndices + }; + + if( vkCreateBuffer( GetDevice(), &buffer_create_info, nullptr, &buffer.Handle ) != VK_SUCCESS ) { + std::cout << "Could not create buffer!" << std::endl; + return false; + } + + if( !AllocateBufferMemory( buffer.Handle, memoryProperty, &buffer.Memory ) ) { + std::cout << "Could not allocate memory for a buffer!" << std::endl; + return false; + } + + if( vkBindBufferMemory( GetDevice(), buffer.Handle, buffer.Memory, 0 ) != VK_SUCCESS ) { + std::cout << "Could not bind memory to a buffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial07::AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { + VkMemoryRequirements buffer_memory_requirements; + vkGetBufferMemoryRequirements( GetDevice(), buffer, &buffer_memory_requirements ); + + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); + + for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { + if( (buffer_memory_requirements.memoryTypeBits & (1 << i)) && + (memory_properties.memoryTypes[i].propertyFlags & property) ) { + + VkMemoryAllocateInfo memory_allocate_info = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + buffer_memory_requirements.size, // VkDeviceSize allocationSize + i // uint32_t memoryTypeIndex + }; + + if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { + return true; + } + } + } + return false; + } + + bool Tutorial07::CreateTexture() { + int width = 0, height = 0, data_size = 0; + std::vector texture_data = Tools::GetImageData( "Data07/texture.png", 4, &width, &height, nullptr, &data_size ); + if( texture_data.size() == 0 ) { + return false; + } + + if( !CreateImage( width, height, &Vulkan.Image.Handle ) ) { + std::cout << "Could not create image!" << std::endl; + return false; + } + + if( !AllocateImageMemory( Vulkan.Image.Handle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &Vulkan.Image.Memory ) ) { + std::cout << "Could not allocate memory for image!" << std::endl; + return false; + } + + if( vkBindImageMemory( GetDevice(), Vulkan.Image.Handle, Vulkan.Image.Memory, 0 ) != VK_SUCCESS ) { + std::cout << "Could not bind memory to an image!" << std::endl; + return false; + } + + if( !CreateImageView( Vulkan.Image ) ) { + std::cout << "Could not create image view!" << std::endl; + return false; + } + + if( !CreateSampler( &Vulkan.Image.Sampler ) ) { + std::cout << "Could not create sampler!" << std::endl; + return false; + } + + if( !CopyTextureData( &texture_data[0], data_size, width, height ) ) { + std::cout << "Could not upload texture data to device memory!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial07::CreateImage( uint32_t width, uint32_t height, VkImage *image ) { + VkImageCreateInfo image_create_info = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void *pNext + 0, // VkImageCreateFlags flags + VK_IMAGE_TYPE_2D, // VkImageType imageType + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format + { // VkExtent3D extent + width, // uint32_t width + height, // uint32_t height + 1 // uint32_t depth + }, + 1, // uint32_t mipLevels + 1, // uint32_t arrayLayers + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling + VK_IMAGE_USAGE_TRANSFER_DST_BIT | // VkImageUsageFlags usage + VK_IMAGE_USAGE_SAMPLED_BIT, + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode + 0, // uint32_t queueFamilyIndexCount + nullptr, // const uint32_t* pQueueFamilyIndices + VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout + }; + + return vkCreateImage( GetDevice(), &image_create_info, nullptr, image ) == VK_SUCCESS; + } + + bool Tutorial07::AllocateImageMemory( VkImage image, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) { + VkMemoryRequirements image_memory_requirements; + vkGetImageMemoryRequirements( GetDevice(), image, &image_memory_requirements ); + + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties ); + + for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) { + if( (image_memory_requirements.memoryTypeBits & (1 << i)) && + (memory_properties.memoryTypes[i].propertyFlags & property) ) { + + VkMemoryAllocateInfo memory_allocate_info = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + image_memory_requirements.size, // VkDeviceSize allocationSize + i // uint32_t memoryTypeIndex + }; + + if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) { + return true; + } + } + } + return false; + } + + bool Tutorial07::CreateImageView( ImageParameters &image_parameters ) { + VkImageViewCreateInfo image_view_create_info = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkImageViewCreateFlags flags + image_parameters.Handle, // VkImage image + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format + { // VkComponentMapping components + VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle r + VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle g + VK_COMPONENT_SWIZZLE_IDENTITY, // VkComponentSwizzle b + VK_COMPONENT_SWIZZLE_IDENTITY // VkComponentSwizzle a + }, + { // VkImageSubresourceRange subresourceRange + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + } + }; + + return vkCreateImageView( GetDevice(), &image_view_create_info, nullptr, &image_parameters.View ) == VK_SUCCESS; + } + + bool Tutorial07::CreateSampler( VkSampler *sampler ) { + VkSamplerCreateInfo sampler_create_info = { + VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0, // VkSamplerCreateFlags flags + VK_FILTER_LINEAR, // VkFilter magFilter + VK_FILTER_LINEAR, // VkFilter minFilter + VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW + 0.0f, // float mipLodBias + VK_FALSE, // VkBool32 anisotropyEnable + 1.0f, // float maxAnisotropy + VK_FALSE, // VkBool32 compareEnable + VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp + 0.0f, // float minLod + 0.0f, // float maxLod + VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor + VK_FALSE // VkBool32 unnormalizedCoordinates + }; + + return vkCreateSampler( GetDevice(), &sampler_create_info, nullptr, sampler ) == VK_SUCCESS; + } + + bool Tutorial07::CopyTextureData( char *texture_data, uint32_t data_size, uint32_t width, uint32_t height ) { + // Prepare data in staging buffer + + void *staging_buffer_memory_pointer; + if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, data_size, 0, &staging_buffer_memory_pointer ) != VK_SUCCESS ) { + std::cout << "Could not map memory and upload texture data to a staging buffer!" << std::endl; + return false; + } + + memcpy( staging_buffer_memory_pointer, texture_data, data_size ); + + VkMappedMemoryRange flush_range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory + 0, // VkDeviceSize offset + data_size // VkDeviceSize size + }; + vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); + + vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); + + // Prepare command buffer to copy data from staging buffer to a vertex buffer + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); + + VkImageSubresourceRange image_subresource_range = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + VkImageMemoryBarrier image_memory_barrier_from_undefined_to_transfer_dst = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkAccessFlags srcAccessMask + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + Vulkan.Image.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier_from_undefined_to_transfer_dst); + + VkBufferImageCopy buffer_image_copy_info = { + 0, // VkDeviceSize bufferOffset + 0, // uint32_t bufferRowLength + 0, // uint32_t bufferImageHeight + { // VkImageSubresourceLayers imageSubresource + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t mipLevel + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }, + { // VkOffset3D imageOffset + 0, // int32_t x + 0, // int32_t y + 0 // int32_t z + }, + { // VkExtent3D imageExtent + width, // uint32_t width + height, // uint32_t height + 1 // uint32_t depth + } + }; + vkCmdCopyBufferToImage( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.Image.Handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy_info ); + + VkImageMemoryBarrier image_memory_barrier_from_transfer_to_shader_read = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + Vulkan.Image.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier_from_transfer_to_shader_read); + + vkEndCommandBuffer( command_buffer ); + + // Submit command buffer and copy data from staging buffer to a vertex buffer + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // uint32_t waitSemaphoreCount + nullptr, // const VkSemaphore *pWaitSemaphores + nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + &command_buffer, // const VkCommandBuffer *pCommandBuffers + 0, // uint32_t signalSemaphoreCount + nullptr // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { + return false; + } + + vkDeviceWaitIdle( GetDevice() ); + + return true; + } + + bool Tutorial07::CreateUniformBuffer() { + Vulkan.UniformBuffer.Size = 16 * sizeof(float); + if( !CreateBuffer( VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Vulkan.UniformBuffer ) ) { + std::cout << "Could not create uniform buffer!" << std::endl; + return false; + } + + if( !CopyUniformBufferData() ) { + return false; + } + + return true; + } + + const std::array Tutorial07::GetUniformBufferData() const { + float half_width = static_cast(GetSwapChain().Extent.width) * 0.5f; + float half_height = static_cast(GetSwapChain().Extent.height) * 0.5f; + + return Tools::GetOrthographicProjectionMatrix( -half_width, half_width, -half_height, half_height, -1.0f, 1.0f ); + } + + bool Tutorial07::CopyUniformBufferData() { + // Prepare data in staging buffer + const std::array uniform_data = GetUniformBufferData(); + + void *staging_buffer_memory_pointer; + if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, Vulkan.UniformBuffer.Size, 0, &staging_buffer_memory_pointer) != VK_SUCCESS ) { + std::cout << "Could not map memory and upload data to a staging buffer!" << std::endl; + return false; + } + + memcpy( staging_buffer_memory_pointer, &uniform_data[0], Vulkan.UniformBuffer.Size ); + + VkMappedMemoryRange flush_range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory + 0, // VkDeviceSize offset + Vulkan.UniformBuffer.Size // VkDeviceSize size + }; + vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); + + vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); + + // Prepare command buffer to copy data from staging buffer to a uniform buffer + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); + + VkBufferCopy buffer_copy_info = { + 0, // VkDeviceSize srcOffset + 0, // VkDeviceSize dstOffset + Vulkan.UniformBuffer.Size // VkDeviceSize size + }; + vkCmdCopyBuffer( command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.UniformBuffer.Handle, 1, &buffer_copy_info ); + + VkBufferMemoryBarrier buffer_memory_barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + nullptr, // const void *pNext + VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_UNIFORM_READ_BIT, // VkAccessFlags dstAccessMask + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + Vulkan.UniformBuffer.Handle, // VkBuffer buffer + 0, // VkDeviceSize offset + VK_WHOLE_SIZE // VkDeviceSize size + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1, &buffer_memory_barrier, 0, nullptr ); + + vkEndCommandBuffer( command_buffer ); + + // Submit command buffer and copy data from staging buffer to a vertex buffer + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // uint32_t waitSemaphoreCount + nullptr, // const VkSemaphore *pWaitSemaphores + nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + &command_buffer, // const VkCommandBuffer *pCommandBuffers + 0, // uint32_t signalSemaphoreCount + nullptr // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { + return false; + } + + vkDeviceWaitIdle( GetDevice() ); + + return true; + } + + bool Tutorial07::CreateDescriptorSetLayout() { + std::vector layout_bindings = { + { + 0, // uint32_t binding + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType + 1, // uint32_t descriptorCount + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags + nullptr // const VkSampler *pImmutableSamplers + }, + { + 1, // uint32_t binding + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType descriptorType + 1, // uint32_t descriptorCount + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags + nullptr // const VkSampler *pImmutableSamplers + } + }; + + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDescriptorSetLayoutCreateFlags flags + static_cast(layout_bindings.size()), // uint32_t bindingCount + &layout_bindings[0] // const VkDescriptorSetLayoutBinding *pBindings + }; + + if( vkCreateDescriptorSetLayout( GetDevice(), &descriptor_set_layout_create_info, nullptr, &Vulkan.DescriptorSet.Layout ) != VK_SUCCESS ) { + std::cout << "Could not create descriptor set layout!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial07::CreateDescriptorPool() { + std::vector pool_sizes = { + { + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType type + 1 // uint32_t descriptorCount + }, + { + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType type + 1 // uint32_t descriptorCount + } + }; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkDescriptorPoolCreateFlags flags + 1, // uint32_t maxSets + static_cast(pool_sizes.size()), // uint32_t poolSizeCount + &pool_sizes[0] // const VkDescriptorPoolSize *pPoolSizes + }; + + if( vkCreateDescriptorPool( GetDevice(), &descriptor_pool_create_info, nullptr, &Vulkan.DescriptorSet.Pool ) != VK_SUCCESS ) { + std::cout << "Could not create descriptor pool!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial07::AllocateDescriptorSet() { + VkDescriptorSetAllocateInfo descriptor_set_allocate_info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.DescriptorSet.Pool, // VkDescriptorPool descriptorPool + 1, // uint32_t descriptorSetCount + &Vulkan.DescriptorSet.Layout // const VkDescriptorSetLayout *pSetLayouts + }; + + if( vkAllocateDescriptorSets( GetDevice(), &descriptor_set_allocate_info, &Vulkan.DescriptorSet.Handle ) != VK_SUCCESS ) { + std::cout << "Could not allocate descriptor set!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial07::UpdateDescriptorSet() { + VkDescriptorImageInfo image_info = { + Vulkan.Image.Sampler, // VkSampler sampler + Vulkan.Image.View, // VkImageView imageView + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout + }; + + VkDescriptorBufferInfo buffer_info = { + Vulkan.UniformBuffer.Handle, // VkBuffer buffer + 0, // VkDeviceSize offset + Vulkan.UniformBuffer.Size // VkDeviceSize range + }; + + std::vector descriptor_writes = { + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.DescriptorSet.Handle, // VkDescriptorSet dstSet + 0, // uint32_t dstBinding + 0, // uint32_t dstArrayElement + 1, // uint32_t descriptorCount + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType + &image_info, // const VkDescriptorImageInfo *pImageInfo + nullptr, // const VkDescriptorBufferInfo *pBufferInfo + nullptr // const VkBufferView *pTexelBufferView + }, + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.DescriptorSet.Handle, // VkDescriptorSet dstSet + 1, // uint32_t dstBinding + 0, // uint32_t dstArrayElement + 1, // uint32_t descriptorCount + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType descriptorType + nullptr, // const VkDescriptorImageInfo *pImageInfo + &buffer_info, // const VkDescriptorBufferInfo *pBufferInfo + nullptr // const VkBufferView *pTexelBufferView + } + }; + + vkUpdateDescriptorSets( GetDevice(), static_cast(descriptor_writes.size()), &descriptor_writes[0], 0, nullptr ); + return true; + } + + bool Tutorial07::CreateRenderPass() { + VkAttachmentDescription attachment_descriptions[] = { + { + 0, // VkAttachmentDescriptionFlags flags + GetSwapChain().Format, // VkFormat format + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout + } + }; + + VkAttachmentReference color_attachment_references[] = { + { + 0, // uint32_t attachment + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout + } + }; + + VkSubpassDescription subpass_descriptions[] = { + { + 0, // VkSubpassDescriptionFlags flags + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint + 0, // uint32_t inputAttachmentCount + nullptr, // const VkAttachmentReference *pInputAttachments + 1, // uint32_t colorAttachmentCount + color_attachment_references, // const VkAttachmentReference *pColorAttachments + nullptr, // const VkAttachmentReference *pResolveAttachments + nullptr, // const VkAttachmentReference *pDepthStencilAttachment + 0, // uint32_t preserveAttachmentCount + nullptr // const uint32_t* pPreserveAttachments + } + }; + + VkRenderPassCreateInfo render_pass_create_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkRenderPassCreateFlags flags + 1, // uint32_t attachmentCount + attachment_descriptions, // const VkAttachmentDescription *pAttachments + 1, // uint32_t subpassCount + subpass_descriptions, // const VkSubpassDescription *pSubpasses + 0, // uint32_t dependencyCount + nullptr // const VkSubpassDependency *pDependencies + }; + + if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) { + std::cout << "Could not create render pass!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial07::CreatePipelineLayout() { + VkPipelineLayoutCreateInfo layout_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineLayoutCreateFlags flags + 1, // uint32_t setLayoutCount + &Vulkan.DescriptorSet.Layout, // const VkDescriptorSetLayout *pSetLayouts + 0, // uint32_t pushConstantRangeCount + nullptr // const VkPushConstantRange *pPushConstantRanges + }; + + if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &Vulkan.PipelineLayout ) != VK_SUCCESS ) { + std::cout << "Could not create pipeline layout!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial07::CreatePipeline() { + Tools::AutoDeleter vertex_shader_module = CreateShaderModule( "Data07/vert.spv" ); + Tools::AutoDeleter fragment_shader_module = CreateShaderModule( "Data07/frag.spv" ); + + if( !vertex_shader_module || !fragment_shader_module ) { + return false; + } + + std::vector shader_stage_create_infos = { + // Vertex shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage + vertex_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + }, + // Fragment shader + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineShaderStageCreateFlags flags + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage + fragment_shader_module.Get(), // VkShaderModule module + "main", // const char *pName + nullptr // const VkSpecializationInfo *pSpecializationInfo + } + }; + + VkVertexInputBindingDescription vertex_binding_description = { + 0, // uint32_t binding + sizeof(VertexData), // uint32_t stride + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate + }; + + VkVertexInputAttributeDescription vertex_attribute_descriptions[] = { + { + 0, // uint32_t location + vertex_binding_description.binding, // uint32_t binding + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format + 0 // uint32_t offset + }, + { + 1, // uint32_t location + vertex_binding_description.binding, // uint32_t binding + VK_FORMAT_R32G32_SFLOAT, // VkFormat format + 4 * sizeof(float) // uint32_t offset + } + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineVertexInputStateCreateFlags flags; + 1, // uint32_t vertexBindingDescriptionCount + &vertex_binding_description, // const VkVertexInputBindingDescription *pVertexBindingDescriptions + 2, // uint32_t vertexAttributeDescriptionCount + vertex_attribute_descriptions // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions + }; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineInputAssemblyStateCreateFlags flags + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology + VK_FALSE // VkBool32 primitiveRestartEnable + }; + + VkPipelineViewportStateCreateInfo viewport_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineViewportStateCreateFlags flags + 1, // uint32_t viewportCount + nullptr, // const VkViewport *pViewports + 1, // uint32_t scissorCount + nullptr // const VkRect2D *pScissors + }; + + VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineRasterizationStateCreateFlags flags + VK_FALSE, // VkBool32 depthClampEnable + VK_FALSE, // VkBool32 rasterizerDiscardEnable + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode + VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace + VK_FALSE, // VkBool32 depthBiasEnable + 0.0f, // float depthBiasConstantFactor + 0.0f, // float depthBiasClamp + 0.0f, // float depthBiasSlopeFactor + 1.0f // float lineWidth + }; + + VkPipelineMultisampleStateCreateInfo multisample_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineMultisampleStateCreateFlags flags + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples + VK_FALSE, // VkBool32 sampleShadingEnable + 1.0f, // float minSampleShading + nullptr, // const VkSampleMask *pSampleMask + VK_FALSE, // VkBool32 alphaToCoverageEnable + VK_FALSE // VkBool32 alphaToOneEnable + }; + + VkPipelineColorBlendAttachmentState color_blend_attachment_state = { + VK_FALSE, // VkBool32 blendEnable + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT + }; + + VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineColorBlendStateCreateFlags flags + VK_FALSE, // VkBool32 logicOpEnable + VK_LOGIC_OP_COPY, // VkLogicOp logicOp + 1, // uint32_t attachmentCount + &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments + { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] + }; + + VkDynamicState dynamic_states[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + + VkPipelineDynamicStateCreateInfo dynamic_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineDynamicStateCreateFlags flags + 2, // uint32_t dynamicStateCount + dynamic_states // const VkDynamicState *pDynamicStates + }; + + VkGraphicsPipelineCreateInfo pipeline_create_info = { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineCreateFlags flags + static_cast(shader_stage_create_infos.size()), // uint32_t stageCount + &shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages + &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; + &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState + nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState + &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState + &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState + &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState + nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState + &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState + &dynamic_state_create_info, // const VkPipelineDynamicStateCreateInfo *pDynamicState + Vulkan.PipelineLayout, // VkPipelineLayout layout + Vulkan.RenderPass, // VkRenderPass renderPass + 0, // uint32_t subpass + VK_NULL_HANDLE, // VkPipeline basePipelineHandle + -1 // int32_t basePipelineIndex + }; + + if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) { + std::cout << "Could not create graphics pipeline!" << std::endl; + return false; + } + return true; + } + + Tools::AutoDeleter Tutorial07::CreateShaderModule( const char* filename ) { + const std::vector code = Tools::GetBinaryFileContents( filename ); + if( code.size() == 0 ) { + return Tools::AutoDeleter(); + } + + VkShaderModuleCreateInfo shader_module_create_info = { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkShaderModuleCreateFlags flags + code.size(), // size_t codeSize + reinterpret_cast(&code[0]) // const uint32_t *pCode + }; + + VkShaderModule shader_module; + if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) { + std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl; + return Tools::AutoDeleter(); + } + + return Tools::AutoDeleter( shader_module, vkDestroyShaderModule, GetDevice() ); + } + + bool Tutorial07::CreateVertexBuffer() { + const std::vector& vertex_data = GetVertexData(); + + Vulkan.VertexBuffer.Size = static_cast(vertex_data.size() * sizeof(vertex_data[0])); + if( !CreateBuffer( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Vulkan.VertexBuffer ) ) { + std::cout << "Could not create vertex buffer!" << std::endl; + return false; + } + + if( !CopyVertexData() ) { + return false; + } + + return true; + } + + const std::vector& Tutorial07::GetVertexData() const { + static const std::vector vertex_data = { + -170.0f, -170.0f, 0.0f, 1.0f, + -0.1f, -0.1f, + // + -170.0f, 170.0f, 0.0f, 1.0f, + -0.1f, 1.1f, + // + 170.0f, -170.0f, 0.0f, 1.0f, + 1.1f, -0.1f, + // + 170.0f, 170.0f, 0.0f, 1.0f, + 1.1f, 1.1f, + }; + + return vertex_data; + } + + bool Tutorial07::CopyVertexData() { + // Prepare data in staging buffer + const std::vector& vertex_data = GetVertexData(); + + void *staging_buffer_memory_pointer; + if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, Vulkan.VertexBuffer.Size, 0, &staging_buffer_memory_pointer) != VK_SUCCESS ) { + std::cout << "Could not map memory and upload data to a staging buffer!" << std::endl; + return false; + } + + memcpy( staging_buffer_memory_pointer, &vertex_data[0], Vulkan.VertexBuffer.Size ); + + VkMappedMemoryRange flush_range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory + 0, // VkDeviceSize offset + Vulkan.VertexBuffer.Size // VkDeviceSize size + }; + vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range ); + + vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory ); + + // Prepare command buffer to copy data from staging buffer to a vertex buffer + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info); + + VkBufferCopy buffer_copy_info = { + 0, // VkDeviceSize srcOffset + 0, // VkDeviceSize dstOffset + Vulkan.VertexBuffer.Size // VkDeviceSize size + }; + vkCmdCopyBuffer(command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.VertexBuffer.Handle, 1, &buffer_copy_info); + + VkBufferMemoryBarrier buffer_memory_barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + nullptr, // const void *pNext + VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkAccessFlags dstAccessMask + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + Vulkan.VertexBuffer.Handle, // VkBuffer buffer + 0, // VkDeviceSize offset + VK_WHOLE_SIZE // VkDeviceSize size + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, &buffer_memory_barrier, 0, nullptr ); + + vkEndCommandBuffer( command_buffer ); + + // Submit command buffer and copy data from staging buffer to a vertex buffer + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // uint32_t waitSemaphoreCount + nullptr, // const VkSemaphore *pWaitSemaphores + nullptr, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + &command_buffer, // const VkCommandBuffer *pCommandBuffers + 0, // uint32_t signalSemaphoreCount + nullptr // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) { + return false; + } + + vkDeviceWaitIdle( GetDevice() ); + + return true; + } + + bool Tutorial07::PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ) { + if( !CreateFramebuffer( framebuffer, image_parameters.View ) ) { + return false; + } + + VkCommandBufferBeginInfo command_buffer_begin_info = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags + nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo + }; + + vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info ); + + VkImageSubresourceRange image_subresource_range = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + uint32_t present_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetPresentQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED; + uint32_t graphics_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetGraphicsQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED; + VkImageMemoryBarrier barrier_from_present_to_draw = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout + present_queue_family_index, // uint32_t srcQueueFamilyIndex + graphics_queue_family_index, // uint32_t dstQueueFamilyIndex + image_parameters.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw ); + + VkClearValue clear_value = { + { 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color + }; + + VkRenderPassBeginInfo render_pass_begin_info = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType + nullptr, // const void *pNext + Vulkan.RenderPass, // VkRenderPass renderPass + framebuffer, // VkFramebuffer framebuffer + { // VkRect2D renderArea + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + GetSwapChain().Extent, // VkExtent2D extent; + }, + 1, // uint32_t clearValueCount + &clear_value // const VkClearValue *pClearValues + }; + + vkCmdBeginRenderPass( command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE ); + + vkCmdBindPipeline( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline ); + + VkViewport viewport = { + 0.0f, // float x + 0.0f, // float y + static_cast(GetSwapChain().Extent.width), // float width + static_cast(GetSwapChain().Extent.height), // float height + 0.0f, // float minDepth + 1.0f // float maxDepth + }; + + VkRect2D scissor = { + { // VkOffset2D offset + 0, // int32_t x + 0 // int32_t y + }, + { // VkExtent2D extent + GetSwapChain().Extent.width, // uint32_t width + GetSwapChain().Extent.height // uint32_t height + } + }; + + vkCmdSetViewport( command_buffer, 0, 1, &viewport ); + vkCmdSetScissor( command_buffer, 0, 1, &scissor ); + + VkDeviceSize offset = 0; + vkCmdBindVertexBuffers( command_buffer, 0, 1, &Vulkan.VertexBuffer.Handle, &offset ); + + vkCmdBindDescriptorSets( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.PipelineLayout, 0, 1, &Vulkan.DescriptorSet.Handle, 0, nullptr ); + + vkCmdDraw( command_buffer, 4, 1, 0, 0 ); + + vkCmdEndRenderPass( command_buffer ); + + VkImageMemoryBarrier barrier_from_draw_to_present = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void *pNext + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask + VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout + graphics_queue_family_index, // uint32_t srcQueueFamilyIndex + present_queue_family_index, // uint32_t dstQueueFamilyIndex + image_parameters.Handle, // VkImage image + image_subresource_range // VkImageSubresourceRange subresourceRange + }; + vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present ); + + if( vkEndCommandBuffer( command_buffer ) != VK_SUCCESS ) { + std::cout << "Could not record command buffer!" << std::endl; + return false; + } + return true; + } + + bool Tutorial07::CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ) { + if( framebuffer != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( GetDevice(), framebuffer, nullptr ); + framebuffer = VK_NULL_HANDLE; + } + + VkFramebufferCreateInfo framebuffer_create_info = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkFramebufferCreateFlags flags + Vulkan.RenderPass, // VkRenderPass renderPass + 1, // uint32_t attachmentCount + &image_view, // const VkImageView *pAttachments + GetSwapChain().Extent.width, // uint32_t width + GetSwapChain().Extent.height, // uint32_t height + 1 // uint32_t layers + }; + + if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &framebuffer ) != VK_SUCCESS ) { + std::cout << "Could not create a framebuffer!" << std::endl; + return false; + } + + return true; + } + + bool Tutorial07::ChildOnWindowSizeChanged() { + if( (GetDevice() != VK_NULL_HANDLE) && + (Vulkan.StagingBuffer.Handle != VK_NULL_HANDLE) ) { + vkDeviceWaitIdle( GetDevice() ); + return CopyUniformBufferData(); + } + return true; + } + + bool Tutorial07::Draw() { + static size_t resource_index = 0; + RenderingResourcesData ¤t_rendering_resource = Vulkan.RenderingResources[resource_index]; + VkSwapchainKHR swap_chain = GetSwapChain().Handle; + uint32_t image_index; + + resource_index = (resource_index + 1) % VulkanTutorial07Parameters::ResourcesCount; + + if( vkWaitForFences( GetDevice(), 1, ¤t_rendering_resource.Fence, VK_FALSE, 1000000000 ) != VK_SUCCESS ) { + std::cout << "Waiting for fence takes too long!" << std::endl; + return false; + } + vkResetFences( GetDevice(), 1, ¤t_rendering_resource.Fence ); + + VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, current_rendering_resource.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index ); + switch( result ) { + case VK_SUCCESS: + case VK_SUBOPTIMAL_KHR: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during swap chain image acquisition!" << std::endl; + return false; + } + + if( !PrepareFrame( current_rendering_resource.CommandBuffer, GetSwapChain().Images[image_index], current_rendering_resource.Framebuffer ) ) { + return false; + } + + VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submit_info = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + ¤t_rendering_resource.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores + &wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask; + 1, // uint32_t commandBufferCount + ¤t_rendering_resource.CommandBuffer, // const VkCommandBuffer *pCommandBuffers + 1, // uint32_t signalSemaphoreCount + ¤t_rendering_resource.FinishedRenderingSemaphore // const VkSemaphore *pSignalSemaphores + }; + + if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, current_rendering_resource.Fence ) != VK_SUCCESS ) { + return false; + } + + VkPresentInfoKHR present_info = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType + nullptr, // const void *pNext + 1, // uint32_t waitSemaphoreCount + ¤t_rendering_resource.FinishedRenderingSemaphore, // const VkSemaphore *pWaitSemaphores + 1, // uint32_t swapchainCount + &swap_chain, // const VkSwapchainKHR *pSwapchains + &image_index, // const uint32_t *pImageIndices + nullptr // VkResult *pResults + }; + result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info ); + + switch( result ) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_SUBOPTIMAL_KHR: + return OnWindowSizeChanged(); + default: + std::cout << "Problem occurred during image presentation!" << std::endl; + return false; + } + + return true; + } + + void Tutorial07::ChildClear() { + } + + Tutorial07::~Tutorial07() { + if( GetDevice() != VK_NULL_HANDLE ) { + vkDeviceWaitIdle( GetDevice() ); + + for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) { + if( Vulkan.RenderingResources[i].Framebuffer != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( GetDevice(), Vulkan.RenderingResources[i].Framebuffer, nullptr ); + } + if( Vulkan.RenderingResources[i].CommandBuffer != VK_NULL_HANDLE ) { + vkFreeCommandBuffers( GetDevice(), Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ); + } + if( Vulkan.RenderingResources[i].ImageAvailableSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].ImageAvailableSemaphore, nullptr ); + } + if( Vulkan.RenderingResources[i].FinishedRenderingSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].FinishedRenderingSemaphore, nullptr ); + } + if( Vulkan.RenderingResources[i].Fence != VK_NULL_HANDLE ) { + vkDestroyFence( GetDevice(), Vulkan.RenderingResources[i].Fence, nullptr ); + } + } + + if( Vulkan.CommandPool != VK_NULL_HANDLE ) { + vkDestroyCommandPool( GetDevice(), Vulkan.CommandPool, nullptr ); + Vulkan.CommandPool = VK_NULL_HANDLE; + } + + DestroyBuffer( Vulkan.VertexBuffer ); + + DestroyBuffer( Vulkan.StagingBuffer ); + + if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) { + vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr ); + Vulkan.GraphicsPipeline = VK_NULL_HANDLE; + } + + if( Vulkan.PipelineLayout != VK_NULL_HANDLE ) { + vkDestroyPipelineLayout( GetDevice(), Vulkan.PipelineLayout, nullptr ); + Vulkan.PipelineLayout = VK_NULL_HANDLE; + } + + if( Vulkan.RenderPass != VK_NULL_HANDLE ) { + vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr ); + Vulkan.RenderPass = VK_NULL_HANDLE; + } + + if( Vulkan.DescriptorSet.Pool != VK_NULL_HANDLE ) { + vkDestroyDescriptorPool( GetDevice(), Vulkan.DescriptorSet.Pool, nullptr ); + Vulkan.DescriptorSet.Pool = VK_NULL_HANDLE; + } + + if( Vulkan.DescriptorSet.Layout != VK_NULL_HANDLE ) { + vkDestroyDescriptorSetLayout( GetDevice(), Vulkan.DescriptorSet.Layout, nullptr ); + Vulkan.DescriptorSet.Layout = VK_NULL_HANDLE; + } + + DestroyBuffer( Vulkan.UniformBuffer ); + + if( Vulkan.Image.Sampler != VK_NULL_HANDLE ) { + vkDestroySampler( GetDevice(), Vulkan.Image.Sampler, nullptr ); + Vulkan.Image.Sampler = VK_NULL_HANDLE; + } + + if( Vulkan.Image.View != VK_NULL_HANDLE ) { + vkDestroyImageView( GetDevice(), Vulkan.Image.View, nullptr ); + Vulkan.Image.View = VK_NULL_HANDLE; + } + + if( Vulkan.Image.Handle != VK_NULL_HANDLE ) { + vkDestroyImage( GetDevice(), Vulkan.Image.Handle, nullptr ); + Vulkan.Image.Handle = VK_NULL_HANDLE; + } + + if( Vulkan.Image.Memory != VK_NULL_HANDLE ) { + vkFreeMemory( GetDevice(), Vulkan.Image.Memory, nullptr ); + Vulkan.Image.Memory = VK_NULL_HANDLE; + } + } + } + + void Tutorial07::DestroyBuffer( BufferParameters& buffer ) { + if( buffer.Handle != VK_NULL_HANDLE ) { + vkDestroyBuffer( GetDevice(), buffer.Handle, nullptr ); + buffer.Handle = VK_NULL_HANDLE; + } + + if( buffer.Memory != VK_NULL_HANDLE ) { + vkFreeMemory( GetDevice(), buffer.Memory, nullptr ); + buffer.Memory = VK_NULL_HANDLE; + } + } + +} // namespace ApiWithoutSecrets diff --git a/Project/Tutorial07/Tutorial07.h b/Project/Tutorial07/Tutorial07.h index 27b264b..571bfe8 100644 --- a/Project/Tutorial07/Tutorial07.h +++ b/Project/Tutorial07/Tutorial07.h @@ -1,177 +1,177 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(TUTORIAL_07_HEADER) -#define TUTORIAL_07_HEADER - -#include "VulkanCommon.h" -#include "Tools.h" - -namespace ApiWithoutSecrets { - - // ************************************************************ // - // BufferParameters // - // // - // Vulkan Buffer's parameters container class // - // ************************************************************ // - struct BufferParameters { - VkBuffer Handle; - VkDeviceMemory Memory; - uint32_t Size; - - BufferParameters() : - Handle( VK_NULL_HANDLE ), - Memory( VK_NULL_HANDLE ), - Size( 0 ) { - } - }; - - // ************************************************************ // - // DescriptorParameters // - // // - // Container class for descriptor related resources // - // ************************************************************ // - struct DescriptorSetParameters { - VkDescriptorPool Pool; - VkDescriptorSetLayout Layout; - VkDescriptorSet Handle; - - DescriptorSetParameters() : - Pool( VK_NULL_HANDLE ), - Layout( VK_NULL_HANDLE ), - Handle( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // VertexData // - // // - // Struct describing data type and format of vertex attributes // - // ************************************************************ // - struct VertexData { - float x, y, z, w; - float u, v; - }; - - // ************************************************************ // - // RenderingResourcesData // - // // - // Struct containing data used during rendering process // - // ************************************************************ // - struct RenderingResourcesData { - VkFramebuffer Framebuffer; - VkCommandBuffer CommandBuffer; - VkSemaphore ImageAvailableSemaphore; - VkSemaphore FinishedRenderingSemaphore; - VkFence Fence; - - RenderingResourcesData() : - Framebuffer( VK_NULL_HANDLE ), - CommandBuffer( VK_NULL_HANDLE ), - ImageAvailableSemaphore( VK_NULL_HANDLE ), - FinishedRenderingSemaphore( VK_NULL_HANDLE ), - Fence( VK_NULL_HANDLE ) { - } - }; - - // ************************************************************ // - // VulkanTutorial04Parameters // - // // - // Vulkan specific parameters // - // ************************************************************ // - struct VulkanTutorial07Parameters { - VkRenderPass RenderPass; - ImageParameters Image; - BufferParameters UniformBuffer; - DescriptorSetParameters DescriptorSet; - VkPipelineLayout PipelineLayout; - VkPipeline GraphicsPipeline; - BufferParameters VertexBuffer; - BufferParameters StagingBuffer; - VkCommandPool CommandPool; - std::vector RenderingResources; - - static const size_t ResourcesCount = 3; - - VulkanTutorial07Parameters() : - RenderPass( VK_NULL_HANDLE ), - Image(), - DescriptorSet(), - PipelineLayout(), - GraphicsPipeline( VK_NULL_HANDLE ), - VertexBuffer(), - StagingBuffer(), - CommandPool( VK_NULL_HANDLE ), - RenderingResources( ResourcesCount ) { - } - }; - - // ************************************************************ // - // Tutorial04 // - // // - // Class for presenting Vulkan usage topics // - // ************************************************************ // - class Tutorial07 : public VulkanCommon { - public: - Tutorial07(); - ~Tutorial07(); - - bool CreateRenderingResources(); - bool CreateStagingBuffer(); - bool CreateTexture(); - bool CreateUniformBuffer(); - bool CreateDescriptorSetLayout(); - bool CreateDescriptorPool(); - bool AllocateDescriptorSet(); - bool UpdateDescriptorSet(); - bool CreateRenderPass(); - bool CreatePipelineLayout(); - bool CreatePipeline(); - bool CreateVertexBuffer(); - - bool Draw() override; - - private: - VulkanTutorial07Parameters Vulkan; - - bool CreateCommandBuffers(); - bool CreateCommandPool(uint32_t queue_family_index, VkCommandPool *pool); - bool AllocateCommandBuffers(VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers); - bool CreateSemaphores(); - bool CreateFences(); - bool CreateBuffer(VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer); - bool AllocateBufferMemory(VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory); - bool CreateImage( uint32_t width, uint32_t height, VkImage *image ); - bool AllocateImageMemory( VkImage image, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ); - bool CreateImageView( ImageParameters &image_parameters ); - bool CreateSampler( VkSampler *sampler ); - bool CopyTextureData( char *texture_data, uint32_t data_size, uint32_t width, uint32_t height ); - const std::array GetUniformBufferData() const; - bool CopyUniformBufferData(); - Tools::AutoDeleter CreateShaderModule( const char* filename ); - const std::vector& GetVertexData() const; - bool CopyVertexData(); - bool PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ); - bool CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ); - void DestroyBuffer( BufferParameters& buffer ); - - bool ChildOnWindowSizeChanged() override; - void ChildClear() override; - }; - -} // namespace ApiWithoutSecrets - +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(TUTORIAL_07_HEADER) +#define TUTORIAL_07_HEADER + +#include "VulkanCommon.h" +#include "Tools.h" + +namespace ApiWithoutSecrets { + + // ************************************************************ // + // BufferParameters // + // // + // Vulkan Buffer's parameters container class // + // ************************************************************ // + struct BufferParameters { + VkBuffer Handle; + VkDeviceMemory Memory; + uint32_t Size; + + BufferParameters() : + Handle( VK_NULL_HANDLE ), + Memory( VK_NULL_HANDLE ), + Size( 0 ) { + } + }; + + // ************************************************************ // + // DescriptorParameters // + // // + // Container class for descriptor related resources // + // ************************************************************ // + struct DescriptorSetParameters { + VkDescriptorPool Pool; + VkDescriptorSetLayout Layout; + VkDescriptorSet Handle; + + DescriptorSetParameters() : + Pool( VK_NULL_HANDLE ), + Layout( VK_NULL_HANDLE ), + Handle( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // VertexData // + // // + // Struct describing data type and format of vertex attributes // + // ************************************************************ // + struct VertexData { + float x, y, z, w; + float u, v; + }; + + // ************************************************************ // + // RenderingResourcesData // + // // + // Struct containing data used during rendering process // + // ************************************************************ // + struct RenderingResourcesData { + VkFramebuffer Framebuffer; + VkCommandBuffer CommandBuffer; + VkSemaphore ImageAvailableSemaphore; + VkSemaphore FinishedRenderingSemaphore; + VkFence Fence; + + RenderingResourcesData() : + Framebuffer( VK_NULL_HANDLE ), + CommandBuffer( VK_NULL_HANDLE ), + ImageAvailableSemaphore( VK_NULL_HANDLE ), + FinishedRenderingSemaphore( VK_NULL_HANDLE ), + Fence( VK_NULL_HANDLE ) { + } + }; + + // ************************************************************ // + // VulkanTutorial04Parameters // + // // + // Vulkan specific parameters // + // ************************************************************ // + struct VulkanTutorial07Parameters { + VkRenderPass RenderPass; + ImageParameters Image; + BufferParameters UniformBuffer; + DescriptorSetParameters DescriptorSet; + VkPipelineLayout PipelineLayout; + VkPipeline GraphicsPipeline; + BufferParameters VertexBuffer; + BufferParameters StagingBuffer; + VkCommandPool CommandPool; + std::vector RenderingResources; + + static const size_t ResourcesCount = 3; + + VulkanTutorial07Parameters() : + RenderPass( VK_NULL_HANDLE ), + Image(), + DescriptorSet(), + PipelineLayout(), + GraphicsPipeline( VK_NULL_HANDLE ), + VertexBuffer(), + StagingBuffer(), + CommandPool( VK_NULL_HANDLE ), + RenderingResources( ResourcesCount ) { + } + }; + + // ************************************************************ // + // Tutorial04 // + // // + // Class for presenting Vulkan usage topics // + // ************************************************************ // + class Tutorial07 : public VulkanCommon { + public: + Tutorial07(); + ~Tutorial07(); + + bool CreateRenderingResources(); + bool CreateStagingBuffer(); + bool CreateTexture(); + bool CreateUniformBuffer(); + bool CreateDescriptorSetLayout(); + bool CreateDescriptorPool(); + bool AllocateDescriptorSet(); + bool UpdateDescriptorSet(); + bool CreateRenderPass(); + bool CreatePipelineLayout(); + bool CreatePipeline(); + bool CreateVertexBuffer(); + + bool Draw() override; + + private: + VulkanTutorial07Parameters Vulkan; + + bool CreateCommandBuffers(); + bool CreateCommandPool(uint32_t queue_family_index, VkCommandPool *pool); + bool AllocateCommandBuffers(VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers); + bool CreateSemaphores(); + bool CreateFences(); + bool CreateBuffer(VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer); + bool AllocateBufferMemory(VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory); + bool CreateImage( uint32_t width, uint32_t height, VkImage *image ); + bool AllocateImageMemory( VkImage image, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ); + bool CreateImageView( ImageParameters &image_parameters ); + bool CreateSampler( VkSampler *sampler ); + bool CopyTextureData( char *texture_data, uint32_t data_size, uint32_t width, uint32_t height ); + const std::array GetUniformBufferData() const; + bool CopyUniformBufferData(); + Tools::AutoDeleter CreateShaderModule( const char* filename ); + const std::vector& GetVertexData() const; + bool CopyVertexData(); + bool PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ); + bool CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ); + void DestroyBuffer( BufferParameters& buffer ); + + bool ChildOnWindowSizeChanged() override; + void ChildClear() override; + }; + +} // namespace ApiWithoutSecrets + #endif // TUTORIAL_07_HEADER \ No newline at end of file diff --git a/Project/Tutorial07/main.cpp b/Project/Tutorial07/main.cpp index 5d38b62..0cf2df1 100644 --- a/Project/Tutorial07/main.cpp +++ b/Project/Tutorial07/main.cpp @@ -1,77 +1,77 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Intel Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. -//////////////////////////////////////////////////////////////////////////////// - -#include "Tutorial07.h" - -int main( int argc, char **argv ) { - ApiWithoutSecrets::OS::Window window; - ApiWithoutSecrets::Tutorial07 tutorial07; - - // Window creation - if( !window.Create( "07 - Uniform Buffers" ) ) { - return -1; - } - - // Vulkan preparations and initialization - if( !tutorial07.PrepareVulkan( window.GetParameters() ) ) { - return -1; - } - - // Tutorial 06 - if( !tutorial07.CreateRenderingResources() ) { - return -1; - } - if( !tutorial07.CreateStagingBuffer() ) { - return -1; - } - if( !tutorial07.CreateTexture() ) { - return -1; - } - if( !tutorial07.CreateUniformBuffer() ) { - return -1; - } - if( !tutorial07.CreateDescriptorSetLayout() ) { - return -1; - } - if( !tutorial07.CreateDescriptorPool() ) { - return -1; - } - if( !tutorial07.AllocateDescriptorSet() ) { - return -1; - } - if( !tutorial07.UpdateDescriptorSet() ) { - return -1; - } - if( !tutorial07.CreateRenderPass() ) { - return -1; - } - if( !tutorial07.CreatePipelineLayout() ) { - return -1; - } - if( !tutorial07.CreatePipeline() ) { - return -1; - } - if( !tutorial07.CreateVertexBuffer() ) { - return -1; - } - - // Rendering loop - if( !window.RenderingLoop( tutorial07 ) ) { - return -1; - } - - return 0; -} +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "Tutorial07.h" + +int main( int argc, char **argv ) { + ApiWithoutSecrets::OS::Window window; + ApiWithoutSecrets::Tutorial07 tutorial07; + + // Window creation + if( !window.Create( "07 - Uniform Buffers" ) ) { + return -1; + } + + // Vulkan preparations and initialization + if( !tutorial07.PrepareVulkan( window.GetParameters() ) ) { + return -1; + } + + // Tutorial 06 + if( !tutorial07.CreateRenderingResources() ) { + return -1; + } + if( !tutorial07.CreateStagingBuffer() ) { + return -1; + } + if( !tutorial07.CreateTexture() ) { + return -1; + } + if( !tutorial07.CreateUniformBuffer() ) { + return -1; + } + if( !tutorial07.CreateDescriptorSetLayout() ) { + return -1; + } + if( !tutorial07.CreateDescriptorPool() ) { + return -1; + } + if( !tutorial07.AllocateDescriptorSet() ) { + return -1; + } + if( !tutorial07.UpdateDescriptorSet() ) { + return -1; + } + if( !tutorial07.CreateRenderPass() ) { + return -1; + } + if( !tutorial07.CreatePipelineLayout() ) { + return -1; + } + if( !tutorial07.CreatePipeline() ) { + return -1; + } + if( !tutorial07.CreateVertexBuffer() ) { + return -1; + } + + // Rendering loop + if( !window.RenderingLoop( tutorial07 ) ) { + return -1; + } + + return 0; +} diff --git a/Project/compile_shaders.bat b/Project/compile_shaders.bat index ae40bba..1308f2a 100644 --- a/Project/compile_shaders.bat +++ b/Project/compile_shaders.bat @@ -1,42 +1,42 @@ -@ECHO OFF -SETLOCAL - -REM ///////////////////////////////////////////////////////////////////////////////////////////// -REM // Copyright 2017 Intel Corporation -REM // -REM // Licensed under the Apache License, Version 2.0 (the "License"); REM // you may not use this file except in compliance with the License. REM // You may obtain a copy of the License at REM // REM // http://www.apache.org/licenses/LICENSE-2.0 REM // REM // Unless required by applicable law or agreed to in writing, software REM // distributed under the License is distributed on an "AS IS" BASIS, REM // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. REM // See the License for the specific language governing permissions and REM // limitations under the License. -REM ///////////////////////////////////////////////////////////////////////////////////////////// - -if [%1] == [] ( - echo No arguments provided! Please specify folder number. - echo Example usage: compile_shaders.bat 03 - goto end -) - -if exist glslangValidator.exe ( - goto convert -) -for %%X in (glslangValidator.exe) do (set glslangValidator=%%~$PATH:X) -if defined glslangValidator ( - goto convert -) - -echo Could not find "glslangValidator.exe" file. -goto end - -:convert - -set folder=Tutorial%1/Data%1 -echo Converting GLSL shaders into SPIR-V assembly in the "%folder%" folder. - -if exist %folder%/shader.vert ( - glslangValidator.exe -V -H -o %folder%/vert.spv %folder%/shader.vert > %folder%/vert.spv.txt -) - -if exist %folder%/shader.frag ( - glslangValidator.exe -V -H -o %folder%/frag.spv %folder%/shader.frag > %folder%/frag.spv.txt -) - -:end - +@ECHO OFF +SETLOCAL + +REM ///////////////////////////////////////////////////////////////////////////////////////////// +REM // Copyright 2017 Intel Corporation +REM // +REM // Licensed under the Apache License, Version 2.0 (the "License"); REM // you may not use this file except in compliance with the License. REM // You may obtain a copy of the License at REM // REM // http://www.apache.org/licenses/LICENSE-2.0 REM // REM // Unless required by applicable law or agreed to in writing, software REM // distributed under the License is distributed on an "AS IS" BASIS, REM // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. REM // See the License for the specific language governing permissions and REM // limitations under the License. +REM ///////////////////////////////////////////////////////////////////////////////////////////// + +if [%1] == [] ( + echo No arguments provided! Please specify folder number. + echo Example usage: compile_shaders.bat 03 + goto end +) + +if exist glslangValidator.exe ( + goto convert +) +for %%X in (glslangValidator.exe) do (set glslangValidator=%%~$PATH:X) +if defined glslangValidator ( + goto convert +) + +echo Could not find "glslangValidator.exe" file. +goto end + +:convert + +set folder=Tutorial%1/Data%1 +echo Converting GLSL shaders into SPIR-V assembly in the "%folder%" folder. + +if exist %folder%/shader.vert ( + glslangValidator.exe -V -H -o %folder%/vert.spv %folder%/shader.vert > %folder%/vert.spv.txt +) + +if exist %folder%/shader.frag ( + glslangValidator.exe -V -H -o %folder%/frag.spv %folder%/shader.frag > %folder%/frag.spv.txt +) + +:end + ENDLOCAL \ No newline at end of file