All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.org.openrndr.draw.Session.kt Maven / Gradle / Ivy

There is a newer version: 0.4.5-alpha6
Show newest version
package org.openrndr.draw

import mu.KotlinLogging
import org.openrndr.internal.Driver

private val logger = KotlinLogging.logger {}
private val sessionStack = mutableMapOf>()

/**
 * Session statistics
 */
class SessionStatistics(
        val renderTargets: Int,
        val colorBuffers: Int,
        val depthBuffers: Int,
        val bufferTextures: Int,
        val indexBuffers: Int,
        val vertexBuffers: Int,
        val shaders: Int,
        val cubemaps: Int,
        val arrayTextures: Int,
        val computeShaders: Int,
        val atomicCounterBuffers: Int,
        val arrayCubemaps: Int,
        val shaderStorageBuffers: Int)

/**
 * Session
 */
class Session(val parent: Session?) {
    val context = Driver.instance.contextID

    companion object {
        /**
         * The session stack (on the active context)
         */
        val stack: ArrayDeque
            get() = sessionStack.getOrPut(Driver.instance.contextID) { ArrayDeque().apply { addLast(Session(null)) } }

        /**
         * The active session (on the active context)
         */
        val active: Session
            get() = stack.last()

        /**
         * The root session (on the active context)
         */
        val root: Session
            get() = stack.first()

        /**
         * Ends the active session and pops it off the session stack (on the active context)
         */
        fun endActive() {
            val session = sessionStack.getValue(Driver.instance.contextID).removeLast()
            session.end()
        }
    }

    private val children = mutableListOf()

    private val renderTargets = mutableSetOf()
    private val colorBuffers = mutableSetOf()
    private val depthBuffers = mutableSetOf()
    private val bufferTextures = mutableSetOf()
    private val vertexBuffers = mutableSetOf()
    private val shaders = mutableSetOf()
    private val computeShaders = mutableSetOf()
    private val cubemaps = mutableSetOf()
    private val arrayTextures = mutableSetOf()
    private val arrayCubemaps = mutableSetOf()
    private val indexBuffers = mutableSetOf()
    private val volumeTextures = mutableSetOf()
    private val shaderStorageBuffers = mutableSetOf()
    private val atomicCounterBuffers = mutableSetOf()

    /** Session statistics */
    val statistics
        get() =
            SessionStatistics(renderTargets = renderTargets.size,
                    colorBuffers = colorBuffers.size,
                    depthBuffers = depthBuffers.size,
                    bufferTextures = bufferTextures.size,
                    indexBuffers = indexBuffers.size,
                    vertexBuffers = vertexBuffers.size,
                    shaders = shaders.size,
                    cubemaps = cubemaps.size,
                    arrayTextures = arrayTextures.size,
                    computeShaders = computeShaders.size,
                    atomicCounterBuffers = atomicCounterBuffers.size,
                    arrayCubemaps = arrayCubemaps.size,
                    shaderStorageBuffers = shaderStorageBuffers.size)

    fun track(renderTarget: RenderTarget) = renderTargets.add(renderTarget)
    fun untrack(renderTarget: RenderTarget) = renderTargets.remove(renderTarget)

    fun track(colorBuffer: ColorBuffer) = colorBuffers.add(colorBuffer)
    fun untrack(colorBuffer: ColorBuffer) = colorBuffers.remove(colorBuffer)

    fun track(depthBuffer: DepthBuffer) = depthBuffers.add(depthBuffer)
    fun untrack(depthBuffer: DepthBuffer) = depthBuffers.remove(depthBuffer)

    fun track(vertexBuffer: VertexBuffer) = vertexBuffers.add(vertexBuffer)
    fun untrack(vertexBuffer: VertexBuffer) = vertexBuffers.remove(vertexBuffer)

    fun track(indexBuffer: IndexBuffer) = indexBuffers.add(indexBuffer)
    fun untrack(indexBuffer: IndexBuffer) = indexBuffers.remove(indexBuffer)

    fun track(shader: Shader) = shaders.add(shader)
    fun untrack(shader: Shader) = shaders.remove(shader)

    fun track(computeShader: ComputeShader) = computeShaders.add(computeShader)
    fun untrack(computeShader: ComputeShader) = computeShaders.remove(computeShader)

    fun track(cubemap: Cubemap) = cubemaps.add(cubemap)
    fun untrack(cubemap: Cubemap) = cubemaps.remove(cubemap)

    fun track(bufferTexture: BufferTexture) = bufferTextures.add(bufferTexture)
    fun untrack(bufferTexture: BufferTexture) = bufferTextures.remove(bufferTexture)

    fun track(arrayTexture: ArrayTexture) = arrayTextures.add(arrayTexture)
    fun untrack(arrayTexture: ArrayTexture) = arrayTextures.remove(arrayTexture)

    fun track(atomicCounterBuffer: AtomicCounterBuffer) = atomicCounterBuffers.add(atomicCounterBuffer)
    fun untrack(atomicCounterBuffer: AtomicCounterBuffer) = atomicCounterBuffers.remove(atomicCounterBuffer)

    fun track(arrayCubemap: ArrayCubemap) = arrayCubemaps.add(arrayCubemap)
    fun untrack(arrayCubemap: ArrayCubemap) = arrayCubemaps.remove(arrayCubemap)

    fun track(volumeTexture: VolumeTexture) = volumeTextures.add(volumeTexture)
    fun untrack(volumeTexture: VolumeTexture) = volumeTextures.remove(volumeTexture)

    fun track(shaderStorageBuffer: ShaderStorageBuffer) = shaderStorageBuffers.add(shaderStorageBuffer)
    fun untrack(shaderStorageBuffer: ShaderStorageBuffer) = shaderStorageBuffers.remove(shaderStorageBuffer)

    /**
     * Fork the session
     */
    fun fork(): Session {
        logger.debug { "starting new session for context [id=${context}]" }
        val child = Session(this)
        sessionStack.getValue(Driver.instance.contextID).addLast(child)
        children.add(child)
        return child
    }

    /**
     * Ends the session, destroys any GPU resources in use by the session
     */
    fun end() {
        parent?.children?.remove(this)

        for (child in children.map { it }) {
            child.end()
        }
        children.clear()

        logger.debug {
            """
                session ended for context [id=${context}]
                destroying ${renderTargets.size} render targets
                destroying ${shaders.size} shaders
                destroying ${colorBuffers.size} color buffers
                destroying ${depthBuffers.size} depth buffers
                destroying ${vertexBuffers.size} vertex buffers
                destroying ${cubemaps.size} cubemaps
                destroying ${bufferTextures.size} buffer textures
                destroying ${arrayTextures.size} array textures
                destroying ${computeShaders.size} compute shaders
                destroying ${atomicCounterBuffers.size} atomic counter buffers
                destroying ${arrayCubemaps.size} array cubemaps
            """.trimIndent()
        }

        renderTargets.map { it }.forEach {
            it.detachColorAttachments()
            it.detachDepthBuffer()
            it.destroy()
        }
        renderTargets.clear()

        colorBuffers.map { it }.forEach {
            it.destroy()
        }
        colorBuffers.clear()

        depthBuffers.map { it }.forEach {
            it.destroy()
        }
        depthBuffers.clear()

        vertexBuffers.map { it }.forEach {
            it.destroy()
        }
        vertexBuffers.clear()

        indexBuffers.map { it }.forEach {
            it.destroy()
        }
        indexBuffers.clear()

        cubemaps.map { it }.forEach {
            it.destroy()
        }
        cubemaps.clear()

        bufferTextures.map { it }.forEach {
            it.destroy()
        }
        bufferTextures.clear()

        shaders.map { it }.forEach {
            it.destroy()
        }
        shaders.clear()

        computeShaders.map { it }.forEach {
            it.destroy()
        }
        computeShaders.clear()

        arrayTextures.map { it }.forEach {
            it.destroy()
        }
        arrayTextures.clear()

        arrayCubemaps.map { it }.forEach {
            it.destroy()
        }
        arrayCubemaps.clear()


        shaderStorageBuffers.map { it }.forEach {
            it.destroy()
        }
        shaderStorageBuffers.clear()
    }
}

/** Runs code inside a (short-lived) session */
fun session(code: () -> Unit) {
    val s = Session.active.fork()
    code()
    s.end()
}

/**
 * Mark a GPU resource or code that uses GPU resources as persistent
 */
fun  persistent(builder: () -> T): T {
    Session.stack.addLast(Session.root)
    val result = builder()
    Session.stack.removeLast()
    return result
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy