| Name |
| |
| ARB_ES3_1_compatibility |
| |
| Name Strings |
| |
| GL_ARB_ES3_1_compatibility |
| |
| Contact |
| |
| Piers Daniell, NVIDIA Corporation (pdaniell 'at' nvidia.com) |
| |
| Contributors |
| |
| Daniel Koch, NVIDIA Corporation (dkoch 'at' nvidia.com) |
| |
| and contributors to the OpenGL ES 3.1 specification |
| |
| Notice |
| |
| Copyright (c) 2014 The Khronos Group Inc. Copyright terms at |
| http://www.khronos.org/registry/speccopyright.html |
| |
| Status |
| |
| Complete. |
| Approved by the ARB on June 26, 2014. |
| Ratified by the Khronos Board of Promoters on August 7, 2014. |
| |
| Version |
| |
| Last Modified Date: September 19, 2014 |
| Revision: 15 |
| |
| Number |
| |
| ARB Extension #159 |
| |
| Dependencies |
| |
| OpenGL 4.4, ARB_ES2_compatibility, ARB_ES3_compatibility are required. |
| |
| This extension is written against The OpenGL 4.4 (Compatibility Profile) |
| specification. |
| |
| Overview |
| |
| This extension adds support for features of OpenGL ES 3.1 that are |
| missing from OpenGL 4.4. Enabling these features will ease the process |
| of porting applications from OpenGL ES 3.1 to OpenGL. |
| |
| In particular this adds the following features: |
| |
| - a new MemoryBarrierByRegion API which is potentially more efficient |
| for specific localized memory access patterns. |
| |
| - increases the minimum required size of SSBOs to 2^27 (128 MB). |
| |
| - support for GLSL ES version 310 (ie #version 310 es). |
| |
| - a new GLSL built-in function, imageAtomicExchange, which performs atomic |
| exchanges on r32f floating point images. |
| |
| - a new GLSL built-in fragment shader input, gl_HelperInvocation, that |
| identifies whether the current fragment shader input is a helper |
| invocation. Fragment shader code can use this variable to skip performing |
| operations that are useless or potentially dangerous for helper |
| invocations. |
| |
| - a new GLSL built-in constant for the maximum supported samples: |
| gl_MaxSamples. |
| |
| - a number of new GLSL built-in constants mirroring the API limits for |
| image uniforms: gl_Max*ImageUniforms, gl_MaxCombinedShaderOutputResources. |
| |
| - new GLSL built-in functions which extend mix() to select between int, |
| uint, and bool components. |
| |
| - add the "coherent" qualifier to all memory variables taken by the GLSL |
| built-in atomic* and imageAtomic* functions. |
| |
| New Procedures and Functions |
| |
| void MemoryBarrierByRegion(bitfield barriers); |
| |
| New Tokens |
| |
| None |
| |
| Additions to Chapter 1 of the OpenGL 4.4 (Compatibility Profile) |
| Specification (Introduction) |
| |
| Modify section 1.3.2 (OpenGL ES) to include mention of OpenGL ES 3.1: |
| |
| OpenGL ES is a ... well-defined subsets of OpenGL. OpenGL ES version |
| 1.1 implements a subset of the OpenGL 1.5 fixed-function API, OpenGL |
| ES 2.0 implements a subset of the OpenGL 2.0 shader-based API, OpenGL |
| ES 3.0 implements a subset of OpenGL 3.3, and OpenGL ES 3.1 implements |
| a subset of OpenGL 4.3. OpenGL ES versions also include ... |
| |
| OpenGL and OpenGL ES are developed ... |
| |
| OpenGL implementations supporting this extension include functionality |
| initially defined in OpenGL ES 3.1, for increased compatibility between |
| OpenGL and OpenGL ES implementations. |
| |
| |
| Modify section 1.3.3 (OpenGL ES Shading Language) to include mention |
| of version 3.10: |
| |
| The Specification should also be read together with companion documents |
| titled "The OpenGL ES Shading Language". Versions 1.00, 3.00 and 3.10 |
| should be read. These documents define versions of the OpenGL ES Shading |
| Language designed for implementations of OpenGL ES 2.0, 3.0 and 3.1, |
| respectively, but also supported by OpenGL implementations. References ... |
| |
| OpenGL implementations supporting this extensions are guaranteed to |
| support versions 1.00, 3.00 and 3.10 of the OpenGL ES Shading Language. |
| |
| |
| Additions to Chapter 7 of the OpenGL 4.4 (Compatibility Profile) |
| Specification (Programs and Shaders) |
| |
| Modify Section 7.12.2, "Shader Memory Access Synchronization", (p. 148) |
| |
| (Append to the end of the section) |
| |
| "The command |
| |
| void MemoryBarrierByRegion(bitfield barriers) |
| |
| behaves as described above for MemoryBarrier, with two differences: |
| |
| First, it narrows the region under consideration so that only reads/writes |
| of prior fragment shaders that are invoked for a smaller region of the |
| framebuffer will be completed/reflected prior to subsequent reads/write of |
| following fragment shaders. The size of the region is implementation |
| dependent and may be as small as one framebuffer pixel. |
| |
| Second, it only applies to memory transactions that may be read by or |
| written by a fragment shader. Therefore, only the barrier bits |
| - ATOMIC_COUNTER_BARRIER_BIT |
| - FRAMEBUFFER_BARRIER_BIT |
| - SHADER_IMAGE_ACCESS_BARRIER_BIT |
| - SHADER_STORAGE_BARRIER_BIT |
| - TEXTURE_FETCH_BARRIER_BIT |
| - UNIFORM_BARRIER_BIT |
| are supported. |
| |
| When barriers is ALL_BARRIER_BITS, shader memory accesses will be |
| synchronized relative to all these barrier bits, but not to other barrier |
| bits specific to MemoryBarrier. This implies that reads/writes for |
| scatter/gather-like algorithms may or may not be completed/reflected after |
| a MemoryBarrierByRegion command. However, for uses such as deferred |
| shading, where a linked list of visible surfaces with the head at a |
| framebuffer address may be constructed, and the entirety of the list is |
| only dependent on previous executions at that framebuffer address, |
| MemoryBarrierByRegion may be significantly more efficient than |
| MemoryBarrier." |
| |
| |
| Additions to Chapter 9 of the OpenGL 4.4 (Compatibility Profile) |
| Specification (Framebuffers and Framebuffer Objects) |
| |
| Modify Section 9.2.3 (Framebuffer Object Queries) in the second |
| paragraph describing GetFramebufferAttachmentParameteriv to add BACK as |
| a valid <attachment>: |
| |
| "If the default framebuffer is bound to <target>, then <attachment> must |
| be one of FRONT_LEFT, FRONT_RIGHT, BACK, BACK_LEFT, or BACK_RIGHT, |
| identifying a color buffer; ... identifying the stencil buffer. Since |
| this command can only query a single framebuffer attachment, BACK is |
| equivalent to BACK_LEFT." |
| |
| Modify the first paragraph of Section 9.4.5 (Effects of |
| Framebuffer State on Framebuffer Dependent Values) |
| |
| "The values of the state variables listed in table 23.85 may change when |
| a change is made to the current framebuffer binding, to the state of the |
| currently bound framebuffer object, or to an image attached to that |
| framebuffer object. Most such state is dependent on the draw framebuffer |
| (DRAW_FRAMEBUFFER_BINDING), but IMPLEMENTATION_COLOR_READ_TYPE and |
| IMPLEMENTATION_COLOR_READ_FORMAT are dependent on the read framebuffer |
| (READ_FRAMEBUFFER_BINDING)." |
| |
| |
| Additions to Chapter 15 of the OpenGL 4.4 (Compatibility Profile) |
| Specification (Programmable Fragment Processing) |
| |
| Modify Section 15.2.2 (Shader Inputs), (p. 530, 5th paragraph) |
| |
| "The built-in variable gl_SampleMaskIn is an integer array... |
| The number of elements in the array is ceil(gl_MaxSamples/32), where |
| gl_MaxSamples is the value of MAX_SAMPLES, the maximum number of |
| color samples supported by the implementation. Bit <n> ... " |
| |
| Modify Section 15.2.3 (Shader Outputs), (p. 532, 2nd paragraph) |
| |
| "The built-in integer array gl_SampleMask can be used ... |
| The number of elements in the arrays is ceil(gl_MaxSamples/32), where |
| gl_MaxSamples is the value of MAX_SAMPLES, the maximum number of |
| color samples supported by the implementation. If bit <n> ... " |
| |
| |
| Additions to Chapter 17 of the OpenGL 4.4 (Compatibility Profile) |
| Specification (Writing Fragments and Samples to the Framebuffer) |
| |
| Modify Section 17.4.1 (Selecting Buffers for Writing), (p. 572, |
| 2nd paragraph) |
| |
| "If the GL is bound to the default framebuffer, then each of the |
| constants must be one of the values listed in table 17.6 or the |
| special value BACK. When the value BACK is used then <n> must |
| be 1 and color values are written into the left buffer for |
| single-buffered contexts, or into the back left buffer for double- |
| buffered contexts. An INVALID_OPERATION error is generated if |
| <bufs> contains the value BACK and <n> does not equal 1." |
| |
| |
| Additions to Chapter 18 of the OpenGL 4.4 (Compatibility Profile) |
| Specification (Drawing, Reading, and Copying Pixels) |
| |
| Modify Section 18.2.1 (Selecting Buffers for Reading), (p. 589) |
| |
| Remove the last paragraph that describes the |
| IMPLEMENTATION_COLOR_READ_FORMAT and IMPLEMENTATION_COLOR_READ_TYPE |
| queries and errors. |
| |
| Modify Section 18.2.2 (ReadPixels), (p. 589) |
| |
| Add the following paragraph at the end of the section: |
| |
| "The preferred parameters for <format> and <type> may be determined by |
| calling GetIntegerv with the symbolic constants |
| IMPLEMENTATION_COLOR_READ_FORMAT and IMPLEMENTATION_COLOR_READ_TYPE, |
| respectively. The implementation chosen format may vary depending on the |
| format of the selected read buffer of the currently bound read |
| framebuffer. |
| |
| An INVALID_OPERATION error is generated by GetIntegerv if pname is |
| IMPLEMENTATION_COLOR_READ_FORMAT or IMPLEMENTATION_COLOR_READ_TYPE and |
| any of: |
| - the read framebuffer is not framebuffer complete |
| - the read framebuffer is a framebuffer object, and the selected read buffer |
| (see section 18.2.1) has no image attached |
| - the selected read buffer is NONE |
| " |
| |
| Additions to Chapter 22 of the OpenGL 4.4 (Compatibility Profile) |
| Specification (Context State Queries) |
| |
| Modify Section 22.2 (Pointer and String Queries), (p. 648) |
| |
| "If <name> is SHADING_LANGUAGE_VERSION, ... |
| Version strings "100", "300 es" and "310 es" correspond to the OpenGL |
| ES Shading Language versions 100, 300 and 310, respectively." |
| |
| |
| |
| Additions to the OpenGL Shading Language |
| |
| Including the following line in a shader can be used to control the |
| language features described in this extension: |
| |
| #extension GL_ARB_ES3_1_compatibility : <behavior> |
| |
| where <behavior> is as specified in section 3.3. |
| |
| New preprocessor #defines are added to the OpenGL Shading Language: |
| |
| #define GL_ARB_ES3_1_compatibility 1 |
| |
| |
| Additions to Chapter 3 of the OpenGL Shading Language 4.40.8 Specification |
| (Basics) |
| |
| Modify the paragraph at the bottom of page 16 in Section 3.3 |
| (Preprocessor) as follows: |
| |
| "... Shaders that specify #version 100 will be treated as targeting |
| version 1.00 of the OpenGL ES Shading Language. Shaders that specify |
| #version 300 will be treated as targeting version 3.00 of the OpenGL |
| ES Shading Language. Shaders that specify #version 310 will be treated |
| as targeting version 3.10 of the OpenGL ES Shading Language. ..." |
| |
| Modify the 3rd paragraph at the top of p16 as follows: |
| |
| A <profile> argument ... |
| If version 300 or 310 is specified, the profile argument is not optional |
| and must be "es", or a compile-time error results. The Language |
| Specification ... |
| |
| |
| Additions to Chapter 4 of the OpenGL Shading Language 4.40.8 Specification |
| (Variables and Types) |
| |
| Modify Section 4.7.2 (Precision Qualifiers) |
| |
| (Replace the first sentence to reference all opaque types instead of just |
| samplers) |
| |
| "Any floating point, integer, or opaque-type declaration can have the |
| type preceded by one of these precision qualifiers: ..." |
| |
| Modify Section 4.7.3 (Default Precision Qualifiers) |
| |
| (Replace the second sentence to reference all opaque types and not just |
| samples) |
| |
| "The type field can be either int or float, any of the opaque types, and |
| the precision-qualifier can be lowp, mediump, or highp. ..." |
| |
| |
| Additions to Chapter 7 of the OpenGL Shading Language 4.40.8 Specification |
| (Built-in Variables) |
| |
| Modify Section 7.1, Built-In Language Variables (p. 122) |
| |
| (Add to list of fragment language built-in variables on page 122) |
| |
| in bool gl_HelperInvocation; |
| |
| (Add after the description of gl_SamplePosition on page 127) |
| |
| "The value gl_HelperInvocation is true if the fragment shader invocation is |
| considered a "helper invocation" and is false otherwise. A "helper |
| invocation" is a fragment-shader invocation that is created solely for the |
| purposes of evaluating derivatives for use in non-helper fragment-shader |
| invocations. Such derivatives are computed implicitly in the built-in |
| function texture() (see section 8.9 "Texture Functions"), and explicitly in |
| the derivative functions in section 8.13.1 "Derivative Functions", for |
| example dFdx() and dFdy(). |
| |
| Fragment shader helper invocations execute the same shader code as |
| non-helper invocations, but will not have side effects that modify the |
| framebuffer or other shader-accessible memory. In particular: |
| |
| * Fragments corresponding to helper invocations are discarded when |
| shader execution is complete, without updating the framebuffer. |
| |
| * Stores to image and buffer variables performed by helper invocations |
| have no effect on the underlying image or buffer memory. |
| |
| * Atomic operations to image, buffer, or atomic counter variables |
| performed by helper invocations have no effect on the underlying image |
| or buffer memory. The values returned by such atomic operations are |
| undefined. |
| |
| Helper invocations may be generated for pixels not covered by a primitive |
| being rendered. While fragment shader inputs qualified with "centroid" |
| are normally required to be sampled in the intersection of the pixel and |
| the primitive, the requirement is ignored for such pixels since there is |
| no intersection between the pixel and primitive. |
| |
| Helper invocations may also be generated for fragments that are covered by |
| a primitive being rendered when the fragment is killed by early fragment |
| tests (using the "early_fragment_tests" qualifier) or where the |
| implementation is able to determine that executing the fragment shader |
| would have no effect other than assisting in computing derivatives for |
| other fragment shader invocations. |
| |
| The set of helper invocations generated when processing any set of |
| primitives is implementation-dependent." |
| |
| Add to section 7.3 Built-in Constants |
| |
| const int gl_MaxSamples = 4; |
| |
| const int gl_MaxVertexImageUniforms = 0; |
| const int gl_MaxFragmentImageUniforms = 8; |
| const int gl_MaxComputeImageUniforms = 8; |
| const int gl_MaxCombinedImageUniforms = 48; |
| const int gl_MaxCombinedShaderOutputResources = 16; |
| |
| Additions to Chapter 8 of the OpenGL Shading Language 4.40.8 Specification |
| (Built-in Functions) |
| |
| Modify Section 8.3, Common Functions |
| |
| (Additions to the table listing common built-in functions) |
| |
| Syntax Description |
| --------------------------- -------------------------------------------------- |
| genIType mix(genIType x, Selects which vector each returned component comes |
| genIType y, from. For a component of a that is false, the |
| genBType a) corresponding component of x is returned. For a |
| genUType mix(genUType x, component of a that is true, the corresponding |
| genUType y, component of y is returned. |
| genBType a) |
| genBType mix(genBType x, |
| genBType y, |
| genBType a) |
| |
| Modify Section 8.11, Atomic Memory Functions |
| |
| (Modify the table on page 173 by adding "coherent" qualifier to all memory |
| variables.) |
| |
| Syntax Description |
| ---------------------------------------- --------------------------------------------------- |
| uint atomicAdd(coherent inout uint mem, Computes a new value by adding the value of data to |
| uint data) the contents mem. |
| int atomicAdd(coherent inout int mem, |
| int data) |
| |
| uint atomicMin(coherent inout uint mem, Computes a new value by taking the minimum of the |
| uint data) value of data and the contents of mem. |
| int atomicMin(coherent inout int mem, |
| int data) |
| |
| uint atomicMax(coherent inout uint mem, Computes a new value by taking the maximum of the |
| uint data) value of data and the contents of mem. |
| int atomicMax(coherent inout int mem, |
| int data) |
| |
| uint atomicAnd(coherent inout uint mem, Computes a new value by performing a bit-wise |
| uint data) AND of the value of data and the contents of mem. |
| int atomicAnd(coherent inout int mem, |
| int data) |
| |
| uint atomicOr(coherent inout uint mem, Computes a new value by performing a bit-wise OR |
| uint data) of the value of data and the contents of mem. |
| int atomicOr(coherent inout int mem, |
| int data) |
| |
| uint atomicXor(coherent inout uint mem, Computes a new value by performing a bit-wise |
| uint data) EXCLUSIVE OR of the value of data and the |
| int atomicXor(coherent inout int mem, contents of mem. |
| int data) |
| |
| uint atomicExchange( Computes a new value by simply copying the value |
| coherent inout uint mem, of data. |
| uint data) |
| int atomicExchange( |
| coherent inout int mem, |
| int data) |
| |
| uint atomicCompSwap( Compares the value of compare and the contents of |
| coherent inout uint mem, mem. If the values are equal, the new value is given |
| uint compare, by data; otherwise, it is taken from the original |
| uint data) contents of mem. |
| int atomicCompSwap( |
| coherent inout int mem, |
| int compare, |
| int data) |
| |
| Modify Section 8.12, Image Functions |
| |
| (Modify the table section listing imageAtomic* on page 175 by adding |
| the "coherent" qualifier to the image parameter and adding a new |
| imageAtomicExchange function for float data.) |
| |
| Syntax Description |
| ------------------------------ --------------------------------------------------- |
| uint imageAtomicAdd( Computes a new value by adding the value of data |
| coherent IMAGE_PARAMS, to the contents of the selected texel. |
| uint data) |
| int imageAtomicAdd( |
| coherent IMAGE_PARAMS, |
| int data) |
| |
| uint imageAtomicMin( Computes a new value by taking the minimum of the |
| coherent IMAGE_PARAMS, value of data and the contents of the selected texel. |
| uint data) |
| int imageAtomicMin( |
| coherent IMAGE_PARAMS, |
| int data) |
| |
| uint imageAtomicMax( Computes a new value by taking the maximum of the |
| coherent IMAGE_PARAMS, value data and the contents of the selected texel. |
| uint data) |
| int imageAtomicMax( |
| coherent IMAGE_PARAMS, |
| int data) |
| |
| uint imageAtomicAnd( Computes a new value by performing a bit-wise |
| coherent IMAGE_PARAMS, AND of the value of data and the contents of the |
| uint data) selected texel. |
| int imageAtomicAnd( |
| coherent IMAGE_PARAMS, |
| int data) |
| |
| uint imageAtomicOr( Computes a new value by performing a bit-wise OR |
| coherent IMAGE_PARAMS, of the value of data and the contents of the selected |
| uint data) texel. |
| int imageAtomicOr( |
| coherent IMAGE_PARAMS, |
| int data) |
| |
| uint imageAtomicXor( Computes a new value by performing a bit-wise |
| coherent IMAGE_PARAMS, EXCLUSIVE OR of the value of data and the |
| uint data) contents of the selected texel. |
| int imageAtomicXor( |
| coherent IMAGE_PARAMS, |
| int data) |
| |
| uint imageAtomicExchange( Computes a new value by simply copying the value of |
| coherent IMAGE_PARAMS, <data>. These functions support 32-bit signed and |
| uint data); unsigned integer operands, and 32-bit float operands. |
| int imageAtomicExchange( |
| coherent IMAGE_PARAMS, |
| int data); |
| float imageAtomicExchange( |
| coherent IMAGE_PARAMS, |
| float data); |
| |
| uint imageAtomicCompSwap( Compares the value of compare and the contents of |
| coherent IMAGE_PARAMS, the selected texel. If the values are equal, the new |
| uint compare, value is given by data; otherwise, it is taken from the |
| uint data) original value loaded from the texel. |
| int imageAtomicCompSwap( |
| coherent IMAGE_PARAMS, |
| int compare, |
| int data) |
| |
| Additions to the AGL/GLX/WGL Specifications |
| |
| None |
| |
| Errors |
| |
| An INVALID_VALUE is generated by MemoryBarrier or MemoryBarrierByRegion |
| if barriers is not the special value ALL_BARRIER_BITS and any of the |
| unsupported bits are set. |
| |
| New State |
| |
| (Modify Table 23.64 - Implementation Dependent Values) |
| |
| Remove IMPLEMENTATION_COLOR_READ_FORMAT and IMPLEMENTATION_COLOR_READ_TYPE. |
| |
| (Modify Table 23.76 - Implementation Dependent Aggregate Shader Limits) |
| |
| Increase the minimum required value of MAX_SHADER_STORAGE_BLOCK_SIZE to 2^27. |
| |
| (Modify Table 23.85 - Framebuffer Dependent Values) |
| |
| Add the following entries: |
| |
| Get Value Type Get Command Minimum Value Description Sec |
| -------------------------------- ---- ----------- ------------- ------------------------------ ---- |
| IMPLEMENTATION_COLOR_READ_TYPE E GetIntegerv - Implementation preferred pixel 18.2 |
| type* |
| IMPLEMENTATION_COLOR_READ_FORMAT E GetIntegerv - Implementation preferred pixel 18.2 |
| format* |
| |
| "* Unlike most framebuffer-dependent state which is queried from the currently bound |
| draw framebuffer, this state is queried from the currently bound read framebuffer." |
| |
| |
| Issues |
| |
| 1) With this extension, is OpenGL 4.4 a complete superset of OpenGL ES 3.1? |
| |
| RESOLVED: No, there are things in OpenGL ES 3.1 that were once in OpenGL |
| but have since been deprecated and removed. There is no plan to bring |
| these back into core OpenGL. Here is a list of those things: |
| |
| - Application-generated object names. |
| |
| - Client vertex and index arrays. |
| |
| - Default vertex array object. |
| |
| - ALPHA, LUMINANCE and LUMINANCE_ALPHA pixel formats. |
| |
| - RED_BITS, GREEN_BITS, BLUE_BITS, DEPTH_BITS and STENCIL_BITS. |
| |
| - GENERATE_MIPMAP_HINT and automatic mipmap generation. |
| |
| - ALIASED_POINT_SIZE_RANGE query. |
| |
| - Line widths greater than 1. |
| |
| - Query of EXTENSIONS with GetString. |
| |
| In addition the error FRAMEBUFFER_INCOMPLETE_DIMENSIONS was in ES2 and the |
| token remains in ES3 and above, but ES3 and above cannot generate this |
| error. This has not been added to OpenGL core. |
| |
| Revision History |
| |
| Rev. Date Author Changes |
| ---- -------- -------- ----------------------------------------------- |
| 15 09/19/14 Jon Leech Remove FRONT as valid <attachment>. |
| |
| 14 09/18/14 Jon Leech Add FRONT and BACK as valid <attachment>s for |
| GetFramebufferAttachmentParameteriv (Bug |
| 12695). |
| |
| 13 05/08/14 pdaniell Allow precision qualifiers to be used with any |
| opaque type, and not just samplers. |
| |
| 12 05/01/14 pdaniell Add #extension support. |
| |
| 11 04/17/14 pdaniell Improve support for the |
| IMPLEMENTATION_COLOR_READ_FORMAT and |
| IMPLEMENTATION_COLOR_READ_TYPE queries to match |
| the OpenGL ES 3.1 spec. |
| |
| 10 04/16/14 pdaniell Add ES compatibility for calling DrawBuffers |
| with BACK. |
| |
| 9 03/20/14 pdaniell Update glMemoryBarrierByRegion language to |
| match latest OpenGL ES 3.1 spec. |
| |
| 8 03/15/14 dkoch Update overview to specifically itemize the |
| additions. |
| |
| 7 03/13/14 pdaniell Remove fixes for ARB_vertex_attrib_binding |
| which have now gone into an OpenGL 4.4 update. |
| |
| 6 03/07/14 pdaniell Update language for glMemoryBarrierByRegion to |
| the latest ES 3.1 spec. |
| |
| 5 03/04/14 pdaniell Add some more built-in constants for shader |
| image load store. |
| |
| 4 03/04/14 dkoch Remove unnecessary edits (Bug 11802). |
| |
| 3 03/02/14 dkoch More complete first draft. |
| |
| 2 02/27/14 pdaniell Complete the first draft. |
| |
| 1 12/20/13 pdaniell Initial draft with overview only. |