commonMain.ru.casperix.opengl.renderer.impl.GraphicDataProvider.kt Maven / Gradle / Ivy
package ru.casperix.opengl.renderer.impl
import ru.casperix.renderer.vector.Geometry
import ru.casperix.renderer.vector.VectorGraphic
import ru.casperix.renderer.vector.vertex.VertexAttributes
import ru.casperix.opengl.renderer.*
@ExperimentalUnsignedTypes
class GraphicDataProvider(val stateController: StateController, val config: OpenGlRendererConfig) {
private val staticConfig = config.cacheConfig.staticConfig
private val shaderProvider = ShaderProvider(config)
/**
* Many elements small and have equal vertex-attributes...
*/
private val cacheDynamicBuffer = mutableMapOf()
/**
* Big geometry is expensive for upload... But have chance that not changed.
*/
private val cacheStaticGeometry = mutableMapOf()
private var cachedIndices = 0
fun getDynamicBufferAmount(): Int {
return cacheDynamicBuffer.size
}
fun getStaticBufferAmount(): Int {
return cacheStaticGeometry.size
}
fun get(stateController: StateController, graphic: VectorGraphic, frameIndex: Long): DeviceGraphicData? {
val geometry = graphic.geometry
val vertices = geometry.vertices
if (vertices.size == 0) {
return null
}
val indices = geometry.indices
if (indices.isEmpty()) {
return null
}
val vertexAttributes = vertices.attributes
val isStatic = staticConfig.using && indices.size >= staticConfig.itemMinIndices
if (isStatic) {
val buffer = cacheStaticGeometry.getOrPut((geometry)) {
val geometryData = createDeviceGeometryData(vertexAttributes)
geometryData.uploadData(stateController, vertices.data, indices, true)
cachedIndices += geometryData.indicesAmount
DeviceGeometryBuffer(geometryData, true)
}
buffer.lastFrame = frameIndex
clearDeprecatedCache(frameIndex)
return createDeviceGraphicData(graphic, buffer)
} else {
val buffer = cacheDynamicBuffer.getOrPut(vertexAttributes) {
DeviceGeometryBuffer(createDeviceGeometryData(vertexAttributes), false)
}
return createDeviceGraphicData(graphic, buffer)
}
}
private fun clearDeprecatedCache(frameIndex: Long) {
if (cachedIndices <= staticConfig.summaryIndicesMax) return
val deprecated = cacheStaticGeometry.entries.filter { it.value.lastFrame < frameIndex - 1 }
deprecated.forEach { (key, buffer) ->
buffer.dispose()
cacheStaticGeometry.remove(key)
cachedIndices -= buffer.data.indicesAmount
if (cachedIndices <= staticConfig.summaryIndicesMin) return
}
}
private fun createDeviceGeometryData(vertexAttributes: VertexAttributes): DeviceGeometryData {
stateController.setGeometry(null)
return DeviceGeometryData(vertexAttributes)
}
private fun createDeviceGraphicData(graphic: VectorGraphic, buffer: DeviceGeometryBuffer): DeviceGraphicData {
val shader = shaderProvider.getOrCreate(buffer.data.attributes, graphic.material)
return DeviceGraphicData(graphic, shader, buffer)
}
}