GLCOPYBUFFERSUBDATA(3G)

πŸ’– glCopyBufferSubData(3G) β€” the manual page, but make it a vibe πŸ’–

okay so bestie, you know how you sometimes need to copy data from one buffer object to another? like literally just scooping up part of one data store and yeeting it into another? that's what this is. glCopyBufferSubData and glCopyNamedBufferSubData are your girls for that. no cap, it's giving "copy all or part of the data store of a buffer object to the data store of another buffer object" energy. slay. ✨


🌸 C SPECIFICATION 🌸

void glCopyBufferSubData(GLenum readTarget, GLenum writeTarget,
                         GLintptr readOffset, GLintptr writeOffset,
                         GLsizeiptr size);

void glCopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer,
                              GLintptr readOffset, GLintptr writeOffset,
                              GLsizeiptr size);

periodt. those are the two functions. memorize them, bestie. πŸ’…


πŸŽ€ PARAMETERS πŸŽ€

okay let's go through these one by one because i want you to actually understand them, not just smile and nod:

  • readTarget β€” for glCopyBufferSubData, this is the target the source buffer object is bound to. like, which slot is your source chillin' in. iykyk.
  • writeTarget β€” for glCopyBufferSubData, this is the target the destination buffer object is bound to. where your data is headed. main character destination energy.
  • readBuffer β€” for glCopyNamedBufferSubData, this is the name of the source buffer object. not the target, the name. different vibe entirely.
  • writeBuffer β€” for glCopyNamedBufferSubData, the name of the destination buffer object. again: name, not target. don't mix them up fr fr.
  • readOffset β€” the offset, in basic machine units, within the source buffer's data store, at which the data will be read. like where in the source you start scooping. πŸ“
  • writeOffset β€” the offset, in basic machine units, within the destination buffer's data store, at which the data will be written. where in the destination you start dumping. two different spots, bestie.
  • size β€” the size, in basic machine units, of the data to be copied from the source buffer to the destination buffer. how many units get copied. slay. πŸ’«

✨ DESCRIPTION ✨

okay so here's the whole situation. glCopyBufferSubData and glCopyNamedBufferSubData copy part of the data store attached to a source buffer object to the data store attached to a destination buffer object. the number of basic machine units indicated by size is copied from the source at offset readOffset to the destination at writeOffset. and just to be clear: readOffset, writeOffset and size are all in terms of basic machine units. not vibes, not bytes-by-accident, basic machine units. πŸ’…

for glCopyBufferSubData, readTarget and writeTarget specify the targets to which the source and destination buffer objects are bound. and here's the important part bestie: they must each be one of the buffer binding targets in this table. i'm not making this up, it's literally the list:

Buffer Binding TargetPurpose
GL_ARRAY_BUFFERVertex attributes
GL_ATOMIC_COUNTER_BUFFERAtomic counter storage
GL_COPY_READ_BUFFERBuffer copy source
GL_COPY_WRITE_BUFFERBuffer copy destination
GL_DISPATCH_INDIRECT_BUFFERIndirect compute dispatch commands
GL_DRAW_INDIRECT_BUFFERIndirect command arguments
GL_ELEMENT_ARRAY_BUFFERVertex array indices
GL_PIXEL_PACK_BUFFERPixel read target
GL_PIXEL_UNPACK_BUFFERTexture data source
GL_QUERY_BUFFERQuery result buffer
GL_SHADER_STORAGE_BUFFERRead-write storage for shaders
GL_TEXTURE_BUFFERTexture data buffer
GL_TRANSFORM_FEEDBACK_BUFFERTransform feedback buffer
GL_UNIFORM_BUFFERUniform block storage

any of these targets may be used, okay? any of them. but GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER are provided specifically to allow copies between buffers without disturbing other GL state. they're the designated copy besties, the ones who don't drag the rest of your GL state into it. iconic. πŸ‘‘

now for the rules, because there are always rules. readOffset, writeOffset and size must all be greater than or equal to zero. all three. don't get cute and use negative numbers, it's not that kind of party. furthermore, $readOffset+size$ must not exceed (yes, the original page spells it "exceeed", i see you typo, you're valid) the size of the source buffer object, and $writeOffset+size$ must not exceed the size of the buffer bound to writeTarget. if the source and destination are the same buffer object, then the source and destination ranges must not overlap. this is important. don't overlap. no cap. 😀


πŸ¦‹ NOTES πŸ¦‹

okay so some targets are version-gated, bestie, and you need to know about it:

  • GL_DISPATCH_INDIRECT_BUFFER and GL_SHADER_STORAGE_BUFFER targets are available only if the GL version is 4.3 or greater. so if you're running something older, no dice.
  • GL_QUERY_BUFFER target is available only if the GL version is 4.4 or greater. again: check your version first, don't come crying to me.

πŸ’€ ERRORS πŸ’€

here we go, the part where things go wrong and you need to know why. buckle up, bestie, this is gonna be a list:

  • GL_INVALID_ENUM is generated by glCopyBufferSubData if readTarget or writeTarget is not one of the buffer binding targets listed above. so if you typed some made-up target, this is your sign. πŸ™ˆ
  • GL_INVALID_OPERATION is generated by glCopyBufferSubData if zero is bound to readTarget or writeTarget. zero is not a buffer. zero is zero. that's the whole thing.
  • GL_INVALID_OPERATION is generated by glCopyNamedBufferSubData if readBuffer or writeBuffer is not the name of an existing buffer object. so if you're using a name that doesn't map to anything, that's a problem.
  • GL_INVALID_VALUE is generated if any of readOffset, writeOffset or size is negative. negative numbers! not allowed! 🚫
  • GL_INVALID_VALUE is generated if $readOffset + size$ is greater than the size of the source buffer object (its value of GL_BUFFER_SIZE). that's the source object's own size, for reference.
  • GL_INVALID_VALUE is generated if $writeOffset + size$ is greater than the size of the destination buffer object. same situation, other side.
  • GL_INVALID_VALUE is generated if the source and destination are the same buffer object, and the ranges $[readOffset,readOffset+size)$ and $[writeOffset,writeOffset+size)$ overlap. the overlap thing again. i told you. i literally told you.
  • GL_INVALID_OPERATION is generated if either the source or destination buffer object is mapped with glMapBufferRange() or glMapBuffer(), unless they were mapped with the GL_MAP_PERSISTENT bit set in the glMapBufferRange access flags. so mapped is a no-go, unless you used the persistent bit. then it's fine. the more you know. πŸ’…

🌈 VERSION SUPPORT 🌈

okay so the vibe check here is: which versions do these functions exist in? and the answer is in table form, which i will not be retyping into prose because technical accuracy is more important than my aesthetic. but here's the table, bestie, and let me tell you, glCopyNamedBufferSubData is famous for being a late bloomer:

Function / Feature Name2.02.13.03.13.23.34.04.14.24.34.44.5
glCopyBufferSubData---βœ”βœ”βœ”βœ”βœ”βœ”βœ”βœ”βœ”
glCopyNamedBufferSubData-----------βœ”

so glCopyBufferSubData shows up in 3.1 and later, while glCopyNamedBufferSubData? literally doesn't exist until 4.5. it's the ultimate "better late than never" energy. 😭


🫢 SEE ALSO 🫢

these are the friends, the supporting cast, the ones you should also check out:

glGenBuffers(), glBindBuffer(), glBufferData(), glBufferSubData(), glGetBufferSubData(), glMapBuffer(), glMapBufferRange()


Copyright Β© 2010-2014 Khronos Group. This material may be distributed subject to the terms and conditions set forth in the Open Publication License, v 1.0, 8 June 1999. http://opencontent.org/openpub/.

Copyright Β© 2010-2014 Khronos Group


okay bestie, that's the whole page. every option, every error, every version check, every copyright line. you're welcome. now go forth and copy those buffers, but not overlappingly, and not negatively, and not while mapped unless you used GL_MAP_PERSISTENT. the way that i believe in you. πŸ’œβœ¨

this has been the [FIXME: source] edition from 08/09/2021, aka the glCopyBufferSubData era of the manual. slay and goodbye πŸŽ€

πŸ“¦ where this page comes from