[Fix] (MG_Backend/DirectVulkan): blendEnable was baked into pipelines without checking VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; disable blending on formats that lack it

This commit is contained in:
2026-07-17 20:03:53 -04:00
parent 48568cdb89
commit 6b223e4d23
@@ -3183,17 +3183,30 @@ void main() {
colorAttachmentFormat = textureResource->format; colorAttachmentFormat = textureResource->format;
} }
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG // Blending on an attachment whose format lacks
// VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT is invalid pipeline state
// (blend support is optional for e.g. 32-bit float formats on some GPUs);
// force-disable it instead of baking undefined behavior into the pipeline.
static UnorderedMap<Int, Bool> formatBlendSupport;
auto blendSupportIt = formatBlendSupport.find(static_cast<Int>(colorAttachmentFormat));
if (blendSupportIt == formatBlendSupport.end()) {
VkFormatProperties formatProperties{}; VkFormatProperties formatProperties{};
vkGetPhysicalDeviceFormatProperties(m_physicalDevice.handle, colorAttachmentFormat, &formatProperties); vkGetPhysicalDeviceFormatProperties(m_physicalDevice.handle, colorAttachmentFormat,
MOBILEGL_ASSERT( &formatProperties);
(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) != 0, const Bool blendable =
"GetOrCreatePipeline: blend is enabled on color attachment %u for format=%d textureId=%d, but the format lacks VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT (program=%u)", (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) != 0;
i, blendSupportIt =
static_cast<Int>(colorAttachmentFormat), formatBlendSupport.emplace(static_cast<Int>(colorAttachmentFormat), blendable).first;
textureExternalIndex, if (!blendable) {
MGLOG_E("GetOrCreatePipeline: format=%d lacks VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; "
"disabling blending on attachments with this format (first hit: attachment %u textureId=%d program=%u)",
static_cast<Int>(colorAttachmentFormat), i, textureExternalIndex,
program.GetExternalIndex()); program.GetExternalIndex());
#endif }
}
if (!blendSupportIt->second) {
effectiveBlendEnabled = false;
}
} }
// Dual-source blending (GL_SRC1_* factors from glBlendFunc paired with // Dual-source blending (GL_SRC1_* factors from glBlendFunc paired with
// glBindFragDataLocationIndexed) requires the dualSrcBlend device feature. It is detected at // glBindFragDataLocationIndexed) requires the dualSrcBlend device feature. It is detected at