Files
IntroductionToVulkan/Project/Tutorial01/Tutorial01.cpp
plapins 766e3f76d6 Added license.txt file.
Added Project folder with source code examples Part 1, Part 2, Part 3 and Part 4.
2016-03-14 20:21:47 +01:00

276 lines
11 KiB
C++

// Copyright 2016 Intel Corporation All Rights Reserved
//
// Intel makes no representations about the suitability of this software for any purpose.
// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
// Intel does not assume any responsibility for any errors which may appear in this software
// nor any responsibility to update it.
#include <vector>
#include "Tutorial01.h"
#include "VulkanFunctions.h"
namespace Tutorial {
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", RTLD_NOW );
#endif
if( VulkanLibrary == nullptr ) {
printf( "Could not load Vulkan library!\n" );
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 )) ) { \
printf( "Could not load exported function: " #fun "!\n" ); \
return false; \
}
#include "ListOfFunctions.inl"
return true;
}
bool Tutorial01::LoadGlobalLevelEntryPoints() {
#define VK_GLOBAL_LEVEL_FUNCTION( fun ) \
if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( nullptr, #fun )) ) { \
printf( "Could not load global level function: " #fun "!\n" ); \
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_API_VERSION // 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 ) {
printf( "Could not create Vulkan instance!\n" );
return false;
}
return true;
}
bool Tutorial01::LoadInstanceLevelEntryPoints() {
#define VK_INSTANCE_LEVEL_FUNCTION( fun ) \
if( !(fun = (PFN_##fun)vkGetInstanceProcAddr( Vulkan.Instance, #fun )) ) { \
printf( "Could not load instance level function: " #fun "\n" ); \
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) ) {
printf( "Error occurred during physical devices enumeration!\n" );
return false;
}
std::vector<VkPhysicalDevice> physical_devices( num_devices );
if( vkEnumeratePhysicalDevices( Vulkan.Instance, &num_devices, &physical_devices[0] ) != VK_SUCCESS ) {
printf( "Error occurred during physical devices enumeration!\n" );
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];
}
}
if( selected_physical_device == VK_NULL_HANDLE ) {
printf( "Could not select physical device based on the chosen properties!\n" );
return false;
}
std::vector<float> 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<uint32_t>(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 ) {
printf( "Could not create Vulkan device!\n" );
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) ) {
printf( "Physical device %p doesn't support required parameters!\n", physical_device );
return false;
}
uint32_t queue_families_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr );
if( queue_families_count == 0 ) {
printf( "Physical device %p doesn't have any queue families!\n", physical_device );
return false;
}
std::vector<VkQueueFamilyProperties> 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;
return true;
}
}
printf( "Could not find queue family with required properties on physical device %p!\n", physical_device );
return false;
}
bool Tutorial01::LoadDeviceLevelEntryPoints() {
#define VK_DEVICE_LEVEL_FUNCTION( fun ) \
if( !(fun = (PFN_##fun)vkGetDeviceProcAddr( Vulkan.Device, #fun )) ) { \
printf( "Could not load device level function: " #fun "!\n" ); \
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 Tutorial