namespace AcDream.App.Rendering.Gpu; /// /// The RHI root: creates every GPU resource, owns the global texture table, and /// drives the frame loop. One instance per graphics context, constructed during /// composition and threaded into renderers in place of the raw GL handle. /// /// Campaign V (see docs/plans/2026-07-27-vulkan-campaign.md) implements /// this interface twice: first on OpenGL — behaviour-preserving, so each renderer /// port is pixel-gated against the previous commit on the shipping backend — and /// then on Vulkan, gated by a GL-versus-Vulkan differential. The GL /// implementation is deleted at slice V11. /// internal interface IGpuDevice : IDisposable { GpuBackendKind Backend { get; } GpuCapabilityRecord Capabilities { get; } /// /// Frame-flight-gated resource release. Resource disposal routes through here /// so nothing is freed while a submitted frame may still reference it. /// IGpuResourceRetirementQueue Retirement { get; } /// GPU timing results from retired frames. IGpuTimerPool Timers { get; } /// /// A registered 1×1 opaque-white texture. Renderers that need a defined /// fallback use this rather than assuming slot 0 means anything — an /// unregistered is /// and must never reach a shader. /// GpuTextureSlot DefaultTextureSlot { get; } IGpuBuffer CreateBuffer(in GpuBufferDescription description); IGpuTexture CreateTexture(in GpuTextureDescription description); /// Creates or returns a cached sampler; sampler state is de-duplicated by value. IGpuSampler CreateSampler(in GpuSamplerDescription description); /// /// Compiles and links a pipeline. Both backends build every pipeline during /// startup, so no frame ever pays a shader-compile or state-revalidation cost. /// IGpuPipeline CreatePipeline(GpuPipelineDescription description); IGpuRenderTarget CreateRenderTarget(in GpuRenderTargetDescription description); /// /// Publishes a (texture, sampler) pair into the global table and returns the /// slot shaders index it by. The same texture registered with two samplers /// occupies two slots — matching how it holds two bindless handles today. /// GpuTextureSlot RegisterTexture(IGpuTexture texture, IGpuSampler sampler); /// /// Returns a slot to the free list. The slot is not reused until the frames /// that could still reference it have retired, so eviction (the texture and /// mesh caches' LRU) cannot alias a live draw onto a new texture. /// void ReleaseTextureSlot(GpuTextureSlot slot); /// Opens the next frame, waiting for its flight slot to retire first. IGpuFrame BeginFrame(); /// /// Defers to the render thread. Replaces /// OpenGLGraphicsDevice.QueueGLAction; loader threads use it to hand /// GPU work back to the thread that owns the context or queue. /// void QueueDeviceAction(Action action); /// Runs queued device actions. Called once per frame from the render thread. void ProcessDeviceActions(); /// /// Reads the presented image back as tightly packed top-left-origin RGBA8. /// This is the seam the automated screenshot gates already use, so the /// pixel-comparison tooling is unaffected by the backend swap. /// byte[] CaptureBackbuffer(int width, int height); /// Blocks until all submitted work completes and every pending retirement has run. void WaitIdle(); }