void Renderer::checkDeviceProperties(VkPhysicalDevice gpu) {
    VkPhysicalDeviceProperties properties;
    VkPhysicalDeviceFeatures features;

    vkGetPhysicalDeviceProperties(gpu, &properties);
    vkGetPhysicalDeviceFeatures(gpu, &features);

    printf("%s\n", properties.deviceName);
    printf("Vulkan Version: %d.%d.%d\n",
           VK_VERSION_MAJOR(properties.apiVersion),
           VK_VERSION_MINOR(properties.apiVersion),
           VK_VERSION_PATCH(properties.apiVersion));
    printf("Driver Version: %d.%d.%d\n\n",
           VK_VERSION_MAJOR(properties.driverVersion),
           VK_VERSION_MINOR(properties.driverVersion),
           VK_VERSION_PATCH(properties.driverVersion));
}
  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<VkQueueFamilyProperties> queue_family_properties( queue_families_count );
    vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, queue_family_properties.data() );
    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;
  }
Exemple #3
0
void vulkan_choose_physical_device(ReaperRoot& root, VulkanBackend& backend, PhysicalDeviceInfo& physicalDeviceInfo)
{
    uint32_t deviceCount = 0;

    Assert(vkEnumeratePhysicalDevices(backend.instance, &deviceCount, nullptr) == VK_SUCCESS);
    Assert(deviceCount > 0);

    log_debug(root, "vulkan: enumerating {} physical devices", deviceCount);

    std::vector<VkPhysicalDevice> availableDevices(deviceCount);
    Assert(vkEnumeratePhysicalDevices(backend.instance, &deviceCount, &availableDevices[0]) == VK_SUCCESS,
           "error occurred during physical devices enumeration");

    uint32_t selected_queue_family_index = UINT32_MAX;
    uint32_t selected_present_queue_family_index = UINT32_MAX;

    // Duplicated two times TODO merge
    std::vector<const char*> extensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};

    VkPhysicalDevice chosenPhysicalDevice = VK_NULL_HANDLE;
    for (auto& device : availableDevices)
    {
        if (vulkan_check_physical_device(root.renderer->window,
                                         device,
                                         backend.presentInfo.surface,
                                         extensions,
                                         selected_queue_family_index,
                                         selected_present_queue_family_index))
        {
            chosenPhysicalDevice = device;
            break;
        }
    }

    Assert(chosenPhysicalDevice != VK_NULL_HANDLE, "could not select physical device based on the chosen properties");

    physicalDeviceInfo.graphicsQueueIndex = selected_queue_family_index;
    physicalDeviceInfo.presentQueueIndex = selected_present_queue_family_index;

    vkGetPhysicalDeviceMemoryProperties(chosenPhysicalDevice, &physicalDeviceInfo.memory);

    // re-fetch device infos TODO avoid
    VkPhysicalDeviceProperties physicalDeviceProperties;
    vkGetPhysicalDeviceProperties(chosenPhysicalDevice, &physicalDeviceProperties);

    log_info(root, "vulkan: selecting device '{}'", physicalDeviceProperties.deviceName);
    log_debug(root, "- type = {}", vulkan_physical_device_type_name(physicalDeviceProperties.deviceType));

    uint32_t apiVersion = physicalDeviceProperties.apiVersion;
    uint32_t driverVersion = physicalDeviceProperties.driverVersion;
    log_debug(root,
              "- api version = {}.{}.{}",
              VK_VERSION_MAJOR(apiVersion),
              VK_VERSION_MINOR(apiVersion),
              VK_VERSION_PATCH(apiVersion));
    log_debug(root,
              "- driver version = {}.{}.{}",
              VK_VERSION_MAJOR(driverVersion),
              VK_VERSION_MINOR(driverVersion),
              VK_VERSION_PATCH(driverVersion));

    log_debug(root,
              "- memory type count = {}, memory heap count = {}",
              physicalDeviceInfo.memory.memoryTypeCount,
              physicalDeviceInfo.memory.memoryHeapCount);

    for (u32 i = 0; i < physicalDeviceInfo.memory.memoryHeapCount; ++i)
    {
        VkMemoryHeap& heap = physicalDeviceInfo.memory.memoryHeaps[i];
        log_debug(root, "- heap {}: available size = {}, flags = {}", i, heap.size, heap.flags);
    }

    backend.physicalDevice = chosenPhysicalDevice;
}
Exemple #4
0
VkResult init_Vulkan(VkInstance& vk_instance, VkDevice* out_device, DrawCommandBuffer* out_draw_command_buffer, SwapChain* out_swap_chain)
{
    if ((out_device == nullptr) || (out_swap_chain == nullptr))
    {
        return VK_ERROR_INITIALIZATION_FAILED;
    }
    VkApplicationInfo app_info = {};
    app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    app_info.pNext = nullptr;
    app_info.pApplicationName = "VT Test";
    app_info.applicationVersion = 0x00000001;
    app_info.pEngineName = "Noengine";
    app_info.engineVersion = 0x00;
    app_info.apiVersion = VK_MAKE_VERSION(1, 0, 2);

    std::vector<const char *> enabledExtensions = { VK_KHR_SURFACE_EXTENSION_NAME };
    enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);

    VkInstanceCreateInfo instance_info = {};
    instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instance_info.pNext = nullptr;
    instance_info.flags = 0;
    instance_info.pApplicationInfo = &app_info;
    instance_info.enabledLayerCount = 0;
    instance_info.ppEnabledLayerNames = nullptr;
    instance_info.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
    instance_info.ppEnabledExtensionNames = enabledExtensions.data();

    VK_THROW(vkCreateInstance(&instance_info, nullptr, &vk_instance)); // Create Vulkan library instance

    out_swap_chain->instance = GetModuleHandle(NULL);
    out_swap_chain->window = setup_window(out_swap_chain->instance, 800, 600, "vk_test");

    uint32_t gpu_count = 0;
    // Get number of available physical devices
    VK_THROW(vkEnumeratePhysicalDevices(vk_instance, &gpu_count, nullptr));
    assert(gpu_count > 0);

    std::vector<VkPhysicalDevice> physicalDevices(gpu_count); // Enumerate devices
    VK_THROW(vkEnumeratePhysicalDevices(vk_instance, &gpu_count, physicalDevices.data()));
    bool surface_created = false;
    VkPhysicalDeviceProperties gpu_properties;
    VkPhysicalDeviceFeatures gpu_feature;
    for (uint32_t gidx = 0; gidx < gpu_count; ++gidx)
    {
        VkPhysicalDevice gpu = physicalDevices[gidx];
        vkGetPhysicalDeviceProperties(gpu, &gpu_properties);
        std::cout << gidx << "Driver Version: " << gpu_properties.driverVersion << "\n";
        std::cout << gidx << "Device Name:    " << gpu_properties.deviceName << "\n";
        std::cout << gidx << "Device Type:    " << gpu_properties.deviceType << "\n";
        std::cout << gidx << "API Version:    " << VK_VERSION_MAJOR(gpu_properties.apiVersion) << "." << VK_VERSION_MINOR(gpu_properties.apiVersion) << "." << VK_VERSION_PATCH(gpu_properties.apiVersion) << "\n";

        // we can choose a gpu based on the features here.
        vkGetPhysicalDeviceFeatures(gpu, &gpu_feature);

        VkResult err = create_surface(vk_instance, gpu, out_device, out_draw_command_buffer, out_swap_chain);
        if (err == VK_SUCCESS)
        {
            surface_created = true;
            break;
        }
    }
    if (!surface_created)
    {
        return VK_ERROR_INITIALIZATION_FAILED;
    }

    return VK_SUCCESS;
}
bool initialize(android_app* app) {
  // Load Android vulkan and retrieve vulkan API function pointers
  if (!InitVulkan()) {
    LOGE("Vulkan is unavailable, install vulkan and re-start");
    return false;
  }

  VkApplicationInfo appInfo = {
      .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
      .pNext = nullptr,
      .apiVersion = VK_MAKE_VERSION(1, 0, 0),
      .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
      .engineVersion = VK_MAKE_VERSION(1, 0, 0),
      .pApplicationName = "tutorial01_load_vulkan",
      .pEngineName = "tutorial",
  };

  // prepare necessary extensions: Vulkan on Android need these to function
  std::vector<const char *> instanceExt, deviceExt;
  instanceExt.push_back("VK_KHR_surface");
  instanceExt.push_back("VK_KHR_android_surface");
  deviceExt.push_back("VK_KHR_swapchain");

  // Create the Vulkan instance
  VkInstanceCreateInfo instanceCreateInfo {
          .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
          .pNext = nullptr,
          .pApplicationInfo = &appInfo,
          .enabledExtensionCount = static_cast<uint32_t>(instanceExt.size()),
          .ppEnabledExtensionNames = instanceExt.data(),
          .enabledLayerCount = 0,
          .ppEnabledLayerNames = nullptr,
  };
  CALL_VK(vkCreateInstance(&instanceCreateInfo, nullptr, &tutorialInstance));

  // if we create a surface, we need the surface extension
  VkAndroidSurfaceCreateInfoKHR createInfo {
          .sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
          .pNext = nullptr,
          .flags = 0,
          .window = app->window };
  CALL_VK(vkCreateAndroidSurfaceKHR(tutorialInstance, &createInfo, nullptr,
                                    &tutorialSurface));

  // Find one GPU to use:
  // On Android, every GPU device is equal -- supporting graphics/compute/present
  // for this sample, we use the very first GPU device found on the system
  uint32_t  gpuCount = 0;
  CALL_VK(vkEnumeratePhysicalDevices(tutorialInstance, &gpuCount, nullptr));
  VkPhysicalDevice tmpGpus[gpuCount];
  CALL_VK(vkEnumeratePhysicalDevices(tutorialInstance, &gpuCount, tmpGpus));
  tutorialGpu = tmpGpus[0];     // Pick up the first GPU Device

  // check for vulkan info on this GPU device
  VkPhysicalDeviceProperties  gpuProperties;
  vkGetPhysicalDeviceProperties(tutorialGpu, &gpuProperties);
  LOGI("Vulkan Physical Device Name: %s", gpuProperties.deviceName);
  LOGI("Vulkan Physical Device Info: apiVersion: %x \n\t driverVersion: %x",
       gpuProperties.apiVersion, gpuProperties.driverVersion);
  LOGI("API Version Supported: %d.%d.%d",
           VK_VERSION_MAJOR(gpuProperties.apiVersion),
           VK_VERSION_MINOR(gpuProperties.apiVersion),
           VK_VERSION_PATCH(gpuProperties.apiVersion));

  VkSurfaceCapabilitiesKHR surfaceCapabilities;
  vkGetPhysicalDeviceSurfaceCapabilitiesKHR(tutorialGpu,
                                            tutorialSurface,
                                            &surfaceCapabilities);

  LOGI("Vulkan Surface Capabilities:\n");
  LOGI("\timage count: %u - %u\n", surfaceCapabilities.minImageCount,
       surfaceCapabilities.maxImageCount);
  LOGI("\tarray layers: %u\n", surfaceCapabilities.maxImageArrayLayers);
  LOGI("\timage size (now): %dx%d\n",
       surfaceCapabilities.currentExtent.width,
       surfaceCapabilities.currentExtent.height);
  LOGI("\timage size (extent): %dx%d - %dx%d\n",
       surfaceCapabilities.minImageExtent.width,
       surfaceCapabilities.minImageExtent.height,
       surfaceCapabilities.maxImageExtent.width,
       surfaceCapabilities.maxImageExtent.height);
  LOGI("\tusage: %x\n", surfaceCapabilities.supportedUsageFlags);
  LOGI("\tcurrent transform: %u\n", surfaceCapabilities.currentTransform);
  LOGI("\tallowed transforms: %x\n", surfaceCapabilities.supportedTransforms);
  LOGI("\tcomposite alpha flags: %u\n", surfaceCapabilities.currentTransform);

  // Create a logical device from GPU we picked
  float priorities[] = { 1.0f, };
  VkDeviceQueueCreateInfo queueCreateInfo {
          .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
          .pNext = nullptr,
          .flags = 0,
          .queueCount = 1,
          .queueFamilyIndex = 0,
          .pQueuePriorities = priorities,
  };

  VkDeviceCreateInfo deviceCreateInfo {
          .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
          .pNext = nullptr,
          .queueCreateInfoCount = 1,
          .pQueueCreateInfos = &queueCreateInfo,
          .enabledLayerCount = 0,
          .ppEnabledLayerNames = nullptr,
          .enabledExtensionCount = static_cast<uint32_t>(deviceExt.size()),
          .ppEnabledExtensionNames = deviceExt.data(),
          .pEnabledFeatures = nullptr,
  };

  CALL_VK(vkCreateDevice(tutorialGpu, &deviceCreateInfo, nullptr,
                         &tutorialDevice));
  initialized_ = true;
  return 0;
}

void terminate() {

  vkDestroySurfaceKHR(tutorialInstance, tutorialSurface, nullptr);
  vkDestroyDevice(tutorialDevice, nullptr);
  vkDestroyInstance(tutorialInstance, nullptr);

  initialized_ = false;
}

// Process the next main command.
void handle_cmd(android_app* app, int32_t cmd) {
  switch (cmd) {
    case APP_CMD_INIT_WINDOW:
      // The window is being shown, get it ready.
      initialize(app);
      break;
    case APP_CMD_TERM_WINDOW:
      // The window is being hidden or closed, clean it up.
      terminate();
      break;
    default:
      LOGI("event not handled: %d", cmd);
  }
}
Exemple #6
0
void SetupDevice()
{
	// Query how many devices are present in the system
	uint32_t deviceCount = 0;
	VkResult result;
	if( !vl.instance )
		SetupInstance();

	result = vkEnumeratePhysicalDevices( vl.instance, &deviceCount, NULL );
	if( result != VK_SUCCESS ) {
		fprintf( stderr, "Failed to query the number of physical devices present: %d", result );
		abort();
	}

	// There has to be at least one device present
	if( deviceCount == 0 ) {
		fprintf( stderr, "Couldn't detect any device present with Vulkan support: %d", result );
		abort();
	}

	// Get the physical devices
	vl.physicalDevices = NewArray( VkPhysicalDevice, deviceCount );

	result = vkEnumeratePhysicalDevices( vl.instance, &deviceCount, vl.physicalDevices );
	if( result != VK_SUCCESS ) {
		fprintf( stderr, "Faied to enumerate physical devices present: %d", result );
		abort();
	}

	{
		// Enumerate all physical devices
		VkPhysicalDeviceProperties deviceProperties;
		uint32_t i;
		for( i = 0; i < deviceCount; i++ ) {
			memset( &deviceProperties, 0, sizeof deviceProperties );
			vkGetPhysicalDeviceProperties( vl.physicalDevices[i], &deviceProperties );
			lprintf( "Driver Version: %d", deviceProperties.driverVersion );
			lprintf( "Device Name:    %s", deviceProperties.deviceName );
			lprintf( "Device Type:    %d", deviceProperties.deviceType );
			lprintf( "API Version:    %d.%d.%d"
				// See note below regarding this:
				, VK_VERSION_MAJOR( deviceProperties.apiVersion )
				, VK_VERSION_MINOR( deviceProperties.apiVersion )
				, VK_VERSION_PATCH( deviceProperties.apiVersion ) );
			{
				uint32_t queueFamilyCount = 0;
				uint32_t i , j;
				VkQueueFamilyProperties *familyProperties;
				vkGetPhysicalDeviceQueueFamilyProperties( vl.physicalDevices[i], &queueFamilyCount, NULL );
				familyProperties = NewArray( VkQueueFamilyProperties, (queueFamilyCount) );

				vkGetPhysicalDeviceQueueFamilyProperties( vl.physicalDevices[i], &queueFamilyCount, familyProperties );

				// Print the families
				for( i = 0; i < deviceCount; i++ ) {
					for( j = 0; j < queueFamilyCount; j++ ) {
						printf( "Count of Queues: %d", familyProperties[j].queueCount );
						printf( "Supported operationg on this queue:" );
						if( familyProperties[j].queueFlags & VK_QUEUE_GRAPHICS_BIT )
							lprintf( "\t\t Graphics" );
						if( familyProperties[j].queueFlags & VK_QUEUE_COMPUTE_BIT )
							lprintf( "\t\t Compute" );
						if( familyProperties[j].queueFlags & VK_QUEUE_TRANSFER_BIT )
							lprintf( "\t\t Transfer" );
						if( familyProperties[j].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT )
							lprintf( "\t\t Sparse Binding" );
					}
				}
			}
		}
	}
}
int sample_main(int argc, char *argv[]) {
    struct sample_info info = {};
    init_global_layer_properties(info);

// Android build not at 1.1 yet
#ifndef ANDROID

    /* VULKAN_KEY_START */

    // Keep track of the major/minor version we can actually use
    uint16_t using_major_version = 1;
    uint16_t using_minor_version = 0;
    std::string using_version_string = "";

    // Set the desired version we want
    uint16_t desired_major_version = 1;
    uint16_t desired_minor_version = 1;
    uint32_t desired_version = VK_MAKE_VERSION(desired_major_version, desired_minor_version, 0);
    std::string desired_version_string = "";
    desired_version_string += std::to_string(desired_major_version);
    desired_version_string += ".";
    desired_version_string += std::to_string(desired_minor_version);
    VkInstance instance = VK_NULL_HANDLE;
    std::vector<VkPhysicalDevice> physical_devices_desired;

    // Determine what API version is available
    uint32_t api_version;
    if (VK_SUCCESS == vkEnumerateInstanceVersion(&api_version)) {
        // Translate the version into major/minor for easier comparison
        uint32_t loader_major_version = VK_VERSION_MAJOR(api_version);
        uint32_t loader_minor_version = VK_VERSION_MINOR(api_version);
        std::cout << "Loader/Runtime support detected for Vulkan " << loader_major_version << "." << loader_minor_version << "\n";

        // Check current version against what we want to run
        if (loader_major_version > desired_major_version ||
            (loader_major_version == desired_major_version && loader_minor_version >= desired_minor_version)) {
            // Initialize the VkApplicationInfo structure with the version of the API we're intending to use
            VkApplicationInfo app_info = {};
            app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
            app_info.pNext = NULL;
            app_info.pApplicationName = APP_SHORT_NAME;
            app_info.applicationVersion = 1;
            app_info.pEngineName = APP_SHORT_NAME;
            app_info.engineVersion = 1;
            app_info.apiVersion = desired_version;

            // Initialize the VkInstanceCreateInfo structure
            VkInstanceCreateInfo inst_info = {};
            inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
            inst_info.pNext = NULL;
            inst_info.flags = 0;
            inst_info.pApplicationInfo = &app_info;
            inst_info.enabledExtensionCount = 0;
            inst_info.ppEnabledExtensionNames = NULL;
            inst_info.enabledLayerCount = 0;
            inst_info.ppEnabledLayerNames = NULL;

            // Attempt to create the instance
            if (VK_SUCCESS != vkCreateInstance(&inst_info, NULL, &instance)) {
                std::cout << "Unknown error creating " << desired_version_string << " Instance\n";
                exit(-1);
            }

            // Get the list of physical devices
            uint32_t phys_dev_count = 1;
            if (VK_SUCCESS != vkEnumeratePhysicalDevices(instance, &phys_dev_count, NULL) || phys_dev_count == 0) {
                std::cout << "Failed searching for Vulkan physical devices\n";
                exit(-1);
            }
            std::vector<VkPhysicalDevice> physical_devices;
            physical_devices.resize(phys_dev_count);
            if (VK_SUCCESS != vkEnumeratePhysicalDevices(instance, &phys_dev_count, physical_devices.data()) ||
                phys_dev_count == 0) {
                std::cout << "Failed enumerating Vulkan physical devices\n";
                exit(-1);
            }

            // Go through the list of physical devices and select only those that are capable of running the API version we want.
            for (uint32_t dev = 0; dev < physical_devices.size(); ++dev) {
                VkPhysicalDeviceProperties physical_device_props = {};
                vkGetPhysicalDeviceProperties(physical_devices[dev], &physical_device_props);
                if (physical_device_props.apiVersion >= desired_version) {
                    physical_devices_desired.push_back(physical_devices[dev]);
                }
            }

            // If we have something in the desired version physical device list, we're good
            if (physical_devices_desired.size() > 0) {
                using_major_version = desired_major_version;
                using_minor_version = desired_minor_version;
            }
        }
    }

    using_version_string += std::to_string(using_major_version);
    using_version_string += ".";
    using_version_string += std::to_string(using_minor_version);

    if (using_minor_version < desired_minor_version) {
        std::cout << "Determined that this system can only use Vulkan API version " << using_version_string
                  << " instead of desired version " << desired_version_string << std::endl;
    } else {
        std::cout << "Determined that this system can run desired Vulkan API version " << desired_version_string << std::endl;
    }

    // Destroy the instance if it was created
    if (VK_NULL_HANDLE == instance) {
        vkDestroyInstance(instance, NULL);
    }

#endif
    /* VULKAN_KEY_END */

    return 0;
}