mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-28 12:51:03 +00:00
skip initial states for cleared renderpass
also refactored the postpone logic
This commit is contained in:
committed by
Baldur Karlsson
parent
aa16eb0ed0
commit
58a6d7eb76
@@ -170,6 +170,11 @@ bool IsDirtyFrameRef(FrameRefType refType)
|
||||
return (refType != eFrameRef_None && refType != eFrameRef_Read);
|
||||
}
|
||||
|
||||
bool IsCompleteWriteFrameRef(FrameRefType refType)
|
||||
{
|
||||
return refType == eFrameRef_CompleteWrite;
|
||||
}
|
||||
|
||||
void ResourceRecord::AddResourceReferences(ResourceRecordHandler *mgr)
|
||||
{
|
||||
for(auto it = m_FrameRefs.begin(); it != m_FrameRefs.end(); ++it)
|
||||
|
||||
@@ -120,6 +120,8 @@ const FrameRefType eFrameRef_Maximum = eFrameRef_WriteBeforeRead;
|
||||
// Threshold value for resource "age", i.e. how long it wasn't
|
||||
// referred with the any write reference.
|
||||
const double PERSISTENT_RESOURCE_AGE = 3000;
|
||||
// how long it wasn't referred with any read reference.
|
||||
const double IRRELEVANT_RESOURCE_AGE = 3000;
|
||||
|
||||
DECLARE_REFLECTION_ENUM(FrameRefType);
|
||||
|
||||
@@ -149,6 +151,7 @@ FrameRefType ComposeFrameRefsFirstKnown(FrameRefType first, FrameRefType second)
|
||||
FrameRefType KeepOldFrameRef(FrameRefType first, FrameRefType second);
|
||||
|
||||
bool IsDirtyFrameRef(FrameRefType refType);
|
||||
bool IsCompleteWriteFrameRef(FrameRefType refType);
|
||||
|
||||
// Captures the possible initialization/reset requirements for resources.
|
||||
// These requirements are entirely determined by the resource's FrameRefType,
|
||||
@@ -645,16 +648,21 @@ public:
|
||||
WrappedResourceType GetWrapper(RealResourceType real);
|
||||
void RemoveWrapper(RealResourceType real);
|
||||
|
||||
void Prepare_ResourceInitialStateIfNeeded(ResourceId id);
|
||||
void Prepare_ResourceIfActivePostponed(ResourceId id);
|
||||
void Prepare_InitialStateIfPostponed(ResourceId id);
|
||||
void SkipOrPostponeOrPrepare_InitialState(ResourceId id, FrameRefType refType);
|
||||
|
||||
void UpdateLastWriteTime(ResourceId id);
|
||||
void UpdateLastWriteTime(ResourceId id, FrameRefType refType);
|
||||
void ResetLastWriteTimes();
|
||||
void ResetCaptureStartTime();
|
||||
void UpdateLastPartialUseTime(ResourceId id, FrameRefType refType);
|
||||
void ResetLastPartialUseTimes();
|
||||
|
||||
bool HasPersistentAge(ResourceId id);
|
||||
bool HasIrrelevantAge(ResourceId id);
|
||||
bool IsResourcePostponed(ResourceId id);
|
||||
bool IsResourcePersistent(ResourceId id);
|
||||
bool IsResourceSkipped(ResourceId id);
|
||||
bool ShouldPostpone(ResourceId id);
|
||||
bool ShouldSkip(ResourceId id);
|
||||
|
||||
virtual bool IsResourceTrackedForPersistency(const WrappedResourceType &res) { return false; }
|
||||
protected:
|
||||
@@ -741,11 +749,18 @@ protected:
|
||||
// During initial resources preparation, persistent resources are
|
||||
// postponed until serializing to RDC file.
|
||||
std::set<ResourceId> m_PostponedResourceIDs;
|
||||
// During initial resources preparation, resources that are completely written
|
||||
// over are skipped
|
||||
std::set<ResourceId> m_SkippedResourceIDs;
|
||||
|
||||
// On marking resource write-referenced in frame, its last write
|
||||
// time is reset. The time is used to determine persistent resources,
|
||||
// and is checked against the `PERSISTENT_RESOURCE_AGE`.
|
||||
std::map<ResourceId, double> m_LastWriteTime;
|
||||
// m_LastPartialUseTime is referring to: eFrameRef_PartialWrite, eFrameRef_Read,
|
||||
// eFrameRef_ReadBeforeWrite, eFrameRef_WriteBeforeRead. The goal is to predict
|
||||
// whether a resource will have a eFrameRef_CompleteWrite reference or not
|
||||
std::map<ResourceId, double> m_LastPartialUseTime;
|
||||
|
||||
// Timestamp at the beginning of the frame capture. Used to determine which
|
||||
// resources to refresh for their last write time (see `m_LastWriteTime`).
|
||||
@@ -804,12 +819,19 @@ void ResourceManager<Configuration>::MarkResourceFrameReferenced(ResourceId id,
|
||||
if(id == ResourceId())
|
||||
return;
|
||||
|
||||
if(IsDirtyFrameRef(refType))
|
||||
if(IsActiveCapturing(m_State))
|
||||
{
|
||||
Prepare_ResourceIfActivePostponed(id);
|
||||
UpdateLastWriteTime(id);
|
||||
SkipOrPostponeOrPrepare_InitialState(id, refType);
|
||||
|
||||
if(IsDirtyFrameRef(refType))
|
||||
{
|
||||
Prepare_InitialStateIfPostponed(id);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateLastPartialUseTime(id, refType);
|
||||
UpdateLastWriteTime(id, refType);
|
||||
|
||||
if(IsBackgroundCapturing(m_State))
|
||||
return;
|
||||
|
||||
@@ -972,10 +994,11 @@ void ResourceManager<Configuration>::FreeInitialContents()
|
||||
m_InitialContents.erase(m_InitialContents.begin());
|
||||
}
|
||||
m_PostponedResourceIDs.clear();
|
||||
m_SkippedResourceIDs.clear();
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
void ResourceManager<Configuration>::Prepare_ResourceInitialStateIfNeeded(ResourceId id)
|
||||
void ResourceManager<Configuration>::Prepare_InitialStateIfPostponed(ResourceId id)
|
||||
{
|
||||
SCOPED_LOCK(m_Lock);
|
||||
|
||||
@@ -983,28 +1006,58 @@ void ResourceManager<Configuration>::Prepare_ResourceInitialStateIfNeeded(Resour
|
||||
return;
|
||||
|
||||
WrappedResourceType res = GetCurrentResource(id);
|
||||
RDCDEBUG("Preparing resource %s after it has been postponed.", ToStr(id).c_str());
|
||||
Prepare_InitialState(res);
|
||||
|
||||
m_PostponedResourceIDs.erase(id);
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
void ResourceManager<Configuration>::Prepare_ResourceIfActivePostponed(ResourceId id)
|
||||
void ResourceManager<Configuration>::SkipOrPostponeOrPrepare_InitialState(ResourceId id,
|
||||
FrameRefType refType)
|
||||
{
|
||||
SCOPED_LOCK(m_Lock);
|
||||
|
||||
// If the resource was postponed during Active Capture, we need to prepare it
|
||||
// right away, since next Read might be invalid.
|
||||
if(!IsActiveCapturing(m_State) || !IsResourcePostponed(id))
|
||||
if(!IsResourceSkipped(id))
|
||||
return;
|
||||
|
||||
RDCDEBUG("Preparing resource %s after it has been postponed.", ToStr(id).c_str());
|
||||
Prepare_ResourceInitialStateIfNeeded(id);
|
||||
// the first time we encounter a skipped resource, we can choose to
|
||||
// skip this resource forever, convert it to be postponed, or prepare
|
||||
// it immediately. We can't retrieve its initial state once it has
|
||||
// been written over.
|
||||
m_SkippedResourceIDs.erase(id);
|
||||
|
||||
// skip this forever if the first encounter is a complete write
|
||||
if(IsCompleteWriteFrameRef(refType))
|
||||
{
|
||||
RDCDEBUG("Resource %s skipped forever on refType of %s)", ToStr(id).c_str(),
|
||||
ToStr(refType).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// If this resource is only being read, we might as well try to
|
||||
// postpone it to conserve memory consumption.
|
||||
if(!IsDirtyFrameRef(refType) && IsResourceTrackedForPersistency(GetCurrentResource(id)))
|
||||
{
|
||||
m_PostponedResourceIDs.insert(id);
|
||||
RDCDEBUG("Resource %s converted from skipped to postponed on refType of %s", ToStr(id).c_str(),
|
||||
ToStr(refType).c_str());
|
||||
SetInitialContents(id, InitialContentData());
|
||||
}
|
||||
else
|
||||
{
|
||||
WrappedResourceType res = GetCurrentResource(id);
|
||||
RDCDEBUG("Preparing resource %s after it has been skipped on refType of %s", ToStr(id).c_str(),
|
||||
ToStr(refType).c_str());
|
||||
Prepare_InitialState(res);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
inline void ResourceManager<Configuration>::UpdateLastWriteTime(ResourceId id)
|
||||
inline void ResourceManager<Configuration>::UpdateLastWriteTime(ResourceId id, FrameRefType refType)
|
||||
{
|
||||
if(!IsDirtyFrameRef(refType))
|
||||
return;
|
||||
SCOPED_LOCK(m_Lock);
|
||||
m_LastWriteTime[id] = m_ResourcesUpdateTimer.GetMilliseconds();
|
||||
}
|
||||
@@ -1031,6 +1084,27 @@ inline void ResourceManager<Configuration>::ResetLastWriteTimes()
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
inline void ResourceManager<Configuration>::UpdateLastPartialUseTime(ResourceId id,
|
||||
FrameRefType refType)
|
||||
{
|
||||
if(IsCompleteWriteFrameRef(refType))
|
||||
return;
|
||||
SCOPED_LOCK(m_Lock);
|
||||
m_LastPartialUseTime[id] = m_ResourcesUpdateTimer.GetMilliseconds();
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
inline void ResourceManager<Configuration>::ResetLastPartialUseTimes()
|
||||
{
|
||||
SCOPED_LOCK(m_Lock);
|
||||
for(auto it = m_LastPartialUseTime.begin(); it != m_LastPartialUseTime.end(); ++it)
|
||||
{
|
||||
if(m_captureStartTime - it->second <= IRRELEVANT_RESOURCE_AGE)
|
||||
it->second = m_ResourcesUpdateTimer.GetMilliseconds();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
inline bool ResourceManager<Configuration>::HasPersistentAge(ResourceId id)
|
||||
{
|
||||
@@ -1044,6 +1118,19 @@ inline bool ResourceManager<Configuration>::HasPersistentAge(ResourceId id)
|
||||
return m_ResourcesUpdateTimer.GetMilliseconds() - it->second >= PERSISTENT_RESOURCE_AGE;
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
inline bool ResourceManager<Configuration>::HasIrrelevantAge(ResourceId id)
|
||||
{
|
||||
SCOPED_LOCK(m_Lock);
|
||||
|
||||
auto it = m_LastPartialUseTime.find(id);
|
||||
|
||||
if(it == m_LastPartialUseTime.end())
|
||||
return true;
|
||||
|
||||
return m_ResourcesUpdateTimer.GetMilliseconds() - it->second >= IRRELEVANT_RESOURCE_AGE;
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
inline bool ResourceManager<Configuration>::IsResourcePostponed(ResourceId id)
|
||||
{
|
||||
@@ -1052,7 +1139,14 @@ inline bool ResourceManager<Configuration>::IsResourcePostponed(ResourceId id)
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
inline bool ResourceManager<Configuration>::IsResourcePersistent(ResourceId id)
|
||||
inline bool ResourceManager<Configuration>::IsResourceSkipped(ResourceId id)
|
||||
{
|
||||
SCOPED_LOCK(m_Lock);
|
||||
return m_SkippedResourceIDs.find(id) != m_SkippedResourceIDs.end();
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
inline bool ResourceManager<Configuration>::ShouldPostpone(ResourceId id)
|
||||
{
|
||||
SCOPED_LOCK(m_Lock);
|
||||
|
||||
@@ -1064,6 +1158,19 @@ inline bool ResourceManager<Configuration>::IsResourcePersistent(ResourceId id)
|
||||
return HasPersistentAge(id);
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
inline bool ResourceManager<Configuration>::ShouldSkip(ResourceId id)
|
||||
{
|
||||
SCOPED_LOCK(m_Lock);
|
||||
|
||||
WrappedResourceType res = GetCurrentResource(id);
|
||||
|
||||
if(!IsResourceTrackedForPersistency(res))
|
||||
return false;
|
||||
|
||||
return HasIrrelevantAge(id);
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
void ResourceManager<Configuration>::CreateInitialContents(ReadSerialiser &ser)
|
||||
{
|
||||
@@ -1201,6 +1308,7 @@ void ResourceManager<Configuration>::PrepareInitialContents()
|
||||
RDCDEBUG("Preparing up to %u potentially dirty resources", (uint32_t)m_DirtyResources.size());
|
||||
uint32_t prepared = 0;
|
||||
uint32_t postponed = 0;
|
||||
uint32_t skipped = 0;
|
||||
|
||||
float num = float(m_DirtyResources.size());
|
||||
float idx = 0.0f;
|
||||
@@ -1225,7 +1333,14 @@ void ResourceManager<Configuration>::PrepareInitialContents()
|
||||
if(record == NULL || record->InternalResource)
|
||||
continue;
|
||||
|
||||
if(IsResourcePersistent(id))
|
||||
if(ShouldSkip(id))
|
||||
{
|
||||
m_SkippedResourceIDs.insert(id);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ShouldPostpone(id))
|
||||
{
|
||||
m_PostponedResourceIDs.insert(id);
|
||||
// Set empty contents here, it'll be prepared on serialization.
|
||||
@@ -1243,7 +1358,7 @@ void ResourceManager<Configuration>::PrepareInitialContents()
|
||||
Prepare_InitialState(res);
|
||||
}
|
||||
|
||||
RDCDEBUG("Prepared %u dirty resources, postponed %u", prepared, postponed);
|
||||
RDCDEBUG("Prepared %u dirty resources, postponed %u, skipped %u", prepared, postponed, skipped);
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
@@ -1270,7 +1385,7 @@ void ResourceManager<Configuration>::InsertInitialContentsChunks(WriteSerialiser
|
||||
!RenderDoc::Inst().GetCaptureOptions().refAllResources)
|
||||
{
|
||||
#if ENABLED(VERBOSE_DIRTY_RESOURCES)
|
||||
RDCDEBUG("Dirty tesource %s is GPU dirty but not referenced - skipping", ToStr(id).c_str());
|
||||
RDCDEBUG("Dirty resource %s is GPU dirty but not referenced - skipping", ToStr(id).c_str());
|
||||
#endif
|
||||
skipped++;
|
||||
continue;
|
||||
@@ -1299,7 +1414,7 @@ void ResourceManager<Configuration>::InsertInitialContentsChunks(WriteSerialiser
|
||||
#endif
|
||||
|
||||
// Load postponed resource if needed.
|
||||
Prepare_ResourceInitialStateIfNeeded(id);
|
||||
Prepare_InitialStateIfPostponed(id);
|
||||
|
||||
dirty++;
|
||||
|
||||
@@ -1638,11 +1753,15 @@ void ResourceManager<Configuration>::ReleaseCurrentResource(ResourceId id)
|
||||
|
||||
// We potentially need to prepare this resource on Active Capture,
|
||||
// if it was postponed, but is about to go away.
|
||||
Prepare_ResourceIfActivePostponed(id);
|
||||
if(IsActiveCapturing(m_State))
|
||||
{
|
||||
Prepare_InitialStateIfPostponed(id);
|
||||
}
|
||||
|
||||
m_CurrentResourceMap.erase(id);
|
||||
m_DirtyResources.erase(id);
|
||||
m_LastWriteTime.erase(id);
|
||||
m_LastPartialUseTime.erase(id);
|
||||
}
|
||||
|
||||
template <typename Configuration>
|
||||
|
||||
@@ -2054,6 +2054,8 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
|
||||
|
||||
GetResourceManager()->ResetLastWriteTimes();
|
||||
|
||||
GetResourceManager()->ResetLastPartialUseTimes();
|
||||
|
||||
GetResourceManager()->MarkUnwrittenResources();
|
||||
|
||||
GetResourceManager()->ClearReferencedMemory();
|
||||
|
||||
@@ -3216,6 +3216,326 @@ VkImageAspectFlags FormatImageAspects(VkFormat fmt)
|
||||
return VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
|
||||
RenderPassInfo::RenderPassInfo(const VkRenderPassCreateInfo &ci)
|
||||
{
|
||||
// *2 in case we need separate barriers for depth and stencil, +1 for the terminating null
|
||||
// attachment info (though separate depth/stencil buffers aren't needed here, we keep the
|
||||
// array size the same)
|
||||
uint32_t arrayCount = ci.attachmentCount * 2 + 1;
|
||||
imageAttachments = new AttachmentInfo[arrayCount];
|
||||
RDCEraseMem(imageAttachments, arrayCount * sizeof(imageAttachments[0]));
|
||||
|
||||
for(uint32_t i = 0; i < ci.attachmentCount; ++i)
|
||||
{
|
||||
imageAttachments[i].record = NULL;
|
||||
imageAttachments[i].barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
imageAttachments[i].barrier.oldLayout = ci.pAttachments[i].initialLayout;
|
||||
imageAttachments[i].barrier.newLayout = ci.pAttachments[i].finalLayout;
|
||||
}
|
||||
|
||||
// VK_KHR_multiview
|
||||
const VkRenderPassMultiviewCreateInfo *multiview =
|
||||
(const VkRenderPassMultiviewCreateInfo *)FindNextStruct(
|
||||
&ci, VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO);
|
||||
|
||||
if(multiview && multiview->subpassCount > 0)
|
||||
{
|
||||
multiviewViewMaskTable = new uint32_t[arrayCount];
|
||||
RDCEraseMem(multiviewViewMaskTable, arrayCount * sizeof(multiviewViewMaskTable[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
multiviewViewMaskTable = NULL;
|
||||
}
|
||||
|
||||
loadOpTable = new VkAttachmentLoadOp[arrayCount];
|
||||
|
||||
// we only care about which attachment doesn't have LOAD specificed, so we
|
||||
// assume all attachments have VK_ATTACHMENT_LOAD_OP_LOAD until proven otherwise
|
||||
for(uint32_t a = 0; a < arrayCount; ++a)
|
||||
loadOpTable[a] = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
|
||||
for(uint32_t s = 0; s < ci.subpassCount; ++s)
|
||||
{
|
||||
const VkAttachmentReference *pColorAttachments = ci.pSubpasses[s].pColorAttachments;
|
||||
const VkAttachmentReference *pResolveAttachments = ci.pSubpasses[s].pResolveAttachments;
|
||||
const VkAttachmentReference *pDepthStencilAttachment = ci.pSubpasses[s].pDepthStencilAttachment;
|
||||
|
||||
if(pColorAttachments)
|
||||
{
|
||||
const VkAttachmentReference *pColorRunner = pColorAttachments;
|
||||
const VkAttachmentReference *pColorEnd = pColorRunner + ci.pSubpasses[s].colorAttachmentCount;
|
||||
|
||||
while(pColorRunner != pColorEnd)
|
||||
{
|
||||
uint32_t index = pColorRunner->attachment;
|
||||
if(index < ci.attachmentCount)
|
||||
{
|
||||
loadOpTable[index] = ci.pAttachments[index].loadOp;
|
||||
|
||||
if(multiviewViewMaskTable)
|
||||
{
|
||||
multiviewViewMaskTable[index] |= multiview->pViewMasks[s];
|
||||
}
|
||||
}
|
||||
++pColorRunner;
|
||||
}
|
||||
}
|
||||
if(pResolveAttachments)
|
||||
{
|
||||
const VkAttachmentReference *pResolveRunner = pResolveAttachments;
|
||||
const VkAttachmentReference *pResolveEnd =
|
||||
pResolveRunner + ci.pSubpasses[s].colorAttachmentCount;
|
||||
|
||||
while(pResolveRunner != pResolveEnd)
|
||||
{
|
||||
uint32_t index = pResolveRunner->attachment;
|
||||
if(index < ci.attachmentCount)
|
||||
{
|
||||
loadOpTable[index] = ci.pAttachments[index].loadOp;
|
||||
|
||||
if(multiviewViewMaskTable)
|
||||
{
|
||||
multiviewViewMaskTable[index] |= multiview->pViewMasks[s];
|
||||
}
|
||||
}
|
||||
++pResolveRunner;
|
||||
}
|
||||
}
|
||||
if(pDepthStencilAttachment)
|
||||
{
|
||||
uint32_t index = pDepthStencilAttachment->attachment;
|
||||
|
||||
if(index < ci.attachmentCount)
|
||||
{
|
||||
VkAttachmentLoadOp depthStencilLoadOp = ci.pAttachments[index].loadOp;
|
||||
|
||||
// make depthstencil VK_ATTACHMENT_LOAD_OP_LOAD if either depth or stencil is
|
||||
// VK_ATTACHMENT_LOAD_OP_LOAD
|
||||
if(depthStencilLoadOp != VK_ATTACHMENT_LOAD_OP_LOAD &&
|
||||
IsStencilFormat(ci.pAttachments[index].format))
|
||||
{
|
||||
depthStencilLoadOp = ci.pAttachments[index].stencilLoadOp;
|
||||
}
|
||||
|
||||
loadOpTable[index] = depthStencilLoadOp;
|
||||
|
||||
if(multiviewViewMaskTable)
|
||||
{
|
||||
multiviewViewMaskTable[index] |= multiview->pViewMasks[s];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RenderPassInfo::RenderPassInfo(const VkRenderPassCreateInfo2 &ci)
|
||||
{
|
||||
// *2 in case we need separate barriers for depth and stencil, +1 for the terminating null
|
||||
// attachment info
|
||||
uint32_t arrayCount = ci.attachmentCount * 2 + 1;
|
||||
imageAttachments = new AttachmentInfo[arrayCount];
|
||||
RDCEraseMem(imageAttachments, arrayCount * sizeof(imageAttachments[0]));
|
||||
|
||||
// need to keep a table for the index remap, because imageAttachments won't have the same
|
||||
// order as ci.pAttachments
|
||||
rdcarray<uint32_t> indexRemapTable;
|
||||
indexRemapTable.fill(ci.attachmentCount, 0xFFFFFFFF);
|
||||
|
||||
for(uint32_t i = 0, a = 0; i < ci.attachmentCount; i++, a++)
|
||||
{
|
||||
imageAttachments[a].record = NULL;
|
||||
imageAttachments[a].barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
imageAttachments[a].barrier.oldLayout = ci.pAttachments[i].initialLayout;
|
||||
imageAttachments[a].barrier.newLayout = ci.pAttachments[i].finalLayout;
|
||||
|
||||
indexRemapTable[i] = a;
|
||||
|
||||
// VK_KHR_separate_depth_stencil_layouts
|
||||
VkAttachmentDescriptionStencilLayoutKHR *separateStencil =
|
||||
(VkAttachmentDescriptionStencilLayoutKHR *)FindNextStruct(
|
||||
&ci.pAttachments[i], VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR);
|
||||
|
||||
if(separateStencil)
|
||||
{
|
||||
imageAttachments[a].barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
// add a separate barrier for stencil
|
||||
a++;
|
||||
|
||||
imageAttachments[a].barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
imageAttachments[a].barrier.oldLayout = separateStencil->stencilInitialLayout;
|
||||
imageAttachments[a].barrier.newLayout = separateStencil->stencilFinalLayout;
|
||||
imageAttachments[a].barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
// if any subpass' viewMask is non-zero, then multiview is enabled
|
||||
multiviewViewMaskTable = NULL;
|
||||
for(uint32_t s = 0; s < ci.subpassCount; ++s)
|
||||
{
|
||||
if(ci.pSubpasses[s].viewMask)
|
||||
{
|
||||
multiviewViewMaskTable = new uint32_t[arrayCount];
|
||||
RDCEraseMem(multiviewViewMaskTable, arrayCount * sizeof(multiviewViewMaskTable[0]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
loadOpTable = new VkAttachmentLoadOp[arrayCount];
|
||||
|
||||
// we only care about which attachment doesn't have LOAD specificed, so we
|
||||
// assume all attachments have VK_ATTACHMENT_LOAD_OP_LOAD until proven otherwise
|
||||
for(uint32_t a = 0; a < arrayCount; ++a)
|
||||
loadOpTable[a] = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
|
||||
for(uint32_t s = 0; s < ci.subpassCount; ++s)
|
||||
{
|
||||
const VkAttachmentReference2 *pColorAttachments = ci.pSubpasses[s].pColorAttachments;
|
||||
const VkAttachmentReference2 *pResolveAttachments = ci.pSubpasses[s].pResolveAttachments;
|
||||
const VkAttachmentReference2 *pDepthStencilAttachment = ci.pSubpasses[s].pDepthStencilAttachment;
|
||||
|
||||
if(pColorAttachments)
|
||||
{
|
||||
const VkAttachmentReference2 *pColorRunner = pColorAttachments;
|
||||
const VkAttachmentReference2 *pColorEnd = pColorRunner + ci.pSubpasses[s].colorAttachmentCount;
|
||||
|
||||
while(pColorRunner != pColorEnd)
|
||||
{
|
||||
uint32_t index = pColorRunner->attachment;
|
||||
if(index < ci.attachmentCount)
|
||||
{
|
||||
uint32_t remappedIndex = indexRemapTable[index];
|
||||
RDCASSERT(remappedIndex < arrayCount);
|
||||
|
||||
loadOpTable[remappedIndex] = ci.pAttachments[index].loadOp;
|
||||
|
||||
if(multiviewViewMaskTable)
|
||||
{
|
||||
multiviewViewMaskTable[remappedIndex] |= ci.pSubpasses[s].viewMask;
|
||||
}
|
||||
}
|
||||
++pColorRunner;
|
||||
}
|
||||
}
|
||||
if(pResolveAttachments)
|
||||
{
|
||||
const VkAttachmentReference2 *pResolveRunner = pResolveAttachments;
|
||||
const VkAttachmentReference2 *pResolveEnd =
|
||||
pResolveRunner + ci.pSubpasses[s].colorAttachmentCount;
|
||||
|
||||
while(pResolveRunner != pResolveEnd)
|
||||
{
|
||||
uint32_t index = pResolveRunner->attachment;
|
||||
if(index < ci.attachmentCount)
|
||||
{
|
||||
uint32_t remappedIndex = indexRemapTable[index];
|
||||
RDCASSERT(remappedIndex < arrayCount);
|
||||
|
||||
loadOpTable[remappedIndex] = ci.pAttachments[index].loadOp;
|
||||
|
||||
if(multiviewViewMaskTable)
|
||||
{
|
||||
multiviewViewMaskTable[remappedIndex] |= ci.pSubpasses[s].viewMask;
|
||||
}
|
||||
}
|
||||
++pResolveRunner;
|
||||
}
|
||||
}
|
||||
if(pDepthStencilAttachment)
|
||||
{
|
||||
uint32_t index = pDepthStencilAttachment->attachment;
|
||||
|
||||
if(index < ci.attachmentCount)
|
||||
{
|
||||
VkAttachmentLoadOp depthStencilLoadOp = ci.pAttachments[index].loadOp;
|
||||
VkAttachmentLoadOp stencilLoadOp = ci.pAttachments[index].stencilLoadOp;
|
||||
|
||||
uint32_t remappedIndex = indexRemapTable[index];
|
||||
RDCASSERT(remappedIndex < arrayCount);
|
||||
|
||||
if(IsStencilFormat(ci.pAttachments[index].format))
|
||||
{
|
||||
// VK_KHR_separate_depth_stencil_layouts
|
||||
VkAttachmentDescriptionStencilLayoutKHR *separateStencil =
|
||||
(VkAttachmentDescriptionStencilLayoutKHR *)FindNextStruct(
|
||||
&ci.pAttachments[index],
|
||||
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR);
|
||||
|
||||
if(separateStencil)
|
||||
{
|
||||
loadOpTable[remappedIndex + 1] = stencilLoadOp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// make depthstencil VK_ATTACHMENT_LOAD_OP_LOAD if either depth or stencil is
|
||||
// VK_ATTACHMENT_LOAD_OP_LOAD
|
||||
if(depthStencilLoadOp != VK_ATTACHMENT_LOAD_OP_LOAD)
|
||||
{
|
||||
depthStencilLoadOp = stencilLoadOp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadOpTable[remappedIndex] = depthStencilLoadOp;
|
||||
|
||||
if(multiviewViewMaskTable)
|
||||
{
|
||||
multiviewViewMaskTable[remappedIndex] |= ci.pSubpasses[s].viewMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RenderPassInfo::~RenderPassInfo()
|
||||
{
|
||||
delete[] imageAttachments;
|
||||
delete[] loadOpTable;
|
||||
delete[] multiviewViewMaskTable;
|
||||
}
|
||||
|
||||
FramebufferInfo::FramebufferInfo(const VkFramebufferCreateInfo &ci)
|
||||
{
|
||||
// *2 in case we need separate barriers for depth and stencil, +1 for the terminating null
|
||||
// attachment info
|
||||
uint32_t arrayCount = ci.attachmentCount * 2 + 1;
|
||||
|
||||
imageAttachments = new AttachmentInfo[arrayCount];
|
||||
RDCEraseMem(imageAttachments, arrayCount * sizeof(imageAttachments[0]));
|
||||
|
||||
width = ci.width;
|
||||
height = ci.height;
|
||||
layers = ci.layers;
|
||||
}
|
||||
FramebufferInfo::~FramebufferInfo()
|
||||
{
|
||||
delete[] imageAttachments;
|
||||
}
|
||||
|
||||
bool FramebufferInfo::AttachmentFullyReferenced(size_t attachmentIndex, const RenderPassInfo *rpi)
|
||||
{
|
||||
VkResourceRecord *att = imageAttachments[attachmentIndex].record;
|
||||
// if framebuffer doesn't reference the entire image
|
||||
if(att->resInfo->imageInfo.extent.width != width || att->resInfo->imageInfo.extent.height != height)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// if view doesn't reference the entire image
|
||||
if(att->viewRange.baseArrayLayer != 0 ||
|
||||
att->viewRange.layerCount() != (uint32_t)att->resInfo->imageInfo.layerCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(rpi->multiviewViewMaskTable)
|
||||
{
|
||||
// check and make sure all views are referenced by the renderpass
|
||||
uint32_t renderpass_viewmask = rpi->multiviewViewMaskTable[attachmentIndex];
|
||||
return (int)Bits::CountOnes(renderpass_viewmask) == att->resInfo->imageInfo.layerCount;
|
||||
}
|
||||
return imageAttachments[attachmentIndex].barrier.subresourceRange.layerCount == layers;
|
||||
}
|
||||
|
||||
int ImgRefs::GetAspectCount() const
|
||||
{
|
||||
int aspectCount = 0;
|
||||
@@ -3421,8 +3741,11 @@ VkResourceRecord::~VkResourceRecord()
|
||||
if(resType == eResCommandBuffer)
|
||||
SAFE_DELETE(cmdInfo);
|
||||
|
||||
if(resType == eResFramebuffer || resType == eResRenderPass)
|
||||
SAFE_DELETE_ARRAY(imageAttachments);
|
||||
if(resType == eResFramebuffer)
|
||||
SAFE_DELETE(framebufferInfo);
|
||||
|
||||
if(resType == eResRenderPass)
|
||||
SAFE_DELETE(renderPassInfo);
|
||||
|
||||
// only the descriptor set layout actually owns this pointer, descriptor sets
|
||||
// have a pointer to it but don't own it
|
||||
@@ -3442,8 +3765,8 @@ VkResourceRecord::~VkResourceRecord()
|
||||
void VkResourceRecord::MarkImageFrameReferenced(VkResourceRecord *img, const ImageRange &range,
|
||||
FrameRefType refType)
|
||||
{
|
||||
// mark backing memory as read
|
||||
MarkResourceFrameReferenced(img->baseResource, eFrameRef_Read);
|
||||
// mark backing memory
|
||||
MarkResourceFrameReferenced(img->baseResource, refType);
|
||||
|
||||
ResourceId id = img->GetResourceID();
|
||||
if(refType != eFrameRef_Read && refType != eFrameRef_None)
|
||||
@@ -3470,8 +3793,8 @@ void VkResourceRecord::MarkImageViewFrameReferenced(VkResourceRecord *view, cons
|
||||
// mark image view as read
|
||||
MarkResourceFrameReferenced(view->GetResourceID(), eFrameRef_Read);
|
||||
|
||||
// mark memory backing image as read
|
||||
MarkResourceFrameReferenced(mem, eFrameRef_Read);
|
||||
// mark memory backing image
|
||||
MarkResourceFrameReferenced(mem, refType);
|
||||
|
||||
if(refType != eFrameRef_Read && refType != eFrameRef_None)
|
||||
cmdInfo->dirtied.insert(img);
|
||||
|
||||
@@ -1108,6 +1108,36 @@ struct AttachmentInfo
|
||||
VkImageMemoryBarrier barrier;
|
||||
};
|
||||
|
||||
struct RenderPassInfo
|
||||
{
|
||||
RenderPassInfo(const VkRenderPassCreateInfo &ci);
|
||||
RenderPassInfo(const VkRenderPassCreateInfo2 &ci);
|
||||
|
||||
~RenderPassInfo();
|
||||
|
||||
AttachmentInfo *imageAttachments;
|
||||
|
||||
// table of loadOps for each attachment
|
||||
VkAttachmentLoadOp *loadOpTable;
|
||||
|
||||
// table of multiview viewMasks for each attachment
|
||||
uint32_t *multiviewViewMaskTable;
|
||||
};
|
||||
|
||||
struct FramebufferInfo
|
||||
{
|
||||
FramebufferInfo(const VkFramebufferCreateInfo &ci);
|
||||
~FramebufferInfo();
|
||||
|
||||
bool AttachmentFullyReferenced(size_t attachmentIndex, const RenderPassInfo *rpi);
|
||||
|
||||
AttachmentInfo *imageAttachments;
|
||||
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t layers;
|
||||
};
|
||||
|
||||
struct ImageRange
|
||||
{
|
||||
ImageRange() {}
|
||||
@@ -2217,7 +2247,8 @@ public:
|
||||
SwapchainInfo *swapInfo; // only for swapchains
|
||||
MemMapState *memMapState; // only for device memory
|
||||
CmdBufferRecordingInfo *cmdInfo; // only for command buffers
|
||||
AttachmentInfo *imageAttachments; // only for framebuffers and render passes
|
||||
FramebufferInfo *framebufferInfo; // only for framebuffers
|
||||
RenderPassInfo *renderPassInfo; // only for render passes
|
||||
PipelineLayoutData *pipeLayoutInfo; // only for pipeline layouts
|
||||
DescriptorSetData *descInfo; // only for descriptor sets and descriptor set layouts
|
||||
DescUpdateTemplate *descTemplateInfo; // only for descriptor update templates
|
||||
|
||||
@@ -1493,6 +1493,7 @@ void WrappedVulkan::vkCmdBeginRenderPass(VkCommandBuffer commandBuffer,
|
||||
record->MarkResourceFrameReferenced(GetResID(pRenderPassBegin->renderPass), eFrameRef_Read);
|
||||
|
||||
VkResourceRecord *fb = GetRecord(pRenderPassBegin->framebuffer);
|
||||
VkResourceRecord *rp = GetRecord(pRenderPassBegin->renderPass);
|
||||
|
||||
record->MarkResourceFrameReferenced(fb->GetResourceID(), eFrameRef_Read);
|
||||
|
||||
@@ -1500,21 +1501,42 @@ void WrappedVulkan::vkCmdBeginRenderPass(VkCommandBuffer commandBuffer,
|
||||
|
||||
barriers.clear();
|
||||
|
||||
if(fb->imageAttachments[0].barrier.sType && fb->imageAttachments[0].record)
|
||||
FramebufferInfo *fbInfo = fb->framebufferInfo;
|
||||
RenderPassInfo *rpInfo = rp->renderPassInfo;
|
||||
|
||||
if(fbInfo->imageAttachments[0].barrier.sType && fbInfo->imageAttachments[0].record)
|
||||
{
|
||||
for(size_t i = 0; fb->imageAttachments[i].barrier.sType; i++)
|
||||
bool renderArea_covers_entire_framebuffer =
|
||||
pRenderPassBegin->renderArea.offset.x == 0 && pRenderPassBegin->renderArea.offset.y == 0 &&
|
||||
pRenderPassBegin->renderArea.extent.width >= fbInfo->width &&
|
||||
pRenderPassBegin->renderArea.extent.height >= fbInfo->height;
|
||||
|
||||
for(size_t i = 0; fbInfo->imageAttachments[i].barrier.sType; i++)
|
||||
{
|
||||
VkResourceRecord *att = fb->imageAttachments[i].record;
|
||||
VkResourceRecord *att = fbInfo->imageAttachments[i].record;
|
||||
if(att == NULL)
|
||||
break;
|
||||
|
||||
record->MarkImageViewFrameReferenced(att, ImageRange(), eFrameRef_ReadBeforeWrite);
|
||||
bool framebuffer_reference_entire_attachment = fbInfo->AttachmentFullyReferenced(i, rpInfo);
|
||||
|
||||
if(fb->imageAttachments[i].barrier.oldLayout != fb->imageAttachments[i].barrier.newLayout)
|
||||
barriers.push_back(fb->imageAttachments[i].barrier);
|
||||
FrameRefType refType = eFrameRef_ReadBeforeWrite;
|
||||
|
||||
if(renderArea_covers_entire_framebuffer && framebuffer_reference_entire_attachment)
|
||||
{
|
||||
if(rpInfo->loadOpTable[i] != VK_ATTACHMENT_LOAD_OP_LOAD)
|
||||
{
|
||||
refType = eFrameRef_CompleteWrite;
|
||||
}
|
||||
}
|
||||
|
||||
record->MarkImageViewFrameReferenced(att, ImageRange(), refType);
|
||||
|
||||
if(fbInfo->imageAttachments[i].barrier.oldLayout !=
|
||||
fbInfo->imageAttachments[i].barrier.newLayout)
|
||||
barriers.push_back(fbInfo->imageAttachments[i].barrier);
|
||||
}
|
||||
}
|
||||
else if(fb->imageAttachments[0].barrier.sType)
|
||||
else if(fbInfo->imageAttachments[0].barrier.sType)
|
||||
{
|
||||
// if we have attachments but the framebuffer doesn't have images, then it's imageless. Look
|
||||
// for the image records now
|
||||
@@ -1528,9 +1550,10 @@ void WrappedVulkan::vkCmdBeginRenderPass(VkCommandBuffer commandBuffer,
|
||||
VkResourceRecord *att = GetRecord(attachmentsInfo->pAttachments[i]);
|
||||
record->MarkImageViewFrameReferenced(att, ImageRange(), eFrameRef_ReadBeforeWrite);
|
||||
|
||||
if(fb->imageAttachments[i].barrier.oldLayout != fb->imageAttachments[i].barrier.newLayout)
|
||||
if(fbInfo->imageAttachments[i].barrier.oldLayout !=
|
||||
fbInfo->imageAttachments[i].barrier.newLayout)
|
||||
{
|
||||
VkImageMemoryBarrier barrier = fb->imageAttachments[i].barrier;
|
||||
VkImageMemoryBarrier barrier = fbInfo->imageAttachments[i].barrier;
|
||||
|
||||
barrier.image = GetResourceManager()->GetCurrentHandle<VkImage>(att->baseResource);
|
||||
barrier.subresourceRange = att->viewRange;
|
||||
@@ -1966,6 +1989,7 @@ void WrappedVulkan::vkCmdBeginRenderPass2(VkCommandBuffer commandBuffer,
|
||||
record->MarkResourceFrameReferenced(GetResID(pRenderPassBegin->renderPass), eFrameRef_Read);
|
||||
|
||||
VkResourceRecord *fb = GetRecord(pRenderPassBegin->framebuffer);
|
||||
VkResourceRecord *rp = GetRecord(pRenderPassBegin->renderPass);
|
||||
|
||||
record->MarkResourceFrameReferenced(fb->GetResourceID(), eFrameRef_Read);
|
||||
|
||||
@@ -1973,18 +1997,39 @@ void WrappedVulkan::vkCmdBeginRenderPass2(VkCommandBuffer commandBuffer,
|
||||
|
||||
barriers.clear();
|
||||
|
||||
if(fb->imageAttachments[0].barrier.sType && fb->imageAttachments[0].record)
|
||||
FramebufferInfo *fbInfo = fb->framebufferInfo;
|
||||
RenderPassInfo *rpInfo = rp->renderPassInfo;
|
||||
|
||||
if(fbInfo->imageAttachments[0].barrier.sType && fbInfo->imageAttachments[0].record)
|
||||
{
|
||||
for(size_t i = 0; fb->imageAttachments[i].barrier.sType; i++)
|
||||
bool renderArea_covers_entire_framebuffer =
|
||||
pRenderPassBegin->renderArea.offset.x == 0 && pRenderPassBegin->renderArea.offset.y == 0 &&
|
||||
pRenderPassBegin->renderArea.extent.width >= fbInfo->width &&
|
||||
pRenderPassBegin->renderArea.extent.height >= fbInfo->height;
|
||||
|
||||
for(size_t i = 0; fbInfo->imageAttachments[i].barrier.sType; i++)
|
||||
{
|
||||
VkResourceRecord *att = fb->imageAttachments[i].record;
|
||||
VkResourceRecord *att = fbInfo->imageAttachments[i].record;
|
||||
if(att == NULL)
|
||||
break;
|
||||
|
||||
record->MarkImageViewFrameReferenced(att, ImageRange(), eFrameRef_ReadBeforeWrite);
|
||||
bool framebuffer_reference_entire_attachment = fbInfo->AttachmentFullyReferenced(i, rpInfo);
|
||||
|
||||
if(fb->imageAttachments[i].barrier.oldLayout != fb->imageAttachments[i].barrier.newLayout)
|
||||
barriers.push_back(fb->imageAttachments[i].barrier);
|
||||
FrameRefType refType = eFrameRef_ReadBeforeWrite;
|
||||
|
||||
if(renderArea_covers_entire_framebuffer && framebuffer_reference_entire_attachment)
|
||||
{
|
||||
if(rpInfo->loadOpTable[i] != VK_ATTACHMENT_LOAD_OP_LOAD)
|
||||
{
|
||||
refType = eFrameRef_CompleteWrite;
|
||||
}
|
||||
}
|
||||
|
||||
record->MarkImageViewFrameReferenced(att, ImageRange(), refType);
|
||||
|
||||
if(fbInfo->imageAttachments[i].barrier.oldLayout !=
|
||||
fbInfo->imageAttachments[i].barrier.newLayout)
|
||||
barriers.push_back(fbInfo->imageAttachments[i].barrier);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2001,9 +2046,10 @@ void WrappedVulkan::vkCmdBeginRenderPass2(VkCommandBuffer commandBuffer,
|
||||
VkResourceRecord *att = GetRecord(attachmentsInfo->pAttachments[i]);
|
||||
record->MarkImageViewFrameReferenced(att, ImageRange(), eFrameRef_ReadBeforeWrite);
|
||||
|
||||
if(fb->imageAttachments[i].barrier.oldLayout != fb->imageAttachments[i].barrier.newLayout)
|
||||
if(fbInfo->imageAttachments[i].barrier.oldLayout !=
|
||||
fbInfo->imageAttachments[i].barrier.newLayout)
|
||||
{
|
||||
VkImageMemoryBarrier barrier = fb->imageAttachments[i].barrier;
|
||||
VkImageMemoryBarrier barrier = fbInfo->imageAttachments[i].barrier;
|
||||
|
||||
barrier.image = GetResourceManager()->GetCurrentHandle<VkImage>(att->baseResource);
|
||||
barrier.subresourceRange = att->viewRange;
|
||||
|
||||
@@ -752,55 +752,52 @@ VkResult WrappedVulkan::vkCreateFramebuffer(VkDevice device,
|
||||
VkResourceRecord *rpRecord = GetRecord(pCreateInfo->renderPass);
|
||||
record->AddParent(rpRecord);
|
||||
|
||||
// *2 in case we need separate barriers for depth and stencil, +1 for the terminating null
|
||||
// attachment info
|
||||
uint32_t arrayCount = pCreateInfo->attachmentCount * 2 + 1;
|
||||
|
||||
record->imageAttachments = new AttachmentInfo[arrayCount];
|
||||
RDCEraseMem(record->imageAttachments, sizeof(AttachmentInfo) * arrayCount);
|
||||
RenderPassInfo *rpInfo = rpRecord->renderPassInfo;
|
||||
FramebufferInfo *fbInfo = record->framebufferInfo = new FramebufferInfo(*pCreateInfo);
|
||||
|
||||
for(uint32_t i = 0, a = 0; i < pCreateInfo->attachmentCount; i++, a++)
|
||||
{
|
||||
record->imageAttachments[a].barrier = rpRecord->imageAttachments[a].barrier;
|
||||
fbInfo->imageAttachments[a].barrier = rpInfo->imageAttachments[a].barrier;
|
||||
|
||||
if((pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT) == 0)
|
||||
{
|
||||
VkResourceRecord *attRecord = GetRecord(pCreateInfo->pAttachments[i]);
|
||||
record->AddParent(attRecord);
|
||||
|
||||
record->imageAttachments[a].record = attRecord;
|
||||
record->imageAttachments[a].barrier.image =
|
||||
fbInfo->imageAttachments[a].record = attRecord;
|
||||
fbInfo->imageAttachments[a].barrier.image =
|
||||
GetResourceManager()->GetCurrentHandle<VkImage>(attRecord->baseResource);
|
||||
record->imageAttachments[a].barrier.subresourceRange = attRecord->viewRange;
|
||||
fbInfo->imageAttachments[a].barrier.subresourceRange = attRecord->viewRange;
|
||||
|
||||
{
|
||||
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;
|
||||
fbInfo->imageAttachments[a].barrier.subresourceRange.baseArrayLayer = 0;
|
||||
fbInfo->imageAttachments[a].barrier.subresourceRange.layerCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if the renderpass specifies an aspect mask that mean split depth/stencil handling, so
|
||||
// respect the aspect mask and the next one will be stencil
|
||||
if(rpRecord->imageAttachments[a].barrier.subresourceRange.aspectMask != 0)
|
||||
if(rpInfo->imageAttachments[a].barrier.subresourceRange.aspectMask != 0)
|
||||
{
|
||||
record->imageAttachments[a].barrier.subresourceRange.aspectMask =
|
||||
rpRecord->imageAttachments[a].barrier.subresourceRange.aspectMask;
|
||||
// restore the aspectMask that might have been trampled by attRecord->viewRange
|
||||
fbInfo->imageAttachments[a].barrier.subresourceRange.aspectMask =
|
||||
rpInfo->imageAttachments[a].barrier.subresourceRange.aspectMask;
|
||||
|
||||
a++;
|
||||
|
||||
// copy most properties from previous barrier
|
||||
record->imageAttachments[a].record = record->imageAttachments[a - 1].record;
|
||||
record->imageAttachments[a].barrier = record->imageAttachments[a - 1].barrier;
|
||||
fbInfo->imageAttachments[a].record = fbInfo->imageAttachments[a - 1].record;
|
||||
fbInfo->imageAttachments[a].barrier = fbInfo->imageAttachments[a - 1].barrier;
|
||||
// copy aspect mask and layouts from the next barrier in the RP
|
||||
record->imageAttachments[a].barrier.subresourceRange.aspectMask =
|
||||
rpRecord->imageAttachments[a].barrier.subresourceRange.aspectMask;
|
||||
record->imageAttachments[a].barrier.oldLayout =
|
||||
rpRecord->imageAttachments[a].barrier.oldLayout;
|
||||
record->imageAttachments[a].barrier.newLayout =
|
||||
rpRecord->imageAttachments[a].barrier.newLayout;
|
||||
fbInfo->imageAttachments[a].barrier.subresourceRange.aspectMask =
|
||||
rpInfo->imageAttachments[a].barrier.subresourceRange.aspectMask;
|
||||
fbInfo->imageAttachments[a].barrier.oldLayout =
|
||||
rpInfo->imageAttachments[a].barrier.oldLayout;
|
||||
fbInfo->imageAttachments[a].barrier.newLayout =
|
||||
rpInfo->imageAttachments[a].barrier.newLayout;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1007,22 +1004,7 @@ VkResult WrappedVulkan::vkCreateRenderPass(VkDevice device, const VkRenderPassCr
|
||||
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pRenderPass);
|
||||
record->AddChunk(chunk);
|
||||
|
||||
// *2 in case we need separate barriers for depth and stencil, +1 for the terminating null
|
||||
// attachment info (though separate depth/stencil buffers aren't needed here, we keep the
|
||||
// array size the same)
|
||||
uint32_t arrayCount = pCreateInfo->attachmentCount * 2 + 1;
|
||||
|
||||
record->imageAttachments = new AttachmentInfo[arrayCount];
|
||||
|
||||
RDCEraseMem(record->imageAttachments, sizeof(AttachmentInfo) * arrayCount);
|
||||
|
||||
for(uint32_t i = 0; i < pCreateInfo->attachmentCount; i++)
|
||||
{
|
||||
record->imageAttachments[i].record = NULL;
|
||||
record->imageAttachments[i].barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
record->imageAttachments[i].barrier.oldLayout = pCreateInfo->pAttachments[i].initialLayout;
|
||||
record->imageAttachments[i].barrier.newLayout = pCreateInfo->pAttachments[i].finalLayout;
|
||||
}
|
||||
record->renderPassInfo = new RenderPassInfo(*pCreateInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1243,42 +1225,7 @@ VkResult WrappedVulkan::vkCreateRenderPass2(VkDevice device,
|
||||
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pRenderPass);
|
||||
record->AddChunk(chunk);
|
||||
|
||||
// *2 in case we need separate barriers for depth and stencil, +1 for the terminating null
|
||||
// attachment info
|
||||
uint32_t arrayCount = pCreateInfo->attachmentCount * 2 + 1;
|
||||
|
||||
record->imageAttachments = new AttachmentInfo[arrayCount];
|
||||
|
||||
RDCEraseMem(record->imageAttachments, sizeof(AttachmentInfo) * arrayCount);
|
||||
|
||||
for(uint32_t i = 0, a = 0; i < pCreateInfo->attachmentCount; i++, a++)
|
||||
{
|
||||
record->imageAttachments[a].record = NULL;
|
||||
record->imageAttachments[a].barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
record->imageAttachments[a].barrier.oldLayout = pCreateInfo->pAttachments[i].initialLayout;
|
||||
record->imageAttachments[a].barrier.newLayout = pCreateInfo->pAttachments[i].finalLayout;
|
||||
|
||||
// VK_KHR_separate_depth_stencil_layouts
|
||||
VkAttachmentDescriptionStencilLayoutKHR *separateStencil =
|
||||
(VkAttachmentDescriptionStencilLayoutKHR *)FindNextStruct(
|
||||
&pCreateInfo->pAttachments[i],
|
||||
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR);
|
||||
|
||||
if(separateStencil)
|
||||
{
|
||||
record->imageAttachments[a].barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
// add a separate barrier for stencil
|
||||
a++;
|
||||
|
||||
record->imageAttachments[a].record = NULL;
|
||||
record->imageAttachments[a].barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
record->imageAttachments[a].barrier.oldLayout = separateStencil->stencilInitialLayout;
|
||||
record->imageAttachments[a].barrier.newLayout = separateStencil->stencilFinalLayout;
|
||||
record->imageAttachments[a].barrier.subresourceRange.aspectMask =
|
||||
VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
}
|
||||
record->renderPassInfo = new RenderPassInfo(*pCreateInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1024,6 +1024,17 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
|
||||
GetResourceManager()->MarkResourceFrameReferenced(record->GetResourceID(),
|
||||
eFrameRef_ReadBeforeWrite);
|
||||
}
|
||||
|
||||
// pull in frame refs while background capturing too
|
||||
for(uint32_t s = 0; s < submitCount; s++)
|
||||
{
|
||||
for(uint32_t i = 0; i < pSubmits[s].commandBufferCount; i++)
|
||||
{
|
||||
VkResourceRecord *record = GetRecord(pSubmits[s].pCommandBuffers[i]);
|
||||
|
||||
record->bakedCommands->AddResourceReferences(GetResourceManager());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(capframe)
|
||||
|
||||
Reference in New Issue
Block a user