Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

New Buffer classes #21

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -35,7 +35,6 @@ subprojects {
enableLanguageFeature("InlineClasses")
enableLanguageFeature("NewInference")
useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
useExperimentalAnnotation("io.ktor.utils.io.core.ExperimentalIoApi")
}
}

3 changes: 1 addition & 2 deletions buildSrc/src/main/kotlin/codegen/Types.kt
Original file line number Diff line number Diff line change
@@ -20,13 +20,12 @@ import com.squareup.kotlinpoet.MemberName


internal val VIRTUAL_STACK = ClassName("com.kgl.core", "VirtualStack")
internal val DIRECT_BUFFER = ClassName("com.kgl.core", "DirectMemory")
internal val C_OPAQUE_POINTER = ClassName("kotlinx.cinterop", "COpaquePointer")
internal val BYTE_VAR = ClassName("kotlinx.cinterop", "ByteVar")

internal val THREAD_LOCAL = ClassName("kotlin.native.concurrent", "ThreadLocal")

internal val MEMORY = ClassName("io.ktor.utils.io.bits", "Memory")

internal val PAIR = ClassName("kotlin", "Pair")

internal val MEMORY_STACK = ClassName("org.lwjgl.system", "MemoryStack")
8 changes: 4 additions & 4 deletions buildSrc/src/main/kotlin/codegen/vulkan/GenerateVulkan.kt
Original file line number Diff line number Diff line change
@@ -845,7 +845,7 @@ open class GenerateVulkan : DefaultTask() {
1 -> {
when(typeName) {
"char" -> STRING
"void" -> if (len.isNotEmpty()) MEMORY else LONG
"void" -> if (len.isNotEmpty()) DIRECT_BUFFER else LONG
else -> {
val mainType = kglClassMap[typeName] ?: TODO("$type has no KGL representation.")
arrayClassesMap[typeName] ?: collectionType.parameterizedBy(mainType)
@@ -1458,14 +1458,14 @@ open class GenerateVulkan : DefaultTask() {
}
val isOptional = member.optional || lengthParam?.optional == true
if (lengthParam != null) {
addParameter(memberNameKt, MEMORY.copy(nullable = isOptional))
addParameter(memberNameKt, DIRECT_BUFFER.copy(nullable = isOptional))

val assert = if (isOptional) "?" else ""
if (platform == Platform.JVM) {
addStatement("target.${member.name}($memberNameKt$assert.buffer)")
addStatement("target.${member.name}($memberNameKt$assert.asJvmByteBuffer())")
} else {
if (isOptional) beginControlFlow("if ($memberNameKt != null)")
addStatement("target.${member.name} = $memberNameKt.pointer")
addStatement("target.${member.name} = $memberNameKt.asCPointer()")
addStatement("target.${member.len[0]} = $memberNameKt.size.%M()", KtxC.CONVERT)
if (isOptional) {
nextControlFlow("else")
1 change: 0 additions & 1 deletion buildSrc/src/main/kotlin/config/Versions.kt
Original file line number Diff line number Diff line change
@@ -16,7 +16,6 @@
package config

object Versions {
const val KTOR_IO = "1.3.2"
const val LWJGL = "3.2.2"
val LWJGL_NATIVES = when {
Config.OS.isWindows -> "natives-windows"
6 changes: 0 additions & 6 deletions kgl-core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ kotlin {
commonMain {
dependencies {
implementation(kotlin("stdlib-common"))
api("io.ktor:ktor-io:${Versions.KTOR_IO}")
}
}
commonTest {
@@ -29,7 +28,6 @@ kotlin {
dependencies {
implementation(kotlin("stdlib-jdk8"))
api("org.lwjgl:lwjgl:${Versions.LWJGL}")
api("io.ktor:ktor-io-jvm:${Versions.KTOR_IO}")
}
}
"test" {
@@ -46,7 +44,6 @@ kotlin {
"main" {
dependencies {
implementation(kotlin("stdlib-js"))
api("io.ktor:ktor-io-js:${Versions.KTOR_IO}")
}
}
"test" {
@@ -74,9 +71,6 @@ kotlin {
kotlin.srcDir("src/nativeMain/kotlin")
resources.srcDir("src/nativeMain/resources")
}
dependencies {
api("io.ktor:ktor-io-native:${Versions.KTOR_IO}")
}
}

"test" {
30 changes: 30 additions & 0 deletions kgl-core/src/commonMain/kotlin/com/kgl/core/Closeable.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.kgl.core

expect interface Closeable {
fun close()
}

inline fun <C : Closeable, R> C.use(block: (C) -> R): R {
var closed = false

return try {
block(this)
} catch (first: Throwable) {
try {
closed = true
close()
} catch (second: Throwable) {
first.addSuppressedInternal(second)
}

throw first
} finally {
if (!closed) {
close()
}
}
}

// Work-around until https://youtrack.jetbrains.com/issue/KT-23737
@PublishedApi
internal expect fun Throwable.addSuppressedInternal(other: Throwable)
20 changes: 20 additions & 0 deletions kgl-core/src/commonMain/kotlin/com/kgl/core/DirectMemory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.kgl.core

expect class DirectMemory {
val size: Long

operator fun get(offset: Long): Byte
operator fun set(offset: Long, value: Byte)

fun get(dst: ByteArray, srcOffset: Long = 0L, dstOffset: Long = 0L, length: Long = dst.size.toLong())
fun set(src: ByteArray, srcOffset: Long = 0L, dstOffset: Long = 0L, length: Long = src.size.toLong())

fun copyTo(dst: DirectMemory, srcOffset: Long = 0L, dstOffset: Long = 0L, length: Long = dst.size - dstOffset)
fun slice(offset: Long, length: Long): DirectMemory
}

@Suppress("NOTHING_TO_INLINE")
internal inline fun DirectMemory.checkBounds(offset: Long, length: Long) {
require(offset in 0 until this.size)
require(length in 0 until (this.size - offset))
}
4 changes: 4 additions & 0 deletions kgl-core/src/commonMain/kotlin/com/kgl/core/MemUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.kgl.core


expect inline fun <T> withMemory(length: Long, block: (DirectMemory) -> T): T
9 changes: 9 additions & 0 deletions kgl-core/src/jsMain/kotlin/com/kgl/core/Closeable.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.kgl.core

actual interface Closeable {
actual fun close()
}

@PublishedApi
internal actual fun Throwable.addSuppressedInternal(other: Throwable) {
}
42 changes: 42 additions & 0 deletions kgl-core/src/jsMain/kotlin/com/kgl/core/DirectMemory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.kgl.core

import org.khronos.webgl.DataView

actual class DirectMemory(private val ptr: DataView) {
actual val size: Long get() = ptr.byteLength.toLong()

actual operator fun get(offset: Long): Byte {
return ptr.getInt8(offset.toInt())
}

actual operator fun set(offset: Long, value: Byte) {
ptr.setInt8(offset.toInt(), value)
}

actual fun get(dst: ByteArray, srcOffset: Long, dstOffset: Long, length: Long) {
checkBounds(srcOffset, length)
for (i in 0 until length) {
dst[(dstOffset + i).toInt()] = get(srcOffset + i)
}
}

actual fun set(src: ByteArray, srcOffset: Long, dstOffset: Long, length: Long) {
checkBounds(dstOffset, length)
for (i in 0 until length) {
this[dstOffset + i] = src[(srcOffset + i).toInt()]
}
}

actual fun copyTo(dst: DirectMemory, srcOffset: Long, dstOffset: Long, length: Long) {
checkBounds(srcOffset, length)
dst.checkBounds(dstOffset, length)
for (i in 0 until length) {
dst[dstOffset + i] = get(srcOffset + i)
}
}

actual fun slice(offset: Long, length: Long): DirectMemory {
checkBounds(offset, length)
return DirectMemory(DataView(ptr.buffer, ptr.byteOffset + offset.toInt(), length.toInt()))
}
}
11 changes: 11 additions & 0 deletions kgl-core/src/jsMain/kotlin/com/kgl/core/MemUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.kgl.core

import org.khronos.webgl.DataView
import org.khronos.webgl.Int8Array

actual inline fun <T> withMemory(length: Long, block: (DirectMemory) -> T): T {
val array = ByteArray(length.toInt())
val jsArray = array.unsafeCast<Int8Array>()
val view = DataView(jsArray.buffer, jsArray.byteOffset, jsArray.byteLength)
return block(DirectMemory(view))
}
8 changes: 8 additions & 0 deletions kgl-core/src/jvmMain/kotlin/com/kgl/core/CloseableJvm.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.kgl.core

actual typealias Closeable = java.io.Closeable

@PublishedApi
internal actual fun Throwable.addSuppressedInternal(other: Throwable) {
addSuppressed(other)
}
50 changes: 50 additions & 0 deletions kgl-core/src/jvmMain/kotlin/com/kgl/core/DirectMemory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.kgl.core

import org.lwjgl.system.MemoryUtil
import org.lwjgl.system.jni.JNINativeInterface
import java.nio.ByteBuffer as JvmByteBuffer

actual class DirectMemory(private val ptr: Long, actual val size: Long) {

constructor(buffer: JvmByteBuffer) : this(MemoryUtil.memAddress(buffer), buffer.capacity().toLong())

actual operator fun get(offset: Long): Byte {
return MemoryUtil.memGetByte(ptr + (offset * Byte.SIZE_BYTES))
}

actual operator fun set(offset: Long, value: Byte) {
MemoryUtil.memPutByte(ptr + (offset * Byte.SIZE_BYTES), value)
}

actual fun get(dst: ByteArray, srcOffset: Long, dstOffset: Long, length: Long) {
checkBounds(srcOffset, length)

JNINativeInterface.nSetByteArrayRegion(dst, dstOffset.toInt(), length.toInt(), ptr + (srcOffset * Byte.SIZE_BYTES))
}

actual fun set(src: ByteArray, srcOffset: Long, dstOffset: Long, length: Long) {
checkBounds(dstOffset, length)
JNINativeInterface.nGetByteArrayRegion(src, srcOffset.toInt(), length.toInt(), ptr + (dstOffset * Byte.SIZE_BYTES))
}

actual fun copyTo(dst: DirectMemory, srcOffset: Long, dstOffset: Long, length: Long) {
checkBounds(srcOffset, length)
dst.checkBounds(dstOffset, length)

MemoryUtil.memCopy(
ptr + (srcOffset * Byte.SIZE_BYTES),
dst.ptr + (dstOffset * Byte.SIZE_BYTES),
length
)
}

actual fun slice(offset: Long, length: Long): DirectMemory {
checkBounds(offset, length)

return DirectMemory(ptr + (offset * Byte.SIZE_BYTES), length)
}

fun asJvmByteBuffer(): JvmByteBuffer {
return MemoryUtil.memByteBuffer(ptr, size.toInt())
}
}
13 changes: 13 additions & 0 deletions kgl-core/src/jvmMain/kotlin/com/kgl/core/MemUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.kgl.core

import org.lwjgl.system.MemoryUtil


actual inline fun <T> withMemory(length: Long, block: (DirectMemory) -> T): T {
val jvmBuffer = MemoryUtil.memAlloc(length.toInt())
try {
return block(DirectMemory(jvmBuffer))
} finally {
MemoryUtil.memFree(jvmBuffer)
}
}
9 changes: 9 additions & 0 deletions kgl-core/src/nativeMain/kotlin/com/kgl/core/Closeable.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.kgl.core

actual interface Closeable {
actual fun close()
}

@PublishedApi
internal actual fun Throwable.addSuppressedInternal(other: Throwable) {
}
48 changes: 48 additions & 0 deletions kgl-core/src/nativeMain/kotlin/com/kgl/core/DirectMemory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.kgl.core

import kotlinx.cinterop.*
import platform.posix.memcpy

actual class DirectMemory(private val ptr: CPointer<ByteVar>, actual val size: Long) {

actual operator fun get(offset: Long): Byte {
return ptr[offset]
}

actual operator fun set(offset: Long, value: Byte) {
ptr[offset] = value
}

actual fun get(dst: ByteArray, srcOffset: Long, dstOffset: Long, length: Long) {
checkBounds(srcOffset, length)

dst.usePinned {
memcpy(it.addressOf(dstOffset.toInt()), ptr + srcOffset, length.convert())
}
}

actual fun set(src: ByteArray, srcOffset: Long, dstOffset: Long, length: Long) {
checkBounds(dstOffset, length)

src.usePinned {
memcpy(ptr + dstOffset, it.addressOf(srcOffset.toInt()), length.convert())
}
}

actual fun copyTo(dst: DirectMemory, srcOffset: Long, dstOffset: Long, length: Long) {
checkBounds(srcOffset, length)
dst.checkBounds(dstOffset, length)

memcpy(dst.ptr + dstOffset, ptr + srcOffset, length.convert())
}

actual fun slice(offset: Long, length: Long): DirectMemory {
checkBounds(offset, length)

return DirectMemory((ptr + offset)!!, length)
}

fun asCPointer(): CPointer<ByteVar> {
return ptr
}
}
12 changes: 12 additions & 0 deletions kgl-core/src/nativeMain/kotlin/com/kgl/core/MemUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.kgl.core

import kotlinx.cinterop.addressOf
import kotlinx.cinterop.usePinned

actual inline fun <T> withMemory(length: Long, block: (DirectMemory) -> T): T {
val array = ByteArray(length.toInt())
return array.usePinned {
val buffer = DirectMemory(it.addressOf(0), length)
block(buffer)
}
}
2 changes: 1 addition & 1 deletion kgl-glfw/src/commonMain/kotlin/com/kgl/glfw/Cursor.kt
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
*/
package com.kgl.glfw

import io.ktor.utils.io.core.Closeable
import com.kgl.core.Closeable

expect class Cursor : Closeable {
constructor(image: Image, xhot: Int, yhot: Int)
5 changes: 2 additions & 3 deletions kgl-glfw/src/commonMain/kotlin/com/kgl/glfw/Image.kt
Original file line number Diff line number Diff line change
@@ -15,7 +15,6 @@
*/
package com.kgl.glfw

import io.ktor.utils.io.bits.Memory
import io.ktor.utils.io.core.ExperimentalIoApi
import com.kgl.core.DirectMemory

data class Image @ExperimentalIoApi constructor(val pixels: Memory, val width: Int, val height: Int)
data class Image(val pixels: DirectMemory, val width: Int, val height: Int)
2 changes: 1 addition & 1 deletion kgl-glfw/src/commonMain/kotlin/com/kgl/glfw/Window.kt
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
*/
package com.kgl.glfw

import io.ktor.utils.io.core.Closeable
import com.kgl.core.Closeable

expect class Window : Closeable {
var position: Pair<Int, Int>
Loading