ovr_multiview2.html (22842B)
1 <!-- 2 Copyright (c) 2019 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>WebGL OVR_multiview2 Conformance Tests</title> 12 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 13 <script src="../../js/js-test-pre.js"></script> 14 <script src="../../js/webgl-test-utils.js"></script> 15 <script src="../../js/tests/ovr_multiview2_util.js"></script> 16 <script id="requireDefine_GL_OVR_multiview2" type="x-shader/x-fragment">#version 300 es 17 #ifndef GL_OVR_multiview2 18 #error no GL_OVR_multiview2 19 #endif 20 precision highp float; 21 out vec4 my_FragColor; 22 void main() { 23 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 24 } 25 </script> 26 <script id="forbidDefine_GL_OVR_multiview" type="x-shader/x-fragment">#version 300 es 27 #ifdef GL_OVR_multiview 28 #error legacy GL_OVR_multiview support must be forbidden 29 #endif 30 precision highp float; 31 out vec4 my_FragColor; 32 void main() { 33 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 34 } 35 </script> 36 <script id="legacyMultiview1Shader" type="x-shader/x-fragment">#version 300 es 37 #extension GL_OVR_multiview: require 38 precision highp float; 39 out vec4 my_FragColor; 40 void main() { 41 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 42 } 43 </script> 44 </head> 45 <body> 46 <div id="description"></div> 47 <div id="console"></div> 48 <script> 49 "use strict"; 50 51 let wtu = WebGLTestUtils; 52 let gl = wtu.create3DContext(null, null, 2); 53 let ext = null; 54 55 function runExtensionDisabledTest() 56 { 57 debug(""); 58 debug("Testing queries with extension disabled"); 59 60 let maxViews = gl.getParameter(0x9631); 61 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query MAX_VIEWS_OVR without enabling OVR_multiview2"); 62 63 let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9630); 64 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR without enabling OVR_multiview2"); 65 let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9632); 66 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR without enabling OVR_multiview2"); 67 } 68 69 function runQueryTest() 70 { 71 debug(""); 72 debug("Testing querying MAX_VIEWS_OVR"); 73 74 let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR); 75 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from querying MAX_VIEWS_OVR"); 76 if (typeof maxViews != 'number') { 77 testFailed("Type of the value of MAX_VIEWS_OVR should be number, was " + (typeof maxViews)); 78 } 79 if (maxViews < 2) { 80 testFailed("Value of MAX_VIEWS_OVR should be at least two, was: " + maxViews); 81 } 82 } 83 84 function runDefaultFramebufferQueryTest() 85 { 86 debug(""); 87 debug("Testing querying base view index and num views on the default framebuffer"); 88 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 89 // Same behavior as FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: 90 gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR); 91 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR is INVALID_ENUM for default framebuffer"); 92 gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR); 93 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR is INVALID_ENUM for default framebuffer"); 94 } 95 96 function runInvalidTextureTypeTest() 97 { 98 debug(""); 99 debug("Testing invalid texture types"); 100 let tex2D = createTextureWithNearestFiltering(gl.TEXTURE_2D); 101 gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 128, 128); 102 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2D, 0, 0, 1); 103 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 2D texture"); 104 105 let texCube = createTextureWithNearestFiltering(gl.TEXTURE_CUBE_MAP); 106 gl.texStorage2D(gl.TEXTURE_CUBE_MAP, 1, gl.RGBA8, 128, 128); 107 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texCube, 0, 0, 1); 108 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a cube map texture"); 109 110 let tex3D = createTextureWithNearestFiltering(gl.TEXTURE_3D); 111 gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, 128, 128, 2); 112 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, 0, 2); 113 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 3D texture"); 114 } 115 116 /** 117 * If allocateStorage is true, the test will allocate texture storage. If it is false, attachments are done without allocations. 118 */ 119 function runFramebufferQueryTest(allocateStorage) 120 { 121 debug(""); 122 debug("Testing querying attachment object type, baseViewIndex, numViews and framebuffer status. Texture storage is " + (allocateStorage ? "allocated" : "not allocated") + "."); 123 124 let checkQueryResult = function(actual, expected, name) { 125 if (actual != expected) { 126 testFailed('Unexpected ' + name + ': ' + actual + ' when it was set to ' + expected); 127 } else { 128 testPassed(name + ' was ' + actual + ' when queried from the framebuffer'); 129 } 130 } 131 132 let setupAndQuery = function(colorTex, levelSet, baseViewIndexSet, numViewsSet) { 133 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, levelSet, baseViewIndexSet, numViewsSet); 134 let objectType = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); 135 if (objectType != gl.TEXTURE) { 136 testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ', should be TEXTURE'); 137 } else { 138 testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was TEXTURE'); 139 } 140 141 let level = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL); 142 checkQueryResult(level, levelSet, "level"); 143 144 let textureName = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); 145 checkQueryResult(textureName, colorTex, "texture object"); 146 147 let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR); 148 checkQueryResult(baseViewIndex, baseViewIndexSet, "baseViewIndex"); 149 150 let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR); 151 checkQueryResult(numViews, numViewsSet, "numViews"); 152 153 let layer = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER); 154 checkQueryResult(layer, baseViewIndexSet, "texture layer (should match baseViewIndex)"); 155 } 156 157 let setupSecondAttachmentAndQueryStatus = function(colorTex2, baseViewIndex, numViews, expectedStatus, msg) { 158 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, colorTex2, 0, baseViewIndex, numViews); 159 let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); 160 if (status != expectedStatus) { 161 testFailed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' did not match with the expected value: ' + wtu.glEnumToString(gl, expectedStatus) + ' - ' + msg); 162 } else { 163 testPassed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' matched with the expected value - ' + msg); 164 } 165 } 166 167 let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR); 168 169 let fb = gl.createFramebuffer(); 170 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 171 let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR); 172 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying baseViewIndex from a nonexistent attachment"); 173 if (baseViewIndex != null) { 174 testFailed('Unexpected baseViewIndex ' + baseViewIndex + ' on a framebuffer without attachments'); 175 } else { 176 testPassed('Querying baseViewIndex returned null on a framebuffer without attachments'); 177 } 178 let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR); 179 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying numViews from a nonexistent attachment"); 180 if (numViews != null) { 181 testFailed('Unexpected numViews ' + numViews + ' on a framebuffer without attachments'); 182 } else { 183 testPassed('Querying numViews returned null on a framebuffer without attachments'); 184 } 185 186 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); 187 if (allocateStorage) { 188 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 2, gl.RGBA8, 128, 128, maxViews); 189 } 190 setupAndQuery(colorTex, 0, 0, maxViews); 191 setupAndQuery(colorTex, 1, 0, 2); 192 setupAndQuery(colorTex, 0, 1, maxViews - 1); 193 194 // Test matching and mismatching attachments for framebuffer status. 195 let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); 196 if (allocateStorage) { 197 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, 128, 128, maxViews); 198 } 199 setupSecondAttachmentAndQueryStatus(colorTex2, 1, maxViews - 1, allocateStorage ? gl.FRAMEBUFFER_COMPLETE : gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 'matching baseViewIndex and numViews on different attachments'); 200 if (allocateStorage) { 201 setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'baseViewIndex mismatch'); 202 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews); 203 setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'numViews mismatch'); 204 } 205 206 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from framebuffer queries"); 207 } 208 209 function runInvalidViewsTest() 210 { 211 debug(""); 212 debug("Testing invalid out-of-range values for baseViewIndex and numViews"); 213 214 let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR); 215 let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS); 216 217 let fb = gl.createFramebuffer(); 218 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb); 219 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); 220 // Don't allocate storage since it's not needed for the validation. 221 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews + 1); 222 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified too many views"); 223 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 0); 224 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified zero views"); 225 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, -1, 2); 226 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified negative baseViewIndex"); 227 228 let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); 229 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews + 1, maxViews); 230 // baseViewIndex + numViews = (maxLayers - maxViews + 1) + maxViews = maxLayers + 1 231 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified so many views that baseViewIndex + numViews is greater than MAX_ARRAY_TEXTURE_LAYERS"); 232 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews, maxViews); 233 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex + numViews is exactly MAX_ARRAY_TEXTURE_LAYERS"); 234 } 235 236 function runDetachTest() 237 { 238 debug(""); 239 debug("Testing detaching multiview attachments"); 240 241 let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR); 242 let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS); 243 244 let fb = gl.createFramebuffer(); 245 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb); 246 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); 247 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews); 248 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, null, 0, maxLayers + 1, 0); 249 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex and numViews are not validated when detaching"); 250 let objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); 251 if (objectType != gl.NONE) { 252 testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE'); 253 } else { 254 testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach'); 255 } 256 257 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews); 258 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0); 259 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Can detach with framebufferTexture2D as well."); 260 objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); 261 if (objectType != gl.NONE) { 262 testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE'); 263 } else { 264 testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach'); 265 } 266 } 267 268 function runShaderCompileTest(extensionEnabled) 269 { 270 debug(""); 271 debug("Testing shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled")); 272 273 let prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "requireDefine_GL_OVR_multiview2"], undefined, undefined, true); 274 expectTrue(!extensionEnabled == !prog, 275 "GL_OVR_multiview2 must be defined by the preprocessor iff OVR_multiview2 is enabled by getExtension."); 276 if (extensionEnabled) { 277 prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "forbidDefine_GL_OVR_multiview"], undefined, undefined, true); 278 expectTrue(prog, "GL_OVR_multiview must never be defined by the preprocessor."); 279 280 prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "legacyMultiview1Shader"], undefined, undefined, true); 281 expectTrue(!prog, "#extension GL_OVR_multiview must be forbidden."); 282 } 283 284 if (!extensionEnabled) { 285 let multiviewShaders = [ 286 getMultiviewPassthroughVertexShader(2), 287 getMultiviewColorFragmentShader() 288 ]; 289 let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true); 290 if (testProgram) { 291 testFailed("Compilation of shaders using extension functionality succeeded when the extension is disabled, should fail."); 292 } else { 293 testPassed("Compilation of shaders using extension functionality should fail when the extension is disabled."); 294 } 295 } 296 } 297 298 function runClearTest() 299 { 300 debug(""); 301 debug("Testing that calling clear() clears all views"); 302 303 let width = 256; 304 let height = 256; 305 306 let views = gl.getParameter(ext.MAX_VIEWS_OVR); 307 308 let fb = gl.createFramebuffer(); 309 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 310 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); 311 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views); 312 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views); 313 314 gl.viewport(0, 0, width, height); 315 316 gl.clearColor(0, 1, 1, 1); 317 gl.clear(gl.COLOR_BUFFER_BIT); 318 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear"); 319 320 let readFb = gl.createFramebuffer(); 321 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb); 322 for (let viewIndex = 0; viewIndex < views; ++viewIndex) { 323 gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex); 324 let expectedColor = [0, 255, 255, 255]; 325 wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be cyan'); 326 } 327 } 328 329 function runFragmentShaderRenderTest() 330 { 331 debug(""); 332 debug("Testing rendering with different colors in fragment shader"); 333 334 let width = 256; 335 let height = 256; 336 337 let views = gl.getParameter(ext.MAX_VIEWS_OVR); 338 339 let multiviewShaders = [ 340 getMultiviewPassthroughVertexShader(views), 341 getMultiviewColorFragmentShader() 342 ]; 343 let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true); 344 if (!testProgram) { 345 testFailed("Compilation with extension enabled failed."); 346 return; 347 } 348 349 let fb = gl.createFramebuffer(); 350 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 351 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); 352 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views); 353 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views); 354 355 gl.viewport(0, 0, width, height); 356 wtu.drawUnitQuad(gl); 357 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw"); 358 359 let readFb = gl.createFramebuffer(); 360 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb); 361 for (let viewIndex = 0; viewIndex < views; ++viewIndex) { 362 gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex); 363 let expectedColor = getExpectedColor(viewIndex); 364 wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor); 365 } 366 } 367 368 function runVertexShaderRenderTest() 369 { 370 debug(""); 371 debug("Testing rendering with different colors in fragment shader, different offsets in vertex shader"); 372 373 let width = 256; 374 let height = 256; 375 376 let views = gl.getParameter(ext.MAX_VIEWS_OVR); 377 378 let multiviewShaders = [ 379 getMultiviewOffsetVertexShader(views), 380 getMultiviewColorFragmentShader() 381 ]; 382 383 let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true); 384 if (!testProgram) { 385 testFailed("Compilation with extension enabled failed."); 386 return; 387 } 388 389 let fb = gl.createFramebuffer(); 390 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 391 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); 392 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views); 393 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views); 394 395 gl.viewport(0, 0, width, height); 396 wtu.drawUnitQuad(gl); 397 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw"); 398 399 let readFb = gl.createFramebuffer(); 400 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb); 401 for (let viewIndex = 0; viewIndex < views; ++viewIndex) { 402 gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex); 403 let expectedColor = getExpectedColor(viewIndex); 404 405 checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex); 406 } 407 } 408 409 function runRealisticUseCaseRenderTest() 410 { 411 debug(""); 412 debug("Testing rendering with a different transformation matrix chosen from a uniform array according to ViewID"); 413 414 let width = 256; 415 let height = 256; 416 417 let views = gl.getParameter(ext.MAX_VIEWS_OVR); 418 419 let multiviewShaders = [ 420 getMultiviewRealisticUseCaseVertexShader(views), 421 getMultiviewColorFragmentShader() 422 ]; 423 424 let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true); 425 if (!testProgram) { 426 testFailed("Compilation with extension enabled failed."); 427 return; 428 } 429 430 let fb = gl.createFramebuffer(); 431 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 432 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); 433 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views); 434 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views); 435 436 gl.viewport(0, 0, width, height); 437 438 let transformLocation = gl.getUniformLocation(testProgram, 'transform'); 439 let transformData = new Float32Array (views * 16); 440 for (let viewIndex = 0; viewIndex < views; ++viewIndex) { 441 let scaleX = 1.0 / views; 442 // offsetX is the position of the left edge of the quad we want to get in normalized device coordinates 443 let offsetX = viewIndex / views * 2.0 - 1.0; 444 445 setupTranslateAndScaleXMatrix(transformData, viewIndex * 16, scaleX, offsetX); 446 } 447 gl.uniformMatrix4fv(transformLocation, false, transformData); 448 449 wtu.drawUnitQuad(gl); 450 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw"); 451 452 let readFb = gl.createFramebuffer(); 453 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb); 454 for (let viewIndex = 0; viewIndex < views; ++viewIndex) { 455 gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex); 456 let expectedColor = getExpectedColor(viewIndex); 457 458 checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex); 459 } 460 } 461 462 function runUniqueObjectTest() 463 { 464 debug(""); 465 debug("Testing that getExtension() returns the same object each time"); 466 gl.getExtension("OVR_multiview2").myProperty = 2; 467 webglHarnessCollectGarbage(); 468 shouldBe('gl.getExtension("OVR_multiview2").myProperty', '2'); 469 } 470 471 description("This test verifies the functionality of the OVR_multiview2 extension, if it is available."); 472 473 debug(""); 474 475 if (!gl) { 476 testFailed("WebGL context does not exist"); 477 } else { 478 testPassed("WebGL context exists"); 479 480 runExtensionDisabledTest(); 481 482 runShaderCompileTest(false); 483 484 debug(""); 485 486 if (!gl.getExtension("OVR_multiview2")) { 487 testPassed("No OVR_multiview2 support -- this is legal"); 488 } else { 489 testPassed("Successfully enabled OVR_multiview2 extension"); 490 ext = gl.getExtension('OVR_multiview2'); 491 492 runShaderCompileTest(true); 493 494 runQueryTest(); 495 496 runDefaultFramebufferQueryTest(); 497 498 runInvalidTextureTypeTest(); 499 500 runFramebufferQueryTest(true); 501 runFramebufferQueryTest(false); 502 503 runInvalidViewsTest(); 504 505 runDetachTest(); 506 507 runClearTest(); 508 509 wtu.setupUnitQuad(gl, 0, 1); 510 511 runFragmentShaderRenderTest(); 512 runVertexShaderRenderTest(); 513 runRealisticUseCaseRenderTest(); 514 runUniqueObjectTest(); 515 } 516 } 517 518 debug(""); 519 var successfullyParsed = true; 520 </script> 521 <script src="../../js/js-test-post.js"></script> 522 523 </body> 524 </html>