Source code

Revision control

Copy as Markdown

Other Tools

<!--
Copyright (c) 2019 The Khronos Group Inc.
Use of this source code is governed by an MIT-style license that can be
found in the LICENSE.txt file.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGL OVR_multiview2 Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<script src="../../js/tests/ovr_multiview2_util.js"></script>
<script id="requireDefine_GL_OVR_multiview2" type="x-shader/x-fragment">#version 300 es
#ifndef GL_OVR_multiview2
#error no GL_OVR_multiview2
#endif
precision highp float;
out vec4 my_FragColor;
void main() {
my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
</script>
<script id="forbidDefine_GL_OVR_multiview" type="x-shader/x-fragment">#version 300 es
#ifdef GL_OVR_multiview
#error legacy GL_OVR_multiview support must be forbidden
#endif
precision highp float;
out vec4 my_FragColor;
void main() {
my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
</script>
<script id="legacyMultiview1Shader" type="x-shader/x-fragment">#version 300 es
#extension GL_OVR_multiview: require
precision highp float;
out vec4 my_FragColor;
void main() {
my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
</script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
let wtu = WebGLTestUtils;
let gl = wtu.create3DContext(null, null, 2);
let ext = null;
function runExtensionDisabledTest()
{
debug("");
debug("Testing queries with extension disabled");
let maxViews = gl.getParameter(0x9631);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query MAX_VIEWS_OVR without enabling OVR_multiview2");
let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9630);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR without enabling OVR_multiview2");
let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9632);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR without enabling OVR_multiview2");
}
function runQueryTest()
{
debug("");
debug("Testing querying MAX_VIEWS_OVR");
let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from querying MAX_VIEWS_OVR");
if (typeof maxViews != 'number') {
testFailed("Type of the value of MAX_VIEWS_OVR should be number, was " + (typeof maxViews));
}
if (maxViews < 2) {
testFailed("Value of MAX_VIEWS_OVR should be at least two, was: " + maxViews);
}
}
function runDefaultFramebufferQueryTest()
{
debug("");
debug("Testing querying base view index and num views on the default framebuffer");
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
// Same behavior as FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR is INVALID_ENUM for default framebuffer");
gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR is INVALID_ENUM for default framebuffer");
}
function runInvalidTextureTypeTest()
{
debug("");
debug("Testing invalid texture types");
let tex2D = createTextureWithNearestFiltering(gl.TEXTURE_2D);
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 128, 128);
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2D, 0, 0, 1);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 2D texture");
let texCube = createTextureWithNearestFiltering(gl.TEXTURE_CUBE_MAP);
gl.texStorage2D(gl.TEXTURE_CUBE_MAP, 1, gl.RGBA8, 128, 128);
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texCube, 0, 0, 1);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a cube map texture");
let tex3D = createTextureWithNearestFiltering(gl.TEXTURE_3D);
gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, 128, 128, 2);
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, 0, 2);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 3D texture");
}
/**
* If allocateStorage is true, the test will allocate texture storage. If it is false, attachments are done without allocations.
*/
function runFramebufferQueryTest(allocateStorage)
{
debug("");
debug("Testing querying attachment object type, baseViewIndex, numViews and framebuffer status. Texture storage is " + (allocateStorage ? "allocated" : "not allocated") + ".");
let checkQueryResult = function(actual, expected, name) {
if (actual != expected) {
testFailed('Unexpected ' + name + ': ' + actual + ' when it was set to ' + expected);
} else {
testPassed(name + ' was ' + actual + ' when queried from the framebuffer');
}
}
let setupAndQuery = function(colorTex, levelSet, baseViewIndexSet, numViewsSet) {
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, levelSet, baseViewIndexSet, numViewsSet);
let objectType = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
if (objectType != gl.TEXTURE) {
testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ', should be TEXTURE');
} else {
testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was TEXTURE');
}
let level = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
checkQueryResult(level, levelSet, "level");
let textureName = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
checkQueryResult(textureName, colorTex, "texture object");
let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
checkQueryResult(baseViewIndex, baseViewIndexSet, "baseViewIndex");
let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
checkQueryResult(numViews, numViewsSet, "numViews");
let layer = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
checkQueryResult(layer, baseViewIndexSet, "texture layer (should match baseViewIndex)");
}
let setupSecondAttachmentAndQueryStatus = function(colorTex2, baseViewIndex, numViews, expectedStatus, msg) {
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, colorTex2, 0, baseViewIndex, numViews);
let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status != expectedStatus) {
testFailed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' did not match with the expected value: ' + wtu.glEnumToString(gl, expectedStatus) + ' - ' + msg);
} else {
testPassed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' matched with the expected value - ' + msg);
}
}
let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying baseViewIndex from a nonexistent attachment");
if (baseViewIndex != null) {
testFailed('Unexpected baseViewIndex ' + baseViewIndex + ' on a framebuffer without attachments');
} else {
testPassed('Querying baseViewIndex returned null on a framebuffer without attachments');
}
let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying numViews from a nonexistent attachment");
if (numViews != null) {
testFailed('Unexpected numViews ' + numViews + ' on a framebuffer without attachments');
} else {
testPassed('Querying numViews returned null on a framebuffer without attachments');
}
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
if (allocateStorage) {
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 2, gl.RGBA8, 128, 128, maxViews);
}
setupAndQuery(colorTex, 0, 0, maxViews);
setupAndQuery(colorTex, 1, 0, 2);
setupAndQuery(colorTex, 0, 1, maxViews - 1);
// Test matching and mismatching attachments for framebuffer status.
let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
if (allocateStorage) {
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, 128, 128, maxViews);
}
setupSecondAttachmentAndQueryStatus(colorTex2, 1, maxViews - 1, allocateStorage ? gl.FRAMEBUFFER_COMPLETE : gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 'matching baseViewIndex and numViews on different attachments');
if (allocateStorage) {
setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'baseViewIndex mismatch');
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'numViews mismatch');
}
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from framebuffer queries");
}
function runInvalidViewsTest()
{
debug("");
debug("Testing invalid out-of-range values for baseViewIndex and numViews");
let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
// Don't allocate storage since it's not needed for the validation.
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews + 1);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified too many views");
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 0);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified zero views");
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, -1, 2);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified negative baseViewIndex");
let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews + 1, maxViews);
// baseViewIndex + numViews = (maxLayers - maxViews + 1) + maxViews = maxLayers + 1
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified so many views that baseViewIndex + numViews is greater than MAX_ARRAY_TEXTURE_LAYERS");
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews, maxViews);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex + numViews is exactly MAX_ARRAY_TEXTURE_LAYERS");
}
function runDetachTest()
{
debug("");
debug("Testing detaching multiview attachments");
let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, null, 0, maxLayers + 1, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex and numViews are not validated when detaching");
let objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
if (objectType != gl.NONE) {
testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE');
} else {
testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
}
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Can detach with framebufferTexture2D as well.");
objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
if (objectType != gl.NONE) {
testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE');
} else {
testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
}
}
function runShaderCompileTest(extensionEnabled)
{
debug("");
debug("Testing shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
let prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "requireDefine_GL_OVR_multiview2"], undefined, undefined, true);
expectTrue(!extensionEnabled == !prog,
"GL_OVR_multiview2 must be defined by the preprocessor iff OVR_multiview2 is enabled by getExtension.");
if (extensionEnabled) {
prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "forbidDefine_GL_OVR_multiview"], undefined, undefined, true);
expectTrue(prog, "GL_OVR_multiview must never be defined by the preprocessor.");
prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "legacyMultiview1Shader"], undefined, undefined, true);
expectTrue(!prog, "#extension GL_OVR_multiview must be forbidden.");
}
if (!extensionEnabled) {
let multiviewShaders = [
getMultiviewPassthroughVertexShader(2),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (testProgram) {
testFailed("Compilation of shaders using extension functionality succeeded when the extension is disabled, should fail.");
} else {
testPassed("Compilation of shaders using extension functionality should fail when the extension is disabled.");
}
}
}
function runClearTest()
{
debug("");
debug("Testing that calling clear() clears all views");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
gl.clearColor(0, 1, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = [0, 255, 255, 255];
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be cyan');
}
}
function runFragmentShaderRenderTest()
{
debug("");
debug("Testing rendering with different colors in fragment shader");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewPassthroughVertexShader(views),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex);
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
}
}
function runVertexShaderRenderTest()
{
debug("");
debug("Testing rendering with different colors in fragment shader, different offsets in vertex shader");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewOffsetVertexShader(views),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex);
checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex);
}
}
function runRealisticUseCaseRenderTest()
{
debug("");
debug("Testing rendering with a different transformation matrix chosen from a uniform array according to ViewID");
let width = 256;
let height = 256;
let views = gl.getParameter(ext.MAX_VIEWS_OVR);
let multiviewShaders = [
getMultiviewRealisticUseCaseVertexShader(views),
getMultiviewColorFragmentShader()
];
let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
if (!testProgram) {
testFailed("Compilation with extension enabled failed.");
return;
}
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
gl.viewport(0, 0, width, height);
let transformLocation = gl.getUniformLocation(testProgram, 'transform');
let transformData = new Float32Array (views * 16);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
let scaleX = 1.0 / views;
// offsetX is the position of the left edge of the quad we want to get in normalized device coordinates
let offsetX = viewIndex / views * 2.0 - 1.0;
setupTranslateAndScaleXMatrix(transformData, viewIndex * 16, scaleX, offsetX);
}
gl.uniformMatrix4fv(transformLocation, false, transformData);
wtu.drawUnitQuad(gl);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
let readFb = gl.createFramebuffer();
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
let expectedColor = getExpectedColor(viewIndex);
checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex);
}
}
function runUniqueObjectTest()
{
debug("");
debug("Testing that getExtension() returns the same object each time");
gl.getExtension("OVR_multiview2").myProperty = 2;
webglHarnessCollectGarbage();
shouldBe('gl.getExtension("OVR_multiview2").myProperty', '2');
}
description("This test verifies the functionality of the OVR_multiview2 extension, if it is available.");
debug("");
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
runExtensionDisabledTest();
runShaderCompileTest(false);
debug("");
if (!gl.getExtension("OVR_multiview2")) {
testPassed("No OVR_multiview2 support -- this is legal");
} else {
testPassed("Successfully enabled OVR_multiview2 extension");
ext = gl.getExtension('OVR_multiview2');
runShaderCompileTest(true);
runQueryTest();
runDefaultFramebufferQueryTest();
runInvalidTextureTypeTest();
runFramebufferQueryTest(true);
runFramebufferQueryTest(false);
runInvalidViewsTest();
runDetachTest();
runClearTest();
wtu.setupUnitQuad(gl, 0, 1);
runFragmentShaderRenderTest();
runVertexShaderRenderTest();
runRealisticUseCaseRenderTest();
runUniqueObjectTest();
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>