Make D3D12Pipe root element centric instead of shader centric

D3D12Pipe now stores an array of root elements, each one corresponding
to a root element or range in the root signature. Migrated usage in the
D3D12 pipeline state viewer and PipeState retrieval of resources.
Restricted number of resource array textures displayed in the texture
viewer to prevent app hangs.
This commit is contained in:
Steve Karolewics
2020-04-04 13:01:01 -07:00
committed by Baldur Karlsson
parent 1d64fffd42
commit 1137c4694c
11 changed files with 934 additions and 967 deletions
+1 -1
View File
@@ -358,9 +358,9 @@ TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D11Pipe, VertexBuffer)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D11Pipe, View)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, ConstantBuffer)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, Layout)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, RegisterSpace)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, ResourceData)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, ResourceState)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, RootSignatureRange)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, Sampler)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, StreamOutBind)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, VertexBuffer)
File diff suppressed because it is too large Load Diff
@@ -81,7 +81,8 @@ private:
ICaptureContext &m_Ctx;
PipelineStateViewer &m_Common;
void setShaderState(const D3D12Pipe::Shader &stage, RDLabel *shader, RDLabel *rootSig,
void setShaderState(const rdcarray<D3D12Pipe::RootSignatureRange> &rootElements,
const D3D12Pipe::Shader &stage, RDLabel *shader, RDLabel *rootSig,
RDTreeWidget *tex, RDTreeWidget *samp, RDTreeWidget *cbuffer,
RDTreeWidget *uavs);
@@ -107,7 +108,8 @@ private:
QVariantList exportViewHTML(const D3D12Pipe::View &view, bool rw,
const ShaderResource *shaderInput, const QString &extraParams);
void exportHTML(QXmlStreamWriter &xml, const D3D12Pipe::InputAssembly &ia);
void exportHTML(QXmlStreamWriter &xml, const D3D12Pipe::Shader &sh);
void exportHTML(QXmlStreamWriter &xml, const D3D12Pipe::Shader &sh,
const rdcarray<D3D12Pipe::RootSignatureRange> &els);
void exportHTML(QXmlStreamWriter &xml, const D3D12Pipe::StreamOut &so);
void exportHTML(QXmlStreamWriter &xml, const D3D12Pipe::Rasterizer &rs);
void exportHTML(QXmlStreamWriter &xml, const D3D12Pipe::OM &om);
+5 -1
View File
@@ -2264,7 +2264,11 @@ void TextureViewer::InitStageResourcePreviews(ShaderStage stage,
const bool collapseArray = dynamicallyUsedResCount > 20;
const int arrayLen = resArray != NULL ? resArray->count() : 1;
int arrayLen = resArray != NULL ? resArray->count() : 1;
// Too many resources to draw can cause a full-OS hang.
// For now, limit the number displayed per resource array.
arrayLen = qMin(arrayLen, 8);
for(int arrayIdx = 0; arrayIdx < arrayLen; arrayIdx++)
{
+73 -80
View File
@@ -187,22 +187,27 @@ struct View
{
DOCUMENT("");
View() = default;
View(uint32_t binding) : bind(binding) {}
View(const View &) = default;
View &operator=(const View &) = default;
bool operator==(const View &o) const
{
return resourceId == o.resourceId && type == o.type && viewFormat == o.viewFormat &&
swizzle[0] == o.swizzle[0] && swizzle[1] == o.swizzle[1] && swizzle[2] == o.swizzle[2] &&
swizzle[3] == o.swizzle[3] && bufferFlags == o.bufferFlags &&
bufferStructCount == o.bufferStructCount && elementByteSize == o.elementByteSize &&
firstElement == o.firstElement && numElements == o.numElements &&
counterResourceId == o.counterResourceId && counterByteOffset == o.counterByteOffset &&
firstMip == o.firstMip && numMips == o.numMips && numSlices == o.numSlices &&
firstSlice == o.firstSlice;
return bind == o.bind && tableIndex == o.tableIndex && resourceId == o.resourceId &&
type == o.type && viewFormat == o.viewFormat && swizzle[0] == o.swizzle[0] &&
swizzle[1] == o.swizzle[1] && swizzle[2] == o.swizzle[2] && swizzle[3] == o.swizzle[3] &&
bufferFlags == o.bufferFlags && bufferStructCount == o.bufferStructCount &&
elementByteSize == o.elementByteSize && firstElement == o.firstElement &&
numElements == o.numElements && counterResourceId == o.counterResourceId &&
counterByteOffset == o.counterByteOffset && firstMip == o.firstMip &&
numMips == o.numMips && numSlices == o.numSlices && firstSlice == o.firstSlice;
}
bool operator<(const View &o) const
{
if(!(bind == o.bind))
return bind < o.bind;
if(!(tableIndex == o.tableIndex))
return tableIndex < o.tableIndex;
if(!(resourceId == o.resourceId))
return resourceId < o.resourceId;
if(!(type == o.type))
@@ -241,10 +246,8 @@ struct View
return firstSlice < o.firstSlice;
return false;
}
DOCUMENT("``True`` if this view is a root parameter (i.e. not in a table).");
bool immediate = false;
DOCUMENT("The index in the original root signature that this descriptor came from.");
uint32_t rootElement = ~0U;
DOCUMENT("The shader register that this view is bound to.");
uint32_t bind = ~0U;
DOCUMENT("The index in the the parent descriptor table where this descriptor came from.");
uint32_t tableIndex = ~0U;
@@ -295,25 +298,23 @@ struct Sampler
{
DOCUMENT("");
Sampler() = default;
Sampler(uint32_t binding) : bind(binding) {}
Sampler(const Sampler &) = default;
Sampler &operator=(const Sampler &) = default;
bool operator==(const Sampler &o) const
{
return immediate == o.immediate && rootElement == o.rootElement && tableIndex == o.tableIndex &&
addressU == o.addressU && addressV == o.addressV && addressW == o.addressW &&
borderColor[0] == o.borderColor[0] && borderColor[1] == o.borderColor[1] &&
borderColor[2] == o.borderColor[2] && borderColor[3] == o.borderColor[3] &&
compareFunction == o.compareFunction && filter == o.filter &&
maxAnisotropy == o.maxAnisotropy && maxLOD == o.maxLOD && minLOD == o.minLOD &&
mipLODBias == o.mipLODBias;
return bind == o.bind && tableIndex == o.tableIndex && addressU == o.addressU &&
addressV == o.addressV && addressW == o.addressW && borderColor[0] == o.borderColor[0] &&
borderColor[1] == o.borderColor[1] && borderColor[2] == o.borderColor[2] &&
borderColor[3] == o.borderColor[3] && compareFunction == o.compareFunction &&
filter == o.filter && maxAnisotropy == o.maxAnisotropy && maxLOD == o.maxLOD &&
minLOD == o.minLOD && mipLODBias == o.mipLODBias;
}
bool operator<(const Sampler &o) const
{
if(!(immediate == o.immediate))
return immediate < o.immediate;
if(!(rootElement == o.rootElement))
return rootElement < o.rootElement;
if(!(bind == o.bind))
return bind < o.bind;
if(!(tableIndex == o.tableIndex))
return tableIndex < o.tableIndex;
if(!(addressU == o.addressU))
@@ -344,10 +345,8 @@ struct Sampler
return mipLODBias < o.mipLODBias;
return false;
}
DOCUMENT("``True`` if this view is a static sampler (i.e. not in a table).");
bool immediate = 0;
DOCUMENT("The index in the original root signature that this descriptor came from.");
uint32_t rootElement = ~0U;
DOCUMENT("The shader register that this sampler is bound to.");
uint32_t bind = ~0U;
DOCUMENT("The index in the the parent descriptor table where this descriptor came from.");
uint32_t tableIndex = ~0U;
@@ -389,21 +388,19 @@ struct ConstantBuffer
{
DOCUMENT("");
ConstantBuffer() = default;
ConstantBuffer(uint32_t binding) : bind(binding) {}
ConstantBuffer(const ConstantBuffer &) = default;
ConstantBuffer &operator=(const ConstantBuffer &) = default;
bool operator==(const ConstantBuffer &o) const
{
return immediate == o.immediate && rootElement == o.rootElement && tableIndex == o.tableIndex &&
resourceId == o.resourceId && byteOffset == o.byteOffset && byteSize == o.byteSize &&
rootValues == o.rootValues;
return bind == o.bind && tableIndex == o.tableIndex && resourceId == o.resourceId &&
byteOffset == o.byteOffset && byteSize == o.byteSize && rootValues == o.rootValues;
}
bool operator<(const ConstantBuffer &o) const
{
if(!(immediate == o.immediate))
return immediate < o.immediate;
if(!(rootElement == o.rootElement))
return rootElement < o.rootElement;
if(!(bind == o.bind))
return bind < o.bind;
if(!(tableIndex == o.tableIndex))
return tableIndex < o.tableIndex;
if(!(resourceId == o.resourceId))
@@ -416,10 +413,8 @@ struct ConstantBuffer
return rootValues < o.rootValues;
return false;
}
DOCUMENT("``True`` if this view is a root constant (i.e. not in a table).");
bool immediate = false;
DOCUMENT("The index in the original root signature that this descriptor came from.");
uint32_t rootElement = ~0U;
DOCUMENT("The shader register that this constant buffer is bound to.");
uint32_t bind = ~0U;
DOCUMENT("The index in the the parent descriptor table where this descriptor came from.");
uint32_t tableIndex = ~0U;
@@ -436,43 +431,55 @@ struct ConstantBuffer
rdcarray<uint32_t> rootValues;
};
DOCUMENT("Contains all of the registers in a single register space mapped to by a root signature.");
struct RegisterSpace
DOCUMENT("Contains information for a single root signature element range");
struct RootSignatureRange
{
DOCUMENT("");
RegisterSpace() = default;
RegisterSpace(const RegisterSpace &) = default;
RegisterSpace &operator=(const RegisterSpace &) = default;
RootSignatureRange() = default;
RootSignatureRange(const RootSignatureRange &) = default;
RootSignatureRange &operator=(const RootSignatureRange &) = default;
bool operator==(const RegisterSpace &o) const
bool operator==(const RootSignatureRange &o) const
{
return spaceIndex == o.spaceIndex && constantBuffers == o.constantBuffers &&
samplers == o.samplers && srvs == o.srvs && uavs == o.uavs;
return immediate == o.immediate && rootElement == o.rootElement && visibility == o.visibility &&
registerSpace == o.registerSpace && constantBuffers == o.constantBuffers &&
samplers == o.samplers && views == o.views;
}
bool operator<(const RegisterSpace &o) const
bool operator<(const RootSignatureRange &o) const
{
if(!(spaceIndex == o.spaceIndex))
return spaceIndex < o.spaceIndex;
if(!(immediate == o.immediate))
return immediate < o.immediate;
if(!(rootElement == o.rootElement))
return rootElement < o.rootElement;
if(!(visibility == o.visibility))
return visibility < o.visibility;
if(!(registerSpace == o.registerSpace))
return registerSpace < o.registerSpace;
if(!(constantBuffers == o.constantBuffers))
return constantBuffers < o.constantBuffers;
if(!(samplers == o.samplers))
return samplers < o.samplers;
if(!(srvs == o.srvs))
return srvs < o.srvs;
if(!(uavs == o.uavs))
return uavs < o.uavs;
if(!(views == o.views))
return views < o.views;
return false;
}
DOCUMENT("The index of this space, since space indices can be sparse");
uint32_t spaceIndex;
DOCUMENT("List of :class:`D3D12ConstantBuffer` containing the constant buffers.");
DOCUMENT("``True`` if this root element is a root constant (i.e. not in a table).");
bool immediate = false;
DOCUMENT("The index in the original root signature that this descriptor came from.");
uint32_t rootElement = ~0U;
DOCUMENT("The :class:`BindType` contained by this element.");
BindType type = BindType::Unknown;
DOCUMENT("The :class:`ShaderStageMask` of this element.");
ShaderStageMask visibility = ShaderStageMask::All;
DOCUMENT("The register space of this element.");
uint32_t registerSpace;
DOCUMENT("List of :class:`ConstantBuffer` containing the constant buffers.");
rdcarray<ConstantBuffer> constantBuffers;
DOCUMENT("List of :class:`D3D12Sampler` containing the samplers.");
DOCUMENT("List of :class:`Sampler` containing the samplers.");
rdcarray<Sampler> samplers;
DOCUMENT("List of :class:`D3D12View` containing the SRVs.");
rdcarray<View> srvs;
DOCUMENT("List of :class:`D3D12View` containing the UAVs.");
rdcarray<View> uavs;
DOCUMENT("List of :class:`View` containing the SRVs or UAVs.");
rdcarray<View> views;
};
DOCUMENT("Describes a D3D12 shader stage.");
@@ -495,23 +502,6 @@ mapping data.
DOCUMENT("A :class:`ShaderStage` identifying which stage this shader is bound to.");
ShaderStage stage = ShaderStage::Vertex;
DOCUMENT("A list of :class:`D3D12RegisterSpace` with the register spaces for this stage.");
rdcarray<RegisterSpace> spaces;
DOCUMENT(R"(Return the index in the :data:`spaces` array of a given register space.
:return: The index if the space exists, or ``-1`` if it doesn't.
:rtype: ``int``
)");
int32_t FindSpace(uint32_t spaceIndex) const
{
for(int32_t i = 0; i < spaces.count(); i++)
if(spaces[i].spaceIndex == spaceIndex)
return i;
return -1;
}
};
DOCUMENT("Describes a binding on the D3D12 stream-out stage.");
@@ -702,7 +692,7 @@ struct OM
rdcarray<View> renderTargets;
DOCUMENT("A :class:`D3D12View` with details of the bound depth-stencil target.");
View depthTarget;
View depthTarget = D3D12Pipe::View(0);
DOCUMENT("``True`` if depth access to the depth-stencil target is read-only.");
bool depthReadOnly = false;
DOCUMENT("``True`` if stenncil access to the depth-stencil target is read-only.");
@@ -775,6 +765,9 @@ struct State
DOCUMENT("The :class:`ResourceId` of the root signature object.");
ResourceId rootSignatureResourceId;
DOCUMENT("A list of :class:`RootSignatureRange` entries comprising the root signature.");
rdcarray<RootSignatureRange> rootElements;
DOCUMENT("A :class:`D3D12InputAssembly` describing the input assembly pipeline stage.");
InputAssembly inputAssembly;
@@ -813,7 +806,7 @@ DECLARE_REFLECTION_STRUCT(D3D12Pipe::InputAssembly);
DECLARE_REFLECTION_STRUCT(D3D12Pipe::View);
DECLARE_REFLECTION_STRUCT(D3D12Pipe::Sampler);
DECLARE_REFLECTION_STRUCT(D3D12Pipe::ConstantBuffer);
DECLARE_REFLECTION_STRUCT(D3D12Pipe::RegisterSpace);
DECLARE_REFLECTION_STRUCT(D3D12Pipe::RootSignatureRange);
DECLARE_REFLECTION_STRUCT(D3D12Pipe::Shader);
DECLARE_REFLECTION_STRUCT(D3D12Pipe::StreamOutBind);
DECLARE_REFLECTION_STRUCT(D3D12Pipe::StreamOut);
+77 -47
View File
@@ -923,20 +923,32 @@ BoundCBuffer PipeState::GetConstantBuffer(ShaderStage stage, uint32_t BufIdx, ui
const Bindpoint &bind =
s.bindpointMapping.constantBlocks[s.reflection->constantBlocks[BufIdx].bindPoint];
int32_t space = s.FindSpace(bind.bindset);
if(space == -1)
return BoundCBuffer();
int32_t shaderReg = bind.bind + (int32_t)ArrayIdx;
if(space >= s.spaces.count() || shaderReg >= s.spaces[space].constantBuffers.count())
return BoundCBuffer();
const D3D12Pipe::ConstantBuffer &descriptor = s.spaces[space].constantBuffers[shaderReg];
bool found = false;
for(size_t i = 0; i < m_D3D12->rootElements.size() && !found; ++i)
{
const D3D12Pipe::RootSignatureRange &element = m_D3D12->rootElements[i];
if((element.visibility & MaskForStage(stage)) == ShaderStageMask::Unknown)
continue;
buf = descriptor.resourceId;
ByteOffset = descriptor.byteOffset;
ByteSize = descriptor.byteSize;
if(element.type == BindType::ConstantBuffer &&
element.registerSpace == (uint32_t)bind.bindset)
{
for(size_t j = 0; j < element.constantBuffers.size(); ++j)
{
const D3D12Pipe::ConstantBuffer &cb = element.constantBuffers[j];
if(cb.bind == (uint32_t)shaderReg)
{
buf = cb.resourceId;
ByteOffset = cb.byteOffset;
ByteSize = cb.byteSize;
found = true;
break;
}
}
}
}
}
}
else if(IsCaptureGL())
@@ -1043,29 +1055,35 @@ rdcarray<BoundResourceArray> PipeState::GetReadOnlyResources(ShaderStage stage)
ret.push_back(BoundResourceArray());
ret.back().bindPoint = bind;
uint32_t count = bind.arraySize == ~0U ? 1 : bind.arraySize;
uint32_t start = bind.bind;
uint32_t end = (bind.arraySize == ~0U) ? bind.arraySize : bind.bind + bind.arraySize;
rdcarray<BoundResource> &val = ret.back().resources;
val.resize(count);
int spaceIndex = 0;
for(int space = 0; space < s.spaces.count(); space++)
for(size_t i = 0; i < m_D3D12->rootElements.size(); ++i)
{
if(s.spaces[space].spaceIndex == (uint32_t)bind.bindset)
const D3D12Pipe::RootSignatureRange &element = m_D3D12->rootElements[i];
if((element.visibility & MaskForStage(stage)) == ShaderStageMask::Unknown)
continue;
if(element.type == BindType::ReadOnlyResource &&
element.registerSpace == (uint32_t)bind.bindset)
{
spaceIndex = space;
break;
for(size_t j = 0; j < element.views.size(); ++j)
{
const D3D12Pipe::View &view = element.views[j];
if(view.bind >= start && view.bind <= end)
{
val.push_back(BoundResource());
BoundResource &b = val.back();
b.resourceId = view.resourceId;
b.firstMip = (int)view.firstMip;
b.firstSlice = (int)view.firstSlice;
b.typeCast = view.viewFormat.compType;
}
}
}
}
for(uint32_t i = 0; i < count; i++)
{
const D3D12Pipe::View &view = s.spaces[spaceIndex].srvs[bind.bind + i];
val[i].resourceId = view.resourceId;
val[i].firstMip = (int)view.firstMip;
val[i].firstSlice = (int)view.firstSlice;
val[i].typeCast = view.viewFormat.compType;
}
}
return ret;
@@ -1198,31 +1216,43 @@ rdcarray<BoundResourceArray> PipeState::GetReadWriteResources(ShaderStage stage)
{
const D3D12Pipe::Shader &s = GetD3D12Stage(stage);
size_t size = 0;
for(int space = 0; space < s.spaces.count(); space++)
size += s.spaces[space].uavs.size();
size_t size = s.bindpointMapping.readWriteResources.size();
ret.reserve(size);
for(int space = 0; space < s.spaces.count(); space++)
for(size_t bp = 0; bp < size; bp++)
{
for(int reg = 0; reg < s.spaces[space].uavs.count(); reg++)
{
const D3D12Pipe::View &bind = s.spaces[space].uavs[reg];
Bindpoint key(s.spaces[space].spaceIndex, reg);
BoundResource val;
const Bindpoint &bind = s.bindpointMapping.readWriteResources[bp];
ret.push_back(BoundResourceArray());
ret.back().bindPoint = bind;
// consider this register to not exist - it's in a gap defined by sparse root signature
// elements
if(bind.rootElement == ~0U)
uint32_t start = bind.bind;
uint32_t end = (bind.arraySize == ~0U) ? bind.arraySize : bind.bind + bind.arraySize;
rdcarray<BoundResource> &val = ret.back().resources;
for(size_t i = 0; i < m_D3D12->rootElements.size(); ++i)
{
const D3D12Pipe::RootSignatureRange &element = m_D3D12->rootElements[i];
if((element.visibility & MaskForStage(stage)) == ShaderStageMask::Unknown)
continue;
val.resourceId = bind.resourceId;
val.firstMip = (int)bind.firstMip;
val.firstSlice = (int)bind.firstSlice;
val.typeCast = bind.viewFormat.compType;
ret.push_back(BoundResourceArray(key, {val}));
if(element.type == BindType::ReadWriteResource &&
element.registerSpace == (uint32_t)bind.bindset)
{
for(size_t j = 0; j < element.views.size(); ++j)
{
const D3D12Pipe::View &view = element.views[j];
if(view.bind >= start && view.bind <= end)
{
val.push_back(BoundResource());
BoundResource &b = val.back();
b.resourceId = view.resourceId;
b.firstMip = (int)view.firstMip;
b.firstSlice = (int)view.firstSlice;
b.typeCast = view.viewFormat.compType;
}
}
}
}
}
}
+2
View File
@@ -679,6 +679,8 @@ rdcstr DoStringise(const BindType &el)
STRINGISE_ENUM_CLASS_NAMED(ReadWriteTBuffer, "RW TexBuffer");
STRINGISE_ENUM_CLASS_NAMED(ReadOnlyBuffer, "Buffer");
STRINGISE_ENUM_CLASS_NAMED(ReadWriteBuffer, "RW Buffer");
STRINGISE_ENUM_CLASS_NAMED(ReadOnlyResource, "Resource");
STRINGISE_ENUM_CLASS_NAMED(ReadWriteResource, "RW Resource");
STRINGISE_ENUM_CLASS_NAMED(InputAttachment, "Input");
}
END_ENUM_STRINGISE();
+10
View File
@@ -659,6 +659,14 @@ DOCUMENT(R"(The type of a shader resource bind.
A buffer that can be read from and written to arbitrarily.
.. data:: ReadOnlyResource
A resource that can only be read from
.. data:: ReadWriteResource
A resource that can be read from and written to arbitrarily.
.. data:: InputAttachment
An input attachment for reading from the target currently being written.
@@ -675,6 +683,8 @@ enum class BindType : uint32_t
ReadWriteTBuffer,
ReadOnlyBuffer,
ReadWriteBuffer,
ReadOnlyResource,
ReadWriteResource,
InputAttachment,
};
+148 -242
View File
@@ -54,41 +54,6 @@ ID3DDevice *GetD3D12DeviceIfAlloc(IUnknown *dev);
static const char *DXBCDisassemblyTarget = "DXBC";
template <class T>
T &resize_and_add(rdcarray<T> &vec, size_t idx)
{
if(idx >= vec.size())
vec.resize(idx + 1);
return vec[idx];
}
D3D12Pipe::RegisterSpace &get_space(rdcarray<D3D12Pipe::RegisterSpace> &dstSpaces,
uint32_t RegisterSpace)
{
// look to see if we've already added this space, if so then return it
for(D3D12Pipe::RegisterSpace &space : dstSpaces)
if(space.spaceIndex == RegisterSpace)
return space;
// otherwise look for the right place to insert it
for(size_t i = 0; i < dstSpaces.size(); i++)
{
if(RegisterSpace < dstSpaces[i].spaceIndex)
{
dstSpaces.insert(i, D3D12Pipe::RegisterSpace());
dstSpaces[i].spaceIndex = RegisterSpace;
return dstSpaces[i];
}
}
// if we got here, we didn't find an existing space nor a place to insert a new one, so we append
// it
dstSpaces.push_back(D3D12Pipe::RegisterSpace());
dstSpaces.back().spaceIndex = RegisterSpace;
return dstSpaces.back();
}
D3D12Replay::D3D12Replay(WrappedID3D12Device *d)
{
m_pDevice = d;
@@ -900,34 +865,51 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor
}
}
void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &rootSig,
const ShaderBindpointMapping &mapping,
rdcarray<D3D12Pipe::RegisterSpace> &dstSpaces,
D3D12_SHADER_VISIBILITY visibility)
ShaderStageMask ToShaderStageMask(D3D12_SHADER_VISIBILITY vis)
{
switch(vis)
{
case D3D12_SHADER_VISIBILITY_ALL: return ShaderStageMask::All;
case D3D12_SHADER_VISIBILITY_VERTEX: return ShaderStageMask::Vertex;
case D3D12_SHADER_VISIBILITY_HULL: return ShaderStageMask::Hull;
case D3D12_SHADER_VISIBILITY_DOMAIN: return ShaderStageMask::Domain;
case D3D12_SHADER_VISIBILITY_GEOMETRY: return ShaderStageMask::Geometry;
case D3D12_SHADER_VISIBILITY_PIXEL: return ShaderStageMask::Pixel;
default: return ShaderStageMask::Unknown;
}
}
void D3D12Replay::FillRootElements(const D3D12RenderState::RootSignature &rootSig,
const ShaderBindpointMapping *mappings[(uint32_t)ShaderStage::Count],
rdcarray<D3D12Pipe::RootSignatureRange> &rootElements)
{
if(rootSig.rootsig == ResourceId())
return;
D3D12ResourceManager *rm = m_pDevice->GetResourceManager();
WrappedID3D12RootSignature *sig =
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(rootSig.rootsig);
// clear first to ensure the spaces are default-initialised
dstSpaces.clear();
dstSpaces.reserve(8);
rootElements.clear();
rootElements.reserve(sig->sig.Parameters.size() + sig->sig.StaticSamplers.size());
for(size_t rootEl = 0; rootEl < sig->sig.Parameters.size(); rootEl++)
{
const D3D12RootSignatureParameter &p = sig->sig.Parameters[rootEl];
if(p.ShaderVisibility != D3D12_SHADER_VISIBILITY_ALL && p.ShaderVisibility != visibility)
continue;
if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS)
{
D3D12Pipe::ConstantBuffer &cb =
resize_and_add(get_space(dstSpaces, p.Constants.RegisterSpace).constantBuffers,
p.Constants.ShaderRegister);
cb.immediate = true;
cb.rootElement = (uint32_t)rootEl;
rootElements.push_back(D3D12Pipe::RootSignatureRange());
D3D12Pipe::RootSignatureRange &element = rootElements.back();
element.immediate = true;
element.rootElement = (uint32_t)rootEl;
element.type = BindType::ConstantBuffer;
element.registerSpace = p.Constants.RegisterSpace;
element.visibility = ToShaderStageMask(p.ShaderVisibility);
element.constantBuffers.push_back(D3D12Pipe::ConstantBuffer(p.Constants.ShaderRegister));
D3D12Pipe::ConstantBuffer &cb = element.constantBuffers.back();
cb.byteSize = uint32_t(sizeof(uint32_t) * p.Constants.Num32BitValues);
if(rootEl < rootSig.sigelems.size())
@@ -943,11 +925,16 @@ void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &root
}
else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV)
{
D3D12Pipe::ConstantBuffer &cb =
resize_and_add(get_space(dstSpaces, p.Descriptor.RegisterSpace).constantBuffers,
p.Descriptor.ShaderRegister);
cb.immediate = true;
cb.rootElement = (uint32_t)rootEl;
rootElements.push_back(D3D12Pipe::RootSignatureRange());
D3D12Pipe::RootSignatureRange &element = rootElements.back();
element.immediate = true;
element.rootElement = (uint32_t)rootEl;
element.type = BindType::ConstantBuffer;
element.registerSpace = p.Descriptor.RegisterSpace;
element.visibility = ToShaderStageMask(p.ShaderVisibility);
element.constantBuffers.push_back(D3D12Pipe::ConstantBuffer(p.Descriptor.ShaderRegister));
D3D12Pipe::ConstantBuffer &cb = element.constantBuffers.back();
if(rootEl < rootSig.sigelems.size())
{
@@ -967,10 +954,16 @@ void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &root
}
else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV)
{
D3D12Pipe::View &view = resize_and_add(get_space(dstSpaces, p.Descriptor.RegisterSpace).srvs,
p.Descriptor.ShaderRegister);
view.immediate = true;
view.rootElement = (uint32_t)rootEl;
rootElements.push_back(D3D12Pipe::RootSignatureRange());
D3D12Pipe::RootSignatureRange &element = rootElements.back();
element.immediate = true;
element.rootElement = (uint32_t)rootEl;
element.type = BindType::ReadOnlyResource;
element.registerSpace = p.Descriptor.RegisterSpace;
element.visibility = ToShaderStageMask(p.ShaderVisibility);
element.views.push_back(D3D12Pipe::View(p.Descriptor.ShaderRegister));
D3D12Pipe::View &view = element.views.back();
if(rootEl < rootSig.sigelems.size())
{
@@ -995,10 +988,16 @@ void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &root
}
else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV)
{
D3D12Pipe::View &view = resize_and_add(get_space(dstSpaces, p.Descriptor.RegisterSpace).uavs,
p.Descriptor.ShaderRegister);
view.immediate = true;
view.rootElement = (uint32_t)rootEl;
rootElements.push_back(D3D12Pipe::RootSignatureRange());
D3D12Pipe::RootSignatureRange &element = rootElements.back();
element.immediate = true;
element.rootElement = (uint32_t)rootEl;
element.type = BindType::ReadWriteResource;
element.registerSpace = p.Descriptor.RegisterSpace;
element.visibility = ToShaderStageMask(p.ShaderVisibility);
element.views.push_back(D3D12Pipe::View(p.Descriptor.ShaderRegister));
D3D12Pipe::View &view = element.views.back();
if(rootEl < rootSig.sigelems.size())
{
@@ -1039,8 +1038,17 @@ void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &root
{
const D3D12_DESCRIPTOR_RANGE1 &range = p.ranges[r];
// Here we diverge slightly from how root signatures store data. A descriptor table can
// contain multiple ranges which can each contain different types. D3D12Pipe treats
// each range as a separate RootElement
rootElements.push_back(D3D12Pipe::RootSignatureRange());
D3D12Pipe::RootSignatureRange &element = rootElements.back();
element.rootElement = (uint32_t)rootEl;
element.registerSpace = range.RegisterSpace;
element.visibility = ToShaderStageMask(p.ShaderVisibility);
UINT shaderReg = range.BaseShaderRegister;
D3D12Pipe::RegisterSpace &regSpace = get_space(dstSpaces, range.RegisterSpace);
D3D12Descriptor *desc = NULL;
@@ -1059,38 +1067,38 @@ void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &root
if(num == UINT_MAX)
{
// find out how many descriptors are left after
UINT availDescriptors = heap->GetNumDescriptors() - offset - UINT(e->offset);
// if this is an unbounded size table, find the matching bindpoint to try and
// upper-bound its size.
// due to D3D12's messed up resource matching, an array of descriptors in the root
// signature might match multiple bindings in the HLSL. So we just need to pick the
// highest-register item in the space and use its size.
const Bindpoint *highestBind = NULL;
UINT maxBindReg = shaderReg + availDescriptors;
const Bindpoint *bind = NULL;
// find the
for(const Bindpoint &b : mapping.readOnlyResources)
// Find shader binds that map any or all of this range to see if we can trim it
for(ShaderStage stage = ShaderStage::Vertex; stage < ShaderStage::Count; ++stage)
{
if(b.bindset == (int32_t)range.RegisterSpace && (bind == NULL || bind->bind < b.bind))
bind = &b;
if((element.visibility & MaskForStage(stage)) != ShaderStageMask::Unknown)
{
// This range is visible to this shader stage, check its mappings
const rdcarray<Bindpoint> &bps = mappings[(uint32_t)stage]->readOnlyResources;
for(size_t b = 0; b < bps.size(); ++b)
{
if(bps[b].bindset == (int32_t)element.registerSpace &&
bps[b].bind >= (int32_t)shaderReg)
{
UINT bindEnd = bps[b].arraySize == ~0U ? ~0U : bps[b].bind + bps[b].arraySize;
if(highestBind == NULL || bindEnd > maxBindReg)
{
highestBind = &bps[b];
maxBindReg = bindEnd;
}
}
}
}
}
// the size is however many registers are between the base of this range and that last
// bind, plus the size of the bind (at least 1 if it's not arrayed).
// If we didn't find any bind, clamp to 128 instead to prevent massive descriptor heaps
// from being passed through.
if(bind)
{
uint32_t arraySize = bind->arraySize == UINT_MAX ? 0U : bind->arraySize;
num = RDCMIN(availDescriptors,
bind->bind - range.BaseShaderRegister + RDCMAX(1U, arraySize));
}
else
{
num = RDCMIN(availDescriptors, 128U);
}
// If we didn't find a bindpoint, this will evaluate to simply availDescriptors - the
// number of remaining entries in the heap. If we did find a bind in this range, it
// will trim to the max register used by bindings in the range.
num = RDCMIN(availDescriptors, maxBindReg - shaderReg);
}
}
else if(num == UINT_MAX)
@@ -1105,15 +1113,12 @@ void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &root
if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER)
{
UINT maxReg = shaderReg + num - 1;
if(maxReg >= regSpace.samplers.size())
regSpace.samplers.resize(maxReg + 1);
element.type = BindType::Sampler;
for(UINT i = 0; i < num; i++, shaderReg++)
{
D3D12Pipe::Sampler &samp = regSpace.samplers[shaderReg];
samp.immediate = false;
samp.rootElement = (uint32_t)rootEl;
element.samplers.push_back(D3D12Pipe::Sampler(shaderReg));
D3D12Pipe::Sampler &samp = element.samplers.back();
samp.tableIndex = offset + i;
if(desc)
@@ -1141,15 +1146,12 @@ void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &root
}
else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV)
{
UINT maxReg = shaderReg + num - 1;
if(maxReg >= regSpace.constantBuffers.size())
regSpace.constantBuffers.resize(maxReg + 1);
element.type = BindType::ConstantBuffer;
for(UINT i = 0; i < num; i++, shaderReg++)
{
D3D12Pipe::ConstantBuffer &cb = regSpace.constantBuffers[shaderReg];
cb.immediate = false;
cb.rootElement = (uint32_t)rootEl;
element.constantBuffers.push_back(D3D12Pipe::ConstantBuffer(shaderReg));
D3D12Pipe::ConstantBuffer &cb = element.constantBuffers.back();
cb.tableIndex = offset + i;
if(desc)
@@ -1166,42 +1168,34 @@ void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &root
}
else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV)
{
UINT maxReg = shaderReg + num - 1;
if(maxReg >= regSpace.srvs.size())
regSpace.srvs.resize(maxReg + 1);
element.type = BindType::ReadOnlyResource;
for(UINT i = 0; i < num; i++, shaderReg++)
{
D3D12Pipe::View &view = regSpace.srvs[shaderReg];
view.immediate = false;
view.rootElement = (uint32_t)rootEl;
element.views.push_back(D3D12Pipe::View(shaderReg));
D3D12Pipe::View &view = element.views.back();
view.tableIndex = offset + i;
if(desc)
{
FillResourceView(view, desc);
desc++;
}
}
}
else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV)
{
UINT maxReg = shaderReg + num - 1;
if(maxReg >= regSpace.uavs.size())
regSpace.uavs.resize(maxReg + 1);
element.type = BindType::ReadWriteResource;
for(UINT i = 0; i < num; i++, shaderReg++)
{
D3D12Pipe::View &view = regSpace.uavs[shaderReg];
view.immediate = false;
view.rootElement = (uint32_t)rootEl;
element.views.push_back(D3D12Pipe::View(shaderReg));
D3D12Pipe::View &view = element.views.back();
view.tableIndex = offset + i;
if(desc)
{
FillResourceView(view, desc);
desc++;
}
}
@@ -1210,18 +1204,21 @@ void D3D12Replay::FillRegisterSpaces(const D3D12RenderState::RootSignature &root
}
}
// Each static sampler gets its own RootElement
for(size_t i = 0; i < sig->sig.StaticSamplers.size(); i++)
{
D3D12_STATIC_SAMPLER_DESC &sampDesc = sig->sig.StaticSamplers[i];
if(sampDesc.ShaderVisibility != D3D12_SHADER_VISIBILITY_ALL &&
sampDesc.ShaderVisibility != visibility)
continue;
rootElements.push_back(D3D12Pipe::RootSignatureRange());
D3D12Pipe::RootSignatureRange &element = rootElements.back();
element.immediate = true;
element.rootElement = (uint32_t)i;
element.type = BindType::Sampler;
element.registerSpace = sampDesc.RegisterSpace;
element.visibility = ToShaderStageMask(sampDesc.ShaderVisibility);
D3D12Pipe::Sampler &samp = resize_and_add(get_space(dstSpaces, sampDesc.RegisterSpace).samplers,
sampDesc.ShaderRegister);
samp.immediate = true;
samp.rootElement = (uint32_t)i;
element.samplers.push_back(D3D12Pipe::Sampler(sampDesc.ShaderRegister));
D3D12Pipe::Sampler &samp = element.samplers.back();
samp.addressU = MakeAddressMode(sampDesc.AddressU);
samp.addressV = MakeAddressMode(sampDesc.AddressV);
@@ -1342,12 +1339,6 @@ void D3D12Replay::SavePipelineState(uint32_t eventId)
state.computeShader.stage = ShaderStage::Compute;
state.computeShader.reflection = &sh->GetDetails();
state.computeShader.bindpointMapping = sh->GetMapping();
state.rootSignatureResourceId = rm->GetOriginalID(rs.compute.rootsig);
if(rs.compute.rootsig != ResourceId())
FillRegisterSpaces(rs.compute, state.computeShader.bindpointMapping,
state.computeShader.spaces, D3D12_SHADER_VISIBILITY_ALL);
}
else if(pipe)
{
@@ -1382,12 +1373,31 @@ void D3D12Replay::SavePipelineState(uint32_t eventId)
dst.bindpointMapping = ShaderBindpointMapping();
dst.reflection = NULL;
}
if(rs.graphics.rootsig != ResourceId())
FillRegisterSpaces(rs.graphics, dst.bindpointMapping, dst.spaces, visibility[stage]);
}
}
state.rootSignatureResourceId = rm->GetOriginalID(rs.graphics.rootsig);
/////////////////////////////////////////////////
// Root Signature
/////////////////////////////////////////////////
{
const ShaderBindpointMapping *mappings[(uint32_t)ShaderStage::Count];
mappings[(uint32_t)ShaderStage::Vertex] = &state.vertexShader.bindpointMapping;
mappings[(uint32_t)ShaderStage::Hull] = &state.hullShader.bindpointMapping;
mappings[(uint32_t)ShaderStage::Domain] = &state.domainShader.bindpointMapping;
mappings[(uint32_t)ShaderStage::Geometry] = &state.geometryShader.bindpointMapping;
mappings[(uint32_t)ShaderStage::Pixel] = &state.pixelShader.bindpointMapping;
mappings[(uint32_t)ShaderStage::Compute] = &state.computeShader.bindpointMapping;
if(pipe && pipe->IsCompute())
{
FillRootElements(rs.compute, mappings, state.rootElements);
state.rootSignatureResourceId = rm->GetOriginalID(rs.compute.rootsig);
}
else if(pipe)
{
FillRootElements(rs.graphics, mappings, state.rootElements);
state.rootSignatureResourceId = rm->GetOriginalID(rs.graphics.rootsig);
}
}
if(pipe && pipe->IsGraphics())
@@ -1462,41 +1472,22 @@ void D3D12Replay::SavePipelineState(uint32_t eventId)
// Output Merger
/////////////////////////////////////////////////
state.outputMerger.renderTargets.resize(rs.rts.size());
state.outputMerger.renderTargets.reserve(rs.rts.size());
for(size_t i = 0; i < rs.rts.size(); i++)
{
D3D12Pipe::View &view = state.outputMerger.renderTargets[i];
const D3D12Descriptor &desc = rs.rts[i];
if(desc.GetResResourceId() != ResourceId())
{
view.rootElement = (uint32_t)i;
view.immediate = false;
state.outputMerger.renderTargets.push_back(D3D12Pipe::View((uint32_t)i));
D3D12Pipe::View &view = state.outputMerger.renderTargets.back();
FillResourceView(view, &desc);
}
else
{
view = D3D12Pipe::View();
}
}
{
D3D12Pipe::View &view = state.outputMerger.depthTarget;
if(rs.dsv.GetResResourceId() != ResourceId())
{
view.rootElement = 0;
view.immediate = false;
FillResourceView(view, &rs.dsv);
}
else
{
view = D3D12Pipe::View();
}
}
if(rs.dsv.GetResResourceId() != ResourceId())
FillResourceView(state.outputMerger.depthTarget, &rs.dsv);
memcpy(state.outputMerger.blendState.blendFactor, rs.blendFactor, sizeof(FLOAT) * 4);
@@ -3958,88 +3949,3 @@ void D3D12_ProcessStructured(RDCFile *rdc, SDFile &output)
static StructuredProcessRegistration D3D12ProcessRegistration(RDCDriver::D3D12,
&D3D12_ProcessStructured);
#if ENABLED(ENABLE_UNIT_TESTS)
#undef None
#include "catch/catch.hpp"
TEST_CASE("Test get_space ensures sorted nature", "[d3d12]")
{
D3D12Pipe::Shader shader;
rdcarray<D3D12Pipe::RegisterSpace> &spaces = shader.spaces;
get_space(spaces, 0).samplers.resize(5);
CHECK(spaces.size() == 1);
REQUIRE(shader.FindSpace(0) == 0);
CHECK(spaces[shader.FindSpace(0)].samplers.size() == 5);
SECTION("Adding in sorted order")
{
get_space(spaces, 3).srvs.resize(7);
get_space(spaces, 4).uavs.resize(9);
get_space(spaces, 1000).constantBuffers.resize(2);
CHECK(spaces.size() == 4);
REQUIRE(shader.FindSpace(0) == 0);
REQUIRE(shader.FindSpace(3) == 1);
REQUIRE(shader.FindSpace(4) == 2);
REQUIRE(shader.FindSpace(1000) == 3);
REQUIRE(shader.FindSpace(99) == -1);
CHECK(spaces[shader.FindSpace(0)].samplers.size() == 5);
CHECK(spaces[shader.FindSpace(3)].srvs.size() == 7);
CHECK(spaces[shader.FindSpace(4)].uavs.size() == 9);
CHECK(spaces[shader.FindSpace(1000)].constantBuffers.size() == 2);
}
SECTION("Adding in reverse sorted order")
{
get_space(spaces, 1000).constantBuffers.resize(2);
get_space(spaces, 4).uavs.resize(9);
get_space(spaces, 3).srvs.resize(7);
CHECK(spaces.size() == 4);
REQUIRE(shader.FindSpace(0) == 0);
REQUIRE(shader.FindSpace(3) == 1);
REQUIRE(shader.FindSpace(4) == 2);
REQUIRE(shader.FindSpace(1000) == 3);
REQUIRE(shader.FindSpace(99) == -1);
CHECK(spaces[shader.FindSpace(0)].samplers.size() == 5);
CHECK(spaces[shader.FindSpace(3)].srvs.size() == 7);
CHECK(spaces[shader.FindSpace(4)].uavs.size() == 9);
CHECK(spaces[shader.FindSpace(1000)].constantBuffers.size() == 2);
}
SECTION("Adding in random order")
{
get_space(spaces, 4).uavs.resize(9);
get_space(spaces, 19).samplers.resize(100);
get_space(spaces, 3).srvs.resize(7);
get_space(spaces, 1000).constantBuffers.resize(2);
CHECK(spaces.size() == 5);
REQUIRE(shader.FindSpace(0) == 0);
REQUIRE(shader.FindSpace(3) == 1);
REQUIRE(shader.FindSpace(4) == 2);
REQUIRE(shader.FindSpace(19) == 3);
REQUIRE(shader.FindSpace(1000) == 4);
REQUIRE(shader.FindSpace(99) == -1);
CHECK(spaces[shader.FindSpace(4)].uavs.size() == 9);
CHECK(spaces[shader.FindSpace(19)].samplers.size() == 100);
CHECK(spaces[shader.FindSpace(0)].samplers.size() == 5);
CHECK(spaces[shader.FindSpace(3)].srvs.size() == 7);
CHECK(spaces[shader.FindSpace(1000)].constantBuffers.size() == 2);
}
}
#endif
+3 -4
View File
@@ -211,10 +211,9 @@ public:
void FileChanged() {}
AMDCounters *GetAMDCounters() { return m_pAMDCounters; }
private:
void FillRegisterSpaces(const D3D12RenderState::RootSignature &rootSig,
const ShaderBindpointMapping &mapping,
rdcarray<D3D12Pipe::RegisterSpace> &spaces,
D3D12_SHADER_VISIBILITY visibility);
void FillRootElements(const D3D12RenderState::RootSignature &rootSig,
const ShaderBindpointMapping *mappings[(uint32_t)ShaderStage::Count],
rdcarray<D3D12Pipe::RootSignatureRange> &rootElements);
void FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor *desc);
void ClearPostVSCache();
+25 -25
View File
@@ -1302,10 +1302,24 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::InputAssembly &el)
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, D3D12Pipe::View &el)
void DoSerialise(SerialiserType &ser, D3D12Pipe::RootSignatureRange &el)
{
SERIALISE_MEMBER(immediate);
SERIALISE_MEMBER(rootElement);
SERIALISE_MEMBER(type);
SERIALISE_MEMBER(visibility);
SERIALISE_MEMBER(registerSpace);
SERIALISE_MEMBER(constantBuffers);
SERIALISE_MEMBER(samplers);
SERIALISE_MEMBER(views);
SIZE_CHECK(96);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, D3D12Pipe::View &el)
{
SERIALISE_MEMBER(bind);
SERIALISE_MEMBER(tableIndex);
SERIALISE_MEMBER(resourceId);
SERIALISE_MEMBER(type);
@@ -1328,14 +1342,13 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::View &el)
SERIALISE_MEMBER(minLODClamp);
SIZE_CHECK(120);
SIZE_CHECK(112);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, D3D12Pipe::Sampler &el)
{
SERIALISE_MEMBER(immediate);
SERIALISE_MEMBER(rootElement);
SERIALISE_MEMBER(bind);
SERIALISE_MEMBER(tableIndex);
SERIALISE_MEMBER(addressU);
SERIALISE_MEMBER(addressV);
@@ -1348,33 +1361,20 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::Sampler &el)
SERIALISE_MEMBER(minLOD);
SERIALISE_MEMBER(mipLODBias);
SIZE_CHECK(76);
SIZE_CHECK(72);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, D3D12Pipe::ConstantBuffer &el)
{
SERIALISE_MEMBER(immediate);
SERIALISE_MEMBER(rootElement);
SERIALISE_MEMBER(bind);
SERIALISE_MEMBER(tableIndex);
SERIALISE_MEMBER(resourceId);
SERIALISE_MEMBER(byteOffset);
SERIALISE_MEMBER(byteSize);
SERIALISE_MEMBER(rootValues);
SIZE_CHECK(64);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, D3D12Pipe::RegisterSpace &el)
{
SERIALISE_MEMBER(spaceIndex);
SERIALISE_MEMBER(constantBuffers);
SERIALISE_MEMBER(samplers);
SERIALISE_MEMBER(srvs);
SERIALISE_MEMBER(uavs);
SIZE_CHECK(104);
SIZE_CHECK(56);
}
template <typename SerialiserType>
@@ -1385,9 +1385,8 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::Shader &el)
SERIALISE_MEMBER_OPT_EMPTY(reflection);
SERIALISE_MEMBER(bindpointMapping);
SERIALISE_MEMBER(stage);
SERIALISE_MEMBER(spaces);
SIZE_CHECK(168);
SIZE_CHECK(144);
}
template <typename SerialiserType>
@@ -1480,7 +1479,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::OM &el)
SERIALISE_MEMBER(multiSampleCount);
SERIALISE_MEMBER(multiSampleQuality);
SIZE_CHECK(288);
SIZE_CHECK(280);
}
template <typename SerialiserType>
@@ -1505,6 +1504,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::State &el)
{
SERIALISE_MEMBER(pipelineResourceId);
SERIALISE_MEMBER(rootSignatureResourceId);
SERIALISE_MEMBER(rootElements);
SERIALISE_MEMBER(inputAssembly);
@@ -1523,7 +1523,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::State &el)
SERIALISE_MEMBER(resourceStates);
SIZE_CHECK(1536);
SIZE_CHECK(1408);
}
#pragma endregion D3D12 pipeline state
@@ -2323,10 +2323,10 @@ INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::OutputMerger)
INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::State)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::Layout)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::InputAssembly)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::RootSignatureRange)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::ConstantBuffer)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::Sampler)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::View)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::RegisterSpace)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::Shader)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::Rasterizer)
INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::OM)