mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-16 12:37:08 +00:00
Optimise UI for large descriptor arrays with few dynamically used binds
* We tune the pipeline state view and texture viewer to only iterate over a small list of dynamically used binds in the (vastly more common) case where unused binds are not being shown.
This commit is contained in:
@@ -315,6 +315,7 @@ struct BoundResourceArray
|
||||
BoundResourceArray(Bindpoint b, const rdcarray<BoundResource> &r) : bindPoint(b), resources(r)
|
||||
{
|
||||
dynamicallyUsedCount = (uint32_t)r.size();
|
||||
firstIndex = 0;
|
||||
}
|
||||
// for convenience for searching the array, we compare only using the BindPoint
|
||||
bool operator==(const BoundResourceArray &o) const { return bindPoint == o.bindPoint; }
|
||||
@@ -330,8 +331,17 @@ struct BoundResourceArray
|
||||
|
||||
Some APIs provide fine-grained usage based on dynamic shader feedback, to support 'bindless'
|
||||
scenarios where only a small sparse subset of bound resources are actually used.
|
||||
|
||||
If this information isn't present this will be set to a large number.
|
||||
)");
|
||||
uint32_t dynamicallyUsedCount = 0;
|
||||
uint32_t dynamicallyUsedCount = ~0U;
|
||||
DOCUMENT(R"(Gives the array index of the first binding in :data:`resource`. If only a small subset
|
||||
of the resources are used by the shader then the array may be rebased such that the first element is
|
||||
not array index 0.
|
||||
|
||||
For more information see :data:`VKBindingElement.dynamicallyUsed`.
|
||||
)");
|
||||
int32_t firstIndex = 0;
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(BoundResourceArray);
|
||||
|
||||
@@ -305,10 +305,12 @@ For some APIs that don't distinguish by entry point, this may be empty.
|
||||
DOCUMENT(R"(Retrieves the read-only resources bound to a particular shader stage.
|
||||
|
||||
:param ShaderStage stage: The shader stage to fetch from.
|
||||
:param bool onlyUsed: Return only a subset of resources containing those actually used by the
|
||||
shader.
|
||||
:return: The currently bound read-only resources.
|
||||
:rtype: ``list`` of :class:`BoundResourceArray` entries
|
||||
)");
|
||||
rdcarray<BoundResourceArray> GetReadOnlyResources(ShaderStage stage) const;
|
||||
rdcarray<BoundResourceArray> GetReadOnlyResources(ShaderStage stage, bool onlyUsed = false) const;
|
||||
|
||||
DOCUMENT(R"(Retrieves the samplers bound to a particular shader stage.
|
||||
|
||||
@@ -321,10 +323,12 @@ For some APIs that don't distinguish by entry point, this may be empty.
|
||||
DOCUMENT(R"(Retrieves the read/write resources bound to a particular shader stage.
|
||||
|
||||
:param ShaderStage stage: The shader stage to fetch from.
|
||||
:param bool onlyUsed: Return only a subset of resources containing those actually used by the
|
||||
shader.
|
||||
:return: The currently bound read/write resources.
|
||||
:rtype: ``list`` of :class:`BoundResourceArray` entries
|
||||
)");
|
||||
rdcarray<BoundResourceArray> GetReadWriteResources(ShaderStage stage) const;
|
||||
rdcarray<BoundResourceArray> GetReadWriteResources(ShaderStage stage, bool onlyUsed = false) const;
|
||||
|
||||
DOCUMENT(R"(Retrieves the read/write resources bound to the depth-stencil output.
|
||||
|
||||
|
||||
@@ -1132,7 +1132,7 @@ rdcarray<BoundResourceArray> PipeState::GetSamplers(ShaderStage stage) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
rdcarray<BoundResourceArray> PipeState::GetReadOnlyResources(ShaderStage stage) const
|
||||
rdcarray<BoundResourceArray> PipeState::GetReadOnlyResources(ShaderStage stage, bool onlyUsed) const
|
||||
{
|
||||
rdcarray<BoundResourceArray> ret;
|
||||
|
||||
@@ -1251,18 +1251,33 @@ rdcarray<BoundResourceArray> PipeState::GetReadOnlyResources(ShaderStage stage)
|
||||
ret.push_back(BoundResourceArray());
|
||||
ret.back().bindPoint = Bindpoint(set, slot);
|
||||
|
||||
rdcarray<BoundResource> &val = ret.back().resources;
|
||||
val.resize(bind.descriptorCount);
|
||||
uint32_t count = bind.descriptorCount;
|
||||
uint32_t firstIdx = 0;
|
||||
|
||||
if(onlyUsed)
|
||||
{
|
||||
firstIdx = (uint32_t)bind.firstUsedIndex;
|
||||
if(bind.dynamicallyUsedCount < count)
|
||||
count = bind.dynamicallyUsedCount;
|
||||
if((uint32_t)bind.lastUsedIndex < count)
|
||||
count = uint32_t(bind.lastUsedIndex - bind.firstUsedIndex + 1);
|
||||
}
|
||||
|
||||
rdcarray<BoundResource> &val = ret.back().resources;
|
||||
val.reserve(count);
|
||||
|
||||
ret.back().firstIndex = (int32_t)firstIdx;
|
||||
ret.back().dynamicallyUsedCount = bind.dynamicallyUsedCount;
|
||||
|
||||
for(uint32_t i = 0; i < bind.descriptorCount; i++)
|
||||
BoundResource res;
|
||||
for(uint32_t i = firstIdx; i < firstIdx + count; i++)
|
||||
{
|
||||
val[i].resourceId = bind.binds[i].resourceResourceId;
|
||||
val[i].dynamicallyUsed = bind.binds[i].dynamicallyUsed;
|
||||
val[i].firstMip = (int)bind.binds[i].firstMip;
|
||||
val[i].firstSlice = (int)bind.binds[i].firstSlice;
|
||||
val[i].typeCast = bind.binds[i].viewFormat.compType;
|
||||
res.resourceId = bind.binds[i].resourceResourceId;
|
||||
res.dynamicallyUsed = bind.binds[i].dynamicallyUsed;
|
||||
res.firstMip = (int)bind.binds[i].firstMip;
|
||||
res.firstSlice = (int)bind.binds[i].firstSlice;
|
||||
res.typeCast = bind.binds[i].viewFormat.compType;
|
||||
val.push_back(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1275,7 +1290,7 @@ rdcarray<BoundResourceArray> PipeState::GetReadOnlyResources(ShaderStage stage)
|
||||
return ret;
|
||||
}
|
||||
|
||||
rdcarray<BoundResourceArray> PipeState::GetReadWriteResources(ShaderStage stage) const
|
||||
rdcarray<BoundResourceArray> PipeState::GetReadWriteResources(ShaderStage stage, bool onlyUsed) const
|
||||
{
|
||||
rdcarray<BoundResourceArray> ret;
|
||||
|
||||
@@ -1417,18 +1432,33 @@ rdcarray<BoundResourceArray> PipeState::GetReadWriteResources(ShaderStage stage)
|
||||
ret.push_back(BoundResourceArray());
|
||||
ret.back().bindPoint = Bindpoint(set, slot);
|
||||
|
||||
rdcarray<BoundResource> &val = ret.back().resources;
|
||||
val.resize(bind.descriptorCount);
|
||||
uint32_t count = bind.descriptorCount;
|
||||
uint32_t firstIdx = 0;
|
||||
|
||||
if(onlyUsed)
|
||||
{
|
||||
firstIdx = (uint32_t)bind.firstUsedIndex;
|
||||
if(bind.dynamicallyUsedCount < count)
|
||||
count = bind.dynamicallyUsedCount;
|
||||
if((uint32_t)bind.lastUsedIndex < count)
|
||||
count = uint32_t(bind.lastUsedIndex - bind.firstUsedIndex + 1);
|
||||
}
|
||||
|
||||
rdcarray<BoundResource> &val = ret.back().resources;
|
||||
val.reserve(count);
|
||||
|
||||
ret.back().firstIndex = (int32_t)firstIdx;
|
||||
ret.back().dynamicallyUsedCount = bind.dynamicallyUsedCount;
|
||||
|
||||
for(uint32_t i = 0; i < bind.descriptorCount; i++)
|
||||
BoundResource res;
|
||||
for(uint32_t i = firstIdx; i < firstIdx + count; i++)
|
||||
{
|
||||
val[i].resourceId = bind.binds[i].resourceResourceId;
|
||||
val[i].dynamicallyUsed = bind.binds[i].dynamicallyUsed;
|
||||
val[i].firstMip = (int)bind.binds[i].firstMip;
|
||||
val[i].firstSlice = (int)bind.binds[i].firstSlice;
|
||||
val[i].typeCast = bind.binds[i].viewFormat.compType;
|
||||
res.resourceId = bind.binds[i].resourceResourceId;
|
||||
res.dynamicallyUsed = bind.binds[i].dynamicallyUsed;
|
||||
res.firstMip = (int)bind.binds[i].firstMip;
|
||||
res.firstSlice = (int)bind.binds[i].firstSlice;
|
||||
res.typeCast = bind.binds[i].viewFormat.compType;
|
||||
val.push_back(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,23 @@ redundant iteration to determine whether any bindings are present.
|
||||
|
||||
For more information see :data:`VKBindingElement.dynamicallyUsed`.
|
||||
)");
|
||||
uint32_t dynamicallyUsedCount = 0;
|
||||
uint32_t dynamicallyUsedCount = ~0U;
|
||||
DOCUMENT(R"(Gives the index of the first binding in :data:`binds` that is dynamically used. Useful
|
||||
to avoid redundant iteration in very large descriptor arrays with a small subset that are used.
|
||||
|
||||
For more information see :data:`VKBindingElement.dynamicallyUsed`.
|
||||
)");
|
||||
int32_t firstUsedIndex = 0;
|
||||
DOCUMENT(R"(Gives the index of the first binding in :data:`binds` that is dynamically used. Useful
|
||||
to avoid redundant iteration in very large descriptor arrays with a small subset that are used.
|
||||
|
||||
.. note::
|
||||
This may be set to a higher value than the number of bindings, if no dynamic use information is
|
||||
available. Ensure that this is an additional check on the bind and the count is still respected.
|
||||
|
||||
For more information see :data:`VKBindingElement.dynamicallyUsed`.
|
||||
)");
|
||||
int32_t lastUsedIndex = 0x7fffffff;
|
||||
DOCUMENT("The :class:`BindType` of this binding.");
|
||||
BindType type = BindType::Unknown;
|
||||
DOCUMENT("The :class:`ShaderStageMask` where this binding is visible.");
|
||||
|
||||
Reference in New Issue
Block a user