@@ -24,7 +24,7 @@ import org.lwjgl.opengl.GL30C.*
2424import org.lwjgl.opengl.GL44.glBufferStorage
2525import java.nio.ByteBuffer
2626
27- interface IBuffer {
27+ abstract class IBuffer (
2828 /* *
2929 * Specifies how many buffer must be used
3030 *
@@ -40,8 +40,13 @@ interface IBuffer {
4040 *
4141 * Triple buffering helps maintain smoother frame rates, but if your app runs faster than the monitor's refresh rate, it offers little benefit as you eventually still wait for vblank synchronization.
4242 */
43- val buffers: Int
43+ val buffers : Int = 1 ,
4444
45+ /* *
46+ * Edge case to handle vertex arrays
47+ */
48+ val isVertexArray : Boolean = false ,
49+ ) {
4550 /* *
4651 * Specifies how the buffers are used
4752 *
@@ -57,7 +62,7 @@ interface IBuffer {
5762 * | GL_DYNAMIC_READ | Data is modified repeatedly and used many times for reading. |
5863 * | GL_DYNAMIC_COPY | Data is modified repeatedly and used many times for copying. |
5964 */
60- val usage: Int
65+ abstract val usage: Int
6166
6267 /* *
6368 * Specifies the target to which the buffer object is bound which must be one
@@ -80,7 +85,7 @@ interface IBuffer {
8085 * | GL_TRANSFORM_FEEDBACK_BUFFER | Transform feedback buffer |
8186 * | GL_UNIFORM_BUFFER | Uniform block storage |
8287 */
83- val target: Int
88+ abstract val target: Int
8489
8590 /* *
8691 * Specifies a combination of access flags indicating the desired
@@ -97,22 +102,22 @@ interface IBuffer {
97102 * | GL_MAP_FLUSH_EXPLICIT_BIT | Requires explicit flushing of modified sub-ranges. | Only with GL_MAP_WRITE_BIT. Data may be undefined if skipped. |
98103 * | GL_MAP_UNSYNCHRONIZED_BIT | Skips synchronization before mapping. | May cause data corruption if regions overlap. |
99104 */
100- val access: Int
105+ abstract val access: Int
101106
102107 /* *
103108 * Index of the current buffer
104109 */
105- var index: Int
110+ var index: Int = 0 ; private set
106111
107112 /* *
108113 * List of all the buffers
109114 */
110- val bufferIds: IntArray
115+ private val bufferIds = IntArray (buffers)
111116
112117 /* *
113118 * Binds the buffer id to the [target]
114119 */
115- fun bind (id : Int ) = glBindBuffer(target, id)
120+ open fun bind (id : Int ) = glBindBuffer(target, id)
116121
117122 /* *
118123 * Binds current the buffer [index] to the [target]
@@ -130,7 +135,7 @@ interface IBuffer {
130135 * Update the current buffer without re-allocating
131136 * Alternative to [map]
132137 */
133- fun update (
138+ open fun update (
134139 data : ByteBuffer ,
135140 offset : Long ,
136141 ): Throwable ? {
@@ -151,15 +156,19 @@ interface IBuffer {
151156 *
152157 * @param data The data to put in the new allocated buffer
153158 */
154- fun allocate (data : ByteBuffer ): Throwable ? {
159+ open fun allocate (data : ByteBuffer ): Throwable ? {
155160 if (! bufferValid(target, access))
156161 return IllegalArgumentException (" Target is not valid. Refer to the table in the documentation" )
157162
158163 if (! bufferUsageValid(usage))
159164 return IllegalArgumentException (" Buffer usage is invalid" )
160165
161- bind()
162- glBufferData(target, data, usage)
166+ repeat(buffers) {
167+ bind()
168+ glBufferData(target, data, usage)
169+ swap()
170+ }
171+
163172 bind(0 )
164173
165174 return null
@@ -171,15 +180,19 @@ interface IBuffer {
171180 *
172181 * @param size The size of the new buffer
173182 */
174- fun allocate (size : Long ): Throwable ? {
183+ open fun allocate (size : Long ): Throwable ? {
175184 if (! bufferValid(target, access))
176185 return IllegalArgumentException (" Target is not valid. Refer to the table in the documentation" )
177186
178187 if (! bufferUsageValid(usage))
179188 return IllegalArgumentException (" Buffer usage is invalid" )
180189
181- bind()
182- glBufferData(target, size.coerceAtLeast(0 ), usage)
190+ repeat(buffers) {
191+ bind()
192+ glBufferData(target, size.coerceAtLeast(0 ), usage)
193+ swap()
194+ }
195+
183196 bind(0 )
184197
185198 return null
@@ -190,15 +203,19 @@ interface IBuffer {
190203 * This function cannot be called twice for the same buffer
191204 * This function handles the buffer binding
192205 */
193- fun storage (data : ByteBuffer ): Throwable ? {
206+ open fun storage (data : ByteBuffer ): Throwable ? {
194207 if (! bufferValid(target, access))
195208 return IllegalArgumentException (" Target is not valid. Refer to the table in the documentation" )
196209
197210 if (! bufferUsageValid(usage))
198211 return IllegalArgumentException (" Buffer usage is invalid" )
199212
200- bind()
201- glBufferStorage(target, data, usage)
213+ repeat(buffers) {
214+ bind()
215+ glBufferStorage(target, data, usage)
216+ swap()
217+ }
218+
202219 bind(0 )
203220
204221 return null
@@ -211,15 +228,19 @@ interface IBuffer {
211228 *
212229 * @param size The size of the storage buffer
213230 */
214- fun storage (size : Long ): Throwable ? {
231+ open fun storage (size : Long ): Throwable ? {
215232 if (! bufferValid(target, access))
216233 return IllegalArgumentException (" Target is not valid. Refer to the table in the documentation" )
217234
218235 if (! bufferUsageValid(usage))
219236 return IllegalArgumentException (" Buffer usage is invalid" )
220237
221- bind()
222- glBufferStorage(target, size.coerceAtLeast(0 ), usage)
238+ repeat(buffers) {
239+ bind()
240+ glBufferStorage(target, size.coerceAtLeast(0 ), usage)
241+ swap()
242+ }
243+
223244 bind(0 )
224245
225246 return null
@@ -228,14 +249,14 @@ interface IBuffer {
228249 /* *
229250 * Maps all or part of a buffer object's data store into the client's address space
230251 *
231- * @param offset Specifies the starting offset within the buffer of the range to be mapped.
232252 * @param size Specifies the length of the range to be mapped.
253+ * @param offset Specifies the starting offset within the buffer of the range to be mapped.
233254 * @param block Lambda scope with the mapped buffer passed in
234255 * @return Error encountered during the mapping process
235256 */
236- fun map (
237- offset : Long ,
257+ open fun map (
238258 size : Long ,
259+ offset : Long ,
239260 block : (ByteBuffer ) -> Unit
240261 ): Throwable ? {
241262 if (
@@ -251,7 +272,7 @@ interface IBuffer {
251272
252273 if (
253274 offset + size > glGetBufferParameteri(target, GL_BUFFER_SIZE )
254- ) return IllegalArgumentException (" Out of bound mapping: $offset + $size > ${glGetBufferParameteri(target, GL_BUFFER_SIZE )} " )
275+ ) return IllegalArgumentException (" Out of bound (is the buffer initialized?) $size + $offset > ${glGetBufferParameteri(target, GL_BUFFER_SIZE )} " )
255276
256277 if (
257278 glGetBufferParameteri(target, GL_BUFFER_MAPPED )
@@ -292,7 +313,7 @@ interface IBuffer {
292313 * @param offset The starting offset within the buffer of the range to be mapped
293314 * @return Error encountered during the mapping process
294315 */
295- fun upload (data : ByteArray , offset : Long ): Throwable ? =
316+ open fun upload (data : ByteArray , offset : Long ): Throwable ? =
296317 upload(ByteBuffer .wrap(data), offset)
297318
298319 /* *
@@ -302,5 +323,13 @@ interface IBuffer {
302323 * @param offset The starting offset within the buffer of the range to be mapped
303324 * @return Error encountered during the mapping process
304325 */
305- fun upload (data : ByteBuffer , offset : Long ): Throwable ?
326+ abstract fun upload (data : ByteBuffer , offset : Long ): Throwable ?
327+
328+ init {
329+ // Special edge case for vertex arrays
330+ check(buffers > 0 ) { " Cannot generate less than one buffer" }
331+
332+ if (isVertexArray) glGenVertexArrays(bufferIds) // If there are more than 1 buffer you should expect undefined behavior, this is not the way to do it
333+ else glGenBuffers(bufferIds)
334+ }
306335}
0 commit comments