From 0f0ade44aea119ccf9e2276abfbfc2a263dc69a0 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 13 Nov 2015 10:23:46 +0100 Subject: [PATCH] Implement descriptor set copies --- .../vulkan/wrappers/vk_descriptor_funcs.cpp | 157 ++++++++++++++++-- 1 file changed, 143 insertions(+), 14 deletions(-) diff --git a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp index b756586c5..f603a282f 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp @@ -385,7 +385,7 @@ bool WrappedVulkan::Serialise_vkUpdateDescriptorSets( // will be invalid with some missing handles. It's safe though to just skip this // update as we only get here if it's never used. - // if a set was never bind, it will have been omitted and we just drop any writes to it + // if a set was never bound, it will have been omitted and we just drop any writes to it bool valid = (writeDesc.destSet != VK_NULL_HANDLE); if(!valid) @@ -445,21 +445,37 @@ bool WrappedVulkan::Serialise_vkUpdateDescriptorSets( { RDCASSERT(writeDesc.destBinding < bindings.size()); - RDCASSERT(writeDesc.destArrayElement == 0); VkDescriptorInfo *bind = bindings[writeDesc.destBinding]; for(uint32_t d=0; d < writeDesc.count; d++) - bind[d] = writeDesc.pDescriptors[d]; + bind[writeDesc.destArrayElement + d] = writeDesc.pDescriptors[d]; } } } else { + // if a set was never bound, it will have been omitted and we just drop any copies to it + if(copyDesc.destSet == VK_NULL_HANDLE || copyDesc.srcSet == VK_NULL_HANDLE) + return true; + ObjDisp(device)->UpdateDescriptorSets(Unwrap(device), 0, NULL, 1, ©Desc); - - // don't want to implement this blindly - RDCUNIMPLEMENTED("Copying descriptors not implemented"); + + // update our local tracking + vector &dstbindings = m_DescriptorSetState[GetResourceManager()->GetNonDispWrapper(copyDesc.destSet)->id].currentBindings; + vector &srcbindings = m_DescriptorSetState[GetResourceManager()->GetNonDispWrapper(copyDesc.srcSet)->id].currentBindings; + + { + RDCASSERT(copyDesc.destBinding < dstbindings.size()); + RDCASSERT(copyDesc.srcBinding < srcbindings.size()); + + VkDescriptorInfo *dstbind = dstbindings[copyDesc.destBinding]; + VkDescriptorInfo *srcbind = srcbindings[copyDesc.srcBinding]; + + for(uint32_t d=0; d < copyDesc.count; d++) + dstbind[copyDesc.destArrayElement+d] = srcbind[copyDesc.srcArrayElement+d]; + } + } delete[] writeDesc.pDescriptors; // delete serialised descriptors array @@ -557,12 +573,33 @@ void WrappedVulkan::vkUpdateDescriptorSets( m_FrameCaptureRecord->AddChunk(scope.Get()); } - // as long as descriptor sets are forced to have initial states, we don't have to mark them ref'd for - // write here. The reason being that as long as we only mark them as ref'd when they're actually bound, - // we can safely skip the ref here and it means any descriptor set updates of descriptor sets that are - // never used in the frame can be ignored. + // Like writes we don't have to mark the written descriptor set as used because unless it's bound somewhere + // we don't need it anyway. However we DO have to mark the source set as used because it doesn't have to + // be bound to still be needed (think about if the dest set is bound somewhere after this copy - what refs + // the source set?). + // At the same time as ref'ing the source set, we must ref all of its resources (via the bindFrameRefs). + // We just ref all rather than looking at only the copied sets to keep things simple. + // This does mean a slightly conservative ref'ing if the dest set doesn't end up getting bound, but we only + // do this during frame capture so it's not too bad. //GetResourceManager()->MarkResourceFrameReferenced(GetResID(pDescriptorCopies[i].destSet), eFrameRef_Write); - //GetResourceManager()->MarkResourceFrameReferenced(GetResID(pDescriptorCopies[i].srcSet), eFrameRef_Read); + + { + GetResourceManager()->MarkResourceFrameReferenced(GetResID(pDescriptorCopies[i].srcSet), eFrameRef_Read); + + VkResourceRecord *setrecord = GetRecord(pDescriptorCopies[i].srcSet); + + for(auto refit = setrecord->descInfo->bindFrameRefs.begin(); refit != setrecord->descInfo->bindFrameRefs.end(); ++refit) + { + GetResourceManager()->MarkResourceFrameReferenced(refit->first, refit->second.second); + + if(refit->second.first & DescriptorSetData::SPARSE_REF_BIT) + { + VkResourceRecord *record = GetResourceManager()->GetResourceRecord(refit->first); + + GetResourceManager()->MarkSparseMapReferenced(record->sparseInfo); + } + } + } } } @@ -673,10 +710,102 @@ void WrappedVulkan::vkUpdateDescriptorSets( } } - if(copyCount > 0) + // this is almost identical to the above loop, except that instead of sourcing the descriptors + // from the writedescriptor struct, we source it from our stored bindings on the source + // descrpitor set + + for(uint32_t i=0; i < copyCount; i++) { - // don't want to implement this blindly - RDCUNIMPLEMENTED("Copying descriptors not implemented"); + VkResourceRecord *dstrecord = GetRecord(pDescriptorCopies[i].destSet); + RDCASSERT(dstrecord->descInfo && dstrecord->descInfo->layout); + const DescSetLayout &layout = *dstrecord->descInfo->layout; + + VkResourceRecord *srcrecord = GetRecord(pDescriptorCopies[i].srcSet); + + RDCASSERT(pDescriptorCopies[i].destBinding < dstrecord->descInfo->descBindings.size()); + RDCASSERT(pDescriptorCopies[i].srcBinding < srcrecord->descInfo->descBindings.size()); + + VkDescriptorInfo *dstbinding = dstrecord->descInfo->descBindings[pDescriptorCopies[i].destBinding]; + VkDescriptorInfo *srcbinding = srcrecord->descInfo->descBindings[pDescriptorCopies[i].srcBinding]; + + FrameRefType ref = eFrameRef_Write; + + switch(layout.bindings[pDescriptorCopies[i].destBinding].descriptorType) + { + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + ref = eFrameRef_Read; + break; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + ref = eFrameRef_Write; + break; + default: + RDCERR("Unexpected descriptor type"); + } + + for(uint32_t d=0; d < pDescriptorCopies[i].count; d++) + { + VkDescriptorInfo &bind = dstbinding[pDescriptorCopies[i].destArrayElement + d]; + + if(bind.bufferView != VK_NULL_HANDLE) + { + dstrecord->RemoveBindFrameRef(GetResID(bind.bufferView)); + if(GetRecord(bind.bufferView)->baseResource != ResourceId()) + dstrecord->RemoveBindFrameRef(GetRecord(bind.bufferView)->baseResource); + } + if(bind.imageView != VK_NULL_HANDLE) + { + dstrecord->RemoveBindFrameRef(GetResID(bind.imageView)); + dstrecord->RemoveBindFrameRef(GetRecord(bind.imageView)->baseResource); + if(GetRecord(bind.imageView)->baseResourceMem != ResourceId()) + dstrecord->RemoveBindFrameRef(GetRecord(bind.imageView)->baseResourceMem); + } + if(bind.sampler != VK_NULL_HANDLE) + { + dstrecord->RemoveBindFrameRef(GetResID(bind.sampler)); + } + if(bind.bufferInfo.buffer != VK_NULL_HANDLE) + { + dstrecord->RemoveBindFrameRef(GetResID(bind.bufferInfo.buffer)); + if(GetRecord(bind.bufferInfo.buffer)->baseResource != ResourceId()) + dstrecord->RemoveBindFrameRef(GetRecord(bind.bufferInfo.buffer)->baseResource); + } + + bind = srcbinding[pDescriptorCopies[i].srcArrayElement + d]; + + if(bind.bufferView != VK_NULL_HANDLE) + { + dstrecord->AddBindFrameRef(GetResID(bind.bufferView), eFrameRef_Read, GetRecord(bind.bufferView)->sparseInfo != NULL); + if(GetRecord(bind.bufferView)->baseResource != ResourceId()) + dstrecord->AddBindFrameRef(GetRecord(bind.bufferView)->baseResource, ref); + } + if(bind.imageView != VK_NULL_HANDLE) + { + dstrecord->AddBindFrameRef(GetResID(bind.imageView), eFrameRef_Read, GetRecord(bind.imageView)->sparseInfo != NULL); + dstrecord->AddBindFrameRef(GetRecord(bind.imageView)->baseResource, ref); + if(GetRecord(bind.imageView)->baseResourceMem != ResourceId()) + dstrecord->AddBindFrameRef(GetRecord(bind.imageView)->baseResourceMem, eFrameRef_Read); + } + if(bind.sampler != VK_NULL_HANDLE) + { + dstrecord->AddBindFrameRef(GetResID(bind.sampler), ref); + } + if(bind.bufferInfo.buffer != VK_NULL_HANDLE) + { + dstrecord->AddBindFrameRef(GetResID(bind.bufferInfo.buffer), eFrameRef_Read, GetRecord(bind.bufferInfo.buffer)->sparseInfo != NULL); + if(GetRecord(bind.bufferInfo.buffer)->baseResource != ResourceId()) + dstrecord->AddBindFrameRef(GetRecord(bind.bufferInfo.buffer)->baseResource, ref); + } + } } + } }