Remove samplers from ReadOnlyResources array, put them in their own list

This commit is contained in:
baldurk
2017-08-31 18:34:17 +01:00
parent 01b1260734
commit b1031c8036
16 changed files with 328 additions and 320 deletions
@@ -876,7 +876,7 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
const ShaderResource &res = shaderDetails->ReadOnlyResources[b];
const BindpointMap &bind = mapping.ReadOnlyResources[b];
if(!res.IsSampler && res.IsReadOnly && bind.bind == i)
if(bind.bind == i)
{
shaderInput = &res;
map = &bind;
@@ -898,17 +898,17 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
{
const D3D11Pipe::Sampler &s = stage.Samplers[i];
const ShaderResource *shaderInput = NULL;
const ShaderSampler *shaderInput = NULL;
const BindpointMap *map = NULL;
if(shaderDetails)
{
for(int b = 0; b < shaderDetails->ReadOnlyResources.count; b++)
for(int b = 0; b < shaderDetails->Samplers.count; b++)
{
const ShaderResource &res = shaderDetails->ReadOnlyResources[b];
const BindpointMap &bind = mapping.ReadOnlyResources[b];
const ShaderSampler &res = shaderDetails->Samplers[b];
const BindpointMap &bind = mapping.Samplers[b];
if(res.IsSampler && bind.bind == i)
if(bind.bind == i)
{
shaderInput = &res;
map = &bind;
@@ -1907,7 +1907,7 @@ void D3D11PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
{
for(const ShaderResource &res : searchstage->ShaderDetails->ReadWriteResources)
{
if(!res.IsTexture && !res.IsSampler && res.bindPoint == bind)
if(!res.IsTexture && res.bindPoint == bind)
{
stage = searchstage;
break;
@@ -1925,7 +1925,7 @@ void D3D11PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
for(const ShaderResource &res : resArray)
{
if(!res.IsTexture && !res.IsSampler && res.bindPoint == bind)
if(!res.IsTexture && res.bindPoint == bind)
{
shaderRes = &res;
break;
@@ -2319,7 +2319,7 @@ QVariantList D3D11PipelineStateViewer::exportViewHTML(const D3D11Pipe::View &vie
{
for(const ShaderResource &bind : refl->ReadOnlyResources)
{
if(!bind.IsSampler && bind.bindPoint == i)
if(bind.bindPoint == i)
{
shaderInput = &bind;
break;
@@ -646,7 +646,7 @@ void D3D12PipelineStateViewer::addResourceRow(const D3D12ViewTag &view,
if(b.bind <= view.reg)
regMatch = (b.arraySize == ~0U) || (b.bind + (int)b.arraySize > view.reg);
if(b.bindset == view.space && regMatch && !res[i].IsSampler)
if(b.bindset == view.space && regMatch)
{
bind = &b;
shaderInput = &res[i];
@@ -976,14 +976,14 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
continue;
const BindpointMap *bind = NULL;
const ShaderResource *shaderInput = NULL;
const ShaderSampler *shaderInput = NULL;
if(stage.ShaderDetails)
{
for(int i = 0; i < stage.BindpointMapping.ReadOnlyResources.count; i++)
for(int i = 0; i < stage.BindpointMapping.Samplers.count; i++)
{
const BindpointMap &b = stage.BindpointMapping.ReadOnlyResources[i];
const ShaderResource &res = stage.ShaderDetails->ReadOnlyResources[i];
const BindpointMap &b = stage.BindpointMapping.Samplers[i];
const ShaderSampler &res = stage.ShaderDetails->Samplers[i];
bool regMatch = b.bind == reg;
@@ -992,7 +992,7 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
if(b.bind <= reg)
regMatch = (b.arraySize == ~0U) || (b.bind + (int)b.arraySize > reg);
if(b.bindset == space && regMatch && res.IsSampler)
if(b.bindset == space && regMatch)
{
bind = &b;
shaderInput = &res;
@@ -1774,8 +1774,7 @@ void D3D12PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
for(int i = 0; i < bindArray.count; i++)
{
if(bindArray[i].bindset == view.space && bindArray[i].bind == view.reg &&
!resArray[i].IsSampler)
if(bindArray[i].bindset == view.space && bindArray[i].bind == view.reg)
{
shaderRes = &resArray[i];
break;
@@ -2423,7 +2422,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe
if(b.bind <= reg)
regMatch = (b.arraySize == ~0U) || (b.bind + (int)b.arraySize > reg);
if(b.bindset == space && regMatch && !res.IsReadOnly && !res.IsSampler)
if(b.bindset == space && regMatch)
{
shaderInput = &res;
break;
@@ -2473,10 +2472,10 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe
if(sh.ShaderDetails)
{
for(int i = 0; i < sh.BindpointMapping.ReadOnlyResources.count; i++)
for(int i = 0; i < sh.BindpointMapping.ReadWriteResources.count; i++)
{
const BindpointMap &b = sh.BindpointMapping.ReadOnlyResources[i];
const ShaderResource &res = sh.ShaderDetails->ReadOnlyResources[i];
const BindpointMap &b = sh.BindpointMapping.ReadWriteResources[i];
const ShaderResource &res = sh.ShaderDetails->ReadWriteResources[i];
bool regMatch = b.bind == reg;
@@ -2485,7 +2484,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe
if(b.bind <= reg)
regMatch = (b.arraySize == ~0U) || (b.bind + (int)b.arraySize > reg);
if(b.bindset == space && regMatch && !res.IsReadOnly && !res.IsSampler)
if(b.bindset == space && regMatch)
{
shaderInput = &res;
break;
@@ -2531,14 +2530,14 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe
if(s.RootElement == ~0U)
continue;
const ShaderResource *shaderInput = NULL;
const ShaderSampler *shaderInput = NULL;
if(sh.ShaderDetails)
{
for(int i = 0; i < sh.BindpointMapping.ReadOnlyResources.count; i++)
for(int i = 0; i < sh.BindpointMapping.Samplers.count; i++)
{
const BindpointMap &b = sh.BindpointMapping.ReadOnlyResources[i];
const ShaderResource &res = sh.ShaderDetails->ReadOnlyResources[i];
const BindpointMap &b = sh.BindpointMapping.Samplers[i];
const ShaderSampler &res = sh.ShaderDetails->Samplers[i];
bool regMatch = b.bind == reg;
@@ -2547,7 +2546,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe
if(b.bind <= reg)
regMatch = (b.arraySize == ~0U) || (b.bind + (int)b.arraySize > reg);
if(b.bindset == space && regMatch && res.IsSampler)
if(b.bindset == space && regMatch)
{
shaderInput = &res;
break;
@@ -618,49 +618,47 @@ QString PipelineStateViewer::GenerateHLSLStub(const ShaderReflection *shaderDeta
lit("Texture2DMSArray"), lit("Texture3D"), lit("TextureCube"), lit("TextureCubeArray"),
};
for(const ShaderSampler &samp : shaderDetails->Samplers)
{
hlsl += lit("//SamplerComparisonState %1 : register(s%2); // can't disambiguate\n"
"SamplerState %1 : register(s%2); // can't disambiguate\n")
.arg(samp.name)
.arg(samp.bindPoint);
}
for(int i = 0; i < 2; i++)
{
const rdctype::array<ShaderResource> &resources =
(i == 0 ? shaderDetails->ReadOnlyResources : shaderDetails->ReadWriteResources);
for(const ShaderResource &res : resources)
{
if(res.IsSampler)
char regChar = 't';
if(i == 1)
{
hlsl += lit("//SamplerComparisonState %1 : register(s%2); // can't disambiguate\n"
"SamplerState %1 : register(s%2); // can't disambiguate\n")
hlsl += lit("RW");
regChar = 'u';
}
if(res.IsTexture)
{
hlsl += lit("%1<%2> %3 : register(%4%5);\n")
.arg(textureDim[(size_t)res.resType])
.arg(res.variableType.descriptor.name)
.arg(res.name)
.arg(QLatin1Char(regChar))
.arg(res.bindPoint);
}
else
{
char regChar = 't';
if(res.variableType.descriptor.rows > 1)
hlsl += lit("Structured");
if(i == 1)
{
hlsl += lit("RW");
regChar = 'u';
}
if(res.IsTexture)
{
hlsl += lit("%1<%2> %3 : register(%4%5);\n")
.arg(textureDim[(size_t)res.resType])
.arg(res.variableType.descriptor.name)
.arg(res.name)
.arg(QLatin1Char(regChar))
.arg(res.bindPoint);
}
else
{
if(res.variableType.descriptor.rows > 1)
hlsl += lit("Structured");
hlsl += lit("Buffer<%1> %2 : register(%3%4);\n")
.arg(res.variableType.descriptor.name)
.arg(res.name)
.arg(QLatin1Char(regChar))
.arg(res.bindPoint);
}
hlsl += lit("Buffer<%1> %2 : register(%3%4);\n")
.arg(res.variableType.descriptor.name)
.arg(res.name)
.arg(QLatin1Char(regChar))
.arg(res.bindPoint);
}
}
}
@@ -712,14 +712,10 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
}
else
{
if(shaderRes->IsSampler)
bindType = BindType::Sampler;
else if(shaderRes->IsSampler && shaderRes->IsTexture)
bindType = BindType::ImageSampler;
else if(shaderRes->resType == TextureDim::Buffer)
bindType = BindType::ReadOnlyTBuffer;
if(shaderRes->resType == TextureDim::Buffer)
bindType = isrw ? BindType::ReadWriteBuffer : BindType::ReadOnlyBuffer;
else
bindType = BindType::ReadOnlyImage;
bindType = isrw ? BindType::ReadWriteImage : BindType::ReadOnlyImage;
}
bool usedSlot = bindMap != NULL && bindMap->used;
-3
View File
@@ -1024,9 +1024,6 @@ RDTreeWidgetItem *ShaderViewer::makeResourceRegister(const BindpointMap &bind, u
const TextureDescription *tex = m_Ctx.GetTexture(bound.Id);
const BufferDescription *buf = m_Ctx.GetBuffer(bound.Id);
if(res.IsSampler)
return NULL;
QChar regChar(QLatin1Char('u'));
if(res.IsReadOnly)
+3 -18
View File
@@ -2006,33 +2006,18 @@ void TextureViewer::InitStageResourcePreviews(ShaderStage stage,
CompType typeHint = resArray != NULL ? resArray->at(arrayIdx).typeHint : CompType::Typeless;
bool used = key.used;
bool samplerBind = false;
bool otherBind = false;
QString bindName;
for(int b = 0; b < resourceDetails.count; b++)
for(const ShaderResource &bind : resourceDetails)
{
const ShaderResource &bind = resourceDetails[b];
if(bind.bindPoint == idx && bind.IsReadOnly)
{
bindName = bind.name;
otherBind = true;
break;
}
if(bind.bindPoint == idx)
{
if(bind.IsSampler && !bind.IsReadOnly)
samplerBind = true;
else
otherBind = true;
bindName = bind.name;
break;
}
}
if(samplerBind && !otherBind)
continue;
if(copy)
{
used = true;
+33 -25
View File
@@ -399,10 +399,30 @@ specialisation constants.
DECLARE_REFLECTION_STRUCT(ConstantBlock);
DOCUMENT(R"(Contains the information for a separate sampler in a shader. If the API doesn't have
the concept of separate samplers, this struct will be unused and only :class:`ShaderResource` is
relevant.
.. note:: that constant blocks will not have a shader resource entry, see :class:`ConstantBlock`.
)");
struct ShaderSampler
{
DOCUMENT("The name of this sampler.");
rdctype::str name;
DOCUMENT(R"(The bindpoint for this block. This is an index in either the
:data:`ShaderBindpointMapping.Samplers` list.
)");
int32_t bindPoint;
};
DECLARE_REFLECTION_STRUCT(ShaderSampler);
DOCUMENT(R"(Contains the information for a shader resource that is made accessible to shaders
directly by means of the API resource binding system.
.. note:: that constant blocks will not have a shader resource entry, see :class:`ConstantBlock`.
.. note:: that constant blocks and samplers will not have a shader resource entry, see
:class:`ConstantBlock` and :class:`ShaderSampler`.
)");
struct ShaderResource
{
@@ -421,14 +441,6 @@ struct ShaderResource
)");
int32_t bindPoint;
DOCUMENT(R"(``True`` if this resource is a sampler.
If the API has no concept of separate samplers, this will always be ``False``.
.. note:: this is not exclusive with the other flags in the case of e.g. combined sampler/texture
objects.
)");
bool IsSampler;
DOCUMENT(R"(``True`` if this resource is a texture, otherwise it is a buffer or sampler (see
:data:`IsSampler`).
)");
@@ -503,6 +515,9 @@ struct ShaderReflection
DOCUMENT("A list of :class:`ConstantBlock` with the shader's constant bindings.");
rdctype::array<ConstantBlock> ConstantBlocks;
DOCUMENT("A list of :class:`ShaderSampler` with the shader's samplers.");
rdctype::array<ShaderSampler> Samplers;
DOCUMENT("A list of :class:`ShaderResource` with the shader's read-only resources.");
rdctype::array<ShaderResource> ReadOnlyResources;
DOCUMENT("A list of :class:`ShaderResource` with the shader's read-write resources.");
@@ -571,19 +586,8 @@ API specific details:
:data:`BindpointMap.arraySize` is likewise unused as D3D11 doesn't have arrayed resource bindings.
The :data:`BindpointMap.bind` value corresponds directly to the index in the appropriate resource
list.
One important thing to note is that samplers are included with read only resources. This means
consumers wanting to map to API bindpoints should know and expect that the
:data:`ReadOnlyResources` list contains potentially duplicate :class:`BindpointMap`, with one
being a SRV and one a sampler.
Note that D3D11 currently uses an identity bindpoint mapping, such that the index in the bindpoint
array is equal to the register, even if it's sparse. E.g. textures ``0`` and ``4`` will be in
bindpoint maps ``0`` and ``4`` with three empty unused maps in ``1``, ``2``, and ``3``. This is
not contractual and should not be relied upon, in future the bindpoint map may be only two
elements that list ``0`` and ``4``, with the shader bindpoints then being ``0`` and ``1``.
:data:`BindpointMap.bind` refers to the register/slot binding within the appropriate type (SRVs for
read-only resources, UAV for read-write resources, samplers/constant buffers in each type).
* OpenGL - Similarly to D3D11, :data:`BindpointMap.bindset` and :data:`BindpointMap.arraySize` are
unused as OpenGL does not have true binding sets or array resource binds.
@@ -594,9 +598,8 @@ API specific details:
the :data:`ReadWriteResources` list. The index is the uniform value of the binding. Since no
objects are namespaced by shader stage, the same value in two shaders refers to the same binding.
* Direct3D12 - As with 11 above, samplers are included in the read only resources array. Likewise
since D3D12 doesn't have true resource arrays (they are linearised into sequential registers)
:data:`BindpointMap.arraySize` is not used.
* Direct3D12 - Since D3D12 doesn't have true resource arrays (they are linearised into sequential
registers) :data:`BindpointMap.arraySize` is not used.
:data:`BindpointMap.bindset` corresponds to register spaces, with :data:`BindpointMap.bind` then
mapping to the register within that space. The root signature then maps these registers to
@@ -619,6 +622,11 @@ struct ShaderBindpointMapping
)");
rdctype::array<BindpointMap> ConstantBlocks;
DOCUMENT(R"(Provides a list of :class:`BindpointMap` entries for remapping the
:data:`ShaderReflection.Samplers` list.
)");
rdctype::array<BindpointMap> Samplers;
DOCUMENT(R"(Provides a list of :class:`BindpointMap` entries for remapping the
:data:`ShaderReflection.ReadOnlyResources` list.
)");
+22 -11
View File
@@ -128,10 +128,11 @@ void Serialiser::Serialise(const char *name, ShaderBindpointMapping &el)
{
Serialise("", el.InputAttributes);
Serialise("", el.ConstantBlocks);
Serialise("", el.Samplers);
Serialise("", el.ReadOnlyResources);
Serialise("", el.ReadWriteResources);
SIZE_CHECK(64);
SIZE_CHECK(80);
}
template <>
@@ -193,10 +194,18 @@ void Serialiser::Serialise(const char *name, ConstantBlock &el)
SIZE_CHECK(48);
}
template <>
void Serialiser::Serialise(const char *name, ShaderSampler &el)
{
Serialise("", el.name);
Serialise("", el.bindPoint);
SIZE_CHECK(24);
}
template <>
void Serialiser::Serialise(const char *name, ShaderResource &el)
{
Serialise("", el.IsSampler);
Serialise("", el.IsTexture);
Serialise("", el.IsReadOnly);
Serialise("", el.resType);
@@ -241,12 +250,14 @@ void Serialiser::Serialise(const char *name, ShaderReflection &el)
Serialise("", el.ConstantBlocks);
Serialise("", el.Samplers);
Serialise("", el.ReadOnlyResources);
Serialise("", el.ReadWriteResources);
Serialise("", el.Interfaces);
SIZE_CHECK(184);
SIZE_CHECK(200);
}
template <>
@@ -401,7 +412,7 @@ void Serialiser::Serialise(const char *name, D3D11Pipe::Shader &el)
Serialise("", el.ConstantBuffers);
Serialise("", el.ClassInstances);
SIZE_CHECK(192);
SIZE_CHECK(208);
}
template <>
@@ -496,7 +507,7 @@ void Serialiser::Serialise(const char *name, D3D11Pipe::State &el)
Serialise("", el.m_RS);
Serialise("", el.m_OM);
SIZE_CHECK(1560);
SIZE_CHECK(1656);
}
#pragma endregion D3D11 pipeline state
@@ -616,7 +627,7 @@ void Serialiser::Serialise(const char *name, D3D12Pipe::Shader &el)
Serialise("", el.stage);
Serialise("", el.Spaces);
SIZE_CHECK(104);
SIZE_CHECK(120);
}
template <>
@@ -735,7 +746,7 @@ void Serialiser::Serialise(const char *name, D3D12Pipe::State &el)
Serialise("", el.Resources);
SIZE_CHECK(1080);
SIZE_CHECK(1176);
}
#pragma endregion D3D12 pipeline state
@@ -789,7 +800,7 @@ void Serialiser::Serialise(const char *name, GLPipe::Shader &el)
if(m_Mode == READING)
el.ShaderDetails = NULL;
SIZE_CHECK(176);
SIZE_CHECK(192);
}
template <>
@@ -967,7 +978,7 @@ void Serialiser::Serialise(const char *name, GLPipe::State &el)
Serialise("", el.m_Hints);
SIZE_CHECK(1832);
SIZE_CHECK(1928);
}
#pragma endregion OpenGL pipeline state
@@ -1090,7 +1101,7 @@ void Serialiser::Serialise(const char *name, VKPipe::Shader &el)
Serialise("", el.specialization);
SIZE_CHECK(144);
SIZE_CHECK(160);
}
template <>
@@ -1251,7 +1262,7 @@ void Serialiser::Serialise(const char *name, VKPipe::State &el)
Serialise("", el.images);
SIZE_CHECK(1328);
SIZE_CHECK(1424);
}
#pragma endregion Vulkan pipeline state
+1 -1
View File
@@ -853,7 +853,7 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global
global.srvs[i].format.stride = bufdesc.StructureByteStride;
// if we didn't get a type from the SRV description, try to pull it from the declaration
for(const DXBC::ShaderInputBind &bind : dxbc->m_Resources)
for(const DXBC::ShaderInputBind &bind : dxbc->m_SRVs)
{
if(bind.reg == (uint32_t)i && bind.dimension == DXBC::ShaderInputBind::DIM_BUFFER &&
bind.retType < DXBC::ShaderInputBind::RETTYPE_MIXED &&
+4 -22
View File
@@ -1519,17 +1519,9 @@ bool D3D11RenderState::shader::Used_SRV(uint32_t slot) const
if(dxbc == NULL)
return true;
for(size_t i = 0; i < dxbc->m_Resources.size(); i++)
{
if(dxbc->m_Resources[i].reg == slot &&
(dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_TEXTURE ||
dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_STRUCTURED ||
dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_TBUFFER ||
dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_BYTEADDRESS))
{
for(const DXBC::ShaderInputBind &bind : dxbc->m_SRVs)
if(bind.reg == slot)
return true;
}
}
return false;
}
@@ -1547,19 +1539,9 @@ bool D3D11RenderState::shader::Used_UAV(uint32_t slot) const
if(dxbc == NULL)
return true;
for(size_t i = 0; i < dxbc->m_Resources.size(); i++)
{
if(dxbc->m_Resources[i].reg == slot &&
(dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED ||
dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_UAV_CONSUME_STRUCTURED ||
dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS ||
dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED ||
dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER ||
dxbc->m_Resources[i].type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED))
{
for(const DXBC::ShaderInputBind &bind : dxbc->m_UAVs)
if(bind.reg == slot)
return true;
}
}
return false;
}
-2
View File
@@ -922,7 +922,6 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg,
gl.glGetProgramResourceiv(sepProg, eGL_UNIFORM, u, numProps, resProps, numProps, NULL, values);
ShaderResource res;
res.IsSampler = false; // no separate sampler objects in GL
res.IsReadOnly = true;
res.IsTexture = true;
res.variableType.descriptor.rows = 1;
@@ -1465,7 +1464,6 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg,
gl.glGetProgramResourceName(sepProg, eGL_SHADER_STORAGE_BLOCK, u, len + 1, NULL, nm);
ShaderResource res;
res.IsSampler = false;
res.IsReadOnly = false;
res.IsTexture = false;
res.resType = TextureDim::Buffer;
@@ -982,14 +982,22 @@ string ASMOperand::toString(DXBCFile *dxbc, ToString flags) const
{
uint32_t idx = (uint32_t)indices[0].index;
for(const ShaderInputBind &b : dxbc->m_Resources)
{
if(b.reg != idx || b.space != 0)
continue;
vector<ShaderInputBind> *list = NULL;
if((type == TYPE_RESOURCE && b.IsROResource()) || (type == TYPE_SAMPLER && b.IsSampler()) ||
(type == TYPE_UNORDERED_ACCESS_VIEW && b.IsUAV()))
if(type == TYPE_RESOURCE)
list = &dxbc->m_SRVs;
else if(type == TYPE_UNORDERED_ACCESS_VIEW)
list = &dxbc->m_UAVs;
else if(type == TYPE_SAMPLER)
list = &dxbc->m_Samplers;
if(list)
{
for(const ShaderInputBind &b : *list)
{
if(b.reg != idx || b.space != 0)
continue;
if(decl)
regstr = str;
str = b.name;
+52 -31
View File
@@ -594,7 +594,9 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength)
else if(h->targetShaderStage == 0x4353) // 'CS'
m_Type = D3D11_ShaderType_Compute;
m_Resources.reserve(h->resources.count);
m_SRVs.reserve(h->resources.count);
m_UAVs.reserve(h->resources.count);
m_Samplers.reserve(h->resources.count);
struct CBufferBind
{
@@ -639,7 +641,7 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength)
// for cbuffers the names can be duplicated, so handle this by assuming
// the order will match between binding declaration and cbuffer declaration
// and append _s onto each subsequent buffer name
if(desc.type == ShaderInputBind::TYPE_CBUFFER)
if(desc.IsCBuffer())
{
string cname = desc.name;
@@ -652,8 +654,22 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength)
cb.bindCount = desc.bindCount;
cbufferbinds[cname] = cb;
}
m_Resources.push_back(desc);
else if(desc.IsSampler())
{
m_Samplers.push_back(desc);
}
else if(desc.IsSRV())
{
m_SRVs.push_back(desc);
}
else if(desc.IsUAV())
{
m_UAVs.push_back(desc);
}
else
{
RDCERR("Unexpected type of resource: %u", desc.type);
}
}
// Expand out any array resources. We deliberately place these at the end of the resources
@@ -666,31 +682,35 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength)
// Note we preserve the arrays in SM5.1
if(h->targetVersion < 0x501)
{
for(size_t i = 0; i < m_Resources.size();)
for(vector<ShaderInputBind> *arr : {&m_SRVs, &m_UAVs, &m_Samplers})
{
if(m_Resources[i].bindCount > 1)
vector<ShaderInputBind> &resArray = *arr;
for(size_t i = 0; i < resArray.size();)
{
ShaderInputBind desc = m_Resources[i];
m_Resources.erase(m_Resources.begin() + i);
string rname = desc.name;
uint32_t arraySize = desc.bindCount;
desc.bindCount = 1;
for(uint32_t a = 0; a < arraySize; a++)
if(resArray[i].bindCount > 1)
{
desc.name = StringFormat::Fmt("%s[%u]", rname.c_str(), a);
m_Resources.push_back(desc);
desc.reg++;
ShaderInputBind desc = resArray[i];
resArray.erase(resArray.begin() + i);
string rname = desc.name;
uint32_t arraySize = desc.bindCount;
desc.bindCount = 1;
for(uint32_t a = 0; a < arraySize; a++)
{
desc.name = StringFormat::Fmt("%s[%u]", rname.c_str(), a);
resArray.push_back(desc);
desc.reg++;
}
// continue from the i'th element again since
// we just removed it.
continue;
}
// continue from the i'th element again since
// we just removed it.
continue;
i++;
}
i++;
}
}
@@ -1071,7 +1091,7 @@ void DXBCFile::GuessResources()
desc.bindCount = 0;
}
m_Resources.push_back(desc);
m_Samplers.push_back(desc);
break;
}
@@ -1136,7 +1156,7 @@ void DXBCFile::GuessResources()
desc.bindCount = 0;
}
m_Resources.push_back(desc);
m_SRVs.push_back(desc);
break;
}
@@ -1173,7 +1193,10 @@ void DXBCFile::GuessResources()
desc.bindCount = 0;
}
m_Resources.push_back(desc);
if(dcl.operand.type == TYPE_RESOURCE)
m_SRVs.push_back(desc);
else
m_UAVs.push_back(desc);
break;
}
@@ -1206,7 +1229,7 @@ void DXBCFile::GuessResources()
desc.bindCount = 0;
}
m_Resources.push_back(desc);
m_SRVs.push_back(desc);
break;
}
@@ -1243,7 +1266,7 @@ void DXBCFile::GuessResources()
desc.bindCount = 0;
}
m_Resources.push_back(desc);
m_UAVs.push_back(desc);
break;
}
@@ -1302,7 +1325,7 @@ void DXBCFile::GuessResources()
desc.bindCount = 0;
}
m_Resources.push_back(desc);
m_UAVs.push_back(desc);
break;
}
@@ -1338,8 +1361,6 @@ void DXBCFile::GuessResources()
CBuffer cb;
m_Resources.push_back(desc);
cb.name = desc.name;
cb.space = dcl.space;
+5 -2
View File
@@ -139,7 +139,7 @@ struct ShaderInputBind
constexpr bool IsCBuffer() const { return type == TYPE_CBUFFER; }
constexpr bool IsSampler() const { return type == TYPE_SAMPLER; }
constexpr bool IsROResource() const
constexpr bool IsSRV() const
{
return type == TYPE_TBUFFER || type == TYPE_TEXTURE || type == TYPE_STRUCTURED ||
type == TYPE_BYTEADDRESS;
@@ -369,7 +369,10 @@ public:
vector<uint32_t> m_Immediate;
bool m_GuessedResources;
vector<ShaderInputBind> m_Resources;
vector<ShaderInputBind> m_SRVs;
vector<ShaderInputBind> m_UAVs;
vector<ShaderInputBind> m_Samplers;
vector<CBuffer> m_CBuffers;
+115 -130
View File
@@ -108,6 +108,102 @@ static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &va
return ret;
}
static void MakeResourceList(bool srv, DXBC::DXBCFile *dxbc, const vector<DXBC::ShaderInputBind> &in,
rdctype::array<BindpointMap> &mapping,
rdctype::array<ShaderResource> &refl)
{
for(size_t i = 0; i < in.size(); i++)
{
const DXBC::ShaderInputBind &r = in[i];
ShaderResource res;
res.name = r.name;
res.IsTexture = (r.type == DXBC::ShaderInputBind::TYPE_TEXTURE &&
r.dimension != DXBC::ShaderInputBind::DIM_UNKNOWN &&
r.dimension != DXBC::ShaderInputBind::DIM_BUFFER &&
r.dimension != DXBC::ShaderInputBind::DIM_BUFFEREX);
res.IsReadOnly = srv;
switch(r.dimension)
{
default:
case DXBC::ShaderInputBind::DIM_UNKNOWN: res.resType = TextureDim::Unknown; break;
case DXBC::ShaderInputBind::DIM_BUFFER:
case DXBC::ShaderInputBind::DIM_BUFFEREX: res.resType = TextureDim::Buffer; break;
case DXBC::ShaderInputBind::DIM_TEXTURE1D: res.resType = TextureDim::Texture1D; break;
case DXBC::ShaderInputBind::DIM_TEXTURE1DARRAY:
res.resType = TextureDim::Texture1DArray;
break;
case DXBC::ShaderInputBind::DIM_TEXTURE2D: res.resType = TextureDim::Texture2D; break;
case DXBC::ShaderInputBind::DIM_TEXTURE2DARRAY:
res.resType = TextureDim::Texture2DArray;
break;
case DXBC::ShaderInputBind::DIM_TEXTURE2DMS: res.resType = TextureDim::Texture2DMS; break;
case DXBC::ShaderInputBind::DIM_TEXTURE2DMSARRAY:
res.resType = TextureDim::Texture2DMSArray;
break;
case DXBC::ShaderInputBind::DIM_TEXTURE3D: res.resType = TextureDim::Texture3D; break;
case DXBC::ShaderInputBind::DIM_TEXTURECUBE: res.resType = TextureDim::TextureCube; break;
case DXBC::ShaderInputBind::DIM_TEXTURECUBEARRAY:
res.resType = TextureDim::TextureCubeArray;
break;
}
if(r.retType != DXBC::ShaderInputBind::RETTYPE_UNKNOWN &&
r.retType != DXBC::ShaderInputBind::RETTYPE_MIXED &&
r.retType != DXBC::ShaderInputBind::RETTYPE_CONTINUED)
{
res.variableType.descriptor.rows = 1;
res.variableType.descriptor.cols = (uint8_t)r.numSamples;
res.variableType.descriptor.elements = 1;
string name;
switch(r.retType)
{
case DXBC::ShaderInputBind::RETTYPE_UNORM: name = "unorm float"; break;
case DXBC::ShaderInputBind::RETTYPE_SNORM: name = "snorm float"; break;
case DXBC::ShaderInputBind::RETTYPE_SINT: name = "int"; break;
case DXBC::ShaderInputBind::RETTYPE_UINT: name = "uint"; break;
case DXBC::ShaderInputBind::RETTYPE_FLOAT: name = "float"; break;
case DXBC::ShaderInputBind::RETTYPE_DOUBLE: name = "double"; break;
default: name = "unknown"; break;
}
name += StringFormat::Fmt("%u", r.numSamples);
res.variableType.descriptor.name = name;
}
else
{
if(dxbc->m_ResourceBinds.find(r.name) != dxbc->m_ResourceBinds.end())
{
uint32_t vecOffset = 0;
res.variableType = MakeShaderVariableType(dxbc->m_ResourceBinds[r.name], vecOffset);
}
else
{
res.variableType.descriptor.rows = 0;
res.variableType.descriptor.cols = 0;
res.variableType.descriptor.elements = 0;
res.variableType.descriptor.name = "";
}
}
res.bindPoint = (int32_t)i;
BindpointMap map;
map.arraySize = r.bindCount == 0 ? ~0U : r.bindCount;
map.bindset = r.space;
map.bind = r.reg;
map.used = true;
mapping[i] = map;
refl[i] = res;
}
}
void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl,
ShaderBindpointMapping *mapping)
{
@@ -204,7 +300,7 @@ void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl,
cb.name = dxbc->m_CBuffers[i].name;
cb.bufferBacked = true;
cb.byteSize = dxbc->m_CBuffers[i].descriptor.byteSize;
cb.bindPoint = (uint32_t)i;
cb.bindPoint = (int32_t)i;
BindpointMap map;
map.arraySize = 1;
@@ -222,143 +318,32 @@ void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl,
}
}
int numRWResources = 0;
int numROResources = 0;
for(size_t i = 0; i < dxbc->m_Resources.size(); i++)
create_array_uninit(mapping->Samplers, dxbc->m_Samplers.size());
create_array_uninit(refl->Samplers, dxbc->m_Samplers.size());
for(size_t i = 0; i < dxbc->m_Samplers.size(); i++)
{
const auto &r = dxbc->m_Resources[i];
ShaderSampler &s = refl->Samplers[i];
if(r.type != DXBC::ShaderInputBind::TYPE_CBUFFER)
{
bool IsReadWrite = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED ||
r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED ||
r.type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS ||
r.type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED ||
r.type == DXBC::ShaderInputBind::TYPE_UAV_CONSUME_STRUCTURED ||
r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER);
if(IsReadWrite)
numRWResources++;
else
numROResources++;
}
}
create_array_uninit(mapping->ReadWriteResources, numRWResources);
create_array_uninit(refl->ReadWriteResources, numRWResources);
create_array_uninit(mapping->ReadOnlyResources, numROResources);
create_array_uninit(refl->ReadOnlyResources, numROResources);
int32_t rwidx = 0, roidx = 0;
for(size_t i = 0; i < dxbc->m_Resources.size(); i++)
{
const auto &r = dxbc->m_Resources[i];
if(r.type == DXBC::ShaderInputBind::TYPE_CBUFFER)
continue;
ShaderResource res;
res.name = r.name;
res.IsSampler = (r.type == DXBC::ShaderInputBind::TYPE_SAMPLER);
res.IsTexture = (r.type == DXBC::ShaderInputBind::TYPE_TEXTURE &&
r.dimension != DXBC::ShaderInputBind::DIM_UNKNOWN &&
r.dimension != DXBC::ShaderInputBind::DIM_BUFFER &&
r.dimension != DXBC::ShaderInputBind::DIM_BUFFEREX);
res.IsReadOnly = (r.type == DXBC::ShaderInputBind::TYPE_TBUFFER ||
r.type == DXBC::ShaderInputBind::TYPE_SAMPLER ||
r.type == DXBC::ShaderInputBind::TYPE_TEXTURE ||
r.type == DXBC::ShaderInputBind::TYPE_STRUCTURED ||
r.type == DXBC::ShaderInputBind::TYPE_BYTEADDRESS);
switch(r.dimension)
{
default:
case DXBC::ShaderInputBind::DIM_UNKNOWN: res.resType = TextureDim::Unknown; break;
case DXBC::ShaderInputBind::DIM_BUFFER:
case DXBC::ShaderInputBind::DIM_BUFFEREX: res.resType = TextureDim::Buffer; break;
case DXBC::ShaderInputBind::DIM_TEXTURE1D: res.resType = TextureDim::Texture1D; break;
case DXBC::ShaderInputBind::DIM_TEXTURE1DARRAY:
res.resType = TextureDim::Texture1DArray;
break;
case DXBC::ShaderInputBind::DIM_TEXTURE2D: res.resType = TextureDim::Texture2D; break;
case DXBC::ShaderInputBind::DIM_TEXTURE2DARRAY:
res.resType = TextureDim::Texture2DArray;
break;
case DXBC::ShaderInputBind::DIM_TEXTURE2DMS: res.resType = TextureDim::Texture2DMS; break;
case DXBC::ShaderInputBind::DIM_TEXTURE2DMSARRAY:
res.resType = TextureDim::Texture2DMSArray;
break;
case DXBC::ShaderInputBind::DIM_TEXTURE3D: res.resType = TextureDim::Texture3D; break;
case DXBC::ShaderInputBind::DIM_TEXTURECUBE: res.resType = TextureDim::TextureCube; break;
case DXBC::ShaderInputBind::DIM_TEXTURECUBEARRAY:
res.resType = TextureDim::TextureCubeArray;
break;
}
if(r.retType != DXBC::ShaderInputBind::RETTYPE_UNKNOWN &&
r.retType != DXBC::ShaderInputBind::RETTYPE_MIXED &&
r.retType != DXBC::ShaderInputBind::RETTYPE_CONTINUED)
{
res.variableType.descriptor.rows = 1;
res.variableType.descriptor.cols = (uint8_t)r.numSamples;
res.variableType.descriptor.elements = 1;
string name;
switch(r.retType)
{
case DXBC::ShaderInputBind::RETTYPE_UNORM: name = "unorm float"; break;
case DXBC::ShaderInputBind::RETTYPE_SNORM: name = "snorm float"; break;
case DXBC::ShaderInputBind::RETTYPE_SINT: name = "int"; break;
case DXBC::ShaderInputBind::RETTYPE_UINT: name = "uint"; break;
case DXBC::ShaderInputBind::RETTYPE_FLOAT: name = "float"; break;
case DXBC::ShaderInputBind::RETTYPE_DOUBLE: name = "double"; break;
default: name = "unknown"; break;
}
name += StringFormat::Fmt("%u", r.numSamples);
res.variableType.descriptor.name = name;
}
else
{
if(dxbc->m_ResourceBinds.find(r.name) != dxbc->m_ResourceBinds.end())
{
uint32_t vecOffset = 0;
res.variableType = MakeShaderVariableType(dxbc->m_ResourceBinds[r.name], vecOffset);
}
else
{
res.variableType.descriptor.rows = 0;
res.variableType.descriptor.cols = 0;
res.variableType.descriptor.elements = 0;
res.variableType.descriptor.name = "";
}
}
res.bindPoint = res.IsReadOnly ? roidx : rwidx;
s.name = dxbc->m_Samplers[i].name;
s.bindPoint = (int32_t)i;
BindpointMap map;
map.arraySize = r.bindCount == 0 ? ~0U : r.bindCount;
map.bindset = r.space;
map.bind = r.reg;
map.arraySize = 1;
map.bindset = dxbc->m_Samplers[i].space;
map.bind = dxbc->m_Samplers[i].reg;
map.used = true;
if(res.IsReadOnly)
{
mapping->ReadOnlyResources[roidx] = map;
refl->ReadOnlyResources[roidx++] = res;
}
else
{
mapping->ReadWriteResources[rwidx] = map;
refl->ReadWriteResources[rwidx++] = res;
}
mapping->Samplers[i] = map;
}
create_array_uninit(mapping->ReadOnlyResources, dxbc->m_SRVs.size());
create_array_uninit(refl->ReadOnlyResources, dxbc->m_SRVs.size());
MakeResourceList(true, dxbc, dxbc->m_SRVs, mapping->ReadOnlyResources, refl->ReadOnlyResources);
create_array_uninit(mapping->ReadWriteResources, dxbc->m_UAVs.size());
create_array_uninit(refl->ReadWriteResources, dxbc->m_UAVs.size());
MakeResourceList(true, dxbc, dxbc->m_UAVs, mapping->ReadWriteResources, refl->ReadWriteResources);
uint32_t numInterfaces = 0;
for(size_t i = 0; i < dxbc->m_Interfaces.variables.size(); i++)
numInterfaces = RDCMAX(dxbc->m_Interfaces.variables[i].descriptor.offset + 1, numInterfaces);
@@ -3901,7 +3901,7 @@ void SPVModule::MakeReflection(ShaderStage stage, const string &entryPoint,
vector<SigParameter> inputs;
vector<SigParameter> outputs;
vector<cblockpair> cblocks;
vector<shaderrespair> roresources, rwresources;
vector<shaderrespair> samplers, roresources, rwresources;
// VKTODOLOW filter to only functions/resources used by entryPoint
@@ -4134,7 +4134,6 @@ void SPVModule::MakeReflection(ShaderStage stage, const string &entryPoint,
if(ssbo)
{
res.IsSampler = false;
res.IsReadOnly = false;
res.IsTexture = false;
res.name = cblock.name;
@@ -4208,8 +4207,8 @@ void SPVModule::MakeReflection(ShaderStage stage, const string &entryPoint,
else if(type->texdim == spv::DimBuffer)
res.resType = TextureDim::Buffer;
res.IsSampler =
type->type == SPVTypeData::eSampledImage || type->type == SPVTypeData::eSampler;
bool sepSampler = (type->type == SPVTypeData::eSampler);
res.IsTexture = res.resType != TextureDim::Buffer && type->type != SPVTypeData::eSampler;
res.IsReadOnly = true;
@@ -4300,7 +4299,9 @@ void SPVModule::MakeReflection(ShaderStage stage, const string &entryPoint,
// are used
RDCASSERT(!bindmap.used || bindmap.bind >= 0);
if(res.IsReadOnly)
if(sepSampler)
samplers.push_back(shaderrespair(bindmap, res));
else if(res.IsReadOnly)
roresources.push_back(shaderrespair(bindmap, res));
else
rwresources.push_back(shaderrespair(bindmap, res));
@@ -4444,12 +4445,16 @@ void SPVModule::MakeReflection(ShaderStage stage, const string &entryPoint,
mapping.InputAttributes[reflection.InputSig[i].regIndex] = (int32_t)i;
std::sort(cblocks.begin(), cblocks.end());
std::sort(samplers.begin(), samplers.end());
std::sort(roresources.begin(), roresources.end());
std::sort(rwresources.begin(), rwresources.end());
create_array_uninit(mapping.ConstantBlocks, cblocks.size());
create_array_uninit(reflection.ConstantBlocks, cblocks.size());
create_array_uninit(mapping.Samplers, samplers.size());
create_array_uninit(reflection.Samplers, samplers.size());
create_array_uninit(mapping.ReadOnlyResources, roresources.size());
create_array_uninit(reflection.ReadOnlyResources, roresources.size());
@@ -4468,6 +4473,18 @@ void SPVModule::MakeReflection(ShaderStage stage, const string &entryPoint,
reflection.ConstantBlocks[i].bindPoint = (int32_t)i;
}
for(size_t i = 0; i < samplers.size(); i++)
{
mapping.Samplers[i] = samplers[i].map;
// fix up any bind points marked with -1. They were sorted to the end
// but from here on we want to just be able to index with the bind point
// without any special casing.
if(mapping.Samplers[i].bind == -1)
mapping.Samplers[i].bind = 0;
reflection.Samplers[i].name = samplers[i].bindres.name;
reflection.Samplers[i].bindPoint = (int32_t)i;
}
for(size_t i = 0; i < roresources.size(); i++)
{
mapping.ReadOnlyResources[i] = roresources[i].map;