Merge pull request #6784 from milescoviello/fix/journal-mesh-output-size

fix(agc): journal the mesh output primitive size
This commit is contained in:
Adrià authored and GitHub committed 2026-10-16 14:03:21 +02:00
commit eb901bcf4e
2 files changed
+24 -5

No files matched your search

@@ -36,15 +36,15 @@ static_assert(sizeof(VkVertexInputBindingDescription) == 12, "VkVertexInputBindi
static_assert(sizeof(VkVertexInputAttributeDescription) == 16, "VkVertexInputAttributeDescription changed: update the recipe codec");
#if defined(__linux__) && defined(__x86_64__) && defined(__GLIBCXX__)
static_assert(sizeof(State) == 752, "State changed: update CanonicalPipelineState and the recipe codec");
static_assert(sizeof(ShaderStages) == 108, "ShaderStages changed: update the recipe codec");
static_assert(sizeof(ShaderRecompiler::MeshConfiguration) == 36, "MeshConfiguration changed: update the recipe codec");
static_assert(sizeof(ShaderStages) == 112, "ShaderStages changed: update the recipe codec");
static_assert(sizeof(ShaderRecompiler::MeshConfiguration) == 40, "MeshConfiguration changed: update the recipe codec");
static_assert(sizeof(ShaderRecompiler::TessellationConfiguration) == 40, "TessellationConfiguration changed: update the recipe codec");
#endif
constexpr std::uint32_t FileMagic = 0x4c4a5041u;
// Bumped when the recipe codec, CanonicalPipelineState or the store key change in a way the
// layout guards above do not catch (a field renumbered or reinterpreted at the same size).
constexpr std::uint32_t FileFormat = 2u;
constexpr std::uint32_t FileFormat = 3u;
constexpr std::uint32_t ModuleRecord = 1u;
constexpr std::uint32_t GraphicsRecord = 2u;
constexpr std::uint32_t ComputeRecord = 3u;
@@ -147,11 +147,11 @@ void encodeOptional(Writer& writer, const std::optional<TValue>& value, void (*e
}
void encodeMesh(Writer& writer, const ShaderRecompiler::MeshConfiguration& mesh) {
for (const auto value : {mesh.inputPrimitive, mesh.primitivesPerGroup, mesh.verticesPerGroup, mesh.maxVertices, mesh.maxPrimitives, mesh.threadsPerGroup, mesh.ldsSizeDwords, mesh.provokingVertex, mesh.esgsItemSize}) writer.U32(value);
for (const auto value : {mesh.inputPrimitive, mesh.primitivesPerGroup, mesh.verticesPerGroup, mesh.maxVertices, mesh.maxPrimitives, mesh.threadsPerGroup, mesh.ldsSizeDwords, mesh.provokingVertex, mesh.esgsItemSize, mesh.outputPrimitiveSize}) writer.U32(value);
}
void decodeMesh(Reader& reader, ShaderRecompiler::MeshConfiguration& mesh) {
for (auto* value : {&mesh.inputPrimitive, &mesh.primitivesPerGroup, &mesh.verticesPerGroup, &mesh.maxVertices, &mesh.maxPrimitives, &mesh.threadsPerGroup, &mesh.ldsSizeDwords, &mesh.provokingVertex, &mesh.esgsItemSize}) *value = reader.U32();
for (auto* value : {&mesh.inputPrimitive, &mesh.primitivesPerGroup, &mesh.verticesPerGroup, &mesh.maxVertices, &mesh.maxPrimitives, &mesh.threadsPerGroup, &mesh.ldsSizeDwords, &mesh.provokingVertex, &mesh.esgsItemSize, &mesh.outputPrimitiveSize}) *value = reader.U32();
}
void encodeTessellation(Writer& writer, const ShaderRecompiler::TessellationConfiguration& tessellation) {
@@ -37,6 +37,7 @@
#include <cstring>
#include <exception>
#include <filesystem>
#include <fstream>
#include <random>
#include <initializer_list>
#include <iostream>
@@ -7537,6 +7538,11 @@ void pipelineJournalTests() {
BuildPipelineStoreKey(grid, context, gridState, input, layouts.View(), shaders, VK_IMAGE_LAYOUT_GENERAL);
BuildPipelineStoreKey(gridReplayed, context, gridDecoded.state, gridDecoded.vertexInput, layouts.View(), shaders, gridDecoded.attachmentLayout);
Require(grid != original && grid == gridReplayed, "the decoded sample grid state keys another pipeline");
auto lineState = state;
lineState.stages.mesh = ShaderRecompiler::MeshConfiguration{1, 2, 2, 4, 4, 32, 64, 1, 4, 2};
GraphicsPipelineRecipe lineDecoded;
Require(DecodeGraphicsPipelineRecipe(EncodeGraphicsPipelineRecipe(MakeGraphicsPipelineRecipe(lineState, input, layouts.View(), shaders, VK_IMAGE_LAYOUT_GENERAL)), lineDecoded), "the line strip mesh recipe does not decode");
Require(lineDecoded.state.stages.mesh && lineDecoded.state.stages.mesh->outputPrimitiveSize == 2u && lineDecoded.state.stages.mesh->esgsItemSize == 4u, "the recipe dropped the mesh output primitive size");
auto fourSampleState = state;
fourSampleState.samples = 4;
auto maskState = fourSampleState;
@@ -7651,6 +7657,19 @@ void pipelineJournalTests() {
const auto after = PipelineJournalTotals();
Require(cancelled->Done() && after.replayFailed == 0 && after.replayRejected == 0 && after.replayedGraphics + after.replayPresent <= totals.replayedGraphics + totals.replayPresent + 1, "a cancelled replay did not stop cleanly");
}
{
const std::uint32_t meshWithoutOutputSize = 2u;
std::fstream file(PipelineJournalPath(), std::ios::in | std::ios::out | std::ios::binary);
file.seekp(4);
file.write(reinterpret_cast<const char*>(&meshWithoutOutputSize), sizeof(meshWithoutOutputSize));
file.close();
Require(file.good(), "the journal header could not be rewritten");
auto stale = StartPipelineJournalReplay(context, fingerprint, hooks);
Require(stale != nullptr, "the replay of a journal in the previous format did not start");
stale->Wait();
const auto discarded = PipelineJournalTotals();
Require(discarded.loadedRecipes == 0 && discarded.loadedModules == 0, "a journal in format 2, whose mesh records lack the output primitive size, was loaded");
}
ClearCachedPipelines(context.device);
}
Require(replayedComputeIdentityLow != 0, "the replayed compute identity is empty");