子群

Vulkan 规范将子群定义为

一组着色器调用,它们可以彼此同步并高效地共享数据。在计算着色器中,局部工作组是子群的超集。

对于许多实现,子群是同时运行相同指令的调用组。子群允许着色器编写者以比单个工作组更精细的粒度工作。

资源

有关子群的更详细信息,请参阅优秀的 Khronos 博客文章以及 Vulkan 开发人员日 2018 的演示文稿(幻灯片视频)。GLSL 支持可以在 GL_KHR_shader_subgroup 扩展中找到。

子群大小

重要的是还要意识到,对于实现来说,子群的大小可以是动态的。某些实现可能会为不同的子群分派具有不同子群大小的着色器。因此,它们可能会隐式地将一个大型子群拆分为更小的子群,或者将一个小型子群表示为一个更大的子群,其中一些调用在启动时处于非活动状态。

VK_EXT_subgroup_size_control

在 Vulkan 1.3 中被提升为核心

创建此扩展的原因是一些实现具有多个子群大小,而 Vulkan 最初只公开一个子群大小。

例如,如果一个实现同时支持大小为 416 的子群,那么以前它们必须只公开一个大小,但现在可以同时公开这两个大小。这允许应用程序在更精细的粒度上控制硬件,以用于公开多个子群大小的实现。如果设备不支持此扩展,则很可能意味着只有一个受支持的子群大小可以公开。

检查支持

在 Vulkan 1.1 中,有关子群的所有信息都可以在 VkPhysicalDeviceSubgroupProperties 中找到

VkPhysicalDeviceSubgroupProperties subgroupProperties;

VkPhysicalDeviceProperties2KHR deviceProperties2;
deviceProperties2.sType      = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
deviceProperties2.pNext      = &subgroupProperties;
vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProperties2);

// Example of checking if supported in fragment shader
if ((subgroupProperties.supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) != 0) {
    // fragment shaders supported
}

// Example of checking if ballot is supported
if ((subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT) != 0) {
    // ballot subgroup operations supported
}

保证支持

对于支持的阶段,Vulkan 规范保证以下支持

如果任何物理设备的队列支持 VK_QUEUE_COMPUTE_BIT,则 supportedStages 将设置 VK_SHADER_STAGE_COMPUTE_BIT 位。

对于支持的操作,Vulkan 规范保证以下支持

如果任何物理设备的队列支持 VK_QUEUE_GRAPHICS_BITVK_QUEUE_COMPUTE_BIT,则 supportedOperations 将设置 VK_SUBGROUP_FEATURE_BASIC_BIT 位。

VK_KHR_shader_subgroup_extended_types

在 Vulkan 1.2 中被提升为核心

如果实现已经支持这些类型,则此扩展允许子群操作在具有子群范围的组操作中使用 8 位整数、16 位整数、64 位整数、16 位浮点数以及这些类型的向量。

例如,如果一个实现支持 8 位整数,那么应用程序现在可以使用 GLSL genI8Type subgroupAdd(genI8Type value); 调用,该调用将映射到 SPIR-V 中的 OpGroupNonUniformFAdd

VK_EXT_shader_subgroup_ballot 和 VK_EXT_shader_subgroup_vote

VK_EXT_shader_subgroup_ballotVK_EXT_shader_subgroup_vote 是最初在 Vulkan 中公开子群的努力。如果应用程序使用的是 Vulkan 1.1 或更高版本,则无需使用这些扩展,而应使用核心 API 查询子群支持。