aboutsummaryrefslogtreecommitdiff
path: root/src/vulkan/device.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/vulkan/device.cc')
-rw-r--r--src/vulkan/device.cc201
1 files changed, 191 insertions, 10 deletions
diff --git a/src/vulkan/device.cc b/src/vulkan/device.cc
index 22cd77a..d951f49 100644
--- a/src/vulkan/device.cc
+++ b/src/vulkan/device.cc
@@ -53,6 +53,36 @@ const char k16BitStorage_InputOutput[] =
const char kSubgroupSizeControl[] = "SubgroupSizeControl.subgroupSizeControl";
const char kComputeFullSubgroups[] = "SubgroupSizeControl.computeFullSubgroups";
+const char kSubgroupSupportedOperations[] = "SubgroupSupportedOperations";
+const char kSubgroupSupportedOperationsBasic[] =
+ "SubgroupSupportedOperations.basic";
+const char kSubgroupSupportedOperationsVote[] =
+ "SubgroupSupportedOperations.vote";
+const char kSubgroupSupportedOperationsArithmetic[] =
+ "SubgroupSupportedOperations.arithmetic";
+const char kSubgroupSupportedOperationsBallot[] =
+ "SubgroupSupportedOperations.ballot";
+const char kSubgroupSupportedOperationsShuffle[] =
+ "SubgroupSupportedOperations.shuffle";
+const char kSubgroupSupportedOperationsShuffleRelative[] =
+ "SubgroupSupportedOperations.shuffleRelative";
+const char kSubgroupSupportedOperationsClustered[] =
+ "SubgroupSupportedOperations.clustered";
+const char kSubgroupSupportedOperationsQuad[] =
+ "SubgroupSupportedOperations.quad";
+const char kSubgroupSupportedStages[] = "SubgroupSupportedStages";
+const char kSubgroupSupportedStagesVertex[] = "SubgroupSupportedStages.vertex";
+const char kSubgroupSupportedStagesTessellationControl[] =
+ "SubgroupSupportedStages.tessellationControl";
+const char kSubgroupSupportedStagesTessellationEvaluation[] =
+ "SubgroupSupportedStages.tessellationEvaluation";
+const char kSubgroupSupportedStagesGeometry[] =
+ "SubgroupSupportedStages.geometry";
+const char kSubgroupSupportedStagesFragment[] =
+ "SubgroupSupportedStages.fragment";
+const char kSubgroupSupportedStagesCompute[] =
+ "SubgroupSupportedStages.compute";
+
struct BaseOutStructure {
VkStructureType sType;
void* pNext;
@@ -437,6 +467,7 @@ Result Device::Initialize(
VkPhysicalDevice16BitStorageFeaturesKHR* storage16_ptrs = nullptr;
VkPhysicalDeviceVulkan11Features* vulkan11_ptrs = nullptr;
VkPhysicalDeviceVulkan12Features* vulkan12_ptrs = nullptr;
+ VkPhysicalDeviceVulkan13Features* vulkan13_ptrs = nullptr;
VkPhysicalDeviceSubgroupSizeControlFeaturesEXT*
subgroup_size_control_features = nullptr;
void* ptr = available_features2.pNext;
@@ -469,6 +500,9 @@ Result Device::Initialize(
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES:
vulkan12_ptrs = static_cast<VkPhysicalDeviceVulkan12Features*>(ptr);
break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES:
+ vulkan13_ptrs = static_cast<VkPhysicalDeviceVulkan13Features*>(ptr);
+ break;
default:
break;
}
@@ -513,7 +547,7 @@ Result Device::Initialize(
"Shader 8-bit storage requested but feature not returned");
}
if ((feature == kSubgroupSizeControl || feature == kComputeFullSubgroups) &&
- subgroup_size_control_features == nullptr) {
+ subgroup_size_control_features == nullptr && vulkan13_ptrs == nullptr) {
return amber::Result("Missing subgroup size control features");
}
@@ -622,13 +656,25 @@ Result Device::Initialize(
}
}
- if (feature == kSubgroupSizeControl &&
- subgroup_size_control_features->subgroupSizeControl != VK_TRUE) {
- return amber::Result("Missing subgroup size control feature");
- }
- if (feature == kComputeFullSubgroups &&
- subgroup_size_control_features->computeFullSubgroups != VK_TRUE) {
- return amber::Result("Missing compute full subgroups feature");
+ // If Vulkan 1.3 structure exists the features are set there.
+ if (vulkan13_ptrs) {
+ if (feature == kSubgroupSizeControl &&
+ vulkan13_ptrs->subgroupSizeControl != VK_TRUE) {
+ return amber::Result("Missing subgroup size control feature");
+ }
+ if (feature == kComputeFullSubgroups &&
+ vulkan13_ptrs->computeFullSubgroups != VK_TRUE) {
+ return amber::Result("Missing compute full subgroups feature");
+ }
+ } else {
+ if (feature == kSubgroupSizeControl &&
+ subgroup_size_control_features->subgroupSizeControl != VK_TRUE) {
+ return amber::Result("Missing subgroup size control feature");
+ }
+ if (feature == kComputeFullSubgroups &&
+ subgroup_size_control_features->computeFullSubgroups != VK_TRUE) {
+ return amber::Result("Missing compute full subgroups feature");
+ }
}
}
@@ -647,19 +693,153 @@ Result Device::Initialize(
std::find(required_features.begin(), required_features.end(),
kSubgroupSizeControl) != required_features.end();
- if (needs_subgroup_size_control) {
+ bool needs_subgroup_supported_operations = false;
+ bool needs_subgroup_supported_stages = false;
+
+ // Search for subgroup supported operations requirements.
+ for (const auto& feature : required_features)
+ if (feature.find(kSubgroupSupportedOperations) != std::string::npos)
+ needs_subgroup_supported_operations = true;
+
+ // Search for subgroup supported stages requirements.
+ for (const auto& feature : required_features)
+ if (feature.find(kSubgroupSupportedStages) != std::string::npos)
+ needs_subgroup_supported_stages = true;
+
+ const bool needs_subgroup_properties =
+ needs_subgroup_supported_operations || needs_subgroup_supported_stages;
+
+ if (needs_subgroup_size_control || needs_subgroup_properties) {
+ // Always chain all physical device properties structs in case at least one
+ // of them is needed.
VkPhysicalDeviceProperties2 properties2 = {};
+ VkPhysicalDeviceSubgroupProperties subgroup_properties = {};
+ VkPhysicalDeviceVulkan11Properties vulkan11_properties = {};
+ VkSubgroupFeatureFlags subgroup_supported_operations;
+ VkShaderStageFlags subgroup_supported_stages;
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
properties2.pNext = &subgroup_size_control_properties_;
subgroup_size_control_properties_.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT;
+ if (SupportsApiVersion(1, 2, 0)) {
+ subgroup_size_control_properties_.pNext = &vulkan11_properties;
+ vulkan11_properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES;
+ } else {
+ subgroup_size_control_properties_.pNext = &subgroup_properties;
+ subgroup_properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
+ }
- if (!SupportsApiVersion(1, 1, 0)) {
+ if (needs_subgroup_size_control && !SupportsApiVersion(1, 1, 0)) {
return Result(
"Vulkan: Device::Initialize subgroup size control feature also "
"requires an API version of 1.1 or higher");
}
+ if (needs_subgroup_properties && !SupportsApiVersion(1, 1, 0)) {
+ return Result(
+ "Vulkan: Device::Initialize subgroup properties also "
+ "requires an API version of 1.1 or higher");
+ }
ptrs_.vkGetPhysicalDeviceProperties2(physical_device_, &properties2);
+
+ if (needs_subgroup_supported_operations) {
+ // Read supported subgroup operations from the correct struct depending on
+ // the device API
+ if (SupportsApiVersion(1, 2, 0)) {
+ subgroup_supported_operations =
+ vulkan11_properties.subgroupSupportedOperations;
+ } else {
+ subgroup_supported_operations = subgroup_properties.supportedOperations;
+ }
+
+ for (const auto& feature : required_features) {
+ if (feature == kSubgroupSupportedOperationsBasic &&
+ !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_BASIC_BIT)) {
+ return amber::Result("Missing subgroup operation basic feature");
+ }
+ if (feature == kSubgroupSupportedOperationsVote &&
+ !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_VOTE_BIT)) {
+ return amber::Result("Missing subgroup operation vote feature");
+ }
+ if (feature == kSubgroupSupportedOperationsArithmetic &&
+ !(subgroup_supported_operations &
+ VK_SUBGROUP_FEATURE_ARITHMETIC_BIT)) {
+ return amber::Result("Missing subgroup operation arithmetic feature");
+ }
+ if (feature == kSubgroupSupportedOperationsBallot &&
+ !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_BALLOT_BIT)) {
+ return amber::Result("Missing subgroup operation ballot feature");
+ }
+ if (feature == kSubgroupSupportedOperationsShuffle &&
+ !(subgroup_supported_operations &
+ VK_SUBGROUP_FEATURE_SHUFFLE_BIT)) {
+ return amber::Result("Missing subgroup operation shuffle feature");
+ }
+ if (feature == kSubgroupSupportedOperationsShuffleRelative &&
+ !(subgroup_supported_operations &
+ VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT)) {
+ return amber::Result(
+ "Missing subgroup operation shuffle relative feature");
+ }
+ if (feature == kSubgroupSupportedOperationsClustered &&
+ !(subgroup_supported_operations &
+ VK_SUBGROUP_FEATURE_CLUSTERED_BIT)) {
+ return amber::Result("Missing subgroup operation clustered feature");
+ }
+ if (feature == kSubgroupSupportedOperationsQuad &&
+ !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_QUAD_BIT)) {
+ return amber::Result("Missing subgroup operation quad feature");
+ }
+ }
+ }
+
+ if (needs_subgroup_supported_stages) {
+ // Read supported subgroup stages from the correct struct depending on the
+ // device API
+ if (SupportsApiVersion(1, 2, 0)) {
+ subgroup_supported_stages = vulkan11_properties.subgroupSupportedStages;
+ } else {
+ subgroup_supported_stages = subgroup_properties.supportedStages;
+ }
+
+ for (const auto& feature : required_features) {
+ if (feature == kSubgroupSupportedStagesVertex &&
+ !(subgroup_supported_stages & VK_SHADER_STAGE_VERTEX_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for vertex shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesTessellationControl &&
+ !(subgroup_supported_stages &
+ VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for tessellation control "
+ "shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesTessellationEvaluation &&
+ !(subgroup_supported_stages &
+ VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for tessellation evaluation "
+ "shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesGeometry &&
+ !(subgroup_supported_stages & VK_SHADER_STAGE_GEOMETRY_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for geometry shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesFragment &&
+ !(subgroup_supported_stages & VK_SHADER_STAGE_FRAGMENT_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for fragment shader stage");
+ }
+ if (feature == kSubgroupSupportedStagesCompute &&
+ !(subgroup_supported_stages & VK_SHADER_STAGE_COMPUTE_BIT)) {
+ return amber::Result(
+ "Subgroup operations not supported for compute shader stage");
+ }
+ }
+ }
}
return {};
@@ -676,6 +856,7 @@ bool Device::IsFormatSupportedByPhysicalDevice(const Format& format,
bool is_buffer_type_image = false;
switch (type) {
case BufferType::kColor:
+ case BufferType::kResolve:
case BufferType::kStorageImage:
flag = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
is_buffer_type_image = true;