namespace AcDream.App.Rendering.Gpu; /// /// Creation parameters for a GPU buffer. is not /// cosmetic: the Vulkan backend publishes it through VK_EXT_debug_utils /// so RenderDoc captures and validation-layer messages name our objects. /// /// Stable identifier, e.g. "mesh-arena-vertex". /// Allocation size. Growth is a create-copy-retire cycle, never a resize. /// Every way the buffer will be consumed. /// Where the memory lives and whether the CPU may write it directly. internal readonly record struct GpuBufferDescription( string Name, long SizeBytes, GpuBufferUsage Usage, GpuMemoryResidency Residency); /// Creation parameters for a sampled texture or a render-target image. /// Stable identifier for debug tooling. /// 2D, or the 2D array every world material uses. /// Pixel format; BC formats are uploaded as compressed blocks. /// Width in texels of mip level 0. /// Height in texels of mip level 0. /// Array layers; 1 for . /// /// Levels to allocate. 1 disables mipping. The backend never silently generates /// mips: is an explicit call, because /// Vulkan cannot blit-generate compressed mips and must take a CPU-built chain. /// internal readonly record struct GpuTextureDescription( string Name, GpuTextureKind Kind, GpuTextureFormat Format, int Width, int Height, int LayerCount, int MipLevelCount); /// /// Sampler state. The set of distinct samplers acdream uses is tiny (wrap/clamp /// × nearest/linear), which is what makes a combined image-sampler descriptor /// table practical: a texture registered twice with different samplers simply /// occupies two table slots, exactly as it holds two bindless handles today. /// internal readonly record struct GpuSamplerDescription( GpuFilter MinFilter, GpuFilter MagFilter, GpuMipFilter MipFilter, GpuAddressMode AddressU, GpuAddressMode AddressV, float MaxAnisotropy) { /// Trilinear repeat — the default for world materials. public static GpuSamplerDescription WorldRepeat { get; } = new( GpuFilter.Linear, GpuFilter.Linear, GpuMipFilter.Linear, GpuAddressMode.Repeat, GpuAddressMode.Repeat, MaxAnisotropy: 1f); /// Trilinear clamped — atlas pages and anything whose edges must not wrap. public static GpuSamplerDescription WorldClamp { get; } = new( GpuFilter.Linear, GpuFilter.Linear, GpuMipFilter.Linear, GpuAddressMode.ClampToEdge, GpuAddressMode.ClampToEdge, MaxAnisotropy: 1f); /// Unfiltered clamped — retail UI icons and the composited 32×32 item art. public static GpuSamplerDescription UiNearest { get; } = new( GpuFilter.Nearest, GpuFilter.Nearest, GpuMipFilter.None, GpuAddressMode.ClampToEdge, GpuAddressMode.ClampToEdge, MaxAnisotropy: 1f); } /// An offscreen colour(+depth) bundle: paperdoll, creature appraisal, portal masking. /// Stable identifier for debug tooling. /// Colour attachment width in pixels. /// Colour attachment height in pixels. /// Colour attachment format. /// Depth/stencil format, or null for a colour-only target. /// 1 for single-sampled. Offscreen targets stay single-sampled. internal readonly record struct GpuRenderTargetDescription( string Name, int Width, int Height, GpuTextureFormat ColorFormat, GpuTextureFormat? DepthFormat, int SampleCount); /// /// A slot in the device's global texture table — the backend-neutral replacement /// for a 64-bit ARB_bindless_texture handle. Renderers write /// into batch data; the shader indexes the descriptor array /// (Vulkan) or the uvec2 handle buffer (GL) with it. /// /// is a loud sentinel, never a usable slot. It exists so /// an unset index is an assertable programming error rather than a silent /// resolve to slot 0 — the failure mode that produced the magenta 1×1 UI /// placeholder bug. Renderers that genuinely need a fallback ask the device for /// , which is a real registered texture. /// internal readonly record struct GpuTextureSlot(uint Index) { /// Sentinel for "no texture assigned". Must never reach a shader. public static GpuTextureSlot Unassigned { get; } = new(uint.MaxValue); public bool IsAssigned => Index != uint.MaxValue; public override string ToString() => IsAssigned ? $"slot#{Index}" : "slot#unassigned"; }