OpenDlssNrNative.kt
src/jvmMain/kotlin/afield/graphics/render/neural/OpenDlssNrNative.kt · 50 lines
@file:afield.runtime.completion.CompletionCategory("Internal")
package afield.graphics.render.neural
import java.lang.foreign.*
import java.lang.foreign.ValueLayout.*
import java.lang.invoke.MethodHandle
import java.nio.file.Path
import kotlin.io.path.*
internal class OpenDlssNrNative(path: Path)
internal class OpenDlssNrNative(path: Path) {
private val lookup=SymbolLookup.libraryLookup(path,Arena.global())
private fun bind(name: String,result: MemoryLayout?,vararg args: MemoryLayout): MethodHandle =
Linker.nativeLinker().downcallHandle(lookup.find("f4nr_$name").orElseThrow(),
if(result==null)FunctionDescriptor.ofVoid(*args) else FunctionDescriptor.of(result,*args))
val probe=bind("probe",JAVA_INT,JAVA_LONG,JAVA_LONG,ADDRESS)
val apply=bind("apply",JAVA_INT,ADDRESS,JAVA_LONG)
val planClose=bind("plan_close",null,ADDRESS)
val create
val create=bind("create",JAVA_INT,JAVA_LONG,JAVA_LONG,JAVA_LONG,JAVA_INT,ADDRESS,ADDRESS,ADDRESS,ADDRESS)
val record=bind("record",JAVA_INT,ADDRESS,JAVA_LONG,ADDRESS)
val destroy=bind("destroy",JAVA_INT,ADDRESS)
val headBuffer=bind("head_buffer",JAVA_LONG,ADDRESS)
val allocatedBytes=bind("allocated_bytes",JAVA_LONG,ADDRESS)
val paddedWidth=bind("padded_width",JAVA_INT,ADDRESS)
private val error=bind("error",ADDRESS)
private val extensions=bind("extensions",ADDRESS)
init
init {
check(bind("abi",JAVA_INT).invokeWithArguments()==2 && bind("image_size",JAVA_INT).invokeWithArguments()==32 &&
bind("controls_size",JAVA_INT).invokeWithArguments()==64) { "Incompatible NR adapter; run buildOpenDlssNrNative" }
}
fun check(code: Any?)
fun check(code: Any?) {check(code==0) { (error.invokeWithArguments() as MemorySegment).reinterpret(4096).getString(0) }}
fun required(): Set<String>
fun required(): Set<String> =(extensions.invokeWithArguments() as MemorySegment).reinterpret(4096).getString(0).lineSequence().filter { it.isNotBlank() }.toSet()
companion object
internal fun root(): Path
internal fun root(): Path = Path.of(System.getProperty("afield.opendlssnr.root", "build/native/field-opendlssnr")).toAbsolutePath()
internal const val ABSENT="Optional NR adapter absent; run ./gradlew buildOpenDlssNr"
internal fun libraryPath(): Path
internal fun libraryPath(): Path=Path.of(System.getenv("FIELD_OPEN_DLSS_NR_LIBRARY") ?: root().resolve("libfield_opendlssnr.so").toString())
private var cached: Result<OpenDlssNrNative>?=null
val loaded: Result<OpenDlssNrNative> get()
The loaded adapter. A missing-library failure is retried once the library appears, so building it while Field runs takes effect at the next device creation (a renderer restart).
val loaded: Result<OpenDlssNrNative> get()=synchronized(this) {
cached?.takeUnless { it.exceptionOrNull()?.message==ABSENT && libraryPath().isRegularFile() } ?: runCatching {
check(System.getProperty("os.name").lowercase().contains("linux") && System.getProperty("os.arch") in setOf("amd64","x86_64")) { "NR adapter supports Linux x86_64" }
check(System.getenv("FIELD_OPEN_DLSS_NR_DISABLE")!="1" && !java.lang.Boolean.getBoolean("afield.opendlssnr.disabled")) { "NR explicitly disabled" }
val path=libraryPath()
check(path.isRegularFile()) { ABSENT }
OpenDlssNrNative(path)
}.also { cached=it }
}
}
}