Merge pull request #2996 from MarcZX100/fix/agc-mesh-wave32-subgroup-2815

fix(agc): require 32-lane subgroups for wave32 mesh programs
This commit is contained in:
Adrià 2026-10-11 01:58:20 +02:00 committed by GitHub
commit a0d669926c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 9 additions and 2 deletions

View File

@ -254,6 +254,7 @@ struct VulkanDevice::State {
// VK_KHR_timeline_semaphore enabled: the recorder's unlocked waits are available.
bool timelineSemaphores = false;
bool computeWave32 = false;
bool meshWave32 = false;
std::uint32_t maxComputeSubgroupSize = 0;
// Indirect draw features enabled (see Graphics::Context).
bool drawIndirectFirstInstance = false;
@ -1241,9 +1242,11 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window) : state(std::make_u
state->InstanceFunction<PFN_vkGetPhysicalDeviceProperties2>("vkGetPhysicalDeviceProperties2")(selected, &sizeProperties);
state->computeWave32 = subgroupSizeFeatures.subgroupSizeControl == VK_TRUE && subgroupSize.minSubgroupSize <= 32u && subgroupSize.maxSubgroupSize >= 32u &&
(subgroupSize.requiredSubgroupSizeStages & VK_SHADER_STAGE_COMPUTE_BIT) != 0;
state->meshWave32 = state->meshShader && subgroupSizeFeatures.subgroupSizeControl == VK_TRUE && subgroupSize.minSubgroupSize <= 32u && subgroupSize.maxSubgroupSize >= 32u &&
(subgroupSize.requiredSubgroupSizeStages & VK_SHADER_STAGE_MESH_BIT_EXT) != 0;
state->maxComputeSubgroupSize = subgroupSize.maxSubgroupSize;
}
if (state->computeWave32) {
if (state->computeWave32 || state->meshWave32) {
subgroupSizeFeatures = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT};
subgroupSizeFeatures.subgroupSizeControl = VK_TRUE;
deviceExtensions.push_back(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);
@ -1251,7 +1254,7 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window) : state(std::make_u
deviceInfo.ppEnabledExtensionNames = deviceExtensions.data();
subgroupSizeFeatures.pNext = byteFeatures.pNext;
byteFeatures.pNext = &subgroupSizeFeatures;
APS5_LOG_OUT("Compute wave32 programs run on subgroups of %u", 32u);
APS5_LOG_OUT("Wave32 programs run on subgroups of %u: compute %d, mesh %d", 32u, state->computeWave32, state->meshWave32);
}
timelineFeatures = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR};
timelineFeatures.timelineSemaphore = VK_TRUE;
@ -2734,6 +2737,7 @@ Graphics::Context VulkanDevice::buildContext() const {
context.samplerFilterMinmax = state->samplerFilterMinmax;
context.nonSeamlessCubeMap = state->nonSeamlessCubeMap;
context.conservativeRasterization = state->conservativeRasterization;
context.meshWave32 = state->meshWave32;
context.provokingVertexLast = state->provokingVertexLast;
context.graphicsPipelineLibrary = state->graphicsPipelineLibrary;
context.provokingVertexModePerPipeline = state->provokingVertexModePerPipeline;

View File

@ -142,6 +142,7 @@ struct Context {
bool samplerFilterMinmax = false;
bool nonSeamlessCubeMap = false;
bool conservativeRasterization = false;
bool meshWave32 = false;
VkBuffer emptyBuffer = VK_NULL_HANDLE;
// The device's list of recorded dispatches whose copied written buffers await a CPU write-back
// (VulkanDevice's State::copiedWriters; the draw counterpart is DrawCopiedWriters): an indirect

View File

@ -212,6 +212,7 @@ Pipeline::Pipeline(const Context& context, const State& state, const VertexInput
std::vector<VkPipelineShaderStageCreateInfo> stages(shaders.size());
std::vector<PipelineSpecialization> specializations;
specializations.reserve(shaders.size());
const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT meshSubgroup{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT, nullptr, 32u};
for (std::uint32_t i = 0; i < shaders.size(); ++i) {
const auto& shader = *shaders[i].program;
VkShaderModuleCreateInfo module{VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
@ -223,6 +224,7 @@ Pipeline::Pipeline(const Context& context, const State& state, const VertexInput
stages[i].stage = stage;
stages[i].module = _modules[i];
stages[i].pName = "main";
if (shaders[i].stage == ShaderRecompiler::ShaderStage::Mesh && context.meshWave32 && shader.hostSubgroupSize == 32u) stages[i].pNext = &meshSubgroup;
specializations.emplace_back(shader);
stages[i].pSpecializationInfo = specializations.back().Info();
}