dawn-cmake/src/dawn_native/vulkan/VulkanExtensions.h
Corentin Wallez 5cef1162b9 Reland: Vulkan: Report and enable subgroup size control device extension.
Reland after a refactor of how the extension handling work in the Vulkan
backend.

The original author is David Turner <david.turner.dev@gmail.com>.

Certain Vulkan ICDs (Intel ones notably) will compile SPIR-V
shaders with an liberal, compiler-selected, subgroup size (i.e.
either 8, 16 or 32). For more context, see [1].

This can be a problem for compute, when one shader stores data
in device memory using a subgroup-size dependent layout, to be
consumed by a another shader. Problems arise when the compiler
decides to compile both shaders with different subgroup sizes.

To work-around this, the VK_EXT_subgroup_size_control device
extension was introduced recently: it allows the device to
report the min/max subgroup sizes it provides, and allows
the Vulkan program to control the subgroup size precisely
if it wants to.

This patch adds support to the Vulkan backend to report and
enable the extension if it is available. Note that:

- This changes the definition of VulkanDeviceKnobs to
  make room for the required pNext-linked chains of
  extensions.

- A helper class, PNextChainBuilder is also provided in
  UtilsVulkan.h to make it easy to build pNext-linked
  extension struct chains at runtime, as required when
  probing device propertires/features, or when
  creating a new VkDevice handle.

- This modifies VulkanDeviceInfo::GatherDeviceInfo() to
  use PNextChainBuilder to query extension features and properties
  in a single call to vkGetPhysicalDevice{Properties,Features}2.

Apart from that, there is no change in behaviour in this CL.
I.e. a later CL might force a specific subgroup size for
consistency, or introduce a new API to let Dawn clients
select a fixed subgroup size.

[1] https://bugs.freedesktop.org/show_bug.cgi?id=108875

Bug: dawn:464
Change-Id: I01e5c28e7dac66f0a57bf35532eb192912b254fa
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23201
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
2020-06-16 07:54:28 +00:00

142 lines
5.0 KiB
C++

// 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.
#ifndef DAWNNATIVE_VULKAN_VULKANEXTENSIONS_H_
#define DAWNNATIVE_VULKAN_VULKANEXTENSIONS_H_
#include <bitset>
#include <unordered_map>
namespace dawn_native { namespace vulkan {
// The list of known instance extensions. They must be in dependency order (this is checked
// inside EnsureDependencies)
enum class InstanceExt {
// Promoted to 1.1
GetPhysicalDeviceProperties2,
ExternalMemoryCapabilities,
ExternalSemaphoreCapabilities,
// Surface extensions
Surface,
FuchsiaImagePipeSurface,
MetalSurface,
WaylandSurface,
Win32Surface,
XcbSurface,
XlibSurface,
// Others
DebugReport,
EnumCount,
};
// A bitset wrapper that is indexed with InstanceExt.
struct InstanceExtSet {
std::bitset<static_cast<size_t>(InstanceExt::EnumCount)> extensionBitSet;
void Set(InstanceExt extension, bool enabled);
bool Has(InstanceExt extension) const;
};
// Information about a known instance extension.
struct InstanceExtInfo {
InstanceExt index;
const char* name;
// The version in which this extension was promoted as built with VK_MAKE_VERSION,
// or NeverPromoted if it was never promoted.
uint32_t versionPromoted;
};
// Returns the information about a known InstanceExt
const InstanceExtInfo& GetInstanceExtInfo(InstanceExt ext);
// Returns a map that maps a Vulkan extension name to its InstanceExt.
std::unordered_map<std::string, InstanceExt> CreateInstanceExtNameMap();
// Sets entries in `extensions` to true if that entry was promoted in Vulkan version `version`
void MarkPromotedExtensions(InstanceExtSet* extensions, uint32_t version);
// From a set of extensions advertised as supported by the instance (or promoted), remove all
// extensions that don't have all their transitive dependencies in advertisedExts.
InstanceExtSet EnsureDependencies(const InstanceExtSet& advertisedExts);
// The list of known device extensions. They must be in dependency order (this is checked
// inside EnsureDependencies)
enum class DeviceExt {
// Promoted to 1.1
BindMemory2,
Maintenance1,
StorageBufferStorageClass,
GetPhysicalDeviceProperties2,
GetMemoryRequirements2,
ExternalMemoryCapabilities,
ExternalSemaphoreCapabilities,
ExternalMemory,
ExternalSemaphore,
_16BitStorage,
SamplerYCbCrConversion,
// Promoted to 1.2
ImageFormatList,
ShaderFloat16Int8,
// External* extensions
ExternalMemoryFD,
ExternalMemoryDmaBuf,
ExternalMemoryZirconHandle,
ExternalSemaphoreFD,
ExternalSemaphoreZirconHandle,
// Others
DebugMarker,
ImageDrmFormatModifier,
Swapchain,
SubgroupSizeControl,
EnumCount,
};
// A bitset wrapper that is indexed with DeviceExt.
struct DeviceExtSet {
std::bitset<static_cast<size_t>(DeviceExt::EnumCount)> extensionBitSet;
void Set(DeviceExt extension, bool enabled);
bool Has(DeviceExt extension) const;
};
// A bitset wrapper that is indexed with DeviceExt.
struct DeviceExtInfo {
DeviceExt index;
const char* name;
// The version in which this extension was promoted as built with VK_MAKE_VERSION,
// or NeverPromoted if it was never promoted.
uint32_t versionPromoted;
};
// Returns the information about a known DeviceExt
const DeviceExtInfo& GetDeviceExtInfo(DeviceExt ext);
// Returns a map that maps a Vulkan extension name to its DeviceExt.
std::unordered_map<std::string, DeviceExt> CreateDeviceExtNameMap();
// Sets entries in `extensions` to true if that entry was promoted in Vulkan version `version`
void MarkPromotedExtensions(DeviceExtSet* extensions, uint32_t version);
// From a set of extensions advertised as supported by the device (or promoted), remove all
// extensions that don't have all their transitive dependencies in advertisedExts or in
// instanceExts.
DeviceExtSet EnsureDependencies(const DeviceExtSet& advertisedExts,
const InstanceExtSet& instanceExts,
uint32_t icdVersion);
}} // namespace dawn_native::vulkan
#endif // DAWNNATIVE_VULKAN_VULKANEXTENSIONS_H_