blob: aa50cd441c622f8ffc40c53d8f7ec1dc56785961 [file] [log] [blame]
Name
APPLE_object_purgeable
Name Strings
GL_APPLE_object_purgeable
Contributors
Andrew Barnes
Bob Beretta
Kenneth Dyke
Alex Eddy
John Harper
Charlie Lao
Jeremy Sandmel
Contact
Charlie Lao, Apple Computer Inc. (clao 'at' apple.com)
Status
TBD
Version
Last Modified Date: September 29, 2006
Number
371
Dependencies
OpenGL 1.5 is required.
The extension is written against the OpenGL 1.5 Specification.
Overview
This extension provides the ability to mark the storage of OpenGL
objects as "purgeable".
Many of today's modern virtual memory systems include the concept of
purgeability in order to avoid unnecessary paging when the object
contents are no longer needed. In OpenGL, objects such as textures,
vertex buffers, pixel buffers, and renderbuffers all have
significant storage requirements. By default, the OpenGL is
required to preserve the contents of these objects regardless of
system resource stress, such as vram shortage or physical memory
shortage. Often this is accomplished by temporarily paging the
contents of objects that are not currently needed to some kind of
secondary storage area. This paging operation can be an unnecessary
computational expense in the cases where the data is not going to be
used again or where the content can be reproduced by the application
with less expense than the paging operation would require.
This extension defines a mechanism for the application to mark the
storage of OpenGL objects as "purgeable" in order to influence these
paging operations. The application can further control the
semantics of making object storage "purgeable" with two options
("volatile" and "released") and "unpurgeable" with two options
("undefined" and "retained")
Applications that use this extension will typically follow one of
two operational models. The typical model for most applications is
to mark an object storage as "purgeable" with the "volatile" option,
and then later mark the storage as "unpurgeable" with the "retained"
option. When this happens, the application may or may not need to
respecify the object contents, depending on the whether the object
storage was actually released. The application can find out whether
the storage was released by examining the return value of the
function which marks the storage as "unpurgeable". This model is
useful when the application does not know at the time it marks the
object storage as "purgeable" whether it will later need those
contents to be valid.
Another operational model is for an application to mark the storage
for an object as "purgeable" with the "released" option, and then
later mark the object "unpurgeable" with the "undefined" option. In
this latter model, the application intends to unconditionally reload
the object contents later on, and so it tells the GL that it is okay
if the contents are "undefined" when the storage is re-allocated.
Note that in both models, it is possible for the contents to become
undefined since they could have actually been purged from the system
in either case. The various options are still useful, however,
since they give more information to the GL about what the
application expects to happen and the GL can use this information to
make better predictions about which paging choices will be more
efficient.
IP Status
No known IP claims.
Issues
1. Why use two functions rather than just one?
The reason we chose two functions is that switching between the
two possible object states - purgeable and unpurgeable - might
be expensive. In addition, the return values of the operation
may be different depending on what state the object storage is
in and whether it has been purged or not. Therefore, we want to
enforce that the state is changed in matching pairs of function
calls, similar to Begin/End. In order to enforce this behavior,
we require two functions.
Applications are required to call ObjectPurgeable and
ObjectUnpurgeable in matched pairs, otherwise INVALID_OPERATION
is generated.
2. What does calling ObjectUnpurgeable with <option> set to
UNDEFINED_APPLE really mean?
An application calls ObjectUnpurgeable in order to change the
state of the object storage to unpurgeable. This is the
"default" state for object storage as defined traditionally in
GL.
Further, by using the <option> of UNDEFINED_APPLE, the
application is also indicating that it does not care about the
previous contents of the storage, if they still exist. This
gives the GL the freedom to allocate new storage or simply reuse
the old storage without spending time to figure out whether the
storage was actually freed and without having to tell the
application which choice was made. In addition, this allows the
function to return without blocking.
In contrast, calling ObjectUnpurgeable with <option> set to
RETAINED_APPLE requests the GL actually determine whether or not
it is possible to retain the original contents of the object,
and to restore the object storage to the previous contents, if
they still exist. This operation generally requires a flush of
the current command stream and often involveds additional work
to determine the state of object.
3. What's the difference between calling ObjectPurgeable and calling
DeleteTextures?
Calling ObjectPurgeable allows the GL to release all storage
that the GL has allocated for the object's contents, but will
still retain the object name and other non-content related state
of the object. If the application intends to re-use the object
again later, it will indicate so calling ObjectUnpurgeable.
In contrast, DeleteTextures deletes the object storage, the
object name, and the rest of the object state. The object can
never again be used.
Note that this means to set the object's name as unused and to
delete non-content related state of the object, the application
is still responsible for calling DeleteTextures.
There are some additional subtle differences though.
In general, calling ObjectPurgeable with the <option>
VOLATILE_APPLE requires less work of the GL than calling
ObjectPurgeable with the <option> set to RELEASED_APPLE.
Further, calling ObjectPurgeable with either option generally
requires less work of the GL than DeleteTextures.
Applications are encouraged, therefore, to use ObjectPurgeable
with the <option> set to VOLATILE_APPLE where possible and fall
back to ObjectPurgeable with the <option> set to RELEASED_APPLE
only if they prefer to have the GL do some amount of work to try
to release the storage. Only if the application really requires
the deletion of the object itself, should the application use
DeleteTextures.
Finally note, though the discussion above refers to
DeleteTextures, the same semantics apply to all object types
with Delete* operations, such as DeleteBuffers,
DeleteRenderbuffers, etc. that support this extension.
4. What should happen when ObjectPurgeable or ObjectUnpurgeable is
called between Begin/End?
This is illegal and returns INVALID_OPERATION error.
5. What should happen if ObjectPurgeable or ObjectUnpurgeable is
called on a currently bound texture, whether it is bound to the
current context or another context?
If the current context marks the storage of a currently bound
object as "purgeable", then attempts to read from or write to
the contents of that storage will result in undefined behavior.
Considering the multiple context case, we use the precedent of
all other state changes made by one context to an object bound
by another context. Namely, changes made to an object by
context A or only guaranteed to be "visible" to context B the
next time context B binds that object. In the interim period
the results of the state change are undefined.
For this extension, this means if context A marks an object's
storage as purgeable and that object is also bound by context B,
then it is undefined as to whether the object's storage will
have defined contents when used by context B. Note that in the
case of this particular extension, the whole point is to allow
the contents of the storage to become undefined so this is not a
particularly surprising outcome.
Applications are therefore advised to assume that they can not
rely on validity of the contents of any object whose storage has
been marked purgeable by any other context. Further, until some
context has marked the object storage as "unpurgeable" again and
the current context has re-bound the object, the current context
should not assume the contents are valid either. And even then
the contents should be assumed to be valid if and only if the
contents have been respecified or ObjectUnpurgeable returned the
value RETAINED_APPLE.
6. What should happen if the TestObject routine from the APPLE_fence
extension is called on an object whose storage has been marked
purgeable?
In short, it should operate "normally".
To be specific, if TestObject is called after calling
ObjectPurgeable with <option> set to VOLATILE_APPLE, the GL will
still determine if there are any pending operations using the
object, and TestObject will return TRUE or FALSE depending on
what it finds.
If TestObject is called after calling ObjectPurgeable with
<option> set to RELEASED_APPLE, the TestObject will generally
immediately return TRUE even though the object may still be in
use. This is acceptable since from user's point of view, the
object's storage has been freed from further use by the GL.
7. How does APPLE_object_purgeable interact with the
APPLE_texture_range extension?
First note that depending on the value of the storage hint
provided in the APPLE_texture_range extension, the GL may have
made multiple copies of the texture data.
In general, calling ObjectPurgeable with <option> set to
VOLATILE_APPLE option indicates that the GL should mark the
multiple copies of the storage as candidates for eviction but
should only release them as needed. In contrast, using the
<option> RELEASED_APPLE indicates that GL should try to go ahead
and release the storage for as many of these copies as is
efficient.
8. How does APPLE_object_purgeable interact with the
APPLE_client_storage extension?
For reference, APPLE_client_storage allows the application to
indicate that it will be responsible for allocating and
retaining the storage for a texture object.
In the APPLE_object_purgeable extension it is up to the
implementation to determine what happens when an object's
storage is marked purgeable and its up to the application to
query to determine whether the storage has been released. Given
that, the APPLE_client_storage has no real practical
interactions with APPLE_object_purgeable.
However, if APPLE_client_storage is supported on a platform that
gives the application control over the volatility of of client
memory, for instance via some sort of virtual memory system
call, then it's possible the application use the
platform-specific virtual memory API to mark as volatile the the
memory backing a texture using APPLE_client_storage for its
storage. The application on such a platform would be
responsible for using additional virtual memory system calls to
determine what happened to memory that was marked purgeable when
it goes to access that memory later on. In this scenario, the
effect would be very similar to the results of using the
APPLE_object_purgeable to mark a texture object's storage as
purgeable, but there is no direct interaction between the two
API's.
9. How does APPLE_object_purgeable interact with the
aglSurfaceTexture API?
For reference, the aglSurfaceTexture allows the application to
specify an AGL drawable as the storage for a GL texture object.
Such a texture object is informally called a "surface texture".
Similar to the APPLE_client_storage case, it is up to the API
that allocated the storage object to handle the purgeability of
that object. Given that, the APPLE_client_storage has no real
practical interactions with AGL surface textures.
10. How does APPLE_object_purgeable interact with the
ARB_vertex_buffer_object and ARB_pixel_buffer_object extensions?
The interactions should be analogous to those that occur with
texture objects.
To mark the storage for a buffer object as purgeable or
unpurgeable, the application can specify BUFFER_OBJECT_APPLE as
the <objectType> parameter in ObjectPurgeable or
ObjectUnpurgeable, respectively. The same rules about undefined
results from reading from or writing to the buffer object
storage while PURGEABLE_APPLE is TRUE apply as well.
13. After an object's storage has been marked as purgeable, what
should happen if CopyTexImage{1|2}D, CopyTexSubImage{1|2}D,
TexSubImage{1|2|3}D, or TexImage{1|2|3}D is called on the
texture? What if user try to texture from it or render to it?
After an object's storage has been marked purgeable, any usage
of the object is undefined until it is marked unpurgeable.
New Procedures and Functions
enum ObjectPurgeableAPPLE(enum objectType, uint name, enum option)
enum ObjectUnpurgeableAPPLE(enum objectType, uint name, enum option)
void GetObjectParameterivAPPLE(enum objectType, uint name, enum
pname, int* params)
New Types
None
New Tokens
Accepted by the <option> parameter of ObjectPurgeable, and returned
by ObjectPurgeable:
RELEASED_APPLE 0x8A19
VOLATILE_APPLE 0x8A1A
Accepted by the <option> parameters of ObjectUnpurgeable, and
returned by ObjectUnpurgeable:
RETAINED_APPLE 0x8A1B
UNDEFINED_APPLE 0x8A1C
Accepted by the <pname> parameters of GetObjectParameteriv:
PURGEABLE_APPLE 0x8A1D
Accepted by the <objectType> parameters of ObjectPurgeableAPPLE,
ObjectUnpurgeableAPPLE and GetObjectParameteriv:
BUFFER_OBJECT_APPLE 0x85B3
(Note: BUFFER_OBJECT_APPLE is also defined in APPLE_fence extension
with the same value.)
Additions to Chapter 2 of the OpenGL 1.5 Specification
(OpenGL Operation)
None
Additions to Chapter 3 of the OpenGL 1.5 Specification (Rasterization)
Additions to Chapter 3 of OpenGL 1.5 Specification (Rasterization)
(add a new section 3.8.16)
3.8.16 Purgeability
The internal data storage of a texture object, renderbuffer object,
or buffer object has a boolean state, PURGEABLE_APPLE that
influences how the object's storage is managed by the GL. The
initial value of PURGEABLE_APPLE is FALSE. The application can
change the value of PURGEABLE_APPLE by using the routines below.
The routine
enum ObjectPurgeableAPPLE(enum objectType, uint name, enum option)
sets PURGEABLE_APPLE to TRUE for the object of type <objectType>
with the id <name>. <objectType> must be one of TEXTURE,
BUFFER_OBJECT_APPLE, or RENDERBUFFER_EXT. If ObjectPurgeableAPPLE is
called and PURGEABLE_APPLE is already TRUE, the error
INVALID_OPERATION is generated.
While PURGEABLE_APPLE is TRUE, the GL may release the storage for
this object and the results of issuing any commands that read from
or write to the storage of that object are undefined.
<option> must be either VOLATILE_APPLE or RELEASED_APPLE. Calling
ObjectPurgeableAPPLE with either option sets PURGEABLE_APPLE to
TRUE, but the value of <option> is used by the GL as a hint to
indicate the application's intended future use of the named object's
storage.
By calling ObjectPurgeableAPPLE with an <option> of VOLATILE_APPLE,
the application is indicating that it does not know if it will want
to re-use the current contents of the object storage again later.
Further, the application is stating that it would like the GL to do
only the minimal amount of work required to set PURGEABLE_APPLE to
TRUE. If ObjectPurgeableAPPLE is called with an <option> of
VOLATILE_APPLE, then ObjectPurgeableAPPLE will also return the value
VOLATILE_APPLE.
In contrast, by calling ObjectPurgeableAPPLE with an <option> of
RELEASED_APPLE, the application is indicating that it does not
intend to re-use the contents of the storage again. Further, the
application is stating that it is acceptable for the GL to do a more
work to encourage the GL to actually release the storage for the
object. The actual mechanism for releasing the storage is
implementation-dependent, but it may require some level of
synchronization and may flush the current context. If
ObjectPurgeableAPPLE is called with an <option> of RELEASED_APPLE,
then ObjectPurgeableAPPLE may return either the value RELEASED_APPLE
or the value VOLATILE_APPLE.
If ObjectPurgeableAPPLE returns the value VOLATILE_APPLE, this means
that the storage for the object may not have been released when
ObjectPurgeableAPPLE returns. In contrast, if ObjectPurgeableAPPLE
returns the value RELEASED_APPLE, this means that the storage for
the object has been released when ObjectPurgeableAPPLE returns.
The routine
enum ObjectUnpurgeableAPPLE(enum object, uint name, enum option)
sets the value of PURGEABLE_APPLE to FALSE for the object of type
<objectType> with the id <name>. If ObjectUnpurgeableAPPLE is
called and PURGEABLE_APPLE is already FALSE, the error
INVALID_OPERATION is returned.
While PURGEABLE_APPLE is FALSE, the storage for an object will not
be released by the GL. This is the default state for object storage.
<option> must be either RETAINED_APPLE or UNDEFINED_APPLE. Calling
ObjectUnpurgeableAPPLE with either option sets PURGEABLE_APPLE to
FALSE, but the value of <option> is used by the GL as a hint to
indicate the application's intended future use of the named object's
storage.
By calling ObjectUnpurgeableAPPLE with an <option> of
RETAINED_APPLE, the application is indicating that it would like to
re-use the contents of the storage, if the storage has not yet been
released. Further, the application is stating that it is acceptable
for the GL to do more work to try to restore the storage the same
state it was in before PURGEABLE_APPLE was set to TRUE. The actual
mechanism for attempting to restore the storage of the object is
implementation-dependent, but it may require some level of
synchronization and may flush the current context. If
ObjectUnpurgeableAPPLE is called with an <option> of RETAINED_APPLE,
then ObjectPurgeableAPPLE may return either the value RETAINED_APPLE
or the value UNDEFINED_APPLE.
In contrast, by calling ObjectUnpurgeableAPPLE with an <option> of
UNDEFINED_APPLE, the application is indicating that it intends to
recreate the contents of the storage from scratch. Further, the
application is is stating that it would like the GL to do only the
minimal amount of work set PURGEABLE_APPLE to FALSE. If
ObjectUnpurgeableAPPLE is called with the <option> set to
UNDEFINED_APPLE, then ObjectUnpurgeableAPPLE will return the value
UNDEFINED_APPLE.
If ObjectUnpurgeableAPPLE returns the value UNDEFINED_APPLE, the
storage is in the same state as a newly created object with
undefined contents. In contrast, if ObjectUnpurgeableAPPLE returns
the value RETAINED_APPLE, this means that the storage has the same
the same contents it did when PURGEABLE_APPLE was most recently set
to FALSE.
Additions to Chapter 4 of the OpenGL 1.5 Specification (Per-Fragment
Operations and the Frame Buffer)
None
Additions to Chapter 5 of the OpenGL 1.5 Specification
(Special Functions)
None
Additions to Chapter 6 of the OpenGL 1.5 Specification (State and State
Requests)
(In section 6.1.3, Enumerated Queries, in the list of state query
functions, add the following)
"void GetObjectParameterivAPPLE(enum objectType,
int name,
enum pname,
void* params);"
(and add the following description to the end of this section)
"GetObjectParameterivAPPLE places in <params> information about the
object of type <objectType> with the id <name>. <objectType> must
be one of TEXTURE, BUFFER_OBJECT_APPLE, or RENDERBUFFER_EXT.
<name> must be a non-zero name of an object of type <type>. If
<pname> is PURGEABLE_APPLE, then when GetObjectParameterivAPPLE
returns, <params> will contain the current value of PURGEABLE_APPLE
for the named object's storage. Note that this query does not
return whether or not the object storage has been purged but simply
whether the state PURGEABLE_APPLE is set to TRUE or FALSE."
Additions to Appendix A of the OpenGL 1.5 Specification (Invariance)
None
Additions to the AGL/EGL/GLX/WGL Specifications
None
Errors
INVALID_ENUM is generated if the <objectType> parameter of
ObjectPurgeableAPPLE or ObjectUnpurgeableAPPLE is not one of
TEXTURE, BUFFER_OBJECT_APPLE, RENDERBUFFER_EXT.
INVALID_ENUM is generated if the <option> parameter of
ObjectPurgeableAPPLE is not VOLATILE_APPLE or RELEASED_APPLE.
INVALID_ENUM is generated if the <option> parameter of
ObjectUnpurgeableAPPLE is not RETAINED_APPLE or UNDEFINED_APPLE.
INVALID_VALUE is generated if the <name> parameter of
ObjectUnpurgeableAPPLE or ObjectUnpurgeableAPPLE is zero.
INVALID_OPERATION is generated if either ObjectUnpurgeableAPPLE or
ObjectUnpurgeableAPPLE is called between the execution of Begin and
the corresponding execution of End.
INVALID_OPERATION is generated if ObjectPurgeableAPPLE is called on
an object with a current value of PURGEABLE set to TRUE
INVALID_OPERATION is generated if ObjectUnpurgeableAPPLE is called
on an object with a current value of PURGEABLE set to FALSE
INVALID_ENUM is generated if the <objectType> parameter of
GetObjectParameterivAPPLE is not one of TEXTURE,
BUFFER_OBJECT_APPLE, or RENDERBUFFER_EXT.
INVALID_VALUE is generated if the <name> parameter of
GetObjectParameterivAPPLE is not the name of an existing
object of type <objectType>.
INVALID_VALUE is generated if the <name> parameter of
GetObjectParameterivAPPLE is zero.
INVALID_ENUM is generated if the <pname> parameter of
GetObjectParameterivAPPLE is PURGEABLE_APPLE.
New State
Each object type that supports this extension has the following new
state:
Type Get Command Inital Value Description Section Attribute
---- ----------------- ------------ ------------ ------- ---------
Z2 GetObjectParameter FALSE GL_PURGEABLE_APPLE 3.8.16 -
New Implementation Dependent State
None
Sample Code
A "one shot" texture is a texture specified, used once, and then
respecified again before it's next use. The sample code below shows
how to use APPLE_object_purgeable to handle "one shot" textures:
/* First, find out if the texture is purgeable already */
boolean purgeable = FALSE;
GetObjectParameter(TEXTURE, name, &purgeable);
if(purgeable)
ObjectUnpurgeable(TEXTURE, name, UNDEFINED_APPLE);
/* Now that the texture is unpurgeable, respecify its contents
*/
BindTexture(TEXTURE_2D, name);
Enable(TEXTURE_2D);
TexImage2D(TEXTURE_2D, 0, RGBA, width, height, 0, RGBA,
UNSIGNED_BYTE, pixels);
/* Draw using the texture */
MyDrawRoutine goes here(...);
/* Now mark the texture as purgeable */
ObjectPurgeable(TEXTURE, name, RELEASED_APPLE);
Texture speculative caching: A FBO is created and texture_name is
attached to it. The application then renders to texture and is
expecting to use this texture later on. In the mean time it does
not want the GL to page it off because it is easy to recreate if
needed.
/* during system idle time, bind the fbo and render into it */
BindFramebufferEXT(FRAMEBUFFER_EXT, fbo_name);
MyDrawRoutineToSpecifyTextureContents(...);
/* We've rendered into the texture but we don't necessarily */
/* need for it to remain valid if the GL wants to release it */
/* so we mark it as purgeable */
ObjectPurgeable(TEXTURE, texture_name, VOLATILE_APPLE);
/* now do some other unrelated rendering */
MyOtherDrawRoutineGoesHere(...);
/* Some time passes and then the application wants to */
/* use the texture, so it markes the texture storage as */
/* unpurgeable and indicates it would like the GL to try to */
/* retain the storage if it still exists */
obj_state = ObjectUnpurgeable(TEXTURE,
texture_name, RETAINED_APPLE);
if(obj_state == RETAINED_APPLE)
{
/* object storage was retained so we can go ahead and use it
*/
BindTexture(TEXTURE_2D, texture_name);
MyDrawRoutineThatUsesTheOriginalTexture(...);
}
else /* object storage was lost */
{
/* We must recreate the original texture contents */
BindFramebufferEXT(FRAMEBUFFER_EXT, fbo_name);
MyDrawRoutineToRespecifyTextureContents(...);
/* object storage has been re-specified so we can go */
/* ahead and use it now */
BindFramebufferEXT(FRAMEBUFFER_EXT, 0);
BindTexture(TEXTURE_2D, texture_name);
MyDrawRoutineThatUsesTheOriginalTexture(...);
}
Revision History
Revision 2, 2006/10/20
- updated issue language to remove some stale resolutions
- revised and clarified language in terms of application intent
for the various <option> flags instead of implementation details
- replaced IsPurgeable with GetObjectParameter
- renamed extension "APPLE_object_purgeable" instead of
"APPLE_object_purgeability" to correlate with new state variable
GL_PURGEABLE_APPLE.
Revision 1, 2006/09/29
- Initial checkin.