foz: Reconstruct specialization constants with correct layout

This commit is contained in:
Tatsuyuki Ishi authored and Baldur Karlsson committed 2022-04-25 14:17:12 +01:00
1 parent a2d77f58db
commit b0ff54fbcf
4 files changed
+42 -5

No files matched your search

@@ -4218,20 +4218,44 @@ QByteArray VulkanPipelineStateViewer::ReconstructSpecializationData(const VKPipe
{
bytebuf specData;
// reconstruct the original spec data as best as we can
if(mapEntries->NumChildren() == 0)
return specData;
if(sh.reflection == NULL)
{
qCritical("Tried to reconstruct specialization constants but reflection data is missing");
return specData;
}
auto specBlockIt =
std::find_if(sh.reflection->constantBlocks.begin(), sh.reflection->constantBlocks.end(),
[](const ConstantBlock &block) { return block.compileConstants; });
if(specBlockIt == sh.reflection->constantBlocks.end())
{
qCritical("Cannot find the constant block for specialization constants");
return specData;
}
const rdcarray<ShaderConstant> &specVars = specBlockIt->variables;
// We don't have access to the buffers in the original creation info, so we try to reconstruct
// from our preprocessed pipeline state instead. Note that this data might have a different order
// from the original call or have unused entries eliminated based on shader reflection.
const bytebuf &src = sh.specializationData;
for(size_t i = 0; i < mapEntries->NumChildren(); i++)
{
const SDObject *map = mapEntries->GetChild(i);
size_t srcByteOffset = map->FindChild("constantID")->AsUInt32() * sizeof(uint64_t);
size_t dstByteOffset = map->FindChild("offset")->AsUInt32();
size_t size = map->FindChild("size")->AsUInt32();
specData.resize_for_index(dstByteOffset + size - 1);
uint32_t constantId = map->FindChild("constantID")->AsUInt32();
int32_t idx = sh.specializationIds.indexOf(constantId);
if(idx == -1)
continue; // Entry was eliminated as it was probably unused --- skip it
size_t srcByteOffset = specVars[idx].byteOffset;
Q_ASSERT(srcByteOffset + size <= src.size());
specData.resize_for_index(dstByteOffset + size - 1);
memcpy(specData.data() + dstByteOffset, src.data() + srcByteOffset, size);
}
+8
View File
@@ -596,6 +596,14 @@ value.
:type: bytes
)");
bytebuf specializationData;
DOCUMENT(R"(The specialization constant ID for each entry in the specialization constant block of
reflection info. This corresponds to the constantID in VkSpecializationMapEntry, while the offset
and size into specializationData can be obtained from the reflection info.
:type: List[int]
)")
rdcarray<uint32_t> specializationIds;
};
DOCUMENT("Describes the state of the fixed-function tessellator.");
+4
View File
@@ -1160,6 +1160,8 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
stage.specializationData.resize_for_index(offs + sizeof(uint64_t));
memcpy(stage.specializationData.data() + offs, &s.value, s.dataSize);
}
if(p.shaders[i].patchData)
stage.specializationIds = p.shaders[i].patchData->specIDs;
}
}
else
@@ -1279,6 +1281,8 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
stages[i]->specializationData.resize_for_index(offs + sizeof(uint64_t));
memcpy(stages[i]->specializationData.data() + offs, &s.value, s.dataSize);
}
if(p.shaders[i].patchData)
stages[i]->specializationIds = p.shaders[i].patchData->specIDs;
}
// Tessellation
+3 -2
View File
@@ -2078,8 +2078,9 @@ void DoSerialise(SerialiserType &ser, VKPipe::Shader &el)
SERIALISE_MEMBER(pushConstantRangeByteOffset);
SERIALISE_MEMBER(pushConstantRangeByteSize);
SERIALISE_MEMBER(specializationData);
SERIALISE_MEMBER(specializationIds);
SIZE_CHECK(200);
SIZE_CHECK(224);
}
template <typename SerialiserType>
@@ -2348,7 +2349,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::State &el)
SERIALISE_MEMBER(conditionalRendering);
SIZE_CHECK(2096);
SIZE_CHECK(2240);
}
#pragma endregion Vulkan pipeline state