mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Add new image tracking to capture side
One notable high-level change is the behaviour of `StartFrameCapture`. The previous implementation serialised the image state when `StartFrameCapture` was called. The new implementation just sets the "old" (beginnin go frame) image state (layouts/queue families) to be the current state at this point; at `EndFrameCapture` the full image state is serialised, including both the "old" (beginning of frame) and "new" (end of frame). Change-Id: I04c18c16a97e065c7a7d0edf058ba3f4803dcf45
This commit is contained in:
committed by
Baldur Karlsson
parent
888abc6a55
commit
1d44386724
+102
-115
@@ -1599,110 +1599,10 @@ void WrappedVulkan::FirstFrame()
|
||||
template <typename SerialiserType>
|
||||
bool WrappedVulkan::Serialise_BeginCaptureFrame(SerialiserType &ser)
|
||||
{
|
||||
rdcarray<VkImageMemoryBarrier> imgBarriers;
|
||||
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock); // not needed on replay, but harmless also
|
||||
GetResourceManager()->SerialiseImageStates(ser, m_ImageLayouts, imgBarriers);
|
||||
}
|
||||
|
||||
SCOPED_LOCK(m_ImageStatesLock);
|
||||
GetResourceManager()->SerialiseImageStates(ser, m_ImageStates);
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
// for the first load, promote any PREINITIALIZED images to GENERAL here since we treat
|
||||
// PREINIT as if it was GENERAL.
|
||||
for(auto it = m_ImageLayouts.begin(); it != m_ImageLayouts.end(); ++it)
|
||||
{
|
||||
if(!it->second.isMemoryBound)
|
||||
continue;
|
||||
|
||||
for(auto stit = it->second.subresourceStates.begin();
|
||||
stit != it->second.subresourceStates.end(); ++stit)
|
||||
{
|
||||
if(stit->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED &&
|
||||
GetResourceManager()->HasCurrentResource(it->first))
|
||||
{
|
||||
VkImage img = GetResourceManager()->GetCurrentHandle<VkImage>(it->first);
|
||||
|
||||
{
|
||||
VkImageMemoryBarrier barrier = {};
|
||||
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
barrier.srcQueueFamilyIndex = m_QueueFamilyIdx;
|
||||
barrier.dstQueueFamilyIndex = m_QueueFamilyIdx;
|
||||
barrier.image = Unwrap(img);
|
||||
barrier.subresourceRange = stit->subresourceRange;
|
||||
|
||||
imgBarriers.push_back(barrier);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!imgBarriers.empty())
|
||||
{
|
||||
VkMarkerRegion region("Frame-start barriers");
|
||||
|
||||
for(size_t i = 0; i < imgBarriers.size(); i++)
|
||||
{
|
||||
// sanitise the layouts before passing to Vulkan
|
||||
if(!IsLoading(m_State))
|
||||
SanitiseOldImageLayout(imgBarriers[i].oldLayout);
|
||||
SanitiseNewImageLayout(imgBarriers[i].newLayout);
|
||||
|
||||
imgBarriers[i].srcAccessMask = MakeAccessMask(imgBarriers[i].oldLayout);
|
||||
imgBarriers[i].dstAccessMask = MakeAccessMask(imgBarriers[i].newLayout);
|
||||
}
|
||||
|
||||
if(SeparateDepthStencil())
|
||||
CombineDepthStencilLayouts(imgBarriers);
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
|
||||
|
||||
#if ENABLED(SINGLE_FLUSH_VALIDATE)
|
||||
for(size_t i = 0; i < imgBarriers.size(); i++)
|
||||
{
|
||||
VkCommandBuffer cmd = GetNextCmd();
|
||||
|
||||
VkResult vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), src_stages, dest_stages, false, 0, NULL, 0,
|
||||
NULL, 1, &imgBarriers[i]);
|
||||
|
||||
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
SubmitCmds();
|
||||
}
|
||||
#else
|
||||
VkCommandBuffer cmd = GetNextCmd();
|
||||
|
||||
VkResult vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), src_stages, dest_stages, false, 0, NULL, 0,
|
||||
NULL, (uint32_t)imgBarriers.size(), &imgBarriers[0]);
|
||||
|
||||
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
SubmitCmds();
|
||||
#endif
|
||||
}
|
||||
// don't need to flush here
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1762,20 +1662,19 @@ void WrappedVulkan::StartFrameCapture(void *dev, void *wnd)
|
||||
}
|
||||
|
||||
GetResourceManager()->PrepareInitialContents();
|
||||
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
|
||||
SubmitCmds();
|
||||
FlushQ();
|
||||
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
|
||||
|
||||
RDCDEBUG("Attempting capture");
|
||||
m_FrameCaptureRecord->DeleteChunks();
|
||||
|
||||
{
|
||||
CACHE_THREAD_SERIALISER();
|
||||
|
||||
SCOPED_SERIALISE_CHUNK(SystemChunk::CaptureBegin);
|
||||
|
||||
Serialise_BeginCaptureFrame(ser);
|
||||
|
||||
// need to hold onto this as it must come right after the capture chunk,
|
||||
// before any command buffers
|
||||
m_HeaderChunk = scope.Get();
|
||||
SCOPED_LOCK(m_ImageStatesLock);
|
||||
for(auto it = m_ImageStates.begin(); it != m_ImageStates.end(); ++it)
|
||||
{
|
||||
it->second.LockWrite()->BeginCapture();
|
||||
}
|
||||
}
|
||||
|
||||
m_State = CaptureState::ActiveCapturing;
|
||||
@@ -2129,7 +2028,6 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
|
||||
|
||||
GetResourceManager()->Serialise_InitialContentsNeeded(ser);
|
||||
GetResourceManager()->InsertDeviceMemoryRefs(ser);
|
||||
GetResourceManager()->InsertImageRefs(ser);
|
||||
|
||||
{
|
||||
SCOPED_SERIALISE_CHUNK(SystemChunk::CaptureScope, 16);
|
||||
@@ -2137,6 +2035,14 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
|
||||
Serialise_CaptureScope(ser);
|
||||
}
|
||||
|
||||
{
|
||||
WriteSerialiser &captureBeginSer = GetThreadSerialiser();
|
||||
ScopedChunk scope(captureBeginSer, SystemChunk::CaptureBegin);
|
||||
|
||||
Serialise_BeginCaptureFrame(captureBeginSer);
|
||||
|
||||
m_HeaderChunk = scope.Get();
|
||||
}
|
||||
m_HeaderChunk->Write(ser);
|
||||
|
||||
// don't need to lock access to m_CmdBufferRecords as we are no longer
|
||||
@@ -3128,8 +3034,8 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
|
||||
return Serialise_vkCmdSetLineStippleEXT(ser, VK_NULL_HANDLE, 0, 0);
|
||||
case VulkanChunk::ImageRefs:
|
||||
{
|
||||
rdcarray<ImgRefsPair> data;
|
||||
return GetResourceManager()->Serialise_ImageRefs(ser, data);
|
||||
SCOPED_LOCK(m_ImageStatesLock);
|
||||
return GetResourceManager()->Serialise_ImageRefs(ser, m_ImageStates);
|
||||
}
|
||||
case VulkanChunk::vkGetSemaphoreCounterValue:
|
||||
return Serialise_vkGetSemaphoreCounterValue(ser, VK_NULL_HANDLE, VK_NULL_HANDLE, NULL);
|
||||
@@ -4191,6 +4097,87 @@ void WrappedVulkan::InsertCommandQueueFamily(ResourceId cmdId, uint32_t queueFam
|
||||
{
|
||||
m_commandQueueFamilies[cmdId] = queueFamilyIndex;
|
||||
}
|
||||
LockedImageStateRef WrappedVulkan::FindImageState(ResourceId id)
|
||||
{
|
||||
SCOPED_LOCK(m_ImageStatesLock);
|
||||
auto it = m_ImageStates.find(id);
|
||||
if(it != m_ImageStates.end())
|
||||
return it->second.LockWrite();
|
||||
else
|
||||
return LockedImageStateRef();
|
||||
}
|
||||
|
||||
LockedConstImageStateRef WrappedVulkan::FindConstImageState(ResourceId id)
|
||||
{
|
||||
SCOPED_LOCK(m_ImageStatesLock);
|
||||
auto it = m_ImageStates.find(id);
|
||||
if(it != m_ImageStates.end())
|
||||
return it->second.LockRead();
|
||||
else
|
||||
return LockedConstImageStateRef();
|
||||
}
|
||||
|
||||
LockedImageStateRef WrappedVulkan::InsertImageState(VkImage wrappedHandle, ResourceId id,
|
||||
const ImageInfo &info, FrameRefType refType,
|
||||
bool *inserted)
|
||||
{
|
||||
SCOPED_LOCK(m_ImageStatesLock);
|
||||
auto it = m_ImageStates.find(id);
|
||||
if(it != m_ImageStates.end())
|
||||
{
|
||||
if(inserted != NULL)
|
||||
*inserted = false;
|
||||
return it->second.LockWrite();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(inserted != NULL)
|
||||
*inserted = true;
|
||||
it = m_ImageStates.insert({id, LockingImageState(wrappedHandle, info, refType)}).first;
|
||||
return it->second.LockWrite();
|
||||
}
|
||||
}
|
||||
|
||||
bool WrappedVulkan::EraseImageState(ResourceId id)
|
||||
{
|
||||
SCOPED_LOCK(m_ImageStatesLock);
|
||||
auto it = m_ImageStates.find(id);
|
||||
if(it != m_ImageStates.end())
|
||||
{
|
||||
m_ImageStates.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WrappedVulkan::UpdateImageStates(const std::map<ResourceId, ImageState> &dstStates)
|
||||
{
|
||||
SCOPED_LOCK(m_ImageStatesLock);
|
||||
auto it = m_ImageStates.begin();
|
||||
auto dstIt = dstStates.begin();
|
||||
ImageTransitionInfo info = GetImageTransitionInfo();
|
||||
while(dstIt != dstStates.end())
|
||||
{
|
||||
if(it == m_ImageStates.end() || dstIt->first < it->first)
|
||||
{
|
||||
it = m_ImageStates
|
||||
.insert({dstIt->first,
|
||||
LockingImageState(dstIt->second.wrappedHandle, dstIt->second.GetImageInfo(),
|
||||
info.GetDefaultRefType())})
|
||||
.first;
|
||||
dstIt->second.InitialState(*it->second.LockWrite());
|
||||
}
|
||||
else if(it->first < dstIt->first)
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
it->second.LockWrite()->Merge(dstIt->second, info);
|
||||
++dstIt;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLED(ENABLE_UNIT_TESTS)
|
||||
|
||||
|
||||
@@ -422,6 +422,9 @@ private:
|
||||
rdcarray<uint32_t> m_QueueFamilyCounts;
|
||||
rdcarray<uint32_t> m_QueueFamilyIndices;
|
||||
|
||||
ImageBarrierSequence m_setupImageBarriers;
|
||||
ImageBarrierSequence m_cleanupImageBarriers;
|
||||
|
||||
// a small amount of helper code during capture for handling resources on different queues in init
|
||||
// states
|
||||
struct ExternalQueue
|
||||
@@ -573,6 +576,7 @@ private:
|
||||
uint32_t subpass = 0;
|
||||
} state;
|
||||
|
||||
std::map<ResourceId, ImageState> imageStates;
|
||||
rdcarray<rdcpair<ResourceId, ImageRegionState>> imgbarriers;
|
||||
|
||||
ResourceId pushDescriptorID[2][64];
|
||||
@@ -754,8 +758,11 @@ private:
|
||||
// used on replay side to track the queue family of command buffers and pools
|
||||
std::map<ResourceId, uint32_t> m_commandQueueFamilies;
|
||||
|
||||
// used both on capture and replay side to track image layouts. Only locked
|
||||
// used both on capture and replay side to track image state. Only locked
|
||||
// in capture
|
||||
std::map<ResourceId, LockingImageState> m_ImageStates;
|
||||
Threading::CriticalSection m_ImageStatesLock;
|
||||
|
||||
std::map<ResourceId, ImageLayouts> m_ImageLayouts;
|
||||
Threading::CriticalSection m_ImageLayoutsLock;
|
||||
|
||||
@@ -1052,6 +1059,18 @@ public:
|
||||
VkDriverInfo GetDriverInfo() { return m_PhysicalDeviceData.driverInfo; }
|
||||
uint32_t FindCommandQueueFamily(ResourceId cmdId);
|
||||
void InsertCommandQueueFamily(ResourceId cmdId, uint32_t queueFamilyIndex);
|
||||
LockedImageStateRef FindImageState(ResourceId id);
|
||||
LockedConstImageStateRef FindConstImageState(ResourceId id);
|
||||
LockedImageStateRef InsertImageState(VkImage wrappedHandle, ResourceId id, const ImageInfo &info,
|
||||
FrameRefType refType, bool *inserted = NULL);
|
||||
bool EraseImageState(ResourceId id);
|
||||
void UpdateImageStates(const std::map<ResourceId, ImageState> &dstStates);
|
||||
|
||||
inline ImageTransitionInfo GetImageTransitionInfo() const
|
||||
{
|
||||
return ImageTransitionInfo(m_State, m_QueueFamilyIdx);
|
||||
}
|
||||
|
||||
// Device initialization
|
||||
|
||||
IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkCreateInstance, const VkInstanceCreateInfo *pCreateInfo,
|
||||
|
||||
@@ -94,9 +94,6 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res)
|
||||
const ResourceInfo &resInfo = *im->record->resInfo;
|
||||
const ImageInfo &imageInfo = resInfo.imageInfo;
|
||||
|
||||
if(!GetResourceManager()->FindImgRefs(id))
|
||||
GetResourceManager()->AddImageFrameRefs(id, imageInfo);
|
||||
|
||||
if(resInfo.IsSparse())
|
||||
{
|
||||
// if the image is sparse we have to do a different kind of initial state prepare,
|
||||
@@ -104,24 +101,23 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res)
|
||||
return Prepare_SparseInitialState((WrappedVkImage *)res);
|
||||
}
|
||||
|
||||
ImageLayouts *layout = NULL;
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
layout = &m_ImageLayouts[im->id];
|
||||
}
|
||||
|
||||
if(layout->queueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL ||
|
||||
layout->queueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT)
|
||||
{
|
||||
RDCWARN("Image %s in external/foreign queue family, initial contents impossible to fetch.",
|
||||
ToStr(im->id).c_str());
|
||||
return true;
|
||||
}
|
||||
LockedImageStateRef state = FindImageState(im->id);
|
||||
|
||||
// if the image has no memory bound, nothing is to be fetched
|
||||
if(!layout->isMemoryBound)
|
||||
if(!state || !state->isMemoryBound)
|
||||
return true;
|
||||
|
||||
for(auto it = state->subresourceStates.begin(); it != state->subresourceStates.end(); ++it)
|
||||
{
|
||||
if(it->state().newQueueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT ||
|
||||
it->state().newQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL)
|
||||
{
|
||||
// This image has a subresource owned by an external/foreign queue family, so we can't fetch
|
||||
// the initial contents.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
VkDevice d = GetDev();
|
||||
// INITSTATEBATCH
|
||||
VkCommandBuffer cmd = GetNextCmd();
|
||||
@@ -274,18 +270,17 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res)
|
||||
|
||||
VkImageAspectFlags aspectFlags = FormatImageAspects(imageInfo.format);
|
||||
|
||||
rdcarray<VkImageMemoryBarrier> setupBarriers, cleanupBarriers;
|
||||
bool extQCleanup = false;
|
||||
ImageBarrierSequence setupBarriers, cleanupBarriers;
|
||||
|
||||
VkImageLayout readingLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
if(arrayIm != VK_NULL_HANDLE)
|
||||
readingLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
TempTransition(ToWrappedHandle<VkImage>(res), readingLayout,
|
||||
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT, setupBarriers,
|
||||
cleanupBarriers, extQCleanup);
|
||||
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
|
||||
|
||||
state->TempTransition(m_QueueFamilyIdx, readingLayout,
|
||||
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT, setupBarriers,
|
||||
cleanupBarriers, GetImageTransitionInfo());
|
||||
InlineSetupImageBarriers(cmd, setupBarriers);
|
||||
m_setupImageBarriers.Merge(setupBarriers);
|
||||
if(arrayIm != VK_NULL_HANDLE)
|
||||
{
|
||||
VkImageMemoryBarrier arrayimBarrier = {
|
||||
@@ -414,18 +409,16 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res)
|
||||
RDCASSERTMSG("buffer wasn't sized sufficiently!", bufOffset <= bufInfo.size, bufOffset,
|
||||
readbackmem.size, imageInfo.extent, imageInfo.format, numLayers,
|
||||
imageInfo.levelCount);
|
||||
|
||||
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
|
||||
InlineCleanupImageBarriers(cmd, cleanupBarriers);
|
||||
m_cleanupImageBarriers.Merge(cleanupBarriers);
|
||||
|
||||
vkr = ObjDisp(d)->EndCommandBuffer(Unwrap(cmd));
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
// INITSTATEBATCH
|
||||
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
|
||||
SubmitCmds();
|
||||
FlushQ();
|
||||
|
||||
if(extQCleanup)
|
||||
SubmitExtQBarriers(~0U, cleanupBarriers);
|
||||
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
|
||||
|
||||
ObjDisp(d)->DestroyBuffer(Unwrap(d), Unwrap(dstBuf), NULL);
|
||||
GetResourceManager()->ReleaseWrappedResource(dstBuf);
|
||||
@@ -1217,7 +1210,7 @@ void WrappedVulkan::Create_InitialState(ResourceId id, WrappedVkRes *live, bool
|
||||
|
||||
if(m_ImageLayouts.find(liveid) == m_ImageLayouts.end())
|
||||
{
|
||||
RDCERR("Couldn't find image info for %s", ToStr(id).c_str());
|
||||
RDCERR("Couldn't find image info for %llu", id);
|
||||
GetResourceManager()->SetInitialContents(
|
||||
id, VkInitialContents(type, VkInitialContents::ClearColorImage));
|
||||
return;
|
||||
|
||||
@@ -33,60 +33,6 @@
|
||||
#define TRDBG(...)
|
||||
#endif
|
||||
|
||||
static void AddAndMerge(rdcarray<VkImageMemoryBarrier> &barriers,
|
||||
rdcarray<rdcpair<ResourceId, ImageRegionState>> &states,
|
||||
const VkImageMemoryBarrier &newBarrier,
|
||||
const rdcpair<ResourceId, ImageRegionState> &newState)
|
||||
{
|
||||
bool add_new = true;
|
||||
|
||||
// see if we can combine our incoming barrier into the last one by expanding the
|
||||
// subresource range. Note we iterate over array layers first, then mips.
|
||||
if(!barriers.empty() && barriers.back().oldLayout == newBarrier.oldLayout &&
|
||||
barriers.back().newLayout == newBarrier.newLayout)
|
||||
{
|
||||
// if it's the same array layer and we're the next mip on, combine
|
||||
if(barriers.back().subresourceRange.aspectMask == newBarrier.subresourceRange.aspectMask &&
|
||||
barriers.back().subresourceRange.baseArrayLayer == newBarrier.subresourceRange.baseArrayLayer &&
|
||||
barriers.back().subresourceRange.layerCount == newBarrier.subresourceRange.layerCount &&
|
||||
barriers.back().subresourceRange.baseMipLevel + barriers.back().subresourceRange.levelCount ==
|
||||
newBarrier.subresourceRange.baseMipLevel)
|
||||
{
|
||||
barriers.back().subresourceRange.levelCount += newBarrier.subresourceRange.levelCount;
|
||||
states.back().second.subresourceRange.levelCount += newBarrier.subresourceRange.levelCount;
|
||||
add_new = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(add_new)
|
||||
{
|
||||
barriers.push_back(newBarrier);
|
||||
states.push_back(newState);
|
||||
}
|
||||
|
||||
// we might have added the last mip(s) in an array layer, allowing us to combine with
|
||||
// the previous array layer. Check for that
|
||||
if(barriers.size() >= 2)
|
||||
{
|
||||
VkImageMemoryBarrier &a = barriers[barriers.size() - 2];
|
||||
VkImageMemoryBarrier &b = barriers[barriers.size() - 1];
|
||||
|
||||
// if the mips are identical and we're the next array layer on, combine
|
||||
if(a.oldLayout == b.oldLayout && a.newLayout == b.newLayout &&
|
||||
a.subresourceRange.aspectMask == b.subresourceRange.aspectMask &&
|
||||
a.subresourceRange.baseMipLevel == b.subresourceRange.baseMipLevel &&
|
||||
a.subresourceRange.levelCount == b.subresourceRange.levelCount &&
|
||||
a.subresourceRange.baseArrayLayer + a.subresourceRange.layerCount ==
|
||||
b.subresourceRange.baseArrayLayer)
|
||||
{
|
||||
a.subresourceRange.layerCount += b.subresourceRange.layerCount;
|
||||
states[states.size() - 2].second.subresourceRange.layerCount += b.subresourceRange.layerCount;
|
||||
barriers.pop_back();
|
||||
states.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SrcBarrierType>
|
||||
void VulkanResourceManager::RecordSingleBarrier(
|
||||
rdcarray<rdcpair<ResourceId, ImageRegionState>> &dststates, ResourceId id,
|
||||
@@ -319,165 +265,133 @@ void VulkanResourceManager::MergeBarriers(rdcarray<rdcpair<ResourceId, ImageRegi
|
||||
|
||||
template <typename SerialiserType>
|
||||
void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser,
|
||||
std::map<ResourceId, ImageLayouts> &states,
|
||||
rdcarray<VkImageMemoryBarrier> &barriers)
|
||||
std::map<ResourceId, LockingImageState> &states)
|
||||
{
|
||||
SERIALISE_ELEMENT_LOCAL(NumImages, (uint32_t)states.size());
|
||||
|
||||
auto srcit = states.begin();
|
||||
|
||||
rdcarray<rdcpair<ResourceId, ImageRegionState>> vec;
|
||||
|
||||
std::set<ResourceId> updatedState;
|
||||
|
||||
for(uint32_t i = 0; i < NumImages; i++)
|
||||
{
|
||||
SERIALISE_ELEMENT_LOCAL(Image, (ResourceId)(srcit->first)).TypedAs("VkImage"_lit);
|
||||
SERIALISE_ELEMENT_LOCAL(ImageState, (ImageLayouts)(srcit->second));
|
||||
|
||||
ResourceId liveid;
|
||||
if(IsReplayingAndReading() && HasLiveResource(Image))
|
||||
liveid = GetLiveID(Image);
|
||||
|
||||
if(IsReplayingAndReading() && liveid != ResourceId())
|
||||
if(ser.IsWriting())
|
||||
{
|
||||
updatedState.insert(liveid);
|
||||
LockedImageStateRef lockedState = srcit->second.LockWrite();
|
||||
::ImageState &ImageState = *lockedState;
|
||||
SERIALISE_ELEMENT(ImageState);
|
||||
++srcit;
|
||||
}
|
||||
else
|
||||
{
|
||||
ImageState imageState;
|
||||
|
||||
VkImageMemoryBarrier t = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
|
||||
|
||||
t.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
t.image = Unwrap(GetCurrentHandle<VkImage>(liveid));
|
||||
t.srcQueueFamilyIndex = ImageState.queueFamilyIndex;
|
||||
t.dstQueueFamilyIndex = ImageState.queueFamilyIndex;
|
||||
m_Core->RemapQueueFamilyIndices(t.srcQueueFamilyIndex, t.dstQueueFamilyIndex);
|
||||
if(t.dstQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED)
|
||||
t.dstQueueFamilyIndex = t.srcQueueFamilyIndex = m_Core->GetQueueFamilyIndex();
|
||||
|
||||
for(ImageRegionState &state : ImageState.subresourceStates)
|
||||
if(ser.VersionLess(0x11))
|
||||
{
|
||||
state.dstQueueFamilyIndex = t.dstQueueFamilyIndex;
|
||||
|
||||
t.newLayout = state.newLayout;
|
||||
t.subresourceRange = state.subresourceRange;
|
||||
|
||||
auto stit = states.find(liveid);
|
||||
|
||||
if(stit == states.end() || stit->second.isMemoryBound)
|
||||
ImageLayouts imageLayouts;
|
||||
{
|
||||
AddAndMerge(barriers, vec, t, make_rdcpair(liveid, state));
|
||||
ImageLayouts &ImageState = imageLayouts;
|
||||
SERIALISE_ELEMENT(ImageState);
|
||||
}
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
if(imageLayouts.imageInfo.extent.depth > 1)
|
||||
imageLayouts.imageInfo.imageType = VK_IMAGE_TYPE_3D;
|
||||
|
||||
imageState = ImageState(VK_NULL_HANDLE, imageLayouts.imageInfo, eFrameRef_Unknown);
|
||||
|
||||
rdcarray<ImageSubresourceStateForRange> subresourceStates;
|
||||
subresourceStates.reserve(imageLayouts.subresourceStates.size());
|
||||
|
||||
for(ImageRegionState &st : imageLayouts.subresourceStates)
|
||||
{
|
||||
ImageSubresourceStateForRange p;
|
||||
p.range = st.subresourceRange;
|
||||
p.range.sliceCount = imageLayouts.imageInfo.extent.depth;
|
||||
p.state.oldQueueFamilyIndex = st.dstQueueFamilyIndex;
|
||||
p.state.newQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
p.state.oldLayout = st.newLayout;
|
||||
p.state.newLayout = imageState.GetImageInfo().initialLayout;
|
||||
p.state.refType = eFrameRef_Unknown;
|
||||
subresourceStates.push_back(p);
|
||||
}
|
||||
|
||||
imageState.subresourceStates.FromArray(subresourceStates);
|
||||
imageState.maxRefType = eFrameRef_Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ser.IsWriting())
|
||||
srcit++;
|
||||
}
|
||||
|
||||
// on replay, any images from the capture which didn't get touched above were created mid-frame so
|
||||
// we reset them to their initialLayout.
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
for(auto it = states.begin(); it != states.end(); ++it)
|
||||
{
|
||||
ResourceId liveid = it->first;
|
||||
|
||||
if(GetOriginalID(liveid) != liveid && updatedState.find(liveid) == updatedState.end())
|
||||
else
|
||||
{
|
||||
VkImageMemoryBarrier t = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
|
||||
t.image = Unwrap(GetCurrentHandle<VkImage>(liveid));
|
||||
t.srcQueueFamilyIndex = it->second.queueFamilyIndex;
|
||||
t.dstQueueFamilyIndex = it->second.queueFamilyIndex;
|
||||
m_Core->RemapQueueFamilyIndices(t.srcQueueFamilyIndex, t.dstQueueFamilyIndex);
|
||||
if(t.dstQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED)
|
||||
t.dstQueueFamilyIndex = t.srcQueueFamilyIndex = m_Core->GetQueueFamilyIndex();
|
||||
|
||||
for(ImageRegionState &state : it->second.subresourceStates)
|
||||
{
|
||||
state.dstQueueFamilyIndex = t.dstQueueFamilyIndex;
|
||||
|
||||
t.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
if(it->second.initialLayout == VK_IMAGE_LAYOUT_PREINITIALIZED)
|
||||
t.oldLayout = state.newLayout;
|
||||
state.newLayout = t.newLayout = it->second.initialLayout;
|
||||
|
||||
t.subresourceRange = state.subresourceRange;
|
||||
|
||||
auto stit = states.find(liveid);
|
||||
|
||||
if(stit == states.end() || stit->second.isMemoryBound)
|
||||
::ImageState &ImageState = imageState;
|
||||
SERIALISE_ELEMENT(ImageState);
|
||||
}
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
imageState.newQueueFamilyTransfers.clear();
|
||||
for(auto it = imageState.subresourceStates.begin();
|
||||
it != imageState.subresourceStates.end(); ++it)
|
||||
{
|
||||
AddAndMerge(barriers, vec, t, make_rdcpair(liveid, state));
|
||||
// Set the current image state (`newLayout`, `newQueueFamilyIndex`, `refType`) to the
|
||||
// initial image state, so that calling `ResetToOldState` will move the image from the
|
||||
// initial state to the state it was in at the beginning of the capture.
|
||||
ImageSubresourceState &state = it->state();
|
||||
state.newLayout = imageState.GetImageInfo().initialLayout;
|
||||
state.newQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(HasLiveResource(Image))
|
||||
{
|
||||
ResourceId liveid = GetLiveID(Image);
|
||||
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
auto stit = states.find(liveid);
|
||||
if(stit == states.end())
|
||||
{
|
||||
imageState.subresourceStates.Unsplit();
|
||||
states.insert({liveid, LockingImageState(imageState)});
|
||||
}
|
||||
else
|
||||
{
|
||||
auto st = stit->second.LockWrite();
|
||||
st->MergeCaptureBeginState(imageState);
|
||||
st->subresourceStates.Unsplit();
|
||||
}
|
||||
}
|
||||
else if(IsActiveReplaying(m_State))
|
||||
{
|
||||
auto current = states.find(liveid)->second.LockRead();
|
||||
auto stit = states.find(liveid);
|
||||
for(auto subit = imageState.subresourceStates.begin();
|
||||
subit != imageState.subresourceStates.end(); ++subit)
|
||||
{
|
||||
uint32_t aspectIndex = 0;
|
||||
for(auto it = ImageAspectFlagIter::begin(imageState.GetImageInfo().Aspects());
|
||||
it != ImageAspectFlagIter::end() && ((*it) & subit->range().aspectMask) == 0;
|
||||
++it, ++aspectIndex)
|
||||
{
|
||||
}
|
||||
auto currentSub = current->subresourceStates.SubresourceValue(
|
||||
aspectIndex, subit->range().baseMipLevel, subit->range().baseArrayLayer,
|
||||
subit->range().baseDepthSlice);
|
||||
RDCASSERT(currentSub.refType == subit->state().refType ||
|
||||
subit->state().refType == eFrameRef_Unknown);
|
||||
RDCASSERT(currentSub.oldLayout == subit->state().oldLayout);
|
||||
RDCASSERT(currentSub.oldQueueFamilyIndex == subit->state().oldQueueFamilyIndex ||
|
||||
subit->state().oldQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we don't have to specify a queue here because all of the images have a specific queue above
|
||||
ApplyBarriers(VK_QUEUE_FAMILY_IGNORED, vec, states);
|
||||
|
||||
for(size_t i = 0; i < vec.size(); i++)
|
||||
{
|
||||
if(barriers[i].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED)
|
||||
barriers[i].oldLayout = vec[i].second.oldLayout;
|
||||
}
|
||||
|
||||
// erase any do-nothing barriers
|
||||
for(size_t i = 0; i < barriers.size();)
|
||||
{
|
||||
VkImageMemoryBarrier &b = barriers[i];
|
||||
|
||||
if(b.oldLayout == UNKNOWN_PREV_IMG_LAYOUT)
|
||||
b.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
if(b.oldLayout == b.newLayout)
|
||||
barriers.erase(i);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
// try to merge images that have been split up by subresource but are now all in the same state
|
||||
// again. Don't do this for depth/stencil resources in case the aspects are split
|
||||
for(auto it = states.begin(); it != states.end(); ++it)
|
||||
{
|
||||
ImageLayouts &layouts = it->second;
|
||||
const ImageInfo &imageInfo = layouts.imageInfo;
|
||||
|
||||
if(layouts.subresourceStates.size() > 1 &&
|
||||
layouts.subresourceStates[0].subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT &&
|
||||
layouts.subresourceStates.size() == size_t(imageInfo.layerCount) * size_t(imageInfo.levelCount))
|
||||
{
|
||||
VkImageLayout layout = layouts.subresourceStates[0].newLayout;
|
||||
|
||||
bool allIdentical = true;
|
||||
|
||||
for(size_t i = 0; i < layouts.subresourceStates.size(); i++)
|
||||
{
|
||||
if(layouts.subresourceStates[i].newLayout != layout)
|
||||
{
|
||||
allIdentical = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(allIdentical)
|
||||
{
|
||||
layouts.subresourceStates.erase(1, ~0U);
|
||||
layouts.subresourceStates[0].subresourceRange.baseArrayLayer = 0;
|
||||
layouts.subresourceStates[0].subresourceRange.baseMipLevel = 0;
|
||||
layouts.subresourceStates[0].subresourceRange.layerCount = imageInfo.layerCount;
|
||||
layouts.subresourceStates[0].subresourceRange.levelCount = imageInfo.levelCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void VulkanResourceManager::SerialiseImageStates(ReadSerialiser &ser,
|
||||
std::map<ResourceId, ImageLayouts> &states,
|
||||
rdcarray<VkImageMemoryBarrier> &barriers);
|
||||
template void VulkanResourceManager::SerialiseImageStates(WriteSerialiser &ser,
|
||||
std::map<ResourceId, ImageLayouts> &states,
|
||||
rdcarray<VkImageMemoryBarrier> &barriers);
|
||||
template void VulkanResourceManager::SerialiseImageStates(
|
||||
WriteSerialiser &ser, std::map<ResourceId, LockingImageState> &states);
|
||||
template void VulkanResourceManager::SerialiseImageStates(
|
||||
ReadSerialiser &ser, std::map<ResourceId, LockingImageState> &states);
|
||||
|
||||
template <class SerialiserType>
|
||||
void DoSerialise(SerialiserType &ser, MemRefInterval &el)
|
||||
@@ -575,28 +489,46 @@ template bool VulkanResourceManager::Serialise_DeviceMemoryRefs(ReadSerialiser &
|
||||
template bool VulkanResourceManager::Serialise_DeviceMemoryRefs(WriteSerialiser &ser,
|
||||
rdcarray<MemRefInterval> &data);
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool VulkanResourceManager::Serialise_ImageRefs(SerialiserType &ser, rdcarray<ImgRefsPair> &data)
|
||||
bool VulkanResourceManager::Serialise_ImageRefs(ReadSerialiser &ser,
|
||||
std::map<ResourceId, LockingImageState> &states)
|
||||
{
|
||||
rdcarray<ImgRefsPair> data;
|
||||
SERIALISE_ELEMENT(data);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
// unpack data into m_ImgFrameRefs
|
||||
for(auto it = data.begin(); it != data.end(); it++)
|
||||
m_ImgFrameRefs.insert({it->image, it->imgRefs});
|
||||
// unpack data into states
|
||||
for(auto it = data.begin(); it != data.end(); ++it)
|
||||
{
|
||||
if(!HasLiveResource(it->image))
|
||||
continue;
|
||||
ResourceId liveid = GetLiveID(it->image);
|
||||
|
||||
auto stit = states.find(liveid);
|
||||
if(stit == states.end())
|
||||
{
|
||||
RDCWARN("Found ImgRefs for unknown image");
|
||||
}
|
||||
else
|
||||
{
|
||||
LockedImageStateRef imst = stit->second.LockWrite();
|
||||
imst->subresourceStates.FromImgRefs(it->imgRefs);
|
||||
FrameRefType maxRefType = eFrameRef_None;
|
||||
for(auto subit = imst->subresourceStates.begin(); subit != imst->subresourceStates.end();
|
||||
++subit)
|
||||
{
|
||||
maxRefType = ComposeFrameRefsDisjoint(maxRefType, subit->state().refType);
|
||||
}
|
||||
imst->maxRefType = maxRefType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool VulkanResourceManager::Serialise_ImageRefs(ReadSerialiser &ser,
|
||||
rdcarray<ImgRefsPair> &imageRefs);
|
||||
template bool VulkanResourceManager::Serialise_ImageRefs(WriteSerialiser &ser,
|
||||
rdcarray<ImgRefsPair> &imageRefs);
|
||||
|
||||
void VulkanResourceManager::InsertDeviceMemoryRefs(WriteSerialiser &ser)
|
||||
{
|
||||
rdcarray<MemRefInterval> data;
|
||||
@@ -617,24 +549,6 @@ void VulkanResourceManager::InsertDeviceMemoryRefs(WriteSerialiser &ser)
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanResourceManager::InsertImageRefs(WriteSerialiser &ser)
|
||||
{
|
||||
rdcarray<ImgRefsPair> data;
|
||||
data.reserve(m_ImgFrameRefs.size());
|
||||
size_t sizeEstimate = 32;
|
||||
|
||||
for(auto it = m_ImgFrameRefs.begin(); it != m_ImgFrameRefs.end(); it++)
|
||||
{
|
||||
data.push_back({it->first, it->second});
|
||||
sizeEstimate += sizeof(ImgRefsPair) + sizeof(FrameRefType) * it->second.rangeRefs.size();
|
||||
}
|
||||
|
||||
{
|
||||
SCOPED_SERIALISE_CHUNK(VulkanChunk::ImageRefs, sizeEstimate);
|
||||
Serialise_ImageRefs(ser, data);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanResourceManager::MarkSparseMapReferenced(ResourceInfo *sparse)
|
||||
{
|
||||
if(sparse == NULL)
|
||||
@@ -857,6 +771,43 @@ void VulkanResourceManager::ApplyBarriers(uint32_t queueFamilyIndex,
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanResourceManager::RecordBarriers(std::map<ResourceId, ImageState> &states,
|
||||
uint32_t queueFamilyIndex, uint32_t numBarriers,
|
||||
const VkImageMemoryBarrier *barriers)
|
||||
{
|
||||
TRDBG("Recording %u barriers", numBarriers);
|
||||
|
||||
for(uint32_t ti = 0; ti < numBarriers; ti++)
|
||||
{
|
||||
const VkImageMemoryBarrier &t = barriers[ti];
|
||||
|
||||
ResourceId id = IsReplayMode(m_State) ? GetNonDispWrapper(t.image)->id : GetResID(t.image);
|
||||
|
||||
if(id == ResourceId())
|
||||
{
|
||||
RDCERR("Couldn't get ID for image in barrier");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto stateIt = states.find(id);
|
||||
if(stateIt == states.end())
|
||||
{
|
||||
LockedConstImageStateRef globalState = m_Core->FindConstImageState(id);
|
||||
if(!globalState)
|
||||
{
|
||||
RDCERR("Recording barrier for unknown image: %s", ToStr(id).c_str());
|
||||
continue;
|
||||
}
|
||||
stateIt = states.insert({id, globalState->CommandBufferInitialState()}).first;
|
||||
}
|
||||
|
||||
ImageState &state = stateIt->second;
|
||||
state.RecordBarrier(t, queueFamilyIndex, m_Core->GetImageTransitionInfo());
|
||||
}
|
||||
|
||||
TRDBG("Post-record, there are %u states", (uint32_t)states.size());
|
||||
}
|
||||
|
||||
ResourceId VulkanResourceManager::GetFirstIDForHandle(uint64_t handle)
|
||||
{
|
||||
for(auto it = m_CurrentResourceMap.begin(); it != m_CurrentResourceMap.end(); ++it)
|
||||
@@ -883,19 +834,6 @@ ResourceId VulkanResourceManager::GetFirstIDForHandle(uint64_t handle)
|
||||
return ResourceId();
|
||||
}
|
||||
|
||||
void VulkanResourceManager::MarkImageFrameReferenced(const VkResourceRecord *img,
|
||||
const ImageRange &range, FrameRefType refType)
|
||||
{
|
||||
MarkImageFrameReferenced(img->GetResourceID(), img->resInfo->imageInfo, range, refType);
|
||||
}
|
||||
|
||||
void VulkanResourceManager::MarkImageFrameReferenced(ResourceId img, const ImageInfo &imageInfo,
|
||||
const ImageRange &range, FrameRefType refType)
|
||||
{
|
||||
FrameRefType maxRef = MarkImageReferenced(m_ImgFrameRefs, img, imageInfo, range, refType);
|
||||
MarkResourceFrameReferenced(img, maxRef, ComposeFrameRefsDisjoint);
|
||||
}
|
||||
|
||||
void VulkanResourceManager::MarkMemoryFrameReferenced(ResourceId mem, VkDeviceSize offset,
|
||||
VkDeviceSize size, FrameRefType refType)
|
||||
{
|
||||
@@ -910,23 +848,6 @@ void VulkanResourceManager::AddMemoryFrameRefs(ResourceId mem)
|
||||
m_MemFrameRefs.insert({mem, MemRefs()});
|
||||
}
|
||||
|
||||
void VulkanResourceManager::AddImageFrameRefs(ResourceId img, const ImageInfo &imageInfo)
|
||||
{
|
||||
m_ImgFrameRefs.insert({img, ImgRefs(imageInfo)});
|
||||
}
|
||||
|
||||
void VulkanResourceManager::MergeReferencedImages(std::map<ResourceId, ImgRefs> &imgRefs)
|
||||
{
|
||||
for(auto j = imgRefs.begin(); j != imgRefs.end(); j++)
|
||||
{
|
||||
auto i = m_ImgFrameRefs.find(j->first);
|
||||
if(i == m_ImgFrameRefs.end())
|
||||
m_ImgFrameRefs.insert(*j);
|
||||
else
|
||||
i->second.Merge(j->second);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanResourceManager::MergeReferencedMemory(std::map<ResourceId, MemRefs> &memRefs)
|
||||
{
|
||||
SCOPED_LOCK(m_Lock);
|
||||
@@ -941,11 +862,6 @@ void VulkanResourceManager::MergeReferencedMemory(std::map<ResourceId, MemRefs>
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanResourceManager::ClearReferencedImages()
|
||||
{
|
||||
m_ImgFrameRefs.clear();
|
||||
}
|
||||
|
||||
void VulkanResourceManager::ClearReferencedMemory()
|
||||
{
|
||||
SCOPED_LOCK(m_Lock);
|
||||
|
||||
@@ -264,18 +264,18 @@ public:
|
||||
rdcarray<rdcpair<ResourceId, ImageRegionState> > &states,
|
||||
std::map<ResourceId, ImageLayouts> &layouts);
|
||||
|
||||
void RecordBarriers(std::map<ResourceId, ImageState> &states, uint32_t queueFamilyIndex,
|
||||
uint32_t numBarriers, const VkImageMemoryBarrier *barriers);
|
||||
|
||||
template <typename SerialiserType>
|
||||
void SerialiseImageStates(SerialiserType &ser, std::map<ResourceId, ImageLayouts> &states,
|
||||
rdcarray<VkImageMemoryBarrier> &barriers);
|
||||
void SerialiseImageStates(SerialiserType &ser, std::map<ResourceId, LockingImageState> &states);
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool Serialise_DeviceMemoryRefs(SerialiserType &ser, rdcarray<MemRefInterval> &data);
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool Serialise_ImageRefs(SerialiserType &ser, rdcarray<ImgRefsPair> &data);
|
||||
bool Serialise_ImageRefs(ReadSerialiser &ser, std::map<ResourceId, LockingImageState> &states);
|
||||
|
||||
void InsertDeviceMemoryRefs(WriteSerialiser &ser);
|
||||
void InsertImageRefs(WriteSerialiser &ser);
|
||||
|
||||
ResourceId GetID(WrappedVkRes *res)
|
||||
{
|
||||
@@ -422,18 +422,11 @@ public:
|
||||
|
||||
void SetInternalResource(ResourceId id);
|
||||
|
||||
void MarkImageFrameReferenced(const VkResourceRecord *img, const ImageRange &range,
|
||||
FrameRefType refType);
|
||||
void MarkImageFrameReferenced(ResourceId img, const ImageInfo &imageInfo, const ImageRange &range,
|
||||
FrameRefType refType);
|
||||
void MarkMemoryFrameReferenced(ResourceId mem, VkDeviceSize start, VkDeviceSize end,
|
||||
FrameRefType refType);
|
||||
void AddMemoryFrameRefs(ResourceId mem);
|
||||
void AddImageFrameRefs(ResourceId img, const ImageInfo &imageInfo);
|
||||
|
||||
void MergeReferencedMemory(std::map<ResourceId, MemRefs> &memRefs);
|
||||
void MergeReferencedImages(std::map<ResourceId, ImgRefs> &imgRefs);
|
||||
void ClearReferencedImages();
|
||||
void ClearReferencedMemory();
|
||||
MemRefs *FindMemRefs(ResourceId mem);
|
||||
ImgRefs *FindImgRefs(ResourceId img);
|
||||
|
||||
@@ -3442,8 +3442,10 @@ void VkResourceRecord::MarkImageFrameReferenced(VkResourceRecord *img, const Ima
|
||||
if(img->resInfo && img->resInfo->IsSparse())
|
||||
cmdInfo->sparse.insert(img->resInfo);
|
||||
|
||||
FrameRefType maxRef =
|
||||
MarkImageReferenced(cmdInfo->imgFrameRefs, id, img->resInfo->imageInfo, range, refType);
|
||||
ImageSubresourceRange range2(range);
|
||||
|
||||
FrameRefType maxRef = MarkImageReferenced(cmdInfo->imageStates, id, img->resInfo->imageInfo,
|
||||
range2, pool->queueFamilyIndex, refType);
|
||||
|
||||
// maintain the reference type of the image itself as the maximum reference type of any
|
||||
// subresource
|
||||
@@ -3465,18 +3467,33 @@ void VkResourceRecord::MarkImageViewFrameReferenced(VkResourceRecord *view, cons
|
||||
if(refType != eFrameRef_Read && refType != eFrameRef_None)
|
||||
cmdInfo->dirtied.insert(img);
|
||||
|
||||
ImageRange imgRange;
|
||||
ImageSubresourceRange imgRange;
|
||||
imgRange.aspectMask = view->viewRange.aspectMask;
|
||||
imgRange.baseMipLevel = view->viewRange.baseMipLevel + range.baseMipLevel;
|
||||
imgRange.levelCount = range.levelCount;
|
||||
imgRange.baseArrayLayer = view->viewRange.baseArrayLayer + range.baseArrayLayer;
|
||||
imgRange.layerCount = range.layerCount;
|
||||
imgRange.offset = range.offset;
|
||||
imgRange.extent = range.extent;
|
||||
imgRange.viewType = view->viewRange.viewType();
|
||||
|
||||
FrameRefType maxRef =
|
||||
MarkImageReferenced(cmdInfo->imgFrameRefs, img, view->resInfo->imageInfo, imgRange, refType);
|
||||
imgRange.baseMipLevel = range.baseMipLevel;
|
||||
imgRange.levelCount = range.levelCount;
|
||||
SanitiseLevelRange(imgRange.baseMipLevel, imgRange.levelCount, view->viewRange.levelCount());
|
||||
imgRange.baseMipLevel += view->viewRange.baseMipLevel;
|
||||
|
||||
if(view->resInfo->imageInfo.imageType == VK_IMAGE_TYPE_3D &&
|
||||
view->viewRange.viewType() != VK_IMAGE_VIEW_TYPE_3D)
|
||||
{
|
||||
imgRange.baseDepthSlice = range.baseArrayLayer;
|
||||
imgRange.sliceCount = range.layerCount;
|
||||
SanitiseLayerRange(imgRange.baseDepthSlice, imgRange.sliceCount, view->viewRange.layerCount());
|
||||
imgRange.baseDepthSlice += view->viewRange.baseArrayLayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
imgRange.baseArrayLayer = range.baseArrayLayer;
|
||||
imgRange.layerCount = range.layerCount;
|
||||
SanitiseLayerRange(imgRange.baseArrayLayer, imgRange.layerCount, view->viewRange.layerCount());
|
||||
imgRange.baseArrayLayer += view->viewRange.baseArrayLayer;
|
||||
}
|
||||
imgRange.Sanitise(view->resInfo->imageInfo);
|
||||
|
||||
FrameRefType maxRef = MarkImageReferenced(cmdInfo->imageStates, img, view->resInfo->imageInfo,
|
||||
imgRange, pool->queueFamilyIndex, refType);
|
||||
|
||||
// maintain the reference type of the image itself as the maximum reference type of any
|
||||
// subresource
|
||||
@@ -3854,6 +3871,20 @@ void ResourceInfo::Update(uint32_t numBindings, const VkSparseMemoryBind *pBindi
|
||||
}
|
||||
}
|
||||
|
||||
FrameRefType MarkImageReferenced(std::map<ResourceId, ImageState> &imageStates, ResourceId img,
|
||||
const ImageInfo &imageInfo, const ImageSubresourceRange &range,
|
||||
uint32_t queueFamilyIndex, FrameRefType refType)
|
||||
{
|
||||
if(refType == eFrameRef_None)
|
||||
return refType;
|
||||
auto it = imageStates.find(img);
|
||||
if(it == imageStates.end())
|
||||
it = imageStates.insert({img, ImageState(VK_NULL_HANDLE, imageInfo, refType)}).first;
|
||||
it->second.Update(range, ImageSubresourceState(queueFamilyIndex, UNKNOWN_PREV_IMG_LAYOUT, refType),
|
||||
ComposeFrameRefs);
|
||||
return it->second.maxRefType;
|
||||
}
|
||||
|
||||
#if ENABLED(ENABLE_UNIT_TESTS)
|
||||
|
||||
#undef None
|
||||
|
||||
@@ -998,6 +998,7 @@ struct ResourceInfo
|
||||
|
||||
struct MemRefs;
|
||||
struct ImgRefs;
|
||||
struct ImageState;
|
||||
|
||||
struct CmdBufferRecordingInfo
|
||||
{
|
||||
@@ -1007,8 +1008,6 @@ struct CmdBufferRecordingInfo
|
||||
VkResourceRecord *framebuffer = NULL;
|
||||
VkResourceRecord *allocRecord = NULL;
|
||||
|
||||
rdcarray<rdcpair<ResourceId, ImageRegionState> > imgbarriers;
|
||||
|
||||
// sparse resources referenced by this command buffer (at submit time
|
||||
// need to go through the sparse mapping and reference all memory)
|
||||
std::set<ResourceInfo *> sparse;
|
||||
@@ -1028,7 +1027,8 @@ struct CmdBufferRecordingInfo
|
||||
|
||||
rdcarray<VkResourceRecord *> subcmds;
|
||||
|
||||
std::map<ResourceId, ImgRefs> imgFrameRefs;
|
||||
std::map<ResourceId, ImageState> imageStates;
|
||||
|
||||
std::map<ResourceId, MemRefs> memFrameRefs;
|
||||
|
||||
// AdvanceFrame/Present should be called after this buffer is submitted
|
||||
@@ -1064,7 +1064,7 @@ struct DescriptorSetData
|
||||
static const uint32_t SPARSE_REF_BIT = 0x80000000;
|
||||
std::map<ResourceId, rdcpair<uint32_t, FrameRefType> > bindFrameRefs;
|
||||
std::map<ResourceId, MemRefs> bindMemRefs;
|
||||
std::map<ResourceId, ImgRefs> bindImgRefs;
|
||||
std::map<ResourceId, ImageState> bindImageStates;
|
||||
};
|
||||
|
||||
struct PipelineLayoutData
|
||||
@@ -1979,6 +1979,10 @@ inline FrameRefType MarkImageReferenced(std::map<ResourceId, ImgRefs> &imgRefs,
|
||||
return MarkImageReferenced(imgRefs, img, imageInfo, range, refType, ComposeFrameRefs);
|
||||
}
|
||||
|
||||
FrameRefType MarkImageReferenced(std::map<ResourceId, ImageState> &imageStates, ResourceId img,
|
||||
const ImageInfo &imageInfo, const ImageSubresourceRange &range,
|
||||
uint32_t queueFamilyIndex, FrameRefType refType);
|
||||
|
||||
template <typename Compose>
|
||||
FrameRefType MarkMemoryReferenced(std::map<ResourceId, MemRefs> &memRefs, ResourceId mem,
|
||||
VkDeviceSize offset, VkDeviceSize size, FrameRefType refType,
|
||||
@@ -2030,10 +2034,10 @@ public:
|
||||
SwapChunks(bakedCommands);
|
||||
cmdInfo->dirtied.swap(bakedCommands->cmdInfo->dirtied);
|
||||
cmdInfo->boundDescSets.swap(bakedCommands->cmdInfo->boundDescSets);
|
||||
cmdInfo->imgbarriers.swap(bakedCommands->cmdInfo->imgbarriers);
|
||||
cmdInfo->subcmds.swap(bakedCommands->cmdInfo->subcmds);
|
||||
cmdInfo->sparse.swap(bakedCommands->cmdInfo->sparse);
|
||||
cmdInfo->imgFrameRefs.swap(bakedCommands->cmdInfo->imgFrameRefs);
|
||||
RDCASSERT(bakedCommands->cmdInfo->imageStates.empty());
|
||||
cmdInfo->imageStates.swap(bakedCommands->cmdInfo->imageStates);
|
||||
cmdInfo->memFrameRefs.swap(bakedCommands->cmdInfo->memFrameRefs);
|
||||
}
|
||||
|
||||
@@ -2069,7 +2073,7 @@ public:
|
||||
rdcpair<uint32_t, FrameRefType> &p = descInfo->bindFrameRefs[view->baseResource];
|
||||
if((p.first & ~DescriptorSetData::SPARSE_REF_BIT) == 0)
|
||||
{
|
||||
descInfo->bindImgRefs.erase(view->baseResource);
|
||||
descInfo->bindImageStates.erase(view->baseResource);
|
||||
p.first = 1;
|
||||
p.second = eFrameRef_None;
|
||||
}
|
||||
@@ -2081,8 +2085,9 @@ public:
|
||||
ImageRange imgRange = ImageRange((VkImageSubresourceRange)view->viewRange);
|
||||
imgRange.viewType = view->viewRange.viewType();
|
||||
|
||||
FrameRefType maxRef = MarkImageReferenced(descInfo->bindImgRefs, view->baseResource,
|
||||
view->resInfo->imageInfo, imgRange, refType);
|
||||
FrameRefType maxRef =
|
||||
MarkImageReferenced(descInfo->bindImageStates, view->baseResource, view->resInfo->imageInfo,
|
||||
ImageSubresourceRange(imgRange), pool->queueFamilyIndex, refType);
|
||||
|
||||
p.second = ComposeFrameRefsDisjoint(p.second, maxRef);
|
||||
}
|
||||
|
||||
@@ -561,6 +561,7 @@ bool WrappedVulkan::Serialise_vkAllocateCommandBuffers(SerialiserType &ser, VkDe
|
||||
{
|
||||
ResourceId live = GetResourceManager()->WrapResource(Unwrap(device), cmd);
|
||||
GetResourceManager()->AddLiveResource(CommandBuffer, cmd);
|
||||
|
||||
m_commandQueueFamilies[live] = m_commandQueueFamilies[GetResID(AllocateInfo.commandPool)];
|
||||
}
|
||||
|
||||
@@ -1683,12 +1684,8 @@ void WrappedVulkan::vkCmdEndRenderPass(VkCommandBuffer commandBuffer)
|
||||
const rdcarray<VkImageMemoryBarrier> &barriers = record->cmdInfo->rpbarriers;
|
||||
|
||||
// apply the implicit layout transitions here
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
GetResourceManager()->RecordBarriers(GetRecord(commandBuffer)->cmdInfo->imgbarriers,
|
||||
m_ImageLayouts, (uint32_t)barriers.size(),
|
||||
barriers.data());
|
||||
}
|
||||
GetResourceManager()->RecordBarriers(record->cmdInfo->imageStates, record->pool->queueFamilyIndex,
|
||||
(uint32_t)barriers.size(), barriers.data());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2197,12 +2194,8 @@ void WrappedVulkan::vkCmdEndRenderPass2(VkCommandBuffer commandBuffer,
|
||||
const rdcarray<VkImageMemoryBarrier> &barriers = record->cmdInfo->rpbarriers;
|
||||
|
||||
// apply the implicit layout transitions here
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
GetResourceManager()->RecordBarriers(GetRecord(commandBuffer)->cmdInfo->imgbarriers,
|
||||
m_ImageLayouts, (uint32_t)barriers.size(),
|
||||
barriers.data());
|
||||
}
|
||||
GetResourceManager()->RecordBarriers(record->cmdInfo->imageStates, record->pool->queueFamilyIndex,
|
||||
(uint32_t)barriers.size(), barriers.data());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3040,9 +3033,8 @@ void WrappedVulkan::vkCmdPipelineBarrier(
|
||||
|
||||
if(imageMemoryBarrierCount > 0)
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
GetResourceManager()->RecordBarriers(GetRecord(commandBuffer)->cmdInfo->imgbarriers,
|
||||
m_ImageLayouts, imageMemoryBarrierCount,
|
||||
GetResourceManager()->RecordBarriers(record->cmdInfo->imageStates,
|
||||
record->pool->queueFamilyIndex, imageMemoryBarrierCount,
|
||||
pImageMemoryBarriers);
|
||||
}
|
||||
}
|
||||
@@ -3661,8 +3653,8 @@ void WrappedVulkan::vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t
|
||||
execRecord->bakedCommands->cmdInfo->boundDescSets.end());
|
||||
record->cmdInfo->subcmds.push_back(execRecord);
|
||||
|
||||
GetResourceManager()->MergeBarriers(record->cmdInfo->imgbarriers,
|
||||
execRecord->bakedCommands->cmdInfo->imgbarriers);
|
||||
ImageState::Merge(record->cmdInfo->imageStates,
|
||||
execRecord->bakedCommands->cmdInfo->imageStates, GetImageTransitionInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,10 +196,8 @@ void WrappedVulkan::vkDestroyImage(VkDevice device, VkImage obj,
|
||||
if(obj == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
m_ImageLayouts.erase(GetResID(obj));
|
||||
}
|
||||
EraseImageState(GetResID(obj));
|
||||
|
||||
VkImage unwrappedObj = Unwrap(obj);
|
||||
GetResourceManager()->ReleaseWrappedResource(obj, true);
|
||||
return ObjDisp(device)->DestroyImage(Unwrap(device), unwrappedObj, pAllocator);
|
||||
@@ -724,16 +722,13 @@ VkResult WrappedVulkan::vkCreateFramebuffer(VkDevice device,
|
||||
GetResourceManager()->GetCurrentHandle<VkImage>(attRecord->baseResource);
|
||||
record->imageAttachments[a].barrier.subresourceRange = attRecord->viewRange;
|
||||
|
||||
ImageLayouts *layout = NULL;
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
layout = &m_ImageLayouts[attRecord->GetResourceID()];
|
||||
}
|
||||
|
||||
if(layout->imageInfo.extent.depth > 1)
|
||||
{
|
||||
record->imageAttachments[a].barrier.subresourceRange.baseArrayLayer = 0;
|
||||
record->imageAttachments[a].barrier.subresourceRange.layerCount = 1;
|
||||
auto state = FindImageState(attRecord->GetResourceID());
|
||||
if(state && state->GetImageInfo().extent.depth > 1)
|
||||
{
|
||||
record->imageAttachments[a].barrier.subresourceRange.baseArrayLayer = 0;
|
||||
record->imageAttachments[a].barrier.subresourceRange.layerCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if the renderpass specifies an aspect mask that mean split depth/stencil handling, so
|
||||
|
||||
@@ -821,8 +821,6 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
|
||||
|
||||
std::set<ResourceId> refdIDs;
|
||||
|
||||
VkResourceRecord *queueRecord = GetRecord(queue);
|
||||
|
||||
for(uint32_t s = 0; s < submitCount; s++)
|
||||
{
|
||||
for(uint32_t i = 0; i < pSubmits[s].commandBufferCount; i++)
|
||||
@@ -832,12 +830,7 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
|
||||
VkResourceRecord *record = GetRecord(pSubmits[s].pCommandBuffers[i]);
|
||||
present |= record->bakedCommands->cmdInfo->present;
|
||||
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
GetResourceManager()->ApplyBarriers(queueRecord->queueFamilyIndex,
|
||||
record->bakedCommands->cmdInfo->imgbarriers,
|
||||
m_ImageLayouts);
|
||||
}
|
||||
UpdateImageStates(record->bakedCommands->cmdInfo->imageStates);
|
||||
|
||||
for(auto it = record->bakedCommands->cmdInfo->dirtied.begin();
|
||||
it != record->bakedCommands->cmdInfo->dirtied.end(); ++it)
|
||||
@@ -896,7 +889,7 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
|
||||
GetResourceManager()->MarkSparseMapReferenced(sparserecord->resInfo);
|
||||
}
|
||||
}
|
||||
GetResourceManager()->MergeReferencedImages(setrecord->descInfo->bindImgRefs);
|
||||
UpdateImageStates(setrecord->descInfo->bindImageStates);
|
||||
GetResourceManager()->MergeReferencedMemory(setrecord->descInfo->bindMemRefs);
|
||||
}
|
||||
|
||||
@@ -908,35 +901,32 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
|
||||
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++)
|
||||
{
|
||||
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);
|
||||
const rdcarray<VkResourceRecord *> &subcmds = record->bakedCommands->cmdInfo->subcmds;
|
||||
|
||||
record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddRef();
|
||||
for(size_t sub = 0; sub < subcmds.size(); sub++)
|
||||
{
|
||||
VkResourceRecord *bakedSubcmds = subcmds[sub]->bakedCommands;
|
||||
bakedSubcmds->AddResourceReferences(GetResourceManager());
|
||||
bakedSubcmds->AddReferencedIDs(refdIDs);
|
||||
UpdateImageStates(bakedSubcmds->cmdInfo->imageStates);
|
||||
GetResourceManager()->MergeReferencedMemory(bakedSubcmds->cmdInfo->memFrameRefs);
|
||||
GetResourceManager()->MarkResourceFrameReferenced(
|
||||
subcmds[sub]->cmdInfo->allocRecord->GetResourceID(), eFrameRef_Read);
|
||||
|
||||
bakedSubcmds->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);
|
||||
for(size_t sub = 0; sub < subcmds.size(); sub++)
|
||||
m_CmdBufferRecords.push_back(subcmds[sub]->bakedCommands);
|
||||
}
|
||||
|
||||
record->bakedCommands->AddRef();
|
||||
|
||||
@@ -1049,14 +1049,14 @@ VkResult WrappedVulkan::vkBindImageMemory(VkDevice device, VkImage image, VkDevi
|
||||
chunk = scope.Get();
|
||||
}
|
||||
|
||||
ImageLayouts *layout = NULL;
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
layout = &m_ImageLayouts[GetResID(image)];
|
||||
LockedImageStateRef state = FindImageState(GetResID(image));
|
||||
if(!state)
|
||||
RDCERR("Binding memory to unknown image %s", ToStr(GetResID(image)).c_str());
|
||||
else
|
||||
state->isMemoryBound = true;
|
||||
}
|
||||
|
||||
layout->isMemoryBound = true;
|
||||
|
||||
// memory object bindings are immutable and must happen before creation or use,
|
||||
// so this can always go into the record, even if a resource is created and bound
|
||||
// to memory mid-frame
|
||||
@@ -1858,43 +1858,7 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo *
|
||||
m_CreationInfo.m_Image[id].Init(GetResourceManager(), m_CreationInfo, pCreateInfo);
|
||||
}
|
||||
|
||||
VkImageSubresourceRange range;
|
||||
range.baseMipLevel = range.baseArrayLayer = 0;
|
||||
range.levelCount = pCreateInfo->mipLevels;
|
||||
range.layerCount = pCreateInfo->arrayLayers;
|
||||
|
||||
ImageLayouts *layout = NULL;
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
layout = &m_ImageLayouts[id];
|
||||
}
|
||||
layout->imageInfo = ImageInfo(*pCreateInfo);
|
||||
|
||||
layout->initialLayout = pCreateInfo->initialLayout;
|
||||
layout->subresourceStates.clear();
|
||||
|
||||
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if(IsDepthOnlyFormat(pCreateInfo->format))
|
||||
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
else if(IsStencilOnlyFormat(pCreateInfo->format))
|
||||
range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
else if(IsDepthOrStencilFormat(pCreateInfo->format))
|
||||
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
// if we don't support separate depth/stencil, track both aspects together
|
||||
if(!SeparateDepthStencil() && IsDepthAndStencilFormat(pCreateInfo->format))
|
||||
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
layout->subresourceStates.push_back(ImageRegionState(
|
||||
VK_QUEUE_FAMILY_IGNORED, range, UNKNOWN_PREV_IMG_LAYOUT, pCreateInfo->initialLayout));
|
||||
|
||||
// if we do support separate depth stencil, add a separate stencil aspect tracker
|
||||
if(SeparateDepthStencil() && IsDepthAndStencilFormat(pCreateInfo->format))
|
||||
{
|
||||
range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
layout->subresourceStates.push_back(ImageRegionState(
|
||||
VK_QUEUE_FAMILY_IGNORED, range, UNKNOWN_PREV_IMG_LAYOUT, pCreateInfo->initialLayout));
|
||||
}
|
||||
InsertImageState(*pImage, id, ImageInfo(*pCreateInfo), eFrameRef_None);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -2204,14 +2168,15 @@ VkResult WrappedVulkan::vkBindImageMemory2(VkDevice device, uint32_t bindInfoCou
|
||||
chunk = scope.Get();
|
||||
}
|
||||
|
||||
ImageLayouts *layout = NULL;
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
layout = &m_ImageLayouts[imgrecord->GetResourceID()];
|
||||
ResourceId id = imgrecord->GetResourceID();
|
||||
LockedImageStateRef state = FindImageState(id);
|
||||
if(!state)
|
||||
RDCERR("Binding memory for unknown image %s", ToStr(id).c_str());
|
||||
else
|
||||
state->isMemoryBound = true;
|
||||
}
|
||||
|
||||
layout->isMemoryBound = true;
|
||||
|
||||
// memory object bindings are immutable and must happen before creation or use,
|
||||
// so this can always go into the record, even if a resource is created and bound
|
||||
// to memory mid-frame
|
||||
|
||||
@@ -917,9 +917,8 @@ void WrappedVulkan::vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t even
|
||||
|
||||
if(imageMemoryBarrierCount > 0)
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
GetResourceManager()->RecordBarriers(GetRecord(commandBuffer)->cmdInfo->imgbarriers,
|
||||
m_ImageLayouts, imageMemoryBarrierCount,
|
||||
GetResourceManager()->RecordBarriers(record->cmdInfo->imageStates,
|
||||
record->pool->queueFamilyIndex, imageMemoryBarrierCount,
|
||||
pImageMemoryBarriers);
|
||||
}
|
||||
|
||||
|
||||
@@ -500,6 +500,9 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device,
|
||||
|
||||
swapInfo.imageInfo = ImageInfo(*pCreateInfo);
|
||||
|
||||
swapInfo.shared = (pCreateInfo->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
|
||||
pCreateInfo->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
|
||||
|
||||
VkResult vkr = VK_SUCCESS;
|
||||
|
||||
const VkDevDispatchTable *vt = ObjDisp(device);
|
||||
@@ -587,18 +590,11 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device,
|
||||
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
// fill out image info so we track resource state barriers
|
||||
ImageLayouts *layout = NULL;
|
||||
{
|
||||
SCOPED_LOCK(m_ImageLayoutsLock);
|
||||
layout = &m_ImageLayouts[imid];
|
||||
LockedImageStateRef state = InsertImageState(
|
||||
images[i], imid, GetRecord(images[i])->resInfo->imageInfo, eFrameRef_None);
|
||||
state->isMemoryBound = true;
|
||||
}
|
||||
layout->imageInfo = GetRecord(images[i])->resInfo->imageInfo;
|
||||
layout->isMemoryBound = true;
|
||||
layout->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
layout->subresourceStates.clear();
|
||||
layout->subresourceStates.push_back(ImageRegionState(
|
||||
VK_QUEUE_FAMILY_IGNORED, range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED));
|
||||
|
||||
{
|
||||
VkImageViewCreateInfo info = {
|
||||
|
||||
Reference in New Issue
Block a user