Во первых, линкуем шейдерные программы сразу

This commit is contained in:
DBotThePony 2023-02-20 14:42:45 +07:00
parent 791e57cb0f
commit b85b90f74c
Signed by: DBot
GPG Key ID: DCC23B5715498507
7 changed files with 31 additions and 93 deletions

View File

@ -8,7 +8,7 @@ import ru.dbotthepony.kstarbound.client.freetype.FreeType
import ru.dbotthepony.kstarbound.client.freetype.InvalidArgumentException import ru.dbotthepony.kstarbound.client.freetype.InvalidArgumentException
import ru.dbotthepony.kstarbound.client.gl.program.GLPrograms import ru.dbotthepony.kstarbound.client.gl.program.GLPrograms
import ru.dbotthepony.kstarbound.client.gl.shader.GLShader import ru.dbotthepony.kstarbound.client.gl.shader.GLShader
import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram
import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableColorableProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableColorableProgram
import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableProgram
import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList
@ -533,11 +533,8 @@ class GLStateTracker(val locator: ISBFileLocator) {
fun use(obj: GLShaderProgram): GLShaderProgram { fun use(obj: GLShaderProgram): GLShaderProgram {
ensureSameThread() ensureSameThread()
if (obj == program) { if (obj === program)
return obj return obj
}
check(obj.linked) { "Program is not linked!" }
program = obj program = obj
glUseProgram(obj.pointer) glUseProgram(obj.pointer)

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.kstarbound.client.gl.program
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.client.gl.shader.GLShader import ru.dbotthepony.kstarbound.client.gl.shader.GLShader
import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram
private fun loadShaders( private fun loadShaders(
vertex: Collection<String>, vertex: Collection<String>,

View File

@ -4,6 +4,7 @@ import ru.dbotthepony.kstarbound.client.gl.BlendFunc
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.client.gl.GLType import ru.dbotthepony.kstarbound.client.gl.GLType
import ru.dbotthepony.kstarbound.client.gl.shader.GLShader import ru.dbotthepony.kstarbound.client.gl.shader.GLShader
import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram
import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableColorableProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableColorableProgram
import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList
import ru.dbotthepony.kstarbound.client.gl.vertex.StreamVertexBuilder import ru.dbotthepony.kstarbound.client.gl.vertex.StreamVertexBuilder
@ -36,19 +37,11 @@ private class SimpleProgram<T : GLShaderProgram>(private val name: String, priva
vertex.unlink() vertex.unlink()
fragment.unlink() fragment.unlink()
if (!newValue.linked) {
newValue.link()
}
return newValue return newValue
} }
} }
class GLLiquidProgram(state: GLStateTracker) : GLInternalProgram(state, "liquid") { class GLLiquidProgram(state: GLStateTracker) : GLInternalProgram(state, "liquid") {
init {
link()
}
val baselineColor = this["baselineColor"]!! val baselineColor = this["baselineColor"]!!
val transform = this["transform"]!! val transform = this["transform"]!!
@ -62,10 +55,6 @@ class GLLiquidProgram(state: GLStateTracker) : GLInternalProgram(state, "liquid"
} }
class GLLightProgram(state: GLStateTracker) : GLInternalProgram(state, "light") { class GLLightProgram(state: GLStateTracker) : GLInternalProgram(state, "light") {
init {
link()
}
val baselineColor = this["baselineColor"]!! val baselineColor = this["baselineColor"]!!
val transform = this["transform"]!! val transform = this["transform"]!!
@ -79,10 +68,6 @@ class GLLightProgram(state: GLStateTracker) : GLInternalProgram(state, "light")
} }
class GLHardLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(state, listOf("hard_light_geometry"), listOf("hard_light_geometry"), listOf("hard_light_geometry")) { class GLHardLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(state, listOf("hard_light_geometry"), listOf("hard_light_geometry"), listOf("hard_light_geometry")) {
init {
link()
}
val transform = this["transform"]!! val transform = this["transform"]!!
val localToWorldTransform = this["localToWorldTransform"]!! val localToWorldTransform = this["localToWorldTransform"]!!
val lightPosition = this["lightPosition"]!! val lightPosition = this["lightPosition"]!!
@ -94,10 +79,6 @@ class GLHardLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(stat
} }
class GLSoftLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(state, listOf("soft_light_geometry2"), listOf("soft_light_geometry2")) { class GLSoftLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(state, listOf("soft_light_geometry2"), listOf("soft_light_geometry2")) {
init {
link()
}
val transform = this["transform"]!! val transform = this["transform"]!!
val lightPenetration = this["lightPenetration"]!! val lightPenetration = this["lightPenetration"]!!
val localToWorldTransform = this["localToWorldTransform"]!! val localToWorldTransform = this["localToWorldTransform"]!!
@ -113,10 +94,6 @@ class GLSoftLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(stat
} }
class GLColorQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "screen_quad") { class GLColorQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "screen_quad") {
init {
link()
}
val color = this["color"]!! val color = this["color"]!!
private val builder by lazy { private val builder by lazy {
@ -163,10 +140,6 @@ class GLColorQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "scre
} }
class GLTextureQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "screen_quad_tex") { class GLTextureQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "screen_quad_tex") {
init {
link()
}
val texture = this["texture0"]!! val texture = this["texture0"]!!
private val builder by lazy { private val builder by lazy {
@ -191,10 +164,6 @@ class GLTextureQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "sc
} }
class GLTextureBlurredQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "screen_quad_tex_blur") { class GLTextureBlurredQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "screen_quad_tex_blur") {
init {
link()
}
val texture = this["texture0"]!! val texture = this["texture0"]!!
private val builder by lazy { private val builder by lazy {
@ -229,10 +198,6 @@ class GLFlatProgram(state: GLStateTracker, vararg shaders: GLShader) : GLTransfo
} }
class GLFlatColorProgram(state: GLStateTracker) : GLInternalProgram(state, "flat_color") { class GLFlatColorProgram(state: GLStateTracker) : GLInternalProgram(state, "flat_color") {
init {
link()
}
val transform = this["transform"]!! val transform = this["transform"]!!
val builder by lazy { val builder by lazy {

View File

@ -1,9 +1,10 @@
package ru.dbotthepony.kstarbound.client.gl.program package ru.dbotthepony.kstarbound.client.gl.shader
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
import org.lwjgl.opengl.GL46.* import org.lwjgl.opengl.GL46.*
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import ru.dbotthepony.kstarbound.client.gl.shader.GLShader import ru.dbotthepony.kstarbound.client.gl.shader.GLShader
import ru.dbotthepony.kstarbound.client.gl.shader.GLUniformLocation import ru.dbotthepony.kstarbound.client.gl.shader.GLUniformLocation
import ru.dbotthepony.kstarbound.client.gl.shader.ShaderLinkException import ru.dbotthepony.kstarbound.client.gl.shader.ShaderLinkException
@ -11,19 +12,37 @@ import ru.dbotthepony.kvector.api.IFloatMatrix
import ru.dbotthepony.kvector.api.IStruct3f import ru.dbotthepony.kvector.api.IStruct3f
import ru.dbotthepony.kvector.api.IStruct4f import ru.dbotthepony.kvector.api.IStruct4f
import java.util.* import java.util.*
import java.util.stream.Stream
import kotlin.collections.HashSet import kotlin.collections.HashSet
open class GLShaderProgram(val state: GLStateTracker, vararg shaders: GLShader) { open class GLShaderProgram(val state: GLStateTracker, shaders: Stream<GLShader>) {
constructor(state: GLStateTracker, shaders: Collection<GLShader>) : this(state, shaders.stream())
constructor(state: GLStateTracker, vararg shaders: GLShader) : this(state, Arrays.stream(shaders))
init { init {
state.ensureSameThread() state.ensureSameThread()
} }
val pointer = glCreateProgram() val pointer = glCreateProgram()
var linked = false
private set
private val attached = HashSet<GLShader>() init {
val access = object : Collection<GLShader> by attached {} checkForGLError()
for (shader in shaders) {
glAttachShader(pointer, shader.pointer)
}
glLinkProgram(pointer)
val success = intArrayOf(0)
glGetProgramiv(pointer, GL_LINK_STATUS, success)
if (success[0] == 0) {
throw ShaderLinkException(glGetProgramInfoLog(pointer))
}
glGetError()
}
private val locationCache = Object2ObjectOpenHashMap<String, Optional<GLUniformLocation>>() private val locationCache = Object2ObjectOpenHashMap<String, Optional<GLUniformLocation>>()
@ -37,7 +56,6 @@ open class GLShaderProgram(val state: GLStateTracker, vararg shaders: GLShader)
*/ */
operator fun get(name: String): GLUniformLocation? { operator fun get(name: String): GLUniformLocation? {
state.ensureSameThread() state.ensureSameThread()
check(linked) { "Shader program is not linked!" }
return locationCache.computeIfAbsent(name, Object2ObjectFunction { return locationCache.computeIfAbsent(name, Object2ObjectFunction {
val location = glGetUniformLocation(pointer, name) val location = glGetUniformLocation(pointer, name)
@ -54,42 +72,5 @@ open class GLShaderProgram(val state: GLStateTracker, vararg shaders: GLShader)
operator fun set(name: String, value: Int) = this[name]?.set(value) operator fun set(name: String, value: Int) = this[name]?.set(value)
operator fun set(name: String, value: IFloatMatrix<*>) = this[name]?.set(value) operator fun set(name: String, value: IFloatMatrix<*>) = this[name]?.set(value)
fun attach(shader: GLShader) {
state.ensureSameThread()
check(!linked) { "Program is already linked!" }
if (!attached.add(shader)) {
throw IllegalStateException("Already attached! $shader")
}
require(!shader.unlinked) { "$shader is already unlinked, and thus can not be used" }
glAttachShader(pointer, shader.pointer)
}
fun link() {
check(!linked) { "Program is already linked!" }
state.ensureSameThread()
glLinkProgram(pointer)
val success = intArrayOf(0)
glGetProgramiv(pointer, GL_LINK_STATUS, success)
if (success[0] == 0) {
throw ShaderLinkException(glGetProgramInfoLog(pointer))
}
glGetError()
linked = true
}
fun use() = state.use(this) fun use() = state.use(this)
fun unlinkChildren() {
attached.forEach(GLShader::unlink)
}
init {
shaders.forEach(this::attach)
}
} }

View File

@ -1,17 +1,12 @@
package ru.dbotthepony.kstarbound.client.gl.shader package ru.dbotthepony.kstarbound.client.gl.shader
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram
import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f
open class GLTransformableProgram(state: GLStateTracker, vararg shaders: GLShader) : GLShaderProgram(state, *shaders) { open class GLTransformableProgram(state: GLStateTracker, vararg shaders: GLShader) : GLShaderProgram(state, *shaders) {
init {
link()
}
val transform = this["_transform"]!! val transform = this["_transform"]!!
init { init {
transform.set(Matrix4f.IDENTITY) transform.set(Matrix4f.IDENTITY)
} }
} }

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.kstarbound.client.gl.shader
import org.lwjgl.opengl.GL41.* import org.lwjgl.opengl.GL41.*
import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram
import ru.dbotthepony.kvector.api.IFloatMatrix import ru.dbotthepony.kvector.api.IFloatMatrix
import ru.dbotthepony.kvector.api.IStruct2f import ru.dbotthepony.kvector.api.IStruct2f
import ru.dbotthepony.kvector.api.IStruct3f import ru.dbotthepony.kvector.api.IStruct3f

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.kstarbound.client.render package ru.dbotthepony.kstarbound.client.render
import org.lwjgl.opengl.GL46.* import org.lwjgl.opengl.GL46.*
import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram
import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject
import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder