mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-27 12:21:11 +00:00
Added InitPolicy
This allows finer control of the initialization/reset behaviour of resources based on their ref type. Currently, these policies only apply to the initialization/reseting of VkDeviceMemory and VkImage resources. Change-Id: Ib647cbaf99b650e8da40d07944400ace7dde504d
This commit is contained in:
committed by
Baldur Karlsson
parent
40c56dafa3
commit
5120622dac
@@ -139,41 +139,97 @@ bool IsDirtyFrameRef(FrameRefType refType);
|
||||
// init/reset requirements.
|
||||
enum InitReqType
|
||||
{
|
||||
// Initial contents of the resource are not used, and also not modified.
|
||||
// No initialization/reset is required for correct replay, but may be helpful
|
||||
// to avoid user confusion when analyzing the resource.
|
||||
// Corresponds to `None` ref type.
|
||||
// No initialization required.
|
||||
eInitReq_None,
|
||||
|
||||
// Initial contents of the resource are not used, but the contents are
|
||||
// potentially modified during the frame.
|
||||
// No initialization/reset is required for correct replay, but may be helpful
|
||||
// to avoid user confusion when analyzing the resource.
|
||||
// Corresponds to `PartialWrite` and `CompleteWrite` ref types.
|
||||
// Initialize the resource by clearing.
|
||||
eInitReq_Clear,
|
||||
|
||||
// Initial contents of the resource are read, but not overwritten;
|
||||
// the resource needs to be initialized before the first replay, but need not
|
||||
// be reset before subsequent replays.
|
||||
// Corresponds to `Read` ref type.
|
||||
eInitReq_InitOnce,
|
||||
// Initialize the resource by copying initial data.
|
||||
eInitReq_Copy,
|
||||
};
|
||||
|
||||
// Initial contents of the resource are read, and later overwritten;
|
||||
// the resource needs to be reset before each replay.
|
||||
// Corresponds to `ReadBeforeWrite` ref type.
|
||||
eInitReq_Reset,
|
||||
enum InitPolicy
|
||||
{
|
||||
// Completely disable optimizations--copy initial data into every resource
|
||||
// before every replay.
|
||||
eInitPolicy_NoOpt,
|
||||
|
||||
// CopyAll--conservative policy which ensures each subresource begins each
|
||||
// replay with the correct initial data.
|
||||
//
|
||||
// Initialization policy:
|
||||
// Copy initial data into each subresource
|
||||
//
|
||||
// Reset policy:
|
||||
// Copy initial data into each subresource which is written
|
||||
eInitPolicy_CopyAll,
|
||||
|
||||
// ClearUnread--avoid copying initial data which is never read by the replay
|
||||
// commands. A user inspecting a resource before it is written may observe
|
||||
// cleared data, rather than the actual initial data.
|
||||
//
|
||||
// Initialization policy:
|
||||
// Copy initial data into each subresource that is read.
|
||||
// Clear each subresource that is not read.
|
||||
//
|
||||
// Reset policy:
|
||||
// Copy initial data into each subresource where the initial data is read
|
||||
// and then overwritten.
|
||||
// Clear each subresource which is written, but whose initial data is not read.
|
||||
eInitPolicy_ClearUnread,
|
||||
|
||||
// Fastest--Initialize/reset as little as possible for correct replay.
|
||||
// A user inspecting a resource before it is written may observe the data
|
||||
// from a future write (from the previous replay).
|
||||
//
|
||||
// Initialization policy:
|
||||
// Copy initial data into each subresource that is read.
|
||||
// Clear each subresource that is not read.
|
||||
//
|
||||
// Reset policy:
|
||||
// Copy initial data into each subresource where the initial data is read
|
||||
// and then overwritten.
|
||||
eInitPolicy_Fastest,
|
||||
};
|
||||
|
||||
// Return the initialization/reset requirements for a FrameRefType
|
||||
inline InitReqType InitReq(FrameRefType refType)
|
||||
inline InitReqType InitReq(FrameRefType refType, InitPolicy policy, bool initialized)
|
||||
{
|
||||
switch(refType)
|
||||
#define COPY_ONCE (initialized ? eInitReq_None : eInitReq_Copy)
|
||||
#define CLEAR_ONCE (initialized ? eInitReq_None : eInitReq_Clear)
|
||||
switch(policy)
|
||||
{
|
||||
case eFrameRef_None: return eInitReq_None;
|
||||
case eFrameRef_Read: return eInitReq_InitOnce;
|
||||
case eFrameRef_ReadBeforeWrite: return eInitReq_Reset;
|
||||
default: return eInitReq_Clear;
|
||||
case eInitPolicy_NoOpt: return eInitReq_Copy;
|
||||
case eInitPolicy_CopyAll:
|
||||
switch(refType)
|
||||
{
|
||||
case eFrameRef_None: return COPY_ONCE;
|
||||
case eFrameRef_Read: return COPY_ONCE;
|
||||
default: return eInitReq_Copy;
|
||||
}
|
||||
case eInitPolicy_ClearUnread:
|
||||
switch(refType)
|
||||
{
|
||||
case eFrameRef_None: return CLEAR_ONCE;
|
||||
case eFrameRef_Read: return COPY_ONCE;
|
||||
case eFrameRef_ReadBeforeWrite: return eInitReq_Copy;
|
||||
case eFrameRef_WriteBeforeRead: return eInitReq_Copy;
|
||||
default: return eInitReq_Clear;
|
||||
}
|
||||
case eInitPolicy_Fastest:
|
||||
switch(refType)
|
||||
{
|
||||
case eFrameRef_None: return CLEAR_ONCE;
|
||||
case eFrameRef_Read: return COPY_ONCE;
|
||||
case eFrameRef_ReadBeforeWrite: return eInitReq_Copy;
|
||||
case eFrameRef_WriteBeforeRead: return COPY_ONCE;
|
||||
default: return CLEAR_ONCE;
|
||||
}
|
||||
default: RDCERR("Unknown initialization policy (%d).", policy); return eInitReq_Copy;
|
||||
}
|
||||
#undef COPY_ONCE
|
||||
#undef CLEAR_ONCE
|
||||
}
|
||||
|
||||
// handle marking a resource referenced for read or write and storing RAW access etc.
|
||||
|
||||
@@ -900,7 +900,7 @@ private:
|
||||
const char *pMessage, void *pUserData);
|
||||
void AddFrameTerminator(uint64_t queueMarkerTag);
|
||||
std::vector<VkImageMemoryBarrier> ImageInitializationBarriers(ResourceId id, WrappedVkRes *live,
|
||||
bool initialized,
|
||||
InitPolicy policy, bool initialized,
|
||||
const ImgRefs *imgRefs) const;
|
||||
void SubmitExtQBarriers(const std::map<uint32_t, std::vector<VkImageMemoryBarrier>> &extQBarriers);
|
||||
|
||||
|
||||
@@ -1314,7 +1314,7 @@ void WrappedVulkan::Create_InitialState(ResourceId id, WrappedVkRes *live, bool
|
||||
}
|
||||
|
||||
std::vector<VkImageMemoryBarrier> WrappedVulkan::ImageInitializationBarriers(
|
||||
ResourceId id, WrappedVkRes *live, bool initialized, const ImgRefs *imgRefs) const
|
||||
ResourceId id, WrappedVkRes *live, InitPolicy policy, bool initialized, const ImgRefs *imgRefs) const
|
||||
{
|
||||
std::vector<VkImageMemoryBarrier> barriers;
|
||||
|
||||
@@ -1346,10 +1346,11 @@ std::vector<VkImageMemoryBarrier> WrappedVulkan::ImageInitializationBarriers(
|
||||
}
|
||||
else
|
||||
{
|
||||
auto initReqs = imgRefs->SubresourceRangeInitReqs(barrier.subresourceRange);
|
||||
auto initReqs =
|
||||
imgRefs->SubresourceRangeInitReqs(barrier.subresourceRange, policy, initialized);
|
||||
for(auto initIt = initReqs.begin(); initIt != initReqs.end(); ++initIt)
|
||||
{
|
||||
if(initIt->second == eInitReq_Reset || initIt->second == eInitReq_Clear)
|
||||
if(initIt->second != eInitReq_None)
|
||||
{
|
||||
barrier.subresourceRange = initIt->first;
|
||||
barriers.push_back(barrier);
|
||||
@@ -1478,6 +1479,7 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
ResourceId orig = GetResourceManager()->GetOriginalID(id);
|
||||
ImgRefs *imgRefs = NULL;
|
||||
bool initialized = false;
|
||||
InitPolicy policy = GetResourceManager()->GetInitPolicy();
|
||||
if(GetResourceManager()->OptimizeInitialState())
|
||||
{
|
||||
imgRefs = GetResourceManager()->FindImgRefs(orig);
|
||||
@@ -1934,8 +1936,8 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<VkImageMemoryBarrier> barriers =
|
||||
ImageInitializationBarriers(id, live, initialized, imgRefs);
|
||||
std::vector<VkImageMemoryBarrier> barriers = ImageInitializationBarriers(
|
||||
id, live, GetResourceManager()->GetInitPolicy(), initialized, imgRefs);
|
||||
DoPipelineBarrier(cmd, (uint32_t)barriers.size(), barriers.data());
|
||||
|
||||
std::map<uint32_t, std::vector<VkImageMemoryBarrier> > extQBarriers = GetExtQBarriers(barriers);
|
||||
@@ -1951,19 +1953,20 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
std::vector<VkBufferImageCopy> copyRegions;
|
||||
std::vector<VkImageSubresourceRange> clearRegions;
|
||||
|
||||
#define INIT_REGION() \
|
||||
if(!initialized) \
|
||||
{ \
|
||||
copyRegions.push_back(region); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
InitReqType initReq = imgRefs->SubresourceInitReq( \
|
||||
imgRefs->AspectIndex((VkImageAspectFlagBits)region.imageSubresource.aspectMask), m, a); \
|
||||
if(initReq == eInitReq_Reset) \
|
||||
copyRegions.push_back(region); \
|
||||
else if(initReq == eInitReq_Clear) \
|
||||
clearRegions.push_back(ImageRange(region.imageSubresource)); \
|
||||
#define INIT_REGION() \
|
||||
if(!initialized) \
|
||||
{ \
|
||||
copyRegions.push_back(region); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
InitReqType initReq = imgRefs->SubresourceInitReq( \
|
||||
imgRefs->AspectIndex((VkImageAspectFlagBits)region.imageSubresource.aspectMask), m, a, \
|
||||
policy, initialized); \
|
||||
if(initReq == eInitReq_Copy) \
|
||||
copyRegions.push_back(region); \
|
||||
else if(initReq == eInitReq_Clear) \
|
||||
clearRegions.push_back(ImageRange(region.imageSubresource)); \
|
||||
}
|
||||
|
||||
// copy each slice/mip individually
|
||||
@@ -2100,22 +2103,23 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
{
|
||||
// No information about the memory usage in the frame.
|
||||
// Pessimistically assume the entire memory needs to be reset.
|
||||
resetReq.update(0, initial.mem.size, eInitReq_Reset,
|
||||
[](InitReqType x, InitReqType y) -> InitReqType { return std::max(x, y); });
|
||||
resetReq.update(0, initial.mem.size, eInitReq_Copy,
|
||||
[](InitReqType x, InitReqType y) -> InitReqType { return RDCMAX(x, y); });
|
||||
}
|
||||
else
|
||||
{
|
||||
bool initialized = memRefs->initializedLiveRes == live;
|
||||
memRefs->initializedLiveRes = live;
|
||||
InitPolicy policy = GetResourceManager()->GetInitPolicy();
|
||||
for(auto it = memRefs->rangeRefs.begin(); it != memRefs->rangeRefs.end(); it++)
|
||||
{
|
||||
InitReqType t = InitReq(it->value());
|
||||
if(t == eInitReq_Reset || (t == eInitReq_InitOnce && !initialized))
|
||||
resetReq.update(it->start(), it->finish(), eInitReq_Reset,
|
||||
[](InitReqType x, InitReqType y) -> InitReqType { return std::max(x, y); });
|
||||
else if(t == eInitReq_Clear || (t == eInitReq_None && !initialized))
|
||||
InitReqType t = InitReq(it->value(), policy, initialized);
|
||||
if(t == eInitReq_Copy)
|
||||
resetReq.update(it->start(), it->finish(), eInitReq_Copy,
|
||||
[](InitReqType x, InitReqType y) -> InitReqType { return RDCMAX(x, y); });
|
||||
else if(t == eInitReq_Clear)
|
||||
resetReq.update(it->start(), it->finish(), eInitReq_Clear,
|
||||
[](InitReqType x, InitReqType y) -> InitReqType { return std::max(x, y); });
|
||||
[](InitReqType x, InitReqType y) -> InitReqType { return RDCMAX(x, y); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2158,7 +2162,7 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
ObjDisp(cmd)->CmdFillBuffer(Unwrap(cmd), Unwrap(dstBuf), it->start(), size, 0);
|
||||
fillCount++;
|
||||
break;
|
||||
case eInitReq_Reset: regions.push_back({it->start(), it->start(), size}); break;
|
||||
case eInitReq_Copy: regions.push_back({it->start(), it->start(), size}); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,6 +441,7 @@ public:
|
||||
ImgRefs *FindImgRefs(ResourceId img);
|
||||
|
||||
inline bool OptimizeInitialState() { return m_OptimizeInitialState; }
|
||||
inline InitPolicy GetInitPolicy() { return m_InitPolicy; }
|
||||
private:
|
||||
bool ResourceTypeRelease(WrappedVkRes *res);
|
||||
|
||||
@@ -457,4 +458,5 @@ private:
|
||||
std::map<ResourceId, MemRefs> m_MemFrameRefs;
|
||||
std::map<ResourceId, ImgRefs> m_ImgFrameRefs;
|
||||
bool m_OptimizeInitialState = false;
|
||||
InitPolicy m_InitPolicy = eInitPolicy_CopyAll;
|
||||
};
|
||||
|
||||
@@ -2964,7 +2964,7 @@ int ImgRefs::SubresourceIndex(int aspectIndex, int level, int layer) const
|
||||
}
|
||||
|
||||
std::vector<rdcpair<VkImageSubresourceRange, InitReqType> > ImgRefs::SubresourceRangeInitReqs(
|
||||
VkImageSubresourceRange range) const
|
||||
VkImageSubresourceRange range, InitPolicy policy, bool initialized) const
|
||||
{
|
||||
VkImageSubresourceRange out(range);
|
||||
std::vector<rdcpair<VkImageSubresourceRange, InitReqType> > res;
|
||||
@@ -3004,7 +3004,8 @@ std::vector<rdcpair<VkImageSubresourceRange, InitReqType> > ImgRefs::Subresource
|
||||
for(int layer = range.baseArrayLayer; layer < splitLayerCount; ++layer)
|
||||
{
|
||||
out.baseArrayLayer = layer;
|
||||
res.push_back(make_rdcpair(out, SubresourceInitReq(aspectIndex, level, layer)));
|
||||
res.push_back(
|
||||
make_rdcpair(out, SubresourceInitReq(aspectIndex, level, layer, policy, initialized)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1136,16 +1136,13 @@ struct ImgRefs
|
||||
{
|
||||
return rangeRefs[SubresourceIndex(aspectIndex, level, layer)];
|
||||
}
|
||||
inline InitReqType SubresourceInitReq(int aspectIndex, int level, int layer) const
|
||||
inline InitReqType SubresourceInitReq(int aspectIndex, int level, int layer, InitPolicy policy,
|
||||
bool initialized) const
|
||||
{
|
||||
return InitReq(SubresourceRef(aspectIndex, level, layer));
|
||||
}
|
||||
inline InitReqType SubresourceInitReq(int aspectIndex, int level, int layer, bool initialized) const
|
||||
{
|
||||
return InitReq(SubresourceRef(aspectIndex, level, layer));
|
||||
return InitReq(SubresourceRef(aspectIndex, level, layer), policy, initialized);
|
||||
}
|
||||
std::vector<rdcpair<VkImageSubresourceRange, InitReqType> > SubresourceRangeInitReqs(
|
||||
VkImageSubresourceRange range) const;
|
||||
VkImageSubresourceRange range, InitPolicy policy, bool initialized) const;
|
||||
void Split(bool splitAspects, bool splitLevels, bool splitLayers);
|
||||
template <typename Compose>
|
||||
FrameRefType Update(ImageRange range, FrameRefType refType, Compose comp);
|
||||
|
||||
Reference in New Issue
Block a user