mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-21 06:51:35 +00:00
Implement bindless feedback for DXBC shaders on D3D12 with patching
This commit is contained in:
@@ -282,6 +282,15 @@ struct View
|
||||
:type: TextureSwizzle4
|
||||
)");
|
||||
TextureSwizzle4 swizzle;
|
||||
DOCUMENT(R"(``True`` if this binding element is dynamically used.
|
||||
|
||||
If set to ``False`` this means that the binding was available to the shader but during execution it
|
||||
was not referenced. The data gathered for setting this variable is conservative, meaning that only
|
||||
accesses through arrays will have this calculated to reduce the required feedback bandwidth - single
|
||||
non-arrayed descriptors may have this value set to ``True`` even if the shader did not use them,
|
||||
since single descriptors may only be dynamically skipped by control flow.
|
||||
)");
|
||||
bool dynamicallyUsed = true;
|
||||
DOCUMENT("The :class:`D3DBufferViewFlags` set for the buffer.");
|
||||
D3DBufferViewFlags bufferFlags = D3DBufferViewFlags::NoFlags;
|
||||
DOCUMENT("If the view has a hidden counter, this stores the current value of the counter.");
|
||||
@@ -464,8 +473,9 @@ struct RootSignatureRange
|
||||
bool operator==(const RootSignatureRange &o) const
|
||||
{
|
||||
return immediate == o.immediate && rootElement == o.rootElement && visibility == o.visibility &&
|
||||
registerSpace == o.registerSpace && constantBuffers == o.constantBuffers &&
|
||||
samplers == o.samplers && views == o.views;
|
||||
registerSpace == o.registerSpace && dynamicallyUsedCount == o.dynamicallyUsedCount &&
|
||||
firstUsedIndex == o.firstUsedIndex && lastUsedIndex == o.lastUsedIndex &&
|
||||
constantBuffers == o.constantBuffers && samplers == o.samplers && views == o.views;
|
||||
}
|
||||
bool operator<(const RootSignatureRange &o) const
|
||||
{
|
||||
@@ -477,6 +487,12 @@ struct RootSignatureRange
|
||||
return visibility < o.visibility;
|
||||
if(!(registerSpace == o.registerSpace))
|
||||
return registerSpace < o.registerSpace;
|
||||
if(!(dynamicallyUsedCount == o.dynamicallyUsedCount))
|
||||
return dynamicallyUsedCount < o.dynamicallyUsedCount;
|
||||
if(!(firstUsedIndex == o.firstUsedIndex))
|
||||
return firstUsedIndex < o.firstUsedIndex;
|
||||
if(!(lastUsedIndex == o.lastUsedIndex))
|
||||
return lastUsedIndex < o.lastUsedIndex;
|
||||
if(!(constantBuffers == o.constantBuffers))
|
||||
return constantBuffers < o.constantBuffers;
|
||||
if(!(samplers == o.samplers))
|
||||
@@ -496,6 +512,28 @@ struct RootSignatureRange
|
||||
ShaderStageMask visibility = ShaderStageMask::All;
|
||||
DOCUMENT("The register space of this element.");
|
||||
uint32_t registerSpace;
|
||||
DOCUMENT(R"(Lists how many bindings in :data:`views` are dynamically used. Useful to avoid
|
||||
redundant iteration to determine whether any bindings are present.
|
||||
|
||||
For more information see :data:`D3D12View.dynamicallyUsed`.
|
||||
)");
|
||||
uint32_t dynamicallyUsedCount = ~0U;
|
||||
DOCUMENT(R"(Gives the index of the first binding in :data:`views` 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:`D3D12View.dynamicallyUsed`.
|
||||
)");
|
||||
int32_t firstUsedIndex = 0;
|
||||
DOCUMENT(R"(Gives the index of the first binding in :data:`views` 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:`D3D12View.dynamicallyUsed`.
|
||||
)");
|
||||
int32_t lastUsedIndex = 0x7fffffff;
|
||||
DOCUMENT(R"(The constant buffers in this range.
|
||||
|
||||
:type: List[D3D12ConstantBuffer]
|
||||
|
||||
@@ -1272,6 +1272,8 @@ rdcarray<BoundResourceArray> PipeState::GetReadOnlyResources(ShaderStage stage,
|
||||
|
||||
rdcarray<BoundResource> &val = ret.back().resources;
|
||||
|
||||
ret.back().dynamicallyUsedCount = 0;
|
||||
|
||||
for(size_t i = 0; i < m_D3D12->rootElements.size(); ++i)
|
||||
{
|
||||
const D3D12Pipe::RootSignatureRange &element = m_D3D12->rootElements[i];
|
||||
@@ -1281,7 +1283,19 @@ rdcarray<BoundResourceArray> PipeState::GetReadOnlyResources(ShaderStage stage,
|
||||
if(element.type == BindType::ReadOnlyResource &&
|
||||
element.registerSpace == (uint32_t)bind.bindset)
|
||||
{
|
||||
for(size_t j = 0; j < element.views.size(); ++j)
|
||||
size_t firstIdx = 0;
|
||||
size_t count = element.views.size();
|
||||
|
||||
if(onlyUsed && val.empty())
|
||||
{
|
||||
firstIdx = (uint32_t)element.firstUsedIndex;
|
||||
count = std::min(count - firstIdx,
|
||||
size_t(element.lastUsedIndex - element.firstUsedIndex + 1));
|
||||
|
||||
ret.back().firstIndex = (int32_t)firstIdx;
|
||||
}
|
||||
|
||||
for(size_t j = firstIdx; j < count; ++j)
|
||||
{
|
||||
const D3D12Pipe::View &view = element.views[j];
|
||||
if(view.bind >= start && view.bind < end)
|
||||
@@ -1289,9 +1303,13 @@ rdcarray<BoundResourceArray> PipeState::GetReadOnlyResources(ShaderStage stage,
|
||||
val.push_back(BoundResource());
|
||||
BoundResource &b = val.back();
|
||||
b.resourceId = view.resourceId;
|
||||
b.dynamicallyUsed = view.dynamicallyUsed;
|
||||
b.firstMip = (int)view.firstMip;
|
||||
b.firstSlice = (int)view.firstSlice;
|
||||
b.typeCast = view.viewFormat.compType;
|
||||
|
||||
if(view.dynamicallyUsed)
|
||||
ret.back().dynamicallyUsedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1352,7 +1370,8 @@ rdcarray<BoundResourceArray> PipeState::GetReadOnlyResources(ShaderStage stage,
|
||||
if(onlyUsed)
|
||||
{
|
||||
firstIdx = (uint32_t)bind.firstUsedIndex;
|
||||
count = std::min(count, uint32_t(bind.lastUsedIndex - bind.firstUsedIndex + 1));
|
||||
count =
|
||||
std::min(count - firstIdx, uint32_t(bind.lastUsedIndex - bind.firstUsedIndex + 1));
|
||||
}
|
||||
|
||||
rdcarray<BoundResource> &val = ret.back().resources;
|
||||
@@ -1454,6 +1473,8 @@ rdcarray<BoundResourceArray> PipeState::GetReadWriteResources(ShaderStage stage,
|
||||
|
||||
rdcarray<BoundResource> &val = ret.back().resources;
|
||||
|
||||
ret.back().dynamicallyUsedCount = 0;
|
||||
|
||||
for(size_t i = 0; i < m_D3D12->rootElements.size(); ++i)
|
||||
{
|
||||
const D3D12Pipe::RootSignatureRange &element = m_D3D12->rootElements[i];
|
||||
@@ -1463,7 +1484,19 @@ rdcarray<BoundResourceArray> PipeState::GetReadWriteResources(ShaderStage stage,
|
||||
if(element.type == BindType::ReadWriteResource &&
|
||||
element.registerSpace == (uint32_t)bind.bindset)
|
||||
{
|
||||
for(size_t j = 0; j < element.views.size(); ++j)
|
||||
size_t firstIdx = 0;
|
||||
size_t count = element.views.size();
|
||||
|
||||
if(onlyUsed && val.empty())
|
||||
{
|
||||
firstIdx = (uint32_t)element.firstUsedIndex;
|
||||
count = std::min(count - firstIdx,
|
||||
size_t(element.lastUsedIndex - element.firstUsedIndex + 1));
|
||||
|
||||
ret.back().firstIndex = (int32_t)firstIdx;
|
||||
}
|
||||
|
||||
for(size_t j = firstIdx; j < count; ++j)
|
||||
{
|
||||
const D3D12Pipe::View &view = element.views[j];
|
||||
if(view.bind >= start && view.bind < end)
|
||||
@@ -1471,9 +1504,13 @@ rdcarray<BoundResourceArray> PipeState::GetReadWriteResources(ShaderStage stage,
|
||||
val.push_back(BoundResource());
|
||||
BoundResource &b = val.back();
|
||||
b.resourceId = view.resourceId;
|
||||
b.dynamicallyUsed = view.dynamicallyUsed;
|
||||
b.firstMip = (int)view.firstMip;
|
||||
b.firstSlice = (int)view.firstSlice;
|
||||
b.typeCast = view.viewFormat.compType;
|
||||
|
||||
if(view.dynamicallyUsed)
|
||||
ret.back().dynamicallyUsedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1530,7 +1567,8 @@ rdcarray<BoundResourceArray> PipeState::GetReadWriteResources(ShaderStage stage,
|
||||
if(onlyUsed)
|
||||
{
|
||||
firstIdx = (uint32_t)bind.firstUsedIndex;
|
||||
count = std::min(count, uint32_t(bind.lastUsedIndex - bind.firstUsedIndex + 1));
|
||||
count =
|
||||
std::min(count - firstIdx, uint32_t(bind.lastUsedIndex - bind.firstUsedIndex + 1));
|
||||
}
|
||||
|
||||
rdcarray<BoundResource> &val = ret.back().resources;
|
||||
|
||||
@@ -421,7 +421,7 @@ DOCUMENT(R"(A single source component for a destination texture swizzle.
|
||||
|
||||
The fixed value ``1``.
|
||||
)");
|
||||
enum class TextureSwizzle : uint32_t
|
||||
enum class TextureSwizzle : uint8_t
|
||||
{
|
||||
Red,
|
||||
Green,
|
||||
@@ -4077,7 +4077,7 @@ DOCUMENT(R"(A set of flags for D3D buffer view properties.
|
||||
|
||||
The buffer is used with a structured buffer with associated hidden counter.
|
||||
)");
|
||||
enum class D3DBufferViewFlags : uint32_t
|
||||
enum class D3DBufferViewFlags : uint8_t
|
||||
{
|
||||
NoFlags = 0x0,
|
||||
Raw = 0x1,
|
||||
|
||||
@@ -231,6 +231,7 @@ struct DescriptorBinding
|
||||
bool operator==(const DescriptorBinding &o) const
|
||||
{
|
||||
return descriptorCount == o.descriptorCount && dynamicallyUsedCount == o.dynamicallyUsedCount &&
|
||||
firstUsedIndex == o.firstUsedIndex && lastUsedIndex == o.lastUsedIndex &&
|
||||
type == o.type && stageFlags == o.stageFlags && binds == o.binds;
|
||||
}
|
||||
bool operator<(const DescriptorBinding &o) const
|
||||
@@ -239,6 +240,10 @@ struct DescriptorBinding
|
||||
return descriptorCount < o.descriptorCount;
|
||||
if(!(dynamicallyUsedCount == o.dynamicallyUsedCount))
|
||||
return dynamicallyUsedCount < o.dynamicallyUsedCount;
|
||||
if(!(firstUsedIndex == o.firstUsedIndex))
|
||||
return firstUsedIndex < o.firstUsedIndex;
|
||||
if(!(lastUsedIndex == o.lastUsedIndex))
|
||||
return lastUsedIndex < o.lastUsedIndex;
|
||||
if(!(type == o.type))
|
||||
return type < o.type;
|
||||
if(!(stageFlags == o.stageFlags))
|
||||
|
||||
Reference in New Issue
Block a user