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.
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
20 precision highp float;
21 out vec4 my_FragColor;
23 my_FragColor = vec4(
0.0,
1.0,
0.0,
1.0);
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
30 precision highp float;
31 out vec4 my_FragColor;
33 my_FragColor = vec4(
0.0,
1.0,
0.0,
1.0);
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;
41 my_FragColor = vec4(
0.0,
1.0,
0.0,
1.0);
46 <div id=
"description"></div>
47 <div id=
"console"></div>
51 let wtu
= WebGLTestUtils
;
52 let gl
= wtu
.create3DContext(null, null, 2);
55 function runExtensionDisabledTest()
58 debug("Testing queries with extension disabled");
60 let maxViews
= gl
.getParameter(0x9631);
61 wtu
.glErrorShouldBe(gl
, gl
.INVALID_ENUM
, "Can't query MAX_VIEWS_OVR without enabling OVR_multiview2");
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");
69 function runQueryTest()
72 debug("Testing querying MAX_VIEWS_OVR");
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
));
80 testFailed("Value of MAX_VIEWS_OVR should be at least two, was: " + maxViews
);
84 function runDefaultFramebufferQueryTest()
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");
96 function runInvalidTextureTypeTest()
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");
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");
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");
117 * If allocateStorage is true, the test will allocate texture storage. If it is false, attachments are done without allocations.
119 function runFramebufferQueryTest(allocateStorage
)
122 debug("Testing querying attachment object type, baseViewIndex, numViews and framebuffer status. Texture storage is " + (allocateStorage
? "allocated" : "not allocated") + ".");
124 let checkQueryResult = function(actual
, expected
, name
) {
125 if (actual
!= expected
) {
126 testFailed('Unexpected ' + name
+ ': ' + actual
+ ' when it was set to ' + expected
);
128 testPassed(name
+ ' was ' + actual
+ ' when queried from the framebuffer');
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');
138 testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was TEXTURE');
141 let level
= gl
.getFramebufferAttachmentParameter(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL
);
142 checkQueryResult(level
, levelSet
, "level");
144 let textureName
= gl
.getFramebufferAttachmentParameter(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
);
145 checkQueryResult(textureName
, colorTex
, "texture object");
147 let baseViewIndex
= gl
.getFramebufferAttachmentParameter(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, ext
.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR
);
148 checkQueryResult(baseViewIndex
, baseViewIndexSet
, "baseViewIndex");
150 let numViews
= gl
.getFramebufferAttachmentParameter(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, ext
.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR
);
151 checkQueryResult(numViews
, numViewsSet
, "numViews");
153 let layer
= gl
.getFramebufferAttachmentParameter(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER
);
154 checkQueryResult(layer
, baseViewIndexSet
, "texture layer (should match baseViewIndex)");
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
);
163 testPassed('Framebuffer status: ' + wtu
.glEnumToString(gl
, status
) + ' matched with the expected value - ' + msg
);
167 let maxViews
= gl
.getParameter(ext
.MAX_VIEWS_OVR
);
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');
176 testPassed('Querying baseViewIndex returned null on a framebuffer without attachments');
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');
183 testPassed('Querying numViews returned null on a framebuffer without attachments');
186 let colorTex
= createTextureWithNearestFiltering(gl
.TEXTURE_2D_ARRAY
);
187 if (allocateStorage
) {
188 gl
.texStorage3D(gl
.TEXTURE_2D_ARRAY
, 2, gl
.RGBA8
, 128, 128, maxViews
);
190 setupAndQuery(colorTex
, 0, 0, maxViews
);
191 setupAndQuery(colorTex
, 1, 0, 2);
192 setupAndQuery(colorTex
, 0, 1, maxViews
- 1);
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
);
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');
206 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "should be no errors from framebuffer queries");
209 function runInvalidViewsTest()
212 debug("Testing invalid out-of-range values for baseViewIndex and numViews");
214 let maxViews
= gl
.getParameter(ext
.MAX_VIEWS_OVR
);
215 let maxLayers
= gl
.getParameter(gl
.MAX_ARRAY_TEXTURE_LAYERS
);
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");
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");
236 function runDetachTest()
239 debug("Testing detaching multiview attachments");
241 let maxViews
= gl
.getParameter(ext
.MAX_VIEWS_OVR
);
242 let maxLayers
= gl
.getParameter(gl
.MAX_ARRAY_TEXTURE_LAYERS
);
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');
254 testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
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');
264 testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
268 function runShaderCompileTest(extensionEnabled
)
271 debug("Testing shader compiles with extension " + (extensionEnabled
? "enabled" : "disabled"));
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.");
280 prog
= wtu
.setupProgram(gl
, [wtu
.simpleVertexShaderESSL300
, "legacyMultiview1Shader"], undefined, undefined, true);
281 expectTrue(!prog
, "#extension GL_OVR_multiview must be forbidden.");
284 if (!extensionEnabled
) {
285 let multiviewShaders
= [
286 getMultiviewPassthroughVertexShader(2),
287 getMultiviewColorFragmentShader()
289 let testProgram
= wtu
.setupProgram(gl
, multiviewShaders
, ['a_position'], [0], true);
291 testFailed("Compilation of shaders using extension functionality succeeded when the extension is disabled, should fail.");
293 testPassed("Compilation of shaders using extension functionality should fail when the extension is disabled.");
298 function runClearTest()
301 debug("Testing that calling clear() clears all views");
306 let views
= gl
.getParameter(ext
.MAX_VIEWS_OVR
);
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
);
314 gl
.viewport(0, 0, width
, height
);
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");
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');
329 function runFragmentShaderRenderTest()
332 debug("Testing rendering with different colors in fragment shader");
337 let views
= gl
.getParameter(ext
.MAX_VIEWS_OVR
);
339 let multiviewShaders
= [
340 getMultiviewPassthroughVertexShader(views
),
341 getMultiviewColorFragmentShader()
343 let testProgram
= wtu
.setupProgram(gl
, multiviewShaders
, ['a_position'], [0], true);
345 testFailed("Compilation with extension enabled failed.");
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
);
355 gl
.viewport(0, 0, width
, height
);
356 wtu
.drawUnitQuad(gl
);
357 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "should be no errors from draw");
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
);
368 function runVertexShaderRenderTest()
371 debug("Testing rendering with different colors in fragment shader, different offsets in vertex shader");
376 let views
= gl
.getParameter(ext
.MAX_VIEWS_OVR
);
378 let multiviewShaders
= [
379 getMultiviewOffsetVertexShader(views
),
380 getMultiviewColorFragmentShader()
383 let testProgram
= wtu
.setupProgram(gl
, multiviewShaders
, ['a_position'], [0], true);
385 testFailed("Compilation with extension enabled failed.");
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
);
395 gl
.viewport(0, 0, width
, height
);
396 wtu
.drawUnitQuad(gl
);
397 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "should be no errors from draw");
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
);
405 checkVerticalStrip(width
, height
, views
, viewIndex
, expectedColor
, 'view ' + viewIndex
);
409 function runRealisticUseCaseRenderTest()
412 debug("Testing rendering with a different transformation matrix chosen from a uniform array according to ViewID");
417 let views
= gl
.getParameter(ext
.MAX_VIEWS_OVR
);
419 let multiviewShaders
= [
420 getMultiviewRealisticUseCaseVertexShader(views
),
421 getMultiviewColorFragmentShader()
424 let testProgram
= wtu
.setupProgram(gl
, multiviewShaders
, ['a_position'], [0], true);
426 testFailed("Compilation with extension enabled failed.");
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
);
436 gl
.viewport(0, 0, width
, height
);
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;
445 setupTranslateAndScaleXMatrix(transformData
, viewIndex
* 16, scaleX
, offsetX
);
447 gl
.uniformMatrix4fv(transformLocation
, false, transformData
);
449 wtu
.drawUnitQuad(gl
);
450 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "should be no errors from draw");
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
);
458 checkVerticalStrip(width
, height
, views
, viewIndex
, expectedColor
, 'view ' + viewIndex
);
462 function runUniqueObjectTest()
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');
471 description("This test verifies the functionality of the OVR_multiview2 extension, if it is available.");
476 testFailed("WebGL context does not exist");
478 testPassed("WebGL context exists");
480 runExtensionDisabledTest();
482 runShaderCompileTest(false);
486 if (!gl
.getExtension("OVR_multiview2")) {
487 testPassed("No OVR_multiview2 support -- this is legal");
489 testPassed("Successfully enabled OVR_multiview2 extension");
490 ext
= gl
.getExtension('OVR_multiview2');
492 runShaderCompileTest(true);
496 runDefaultFramebufferQueryTest();
498 runInvalidTextureTypeTest();
500 runFramebufferQueryTest(true);
501 runFramebufferQueryTest(false);
503 runInvalidViewsTest();
509 wtu
.setupUnitQuad(gl
, 0, 1);
511 runFragmentShaderRenderTest();
512 runVertexShaderRenderTest();
513 runRealisticUseCaseRenderTest();
514 runUniqueObjectTest();
519 var successfullyParsed
= true;
521 <script src=
"../../js/js-test-post.js"></script>