feat(render): shader ABI v2 - AtmosphericFrame gains clock/wind blocks; caster pass binds it (Campaign VM VM6a)
AtmosphericFrame (set 3/binding 5) grows additively from 160 to 192 bytes: two appended vec4 members, uAtmosphereClockWind and uAtmosphereWindAmplitude, carry the foliage-wind clock/weather and amplitude inputs VM6b's shader displacement will read. RenderPackShaderAbi renames the old constant to AtmosphericFrameSizeBytesV1 (160), adds AtmosphericFrameSizeBytesV2 (192), keeps AtmosphericFrameSizeBytes pointing at the current (v2) size, and adds ShaderAbiVersion = 2. RenderPackSpirvValidator.ValidateAtmosphericFrame accepts either the v1 (seven-member, 160-byte) or v2 (nine-member, 192-byte) shape and rejects anything else naming both — this is why the frozen external sample packs under samples/*/Shaders/*.spv, whose GLSL sources are not in this tree, need no rebuild: a v1 shader bound to the 192-byte buffer still reads correctly, since a bound range only needs to be >= the block's own declared size. DirectionalSunShadowRenderer's caster pass now binds AtmosphericFrame too (both the multiview and per-cascade sites), through a new AtmosphericFrameBufferBinding the graph owns and supplies via DirectionalSunShadowRenderInput. AtmosphericPostProcessGraph.RenderDirectionalShadows builds its own 192-byte ring allocation for this, separate from the world receiver's frame block, because the caster pass runs before RenderPostProcess constructs that block within the same frame. The four world caster pipeline variants (opaque/cutout, base/multiview) are now allowed to declare binding 5 in the validator; terrain casters are untouched. This commit is plumbing only: the two new members are always written but never read by any shader yet (zero placeholders), so pack-on and pack-off output are both pixel-identical to before. VM6b wires the real weather-driven values and the shader-side displacement. App hermetic filter: 5972/5974 (2 pre-existing failures unrelated to this change, confirmed against the unmodified baseline). Core.Tests hermetic: 4697/4697. RenderPackValidator.Tests: 30/30. VulkanShaderManifestTests (retail oracle set): 7/7, byte-identical. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
a0157693ec
commit
0930c35d1d
17 changed files with 340 additions and 32 deletions
|
|
@ -7,9 +7,27 @@ namespace AcDream.Plugin.Abstractions.Rendering;
|
|||
/// </summary>
|
||||
public static class RenderPackShaderAbi
|
||||
{
|
||||
/// <summary>
|
||||
/// Campaign VM VM6: the render-pack shader ABI version this host writes
|
||||
/// and binds. v2 is additive over v1 — see <see cref="AtmosphericFrameSizeBytesV2"/>.
|
||||
/// </summary>
|
||||
public const int ShaderAbiVersion = 2;
|
||||
|
||||
public const int UniformDescriptorSet = 3;
|
||||
public const int AtmosphericFrameBinding = 5;
|
||||
public const int AtmosphericFrameSizeBytes = 160;
|
||||
|
||||
/// <summary>ABI v1 AtmosphericFrame size: seven vec4/mat4 members, 160 bytes.</summary>
|
||||
public const int AtmosphericFrameSizeBytesV1 = 160;
|
||||
|
||||
/// <summary>
|
||||
/// ABI v2 AtmosphericFrame size: v1's 160 bytes plus two appended vec4
|
||||
/// members (foliage-wind clock/weather and amplitude), 192 bytes.
|
||||
/// </summary>
|
||||
public const int AtmosphericFrameSizeBytesV2 = 192;
|
||||
|
||||
/// <summary>What the host allocates and binds. Always the current ABI version.</summary>
|
||||
public const int AtmosphericFrameSizeBytes = AtmosphericFrameSizeBytesV2;
|
||||
|
||||
public const int DirectionalShadowBinding = 6;
|
||||
public const int DirectionalShadowSizeBytes = 336;
|
||||
public const int PackPassBinding = 7;
|
||||
|
|
|
|||
|
|
@ -67,14 +67,20 @@ public static class RenderPackSpirvValidator
|
|||
new([], [], false, false, true, false, false),
|
||||
RenderPipelineVariantSemantic.TerrainMultiviewDirectionalShadowCaster =>
|
||||
new([], [], false, false, true, false, false),
|
||||
// Campaign VM VM6: these four world caster variants now bind
|
||||
// AtmosphericFrame (set 3/binding 5) for foliage_wind.glsl's
|
||||
// clock/wind inputs — the shadow must move with the leaf, and the
|
||||
// shared include is what keeps caster and receiver from drifting
|
||||
// apart. Terrain casters are untouched and keep AllowAtmosphericFrame
|
||||
// false.
|
||||
RenderPipelineVariantSemantic.WorldOpaqueDirectionalShadowCaster =>
|
||||
new([0u], [], false, false, true, false, false),
|
||||
new([0u], [], false, true, true, false, false),
|
||||
RenderPipelineVariantSemantic.WorldOpaqueMultiviewDirectionalShadowCaster =>
|
||||
new([0u], [], false, false, true, false, false),
|
||||
new([0u], [], false, true, true, false, false),
|
||||
RenderPipelineVariantSemantic.WorldAlphaCutoutDirectionalShadowCaster =>
|
||||
new([0u, 1u], [], true, false, true, false, false),
|
||||
new([0u, 1u], [], true, true, true, false, false),
|
||||
RenderPipelineVariantSemantic.WorldAlphaCutoutMultiviewDirectionalShadowCaster =>
|
||||
new([0u, 1u], [], true, false, true, false, false),
|
||||
new([0u, 1u], [], true, true, true, false, false),
|
||||
RenderPipelineVariantSemantic.TerrainDirectionalShadowReceiver =>
|
||||
new([], [1u, 2u, 3u], true, false, true, false, true),
|
||||
RenderPipelineVariantSemantic.WorldDirectionalShadowReceiver =>
|
||||
|
|
@ -247,8 +253,17 @@ public static class RenderPackSpirvValidator
|
|||
|
||||
private static string? ValidateAtmosphericFrame(Module module, uint id, uint[] members)
|
||||
{
|
||||
if (members.Length != 7)
|
||||
return "AtmosphericFrame must contain exactly seven members and occupy 160 bytes";
|
||||
// Campaign VM VM6: ABI v2 is additive over v1 — a module declares
|
||||
// EITHER the seven-member/160-byte v1 shape (frozen external sample
|
||||
// packs, and every pass this campaign did not touch) OR the
|
||||
// nine-member/192-byte v2 shape (the world receiver + directional-
|
||||
// shadow caster passes VM6 gave foliage-wind inputs). Any other
|
||||
// member count is rejected naming both accepted layouts.
|
||||
if (members.Length != 7 && members.Length != 9)
|
||||
{
|
||||
return "AtmosphericFrame must match ABI v1 (seven members, 160 bytes) or "
|
||||
+ "ABI v2 (nine members, 192 bytes)";
|
||||
}
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (!module.IsFloatVector(members[i], 4) || module.MemberOffset(id, i) != (uint)(i * 16))
|
||||
|
|
@ -259,6 +274,13 @@ public static class RenderPackSpirvValidator
|
|||
|| module.MemberDecoration(id, 6, Decoration.ColMajor) is null
|
||||
|| module.MemberDecoration(id, 6, Decoration.MatrixStride) != 16)
|
||||
return "AtmosphericFrame inverse-view-projection layout does not match ABI v1";
|
||||
if (members.Length == 7)
|
||||
return null;
|
||||
|
||||
if (!module.IsFloatVector(members[7], 4) || module.MemberOffset(id, 7) != 160)
|
||||
return "AtmosphericFrame clock/wind member does not match ABI v2";
|
||||
if (!module.IsFloatVector(members[8], 4) || module.MemberOffset(id, 8) != 176)
|
||||
return "AtmosphericFrame wind-amplitude member does not match ABI v2";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue