diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index 4e6995cd9..4391a3b5d 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -832,7 +832,7 @@ bool IsValid(const VkWriteDescriptorSet &write, uint32_t arrayElement) return false; } -void DescriptorSetSlot::RemoveBindRefs(VkResourceRecord *record) +void DescriptorSetBindingElement::RemoveBindRefs(VkResourceRecord *record) { SCOPED_LOCK(record->descInfo->refLock); @@ -877,7 +877,7 @@ void DescriptorSetSlot::RemoveBindRefs(VkResourceRecord *record) imageInfo.sampler = VK_NULL_HANDLE; } -void DescriptorSetSlot::AddBindRefs(VkResourceRecord *record, FrameRefType ref) +void DescriptorSetBindingElement::AddBindRefs(VkResourceRecord *record, FrameRefType ref) { SCOPED_LOCK(record->descInfo->refLock); @@ -910,3 +910,16 @@ void DescriptorSetSlot::AddBindRefs(VkResourceRecord *record, FrameRefType ref) record->AddMemFrameRef(buf->baseResource, buf->memOffset, buf->memSize, ref); } } + +void DescriptorSetSlot::CreateFrom(const DescriptorSetBindingElement &slot) +{ + bufferInfo.buffer = GetResID(slot.bufferInfo.buffer); + bufferInfo.offset = slot.bufferInfo.offset; + bufferInfo.range = slot.bufferInfo.range; + + imageInfo.sampler = GetResID(slot.imageInfo.sampler); + imageInfo.imageView = GetResID(slot.imageInfo.imageView); + imageInfo.imageLayout = slot.imageInfo.imageLayout; + + texelBufferView = GetResID(slot.texelBufferView); +} diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index ac41e98b7..4554fc632 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -368,7 +368,7 @@ FrameRefType GetRefType(VkDescriptorType descType); // the possible contents of a descriptor set slot, // taken from the VkWriteDescriptorSet -struct DescriptorSetSlot +struct DescriptorSetBindingElement { VkDescriptorBufferInfo bufferInfo; VkDescriptorImageInfo imageInfo; @@ -378,6 +378,39 @@ struct DescriptorSetSlot void AddBindRefs(VkResourceRecord *record, FrameRefType ref); }; +// serialisable snapshot of descriptor set slots. Needed because if we snapshot +// DescriptorSetBindingElement +// the VkBuffer or VkImageView handles may have been deleted and recreated by the time we fetch +// their ResourceId +struct DescriptorSetSlotBufferInfo +{ + ResourceId buffer; + VkDeviceSize offset; + VkDeviceSize range; +}; + +struct DescriptorSetSlotImageInfo +{ + ResourceId sampler; + ResourceId imageView; + VkImageLayout imageLayout; +}; + +struct DescriptorSetSlot +{ + void CreateFrom(const DescriptorSetBindingElement &slot); + + // VkDescriptorBufferInfo + DescriptorSetSlotBufferInfo bufferInfo; + + // VkDescriptorImageInfo + DescriptorSetSlotImageInfo imageInfo; + + ResourceId texelBufferView; +}; + +DECLARE_REFLECTION_STRUCT(DescriptorSetSlotBufferInfo); +DECLARE_REFLECTION_STRUCT(DescriptorSetSlotImageInfo); DECLARE_REFLECTION_STRUCT(DescriptorSetSlot); bool IsValid(const VkWriteDescriptorSet &write, uint32_t arrayElement); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 5525a0e0a..7a35f2cf7 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -3773,7 +3773,7 @@ void WrappedVulkan::AddUsage(VulkanDrawcallTreeNode &drawNode, vector currentBindings; + vector currentBindings; bool push; void clear() diff --git a/renderdoc/driver/vulkan/vk_info.cpp b/renderdoc/driver/vulkan/vk_info.cpp index 0d0bc189b..badad1928 100644 --- a/renderdoc/driver/vulkan/vk_info.cpp +++ b/renderdoc/driver/vulkan/vk_info.cpp @@ -124,18 +124,18 @@ void DescSetLayout::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo } } -void DescSetLayout::CreateBindingsArray(std::vector &descBindings) const +void DescSetLayout::CreateBindingsArray(std::vector &descBindings) const { descBindings.resize(bindings.size()); for(size_t i = 0; i < bindings.size(); i++) { - descBindings[i] = new DescriptorSetSlot[bindings[i].descriptorCount]; - memset(descBindings[i], 0, sizeof(DescriptorSetSlot) * bindings[i].descriptorCount); + descBindings[i] = new DescriptorSetBindingElement[bindings[i].descriptorCount]; + memset(descBindings[i], 0, sizeof(DescriptorSetBindingElement) * bindings[i].descriptorCount); } } void DescSetLayout::UpdateBindingsArray(const DescSetLayout &prevLayout, - std::vector &descBindings) const + std::vector &descBindings) const { // if we have fewer bindings now, delete the orphaned bindings arrays for(size_t i = bindings.size(); i < prevLayout.bindings.size(); i++) @@ -148,13 +148,14 @@ void DescSetLayout::UpdateBindingsArray(const DescSetLayout &prevLayout, for(size_t i = 0; i < bindings.size(); i++) { // allocate new slot array - DescriptorSetSlot *newSlots = new DescriptorSetSlot[bindings[i].descriptorCount]; - memset(newSlots, 0, sizeof(DescriptorSetSlot) * bindings[i].descriptorCount); + DescriptorSetBindingElement *newSlots = + new DescriptorSetBindingElement[bindings[i].descriptorCount]; + memset(newSlots, 0, sizeof(DescriptorSetBindingElement) * bindings[i].descriptorCount); // copy over any previous bindings that overlapped if(i < prevLayout.bindings.size()) memcpy(newSlots, descBindings[i], - sizeof(DescriptorSetSlot) * + sizeof(DescriptorSetBindingElement) * RDCMIN(prevLayout.bindings[i].descriptorCount, bindings[i].descriptorCount)); // delete old array, and assign the new one diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index f6b9b1919..fe15439ed 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -59,9 +59,9 @@ struct DescSetLayout void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, const VkDescriptorSetLayoutCreateInfo *pCreateInfo); - void CreateBindingsArray(std::vector &descBindings) const; + void CreateBindingsArray(std::vector &descBindings) const; void UpdateBindingsArray(const DescSetLayout &prevLayout, - std::vector &descBindings) const; + std::vector &descBindings) const; struct Binding { diff --git a/renderdoc/driver/vulkan/vk_initstate.cpp b/renderdoc/driver/vulkan/vk_initstate.cpp index 3a5486a2e..69d90ed9d 100644 --- a/renderdoc/driver/vulkan/vk_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_initstate.cpp @@ -69,7 +69,7 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) { for(uint32_t b = 0; b < layout.bindings[i].descriptorCount; b++) { - initialContents.descriptorSlots[e++] = record->descInfo->descBindings[i][b]; + initialContents.descriptorSlots[e++].CreateFrom(record->descInfo->descBindings[i][b]); } } } @@ -637,7 +637,7 @@ uint64_t WrappedVulkan::GetSize_InitialState(ResourceId id, const VkInitialConte for(size_t i = 0; i < layout.bindings.size(); i++) NumBindings += layout.bindings[i].descriptorCount; - return 32 + NumBindings * sizeof(DescriptorSetSlot); + return 32 + NumBindings * sizeof(DescriptorSetBindingElement); } else if(initial.type == eResBuffer) { @@ -695,7 +695,7 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id, RDCASSERT(record->descInfo && record->descInfo->layout); const DescSetLayout &layout = *record->descInfo->layout; - Bindings = (DescriptorSetSlot *)initial->descriptorSlots; + Bindings = initial->descriptorSlots; for(size_t i = 0; i < layout.bindings.size(); i++) NumBindings += layout.bindings[i].descriptorCount; @@ -785,9 +785,9 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id, // skipping any invalid descriptors. // quick check for slots that were completely uninitialised and so don't have valid data - if(descriptorCount == 1 && src->texelBufferView == VK_NULL_HANDLE && - src->imageInfo.sampler == VK_NULL_HANDLE && src->imageInfo.imageView == VK_NULL_HANDLE && - src->bufferInfo.buffer == VK_NULL_HANDLE) + if(descriptorCount == 1 && src->texelBufferView == ResourceId() && + src->imageInfo.sampler == ResourceId() && src->imageInfo.imageView == ResourceId() && + src->bufferInfo.buffer == ResourceId()) { // do nothing - don't increment bind so that the same write descriptor is used next time. continue; @@ -804,7 +804,13 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id, case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: { for(uint32_t d = 0; d < descriptorCount; d++) - dstImage[d] = src[d].imageInfo; + { + dstImage[d].imageView = + GetResourceManager()->GetLiveHandle(src[d].imageInfo.imageView); + dstImage[d].sampler = + GetResourceManager()->GetLiveHandle(src[d].imageInfo.sampler); + dstImage[d].imageLayout = src[d].imageInfo.imageLayout; + } if(immutableSamplers) { @@ -823,7 +829,8 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id, case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { for(uint32_t d = 0; d < descriptorCount; d++) - dstTexelBuffer[d] = src[d].texelBufferView; + dstTexelBuffer[d] = + GetResourceManager()->GetLiveHandle(src[d].texelBufferView); writes[bind].pTexelBufferView = dstTexelBuffer; // NULL the others @@ -837,7 +844,12 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id, case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: { for(uint32_t d = 0; d < descriptorCount; d++) - dstBuffer[d] = src[d].bufferInfo; + { + dstBuffer[d].buffer = + GetResourceManager()->GetLiveHandle(src[d].bufferInfo.buffer); + dstBuffer[d].offset = src[d].bufferInfo.offset; + dstBuffer[d].range = src[d].bufferInfo.range; + } writes[bind].pBufferInfo = dstBuffer; // NULL the others @@ -1308,13 +1320,13 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten // need to blat over the current descriptor set contents, so these are available // when we want to fetch pipeline state - vector &bindings = m_DescriptorSetState[id].currentBindings; + vector &bindings = m_DescriptorSetState[id].currentBindings; for(uint32_t i = 0; i < initial.numDescriptors; i++) { RDCASSERT(writes[i].dstBinding < bindings.size()); - DescriptorSetSlot *bind = bindings[writes[i].dstBinding]; + DescriptorSetBindingElement *bind = bindings[writes[i].dstBinding]; for(uint32_t d = 0; d < writes[i].descriptorCount; d++) { diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index 1e1a38923..5fa8b6079 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -1493,7 +1493,7 @@ void VulkanReplay::PatchReservedDescriptors(const VulkanStatePipeline &pipe, if(bind.descriptorCount == 0 || bind.stageFlags == 0) continue; - DescriptorSetSlot *slot = setInfo.currentBindings[b]; + DescriptorSetBindingElement *slot = setInfo.currentBindings[b]; write.dstBinding = uint32_t(b + newBindingsCount); write.dstArrayElement = 0; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 5689bac56..b4dddd2fb 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -1403,7 +1403,7 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) dst.bindings.resize(m_pDriver->m_DescriptorSetState[src].currentBindings.size()); for(size_t b = 0; b < m_pDriver->m_DescriptorSetState[src].currentBindings.size(); b++) { - DescriptorSetSlot *info = m_pDriver->m_DescriptorSetState[src].currentBindings[b]; + DescriptorSetBindingElement *info = m_pDriver->m_DescriptorSetState[src].currentBindings[b]; const DescSetLayout::Binding &layoutBind = c.m_DescSetLayout[layoutId].bindings[b]; curBind.bind = (uint32_t)b; diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index 154b0f07f..6df7a1be4 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -955,7 +955,7 @@ struct DescriptorSetData // descriptor set bindings for this descriptor set. Filled out on // create from the layout. - vector descBindings; + vector descBindings; // lock protecting bindFrameRefs and bindMemRefs Threading::CriticalSection refLock; diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index c952748f8..c684729be 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -3360,6 +3360,22 @@ void Deserialise(const VkDebugUtilsMessengerCreateInfoEXT &el) // this isn't a real vulkan type, it's our own "anything that could be in a descriptor" // structure that +template +void DoSerialise(SerialiserType &ser, DescriptorSetSlotImageInfo &el) +{ + SERIALISE_MEMBER(sampler).TypedAs("VkSampler"); + SERIALISE_MEMBER(imageView).TypedAs("VkImageView"); + SERIALISE_MEMBER(imageLayout); +} + +template +void DoSerialise(SerialiserType &ser, DescriptorSetSlotBufferInfo &el) +{ + SERIALISE_MEMBER(buffer).TypedAs("VkBuffer"); + SERIALISE_MEMBER(offset); + SERIALISE_MEMBER(range); +} + template void DoSerialise(SerialiserType &ser, DescriptorSetSlot &el) { @@ -3372,9 +3388,9 @@ void DoSerialise(SerialiserType &ser, DescriptorSetSlot &el) ser.SetStructArg( uint64_t(VkDescriptorImageInfoValidity::Sampler | VkDescriptorImageInfoValidity::ImageView)); - SERIALISE_MEMBER(bufferInfo); - SERIALISE_MEMBER(imageInfo); - SERIALISE_MEMBER(texelBufferView); + SERIALISE_MEMBER(bufferInfo).TypedAs("VkDescriptorBufferInfo"); + SERIALISE_MEMBER(imageInfo).TypedAs("VkDescriptorImageInfo"); + SERIALISE_MEMBER(texelBufferView).TypedAs("VkBufferView"); } template diff --git a/renderdoc/driver/vulkan/vk_state.cpp b/renderdoc/driver/vulkan/vk_state.cpp index 7dc81eee7..fa9786cd1 100644 --- a/renderdoc/driver/vulkan/vk_state.cpp +++ b/renderdoc/driver/vulkan/vk_state.cpp @@ -462,7 +462,7 @@ void VulkanRenderState::BindDescriptorSet(const DescSetLayout &descLayout, VkCom push.descriptorType = bind.descriptorType; push.descriptorCount = bind.descriptorCount; - DescriptorSetSlot *slots = setInfo.currentBindings[b]; + DescriptorSetBindingElement *slots = setInfo.currentBindings[b]; if(push.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER || push.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index 7d33da217..50f2c1aaf 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -3502,7 +3502,7 @@ void WrappedVulkan::ApplyPushDescriptorWrites(VkPipelineBindPoint pipelineBindPo const DescSetLayout &desclayout = m_CreationInfo.m_DescSetLayout[descSetLayouts[set]]; - std::vector &bindings = m_DescriptorSetState[setId].currentBindings; + std::vector &bindings = m_DescriptorSetState[setId].currentBindings; ResourceId prevLayout = m_DescriptorSetState[setId].layout; if(prevLayout == ResourceId()) @@ -3523,7 +3523,7 @@ void WrappedVulkan::ApplyPushDescriptorWrites(VkPipelineBindPoint pipelineBindPo RDCASSERT(writeDesc.dstBinding < bindings.size()); - DescriptorSetSlot **bind = &bindings[writeDesc.dstBinding]; + DescriptorSetBindingElement **bind = &bindings[writeDesc.dstBinding]; const DescSetLayout::Binding *layoutBinding = &desclayout.bindings[writeDesc.dstBinding]; uint32_t curIdx = writeDesc.dstArrayElement; diff --git a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp index 4f0fa4530..a214dbc70 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp @@ -653,13 +653,13 @@ void WrappedVulkan::ReplayDescriptorSetWrite(VkDevice device, const VkWriteDescr ObjDisp(device)->UpdateDescriptorSets(Unwrap(device), 1, &unwrapped, 0, NULL); // update our local tracking - std::vector &bindings = + std::vector &bindings = m_DescriptorSetState[GetResID(writeDesc.dstSet)].currentBindings; { RDCASSERT(writeDesc.dstBinding < bindings.size()); - DescriptorSetSlot **bind = &bindings[writeDesc.dstBinding]; + DescriptorSetBindingElement **bind = &bindings[writeDesc.dstBinding]; layoutBinding = &layout.bindings[writeDesc.dstBinding]; curIdx = writeDesc.dstArrayElement; @@ -733,8 +733,10 @@ void WrappedVulkan::ReplayDescriptorSetCopy(VkDevice device, const VkCopyDescrip ResourceId srcSetId = GetResID(copyDesc.srcSet); // update our local tracking - std::vector &dstbindings = m_DescriptorSetState[dstSetId].currentBindings; - std::vector &srcbindings = m_DescriptorSetState[srcSetId].currentBindings; + std::vector &dstbindings = + m_DescriptorSetState[dstSetId].currentBindings; + std::vector &srcbindings = + m_DescriptorSetState[srcSetId].currentBindings; { RDCASSERT(copyDesc.dstBinding < dstbindings.size()); @@ -748,8 +750,8 @@ void WrappedVulkan::ReplayDescriptorSetCopy(VkDevice device, const VkCopyDescrip const DescSetLayout::Binding *layoutSrcBinding = &srclayout.bindings[copyDesc.srcBinding]; const DescSetLayout::Binding *layoutDstBinding = &dstlayout.bindings[copyDesc.dstBinding]; - DescriptorSetSlot **dstbind = &dstbindings[copyDesc.dstBinding]; - DescriptorSetSlot **srcbind = &srcbindings[copyDesc.srcBinding]; + DescriptorSetBindingElement **dstbind = &dstbindings[copyDesc.dstBinding]; + DescriptorSetBindingElement **srcbind = &srcbindings[copyDesc.srcBinding]; uint32_t curDstIdx = copyDesc.dstArrayElement; uint32_t curSrcIdx = copyDesc.srcArrayElement; @@ -986,7 +988,7 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, RDCASSERT(descWrite.dstBinding < record->descInfo->descBindings.size()); - DescriptorSetSlot **binding = &record->descInfo->descBindings[descWrite.dstBinding]; + DescriptorSetBindingElement **binding = &record->descInfo->descBindings[descWrite.dstBinding]; const DescSetLayout::Binding *layoutBinding = &layout.bindings[descWrite.dstBinding]; @@ -1030,7 +1032,7 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, curIdx = 0; } - DescriptorSetSlot &bind = (*binding)[curIdx]; + DescriptorSetBindingElement &bind = (*binding)[curIdx]; bind.RemoveBindRefs(record); @@ -1080,9 +1082,9 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, RDCASSERT(pDescriptorCopies[i].dstBinding < dstrecord->descInfo->descBindings.size()); RDCASSERT(pDescriptorCopies[i].srcBinding < srcrecord->descInfo->descBindings.size()); - DescriptorSetSlot **dstbinding = + DescriptorSetBindingElement **dstbinding = &dstrecord->descInfo->descBindings[pDescriptorCopies[i].dstBinding]; - DescriptorSetSlot **srcbinding = + DescriptorSetBindingElement **srcbinding = &srcrecord->descInfo->descBindings[pDescriptorCopies[i].srcBinding]; const DescSetLayout::Binding *dstlayoutBinding = @@ -1114,7 +1116,7 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, curSrcIdx = 0; } - DescriptorSetSlot &bind = (*dstbinding)[curDstIdx]; + DescriptorSetBindingElement &bind = (*dstbinding)[curDstIdx]; bind.RemoveBindRefs(dstrecord); bind = (*srcbinding)[curSrcIdx]; @@ -1367,7 +1369,7 @@ void WrappedVulkan::vkUpdateDescriptorSetWithTemplate( RDCASSERT(entry.dstBinding < record->descInfo->descBindings.size()); - DescriptorSetSlot **binding = &record->descInfo->descBindings[entry.dstBinding]; + DescriptorSetBindingElement **binding = &record->descInfo->descBindings[entry.dstBinding]; const DescSetLayout::Binding *layoutBinding = &layout.bindings[entry.dstBinding]; @@ -1398,7 +1400,7 @@ void WrappedVulkan::vkUpdateDescriptorSetWithTemplate( const byte *src = (const byte *)pData + entry.offset + entry.stride * d; - DescriptorSetSlot &bind = (*binding)[curIdx]; + DescriptorSetBindingElement &bind = (*binding)[curIdx]; bind.RemoveBindRefs(record); diff --git a/renderdoc/serialise/serialiser.h b/renderdoc/serialise/serialiser.h index 4a93461dc..5d580e3e4 100644 --- a/renderdoc/serialise/serialiser.h +++ b/renderdoc/serialise/serialiser.h @@ -1328,8 +1328,11 @@ public: SDObject *last = current.data.children.back(); last->type.name = name; - for(SDObject *obj : last->data.children) - obj->type.name = name; + if(last->type.basetype == SDBasic::Array) + { + for(SDObject *obj : last->data.children) + obj->type.name = name; + } } }