TextureSampler.kt
src/jvmMain/kotlin/afield/graphics/texture/TextureSampler.kt · 75 lines
TextureSampler wraps a VkSampler: filtering, mipmap mode, anisotropy and per-axis address modes for sampling a texture in a shader.
package afield.graphics.texture
import org.lwjgl.system.MemoryStack
import org.lwjgl.vulkan.VK10
import org.lwjgl.vulkan.VK10.vkCreateSampler
import org.lwjgl.vulkan.VkSamplerCreateInfo
import afield.graphics.vulkan.Renderer
import afield.document.context.fromContext
import afield.graphics.vulkan.util.AutoDisposer
import afield.graphics.vulkan.util.vkCheck
import kotlin.math.max
class TextureSampler
class TextureSampler(
val renderer: Renderer = fromContext(null),
mipLevels: Int,
anisotropyEnable: Boolean,
filter: Int = VK10.VK_FILTER_LINEAR,
mipmapMode: Int = if (filter == VK10.VK_FILTER_LINEAR) VK10.VK_SAMPLER_MIPMAP_MODE_LINEAR else VK10.VK_SAMPLER_MIPMAP_MODE_NEAREST,
addressModeU: Int = VK10.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
addressModeV: Int = VK10.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
addressModeW: Int = VK10.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
) {
var vkSampler: Long = 0
private val autoDisposeToken = AutoDisposer.register(this, "TextureSampler(mips=$mipLevels)", owner = renderer.device) { /* set after init */ }
init
init {
println(" making sampler")
MemoryStack.stackPush().use { stack ->
val samplerInfo = VkSamplerCreateInfo.calloc(stack)
.sType(VK10.VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO)
.magFilter(filter)
.minFilter(filter)
.addressModeU(addressModeU)
.addressModeV(addressModeV)
.addressModeW(addressModeW)
.borderColor(VK10.VK_BORDER_COLOR_INT_OPAQUE_BLACK)
.unnormalizedCoordinates(false)
.compareEnable(false)
.compareOp(VK10.VK_COMPARE_OP_ALWAYS)
.mipmapMode(mipmapMode)
.minLod(0.0f)
.maxLod(max(0, mipLevels - 1).toFloat())
.mipLodBias(0.0f)
samplerInfo
.anisotropyEnable(false)
// .maxAnisotropy(MAX_ANISOTROPY.toFloat())
val lp = stack.mallocLong(1)
vkCheck(vkCreateSampler(renderer.device.vkDevice, samplerInfo, null, lp), "Failed to create sampler")
vkSampler = lp[0]
}
autoDisposeToken.updateCleanup(snapshotCleanup())
}
fun cleanup()
fun cleanup() {
if (!autoDisposeToken.disable()) return
VK10.vkDestroySampler(renderer.device.vkDevice, vkSampler, null)
}
private fun snapshotCleanup(): () -> Unit {
val dev = renderer.device.vkDevice
val sampler = vkSampler
return { VK10.vkDestroySampler(dev, sampler, null) }
}
companion object
companion object {
private const val MAX_ANISOTROPY = 16
}
}