// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
priv enum AutoReleaseEntry {
TrackBuffer(Buffer)
TrackShaderModule(ShaderModule)
TrackComputePipeline(ComputePipeline)
TrackTexture(Texture)
TrackTextureView(TextureView)
TrackSurface(Surface)
TrackSampler(Sampler)
TrackRenderPipeline(RenderPipeline)
TrackRenderBundleEncoder(RenderBundleEncoder)
TrackRenderBundle(RenderBundle)
TrackBindGroupLayout(BindGroupLayout)
TrackBindGroup(BindGroup)
TrackPipelineLayout(PipelineLayout)
TrackQuerySet(QuerySet)
TrackCommandEncoder(CommandEncoder)
TrackCommandBuffer(CommandBuffer)
TrackComputePass(ComputePass)
TrackRenderPass(RenderPass)
}
///|
fn release_auto_release_entry(entry : AutoReleaseEntry) -> Unit {
match entry {
TrackBuffer(buffer) => buffer.release()
TrackShaderModule(shader) => shader.release()
TrackComputePipeline(pipeline) => pipeline.release()
TrackTexture(texture) => texture.release()
TrackTextureView(view) => view.release()
TrackSurface(surface) => surface.release()
TrackSampler(sampler) => sampler.release()
TrackRenderPipeline(pipeline) => pipeline.release()
TrackRenderBundleEncoder(encoder) => encoder.release()
TrackRenderBundle(bundle) => bundle.release()
TrackBindGroupLayout(layout) => layout.release()
TrackBindGroup(group) => group.release()
TrackPipelineLayout(layout) => layout.release()
TrackQuerySet(query_set) => query_set.release()
TrackCommandEncoder(encoder) => encoder.release()
TrackCommandBuffer(buffer) => buffer.release()
TrackComputePass(pass) => pass.release()
TrackRenderPass(pass) => pass.release()
}
}
///|
priv struct AutoReleasePoolState {
mut entries : Array[AutoReleaseEntry]
mut released : Bool
}
///|
pub struct AutoReleasePool {
priv state : Ref[AutoReleasePoolState]
}
///|
pub fn AutoReleasePool::new() -> AutoReleasePool {
{ state: @ref.new({ entries: [], released: false }) }
}
///|
fn AutoReleasePool::push(
self : AutoReleasePool,
entry : AutoReleaseEntry,
) -> Unit {
guard !self.state.val.released else {
abort("AutoReleasePool already released")
}
self.state.val.entries.push(entry)
}
///|
pub fn AutoReleasePool::release(self : AutoReleasePool) -> Unit {
if self.state.val.released {
return
}
for i = self.state.val.entries.length() - 1; i >= 0; i = i - 1 {
release_auto_release_entry(self.state.val.entries[i])
}
self.state.val.entries = []
self.state.val.released = true
}
///|
pub fn AutoReleasePool::track_buffer(
self : AutoReleasePool,
buffer : Buffer,
) -> Buffer {
self.push(TrackBuffer(buffer))
buffer
}
///|
pub fn AutoReleasePool::track_shader_module(
self : AutoReleasePool,
shader : ShaderModule,
) -> ShaderModule {
self.push(TrackShaderModule(shader))
shader
}
///|
pub fn AutoReleasePool::track_compute_pipeline(
self : AutoReleasePool,
pipeline : ComputePipeline,
) -> ComputePipeline {
self.push(TrackComputePipeline(pipeline))
pipeline
}
///|
pub fn AutoReleasePool::track_texture(
self : AutoReleasePool,
texture : Texture,
) -> Texture {
self.push(TrackTexture(texture))
texture
}
///|
pub fn AutoReleasePool::track_texture_view(
self : AutoReleasePool,
view : TextureView,
) -> TextureView {
self.push(TrackTextureView(view))
view
}
///|
pub fn AutoReleasePool::track_surface(
self : AutoReleasePool,
surface : Surface,
) -> Surface {
self.push(TrackSurface(surface))
surface
}
///|
pub fn AutoReleasePool::track_sampler(
self : AutoReleasePool,
sampler : Sampler,
) -> Sampler {
self.push(TrackSampler(sampler))
sampler
}
///|
pub fn AutoReleasePool::track_render_pipeline(
self : AutoReleasePool,
pipeline : RenderPipeline,
) -> RenderPipeline {
self.push(TrackRenderPipeline(pipeline))
pipeline
}
///|
pub fn AutoReleasePool::track_render_bundle_encoder(
self : AutoReleasePool,
encoder : RenderBundleEncoder,
) -> RenderBundleEncoder {
self.push(TrackRenderBundleEncoder(encoder))
encoder
}
///|
pub fn AutoReleasePool::track_render_bundle(
self : AutoReleasePool,
bundle : RenderBundle,
) -> RenderBundle {
self.push(TrackRenderBundle(bundle))
bundle
}
///|
pub fn AutoReleasePool::track_bind_group_layout(
self : AutoReleasePool,
layout : BindGroupLayout,
) -> BindGroupLayout {
self.push(TrackBindGroupLayout(layout))
layout
}
///|
pub fn AutoReleasePool::track_bind_group(
self : AutoReleasePool,
group : BindGroup,
) -> BindGroup {
self.push(TrackBindGroup(group))
group
}
///|
pub fn AutoReleasePool::track_pipeline_layout(
self : AutoReleasePool,
layout : PipelineLayout,
) -> PipelineLayout {
self.push(TrackPipelineLayout(layout))
layout
}
///|
pub fn AutoReleasePool::track_query_set(
self : AutoReleasePool,
query_set : QuerySet,
) -> QuerySet {
self.push(TrackQuerySet(query_set))
query_set
}
///|
pub fn AutoReleasePool::track_command_encoder(
self : AutoReleasePool,
encoder : CommandEncoder,
) -> CommandEncoder {
self.push(TrackCommandEncoder(encoder))
encoder
}
///|
pub fn AutoReleasePool::track_command_buffer(
self : AutoReleasePool,
command_buffer : CommandBuffer,
) -> CommandBuffer {
self.push(TrackCommandBuffer(command_buffer))
command_buffer
}
///|
pub fn AutoReleasePool::track_compute_pass(
self : AutoReleasePool,
pass : ComputePass,
) -> ComputePass {
self.push(TrackComputePass(pass))
pass
}
///|
pub fn AutoReleasePool::track_render_pass(
self : AutoReleasePool,
pass : RenderPass,
) -> RenderPass {
self.push(TrackRenderPass(pass))
pass
}