using System.Numerics;
using System.Runtime.InteropServices;
namespace AcDream.App.Rendering.Gpu;
///
/// The single push-constant block shared by every acdream pipeline — 96 of the
/// 128 bytes Vulkan guarantees, leaving 32 bytes of headroom for later slices.
///
/// One shared block (rather than a per-shader block) is what lets every world
/// pipeline share ONE pipeline layout, so switching pipelines mid-pass does not
/// invalidate bound descriptor sets or push constants. Shaders declare only the
/// fields they read; unused fields cost nothing.
///
/// The GL backend maps each field to the correspondingly named uniform and skips
/// any the program does not declare (location -1). The Vulkan backend writes the
/// struct verbatim with one vkCmdPushConstants.
///
/// Layout is asserted by GpuContractTests; changing it is a contract change
/// that must land together with the matching edit to the shared GLSL preamble.
///
[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct GpuPushConstants
{
///
/// GLSL uViewProjection. acdream's cameras build this with
/// Matrix4x4.CreatePerspectiveFieldOfView, whose NDC z range is [0,1] —
/// already Vulkan's convention (see PortalProjection.cs). No projection
/// rework is needed for the migration, and Vulkan gains the half of the depth
/// range GL was discarding.
///
public Matrix4x4 ViewProjection;
///
/// GLSL uDrawIDOffset. Issue #52: the draw index resets to 0 at the
/// start of each multi-draw-indirect call, so a pass that begins partway into
/// the batch array must offset its lookup. Vulkan's gl_DrawID resets
/// identically per vkCmdDrawIndexedIndirect, so the pattern carries over
/// unchanged.
///
public int DrawIdOffset;
/// GLSL uLightingMode: 0 = object (plain Lambert + sun), 1 = EnvCell (half-Lambert wrap, no sun).
public int LightingMode;
/// GLSL uRenderPass: 0 = opaque, 1 = translucent.
public int RenderPass;
/// GLSL uLightDebug: #176 stripe-hunt isolation modes; 0 = off.
public int LightDebug;
///
/// GLSL uTextureIndexA. Primary texture-table slot for pipelines whose
/// texture is per-pass rather than per-batch — currently the terrain atlas.
///
public uint TextureIndexA;
/// GLSL uTextureIndexB. Secondary per-pass slot — currently the terrain alpha-mask array.
public uint TextureIndexB;
///
/// GLSL uParamA. Spare scalar, claimed at slice V6e by
/// particle_mesh as the array layer its per-pass texture is sampled
/// from — a value the shader converted to float anyway.
///
public float ParamA;
/// GLSL uParamB. Spare scalar; unclaimed at V0.
public float ParamB;
/// Neutral defaults: identity transform, opaque object lighting, no debug mode.
public static GpuPushConstants Default => new()
{
ViewProjection = Matrix4x4.Identity,
DrawIdOffset = 0,
LightingMode = 0,
RenderPass = 0,
LightDebug = 0,
TextureIndexA = 0,
TextureIndexB = 0,
ParamA = 0f,
ParamB = 0f,
};
}