Skip to content

Commit 113f96a

Browse files
committed
Better use of pbo
1 parent e39ef2a commit 113f96a

File tree

3 files changed

+72
-52
lines changed

3 files changed

+72
-52
lines changed

common/src/main/kotlin/com/lambda/graphics/buffer/Buffer.kt

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,17 @@ abstract class Buffer(
4040
/**
4141
* Specifies how the buffers are used
4242
*
43-
* | Buffer Usage | Description |
44-
* |--------------------------------|-----------------------------------------------------------------|
45-
* | GL_STREAM_DRAW | Data is set once and used a few times for drawing. |
46-
* | GL_STREAM_READ | Data is set once and used a few times for reading. |
47-
* | GL_STREAM_COPY | Data is set once and used a few times for copying. |
48-
* | GL_STATIC_DRAW | Data is set once and used many times for drawing. |
49-
* | GL_STATIC_READ | Data is set once and used many times for reading. |
50-
* | GL_STATIC_COPY | Data is set once and used many times for copying. |
51-
* | GL_DYNAMIC_DRAW | Data is modified repeatedly and used many times for drawing. |
52-
* | GL_DYNAMIC_READ | Data is modified repeatedly and used many times for reading. |
53-
* | GL_DYNAMIC_COPY | Data is modified repeatedly and used many times for copying. |
43+
* | Buffer Usage | Description |
44+
* |----------------------------------|-----------------------------------------------------------------|
45+
* | [GL_STREAM_DRAW] | Data is set once and used a few times for drawing. |
46+
* | [GL_STREAM_READ] | Data is set once and used a few times for reading. |
47+
* | [GL_STREAM_COPY] | Data is set once and used a few times for copying. |
48+
* | [GL_STATIC_DRAW] | Data is set once and used many times for drawing. |
49+
* | [GL_STATIC_READ] | Data is set once and used many times for reading. |
50+
* | [GL_STATIC_COPY] | Data is set once and used many times for copying. |
51+
* | [GL_DYNAMIC_DRAW] | Data is modified repeatedly and used many times for drawing. |
52+
* | [GL_DYNAMIC_READ] | Data is modified repeatedly and used many times for reading. |
53+
* | [GL_DYNAMIC_COPY] | Data is modified repeatedly and used many times for copying. |
5454
*
5555
* @see <a href="https://www.khronos.org/opengl/wiki/Buffer_Object">Buffer object</a>
5656
*/
@@ -60,22 +60,22 @@ abstract class Buffer(
6060
* Specifies the target to which the buffer object is bound which must be one
6161
* of the following:
6262
*
63-
* | Buffer Binding Target | Purpose |
64-
* |-------------------------------|--------------------------------------|
65-
* | GL_ARRAY_BUFFER | Vertex attributes |
66-
* | GL_ATOMIC_COUNTER_BUFFER | Atomic counter storage |
67-
* | GL_COPY_READ_BUFFER | Buffer copy source |
68-
* | GL_COPY_WRITE_BUFFER | Buffer copy destination |
69-
* | GL_DISPATCH_INDIRECT_BUFFER | Indirect compute dispatch commands |
70-
* | GL_DRAW_INDIRECT_BUFFER | Indirect command arguments |
71-
* | GL_ELEMENT_ARRAY_BUFFER | Vertex array indices |
72-
* | GL_PIXEL_PACK_BUFFER | Pixel read target |
73-
* | GL_PIXEL_UNPACK_BUFFER | Texture data source |
74-
* | GL_QUERY_BUFFER | Query result buffer |
75-
* | GL_SHADER_STORAGE_BUFFER | Read-write storage for shaders |
76-
* | GL_TEXTURE_BUFFER | Texture data buffer |
77-
* | GL_TRANSFORM_FEEDBACK_BUFFER | Transform feedback buffer |
78-
* | GL_UNIFORM_BUFFER | Uniform block storage |
63+
* | Buffer Binding Target | Purpose |
64+
* |---------------------------------|--------------------------------------|
65+
* | [GL_ARRAY_BUFFER] | Vertex attributes |
66+
* | [GL_ATOMIC_COUNTER_BUFFER] | Atomic counter storage |
67+
* | [GL_COPY_READ_BUFFER] | Buffer copy source |
68+
* | [GL_COPY_WRITE_BUFFER] | Buffer copy destination |
69+
* | [GL_DISPATCH_INDIRECT_BUFFER] | Indirect compute dispatch commands |
70+
* | [GL_DRAW_INDIRECT_BUFFER] | Indirect command arguments |
71+
* | [GL_ELEMENT_ARRAY_BUFFER] | Vertex array indices |
72+
* | [GL_PIXEL_PACK_BUFFER] | Pixel read target |
73+
* | [GL_PIXEL_UNPACK_BUFFER] | Texture data source |
74+
* | [GL_QUERY_BUFFER] | Query result buffer |
75+
* | [GL_SHADER_STORAGE_BUFFER] | Read-write storage for shaders |
76+
* | [GL_TEXTURE_BUFFER] | Texture data buffer |
77+
* | [GL_TRANSFORM_FEEDBACK_BUFFER] | Transform feedback buffer |
78+
* | [GL_UNIFORM_BUFFER] | Uniform block storage |
7979
*
8080
* @see <a href="https://www.khronos.org/opengl/wiki/Buffer_Object">Buffer object</a>
8181
*/
@@ -85,16 +85,18 @@ abstract class Buffer(
8585
* Specifies a combination of access flags indicating the desired
8686
* access to the mapping range and must contain one or more of the following:
8787
*
88-
* | Flag | Description | Disclaimer |
89-
* |-------------------------------|-----------------------------------------------------|---------------------------------------------------------------|
90-
* | GL_MAP_READ_BIT | Allows reading buffer data. | Undefined if used without this flag. |
91-
* | GL_MAP_WRITE_BIT | Allows modifying buffer data. | Undefined if used without this flag. |
92-
* | GL_MAP_PERSISTENT_BIT | Enables persistent mapping during GL operations. | Requires proper allocation with GL_MAP_PERSISTENT_BIT. |
93-
* | GL_MAP_COHERENT_BIT | Ensures changes are visible without extra steps. | Without this, explicit sync is needed. |
94-
* | GL_MAP_INVALIDATE_RANGE_BIT | Discards previous contents of the mapped range. | Cannot be used with GL_MAP_READ_BIT. |
95-
* | GL_MAP_INVALIDATE_BUFFER_BIT | Discards previous contents of the entire buffer. | Cannot be used with GL_MAP_READ_BIT. |
96-
* | GL_MAP_FLUSH_EXPLICIT_BIT | Requires explicit flushing of modified sub-ranges. | Only with GL_MAP_WRITE_BIT. Data may be undefined if skipped. |
97-
* | GL_MAP_UNSYNCHRONIZED_BIT | Skips synchronization before mapping. | May cause data corruption if regions overlap. |
88+
* | Flag | Description | Information |
89+
* |--------------------------------|-----------------------------------------------------|-------------------------------------------------------------------------------------------|
90+
* | [GL_MAP_READ_BIT] | Allows reading buffer data. | Buffer must be created with this flag. Undefined if not included in access. |
91+
* | [GL_MAP_WRITE_BIT] | Allows modifying buffer data. | Buffer must be created with this flag. Undefined if not included in access. |
92+
* | [GL_MAP_PERSISTENT_BIT] | Enables persistent mapping during GL operations. | Requires buffer to be created with [GL_MAP_PERSISTENT_BIT]. |
93+
* | [GL_MAP_COHERENT_BIT] | Ensures changes are visible to the GPU. | Requires buffer creation with [GL_MAP_PERSISTENT_BIT] or explicit sync. |
94+
* | [GL_MAP_INVALIDATE_RANGE_BIT] | Discards previous contents of the mapped range. | Cannot be used with [GL_MAP_READ_BIT]. |
95+
* | [GL_MAP_INVALIDATE_BUFFER_BIT] | Discards previous contents of the entire buffer. | Cannot be used with [GL_MAP_READ_BIT]. |
96+
* | [GL_MAP_FLUSH_EXPLICIT_BIT] | Requires explicit flushing of modified sub-ranges. | Only valid with [GL_MAP_WRITE_BIT]. Data may be undefined if flushing is skipped. |
97+
* | [GL_MAP_UNSYNCHRONIZED_BIT] | Skips synchronization before mapping. | May cause data corruption if buffer is accessed concurrently. |
98+
* | [GL_DYNAMIC_STORAGE_BIT] | Allows updates via [glBufferSubData]. | If omitted, [glBufferSubData] will fail. |
99+
* | [GL_CLIENT_STORAGE_BIT] | Hints that the buffer should prefer client storage. | Implementation-dependent optimization. |
98100
*
99101
* @see <a href="https://www.khronos.org/opengl/wiki/Buffer_Object">Buffer object</a>
100102
*/
@@ -257,8 +259,6 @@ abstract class Buffer(
257259
/**
258260
* Maps a specified region of the buffer's data store into client memory, processes it using the provided lambda, and then unmaps the buffer.
259261
*
260-
* This function does not handle the binding.
261-
*
262262
* If [access] contains the `GL_MAP_PERSISTENT_BIT` flag, the buffer will not be unmapped.
263263
*
264264
* @param size Specifies the length of the range to be mapped.
@@ -269,26 +269,25 @@ abstract class Buffer(
269269
*/
270270
open fun map(size: Long, offset: Long, block: (ByteBuffer) -> Unit = {}): ByteBuffer {
271271
validate()
272+
bind()
272273

273274
check(offset >= 0 || size >= 0)
274275
{ "Invalid offset or size parameter offset: $offset size: $size." }
275276

276277
check(offset + size <= glGetBufferParameteri(target, GL_BUFFER_SIZE))
277278
{ "Out of bound (is the buffer initialized?) $size + $offset > ${glGetBufferParameteri(target, GL_BUFFER_SIZE)}." }
278279

279-
check(glGetInteger(bindingCheckMappings.getValue(target)) == GL_TRUE)
280-
{ "Target is zero bound." }
281-
282280
check(glGetBufferParameteri(target, GL_BUFFER_MAPPED) == GL_FALSE)
283281
{ "Buffer is already mapped." }
284282

285-
check(access and GL_MAP_WRITE_BIT != 0 && access and GL_MAP_READ_BIT != 0)
283+
check(access and GL_MAP_WRITE_BIT != 0 || access and GL_MAP_READ_BIT != 0)
286284
{ "Neither GL_MAP_READ_BIT nor GL_MAP_WRITE_BIT is set." }
287285

288-
check(access and GL_MAP_READ_BIT != 0 &&
286+
check((access and GL_MAP_READ_BIT != 0 &&
289287
(access and GL_MAP_INVALIDATE_RANGE_BIT != 0 ||
290288
access and GL_MAP_INVALIDATE_BUFFER_BIT != 0 ||
291-
access and GL_MAP_UNSYNCHRONIZED_BIT != 0)
289+
access and GL_MAP_UNSYNCHRONIZED_BIT != 0)) ||
290+
access and GL_MAP_WRITE_BIT != 0
292291
)
293292
{ "GL_MAP_READ_BIT is set and any of GL_MAP_INVALIDATE_RANGE_BIT, GL_MAP_INVALIDATE_BUFFER_BIT or GL_MAP_UNSYNCHRONIZED_BIT is set." }
294293

@@ -302,6 +301,8 @@ abstract class Buffer(
302301
throw IllegalStateException("An unknown error occurred due to GPU memory availability of buffer corruption.")
303302
}
304303

304+
bind(0)
305+
305306
return sharedRegion
306307
}
307308

common/src/main/kotlin/com/lambda/graphics/buffer/pixel/PixelBuffer.kt

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package com.lambda.graphics.buffer.pixel
2020
import com.lambda.graphics.buffer.Buffer
2121
import com.lambda.graphics.gl.putTo
2222
import com.lambda.graphics.texture.Texture
23+
import com.lambda.threading.runSafeGameScheduled
2324
import com.lambda.util.math.MathUtils.toInt
2425
import org.lwjgl.opengl.GL45C.*
2526
import java.nio.ByteBuffer
@@ -31,25 +32,38 @@ import java.nio.ByteBuffer
3132
* Functions that perform an upload operation, a pixel unpack, will use the buffer object bound to the target GL_PIXEL_UNPACK_BUFFER.
3233
* If a buffer is bound, then the pointer value that those functions take is not a pointer, but an offset from the beginning of that buffer.
3334
*
35+
* Asynchronous should only be used for medium-size blocks of data being updated one time or less per frame
36+
* Persistent should only be used for streaming operations with large blocks of data updated once or more per frame
37+
*
3438
* @property texture The [Texture] instance to use
3539
* @property asynchronous Whether to use 2 buffers or not
36-
* @property bufferMapping Whether to map a block in memory to upload or not
40+
* @property persistent Whether to map a block in memory to upload or not
3741
*
38-
* @see <a href="https://www.khronos.org/opengl/wiki/Pixel_Buffer_Object">Reference</a>
42+
* @see <a href="https://www.khronos.org/opengl/wiki/Pixel_Buffer_Object">Pixel buffer object</a>
3943
*/
4044
class PixelBuffer(
4145
private val texture: Texture,
4246
private val asynchronous: Boolean = false,
43-
private val bufferMapping: Boolean = false,
47+
private val persistent: Boolean = false,
4448
) : Buffer(buffers = asynchronous.toInt() + 1) {
4549
override val usage = GL_STATIC_DRAW
4650
override val target = GL_PIXEL_UNPACK_BUFFER
47-
override val access = GL_MAP_WRITE_BIT or GL_DYNAMIC_STORAGE_BIT or GL_MAP_PERSISTENT_BIT
51+
override val access =
52+
if (persistent) GL_MAP_WRITE_BIT or GL_DYNAMIC_STORAGE_BIT or GL_MAP_PERSISTENT_BIT or GL_MAP_COHERENT_BIT
53+
else GL_MAP_WRITE_BIT or GL_DYNAMIC_STORAGE_BIT
4854

4955
private val channels = channelMapping[texture.format] ?: throw IllegalArgumentException("Invalid image format, expected OpenGL format, got ${texture.format} instead")
5056
private val size = texture.width * texture.height * channels * 1L
57+
// private var sharedRegion: ByteBuffer? = null
5158

5259
override fun upload(data: ByteBuffer, offset: Long) {
60+
if (!asynchronous) {
61+
glBindTexture(GL_TEXTURE_2D, texture.id)
62+
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture.width, texture.height, texture.format, GL_UNSIGNED_BYTE, data)
63+
glBindTexture(GL_TEXTURE_2D, 0)
64+
return
65+
}
66+
5367
bind()
5468
glBindTexture(GL_TEXTURE_2D, texture.id)
5569

@@ -69,8 +83,9 @@ class PixelBuffer(
6983
swap()
7084
bind()
7185

72-
if (bufferMapping) map(size, offset, data::putTo)
73-
else update(data, offset)
86+
// if (persistent) data.putTo(sharedRegion)
87+
// else update(data, offset)
88+
update(data, offset)
7489

7590
bind(0)
7691
}
@@ -87,6 +102,10 @@ class PixelBuffer(
87102
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
88103

89104
storage(size)
105+
106+
// bind()
107+
// sharedRegion = if (persistent) map(size, 0) else null
108+
// bind(0)
90109
}
91110

92111
companion object {

common/src/main/kotlin/com/lambda/graphics/gl/Memory.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ val Long.kibibyte get() = this * 1024
3535
val Long.mebibyte get() = this * 1024 * 1024
3636
val Long.gibibyte get() = this * 1024 * 1024 * 1024
3737

38-
fun ByteBuffer.putTo(dst: ByteBuffer) { dst.put(this) }
38+
fun ByteBuffer.putTo(dst: ByteBuffer?) { dst?.put(this) }

0 commit comments

Comments
 (0)