mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Fix, Test] (MG_Backend/DirectVulkan, MG_IntegrationTest): let the binding remap accept the descriptor arrays that now have per-element paths, and reserve image-info scratch for them
This commit is contained in:
@@ -1834,10 +1834,25 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
for (auto* binding : bindings) {
|
||||
MOBILEGL_ASSERT(binding != nullptr, "ProgramFactory: null descriptor binding reflection record");
|
||||
const auto kind = ReflectDescriptorTypeToBindingKind(binding->descriptor_type);
|
||||
// UBO instance arrays (uniform Block {...} b[N];) occupy one binding with
|
||||
// descriptorCount = N; other descriptor arrays stay unsupported and must
|
||||
// fail program creation cleanly rather than continue with corrupt state.
|
||||
if (binding->count != 1 && kind != ProgramFactory::DescriptorBindingKind::UniformBufferDynamic) {
|
||||
// A descriptor ARRAY occupies one binding with descriptorCount = N, and is
|
||||
// supported for exactly the kinds that have a per-element resolve path in
|
||||
// UniformManager::BindProgramUniformBuffers: UBO instance arrays
|
||||
// (uniform Block {...} b[N];), storage-block instance arrays, and image
|
||||
// uniform arrays. Anything else must fail program creation cleanly rather
|
||||
// than continue with corrupt state.
|
||||
//
|
||||
// Getting listed here is not cosmetic: a kind that is rejected leaves
|
||||
// GetOrCreateProgram's MOBILEGL_ASSERT(remapOk) as the only complaint, and
|
||||
// that assert compiles out above DEBUG - so a release build SILENTLY kept
|
||||
// glslang's per-stage auto-mapped binding numbers, skipping the cross-stage
|
||||
// unification and the set->0 normalisation this function exists to do. A
|
||||
// program with an image array plus any second descriptor got aliased
|
||||
// bindings out of that, and a DEBUG build trapped on the same program.
|
||||
const Bool arraySupportedForKind =
|
||||
kind == ProgramFactory::DescriptorBindingKind::UniformBufferDynamic ||
|
||||
kind == ProgramFactory::DescriptorBindingKind::StorageBuffer ||
|
||||
kind == ProgramFactory::DescriptorBindingKind::StorageImage;
|
||||
if (binding->count != 1 && !arraySupportedForKind) {
|
||||
MGLOG_E("ProgramFactory: descriptor arrays are unsupported for this descriptor "
|
||||
"kind (name='%s' count=%u type=%d)",
|
||||
binding->name ? binding->name : "<null>", binding->count,
|
||||
@@ -2609,8 +2624,19 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// a storage BLOCK array, whose elements take consecutive GL binding points
|
||||
// from the declared one, each element of an image array carries its own
|
||||
// independently assigned image unit - see ResolveStorageImageDescriptor.
|
||||
entry.bindingDescriptorCounts[binding] =
|
||||
static_cast<Uint16>(std::max<Uint32>(1u, sampler->count));
|
||||
// Bounds-checked like the UBO array path above: descriptorCount goes
|
||||
// straight into a VkDescriptorSetLayoutBinding, and the bind path reserves
|
||||
// scratch from it, so an absurd array size has to be refused here rather
|
||||
// than narrowed into a Uint16 (where 65536 would become 0).
|
||||
const Uint32 imageArrayCount = std::max<Uint32>(1u, sampler->count);
|
||||
if (imageArrayCount > m_maxBindings) {
|
||||
MGLOG_E("ProgramFactory::ReflectLayout: image array '%s' at binding %u has %u elements, "
|
||||
"past the %u this device can describe",
|
||||
uniformName.c_str(), binding, imageArrayCount, m_maxBindings);
|
||||
entry.bindingKinds[binding] = DescriptorBindingKind::None;
|
||||
continue;
|
||||
}
|
||||
entry.bindingDescriptorCounts[binding] = static_cast<Uint16>(imageArrayCount);
|
||||
|
||||
const VkFormat reflectedFormat =
|
||||
ConvertSpirvImageFormatToVkFormat(sampler->image.image_format);
|
||||
|
||||
@@ -1443,7 +1443,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
writes.reserve(m_maxBindings);
|
||||
bufferInfos.reserve(m_maxBindings + uboArrayExtra + ssboArrayExtra);
|
||||
imageInfos.reserve(m_maxBindings);
|
||||
// ssboArrayExtra sums EVERY arrayed binding's surplus, image arrays included, so it is
|
||||
// the right worst case for this container too now that a storage-image binding pushes
|
||||
// one info per element. Reserving only m_maxBindings here was exact while every binding
|
||||
// pushed exactly one - and would have let the vector reallocate under an image array,
|
||||
// dangling every pImageInfo already recorded in `writes` (including the sampler
|
||||
// branch's &imageInfos.back()) before vkUpdateDescriptorSets reads them.
|
||||
imageInfos.reserve(m_maxBindings + ssboArrayExtra);
|
||||
texelBufferViews.reserve(m_maxBindings);
|
||||
dynamicOffsets.reserve(programObj.dynamicBindings.size() + uboArrayExtra);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user