1Name 2 3 AMD_framebuffer_sample_positions 4 5Name Strings 6 7 GL_AMD_framebuffer_sample_positions 8 9Contact 10 11 Mais Alnasser, AMD (mais.alnasser 'at' amd.com) 12 13Contributors 14 15 Mais Alnasser, AMD 16 Graham Sellers, AMD 17 18Status 19 20 Shipping 21 22Version 23 24 Last Modified Date: 11/10/16 25 Revision: 4 26 27Number 28 29 OpenGL Extension #454 30 31Dependencies 32 33 OpenGL 3.2 is required. 34 35 This specification interacts with EXT_direct_state_access. 36 37 This extension is written against the OpenGL 4.4 (Core) specification. 38 39Overview 40 41 In unextended GL, the sub-pixel loations of multisampled textures and 42 renderbuffers are generally determined in an implementation dependent 43 manner. Some algorithms -- in particular custom antialiasing functions -- 44 depend on the knowledge of, or even require control over the positions of 45 samples within each pixel. 46 47 The AMD_sample_positions extension added some control over the positions 48 of samples within a single framebuffer. However, it forced all pixels 49 within a framebuffer to have the set of sample positions. 50 51 This extension provides a mechanism to explicitly set sample positions for 52 a framebuffer object with multi-sampled attachments in a repeating pattern, 53 allowing different pixels to use different sub-pixel locations for their 54 samples. The sample locations used by the FBO can be fixed for all pixels 55 in the FBO�s attachments or they can be fixed for a sampling pattern 56 comprised of multiple pixels, where the sampling pattern is repeated over 57 all pixels. The rate of repeat of this sampling pattern size itself is 58 fixed and is implementation-dependent. 59 60New Tokens 61 62 Accepted by the <pname> parameter of GetFloatv: 63 64 SUBSAMPLE_DISTANCE_AMD 0x883F 65 66 Accepted by the <pname> parameter of GetIntegerv: 67 68 PIXELS_PER_SAMPLE_PATTERN_X_AMD 0x91AE 69 PIXELS_PER_SAMPLE_PATTERN_Y_AMD 0x91AF 70 71 Accepted by the <pixelindex> parameter of FramebufferSamplePositionsfvAMD, 72 NamedFramebufferSamplePositionsfvAMD, GetFramebufferParameterfvAMD 73 and GetNamedFramebufferParameterfvAMD: 74 75 ALL_PIXELS_AMD 0xFFFFFFFF 76 77 78New Procedures and Functions 79 80 void FramebufferSamplePositionsfvAMD(enum target, uint numsamples, 81 uint pixelindex, const float *values) 82 83 void NamedFramebufferSamplePositionsfvAMD(uint framebuffer, 84 uint numsamples, uint pixelindex, const float *values) 85 86 void GetFramebufferParameterfvAMD(enum target, enum pname, 87 uint numsamples, uint pixelindex, sizei size, float *values) 88 89 void GetNamedFramebufferParameterfvAMD(uint framebuffer, 90 enum pname, uint numsamples, uint pixelindex, sizei size, 91 float *values) 92 93 94Additions to Chapter 9 of the OpenGL 4.4 (Core) Specification 95(Framebuffers and Framebuffer Objects) 96 97 Add section 9.2.9, Framebuffer Sample Positions, p. 287 98 99 Sample locations can be modified for all pixels in a multi-sampled 100 framebuffer using the following command: 101 102 void FramebufferSamplePositionsfvAMD(enum target, 103 uint numsamples, 104 uint pixelindex, 105 const float *values); 106 107 <target> must be DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or FRAMEBUFFER. 108 <numsamples> is the number of samples to set and must be greater 109 than 0 and less than or equal to the value of SAMPLES. The error 110 INVALID_VALUE is generated if <numsamples> is outside this range. 111 <pixelindex> is the index of the pixel to set the samples for and 112 must be greater than or equal to 0 and less than the result of querying 113 PIXELS_PER_SAMPLE_PATTERN_X_AMD multiplied by the result of 114 querying PIXELS_PER_SAMPLE_PATTERN_Y_AMD. The pixels are ordered left to 115 right, top to bottom, where the origin is the upper left corner. 116 <pixelindex> may also specify ALL_PIXELS_AMD, which sets samples of all 117 pixels to the same set of locations. The error INVALID_VALUE is generated 118 if <pixelindex> is less than zero or is greater than or equal to the 119 result of querying PIXELS_PER_SAMPLE_PATTERN_X_AMD multiplied by the 120 result of querying PIXELS_PER_SAMPLE_PATTERN_Y_AMD and is not equal to 121 ALL_PIXELS_AMD. The sample locations are set by passing floating point 122 values of x and y in <values[2 * i]> and <values[2 * i + 1]> respectively, 123 all in the range [0.0, 1.0), corresponding to the <x> and <y> locations in 124 pixel space of that sample, respectively. (0.5, 0.5) thus corresponds to 125 the pixel center. The range [0.0, 0.1) implies that sample locations cannot 126 overlap at pixel boundaries. 127 128 FramebufferSamplePositionsfvAMD generates an INVALID_OPERATION error if the 129 currently bound framebuffer is incomplete or is the default framebuffer. 130 131 If <values> is NULL, <numSamples> is ignored and all sample positions for 132 <pixelindex> are returned to their default values. Passing ALL_PIXELS_AMD 133 therefore resets the sample positions for all pixels in the sampling 134 pattern. 135 136 The subpixel range [0,1) is discretized based on the implementation- 137 dependent value of SUBSAMPLE_DISTANCE_AMD. GetFloatv can be used with 138 SUBSAMPLE_DISTANCE_AMD as the pname parameter to query the subpixel 139 precision, which is the same for both the vertical and horizontal 140 directions. Given two sample positions (x0, y0) and (x1, y1), one can make 141 sure they don't fall in the same subpixel if 142 143 abs(x0 - x1) >= ssd and abs(y0 - y1) >= ssd, 144 145 where ssd is the float value returned when querying SUBSAMPLE_DISTANCE_AMD. 146 147 The quantized sample positions can be retrieved via the new entry point: 148 149 void GetFramebufferParameterfvAMD(enum target, 150 enum pname, 151 uint numsamples, 152 uint pixelindex, 153 sizei size, 154 float *values); 155 156 <target> must be DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or FRAMEBUFFER. 157 FRAMEBUFFER is equivalent to DRAW_FRAMEBUFFER. <pname> must be 158 SAMPLE_POSITIONS. <numsamples> is the number of samples to get and must 159 be greater than 0 and less than or equal to the value of SAMPLES. The 160 error INVALID_VALUE is generated if <numsamples> is outside this range. 161 <pixelindex> is the index of the pixel to set the samples for and must be 162 less than the result of querying PIXELS_PER_SAMPLE_PATTERN_X_AMD 163 multiplied by the result of querying PIXELS_PER_SAMPLE_PATTERN_Y_AMD. 164 Calling GetFramebufferParameterfvAMD with <pixelindex> within this 165 range retrieves the set of sample positions for the pixel matching 166 <pixelindex>. <pixelindex> can also be equal to ALL_PIXELS_AMD, which 167 would cause the function to return an array of the requested <numsamples> 168 per each pixel in the sampling pattern. 169 170 The error INVALID_VALUE is generated if <pixelindex> is less than 171 zero or is greater than or equal to the result of querying 172 PIXELS_PER_SAMPLE_PATTERN_X_AMD multiplied by the result of querying 173 PIXELS_PER_SAMPLE_PATTERN_Y_AMD and is not equal to ALL_SAMPLES. The 174 samples returned are ordered per pixel, and the order of the pixels would 175 be left to right, then top to bottom, where the sampling pattern origin is 176 the upper left corner. <size> is the requested size of the retrieved sample 177 locations in bytes. <values> will contain the returned <x> and <y> 178 coordinates of the requested samples in pixel space. The sample locations 179 returned are all in the range [0, 1), corresponding to the <x> and <y> 180 locations in pixel space of that sample, respectively. (0.5, 0.5) thus 181 corresponds to the pixel center. 182 183 The commands: 184 185 void NamedFramebufferSamplePositionsfvAMD(uint framebuffer, 186 uint numsamples, 187 uint pixelindex, 188 const float *values); 189 190 void GetNamedFramebufferParameterfvAMD(uint framebuffer, 191 enum pname, 192 uint numsamples, 193 uint pixelindex, 194 sizei size, 195 float *value); 196 197 behave identically to FramebufferSamplePositionsfvAMD and 198 GetFramebufferSampleParameterfvAMD, except that the target of the 199 operation is the framebuffer object named <framebuffer> rather than 200 the object bound to a specified target. If <framebuffer> is not the name 201 of an existing framebuffer object an INVALID_OPERATION error is generated. 202 203Additions to Chapter 14 of the OpenGL 4.4 (Core) Specification (Fixed-Function 204Primitive Assembly and Rasterization) 205 206 (Modify Section 14.3, Antialiasing, p. 412) 207 208 Add after the segment: "If the multisample mode does not have fixed sample 209 locations, the returned values may only reflect the locations of samples 210 within some pixels.", append: 211 212 If GetMultisamplefv is used to query the result of using 213 FramebufferSamplePositionsfvAMD or NamedFramebufferSamplePositionsfvAMD 214 with ALL_PIXELS_AMD, the returned sample position matches that of 215 <pixelindex> equal to zero. 216 217Errors 218 219 INVALID_VALUE is generated by FramebufferSamplePositionsfvAMD, 220 NamedFramebufferSamplePositionsfvAMD, GetFramebufferParameterfvAMD 221 and GetNamedFramebufferParameterfvAMD if numsamples is greater than 222 the value of SAMPLES. 223 224 INVALID_VALUE is generated by FramebufferSamplePositionsfvAMD if 225 pixelindex is greater than or equal to the value of 226 NUM_PIXELS_PER_SAMPLE_PATTERN_X_AMD * NUM_PIXELS_PER_SAMPLE_PATTERN_Y_AMD 227 and is not equal to ALL_SAMPLES_AMD. 228 229 INVALID_OPERATION is generated by FramebufferSamplePositionsfvAMD 230 if the currently bound framebuffer is the default framebuffer. 231 232 INVALID_OPERATION is generated by NamedFramebufferSamplePositionsfvAMD 233 if the <framebuffer> is not the name of an existing framebufer object. 234 235 INVALID_OPERATION is generated by FramebufferSamplePositionsfvAMD 236 if the currently bound framebuffer is incomplete. 237 238 INVALID_OPERATION is generated by NamedFramebufferSamplePositionsfvAMD 239 if the <framebuffer> is incomplete. 240 241New State 242 243 Add to Table 23.24, Framebuffer (state per framebuffer object), p. 545: 244 245 Get Value Type Get Command Value Description Sec. 246 --------- ---- ----------- ----- ------------------------------ ----- 247 SAMPLE_POSITIONS 2xR+ GetFramebufferParameterfvAMD The (x, y) sample locations in 9.2.9 248 the range [0, 1) 249 250New Implementation Dependent State 251 252 Add to Table 23.11, Multisampling, p. 532: 253 254 Get Value Type Get Command Value Description Sec. 255 --------- ------- ----------- ------- ------------------------ ----- 256 SUBSAMPLE_DISTANCE_AMD R+ GetFloatv precision step between 9.2.9 257 subsamples 258 PIXELS_PER_SAMPLE_PATTERN_X_AMD Z+ GetIntegerv number of pixels in the 9.2.9 259 X direction 260 PIXELS_PER_SAMPLE_PATTERN_Y_AMD Z+ GetIntegerv number of pixels in the 9.2.9 261 Y direction 262 263Interaction with ARB_texture_multisample 264 265 If ARB_texture_multisample is not supported, remove all references to 266 GetMultisamplefv. 267 268 269Dependencies on EXT_direct_state_access 270 271 If EXT_direct_state_access is not supported, remove references to the 272 Named* commands added by this extension. 273 274 275Issues 276 277 (1) What happens if an app just sets one sample position? 278 279 RESOLVED: Any attachment to the bound FBO will have the index 0 280 position updated. All the rest of the positions will keep their 281 original values. Any other FBOs will not be affected by this change. 282 283 284 (2) Should we also expose the precision? Can an app use it in setting 285 sample positions? 286 287 RESOLVED: SUBSAMPLE_DISTANCE_AMD is added as a new token. It can be 288 used by GetFloatv to query the precision step, which will be the same 289 for both the vertical and horizontal directions. The subpixel range 290 [0,1) is discretized based on the value of SUBSAMPLE_DISTANCE_AMD. 291 Let ssd be the float value returned when SUBSAMPLE_DISTANCE_AMD is 292 queried, then one can infer the subpixilization to be 1/ssd+1. For 293 example, if ssd = 0.06667 then the pixel is subdivided into 294 1/0.0667+1 = 16 subpixels in each dimension. 295 296 One can also avoid using sample positions that would map to the same 297 subpixel. A coordinate c will map to the greatest multiple of ssd that 298 is less or equal to c. For example, given two sample positions, 299 (x0, y0) and (x1, y1), if abs(x1-x0) < ssd and abs(y1-y0) < ssd, then 300 both points will map to the same subpixel, which means the application 301 might want to substitute one of these positions with another that is 302 not redundant. 303 304 Using numerical values as an example, let a = (0.201, 0.0) and 305 b = (0.25, 0.5) be sample positions and ssd = 0.06667. Both the 306 x-coordinate values 0.201 and 0.25 fall between 0.06667*3=0.2 and 307 0.06667*4 = 0.26667 and would therefore map to the same value of 0.2. 308 The y-coordinates also map to the same value of 0 because they both 309 belong in the range [0, 0.06667). This means the two points are 310 redundant. Therefore, the application should choose a different point 311 c = (0.3, 0.45) for example. c would be a good choice because the 312 distance between its x-coordinate and a's x-coordinate is greater than 313 ssd, that is 0.3-0.201 > 0.06667. 314 315 (3) What would be the expected results for the following scenarios: 316 317 Scenario 1 318 The current number of samples in the framebuffer is 8. 319 The application requests 5 sample positions and GL_ALL_PIXELS. 320 The application passes 22*2*sizeof(GLuint) as the size in bytes 321 (more than needed). 322 323 RESOLVED: The returned array would have a capped size of 324 20*2*sizeof(GLuint) and will contain the first 5 samples of pixel 325 (x0, y0), then the first 5 samples of pixel (x1, y0), then the first 326 5 samples of pixel (x0, y1) and finally the first 5 samples of pixel 327 (x1, y1). 328 329 Scenario 2 330 The current number of samples in the framebuffer is 8. 331 The application requests 5 sample positions and GL_ALL_PIXELS. 332 The application passes 18*2*sizeof(GLuint) as the size in bytes 333 (less than needed). 334 335 RESOLVED: The returned array would have a size of 18*2*sizeof(GLuint) 336 and will contain the first 5 samples of pixel (x0, y0), then the first 337 5 samples of pixel (x1, y0), then the first 5 samples of pixel 338 (x0, y1) and finally the first 3 samples of pixel (x1, y1). 339 340 Scenario 3 341 The current number of samples in the framebuffer is 8. 342 The application requests 5 sample positions and GL_ALL_PIXELS. 343 The application passes 12*2*sizeof(GLuint) as the size in bytes 344 (less than needed). 345 346 RESOLVED: The returned array would have a size of 12*2*sizeof(GLuint) 347 and will contain the first 5 samples of pixel (x0, y0), then the first 348 5 samples of pixel (x1, y0), and the first 2 samples of pixel 349 (x0, y1). 350 351 (4) What is the expected behavior of a multisampled texture is attached 352 with <fixedsamplelocations> equal to TRUE and then the application 353 attempts to set different samples per pixels in a sampling pattern? 354 355 RESOLVED: If <fixedsamplelocations> is set to TRUE, the sample 356 positions in <pixelindex> equaling zero get replicated to all other 357 pixels in the sampling pattern. 358 359 (5) What is the result of rendering to a framebuffer, changing its sample 360 locations and then rendering again into that framebuffer without 361 clearing it first? 362 363 RESOLVED: The result is effectively undefined. The result of rendering 364 will not be consistent between the two passes. No ill effect should 365 come of this, but the framebuffer content may appear corrupted. 366 367Revision History 368 369 Rev. Date Author Changes 370 ---- -------- -------- ----------------------------------------- 371 4 11/10/16 malnasse Modify the 'framebuffer' parameter in 372 GetNamedFramebufferParameterfvAMD from 373 GLenum to GLuint to match the DSA style. 374 3 11/09/16 malnasse Update PIXELS_PER_SAMPLE_PATTERN_X_AMD and 375 PIXELS_PER_SAMPLE_PATTERN_Y_AMD token values. 376 2 04/18/14 gsellers Ready for posting. 377 1 10/14/13 malnasse First revision. 378 379