blob: 9cc52ec79cb4990db9bff2bb86f58a1dc16bc783 [file] [log] [blame]
Martin Radev14a26ae2017-07-24 15:56:29 +03001//
2// Copyright 2017 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// Multiview draw tests:
7// Test issuing multiview Draw* commands.
8//
9
Martin Radevc1d4e552017-08-21 12:01:10 +030010#include "platform/WorkaroundsD3D.h"
Olli Etuahof26b27e2018-08-17 11:01:19 +030011#include "test_utils/MultiviewTest.h"
Martin Radev14a26ae2017-07-24 15:56:29 +030012#include "test_utils/gl_raii.h"
13
14using namespace angle;
15
Martin Radev61bd9992017-08-11 13:10:55 +030016namespace
17{
Martin Radev61bd9992017-08-11 13:10:55 +030018
19std::vector<Vector2> ConvertPixelCoordinatesToClipSpace(const std::vector<Vector2I> &pixels,
20 int width,
21 int height)
22{
23 std::vector<Vector2> result(pixels.size());
24 for (size_t i = 0; i < pixels.size(); ++i)
25 {
26 const auto &pixel = pixels[i];
27 float pixelCenterRelativeX = (static_cast<float>(pixel.x()) + .5f) / width;
28 float pixelCenterRelativeY = (static_cast<float>(pixel.y()) + .5f) / height;
29 float xInClipSpace = 2.f * pixelCenterRelativeX - 1.f;
30 float yInClipSpace = 2.f * pixelCenterRelativeY - 1.f;
31 result[i] = Vector2(xInClipSpace, yInClipSpace);
32 }
33 return result;
34}
35} // namespace
36
Olli Etuahof26b27e2018-08-17 11:01:19 +030037struct MultiviewRenderTestParams final : public MultiviewImplementationParams
Martin Radev3c25ad02017-08-22 17:36:53 +030038{
Olli Etuahof26b27e2018-08-17 11:01:19 +030039 MultiviewRenderTestParams(GLenum multiviewLayout,
40 const MultiviewImplementationParams &implementationParams)
Martin Radevc1d4e552017-08-21 12:01:10 +030041 : MultiviewImplementationParams(implementationParams), mMultiviewLayout(multiviewLayout)
Martin Radev3c25ad02017-08-22 17:36:53 +030042 {
43 ASSERT(multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE ||
44 multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
45 }
46 GLenum mMultiviewLayout;
47};
48
Olli Etuahof26b27e2018-08-17 11:01:19 +030049std::ostream &operator<<(std::ostream &os, const MultiviewRenderTestParams &params)
Martin Radev3c25ad02017-08-22 17:36:53 +030050{
Martin Radevc1d4e552017-08-21 12:01:10 +030051 const MultiviewImplementationParams &base =
52 static_cast<const MultiviewImplementationParams &>(params);
Martin Radev3c25ad02017-08-22 17:36:53 +030053 os << base;
54 switch (params.mMultiviewLayout)
55 {
56 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
57 os << "_layered";
58 break;
59 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
60 os << "_side_by_side";
61 break;
62 default:
63 UNREACHABLE();
64 }
65 return os;
66}
67
Olli Etuaho4836acc2018-08-20 15:23:18 +030068class MultiviewFramebufferTestBase : public MultiviewTestBase
Martin Radev8f276e22017-05-30 12:05:52 +030069{
70 protected:
Olli Etuaho4836acc2018-08-20 15:23:18 +030071 MultiviewFramebufferTestBase(const PlatformParameters &params, GLenum multiviewLayout)
Olli Etuahof26b27e2018-08-17 11:01:19 +030072 : MultiviewTestBase(params),
Martin Radev3c25ad02017-08-22 17:36:53 +030073 mViewWidth(0),
74 mViewHeight(0),
Olli Etuaho4836acc2018-08-20 15:23:18 +030075 mNumViews(0),
76 mMultiviewLayout(multiviewLayout)
Martin Radev8f276e22017-05-30 12:05:52 +030077 {
Martin Radev3c25ad02017-08-22 17:36:53 +030078 }
Olli Etuaho4836acc2018-08-20 15:23:18 +030079 void FramebufferTestSetUp() { MultiviewTestBase::MultiviewTestBaseSetUp(); }
80 void updateFBOs(int viewWidth, int height, int numViews, int numLayers, int baseViewIndex)
Martin Radev3c25ad02017-08-22 17:36:53 +030081 {
Martin Radev72b4e1e2017-08-31 15:42:56 +030082 ASSERT(numViews + baseViewIndex <= numLayers);
83
Martin Radev3c25ad02017-08-22 17:36:53 +030084 mViewWidth = viewWidth;
85 mViewHeight = height;
86 mNumViews = numViews;
Martin Radev8f276e22017-05-30 12:05:52 +030087
Martin Radev0abb7a22017-08-28 15:34:45 +030088 mColorTexture.reset();
89 mDepthTexture.reset();
90 mDrawFramebuffer.reset();
91 mReadFramebuffer.clear();
92
Martin Radev8f276e22017-05-30 12:05:52 +030093 // Create color and depth textures.
Martin Radev3c25ad02017-08-22 17:36:53 +030094 switch (mMultiviewLayout)
Martin Radev8f276e22017-05-30 12:05:52 +030095 {
Martin Radev3c25ad02017-08-22 17:36:53 +030096 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
97 {
98 int textureWidth = viewWidth * numViews;
99 glBindTexture(GL_TEXTURE_2D, mColorTexture);
100 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, height, 0, GL_RGBA,
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500101 GL_UNSIGNED_BYTE, nullptr);
Martin Radev3c25ad02017-08-22 17:36:53 +0300102 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
104
105 glBindTexture(GL_TEXTURE_2D, mDepthTexture);
106 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, textureWidth, height, 0,
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500107 GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
Martin Radev3c25ad02017-08-22 17:36:53 +0300108 glBindTexture(GL_TEXTURE_2D, 0);
109 break;
110 }
111 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
112 glBindTexture(GL_TEXTURE_2D_ARRAY, mColorTexture);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300113 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, viewWidth, height, numLayers, 0,
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500114 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev3c25ad02017-08-22 17:36:53 +0300115 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
116 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
117
118 glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthTexture);
119 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, viewWidth, height,
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500120 numLayers, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
Martin Radev3c25ad02017-08-22 17:36:53 +0300121 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
122 break;
123 default:
124 UNREACHABLE();
Martin Radev8f276e22017-05-30 12:05:52 +0300125 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300126 ASSERT_GL_NO_ERROR();
127
128 // Create draw framebuffer to be used for multiview rendering.
129 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
130 switch (mMultiviewLayout)
131 {
132 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
133 {
134 std::vector<GLint> viewportOffsets(numViews * 2);
135 for (int i = 0u; i < numViews; ++i)
136 {
137 viewportOffsets[i * 2] = i * viewWidth;
138 viewportOffsets[i * 2 + 1] = 0;
139 }
140 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER,
141 GL_COLOR_ATTACHMENT0, mColorTexture, 0,
142 numViews, &viewportOffsets[0]);
143 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER,
144 GL_DEPTH_ATTACHMENT, mDepthTexture, 0,
145 numViews, &viewportOffsets[0]);
146 break;
147 }
148 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
149 glFramebufferTextureMultiviewLayeredANGLE(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
Martin Radev72b4e1e2017-08-31 15:42:56 +0300150 mColorTexture, 0, baseViewIndex,
151 numViews);
Martin Radev3c25ad02017-08-22 17:36:53 +0300152 glFramebufferTextureMultiviewLayeredANGLE(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
Martin Radev72b4e1e2017-08-31 15:42:56 +0300153 mDepthTexture, 0, baseViewIndex,
154 numViews);
Martin Radev3c25ad02017-08-22 17:36:53 +0300155 break;
156 default:
157 UNREACHABLE();
158 }
Martin Radev8f276e22017-05-30 12:05:52 +0300159
160 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
161 glDrawBuffers(1, DrawBuffers);
162 ASSERT_GL_NO_ERROR();
163 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
164
165 // Create read framebuffer to be used to retrieve the pixel information for testing
166 // purposes.
Martin Radev3c25ad02017-08-22 17:36:53 +0300167 switch (mMultiviewLayout)
168 {
169 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
170 mReadFramebuffer.resize(1);
171 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[0]);
172 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
173 mColorTexture, 0);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300174 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
175 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
Martin Radev3c25ad02017-08-22 17:36:53 +0300176 break;
177 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Martin Radev72b4e1e2017-08-31 15:42:56 +0300178 mReadFramebuffer.resize(numLayers);
179 for (int i = 0; i < numLayers; ++i)
Martin Radev3c25ad02017-08-22 17:36:53 +0300180 {
Martin Radev72b4e1e2017-08-31 15:42:56 +0300181 glBindFramebuffer(GL_FRAMEBUFFER, mReadFramebuffer[i]);
182 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mColorTexture,
183 0, i);
184 glClearColor(0, 0, 0, 0);
185 glClear(GL_COLOR_BUFFER_BIT);
186 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
187 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
Martin Radev3c25ad02017-08-22 17:36:53 +0300188 }
Martin Radev72b4e1e2017-08-31 15:42:56 +0300189 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
Martin Radev3c25ad02017-08-22 17:36:53 +0300190 break;
191 default:
192 UNREACHABLE();
193 }
Martin Radev8f276e22017-05-30 12:05:52 +0300194
195 // Clear the buffers.
Martin Radev3c25ad02017-08-22 17:36:53 +0300196 glViewport(0, 0, viewWidth, height);
197 if (mMultiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE)
198 {
199 // Enable the scissor test only for side-by-side framebuffers.
200 glEnable(GL_SCISSOR_TEST);
201 glScissor(0, 0, viewWidth, height);
202 }
Martin Radev61bd9992017-08-11 13:10:55 +0300203 glClearColor(0, 0, 0, 1);
Martin Radev8f276e22017-05-30 12:05:52 +0300204 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev3c25ad02017-08-22 17:36:53 +0300205 }
Martin Radev8f276e22017-05-30 12:05:52 +0300206
Olli Etuaho4836acc2018-08-20 15:23:18 +0300207 void updateFBOs(int viewWidth, int height, int numViews)
Martin Radev72b4e1e2017-08-31 15:42:56 +0300208 {
Olli Etuaho4836acc2018-08-20 15:23:18 +0300209 updateFBOs(viewWidth, height, numViews, numViews, 0);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300210 }
211
Olli Etuaho4836acc2018-08-20 15:23:18 +0300212 void bindMemberDrawFramebuffer() { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer); }
213
Martin Radev3c25ad02017-08-22 17:36:53 +0300214 GLColor GetViewColor(int x, int y, int view)
215 {
216 switch (mMultiviewLayout)
217 {
218 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
219 return ReadColor(view * mViewWidth + x, y);
220 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
221 ASSERT(static_cast<size_t>(view) < mReadFramebuffer.size());
222 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[view]);
223 return ReadColor(x, y);
224 default:
225 UNREACHABLE();
226 }
227 return GLColor(0, 0, 0, 0);
Martin Radev8f276e22017-05-30 12:05:52 +0300228 }
229
230 GLTexture mColorTexture;
231 GLTexture mDepthTexture;
Martin Radev3c25ad02017-08-22 17:36:53 +0300232 int mViewWidth;
233 int mViewHeight;
234 int mNumViews;
Olli Etuaho4836acc2018-08-20 15:23:18 +0300235
236 private:
237 GLFramebuffer mDrawFramebuffer;
238 std::vector<GLFramebuffer> mReadFramebuffer;
239 GLenum mMultiviewLayout;
Martin Radev8f276e22017-05-30 12:05:52 +0300240};
241
Olli Etuaho4836acc2018-08-20 15:23:18 +0300242class MultiviewRenderTest : public MultiviewFramebufferTestBase,
Olli Etuahof26b27e2018-08-17 11:01:19 +0300243 public ::testing::TestWithParam<MultiviewRenderTestParams>
Martin Radev8f276e22017-05-30 12:05:52 +0300244{
245 protected:
Olli Etuaho4836acc2018-08-20 15:23:18 +0300246 MultiviewRenderTest() : MultiviewFramebufferTestBase(GetParam(), GetParam().mMultiviewLayout) {}
247 void SetUp() override { MultiviewFramebufferTestBase::FramebufferTestSetUp(); }
Martin Radevc1d4e552017-08-21 12:01:10 +0300248
249 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) override
250 {
251 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
252 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300253};
254
Jamie Madill04c084d2018-08-08 15:49:28 -0400255constexpr char kDualViewVSSource[] = R"(#version 300 es
256#extension GL_OVR_multiview : require
257layout(num_views = 2) in;
258in vec4 vPosition;
259void main()
260{
261 gl_Position.x = (gl_ViewID_OVR == 0u ? vPosition.x*0.5 + 0.5 : vPosition.x*0.5);
262 gl_Position.yzw = vPosition.yzw;
263})";
264
265constexpr char kDualViewFSSource[] = R"(#version 300 es
266#extension GL_OVR_multiview : require
267precision mediump float;
268out vec4 col;
269void main()
270{
271 col = vec4(0,1,0,1);
272})";
273
Martin Radev3c25ad02017-08-22 17:36:53 +0300274class MultiviewRenderDualViewTest : public MultiviewRenderTest
275{
276 protected:
277 MultiviewRenderDualViewTest() : mProgram(0u) {}
278 ~MultiviewRenderDualViewTest()
Martin Radev8f276e22017-05-30 12:05:52 +0300279 {
280 if (mProgram != 0u)
281 {
282 glDeleteProgram(mProgram);
283 }
284 }
285
286 void SetUp() override
287 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300288 MultiviewRenderTest::SetUp();
Martin Radev8f276e22017-05-30 12:05:52 +0300289
290 if (!requestMultiviewExtension())
291 {
292 return;
293 }
294
Olli Etuaho4836acc2018-08-20 15:23:18 +0300295 updateFBOs(2, 1, 2);
Jamie Madill04c084d2018-08-08 15:49:28 -0400296 mProgram = CompileProgram(kDualViewVSSource, kDualViewFSSource);
Martin Radev61bd9992017-08-11 13:10:55 +0300297 ASSERT_NE(mProgram, 0u);
Martin Radev8f276e22017-05-30 12:05:52 +0300298 glUseProgram(mProgram);
299 ASSERT_GL_NO_ERROR();
300 }
301
302 void checkOutput()
303 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300304 EXPECT_EQ(GLColor::black, GetViewColor(0, 0, 0));
Martin Radev67a8a012017-09-08 13:03:52 +0300305 EXPECT_EQ(GLColor::green, GetViewColor(1, 0, 0));
306 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev3c25ad02017-08-22 17:36:53 +0300307 EXPECT_EQ(GLColor::black, GetViewColor(1, 0, 1));
Martin Radev8f276e22017-05-30 12:05:52 +0300308 }
309
310 GLuint mProgram;
311};
312
Jamie Madill04c084d2018-08-08 15:49:28 -0400313class MultiviewDrawValidationTest : public MultiviewRenderDualViewTest
314{
315 protected:
316 MultiviewDrawValidationTest() {}
317
318 void SetUp() override
319 {
320 MultiviewRenderDualViewTest::SetUp();
321
322 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
323
324 glBindTexture(GL_TEXTURE_2D, mTex2d);
325 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
326
327 glBindVertexArray(mVao);
328
329 const float kVertexData[3] = {0.0f};
330 glBindBuffer(GL_ARRAY_BUFFER, mVbo);
331 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3u, &kVertexData[0], GL_STATIC_DRAW);
332
333 const unsigned int kIndices[3] = {0u, 1u, 2u};
334 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIbo);
335 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3, &kIndices[0],
336 GL_STATIC_DRAW);
337 ASSERT_GL_NO_ERROR();
338 }
339
340 GLTexture mTex2d;
341 GLVertexArray mVao;
342 GLBuffer mVbo;
343 GLBuffer mIbo;
344 GLFramebuffer mFramebuffer;
345};
346
Martin Radev3c25ad02017-08-22 17:36:53 +0300347class MultiviewOcclusionQueryTest : public MultiviewRenderTest
Martin Radev0d671c92017-08-10 16:41:52 +0300348{
349 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300350 MultiviewOcclusionQueryTest() {}
Martin Radev0d671c92017-08-10 16:41:52 +0300351
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400352 bool requestOcclusionQueryExtension()
353 {
354 if (extensionRequestable("GL_EXT_occlusion_query_boolean"))
355 {
356 glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean");
357 }
358
359 if (!extensionEnabled("GL_EXT_occlusion_query_boolean"))
360 {
361 std::cout << "Test skipped due to missing GL_EXT_occlusion_query_boolean." << std::endl;
362 return false;
363 }
364 return true;
365 }
366
Martin Radev0d671c92017-08-10 16:41:52 +0300367 GLuint drawAndRetrieveOcclusionQueryResult(GLuint program)
368 {
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400369 GLQueryEXT query;
370 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED, query);
Martin Radev0d671c92017-08-10 16:41:52 +0300371 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
372 glEndQueryEXT(GL_ANY_SAMPLES_PASSED);
373
374 GLuint result = GL_TRUE;
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400375 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT, &result);
Martin Radev0d671c92017-08-10 16:41:52 +0300376 return result;
377 }
378};
379
Martin Radev3c25ad02017-08-22 17:36:53 +0300380class MultiviewProgramGenerationTest : public MultiviewRenderTest
Martin Radev41ac68e2017-06-06 12:16:58 +0300381{
382 protected:
383 MultiviewProgramGenerationTest() {}
384};
385
Martin Radev3c25ad02017-08-22 17:36:53 +0300386class MultiviewRenderPrimitiveTest : public MultiviewRenderTest
Martin Radev61bd9992017-08-11 13:10:55 +0300387{
388 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300389 MultiviewRenderPrimitiveTest() {}
Martin Radev61bd9992017-08-11 13:10:55 +0300390
391 void setupGeometry(const std::vector<Vector2> &vertexData)
392 {
Martin Radev61bd9992017-08-11 13:10:55 +0300393 glBindBuffer(GL_ARRAY_BUFFER, mVBO);
394 glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(Vector2), vertexData.data(),
395 GL_STATIC_DRAW);
396 glEnableVertexAttribArray(0);
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500397 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
Martin Radev61bd9992017-08-11 13:10:55 +0300398 }
399
Martin Radev67a8a012017-09-08 13:03:52 +0300400 void checkGreenChannel(const GLubyte expectedGreenChannelData[])
Martin Radev61bd9992017-08-11 13:10:55 +0300401 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300402 for (int view = 0; view < mNumViews; ++view)
Martin Radev61bd9992017-08-11 13:10:55 +0300403 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300404 for (int w = 0; w < mViewWidth; ++w)
Martin Radev61bd9992017-08-11 13:10:55 +0300405 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300406 for (int h = 0; h < mViewHeight; ++h)
407 {
408 size_t flatIndex =
409 static_cast<size_t>(view * mViewWidth * mViewHeight + mViewWidth * h + w);
Martin Radev67a8a012017-09-08 13:03:52 +0300410 EXPECT_EQ(GLColor(0, expectedGreenChannelData[flatIndex], 0, 255),
Martin Radev3c25ad02017-08-22 17:36:53 +0300411 GetViewColor(w, h, view));
412 }
Martin Radev61bd9992017-08-11 13:10:55 +0300413 }
414 }
415 }
Martin Radev61bd9992017-08-11 13:10:55 +0300416 GLBuffer mVBO;
417};
418
Olli Etuaho4836acc2018-08-20 15:23:18 +0300419class MultiviewSideBySideRenderTest : public MultiviewFramebufferTestBase,
Martin Radevc1d4e552017-08-21 12:01:10 +0300420 public ::testing::TestWithParam<MultiviewImplementationParams>
Martin Radev3c25ad02017-08-22 17:36:53 +0300421{
422 protected:
423 MultiviewSideBySideRenderTest()
Olli Etuaho4836acc2018-08-20 15:23:18 +0300424 : MultiviewFramebufferTestBase(GetParam(), GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE)
Martin Radev3c25ad02017-08-22 17:36:53 +0300425 {
426 }
Olli Etuaho4836acc2018-08-20 15:23:18 +0300427 void SetUp() override { MultiviewFramebufferTestBase::FramebufferTestSetUp(); }
Martin Radevc1d4e552017-08-21 12:01:10 +0300428 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) override
429 {
430 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
431 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300432};
433
Olli Etuaho4836acc2018-08-20 15:23:18 +0300434class MultiviewLayeredRenderTest : public MultiviewFramebufferTestBase,
Martin Radevc1d4e552017-08-21 12:01:10 +0300435 public ::testing::TestWithParam<MultiviewImplementationParams>
Martin Radev72b4e1e2017-08-31 15:42:56 +0300436{
437 protected:
438 MultiviewLayeredRenderTest()
Olli Etuaho4836acc2018-08-20 15:23:18 +0300439 : MultiviewFramebufferTestBase(GetParam(), GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE)
Martin Radev72b4e1e2017-08-31 15:42:56 +0300440 {
441 }
Olli Etuaho4836acc2018-08-20 15:23:18 +0300442 void SetUp() override { MultiviewFramebufferTestBase::FramebufferTestSetUp(); }
Martin Radevc1d4e552017-08-21 12:01:10 +0300443 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) override
444 {
445 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
446 }
Martin Radev72b4e1e2017-08-31 15:42:56 +0300447};
448
Martin Radev14a26ae2017-07-24 15:56:29 +0300449// The test verifies that glDraw*Indirect:
450// 1) generates an INVALID_OPERATION error if the number of views in the draw framebuffer is greater
451// than 1.
452// 2) does not generate any error if the draw framebuffer has exactly 1 view.
Martin Radev7cf61662017-07-26 17:10:53 +0300453TEST_P(MultiviewDrawValidationTest, IndirectDraw)
Martin Radev14a26ae2017-07-24 15:56:29 +0300454{
455 if (!requestMultiviewExtension())
456 {
457 return;
458 }
459
Martin Radev14a26ae2017-07-24 15:56:29 +0300460 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Martin Radev14a26ae2017-07-24 15:56:29 +0300461
462 const std::string fsSource =
463 "#version 300 es\n"
464 "#extension GL_OVR_multiview : require\n"
465 "precision mediump float;\n"
466 "void main()\n"
467 "{}\n";
468
Martin Radev14a26ae2017-07-24 15:56:29 +0300469 GLBuffer commandBuffer;
470 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, commandBuffer);
471 const GLuint commandData[] = {1u, 1u, 0u, 0u, 0u};
472 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(GLuint) * 5u, &commandData[0], GL_STATIC_DRAW);
473 ASSERT_GL_NO_ERROR();
474
Martin Radev14a26ae2017-07-24 15:56:29 +0300475 // Check for a GL_INVALID_OPERATION error with the framebuffer having 2 views.
476 {
477 const std::string &vsSource =
478 "#version 300 es\n"
479 "#extension GL_OVR_multiview : require\n"
480 "layout(num_views = 2) in;\n"
481 "void main()\n"
482 "{}\n";
483 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
484 glUseProgram(program);
485
Martin Radev7cf61662017-07-26 17:10:53 +0300486 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
487 0, 2, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300488
489 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
490 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
491
492 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
493 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
494 }
495
496 // Check that no errors are generated if the number of views is 1.
497 {
498 const std::string &vsSource =
499 "#version 300 es\n"
500 "#extension GL_OVR_multiview : require\n"
501 "layout(num_views = 1) in;\n"
502 "void main()\n"
503 "{}\n";
504 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
505 glUseProgram(program);
506
Martin Radev7cf61662017-07-26 17:10:53 +0300507 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
508 0, 1, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300509
510 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
511 EXPECT_GL_NO_ERROR();
512
513 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
514 EXPECT_GL_NO_ERROR();
515 }
516}
517
Martin Radev7cf61662017-07-26 17:10:53 +0300518// The test verifies that glDraw*:
519// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer and
520// program differs.
521// 2) does not generate any error if the number of views is the same.
Martin Radev7cf61662017-07-26 17:10:53 +0300522TEST_P(MultiviewDrawValidationTest, NumViewsMismatch)
523{
524 if (!requestMultiviewExtension())
525 {
526 return;
527 }
528
529 const GLint viewportOffsets[4] = {0, 0, 2, 0};
530
531 const std::string &vsSource =
532 "#version 300 es\n"
533 "#extension GL_OVR_multiview : require\n"
534 "layout(num_views = 2) in;\n"
535 "void main()\n"
536 "{}\n";
537 const std::string &fsSource =
538 "#version 300 es\n"
539 "#extension GL_OVR_multiview : require\n"
540 "precision mediump float;\n"
541 "void main()\n"
542 "{}\n";
543 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
544 glUseProgram(program);
545
546 // Check for a GL_INVALID_OPERATION error with the framebuffer and program having different
547 // number of views.
548 {
549 // The framebuffer has only 1 view.
550 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
551 0, 1, &viewportOffsets[0]);
552
553 glDrawArrays(GL_TRIANGLES, 0, 3);
554 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
555
556 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
557 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
558 }
559
560 // Check that no errors are generated if the number of views in both program and draw
561 // framebuffer matches.
562 {
563 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
564 0, 2, &viewportOffsets[0]);
565
566 glDrawArrays(GL_TRIANGLES, 0, 3);
567 EXPECT_GL_NO_ERROR();
568
569 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
570 EXPECT_GL_NO_ERROR();
571 }
Martin Radevda8e2572017-09-12 17:21:16 +0300572}
Martin Radev7cf61662017-07-26 17:10:53 +0300573
Martin Radevda8e2572017-09-12 17:21:16 +0300574// The test verifies that glDraw* generates an INVALID_OPERATION error if the program does not use
575// the multiview extension, but the active draw framebuffer has more than one view.
576TEST_P(MultiviewDrawValidationTest, NumViewsMismatchForNonMultiviewProgram)
577{
578 if (!requestMultiviewExtension())
Martin Radev7cf61662017-07-26 17:10:53 +0300579 {
Martin Radevda8e2572017-09-12 17:21:16 +0300580 return;
Martin Radev7cf61662017-07-26 17:10:53 +0300581 }
Martin Radevda8e2572017-09-12 17:21:16 +0300582
583 const std::string &vsSourceNoMultiview =
584 "#version 300 es\n"
585 "void main()\n"
586 "{}\n";
587 const std::string &fsSourceNoMultiview =
588 "#version 300 es\n"
589 "precision mediump float;\n"
590 "void main()\n"
591 "{}\n";
592 ANGLE_GL_PROGRAM(programNoMultiview, vsSourceNoMultiview, fsSourceNoMultiview);
593 glUseProgram(programNoMultiview);
594
595 const GLint viewportOffsets[4] = {0, 0, 2, 0};
596 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d, 0, 2,
597 &viewportOffsets[0]);
598
599 glDrawArrays(GL_TRIANGLES, 0, 3);
600 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
601
602 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
603 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radev7cf61662017-07-26 17:10:53 +0300604}
605
Martin Radev7e69f762017-07-27 14:54:13 +0300606// The test verifies that glDraw*:
607// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
608// greater than 1 and there is an active transform feedback object.
609// 2) does not generate any error if the number of views in the draw framebuffer is 1.
610TEST_P(MultiviewDrawValidationTest, ActiveTransformFeedback)
611{
612 if (!requestMultiviewExtension())
613 {
614 return;
615 }
616
617 const GLint viewportOffsets[4] = {0, 0, 2, 0};
618
619 const std::string &vsSource =
Olli Etuaho3755c482017-10-13 15:40:26 +0300620 R"(#version 300 es
621 out float tfVarying;
622 void main()
623 {
624 tfVarying = 1.0;
625 })";
Martin Radev7e69f762017-07-27 14:54:13 +0300626 const std::string &fsSource =
Olli Etuaho3755c482017-10-13 15:40:26 +0300627 R"(#version 300 es
628 precision mediump float;
629 void main()
630 {})";
Jamie Madill04c084d2018-08-08 15:49:28 -0400631
Olli Etuaho3755c482017-10-13 15:40:26 +0300632 std::vector<std::string> tfVaryings;
Jamie Madill04c084d2018-08-08 15:49:28 -0400633 tfVaryings.emplace_back("tfVarying");
634 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(singleViewProgram, vsSource, fsSource, tfVaryings,
Olli Etuaho3755c482017-10-13 15:40:26 +0300635 GL_SEPARATE_ATTRIBS);
Jamie Madill04c084d2018-08-08 15:49:28 -0400636
637 std::vector<std::string> dualViewTFVaryings;
638 dualViewTFVaryings.emplace_back("gl_Position");
639 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(dualViewProgram, kDualViewVSSource, kDualViewFSSource,
640 dualViewTFVaryings, GL_SEPARATE_ATTRIBS);
Martin Radev7e69f762017-07-27 14:54:13 +0300641
642 GLBuffer tbo;
643 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);
Jamie Madill04c084d2018-08-08 15:49:28 -0400644 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 16u, nullptr, GL_STATIC_DRAW);
Martin Radev7e69f762017-07-27 14:54:13 +0300645
646 GLTransformFeedback transformFeedback;
647 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
Olli Etuaho3755c482017-10-13 15:40:26 +0300648
649 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
650
Jamie Madill04c084d2018-08-08 15:49:28 -0400651 glUseProgram(dualViewProgram);
Martin Radev7e69f762017-07-27 14:54:13 +0300652 glBeginTransformFeedback(GL_TRIANGLES);
653 ASSERT_GL_NO_ERROR();
654
655 // Check that drawArrays generates an error when there is an active transform feedback object
656 // and the number of views in the draw framebuffer is greater than 1.
657 {
658 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
659 0, 2, &viewportOffsets[0]);
660 glDrawArrays(GL_TRIANGLES, 0, 3);
661 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
662 }
663
Jamie Madill04c084d2018-08-08 15:49:28 -0400664 glEndTransformFeedback();
665
666 // Ending transform feedback should allow the draw to succeed.
667 {
668 glDrawArrays(GL_TRIANGLES, 0, 3);
669 EXPECT_GL_NO_ERROR();
670 }
671
672 // A paused transform feedback should still trigger an error.
673 glBeginTransformFeedback(GL_TRIANGLES);
674 glPauseTransformFeedback();
675 ASSERT_GL_NO_ERROR();
676
677 glDrawArrays(GL_TRIANGLES, 0, 3);
678 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
679
680 // Unbind transform feedback - should succeed.
681 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
682 glDrawArrays(GL_TRIANGLES, 0, 3);
683 ASSERT_GL_NO_ERROR();
684
685 // Rebind paused transform feedback - should fail.
686 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
687 glDrawArrays(GL_TRIANGLES, 0, 3);
688 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
689
690 glResumeTransformFeedback();
691 glEndTransformFeedback();
692
693 glUseProgram(singleViewProgram);
694 glBeginTransformFeedback(GL_TRIANGLES);
695 ASSERT_GL_NO_ERROR();
696
Martin Radev7e69f762017-07-27 14:54:13 +0300697 // Check that drawArrays does not generate an error when the number of views in the draw
698 // framebuffer is 1.
699 {
700 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
701 0, 1, &viewportOffsets[0]);
702 glDrawArrays(GL_TRIANGLES, 0, 3);
703 EXPECT_GL_NO_ERROR();
704 }
705
706 glEndTransformFeedback();
707}
708
Martin Radevffe754b2017-07-31 10:38:07 +0300709// The test verifies that glDraw*:
710// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
711// greater than 1 and there is an active query for target GL_TIME_ELAPSED_EXT.
712// 2) does not generate any error if the number of views in the draw framebuffer is 1.
713TEST_P(MultiviewDrawValidationTest, ActiveTimeElapsedQuery)
714{
Yunchao He9550c602018-02-13 14:47:05 +0800715 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevffe754b2017-07-31 10:38:07 +0300716
Olli Etuaho94c91a92018-07-19 15:10:24 +0300717 if (extensionRequestable("GL_EXT_disjoint_timer_query"))
718 {
719 glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
720 }
721
Yunchao He9550c602018-02-13 14:47:05 +0800722 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_disjoint_timer_query"));
Martin Radevffe754b2017-07-31 10:38:07 +0300723
724 const GLint viewportOffsets[4] = {0, 0, 2, 0};
725 const std::string &vsSource =
726 "#version 300 es\n"
727 "void main()\n"
728 "{}\n";
729 const std::string &fsSource =
730 "#version 300 es\n"
731 "precision mediump float;\n"
732 "void main()\n"
733 "{}\n";
Jamie Madill04c084d2018-08-08 15:49:28 -0400734 ANGLE_GL_PROGRAM(singleViewProgram, vsSource, fsSource);
735 glUseProgram(singleViewProgram);
Martin Radevffe754b2017-07-31 10:38:07 +0300736
737 GLuint query = 0u;
738 glGenQueriesEXT(1, &query);
739 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
740
741 // Check first case.
742 {
Jamie Madill04c084d2018-08-08 15:49:28 -0400743 glUseProgram(mProgram);
Martin Radevffe754b2017-07-31 10:38:07 +0300744 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
745 0, 2, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300746 glClear(GL_COLOR_BUFFER_BIT);
747 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radevffe754b2017-07-31 10:38:07 +0300748 glDrawArrays(GL_TRIANGLES, 0, 3);
749 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
750 }
751
752 // Check second case.
753 {
Jamie Madill04c084d2018-08-08 15:49:28 -0400754 glUseProgram(singleViewProgram);
Martin Radevffe754b2017-07-31 10:38:07 +0300755 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
756 0, 1, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300757 glClear(GL_COLOR_BUFFER_BIT);
758 EXPECT_GL_NO_ERROR();
Martin Radevffe754b2017-07-31 10:38:07 +0300759 glDrawArrays(GL_TRIANGLES, 0, 3);
760 EXPECT_GL_NO_ERROR();
761 }
762
763 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
764 glDeleteQueries(1, &query);
Jamie Madill04c084d2018-08-08 15:49:28 -0400765
766 // Check starting a query after a successful draw.
767 {
768 glUseProgram(mProgram);
769 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
770 0, 2, &viewportOffsets[0]);
771 glClear(GL_COLOR_BUFFER_BIT);
772 EXPECT_GL_NO_ERROR();
773 glDrawArrays(GL_TRIANGLES, 0, 3);
774 EXPECT_GL_NO_ERROR();
775
776 glGenQueriesEXT(1, &query);
777 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
778
779 glDrawArrays(GL_TRIANGLES, 0, 3);
780 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
781
782 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
783 glDrawArrays(GL_TRIANGLES, 0, 3);
784 EXPECT_GL_NO_ERROR();
785
786 glDeleteQueries(1, &query);
787 }
Martin Radevffe754b2017-07-31 10:38:07 +0300788}
789
Martin Radev8f276e22017-05-30 12:05:52 +0300790// The test checks that glDrawArrays can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300791TEST_P(MultiviewRenderDualViewTest, DrawArrays)
Martin Radev8f276e22017-05-30 12:05:52 +0300792{
793 if (!requestMultiviewExtension())
794 {
795 return;
796 }
797 drawQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
798 ASSERT_GL_NO_ERROR();
799
800 checkOutput();
801}
802
803// The test checks that glDrawElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300804TEST_P(MultiviewRenderDualViewTest, DrawElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300805{
806 if (!requestMultiviewExtension())
807 {
808 return;
809 }
810 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
811 ASSERT_GL_NO_ERROR();
812
813 checkOutput();
814}
815
816// The test checks that glDrawRangeElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300817TEST_P(MultiviewRenderDualViewTest, DrawRangeElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300818{
819 if (!requestMultiviewExtension())
820 {
821 return;
822 }
823 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true, true);
824 ASSERT_GL_NO_ERROR();
825
826 checkOutput();
827}
828
829// The test checks that glDrawArrays can be used to render into four views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300830TEST_P(MultiviewRenderTest, DrawArraysFourViews)
Martin Radev8f276e22017-05-30 12:05:52 +0300831{
832 if (!requestMultiviewExtension())
833 {
834 return;
835 }
836
837 const std::string vsSource =
838 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300839 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300840 "layout(num_views = 4) in;\n"
841 "in vec4 vPosition;\n"
842 "void main()\n"
843 "{\n"
844 " if (gl_ViewID_OVR == 0u) {\n"
845 " gl_Position.x = vPosition.x*0.25 - 0.75;\n"
846 " } else if (gl_ViewID_OVR == 1u) {\n"
847 " gl_Position.x = vPosition.x*0.25 - 0.25;\n"
848 " } else if (gl_ViewID_OVR == 2u) {\n"
849 " gl_Position.x = vPosition.x*0.25 + 0.25;\n"
850 " } else {\n"
851 " gl_Position.x = vPosition.x*0.25 + 0.75;\n"
852 " }"
853 " gl_Position.yzw = vPosition.yzw;\n"
854 "}\n";
855
856 const std::string fsSource =
857 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300858 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300859 "precision mediump float;\n"
860 "out vec4 col;\n"
861 "void main()\n"
862 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +0300863 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300864 "}\n";
865
Olli Etuaho4836acc2018-08-20 15:23:18 +0300866 updateFBOs(4, 1, 4);
Martin Radev8f276e22017-05-30 12:05:52 +0300867 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev8f276e22017-05-30 12:05:52 +0300868
869 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
870 ASSERT_GL_NO_ERROR();
871
872 for (int i = 0; i < 4; ++i)
873 {
874 for (int j = 0; j < 4; ++j)
875 {
Martin Radev8f276e22017-05-30 12:05:52 +0300876 if (i == j)
877 {
Martin Radev67a8a012017-09-08 13:03:52 +0300878 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +0300879 }
880 else
881 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300882 EXPECT_EQ(GLColor::black, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +0300883 }
884 }
885 }
886 EXPECT_GL_NO_ERROR();
887}
888
889// The test checks that glDrawArraysInstanced can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300890TEST_P(MultiviewRenderTest, DrawArraysInstanced)
Martin Radev8f276e22017-05-30 12:05:52 +0300891{
892 if (!requestMultiviewExtension())
893 {
894 return;
895 }
896
897 const std::string vsSource =
898 "#version 300 es\n"
899 "#extension GL_OVR_multiview : require\n"
900 "layout(num_views = 2) in;\n"
901 "in vec4 vPosition;\n"
902 "void main()\n"
903 "{\n"
904 " vec4 p = vPosition;\n"
905 " if (gl_InstanceID == 1){\n"
906 " p.y = .5*p.y + .5;\n"
907 " } else {\n"
908 " p.y = p.y*.5;\n"
909 " }\n"
910 " gl_Position.x = (gl_ViewID_OVR == 0u ? p.x*0.5 + 0.5 : p.x*0.5);\n"
911 " gl_Position.yzw = p.yzw;\n"
912 "}\n";
913
914 const std::string fsSource =
915 "#version 300 es\n"
916 "#extension GL_OVR_multiview : require\n"
917 "precision mediump float;\n"
918 "out vec4 col;\n"
919 "void main()\n"
920 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +0300921 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300922 "}\n";
923
Martin Radev3c25ad02017-08-22 17:36:53 +0300924 const int kViewWidth = 2;
925 const int kViewHeight = 2;
926 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +0300927 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev8f276e22017-05-30 12:05:52 +0300928 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev8f276e22017-05-30 12:05:52 +0300929
Martin Radev67a8a012017-09-08 13:03:52 +0300930 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 2u);
Martin Radev8f276e22017-05-30 12:05:52 +0300931 ASSERT_GL_NO_ERROR();
932
Martin Radev67a8a012017-09-08 13:03:52 +0300933 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {{{0, 255}, {0, 255}},
934 {{255, 0}, {255, 0}}};
Martin Radev3c25ad02017-08-22 17:36:53 +0300935
936 for (int view = 0; view < 2; ++view)
Martin Radev8f276e22017-05-30 12:05:52 +0300937 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300938 for (int y = 0; y < 2; ++y)
Martin Radev8f276e22017-05-30 12:05:52 +0300939 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300940 for (int x = 0; x < 2; ++x)
941 {
Martin Radev67a8a012017-09-08 13:03:52 +0300942 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][y][x], 0, 255),
Martin Radev3c25ad02017-08-22 17:36:53 +0300943 GetViewColor(x, y, view));
944 }
Martin Radev8f276e22017-05-30 12:05:52 +0300945 }
946 }
947}
948
Martin Radev553590a2017-07-31 16:40:39 +0300949// The test verifies that the attribute divisor is correctly adjusted when drawing with a multi-view
950// program. The test draws 4 instances of a quad each of which covers a single pixel. The x and y
951// offset of each quad are passed as separate attributes which are indexed based on the
952// corresponding attribute divisors. A divisor of 1 is used for the y offset to have all quads
953// drawn vertically next to each other. A divisor of 3 is used for the x offset to have the last
954// quad offsetted by one pixel to the right. Note that the number of views is divisible by 1, but
955// not by 3.
Martin Radev3c25ad02017-08-22 17:36:53 +0300956TEST_P(MultiviewRenderTest, AttribDivisor)
Martin Radev553590a2017-07-31 16:40:39 +0300957{
958 if (!requestMultiviewExtension())
959 {
960 return;
961 }
962
963 const std::string &vsSource =
964 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300965 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +0300966 "layout(num_views = 2) in;\n"
967 "in vec3 vPosition;\n"
968 "in float offsetX;\n"
969 "in float offsetY;\n"
970 "void main()\n"
971 "{\n"
972 " vec4 p = vec4(vPosition, 1.);\n"
Martin Radev0abb7a22017-08-28 15:34:45 +0300973 " p.xy = p.xy * 0.25 - vec2(0.75) + vec2(offsetX, offsetY);\n"
Martin Radev553590a2017-07-31 16:40:39 +0300974 " gl_Position.x = (gl_ViewID_OVR == 0u ? p.x : p.x + 1.0);\n"
975 " gl_Position.yzw = p.yzw;\n"
976 "}\n";
977
978 const std::string &fsSource =
979 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300980 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +0300981 "precision mediump float;\n"
982 "out vec4 col;\n"
983 "void main()\n"
984 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +0300985 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +0300986 "}\n";
Martin Radev3c25ad02017-08-22 17:36:53 +0300987
988 const int kViewWidth = 4;
989 const int kViewHeight = 4;
990 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +0300991 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev553590a2017-07-31 16:40:39 +0300992 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev553590a2017-07-31 16:40:39 +0300993
994 GLBuffer xOffsetVBO;
995 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
996 const GLfloat xOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.0f};
997 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, xOffsetData, GL_STATIC_DRAW);
998 GLint xOffsetLoc = glGetAttribLocation(program, "offsetX");
999 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1000 glVertexAttribDivisor(xOffsetLoc, 3);
1001 glEnableVertexAttribArray(xOffsetLoc);
1002
1003 GLBuffer yOffsetVBO;
1004 glBindBuffer(GL_ARRAY_BUFFER, yOffsetVBO);
1005 const GLfloat yOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1006 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, yOffsetData, GL_STATIC_DRAW);
1007 GLint yOffsetLoc = glGetAttribLocation(program, "offsetY");
1008 glVertexAttribDivisor(yOffsetLoc, 1);
1009 glVertexAttribPointer(yOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1010 glEnableVertexAttribArray(yOffsetLoc);
1011
Martin Radev67a8a012017-09-08 13:03:52 +03001012 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev553590a2017-07-31 16:40:39 +03001013 ASSERT_GL_NO_ERROR();
1014
Martin Radev67a8a012017-09-08 13:03:52 +03001015 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001016 {{255, 0, 0, 0}, {255, 0, 0, 0}, {255, 0, 0, 0}, {0, 255, 0, 0}},
1017 {{0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 0, 255}}};
1018 for (int view = 0; view < 2; ++view)
Martin Radev553590a2017-07-31 16:40:39 +03001019 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001020 for (int row = 0; row < 4; ++row)
Martin Radev553590a2017-07-31 16:40:39 +03001021 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001022 for (int col = 0; col < 4; ++col)
1023 {
Martin Radev67a8a012017-09-08 13:03:52 +03001024 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][row][col], 0, 255),
Martin Radev3c25ad02017-08-22 17:36:53 +03001025 GetViewColor(col, row, view));
1026 }
Martin Radev553590a2017-07-31 16:40:39 +03001027 }
1028 }
1029}
1030
1031// Test that different sequences of vertexAttribDivisor, useProgram and bindVertexArray in a
1032// multi-view context propagate the correct divisor to the driver.
Martin Radev3c25ad02017-08-22 17:36:53 +03001033TEST_P(MultiviewRenderTest, DivisorOrderOfOperation)
Martin Radev553590a2017-07-31 16:40:39 +03001034{
1035 if (!requestMultiviewExtension())
1036 {
1037 return;
1038 }
1039
Olli Etuaho4836acc2018-08-20 15:23:18 +03001040 updateFBOs(1, 1, 2);
Martin Radev553590a2017-07-31 16:40:39 +03001041
1042 // Create multiview program.
1043 const std::string &vs =
1044 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001045 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001046 "layout(num_views = 2) in;\n"
1047 "layout(location = 0) in vec2 vPosition;\n"
1048 "layout(location = 1) in float offsetX;\n"
1049 "void main()\n"
1050 "{\n"
1051 " vec4 p = vec4(vPosition, 0.0, 1.0);\n"
1052 " p.x += offsetX;\n"
1053 " gl_Position = p;\n"
1054 "}\n";
1055
1056 const std::string &fs =
1057 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001058 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001059 "precision mediump float;\n"
1060 "out vec4 col;\n"
1061 "void main()\n"
1062 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001063 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001064 "}\n";
1065
1066 ANGLE_GL_PROGRAM(program, vs, fs);
1067
1068 const std::string &dummyVS =
1069 "#version 300 es\n"
1070 "layout(location = 0) in vec2 vPosition;\n"
1071 "layout(location = 1) in float offsetX;\n"
1072 "void main()\n"
1073 "{\n"
1074 " gl_Position = vec4(vPosition, 0.0, 1.0);\n"
1075 "}\n";
1076
1077 const std::string &dummyFS =
1078 "#version 300 es\n"
1079 "precision mediump float;\n"
1080 "out vec4 col;\n"
1081 "void main()\n"
1082 "{\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001083 " col = vec4(0,0,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001084 "}\n";
1085
1086 ANGLE_GL_PROGRAM(dummyProgram, dummyVS, dummyFS);
1087
1088 GLBuffer xOffsetVBO;
1089 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1090 const GLfloat xOffsetData[12] = {0.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f,
1091 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f};
1092 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 12, xOffsetData, GL_STATIC_DRAW);
1093
1094 GLBuffer vertexVBO;
1095 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1096 Vector2 kQuadVertices[6] = {Vector2(-1.f, -1.f), Vector2(1.f, -1.f), Vector2(1.f, 1.f),
1097 Vector2(-1.f, -1.f), Vector2(1.f, 1.f), Vector2(-1.f, 1.f)};
1098 glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW);
1099
1100 GLVertexArray vao[2];
1101 for (size_t i = 0u; i < 2u; ++i)
1102 {
1103 glBindVertexArray(vao[i]);
1104
1105 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1106 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
1107 glEnableVertexAttribArray(0);
1108
1109 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1110 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
1111 glEnableVertexAttribArray(1);
1112 }
1113 ASSERT_GL_NO_ERROR();
1114
1115 glViewport(0, 0, 1, 1);
1116 glScissor(0, 0, 1, 1);
Martin Radeveef80e42017-08-11 14:44:57 +03001117 glEnable(GL_SCISSOR_TEST);
Martin Radev61bd9992017-08-11 13:10:55 +03001118 glClearColor(0, 0, 0, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001119
1120 // Clear the buffers, propagate divisor to the driver, bind the vao and keep it active.
1121 // It is necessary to call draw, so that the divisor is propagated and to guarantee that dirty
1122 // bits are cleared.
1123 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001124 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1125 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001126 glBindVertexArray(vao[0]);
1127 glVertexAttribDivisor(1, 0);
1128 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1129 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001130 ASSERT_GL_NO_ERROR();
1131
1132 // Check that vertexAttribDivisor uses the number of views to update the divisor.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001133 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001134 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001135 glUseProgram(program);
1136 glVertexAttribDivisor(1, 1);
1137 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev67a8a012017-09-08 13:03:52 +03001138 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1139 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001140
1141 // Clear the buffers and propagate divisor to the driver.
1142 // We keep the vao active and propagate the divisor to guarantee that there are no unresolved
1143 // dirty bits when useProgram is called.
1144 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001145 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1146 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001147 glVertexAttribDivisor(1, 1);
1148 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1149 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001150 ASSERT_GL_NO_ERROR();
1151
1152 // Check that useProgram uses the number of views to update the divisor.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001153 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001154 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001155 glUseProgram(program);
1156 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev67a8a012017-09-08 13:03:52 +03001157 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1158 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001159
1160 // We go through similar steps as before.
1161 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001162 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1163 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001164 glVertexAttribDivisor(1, 1);
1165 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1166 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001167 ASSERT_GL_NO_ERROR();
1168
1169 // Check that bindVertexArray uses the number of views to update the divisor.
1170 {
1171 // Call useProgram with vao[1] being active to guarantee that useProgram will adjust the
1172 // divisor for vao[1] only.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001173 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001174 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001175 glBindVertexArray(vao[1]);
1176 glUseProgram(program);
1177 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001178 glBindVertexArray(0);
1179 ASSERT_GL_NO_ERROR();
1180 }
1181 // Bind vao[0] after useProgram is called to ensure that bindVertexArray is the call which
1182 // adjusts the divisor.
Martin Radevda8e2572017-09-12 17:21:16 +03001183 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001184 glBindVertexArray(vao[0]);
1185 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev67a8a012017-09-08 13:03:52 +03001186 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1187 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001188}
1189
Martin Radev0d671c92017-08-10 16:41:52 +03001190// Test that no fragments pass the occlusion query for a multi-view vertex shader which always
1191// transforms geometry to be outside of the clip region.
Martin Radev3c25ad02017-08-22 17:36:53 +03001192TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryNothingVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001193{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001194 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1195 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001196
1197 const std::string vsSource =
1198 "#version 300 es\n"
1199 "#extension GL_OVR_multiview : require\n"
1200 "layout(num_views = 2) in;\n"
1201 "in vec3 vPosition;\n"
1202 "void main()\n"
1203 "{\n"
1204 " gl_Position.x = 2.0;\n"
1205 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1206 "}\n";
1207
1208 const std::string fsSource =
1209 "#version 300 es\n"
1210 "#extension GL_OVR_multiview : require\n"
1211 "precision mediump float;\n"
1212 "out vec4 col;\n"
1213 "void main()\n"
1214 "{\n"
1215 " col = vec4(1,0,0,0);\n"
1216 "}\n";
1217 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001218 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001219
1220 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1221 ASSERT_GL_NO_ERROR();
1222 EXPECT_GL_FALSE(result);
1223}
1224
1225// Test that there are fragments passing the occlusion query if only view 0 can produce
1226// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001227TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyLeftVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001228{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001229 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1230 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001231
1232 const std::string vsSource =
1233 "#version 300 es\n"
1234 "#extension GL_OVR_multiview : require\n"
1235 "layout(num_views = 2) in;\n"
1236 "in vec3 vPosition;\n"
1237 "void main()\n"
1238 "{\n"
1239 " gl_Position.x = gl_ViewID_OVR == 0u ? vPosition.x : 2.0;\n"
1240 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1241 "}\n";
1242
1243 const std::string fsSource =
1244 "#version 300 es\n"
1245 "#extension GL_OVR_multiview : require\n"
1246 "precision mediump float;\n"
1247 "out vec4 col;\n"
1248 "void main()\n"
1249 "{\n"
1250 " col = vec4(1,0,0,0);\n"
1251 "}\n";
1252 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001253 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001254
1255 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1256 ASSERT_GL_NO_ERROR();
1257 EXPECT_GL_TRUE(result);
1258}
1259
1260// Test that there are fragments passing the occlusion query if only view 1 can produce
1261// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001262TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyRightVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001263{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001264 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1265 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001266
1267 const std::string vsSource =
1268 "#version 300 es\n"
1269 "#extension GL_OVR_multiview : require\n"
1270 "layout(num_views = 2) in;\n"
1271 "in vec3 vPosition;\n"
1272 "void main()\n"
1273 "{\n"
1274 " gl_Position.x = gl_ViewID_OVR == 1u ? vPosition.x : 2.0;\n"
1275 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1276 "}\n";
1277
1278 const std::string fsSource =
1279 "#version 300 es\n"
1280 "#extension GL_OVR_multiview : require\n"
1281 "precision mediump float;\n"
1282 "out vec4 col;\n"
1283 "void main()\n"
1284 "{\n"
1285 " col = vec4(1,0,0,0);\n"
1286 "}\n";
1287 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001288 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001289
1290 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1291 ASSERT_GL_NO_ERROR();
1292 EXPECT_GL_TRUE(result);
1293}
1294
Martin Radev41ac68e2017-06-06 12:16:58 +03001295// Test that a simple multi-view program which doesn't use gl_ViewID_OVR in neither VS nor FS
1296// compiles and links without an error.
1297TEST_P(MultiviewProgramGenerationTest, SimpleProgram)
1298{
1299 if (!requestMultiviewExtension())
1300 {
1301 return;
1302 }
1303
1304 const std::string vsSource =
1305 "#version 300 es\n"
1306 "#extension GL_OVR_multiview : require\n"
1307 "layout(num_views = 2) in;\n"
1308 "void main()\n"
1309 "{\n"
1310 "}\n";
1311
1312 const std::string fsSource =
1313 "#version 300 es\n"
1314 "#extension GL_OVR_multiview : require\n"
1315 "precision mediump float;\n"
1316 "void main()\n"
1317 "{\n"
1318 "}\n";
1319
1320 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1321 glUseProgram(program);
1322
1323 EXPECT_GL_NO_ERROR();
1324}
1325
1326// Test that a simple multi-view program which uses gl_ViewID_OVR only in VS compiles and links
1327// without an error.
1328TEST_P(MultiviewProgramGenerationTest, UseViewIDInVertexShader)
1329{
1330 if (!requestMultiviewExtension())
1331 {
1332 return;
1333 }
1334
1335 const std::string vsSource =
1336 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001337 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001338 "layout(num_views = 2) in;\n"
1339 "void main()\n"
1340 "{\n"
1341 " if (gl_ViewID_OVR == 0u) {\n"
1342 " gl_Position = vec4(1,0,0,1);\n"
1343 " } else {\n"
1344 " gl_Position = vec4(-1,0,0,1);\n"
1345 " }\n"
1346 "}\n";
1347
1348 const std::string fsSource =
1349 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001350 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001351 "precision mediump float;\n"
1352 "void main()\n"
1353 "{\n"
1354 "}\n";
1355
1356 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1357 glUseProgram(program);
1358
1359 EXPECT_GL_NO_ERROR();
1360}
1361
1362// Test that a simple multi-view program which uses gl_ViewID_OVR only in FS compiles and links
1363// without an error.
1364TEST_P(MultiviewProgramGenerationTest, UseViewIDInFragmentShader)
1365{
1366 if (!requestMultiviewExtension())
1367 {
1368 return;
1369 }
1370
1371 const std::string vsSource =
1372 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001373 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001374 "layout(num_views = 2) in;\n"
1375 "void main()\n"
1376 "{\n"
1377 "}\n";
1378
1379 const std::string fsSource =
1380 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001381 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001382 "precision mediump float;\n"
1383 "out vec4 col;\n"
1384 "void main()\n"
1385 "{\n"
1386 " if (gl_ViewID_OVR == 0u) {\n"
1387 " col = vec4(1,0,0,1);\n"
1388 " } else {\n"
1389 " col = vec4(-1,0,0,1);\n"
1390 " }\n"
1391 "}\n";
1392
1393 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1394 glUseProgram(program);
1395
1396 EXPECT_GL_NO_ERROR();
1397}
1398
Martin Radev61bd9992017-08-11 13:10:55 +03001399// The test checks that GL_POINTS is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001400TEST_P(MultiviewRenderPrimitiveTest, Points)
Martin Radev61bd9992017-08-11 13:10:55 +03001401{
1402 if (!requestMultiviewExtension())
1403 {
1404 return;
1405 }
1406
Geoff Lang25858162017-11-06 11:25:58 -05001407 // Test failing on P400 graphics card (anglebug.com/2228)
1408 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
1409
Martin Radev61bd9992017-08-11 13:10:55 +03001410 const std::string vsSource =
1411 "#version 300 es\n"
1412 "#extension GL_OVR_multiview : require\n"
1413 "layout(num_views = 2) in;\n"
1414 "layout(location=0) in vec2 vPosition;\n"
1415 "void main()\n"
1416 "{\n"
1417 " gl_PointSize = 1.0;\n"
1418 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1419 "}\n";
1420
1421 const std::string fsSource =
1422 "#version 300 es\n"
1423 "#extension GL_OVR_multiview : require\n"
1424 "precision mediump float;\n"
1425 "out vec4 col;\n"
1426 "void main()\n"
1427 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001428 " col = vec4(0,1,0,1);\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001429 "}\n";
1430 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1431 glUseProgram(program);
1432
Martin Radev3c25ad02017-08-22 17:36:53 +03001433 const int kViewWidth = 4;
1434 const int kViewHeight = 2;
1435 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001436 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001437
1438 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 1)};
1439 std::vector<Vector2> vertexDataInClipSpace =
1440 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1441 setupGeometry(vertexDataInClipSpace);
1442
1443 glDrawArrays(GL_POINTS, 0, 2);
1444
Martin Radev67a8a012017-09-08 13:03:52 +03001445 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001446 {{255, 0, 0, 0}, {0, 0, 0, 255}}, {{255, 0, 0, 0}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001447 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001448}
1449
1450// The test checks that GL_LINES is correctly rendered.
1451// The behavior of this test is not guaranteed by the spec:
1452// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1453// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1454// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1455// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001456TEST_P(MultiviewRenderPrimitiveTest, Lines)
Martin Radev61bd9992017-08-11 13:10:55 +03001457{
1458 if (!requestMultiviewExtension())
1459 {
1460 return;
1461 }
1462
Martin Radevced5c862017-08-17 16:05:29 +03001463 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001464 ASSERT_NE(program, 0u);
1465 glUseProgram(program);
1466 ASSERT_GL_NO_ERROR();
1467
Martin Radev3c25ad02017-08-22 17:36:53 +03001468 const int kViewWidth = 4;
1469 const int kViewHeight = 2;
1470 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001471 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001472
1473 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(4, 0)};
1474 std::vector<Vector2> vertexDataInClipSpace =
1475 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1476 setupGeometry(vertexDataInClipSpace);
1477
1478 glDrawArrays(GL_LINES, 0, 2);
1479
Martin Radev67a8a012017-09-08 13:03:52 +03001480 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001481 {{255, 255, 255, 255}, {0, 0, 0, 0}}, {{255, 255, 255, 255}, {0, 0, 0, 0}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001482 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001483
1484 glDeleteProgram(program);
1485}
1486
1487// The test checks that GL_LINE_STRIP is correctly rendered.
1488// The behavior of this test is not guaranteed by the spec:
1489// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1490// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1491// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1492// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001493TEST_P(MultiviewRenderPrimitiveTest, LineStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001494{
1495 if (!requestMultiviewExtension())
1496 {
1497 return;
1498 }
1499
Martin Radevced5c862017-08-17 16:05:29 +03001500 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001501 ASSERT_NE(program, 0u);
1502 glUseProgram(program);
1503 ASSERT_GL_NO_ERROR();
1504
Martin Radev3c25ad02017-08-22 17:36:53 +03001505 const int kViewWidth = 4;
1506 const int kViewHeight = 2;
1507 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001508 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001509
1510 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 2)};
1511 std::vector<Vector2> vertexDataInClipSpace =
1512 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1513 setupGeometry(vertexDataInClipSpace);
1514
1515 glDrawArrays(GL_LINE_STRIP, 0, 3);
1516
Martin Radev67a8a012017-09-08 13:03:52 +03001517 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001518 {{255, 255, 255, 255}, {0, 0, 0, 255}}, {{255, 255, 255, 255}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001519 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001520
1521 glDeleteProgram(program);
1522}
1523
1524// The test checks that GL_LINE_LOOP is correctly rendered.
1525// The behavior of this test is not guaranteed by the spec:
1526// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1527// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1528// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1529// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001530TEST_P(MultiviewRenderPrimitiveTest, LineLoop)
Martin Radev61bd9992017-08-11 13:10:55 +03001531{
1532 if (!requestMultiviewExtension())
1533 {
1534 return;
1535 }
1536
Martin Radevced5c862017-08-17 16:05:29 +03001537 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001538 ASSERT_NE(program, 0u);
1539 glUseProgram(program);
1540 ASSERT_GL_NO_ERROR();
1541
Martin Radev3c25ad02017-08-22 17:36:53 +03001542 const int kViewWidth = 4;
1543 const int kViewHeight = 4;
1544 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001545 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001546
1547 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 3),
1548 Vector2I(0, 3)};
1549 std::vector<Vector2> vertexDataInClipSpace =
1550 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 4);
1551 setupGeometry(vertexDataInClipSpace);
1552
1553 glDrawArrays(GL_LINE_LOOP, 0, 4);
1554
Martin Radev67a8a012017-09-08 13:03:52 +03001555 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001556 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}},
1557 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001558 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001559
1560 glDeleteProgram(program);
1561}
1562
1563// The test checks that GL_TRIANGLE_STRIP is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001564TEST_P(MultiviewRenderPrimitiveTest, TriangleStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001565{
1566 if (!requestMultiviewExtension())
1567 {
1568 return;
1569 }
1570
Martin Radevced5c862017-08-17 16:05:29 +03001571 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001572 ASSERT_NE(program, 0u);
1573 glUseProgram(program);
1574 ASSERT_GL_NO_ERROR();
1575
1576 std::vector<Vector2> vertexDataInClipSpace = {Vector2(1.0f, 0.0f), Vector2(0.0f, 0.0f),
1577 Vector2(1.0f, 1.0f), Vector2(0.0f, 1.0f)};
1578 setupGeometry(vertexDataInClipSpace);
1579
Martin Radev3c25ad02017-08-22 17:36:53 +03001580 const int kViewWidth = 2;
1581 const int kViewHeight = 2;
1582 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001583 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001584
1585 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1586
Martin Radev67a8a012017-09-08 13:03:52 +03001587 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1588 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1589 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001590
1591 glDeleteProgram(program);
1592}
1593
1594// The test checks that GL_TRIANGLE_FAN is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001595TEST_P(MultiviewRenderPrimitiveTest, TriangleFan)
Martin Radev61bd9992017-08-11 13:10:55 +03001596{
1597 if (!requestMultiviewExtension())
1598 {
1599 return;
1600 }
1601
Martin Radevced5c862017-08-17 16:05:29 +03001602 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001603 ASSERT_NE(program, 0u);
1604 glUseProgram(program);
1605 ASSERT_GL_NO_ERROR();
1606
1607 std::vector<Vector2> vertexDataInClipSpace = {Vector2(0.0f, 0.0f), Vector2(0.0f, 1.0f),
1608 Vector2(1.0f, 1.0f), Vector2(1.0f, 0.0f)};
1609 setupGeometry(vertexDataInClipSpace);
1610
Martin Radev3c25ad02017-08-22 17:36:53 +03001611 const int kViewWidth = 2;
1612 const int kViewHeight = 2;
1613 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001614 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001615
1616 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1617
Martin Radev67a8a012017-09-08 13:03:52 +03001618 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1619 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1620 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001621
1622 glDeleteProgram(program);
1623}
1624
1625// Test that rendering enlarged points and lines does not leak fragments outside of the views'
1626// bounds. The test does not rely on the actual line width being greater than 1.0.
Martin Radev3c25ad02017-08-22 17:36:53 +03001627TEST_P(MultiviewSideBySideRenderTest, NoLeakingFragments)
Martin Radev61bd9992017-08-11 13:10:55 +03001628{
Luc Ferronaf7dc012018-06-26 07:56:49 -04001629 // TODO(oetuaho): Diagnose and fix http://anglebug.com/2687
1630 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
1631
Martin Radev61bd9992017-08-11 13:10:55 +03001632 if (!requestMultiviewExtension())
1633 {
1634 return;
1635 }
1636
Olli Etuaho4836acc2018-08-20 15:23:18 +03001637 updateFBOs(2, 1, 2);
Martin Radev61bd9992017-08-11 13:10:55 +03001638
1639 GLint viewportOffsets[4] = {1, 0, 3, 0};
1640 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1641 mColorTexture, 0, 2, &viewportOffsets[0]);
1642 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
1643 mDepthTexture, 0, 2, &viewportOffsets[0]);
1644
1645 glViewport(0, 0, 1, 1);
1646 glScissor(0, 0, 1, 1);
1647 glEnable(GL_SCISSOR_TEST);
1648
1649 const std::string vsSource =
1650 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001651 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001652 "layout(num_views = 2) in;\n"
1653 "layout(location=0) in vec2 vPosition;\n"
1654 "void main()\n"
1655 "{\n"
1656 " gl_PointSize = 10.0;\n"
1657 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1658 "}\n";
1659
1660 const std::string fsSource =
1661 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001662 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001663 "precision mediump float;\n"
1664 "out vec4 col;\n"
1665 "void main()\n"
1666 "{\n"
1667 " if (gl_ViewID_OVR == 0u) {\n"
1668 " col = vec4(1,0,0,1);\n"
1669 " } else {\n"
1670 " col = vec4(0,1,0,1);\n"
1671 " }\n"
1672 "}\n";
1673 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1674 glUseProgram(program);
1675
1676 const std::vector<Vector2I> &windowCoordinates = {Vector2I(0, 0), Vector2I(2, 0)};
1677 const std::vector<Vector2> &vertexDataInClipSpace =
1678 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 1, 1);
Martin Radev3c25ad02017-08-22 17:36:53 +03001679
1680 GLBuffer vbo;
1681 glBindBuffer(GL_ARRAY_BUFFER, vbo);
1682 glBufferData(GL_ARRAY_BUFFER, vertexDataInClipSpace.size() * sizeof(Vector2),
1683 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
1684 glEnableVertexAttribArray(0);
Luc Ferronadcf0ae2018-01-24 08:27:37 -05001685 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
Martin Radev61bd9992017-08-11 13:10:55 +03001686
1687 // Test rendering points.
1688 {
1689 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1690 glDrawArrays(GL_POINTS, 0, 2);
1691 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1692 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
1693 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::black);
1694 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1695 }
1696
1697 // Test rendering lines.
1698 {
1699 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1700 glLineWidth(10.f);
1701 glDrawArrays(GL_LINES, 0, 2);
1702 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1703 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
1704 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::black);
1705 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1706 }
1707}
1708
Martin Radev0abb7a22017-08-28 15:34:45 +03001709// Verify that re-linking a program adjusts the attribute divisor.
1710// The test uses instacing to draw for each view a strips of two red quads and two blue quads next
1711// to each other. The quads' position and color depend on the corresponding attribute divisors.
1712TEST_P(MultiviewRenderTest, ProgramRelinkUpdatesAttribDivisor)
1713{
1714 if (!requestMultiviewExtension())
1715 {
1716 return;
1717 }
1718
1719 const int kViewWidth = 4;
1720 const int kViewHeight = 1;
1721 const int kNumViews = 2;
1722
1723 const std::string &fsSource =
1724 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001725 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001726 "precision mediump float;\n"
1727 "in vec4 oColor;\n"
1728 "out vec4 col;\n"
1729 "void main()\n"
1730 "{\n"
1731 " col = oColor;\n"
1732 "}\n";
1733
1734 auto generateVertexShaderSource = [](int numViews) -> std::string {
1735 std::string source =
1736 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001737 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001738 "layout(num_views = " +
1739 ToString(numViews) +
1740 ") in;\n"
1741 "in vec3 vPosition;\n"
1742 "in float vOffsetX;\n"
1743 "in vec4 vColor;\n"
1744 "out vec4 oColor;\n"
1745 "void main()\n"
1746 "{\n"
1747 " vec4 p = vec4(vPosition, 1.);\n"
1748 " p.x = p.x * 0.25 - 0.75 + vOffsetX;\n"
1749 " oColor = vColor;\n"
1750 " gl_Position = p;\n"
1751 "}\n";
1752 return source;
1753 };
1754
1755 std::string vsSource = generateVertexShaderSource(kNumViews);
1756 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1757 glUseProgram(program);
1758
1759 GLint positionLoc;
1760 GLBuffer xOffsetVBO;
1761 GLint xOffsetLoc;
1762 GLBuffer colorVBO;
1763 GLint colorLoc;
1764
1765 {
1766 // Initialize buffers and setup attributes.
1767 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1768 const GLfloat kXOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1769 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, kXOffsetData, GL_STATIC_DRAW);
1770 xOffsetLoc = glGetAttribLocation(program, "vOffsetX");
1771 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1772 glVertexAttribDivisor(xOffsetLoc, 1);
1773 glEnableVertexAttribArray(xOffsetLoc);
1774
1775 glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
1776 const GLColor kColors[2] = {GLColor::red, GLColor::blue};
1777 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 2, kColors, GL_STATIC_DRAW);
1778 colorLoc = glGetAttribLocation(program, "vColor");
1779 glVertexAttribDivisor(colorLoc, 2);
1780 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1781 glEnableVertexAttribArray(colorLoc);
1782
1783 positionLoc = glGetAttribLocation(program, "vPosition");
1784 }
1785
1786 {
Olli Etuaho4836acc2018-08-20 15:23:18 +03001787 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev0abb7a22017-08-28 15:34:45 +03001788
Martin Radev67a8a012017-09-08 13:03:52 +03001789 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001790 ASSERT_GL_NO_ERROR();
1791
1792 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
1793 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, 0));
1794 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, 0));
1795 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, 0));
1796 }
1797
1798 {
1799 const int kNewNumViews = 3;
1800 vsSource = generateVertexShaderSource(kNewNumViews);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001801 updateFBOs(kViewWidth, kViewHeight, kNewNumViews);
Martin Radev0abb7a22017-08-28 15:34:45 +03001802
1803 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
1804 ASSERT_NE(0u, vs);
1805 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
1806 ASSERT_NE(0u, fs);
1807
1808 GLint numAttachedShaders = 0;
1809 glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
1810
1811 GLuint attachedShaders[2] = {0u};
1812 glGetAttachedShaders(program, numAttachedShaders, nullptr, attachedShaders);
1813 for (int i = 0; i < 2; ++i)
1814 {
1815 glDetachShader(program, attachedShaders[i]);
1816 }
1817
1818 glAttachShader(program, vs);
1819 glDeleteShader(vs);
1820
1821 glAttachShader(program, fs);
1822 glDeleteShader(fs);
1823
1824 glBindAttribLocation(program, positionLoc, "vPosition");
1825 glBindAttribLocation(program, xOffsetLoc, "vOffsetX");
1826 glBindAttribLocation(program, colorLoc, "vColor");
1827
1828 glLinkProgram(program);
1829
Martin Radev67a8a012017-09-08 13:03:52 +03001830 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001831 ASSERT_GL_NO_ERROR();
1832
1833 for (int i = 0; i < kNewNumViews; ++i)
1834 {
1835 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, i));
1836 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, i));
1837 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, i));
1838 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, i));
1839 }
1840 }
1841}
1842
Martin Radevced5c862017-08-17 16:05:29 +03001843// Test that useProgram applies the number of views in computing the final value of the attribute
1844// divisor.
1845TEST_P(MultiviewRenderTest, DivisorUpdatedOnProgramChange)
1846{
1847 if (!requestMultiviewExtension())
1848 {
1849 return;
1850 }
1851
Geoff Lang25858162017-11-06 11:25:58 -05001852 // Test failing on P400 graphics card (anglebug.com/2228)
1853 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
1854
Martin Radevced5c862017-08-17 16:05:29 +03001855 GLVertexArray vao;
1856 glBindVertexArray(vao);
1857 GLBuffer vbo;
1858 glBindBuffer(GL_ARRAY_BUFFER, vbo);
1859 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(1, 0), Vector2I(2, 0),
1860 Vector2I(3, 0)};
1861 std::vector<Vector2> vertexDataInClipSpace =
1862 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 1);
1863 // Fill with x positions so that the resulting clip space coordinate fails the clip test.
1864 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector2) * vertexDataInClipSpace.size(),
1865 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
1866 glEnableVertexAttribArray(0);
1867 glVertexAttribPointer(0, 2, GL_FLOAT, 0, 0, nullptr);
1868 glVertexAttribDivisor(0, 1);
1869 ASSERT_GL_NO_ERROR();
1870
1871 // Create a program and fbo with N views and draw N instances of a point horizontally.
1872 for (int numViews = 2; numViews <= 4; ++numViews)
1873 {
Olli Etuaho4836acc2018-08-20 15:23:18 +03001874 updateFBOs(4, 1, numViews);
Martin Radevced5c862017-08-17 16:05:29 +03001875 ASSERT_GL_NO_ERROR();
1876
1877 GLuint program = CreateSimplePassthroughProgram(numViews);
1878 ASSERT_NE(program, 0u);
1879 glUseProgram(program);
1880 ASSERT_GL_NO_ERROR();
1881
1882 glDrawArraysInstanced(GL_POINTS, 0, 1, numViews);
1883
1884 for (int view = 0; view < numViews; ++view)
1885 {
1886 for (int j = 0; j < numViews; ++j)
1887 {
Martin Radev67a8a012017-09-08 13:03:52 +03001888 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, view));
Martin Radevced5c862017-08-17 16:05:29 +03001889 }
1890 for (int j = numViews; j < 4; ++j)
1891 {
1892 EXPECT_EQ(GLColor::black, GetViewColor(j, 0, view));
1893 }
1894 }
1895
1896 glDeleteProgram(program);
1897 }
1898}
1899
Martin Radev72b4e1e2017-08-31 15:42:56 +03001900// The test checks that gl_ViewID_OVR is correctly propagated to the fragment shader.
1901TEST_P(MultiviewRenderTest, SelectColorBasedOnViewIDOVR)
1902{
1903 if (!requestMultiviewExtension())
1904 {
1905 return;
1906 }
1907
1908 const std::string vsSource =
1909 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001910 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03001911 "layout(num_views = 3) in;\n"
1912 "in vec3 vPosition;\n"
1913 "void main()\n"
1914 "{\n"
1915 " gl_Position = vec4(vPosition, 1.);\n"
1916 "}\n";
1917
1918 const std::string fsSource =
1919 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001920 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03001921 "precision mediump float;\n"
1922 "out vec4 col;\n"
1923 "void main()\n"
1924 "{\n"
1925 " if (gl_ViewID_OVR == 0u) {\n"
1926 " col = vec4(1,0,0,1);\n"
1927 " } else if (gl_ViewID_OVR == 1u) {\n"
1928 " col = vec4(0,1,0,1);\n"
1929 " } else if (gl_ViewID_OVR == 2u) {\n"
1930 " col = vec4(0,0,1,1);\n"
1931 " } else {\n"
1932 " col = vec4(0,0,0,0);\n"
1933 " }\n"
1934 "}\n";
1935
Olli Etuaho4836acc2018-08-20 15:23:18 +03001936 updateFBOs(1, 1, 3);
Martin Radev72b4e1e2017-08-31 15:42:56 +03001937 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev72b4e1e2017-08-31 15:42:56 +03001938
1939 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
1940 ASSERT_GL_NO_ERROR();
1941
1942 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
1943 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
1944 EXPECT_EQ(GLColor::blue, GetViewColor(0, 0, 2));
1945}
1946
1947// The test checks that the inactive layers of a 2D texture array are not written to by a
1948// multi-view program.
1949TEST_P(MultiviewLayeredRenderTest, RenderToSubrageOfLayers)
1950{
1951 if (!requestMultiviewExtension())
1952 {
1953 return;
1954 }
1955
1956 const std::string vsSource =
1957 "#version 300 es\n"
1958 "#extension GL_OVR_multiview : require\n"
1959 "layout(num_views = 2) in;\n"
1960 "in vec3 vPosition;\n"
1961 "void main()\n"
1962 "{\n"
1963 " gl_Position = vec4(vPosition, 1.);\n"
1964 "}\n";
1965
1966 const std::string fsSource =
1967 "#version 300 es\n"
1968 "#extension GL_OVR_multiview : require\n"
1969 "precision mediump float;\n"
1970 "out vec4 col;\n"
1971 "void main()\n"
1972 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001973 " col = vec4(0,1,0,1);\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03001974 "}\n";
1975
Olli Etuaho4836acc2018-08-20 15:23:18 +03001976 updateFBOs(1, 1, 2, 4, 1);
Martin Radev72b4e1e2017-08-31 15:42:56 +03001977 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev72b4e1e2017-08-31 15:42:56 +03001978
1979 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
1980 ASSERT_GL_NO_ERROR();
1981
1982 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 0));
Martin Radev67a8a012017-09-08 13:03:52 +03001983 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
1984 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 2));
Martin Radev72b4e1e2017-08-31 15:42:56 +03001985 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 3));
1986}
1987
Martin Radevc1d4e552017-08-21 12:01:10 +03001988// The D3D11 renderer uses a GS whenever the varyings are flat interpolated which can cause
1989// potential bugs if the view is selected in the VS. The test contains a program in which the
1990// gl_InstanceID is passed as a flat varying to the fragment shader where it is used to discard the
1991// fragment if its value is negative. The gl_InstanceID should never be negative and that branch is
1992// never taken. One quad is drawn and the color is selected based on the ViewID - red for view 0 and
1993// green for view 1.
1994TEST_P(MultiviewRenderTest, FlatInterpolation)
Martin Radev3c25ad02017-08-22 17:36:53 +03001995{
Martin Radevc1d4e552017-08-21 12:01:10 +03001996 if (!requestMultiviewExtension())
1997 {
1998 return;
1999 }
2000
2001 const std::string vsSource =
2002 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002003 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002004 "layout(num_views = 2) in;\n"
2005 "in vec3 vPosition;\n"
2006 "flat out int oInstanceID;\n"
2007 "void main()\n"
2008 "{\n"
2009 " gl_Position = vec4(vPosition, 1.);\n"
2010 " oInstanceID = gl_InstanceID;\n"
2011 "}\n";
2012
2013 const std::string fsSource =
2014 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002015 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002016 "precision mediump float;\n"
2017 "flat in int oInstanceID;\n"
2018 "out vec4 col;\n"
2019 "void main()\n"
2020 "{\n"
2021 " if (oInstanceID < 0) {\n"
2022 " discard;\n"
2023 " }\n"
2024 " if (gl_ViewID_OVR == 0u) {\n"
2025 " col = vec4(1,0,0,1);\n"
2026 " } else {\n"
2027 " col = vec4(0,1,0,1);\n"
2028 " }\n"
2029 "}\n";
2030
Olli Etuaho4836acc2018-08-20 15:23:18 +03002031 updateFBOs(1, 1, 2);
Martin Radevc1d4e552017-08-21 12:01:10 +03002032 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
2033
2034 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2035 ASSERT_GL_NO_ERROR();
2036
2037 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2038 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev3c25ad02017-08-22 17:36:53 +03002039}
2040
Olli Etuaho604d8732018-07-20 11:02:43 +03002041// This test assigns gl_ViewID_OVR to a flat int varying and then sets the color based on that
2042// varying in the fragment shader.
2043TEST_P(MultiviewRenderTest, FlatInterpolation2)
2044{
2045 if (!requestMultiviewExtension())
2046 {
2047 return;
2048 }
2049
2050 const std::string vsSource =
2051 "#version 300 es\n"
2052 "#extension GL_OVR_multiview : require\n"
2053 "layout(num_views = 2) in;\n"
2054 "in vec3 vPosition;\n"
2055 "flat out int flatVarying;\n"
2056 "void main()\n"
2057 "{\n"
2058 " gl_Position = vec4(vPosition, 1.);\n"
2059 " flatVarying = int(gl_ViewID_OVR);\n"
2060 "}\n";
2061
2062 const std::string fsSource =
2063 "#version 300 es\n"
2064 "#extension GL_OVR_multiview : require\n"
2065 "precision mediump float;\n"
2066 "flat in int flatVarying;\n"
2067 "out vec4 col;\n"
2068 "void main()\n"
2069 "{\n"
2070 " if (flatVarying == 0) {\n"
2071 " col = vec4(1,0,0,1);\n"
2072 " } else {\n"
2073 " col = vec4(0,1,0,1);\n"
2074 " }\n"
2075 "}\n";
2076
Olli Etuaho4836acc2018-08-20 15:23:18 +03002077 updateFBOs(1, 1, 2);
Olli Etuaho604d8732018-07-20 11:02:43 +03002078 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
2079
2080 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2081 ASSERT_GL_NO_ERROR();
2082
2083 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2084 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2085}
2086
Martin Radev265a6d42017-09-12 16:51:37 +03002087// The test is added to cover a bug which resulted in the viewport/scissor and viewport offsets not
2088// being correctly applied.
2089TEST_P(MultiviewSideBySideRenderTest, ViewportOffsetsAppliedBugCoverage)
2090{
2091 if (!requestMultiviewExtension())
2092 {
2093 return;
2094 }
2095
Olli Etuaho4836acc2018-08-20 15:23:18 +03002096 updateFBOs(1, 1, 2);
Martin Radev265a6d42017-09-12 16:51:37 +03002097
2098 // Create multiview program.
2099 const std::string &vs =
2100 "#version 300 es\n"
2101 "#extension GL_OVR_multiview : require\n"
2102 "layout(num_views = 2) in;\n"
2103 "layout(location = 0) in vec3 vPosition;\n"
2104 "void main()\n"
2105 "{\n"
2106 " gl_Position = vec4(vPosition, 1.0);\n"
2107 "}\n";
2108
2109 const std::string &fs =
2110 "#version 300 es\n"
2111 "#extension GL_OVR_multiview : require\n"
2112 "precision mediump float;\n"
2113 "out vec4 col;\n"
2114 "void main()\n"
2115 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03002116 " col = vec4(0,1,0,1);\n"
Martin Radev265a6d42017-09-12 16:51:37 +03002117 "}\n";
2118
2119 ANGLE_GL_PROGRAM(program, vs, fs);
2120
2121 glViewport(0, 0, 1, 1);
2122 glScissor(0, 0, 1, 1);
2123 glEnable(GL_SCISSOR_TEST);
2124 glClearColor(0, 0, 0, 1);
2125
2126 // Bind the default FBO and make sure that the state is synchronized.
2127 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2128 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2129 ASSERT_GL_NO_ERROR();
2130
2131 // Draw and check that both views are rendered to.
Olli Etuaho4836acc2018-08-20 15:23:18 +03002132 bindMemberDrawFramebuffer();
Martin Radev265a6d42017-09-12 16:51:37 +03002133 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev67a8a012017-09-08 13:03:52 +03002134
Martin Radev265a6d42017-09-12 16:51:37 +03002135 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
Martin Radev67a8a012017-09-08 13:03:52 +03002136 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
2137 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev265a6d42017-09-12 16:51:37 +03002138}
2139
Olli Etuahof26b27e2018-08-17 11:01:19 +03002140MultiviewRenderTestParams SideBySideVertexShaderOpenGL(GLint majorVersion = 3,
2141 GLint minorVersion = 0)
Martin Radev3c25ad02017-08-22 17:36:53 +03002142{
Olli Etuahof26b27e2018-08-17 11:01:19 +03002143 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE,
2144 VertexShaderOpenGL(majorVersion, minorVersion));
Martin Radev3c25ad02017-08-22 17:36:53 +03002145}
2146
Olli Etuahof26b27e2018-08-17 11:01:19 +03002147MultiviewRenderTestParams LayeredVertexShaderOpenGL()
Martin Radev3c25ad02017-08-22 17:36:53 +03002148{
Olli Etuahof26b27e2018-08-17 11:01:19 +03002149 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
2150 VertexShaderOpenGL(3, 0));
Martin Radev3c25ad02017-08-22 17:36:53 +03002151}
2152
Olli Etuahof26b27e2018-08-17 11:01:19 +03002153MultiviewRenderTestParams SideBySideGeomShaderD3D11()
Martin Radev72b4e1e2017-08-31 15:42:56 +03002154{
Olli Etuahof26b27e2018-08-17 11:01:19 +03002155 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE,
2156 GeomShaderD3D11(3, 0));
Martin Radevc1d4e552017-08-21 12:01:10 +03002157}
2158
Olli Etuahof26b27e2018-08-17 11:01:19 +03002159MultiviewRenderTestParams LayeredGeomShaderD3D11()
Martin Radevc1d4e552017-08-21 12:01:10 +03002160{
Olli Etuahof26b27e2018-08-17 11:01:19 +03002161 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, GeomShaderD3D11(3, 0));
Martin Radevc1d4e552017-08-21 12:01:10 +03002162}
2163
Olli Etuahof26b27e2018-08-17 11:01:19 +03002164MultiviewRenderTestParams SideBySideVertexShaderD3D11(GLint majorVersion = 3,
2165 GLint minorVersion = 0)
Martin Radevc1d4e552017-08-21 12:01:10 +03002166{
Olli Etuahof26b27e2018-08-17 11:01:19 +03002167 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE,
2168 VertexShaderD3D11(majorVersion, minorVersion));
Martin Radevc1d4e552017-08-21 12:01:10 +03002169}
2170
Olli Etuahof26b27e2018-08-17 11:01:19 +03002171MultiviewRenderTestParams LayeredVertexShaderD3D11()
Martin Radevc1d4e552017-08-21 12:01:10 +03002172{
Olli Etuahof26b27e2018-08-17 11:01:19 +03002173 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
2174 VertexShaderD3D11(3, 0));
Martin Radev72b4e1e2017-08-31 15:42:56 +03002175}
2176
Jamie Madill04c084d2018-08-08 15:49:28 -04002177ANGLE_INSTANTIATE_TEST(MultiviewDrawValidationTest,
2178 SideBySideVertexShaderOpenGL(3, 1),
2179 SideBySideVertexShaderD3D11(3, 1));
Martin Radevced5c862017-08-17 16:05:29 +03002180ANGLE_INSTANTIATE_TEST(MultiviewRenderDualViewTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002181 SideBySideVertexShaderOpenGL(),
2182 LayeredVertexShaderOpenGL(),
2183 SideBySideGeomShaderD3D11(),
2184 SideBySideVertexShaderD3D11(),
2185 LayeredGeomShaderD3D11(),
2186 LayeredVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002187ANGLE_INSTANTIATE_TEST(MultiviewRenderTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002188 SideBySideVertexShaderOpenGL(),
2189 LayeredVertexShaderOpenGL(),
2190 SideBySideGeomShaderD3D11(),
2191 SideBySideVertexShaderD3D11(),
2192 LayeredGeomShaderD3D11(),
2193 LayeredVertexShaderD3D11());
Martin Radevced5c862017-08-17 16:05:29 +03002194ANGLE_INSTANTIATE_TEST(MultiviewOcclusionQueryTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002195 SideBySideVertexShaderOpenGL(),
2196 LayeredVertexShaderOpenGL(),
2197 SideBySideGeomShaderD3D11(),
2198 SideBySideVertexShaderD3D11(),
2199 LayeredGeomShaderD3D11(),
2200 LayeredVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002201ANGLE_INSTANTIATE_TEST(MultiviewProgramGenerationTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002202 SideBySideVertexShaderOpenGL(),
2203 LayeredVertexShaderOpenGL(),
2204 SideBySideGeomShaderD3D11(),
2205 SideBySideVertexShaderD3D11(),
2206 LayeredGeomShaderD3D11(),
2207 LayeredVertexShaderD3D11());
Martin Radevced5c862017-08-17 16:05:29 +03002208ANGLE_INSTANTIATE_TEST(MultiviewRenderPrimitiveTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002209 SideBySideVertexShaderOpenGL(),
2210 LayeredVertexShaderOpenGL(),
2211 SideBySideGeomShaderD3D11(),
2212 SideBySideVertexShaderD3D11(),
2213 LayeredGeomShaderD3D11(),
2214 LayeredVertexShaderD3D11());
Jamie Madill04c084d2018-08-08 15:49:28 -04002215ANGLE_INSTANTIATE_TEST(MultiviewSideBySideRenderTest,
2216 VertexShaderOpenGL(3, 0),
2217 GeomShaderD3D11(3, 0));
2218ANGLE_INSTANTIATE_TEST(MultiviewLayeredRenderTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));