Files
orx/openrndr-demos/src/demo/kotlin/DemoComputeStyle02.kt
2025-09-01 20:40:06 +02:00

83 lines
3.0 KiB
Kotlin

import org.openrndr.application
import org.openrndr.draw.*
import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
/**
* A program identical to compute01.kt, except that the order of variables
* `age` and `pos` have been swapped, resulting in a less ideal memory layout.
* In this case the SSBO requires 192 bytes instead of 112, and padding is
* inserted after the variables `time`, `age` and `pos`.
*
* Output: byteBuffer -> text
*/
fun main() = application {
program {
// Define SSBO format
val fmt = shaderStorageFormat {
primitive("time", BufferPrimitiveType.FLOAT32)
primitive("vertex", BufferPrimitiveType.VECTOR2_FLOAT32, 3)
struct("Particle", "particles", 5) {
primitive("age", BufferPrimitiveType.FLOAT32)
primitive("pos", BufferPrimitiveType.VECTOR3_FLOAT32)
}
}
println("Study the padding in the format:\n$fmt\n")
// Create SSBO
val ssbo = shaderStorageBuffer(fmt)
// Populate SSBO
ssbo.put {
write(3.0.toFloat()) // time
repeat(3) {
write(Vector2(1.1, 1.2)) // vertex
}
repeat(5) {
write(1.0.toFloat()) // age
write(Vector3(2.1, 2.2, 2.3))// pos
}
}
// Create Compute Shader
val cs = computeStyle {
computeTransform = """
b_myData.time = 3.3;
b_myData.vertex[0] = vec2(7.01);
b_myData.vertex[1] = vec2(7.02);
b_myData.vertex[2] = vec2(7.03);
b_myData.particles[0].pos = vec3(112.0);
b_myData.particles[0].age = 111.0;
""".trimIndent()
}
cs.buffer("myData", ssbo)
// Download SSBO data to CPU
val byteBufferBeforeExecute = ssbo.createByteBuffer()
byteBufferBeforeExecute.rewind()
ssbo.read(byteBufferBeforeExecute)
// Execute compute shader
cs.execute(1, 1, 1)
// Download SSBO data to CPU
val byteBufferAfterExecute = ssbo.createByteBuffer()
byteBufferAfterExecute.rewind()
ssbo.read(byteBufferAfterExecute)
// Debugging
// Notice the (maybe unexpected) 0.0 padding values printed on the console.
// Depending on the variable size in bytes, padding may be added by the system
// to align them in memory. This will depend on the sizes of the involved variables,
// and their order. For instance, a vec3 and a float do not require padding, but
// a float followed by a vec3 pads the float with 3 values, and the vec3 with one.
// Run compute02.kt and study the output to observe a more inefficient layout.
byteBufferBeforeExecute.rewind()
byteBufferAfterExecute.rewind()
repeat(ssbo.format.size / 4) {
println("$it: ${byteBufferBeforeExecute.float} -> ${byteBufferAfterExecute.float}")
}
}
}