[Fix] (MG_Backend/DirectVulkan): fix 1.21.6+ intermittent crashing

- Try coerce vertex input format to please Vulkan driver
- Skip inactive UBO instead of hard fast-fail
This commit is contained in:
2026-05-10 11:53:26 +08:00
parent 4a36d63c1b
commit 4972ebf914
2 changed files with 73 additions and 41 deletions
@@ -1376,14 +1376,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
"ProgramFactory::ReflectLayout: UBO binding %u exceeds maxBindings=%u for '%s'",
binding, m_maxBindings, ubo.name.c_str());
MOBILEGL_ASSERT(entry.bindingKinds[binding] == DescriptorBindingKind::None ||
entry.bindingKinds[binding] == DescriptorBindingKind::UniformBufferDynamic,
"ProgramFactory::ReflectLayout: descriptor binding %u has conflicting kinds for UBO '%s'",
binding, ubo.name.c_str());
entry.bindingKinds[binding] = DescriptorBindingKind::UniformBufferDynamic;
// Check for global UBO
if (std::strstr(ubo.name.c_str(), MG_Util::ShaderTranspiler::GLOBAL_UBO_NAME) != nullptr) {
MOBILEGL_ASSERT(entry.bindingKinds[binding] == DescriptorBindingKind::None ||
entry.bindingKinds[binding] == DescriptorBindingKind::UniformBufferDynamic,
"ProgramFactory::ReflectLayout: descriptor binding %u has conflicting kinds for UBO '%s'",
binding, ubo.name.c_str());
entry.bindingKinds[binding] = DescriptorBindingKind::UniformBufferDynamic;
MOBILEGL_ASSERT(entry.globalUboBinding < 0 || entry.globalUboBinding == static_cast<Int>(binding),
"ProgramFactory::ReflectLayout: global UBO binding mismatch (%d vs %u)",
entry.globalUboBinding, binding);
@@ -1395,8 +1394,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
const Uint blockIndex = program.GetUniformBlockIndex(ubo.name.c_str());
MOBILEGL_ASSERT(blockIndex != 0xFFFFFFFFu,
"ProgramFactory::ReflectLayout: failed to resolve uniform block '%s'", ubo.name.c_str());
if (blockIndex == 0xFFFFFFFFu) {
MGLOG_D("ProgramFactory::ReflectLayout: skipping inactive UBO '%s' at binding %u",
ubo.name.c_str(), binding);
continue;
}
MOBILEGL_ASSERT(entry.bindingKinds[binding] == DescriptorBindingKind::None ||
entry.bindingKinds[binding] == DescriptorBindingKind::UniformBufferDynamic,
"ProgramFactory::ReflectLayout: descriptor binding %u has conflicting kinds for UBO '%s'",
binding, ubo.name.c_str());
entry.bindingKinds[binding] = DescriptorBindingKind::UniformBufferDynamic;
MOBILEGL_ASSERT(entry.globalUboBinding != static_cast<Int>(binding),
"ProgramFactory::ReflectLayout: regular UBO '%s' collides with global UBO binding %u",
ubo.name.c_str(), binding);
@@ -207,82 +207,106 @@ namespace MobileGL::MG_Backend::DirectVulkan {
outFormat = sourceFormat;
return true;
}
if (sourceDomain == NumericDomain::FloatLike || targetDomain == NumericDomain::FloatLike) {
if (sourceDomain == NumericDomain::FloatLike) {
return false;
}
switch (sourceFormat) {
case VK_FORMAT_R32_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R32_UINT : sourceFormat;
return true;
if (targetDomain == NumericDomain::Uint) {
outFormat = VK_FORMAT_R32_UINT;
return true;
}
return false;
case VK_FORMAT_R32G32_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R32G32_UINT : sourceFormat;
return true;
if (targetDomain == NumericDomain::Uint) {
outFormat = VK_FORMAT_R32G32_UINT;
return true;
}
return false;
case VK_FORMAT_R32G32B32_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R32G32B32_UINT : sourceFormat;
return true;
if (targetDomain == NumericDomain::Uint) {
outFormat = VK_FORMAT_R32G32B32_UINT;
return true;
}
return false;
case VK_FORMAT_R32G32B32A32_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R32G32B32A32_UINT : sourceFormat;
return true;
if (targetDomain == NumericDomain::Uint) {
outFormat = VK_FORMAT_R32G32B32A32_UINT;
return true;
}
return false;
case VK_FORMAT_R32_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R32_SINT : sourceFormat;
return true;
if (targetDomain == NumericDomain::Sint) {
outFormat = VK_FORMAT_R32_SINT;
return true;
}
return false;
case VK_FORMAT_R32G32_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R32G32_SINT : sourceFormat;
return true;
if (targetDomain == NumericDomain::Sint) {
outFormat = VK_FORMAT_R32G32_SINT;
return true;
}
return false;
case VK_FORMAT_R32G32B32_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R32G32B32_SINT : sourceFormat;
return true;
if (targetDomain == NumericDomain::Sint) {
outFormat = VK_FORMAT_R32G32B32_SINT;
return true;
}
return false;
case VK_FORMAT_R32G32B32A32_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R32G32B32A32_SINT : sourceFormat;
return true;
if (targetDomain == NumericDomain::Sint) {
outFormat = VK_FORMAT_R32G32B32A32_SINT;
return true;
}
return false;
case VK_FORMAT_R16_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R16_UINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R16_UINT : VK_FORMAT_R16_SSCALED;
return true;
case VK_FORMAT_R16G16_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R16G16_UINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R16G16_UINT : VK_FORMAT_R16G16_SSCALED;
return true;
case VK_FORMAT_R16G16B16_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R16G16B16_UINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R16G16B16_UINT : VK_FORMAT_R16G16B16_SSCALED;
return true;
case VK_FORMAT_R16G16B16A16_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R16G16B16A16_UINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R16G16B16A16_UINT : VK_FORMAT_R16G16B16A16_SSCALED;
return true;
case VK_FORMAT_R16_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R16_SINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R16_SINT : VK_FORMAT_R16_USCALED;
return true;
case VK_FORMAT_R16G16_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R16G16_SINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R16G16_SINT : VK_FORMAT_R16G16_USCALED;
return true;
case VK_FORMAT_R16G16B16_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R16G16B16_SINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R16G16B16_SINT : VK_FORMAT_R16G16B16_USCALED;
return true;
case VK_FORMAT_R16G16B16A16_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R16G16B16A16_SINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R16G16B16A16_SINT : VK_FORMAT_R16G16B16A16_USCALED;
return true;
case VK_FORMAT_R8_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R8_UINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R8_UINT : VK_FORMAT_R8_SSCALED;
return true;
case VK_FORMAT_R8G8_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R8G8_UINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R8G8_UINT : VK_FORMAT_R8G8_SSCALED;
return true;
case VK_FORMAT_R8G8B8_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R8G8B8_UINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R8G8B8_UINT : VK_FORMAT_R8G8B8_SSCALED;
return true;
case VK_FORMAT_R8G8B8A8_SINT:
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R8G8B8A8_UINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Uint ? VK_FORMAT_R8G8B8A8_UINT : VK_FORMAT_R8G8B8A8_SSCALED;
return true;
case VK_FORMAT_R8_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R8_SINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R8_SINT : VK_FORMAT_R8_USCALED;
return true;
case VK_FORMAT_R8G8_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R8G8_SINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R8G8_SINT : VK_FORMAT_R8G8_USCALED;
return true;
case VK_FORMAT_R8G8B8_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R8G8B8_SINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R8G8B8_SINT : VK_FORMAT_R8G8B8_USCALED;
return true;
case VK_FORMAT_R8G8B8A8_UINT:
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R8G8B8A8_SINT : sourceFormat;
outFormat = targetDomain == NumericDomain::Sint ? VK_FORMAT_R8G8B8A8_SINT : VK_FORMAT_R8G8B8A8_USCALED;
return true;
default:
return false;