[Feat] (MG_Config, MG_Util): a preference knob and POST rows for Magma's multi-draw tiers

MOBILEGL_MAGMA_MULTIDRAW_MODE=ext|indirect|unroll|auto selects the
DirectVulkan multi-draw dispatch tier, clamped to what the device
supports with one INFO line when it falls back; auto (and unset) picks
the best supported tier. Invalid values keep auto. Magma-only: the
variable has no effect on DirectGLES. Note for the escape hatch:
mode=unroll also forces the GL indirect multi-draw paths onto their
per-command loop, where gl_DrawID reads 0 for every sub-draw -
Flywheel-style content that keys on flw_drawId renders accordingly.

Three DriverPost rows per the POST rule: VK_EXT_multi_draw
(PASS/INFO), the multiDrawIndirect feature (WARN downgraded to INFO -
there is always a fallback tier), and the resolved dispatch tier with
the full chain. drawIndirectFirstInstance gains a row too, since the
indirect tier's legality check now relies on it.
This commit is contained in:
BZLZHH
2026-08-07 06:41:21 -04:00
parent d5f5e6405b
commit 231d5c90e4
3 changed files with 73 additions and 2 deletions
+39 -2
View File
@@ -1426,8 +1426,9 @@ namespace MobileGL::MG_Util::SelfTest {
if (features.multiDrawIndirect == VK_TRUE) {
builder.Pass("multiDrawIndirect", "indirect multi-draw batches run as single native commands");
} else {
builder.Warn("multiDrawIndirect",
"unsupported; indirect multi-draw batches fall back to one draw per command");
builder.Info("multiDrawIndirect",
"unsupported; multi-draw batches fall back to one draw per command (tier "
"\"indirect\" of the multi-draw dispatch is unavailable)");
}
if (features.drawIndirectFirstInstance == VK_TRUE) {
builder.Pass("drawIndirectFirstInstance", "indirect commands may carry a non-zero firstInstance");
@@ -1435,6 +1436,42 @@ namespace MobileGL::MG_Util::SelfTest {
builder.Warn("drawIndirectFirstInstance",
"unsupported; indirect commands with a non-zero baseInstance cannot run natively");
}
// Multi-draw dispatch tiers (ext -> indirect -> unroll). INFO on the missing
// pieces: every tier has a fallback, nothing is lost, only batched into more
// commands. The renderer resolves the same chain at device creation, clamped
// by MOBILEGL_MAGMA_MULTIDRAW_MODE.
{
Bool multiDrawExtUsable = false;
if (HasVkExtension(deviceExtensions, VK_EXT_MULTI_DRAW_EXTENSION_NAME) &&
vkGetPhysicalDeviceFeatures2Fn != nullptr) {
VkPhysicalDeviceMultiDrawFeaturesEXT multiDrawFeatures{};
multiDrawFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT;
VkPhysicalDeviceFeatures2 features2{};
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
features2.pNext = &multiDrawFeatures;
vkGetPhysicalDeviceFeatures2Fn(physicalDevice, &features2);
multiDrawExtUsable = multiDrawFeatures.multiDraw == VK_TRUE;
}
if (multiDrawExtUsable) {
builder.Pass("VK_EXT_multi_draw",
"supported; a glMultiDraw* batch runs as one vkCmdDrawMulti(Indexed)EXT");
} else {
builder.Info("VK_EXT_multi_draw",
"unsupported; glMultiDraw* batches use the indirect or unrolled tier");
}
const char* resolvedTier = multiDrawExtUsable ? "ext"
: features.multiDrawIndirect == VK_TRUE ? "indirect"
: "unroll";
String tierDetail = format("default tier \"{}\" (chain: ext -> indirect -> unroll)", resolvedTier);
const MG_Config::MultiDrawMode multiDrawMode = MG_Config::Features.MagmaMultiDrawMode;
if (multiDrawMode != MG_Config::MultiDrawMode::Auto) {
tierDetail += format("; MOBILEGL_MAGMA_MULTIDRAW_MODE={} caps it (clamped to device support)",
multiDrawMode == MG_Config::MultiDrawMode::Ext ? "ext"
: multiDrawMode == MG_Config::MultiDrawMode::Indirect ? "indirect"
: "unroll");
}
builder.Info("Multi-draw dispatch tier", tierDetail);
}
if (features.vertexPipelineStoresAndAtomics == VK_TRUE) {
builder.Pass("vertexPipelineStoresAndAtomics",
"supported by driver (not currently enabled by the DirectVulkan backend)");