blob: b3606c5b8f8d23dd966e66a34e45ed647734f0ae [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "utils.h"
#include <optional>
#include <unordered_set>
namespace {
static void PrintProps(const std::vector<std::string> &props) {
for (const auto &prop : props) {
printf("\t%s\n", prop.c_str());
}
printf("\n");
}
} // namespace
namespace vkp {
//
// Enumerate properties categorically using |search_prop| and populate |props_found_set|
// with the results. Returns false if no properties are enumerated.
//
static bool EnumerateProperties(SearchProp search_prop, const vk::PhysicalDevice &phys_device,
const char *layer,
std::unordered_set<std::string> *props_found_set) {
std::optional<vk::ResultValue<std::vector<vk::ExtensionProperties>>> rv_ext;
std::optional<vk::ResultValue<std::vector<vk::LayerProperties>>> rv_layer;
std::vector<vk::ExtensionProperties> ext_props;
std::vector<vk::LayerProperties> layer_props;
switch (search_prop) {
case INSTANCE_EXT_PROP:
if (layer) {
rv_ext = vk::enumerateInstanceExtensionProperties(std::string(layer));
} else {
rv_ext = vk::enumerateInstanceExtensionProperties(nullptr);
}
if (vk::Result::eSuccess != rv_ext->result) {
RTN_MSG(false, "VK Error: 0x%x - Failed to enumerate extension properties.",
rv_ext->result);
}
ext_props = rv_ext->value;
break;
case INSTANCE_LAYER_PROP:
rv_layer = vk::enumerateInstanceLayerProperties();
if (vk::Result::eSuccess != rv_layer->result) {
RTN_MSG(false, "VK Error: 0x%x - Failed to enumerate layer properties.", rv_layer->result);
}
layer_props = rv_layer->value;
break;
case PHYS_DEVICE_EXT_PROP:
if (layer) {
rv_ext = phys_device.enumerateDeviceExtensionProperties(std::string(layer));
} else {
rv_ext = phys_device.enumerateDeviceExtensionProperties(nullptr);
}
if (vk::Result::eSuccess != rv_ext->result) {
RTN_MSG(false, "VK Error: 0x%x - Failed to enumerate layer properties.", rv_ext->result);
}
ext_props = rv_ext->value;
break;
}
if (search_prop == INSTANCE_LAYER_PROP) {
for (auto &prop : layer_props) {
props_found_set->insert(std::string(prop.layerName));
}
} else {
for (auto &prop : ext_props) {
props_found_set->insert(std::string(prop.extensionName));
}
}
return true;
}
bool FindMatchingProperties(const std::vector<const char *> &desired_props, SearchProp search_prop,
const vk::PhysicalDevice *phys_device, const char *layer,
std::vector<std::string> *missing_props_out) {
std::unordered_set<std::string> props_found_set;
// Match Vulkan properties. "Vulkan properties" are those
// found when the layer argument is set to null.
bool success = EnumerateProperties(search_prop, *phys_device, nullptr, &props_found_set);
if (!success) {
if (missing_props_out) {
missing_props_out->insert(missing_props_out->end(), desired_props.begin(),
desired_props.end());
}
RTN_MSG(false, "Unable to match vulkan properties.\n");
}
// Match layer properties.
if (search_prop != INSTANCE_LAYER_PROP && layer &&
props_found_set.size() != desired_props.size()) {
success = EnumerateProperties(search_prop, *phys_device, layer, &props_found_set);
}
if (missing_props_out) {
for (const auto &prop : desired_props) {
auto iter = props_found_set.find(prop);
if (iter == props_found_set.end()) {
missing_props_out->emplace_back(*iter);
}
}
}
if (missing_props_out && !missing_props_out->empty()) {
PrintProps(*missing_props_out);
}
return props_found_set.size() == desired_props.size();
}
bool FindGraphicsQueueFamilies(vk::PhysicalDevice phys_device, VkSurfaceKHR surface,
std::vector<uint32_t> *queue_family_indices) {
auto queue_families = phys_device.getQueueFamilyProperties();
int queue_family_index = 0;
for (const auto &queue_family : queue_families) {
auto rv = phys_device.getSurfaceSupportKHR(queue_family_index, surface);
if (vk::Result::eSuccess != rv.result) {
RTN_MSG(false, "VK Error: 0x%x - Failed to get surface present support.", rv.result);
}
const vk::Bool32 present_support = rv.value;
if ((queue_family.queueCount > 0) && (queue_family.queueFlags & vk::QueueFlagBits::eGraphics) &&
present_support) {
if (queue_family_indices) {
queue_family_indices->emplace_back(queue_family_index);
}
return true;
}
queue_family_index++;
}
RTN_MSG(false, "No queue family indices found.\n");
}
int FindMemoryIndex(const vk::PhysicalDevice &phys_dev, const uint32_t memory_type_bits,
const vk::MemoryPropertyFlags &desired_props) {
vk::PhysicalDeviceMemoryProperties memory_props;
phys_dev.getMemoryProperties(&memory_props);
for (uint32_t i = 0; i < memory_props.memoryTypeCount; i++) {
if ((memory_type_bits & (1 << i)) &&
(memory_props.memoryTypes[i].propertyFlags & desired_props) == desired_props) {
return i;
}
}
RTN_MSG(-1, "Error: Unable to find memory property index.");
}
void LogMemoryProperties(const vk::PhysicalDevice &phys_dev) {
vk::PhysicalDeviceMemoryProperties memory_props;
phys_dev.getMemoryProperties(&memory_props);
const uint32_t memory_type_ct = memory_props.memoryTypeCount;
const vk::MemoryType *types = memory_props.memoryTypes;
printf("\nMemory Types: %d\n", memory_type_ct);
for (uint32_t i = 0; i < memory_type_ct; i++) {
const vk::MemoryType &type = types[i];
printf("\tHeap Index: %d\n", type.heapIndex);
if (type.propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal)
printf("\t\tDevice Local\n");
if (type.propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)
printf("\t\tHost Visible\n");
if (type.propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent)
printf("\t\tHost Coherent\n");
if (type.propertyFlags & vk::MemoryPropertyFlagBits::eHostCached)
printf("\t\tHost Cached\n");
if (type.propertyFlags & vk::MemoryPropertyFlagBits::eLazilyAllocated)
printf("\t\tLazily Allocated\n");
if (type.propertyFlags & vk::MemoryPropertyFlagBits::eProtected)
printf("\t\tProtected\n");
if (type.propertyFlags & vk::MemoryPropertyFlagBits::eDeviceCoherentAMD)
printf("\t\tDevice Coherent AMD\n");
if (type.propertyFlags & vk::MemoryPropertyFlagBits::eDeviceUncachedAMD)
printf("\t\tDevice Uncached AMD\n");
}
printf("\n");
}
} // namespace vkp