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

iosMacosMain.korlibs.metal.AGMetal.kt Maven / Gradle / Ivy

There is a newer version: 4.0.10
Show newest version
package korlibs.metal

import korlibs.memory.*
import korlibs.graphics.*
import korlibs.graphics.shader.*
import korlibs.metal.shader.*
import kotlinx.cinterop.*
import platform.Metal.*
import platform.MetalKit.*

class AGMetal(private val view: MTKView) : AG() {

    private val device = MTLCreateSystemDefaultDevice() ?: error("fail to create metal device")
    private val commandQueue = device.newCommandQueue() ?: error("fail to create metal command queue")
    private val programs = HashMap()
    // TODO: this will be rework on next iteration
    private val buffersv1 = HashMap()
    private val buffers = HashMap>()

    override fun draw(
        frameBuffer: AGFrameBufferBase,
        frameBufferInfo: AGFrameBufferInfo,
        vertexData: AGVertexArrayObject,
        program: Program,
        drawType: AGDrawType,
        vertexCount: Int,
        indices: AGBuffer?,
        indexType: AGIndexType,
        drawOffset: Int,
        blending: AGBlending,
        uniformBlocks: UniformBlocksBuffersRef,
        textureUnits: AGTextureUnits,
        stencilRef: AGStencilReference,
        stencilOpFunc: AGStencilOpFunc,
        colorMask: AGColorMask,
        depthAndFrontFace: AGDepthAndFrontFace,
        scissor: AGScissor,
        cullFace: AGCullFace,
        instances: Int
    ) {
        autoreleasepool { // TODO: Check if that necessary

            val currentProgram = getProgram(
                program
            )

            val commandBuffer = commandQueue.commandBuffer() ?: error("fail to get command buffer")
            val renderPassDescriptor =
                view.currentRenderPassDescriptor ?: error("fail to get current render pass descriptor")

            val renderCommanderEncoder = commandBuffer.renderCommandEncoderWithDescriptor(renderPassDescriptor)
                ?: error("fail to get render commander encoder")

            renderCommanderEncoder.apply {
                setViewport(frameBufferInfo.toViewPort())
                setRenderPipelineState(currentProgram.renderPipelineState)

                // TODO: support texture
                //setFragmentTexture(texture, 0)
                //setFragmentSamplerState(samplerState, 0)

                var currentBuffer = 0uL
                vertexData.list.fastForEach{ buffer ->
                    setVertexBuffer(buffer.buffer.toMetal.buffer, 0, currentBuffer)
                    currentBuffer += 1uL
                }

                uniformBlocks.fastForEachBlock { index, block, buffer, valueIndex ->
                    TODO()
                }
                //uniformBlocks.fastForEachUniform {
                //    setVertexBuffer(it.data.toMetal.buffer, 0, currentBuffer)
                //    currentBuffer += 1uL
                //}

                //uniforms.values.fastForEach { buffer ->
                //    setVertexBuffer(buffer.data.toMetal.buffer, 0, currentBuffer)
                //    currentBuffer += 1uL
                //}

                if (indices != null) {
                    drawIndexedPrimitives(drawType.toMetal(), vertexCount.toULong(), indexType.toMetal(), indices.toMetal.buffer, 0)
                } else {
                    TODO("Not yet supported, rendering without vertex indexes")
                }

                popDebugGroup()
                endEncoding()
            }

            val drawable = view.currentDrawable ?: error("fail to get current drawable")
            commandBuffer.presentDrawable(drawable)
            commandBuffer.commit()
        }
    }


    private val Buffer.toMetal: MTLBuffer
        get() = buffersv1
            .getOrPut(this) {
                val size = sizeInBytes.toULong()
                device.newBuffer(size)
                    .also { it.insert(data) }
            }

    private val AGBuffer.toMetal: MTLBuffer
        get() = (mem ?: error("cannot create buffer from null memory")).toMetal

    private fun getProgram(program: Program) = programs
        .getOrPut(program) {
            MetalShaderCompiler.compile(device, program)
        }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy