blob: ea0ccabbd1fd64948ca99cfc32577820ee60d282 [file] [log] [blame]
// Copyright 2020 The Dawn Authors
//
// 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 "dawn_native/vulkan/VulkanExtensions.h"
#include "common/Assert.h"
#include "common/vulkan_platform.h"
#include <array>
#include <limits>
namespace dawn_native { namespace vulkan {
static constexpr uint32_t VulkanVersion_1_1 = VK_MAKE_VERSION(1, 1, 0);
static constexpr uint32_t NeverPromoted = std::numeric_limits<uint32_t>::max();
// A static array for InstanceExtInfo that can be indexed with InstanceExts.
// GetInstanceExtInfo checks that "index" matches the index used to access this array so an
// assert will fire if it isn't in the correct order.
static constexpr size_t kInstanceExtCount = static_cast<size_t>(InstanceExt::EnumCount);
static constexpr std::array<InstanceExtInfo, kInstanceExtCount> sInstanceExtInfos{{
//
{InstanceExt::GetPhysicalDeviceProperties2, "VK_KHR_get_physical_device_properties2",
VulkanVersion_1_1},
{InstanceExt::ExternalMemoryCapabilities, "VK_KHR_external_memory_capabilities",
VulkanVersion_1_1},
{InstanceExt::ExternalSemaphoreCapabilities, "VK_KHR_external_semaphore_capabilities",
VulkanVersion_1_1},
{InstanceExt::Surface, "VK_KHR_surface", NeverPromoted},
{InstanceExt::FuchsiaImagePipeSurface, "VK_FUCHSIA_imagepipe_surface", NeverPromoted},
{InstanceExt::MetalSurface, "VK_EXT_metal_surface", NeverPromoted},
{InstanceExt::WaylandSurface, "VK_KHR_wayland_surface", NeverPromoted},
{InstanceExt::Win32Surface, "VK_KHR_win32_surface", NeverPromoted},
{InstanceExt::XcbSurface, "VK_KHR_xcb_surface", NeverPromoted},
{InstanceExt::XlibSurface, "VK_KHR_xlib_surface", NeverPromoted},
{InstanceExt::DebugReport, "VK_EXT_debug_report", NeverPromoted}
//
}};
void InstanceExtSet::Set(InstanceExt extension, bool enabled) {
extensionBitSet.set(static_cast<uint32_t>(extension), enabled);
}
bool InstanceExtSet::Has(InstanceExt extension) const {
return extensionBitSet[static_cast<uint32_t>(extension)];
}
const InstanceExtInfo& GetInstanceExtInfo(InstanceExt ext) {
uint32_t index = static_cast<uint32_t>(ext);
ASSERT(index < sInstanceExtInfos.size());
ASSERT(sInstanceExtInfos[index].index == ext);
return sInstanceExtInfos[index];
}
std::unordered_map<std::string, InstanceExt> CreateInstanceExtNameMap() {
std::unordered_map<std::string, InstanceExt> result;
for (const InstanceExtInfo& info : sInstanceExtInfos) {
result[info.name] = info.index;
}
return result;
}
InstanceExtSet EnsureDependencies(const InstanceExtSet& advertisedExts) {
// We need to check that all transitive dependencies of extensions are advertised.
// To do that in a single pass and no data structures, the extensions are topologically
// sorted in the definition of InstanceExt.
// To ensure the order is correct, we mark visited extensions in `visitedSet` and each
// dependency check will first assert all its dependents have been visited.
InstanceExtSet visitedSet;
InstanceExtSet trimmedSet;
auto HasDep = [&](InstanceExt ext) -> bool {
ASSERT(visitedSet.Has(ext));
return trimmedSet.Has(ext);
};
for (uint32_t i = 0; i < sInstanceExtInfos.size(); i++) {
InstanceExt ext = static_cast<InstanceExt>(i);
bool hasDependencies = false;
switch (ext) {
case InstanceExt::GetPhysicalDeviceProperties2:
case InstanceExt::Surface:
case InstanceExt::DebugReport:
hasDependencies = true;
break;
case InstanceExt::ExternalMemoryCapabilities:
case InstanceExt::ExternalSemaphoreCapabilities:
hasDependencies = HasDep(InstanceExt::GetPhysicalDeviceProperties2);
break;
case InstanceExt::FuchsiaImagePipeSurface:
case InstanceExt::MetalSurface:
case InstanceExt::WaylandSurface:
case InstanceExt::Win32Surface:
case InstanceExt::XcbSurface:
case InstanceExt::XlibSurface:
hasDependencies = HasDep(InstanceExt::Surface);
break;
default:
UNREACHABLE();
break;
}
trimmedSet.Set(ext, hasDependencies && advertisedExts.Has(ext));
visitedSet.Set(ext, true);
}
return trimmedSet;
}
void MarkPromotedExtensions(InstanceExtSet* extensions, uint32_t version) {
for (const InstanceExtInfo& info : sInstanceExtInfos) {
if (info.versionPromoted <= version) {
extensions->Set(info.index, true);
}
}
}
}} // namespace dawn_native::vulkan