kool icon indicating copy to clipboard operation
kool copied to clipboard

java.nio.BufferOverflowException or indeces ignoring

Open andrey-zakharov opened this issue 3 years ago • 2 comments

I've suddenly faced to

Exception in thread "main" java.nio.BufferOverflowException
	at java.base/java.nio.Buffer.nextPutIndex(Buffer.java:730)
	at java.base/java.nio.DirectByteBuffer.putFloat(DirectByteBuffer.java:916)
	at de.fabmax.kool.util.MixedBufferImpl.putFloat32(Buffer.kt:289)
	at de.fabmax.kool.util.MixedBuffer$DefaultImpls.putFloat32(Buffer.kt:169)
	at de.fabmax.kool.util.MixedBufferImpl.putFloat32(Buffer.kt:190)
	at de.fabmax.kool.pipeline.Uniform2fv.putToBuffer(Uniform.kt:106)
	at de.fabmax.kool.pipeline.BufferLayout.putToBuffer(BufferLayout.kt:22)
	at de.fabmax.kool.platform.gl.MappedUbo.setUniform(MappedUniform.kt:50)
	at de.fabmax.kool.platform.gl.CompiledShader$ShaderInstance.bindInstance(CompiledShader.kt:280)
	at de.fabmax.kool.platform.gl.CompiledShader.bindInstance(CompiledShader.kt:134)
	at de.fabmax.kool.platform.gl.ShaderManager.setupShader(ShaderManager.kt:23)
	at de.fabmax.kool.platform.gl.QueueRendererGl.renderQueue(QueueRendererGl.kt:64)
	at de.fabmax.kool.platform.gl.GlRenderBackend.drawFrame(GlRenderBackend.kt:116)
	at de.fabmax.kool.platform.Lwjgl3Context.run(Lwjgl3Context.kt:124)
	at App.<init>(App.kt:35)
	at MainKt.main(main.kt:5)
	at MainKt.main(main.kt)

and looks like here https://github.com/fabmax/kool/blob/f7e6d2e9bc8f9b936a0f1f120d08af67c8b4ad43/kool-core/src/jvmMain/kotlin/de/fabmax/kool/platform/gl/CompiledShader.kt#L83

    private fun setupUboLayout(desc: UniformBuffer, blockIndex: Int) {
        val blockSize = glGetActiveUniformBlocki(prog, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE)
        val indices = IntArray(desc.uniforms.size)
        val offsets = IntArray(desc.uniforms.size)

        MemoryStack.stackPush().use { stack ->
            val uniformNames = desc.uniforms.map {
                if (it.length > 1) { MemoryUtil.memASCII("${it.name}[0]") } else { MemoryUtil.memASCII(it.name) }
            }.toTypedArray()
            val namePointers = stack.pointers(*uniformNames)
            glGetUniformIndices(prog, namePointers, indices)
            glGetActiveUniformsiv(prog, indices, GL_UNIFORM_OFFSET, offsets)
        }
        glUniformBlockBinding(prog, blockIndex, desc.binding)
        uboLayouts[desc.name] = ExternalBufferLayout(desc.uniforms, offsets, blockSize)
    }

(and in WebGL version too) indiced only used by gl call, and offsets is still in indices order? For example, if we have

indices = {int[2]@3664} [1, 0]
 0 = 1
 1 = 0

and offsets like

offsets = {int[2]@3665} [0, 64]
 0 = 0
 1 = 64

and uniforms like

desc.uniforms = {ArrayList@4006}  size = 2
 0 = {UniformMat4f@4008} uMvpMat
  value = {Mat4f@4013} de.fabmax.kool.math.Mat4f@24b52d3e
  name = "uMvpMat"
  size = 64
  length = 1
  isArray {boolean} 
 1 = {Uniform2fv@4009} roots
  value = {MutableVec2f[3]@4012} 
  name = "roots"
  size = 48
  length = 3
  isArray {boolean} 

it would brake??? Or i'm missing something? Please, help! :+1:

andrey-zakharov avatar Jul 08 '22 13:07 andrey-zakharov

The problem is the Vec2 array uniform. When the Uniform2fv puts the values to the buffer it expects the buffer to be in Std140 layout, meaning that the individual Vec2f values are padded with 8 additional 0-bytes. However, apparently OpenGL expects the values to be tightly packed, therefore the created buffer is too small to take the values including padding, resulting in the BufferOverflow.

I should probably fix that... Until then, as a workaround, you should be able to use a Vec4 array uniform and only use the xy values of the Vec4s.

fabmax avatar Jul 09 '22 19:07 fabmax

Not thoroughly tested, but I pushed a commit, which should fix that

fabmax avatar Jul 12 '22 20:07 fabmax