As a general principle, any feature which requires synchronisation between client state and server state can't go in a display list, as that would require glCallList() to be "executed" on both the client and server so that the states don't become desynchronised. E.g. glBindBuffer() can't go into a display list as the client needs to know whether a buffer is bound in order to determine whether "pointer" arguments to glVertexPointer() etc are pointers to data which should be sent with each draw command, or offsets into server-side buffer objects.
The fact that a display list can contain mismatched glBegin/glEnd commands, partial immediate-mode vertex specifications, etc is a consequence of display lists being nothing more than recording and playback of the command stream. Contrary to what might be inferred from "GL_COMPILE", implementations typically don't attempt to optimise the contents of a display list, they just store the commands verbatim.
A notable exception is that some OpenGL 1.0 implementations worked around the single-texture limitation (glGenTextures, glBindTexture etc were added in 1.1) by optimising display lists containing glTexImage() commands. But that's ancient history.
Indeed, a GL implementation essentially needs to "flush" the used vertices and indices from client side memory to GPU at each draw call, so yes it sucks. However, there was no need to throw the baby out with the bath water. There were several ways out, for example a set of additional calls giving the GL implementation "promises" that the client side data would not change until the pointer was changed for example. The catch being that that can end up walking a similar road as the current buffer object Ouija board we have now. Right now for streaming vertex data, it is.. a pain. Greater hilarity is in order for when the memory is unified. The current GL interface for buffer object data is an embarrassment when one sees that all one wants is to write the data into memory with the promise that one is not writing into that memory while the GPU is using it.Quote:
Originally Posted by GClements
Or just provide a query what the behavior is and let it be undefined. There are plenty of bits in the GL specification that are undefined and left at the vendor's discretion on what to do. For example when a triangle edge passes exactly through the center of a pixel weather or not that pixel is rasterized; all that one has is that neighboring triangle sharing an edge shall not rasterize the same pixels twice.Quote:
The main problem with quads was that their tessellation into triangles was unspecified, i.e. which diagonal was used for the split. It seems like it would have been simple enough to just specify the behaviour, although this might have had political ramifications (i.e. unless all drivers behaved the same way, any given choice would make some existing drivers "correct" and others "incorrect").
... glVertexAttribPointer by specifying values that aren't correct even with VBOs. In conjunction with a corresponding draw call, you can easily go out of bounds of the buffer object's data store ... but that's what GL_ARB_robustness is for. Even if the draw call specifies the correct values for the set of primitives to be rendered, incorrectly setup arrays can still lead to access violations - and vice versa.
In general, at any time you operate on memory with accesses that aren't explicitly checked, caught and handled if incorrect, you can get into trouble.
That's not true. The size of memory that is passed to glBufferData or glBufferSubData is an explicit parameter. Yes, the user can get it wrong, but at least the size is there, as opposed to glVertexAttribPointer, where there is no size at all. The size of the buffer for a pixel transfer is implicitly specified based on a complex function of the parameters to the pixel transfer call (and a few global parameters). With mapping, again the size is either explicitly given or is implicit.Quote:
True, but the same applies to any GL call that requires a client-side memory pointer (or returns one that may be written to): glBufferData, glTexImage, glMapBuffer, etc.
And most important of all, all of these functions will be done with the pointer upon their return (well, except for mapping, but that's a special case). So any modifications to client memory are local modifications. Everything you need to know to verify that you have provided sufficient memory should be right there.
glVertexAttribPointer's boundaries are defined only by the eventual draw call, which may be an indexed rendering call that could fetch from quite simply anywhere. And the fetching is non-local; indeed, the place where the render call happens could be very far away from where the initial setup happened.
This all leads to it being nearly impossible to verify via inspection that any particular use of client-side arrays is safe. You will have to trace through a lot of non-local code to make sure.
I think this wording is misleading. Yes, I know what you mean, but you don't bound glVertexAttribPointer - the lower bound for fetching is established by glVertexAttribPointer. You can offset the lower bound but that doesn't change the fact that ultimately the lower bound is specified by the offset passed to glVertexAttribPointer. The upper bound is defined as a function of both the values specified by glVertexAttribPointer and the draw call. Your statement sounds as if a draw call could make up for an incorrectly specified offset in glVertexAttribPointer, for instance by specifying a negative first argument (which leads to undefined behavior) or by specifying negative indices (which will simply be converted to an unsigned integral type).Quote:
Originally Posted by Alfonse