| Name |
| |
| AMD_framebuffer_sample_positions |
| |
| Name Strings |
| |
| GL_AMD_framebuffer_sample_positions |
| |
| Contact |
| |
| Mais Alnasser, AMD (mais.alnasser 'at' amd.com) |
| |
| Contributors |
| |
| Mais Alnasser, AMD |
| Graham Sellers, AMD |
| |
| Status |
| |
| Shipping |
| |
| Version |
| |
| Last Modified Date: 11/10/16 |
| Revision: 4 |
| |
| Number |
| |
| OpenGL Extension #454 |
| |
| Dependencies |
| |
| OpenGL 3.2 is required. |
| |
| This specification interacts with EXT_direct_state_access. |
| |
| This extension is written against the OpenGL 4.4 (Core) specification. |
| |
| Overview |
| |
| In unextended GL, the sub-pixel loations of multisampled textures and |
| renderbuffers are generally determined in an implementation dependent |
| manner. Some algorithms -- in particular custom antialiasing functions -- |
| depend on the knowledge of, or even require control over the positions of |
| samples within each pixel. |
| |
| The AMD_sample_positions extension added some control over the positions |
| of samples within a single framebuffer. However, it forced all pixels |
| within a framebuffer to have the set of sample positions. |
| |
| This extension provides a mechanism to explicitly set sample positions for |
| a framebuffer object with multi-sampled attachments in a repeating pattern, |
| allowing different pixels to use different sub-pixel locations for their |
| samples. The sample locations used by the FBO can be fixed for all pixels |
| in the FBOs attachments or they can be fixed for a sampling pattern |
| comprised of multiple pixels, where the sampling pattern is repeated over |
| all pixels. The rate of repeat of this sampling pattern size itself is |
| fixed and is implementation-dependent. |
| |
| New Tokens |
| |
| Accepted by the <pname> parameter of GetFloatv: |
| |
| SUBSAMPLE_DISTANCE_AMD 0x883F |
| |
| Accepted by the <pname> parameter of GetIntegerv: |
| |
| PIXELS_PER_SAMPLE_PATTERN_X_AMD 0x91AE |
| PIXELS_PER_SAMPLE_PATTERN_Y_AMD 0x91AF |
| |
| Accepted by the <pixelindex> parameter of FramebufferSamplePositionsfvAMD, |
| NamedFramebufferSamplePositionsfvAMD, GetFramebufferParameterfvAMD |
| and GetNamedFramebufferParameterfvAMD: |
| |
| ALL_PIXELS_AMD 0xFFFFFFFF |
| |
| |
| New Procedures and Functions |
| |
| void FramebufferSamplePositionsfvAMD(enum target, uint numsamples, |
| uint pixelindex, const float *values) |
| |
| void NamedFramebufferSamplePositionsfvAMD(uint framebuffer, |
| uint numsamples, uint pixelindex, const float *values) |
| |
| void GetFramebufferParameterfvAMD(enum target, enum pname, |
| uint numsamples, uint pixelindex, sizei size, float *values) |
| |
| void GetNamedFramebufferParameterfvAMD(uint framebuffer, |
| enum pname, uint numsamples, uint pixelindex, sizei size, |
| float *values) |
| |
| |
| Additions to Chapter 9 of the OpenGL 4.4 (Core) Specification |
| (Framebuffers and Framebuffer Objects) |
| |
| Add section 9.2.9, Framebuffer Sample Positions, p. 287 |
| |
| Sample locations can be modified for all pixels in a multi-sampled |
| framebuffer using the following command: |
| |
| void FramebufferSamplePositionsfvAMD(enum target, |
| uint numsamples, |
| uint pixelindex, |
| const float *values); |
| |
| <target> must be DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or FRAMEBUFFER. |
| <numsamples> is the number of samples to set and must be greater |
| than 0 and less than or equal to the value of SAMPLES. The error |
| INVALID_VALUE is generated if <numsamples> is outside this range. |
| <pixelindex> is the index of the pixel to set the samples for and |
| must be greater than or equal to 0 and less than the result of querying |
| PIXELS_PER_SAMPLE_PATTERN_X_AMD multiplied by the result of |
| querying PIXELS_PER_SAMPLE_PATTERN_Y_AMD. The pixels are ordered left to |
| right, top to bottom, where the origin is the upper left corner. |
| <pixelindex> may also specify ALL_PIXELS_AMD, which sets samples of all |
| pixels to the same set of locations. The error INVALID_VALUE is generated |
| if <pixelindex> is less than zero or is greater than or equal to the |
| result of querying PIXELS_PER_SAMPLE_PATTERN_X_AMD multiplied by the |
| result of querying PIXELS_PER_SAMPLE_PATTERN_Y_AMD and is not equal to |
| ALL_PIXELS_AMD. The sample locations are set by passing floating point |
| values of x and y in <values[2 * i]> and <values[2 * i + 1]> respectively, |
| all in the range [0.0, 1.0), corresponding to the <x> and <y> locations in |
| pixel space of that sample, respectively. (0.5, 0.5) thus corresponds to |
| the pixel center. The range [0.0, 0.1) implies that sample locations cannot |
| overlap at pixel boundaries. |
| |
| FramebufferSamplePositionsfvAMD generates an INVALID_OPERATION error if the |
| currently bound framebuffer is incomplete or is the default framebuffer. |
| |
| If <values> is NULL, <numSamples> is ignored and all sample positions for |
| <pixelindex> are returned to their default values. Passing ALL_PIXELS_AMD |
| therefore resets the sample positions for all pixels in the sampling |
| pattern. |
| |
| The subpixel range [0,1) is discretized based on the implementation- |
| dependent value of SUBSAMPLE_DISTANCE_AMD. GetFloatv can be used with |
| SUBSAMPLE_DISTANCE_AMD as the pname parameter to query the subpixel |
| precision, which is the same for both the vertical and horizontal |
| directions. Given two sample positions (x0, y0) and (x1, y1), one can make |
| sure they don't fall in the same subpixel if |
| |
| abs(x0 - x1) >= ssd and abs(y0 - y1) >= ssd, |
| |
| where ssd is the float value returned when querying SUBSAMPLE_DISTANCE_AMD. |
| |
| The quantized sample positions can be retrieved via the new entry point: |
| |
| void GetFramebufferParameterfvAMD(enum target, |
| enum pname, |
| uint numsamples, |
| uint pixelindex, |
| sizei size, |
| float *values); |
| |
| <target> must be DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or FRAMEBUFFER. |
| FRAMEBUFFER is equivalent to DRAW_FRAMEBUFFER. <pname> must be |
| SAMPLE_POSITIONS. <numsamples> is the number of samples to get and must |
| be greater than 0 and less than or equal to the value of SAMPLES. The |
| error INVALID_VALUE is generated if <numsamples> is outside this range. |
| <pixelindex> is the index of the pixel to set the samples for and must be |
| less than the result of querying PIXELS_PER_SAMPLE_PATTERN_X_AMD |
| multiplied by the result of querying PIXELS_PER_SAMPLE_PATTERN_Y_AMD. |
| Calling GetFramebufferParameterfvAMD with <pixelindex> within this |
| range retrieves the set of sample positions for the pixel matching |
| <pixelindex>. <pixelindex> can also be equal to ALL_PIXELS_AMD, which |
| would cause the function to return an array of the requested <numsamples> |
| per each pixel in the sampling pattern. |
| |
| The error INVALID_VALUE is generated if <pixelindex> is less than |
| zero or is greater than or equal to the result of querying |
| PIXELS_PER_SAMPLE_PATTERN_X_AMD multiplied by the result of querying |
| PIXELS_PER_SAMPLE_PATTERN_Y_AMD and is not equal to ALL_SAMPLES. The |
| samples returned are ordered per pixel, and the order of the pixels would |
| be left to right, then top to bottom, where the sampling pattern origin is |
| the upper left corner. <size> is the requested size of the retrieved sample |
| locations in bytes. <values> will contain the returned <x> and <y> |
| coordinates of the requested samples in pixel space. The sample locations |
| returned are all in the range [0, 1), corresponding to the <x> and <y> |
| locations in pixel space of that sample, respectively. (0.5, 0.5) thus |
| corresponds to the pixel center. |
| |
| The commands: |
| |
| void NamedFramebufferSamplePositionsfvAMD(uint framebuffer, |
| uint numsamples, |
| uint pixelindex, |
| const float *values); |
| |
| void GetNamedFramebufferParameterfvAMD(uint framebuffer, |
| enum pname, |
| uint numsamples, |
| uint pixelindex, |
| sizei size, |
| float *value); |
| |
| behave identically to FramebufferSamplePositionsfvAMD and |
| GetFramebufferSampleParameterfvAMD, except that the target of the |
| operation is the framebuffer object named <framebuffer> rather than |
| the object bound to a specified target. If <framebuffer> is not the name |
| of an existing framebuffer object an INVALID_OPERATION error is generated. |
| |
| Additions to Chapter 14 of the OpenGL 4.4 (Core) Specification (Fixed-Function |
| Primitive Assembly and Rasterization) |
| |
| (Modify Section 14.3, Antialiasing, p. 412) |
| |
| Add after the segment: "If the multisample mode does not have fixed sample |
| locations, the returned values may only reflect the locations of samples |
| within some pixels.", append: |
| |
| If GetMultisamplefv is used to query the result of using |
| FramebufferSamplePositionsfvAMD or NamedFramebufferSamplePositionsfvAMD |
| with ALL_PIXELS_AMD, the returned sample position matches that of |
| <pixelindex> equal to zero. |
| |
| Errors |
| |
| INVALID_VALUE is generated by FramebufferSamplePositionsfvAMD, |
| NamedFramebufferSamplePositionsfvAMD, GetFramebufferParameterfvAMD |
| and GetNamedFramebufferParameterfvAMD if numsamples is greater than |
| the value of SAMPLES. |
| |
| INVALID_VALUE is generated by FramebufferSamplePositionsfvAMD if |
| pixelindex is greater than or equal to the value of |
| NUM_PIXELS_PER_SAMPLE_PATTERN_X_AMD * NUM_PIXELS_PER_SAMPLE_PATTERN_Y_AMD |
| and is not equal to ALL_SAMPLES_AMD. |
| |
| INVALID_OPERATION is generated by FramebufferSamplePositionsfvAMD |
| if the currently bound framebuffer is the default framebuffer. |
| |
| INVALID_OPERATION is generated by NamedFramebufferSamplePositionsfvAMD |
| if the <framebuffer> is not the name of an existing framebufer object. |
| |
| INVALID_OPERATION is generated by FramebufferSamplePositionsfvAMD |
| if the currently bound framebuffer is incomplete. |
| |
| INVALID_OPERATION is generated by NamedFramebufferSamplePositionsfvAMD |
| if the <framebuffer> is incomplete. |
| |
| New State |
| |
| Add to Table 23.24, Framebuffer (state per framebuffer object), p. 545: |
| |
| Get Value Type Get Command Value Description Sec. |
| --------- ---- ----------- ----- ------------------------------ ----- |
| SAMPLE_POSITIONS 2xR+ GetFramebufferParameterfvAMD The (x, y) sample locations in 9.2.9 |
| the range [0, 1) |
| |
| New Implementation Dependent State |
| |
| Add to Table 23.11, Multisampling, p. 532: |
| |
| Get Value Type Get Command Value Description Sec. |
| --------- ------- ----------- ------- ------------------------ ----- |
| SUBSAMPLE_DISTANCE_AMD R+ GetFloatv precision step between 9.2.9 |
| subsamples |
| PIXELS_PER_SAMPLE_PATTERN_X_AMD Z+ GetIntegerv number of pixels in the 9.2.9 |
| X direction |
| PIXELS_PER_SAMPLE_PATTERN_Y_AMD Z+ GetIntegerv number of pixels in the 9.2.9 |
| Y direction |
| |
| Interaction with ARB_texture_multisample |
| |
| If ARB_texture_multisample is not supported, remove all references to |
| GetMultisamplefv. |
| |
| |
| Dependencies on EXT_direct_state_access |
| |
| If EXT_direct_state_access is not supported, remove references to the |
| Named* commands added by this extension. |
| |
| |
| Issues |
| |
| (1) What happens if an app just sets one sample position? |
| |
| RESOLVED: Any attachment to the bound FBO will have the index 0 |
| position updated. All the rest of the positions will keep their |
| original values. Any other FBOs will not be affected by this change. |
| |
| |
| (2) Should we also expose the precision? Can an app use it in setting |
| sample positions? |
| |
| RESOLVED: SUBSAMPLE_DISTANCE_AMD is added as a new token. It can be |
| used by GetFloatv to query the precision step, which will be the same |
| for both the vertical and horizontal directions. The subpixel range |
| [0,1) is discretized based on the value of SUBSAMPLE_DISTANCE_AMD. |
| Let ssd be the float value returned when SUBSAMPLE_DISTANCE_AMD is |
| queried, then one can infer the subpixilization to be 1/ssd+1. For |
| example, if ssd = 0.06667 then the pixel is subdivided into |
| 1/0.0667+1 = 16 subpixels in each dimension. |
| |
| One can also avoid using sample positions that would map to the same |
| subpixel. A coordinate c will map to the greatest multiple of ssd that |
| is less or equal to c. For example, given two sample positions, |
| (x0, y0) and (x1, y1), if abs(x1-x0) < ssd and abs(y1-y0) < ssd, then |
| both points will map to the same subpixel, which means the application |
| might want to substitute one of these positions with another that is |
| not redundant. |
| |
| Using numerical values as an example, let a = (0.201, 0.0) and |
| b = (0.25, 0.5) be sample positions and ssd = 0.06667. Both the |
| x-coordinate values 0.201 and 0.25 fall between 0.06667*3=0.2 and |
| 0.06667*4 = 0.26667 and would therefore map to the same value of 0.2. |
| The y-coordinates also map to the same value of 0 because they both |
| belong in the range [0, 0.06667). This means the two points are |
| redundant. Therefore, the application should choose a different point |
| c = (0.3, 0.45) for example. c would be a good choice because the |
| distance between its x-coordinate and a's x-coordinate is greater than |
| ssd, that is 0.3-0.201 > 0.06667. |
| |
| (3) What would be the expected results for the following scenarios: |
| |
| Scenario 1 |
| The current number of samples in the framebuffer is 8. |
| The application requests 5 sample positions and GL_ALL_PIXELS. |
| The application passes 22*2*sizeof(GLuint) as the size in bytes |
| (more than needed). |
| |
| RESOLVED: The returned array would have a capped size of |
| 20*2*sizeof(GLuint) and will contain the first 5 samples of pixel |
| (x0, y0), then the first 5 samples of pixel (x1, y0), then the first |
| 5 samples of pixel (x0, y1) and finally the first 5 samples of pixel |
| (x1, y1). |
| |
| Scenario 2 |
| The current number of samples in the framebuffer is 8. |
| The application requests 5 sample positions and GL_ALL_PIXELS. |
| The application passes 18*2*sizeof(GLuint) as the size in bytes |
| (less than needed). |
| |
| RESOLVED: The returned array would have a size of 18*2*sizeof(GLuint) |
| and will contain the first 5 samples of pixel (x0, y0), then the first |
| 5 samples of pixel (x1, y0), then the first 5 samples of pixel |
| (x0, y1) and finally the first 3 samples of pixel (x1, y1). |
| |
| Scenario 3 |
| The current number of samples in the framebuffer is 8. |
| The application requests 5 sample positions and GL_ALL_PIXELS. |
| The application passes 12*2*sizeof(GLuint) as the size in bytes |
| (less than needed). |
| |
| RESOLVED: The returned array would have a size of 12*2*sizeof(GLuint) |
| and will contain the first 5 samples of pixel (x0, y0), then the first |
| 5 samples of pixel (x1, y0), and the first 2 samples of pixel |
| (x0, y1). |
| |
| (4) What is the expected behavior of a multisampled texture is attached |
| with <fixedsamplelocations> equal to TRUE and then the application |
| attempts to set different samples per pixels in a sampling pattern? |
| |
| RESOLVED: If <fixedsamplelocations> is set to TRUE, the sample |
| positions in <pixelindex> equaling zero get replicated to all other |
| pixels in the sampling pattern. |
| |
| (5) What is the result of rendering to a framebuffer, changing its sample |
| locations and then rendering again into that framebuffer without |
| clearing it first? |
| |
| RESOLVED: The result is effectively undefined. The result of rendering |
| will not be consistent between the two passes. No ill effect should |
| come of this, but the framebuffer content may appear corrupted. |
| |
| Revision History |
| |
| Rev. Date Author Changes |
| ---- -------- -------- ----------------------------------------- |
| 4 11/10/16 malnasse Modify the 'framebuffer' parameter in |
| GetNamedFramebufferParameterfvAMD from |
| GLenum to GLuint to match the DSA style. |
| 3 11/09/16 malnasse Update PIXELS_PER_SAMPLE_PATTERN_X_AMD and |
| PIXELS_PER_SAMPLE_PATTERN_Y_AMD token values. |
| 2 04/18/14 gsellers Ready for posting. |
| 1 10/14/13 malnasse First revision. |
| |