Expand locking around vulkan queues

* Submits need to be atomic vs starting and ending captures, or a partial submit
  could be included in the capture.
This commit is contained in:
baldurk
2019-09-30 16:24:38 +01:00
parent 2f82e3a23a
commit d3a4f5dc09
5 changed files with 265 additions and 264 deletions
+3 -3
View File
@@ -1489,7 +1489,7 @@ void WrappedVulkan::StartFrameCapture(void *dev, void *wnd)
// will check to see if they need to markdirty or markpendingdirty
// and go into the frame record.
{
SCOPED_LOCK(m_CapTransitionLock);
SCOPED_WRITELOCK(m_CapTransitionLock);
// wait for all work to finish and apply a memory barrier to ensure all memory is visible
for(size_t i = 0; i < m_QueueFamilies.size(); i++)
@@ -1627,7 +1627,7 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
// transition back to IDLE atomically
{
SCOPED_LOCK(m_CapTransitionLock);
SCOPED_WRITELOCK(m_CapTransitionLock);
EndCaptureFrame(backbuffer);
m_State = CaptureState::BackgroundCapturing;
@@ -1969,7 +1969,7 @@ bool WrappedVulkan::DiscardFrameCapture(void *dev, void *wnd)
// transition back to IDLE atomically
{
SCOPED_LOCK(m_CapTransitionLock);
SCOPED_WRITELOCK(m_CapTransitionLock);
m_State = CaptureState::BackgroundCapturing;
+1 -1
View File
@@ -325,7 +325,7 @@ private:
VulkanShaderCache *m_ShaderCache = NULL;
VulkanTextRenderer *m_TextRenderer = NULL;
Threading::CriticalSection m_CapTransitionLock;
Threading::RWLock m_CapTransitionLock;
VulkanDrawcallCallback *m_DrawcallCallback;
@@ -929,68 +929,69 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
Unwrap(device), writeCount, unwrappedWrites, copyCount, unwrappedCopies));
}
bool capframe = false;
{
SCOPED_LOCK(m_CapTransitionLock);
capframe = IsActiveCapturing(m_State);
}
if(capframe)
{
// don't have to mark referenced any of the resources pointed to by the descriptor set - that's
// handled on queue submission by marking ref'd all the current bindings of the sets referenced
// by the cmd buffer
SCOPED_READLOCK(m_CapTransitionLock);
if(IsActiveCapturing(m_State))
{
CACHE_THREAD_SERIALISER();
// don't have to mark referenced any of the resources pointed to by the descriptor set -
// that's
// handled on queue submission by marking ref'd all the current bindings of the sets
// referenced
// by the cmd buffer
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkUpdateDescriptorSets);
Serialise_vkUpdateDescriptorSets(ser, device, writeCount, pDescriptorWrites, copyCount,
pDescriptorCopies);
m_FrameCaptureRecord->AddChunk(scope.Get());
}
// previously we would not mark descriptor set destinations as ref'd here. This is because all
// descriptor sets are implicitly dirty and they're only actually *needed* when bound - we can
// safely skip any updates of unused descriptor sets. However for consistency with template
// updates below, we pull them in here even if they won't technically be needed.
for(uint32_t i = 0; i < writeCount; i++)
{
GetResourceManager()->MarkResourceFrameReferenced(GetResID(pDescriptorWrites[i].dstSet),
eFrameRef_PartialWrite);
}
for(uint32_t i = 0; i < copyCount; i++)
{
// At the same time as ref'ing the source set, we must ref all of its resources (via the
// bindFrameRefs). This is because they must be valid even if the source set is not ever bound
// (and so its bindings aren't pulled in).
//
// 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].dstSet),
eFrameRef_PartialWrite);
GetResourceManager()->MarkResourceFrameReferenced(GetResID(pDescriptorCopies[i].srcSet),
eFrameRef_Read);
VkResourceRecord *setrecord = GetRecord(pDescriptorCopies[i].srcSet);
SCOPED_LOCK(setrecord->descInfo->refLock);
for(auto refit = setrecord->descInfo->bindFrameRefs.begin();
refit != setrecord->descInfo->bindFrameRefs.end(); ++refit)
{
GetResourceManager()->MarkResourceFrameReferenced(refit->first, refit->second.second);
CACHE_THREAD_SERIALISER();
if(refit->second.first & DescriptorSetData::SPARSE_REF_BIT)
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkUpdateDescriptorSets);
Serialise_vkUpdateDescriptorSets(ser, device, writeCount, pDescriptorWrites, copyCount,
pDescriptorCopies);
m_FrameCaptureRecord->AddChunk(scope.Get());
}
// previously we would not mark descriptor set destinations as ref'd here. This is because all
// descriptor sets are implicitly dirty and they're only actually *needed* when bound - we can
// safely skip any updates of unused descriptor sets. However for consistency with template
// updates below, we pull them in here even if they won't technically be needed.
for(uint32_t i = 0; i < writeCount; i++)
{
GetResourceManager()->MarkResourceFrameReferenced(GetResID(pDescriptorWrites[i].dstSet),
eFrameRef_PartialWrite);
}
for(uint32_t i = 0; i < copyCount; i++)
{
// At the same time as ref'ing the source set, we must ref all of its resources (via the
// bindFrameRefs). This is because they must be valid even if the source set is not ever
// bound
// (and so its bindings aren't pulled in).
//
// 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].dstSet),
eFrameRef_PartialWrite);
GetResourceManager()->MarkResourceFrameReferenced(GetResID(pDescriptorCopies[i].srcSet),
eFrameRef_Read);
VkResourceRecord *setrecord = GetRecord(pDescriptorCopies[i].srcSet);
SCOPED_LOCK(setrecord->descInfo->refLock);
for(auto refit = setrecord->descInfo->bindFrameRefs.begin();
refit != setrecord->descInfo->bindFrameRefs.end(); ++refit)
{
VkResourceRecord *record = GetResourceManager()->GetResourceRecord(refit->first);
GetResourceManager()->MarkResourceFrameReferenced(refit->first, refit->second.second);
GetResourceManager()->MarkSparseMapReferenced(record->resInfo);
if(refit->second.first & DescriptorSetData::SPARSE_REF_BIT)
{
VkResourceRecord *record = GetResourceManager()->GetResourceRecord(refit->first);
GetResourceManager()->MarkSparseMapReferenced(record->resInfo);
}
}
}
}
@@ -1360,27 +1361,25 @@ void WrappedVulkan::vkUpdateDescriptorSetWithTemplate(
Unwrap(device), Unwrap(descriptorSet), Unwrap(descriptorUpdateTemplate), memory));
}
bool capframe = false;
{
SCOPED_LOCK(m_CapTransitionLock);
capframe = IsActiveCapturing(m_State);
}
SCOPED_READLOCK(m_CapTransitionLock);
if(capframe)
{
CACHE_THREAD_SERIALISER();
if(IsActiveCapturing(m_State))
{
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkUpdateDescriptorSetWithTemplate);
Serialise_vkUpdateDescriptorSetWithTemplate(ser, device, descriptorSet,
descriptorUpdateTemplate, pData);
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkUpdateDescriptorSetWithTemplate);
Serialise_vkUpdateDescriptorSetWithTemplate(ser, device, descriptorSet,
descriptorUpdateTemplate, pData);
m_FrameCaptureRecord->AddChunk(scope.Get());
m_FrameCaptureRecord->AddChunk(scope.Get());
// mark the destination set and template as referenced
GetResourceManager()->MarkResourceFrameReferenced(GetResID(descriptorSet),
eFrameRef_PartialWrite);
GetResourceManager()->MarkResourceFrameReferenced(GetResID(descriptorUpdateTemplate),
eFrameRef_Read);
// mark the destination set and template as referenced
GetResourceManager()->MarkResourceFrameReferenced(GetResID(descriptorSet),
eFrameRef_PartialWrite);
GetResourceManager()->MarkResourceFrameReferenced(GetResID(descriptorUpdateTemplate),
eFrameRef_Read);
}
}
// need to track descriptor set contents whether capframing or idle
@@ -781,247 +781,249 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
SERIALISE_TIME_CALL(ret = ObjDisp(queue)->QueueSubmit(Unwrap(queue), submitCount,
unwrappedSubmits, Unwrap(fence)));
bool capframe = false;
bool present = false;
{
SCOPED_LOCK(m_CapTransitionLock);
capframe = IsActiveCapturing(m_State);
}
SCOPED_READLOCK(m_CapTransitionLock);
std::set<ResourceId> refdIDs;
bool capframe = IsActiveCapturing(m_State);
VkResourceRecord *queueRecord = GetRecord(queue);
std::set<ResourceId> refdIDs;
for(uint32_t s = 0; s < submitCount; s++)
{
for(uint32_t i = 0; i < pSubmits[s].commandBufferCount; i++)
VkResourceRecord *queueRecord = GetRecord(queue);
for(uint32_t s = 0; s < submitCount; s++)
{
ResourceId cmd = GetResID(pSubmits[s].pCommandBuffers[i]);
VkResourceRecord *record = GetRecord(pSubmits[s].pCommandBuffers[i]);
present |= record->bakedCommands->cmdInfo->present;
for(uint32_t i = 0; i < pSubmits[s].commandBufferCount; i++)
{
SCOPED_LOCK(m_ImageLayoutsLock);
GetResourceManager()->ApplyBarriers(queueRecord->queueFamilyIndex,
record->bakedCommands->cmdInfo->imgbarriers,
m_ImageLayouts);
}
ResourceId cmd = GetResID(pSubmits[s].pCommandBuffers[i]);
for(auto it = record->bakedCommands->cmdInfo->dirtied.begin();
it != record->bakedCommands->cmdInfo->dirtied.end(); ++it)
{
if(GetResourceManager()->HasCurrentResource(*it))
GetResourceManager()->MarkDirtyResource(*it);
}
VkResourceRecord *record = GetRecord(pSubmits[s].pCommandBuffers[i]);
present |= record->bakedCommands->cmdInfo->present;
// with EXT_descriptor_indexing a binding might have been updated after
// vkCmdBindDescriptorSets, so we need to track dirtied here at the last second.
for(auto it = record->bakedCommands->cmdInfo->boundDescSets.begin();
it != record->bakedCommands->cmdInfo->boundDescSets.end(); ++it)
{
VkResourceRecord *setrecord = GetRecord(*it);
SCOPED_LOCK(setrecord->descInfo->refLock);
const std::map<ResourceId, rdcpair<uint32_t, FrameRefType>> &frameRefs =
setrecord->descInfo->bindFrameRefs;
for(auto refit = frameRefs.begin(); refit != frameRefs.end(); ++refit)
{
if(refit->second.second == eFrameRef_PartialWrite ||
refit->second.second == eFrameRef_ReadBeforeWrite)
{
if(GetResourceManager()->HasCurrentResource(refit->first))
GetResourceManager()->MarkDirtyResource(refit->first);
}
SCOPED_LOCK(m_ImageLayoutsLock);
GetResourceManager()->ApplyBarriers(queueRecord->queueFamilyIndex,
record->bakedCommands->cmdInfo->imgbarriers,
m_ImageLayouts);
}
}
if(capframe)
{
// for each bound descriptor set, mark it referenced as well as all resources currently
// bound to it
for(auto it = record->bakedCommands->cmdInfo->dirtied.begin();
it != record->bakedCommands->cmdInfo->dirtied.end(); ++it)
{
if(GetResourceManager()->HasCurrentResource(*it))
GetResourceManager()->MarkDirtyResource(*it);
}
// with EXT_descriptor_indexing a binding might have been updated after
// vkCmdBindDescriptorSets, so we need to track dirtied here at the last second.
for(auto it = record->bakedCommands->cmdInfo->boundDescSets.begin();
it != record->bakedCommands->cmdInfo->boundDescSets.end(); ++it)
{
GetResourceManager()->MarkResourceFrameReferenced(GetResID(*it), eFrameRef_Read);
VkResourceRecord *setrecord = GetRecord(*it);
SCOPED_LOCK(setrecord->descInfo->refLock);
for(auto refit = setrecord->descInfo->bindFrameRefs.begin();
refit != setrecord->descInfo->bindFrameRefs.end(); ++refit)
const std::map<ResourceId, rdcpair<uint32_t, FrameRefType>> &frameRefs =
setrecord->descInfo->bindFrameRefs;
for(auto refit = frameRefs.begin(); refit != frameRefs.end(); ++refit)
{
refdIDs.insert(refit->first);
GetResourceManager()->MarkResourceFrameReferenced(refit->first, refit->second.second);
if(refit->second.first & DescriptorSetData::SPARSE_REF_BIT)
if(refit->second.second == eFrameRef_PartialWrite ||
refit->second.second == eFrameRef_ReadBeforeWrite)
{
VkResourceRecord *sparserecord = GetResourceManager()->GetResourceRecord(refit->first);
GetResourceManager()->MarkSparseMapReferenced(sparserecord->resInfo);
if(GetResourceManager()->HasCurrentResource(refit->first))
GetResourceManager()->MarkDirtyResource(refit->first);
}
}
GetResourceManager()->MergeReferencedImages(setrecord->descInfo->bindImgRefs);
GetResourceManager()->MergeReferencedMemory(setrecord->descInfo->bindMemRefs);
}
for(auto it = record->bakedCommands->cmdInfo->sparse.begin();
it != record->bakedCommands->cmdInfo->sparse.end(); ++it)
GetResourceManager()->MarkSparseMapReferenced(*it);
// pull in frame refs from this baked command buffer
record->bakedCommands->AddResourceReferences(GetResourceManager());
record->bakedCommands->AddReferencedIDs(refdIDs);
GetResourceManager()->MergeReferencedImages(record->bakedCommands->cmdInfo->imgFrameRefs);
GetResourceManager()->MergeReferencedMemory(record->bakedCommands->cmdInfo->memFrameRefs);
// ref the parent command buffer's alloc record, this will pull in the cmd buffer pool
GetResourceManager()->MarkResourceFrameReferenced(
record->cmdInfo->allocRecord->GetResourceID(), eFrameRef_Read);
for(size_t sub = 0; sub < record->bakedCommands->cmdInfo->subcmds.size(); sub++)
if(capframe)
{
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddResourceReferences(
GetResourceManager());
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddReferencedIDs(refdIDs);
GetResourceManager()->MergeReferencedImages(
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->cmdInfo->imgFrameRefs);
GetResourceManager()->MergeReferencedMemory(
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->cmdInfo->memFrameRefs);
// for each bound descriptor set, mark it referenced as well as all resources currently
// bound to it
for(auto it = record->bakedCommands->cmdInfo->boundDescSets.begin();
it != record->bakedCommands->cmdInfo->boundDescSets.end(); ++it)
{
GetResourceManager()->MarkResourceFrameReferenced(GetResID(*it), eFrameRef_Read);
VkResourceRecord *setrecord = GetRecord(*it);
SCOPED_LOCK(setrecord->descInfo->refLock);
for(auto refit = setrecord->descInfo->bindFrameRefs.begin();
refit != setrecord->descInfo->bindFrameRefs.end(); ++refit)
{
refdIDs.insert(refit->first);
GetResourceManager()->MarkResourceFrameReferenced(refit->first, refit->second.second);
if(refit->second.first & DescriptorSetData::SPARSE_REF_BIT)
{
VkResourceRecord *sparserecord =
GetResourceManager()->GetResourceRecord(refit->first);
GetResourceManager()->MarkSparseMapReferenced(sparserecord->resInfo);
}
}
GetResourceManager()->MergeReferencedImages(setrecord->descInfo->bindImgRefs);
GetResourceManager()->MergeReferencedMemory(setrecord->descInfo->bindMemRefs);
}
for(auto it = record->bakedCommands->cmdInfo->sparse.begin();
it != record->bakedCommands->cmdInfo->sparse.end(); ++it)
GetResourceManager()->MarkSparseMapReferenced(*it);
// pull in frame refs from this baked command buffer
record->bakedCommands->AddResourceReferences(GetResourceManager());
record->bakedCommands->AddReferencedIDs(refdIDs);
GetResourceManager()->MergeReferencedImages(record->bakedCommands->cmdInfo->imgFrameRefs);
GetResourceManager()->MergeReferencedMemory(record->bakedCommands->cmdInfo->memFrameRefs);
// ref the parent command buffer's alloc record, this will pull in the cmd buffer pool
GetResourceManager()->MarkResourceFrameReferenced(
record->bakedCommands->cmdInfo->subcmds[sub]->cmdInfo->allocRecord->GetResourceID(),
eFrameRef_Read);
record->cmdInfo->allocRecord->GetResourceID(), eFrameRef_Read);
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddRef();
}
{
SCOPED_LOCK(m_CmdBufferRecordsLock);
m_CmdBufferRecords.push_back(record->bakedCommands);
for(size_t sub = 0; sub < record->bakedCommands->cmdInfo->subcmds.size(); sub++)
m_CmdBufferRecords.push_back(record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands);
{
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddResourceReferences(
GetResourceManager());
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddReferencedIDs(refdIDs);
GetResourceManager()->MergeReferencedImages(
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->cmdInfo->imgFrameRefs);
GetResourceManager()->MergeReferencedMemory(
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->cmdInfo->memFrameRefs);
GetResourceManager()->MarkResourceFrameReferenced(
record->bakedCommands->cmdInfo->subcmds[sub]->cmdInfo->allocRecord->GetResourceID(),
eFrameRef_Read);
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddRef();
}
{
SCOPED_LOCK(m_CmdBufferRecordsLock);
m_CmdBufferRecords.push_back(record->bakedCommands);
for(size_t sub = 0; sub < record->bakedCommands->cmdInfo->subcmds.size(); sub++)
m_CmdBufferRecords.push_back(
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands);
}
record->bakedCommands->AddRef();
}
record->bakedCommands->AddRef();
record->cmdInfo->dirtied.clear();
}
}
if(capframe)
{
GetResourceManager()->MarkResourceFrameReferenced(GetResID(queue), eFrameRef_Read);
if(fence != VK_NULL_HANDLE)
GetResourceManager()->MarkResourceFrameReferenced(GetResID(fence), eFrameRef_Read);
std::vector<VkResourceRecord *> maps;
{
SCOPED_LOCK(m_CoherentMapsLock);
maps = m_CoherentMaps;
}
record->cmdInfo->dirtied.clear();
}
}
if(capframe)
{
GetResourceManager()->MarkResourceFrameReferenced(GetResID(queue), eFrameRef_Read);
if(fence != VK_NULL_HANDLE)
GetResourceManager()->MarkResourceFrameReferenced(GetResID(fence), eFrameRef_Read);
std::vector<VkResourceRecord *> maps;
{
SCOPED_LOCK(m_CoherentMapsLock);
maps = m_CoherentMaps;
}
for(auto it = maps.begin(); it != maps.end(); ++it)
{
VkResourceRecord *record = *it;
MemMapState &state = *record->memMapState;
// potential persistent map
if(state.mapCoherent && state.mappedPtr && !state.mapFlushed)
for(auto it = maps.begin(); it != maps.end(); ++it)
{
// only need to flush memory that could affect this submitted batch of work
if(refdIDs.find(record->GetResourceID()) == refdIDs.end())
{
RDCDEBUG("Map of memory %llu not referenced in this queue - not flushing",
record->GetResourceID());
continue;
}
VkResourceRecord *record = *it;
MemMapState &state = *record->memMapState;
size_t diffStart = 0, diffEnd = 0;
bool found = true;
// potential persistent map
if(state.mapCoherent && state.mappedPtr && !state.mapFlushed)
{
// only need to flush memory that could affect this submitted batch of work
if(refdIDs.find(record->GetResourceID()) == refdIDs.end())
{
RDCDEBUG("Map of memory %llu not referenced in this queue - not flushing",
record->GetResourceID());
continue;
}
size_t diffStart = 0, diffEnd = 0;
bool found = true;
// enabled as this is necessary for programs with very large coherent mappings
// (> 1GB) as otherwise more than a couple of vkQueueSubmit calls leads to vast
// memory allocation. There might still be bugs lurking in here though
#if 1
// this causes vkFlushMappedMemoryRanges call to allocate and copy to refData
// from serialised buffer. We want to copy *precisely* the serialised data,
// otherwise there is a gap in time between serialising out a snapshot of
// the buffer and whenever we then copy into the ref data, e.g. below.
// during this time, data could be written to the buffer and it won't have
// been caught in the serialised snapshot, and if it doesn't change then
// it *also* won't be caught in any future FindDiffRange() calls.
//
// Likewise once refData is allocated, the call below will also update it
// with the data serialised out for the same reason.
//
// Note: it's still possible that data is being written to by the
// application while it's being serialised out in the snapshot below. That
// is OK, since the application is responsible for ensuring it's not writing
// data that would be needed by the GPU in this submit. As long as the
// refdata we use for future use is identical to what was serialised, we
// shouldn't miss anything
state.needRefData = true;
// this causes vkFlushMappedMemoryRanges call to allocate and copy to refData
// from serialised buffer. We want to copy *precisely* the serialised data,
// otherwise there is a gap in time between serialising out a snapshot of
// the buffer and whenever we then copy into the ref data, e.g. below.
// during this time, data could be written to the buffer and it won't have
// been caught in the serialised snapshot, and if it doesn't change then
// it *also* won't be caught in any future FindDiffRange() calls.
//
// Likewise once refData is allocated, the call below will also update it
// with the data serialised out for the same reason.
//
// Note: it's still possible that data is being written to by the
// application while it's being serialised out in the snapshot below. That
// is OK, since the application is responsible for ensuring it's not writing
// data that would be needed by the GPU in this submit. As long as the
// refdata we use for future use is identical to what was serialised, we
// shouldn't miss anything
state.needRefData = true;
// if we have a previous set of data, compare.
// otherwise just serialise it all
if(state.refData)
found = FindDiffRange((byte *)state.mappedPtr, state.refData, (size_t)state.mapSize,
diffStart, diffEnd);
else
// if we have a previous set of data, compare.
// otherwise just serialise it all
if(state.refData)
found = FindDiffRange((byte *)state.mappedPtr, state.refData, (size_t)state.mapSize,
diffStart, diffEnd);
else
#endif
diffEnd = (size_t)state.mapSize;
if(found)
{
// MULTIDEVICE should find the device for this queue.
// MULTIDEVICE only want to flush maps associated with this queue
VkDevice dev = GetDev();
diffEnd = (size_t)state.mapSize;
if(found)
{
RDCLOG("Persistent map flush forced for %llu (%llu -> %llu)", record->GetResourceID(),
(uint64_t)diffStart, (uint64_t)diffEnd);
VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, NULL,
(VkDeviceMemory)(uint64_t)record->Resource,
state.mapOffset + diffStart, diffEnd - diffStart};
vkFlushMappedMemoryRanges(dev, 1, &range);
state.mapFlushed = false;
}
// MULTIDEVICE should find the device for this queue.
// MULTIDEVICE only want to flush maps associated with this queue
VkDevice dev = GetDev();
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
}
else
{
RDCDEBUG("Persistent map flush not needed for %llu", record->GetResourceID());
{
RDCLOG("Persistent map flush forced for %llu (%llu -> %llu)", record->GetResourceID(),
(uint64_t)diffStart, (uint64_t)diffEnd);
VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, NULL,
(VkDeviceMemory)(uint64_t)record->Resource,
state.mapOffset + diffStart, diffEnd - diffStart};
vkFlushMappedMemoryRanges(dev, 1, &range);
state.mapFlushed = false;
}
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
}
else
{
RDCDEBUG("Persistent map flush not needed for %llu", record->GetResourceID());
}
}
}
}
{
CACHE_THREAD_SERIALISER();
{
CACHE_THREAD_SERIALISER();
ser.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkQueueSubmit);
Serialise_vkQueueSubmit(ser, queue, submitCount, pSubmits, fence);
ser.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkQueueSubmit);
Serialise_vkQueueSubmit(ser, queue, submitCount, pSubmits, fence);
m_FrameCaptureRecord->AddChunk(scope.Get());
}
m_FrameCaptureRecord->AddChunk(scope.Get());
}
for(uint32_t s = 0; s < submitCount; s++)
{
for(uint32_t sem = 0; sem < pSubmits[s].waitSemaphoreCount; sem++)
GetResourceManager()->MarkResourceFrameReferenced(
GetResID(pSubmits[s].pWaitSemaphores[sem]), eFrameRef_Read);
for(uint32_t s = 0; s < submitCount; s++)
{
for(uint32_t sem = 0; sem < pSubmits[s].waitSemaphoreCount; sem++)
GetResourceManager()->MarkResourceFrameReferenced(
GetResID(pSubmits[s].pWaitSemaphores[sem]), eFrameRef_Read);
for(uint32_t sem = 0; sem < pSubmits[s].signalSemaphoreCount; sem++)
GetResourceManager()->MarkResourceFrameReferenced(
GetResID(pSubmits[s].pSignalSemaphores[sem]), eFrameRef_Read);
for(uint32_t sem = 0; sem < pSubmits[s].signalSemaphoreCount; sem++)
GetResourceManager()->MarkResourceFrameReferenced(
GetResID(pSubmits[s].pSignalSemaphores[sem]), eFrameRef_Read);
}
}
}
@@ -634,7 +634,7 @@ void WrappedVulkan::vkUnmapMemory(VkDevice device, VkDeviceMemory mem)
bool capframe = false;
{
SCOPED_LOCK(m_CapTransitionLock);
SCOPED_READLOCK(m_CapTransitionLock);
capframe = IsActiveCapturing(m_State);
if(!capframe)
@@ -783,7 +783,7 @@ VkResult WrappedVulkan::vkFlushMappedMemoryRanges(VkDevice device, uint32_t memR
{
bool capframe = false;
{
SCOPED_LOCK(m_CapTransitionLock);
SCOPED_READLOCK(m_CapTransitionLock);
capframe = IsActiveCapturing(m_State);
}